[ODE] ODE in Myst V: A Postmortem
Colin Bonstead
colin at cyan.com
Tue Jun 21 15:58:17 MST 2005
I've pretty much wrapped up the physics work in Myst V, so I figured I'd
send out an email to the list with the details of what kind of issues I
ran into.
For our previous game, Uru, we used the Havok 1 engine for our physics.
The characters were simulated as 3 different size spheres stacked on top
of each other. Movement was accomplished by just setting the linear
velocity based on the player animation. This worked well since Havok
resolved all collisions each frame, so there wasn't any "jittering" when
you pushed yourself into a wall. We had some physical objects scattered
around that you could push, but no real fancy physical interaction.
When we were reworking the engine for Myst V though, we decided to drop
Havok and go with ODE. The main reasons were that we wanted to ship on
Mac, which Havok didn't support (thus killing the Uru Mac port we were
going to do), and ODE was free. We had evaluated ODE during Uru, but at
that time it didn't support trimeshes, which was a deal breaker.
Going from Havok to ODE, the main issues were the lack of convex hull
support and the fact that collisions weren't completely resolved each
step. In Uru, pretty much all detectors were made from convex hulls.
Since they have a definite inside and outside they can detect when
another physical is completely inside them, unlike a trimesh. Since ODE
doesn't have hulls I had to make the artists use either box or sphere
detectors, or use a trimesh and make sure the object that's going to be
inside them will always be touching a triangle. That was unfortunate,
but they adapted to those restrictions.
The bigger problem was the collision resolution. Since ODE uses the ERP
to resolve collisions over multiple steps you can run into cases where
an object being forced into some static geometry will push in and out
instead of stopping dead. In Havok the penetrations were always
resolved, so our character controller was much simpler.
For the Myst V avatar I used a capped cylinder. In Havok we kept our
characters upright by setting an inertial tensor that was wacked out
enough to make it impossible to get any angular rotation. (Then for
turning we would just manually set the rotation.) That didn't work in
ODE so I initially tried making a joint that would disallow any rotation
in the x and y. That worked, but after scooting around a little the
character would begin slowly tipping over. It was a problem I ran into
more than once, where a joint just wasn't stable. So, I gave up on the
idea of a joint and went with what Alen from Croteam suggested and just
created a flag in ODE that would prevent a body from ever getting
angular velocity. (I just added a few checks in the step for the flag
and didn't add angular velocity in those cases.)
Moving the avatar by setting the linear velocity directly, like we did
in Havok, didn't work too well. I don't remember exactly what happened,
but I do remember that everyone on the mailing list said it was a bad
idea. Again I went with Alen's suggestion here and made a custom joint
that set the x and y linear velocity. That worked fine but due to the
collision joint sponginess I needed an additional check to keep the
avatar from running full force into walls. I added an additional capped
cylinder that was slightly bigger than the collision one and it just
detected collisions without making any contact joints. Then I took the
normals from all the contacts and decided if we were about to run into a
wall. If so, I would redirect the velocity to slide along the wall, or
just kill it if there was nowhere to go.
To get good contact normals from the trimesh I had to add another
special flag to only return normals. By default you'll get the best
separating axis, which isn't necessarily the normal of the triangle you
hit (for instance, if you're on an edge). In addition, to clean up the
amount of contacts I implemented the contact reduction method from Game
Gems 4(?), which is checked into the unstable tree.
The main problem I ran into was with the instability of the ODE joints.
I run our simulation at a fixed 100 Hz, and clamp the per-frame delta to
a max of 100 ms (so we don't kill the framerate even more by doing too
many steps during a slow frame). That works great on fast machines, but
on slow ones (ie dropping below 10 fps at times) the joints tend to get
unreliable. The avatar can run pretty fast (around 20 feet per second I
believe) and we ran into a problem near the end of development where in
low framerate situations the avatar would sometimes pass through boxes.
Changing those to trimeshes fixed the problem, I think because they
generate more contacts. I did a lot of work playing with different ERP
values, step sizes, stepping methods, etc, but nothing fully cured the
problem.
Overall I'm fairly happy with ODE, in the sense that the price is right
and it allowed us to do a Mac version. However, I wouldn't recommend it
to any other commercial game developers. The community is pretty
helpful, but it just isn't the same as having support from a commercial
physics engine. Also, development is pretty stagnant right now. The
biggest reason I'd recommend against it though is the fact that Novodex
is basically being given away for free if you commit to using a decent
amount of physics in your game. Ageia wants to create a market for its
physics accelerators, and they're willing to take a bath on Novodex to
do that. I'm sure Havok is not happy about that.
Anyway, if anyone has any questions or comments I'll be happy to reply.
Colin Bonstead
Lead Engine Programmer
Cyan Worlds
More information about the ODE
mailing list