This whole walking Gladius avatar think has taken a bit longer than expected. Still, I think I made some good progress last night. I have the right leg of the avatar moving back-and-forth:
I wound up with a poor algorithm for implementing the back and forth—effectively hard coding when to swing the leg in the opposite direction. I had originally planned on leaving it as-is, preferring working to elegant. But the ugly started to wear on me.
And it also occurred to me that, if I need to oscillate between 1 and -1, that is what sines and cosines are for. So I switch my game task function to use this instead:
var task = new engine.FunctionTask( function() {
var entity = space.findNamed("right-leg-frame")
, transform = entity.findComponent("Transform")
, amplitude = Math.sin(space.clock.time/500);
transform.setRotation([0,0, amplitude*(Math.PI/8)]);
});
task.start();
The problem with this approach is that the leg swings back and forth like a pendulum (slowing at the extremes), not so much like a leg. I eventually stumble on an algorithm for more of a triangle wave. which seems to do the trick:
var task = new engine.FunctionTask( function() {
var entity = space.findNamed("right-leg-frame")
, transform = entity.findComponent("Transform")
, t = space.clock.time
, w = 500
, amplitude = (w/2 - Math.abs((t % (2*w)) - w))/w;
transform.setRotation([0,0, amplitude*(Math.PI/8)]);
});
The arms are a little more difficult because of the angles. To handle these, I add two frames of reference: one for the initial shift and rotation relative to the body and a second that I can use to implement simpler swinging: space.add(new engine.Entity("right-arm-frame1",
[
new engine.core.Transform([0.5, 0, 0], [0, -Math.PI/8, Math.PI/3])
],
["avatar"],
space.findNamed("body")
));
space.add(new engine.Entity("right-arm-frame",
[
new engine.core.Transform()
],
["avatar"],
space.findNamed("right-arm-frame1")
));
space.add(new engine.Entity("right-arm",
[
new engine.core.Transform([0, -0.5, 0]),
new cubicvr.Model(resources.cylinder_mesh, resources.blue_material)
],
["avatar"],
space.findNamed("right-arm-frame")
));
At this point, my game task()
is doing more than tranforming one limb. It has to coordinate four extremities. So I move the arm and leg transforms out of the game
task()
, leaving task()
to just swing the arms: var w = 500
, arm1 = space.findNamed("left-arm-frame").findComponent("Transform")
, arm2 = space.findNamed("right-arm-frame").findComponent("Transform")
, leg1 = space.findNamed("left-leg-frame").findComponent("Transform")
, leg2 = space.findNamed("right-leg-frame").findComponent("Transform");
var task = new engine.FunctionTask( function() {
var t = space.clock.time
, amplitude = (w/2 - Math.abs((t % (2*w)) - w))/w;
leg1.setRotation([ amplitude*(Math.PI/8), 0, 0]);
leg2.setRotation([ -1*amplitude*(Math.PI/8), 0, 0]);
arm1.setRotation([ 0, 0, -1*amplitude*(Math.PI/8)]);
arm2.setRotation([ -1*amplitude*(Math.PI/8), 0, 0]);
});
After rotating the camera a bit for a better view, I see the arms and legs move:And do so in unison:
That will do as a nice stopping point for tonight. The chain of reference frames is both handy (for calculations) and a pain (for added code). I will have to mull that over. That aside, I'm pretty happy with the implementation as well as the result.
Day #448
No comments:
Post a Comment