1 /*
2 	Copyright (C) 2005-2007 Feeling Software Inc.
3 	Portions of the code are:
4 	Copyright (C) 2005-2007 Sony Computer Entertainment America
5 
6 	MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8 
9 /**
10 	@file FMQuaternion.h
11 	The file containing the class for quaternions.
12 */
13 
14 #ifndef _FM_QUATERNION_H_
15 #define _FM_QUATERNION_H_
16 
17 /**
18 	A quaternion.
19 	Used to represent rotations: quaternions have the sole advantage of reduced
20 	floating-point error when concatenating rotations.
21 
22 	@ingroup FMath
23 */
24 class FCOLLADA_EXPORT FMQuaternion
25 {
26 public:
27 	float x;	/**< The i component. */
28 	float y;	/**< The j component. */
29 	float z;	/**< The k component. */
30 	float w;	/**< The scalar component. */
31 
32 #ifndef _DEBUG
33 	/**	Creates an empty FMQuaternion.
34 		The default values are non deterministic. */
FMQuaternion()35 	FMQuaternion() {}
36 #else
FMQuaternion()37 	FMQuaternion() { x = 123456789.0f; y = 123456789.0f; z = 123456789.0f; w = 123456789.0f; }
38 #endif
39 
40 	/**	Creates the quaternion with the given component values.
41 		@param _x The i component.
42 		@param _y The j component.
43 		@param _z The k component.
44 		@param _w The scalar component. */
FMQuaternion(float _x,float _y,float _z,float _w)45 	FMQuaternion(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
46 
47 	/**	Creates the quaternion with the given component values.
48 		@param values A static float array containing at least four elements. */
49 	FMQuaternion(const float* values);
50 	FMQuaternion(const double* values); /**< See above. */
51 
52 	/**	Creates the quaternion from a given axis and angle of rotation.
53 		@param axis The axis of rotation.
54 		@param angle The angle of rotation in radians. */
55 	FMQuaternion(const FMVector3& axis, float angle);
56 
57 	/** Retrieves this quaternion as an array of \c floats.
58 		@return The \c float array. */
59 	inline operator float*() { return &x; }
60 	inline operator const float*() const { return &x; } /**< See above. */
61 
62 	/** Assign this FMQuaternion to the given \c float array.
63 		Assigns each coordinate of this FMQuaternion to the elements in the
64 		\c float array. The first element to the i component, the second to the
65 		j, the third to the k, and the forth to the scalar.
66 		@param v The \c float array to assign with.
67 		@return This quaternion. */
68 	inline FMQuaternion& operator =(const float* v) { x = *v; y = *(v + 1); z = *(v + 2); w = *(v + 3); return *this; }
69 
70 	/**	Retrieves the squared length of the vector.
71 		@return The squared length of this vector. */
LengthSquared()72 	inline float LengthSquared() const { return x * x + y * y + z * z + w * w; }
73 
74 	/**	Retrieves the length of the vector.
75 		@return The length of this vector. */
Length()76 	inline float Length() const { return sqrtf(x * x + y * y + z * z + w * w); }
77 
78 	/** Normalizes this vector. */
NormalizeIt()79 	inline void NormalizeIt() { float l = Length(); if (l > 0.0f) { x /= l; y /= l; z /= l; w /= l; }}
80 
81 	/** Returns a quaternion with a unit length at the same space as this quaternion
82 		@return A FMVector3 with length 1 and same direction as this vector. */
Normalize()83 	inline FMQuaternion Normalize() const { float l = Length(); return FMQuaternion(x / l, y / l, z / l, w / l); }
84 
85 	/** Returns the concatonation of this quaternion rotation and the given
86 		quaternion rotation.
87 		@param q A second quaternion rotation.
88 		@return The result of the two quaternion rotation. */
89 	FMQuaternion operator*(const FMQuaternion& q) const;
90 
91 	/** Returns the concatonation of this quaternion rotation applied
92 		on the given vector. This concatonation works great on
93 		vector but will give strange results for points.
94 		@param v A 3D vector to rotate.
95 		@return The rotated 3D vector. */
96 	FMVector3 operator*(const FMVector3& v) const;
97 
98 	/** Returns the conjugate of this quaternion.
99 		@return The conjugate. */
100 	inline FMQuaternion operator~() const { return FMQuaternion(-x, -y, -z, w); }
101 
102 	/** Applies quaternion multiplication of the given quaternion with this
103 		quaternion and returns the value.
104 		@param q The quaternion multiplied with.
105 		@return The resulting quaternion. */
106 	inline FMQuaternion& operator*=(const FMQuaternion& q) { return (*this) = (*this) * q; }
107 
108 	/** Copy constructor.
109 		Clones the given quaternion into this quaternion.
110 		@param q A quaternion to clone.
111 		@return This quaternion. */
112 	inline FMQuaternion& operator=(const FMQuaternion& q) { x = q.x; y = q.y; z = q.z; w = q.w; return (*this); }
113 
114 	/** Returns the slerp of this quaternion to other at time time
115 		@param other The Quaternion to interpolate to
116 		@param time The percentage (0 < time < 1) to slerp
117 		@return The Quaternion formed by the slerp */
118 	FMQuaternion slerp(const FMQuaternion& other, float time) const;
119 
120 	/** Converts a quaternion to its Euler rotation angles.
121 		@param previousAngles To support animated quaternions conversion,
122 			you need to pass in the previous quaternion's converted angles.
123 			The closest angles to the previous angles will be returned for a smooth animation.
124 			If this parameter is NULL, one valid set of angles will be returned.
125 		@return A 3D vector containing the Euler rotation angles. */
126 	FMVector3 ToEuler(FMVector3* previousAngles = NULL) const;
127 
128 	/** Converts a quaternion to a angle-axis rotation.
129 		@param axis The returned axis for the rotation.
130 		@param angle The returned angle for the rotation, in radians. */
131 	void ToAngleAxis(FMVector3& axis, float& angle) const;
132 
133 	/** Converts a quaternion to a transformation matrix.
134 		@return The transformation matrix for this quaternion. */
135 	FMMatrix44 ToMatrix() const;
136 
137 	/** Sets the Quaternions transform onto the specified matrix.
138 		This will overwrite any existing rotations, but not positions
139 		@param m  The matrix to set our transform onto */
140 	void SetToMatrix(FMMatrix44& m) const;
141 
142 	/** Get the FMQuaternion representation of the Euler rotation angles.
143 		@param x The rotation about the x-axis (roll), in radians.
144 		@param y The rotation about the y-axis (pitch), in radians.
145 		@param z The rotation about the z-axis (yaw), in radians.
146 	 */
147 	static FMQuaternion EulerRotationQuaternion(float x, float y, float z);
148 
149 	/** Get the FMQuaternion that represents the FMMatrix44 rotation
150 		@param mat The matrix whose rotation we will represent */
151 	static FMQuaternion MatrixRotationQuaternion(const FMMatrix44& mat);
152 
153 public:
154 	static const FMQuaternion Zero; /**< The zero quaternion. */
155 
156 	/** The identity quaternion.
157 		Transforming a vector or a point with this quaternion
158 		returns the same vector or point. */
159 	static const FMQuaternion Identity;
160 };
161 
162 /** Retrieves whether two quaternions are equivalent.
163 	@param a A first quaternion.
164 	@param b A second quaternion.
165 	@return Whether the two quaternions are equivalent. */
IsEquivalent(const FMQuaternion & a,const FMQuaternion & b)166 inline bool IsEquivalent(const FMQuaternion& a, const FMQuaternion& b)
167 {
168 	return IsEquivalent(a.x, b.x) && IsEquivalent(a.y, b.y) && IsEquivalent(a.z, b.z) && IsEquivalent(a.w, b.w);
169 }
170 
171 #endif // _FM_QUATERNION_H_
172