Seeking feedback on Havok Physics visualizations for debug

I’m seeking feedback on my approach to physics debugging visualization.

The ideas and development were spurred by @regna post here and the contributions in that thread by @roland, @Cedric, @riven04, and @qq2315137135.

All the details are below. To set the stage, here is how you enable the visualization of lines emanating from a contact point in the direction of its normal and scaled relative to the size of the impulse imparted. All observers, data management, and the translation of the PhysicsEvent data into a visualization every frame are handled within the class.

var debugLines = new ContactLines({width:0.005,propertyName:"impulse",scale:2e6},hk,scene).enable();

And to turn the visualization and data collection off:

debugLines.disable();

Please review the following and feel free to provide feedback about any aspect. I am already planning to translate it into TypeScript to improve the likelihood of it becoming integrated and distributed with Babylon.

I have a set of classes that enable easy visualizion of Havok physics. I’m looking for feedback on this initial approach. After a brief review of a few engines and their associated mechanisms for visualization, it appears that PhysicsDebug layers from other engines separate out 1) the collection of the data (which come from the engine itself) and 2) a defined interface for visualization or transmission of that data. An object/instance of a visualization class implements that defined interface that is attached to and called directly from the engine. The physics engines vary in the level of integration with the visualization class, thus the visualization interface varies.

My approach here attaches to Havok (by passing in the Plugin) and extracts data either from Havok Plugin methods (havokPlugin) or directly from the Engine (havokPlugin._hknp). The Havok Plugin is a thin layer above the Havok engine itself. Some of the methods in the engine can be quite complicated, such as when body instances or compound shapes are involved. I’m leaning towards adapting to the Plugin instead of the Engine because it reduces this complexity. And because user-level Babylon code only uses the Plugin, any differences between the Engine and the Plugin still constitute a “problem with Babylon Havok,” so there is little to be gained by extracting data “closer to Havok.” When the information needed is only available from the Engine or when there are performance improvements from avoiding additional memory or translation, the Engine is accessed directly.

// Examples of Plugin methods used:
//havokPlugin._bodies
//havokPlugin.onCollisionObservable

// Examples of Havok engine methods used:
//havokPlugin._hknp.HP_Body_GetQTransform
//havokPlugin._hknp.HP_Body_GetActivationState

Below, you’ll find an explanation of my approach including what is already implemented and ideas for additional visualizations and options. Please comment!

/**
 * 
 * Currently, the general pattern is shown below. Examples are shown at the end.
 *  
 * class PhysicsDebug* { // for example: ContactLines, ContactPoints, DebugMeshes
 * constructor(options, havokPlugin, scene) - allocate empty arrays, capture options
 *     options - {parameter:value,...}
 * enable() - allocate memory and enable observers for rendering and object management
 * disable() - deallocate memory to minimal and disable observers
 *    - memory allocated is similar to post-constructor
 * set parameter(value) - change parameter value
 *    .
 *    .
 *    .
 * }
 * 
 * DebugMeshes contains options to show physics parameters related to PhysicsBody
 * and in the local space of the PhysicsBody:
 * - wireframe of PhysicsBody shape
 * - ActivationState ACTIVE or INACTIVE (color)
 * - can add? CG, inertia vector, local axes, bounding box
 * - maybe: face normals
 * - what about? ActivationControl, PreStepType, MotionType (with duration)
 * - what about? SimpleMaterial option along with wireframe? 
 * - what about? velocity angular/linear, possibly scaled relative to maximums?
 * - what about? adding/removing per body? specifying inclusion or exclusion lists?
 * 
 * ContactPoints shows the points of collision or trigger (with duration)
 * - currently a sphere with specified diameter
 * - what about? color based on EventType? attached to one or both Meshes with duration?
 * 
 * ContactLines shows lines at contact points in the direction of its normal.
 * - width parameter
 * - scaled by impulse (collision only) or distance (collision or trigger)
 * - additional scale parameter
 * - color by eventType: Collision / Trigger, Start / Continue / Stop
 * - what about? adding duration?
 * - what about maybe? highlight facet on mesh (with duration)?
 * 
 * Constraints (not yet started)
 * - with limits?
 * - what about? motors and spring-dampened motors
 * Types: BALL_AND_SOCKET, DISTANCE, HINGE, LOCK, PRISMATIC, SIX_DOF, SLIDER
 * 
 * No idea yet on how to handle these, but here is a list of general constraint parameters.
 * 
 * PhysicsConstraintParameters {
 *     axisA?: Vector3;
 *     axisB?: Vector3;
 *     collision?: boolean;
 *     maxDistance?: number;
 *     perpAxisA?: Vector3;
 *     perpAxisB?: Vector3;
 *     pivotA?: Vector3;
 *     pivotB?: Vector3;
 * }
 * 
 * Example usage:
 * new ContactLines({width:0.005,propertyName:"impulse",scale:2e6},hk,scene).enable();
 * new ContactPoints({duration:1000,diameter:0.01},hk,scene).enable();
 * new DebugMeshes(hk,scene).enable();
 */
5 Likes

I would add that physics visualization/debug vis is the first step toward a physics editor.
Constraints are a bit difficult to set in the code. The possibility to edit/tweak contraints and live test it would be so great!

2 Likes

Thank you so much, @HiGreg :slight_smile: I love the list of features you shared.

I’ve been trying to debug visualize Havok joint limits, and I think I found a bug:

It would be amazing if we had full debug visualization of Havok joints.

Agreed. I think 6DOF is a superset of all others. I’m ruminating on how to do it while I’m learning how to visualize data from Havok. As you might imagine, and can see in the playground below, it’s not trivial.

To show how simple it is to use the classes I’m creating (instantiate the class with options, and call .enable()), I’ve added my current working DebugMeshes class to a playground to show how it works.

I’ve added a few options since my last post. The playground mostly just shows off local axes and linear velocity.

DebugMeshes contains options to show physics parameters related to PhysicsBody in the local space of the PhysicsBody:

  • wireframe of PhysicsBody shape
  • ActivationState ACTIVE or INACTIVE (color)
  • Center of Mass,
  • local axes,
  • bounding box,
  • linear velocity

Comments welcome! If you try it out with other playgrounds, add a link here. Be sure to copy the whole class including the version date.

I’m thinking of changing the name from Meshes to Bodies or similar.

The playground is one that reveals either a bug or limitation in Havok Engine (for more info about the playground, see Havok Precision - #33 by HiGreg)

Edit: running for a minute or two, the playground crashes with the upper left sad face box. Rerunning gives the error “Unable to create uniform buffer.” Not sure if there’s a general problem or if I’m just stressing my browser.

2 Likes

And here’s a video of bouncy dice with contact points, axes, and linear velocity. Near the end you can see inactive physicbodies turn from green to red.

2 Likes

That’s awesome! Were the red and green colors of the dice based on the ActivationState?

Yes. Each frame on each body, I call HP_Body_GetActivationState() directly from the Engine. I don’t see the equivalent in the Plugin.

1 Like

Here’s an update on the physics debug visualization classes. I’ve converted to TypeScript, and toiled through quite a few errors. I’ve gone all-in on GreasedLineMesh, but not sure about the amount of perFrame updates on all the velocity and contact lines. Something was causing the WebGL context to be lost.

Although context loss seems to be gone at the moment, there are still weird freezes when there are lots of moving objects (about 3 seconds of smooth followed by 6 seconds of freeze, repeating). I’m testing with about 56 bouncing dice in a box. Here’s a preview with just a few.

  • DebugBodies - wireframe or boundingbox, active (green) inactive (red), center of mass, local axes, velocity linear

  • ContactLines - shows collision lines along the normal, scalable by impulse. Color indicates starting (red) or continuing (yellow).

  • ContactPoints - shows temporary dots (lasting 250 milliseconds) at contact points

       /* Example usage:
       * new ContactLines({width:0.005,propertyName:"impulse",scale:2e6},hk,scene).enable();
       * new ContactPoints({duration:1000,diameter:0.01},hk,scene).enable();
       * new DebugBodies({}, hk, scene).enable();
       *
       */
      
      // example:
      // new DebugBodies({showAxes:true,velocityScale:.2,velocityLineWidth:0.01,},hk,scene).enable();
    
3 Likes

First draft of joints visualization.

This is a generic implementation that visualizes pivot point and axis of PhysicsConstraint.

No limits and no 6DOF yet.

Somewhat optimized for updating transforms from PhysicsBody as each constraint is a Mesh with submeshes (i.e. Merged), then thinInstanced for each joint.

Only showing one constraint, both A and B (aka parent and child). Hopefully this will continue to work well as I add constraints and joints.

3 Likes

That’s awesome :smile: If it can help, I can take a video of built-in debug drawings for different joint types in Bullet and PhysX. We could use good aspects from both in the Havok joint debug drawing

That would help immensely!

Also helpful would be code or playgrounds implementing Havok joints and constraints.

1 Like

Awesome! Let me look into the video and PG’s later today and the weekend

1 Like

I haven’t built this into a debug class, but here’s what I’ve got so far. Almost posted as another thread but don’t want to pollute.

Visualizing constraints’ linear axes.

First, the cool visualization. After loading, tap for chaos.

Looking for feedback on this theory. I haven’t seen it presented this way, but I can’t say I’ve read all the documentation. Regarding the AxisMode of PhysicsConstraints, is there anything wrong with this way of thinking about it?


There are three vectors and one point that are user-specified on each of two bodies in a PhysicsConstraint. These axes are called Axis, perpAxis, and the (unnamed) normal to Axis and perpAxis. These form three orthogonal axes with their origin at the user-defined point called Pivot. One body is called A, or Parent, and the other is called B, or Child.

Each of these axes has a LINEAR component and an ANGULAR component, where LINEAR references position along the axis and ANGULAR references rotation around that axis. In this context, X, Y, and Z are references to Axis, PerpAxis, and the Normal, respectively.

A user can place fixed upper and lower limits on each of these axes. These limits constitute a box relative to box A’s axes within which body B’s Pivot is constrained.

Here is a visualization of this. In the playground, boxA is red and boxB is yellow. BoxB’s Pivot is purple and the linear constraints are visualized as a gray box. Gravity is set to zero and each body has the same mass. Tapping the screen imparts a force to boxB. Note how the purple Pivot says within the gray limits. When the yellow box reaches its limits, momentum is transferred to boxA (through the constraint) and boxA moves as a result.

All possible constraint combinations (see this post) are shown. This is the same demo as the first link, but with non-cube limits:

If you modify the code to attach the limits box to boxB instead of A, then it’s not seeming to constrain boxA. I think this substantiates the theory above.

3 Likes