ThreeJS:在PlaneBufferGeometry中查找相邻面
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreeJS:在PlaneBufferGeometry中查找相邻面相关的知识,希望对你有一定的参考价值。
我正在寻找一种更好/更快的方法来找到我的PlaneBufferGeometry
中的相邻面孔(具有相同的边缘)。目前,我的THREE.Raycaster
与我的对象很好相交(使用intersectObject
)。但是我需要找到所有周围的面孔。
目前,我使用以下肮脏的方法来查找“隔壁”的面孔。它在我的情况下效果很好,但感觉不正确:
let rc = new THREE.Raycaster();
let intersects = [];
for (let i = -1; i <= 1; i++)
for (let j = -1; j <= 1; j++)
let v = new THREE.Vector3(x + i, y, z + j);
rc.set(v, new THREE.Vector3(0, -1, 0));
rc.near = 0;
rc.far = 2;
let subIntersects = rc.intersectObject(mesh);
for (let n = 0; n < subIntersects.length; n++)
intersects.push(subIntersects[n]);
例如,是否有一种方法可以在mesh.geometry.attributes.position.array
中快速找到这些面孔?欢迎任何建议。预先感谢!
答案
您提到了位置数组中的5万个商品。在我看来,这似乎并不慢。这个示例只有10x10,所以数组中有100个项目,因此很容易看到它正在工作,但是我将其设置为200x200,这是40k个项目,而且看起来足够快了吗?
'use strict';
function main()
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer(canvas);
const fov = 60;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 200;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 1;
const scene = new THREE.Scene();
scene.background = new THREE.Color('#444');
scene.add(camera);
const planeGeometry = new THREE.PlaneBufferGeometry(1, 1, 20, 20);
const material = new THREE.MeshBasicMaterial(color: 'blue');
const plane = new THREE.Mesh(planeGeometry, material);
scene.add(plane);
const edgeGeometry = new THREE.BufferGeometry();
const positionNumComponents = 3;
edgeGeometry.setAttribute('position', planeGeometry.getAttribute('position'));
edgeGeometry.setIndex([]);
const edgeMaterial = new THREE.MeshBasicMaterial(
color: 'yellow',
wireframe: true,
depthTest: false,
);
const edges = new THREE.Mesh(edgeGeometry, edgeMaterial);
scene.add(edges);
function resizeRendererToDisplaySize(renderer)
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize)
renderer.setSize(width, height, false);
return needResize;
class PickHelper
constructor()
this.raycaster = new THREE.Raycaster();
pick(normalizedPosition, scene, camera, time)
// cast a ray through the frustum
this.raycaster.setFromCamera(normalizedPosition, camera);
// get the list of objects the ray intersected
const intersectedObjects = this.raycaster.intersectObjects(scene.children, [plane]);
if (intersectedObjects.length)
// pick the first object. It's the closest one
const intersection = intersectedObjects[0];
const faceIndex = intersection.faceIndex;
const indexAttribute = planeGeometry.getIndex();
const indices = indexAttribute.array;
const vertIds = indices.slice(faceIndex * 3, faceIndex * 3 + 3);
const neighbors = []; // note: self will be added to list
for (let i = 0; i < indices.length; i += 3)
for (let j = 0; j < 3; ++j)
const p0Ndx = indices[i + j];
const p1Ndx = indices[i + (j + 1) % 3];
if ((p0Ndx === vertIds[0] && p1Ndx === vertIds[1]) ||
(p0Ndx === vertIds[1] && p1Ndx === vertIds[0]) ||
(p0Ndx === vertIds[1] && p1Ndx === vertIds[2]) ||
(p0Ndx === vertIds[2] && p1Ndx === vertIds[1]) ||
(p0Ndx === vertIds[2] && p1Ndx === vertIds[0]) ||
(p0Ndx === vertIds[0] && p1Ndx === vertIds[2]))
neighbors.push(...indices.slice(i, i + 3));
break;
const edgeIndices = edgeGeometry.getIndex();
edgeIndices.array = new Uint16Array(neighbors);
edgeIndices.count = neighbors.length;
edgeIndices.needsUpdate = true;
const pickPosition = x: 0, y: 0;
const pickHelper = new PickHelper();
clearPickPosition();
function render(time)
time *= 0.001; // convert to seconds;
if (resizeRendererToDisplaySize(renderer))
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
pickHelper.pick(pickPosition, scene, camera, time);
renderer.render(scene, camera);
requestAnimationFrame(render);
requestAnimationFrame(render);
function getCanvasRelativePosition(event)
const rect = canvas.getBoundingClientRect();
return
x: event.clientX - rect.left,
y: event.clientY - rect.top,
;
function setPickPosition(event)
const pos = getCanvasRelativePosition(event);
pickPosition.x = (pos.x / canvas.clientWidth ) * 2 - 1;
pickPosition.y = (pos.y / canvas.clientHeight) * -2 + 1; // note we flip Y
function clearPickPosition()
// unlike the mouse which always has a position
// if the user stops touching the screen we want
// to stop picking. For now we just pick a value
// unlikely to pick something
pickPosition.x = -100000;
pickPosition.y = -100000;
window.addEventListener('mousemove', setPickPosition);
window.addEventListener('mouseout', clearPickPosition);
window.addEventListener('mouseleave', clearPickPosition);
window.addEventListener('touchstart', (event) =>
// prevent the window from scrolling
event.preventDefault();
setPickPosition(event.touches[0]);
, passive: false);
window.addEventListener('touchmove', (event) =>
setPickPosition(event.touches[0]);
);
window.addEventListener('touchend', clearPickPosition);
main();
body margin: 0;
canvas width: 100vw; height: 100vh; display: block;
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r112/build/three.js"></script>
<canvas id="c"></canvas>
以上是关于ThreeJS:在PlaneBufferGeometry中查找相邻面的主要内容,如果未能解决你的问题,请参考以下文章