Subversion Repositories gelsvn

Rev

Rev 327 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
595 jab 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
 
2 bj 7
#include "ArithSqMat4x4Float.h"
8
#include "Mat4x4f.h"
113 jab 9
#include "Mat4x4d.h"
2 bj 10
 
324 jab 11
namespace CGLA {
12
 
2 bj 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
	{
327 jab 36
		//   The following com[3]e has been copied from a gem in Graphics Gems II by
2 bj 37
		//   Kevin Wu.                      
595 jab 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"
2 bj 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]) && 
5 jab 54
					is_tiny(this_mat[3][3]-1.0)))
2 bj 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
	{
5 jab 144
		double a1, a2, a3, a4, b1, b2, b3, b4;
145
		double c1, c2, c3, c4, d1, d2, d3, d4;
2 bj 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
	{
5 jab 193
		double det = determinant( in );
2 bj 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
 
112 jab 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>&);
2 bj 211
 
112 jab 212
 
2 bj 213
}