【问题标题】:Raycasting on Three.JS Object3D Meshes in Autodesk Forge Viewer在 Autodesk Forge Viewer 中对 Three.JS Object3D 网格进行光线投射
【发布时间】:2023-03-28 00:04:01
【问题描述】:

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

正如链接中的文档所指定:

不幸的是,这有一个副作用:本机查看器选择机制必须处理不具备预期属性的网格。

它可以修复,但您可能必须编辑查看器的代码并加载自定义版本,请参阅下面的修复 (viewer3D.js #L21962)。另一种选择是以与查看器相同的方式创建自定义几何体,因此它可以参与选择,但可能需要更多工作。如果您有更好的解决方案,我很高兴听到它...

起初,我添加了常规的 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 而不是常规几何图形,因此我使用从 BufferGeometry 创建的 Object3D 进行了测试,它已经消除了上面在单点单击时出现的错误,但它仍然没有t 支持光线投射,即使使用我的自定义光线投射器:

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.SceneAfter 中添加的对象执行光线投射?

  2. 似乎link 建议我以与查看器相同的方式创建自定义几何图形。有这方面的参考吗?

提前致谢。

【问题讨论】:

    标签: raycasting autodesk-forge autodesk-viewer


    【解决方案1】:

    自定义网格上的光线投射对我来说效果很好,所以请看看我的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
      }
    

    希望有帮助

    【讨论】:

      猜你喜欢
      • 2020-01-16
      • 1970-01-01
      • 2013-07-10
      • 2016-06-19
      • 2020-03-07
      • 1970-01-01
      • 2014-06-29
      • 2019-05-09
      • 1970-01-01
      相关资源
      最近更新 更多