GteTransform.cpp
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #include <GTEnginePCH.h>
10 #include <algorithm>
11 using namespace gte;
12 
14 
15 
17  :
18  mTranslate({ 0.0f, 0.0f, 0.0f, 1.0f }),
19  mScale({ 1.0f, 1.0f, 1.0f, 1.0f }),
20  mIsIdentity(true),
21  mIsRSMatrix(true),
22  mIsUniformScale(true),
23  mInverseNeedsUpdate(false)
24 {
25  mHMatrix.MakeIdentity();
26  mInvHMatrix.MakeIdentity();
27  mMatrix.MakeIdentity();
28 }
29 
31 {
32  mMatrix.MakeIdentity();
33  mTranslate = { 0.0f, 0.0f, 0.0f, 1.0f };
34  mScale = { 1.0f, 1.0f, 1.0f, 1.0f };
35  mIsIdentity = true;
36  mIsRSMatrix = true;
37  mIsUniformScale = true;
38  UpdateHMatrix();
39 }
40 
42 {
43  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
44  mScale = { 1.0f, 1.0f, 1.0f, 1.0f };
45  mIsUniformScale = true;
46  UpdateHMatrix();
47 }
48 
50 {
51  mMatrix = rotate;
52  mIsIdentity = false;
53  mIsRSMatrix = true;
54  UpdateHMatrix();
55 }
56 
58 {
59  mMatrix = matrix;
60  mIsIdentity = false;
61  mIsRSMatrix = false;
62  mIsUniformScale = false;
63  UpdateHMatrix();
64 }
65 
66 void Transform::SetTranslation(float x0, float x1, float x2)
67 {
68  mTranslate = { x0, x1, x2, 1.0f };
69  mIsIdentity = false;
70  UpdateHMatrix();
71 }
72 
74 {
75  SetTranslation(translate[0], translate[1], translate[2]);
76 }
77 
79 {
80  SetTranslation(translate[0], translate[1], translate[2]);
81 }
82 
83 void Transform::SetScale(float s0, float s1, float s2)
84 {
85  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
86  LogAssert(s0 != 0.0f && s1 != 0.0f && s2 != 0.0f,
87  "Scales must be nonzero.");
88 
89  mScale = { s0, s1, s2, 1.0f };
90  mIsIdentity = false;
91  mIsUniformScale = false;
92  UpdateHMatrix();
93 }
94 
96 {
97  SetScale(scale[0], scale[1], scale[2]);
98 }
99 
101 {
102  SetScale(scale[0], scale[1], scale[2]);
103 }
104 
106 {
107  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
108  LogAssert(scale != 0.0f, "Scale must be nonzero.");
109 
110  mScale = { scale, scale, scale, 1.0f };
111  mIsIdentity = false;
112  mIsUniformScale = true;
113  UpdateHMatrix();
114 }
115 
117 {
118  mMatrix.MakeIdentity();
119  for (int r = 0; r < 3; ++r)
120  {
121  for (int c = 0; c < 3; ++c)
122  {
123  mMatrix(r, c) = rotate(r, c);
124  }
125  }
126 
127  mIsIdentity = false;
128  mIsRSMatrix = true;
129  UpdateHMatrix();
130 }
131 
133 {
134  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
135  for (int r = 0; r < 3; ++r)
136  {
137  for (int c = 0; c < 3; ++c)
138  {
139  rotate(r, c) = mMatrix(r, c);
140  }
141  }
142 }
143 
145 {
147  mIsIdentity = false;
148  mIsRSMatrix = true;
149  UpdateHMatrix();
150 }
151 
153 {
154  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
156 }
157 
159 {
160  mMatrix = Rotation<4, float>(axisAngle);
161  mIsIdentity = false;
162  mIsRSMatrix = true;
163  UpdateHMatrix();
164 }
165 
167 {
168  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
169  axisAngle = Rotation<4, float>(mMatrix);
170 }
171 
173 {
174  mMatrix = Rotation<4, float>(eulerAngles);
175  mIsIdentity = false;
176  mIsRSMatrix = true;
177  UpdateHMatrix();
178 }
179 
181 {
182  LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
183  eulerAngles = Rotation<4, float>(mMatrix)(eulerAngles.axis[0],
184  eulerAngles.axis[1], eulerAngles.axis[2]);
185 }
186 
187 float Transform::GetNorm() const
188 {
189  float r0, r1, r2;
190 
191  if (mIsRSMatrix)
192  {
193  // A RS matrix (GTE_USE_MAT_VEC) or an SR matrix (GTE_USE_VEC_MAT).
194  r0 = fabs(mScale[0]);
195  r1 = fabs(mScale[1]);
196  r2 = fabs(mScale[2]);
197  }
198  else
199  {
200  // The spectral norm (the maximum absolute value of the eigenvalues)
201  // is smaller or equal to this norm. Therefore, this function returns
202  // an approximation to the maximum scale.
203 
204 #if defined(GTE_USE_MAT_VEC)
205  // Use the max-row-sum matrix norm.
206  r0 = fabs(mMatrix(0, 0)) + fabs(mMatrix(0, 1)) + fabs(mMatrix(0, 2));
207  r1 = fabs(mMatrix(1, 0)) + fabs(mMatrix(1, 1)) + fabs(mMatrix(1, 2));
208  r2 = fabs(mMatrix(2, 0)) + fabs(mMatrix(2, 1)) + fabs(mMatrix(2, 2));
209 #else
210  // Use the max-col-sum matrix norm.
211  r0 = fabs(mMatrix(0, 0)) + fabs(mMatrix(1, 0)) + fabs(mMatrix(2, 0));
212  r1 = fabs(mMatrix(0, 1)) + fabs(mMatrix(1, 1)) + fabs(mMatrix(2, 1));
213  r2 = fabs(mMatrix(0, 2)) + fabs(mMatrix(1, 2)) + fabs(mMatrix(2, 2));
214 #endif
215  }
216 
217  return std::max(std::max(r0, r1), r2);
218 }
219 
221 {
223  {
224  if (mIsIdentity)
225  {
226  mInvHMatrix.MakeIdentity();
227  }
228  else
229  {
230  if (mIsRSMatrix)
231  {
232  if (mIsUniformScale)
233  {
234  float invScale = 1.0f / mScale[0];
235 #if defined(GTE_USE_MAT_VEC)
236  mInvHMatrix(0, 0) = invScale * mMatrix(0, 0);
237  mInvHMatrix(0, 1) = invScale * mMatrix(1, 0);
238  mInvHMatrix(0, 2) = invScale * mMatrix(2, 0);
239  mInvHMatrix(1, 0) = invScale * mMatrix(0, 1);
240  mInvHMatrix(1, 1) = invScale * mMatrix(1, 1);
241  mInvHMatrix(1, 2) = invScale * mMatrix(2, 1);
242  mInvHMatrix(2, 0) = invScale * mMatrix(0, 2);
243  mInvHMatrix(2, 1) = invScale * mMatrix(1, 2);
244  mInvHMatrix(2, 2) = invScale * mMatrix(2, 2);
245 #else
246  mInvHMatrix(0, 0) = mMatrix(0, 0) * invScale;
247  mInvHMatrix(0, 1) = mMatrix(1, 0) * invScale;
248  mInvHMatrix(0, 2) = mMatrix(2, 0) * invScale;
249  mInvHMatrix(1, 0) = mMatrix(0, 1) * invScale;
250  mInvHMatrix(1, 1) = mMatrix(1, 1) * invScale;
251  mInvHMatrix(1, 2) = mMatrix(2, 1) * invScale;
252  mInvHMatrix(2, 0) = mMatrix(0, 2) * invScale;
253  mInvHMatrix(2, 1) = mMatrix(1, 2) * invScale;
254  mInvHMatrix(2, 2) = mMatrix(2, 2) * invScale;
255 #endif
256  }
257  else
258  {
259  // Replace 3 reciprocals by 6 multiplies and 1 reciprocal.
260  float s01 = mScale[0] * mScale[1];
261  float s02 = mScale[0] * mScale[2];
262  float s12 = mScale[1] * mScale[2];
263  float invs012 = 1.0f / (s01 * mScale[2]);
264  float invS0 = s12 * invs012;
265  float invS1 = s02 * invs012;
266  float invS2 = s01 * invs012;
267 #if defined(GTE_USE_MAT_VEC)
268  mInvHMatrix(0, 0) = invS0 * mMatrix(0, 0);
269  mInvHMatrix(0, 1) = invS0 * mMatrix(1, 0);
270  mInvHMatrix(0, 2) = invS0 * mMatrix(2, 0);
271  mInvHMatrix(1, 0) = invS1 * mMatrix(0, 1);
272  mInvHMatrix(1, 1) = invS1 * mMatrix(1, 1);
273  mInvHMatrix(1, 2) = invS1 * mMatrix(2, 1);
274  mInvHMatrix(2, 0) = invS2 * mMatrix(0, 2);
275  mInvHMatrix(2, 1) = invS2 * mMatrix(1, 2);
276  mInvHMatrix(2, 2) = invS2 * mMatrix(2, 2);
277 #else
278  mInvHMatrix(0, 0) = mMatrix(0, 0) * invS0;
279  mInvHMatrix(0, 1) = mMatrix(1, 0) * invS1;
280  mInvHMatrix(0, 2) = mMatrix(2, 0) * invS2;
281  mInvHMatrix(1, 0) = mMatrix(0, 1) * invS0;
282  mInvHMatrix(1, 1) = mMatrix(1, 1) * invS1;
283  mInvHMatrix(1, 2) = mMatrix(2, 1) * invS2;
284  mInvHMatrix(2, 0) = mMatrix(0, 2) * invS0;
285  mInvHMatrix(2, 1) = mMatrix(1, 2) * invS1;
286  mInvHMatrix(2, 2) = mMatrix(2, 2) * invS2;
287 #endif
288  }
289  }
290  else
291  {
293  }
294 
295 #if defined(GTE_USE_MAT_VEC)
296  mInvHMatrix(0, 3) = -(
297  mInvHMatrix(0, 0) * mTranslate[0] +
298  mInvHMatrix(0, 1) * mTranslate[1] +
299  mInvHMatrix(0, 2) * mTranslate[2]
300  );
301 
302  mInvHMatrix(1, 3) = -(
303  mInvHMatrix(1, 0) * mTranslate[0] +
304  mInvHMatrix(1, 1) * mTranslate[1] +
305  mInvHMatrix(1, 2) * mTranslate[2]
306  );
307 
308  mInvHMatrix(2, 3) = -(
309  mInvHMatrix(2, 0) * mTranslate[0] +
310  mInvHMatrix(2, 1) * mTranslate[1] +
311  mInvHMatrix(2, 2) * mTranslate[2]
312  );
313 
314  // The last row of mHMatrix is always (0,0,0,1) for an affine
315  // transformation, so it is set once in the constructor. It is
316  // not necessary to reset it here.
317 #else
318  mInvHMatrix(3, 0) = -(
319  mInvHMatrix(0, 0) * mTranslate[0] +
320  mInvHMatrix(1, 0) * mTranslate[1] +
321  mInvHMatrix(2, 0) * mTranslate[2]
322  );
323 
324  mInvHMatrix(3, 1) = -(
325  mInvHMatrix(0, 1) * mTranslate[0] +
326  mInvHMatrix(1, 1) * mTranslate[1] +
327  mInvHMatrix(2, 1) * mTranslate[2]
328  );
329 
330  mInvHMatrix(3, 2) = -(
331  mInvHMatrix(0, 2) * mTranslate[0] +
332  mInvHMatrix(1, 2) * mTranslate[1] +
333  mInvHMatrix(2, 2) * mTranslate[2]
334  );
335 
336  // The last column of mHMatrix is always (0,0,0,1) for an affine
337  // transformation, so it is set once in the constructor. It is
338  // not necessary to reset it here.
339 #endif
340  }
341 
342  mInverseNeedsUpdate = false;
343  }
344 
345  return mInvHMatrix;
346 }
347 
349 {
350  Transform inverse;
351 
352  if (mIsIdentity)
353  {
354  inverse.MakeIdentity();
355  }
356  else
357  {
359  {
360  inverse.SetRotation(Transpose(GetRotation()));
361  inverse.SetUniformScale(1.0f / GetUniformScale());
362  }
363  else
364  {
365  Matrix4x4<float> invUpper;
366  Invert3x3(GetMatrix(), invUpper);
367  inverse.SetMatrix(invUpper);
368  }
370  inverse.SetTranslation(inverse.GetMatrix() * trn);
371  }
372 
373  mInverseNeedsUpdate = true;
374  return inverse;
375 }
376 
378 {
379  if (mIsIdentity)
380  {
381  mHMatrix.MakeIdentity();
382  }
383  else
384  {
385  if (mIsRSMatrix)
386  {
387 #if defined(GTE_USE_MAT_VEC)
388  mHMatrix(0, 0) = mMatrix(0, 0) * mScale[0];
389  mHMatrix(0, 1) = mMatrix(0, 1) * mScale[1];
390  mHMatrix(0, 2) = mMatrix(0, 2) * mScale[2];
391  mHMatrix(1, 0) = mMatrix(1, 0) * mScale[0];
392  mHMatrix(1, 1) = mMatrix(1, 1) * mScale[1];
393  mHMatrix(1, 2) = mMatrix(1, 2) * mScale[2];
394  mHMatrix(2, 0) = mMatrix(2, 0) * mScale[0];
395  mHMatrix(2, 1) = mMatrix(2, 1) * mScale[1];
396  mHMatrix(2, 2) = mMatrix(2, 2) * mScale[2];
397 #else
398  mHMatrix(0, 0) = mScale[0] * mMatrix(0, 0);
399  mHMatrix(0, 1) = mScale[0] * mMatrix(0, 1);
400  mHMatrix(0, 2) = mScale[0] * mMatrix(0, 2);
401  mHMatrix(1, 0) = mScale[1] * mMatrix(1, 0);
402  mHMatrix(1, 1) = mScale[1] * mMatrix(1, 1);
403  mHMatrix(1, 2) = mScale[1] * mMatrix(1, 2);
404  mHMatrix(2, 0) = mScale[2] * mMatrix(2, 0);
405  mHMatrix(2, 1) = mScale[2] * mMatrix(2, 1);
406  mHMatrix(2, 2) = mScale[2] * mMatrix(2, 2);
407 #endif
408  }
409  else
410  {
411  mHMatrix(0, 0) = mMatrix(0, 0);
412  mHMatrix(0, 1) = mMatrix(0, 1);
413  mHMatrix(0, 2) = mMatrix(0, 2);
414  mHMatrix(1, 0) = mMatrix(1, 0);
415  mHMatrix(1, 1) = mMatrix(1, 1);
416  mHMatrix(1, 2) = mMatrix(1, 2);
417  mHMatrix(2, 0) = mMatrix(2, 0);
418  mHMatrix(2, 1) = mMatrix(2, 1);
419  mHMatrix(2, 2) = mMatrix(2, 2);
420  }
421 
422 #if defined(GTE_USE_MAT_VEC)
423  mHMatrix(0, 3) = mTranslate[0];
424  mHMatrix(1, 3) = mTranslate[1];
425  mHMatrix(2, 3) = mTranslate[2];
426 
427  // The last row of mHMatrix is always (0,0,0,1) for an affine
428  // transformation, so it is set once in the constructor. It is not
429  // necessary to reset it here.
430 #else
431  mHMatrix(3, 0) = mTranslate[0];
432  mHMatrix(3, 1) = mTranslate[1];
433  mHMatrix(3, 2) = mTranslate[2];
434 
435  // The last column of mHMatrix is always (0,0,0,1) for an affine
436  // transformation, so it is set once in the constructor. It is not
437  // necessary to reset it here.
438 #endif
439  }
440 
441  mInverseNeedsUpdate = true;
442 }
443 
445  Matrix4x4<float>& invMat)
446 {
447  // Compute the adjoint of M (3x3).
448  invMat(0, 0) = mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1);
449  invMat(0, 1) = mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2);
450  invMat(0, 2) = mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1);
451  invMat(0, 3) = 0.0f;
452  invMat(1, 0) = mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2);
453  invMat(1, 1) = mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0);
454  invMat(1, 2) = mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2);
455  invMat(1, 3) = 0.0f;
456  invMat(2, 0) = mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0);
457  invMat(2, 1) = mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1);
458  invMat(2, 2) = mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0);
459  invMat(2, 3) = 0.0f;
460  invMat(3, 0) = 0.0f;
461  invMat(3, 1) = 0.0f;
462  invMat(3, 2) = 0.0f;
463  invMat(3, 3) = 1.0f;
464 
465  // Compute the reciprocal of the determinant of M.
466  float invDet = 1.0f / (
467  mat(0, 0) * invMat(0, 0) +
468  mat(0, 1) * invMat(1, 0) +
469  mat(0, 2) * invMat(2, 0)
470  );
471 
472  // inverse(M) = adjoint(M)/determinant(M).
473  invMat(0, 0) *= invDet;
474  invMat(0, 1) *= invDet;
475  invMat(0, 2) *= invDet;
476  invMat(1, 0) *= invDet;
477  invMat(1, 1) *= invDet;
478  invMat(1, 2) *= invDet;
479  invMat(2, 0) *= invDet;
480  invMat(2, 1) *= invDet;
481  invMat(2, 2) *= invDet;
482 }
483 
484 namespace gte
485 {
486 
488 {
489  return M.GetHMatrix() * V;
490 }
491 
493 {
494  return V * M.GetHMatrix();
495 }
496 
498 {
499  if (A.IsIdentity())
500  {
501  return B;
502  }
503 
504  if (B.IsIdentity())
505  {
506  return A;
507  }
508 
509  Transform product;
510 
511  if (A.IsRSMatrix() && B.IsRSMatrix())
512  {
513 #if defined(GTE_USE_MAT_VEC)
514  if (A.IsUniformScale())
515  {
516  product.SetRotation(A.GetRotation() * B.GetRotation());
517 
518  product.SetTranslation(A.GetUniformScale()*(
519  A.GetRotation() * B.GetTranslationW0()) +
520  A.GetTranslationW1());
521 
522  if (B.IsUniformScale())
523  {
524  product.SetUniformScale(
525  A.GetUniformScale() * B.GetUniformScale());
526  }
527  else
528  {
529  product.SetScale(A.GetUniformScale() * B.GetScale());
530  }
531 
532  return product;
533  }
534 #else
535  if (B.IsUniformScale())
536  {
537  product.SetRotation(A.GetRotation() * B.GetRotation());
538 
539  product.SetTranslation(B.GetUniformScale()*(
541 
542  if (A.IsUniformScale())
543  {
544  product.SetUniformScale(
545  A.GetUniformScale() * B.GetUniformScale());
546  }
547  else
548  {
549  product.SetScale(A.GetScale() * B.GetUniformScale());
550  }
551 
552  return product;
553  }
554 #endif
555  }
556 
557  // In all remaining cases, the matrix cannot be written as R*S*X+T.
558  Matrix4x4<float> matMA;
559  if (A.IsRSMatrix())
560  {
561 #if defined(GTE_USE_MAT_VEC)
562  matMA = MultiplyMD(A.GetRotation(), A.GetScaleW1());
563 #else
564  matMA = MultiplyDM(A.GetScaleW1(), A.GetRotation());
565 #endif
566  }
567  else
568  {
569  matMA = A.GetMatrix();
570  }
571 
572  Matrix4x4<float> matMB;
573  if (B.IsRSMatrix())
574  {
575 #if defined(GTE_USE_MAT_VEC)
576  matMB = MultiplyMD(B.GetRotation(), B.GetScaleW1());
577 #else
578  matMB = MultiplyDM(B.GetScaleW1(), B.GetRotation());
579 #endif
580  }
581  else
582  {
583  matMB = B.GetMatrix();
584  }
585 
586  product.SetMatrix(matMA * matMB);
587 #if defined(GTE_USE_MAT_VEC)
588  product.SetTranslation(matMA * B.GetTranslationW0() +
589  A.GetTranslationW1());
590 #else
591  product.SetTranslation(A.GetTranslationW0() * matMB +
592  B.GetTranslationW1());
593 #endif
594  return product;
595 }
596 
597 }
bool IsIdentity() const
Definition: GteTransform.h:202
bool mInverseNeedsUpdate
Definition: GteTransform.h:178
float GetUniformScale() const
Definition: GteTransform.h:255
float GetNorm() const
void SetUniformScale(float scale)
Matrix4x4< float > mHMatrix
Definition: GteTransform.h:171
static void Invert3x3(Matrix4x4< float > const &mat, Matrix4x4< float > &invMat)
GLuint GLenum matrix
Definition: glext.h:10574
Matrix4x4< float > mInvHMatrix
Definition: GteTransform.h:172
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9914
#define LogAssert(condition, message)
Definition: GteLogger.h:86
Matrix4x4< float > const & GetHMatrix() const
Definition: GteTransform.h:262
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s0
Definition: glext.h:9013
Matrix4x4< float > mMatrix
Definition: GteTransform.h:174
GMatrix< Real > MultiplyMD(GMatrix< Real > const &M, GVector< Real > const &D)
Definition: GteGMatrix.h:781
bool IsRSMatrix() const
Definition: GteTransform.h:207
Transform Inverse() const
void SetScale(float s0, float s1, float s2)
GMatrix< Real > Transpose(GMatrix< Real > const &M)
Definition: GteGMatrix.h:637
const GLubyte * c
Definition: glext.h:11671
Vector4< float > GetScaleW1() const
Definition: GteTransform.h:249
bool IsUniformScale() const
Definition: GteTransform.h:212
GLuint GLfloat x0
Definition: glext.h:9013
Matrix4x4< float > const & GetRotation() const
Definition: GteTransform.h:217
Vector3< float > GetScale() const
Definition: GteTransform.h:243
Matrix4x4< float > const & GetMatrix() const
Definition: GteTransform.h:223
void MakeUnitScale()
GLuint GLfloat GLfloat GLfloat x1
Definition: glext.h:9013
GLboolean r
Definition: glcorearb.h:1217
void SetMatrix(Matrix4x4< float > const &matrix)
GLfixed GLfixed x2
Definition: glext.h:4952
GLfloat f
Definition: glcorearb.h:1921
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:255
Vector4< float > mTranslate
Definition: GteTransform.h:175
void SetRotation(Matrix4x4< float > const &rotate)
static Transform const IDENTITY
Definition: GteTransform.h:157
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition: glext.h:9013
Vector4< float > GetTranslationW0() const
Definition: GteTransform.h:233
Vector4< float > GetTranslationW1() const
Definition: GteTransform.h:238
void SetTranslation(float x0, float x1, float x2)
Vector4< float > operator*(Transform const &M, Vector4< float > const &V)
Matrix4x4< float > const & GetHInverse() const
Vector4< float > mScale
Definition: GteTransform.h:176
GMatrix< Real > MultiplyDM(GVector< Real > const &D, GMatrix< Real > const &M)
Definition: GteGMatrix.h:798


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01