最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Three.js頂點射線碰撞檢測具體實現(xiàn)步驟詳解

 更新時間:2026年03月09日 09:34:01   作者:晴晴723734  
在three.js中射線檢測是一種常用的技術(shù),用于模擬光線在3D空間中的傳播并找出其與場景中其他物體的碰撞,這篇文章主要介紹了Three.js頂點射線碰撞檢測具體實現(xiàn)步驟的相關(guān)資料,需要的朋友可以參考下

一、基本思路

核心算法流程:

第1步:遍歷幾何體所有頂點,分別創(chuàng)建與幾何體中心坐標構(gòu)成的射線

對于 每個幾何體A 的 每個頂點V:
   頂點位置 = V 的世界坐標位置
   中心位置 = 幾何體A 的世界坐標中心點
   方向向量 = 中心位置 - 頂點位置
   
   創(chuàng)建射線Raycaster:
      起點 = 頂點位置
      方向 = 方向向量(歸一化)

實現(xiàn)細節(jié):

  • 獲取幾何體的頂點坐標數(shù)組(Float32Array,每3個值表示一個頂點的x,y,z坐標)
  • 將頂點從局部坐標系轉(zhuǎn)換到世界坐標系
  • 計算幾何體的世界中心點(通常是物體位置)
  • 對每個頂點創(chuàng)建從頂點指向中心的射線

第2步:射線交叉計算

對于 幾何體A 的 每條射線R:
   使用Raycaster的intersectObject()方法:
       檢測射線R 是否與 幾何體B 相交
       如果相交:
           獲取交點信息(交點坐標、距離、面信息等)

關(guān)鍵點:

  • Raycaster.intersectObject(幾何體B) 返回交點數(shù)組
  • 交點數(shù)組按距離從近到遠排序
  • 如果射線與幾何體B有交點,說明這條射線可能穿過了幾何體B

第3步:通過距離判斷兩個網(wǎng)格模型是否碰撞

對于 幾何體A 的 每條射線R 的 每個交點I:
   計算:起點到交點的距離 = 距離1
   計算:起點到幾何體A中心的距離 = 距離2
   
   如果 距離1 < 距離2:
       說明射線在到達自己中心之前就擊中了對方
       判斷為"這條射線穿過了對方幾何體"
   
   如果 至少有一條射線穿過對方幾何體:
       判斷為"兩個幾何體發(fā)生碰撞"

邏輯解釋:

  • 射線是從自己頂點指向自己中心的
  • 如果射線在到達自己中心之前就擊中了對方,說明對方在自己"內(nèi)部"或"前方"
  • 如果射線先到達自己中心,說明對方在自己"后方"或"外部"

二、具體實現(xiàn)步驟詳解

Step 1: 獲取幾何體所有頂點(世界坐標)

// 1.1 獲取幾何體的頂點位置數(shù)據(jù)
const geometry = mesh.geometry
const positionAttribute = geometry.attributes.position
const positions = positionAttribute.array  // [x1, y1, z1, x2, y2, z2, ...]

// 1.2 獲取世界變換矩陣
const matrixWorld = mesh.matrixWorld

// 1.3 遍歷所有頂點,轉(zhuǎn)換為世界坐標
const worldVertices = []
for (let i = 0; i < positions.length; i += 3) {
  // 創(chuàng)建局部坐標頂點
  const localVertex = new THREE.Vector3(
    positions[i],     // x
    positions[i + 1], // y
    positions[i + 2]  // z
  )
  
  // 轉(zhuǎn)換為世界坐標
  const worldVertex = localVertex.clone()
  worldVertex.applyMatrix4(matrixWorld)
  
  worldVertices.push(worldVertex)
}

Step 2: 計算幾何體中心點(世界坐標)

// 方法1:直接使用mesh的世界位置(對于對稱幾何體)
const center = new THREE.Vector3()
mesh.getWorldPosition(center)

// 方法2:計算所有頂點的平均值(更精確)
let sum = new THREE.Vector3(0, 0, 0)
for (const vertex of worldVertices) {
  sum.add(vertex)
}
const center = sum.divideScalar(worldVertices.length)

Step 3: 創(chuàng)建頂點到中心的射線

// 3.1 創(chuàng)建Raycaster實例
const raycaster = new THREE.Raycaster()

// 3.2 對于每個頂點,創(chuàng)建從頂點指向中心的射線
for (const vertex of worldVertices) {
  // 計算方向向量(從頂點指向中心)
  const direction = center.clone().sub(vertex).normalize()
  
  // 設(shè)置射線
  raycaster.set(vertex, direction)
  
  // 現(xiàn)在raycaster就代表了一條從頂點指向中心的射線
  // 我們可以用它來檢測與其他幾何體的交點
}

Step 4: 射線交叉計算

// 4.1 檢測射線是否與另一個幾何體相交
const otherMesh = ... // 另一個幾何體
const intersects = raycaster.intersectObject(otherMesh)

// 4.2 分析交點信息
if (intersects.length > 0) {
  const firstIntersect = intersects[0]  // 最近的交點
  
  // 交點信息包含:
  // - point: 交點坐標(Vector3)
  // - distance: 從射線起點到交點的距離
  // - object: 被擊中的物體
  // - face: 被擊中的面
  // - faceIndex: 面的索引
}

Step 5: 通過距離判斷是否碰撞

// 5.1 計算關(guān)鍵距離
const distanceToIntersect = vertex.distanceTo(firstIntersect.point)  // 頂點到交點的距離
const distanceToCenter = vertex.distanceTo(center)                  // 頂點到中心的距離

// 5.2 判斷邏輯
if (distanceToIntersect < distanceToCenter) {
  // 情況:射線在到達自己中心之前就擊中了對方
  // 說明對方幾何體在自己"前方"或"內(nèi)部"
  // 這很可能表示兩個幾何體相交或碰撞
  
  console.log('這條射線穿過了對方幾何體!')
  
  // 記錄碰撞信息
  collisions.push({
    vertex: vertex,
    intersectPoint: firstIntersect.point,
    rayDirection: direction
  })
} else {
  // 情況:射線先到達自己中心,然后才可能擊中對方
  // 說明對方幾何體在自己"后方"或"外部"
  // 這很可能表示兩個幾何體沒有碰撞
}

Step 6: 綜合判斷碰撞

// 6.1 統(tǒng)計所有穿過的射線
let collisionCount = 0
for (所有頂點射線) {
  if (射線穿過了對方幾何體) {
    collisionCount++
  }
}

// 6.2 判斷是否發(fā)生碰撞
if (collisionCount > 0) {
  console.log(`發(fā)生碰撞!共有 ${collisionCount} 條射線穿過對方幾何體`)
  return true  // 發(fā)生碰撞
} else {
  console.log('沒有碰撞')
  return false  // 沒有碰撞
}

三、數(shù)學原理圖解

情況1:發(fā)生碰撞(射線穿過對方)
       頂點
        │
        │ 距離1(到交點)
        │
        ▼ 交點(在對方幾何體上)
        │
        │ 距離2(從交點到中心)
        │
        ▼ 中心
       
       距離1 < 距離1+距離2(即距離1 < 頂點到中心的距離)
       ∴ 射線在到達中心之前擊中了對方 → 碰撞!

情況2:沒有碰撞(射線先到中心)
       頂點
        │
        │ 距離1(到中心)
        │
        ▼ 中心
        │
        │ 距離2(從中心到交點)
        │
        ▼ 交點(在對方幾何體上)
       
       距離1 < 距離1+距離2(但射線要先經(jīng)過中心)
       ∴ 射線先到達中心,然后才可能擊中對方 → 沒有碰撞!

四、性能優(yōu)化考慮

1. 頂點采樣優(yōu)化

// 不檢測所有頂點,只采樣一部分
const sampleRate = 0.3  // 采樣率30%
for (let i = 0; i < worldVertices.length; i += Math.floor(1/sampleRate)) {
  // 只檢測部分頂點
}

2. 分層次檢測

// 第一步:快速檢測(包圍盒)
const box1 = new THREE.Box3().setFromObject(mesh1)
const box2 = new THREE.Box3().setFromObject(mesh2)

if (!box1.intersectsBox(box2)) {
  return false  // 包圍盒不相交,肯定不碰撞,快速返回
}

// 第二步:精確檢測(頂點射線)
// 只有包圍盒相交時,才進行更耗時的頂點檢測

3. 空間分割優(yōu)化

// 使用八叉樹或BVH(包圍盒層次結(jié)構(gòu))加速
// 只檢測可能相交的幾何體

4. 距離閾值優(yōu)化

// 添加容差閾值
const threshold = 0.01  // 1厘米容差
if (distanceToIntersect < distanceToCenter + threshold) {
  // 考慮為碰撞(避免浮點數(shù)精度問題)
}

五、適用場景與限制

適用場景:

  1. 需要精確碰撞檢測(如物理模擬、游戲碰撞)
  2. 不規(guī)則幾何體碰撞(非AABB/球體等簡單形狀)
  3. 需要知道碰撞位置(不僅僅是是否碰撞)

限制:

  1. 計算量大:頂點越多越慢
  2. 凹形幾何體問題:射線可能從凹處"穿過"而不碰撞
  3. 薄物體問題:對于非常薄的幾何體可能漏檢

六、偽代碼總結(jié)

function 頂點射線碰撞檢測(幾何體A, 幾何體B):
    // Step 1: 獲取頂點
    頂點數(shù)組A = 獲取世界坐標頂點(幾何體A)
    頂點數(shù)組B = 獲取世界坐標頂點(幾何體B)
    
    // Step 2: 計算中心
    中心A = 計算世界中心(幾何體A)
    中心B = 計算世界中心(幾何體B)
    
    // Step 3-4: 檢測A的頂點射線
    for 每個頂點V in 頂點數(shù)組A:
        方向 = 歸一化(中心A - 頂點V)
        射線 = 創(chuàng)建射線(頂點V, 方向)
        交點 = 射線.檢測相交(幾何體B)
        
        if 交點存在:
            if 距離(頂點V, 交點) < 距離(頂點V, 中心A):
                碰撞計數(shù)器++
    
    // Step 3-4: 檢測B的頂點射線
    for 每個頂點V in 頂點數(shù)組B:
        方向 = 歸一化(中心B - 頂點V)
        射線 = 創(chuàng)建射線(頂點V, 方向)
        交點 = 射線.檢測相交(幾何體A)
        
        if 交點存在:
            if 距離(頂點V, 交點) < 距離(頂點V, 中心B):
                碰撞計數(shù)器++
    
    // Step 5: 判斷結(jié)果
    if 碰撞計數(shù)器 > 0:
        return true  // 發(fā)生碰撞
    else:
        return false // 沒有碰撞

—# Three.js 頂點射線碰撞檢測實現(xiàn)步驟詳解

一、基本思路

核心算法流程:

第1步:遍歷幾何體所有頂點,分別創(chuàng)建與幾何體中心坐標構(gòu)成的射線

對于 每個幾何體A 的 每個頂點V:
   頂點位置 = V 的世界坐標位置
   中心位置 = 幾何體A 的世界坐標中心點
   方向向量 = 中心位置 - 頂點位置
   
   創(chuàng)建射線Raycaster:
      起點 = 頂點位置
      方向 = 方向向量(歸一化)

實現(xiàn)細節(jié):

  • 獲取幾何體的頂點坐標數(shù)組(Float32Array,每3個值表示一個頂點的x,y,z坐標)
  • 將頂點從局部坐標系轉(zhuǎn)換到世界坐標系
  • 計算幾何體的世界中心點(通常是物體位置)
  • 對每個頂點創(chuàng)建從頂點指向中心的射線

第2步:射線交叉計算

對于 幾何體A 的 每條射線R:
   使用Raycaster的intersectObject()方法:
       檢測射線R 是否與 幾何體B 相交
       如果相交:
           獲取交點信息(交點坐標、距離、面信息等)

關(guān)鍵點:

  • Raycaster.intersectObject(幾何體B) 返回交點數(shù)組
  • 交點數(shù)組按距離從近到遠排序
  • 如果射線與幾何體B有交點,說明這條射線可能穿過了幾何體B

第3步:通過距離判斷兩個網(wǎng)格模型是否碰撞

對于 幾何體A 的 每條射線R 的 每個交點I:
   計算:起點到交點的距離 = 距離1
   計算:起點到幾何體A中心的距離 = 距離2
   
   如果 距離1 < 距離2:
       說明射線在到達自己中心之前就擊中了對方
       判斷為"這條射線穿過了對方幾何體"
   
   如果 至少有一條射線穿過對方幾何體:
       判斷為"兩個幾何體發(fā)生碰撞"

邏輯解釋:

  • 射線是從自己頂點指向自己中心的
  • 如果射線在到達自己中心之前就擊中了對方,說明對方在自己"內(nèi)部"或"前方"
  • 如果射線先到達自己中心,說明對方在自己"后方"或"外部"

二、具體實現(xiàn)步驟詳解

Step 1: 獲取幾何體所有頂點(世界坐標)

// 1.1 獲取幾何體的頂點位置數(shù)據(jù)
const geometry = mesh.geometry
const positionAttribute = geometry.attributes.position
const positions = positionAttribute.array  // [x1, y1, z1, x2, y2, z2, ...]

// 1.2 獲取世界變換矩陣
const matrixWorld = mesh.matrixWorld

// 1.3 遍歷所有頂點,轉(zhuǎn)換為世界坐標
const worldVertices = []
for (let i = 0; i < positions.length; i += 3) {
  // 創(chuàng)建局部坐標頂點
  const localVertex = new THREE.Vector3(
    positions[i],     // x
    positions[i + 1], // y
    positions[i + 2]  // z
  )
  
  // 轉(zhuǎn)換為世界坐標
  const worldVertex = localVertex.clone()
  worldVertex.applyMatrix4(matrixWorld)
  
  worldVertices.push(worldVertex)
}

Step 2: 計算幾何體中心點(世界坐標)

// 方法1:直接使用mesh的世界位置(對于對稱幾何體)
const center = new THREE.Vector3()
mesh.getWorldPosition(center)

// 方法2:計算所有頂點的平均值(更精確)
let sum = new THREE.Vector3(0, 0, 0)
for (const vertex of worldVertices) {
  sum.add(vertex)
}
const center = sum.divideScalar(worldVertices.length)

Step 3: 創(chuàng)建頂點到中心的射線

// 3.1 創(chuàng)建Raycaster實例
const raycaster = new THREE.Raycaster()

// 3.2 對于每個頂點,創(chuàng)建從頂點指向中心的射線
for (const vertex of worldVertices) {
  // 計算方向向量(從頂點指向中心)
  const direction = center.clone().sub(vertex).normalize()
  
  // 設(shè)置射線
  raycaster.set(vertex, direction)
  
  // 現(xiàn)在raycaster就代表了一條從頂點指向中心的射線
  // 我們可以用它來檢測與其他幾何體的交點
}

Step 4: 射線交叉計算

// 4.1 檢測射線是否與另一個幾何體相交
const otherMesh = ... // 另一個幾何體
const intersects = raycaster.intersectObject(otherMesh)

// 4.2 分析交點信息
if (intersects.length > 0) {
  const firstIntersect = intersects[0]  // 最近的交點
  
  // 交點信息包含:
  // - point: 交點坐標(Vector3)
  // - distance: 從射線起點到交點的距離
  // - object: 被擊中的物體
  // - face: 被擊中的面
  // - faceIndex: 面的索引
}

Step 5: 通過距離判斷是否碰撞

// 5.1 計算關(guān)鍵距離
const distanceToIntersect = vertex.distanceTo(firstIntersect.point)  // 頂點到交點的距離
const distanceToCenter = vertex.distanceTo(center)                  // 頂點到中心的距離

// 5.2 判斷邏輯
if (distanceToIntersect < distanceToCenter) {
  // 情況:射線在到達自己中心之前就擊中了對方
  // 說明對方幾何體在自己"前方"或"內(nèi)部"
  // 這很可能表示兩個幾何體相交或碰撞
  
  console.log('這條射線穿過了對方幾何體!')
  
  // 記錄碰撞信息
  collisions.push({
    vertex: vertex,
    intersectPoint: firstIntersect.point,
    rayDirection: direction
  })
} else {
  // 情況:射線先到達自己中心,然后才可能擊中對方
  // 說明對方幾何體在自己"后方"或"外部"
  // 這很可能表示兩個幾何體沒有碰撞
}

Step 6: 綜合判斷碰撞

// 6.1 統(tǒng)計所有穿過的射線
let collisionCount = 0
for (所有頂點射線) {
  if (射線穿過了對方幾何體) {
    collisionCount++
  }
}

// 6.2 判斷是否發(fā)生碰撞
if (collisionCount > 0) {
  console.log(`發(fā)生碰撞!共有 ${collisionCount} 條射線穿過對方幾何體`)
  return true  // 發(fā)生碰撞
} else {
  console.log('沒有碰撞')
  return false  // 沒有碰撞
}

三、數(shù)學原理圖解

情況1:發(fā)生碰撞(射線穿過對方)
       頂點
        │
        │ 距離1(到交點)
        │
        ▼ 交點(在對方幾何體上)
        │
        │ 距離2(從交點到中心)
        │
        ▼ 中心
       
       距離1 < 距離1+距離2(即距離1 < 頂點到中心的距離)
       ∴ 射線在到達中心之前擊中了對方 → 碰撞!

情況2:沒有碰撞(射線先到中心)
       頂點
        │
        │ 距離1(到中心)
        │
        ▼ 中心
        │
        │ 距離2(從中心到交點)
        │
        ▼ 交點(在對方幾何體上)
       
       距離1 < 距離1+距離2(但射線要先經(jīng)過中心)
       ∴ 射線先到達中心,然后才可能擊中對方 → 沒有碰撞!

四、性能優(yōu)化考慮

1. 頂點采樣優(yōu)化

// 不檢測所有頂點,只采樣一部分
const sampleRate = 0.3  // 采樣率30%
for (let i = 0; i < worldVertices.length; i += Math.floor(1/sampleRate)) {
  // 只檢測部分頂點
}

2. 分層次檢測

// 第一步:快速檢測(包圍盒)
const box1 = new THREE.Box3().setFromObject(mesh1)
const box2 = new THREE.Box3().setFromObject(mesh2)

if (!box1.intersectsBox(box2)) {
  return false  // 包圍盒不相交,肯定不碰撞,快速返回
}

// 第二步:精確檢測(頂點射線)
// 只有包圍盒相交時,才進行更耗時的頂點檢測

3. 空間分割優(yōu)化

// 使用八叉樹或BVH(包圍盒層次結(jié)構(gòu))加速
// 只檢測可能相交的幾何體

4. 距離閾值優(yōu)化

// 添加容差閾值
const threshold = 0.01  // 1厘米容差
if (distanceToIntersect < distanceToCenter + threshold) {
  // 考慮為碰撞(避免浮點數(shù)精度問題)
}

五、適用場景與限制

適用場景:

  1. 需要精確碰撞檢測(如物理模擬、游戲碰撞)
  2. 不規(guī)則幾何體碰撞(非AABB/球體等簡單形狀)
  3. 需要知道碰撞位置(不僅僅是是否碰撞)

限制:

  1. 計算量大:頂點越多越慢
  2. 凹形幾何體問題:射線可能從凹處"穿過"而不碰撞
  3. 薄物體問題:對于非常薄的幾何體可能漏檢

六、偽代碼總結(jié)

function 頂點射線碰撞檢測(幾何體A, 幾何體B):
    // Step 1: 獲取頂點
    頂點數(shù)組A = 獲取世界坐標頂點(幾何體A)
    頂點數(shù)組B = 獲取世界坐標頂點(幾何體B)
    
    // Step 2: 計算中心
    中心A = 計算世界中心(幾何體A)
    中心B = 計算世界中心(幾何體B)
    
    // Step 3-4: 檢測A的頂點射線
    for 每個頂點V in 頂點數(shù)組A:
        方向 = 歸一化(中心A - 頂點V)
        射線 = 創(chuàng)建射線(頂點V, 方向)
        交點 = 射線.檢測相交(幾何體B)
        
        if 交點存在:
            if 距離(頂點V, 交點) < 距離(頂點V, 中心A):
                碰撞計數(shù)器++
    
    // Step 3-4: 檢測B的頂點射線
    for 每個頂點V in 頂點數(shù)組B:
        方向 = 歸一化(中心B - 頂點V)
        射線 = 創(chuàng)建射線(頂點V, 方向)
        交點 = 射線.檢測相交(幾何體A)
        
        if 交點存在:
            if 距離(頂點V, 交點) < 距離(頂點V, 中心B):
                碰撞計數(shù)器++
    
    // Step 5: 判斷結(jié)果
    if 碰撞計數(shù)器 > 0:
        return true  // 發(fā)生碰撞
    else:
        return false // 沒有碰撞

這個算法的主要思想是:如果一個幾何體的頂點發(fā)出的、指向自己中心的射線,在到達中心之前就擊中了另一個幾何體,那么這兩個幾何體很可能發(fā)生了碰撞或相交。

這個算法的主要思想是:如果一個幾何體的頂點發(fā)出的、指向自己中心的射線,在到達中心之前就擊中了另一個幾何體,那么這兩個幾何體很可能發(fā)生了碰撞或相交。

<template>
  <div ref="containerRef"></div>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import * as THREE from 'three'

const containerRef = ref(null)
let cube1, cube2

onMounted(() => {
  const scene = new THREE.Scene()
  scene.background = new THREE.Color(0x111111)
  
  const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000)
  camera.position.set(0, 5, 10)
  
  const renderer = new THREE.WebGLRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight)
  containerRef.value.appendChild(renderer.domElement)
  
  // 創(chuàng)建立方體1(可移動)
  cube1 = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
  )
  cube1.position.set(-3, 0, 0)
  scene.add(cube1)
  
  // 創(chuàng)建立方體2(靜止)
  cube2 = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial({ color: 0x0000ff, wireframe: true })
  )
  cube2.position.set(0, 0, 0)
  scene.add(cube2)
  
  // 輔助線
  scene.add(new THREE.AxesHelper(5))
  
  // 核心算法:頂點射線碰撞檢測
  const checkVertexRayCollision = () => {
    console.log('=== 頂點射線碰撞檢測 ===')
    
    // 1. 獲取頂點(世界坐標)
    const getVertices = (mesh) => {
      const geometry = mesh.geometry
      const positions = geometry.attributes.position.array
      const vertices = []
      const matrixWorld = mesh.matrixWorld
      
      for (let i = 0; i < positions.length; i += 3) {
        const vertex = new THREE.Vector3(
          positions[i],
          positions[i + 1],
          positions[i + 2]
        )
        vertex.applyMatrix4(matrixWorld)
        vertices.push(vertex)
      }
      return vertices
    }
    
    const vertices1 = getVertices(cube1)
    const vertices2 = getVertices(cube2)
    
    // 2. 獲取中心點(世界坐標)
    const center1 = new THREE.Vector3()
    cube1.getWorldPosition(center1)
    
    const center2 = new THREE.Vector3()
    cube2.getWorldPosition(center2)
    
    console.log('立方體1頂點數(shù):', vertices1.length)
    console.log('立方體2頂點數(shù):', vertices2.length)
    console.log('立方體1中心:', center1)
    console.log('立方體2中心:', center2)
    
    // 3. 檢測立方體1的頂點射線
    let collisionCount = 0
    
    for (let i = 0; i < vertices1.length; i++) {
      const vertex = vertices1[i]
      const direction = new THREE.Vector3().subVectors(center1, vertex).normalize()
      
      const raycaster = new THREE.Raycaster()
      raycaster.set(vertex, direction)
      
      const intersects = raycaster.intersectObject(cube2)
      
      if (intersects.length > 0) {
        const intersect = intersects[0]
        const distanceToHit = vertex.distanceTo(intersect.point)
        const distanceToCenter = vertex.distanceTo(center1)
        
        if (distanceToHit < distanceToCenter) {
          collisionCount++
          console.log(`立方體1頂點${i}: 射線穿過了立方體2`)
        }
      }
    }
    
    // 4. 檢測立方體2的頂點射線
    for (let i = 0; i < vertices2.length; i++) {
      const vertex = vertices2[i]
      const direction = new THREE.Vector3().subVectors(center2, vertex).normalize()
      
      const raycaster = new THREE.Raycaster()
      raycaster.set(vertex, direction)
      
      const intersects = raycaster.intersectObject(cube1)
      
      if (intersects.length > 0) {
        const intersect = intersects[0]
        const distanceToHit = vertex.distanceTo(intersect.point)
        const distanceToCenter = vertex.distanceTo(center2)
        
        if (distanceToHit < distanceToCenter) {
          collisionCount++
          console.log(`立方體2頂點${i}: 射線穿過了立方體1`)
        }
      }
    }
    
    // 5. 判斷結(jié)果
    if (collisionCount > 0) {
      console.log(`?? 發(fā)生碰撞!共有 ${collisionCount} 條射線相交`)
      cube1.material.color.set(0xff00ff)
      cube2.material.color.set(0xff00ff)
      return true
    } else {
      console.log('? 沒有碰撞')
      cube1.material.color.set(0xff0000)
      cube2.material.color.set(0x0000ff)
      return false
    }
  }
  
  // 自動移動并檢測
  let direction = 1
  const animate = () => {
    requestAnimationFrame(animate)
    
    // 移動立方體1
    cube1.position.x += 0.01 * direction
    
    // 邊界檢測
    if (cube1.position.x > 2) direction = -1
    if (cube1.position.x < -4) direction = 1
    
    // 每10幀檢測一次
    if (Math.floor(cube1.position.x * 10) % 10 === 0) {
      checkVertexRayCollision()
    }
    
    renderer.render(scene, camera)
  }
  animate()
})
</script>

<style scoped>
div {
  width: 100vw;
  height: 100vh;
}
</style>

總結(jié) 

到此這篇關(guān)于Three.js頂點射線碰撞檢測具體實現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Three.js頂點射線碰撞檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Bootstrap中data-target 到底是什么

    Bootstrap中data-target 到底是什么

    這篇文章主要介紹了Bootstrap中data-target 到底是什么的相關(guān)資料,我目前理解到在bootstrap中data-target,data-toggle等屬性主要有兩種作用,具體哪兩種作用,大家通過本文詳細了解下
    2017-02-02
  • JavaScript?Object.defineProperty與proxy代理模式的使用詳細分析

    JavaScript?Object.defineProperty與proxy代理模式的使用詳細分析

    這篇文章主要介紹了JavaScript?Object.defineProperty與proxy代理模式的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-10-10
  • JS+DIV+CSS排版布局實現(xiàn)美觀的選項卡效果

    JS+DIV+CSS排版布局實現(xiàn)美觀的選項卡效果

    這篇文章主要介紹了JS+DIV+CSS排版布局實現(xiàn)美觀的選項卡效果,通過簡單的div+css布局結(jié)合JavaScript切換頁面樣式實現(xiàn)美觀的選項卡效果,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • js數(shù)組案例之五子棋游戲

    js數(shù)組案例之五子棋游戲

    這篇文章主要為大家詳細介紹了js數(shù)組案例之五子棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 談?wù)凧avaScript數(shù)組常用方法總結(jié)

    談?wù)凧avaScript數(shù)組常用方法總結(jié)

    本篇文章主要介紹了談?wù)凧avaScript數(shù)組常用方法總結(jié),在JavaScript中,我們需要時常對數(shù)組進行操作。一起跟隨小編過來看看吧
    2017-01-01
  • 小程序富文本提取圖片可放大縮小

    小程序富文本提取圖片可放大縮小

    這篇文章主要為大家詳細介紹了小程序富文本提取圖片可放大縮小,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • JavaScript實現(xiàn)英語單詞題庫

    JavaScript實現(xiàn)英語單詞題庫

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)英語單詞題庫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • JavaScript中URL.createObjectURL和Blob實現(xiàn)保存文件

    JavaScript中URL.createObjectURL和Blob實現(xiàn)保存文件

    本文介紹了利用JavaScript中的Blob對象和URL.createObjectURL方法在瀏覽器端創(chuàng)建文件并實現(xiàn)下載功能,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2025-07-07
  • Layui 設(shè)置select下拉框自動選中某項的方法

    Layui 設(shè)置select下拉框自動選中某項的方法

    今天小編就為大家分享一篇Layui 設(shè)置select下拉框自動選中某項的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • typescript中type和interface的區(qū)別有哪些

    typescript中type和interface的區(qū)別有哪些

    大家使用typescript總會使用到interface和type,所以下面這篇文章主要給大家介紹了關(guān)于typescript中type和interface區(qū)別的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-02-02

最新評論

教育| 怀仁县| 金乡县| 巴青县| 澄迈县| 泌阳县| 河西区| 湖北省| 崇文区| 封丘县| 察雅县| 青田县| 玛曲县| 象州县| 吉木萨尔县| 金阳县| 霍山县| 化州市| 鄂州市| 潞西市| 开原市| 蚌埠市| 潞城市| 宁武县| 基隆市| 迁安市| 格尔木市| 柯坪县| 伽师县| 中山市| 图木舒克市| 水富县| 隆德县| 上思县| 开原市| 仙桃市| 内丘县| 类乌齐县| 吴旗县| 方正县| 班玛县|