三个js:我的观点是否可见或被遮挡?

时间:2018-01-18 10:01:11

标签: three.js visibility occlusion-culling

我在空间中有一个点在三个js查看器中表达一个向量。附加到这一点有一个“HTML注释”

visible annotation

我想在点不可见时隐藏(在同一网格的其他表面后面或被其他网格隐藏)。例如,在下图中,它应该被隐藏:

should be invisible

我正在使用一些代码来检查注释是否在另一个问题中建议的平截头体中,但这并不完全有效,因为只有当我非常戏剧性地旋转对象时注释才会消失。见下图:

now is not visible

你能帮我解决一下我的问题吗?

到目前为止我的代码:

const vector = new THREE.Vector3(x, y, z);

this.aCamera.updateMatrix();
this.aCamera.updateMatrixWorld(true);

let frustum = new THREE.Frustum();
frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(this.aCamera.projectionMatrix, this.aCamera.matrixWorldInverse));

  // check if annotation is in view
  if (frustum.containsPoint(vector)) {
       anAnnotation.css({opacity: 0});
  } else {
        anAnnotation.css({opacity: 1});
  }

1 个答案:

答案 0 :(得分:0)

我可以想到两种方法。

首先,您可以使用raycaster(代码来自内存,不完全确定这将100%像这样工作):

  • 使用从相机指向标记的光线设置raycaster:

    // somewhere outside
    const raycaster = new THREE.Raycaster();
    const v = new THREE.Vector3();
    
    // in the animation-loop
    v.copy(marker.position).sub(camera.position).normalize();
    raycaster.set(camera.position, v);
    
  • 获取与该光线相交的对象

    // you might want to be a bit more specific
    const intersections = raycaster.intersectObjects(scene, true);
    
  • 如果第一个十字路口不是标记,则至少部分遮挡

    if (intersections.length > 0 && intersections[0].object !== marker) {
      // hide marker...
    }
    

对于面积有限的较少数量的对象/对象,这可能会正常工作。对于非常复杂的物体,raycaster非常慢,你可能想要使用预先渲染的深度图。

  • 在渲染场景之前,只将遮挡物渲染到深度贴图中(您可以使用object.layerscamera.layersLayer docs)来控制渲染的内容)

    // outside animation-loop
    const depthMaterial =  new THREE.MeshDepthMaterial({
      depthPacking: THREE.RGBADepthPacking
    });
    
    const depthTarget = new THREE.WebGLRenderTarget(
      rendererWidth, 
      rendererHeight
    );
    
    
    // before rendering scene
    camera.layers.disable(MARKERS_LAYER);
    scene.overrideMaterial = depthMaterial;
    renderer.render(scene, camera, depthTarget);
    camera.layers.enable(MARKERS_LAYER);
    
  • 现在您可以投影标记的坐标,并将该位置的depthMap的深度与标记的z距离进行比较。有关如何从深度图中读取世界空间坐标,请参阅this codepen