天天看点

Threejs 通过 Raycaster 进行物体碰撞检测

参考:http://www.wukai.me/2015/12/28/threejs-collision/

1: 

创建Raycaster, 设置摄像机。

this.rayCaster = new THREE.Raycaster();

this.rayCaster.camera = camera;

2:

 this.spaceShip 是玩家操作的类,我创建了一个专门用于检测碰撞的THREE.BoxGeometry

 this.stoneList 是 需要被检测碰撞的物体 从屏幕里向外飞出,通过 new THREE.Sprite(new THREE.SpriteMaterial({ map: texture })); 创建

下面是检测碰撞的逻辑, 在update中每帧进行调用
private isCollision () {
    if(this.spaceShip && this.stoneList.length) {
        // 获取到用于检测碰撞的BoxGeometry的geometry;
        let geometry = this.spaceShip.crashGeometry;
        // 获取当前操作物体的坐标作为原点
        let originPoint = this.spaceShip.position.clone();

        // 遍历Geometry上每个顶点,用射线对其进行碰撞检测
        // @ts-ignore
        for (let vertexIndex = 0; vertexIndex < geometry.vertices.length; vertexIndex++) {
            // 顶点原始坐标
            // @ts-ignore
            let localVertex = geometry.vertices[vertexIndex].clone();
            // 顶点经过变换后的坐标
            let globalVertex = localVertex.applyMatrix4(this.spaceShip.matrix);
            let directionVector = globalVertex.sub(this.spaceShip.position);
            this.rayCaster.set(originPoint, directionVector.clone().normalize())

            let collisionResults = this.rayCaster.intersectObjects(this.stoneList);
            if (collisionResults.length > 0) {
                let dis = collisionResults[0].distance;
                let length = directionVector.length();
                // 发生碰撞
                if(dis < length) {
                    // @ts-ignore
                    let gameObjectId = collisionResults[0].object.parent.gameObjectID;
                    this.removeStone(gameObjectId);
                    let chance = UserData.i.chance - 1;
                    if(chance < 0) {
                        CommandManager.i.pushCommandInfo({
                            cmdName: CommandName.ReplaceSceneCmd,
                            isUpgrade: false
                        })
                    } else {
                        UserData.i.chance--;
                    }
                    break;
                }
            }
        }
    }
}      

继续阅读