在 Autodesk Forge Viewer 中对 Three.JS 个 Object3D 网格进行光线投射

Raycasting on Three.JS Object3D Meshes in Autodesk Forge Viewer

我一直在尝试对我在 THREE.Scene 中添加的对象执行光线投射,提供为 viewer.impl.sceneAfter(我已经按照此 link 作为添加教程支持透明度的对象)。

如 link 中的文档指定:

Unfortunately this has a side-effect: the native viewer selection mechanism has to deal with meshes that do not have the properties it expects.

It can be fixed but you likely have to edit the code of the viewer and load a custom version, see my fix below (viewer3D.js #L21962). Another option would be to create the custom geometry the same way the viewer does, so it could participate in the selection, but probably more work. If you have a better fix, I'm happy to hear it ...

起初,我添加了常规的 THREE.Object3Ds,当我​​执行单击操作时出现错误:

wgs.js:1889 Uncaught TypeError: Cannot read property 'index' of undefined

我认为是,来自查看器的 meshRayCast 函数:

function meshRayCast( mesh, raycaster, intersects ) {

    init_three();

    var geometry = mesh.geometry;

    if (!geometry)
        return;

    var material = mesh.material;
    
    var side = material ? material.side : THREE.FrontSide;

    var attributes = geometry.attributes;

    inverseMatrix.getInverse( mesh.matrixWorld );
    ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );

    var a, b, c, i, j, il;
    var precision = raycaster.precision;
    var positions, stride, intersectionPoint, distance;

    if (attributes.index !== undefined) {   <----RIGHT HERE

从源代码中,我注意到 Autodesk Viewer 需要 THREE.BufferGeometry 而不是常规几何体,所以我使用从 BufferGeometries 创建的 Object3D 进行了测试,它已经消除了上面的单击错误,但是它仍然不支持光线投射,即使使用我的自定义光线投射器也是如此:

class SceneSelector {
  constructor(viewer){
    this.raycaster = new THREE.Raycaster();
    this.viewer= viewer;
  }

  selectByType(type,vectorXY){
    const camera = this.viewer.getCamera();
    const direction = new THREE.Vector3();
    const pointerDir = new THREE.Vector3();

    if(camera.isPerspective){
      direction.set(vectorXY.x,vectorXY.y,0.5);
      direction.unproject(camera);
      this.raycaster.set(camera.position,
                         direction.sub(camera.position).normalize());
    } else {
      direction.set(vectorXY.x,vectorXY.y,-1);
      direction.unproject(camera);
      this.raycaster.set(direction,
                         pointerDir.transformDirection(camera.matrixWorld));
    }
    const filteredObjects = this.viewer.impl.sceneAfter.children.filter(obj=>{
      return obj.type == type;
    });
    const intersects = this.raycaster.intersectObjects(filteredObjects,true);
    return intersects ? intersects[0] : null;
  }
};

我已经测试了 link 提供的各种其他查看器提供的光线投射功能,但对我不起作用。

(总结)我的问题是:

  1. 有什么方法可以对THREE.Scene之后添加的对象进行光线投射吗?

  2. link 似乎建议我像查看器一样创建自定义几何图形。有这方面的参考资料吗?

提前致谢。

自定义网格上的光线投射在我这边工作得很好,所以请看看我的 RotateTool。它使用的是叠加场景,我尝试在自定义网格上设置透明度,效果很好。在下面的代码中,如果我用 sceneAfter 替换覆盖,它也可以正常工作,我可以使用 raycaster 检测鼠标在 gizmo 上的点击:

createGizmo (center, euler, size, radius, color, range, axis) {

    var material = new GizmoMaterial({
      color: color
    })

    var subMaterial = new GizmoMaterial({
      color: color
    })

    var torusGizmo = new THREE.Mesh(
      new THREE.TorusGeometry(
        radius, size, 64, 64, range),
      material)

    var subTorus = new THREE.Mesh(
      new THREE.TorusGeometry(
        radius, size, 64, 64, 2 * Math.PI),
      subMaterial)

    subTorus.material.highlight(true)

    var transform = new THREE.Matrix4()

    var q = new THREE.Quaternion()

    q.setFromEuler(euler)

    var s = new THREE.Vector3(1, 1, 1)

    transform.compose(center, q, s)

    torusGizmo.applyMatrix(transform)

    subTorus.applyMatrix(transform)

    var plane = this.createBox(
      this.size * 100,
      this.size * 100,
      0.01)

    plane.applyMatrix(transform)

    subTorus.visible = false

    //this.viewer.impl.addOverlay(
    //  this.overlayScene, torusGizmo)
    //
    //this.viewer.impl.addOverlay(
    //  this.overlayScene, subTorus)

    this.viewer.impl.sceneAfter.add(torusGizmo)
    this.viewer.impl.sceneAfter.add(subTorus)

    torusGizmo.subGizmo = subTorus
    torusGizmo.plane = plane
    torusGizmo.axis = axis

    return torusGizmo
  }

希望对您有所帮助