aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llquaternion.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:42 -0500
committerJacek Antonelli2008-08-15 23:45:42 -0500
commitce28e056c20bf2723f565bbf464b87781ec248a2 (patch)
treeef7b0501c4de4b631a916305cbc2a5fdc125e52d /linden/indra/llmath/llquaternion.cpp
parentSecond Life viewer sources 1.19.1.4b (diff)
downloadmeta-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.cpp186
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;
51LLQuaternion::LLQuaternion(const LLMatrix4 &mat) 51LLQuaternion::LLQuaternion(const LLMatrix4 &mat)
52{ 52{
53 *this = mat.quaternion(); 53 *this = mat.quaternion();
54 normQuat(); 54 normalize();
55} 55}
56 56
57LLQuaternion::LLQuaternion(const LLMatrix3 &mat) 57LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
58{ 58{
59 *this = mat.quaternion(); 59 *this = mat.quaternion();
60 normQuat(); 60 normalize();
61} 61}
62 62
63LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) 63LLQuaternion::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
79LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) 79LLQuaternion::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
95LLQuaternion::LLQuaternion(const LLVector3 &x_axis, 95LLQuaternion::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
141const 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
160const 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
179const 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
197const 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
208const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat)
209{
210 *this = mat.quaternion();
211 normalize();
212 return (*this);
213}
214
215// deprecated
216const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat)
217{
218 *this = mat.quaternion();
219 normalize();
220 return (*this);
221}
222
223// deprecated
141const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) 224const 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
160const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) 244const 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
179const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) 263const 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
291const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat)
292{
293 *this = mat.quaternion();
294 normalize();
295 return (*this);
296}
297
298const 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
745const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat)
746{
747 *this = mat.quaternion();
748 normQuat();
749 return (*this);
750}
751
752const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
753{
754 *this = mat.quaternion();
755 normQuat();
756 return (*this);
757}
758
759void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const 843void 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