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中查找相邻面的主要内容,如果未能解决你的问题,请参考以下文章

threejs 复杂模型光线效果怎么调

threejs文档翻译:一.创建场景

ThreeJs到Qt

threejs中绘制文字

ThreeJS - 如何找到枢轴点

ThreeJS 分子 - 双键