Open AshDevFr opened 3 years ago
I have found that if you use an indexed geometry, and then loop through points and faces, convex on convex works pretty well most of the time. If you need to merge vertices, I would recommend BufferGeometryUtils or if you are using an import statement this will work. code for creating convex from indexed geometry:
function createFromIndexed(mesh){
let geometry = mesh.geometry;
geometry.deleteAttribute('normal');
//if not planning on putting textures on the mesh, you can delete the uv mapping for better vertice merging
//geometry.deleteAttribute('uv');
geometry = THREE.BufferGeometryUtils.mergeVertices(geometry);
//if using import statement
//geometry = BufferGeometryUtils.mergeVertices(geometry);
mesh.geometry = geometry;
let position = geometry.attributes.position.array;
let geomFaces = geometry.index.array;
const points = [];
const faces = [];
for(var i = 0;i<position.length;i+=3){
points.push(new CANNON.Vec3(position[i],position[i+1],position[i+2]);
}
for(var i = 0;i<geomFaces.length;i+=3){
faces.push([geomFaces[i],geomFaces[i+1],geomFaces[i+2]);
}
return new CANNON.ConvexPolyhedron(points,faces);
}
Has this been solved yet? I'm getting the same problem.
Because of the way that cannon.js is programmed, if the convex triangles are not all connected, then convex-convex collision will not work. Which is why you can use either buffer geometry utils to merge the vertices, or make your own geometry that is indexed. unfortunately, you have to do one of the two for convex-convex collision, the answer stated above, does the one where you merge the vertices with buffer geometry utils.
Greetings everyone.
Convex polyhedron never behaved correctly for me with more complex shapes. To fix this, I created a Python script with blender that parses the boxes in a collection, which you should name "Colliders," then it will print out json format text in the console, and using that json file I parse it and generate the proper box colliders in my game.
Here is the blender python script:
import bpy
import math
collection = bpy.data.collections.get("Colliders")
# Get all objects in the scene
all_objects = collection.objects
# Count meshes for formatting
meshCount = 0
for obj in all_objects:
if obj.type == 'MESH':
meshCount += 1
# Print mesh information using ID counter
objectID = 0
print("{")
for obj in all_objects:
if obj.type == 'MESH':
print(" \"box_" + str(objectID) + "\":{")
# Position
position = obj.location
print(" \"position\":{")
print(" \"x\":" + str(position.x) + ",")
print(" \"y\":" + str(position.y) + ",")
print(" \"z\":" + str(position.z))
print(" },")
# Scale
scale = obj.scale
print(" \"scale\":{")
print(" \"x\":" + str(scale.x) + ",")
print(" \"y\":" + str(scale.y) + ",")
print(" \"z\":" + str(scale.z))
print(" },")
# Rotation (Euler)
rotation = obj.rotation_euler
print(" \"rotation\":{")
print(" \"x\":" + str(math.degrees(rotation.x)) + ",")
print(" \"y\":" + str(math.degrees(rotation.y)) + ",")
print(" \"z\":" + str(math.degrees(rotation.z)))
print(" }")
if(objectID != meshCount - 1):
print(" },\n")
else:
print(" }")
objectID += 1
print("}")
That will generate the json text. Copy that from your console, paste it in a .json file, and parse it like so in a js file with cannon:
/*
* Creating the level collision geometry
*/
async function GenerateLevelColliders(){
// RigidBody
levelRigidbody = new CANNON.Body({
type: CANNON.Body.STATIC
});
// Parse the JSON file
await fetch("levelColliders/level_" + currentLevel + ".json")
.then(response => response.json())
.then(data => {
let boxID = 0;
for (let boxKey in data) {
if(data.hasOwnProperty(boxKey)){
const box = data[boxKey];
const position = box.position;
const scale = box.scale;
const rotation = box.rotation;
let boxShape = new CANNON.Box(new CANNON.Vec3(scale.x, scale.y, scale.z));
// Set the last box as the "checkpoint"
if(boxID == Object.keys(data).length - 1){
// Create a specific body for final shape
levelEndRigidbody = new CANNON.Body({
type: CANNON.Body.STATIC
});
// Add its box
levelEndRigidbody.addShape(
boxShape,
new CANNON.Vec3(position.x , position.z, -position.y), // ~ Y is up in blender
EulerToQuaternion(rotation.x + 90, rotation.z, -rotation.y)
);
} else {
// Add each other box given position, scale and rotation
levelRigidbody.addShape(
boxShape,
new CANNON.Vec3(position.x , position.z, -position.y), // ~ Y is up in blender
EulerToQuaternion(rotation.x + 90, rotation.z, -rotation.y)
);
}
boxID += 1;
}
}
})
.catch(error => {
console.error('Error parsing JSON file:', error);
});
// Add the bodies
PhysicsWorld.addBody(levelRigidbody);
PhysicsWorld.addBody(levelEndRigidbody);
console.log("Finished loading: levelColliders/level_" + currentLevel + ".json ☑");
}
Keep in mind you must:
Hope this is helpful for game devs building larger levels with a bunch of colliders. The only downside to this is your colliders will use only boxes as primitives, but I'm sure this pipeline can be applied to spheres, and even tris.
I know this issue is pretty old but I am now also getting a problem with convex hulls which is that my objects just completely fly away after they collide with something, is there a way to fix this without running external scripts? Also I am not familiar with blender's scripting, can anyone show me how this works with some screenshots? thx a lot :) (please excuse my bad english)
Hi, I have been trying to use CANNON.ConvexPolyhedron to handle collision between different type of objects.
When they collide with the plane or other type of shapes there is no issue but when two ConvexPolyhedron collide I get an error:
This is how I create my shape:
I am using
Three.js
version0.126.1
andCannon.js
version0.6.2
I created a sandbox if anybody wants to take a look: https://codesandbox.io/s/hardcore-glitter-wxscw?file=/src/index.js
Am I missing something ?
Thank you for your time.