Reputation: 873
I am using the following code to generate two spheres in cannonjs with Three.js as rendering module.
var world, mass, body, shape, timeStep=1/60,
camera, scene, renderer, geometry, material, mesh;
initThree();
initCannon();
animate();
function initCannon() {
world = new CANNON.World();
world.gravity.set(0,0,0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
geometry = new THREE.SphereGeometry( 3);
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh( geometry, material );
body = new CANNON.Body({mass:0.2});
body.angularVelocity.set(0,5,0);
body.angularDamping = 0.9;
world.add(body);
scene.add(mesh);
geometry = new THREE.SphereGeometry(2);
material = new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe: true } );
mesh = new THREE.Mesh(geometry,material);
body = new CANNON.Body({mass: 1});
body.angularVelocity.set(0,10,0);
body.angularDamping = 0.5;
world.add(body);
scene.add(mesh);
}
function initThree() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.z = 5;
scene.add( camera );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
updatePhysics();
render();
}
function updatePhysics() {
// Step the physics world
world.step(timeStep);
// Copy coordinates from Cannon.js to Three.js
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
}
function render() {
renderer.render( scene, camera );
}
As a result, I do get two spheres on display, but only the second body declared in initCannon() animates. The cannonjs body is somehow not associated with the Three.js mesh. I tried "body.mesh=mesh", but it doesn't help.
The declaration for the mesh was originally done in initThree() but I don't figure if that matters anyway.
What am I doing wrong? Please help. Ask for any more details if needed.
Upvotes: 0
Views: 2325
Reputation: 10776
You're overwriting variables. In the beginning you declare a variable body
, and then you say body = new CANNON.Body...
and after that you use the same sentence for the second sphere, so the first one gets overwritten. You should have a variable body2, a variable mesh2 to avoid this. This approach would work ok if you only need two bodies, but if you're planning to have more you need a different approach: Arrays. In an Array you can store all your bodies and then loop through it and handle each one singularly. Example:
Here we create 10 bodies:
var bodies= []; //create the array
for (var i = 0; i < 10; i++) {
bodies.push({ //insert into the array an object that contains the information for each body/mesh
body: new CANNON.Body({mass:0.2}),
mesh = new THREE.Mesh(geometry,material)
})
};
And then we use them:
for (var i=0, l=bodies.length; i < l; i++) { //we loop through each body
var body = bodies[i]; //this will be the current body
//MOVE THE BODY AND UPDATE THE MESH HERE
}
This would be a better approach. It's more maintainable and you can have as many bodies as the browser can handle. If you only need two, your fastest fix would to add a second variable for the second body and handle it separately.
EDIT: Watch this: https://www.youtube.com/watch?v=tW6pmzd34Hc he stores the circles into an array as well. I hope it makes it a little bit clearer.
Upvotes: 1