source: trunk/VUT/GtpVisibilityPreprocessor/src/Matrix4x4.cpp @ 209

Revision 209, 13.9 KB checked in by bittner, 19 years ago (diff)

data added

Line 
1#include "Matrix4x4.h"
2#include "Vector3.h"
3
4// standard headers
5#include <iomanip>
6using namespace std;
7
8
9Matrix4x4::Matrix4x4(const Vector3 &a, const Vector3 &b, const Vector3 &c)
10{
11  // first index is column [x], the second is row [y]
12  x[0][0] = a.x;
13  x[1][0] = a.y;
14  x[2][0] = a.z;
15  x[3][0] = 0.0f;
16
17  x[0][1] = b.x;
18  x[1][1] = b.y;
19  x[2][1] = b.z;
20  x[3][1] = 0.0f;
21
22  x[0][2] = c.x;
23  x[1][2] = c.y;
24  x[2][2] = c.z;
25  x[3][2] = 0.0f;
26
27  x[0][3] = 0.0f;
28  x[1][3] = 0.0f;
29  x[2][3] = 0.0f;
30  x[3][3] = 1.0f;
31}
32
33void
34Matrix4x4::SetColumns(const Vector3 &a, const Vector3 &b, const Vector3 &c)
35{
36  // first index is column [x], the second is row [y]
37  x[0][0] = a.x;
38  x[1][0] = b.x;
39  x[2][0] = c.x;
40  x[3][0] = 0.0f;
41
42  x[0][1] = a.y;
43  x[1][1] = b.y;
44  x[2][1] = c.y;
45  x[3][1] = 0.0f;
46
47  x[0][2] = a.z;
48  x[1][2] = b.z;
49  x[2][2] = c.z;
50  x[3][2] = 0.0f;
51
52  x[0][3] = 0.0f;
53  x[1][3] = 0.0f;
54  x[2][3] = 0.0f;
55  x[3][3] = 1.0f;
56}
57
58// full constructor
59Matrix4x4::Matrix4x4(float x11, float x12, float x13, float x14,
60                     float x21, float x22, float x23, float x24,
61                     float x31, float x32, float x33, float x34,
62                     float x41, float x42, float x43, float x44)
63{
64  // first index is column [x], the second is row [y]
65  x[0][0] = x11;
66  x[1][0] = x12;
67  x[2][0] = x13;
68  x[3][0] = x14;
69
70  x[0][1] = x21;
71  x[1][1] = x22;
72  x[2][1] = x23;
73  x[3][1] = x24;
74
75  x[0][2] = x31;
76  x[1][2] = x32;
77  x[2][2] = x33;
78  x[3][2] = x34;
79
80  x[0][3] = x41;
81  x[1][3] = x42;
82  x[2][3] = x43;
83  x[3][3] = x44;
84}
85
86// inverse matrix computation gauss_jacobiho method .. from N.R. in C
87// if matrix is regular = computatation successfull = returns 0
88// in case of singular matrix returns 1
89int
90Matrix4x4::Invert()
91{
92  int indxc[4],indxr[4],ipiv[4];
93  int i,icol,irow,j,k,l,ll,n;
94  float big,dum,pivinv,temp;
95  // satisfy the compiler
96  icol = irow = 0;
97
98  // the size of the matrix
99  n = 4;
100
101  for ( j = 0 ; j < n ; j++) /* zero pivots */
102    ipiv[j] = 0;
103
104  for ( i = 0; i < n; i++)
105  {
106    big = 0.0;
107    for (j = 0 ; j < n ; j++)
108      if (ipiv[j] != 1)
109        for ( k = 0 ; k<n ; k++)
110        {
111          if (ipiv[k] == 0)
112          {
113            if (fabs(x[k][j]) >= big)
114            {
115              big = fabs(x[k][j]);
116              irow = j;
117              icol = k;
118            }
119          }
120          else
121            if (ipiv[k] > 1)
122              return 1; /* singular matrix */
123        }
124    ++(ipiv[icol]);
125    if (irow != icol)
126    {
127      for ( l = 0 ; l<n ; l++)
128      {
129        temp = x[l][icol];
130        x[l][icol] = x[l][irow];
131        x[l][irow] = temp;
132      }
133    }
134    indxr[i] = irow;
135    indxc[i] = icol;
136    if (x[icol][icol] == 0.0)
137      return 1; /* singular matrix */
138
139    pivinv = 1.0 / x[icol][icol];
140    x[icol][icol] = 1.0 ;
141    for ( l = 0 ; l<n ; l++)
142      x[l][icol] = x[l][icol] * pivinv ;
143   
144    for (ll = 0 ; ll < n ; ll++)
145      if (ll != icol)
146      {
147        dum = x[icol][ll];
148        x[icol][ll] = 0.0;
149        for ( l = 0 ; l<n ; l++)
150          x[l][ll] = x[l][ll] - x[l][icol] * dum ;
151      }
152  }
153  for ( l = n; l--; )
154  {
155    if (indxr[l] != indxc[l])
156      for ( k = 0; k<n ; k++)
157      {
158        temp = x[indxr[l]][k];
159        x[indxr[l]][k] = x[indxc[l]][k];
160        x[indxc[l]][k] = temp;
161      }
162  }
163
164  return 0 ; // matrix is regular .. inversion has been succesfull
165}
166
167// Invert the given matrix using the above inversion routine.
168Matrix4x4
169Invert(const Matrix4x4& M)
170{
171  Matrix4x4 InvertMe = M;
172  InvertMe.Invert();
173  return InvertMe;
174}
175
176
177// Transpose the matrix.
178void
179Matrix4x4::Transpose()
180{
181  for (int i = 0; i < 4; i++)
182    for (int j = i; j < 4; j++)
183      if (i != j) {
184        float temp = x[i][j];
185        x[i][j] = x[j][i];
186        x[j][i] = temp;
187      }
188}
189
190// Transpose the given matrix using the transpose routine above.
191Matrix4x4
192Transpose(const Matrix4x4& M)
193{
194  Matrix4x4 TransposeMe = M;
195  TransposeMe.Transpose();
196  return TransposeMe;
197}
198
199// Construct an identity matrix.
200Matrix4x4
201IdentityMatrix()
202{
203  Matrix4x4 M;
204
205  for (int i = 0; i < 4; i++)
206    for (int j = 0; j < 4; j++)
207      M.x[i][j] = (i == j) ? 1.0 : 0.0;
208  return M;
209}
210
211// Construct a zero matrix.
212Matrix4x4
213ZeroMatrix()
214{
215  Matrix4x4 M;
216  for (int i = 0; i < 4; i++)
217    for (int j = 0; j < 4; j++)
218      M.x[i][j] = 0;
219  return M;
220}
221
222// Construct a translation matrix given the location to translate to.
223Matrix4x4
224TranslationMatrix(const Vector3& Location)
225{
226  Matrix4x4 M = IdentityMatrix();
227  M.x[3][0] = Location.x;
228  M.x[3][1] = Location.y;
229  M.x[3][2] = Location.z;
230  return M;
231}
232
233// Construct a rotation matrix.  Rotates Angle radians about the
234// X axis.
235Matrix4x4
236RotationXMatrix(float Angle)
237{
238  Matrix4x4 M = IdentityMatrix();
239  float Cosine = cos(Angle);
240  float Sine = sin(Angle);
241  M.x[1][1] = Cosine;
242  M.x[2][1] = -Sine;
243  M.x[1][2] = Sine;
244  M.x[2][2] = Cosine;
245  return M;
246}
247
248// Construct a rotation matrix.  Rotates Angle radians about the
249// Y axis.
250Matrix4x4
251RotationYMatrix(float Angle)
252{
253  Matrix4x4 M = IdentityMatrix();
254  float Cosine = cos(Angle);
255  float Sine = sin(Angle);
256  M.x[0][0] = Cosine;
257  M.x[2][0] = -Sine;
258  M.x[0][2] = Sine;
259  M.x[2][2] = Cosine;
260  return M;
261}
262
263// Construct a rotation matrix.  Rotates Angle radians about the
264// Z axis.
265Matrix4x4
266RotationZMatrix(float Angle)
267{
268  Matrix4x4 M = IdentityMatrix();
269  float Cosine = cos(Angle);
270  float Sine = sin(Angle);
271  M.x[0][0] = Cosine;
272  M.x[1][0] = -Sine;
273  M.x[0][1] = Sine;
274  M.x[1][1] = Cosine;
275  return M;
276}
277
278// Construct a yaw-pitch-roll rotation matrix.  Rotate Yaw
279// radians about the XY axis, rotate Pitch radians in the
280// plane defined by the Yaw rotation, and rotate Roll radians
281// about the axis defined by the previous two angles.
282Matrix4x4
283RotationYPRMatrix(float Yaw, float Pitch, float Roll)
284{
285  Matrix4x4 M;
286  float ch = cos(Yaw);
287  float sh = sin(Yaw);
288  float cp = cos(Pitch);
289  float sp = sin(Pitch);
290  float cr = cos(Roll);
291  float sr = sin(Roll);
292
293  M.x[0][0] = ch * cr + sh * sp * sr;
294  M.x[1][0] = -ch * sr + sh * sp * cr;
295  M.x[2][0] = sh * cp;
296  M.x[0][1] = sr * cp;
297  M.x[1][1] = cr * cp;
298  M.x[2][1] = -sp;
299  M.x[0][2] = -sh * cr - ch * sp * sr;
300  M.x[1][2] = sr * sh + ch * sp * cr;
301  M.x[2][2] = ch * cp;
302  for (int i = 0; i < 4; i++)
303    M.x[3][i] = M.x[i][3] = 0;
304  M.x[3][3] = 1;
305
306  return M;
307}
308
309// Construct a rotation of a given angle about a given axis.
310// Derived from Eric Haines's SPD (Standard Procedural
311// Database).
312Matrix4x4
313RotationAxisMatrix(const Vector3& axis, float angle)
314{
315  Matrix4x4 M;
316  double cosine = cos(angle);
317  double sine = sin(angle);
318  double one_minus_cosine = 1 - cosine;
319
320  M.x[0][0] = axis.x * axis.x + (1.0 - axis.x * axis.x) * cosine;
321  M.x[0][1] = axis.x * axis.y * one_minus_cosine + axis.z * sine;
322  M.x[0][2] = axis.x * axis.z * one_minus_cosine - axis.y * sine;
323  M.x[0][3] = 0;
324
325  M.x[1][0] = axis.x * axis.y * one_minus_cosine - axis.z * sine;
326  M.x[1][1] = axis.y * axis.y + (1.0 - axis.y * axis.y) * cosine;
327  M.x[1][2] = axis.y * axis.z * one_minus_cosine + axis.x * sine;
328  M.x[1][3] = 0;
329
330  M.x[2][0] = axis.x * axis.z * one_minus_cosine + axis.y * sine;
331  M.x[2][1] = axis.y * axis.z * one_minus_cosine - axis.x * sine;
332  M.x[2][2] = axis.z * axis.z + (1.0 - axis.z * axis.z) * cosine;
333  M.x[2][3] = 0;
334
335  M.x[3][0] = 0;
336  M.x[3][1] = 0;
337  M.x[3][2] = 0;
338  M.x[3][3] = 1;
339
340  return M;
341}
342
343
344// Constructs the rotation matrix that rotates 'vec1' to 'vec2'
345Matrix4x4
346RotationVectorsMatrix(const Vector3 &vecStart,
347                      const Vector3 &vecTo)
348{
349  Vector3 vec = CrossProd(vecStart, vecTo);
350 
351  if (Magnitude(vec) > Limits::Small) {
352    // vector exist, compute angle
353    float angle = acos(DotProd(vecStart, vecTo));
354    // normalize for sure
355    vec.Normalize();
356    return RotationAxisMatrix(vec, angle);
357  }
358
359  // opposite or colinear vectors
360  Matrix4x4 ret = IdentityMatrix();
361  if (DotProd(vecStart, vecTo) < 0.0)
362    ret *= -1.0; // opposite vectors
363
364  return ret;
365}
366
367
368// Construct a scale matrix given the X, Y, and Z parameters
369// to scale by.  To scale uniformly, let X==Y==Z.
370Matrix4x4
371ScaleMatrix(float X, float Y, float Z)
372{
373  Matrix4x4 M = IdentityMatrix();
374
375  M.x[0][0] = X;
376  M.x[1][1] = Y;
377  M.x[2][2] = Z;
378
379  return M;
380}
381
382// Construct a rotation matrix that makes the x, y, z axes
383// correspond to the vectors given.
384Matrix4x4
385GenRotation(const Vector3 &x, const Vector3 &y, const Vector3 &z)
386{
387  Matrix4x4 M = IdentityMatrix();
388
389#if 1
390  //  x  y
391  M.x[0][0] = x.x;
392  M.x[1][0] = x.y;
393  M.x[2][0] = x.z;
394
395  M.x[0][1] = y.x;
396  M.x[1][1] = y.y;
397  M.x[2][1] = y.z;
398
399  M.x[0][2] = z.x;
400  M.x[1][2] = z.y;
401  M.x[2][2] = z.z;
402#else
403  //  x  y -- old version
404  M.x[0][0] = x.x;
405  M.x[0][1] = x.y;
406  M.x[0][2] = x.z;
407
408  M.x[1][0] = y.x;
409  M.x[1][1] = y.y;
410  M.x[1][2] = y.z;
411
412  M.x[2][0] = z.x;
413  M.x[2][1] = z.y;
414  M.x[2][2] = z.z;
415#endif
416
417  return M;
418}
419
420// Construct a quadric matrix.  After Foley et al. pp. 528-529.
421Matrix4x4
422QuadricMatrix(float a, float b, float c, float d, float e,
423              float f, float g, float h, float j, float k)
424{
425  Matrix4x4 M;
426
427  M.x[0][0] = a;  M.x[0][1] = d;  M.x[0][2] = f;  M.x[0][3] = g;
428  M.x[1][0] = d;  M.x[1][1] = b;  M.x[1][2] = e;  M.x[1][3] = h;
429  M.x[2][0] = f;  M.x[2][1] = e;  M.x[2][2] = c;  M.x[2][3] = j;
430  M.x[3][0] = g;  M.x[3][1] = h;  M.x[3][2] = j;  M.x[3][3] = k;
431
432  return M;
433}
434
435// Construct various "mirror" matrices, which flip coordinate
436// signs in the various axes specified.
437Matrix4x4
438MirrorX()
439{
440  Matrix4x4 M = IdentityMatrix();
441  M.x[0][0] = -1;
442  return M;
443}
444
445Matrix4x4
446MirrorY()
447{
448  Matrix4x4 M = IdentityMatrix();
449  M.x[1][1] = -1;
450  return M;
451}
452
453Matrix4x4
454MirrorZ()
455{
456  Matrix4x4 M = IdentityMatrix();
457  M.x[2][2] = -1;
458  return M;
459}
460
461Matrix4x4
462RotationOnly(const Matrix4x4& x)
463{
464  Matrix4x4 M = x;
465  M.x[3][0] = M.x[3][1] = M.x[3][2] = 0;
466  return M;
467}
468
469// Add corresponding elements of the two matrices.
470Matrix4x4&
471Matrix4x4::operator+= (const Matrix4x4& A)
472{
473  for (int i = 0; i < 4; i++)
474    for (int j = 0; j < 4; j++)
475      x[i][j] += A.x[i][j];
476  return *this;
477}
478
479// Subtract corresponding elements of the matrices.
480Matrix4x4&
481Matrix4x4::operator-= (const Matrix4x4& A)
482{
483  for (int i = 0; i < 4; i++)
484    for (int j = 0; j < 4; j++)
485      x[i][j] -= A.x[i][j];
486  return *this;
487}
488
489// Scale each element of the matrix by A.
490Matrix4x4&
491Matrix4x4::operator*= (float A)
492{
493  for (int i = 0; i < 4; i++)
494    for (int j = 0; j < 4; j++)
495      x[i][j] *= A;
496  return *this;
497}
498
499// Multiply two matrices.
500Matrix4x4&
501Matrix4x4::operator*= (const Matrix4x4& A)
502{
503  Matrix4x4 ret = *this;
504
505  for (int i = 0; i < 4; i++)
506    for (int j = 0; j < 4; j++) {
507      float subt = 0;
508      for (int k = 0; k < 4; k++)
509        subt += ret.x[i][k] * A.x[k][j];
510      x[i][j] = subt;
511    }
512  return *this;
513}
514
515// Add corresponding elements of the matrices.
516Matrix4x4
517operator+ (const Matrix4x4& A, const Matrix4x4& B)
518{
519  Matrix4x4 ret;
520
521  for (int i = 0; i < 4; i++)
522    for (int j = 0; j < 4; j++)
523      ret.x[i][j] = A.x[i][j] + B.x[i][j];
524  return ret;
525}
526
527// Subtract corresponding elements of the matrices.
528Matrix4x4
529operator- (const Matrix4x4& A, const Matrix4x4& B)
530{
531  Matrix4x4 ret;
532
533  for (int i = 0; i < 4; i++)
534    for (int j = 0; j < 4; j++)
535      ret.x[i][j] = A.x[i][j] - B.x[i][j];
536  return ret;
537}
538
539// Multiply matrices.
540Matrix4x4
541operator* (const Matrix4x4& A, const Matrix4x4& B)
542{
543  Matrix4x4 ret;
544
545  for (int i = 0; i < 4; i++)
546    for (int j = 0; j < 4; j++) {
547      float subt = 0;
548      for (int k = 0; k < 4; k++)
549        subt += A.x[i][k] * B.x[k][j];
550      ret.x[i][j] = subt;
551    }
552  return ret;
553}
554
555// Transform a vector by a matrix.
556Vector3
557operator* (const Matrix4x4& M, const Vector3& v)
558{
559  Vector3 ret;
560  float denom;
561
562  ret.x = v.x * M.x[0][0] + v.y * M.x[1][0] + v.z * M.x[2][0] + M.x[3][0];
563  ret.y = v.x * M.x[0][1] + v.y * M.x[1][1] + v.z * M.x[2][1] + M.x[3][1];
564  ret.z = v.x * M.x[0][2] + v.y * M.x[1][2] + v.z * M.x[2][2] + M.x[3][2];
565  denom = M.x[0][3] + M.x[1][3] + M.x[2][3] + M.x[3][3];
566  if (denom != 1.0)
567    ret /= denom;
568  return ret;
569}
570
571// Apply the rotation portion of a matrix to a vector.
572Vector3
573RotateOnly(const Matrix4x4& M, const Vector3& v)
574{
575  Vector3 ret;
576  float denom;
577
578  ret.x = v.x * M.x[0][0] + v.y * M.x[1][0] + v.z * M.x[2][0];
579  ret.y = v.x * M.x[0][1] + v.y * M.x[1][1] + v.z * M.x[2][1];
580  ret.z = v.x * M.x[0][2] + v.y * M.x[1][2] + v.z * M.x[2][2];
581  denom = M.x[0][3] + M.x[1][3] + M.x[2][3] + M.x[3][3];
582  if (denom != 1.0)
583    ret /= denom;
584  return ret;
585}
586
587// Scale each element of the matrix by B.
588Matrix4x4
589operator* (const Matrix4x4& A, float B)
590{
591  Matrix4x4 ret;
592
593  for (int i = 0; i < 4; i++)
594    for (int j = 0; j < 4; j++)
595      ret.x[i][j] = A.x[i][j] * B;
596  return ret;
597}
598
599// Overloaded << for C++-style output.
600ostream&
601operator<< (ostream& s, const Matrix4x4& M)
602{
603  for (int i = 0; i < 4; i++) { // y
604    for (int j = 0; j < 4; j++) { // x
605                                          //  x  y
606      s << setprecision(4) << setw(10) << M.x[j][i];
607    }
608    s << '\n';
609  }
610  return s;
611}
612
613// Rotate a direction vector...
614Vector3
615PlaneRotate(const Matrix4x4& tform, const Vector3& p)
616{
617  // I sure hope that matrix is invertible...
618  Matrix4x4 use = Transpose(Invert(tform));
619
620  return RotateOnly(use, p);
621}
622
623// Transform a normal
624Vector3
625TransformNormal(const Matrix4x4& tform, const Vector3& n)
626{
627  Matrix4x4 use = NormalTransformMatrix(tform);
628
629  return RotateOnly(use, n);
630}
631 
632Matrix4x4
633NormalTransformMatrix(const Matrix4x4 &tform)
634{
635  Matrix4x4 m = tform;
636  // for normal translation vector must be zero!
637  m.x[3][0] = m.x[3][1] = m.x[3][2] = 0.0;
638  // I sure hope that matrix is invertible...
639  return Transpose(Invert(m));
640}
641
642Vector3
643GetTranslation(const Matrix4x4 &M)
644{
645  return Vector3(M.x[3][0], M.x[3][1], M.x[3][2]);
646}
Note: See TracBrowser for help on using the repository browser.