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

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

Merged sources with ViewCellBsp?

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