【问题标题】:THREE.js Detecting collision with Raycaster and BufferGeometryTHREE.js 检测与 Raycaster 和 BufferGeometry 的碰撞
【发布时间】:2020-10-15 19:01:28
【问题描述】:

我是 3d 编程和 THREE.js 方面的新手,需要一些帮助以进行正确的碰撞检测。

我使用下面的方法来检测sourceElements和targetElements之间的碰撞

detect(): void {
    if (!this.sourceElements.length || !this.targetElements.length) {
       return;
    }

    for (let i = 0; i < this.sourceElements.length; i+= 1) {
        const originPoint = this.sourceElements[i].position.clone();

        for (let vertexIndex = 0; vertexIndex < (<Geometry>this.sourceElements[i].geometry).vertices.length; vertexIndex++) {
            let localVertex = (<Geometry>this.sourceElements[i].geometry).vertices[vertexIndex].clone();
            let globalVertex = localVertex.applyMatrix4(this.sourceElements[i].matrix);
            let directionVector = globalVertex.sub(this.sourceElements[i].position);
            let ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
            let collisionResults = ray.intersectObjects(this.targetElements, false); // @TODO create method
            if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
                console.log('<<<<HIT>>>>>', collisionResults[0].object.name);

                // if hit was detected there's no need to analyze more
                return;
            }
        }
    }
  }

如果源元素具有几何图形,则此代码运行良好。 问题是最近出于性能原因,我开始导入具有 BufferGeometry 的较大 Gltf 模型。 BufferGeometry 没有顶点,但不是这个有attributes.position.array和坐标。

所以我尝试根据这些数据生成顶点

let v: Vector3 = new THREE.Vector3();
// iterate over source elements        
for (let i = 0; i < sourceElements.length; i += 1) {
    let geometry = sourceElements[i].geometry;
    // if there's any with BufferGeometry generate vertices based on 
    if ( geometry instanceof THREE.BufferGeometry ) {
        const vertices: Array<Vector3> = [];
        const positions = geometry.attributes.position.array;
                
        console.log('CollisionDetector BufferGeometry detected', geometry);

        for ( let k = 0; k < positions.length; k += 3 ) {
            v.set(positions[ k ],positions[ k + 1 ], positions[ k + 2 ]);
            vertices.push(v);
        }
    }
}

上面的代码不会失败并生成一个 Vector3 对象数组,然后我将其用于光线投射,但不幸的是,从未检测到碰撞。

无论哪种几何体有对象,我应该在我的代码中进行哪些更改以获得通用的碰撞检测方法?

提前致谢

【问题讨论】:

  • 加载模型后,尝试使用.intersectObjects() 像这样.intersectObjects(this.targetElements, true)
  • 感谢您的快速响应。我也尝试过 true 但也没有检测到碰撞

标签: typescript three.js 3d raycasting


【解决方案1】:

在您的代码中,当填充您的 vertices 数组时,您将 references 推送到 v 到数组中。这意味着当您在别处更新v 时,所有这些引用也会更新。您基本上没有与任何其他顶点进行比较,而是与形状的最后一个顶点进行比较。

使用Vector3.clone() 确保您拥有唯一的Vector3s 很容易。

let v: Vector3 = new THREE.Vector3();
// iterate over source elements        
for (let i = 0; i < sourceElements.length; i += 1) {
    let geometry = sourceElements[i].geometry;
    // if there's any with BufferGeometry generate vertices based on 
    if ( geometry instanceof THREE.BufferGeometry ) {
        const vertices: Array<Vector3> = [];
        const positions = geometry.attributes.position.array;
                
        console.log('CollisionDetector BufferGeometry detected', geometry);

        for ( let k = 0; k < positions.length; k += 3 ) {
            v.set(positions[ k ],positions[ k + 1 ], positions[ k + 2 ]);
            vertices.push(v.clone()); // <---- Creates a copy!
        }
    }
}

请注意,在推入顶点的那一行,我调用v.clone()。这将使用您设置的值创建 v 的副本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-07
    • 2019-04-30
    • 2014-03-29
    • 2012-07-13
    • 2023-04-04
    • 1970-01-01
    • 2017-06-17
    • 2011-09-05
    相关资源
    最近更新 更多