【问题标题】:How to raycast onto a pointcloud in ThreeJs R71如何在 ThreeJs R71 中将光线投射到点云上
【发布时间】:2019-12-01 20:08:28
【问题描述】:

我在包含 Threejs r71 的 autodesk forge 工作,我想使用 raycaster 来检测点云中不同元素的点击。

感谢您使用 ThreeJs r71 执行此操作的示例代码。

现在,我使用 forge 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:它实际上并没有检测到我的点云和鼠标的交叉点。

【问题讨论】:

    标签: javascript three.js autodesk-forge


    【解决方案1】:

    我使用一些查看器 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 空间中特定位置的丰富注释。使用这种方法,您不必担心自定义交叉点 - 浏览器会为您处理一切。

    【讨论】:

      猜你喜欢
      • 2017-02-21
      • 2015-10-17
      • 2022-10-15
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      相关资源
      最近更新 更多