# Oblivion/Oblivion Bhk Constraints

## Contents |

# Bhk Constraint Tutorial

This stuff is not for NifSkope newbies. You're better be able to create basic collision models before playing with constraints.

## Introduction

A constraint is a connection between two Bodies. It limits the freedom of movement of the two objects. The Oblivion adapted version of the Havok engine can use several types of constraints, each allowing different types of freedom.

- bhkLimitedHingeConstraint
- bhkHingeConstraint,
- bhkRagdollConstraint,
- bhkMalleableConstraint,
- bhkStiffSpringConstraint,
- bhkPrismaticConstraint.

I'll use the vanilla greymaresign.nif to demonstrate. Open it in NifSkope (latest version, if possible). Find the bhkLimitedHingeConstraint (block number 13).

## General Properties

Constraints are always linked to a bhkRigidBody, or bhkRigidBodyT. Select the parent rigidbody of the constraint. You can find Num Constraints, and the Constraints array somewhere at the bottom of Block Details. It's possible to attach multiple constraints to a rigidbody. It's the same mechanism as attaching a NiTriShape to a NiNode. NifSkope draws a graphic representation for constraints. These are brown and green shapes, they are to help tuning the properties. Generally true that constraints will work well in-game if the brown and green shapes overlap. There are five properties which can be found in every constraint (select bhkLimitedHingeConstraint):

- Num Entities (called Num Bodies in older versions of NifSkope)
- Entities (called Bodies in older versions of NifSkope)
- Priority (called Unknown Int in older versions of NifSkope)
- Pivot A
- Pivot B

**Num Entities:** defines how many rigidbodies are connected by the constraint. Oblivion constraints can connect only two Bodies.

**Entities:** defines which rigidbodies are connected. The first one is always the parent of the constraint. The second one is always the other rigidbody. The connected rigidbodies must be part of NiNiodes which are in parent-child relationship. Check the general structure of the greymaresign. The GreyMareSign NiNode (0) contains the static part of the collision model. It's child, GreyMareSignReal NiNode (9) contains the moving part. The constraint is part of the child NiNode branch, but it could be attached to the rigidbody of the parent NiNode as well, it works correctly both ways.

**Priority:** it's usually 1 in Oblivion nifs.

**Pivot A:** you can find this if you expand the LimitedHingeDescriptor. It defines the point where the constraint is attached to its parent rigidbody. It's always represented by a brown dot. Change the Z element of the Pivot A vector to 9. It's the brown dot at the center of the brown circle.

**Pivot B:** defines the point where the constraint is attached to the other rigidbody. It's always represented by a green dot.

*Hint: right click on the constraint, and choose Havok -> A->B. NifSkope calculates Pivot B automatically, to make the pivots overlapping. This is needed becouse the vectors are in the local frames of the rigidbodies, which can differ.*

## bhkLimitedHingeConstraint

This constraint allows only rotation along a specified axis, between the speciefied boundaries. Check this short video which demonstrates its behavior.

bhkLimitedHingeConstraint specific properties:

- Axle A
- Axle B
- Perp2AxleInA1
- Perp2AxleInA2
- Perp2AxleInB2
- Min Angle
- Max Angle
- Max Friction

**Axle A:** defines the axle of rotation in the local frame of the parent rigidbody. It's represented by a continous brown line, which is perpendicular to the plane of the brown circle. As you may guessed already, the circle represents the plane
of rotation.

**Axle B:** defines the axle of rotation in the local frame of the other rigidbody.

**Perp2AxleInA1 & Perp2AxleInA2:** Perp2AxleInA1 and Perp2AxleInA2 together define a reference angle (the 0 angle) and the positive direction of the rotation. Perp2AxleInA1 is represented by a continous brown line. This defines the 0 angle. If Axle (thumb), Perp2AxleInA1 (forefinger), and Perp2AxleInA2 (middle finger) make up a right-handed frame, then the rotation is right-handed, and vice-versa. This is all not important in practice, these three vectors must be diagonal to each other, and the Perp vectors must be on the rotation plane, that's all. They are correct if the circle is not distorted.

**Perp2AxleInB2:** use the A->B spell in order to have NifSkope calculate it for you.

**Min Angle:** defines the minimum angle of the region where the body is able to rotate, in radii.

**Max Angle:** max angle of the region. The body is able to rotate in the angle range represented by a thick stripe along the circle. The excluded region is represented by the thin circle-section.

**Max Friction:** friction of the constraint. I.e. how rusty is the hinge.

The settings of the constraint on the video can be seen on this picture:

## bhkHingeConstraint

It's the same as bhkLimitedHingeConstraint, but there's no limited region. It can rotate all around, for infinity. Perfect choice for cart-wheels. Check this short video which demonstrates its behavior.

bhkHingeConstraint specific properties:

- Axle B
- Perp2AxleInA1
- Perp2AxleInA2

All the same as in the limited hinge. It's represented by a thick green circle. There's no brown circle to overlap with in this case.

*Hint: fill the pivots, and set the Axle and Perps to zeros. The hinge becomes truly unlimited.*

Let's add a bhkHingeConstraint to the greymaresign, just for practice. Add it by right-clicking on the bhkLimitedHingeConstraint (clicking on this becouse the block number will become correct right away), and selecting Block -> Insert -> Havok -> bhkHingeConstraint. Select the limited hinge's parent rigidbody (12), and assign the new hinge to its Constraints array (replace the limited hinge). Select the new hinge, increase Num Entities to 2, and refresh the Entities array. The first Entity must be the hinge's parent rigidbody (12), the second one is the other rigidbody (7). Copy-paste the Pivot A and Axle B from the limited hinge (or leave the pivot at 0, 0, 0, the sign will rotate around its center then). Use the A->B spell, to get a correct Pivot B. Delete the bhkLimitedHingeConstraint. It's ready! Try it in-game.

The block order in vanilla nifs: first comes the bhkshape, then the rigidbody, then the constraint, then the collision object. The settings of the constraint on the video can be seen on this picture:

## bhkRagdollConstraint

The ragdoll constraint allows the body to twist around a specified axis, and also to rotate around the pivot, between specified boundaries. An example of use is chains. It's represented by overlapping brown and green cones. The body can move freely in this cone. Check this short video which demonstrates its behavior.

bhkRagdollConstraint specific properties:

- Twist A
- Twist B
- Plane A
- Plane B
- Twist Min Angle
- Twist Max Angle
- Plane Min Angle
- Plane Max Angle
- Cone Min Angle
- Max Friction

**Twist A:** defines the axis of twisting, in the parent rigidbody's reference frame. If the rigidbody is not rotated, then (0, 0, -1) will make the cone to look down.

**Plane A:** defines the plane where the body can move around freely (between limits, of course). It must be diagonal to the Twist axis. E.g. if Twist A is (0, 0, -1), then Plane A must be (1, 0, 0) or (-1, 0, 0) or (0, 1, 0) or (0, -1, 0). The Plane vector is not a normal, but a vector on the plane. Check this picture.

**Twist B & Plane B:** use the A->B spell.

**Twist Min & Max Angle:** limits the rotation along the Twist axis.

**Plane Min & Max Angle:** limits the width of the cone.

**Cone Min Angle:** limits the width of the cone in a diagonal direction. Again, check the above picture. Checking a skeleton.nif, or the roothavok01.nif, and playing around with the angles also helps to understand.

**Max Friction:** same as at the limited hinge.

The settings of the constraint on the video can be seen on this picture:

## bhkMalleableConstraint

This is a joker constraint. It can be either limited hinge, or ragdoll. Furthermore it has two additional properties, Tau and Damping. Probably left from the developement phase of the game.

bhkMalleableConstraint specific properties:

- Type
- Tau
- Damping
- Unknown Int 2
- Unknown Int 3
- Unknown Link 1
- Unknown Link 2

**Type:** defines the type of the constraint. If Type=2 it becomes a limited hinge, if Type=7 it becomes a ragdoll.

**Tau:** defines the ratio between the force needed to keep the bodies together, and the force applied by the constraint. If Tau=1 then the bond is 100%, full force is applied to keep the bodies together. If Tau=0.8 then only 80% of the needed force is applied, and the constraint becomes elastic (I can be wrong with the numbers here).

**Damping:** the energy of movement decreases over time, by this amount.

**Unknowns:** unknown.

## bhkStiffSpringConstraint

This constraint acts as an invisible rod, which connects the bodies. It's represented by a green spring. The name suggests it's a spring, but it isn't. It's a *stiff* spring, not flexible.
Check this short video which demonstrates its behavior.

bhkStiffSpringConstraint specific properties:

- Length

**Length:** defines the length of the spring (rod).

*Hint: right-click on the constraint, and select Havok -> Calculate Spring Length. NifSkope calculates Length as the distance between the pivots.*

Length can be specified longer or shorter than the pivots' distance though (it's set to longer on the example video). The A->B spell is not available for this constraint, becouse the pivots define where are the two ends of the rod attached to the bodies. The bodies can freely rotate around the ends.

The settings of the constraint on the video can be seen on this picture:

## bhkPrismaticConstraint

The prismatic constraint acts like a rail where the body can move along freely between the specified limits. It's representation is a brown rail. Check this short video which demonstrates its behavior.

bhkPrismaticConstraint specific properties:

- Rotation
- Sliding Axis
- Plane
- Min Distance
- Max Distance
- Friction

**Rotation:** defines the rotation matrix of the parent rigidbody. It will be rotated by this matrix. It doesn't really make sense since the rigidbody contains a Rotation matrix itself. If you don't want rotate it, then set it to

(0, 0, 0, 0)

(1, 0, 0, 0)

(0, 1, 0, 0)

(0, 0, 1, 0)

*Hint: set Rotation to all zeros to make the body rotate freely.*

**Sliding Axis:** defines the direction of the rail. The body will be able to move along this axis.

**Plane:** defines the normal vector of the plane (a vector which is perpendicular to the plane) where the object can move freely. Generally it must be perpendicular to the Sliding Axis.

**Min & Max Distance:** defines the boundaries of the track, counted from Pivot A.

**Friction:** same as always.

The settings of the constraint on the video can be seen on this picture:

## Advices

- Always use primitive shapes or convex vertices shapes.
- Pay attention to the Col Filter of the rigidbody. Click on the flag icon next to Col Filter, enable the Linked checkbox, and set the appropriate Part Number. Part Number of the first chain piece must be 0, the second piece must have 1 and so on. It's not a complete disaster (i.e. crash) if you don't want to mess with these, but prevents collision of the parts when set properly.
- If you have more chains next to each other, and you want to prevent collision between them, then put them onto the OL_TERRAIN layer.
- Longer (above 10-20 pieces) chains are very instable. They tend to play perpeetum mobile. You can stabilize them by increasing Linear and Angular Damping of the rigidbodies.
- Unknown Byte 2 of the bhkRigidBody is some kind of precision flag. It's 2 by default for non-static objects, which means the movement of the object is stopped when its speed is near, but not zero (signs stopping mid-swing). Set it to 0 or 1 for more precise movement. It's needed only in very rare cases though.
- Unknown Int 9 of the bhkRigidBody is weather flag. Set it to 1 if you want your object to be affected by wind.
- Use the new Blender scripts! Even if you're a Max user, use Blender to calculate a correct Inertia and Center for your rigidbodies. This is essential for realistic moving!