Click or drag to resize
DigitalRunePose (Position and Orientation)

Positioning objects in 3D space is essential in games. This section introduces a type called Pose that describes the position and orientation of an object.

This topic contains the following sections:

What is a Pose?

DigitalRune Geometry provides a value type called Pose. A pose describes a position (see Position) and an orientation (see Orientation) in 3D space. It is very similar to a transformation matrix: Both are used to describe a transformation in space. When using transformation matrices we usually use the terms "rotation" and "translation". When using a pose we use the terms "orientation" and "position". But that’s just a subtle difference – it pretty much means the same.

A pose can be used to describe the position and orientation of any object in a 3D space: shapes, rigid bodies, characters, cameras, etc.

Note Note

One might ask, why is this type Pose in DigitalRune Geometry and not in DigitalRune Mathematics? The reason is that the types in DigitalRune Mathematics have no particular meaning. A Vector3F might be a position, a direction, or something completely different. Similarly, a Matrix44F can be used for all sorts of things. Whereas, in DigitalRune Geometry deals with geometric objects in 3D space. Here, vectors and matrices have a particular meaning - hence we have wrapped them and created a type called Pose.

Working with matrices is notoriously difficult and error-prone: Do I have to multiply the matrices from the right or from the left? Do I need to multiply with the matrix or the inverse matrix? Is the translation stored the last column or row in 4x4 matrix? Etc.

Pose was designed to make common tasks in game development easier - and to avoid headaches while coding.

Reasons for using Pose

The type Pose is highly optimized for its particular purpose:

  • Pose is a value type (struct), so in general there is no need to worry about memory allocations on the heap ("garbage").
  • A single pose requires 48 bytes - that's less memory than a matrix in XNA.
  • Concatenating (multiplying) two poses is faster than concatenating two transformation matrices.
  • Transforming a vector using a pose is faster than multiplying a vector with a 4x4 matrix.
  • Inverting a Pose is much faster than inverting a 4x4 matrix.
How to use a Pose?

Here are some examples showing how to define a pose.

C#
// Create a new Pose that contains no translation and no rotation.
Pose pose = Pose.Identity;

// Create a Pose that defines a position of (1, 2, 3).
pose = new Pose(new Vector3F(1, 2, 3));

// Create a Pose that defines an orientation of 30° around the x-axis.
pose = new Pose(Matrix33F.CreateRotationX(MathHelper.ToRadians(30)));

// Or, using QuaternionF instead of Matrix33F.
pose = new Pose(QuaternionF.CreateRotationX(MathHelper.ToRadians(30)));

// A Pose can be manipulated directly using its fields ‘Position’ and ‘Orientation’:
// Let's move the object 10 units in y direction.
pose.Position += new Vector3F(0, 10, 0);

// Or, let's rotate the object 10° further around the z-axis.
pose.Orientation = Matrix33F.CreateRotationZ(MathHelper.ToRadians(10)) * pose.Orientation;

Once a pose is defined, it can be use to transform objects.

C#
// Let's transform a point from local space to world space.
var pointLocal = new Vector3F(1, 0, 0);
var pointWorld = pose.ToWorldPosition(pointLocal);

// Let's transform a direction from local space to world space.
var directionLocal = Vector3F.Forward;
var directionWorld = pose.ToWorldDirection(directionLocal);
Note Note

Note the postfixes "local" and "world". That’s a convention we use internally to describe the space a variable is defined in.

C#
// Of course, we can also transform objects from world space to local space.
pointLocal = pose.ToLocalPosition(pointWorld);
directionLocal = pose.ToLocalDirection(directionWorld);

A pose can also be used similarly to a 4x4 transformation matrix.

C#
// We can multiply a Vector4F directly with a Pose instead of a Matrix44F.
var pLocal = new Vector4F(1, 0, 0, 1); // The position (1, 0, 0) in homogeneous coordinates.
var pWorld = pose * pLocal;

Different poses can be combined just as one would concatenate transformation matrices. It is also possible to compute the inverse transformation of a pose:

C#
// Let's concatenate two Poses by multiplying them - just as we would to with matrices.
var pose3 = pose2 * pose1;

// Just like with matrices we can also compute the inverse of a Pose.
var inversePose = pose.Inverse;

A pose also provides implicit cast operators to convert a Pose to a Matrix44F or an XNA Matrix.

C#
// Let's convert a Pose to a Matrix.
Matrix worldMatrix = pose;

// That's useful, for example, when we have defined the pose of a Model in XNA.
// To render the Model we have to assign the world transformation matrix of the
// Model to the Effect used for rendering.
basicEffect.World = pose;
WARNING: Common pitfall when working with value types such as Vector3, Matrix, Pose

There are two common pitfalls when working with value types such as Pose.

Beware of the default constructor

The default constructor of Pose sets all fields to 0 - it does not create a valid transformation! Instead, you should set the pose to Identity.

C#
Pose p1 = new Pose();    // WARNING: Not a valid transformation!
Pose p2 = Pose.Identity; // Valid transformation!

Watch out for properties

Let's assume you have an object with a property Pose:

C#
class MyObject
{
  public Pose Pose { get; set; }

  // ...
}

Now, if you want to update the position you can't just assign a new vector.

C#
// Warning: This should give squiggly lines in Visual Studio.
myObject.Pose.Position = new Vector3F(1, 2, 3);

Above line is not working as expected because the getter of the property actually returns a copy of the pose. You always have to assign the new pose as a whole:

C#
// Here's the right way to do it:
myObject.Pose = new Pose(new Vector3F(1, 2, 3), myObject.Pose.Orientation);
See Also