Three.js 光线投射碰撞不起作用
Three.js raycasting collision not working
我正在开发街机风格的珠穆朗玛峰飞行模拟器。
在我正在构建它的调试器中,我有一个地形和直升机 class,它生成 BufferGeometry 地形网格、直升机停机坪几何图形组以及直升机相机和几何图形组。
我的问题是目前我似乎无法检测到任何碰撞。我想它可能不支持 BufferGeometries,所以这对我来说是个问题,因为我需要地形作为缓冲区,因为它太膨胀了……作为标准几何体,它会导致浏览器内存崩溃。
但是,单独测试直升机停机坪的几何形状仍然不会触发。它们在一个组中,所以我将这些组添加到全局 window 数组并将碰撞检查设置为递归但无济于事。
最终,我对其他形式的碰撞检测持开放态度,并且可能需要两种类型,因为我有使用缓冲区几何形状。关于如何解决这个问题或更好的解决方案有什么想法吗?
直升机对象本身
// Rect to Simulate Helicopter
const geometry = new THREE.BoxGeometry( 2, 1, 4 ),
material = new THREE.MeshBasicMaterial(),
rect = new THREE.Mesh( geometry, material );
rect.position.x = 0;
rect.position.y = terrain.returnCameraStartPosY();
rect.position.z = 0;
rect.rotation.order = "YXZ";
rect.name = "heli";
// Link Camera and Helicopter
const heliCam = new THREE.Group(),
player = new Helicopter(heliCam, "OH-58 Kiowa", 14000);
heliCam.add(camera);
heliCam.add(rect);
heliCam.position.set( 0, 2040, -2000 );
heliCam.name = "heliCam";
scene.add(heliCam);
将对象添加到全局碰撞阵列
// Add Terrain
const terrain = new Terrain.ProceduralTerrain(),
terrainObj = terrain.returnTerrainObj(),
helipadEnd = new Terrain.Helipad( 0, 1200, -3600, "Finish", true ),
helipadStart = new Terrain.Helipad( 0, 2000, -2000, "Start", false ),
helipadObjStart = helipadStart.returnHelipadObj(),
helipadObjEnd = helipadEnd.returnHelipadObj();
window.collidableMeshList.push(terrainObj);
window.collidableMeshList.push(helipadObjStart);
window.collidableMeshList.push(helipadObjEnd);
碰撞检测功能运行每帧
collisionDetection(){
const playerOrigin = this.heli.children[1].clone(); // Get Box Mesh from Player Group
for (let i = playerOrigin.geometry.vertices.length - 1; i >= 0; i--) {
const localVertex = playerOrigin.geometry.vertices[i].clone(),
globalVertex = localVertex.applyMatrix4( playerOrigin.matrix ),
directionVector = globalVertex.sub( playerOrigin.position ),
ray = new THREE.Raycaster( playerOrigin, directionVector.clone().normalize() ),
collisionResults = ray.intersectObjects( window.collidableMeshList, true ); // Recursive Boolean for children
if ( collisionResults.length > 0 ){
this.landed = true;
console.log("Collision");
}
// if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ){
// this.landed = true;
// console.log("Collision with vectorLength")
// }
}
}
很难说出您的自定义 类 内部发生了什么,但看起来您正在使用 Object3D
作为 raycaster 的第一个参数,而不是 Vector3
当你使用 this.heli.children[1].clone()
时。你为什么不试试这样的东西:
var raycaster = new THREE.Raycaster();
var origin = this.heli.children[1].position;
raycaster.set(origin, direction);
此外,您确定使用的是 BufferGeometry 吗?因为当你像这样访问一个顶点值时:playerOrigin.geometry.vertices[i]
,它应该给你一个错误。没有vertices
attribute in a BufferGeometry
所以我不知道你是如何确定方向向量的。
我正在开发街机风格的珠穆朗玛峰飞行模拟器。
在我正在构建它的调试器中,我有一个地形和直升机 class,它生成 BufferGeometry 地形网格、直升机停机坪几何图形组以及直升机相机和几何图形组。
我的问题是目前我似乎无法检测到任何碰撞。我想它可能不支持 BufferGeometries,所以这对我来说是个问题,因为我需要地形作为缓冲区,因为它太膨胀了……作为标准几何体,它会导致浏览器内存崩溃。
但是,单独测试直升机停机坪的几何形状仍然不会触发。它们在一个组中,所以我将这些组添加到全局 window 数组并将碰撞检查设置为递归但无济于事。
最终,我对其他形式的碰撞检测持开放态度,并且可能需要两种类型,因为我有使用缓冲区几何形状。关于如何解决这个问题或更好的解决方案有什么想法吗?
直升机对象本身
// Rect to Simulate Helicopter
const geometry = new THREE.BoxGeometry( 2, 1, 4 ),
material = new THREE.MeshBasicMaterial(),
rect = new THREE.Mesh( geometry, material );
rect.position.x = 0;
rect.position.y = terrain.returnCameraStartPosY();
rect.position.z = 0;
rect.rotation.order = "YXZ";
rect.name = "heli";
// Link Camera and Helicopter
const heliCam = new THREE.Group(),
player = new Helicopter(heliCam, "OH-58 Kiowa", 14000);
heliCam.add(camera);
heliCam.add(rect);
heliCam.position.set( 0, 2040, -2000 );
heliCam.name = "heliCam";
scene.add(heliCam);
将对象添加到全局碰撞阵列
// Add Terrain
const terrain = new Terrain.ProceduralTerrain(),
terrainObj = terrain.returnTerrainObj(),
helipadEnd = new Terrain.Helipad( 0, 1200, -3600, "Finish", true ),
helipadStart = new Terrain.Helipad( 0, 2000, -2000, "Start", false ),
helipadObjStart = helipadStart.returnHelipadObj(),
helipadObjEnd = helipadEnd.returnHelipadObj();
window.collidableMeshList.push(terrainObj);
window.collidableMeshList.push(helipadObjStart);
window.collidableMeshList.push(helipadObjEnd);
碰撞检测功能运行每帧
collisionDetection(){
const playerOrigin = this.heli.children[1].clone(); // Get Box Mesh from Player Group
for (let i = playerOrigin.geometry.vertices.length - 1; i >= 0; i--) {
const localVertex = playerOrigin.geometry.vertices[i].clone(),
globalVertex = localVertex.applyMatrix4( playerOrigin.matrix ),
directionVector = globalVertex.sub( playerOrigin.position ),
ray = new THREE.Raycaster( playerOrigin, directionVector.clone().normalize() ),
collisionResults = ray.intersectObjects( window.collidableMeshList, true ); // Recursive Boolean for children
if ( collisionResults.length > 0 ){
this.landed = true;
console.log("Collision");
}
// if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ){
// this.landed = true;
// console.log("Collision with vectorLength")
// }
}
}
很难说出您的自定义 类 内部发生了什么,但看起来您正在使用 Object3D
作为 raycaster 的第一个参数,而不是 Vector3
当你使用 this.heli.children[1].clone()
时。你为什么不试试这样的东西:
var raycaster = new THREE.Raycaster();
var origin = this.heli.children[1].position;
raycaster.set(origin, direction);
此外,您确定使用的是 BufferGeometry 吗?因为当你像这样访问一个顶点值时:playerOrigin.geometry.vertices[i]
,它应该给你一个错误。没有vertices
attribute in a BufferGeometry
所以我不知道你是如何确定方向向量的。