#region File Description
//-----------------------------------------------------------------------------
// A class containing all the basic transformations a renderable object can have.
// This include: Translation, Rotation, and Scale.
//
// Author: Ronen Ness.
// Since: 2017.
//-----------------------------------------------------------------------------
#endregion
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace MonoGameSceneGraph
{
///
/// MonoGameSceneGraph is the main namespace that contains all the MonoGame-SceneGraph entities.
///
[System.Runtime.CompilerServices.CompilerGenerated]
class NamespaceDoc
{
}
///
/// How to apply rotation (euler vs quaternion).
///
public enum RotationType
{
///
/// Euler rotation.
///
Euler,
///
/// Quaternion rotation.
///
Quaternion,
}
///
/// Different way to build matrix from transformations.
///
public enum TransformOrder
{
///
/// Apply position, then rotation, then scale.
///
PositionRotationScale,
///
/// Apply position, then scale, then rotation.
///
PositionScaleRotation,
///
/// Apply scale, then position, then rotation.
///
ScalePositionRotation,
///
/// Apply scale, then rotation, then position.
///
ScaleRotationPosition,
///
/// Apply rotation, then scale, then position.
///
RotationScalePosition,
///
/// Apply rotation, then position, then scale.
///
RotationPositionScale,
}
///
/// Different ways to apply rotation (order in which we rotate the different axis).
///
public enum RotationOrder
{
///
/// Rotate by axis order X, Y, Z.
///
RotateXYZ,
///
/// Rotate by axis order X, Z, Y.
///
RotateXZY,
///
/// Rotate by axis order Y, X, Z.
///
RotateYXZ,
///
/// Rotate by axis order Y, Z, X.
///
RotateYZX,
///
/// Rotate by axis order Z, X, Y.
///
RotateZXY,
///
/// Rotate by axis order Z, Y, X.
///
RotateZYX,
}
///
/// Contain all the possible node transformations.
///
public class Transformations
{
///
/// Node position / translation.
///
public Vector3 Position;
///
/// Node rotation.
///
public Vector3 Rotation;
///
/// Node scale.
///
public Vector3 Scale;
///
/// Order to apply different transformations to create the final matrix.
///
public TransformOrder TransformOrder = TransformOrder.ScaleRotationPosition;
///
/// Axis order to apply rotation.
///
public RotationOrder RotationOrder = RotationOrder.RotateYXZ;
///
/// What type of rotation to use.
///
public RotationType RotationType = RotationType.Quaternion;
///
/// Create new default transformations.
///
public Transformations()
{
Position = Vector3.Zero;
Rotation = Vector3.Zero;
Scale = Vector3.One;
}
///
/// Clone transformations.
///
public Transformations(Transformations other)
{
Position = other.Position;
Rotation = other.Rotation;
Scale = other.Scale;
TransformOrder = other.TransformOrder;
RotationOrder = other.RotationOrder;
RotationType = other.RotationType;
}
///
/// Clone transformations.
///
/// Copy of this transformations.
public Transformations Clone()
{
return new Transformations(this);
}
///
/// Build and return just the rotation matrix for this treansformations.
///
/// Rotation matrix.
public Matrix BuildRotationMatrix()
{
// handle euler rotation
if (RotationType == RotationType.Euler)
{
switch (RotationOrder)
{
case RotationOrder.RotateXYZ:
return Matrix.CreateRotationX(Rotation.X) * Matrix.CreateRotationY(Rotation.Y) * Matrix.CreateRotationZ(Rotation.Z);
case RotationOrder.RotateXZY:
return Matrix.CreateRotationX(Rotation.X) * Matrix.CreateRotationZ(Rotation.Z) * Matrix.CreateRotationY(Rotation.Y);
case RotationOrder.RotateYXZ:
return Matrix.CreateFromYawPitchRoll(Rotation.Y, Rotation.X, Rotation.Z);
case RotationOrder.RotateYZX:
return Matrix.CreateRotationY(Rotation.Y) * Matrix.CreateRotationZ(Rotation.Z) * Matrix.CreateRotationX(Rotation.X);
case RotationOrder.RotateZXY:
return Matrix.CreateRotationZ(Rotation.Z) * Matrix.CreateRotationX(Rotation.X) * Matrix.CreateRotationY(Rotation.Y);
case RotationOrder.RotateZYX:
return Matrix.CreateRotationZ(Rotation.Z) * Matrix.CreateRotationY(Rotation.Y) * Matrix.CreateRotationX(Rotation.X);
default:
throw new System.Exception("Unknown rotation order!");
}
}
// handle quaternion rotation
else if (RotationType == RotationType.Quaternion)
{
// quaternion to use
Quaternion quat;
// build quaternion based on rotation order
switch (RotationOrder)
{
case RotationOrder.RotateXYZ:
quat = Quaternion.CreateFromAxisAngle(Vector3.UnitX, Rotation.X) * Quaternion.CreateFromAxisAngle(Vector3.UnitY, Rotation.Y) * Quaternion.CreateFromAxisAngle(Vector3.UnitZ, Rotation.Z);
break;
case RotationOrder.RotateXZY:
quat = Quaternion.CreateFromAxisAngle(Vector3.UnitX, Rotation.X) * Quaternion.CreateFromAxisAngle(Vector3.UnitZ, Rotation.Z) * Quaternion.CreateFromAxisAngle(Vector3.UnitY, Rotation.Y);
break;
case RotationOrder.RotateYXZ:
quat = Quaternion.CreateFromYawPitchRoll(Rotation.Y, Rotation.X, Rotation.Z);
break;
case RotationOrder.RotateYZX:
quat = Quaternion.CreateFromAxisAngle(Vector3.UnitY, Rotation.Y) * Quaternion.CreateFromAxisAngle(Vector3.UnitZ, Rotation.Z) * Quaternion.CreateFromAxisAngle(Vector3.UnitX, Rotation.X);
break;
case RotationOrder.RotateZXY:
quat = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, Rotation.Z) * Quaternion.CreateFromAxisAngle(Vector3.UnitX, Rotation.X) * Quaternion.CreateFromAxisAngle(Vector3.UnitY, Rotation.Y);
break;
case RotationOrder.RotateZYX:
quat = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, Rotation.Z) * Quaternion.CreateFromAxisAngle(Vector3.UnitY, Rotation.Y) * Quaternion.CreateFromAxisAngle(Vector3.UnitX, Rotation.X);
break;
default:
throw new System.Exception("Unknown rotation order!");
}
// convert to a matrix and return
return Matrix.CreateFromQuaternion(quat);
}
// should never happen.
else
{
throw new System.Exception("Unknown rotation type!");
}
}
///
/// Build and return a matrix from current transformations.
///
/// Matrix with all transformations applied.
public Matrix BuildMatrix()
{
// create the matrix parts
Matrix pos = Matrix.CreateTranslation(Position);
Matrix rot = BuildRotationMatrix();
Matrix scale = Matrix.CreateScale(Scale);
// build and return matrix based on order
switch (TransformOrder)
{
case TransformOrder.PositionRotationScale:
return pos * rot * scale;
case TransformOrder.PositionScaleRotation:
return pos * scale * rot;
case TransformOrder.ScalePositionRotation:
return scale * pos * rot;
case TransformOrder.ScaleRotationPosition:
return scale * rot * pos;
case TransformOrder.RotationScalePosition:
return rot * scale * pos;
case TransformOrder.RotationPositionScale:
return rot * pos * scale;
default:
throw new System.Exception("Unknown build matrix order!");
}
}
}
}