Wednesday, July 18, 2012

Animating Three.js Legs

‹prev | My Chain | next›

Today is mostly filled with fun as OSCON, but the gods of my chain must be appeased. So I pick back up with the Three.js avatar that I created yesterday:

Today, I would to add simple animation. To keep things short, I am only going to animate the legs. I will worry about the arms tomorrow as the additional rotation should complicate things slightly.

I start by adding two more global variables at the top of my avatar.js script:
var camera, scene, renderer, clock,
avatar, avatar_left_leg, avatar_right_leg;
In Gladius / CubicVR.js, I have been naming those objects and assigning them to variables on demand. It turns out to be possible to do the same in Three.js:
  var left_leg = limb(material); = 'left_leg';
  left_leg.rotation.z = Math.PI;
  left_leg.position.y = -250;
  left_leg.position.x = -100;
  left_leg.position.z = -50;
The limb() is the simple generator from yesterday that produces a grouped set of 3D objects; in this case it produces a leg and foot. After setting the name and doing the same for the right leg, I can assign the global variables after the avatar is assembled:
function init() {
  scene = new THREE.Scene();
  // ...
  avatar = buildAvatar();

  avatar_left_leg = avatar.getChildByName("left_leg", true);
  avatar_right_leg = avatar.getChildByName("right_leg", true);
  // ...
The true second argument to getChildByName() instructs the method to look at the top-level avatar object and all children and grandchildren objects.

I will use the algorithm from the gladius avatar to animate this one as well. First off, I need a clock object. I build that in the initialization code:
document.addEventListener( "DOMContentLoaded", function( e ) {

  clock = new THREE.Clock(true);
The true argument in this case starts the clock immediately rather than waiting for a manual call to start().

With that, I am ready to apply the walking algorithm to the two legs. This is done in the render() method, which is invoked on each subsequent frame:
var w = 500;
function render() {
  var t_float = clock.getElapsedTime()
    , t = t_float * 1000
    , amplitude = (w/2 - Math.abs((t % (2*w)) - w))/w;

  avatar_left_leg.rotation.x  =    amplitude*(Math.PI/8);
  avatar_right_leg.rotation.x = -1*amplitude*(Math.PI/8);

  renderer.render(scene, camera);
The only difference between this animation and the one that I did for Gladius is that the Clock object in Three.js produces a float of seconds when getElapsedTime() is invoked instead of an integer of the number of milliseconds. So, after simply multiplying by 1000, I have the number of milliseconds and... everything works.

I can watch as my avatar steps forward with its right foot:

And then the left:

That will do for a stopping point today. Tomorrow I will get the arms swinging in unison and possibly add some camera panning.

Day #451

No comments:

Post a Comment