【问题标题】:Three.js, PointerLock And Collision Detection三.js、PointerLock和碰撞检测
【发布时间】:2013-08-31 10:02:15
【问题描述】:

我正在开发一个 3D 虚拟家庭项目。除了碰撞检测,一切都很好。 我将 PointerLockControls 用于我的相机和移动。但我不确定如何检测每个可能方向的碰撞。 为简单起见,我从 (0,0,0) 上的简单立方体向前和向后碰撞开始:

rays = [
    new THREE.Vector3(0, 0, 1),
    new THREE.Vector3(0, 0, -1)
];

然后:

function detectCollision() {
var vector;
var projector = new THREE.Projector();

for (var i = 0; i < rays.length; i++) {
    var vector = rays[i].clone();
    projector.unprojectVector(vector, camera);

    var rayCaster = new THREE.Raycaster(controls.getObject().position, vector.sub(controls.getObject().position).normalize());
    var intersects = rayCaster.intersectObject(cube, true);

    if (intersects.length > 0 && intersects[0].distance < 50) {
        console.log(vector);
        console.log(i, intersects);
        $("#status").text("Collision detected @ " + rays[i].x + "," + rays[i].z +
            "<br \>" + intersects[0].distance);
    }
}

但是当我足够接近我的立方体时,控制台会显示两条光线都击中了立方体!所以为什么? 我的光线有问题吗? vector(0,0,1) 应该是向后的,(0,0,-1) 应该是向前的,对吧? 请帮助我,在我迷失在 3d 中之前! 谢谢。

【问题讨论】:

  • 只用一根射线试试,看看你能不能从那里弄清楚。我认为每条光线都向您认为的相反方向投射,因此(取决于您面对的方向)“前向”实际上从与您的立方体的交叉点开始并朝向相机,而“后向” “一个人从镜头后面开始朝它走去。因此,请尝试切换得出光线投射器方向的减法顺序。
  • 经过更多测试,我发现四个法线向量之间存在关系((0,0,1),(0,0,-1),(1,0,0), (-1,0,0)) 和相机(指针锁定控件)方向。例如,当我将相机旋转 180 度时,现在前向矢量应该是后向矢量,依此类推。对?那么计算光线投射的实际方向向量的公式是什么?
  • PointerLockerControls 已经有一个 getDirection 方法和光线投射,它可以让您与摄像机前的对象相交。但我正在寻找的是当您向后或向左/右侧移动相机时与相机后面或之外的物体的交集。
  • 我明白这一点。我给出的例子是向玩家周围的各个方向投射光线。此外,如果您有相机的方向,您可以使用它来推导出其他方向。

标签: three.js collision-detection


【解决方案1】:

我终于发现了!!解决方案。我数学不好,但最后我弄明白了。
在我从指针储物柜控件获得方向后,取决于按下哪个键,我将方向放入旋转矩阵以获得实际的方向向量(感谢 Icemonster 的线索):

function detectCollision() {
unlockAllDirection();

var rotationMatrix;
var cameraDirection = controls.getDirection(new THREE.Vector3(0, 0, 0)).clone();

if (controls.moveForward()) {
    // Nothing to do!
}
else if (controls.moveBackward()) {
    rotationMatrix = new THREE.Matrix4();
    rotationMatrix.makeRotationY(180 * Math.PI / 180);
}
else if (controls.moveLeft()) {
    rotationMatrix = new THREE.Matrix4();
    rotationMatrix.makeRotationY(90 * Math.PI / 180);
}
else if (controls.moveRight()) {
    rotationMatrix = new THREE.Matrix4();
    rotationMatrix.makeRotationY((360-90) * Math.PI / 180);
}
else return;

if (rotationMatrix !== undefined){
    cameraDirection.applyMatrix4(rotationMatrix);
}
var rayCaster = new THREE.Raycaster(controls.getObject().position, cameraDirection);    
var intersects = rayCaster.intersectObject(hitMesh, true);  

$("#status").html("camera direction x: " + cameraDirection.x + " , z: " + cameraDirection.z);

if ((intersects.length > 0 && intersects[0].distance < 25)) {
    lockDirection();
    $("#status").append("<br />Collision detected @ " + intersects[0].distance);

    var geometry = new THREE.Geometry();
    geometry.vertices.push(intersects[0].point);
    geometry.vertices.push(controls.getObject().position);
    scene.remove(rayLine);
    rayLine = new THREE.Line(geometry, new THREE.LineBasicMaterial({color: 0xFF00FF, linewidth: 2}));
    scene.add(rayLine);
}
}

我还对 PointerLockControls.js 进行了一些更改,以在相机撞到对撞机对象时停止移动。我在这里上传我的样本:CameraRayCasting.zip

更新
最后我找到了一些时间来完成我的 TouchControls 项目。它使用threejs v0.77.1,并支持触摸和点击测试。
在这里查看:TouchControls

【讨论】:

  • 会给这个答案+10!使用three.js r71。通过我过去常常命中检测而不是碰撞。我们绝对需要更多帮助才能使用 webgl/three.js。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 2013-12-05
  • 2011-09-05
相关资源
最近更新 更多