diff options
author | Jacek Antonelli | 2008-08-15 23:45:42 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:42 -0500 |
commit | ce28e056c20bf2723f565bbf464b87781ec248a2 (patch) | |
tree | ef7b0501c4de4b631a916305cbc2a5fdc125e52d /linden/indra/llmath/llquaternion.cpp | |
parent | Second Life viewer sources 1.19.1.4b (diff) | |
download | meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.zip meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.gz meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.bz2 meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.xz |
Second Life viewer sources 1.20.2
Diffstat (limited to 'linden/indra/llmath/llquaternion.cpp')
-rw-r--r-- | linden/indra/llmath/llquaternion.cpp | 186 |
1 files changed, 144 insertions, 42 deletions
diff --git a/linden/indra/llmath/llquaternion.cpp b/linden/indra/llmath/llquaternion.cpp index ea51e28..ab4855b 100644 --- a/linden/indra/llmath/llquaternion.cpp +++ b/linden/indra/llmath/llquaternion.cpp | |||
@@ -51,19 +51,19 @@ const LLQuaternion LLQuaternion::DEFAULT; | |||
51 | LLQuaternion::LLQuaternion(const LLMatrix4 &mat) | 51 | LLQuaternion::LLQuaternion(const LLMatrix4 &mat) |
52 | { | 52 | { |
53 | *this = mat.quaternion(); | 53 | *this = mat.quaternion(); |
54 | normQuat(); | 54 | normalize(); |
55 | } | 55 | } |
56 | 56 | ||
57 | LLQuaternion::LLQuaternion(const LLMatrix3 &mat) | 57 | LLQuaternion::LLQuaternion(const LLMatrix3 &mat) |
58 | { | 58 | { |
59 | *this = mat.quaternion(); | 59 | *this = mat.quaternion(); |
60 | normQuat(); | 60 | normalize(); |
61 | } | 61 | } |
62 | 62 | ||
63 | LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) | 63 | LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) |
64 | { | 64 | { |
65 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); | 65 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); |
66 | v.normVec(); | 66 | v.normalize(); |
67 | 67 | ||
68 | F32 c, s; | 68 | F32 c, s; |
69 | c = cosf(angle*0.5f); | 69 | c = cosf(angle*0.5f); |
@@ -73,13 +73,13 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) | |||
73 | mQ[VY] = v.mV[VY] * s; | 73 | mQ[VY] = v.mV[VY] * s; |
74 | mQ[VZ] = v.mV[VZ] * s; | 74 | mQ[VZ] = v.mV[VZ] * s; |
75 | mQ[VW] = c; | 75 | mQ[VW] = c; |
76 | normQuat(); | 76 | normalize(); |
77 | } | 77 | } |
78 | 78 | ||
79 | LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) | 79 | LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) |
80 | { | 80 | { |
81 | LLVector3 v(vec); | 81 | LLVector3 v(vec); |
82 | v.normVec(); | 82 | v.normalize(); |
83 | 83 | ||
84 | F32 c, s; | 84 | F32 c, s; |
85 | c = cosf(angle*0.5f); | 85 | c = cosf(angle*0.5f); |
@@ -89,7 +89,7 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) | |||
89 | mQ[VY] = v.mV[VY] * s; | 89 | mQ[VY] = v.mV[VY] * s; |
90 | mQ[VZ] = v.mV[VZ] * s; | 90 | mQ[VZ] = v.mV[VZ] * s; |
91 | mQ[VW] = c; | 91 | mQ[VW] = c; |
92 | normQuat(); | 92 | normalize(); |
93 | } | 93 | } |
94 | 94 | ||
95 | LLQuaternion::LLQuaternion(const LLVector3 &x_axis, | 95 | LLQuaternion::LLQuaternion(const LLVector3 &x_axis, |
@@ -99,7 +99,7 @@ LLQuaternion::LLQuaternion(const LLVector3 &x_axis, | |||
99 | LLMatrix3 mat; | 99 | LLMatrix3 mat; |
100 | mat.setRows(x_axis, y_axis, z_axis); | 100 | mat.setRows(x_axis, y_axis, z_axis); |
101 | *this = mat.quaternion(); | 101 | *this = mat.quaternion(); |
102 | normQuat(); | 102 | normalize(); |
103 | } | 103 | } |
104 | 104 | ||
105 | // Quatizations | 105 | // Quatizations |
@@ -138,10 +138,93 @@ void LLQuaternion::quantize8(F32 lower, F32 upper) | |||
138 | 138 | ||
139 | // Set LLQuaternion routines | 139 | // Set LLQuaternion routines |
140 | 140 | ||
141 | const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z) | ||
142 | { | ||
143 | LLVector3 vec(x, y, z); | ||
144 | vec.normalize(); | ||
145 | |||
146 | angle *= 0.5f; | ||
147 | F32 c, s; | ||
148 | c = cosf(angle); | ||
149 | s = sinf(angle); | ||
150 | |||
151 | mQ[VX] = vec.mV[VX]*s; | ||
152 | mQ[VY] = vec.mV[VY]*s; | ||
153 | mQ[VZ] = vec.mV[VZ]*s; | ||
154 | mQ[VW] = c; | ||
155 | |||
156 | normalize(); | ||
157 | return (*this); | ||
158 | } | ||
159 | |||
160 | const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec) | ||
161 | { | ||
162 | LLVector3 v(vec); | ||
163 | v.normalize(); | ||
164 | |||
165 | angle *= 0.5f; | ||
166 | F32 c, s; | ||
167 | c = cosf(angle); | ||
168 | s = sinf(angle); | ||
169 | |||
170 | mQ[VX] = v.mV[VX]*s; | ||
171 | mQ[VY] = v.mV[VY]*s; | ||
172 | mQ[VZ] = v.mV[VZ]*s; | ||
173 | mQ[VW] = c; | ||
174 | |||
175 | normalize(); | ||
176 | return (*this); | ||
177 | } | ||
178 | |||
179 | const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec) | ||
180 | { | ||
181 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); | ||
182 | v.normalize(); | ||
183 | |||
184 | F32 c, s; | ||
185 | c = cosf(angle*0.5f); | ||
186 | s = sinf(angle*0.5f); | ||
187 | |||
188 | mQ[VX] = v.mV[VX]*s; | ||
189 | mQ[VY] = v.mV[VY]*s; | ||
190 | mQ[VZ] = v.mV[VZ]*s; | ||
191 | mQ[VW] = c; | ||
192 | |||
193 | normalize(); | ||
194 | return (*this); | ||
195 | } | ||
196 | |||
197 | const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw) | ||
198 | { | ||
199 | LLMatrix3 rot_mat(roll, pitch, yaw); | ||
200 | rot_mat.orthogonalize(); | ||
201 | *this = rot_mat.quaternion(); | ||
202 | |||
203 | normalize(); | ||
204 | return (*this); | ||
205 | } | ||
206 | |||
207 | // deprecated | ||
208 | const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat) | ||
209 | { | ||
210 | *this = mat.quaternion(); | ||
211 | normalize(); | ||
212 | return (*this); | ||
213 | } | ||
214 | |||
215 | // deprecated | ||
216 | const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat) | ||
217 | { | ||
218 | *this = mat.quaternion(); | ||
219 | normalize(); | ||
220 | return (*this); | ||
221 | } | ||
222 | |||
223 | // deprecated | ||
141 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) | 224 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) |
142 | { | 225 | { |
143 | LLVector3 vec(x, y, z); | 226 | LLVector3 vec(x, y, z); |
144 | vec.normVec(); | 227 | vec.normalize(); |
145 | 228 | ||
146 | angle *= 0.5f; | 229 | angle *= 0.5f; |
147 | F32 c, s; | 230 | F32 c, s; |
@@ -153,14 +236,15 @@ const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) | |||
153 | mQ[VZ] = vec.mV[VZ]*s; | 236 | mQ[VZ] = vec.mV[VZ]*s; |
154 | mQ[VW] = c; | 237 | mQ[VW] = c; |
155 | 238 | ||
156 | normQuat(); | 239 | normalize(); |
157 | return (*this); | 240 | return (*this); |
158 | } | 241 | } |
159 | 242 | ||
243 | // deprecated | ||
160 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) | 244 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) |
161 | { | 245 | { |
162 | LLVector3 v(vec); | 246 | LLVector3 v(vec); |
163 | v.normVec(); | 247 | v.normalize(); |
164 | 248 | ||
165 | angle *= 0.5f; | 249 | angle *= 0.5f; |
166 | F32 c, s; | 250 | F32 c, s; |
@@ -172,14 +256,14 @@ const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) | |||
172 | mQ[VZ] = v.mV[VZ]*s; | 256 | mQ[VZ] = v.mV[VZ]*s; |
173 | mQ[VW] = c; | 257 | mQ[VW] = c; |
174 | 258 | ||
175 | normQuat(); | 259 | normalize(); |
176 | return (*this); | 260 | return (*this); |
177 | } | 261 | } |
178 | 262 | ||
179 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) | 263 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) |
180 | { | 264 | { |
181 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); | 265 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); |
182 | v.normVec(); | 266 | v.normalize(); |
183 | 267 | ||
184 | F32 c, s; | 268 | F32 c, s; |
185 | c = cosf(angle*0.5f); | 269 | c = cosf(angle*0.5f); |
@@ -190,7 +274,7 @@ const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) | |||
190 | mQ[VZ] = v.mV[VZ]*s; | 274 | mQ[VZ] = v.mV[VZ]*s; |
191 | mQ[VW] = c; | 275 | mQ[VW] = c; |
192 | 276 | ||
193 | normQuat(); | 277 | normalize(); |
194 | return (*this); | 278 | return (*this); |
195 | } | 279 | } |
196 | 280 | ||
@@ -200,7 +284,21 @@ const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw) | |||
200 | rot_mat.orthogonalize(); | 284 | rot_mat.orthogonalize(); |
201 | *this = rot_mat.quaternion(); | 285 | *this = rot_mat.quaternion(); |
202 | 286 | ||
203 | normQuat(); | 287 | normalize(); |
288 | return (*this); | ||
289 | } | ||
290 | |||
291 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) | ||
292 | { | ||
293 | *this = mat.quaternion(); | ||
294 | normalize(); | ||
295 | return (*this); | ||
296 | } | ||
297 | |||
298 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) | ||
299 | { | ||
300 | *this = mat.quaternion(); | ||
301 | normalize(); | ||
204 | return (*this); | 302 | return (*this); |
205 | //#if 1 | 303 | //#if 1 |
206 | // // NOTE: LLQuaternion's are actually inverted with respect to | 304 | // // NOTE: LLQuaternion's are actually inverted with respect to |
@@ -337,8 +435,8 @@ void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) | |||
337 | 435 | ||
338 | // Make sure neither vector is zero length. Also normalize | 436 | // Make sure neither vector is zero length. Also normalize |
339 | // the vectors while we are at it. | 437 | // the vectors while we are at it. |
340 | F32 vec_a_mag = vec_a.normVec(); | 438 | F32 vec_a_mag = vec_a.normalize(); |
341 | F32 vec_b_mag = vec_b.normVec(); | 439 | F32 vec_b_mag = vec_b.normalize(); |
342 | if (vec_a_mag < F_APPROXIMATELY_ZERO || | 440 | if (vec_a_mag < F_APPROXIMATELY_ZERO || |
343 | vec_b_mag < F_APPROXIMATELY_ZERO) | 441 | vec_b_mag < F_APPROXIMATELY_ZERO) |
344 | { | 442 | { |
@@ -370,7 +468,7 @@ void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) | |||
370 | ortho_axis -= proj; | 468 | ortho_axis -= proj; |
371 | 469 | ||
372 | // Turn this into an orthonormal axis. | 470 | // Turn this into an orthonormal axis. |
373 | F32 ortho_length = ortho_axis.normVec(); | 471 | F32 ortho_length = ortho_axis.normalize(); |
374 | // If the axis' length is 0, then our guess at an orthogonal axis | 472 | // If the axis' length is 0, then our guess at an orthogonal axis |
375 | // was wrong (a is parallel to the x-axis). | 473 | // was wrong (a is parallel to the x-axis). |
376 | if (ortho_length < F_APPROXIMATELY_ZERO) | 474 | if (ortho_length < F_APPROXIMATELY_ZERO) |
@@ -391,7 +489,7 @@ void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) | |||
391 | // Return the rotation between these vectors. | 489 | // Return the rotation between these vectors. |
392 | F32 theta = (F32)acos(cos_theta); | 490 | F32 theta = (F32)acos(cos_theta); |
393 | 491 | ||
394 | setQuat(theta, axis); | 492 | setAngleAxis(theta, axis); |
395 | } | 493 | } |
396 | } | 494 | } |
397 | 495 | ||
@@ -516,7 +614,7 @@ LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) | |||
516 | { | 614 | { |
517 | LLQuaternion r; | 615 | LLQuaternion r; |
518 | r = t * (q - p) + p; | 616 | r = t * (q - p) + p; |
519 | r.normQuat(); | 617 | r.normalize(); |
520 | return r; | 618 | return r; |
521 | } | 619 | } |
522 | #endif | 620 | #endif |
@@ -529,7 +627,7 @@ LLQuaternion lerp(F32 t, const LLQuaternion &q) | |||
529 | r.mQ[VY] = t * q.mQ[VY]; | 627 | r.mQ[VY] = t * q.mQ[VY]; |
530 | r.mQ[VZ] = t * q.mQ[VZ]; | 628 | r.mQ[VZ] = t * q.mQ[VZ]; |
531 | r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; | 629 | r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; |
532 | r.normQuat(); | 630 | r.normalize(); |
533 | return r; | 631 | return r; |
534 | } | 632 | } |
535 | 633 | ||
@@ -544,7 +642,7 @@ LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) | |||
544 | r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); | 642 | r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); |
545 | r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); | 643 | r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); |
546 | r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); | 644 | r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); |
547 | r.normQuat(); | 645 | r.normalize(); |
548 | return r; | 646 | return r; |
549 | } | 647 | } |
550 | 648 | ||
@@ -640,8 +738,8 @@ LLQuaternion slerp(F32 t, const LLQuaternion &q) | |||
640 | // when c < 0.0 then theta > PI/2 | 738 | // when c < 0.0 then theta > PI/2 |
641 | // since quat and -quat are the same rotation we invert one of | 739 | // since quat and -quat are the same rotation we invert one of |
642 | // p or q to reduce unecessary spins | 740 | // p or q to reduce unecessary spins |
643 | // A equivalent way to do it is to convert acos(c) as if it had been negative, | 741 | // A equivalent way to do it is to convert acos(c) as if it had |
644 | // and to negate stp | 742 | // been negative, and to negate stp |
645 | angle = (F32) acos(-c); | 743 | angle = (F32) acos(-c); |
646 | stp = -(F32) sin(angle * (1.f - t)); | 744 | stp = -(F32) sin(angle * (1.f - t)); |
647 | stq = (F32) sin(angle * t); | 745 | stq = (F32) sin(angle * t); |
@@ -742,20 +840,6 @@ LLQuaternion::Order StringToOrder( const char *str ) | |||
742 | return LLQuaternion::XYZ; | 840 | return LLQuaternion::XYZ; |
743 | } | 841 | } |
744 | 842 | ||
745 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) | ||
746 | { | ||
747 | *this = mat.quaternion(); | ||
748 | normQuat(); | ||
749 | return (*this); | ||
750 | } | ||
751 | |||
752 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) | ||
753 | { | ||
754 | *this = mat.quaternion(); | ||
755 | normQuat(); | ||
756 | return (*this); | ||
757 | } | ||
758 | |||
759 | void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const | 843 | void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const |
760 | { | 844 | { |
761 | F32 cos_a = mQ[VW]; | 845 | F32 cos_a = mQ[VW]; |
@@ -769,10 +853,28 @@ void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const | |||
769 | else | 853 | else |
770 | sin_a = 1.f/sin_a; | 854 | sin_a = 1.f/sin_a; |
771 | 855 | ||
772 | *angle = 2.0f * (F32) acos( cos_a ); | 856 | F32 temp_angle = 2.0f * (F32) acos( cos_a ); |
773 | vec.mV[VX] = mQ[VX] * sin_a; | 857 | if (temp_angle > F_PI) |
774 | vec.mV[VY] = mQ[VY] * sin_a; | 858 | { |
775 | vec.mV[VZ] = mQ[VZ] * sin_a; | 859 | // The (angle,axis) pair should never have angles outside [PI, -PI] |
860 | // since we want the _shortest_ (angle,axis) solution. | ||
861 | // Since acos is defined for [0, PI], and we multiply by 2.0, we | ||
862 | // can push the angle outside the acceptible range. | ||
863 | // When this happens we set the angle to the other portion of a | ||
864 | // full 2PI rotation, and negate the axis, which reverses the | ||
865 | // direction of the rotation (by the right-hand rule). | ||
866 | *angle = 2.f * F_PI - temp_angle; | ||
867 | vec.mV[VX] = - mQ[VX] * sin_a; | ||
868 | vec.mV[VY] = - mQ[VY] * sin_a; | ||
869 | vec.mV[VZ] = - mQ[VZ] * sin_a; | ||
870 | } | ||
871 | else | ||
872 | { | ||
873 | *angle = temp_angle; | ||
874 | vec.mV[VX] = mQ[VX] * sin_a; | ||
875 | vec.mV[VY] = mQ[VY] * sin_a; | ||
876 | vec.mV[VZ] = mQ[VZ] * sin_a; | ||
877 | } | ||
776 | } | 878 | } |
777 | 879 | ||
778 | 880 | ||
@@ -846,7 +948,7 @@ BOOL LLQuaternion::parseQuat(const char* buf, LLQuaternion* value) | |||
846 | S32 count = sscanf( buf, "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); | 948 | S32 count = sscanf( buf, "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); |
847 | if( 4 == count ) | 949 | if( 4 == count ) |
848 | { | 950 | { |
849 | value->setQuat( quat ); | 951 | value->set( quat ); |
850 | return TRUE; | 952 | return TRUE; |
851 | } | 953 | } |
852 | 954 | ||