diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llmath/llquaternion.h | 164 |
1 files changed, 137 insertions, 27 deletions
diff --git a/linden/indra/llmath/llquaternion.h b/linden/indra/llmath/llquaternion.h index 6805437..048db2d 100644 --- a/linden/indra/llmath/llquaternion.h +++ b/linden/indra/llmath/llquaternion.h | |||
@@ -57,10 +57,10 @@ public: | |||
57 | LLQuaternion(); // Initializes Quaternion to (0,0,0,1) | 57 | LLQuaternion(); // Initializes Quaternion to (0,0,0,1) |
58 | explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 | 58 | explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 |
59 | explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 | 59 | explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 |
60 | LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normQuat(x, y, z, w) | 60 | LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w) |
61 | LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) | 61 | LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) |
62 | LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) | 62 | LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) |
63 | LLQuaternion(const F32 *q); // Initializes Quaternion to normQuat(x, y, z, w) | 63 | LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w) |
64 | LLQuaternion(const LLVector3 &x_axis, | 64 | LLQuaternion(const LLVector3 &x_axis, |
65 | const LLVector3 &y_axis, | 65 | const LLVector3 &y_axis, |
66 | const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] | 66 | const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] |
@@ -71,15 +71,27 @@ public: | |||
71 | void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization | 71 | void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization |
72 | void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization | 72 | void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization |
73 | void loadIdentity(); // Loads the quaternion that represents the identity rotation | 73 | void loadIdentity(); // Loads the quaternion that represents the identity rotation |
74 | const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normQuat(x, y, z, w) | 74 | |
75 | const LLQuaternion& setQuat(const LLQuaternion &quat); // Copies Quaternion | 75 | const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) |
76 | const LLQuaternion& setQuat(const F32 *q); // Sets Quaternion to normQuat(quat[VX], quat[VY], quat[VZ], quat[VW]) | 76 | const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion |
77 | const LLQuaternion& setQuat(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) | 77 | const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) |
78 | const LLQuaternion& setQuat(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) | 78 | const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) |
79 | const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) | 79 | const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) |
80 | const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) | 80 | |
81 | const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) | 81 | const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) |
82 | const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) | 82 | const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) |
83 | const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) | ||
84 | const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) | ||
85 | |||
86 | const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated | ||
87 | const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated | ||
88 | const LLQuaternion& setQuat(const F32 *q); // deprecated | ||
89 | const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated | ||
90 | const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated | ||
91 | const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated | ||
92 | const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated | ||
93 | const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated | ||
94 | const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated | ||
83 | 95 | ||
84 | LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion | 96 | LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion |
85 | LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion | 97 | LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion |
@@ -87,11 +99,16 @@ public: | |||
87 | void getAngleAxis(F32* angle, LLVector3 &vec) const; | 99 | void getAngleAxis(F32* angle, LLVector3 &vec) const; |
88 | void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; | 100 | void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; |
89 | 101 | ||
90 | F32 normQuat(); // Normalizes Quaternion and returns magnitude | 102 | F32 normalize(); // Normalizes Quaternion and returns magnitude |
91 | const LLQuaternion& conjQuat(void); // Conjugates Quaternion and returns result | 103 | F32 normQuat(); // deprecated |
104 | |||
105 | const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result | ||
106 | const LLQuaternion& conjQuat(void); // deprecated | ||
92 | 107 | ||
93 | // Other useful methods | 108 | // Other useful methods |
94 | const LLQuaternion& transQuat(); // Transpose | 109 | const LLQuaternion& transpose(); // transpose (same as conjugate) |
110 | const LLQuaternion& transQuat(); // deprecated | ||
111 | |||
95 | void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b | 112 | void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b |
96 | const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians | 113 | const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians |
97 | 114 | ||
@@ -189,7 +206,7 @@ inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w) | |||
189 | mQ[VS] = w; | 206 | mQ[VS] = w; |
190 | 207 | ||
191 | //RN: don't normalize this case as its used mainly for temporaries during calculations | 208 | //RN: don't normalize this case as its used mainly for temporaries during calculations |
192 | //normQuat(); | 209 | //normalize(); |
193 | /* | 210 | /* |
194 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | 211 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); |
195 | mag -= 1.f; | 212 | mag -= 1.f; |
@@ -205,7 +222,7 @@ inline LLQuaternion::LLQuaternion(const F32 *q) | |||
205 | mQ[VZ] = q[VZ]; | 222 | mQ[VZ] = q[VZ]; |
206 | mQ[VS] = q[VW]; | 223 | mQ[VS] = q[VW]; |
207 | 224 | ||
208 | normQuat(); | 225 | normalize(); |
209 | /* | 226 | /* |
210 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | 227 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); |
211 | mag -= 1.f; | 228 | mag -= 1.f; |
@@ -224,33 +241,67 @@ inline void LLQuaternion::loadIdentity() | |||
224 | } | 241 | } |
225 | 242 | ||
226 | 243 | ||
244 | inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) | ||
245 | { | ||
246 | mQ[VX] = x; | ||
247 | mQ[VY] = y; | ||
248 | mQ[VZ] = z; | ||
249 | mQ[VS] = w; | ||
250 | normalize(); | ||
251 | return (*this); | ||
252 | } | ||
253 | |||
254 | inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat) | ||
255 | { | ||
256 | mQ[VX] = quat.mQ[VX]; | ||
257 | mQ[VY] = quat.mQ[VY]; | ||
258 | mQ[VZ] = quat.mQ[VZ]; | ||
259 | mQ[VW] = quat.mQ[VW]; | ||
260 | normalize(); | ||
261 | return (*this); | ||
262 | } | ||
263 | |||
264 | inline const LLQuaternion& LLQuaternion::set(const F32 *q) | ||
265 | { | ||
266 | mQ[VX] = q[VX]; | ||
267 | mQ[VY] = q[VY]; | ||
268 | mQ[VZ] = q[VZ]; | ||
269 | mQ[VS] = q[VW]; | ||
270 | normalize(); | ||
271 | return (*this); | ||
272 | } | ||
273 | |||
274 | |||
275 | // deprecated | ||
227 | inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) | 276 | inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) |
228 | { | 277 | { |
229 | mQ[VX] = x; | 278 | mQ[VX] = x; |
230 | mQ[VY] = y; | 279 | mQ[VY] = y; |
231 | mQ[VZ] = z; | 280 | mQ[VZ] = z; |
232 | mQ[VS] = w; | 281 | mQ[VS] = w; |
233 | normQuat(); | 282 | normalize(); |
234 | return (*this); | 283 | return (*this); |
235 | } | 284 | } |
236 | 285 | ||
286 | // deprecated | ||
237 | inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) | 287 | inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) |
238 | { | 288 | { |
239 | mQ[VX] = quat.mQ[VX]; | 289 | mQ[VX] = quat.mQ[VX]; |
240 | mQ[VY] = quat.mQ[VY]; | 290 | mQ[VY] = quat.mQ[VY]; |
241 | mQ[VZ] = quat.mQ[VZ]; | 291 | mQ[VZ] = quat.mQ[VZ]; |
242 | mQ[VW] = quat.mQ[VW]; | 292 | mQ[VW] = quat.mQ[VW]; |
243 | normQuat(); | 293 | normalize(); |
244 | return (*this); | 294 | return (*this); |
245 | } | 295 | } |
246 | 296 | ||
297 | // deprecated | ||
247 | inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) | 298 | inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) |
248 | { | 299 | { |
249 | mQ[VX] = q[VX]; | 300 | mQ[VX] = q[VX]; |
250 | mQ[VY] = q[VY]; | 301 | mQ[VY] = q[VY]; |
251 | mQ[VZ] = q[VZ]; | 302 | mQ[VZ] = q[VZ]; |
252 | mQ[VS] = q[VW]; | 303 | mQ[VS] = q[VW]; |
253 | normQuat(); | 304 | normalize(); |
254 | return (*this); | 305 | return (*this); |
255 | } | 306 | } |
256 | 307 | ||
@@ -270,10 +321,36 @@ inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const | |||
270 | else | 321 | else |
271 | sin_a = 1.f/sin_a; | 322 | sin_a = 1.f/sin_a; |
272 | 323 | ||
273 | *angle = 2.0f * (F32) acos( cos_a ); | 324 | F32 temp_angle = 2.0f * (F32) acos( cos_a ); |
274 | *x = mQ[VX] * sin_a; | 325 | if (temp_angle > F_PI) |
275 | *y = mQ[VY] * sin_a; | 326 | { |
276 | *z = mQ[VZ] * sin_a; | 327 | // The (angle,axis) pair should never have angles outside [PI, -PI] |
328 | // since we want the _shortest_ (angle,axis) solution. | ||
329 | // Since acos is defined for [0, PI], and we multiply by 2.0, we | ||
330 | // can push the angle outside the acceptible range. | ||
331 | // When this happens we set the angle to the other portion of a | ||
332 | // full 2PI rotation, and negate the axis, which reverses the | ||
333 | // direction of the rotation (by the right-hand rule). | ||
334 | *angle = 2.f * F_PI - temp_angle; | ||
335 | *x = - mQ[VX] * sin_a; | ||
336 | *y = - mQ[VY] * sin_a; | ||
337 | *z = - mQ[VZ] * sin_a; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | *angle = temp_angle; | ||
342 | *x = mQ[VX] * sin_a; | ||
343 | *y = mQ[VY] * sin_a; | ||
344 | *z = mQ[VZ] * sin_a; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | inline const LLQuaternion& LLQuaternion::conjugate() | ||
349 | { | ||
350 | mQ[VX] *= -1.f; | ||
351 | mQ[VY] *= -1.f; | ||
352 | mQ[VZ] *= -1.f; | ||
353 | return (*this); | ||
277 | } | 354 | } |
278 | 355 | ||
279 | inline const LLQuaternion& LLQuaternion::conjQuat() | 356 | inline const LLQuaternion& LLQuaternion::conjQuat() |
@@ -285,12 +362,21 @@ inline const LLQuaternion& LLQuaternion::conjQuat() | |||
285 | } | 362 | } |
286 | 363 | ||
287 | // Transpose | 364 | // Transpose |
365 | inline const LLQuaternion& LLQuaternion::transpose() | ||
366 | { | ||
367 | mQ[VX] *= -1.f; | ||
368 | mQ[VY] *= -1.f; | ||
369 | mQ[VZ] *= -1.f; | ||
370 | return (*this); | ||
371 | } | ||
372 | |||
373 | // deprecated | ||
288 | inline const LLQuaternion& LLQuaternion::transQuat() | 374 | inline const LLQuaternion& LLQuaternion::transQuat() |
289 | { | 375 | { |
290 | mQ[VX] = -mQ[VX]; | 376 | mQ[VX] *= -1.f; |
291 | mQ[VY] = -mQ[VY]; | 377 | mQ[VY] *= -1.f; |
292 | mQ[VZ] = -mQ[VZ]; | 378 | mQ[VZ] *= -1.f; |
293 | return *this; | 379 | return (*this); |
294 | } | 380 | } |
295 | 381 | ||
296 | 382 | ||
@@ -382,6 +468,30 @@ inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b) | |||
382 | return a; | 468 | return a; |
383 | } | 469 | } |
384 | 470 | ||
471 | inline F32 LLQuaternion::normalize() | ||
472 | { | ||
473 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | ||
474 | |||
475 | if (mag > FP_MAG_THRESHOLD) | ||
476 | { | ||
477 | F32 oomag = 1.f/mag; | ||
478 | mQ[VX] *= oomag; | ||
479 | mQ[VY] *= oomag; | ||
480 | mQ[VZ] *= oomag; | ||
481 | mQ[VS] *= oomag; | ||
482 | } | ||
483 | else | ||
484 | { | ||
485 | mQ[VX] = 0.f; | ||
486 | mQ[VY] = 0.f; | ||
487 | mQ[VZ] = 0.f; | ||
488 | mQ[VS] = 1.f; | ||
489 | } | ||
490 | |||
491 | return mag; | ||
492 | } | ||
493 | |||
494 | // deprecated | ||
385 | inline F32 LLQuaternion::normQuat() | 495 | inline F32 LLQuaternion::normQuat() |
386 | { | 496 | { |
387 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | 497 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); |