1

我正在努力在 LWJGL 3 中创建体素引擎,我已经掌握了所有基础知识(块、网格渲染等)。

现在我正在使用 JBullet 添加物理。这是我第一次直接使用 JBullet,但我之前在其他 3D 引擎中使用过 Bullet。

这里我收集到,创建与我的网格形状相同的碰撞对象所需要做的就是将顶点和索引插入 aTriangleIndexVertexArray并将其用于 a BvhTriangleMeshShape

这是我的代码:

    float[] coords = mesh.getVertices();
    int[] indices = mesh.getIndices();

    if (indices.length > 0) {
        IndexedMesh indexedMesh = new IndexedMesh();
        indexedMesh.numTriangles = indices.length / 3;
        indexedMesh.triangleIndexBase = ByteBuffer.allocateDirect(indices.length*Float.BYTES).order(ByteOrder.nativeOrder());
        indexedMesh.triangleIndexBase.asIntBuffer().put(indices);
        indexedMesh.triangleIndexStride = 3 * Float.BYTES;
        indexedMesh.numVertices = coords.length / 3;
        indexedMesh.vertexBase = ByteBuffer.allocateDirect(coords.length*Float.BYTES).order(ByteOrder.nativeOrder());
        indexedMesh.vertexBase.asFloatBuffer().put(coords);
        indexedMesh.vertexStride = 3 * Float.BYTES;

        TriangleIndexVertexArray vertArray = new TriangleIndexVertexArray();
        vertArray.addIndexedMesh(indexedMesh);

        boolean useQuantizedAabbCompression = false;
        BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(vertArray, useQuantizedAabbCompression);

        CollisionShape collisionShape = meshShape;

        CollisionObject colObject = new CollisionObject();
        colObject.setCollisionShape(collisionShape);
        colObject.setWorldTransform(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(position.x, position.y, position.z), 1f)));
        dynamicsWorld.addCollisionObject(colObject);

    } else {
        System.err.println("Failed to extract geometry from model. ");
    }

我知道顶点和索引是有效的,因为我在绘制网格后将它们放在这里。

这似乎有点工作,但是当我尝试将一个立方体刚体放到地形上时,它似乎在地形上方碰撞!(我知道立方体设置正确,因为如果我移除网格对撞机,它会在 处撞击基础接地平面y=0)。

在此处输入图像描述

我想这可能是一个扩展问题(虽然我不明白这可能是怎么回事),所以我尝试改变:

colObject.setWorldTransform(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(position.x, position.y, position.z), 1f)));至:

colObject.setWorldTransform(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(position.x, position.y, position.z), 0.5f)));

但是在改变比例之后,1它就像网格对撞机不存在一样。

很难找到 JBullet 围绕网格碰撞的任何资源或代码,我已经为此工作了将近 2 天,所以我希望你们中的一些以前做过的人可以帮助我:)

更新1:

我创建了 IDebugDrawer 的实现,以便可以在场景中绘制调试信息。

为了测试它,我只用一个基本的地平面和一个下降的立方体来运行它。我注意到当立方体下落时,aabb 与立方体的大小相匹配,但是当它撞到地板时,aabb 变得比原来大得多。

在此处输入图像描述

我将假设这是由于碰撞弹跳导致的正常 Bullet 行为,稍后再看,因为它不会影响我当前的问题。

我重新启用了从块网格中生成对撞机,并看到了这个:

在此处输入图像描述

看起来块的 aabb 可视化比实际块高很多(我知道我对整个碰撞对象的 y 定位是正确的)。

在此处输入图像描述

我将尝试弄清楚是否可以绘制实际的碰撞网格。

更新 2:

据我看到的源,碰撞器的网格应该在调试中绘制,所以我不确定为什么它不是。

我尝试将 Box 刚体更改为球体,它实际上滚过可视化 aabb 的顶部,用于地形对撞机。它只是滚平了,并没有撞到或下到那里的山丘或地形的斜坡上,所以它显然只是在 aabb 的平坦顶部滚动。

4

1 回答 1

1

所以在添加调试抽屉后,我很困惑为什么 aabb 比它应该的大 2 倍。

在花了几个小时尝试调整之后,我注意到了一些奇怪的东西——碰撞器和块的边缘之间有 0.25 的间隙。我继续缩小并惊讶地注意到这一点:

在此处输入图像描述

有额外的行和列的对撞机?不,这没有意义,应该有 5x5 碰撞器来匹配 5x5 块。

然后我数了数块并意识到碰撞器跨越64 个块(我的块是 32x32!)。

我很快意识到这是一个扩展问题,并且在添加后

BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(vertArray, useQuantizedAabbCompression);
meshShape.setLocalScaling(new Vector3f(0.5f, 0.5f, 0.5f));

要将对撞机缩小一半,一切都合适且有效!我的“球体”滚动并停在了地形中应该有的山丘上。

在此处输入图像描述

我将 LWJGL 网格转换为 JBullet 网格冷却器的完整代码是:

public void addMesh(org.joml.Vector3f position, Mesh mesh){
    float[] coords = mesh.getVertices();
    int[] indices = mesh.getIndices();

    if (indices.length > 0) {

        IndexedMesh indexedMesh = new IndexedMesh();
        indexedMesh.numTriangles = indices.length / 3;
        indexedMesh.triangleIndexBase = ByteBuffer.allocateDirect(indices.length*Integer.BYTES).order(ByteOrder.nativeOrder());
        indexedMesh.triangleIndexBase.rewind();
        indexedMesh.triangleIndexBase.asIntBuffer().put(indices);
        indexedMesh.triangleIndexStride = 3 * Integer.BYTES;
        indexedMesh.numVertices = coords.length / 3;
        indexedMesh.vertexBase = ByteBuffer.allocateDirect(coords.length*Float.BYTES).order(ByteOrder.nativeOrder());
        indexedMesh.vertexBase.rewind();
        indexedMesh.vertexBase.asFloatBuffer().put(coords);
        indexedMesh.vertexStride = 3 * Float.BYTES;

        TriangleIndexVertexArray vertArray = new TriangleIndexVertexArray();
        vertArray.addIndexedMesh(indexedMesh);

        boolean useQuantizedAabbCompression = false;
        BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(vertArray, useQuantizedAabbCompression);
        meshShape.setLocalScaling(new Vector3f(0.5f, 0.5f, 0.5f));

        CollisionShape collisionShape = meshShape;

        CollisionObject colObject = new CollisionObject();
        colObject.setCollisionShape(collisionShape);
        colObject.setWorldTransform(new Transform(new Matrix4f(new Quat4f(0, 0, 0, 1), new Vector3f(position.x, position.y, position.z), 1f)));
        dynamicsWorld.addCollisionObject(colObject);

    } else {
        System.err.println("Failed to extract geometry from model. ");
    }

}

更新1:

尽管缩放是解决上述问题的方法,但它让我更深入地观察并意识到我错误地使用了块大小 ( 0.5f) 作为网格视图矩阵中的网格缩放因子。将比例更改为1喜欢它应该修复它。

于 2016-11-29T21:24:55.597 回答