4

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

可见注释

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

应该是不可见的

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

现在不可见

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

到目前为止,这是我的代码:

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});
  }
4

1 回答 1

2

我可以想到两种方法来做到这一点。

首先,您可以使用光线投射器(代码来自内存,不完全确定这会 100% 像这样工作):

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

    // 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...
    }
    

这可能适用于较少数量的对象/面部数量有限的对象。对于非常复杂的对象,光线投射器非常缓慢,您可能需要使用预渲染的深度图。

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

    // 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 距离进行比较。请参阅此代码笔以了解如何从深度图中读取世界空间坐标。

于 2018-01-18T11:44:53.453 回答