2024-10-15|閱讀時間 ‧ 約 0 分鐘

Three-mesh-bvh shapecast函式

前情提要

Three-mesh-bvh套件加速搜尋原理簡介這篇文章介紹Three-mesh-bvh套件加速搜尋的原理,且該文提到判斷兩個模型是否相交的功能,只需簡單呼叫Three-mesh-bvh套件提供的函式即可實現。

利用shapecast函式參與過濾的過程

raw-image


shapecast讓我們能參與加速搜尋的過程,如果有更進階的需求,例如想找出所有相交的點,可以通過shapecast函式實作。

附上Demo鏈接:Three-mesh-bvh shapecast demo




// 一些參數、函式資訊資訊不完整,完整版可參考上方Demo鏈接

// 準備參數
const tempPoint = new THREE.Vector3();
const { frogMesh, staticMesh } = Editor;
const frogGeometry = frogMesh.geometry;
const frogIndexAttr = frogGeometry.index;
const staticGeometry = staticMesh.geometry;
const staticGeometryRelativeMatrix = staticMesh.matrix.clone().multiply(frogMesh.matrix.clone().invert());
const staticMeshRelativeBox = staticGeometry.boundingBox.clone().applyMatrix4(staticGeometryRelativeMatrix);

// 利用shapecast,找出frogMesh與staticMesh所有相交的點
const intersectPointSet = new Set();
frogGeometry.boundsTree.shapecast({
  // 持續細分有相交的包圍框
  intersectsBounds: (box) => {
    if (!box.intersectsBox(staticMeshRelativeBox)) return NOT_INTERSECTED;
    return INTERSECTED;
  },
  // 分別判斷三角形三個點是否在staticMesh內,是就收集到intersectPointSet內
  intersectsTriangle: (triangle, triIndex) => {
    if (!triangle.intersectsBox(staticMeshRelativeBox)) return false;
    if (checkIfMeshIncludePoint(staticMesh, tempPoint.copy(triangle.a).applyMatrix4(frogMesh.matrix)))
      intersectPointSet.add(frogIndexAttr.getX(triIndex * 3));
    if (checkIfMeshIncludePoint(staticMesh, tempPoint.copy(triangle.b).applyMatrix4(frogMesh.matrix)))
      intersectPointSet.add(frogIndexAttr.getX(triIndex * 3 + 1));
    if (checkIfMeshIncludePoint(staticMesh, tempPoint.copy(triangle.c).applyMatrix4(frogMesh.matrix)))
      intersectPointSet.add(frogIndexAttr.getX(triIndex * 3 + 2));
  },
});

intersectsBounds方法可以遍歷bvh逐漸細分的包圍框

  1. 回傳NOT_INTERSECTED,則不會繼續細分這個包圍框。
  2. 回傳INTERSECTED,則繼續細分該包圍框。
  3. 回傳CONTAINED,則只細分該包圍框,其他的就不管了。
    1. 如果只想簡單判斷某個點與模型是否相交,可以使用CONTAINED繼續細分這個包圍框。
    2. 如果你想收集兩個模型相交的所有三角形,這個就不適合,因為可能其他包圍框也有相交。

intersectsRange方法,在遍歷到最小包圍框後,會遍歷裡面的一組三角形

  1. 回傳true代表這組三角形符合條件,結束shapecast函式。
  2. 如果想收集三角形,可以不傳入該函式,直接到下一步intersectsTriangle遍歷所有三角形。

intersectsTriangle方法遍歷子包圍框內所有三角形

  1. 回傳true代表這個三角形符合條件,結束shapecast函式。
  2. 如果想收集三角形就回傳false,在此收集符合條件的三角形
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.