用三个创建大炮主体。网格

问题描述 投票:0回答:1

我有一个 THREE.js 平面,使用 Perlin 噪声上下移动点来制作地形。现在我需要为相机添加物理特性以防止它从飞机上掉下来。

我希望创建一个函数,可以从网格中检索顶点和面,并将它们作为凸多面体复制到 CANNON 体上。这是我到目前为止所拥有的,但不起作用:

function setPhysicsGeometry(mesh, body) {
    const vertices = mesh.geometry.vertices;
    const shape = new CANNON.ConvexPolyhedron();

    vertices.forEach(function(vertex) {
        // Adjust vertex position based on the physics properties
        vertex.z = 0; // Assuming initial z position is 0

        // Add the vertex to the shape
        shape.vertices.push(new CANNON.Vec3(vertex.x, vertex.y, vertex.z));
    });

    // Compute the faces of the shape
    const faces = [];
    for (let i = 0; i < mesh.geometry.faces.length; i++) {
        const face = mesh.geometry.faces[i];
        faces.push([face.a, face.b, face.c]);
    }
    shape.faces = faces;

    // Update the shape's bounding box
    shape.updateNormals();
    shape.updateEdges();

    // Assign the shape to the body
    body.addShape(shape);
}

这是我收到的错误:

Uncaught TypeError: shape.updateNormals is not a function

shape.updateEdges() 也会发生同样的事情

这是这两个函数的问题还是我过度简化了困难/不可能的事情。

谢谢

更新: 我做了一个可以工作但速度超级慢的函数:

function createShape(geo) {
    const bufferedGeo = new THREE.BufferGeometry().fromGeometry(geo); // Turn geometry into buffer geo

    let position = bufferedGeo.attributes.position.array
    const points = []

    for (let i = 0; i < position.length; i += 3) {
        points.push(new CANNON.Vec3(position[i], position[i + 1], position[i + 2]))
    }
    const faces = []
    
    for (let i = 0; i < position.length / 3; i += 3) {
        faces.push([i, i + 1, i + 2])
    }

    const shape = new CANNON.ConvexPolyhedron(points, faces)
    
    return shape
}

这是我得到的一个错误,表明法线的排序顺序错误:

.faceNormals[1011] = Vec3(-0.38237948261368415,0.4673447646702331,-0.7971040096570934) looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule.

我不知道如何修复它,因为它们只是从几何体中取出的

javascript three.js cannon.js
1个回答
0
投票

我解决了它(不完全,仍然存在物理问题,但这是一个不同的问题)。

感谢This Guy向我发送了一个令人惊奇的示例,说明我从哪里获得了解决方案。我试图使用凸多面体来获得我自己的身体形状。我认为仍然可以做到这一点,但是以正确的语法对面和法线进行排序确实很困难。相反,我使用了 Trimesh,这要简单得多。

但是,在示例中,他使用了

new THREE.TorusKnotGeometry()
,然后直接进入了
createTrimesh()
。对我来说,这会返回错误,因为 THREE.js 几何图形不是缓冲区几何图形。所以我用一个简单的函数进行了更改,它没有返回任何错误。物理学仍然无法作用于该物体。因此,在感觉像是两个长的时间之后,我将位置和四分从 THREE.js 网格复制到 CANNON 主体,效果非常好。这是完整的代码:

复制位置和四分的代码

function copy(threeMesh, cannonBody) {
    // Copy position
    const position = new CANNON.Vec3(
        threeMesh.position.x,
        threeMesh.position.y,
        threeMesh.position.z
    );
    cannonBody.position.copy(position);

    // Copy rotation
    const quaternion = new CANNON.Quaternion(
        threeMesh.quaternion.x,
        threeMesh.quaternion.y,
        threeMesh.quaternion.z,
        threeMesh.quaternion.w
    );
    cannonBody.quaternion.copy(quaternion);
}

创建 Trimesh 的代码:

function buffer(geo) {
    const bufferedGeo = new THREE.BufferGeometry().fromGeometry(geo);
    return bufferedGeo;
}

function CreateTrimesh(geometry) {
    const vertices = buffer(geometry).attributes.position.array
    const indices = Object.keys(vertices).map(Number)
    return new CANNON.Trimesh(vertices, indices)
}

网格和主体代码:

var platformGeometry = createCustomGeometry(terrain, size + 1, size + 1)
var platformMaterial = new THREE.MeshPhongMaterial({ color: 0x00ff00, wireframe: false, side: THREE.DoubleSide});
var platform = new THREE.Mesh(platformGeometry, platformMaterial);
platform.receiveShadow = true;
platform.castShadow = true
platform.position.set(0, 0, 0)
platform.rotation.x = Math.PI / 2
scene.add(platform);

var platShape = CreateTrimesh(platformGeometry, platform)
var platBody = new CANNON.Body({ mass: 0, shape: platShape });
copy(platform, platBody)
world.addBody(platBody)
© www.soinside.com 2019 - 2024. All rights reserved.