Sunday, August 19, 2012

Can't Group Physijs Objects in Three.js

‹prev | My Chain | next›

Up tonight, I plan to add some physics to my Three.js rafting game. This means adding the Physijs physics engine to my HTML:
<!DOCTYPE html>
<html>
  <head>
    <script src="scripts/Three.js"></script>
    <script src="scripts/physi.js"></script>
    <script src="scripts/raft.js"></script>
    <title>Raft</title>
  </head>
  <body>
    <p>j / k to rotate</p>
  </body>
</html>
Then, in raft.js, I configure Physijs:
var raft, camera, scene, renderer;

Physijs.scripts.worker = 'scripts/physijs_worker.js';
Physijs.scripts.ammo = 'ammo.js';

document.addEventListener( "DOMContentLoaded", function() {
  init();
  animate();
});
//...
Then I convert the objects in the game into Physijs objects:
function init() {
  // ...
  scene = new Physijs.Scene;

  // Land
  var land = new Physijs.PlaneMesh(
    new THREE.PlaneGeometry(1e6, 1e6),
    new THREE.MeshBasicMaterial({color: 0x7CFC00})
  );
  scene.add(land);

  raft = new Physijs.ConvexMesh(
    new THREE.TorusGeometry(25, 10, 16, 16),
    new THREE.MeshNormalMaterial()
  );
  raft.position.y = 10;
  raft.rotation.x = Math.PI/2;
  scene.add(raft);
  // ...
}
And lastly, I add physics updates to the animate() function:
function animate() {
  requestAnimationFrame(animate);
  scene.simulate(); // run physics
  render();
}
With my simple setup physijs-ified, I am ready to start adding things to bounce against and push my raft. That is, I create a river with banks:
function riverSegment() {
  var segment = new THREE.Object3D();

  var water = new Physijs.PlaneMesh(
    new THREE.PlaneGeometry(1500, 500),
    new THREE.MeshBasicMaterial({color: 0x483D8B})
  );
  water.position.x = 750;
  segment.add(water);

  var bank1 = new Physijs.BoxMesh(
    new THREE.CubeGeometry(1500, 100, 100),
    Physijs.createMaterial(
      new THREE.MeshNormalMaterial(), 0.2, 1.0
    ),
    0
  );
  bank1.position.x = 750;
  bank1.position.z = -250;
  segment.add(bank1);

  return segment;
}
Only when I push my raft with a simple force:
raft.applyCentralForce(new THREE.Vector3(1e9, 0, -1e9));
It goes right through the wall.

It takes me a very long time to track the problem down. It seems that Physijs objects added to an Object3D are not seen by scene when updated for physics in the animate() block.

I am able to bounce my raft off of the bank if I add it directly to the scene:
function init() {
  // ..
  scene = new Physijs.Scene;

  // River
  var river1 = riverSegment();
  river1.position.x = 50;
  scene.add(river1);

  var bank1 = new Physijs.BoxMesh(
    new THREE.CubeGeometry(1500, 100, 100),
    Physijs.createMaterial(
      new THREE.MeshNormalMaterial(), 0.2, 1.0
    ),
    0
  );
  bank1.position.x = 750;
  bank1.position.z = -250;
  scene.add(bank1);

  raft = new Physijs.ConvexMesh(/* ... */);
  // ...
}
Although that does give me a river bank, I am at a loss for how to easily add it to the scene for the raft to float down. I suppose my riverSegment() function will need to create segments directly in the scene. That is not exactly ideal as I will have to position and rotate river and bank segments individually.

Hopefully I can come up with something better before tomorrow.

Day #483

No comments:

Post a Comment