1 // Copyright 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 3 of the License,
9 or (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * d3/et.h: Represent three-dimensional Euclidean transformations.
31 #define M_PI 3.14159265358979323846
35 * Structure to describe a three-dimensional euclidean transformation.
37 * We consider points to be transformed as homogeneous coordinate vectors
38 * multiplied on the right of the transformation matrix. The transformations
39 * are assumed to be small, so xyz Euler angles are used to specify rotation.
40 * The order of transformations is (starting with a point representation in the
41 * original coordinate system):
43 * i) translation of the point
44 * ii) x-rotation about the origin
45 * iii) y-rotation about the origin
46 * iv) z-rotation about the origin
48 * For more information on Euler angles, see:
50 * http://mathworld.wolfram.com/EulerAngles.html
52 * For more information on rotation matrices, see:
54 * http://mathworld.wolfram.com/RotationMatrix.html
56 * XXX: inconsistently with the 2D class, this class uses radians to represent
63 ale_pos translation
[3];
65 mutable ale_pos matrix
[4][4];
66 mutable ale_pos matrix_inverse
[4][4];
67 mutable int resultant_memo
;
68 mutable int resultant_inverse_memo
;
72 * Create an identity matrix
74 void mident(ale_pos m1
[4][4]) const {
75 for (int i
= 0; i
< 4; i
++)
76 for (int j
= 0; j
< 4; j
++)
77 m1
[i
][j
] = (i
== j
) ? 1 : 0;
81 * Create a rotation matrix
83 void mrot(ale_pos m1
[4][4], ale_pos angle
, int index
) const {
85 m1
[(index
+1)%3][(index
+1)%3] = cos(angle
);
86 m1
[(index
+2)%3][(index
+2)%3] = cos(angle
);
87 m1
[(index
+1)%3][(index
+2)%3] = sin(angle
);
88 m1
[(index
+2)%3][(index
+1)%3] = -sin(angle
);
92 * Multiply matrices M1 and M2; return result M3.
94 void mmult(ale_pos m3
[4][4], ale_pos m1
[4][4], ale_pos m2
[4][4]) const {
97 for (int i
= 0; i
< 4; i
++)
98 for (int j
= 0; j
< 4; j
++)
99 for (m3
[i
][j
] = 0, k
= 0; k
< 4; k
++)
100 m3
[i
][j
] += m1
[i
][k
] * m2
[k
][j
];
104 * Calculate resultant matrix values.
106 void resultant() const {
109 * If we already know the answers, don't bother calculating
120 ale_pos m1
[4][4], m2
[4][4], m3
[4][4];
128 for (int i
= 0; i
< 3; i
++)
129 m1
[i
][3] = translation
[i
];
135 mrot(m2
, rotation
[0], 0);
142 mrot(m1
, rotation
[1], 1);
149 mrot(m3
, rotation
[2], 2);
150 mmult(matrix
, m3
, m2
);
156 * Calculate the inverse transform matrix values.
158 void resultant_inverse () const {
161 * If we already know the answers, don't bother calculating
165 if (resultant_inverse_memo
)
169 * The inverse can be explicitly calculated from the rotation
170 * and translation parameters. We invert the individual
171 * matrices and reverse the order of multiplication.
174 ale_pos m1
[4][4], m2
[4][4], m3
[4][4];
182 for (int i
= 0; i
< 3; i
++)
183 m1
[i
][3] = -translation
[i
];
189 mrot(m2
, -rotation
[0], 0);
196 mrot(m1
, -rotation
[1], 1);
203 mrot(m3
, -rotation
[2], 2);
204 mmult(matrix_inverse
, m2
, m3
);
206 resultant_inverse_memo
= 1;
213 struct point
transform(struct point p
) const {
218 for (int i
= 0; i
< 3; i
++) {
219 for (int k
= 0; k
< 3; k
++)
220 result
[i
] += matrix
[i
][k
] * p
[k
];
221 result
[i
] += matrix
[i
][3];
228 * operator() is the transformation operator.
230 struct point
operator()(struct point p
) const {
235 * Map point p using the inverse of the transform.
237 struct point
inverse_transform(struct point p
) const {
242 for (int i
= 0; i
< 3; i
++) {
243 for (int k
= 0; k
< 3; k
++)
244 result
[i
] += matrix_inverse
[i
][k
] * p
[k
];
245 result
[i
] += matrix_inverse
[i
][3];
252 * Default constructor
254 * Returns the identity transformation.
256 * Note: identity() depends on this.
260 resultant_inverse_memo
= 0;
271 et(ale_pos x
, ale_pos y
, ale_pos z
, ale_pos P
, ale_pos Y
, ale_pos R
) {
273 resultant_inverse_memo
= 0;
285 * Return identity transformation.
287 static struct et
identity() {
294 * Set Euclidean parameters (x, y, z, P, Y, R).
296 void set(double values
[6]) {
297 for (int i
= 0; i
< 3; i
++)
298 translation
[i
] = values
[i
];
299 for (int i
= 0; i
< 3; i
++)
300 rotation
[i
] = values
[i
+ 3];
304 * Adjust translation in the indicated manner.
306 void modify_translation(int i1
, ale_pos diff
) {
311 resultant_inverse_memo
= 0;
313 translation
[i1
] += diff
;
316 void set_translation(int i1
, ale_pos new_value
) {
321 resultant_inverse_memo
= 0;
323 translation
[i1
] = new_value
;
327 * Adjust rotation in the indicated manner.
329 void modify_rotation(int i1
, ale_pos diff
) {
334 resultant_inverse_memo
= 0;
336 rotation
[i1
] += diff
;
339 void set_rotation(int i1
, ale_pos new_value
) {
344 resultant_inverse_memo
= 0;
346 rotation
[i1
] = new_value
;
349 ale_pos
get_rotation(int i1
) {
356 ale_pos
get_translation(int i1
) {
360 return translation
[i1
];
364 void debug_output() {
365 fprintf(stderr
, "[et.do t=[%f %f %f] r=[%f %f %f]\n"
366 " m=[[%f %f %f %f] [%f %f %f %f] [%f %f %f %f] [%f %f %f %f]]\n"
367 " mi=[[%f %f %f %f] [%f %f %f %f] [%f %f %f %f] [%f %f %f %f]]\n"
369 (double) translation
[0], (double) translation
[1], (double) translation
[2],
370 (double) rotation
[0], (double) rotation
[1], (double) rotation
[2],
371 (double) matrix
[0][0], (double) matrix
[0][1], (double) matrix
[0][2], (double) matrix
[0][3],
372 (double) matrix
[1][0], (double) matrix
[1][1], (double) matrix
[1][2], (double) matrix
[1][3],
373 (double) matrix
[2][0], (double) matrix
[2][1], (double) matrix
[2][2], (double) matrix
[2][3],
374 (double) matrix
[3][0], (double) matrix
[3][1], (double) matrix
[3][2], (double) matrix
[3][3],
375 (double) matrix_inverse
[0][0], (double) matrix_inverse
[0][1], (double) matrix_inverse
[0][2], (double) matrix_inverse
[0][3],
376 (double) matrix_inverse
[1][0], (double) matrix_inverse
[1][1], (double) matrix_inverse
[1][2], (double) matrix_inverse
[1][3],
377 (double) matrix_inverse
[2][0], (double) matrix_inverse
[2][1], (double) matrix_inverse
[2][2], (double) matrix_inverse
[2][3],
378 (double) matrix_inverse
[3][0], (double) matrix_inverse
[3][1], (double) matrix_inverse
[3][2], (double) matrix_inverse
[3][3],
379 resultant_memo
, resultant_inverse_memo
);