Getting a list of PhysicsConstraints?

How can I get a list of constraints added to the Havok physics engine?

I’ve looked in HavokPlugin, Havok interface layer (HavokPhysics.d.ts, and decoded HavokPhysics_es.js) as well as PhysicsBody. Am I missing something?

It looks like the PhysicsViewer requires calling .showConstraint after the constraint is created. I want to get a list of all constraints. How?

1 Like

I’m interested in this too :slight_smile:

To clarify, is this a Havok function that returns a list of HP_ConstraintId for a given HP_WorldId?

That’s what I was hoping for! Or in the style of collisionEvents from the Integration layer:

HP_World_GetCollisionEvents(…)
HP_World_GetNextCollisionEvent(…)
HP_Event_AsCollision(…)

1 Like

That sounds great. There’s also the style of the compound shape children API in the Integration Layer that could be good for this too:

/** Get the number of children of the container. */
HP_Shape_GetNumChildren(container : HP_ShapeId): [Result, number];
/** Returns the HP_ShapeId of the child shape at index `childIndex` in the container. */
HP_Shape_GetChildShape(container : HP_ShapeId, childIndex : number) : [Result, HP_ShapeId];

That’s even better. Unfortunately, I don’t see anything in the interface layer (provided by Havok directly interfacing the WASM).

Because Havok doesn’t provide an API call for that, maybe saving them in the plugin would suffice for now, but I’d hate to use additional memory. Something like a jointId to Physics constraint Map() in initConstraint or addConstraint (havokPlugin.ts line 1807) then removed from the Map in disposeConstraint (line 2075).

There is a lot of calculations of derived values (perpAxisA when not given in options). I can only hope at this point that simply saving the jointId and the constraint, along with getting access to the private variable _constraintToBodyIdPair would be enough to decode and debug constraints.

1 Like

Something like his might work? (I’m mixing typescript and javascript, and I haven’t tried it yet. I’m sure there are mistakes)

class HavokPluginSaveConstraints extends HavokPlugin {
    public Constraints =  Map()
    public initConstraint(constraint: PhysicsConstraint, body: PhysicsBody, childBody: PhysicsBody, instanceIndex?: number, childInstanceIndex?: number): void {
        super(constraint, body, childBody, instanceIndex, childInstanceIndex);
        const jointId = constraint._pluginData.peek();
        this.Constraints.set(jointId,constraint);
    }

    // use getBodiesUsingConstraint(constraint) to get body pair

    public disposeConstraint(constraint: PhysicsConstraint): void {
       for (const jointId of constraint._pluginData) {
            Constraints.delete(jointId)
        }
        super(constraint)
    }
}

There is no api for querying world bodies or constraints. I don’t know if there is a technical limitation for adding these methods but in the mean time, what is the use case for that @HiGreg ?
I guess you can keep track of the bodies and constraints created in your app?

My use case is a general physics debug visualization.

I want to set it up to easily enable, without the user specifying a list of constraints. Though I expect I will also include the option to specify constraints when the user doesn’t want to show all.

Edit: I think my HavokPlugin subclass (above) might work for now.

I like intrumented engines. Maybe with options provided at engine construction where user set debugger behavior: none(default) where user handles it with physicsViewer or fullyInstrumented : a physics viewer is instanciated and filled with bodies/constraints when they are created/destroyed:

Does that mean you’d prefer that HavokPlugin be modified or subclassed to provide these visualizations? I think that may be the right layer.

I’m honing the performance of the visualizations to minimize object creation and CPU->GPU updates. The amount of work is worth capturing in classes rather than left to the user.

It is beyond providing line/color arrays, actually creating BABYLON meshes and materials and updating them per frame with observers. My concern is the creation and update of those objects seems like it should be a layer “above” HavokPlugin. Either way, the objects and optimizations I have will be useful, and could be placed within the code “above” or within HavokPlugin.

When I have sufficiently commented and tested, I’ll post updated classes in a PG for discussion.

3 Likes

I created the following class (in TypeScript) that extends HavokPlugin called HavokPluginSaveConstraints. It keeps track of added contraints for (future) debugging. It seems to work in my limited testing.

class HavokPluginSaveConstraints extends BABYLON.HavokPlugin {
    Constraints =  new Map();
    public initConstraint(constraint: BABYLON.PhysicsConstraint, body: BABYLON.PhysicsBody, childBody: BABYLON.PhysicsBody, instanceIndex?: number, childInstanceIndex?: number): void {
        super.initConstraint(constraint, body, childBody, instanceIndex, childInstanceIndex);
        const jointId = constraint._pluginData[constraint._pluginData.length-1];
        this.Constraints.set(jointId[0],constraint);
    }

    // use getBodiesUsingConstraint(constraint) to get body pair

    public disposeConstraint(constraint: BABYLON.PhysicsConstraint): void {
            for (const jointId of constraint._pluginData) {
                    this.Constraints.delete(jointId[0])
            }
            super.disposeConstraint(constraint)
    }

    // ignore that we are getting a private variable
    // this will break when private _variables are enforced
    // the _bodies variable in HavokPlugin should be defined as protected so that we can expose it in a subclass
    // @ts-ignore
    public get bodies() { return this._bodies; }
}

Edit: added jointId[0] to get number instead of using jointId as array.

2 Likes