Cannon js shape from geopmety

Hi.

I have a mesh that uses a geometry like this.geometry = new THREE.TetrahedronGeometry(0.4,0)

I would like to create a custom shape for cannones so that I can use it for collision detection it has to be accurate, but I am stuck.

Thank you.

I don’t know the functions of the canon.
you can create from your geometry triangles.

https://sbcode.net/threejs/convexgeometry/

It doesn’t work well with concave objects or with holes, in these cases other techniques are needed

with ammo.js is this

              function Float32Concat(a, b) { var c = a.length, d = new Float32Array(c + b.length); return d.set(a), d.set(b, c), d };

              meshmodel = new THREE.BufferGeometry();
                triangle_mesh = new Ammo.btTriangleMesh();
                obj.traverse(child => { // multiple geometry
                    if (child.isMesh && child.geometry && !child.isDebugPhysics) {
                        verticesPos = Float32Concat(verticesPos, child.geometry.attributes.position.array);
                    }
                });
                meshmodel.setAttribute('position', new THREE.BufferAttribute(verticesPos, 3));
                // Calcular o centro geométrico (centroid)                
                for (let i = 0; i < verticesPos.length; i += 3) {
                    centroidMesh.add(new THREE.Vector3(verticesPos[i], verticesPos[i + 1], verticesPos[i + 2]));
                }
                centroidMesh.divideScalar(verticesPos.length / 3);
                if (extra && extra.ignoreCentroid) centroidMesh.set(0, 0, 0);
                for (let i = 0; i < verticesPos.length; i += 9) {
                    vectA.setValue((verticesPos[i] - centroidMesh.x) * scale.x, (verticesPos[i + 1] - centroidMesh.y) * scale.y, (verticesPos[i + 2] - centroidMesh.z) * scale.z);
                    vectB.setValue((verticesPos[i + 3] - centroidMesh.x) * scale.x, (verticesPos[i + 4] - centroidMesh.y) * scale.y, (verticesPos[i + 5] - centroidMesh.z) * scale.z);
                    vectC.setValue((verticesPos[i + 6] - centroidMesh.x) * scale.x, (verticesPos[i + 7] - centroidMesh.y) * scale.y, (verticesPos[i + 8] - centroidMesh.z) * scale.z);
                    // Adicionar os triângulos ao btTriangleMesh
                    triangle_mesh.addTriangle(vectA, vectB, vectC);
                }
    
                // Criar o shape apropriado para o btTriangleMesh (btBvhTriangleMeshShape ou btConvexTriangleMeshShape)
                shape = new Ammo.btConvexTriangleMeshShape(triangle_mesh, true); // Outra opção caso seja necessário um shape convexo
                // Definir a margem do shape, se necessário
                shape.setMargin(this.conf.margim);
                break;

Thank you.

I am trying this but and it works untils the objects colide I get and error cannon-es.js?v=4e55d3ca:716 Uncaught TypeError: Cannot read properties of undefined (reading ‘x’)

this.geometry = new THREE.IcosahedronGeometry(0.4,0) let pos = this.geometry.attributes.position; let count = pos.count/3; let bary = [];
    for(let i = 0; i < count; i++){
       bary.push(0,0,1, 0,1,0, 1,0,0);
    }
    bary = new Float32Array(bary);
  
    this.geometry.setAttribute('barycentric', new THREE.BufferAttribute(bary, 3));
   
    this.mesh = new THREE.Mesh(this.geometry, this.material);
    this.scene.add(this.mesh);

    let position = this.geometry.attributes.position.array;
    const icosahedronPoints = [];
    for (let i = 0; i < position.length; i += 3) {
        icosahedronPoints.push(new CANNON.Vec3(position[i], position[i + 1], position[i + 2]));
    }
    
    const icosahedronFaces = [];
    for (let i = 0; i < icosahedronPoints.length; i += 3) {
        icosahedronFaces.push([i, i + 1, i + 2]);
    }
    
    this.icosahedronShape = new CANNON.ConvexPolyhedron({
        vertices: icosahedronPoints,
        faces: icosahedronFaces,
    })
  

    // Create a ConvexPolyhedron shape for Cannon-ES
    this.body = new CANNON.Body({ mass: 1 })
    this.body.addShape(this.icosahedronShape)
    this.body.position.x = this.mesh.position.x
    this.body.position.y = this.mesh.position.y
    this.body.position.z = this.mesh.position.z
    this.world.addBody(this.body)

https://codesandbox.io/p/sandbox/08s1u

import { Geometry } from "three-stdlib"

/**
 * Returns legacy geometry vertices, faces for ConvP
 * @param {THREE.BufferGeometry} bufferGeometry
 */
function toConvexProps(bufferGeometry) {
  const geo = new Geometry().fromBufferGeometry(bufferGeometry)
  // Merge duplicate vertices resulting from glTF export.
  // Cannon assumes contiguous, closed meshes to work
  geo.mergeVertices()
  return [geo.vertices.map((v) => [v.x, v.y, v.z]), geo.faces.map((f) => [f.a, f.b, f.c]), []]
}

then again, i would not bother or waste time trying it. cannon is too slow to handle custom shapes/convex polyhedrons. it can barely keep up with simple shapes but it is about multiple thousands of times slower handling complex shapes than rapier and all the others. a few TetrahedronGeometry and your fps goes from 120 to 1.

1 Like

I tried it dose not work, I gave up and moved to Rapier, it took a few hours to get my brain around it but it is more flexible and better designed for this kind of things,…

Are you heared about jolt physics in three.js examples. It have many good examples. Yesterday i wrote code with gpt which convert three.js geometry to jolt physics geometry. Rapier to good and fast.
https://jrouwe.github.io/JoltPhysics.js/

Thank you for your help but I figured it out with rapier, for what I need now is good enough as for the cannon it is not well maintained when it comes to custom geometries, if you can work with the built it geometries is good but not with custom geometries I have spent a few days on it and could not find a way to make it work.