User:Kesta/Tutorials/Nifskope LimitedHingeConstraints

Hinge constraints can be setup in Nifskope.

Their purpose is to “tie” 2 rigid bodies together, allowing a single axis of rotation between them, limited by a max and a min angle.

Some typical use case for hinge constraints seen in Vanilla are Inn Signs and Books’ world model.

Nif Preparation before setting up the constraint
Before setting up your hinge constraint, you want to make sure your nif architecture have at least two rigidbodies, each under its own node (Node2 can be a child of Node1 though).

The mesh (if there is even one ^^) can either be directly placed under the same NiNode as its collision (simple meshes), or exist somewhere else in the nif and be rigged through a Skin Instance to the collision’s node (the node then effectively becoming a bone).

Make sure both rigid bodies are of type bhkRigidBodyT (the T is important). At least the ones supposed to be able to move. If they don’t have the T, simply right click on it, and select Block->Convert->Havok->bhkRigidBodyT Also ensure that the parent bhkCollisionObject have the flags ACTIVE and SYNC_ON_UPDATE

As a general consideration, to prevent any kind of performance issues, it is recommended that constraints or animation in nifs are applied to fairly simple collision, such as box, sphere, capsule or convex vertices.

Creating the Limited Hinge Constraint
You only need to set the hinge constraint for 1 of the 2 bodies: The one “that move relatively for the other”. Alongside the usual bdkRigidBody properties, you want to add a constraints:

Locate the Num Constraints properties, and set it to 1. Then click on the refresh button on the Constraints properties to make the list update with the relevant number of entries.

Then click on the green + and select bhkLimitedHingeConstraint

Configuring the Limited Hinge Constraint
Select the bhkLimitedHingeConstraint created previously and set its properties:

For Num Entities, input 2, then refresh the Entities list to have the 2 entries. In the first entry, enter the block number of the bhkRigidBodyT you’re setting up this constraint on, and in the second entry, the block number of the bhkRigidBody(T) you’re setting up this constraint against.

A little illustration of the bhkLimitedHingeConstraint properties for good measure:

You can just leave the priority at 1 (or set it to 1 if it isn’t) if you’re working on a simple mesh. Exact meaning of this setting is still unknown, although it’s general purpose is identified as setting priorities between multiple constraints.

Then it’s time for some maths and a few coordinates to set

VERY IMPORTANT These coordinates are to be set in the coordinate system of the rigidbody, not the world! This isn’t necessarily the coordinates system displayed in the main Nifskope frame, but the one that appear when you select the node:

In the screenshot above, notice how the coordinates system is rotated relatively to the main model’s one. This is due to the accumulated Translations and Rotations of all the parents NiNode pointed in the nif architecture.

With that in mind, set the axis of rotation for your constraint in Axis A. Note the X Y Z W setup, This is a common way of defining vectors in Nif format: X Y and Z should form a unit vector (norm equal to 1), and W is the “weight”, i.e. the norm of the actual vector you’re defining. For the purpose of a simple axis, the W don’t really matter so set it to 1.

Then with the same considerations as above, fill in the Perp Axis in A1, Perp Axis in A2, and Pivot A properties: Perp Axis in A1 should be orthogonal to Axis A, and will define the angle 0. Perp Axis in A2 is simply the dot product of Axis A and Perp Axis in A1 (if you’re wondering why you have to set it yourself, it is likely set directly in the model as an optimization so the game don’t have to compute it by itself each time). Pivot A is the coordinates of the pivot point. Here you want to ignore the W, and simply input the X Y Z coordinates.

Then, you’ll have to redo the same for the “Axis B” in a semi-automated ways: These are the same than for their Axis A counterpart, except expressed in the coordinate system of the second entity.

Finally, set Min Angle and Max Angle to limit the range of the constraint (in radians, not degrees), and the Max Friction, which will define how strong the constraint will slow/resist the movement. It’s recommended to fine tune these 3 values once the model is final and implemented, to make sure the constraint really feel natural once subject to the various things that can happens to it in engine.

For a simple idle constraint, leave the Motor Type to MOTOR_NONE.

That’s it, if your bhkRigidBodies are properly setup themselves, and the rest of your Nif architecture, your constraint should now work in game.