如何在ThreeJs R71中光线投射到点云上

时间:2019-07-23 18:05:28

标签: javascript three.js autodesk-forge

我正在使用包含Threejs r71的Autodesk Forge工作,我想使用光线投射器来检测对点云中不同元素的点击。

有关使用ThreeJs r71进行此操作的示例代码。

现在,我在伪造的api中注册一个扩展,并在其中运行下面的代码。它创建一个点云并将点定位在预定位置(保存在cameraInfo数组中)。

let geometry = new THREE.Geometry();
this.cameraInfo.forEach( function(e) {
        geometry.vertices.push(e.position);
    }
)
const material = new THREE.PointCloudMaterial( { size: 150, color: 0Xff0000, sizeAttenuation: true } );
this.points = new THREE.PointCloud( geometry, material );
this.scene.add(this.points);

/* Set up event listeners */
document.addEventListener('mousemove', event => {
    // console.log('mouse move!');
    let mouse = {
        x: ( event.clientX / window.innerWidth ) * 2 - 1,
        y: - ( event.clientY / window.innerHeight ) * 2 + 1
    };

    let raycaster = new THREE.Raycaster();

    raycaster.params.PointCloud.threshold = 15;
    let vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(this.camera);
    raycaster.ray.set(this.camera.position, vector.sub(this.camera.position).normalize());
    this.scene.updateMatrixWorld();
    let intersects = raycaster.intersectObject(this.points);


    if (intersects.length > 0) {
        const hitIndex = intersects[0].index;
        const hitPoint = this.points.geometry.vertices[ hitIndex ];
        console.log(hitIndex);
        console.log(hitPoint);
    }

}, false);

输出似乎不合逻辑。在某些摄像头位置,它会不断告诉我它与点云中的某个项目相交(无论鼠标在哪里)。在某些相机位置,它根本不会检测到相交。

TLDR:它实际上并没有检测到我的点云和鼠标的交点。

1 个答案:

答案 0 :(得分:0)

我使用一些查看器API(使用了点云中的几个示例点)对代码进行了一些简化:

  const viewer = NOP_VIEWER;
  const geometry = new THREE.Geometry();
  for (let i = -100; i <= 100; i += 10) {
    geometry.vertices.push(new THREE.Vector3(i, i, i));
  }
  const material = new THREE.PointCloudMaterial({ size: 50, color: 0Xff0000, sizeAttenuation: true });
  const points = new THREE.PointCloud(geometry, material);
  viewer.impl.scene.add(points);

  const raycaster = new THREE.Raycaster();
  raycaster.params.PointCloud.threshold = 50;
  document.addEventListener('mousemove', function(event) {
    const ray = viewer.impl.viewportToRay(viewer.impl.clientToViewport(event.clientX, event.clientY));
    raycaster.ray.set(ray.origin, ray.direction);
    let intersects = raycaster.intersectObject(viewer.impl.scene, true);
    if (intersects.length > 0) {
      console.log(intersects[0]);
    }
  });

我相信您需要调整raycaster.params.PointCloud.threshold的值。 three.js中的光线投射逻辑实际上并不与您在屏幕上看到的“盒子”点相交。它仅计算射线与点之间的距离(在世界坐标系中),并且仅在距离小于阈值时才输出交点。在我的示例中,我尝试将阈值设置为50,并且相交结果要好一些。

请注意,如果场景中不一定需要点云,请考虑将HTML元素覆盖在3D视图上。我们正在https://forge-digital-twin.autodesk.io演示(source)中使用该方法来显示附加到3D空间中特定位置的丰富注释。使用这种方法,您不必担心自定义交集-浏览器会为您处理一切。

相关问题