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

Revision 176, 13.1 KB checked in by bittner, 19 years ago (diff)

cosine sampling bug fixed

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