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