source: GTP/trunk/App/Demos/Vis/CHC_revisited/Matrix4x4.cpp @ 2746

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