For the last day or two, I've been struggling with Box2D.js collision detection in Gladius. I was able to get the plugin sourced and running. I was even able to get some collisions detected. But I was thwarted when trying to detect collisions along the z-axis. Everything was registering as a collision.
Luckily, Gladius has some very helpful authors. Late last night, Alan Kligman pointed out what I was not seeing: that Box2D.js is only a 2D library. By default, Box2D is detecting collisions in the XY plane. Anything along the z-axis is projected down onto the XY plane, meaning that I will see collisions if the XY coordinates of colliding objects align—even if they are separated by 1,000,000 pixels in along the z-axis.
In my avatar simulation, the x-axis runs from left to right:
That is perfectly OK, but the y-axis (the other axis on which collision coordinates matter), is up-and-down. Since the avatar is constrained to walking on the island, the y-axis coordinate is always zero. In other words, I am trying to detect collisions in a useless dimension.
My first inclination is to rotate the Box2D entities into the XZ plane. Rotating 90° about the y-axis ought to shift the collision planes from XY to XZ:
var obstacle = new engine.Entity( "obstacle-box2d",
[
new engine.core.Transform([0, 0, 10], [Math.PI/2, 0, 0]),
obstacleBox2d,
new cubicvr.Model( resources.sphere_mesh, resources.yellow_material )
]
);
space.add( obstacle );
space.add(new engine.Entity("avatar-box2d",
[
new engine.core.Transform([0, 0, 0], [Math.PI/2, 0, 0]),
avatarBox2d
],
[],
space.findNamed("avatar")
));
Only this has no effect. Immediately after page load, I still see a collision event from the callback: var bodyDefinition = new box2d.BodyDefinition();
var fixtureDefinition = new box2d.FixtureDefinition({
shape:new box2d.BoxShape(0.25,0.25)
});
var obstacleBox2d = new box2d.Body({
bodyDefinition: bodyDefinition,
fixtureDefinition: fixtureDefinition
});
obstacleBox2d.onContactBegin = function(event){
console.log("Obstable contact begin");
this.owner.findComponent( "Model").setMaterialDefinition(resources.grey_material);
};
So it seems that everything really needs to be in the XY plane. This is a bit of a pain, but I re-position the camera along the y-axis (instead of the usual z-axis) and rotate back to the origin: space.add(new engine.Entity("camera",
[
new engine.core.Transform([0, -25, 5], [Math.PI/2, 0, 0]),
new cubicvr.Camera()
]
));
After removing the previous rotation attempts, I now see no collision as I place the obstacle anywhere in the XY plane (the obstacle remains yellow unless there is a collision):But if there is an actual collision, the obstacle detects it:
At this point, I have broken my avatar down to the most basic pieces in order to understand the problem. Tomorrow, I am going to put it back together to make sure that it all still works.
Day #470
No comments:
Post a Comment