Subversion Repositories gelsvn

Rev

Rev 112 | Rev 324 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
}