This article is motivated by the need to explain the strange behaviors of the Havok physics simulation Xtra. Long story short: the Havok Xtra needs work. It's a great tool and sure beats rolling your own, but it's not yet a polished product. Hopefully the developers will take note of comments from the community and incorporate some improvements into the next version.
The cloneModelFromCastmember () function lets us do tricky linking of modelresources between Shockwave 3D cast members. Havok doesn't appear to "see" models created in this way, so it will return void when trying to create rigid bodies from such models. One solution posted to the DIRECTOR-L mailing list was to call updateStage () just after calling addModifer (#meshDeform) on the copied model, before creating the rigid body. In essence, we do the following (assuming that "scene" is the cast member we're adding the model into, and "Crate 01" is the cast member containing the model we want to copy, named "TheCrateP"):
model = scene.cloneModelFromCastmember("TheCrate", "TheCrateP", member("Crate 01"))
model.addModifier (#meshdeform)
updatestage ()
hvk.makeMovableRigidBody(model.name, 10.0)
I got this to work only by setting a breakpoint in my script then closing the debug window and continuing execution. However, it wouldn't work under non-debug circumstances. I'm still working on this one, so I'll post a final solution soon. A possible workaround (but less flexible) is to fall back on loadFile () to load the Shockwave 3D file containing the modelresource. This doesn't work for me either, so I'm suspecting that it may be related to loading state, due to the fact that debugging adds a delay that may result in the code running properly.
If two rigid bodies interpenetrate when Havok is initalized, they will pass through each other without colliding. The only workaround is to look for strange collision behavior in the simulation then investigate the starting positions of objects acting strangely.
It just plain crashes if you call it in the collision handler registered with havok.registerInterest (). Seems to work in any other context, though.
For example, add the following code (swap objects names to match your application) to the Shockwave 3D sprite:
hk.registerInterest ("TheBall", #all, 100, 0, #collision, me)
hk.registerInterest ("TheBall", #all, 10, 0, #collision, me)
hk.removeInterest ("TheBall")
You'd think that no collision events are generated, but the collision handler is *still* called! In addition, the frequency of collision events is 10 per second. From this we see that registerInterest () and removeInterest () act like queue operations, one pushes and the other pops. So if you want to make sure you're not generating any collision events, call removeInterest () the same number of times as you called registerInterest ().
First impact is important for executing sound and particle effects to enhance the realism in a scene. If we can't distinguish between first impact and subsequent interactions, for example, when a bullet strikes an object, we'll end up with a rapid staccato of sound effects playing over and over.
There's no direct way of querying the Havok Xtra to determine whether a collision reported to a collision handler is the first collision between two objects or if it's a continuation of the first impact (e.g., pushing, sliding—nearly stationary forces). There are two viewpoints on the definition of "first collision":
If you think about it, the impluse-based method is more physically-correct. Envision a bullet fired into a metal wall: when it ricochets a quick loud sound will result. Now imagine the same bullet is wedged between two metal walls which are slowly pushed together with increasing force. The magnitude of the force exerted on the bullet by the walls in the second case is the same as in the first case, except it takes longer to reach this magnitude in the second case. Thus, we must take into account the force over time.
We can emulate the impulse-based approach using the temporal approach: just analyze the impulse upon the first collision. This way we get a clean definition of first impact and we can use the impulse to modulate whatever special effect we execute. E.g., emit dust particles around the boundary of the collision manifold upon first impact, with the amount and speed of the particles depending on the impulse upon impact. But this still misses some special cases, like when a bullet resting against a wall is "smashed" into it by a mallet with enough force to emit a bullet sound effect.
![]() |
Want to get a list of *all* colliding objects? Just look up havok.collisionList, right? Wrong. To see why, we'll do a simple test. I'll assume you've got a scene setup just like the Havok Quickstart Guide. So there's a Havok member and a Shockwave 3D member with a sphere model called TheBall, a cube model called TheBox, and another cube model called TheGround.
Then, to be *extra sure* we're not missing any in-between steps, we register a time-step callback:
hk.registerStepCallback (#stepper, me)
with the #stepper handler defined as follows:
on stepper me, timeStep if hk.collisionList <> [] then put hk.collisionList end if end
Run this movie—look at the message window. Nothing! Now we try the same experiment, except we register interest in the models TheBall and TheCube:
hk.registerInterest ("TheBox", "TheBall", 10, 0, #collision, me)
Recompile the script and run the movie again. Now the message window displays the names of *only two* of the three objects colliding in the scene. Why? Because havok.collisionList only holds collisions between objects registered to be "of interest"*.
But we haven't exhausted every possibility for achieving what we want—what about havok.enableCollisions ()? Good guess—but it doesn't work either.
Yet another strange artifact of the Havok's collision detection system. To see what I'm talking about, register a time-step callback (as we did above)
hk.registerStepCallback (#stepper, me)
with the #stepper handler defined as follows:
on stepper me, timeStep if hk.collisionList <> [] then put hk.collisionList end if end
Now setup some objects in your scene so that they'll collide with each other, and write a collision handler that prints a notification message every time it's called.
on collision me put "collision handler called" end
Notice that the collision list printed in the message window is empty for time-steps that don't correspond to a call to the collision handler. This means that collisions effectively "don't occur" during any time-steps that run with higher frequency than the collision handler.
See Also:
Optimizing Real-time Physics
Lingo Pitfalls