1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 // Quaternion-math borrowed from plib http://plib.sourceforge.net/index.html
24 // Which is covered by LGPL2
25 // And has this additional copyright note:
26 /*
27  Quaternion routines are Copyright (C) 1999
28  Kevin B. Thompson <kevinbthompson@yahoo.com>
29  Modified by Sylvan W. Clebsch <sylvan@stanford.edu>
30  Largely rewritten by "Negative0" <negative0@earthlink.net>
31  */
32 
33 #ifndef MATH_QUAT_H
34 #define MATH_QUAT_H
35 
36 #include "common/scummsys.h"
37 #include "common/endian.h"
38 
39 #include "math/rotation3d.h"
40 #include "math/vector.h"
41 #include "math/angle.h"
42 #include "math/vector4d.h"
43 #include "math/matrix4.h"
44 
45 namespace Math {
46 
47 class Quaternion : public Vector4d {
48 public:
49 	/**
50 	 * Default Constructor, creates an identity Quaternion with no rotation.
51 	 */
Quaternion()52 	Quaternion() : Vector4d(0, 0, 0, 1.0) {}
53 
54 	/**
55 	 * Constructor from four floats in the order X,Y,Z,W
56 	 * The initial values should be normalized, otherwise call normalize() after creation
57 	 * @param lx		The X value of the Quaternion
58 	 * @param ly		The Y value of the Quaternion
59 	 * @param lz		The Z value of the Quaternion
60 	 * @param lw		The W value of the Quaternion
61 	 */
Quaternion(float lx,float ly,float lz,float lw)62 	Quaternion(float lx, float ly, float lz, float lw) : Vector4d(lx, ly, lz, lw) {}
63 
64 	/**
65 	 * Constructor from an existing Quaternion
66 	 * @param q		The existing quaternion
67 	 * @return		The new Quaternion
68 	 */
Quaternion(const Quaternion & q)69 	Quaternion(const Quaternion &q) : Vector4d(q.x(), q.y(), q.z(), q.w()) {}
70 
71 	/**
72 	 * Constructor from a vector of four floats in the order X,Y,Z,W
73 	 * The initial values should be normalized, otherwise call normalize() after creation
74 	 * @param vec		The vector of floats comprising the quaternion
75 	 * @return		The new Quaternion
76 	 */
Quaternion(const Vector4d & vec)77 	Quaternion(const Vector4d &vec) : Vector4d(vec.x(), vec.y(), vec.z(), vec.w()) {}
78 
79 	/**
80 	 * Constructor from a rotation matrix
81 	 * @param m		The rotation matrix
82 	 * @return		The new Quaternion
83 	 */
84 	Quaternion(const Matrix3 &m);
85 
86 	/**
87 	 * Constructor from a rotation matrix
88 	 * @param m		The rotation matrix
89 	 * @return		The new Quaternion
90 	 */
91 	Quaternion(const Matrix4 &m);
92 
93 	/** Set the Quaternion from a rotation matrix
94 	 * @param m		The matrix used to set the Quaternion
95 	 */
96 	void fromMatrix(const Matrix3 &m);
97 
98 	/**
99 	 * Constructor from an axis vector and the angle to rotate on that axis
100 	 * @param axis		The axis to perform the rotation around
101 	 * @param angle		The angle amount to rotate
102 	 * @return		The new Quaternion
103 	 */
104 	Quaternion(const Vector3d &axis, const Angle &angle);
105 
106 	/**
107 	 * Constructs a Quaternion from Euler Coordinates
108 	 * @param first		The Euler Angle for the first Axis
109 	 * @param second	The Euler Angle for the second Axis
110 	 * @param third		The Euler Angle for the third Axis
111 	 * @param order		The Euler Order, specified in Rotation3D
112 	 * @return		The new Quaternion
113 	 */
114 	static Quaternion fromEuler(const Angle &first, const Angle &second, const Angle &third, EulerOrder order);
115 
116 	/**
117 	 * Returns Euler Angles based on the Euler Order
118 	 * @param first		The Euler Angle for the first Axis
119 	 * @param second	The Euler Angle for the second Axis
120 	 * @param third		The Euler Angle for the third Axis
121 	 * @param order		The Euler Order, specified in Rotation3D
122 	 * @return		The new Quaternion
123 	 */
124 	void getEuler(Angle *first, Angle *second, Angle *third, EulerOrder order) const;
125 
126 	/**
127 	 * Create a Quaternion from a rotation around the X Axis
128 	 * @param angle		The Euler Angle for rotation
129 	 * @return		The resulting Quaternion
130 	 */
131 	static Quaternion xAxis(const Angle &angle);
132 
133 	/**
134 	 * Create a Quaternion from a rotation around the Y Axis
135 	 * @param angle		The Euler Angle for rotation
136 	 * @return		The resulting Quaternion
137 	 */
138 	static Quaternion yAxis(const Angle &angle);
139 
140 	/**
141 	 * Create a Quaternion from a rotation around the Z Axis
142 	 * @param angle		The Euler Angle for rotation
143 	 * @return		The resulting Quaternion
144 	 */
145 	static Quaternion zAxis(const Angle &angle);
146 
147 	/**
148 	 * Normalize the Quaternion
149 	 * @return		A reference to this quaternion
150 	 */
151 	Quaternion &normalize();
152 
153 	/**
154 	 * Rotate a vector by a Quaternion
155 	 * @param v The Vector to be rotated
156 	 */
157 	void transform(Vector3d &v) const;
158 
159 	/**
160 	 * Converts from this Quaternion to a Matrix4 representation
161 	 * @return              The resulting matrix
162 	 */
163 	Matrix4 toMatrix() const;
164 
165 	/**
166 	 * Converts from this Quaternion to a Matrix4 representation
167 	 * @param dst           The resulting matrix
168 	 */
169 	void toMatrix(Matrix4 &dst) const;
170 
171 	/**
172 	 * Make a new Quaternion that's the inverse of this Quaternion
173 	 * @return		The resulting Quaternion
174 	 */
175 	Quaternion inverse() const;
176 
177 	/**
178 	 * Slerps between this quaternion and to by factor t
179 	 * @param to		the quaternion to slerp between
180 	 * @param t		factor to slerp by.
181 	 * @return		the resulting quaternion.
182 	 */
183 	Quaternion slerpQuat(const Quaternion& to, const float t) const;
184 
185 	/**
186 	 * Get the direction vector specified by col
187 	 * @param col		Column in the rotation matrix to get the direction vector from
188 	 * @return		The resulting Vector3d
189 	 */
190 	Vector3d directionVector(const int col) const;
191 
192 	/**
193 	 * Get the angle between two quaternions
194 	 * @param to		The quaternion we're comparing against
195 	 * @return		The angle between the two
196 	 */
197 	Angle getAngleBetween(const Quaternion &to);
198 
199 	/**
200 	 * Assignment operator
201 	 * @param vec           The source quaternion
202 	 * @return              A reference to this Quaternion
203 	 */
204 	Quaternion& operator=(const Quaternion& quat);
205 
206 	/**
207 	 * Multiply two Quaternions
208 	 * @param quat          The Quaternion multiplicand
209 	 * @return              The result of the multiplication
210 	 */
211 	Quaternion operator*(const Quaternion &quat) const;
212 	Quaternion& operator*=(const Quaternion &quat);
213 
214 	/**
215 	 * Multiply this Quaternion by a constant
216 	 * @param quat 		The Quaternion multiplicand
217 	 * @return		The result of the multiplication
218 	 */
219 	Quaternion operator*(const float c) const;
220 
221 	/**
222 	 * Sum two quaternions
223 	 * @param quat 		The Quaternion to be added
224 	 * @return		The result of the addition
225 	 */
226 	Quaternion operator+(const Quaternion &o) const;
227 	Quaternion& operator+=(const Quaternion &o);
228 
229 	/**
230 	 * Compare quaternions
231 	 * @param quat 		The Quaternion to be compared
232 	 * @return		The result of the comparison
233 	 */
234 	bool operator==(const Quaternion &o) const;
235 	bool operator!=(const Quaternion &o) const;
236 };
237 
238 } // end of namespace Math
239 
240 #endif
241