Saturday, August 11, 2012

Getting Started with Physijs

‹prev | My Chain | next›

I think I have a decent handle on the Box2D.js plugin for Gladius (so I probably understand ~5% or so). I liked it very much, especially the ability to express collision events. Tonight, I am going to take a look at another physics engine: Physijs for Three.js.

For this, I am revisiting my Three.js avatar island. I already have collision detection implemented in this island—there is an invisible fence all around the island preventing the avatar from leaving:


The collision detection is based on the rays built into Three.js. Since a ray has position and direction, it makes it easy to see what is in the way. Three.js exploits this by including methods to calculate distance until impact as well as methods to aid in detecting collisions.

In my existing implementation, I use a ray to check for a collision with an invisible fence. If there is a collision, I disable the movement state of my avatar:
  var vector = new THREE.Vector3( x, 0, z );
  var ray = new THREE.Ray(controls.object.position, vector);
  var intersects = ray.intersectObjects(blockers);

  if (intersects.length > 0) {
    if (intersects[0].distance < 75) {
      if (controls.moveLeft) controls.moveLeft = false;
      if (controls.moveRight) controls.moveRight = false;
      if (controls.moveBackward) controls.moveBackward = false;
      if (controls.moveForward) controls.moveForward = false;
    }
  }
There are two problems with this approach. First, it only detects collisions in the direction of the ray. If something bumps my avatar from the side no collision would be seen. The second problem is that I have to do any of this myself. With Box2D, I simply created a static object, which stopped my avatar from moving any further.

I did run into some problems with controls and movement under Box2D. I would expect similar problems with Physijs, but maybe I'll get lucky.

So I start by grabbing the latest Physijs:
wget https://github.com/chandlerprall/Physijs/tarball/master -O physijs.tar.gz
I untar the download and copy the JavaScript files into my project:
➜  src  tar tzf ~/Downloads/physijs.tar.gz 
➜  src  cd chandlerprall-Physijs-f7b5b0b 
➜  chandlerprall-Physijs-f7b5b0b  cp physi*.js ~/repos/three-my/scripts/
I also grab ammo.js since physijs is based on it:
➜  chandlerprall-Physijs-f7b5b0b  cp examples/js/ammo.js ~/repos/three-my/scripts 
Next, I add a <script> tag pointing to physijs:
<!DOCTYPE html>
<html>
  <head>
    <script src="scripts/Three.js"></script>
    <script src="scripts/Tween.js"></script>
    <script src="scripts/physi.js"></script>
    <script src="scripts/avatar.js"></script>
    <title>Avatar</title>
  </head>
  <body>
    <p>w, a, s, d to move</p>
  </body>
</html>
I do not need to add a <script> tag for ammo.js—that is pulled in via Ajax when define in avatar.js:
Physijs.scripts.worker = 'scripts/physijs_worker.js';
Physijs.scripts.ammo = 'ammo.js';
Then I replace the Three.js scene object with a Physijs scene:
function init() {
  // scene = new THREE.Scene();
  scene = new Physijs.Scene;
  // ...
}
At this point, everything is loading as desired (including the worker and ammo scripts). The scene is still displaying correctly and I can still move the avatar with first-person controls. That is some nice compatibility.

I add a ball to the scene:
  // A ball
  var ballGeometry = new THREE.SphereGeometry(100)
    , ballMaterial = new THREE.MeshNormalMaterial()
    , ball = new Physijs.SphereMesh(ballGeometry, ballMaterial);
  ball.position.z = -500;
  ball.position.y = 50;
  scene.add(ball);
I also build the avatar's body with a Physijs mesh:
  var body_geometry = new THREE.CylinderGeometry(1, 100, 100);
  // var body = new THREE.Mesh(body_geometry, material);
  var body = new Physijs.ConvexMesh(body_geometry, material);
  avatar.add(body);
Lastly, I tell the scene to simulate physics whenever the scene renders:
unction render() {
  // ...
  scene.simulate(); // run physics

  renderer.render(scene, camera);

  controls.update(clock.getDelta());
}
Unfortunately, when I move my avatar into the ball, it passes right through. Also my ball melts into the island:


Ah well, this is a good start. I suspect the melting is due to the island not being a Physijs surface. As for the avatar not bumping into the ball, I suspect that this is because I am using first-person controls to move the avatar rather than physics. I will get started tackling my theories tomorrow.


Day #475

No comments:

Post a Comment