使用THREE.Raycaster进行碰撞检测时遇到奇怪的事情(r68)

时间:2016-06-11 12:35:17

标签: javascript three.js

到目前为止,我已经成功地使用THREE.Raycaster来测试我的游戏引擎中的许多内容的碰撞,它很棒并且效果很好。

然而,最近我遇到了一些非常奇怪的东西,我似乎无法弄明白。从我的角度来看,我的逻辑和代码是合理的,但预期的结果是不正确的。 也许我只是错过了一些明显的东西,所以我想我会寻求一些帮助。

我正在从一组网格顶部的中心一个接一个地投射出圆弧。网格都是父Object3D的子节点,目标是测试原始网格和其他网格之间的碰撞,这些网格也是父网格的子网格。为了测试我的光线,我正在使用THREE.ArrowHelper

以下是我的代码结果的图片 - http://imgur.com/ipzYUsa

在此图像中,ArrowHelper个对象的位置(原点:方向)正是我想要的。但是,是的,这张照片有问题,产生的代码是:

var degree = Math.PI / 16,
    tiles = this.tilesContainer.children,
    tilesNum = tiles.length,
    raycaster = new THREE.Raycaster(),
    rayDirections, rayDirectionsNum, rayOrigin, rayDirection, collisions,
    tile, i, j, k;

for (i = 0; i < tilesNum; i++) {
    tile = tiles[i];
    rayOrigin = new THREE.Vector3(
        tile.position.x,
        tile.geometry.boundingBox.max.y,
        tile.position.z
    );
    rayDirections = [];

    for (j = 0; j < Math.PI * 2; j += degree) {
        rayDirections.push(new THREE.Vector3(Math.sin(j), 0, Math.cos(j)).normalize());
    }

    rayDirectionsNum = rayDirections.length;

    for (k = 0; k < rayDirectionsNum; k++) {
        rayDirection = rayDirections[k];

        raycaster.set(rayOrigin, rayDirection);

        collisions = raycaster.intersectObjects(tiles);

        this.testRay(rayOrigin, rayDirection, collisions);
    }
}

testRay方法如下所示:

testRay: function (origin, direction, collisions) {
    var arrowHelper = new THREE.ArrowHelper(
        direction,
        origin,
        1,
        (collisions.length === 0) ? 0xFF0000 : 0x0000FF
    );

    this.scene.add(arrowHelper);
}

现在,很明显,有关此图像的内容尚未解决。与其他网格碰撞的光线应为蓝色,而不碰撞的光线应为红色。 从这张图片可以清楚地看出,某些东西完全不合适,当我检查碰撞时,我得到了一些非常不合理的结果。对于很多在图像中显示为蓝色的光线,我会遇到大量的碰撞,有时像单个光线的30次碰撞,但即使它们紧挨着其他瓷砖也没有其他的碰撞。

我无法弄清楚它可能是什么。怎么这么多应该是蓝色的光线是红色的呢?而且,水平边缘的瓷砖光线如何与不存在的瓷砖发生蓝色碰撞?

真的挠我的头(读:反复抨击我的头),任何帮助都会受到超级赞赏!

2 个答案:

答案 0 :(得分:1)

解决方案实际上不在此代码之内,至少我不相信,与过时的r68版本相关。

制作拼贴网格时,我需要在它们上设置三个属性

tileMesh.matrixAutoUpdate = false;
tileMesh.updateMatrix();
tileMesh.updateMatrixWorld(); // this is new

我正在做前两个,而不是最后一个。为什么这是必要的,我不知道,这对我来说似乎有点奇怪但是这就解决了我的问题。我在场景中有一个AxisHelper,如果您查看原始图像,您会注意到所有蓝色的ArrowHelper个对象实际上都指向AxisHelper。这真的很奇怪,因为AxisHelper已添加到场景中,而不是tilesContainer。将ArrowHelper个对象添加到tilesContainer没有任何帮助。

渲染场景的过程在将AxisHelper添加到场景之前和初始渲染发生之前运行了raycaster代码。如果我在添加AxisHelper后移动了raycaster代码调用,问题也解决了,但这是一个hacky解决方案。

所以真正的解决方法是将.updateMatrixWorld()添加到切片中。结果现在看起来像http://imgur.com/8LewqxL,这是正确的(ArrowHelper对象的长度已缩短,因此它们不会重叠。)

非常感谢Manthrax对他的帮助。

答案 1 :(得分:0)

我认为你做了一些本地和全球空间错误。我没有看到你出错的地方,但你所有的位置和方向计算似乎都在tilesContainer的本地系统中。您在本地与全球坐标系处理方面是否一致?

例如,您将arrowHelper添加到scene而不是tilesContainer。可能是tilesContainer设置了rotation,因此箭头指向的是另一个方向。

例如,如果您将箭头添加到tilesContainer,会发生什么?