天天看點

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;
                }
            }
        }
    }
}      

繼續閱讀