660 |
khor |
1 |
/* ----------------------------------------------------------------------- *
|
|
|
2 |
* This file is part of GEL, http://www.imm.dtu.dk/GEL
|
|
|
3 |
* Copyright (C) the authors and DTU Informatics
|
|
|
4 |
* For license and list of authors, see ../../doc/intro.pdf
|
|
|
5 |
* ----------------------------------------------------------------------- */
|
|
|
6 |
|
|
|
7 |
#include "ArithSqMat4x4Float.h"
|
|
|
8 |
#include "Mat4x4f.h"
|
|
|
9 |
#include "Mat4x4d.h"
|
|
|
10 |
|
|
|
11 |
namespace CGLA {
|
|
|
12 |
|
|
|
13 |
namespace
|
|
|
14 |
{
|
|
|
15 |
|
|
|
16 |
/* Aux func. computes 3x3 determinants. */
|
|
|
17 |
template<class T>
|
|
|
18 |
inline T d3x3f( T a0, T a1, T a2,
|
|
|
19 |
T b0, T b1, T b2,
|
|
|
20 |
T c0, T c1, T c2 )
|
|
|
21 |
{
|
|
|
22 |
return a0*b1*c2 +
|
|
|
23 |
a1*b2*c0 +
|
|
|
24 |
a2*b0*c1 -
|
|
|
25 |
a2*b1*c0 -
|
|
|
26 |
a0*b2*c1 -
|
|
|
27 |
a1*b0*c2 ;
|
|
|
28 |
}
|
|
|
29 |
}
|
|
|
30 |
|
|
|
31 |
|
|
|
32 |
|
|
|
33 |
template<class V, class M>
|
|
|
34 |
M invert_affine(const ArithSqMat4x4Float<V,M>& this_mat)
|
|
|
35 |
{
|
|
|
36 |
// The following com[3]e has been copied from a gem in Graphics Gems II by
|
|
|
37 |
// Kevin Wu.
|
|
|
38 |
// From the EULA: "Using the code is permitted in any program, product, or
|
|
|
39 |
// library, non-commercial or commercial. Giving credit is not required, though is a nice gesture"
|
|
|
40 |
// The function is very fast, but it can only invert affine matrices. An
|
|
|
41 |
// exception NotAffine is thrown if the matrix is not affine, and another
|
|
|
42 |
// exception Singular is thrown if the matrix is singular.
|
|
|
43 |
|
|
|
44 |
typedef typename M::ScalarType ScalarType;
|
|
|
45 |
|
|
|
46 |
M new_mat;
|
|
|
47 |
ScalarType det_1;
|
|
|
48 |
ScalarType pos, neg, temp;
|
|
|
49 |
|
|
|
50 |
|
|
|
51 |
if (!(is_tiny(this_mat[3][0]) &&
|
|
|
52 |
is_tiny(this_mat[3][1]) &&
|
|
|
53 |
is_tiny(this_mat[3][2]) &&
|
|
|
54 |
is_tiny(this_mat[3][3]-1.0)))
|
|
|
55 |
throw(Mat4x4fNotAffine("Can only invert affine matrices"));
|
|
|
56 |
|
|
|
57 |
#define ACCUMULATE if (temp >= 0.0) pos += temp; else neg += temp
|
|
|
58 |
|
|
|
59 |
/*
|
|
|
60 |
* Calculate the determinant of submatrix A and determine if the
|
|
|
61 |
* the matrix is singular as limited by the float precision
|
|
|
62 |
* floating-point this_mat representation.
|
|
|
63 |
*/
|
|
|
64 |
|
|
|
65 |
pos = neg = 0.0;
|
|
|
66 |
temp = this_mat[0][0] * this_mat[1][1] * this_mat[2][2];
|
|
|
67 |
ACCUMULATE;
|
|
|
68 |
temp = this_mat[1][0] * this_mat[2][1] * this_mat[0][2];
|
|
|
69 |
ACCUMULATE;
|
|
|
70 |
temp = this_mat[2][0] * this_mat[0][1] * this_mat[1][2];
|
|
|
71 |
ACCUMULATE;
|
|
|
72 |
temp = -this_mat[2][0] * this_mat[1][1] * this_mat[0][2];
|
|
|
73 |
ACCUMULATE;
|
|
|
74 |
temp = -this_mat[1][0] * this_mat[0][1] * this_mat[2][2];
|
|
|
75 |
ACCUMULATE;
|
|
|
76 |
temp = -this_mat[0][0] * this_mat[2][1] * this_mat[1][2];
|
|
|
77 |
ACCUMULATE;
|
|
|
78 |
det_1 = pos + neg;
|
|
|
79 |
|
|
|
80 |
/* Is the submatrix A singular? */
|
|
|
81 |
if ((det_1 == 0.0) || (fabs(det_1 / (pos - neg)) < MINUTE))
|
|
|
82 |
{
|
|
|
83 |
/* Mat4x4f M has no inverse */
|
|
|
84 |
throw(Mat4x4fSingular("Tried to invert Singular matrix"));
|
|
|
85 |
}
|
|
|
86 |
|
|
|
87 |
else {
|
|
|
88 |
|
|
|
89 |
/* Calculate inverse(A) = adj(A) / det(A) */
|
|
|
90 |
det_1 = 1.0 / det_1;
|
|
|
91 |
new_mat[0][0] = ( this_mat[1][1] * this_mat[2][2] -
|
|
|
92 |
this_mat[2][1] * this_mat[1][2] )
|
|
|
93 |
* det_1;
|
|
|
94 |
new_mat[0][1] = - ( this_mat[0][1] * this_mat[2][2] -
|
|
|
95 |
this_mat[2][1] * this_mat[0][2] )
|
|
|
96 |
* det_1;
|
|
|
97 |
new_mat[0][2] = ( this_mat[0][1] * this_mat[1][2] -
|
|
|
98 |
this_mat[1][1] * this_mat[0][2] )
|
|
|
99 |
* det_1;
|
|
|
100 |
new_mat[1][0] = - ( this_mat[1][0] * this_mat[2][2] -
|
|
|
101 |
this_mat[2][0] * this_mat[1][2] )
|
|
|
102 |
* det_1;
|
|
|
103 |
new_mat[1][1] = ( this_mat[0][0] * this_mat[2][2] -
|
|
|
104 |
this_mat[2][0] * this_mat[0][2] )
|
|
|
105 |
* det_1;
|
|
|
106 |
new_mat[1][2] = - ( this_mat[0][0] * this_mat[1][2] -
|
|
|
107 |
this_mat[1][0] * this_mat[0][2] )
|
|
|
108 |
* det_1;
|
|
|
109 |
new_mat[2][0] = ( this_mat[1][0] * this_mat[2][1] -
|
|
|
110 |
this_mat[2][0] * this_mat[1][1] )
|
|
|
111 |
* det_1;
|
|
|
112 |
new_mat[2][1] = - ( this_mat[0][0] * this_mat[2][1] -
|
|
|
113 |
this_mat[2][0] * this_mat[0][1] )
|
|
|
114 |
* det_1;
|
|
|
115 |
new_mat[2][2] = ( this_mat[0][0] * this_mat[1][1] -
|
|
|
116 |
this_mat[1][0] * this_mat[0][1] )
|
|
|
117 |
* det_1;
|
|
|
118 |
|
|
|
119 |
/* Calculate -C * inverse(A) */
|
|
|
120 |
new_mat[0][3] = - ( this_mat[0][3] * new_mat[0][0] +
|
|
|
121 |
this_mat[1][3] * new_mat[0][1] +
|
|
|
122 |
this_mat[2][3] * new_mat[0][2] );
|
|
|
123 |
new_mat[1][3] = - ( this_mat[0][3] * new_mat[1][0] +
|
|
|
124 |
this_mat[1][3] * new_mat[1][1] +
|
|
|
125 |
this_mat[2][3] * new_mat[1][2] );
|
|
|
126 |
new_mat[2][3] = - ( this_mat[0][3] * new_mat[2][0] +
|
|
|
127 |
this_mat[1][3] * new_mat[2][1] +
|
|
|
128 |
this_mat[2][3] * new_mat[2][2] );
|
|
|
129 |
|
|
|
130 |
/* Fill in last column */
|
|
|
131 |
new_mat[3][0] = new_mat[3][1] = new_mat[3][2] = 0.0;
|
|
|
132 |
new_mat[3][3] = 1.0;
|
|
|
133 |
|
|
|
134 |
return new_mat;
|
|
|
135 |
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
#undef ACCUMULATE
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
template<class V, class M>
|
|
|
142 |
M adjoint(const ArithSqMat4x4Float<V,M>& in)
|
|
|
143 |
{
|
|
|
144 |
double a1, a2, a3, a4, b1, b2, b3, b4;
|
|
|
145 |
double c1, c2, c3, c4, d1, d2, d3, d4;
|
|
|
146 |
|
|
|
147 |
/* assign to individual variable names to aid */
|
|
|
148 |
/* selecting correct values */
|
|
|
149 |
|
|
|
150 |
a1 = in[0][0]; b1 = in[0][1];
|
|
|
151 |
c1 = in[0][2]; d1 = in[0][3];
|
|
|
152 |
|
|
|
153 |
a2 = in[1][0]; b2 = in[1][1];
|
|
|
154 |
c2 = in[1][2]; d2 = in[1][3];
|
|
|
155 |
|
|
|
156 |
a3 = in[2][0]; b3 = in[2][1];
|
|
|
157 |
c3 = in[2][2]; d3 = in[2][3];
|
|
|
158 |
|
|
|
159 |
a4 = in[3][0]; b4 = in[3][1];
|
|
|
160 |
c4 = in[3][2]; d4 = in[3][3];
|
|
|
161 |
|
|
|
162 |
|
|
|
163 |
/* row column labeling reversed since we transpose rows & columns */
|
|
|
164 |
|
|
|
165 |
M out;
|
|
|
166 |
out[0][0] = d3x3f( b2, b3, b4, c2, c3, c4, d2, d3, d4);
|
|
|
167 |
out[1][0] = - d3x3f( a2, a3, a4, c2, c3, c4, d2, d3, d4);
|
|
|
168 |
out[2][0] = d3x3f( a2, a3, a4, b2, b3, b4, d2, d3, d4);
|
|
|
169 |
out[3][0] = - d3x3f( a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
|
|
170 |
|
|
|
171 |
out[0][1] = - d3x3f( b1, b3, b4, c1, c3, c4, d1, d3, d4);
|
|
|
172 |
out[1][1] = d3x3f( a1, a3, a4, c1, c3, c4, d1, d3, d4);
|
|
|
173 |
out[2][1] = - d3x3f( a1, a3, a4, b1, b3, b4, d1, d3, d4);
|
|
|
174 |
out[3][1] = d3x3f( a1, a3, a4, b1, b3, b4, c1, c3, c4);
|
|
|
175 |
|
|
|
176 |
out[0][2] = d3x3f( b1, b2, b4, c1, c2, c4, d1, d2, d4);
|
|
|
177 |
out[1][2] = - d3x3f( a1, a2, a4, c1, c2, c4, d1, d2, d4);
|
|
|
178 |
out[2][2] = d3x3f( a1, a2, a4, b1, b2, b4, d1, d2, d4);
|
|
|
179 |
out[3][2] = - d3x3f( a1, a2, a4, b1, b2, b4, c1, c2, c4);
|
|
|
180 |
|
|
|
181 |
out[0][3] = - d3x3f( b1, b2, b3, c1, c2, c3, d1, d2, d3);
|
|
|
182 |
out[1][3] = d3x3f( a1, a2, a3, c1, c2, c3, d1, d2, d3);
|
|
|
183 |
out[2][3] = - d3x3f( a1, a2, a3, b1, b2, b3, d1, d2, d3);
|
|
|
184 |
out[3][3] = d3x3f( a1, a2, a3, b1, b2, b3, c1, c2, c3);
|
|
|
185 |
|
|
|
186 |
return out;
|
|
|
187 |
}
|
|
|
188 |
|
|
|
189 |
|
|
|
190 |
template<class V, class M>
|
|
|
191 |
M invert(const ArithSqMat4x4Float<V,M>& in)
|
|
|
192 |
{
|
|
|
193 |
double det = determinant( in );
|
|
|
194 |
if (is_tiny(det))
|
|
|
195 |
throw(Mat4x4fSingular("Tried to invert Singular matrix"));
|
|
|
196 |
M out = adjoint(in);
|
|
|
197 |
out/=det;
|
|
|
198 |
return out;
|
|
|
199 |
}
|
|
|
200 |
|
|
|
201 |
|
|
|
202 |
template class ArithSqMat4x4Float<Vec4f, Mat4x4f>;
|
|
|
203 |
template Mat4x4f adjoint(const ArithSqMat4x4Float<Vec4f,Mat4x4f>&);
|
|
|
204 |
template Mat4x4f invert(const ArithSqMat4x4Float<Vec4f,Mat4x4f>&);
|
|
|
205 |
template Mat4x4f invert_affine(const ArithSqMat4x4Float<Vec4f,Mat4x4f>&);
|
|
|
206 |
|
|
|
207 |
template class ArithSqMat4x4Float<Vec4d, Mat4x4d>;
|
|
|
208 |
template Mat4x4d adjoint(const ArithSqMat4x4Float<Vec4d,Mat4x4d>&);
|
|
|
209 |
template Mat4x4d invert(const ArithSqMat4x4Float<Vec4d,Mat4x4d>&);
|
|
|
210 |
template Mat4x4d invert_affine(const ArithSqMat4x4Float<Vec4d,Mat4x4d>&);
|
|
|
211 |
|
|
|
212 |
|
|
|
213 |
}
|