Physics from Geometry hole objects - Ammo


https://didisoftwares.ddns.net/7/index.html

Has anyone managed to apply physics to a geometry that has a hole?
I know it’s possible with convexhull, but it covers the geometry hole. I’m trying directly with the triangles but the physics is strange, for example the tire stays upright.

console itens: model1, model2, tire
example: physics.bodyJump(model2,new THREE.Vector3(0,10,0));

https://didisoftwares.ddns.net/7/js/physics.js

case 'mesh':
                let triangleArrays = [];
                triangle_mesh = new Ammo.btTriangleMesh();
                verticesPos = new Float32Array();
                obj.traverse(child => { //multiple geometry
                    if (child.isMesh && child.geometry) {                        
                        verticesPos = Float32Concat(verticesPos,child.geometry.attributes.position.array);
                    }
                });
                let computedTriangles = 0;
                for (let i = 0; i < verticesPos.length; i += 9) {
                    let v1 = new Ammo.btVector3(verticesPos[i], verticesPos[i + 1], verticesPos[i + 2]);
                    let v2 = new Ammo.btVector3(verticesPos[i + 3], verticesPos[i + 4], verticesPos[i + 5]);
                    let v3 = new Ammo.btVector3(verticesPos[i + 6], verticesPos[i + 7], verticesPos[i + 8]);
                    triangle_mesh.addTriangle(v1, v2, v3, false);
                    Ammo.destroy(v1);
                    Ammo.destroy(v2);
                    Ammo.destroy(v3);
                    computedTriangles++;
                    if (computedTriangles > 1) {
                        shape = new Ammo.btConvexTriangleMeshShape(triangle_mesh, true);
                        triangle_mesh = new Ammo.btTriangleMesh();
                        computedTriangles = 0;
                        triangleArrays.push(shape);
                    }
                }
                shape = new Ammo.btCompoundShape(true, triangleArrays.length - 1);
                let transform = new Ammo.btTransform();
                transform.setIdentity();
                for (var i = 0; i < triangleArrays.length; i++) {
                    shape.addChildShape(transform, triangleArrays[i]);
                }
                meshmodel = new THREE.BufferGeometry();
                meshmodel.setAttribute('position', new THREE.BufferAttribute(verticesPos, 3));
                for (let i = 0; i < verticesPos.length; i += 3) {
                    triangles.push({ x: verticesPos[i], y: verticesPos[i + 1], z: verticesPos[i + 2] });
                }

                break;
            case 'triangle':
                meshmodel = new THREE.BufferGeometry();
                triangle_mesh = new Ammo.btTriangleMesh();

                // Declare vetores para as posições dos vértices
                vectA = new Ammo.btVector3(0, 0, 0);
                vectB = new Ammo.btVector3(0, 0, 0);
                vectC = new Ammo.btVector3(0, 0, 0);

                // Recupera as posições dos vértices da geometria do objeto
                //verticesPos = obj.geometry.attributes.position.array;
                verticesPos = new Float32Array();
                obj.traverse(child => { //multiple geometry
                    if (child.isMesh && child.geometry) {                        
                        verticesPos = Float32Concat(verticesPos,child.geometry.attributes.position.array);
                    }
                });
                meshmodel.setAttribute('position', new THREE.BufferAttribute(verticesPos, 3));

                let normals = new Float32Array();
                obj.traverse(child => { //multiple geometry
                    if (child.isMesh && child.geometry) {                        
                        normals = Float32Concat(normals,child.geometry.attributes.normal.array);
                    }
                });
                // Recupera as normais das faces, se estiverem disponíveis
                //let normals = obj.geometry.attributes.normal.array;

                // Adiciona os triângulos ao btTriangleMesh
                for (let i = 0; i < verticesPos.length; i += 9) {
                    // Define os vértices A, B, C para cada triângulo
                    vectA.setValue(verticesPos[i], verticesPos[i + 1], verticesPos[i + 2]);
                    vectB.setValue(verticesPos[i + 3], verticesPos[i + 4], verticesPos[i + 5]);
                    vectC.setValue(verticesPos[i + 6], verticesPos[i + 7], verticesPos[i + 8]);

                    // Adiciona os triângulos ao btTriangleMesh
                    triangle_mesh.addTriangle(vectA, vectB, vectC);

                    // Se as normais estiverem disponíveis, também pode ser útil usá-las para corrigir a orientação
                    if (normals && normals.length >= i + 9) {
                        let normalA = new Ammo.btVector3(normals[i], normals[i + 1], normals[i + 2]);
                        let normalB = new Ammo.btVector3(normals[i + 3], normals[i + 4], normals[i + 5]);
                        let normalC = new Ammo.btVector3(normals[i + 6], normals[i + 7], normals[i + 8]);
                        Ammo.destroy(normalA);
                        Ammo.destroy(normalB);
                        Ammo.destroy(normalC);
                    }
                }

                // Limpa os recursos Ammo
                Ammo.destroy(vectA);
                Ammo.destroy(vectB);
                Ammo.destroy(vectC);
                // Cria o shape apropriado para o btTriangleMesh (btBvhTriangleMeshShape ou btConvexTriangleMeshShape)
                //shape = new Ammo.btBvhTriangleMeshShape(triangle_mesh, false); // Utilize btBvhTriangleMeshShape ou btConvexTriangleMeshShape conforme necessário
                shape = new Ammo.btConvexTriangleMeshShape(triangle_mesh, true); // Outra opção caso seja necessário um shape convexo

                // Define a margem do shape, se necessário
                shape.setMargin(this.conf.margim);

                break;

Do you initialize the inertia tensor? The inertia tensor controls how/what axis the object tends to rotate around, based on the distribution of its mass.
The math to compute for non platonic solids is gnarly, but you can often just fake up 3 number values until it “feels” right.

from chatgpt, “ammo.js inertia tensor setup for a roughly cylindrical/wheel kind of thing”:

// Assume mass, radius, and height are already defined
var mass = 1; // Replace with actual mass
var radius = 1; // Replace with actual radius
var height = 2; // Replace with actual height

var cylinderShape = new Ammo.btCylinderShape(new Ammo.btVector3(radius, height * 0.5, radius));

// Calculate inertia tensor components
var I_x = (1 / 12) * mass * (3 * radius * radius + height * height);
var I_y = (1 / 2) * mass * radius * radius;
var I_z = I_x;

var inertia = new Ammo.btVector3(I_x, I_y, I_z);
cylinderShape.calculateLocalInertia(mass, inertia);

// Create the rigid body
var transform = new Ammo.btTransform();
transform.setIdentity();
var position = new Ammo.btVector3(0, 0, 0); // Replace with actual position
transform.setOrigin(position);
var motionState = new Ammo.btDefaultMotionState(transform);
var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, cylinderShape, inertia);
var body = new Ammo.btRigidBody(rbInfo);

// Add the body to the dynamics world
dynamicsWorld.addRigidBody(body);

1 Like

There is a relatively recent update including “closed rings” kind of shapes (aka: dynamic concave shapes) btGImpactMeshShape

Here is the githack link directly using the demo source in the “examples”
https://rawcdn.githack.com/kripken/ammo.js/1ed8b58c7058a5f697f2642ceef8ee20fdd55e10/examples/webgl_demo_gimpact_chain/index.html

The readme of ammo.js was not updated to show this demo.

1 Like

The new version is very good, however this model still uses the convexhull that joins all the points of an object to create the physics, this covers holes that the object has

you were right the error was the center of mass of the object, when imported the object.scene may not be in the center of mass.
i used this conversion before physics apply.
image

1 Like

This is a solution for too, use this for impact objects, but need be called for only 1 object per time:
https://didisoftwares.ddns.net/7/index.html

physics.createObj(child,‘geometry’,‘obj’,null,1);