Subversion Repositories gelsvn

Rev

Rev 5 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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