检测可能被物体隐藏的网格的可见性

Detect visibility of mesh which could possibly be hidden by object

我有一个场景,其中包括一个 Object3D 代表一个地球和多个代表这个地球上的点的网格元素。我使用 OrbitControls 来允许交互。此外,我将 HTMLElements 附加到地球上的点。由于地球仪基本上是一个球体,因此放置在背面时相机可能看不到点。

如何检测对象 camera/hidden 是否可见这样的点?这样做我想隐藏与网格可见性相关的 HTMLElementHTMLElement 的位置在渲染时更新,因此我假设此检查也应该在渲染时发生:

private render() {
   this.renderer.render(this.scene, this.camera);

   this.points.forEach(({ label, mesh }) => {
      const screen = this.toScreenPosition(mesh);
      label.style.transform = `translate3d(${screen.x - 15}px, ${screen.y}px, 0)`;
   });

   this.requestId = window.requestAnimationFrame(this.render.bind(this));
}

渲染中的工作代码:

this.points.forEach(({ label, mesh }) => {
    const screen = this.toScreenPosition(mesh);
    label.style.transform = `translate3d(${screen.x - 15}px, ${screen.y}px, 0)`;

    const direction = new Vector3();
    direction.copy(mesh.position).sub(this.camera.position).normalize();
    this.raycaster.set(this.camera.position, direction);
    const intersections = this.raycaster.intersectObject(this.scene, true);
    const intersected = intersections.length > 0 ? intersections[0].object.uuid === mesh.uuid : false;

    if (intersected && label.style.opacity === "0") {
        label.style.opacity = "1";
    } else if (!intersected && label.style.opacity === "1") {
        label.style.opacity = "0";
    }
});

我推荐一个简单的两步算法:

  • 首先,检查给定点是否在视锥体中。实现该功能的代码分享于:three.js - check if object is still in view of the camera.
  • 如果测试通过,则需要验证该点是否被3D物体遮挡。检查这一点的典型方法是视线测试。这意味着您可以根据相机的位置和从相机指向给定点的方向设置光线投射器。然后测试场景中的 3D 对象是否与这条射线相交。如果没有交点,则该点不会被遮挡。否则它是,你可以隐藏相应的标签。