view include/Transform.h @ 15:ea32c94fc495

General minor improvements. - Spelling corrections. - Made the top level constants like PI static. - Changed instances of literal 1 and 0 to T(1) and T(0)
author Eris Caffee <discordia@eldalin.com>
date Sun, 19 May 2013 20:17:16 -0500
parents c029247daf0e
children 2ac83ae9129b
line source
1 #ifndef TRANSFORM_H_
2 #define TRANSFORM_H_
4 // Needs Vector.h and Matrix.h, but this file is not intended to be included
5 // directly. Just include Math.h and everything will be set up correctly.
7 namespace arda
8 {
9 namespace Math
10 {
12 //////////////////////////////////////////////////////////////////////////
14 // Transformation by distance d
15 template <typename T>
16 void get_trans_mat44(arda::Math::Matrix44<T> & M, arda::Math::Vector4<T> d);
18 // Rotation by angle around vector v
19 template <typename T>
20 void get_rot_mat33(arda::Math::Matrix33<T> & M, float angle, arda::Math::Vector3<T> v);
22 template <typename T>
23 void get_rot_mat44(arda::Math::Matrix44<T> & M, float angle, arda::Math::Vector3<T> v);
25 // Uniform scaling by factor of s
26 template <typename T>
27 void get_scale_mat44(arda::Math::Matrix44<T> & M, float s);
29 // Non-uniform scaling
30 template <typename T>
31 void get_scale_mat44(arda::Math::Matrix44<T> & M, arda::Math::Vector3<T> s);
33 // Non-uniform scaling along arbitrary axis
34 template <typename T>
35 void get_scale_mat44(arda::Math::Matrix44<T> & M, arda::Math::Vector3<T> s,
36 arda::Math::Vector3<T> x, arda::Math::Vector3<T> y, arda::Math::Vector3<T> z);
38 // Shear ith coordinate with respect to jth coordinate by s. i and j are zero based column indexes.
39 // (x = 0, y = 1, z = 2)
40 template <typename T>
41 void get_shear_mat44(arda::Math::Matrix44<T> & M, int i, int j, float s);
43 template <typename T>
44 void get_transform_mat44(arda::Math::Matrix44<T> & M, float angle, arda::Math::Vector3<T> v, arda::Math::Vector3<T> d);
46 // Rotate by angle around v with center of rotation p.
47 template <typename T>
48 void get_rot_about_point_mat44(arda::Math::Matrix33<T> & M, float angle, arda::Math::Vector3<T> v, arda::Math::Vector3<T> p);
50 } // namespace Math
52 } // namespace arda
55 ////////////////////////////////////////////////////////////////////////////////
56 template <typename T>
57 void arda::Math::get_trans_mat44(arda::Math::Matrix44<T> & M, arda::Math::Vector3<T> d)
58 {
59 M.setidentity();
60 M.setcol(3, d.x, d.y, d.z, 1);
61 }
63 ////////////////////////////////////////////////////////////////////////////////
64 template <typename T>
65 void arda::Math::get_rot_mat33(arda::Math::Matrix33<T> & M, float angle, arda::Math::Vector3<T> v)
66 {
67 // TODO Replace == comparision of floating point number!
68 if (0.0 == v.length()) {
69 M.setidentity();
70 return;
71 }
73 // TODO: I should also immediately return identity if angle is a multiple of 2*PI but I'm not
74 // yet sure how I should I check for that (taking into account floating point imprecision).
77 v.normalize();
79 float c = cos(angle);
80 float s = sin(angle);
81 float one_minus_c = 1.0f - c;
83 // Remember: the "rows" as written here are actually the columns of the matrix.
84 M.assign(
85 c + one_minus_c * v.x * v.x , one_minus_c * v.x * v.y + s * v.z , one_minus_c * v.x * v.z - s * v.y ,
86 one_minus_c * v.x * v.y - s * v.z , c + one_minus_c * v.y * v.y , one_minus_c * v.y * v.z + s * v.x ,
87 one_minus_c * v.x * v.z + s * v.y , one_minus_c * v.y * v.z - s * v.x , c + one_minus_c * v.z * v.z
88 );
89 }
91 ////////////////////////////////////////////////////////////////////////////////
92 template <typename T>
93 void arda::Math::get_rot_mat44(arda::Math::Matrix44<T> & M, float angle, arda::Math::Vector3<T> v)
94 {
95 arda::Math::Matrix33<T> M33;
96 arda::Math::get_rot_mat33(M33, angle, v);
97 M.assign(M33[0], M33[1], M33[2], 0, M33[3], M33[4], M33[5], 0, M33[6], M33[7], M33[8], 0, 0, 0, 0, 1);
98 }
100 ////////////////////////////////////////////////////////////////////////////////
101 template <typename T>
102 void arda::Math::get_scale_mat44(arda::Math::Matrix44<T> & M, float s)
103 {
104 M.setidentity();
105 M *= s;
106 M[15] = 1;
107 }
109 ////////////////////////////////////////////////////////////////////////////////
110 template <typename T>
111 void arda::Math::get_scale_mat44(arda::Math::Matrix44<T> & M, arda::Math::Vector3<T> s)
112 {
113 M.setidentity();
114 M[0] = s.x;
115 M[5] = s.y;
116 M[10] = s.z;
117 }
119 ////////////////////////////////////////////////////////////////////////////////
120 template <typename T>
121 void arda::Math::get_scale_mat44(arda::Math::Matrix44<T> & M, arda::Math::Vector3<T> s,
122 arda::Math::Vector3<T> x, arda::Math::Vector3<T> y, arda::Math::Vector3<T> z)
123 {
124 // TODO Replace == comparision of floating point number!
125 assert(0 == x.dot(y));
126 assert(0 == x.dot(z));
127 assert(0 == y.dot(z));
129 arda::Math::Matrix44<T> F, Ft, S;
130 F.setcol(0, x.x, x.y, x.z, 0);
131 F.setcol(1, y.x, y.y, y.z, 0);
132 F.setcol(2, z.x, z.y, z.z, 0);
133 F.setcol(3, 0, 0, 0, 1);
135 Ft = arda::Math::transpose(F);
136 arda::Math::get_scale_mat44(S, s);
138 M = F * S * Ft;
139 }
141 ////////////////////////////////////////////////////////////////////////////////
142 template <typename T>
143 void arda::Math::get_shear_mat44(arda::Math::Matrix44<T> & M, int i, int j, float s)
144 {
145 assert(i<3 && i>=0);
146 assert(j<3 && j>=0);
147 M.setidentity();
148 M[4*j + i] = s;
149 }
152 ////////////////////////////////////////////////////////////////////////////////
153 template <typename T>
154 void arda::Math::get_transform_mat44(arda::Math::Matrix44<T> & M,
155 float angle, arda::Math::Vector3<T> v,
156 arda::Math::Vector3<T> d)
157 {
158 arda::Math::Matrix33<T> M33;
159 arda::Math::get_rot_mat33(M33, angle, v);
160 M.assign(M33[0], M33[1], M33[2], 0, M33[3], M33[4], M33[5], 0, M33[6], M33[7], M33[8], 0, d.x, d.y, d.z, 1);
161 }
165 ////////////////////////////////////////////////////////////////////////////////
166 // I initially wrote this while trying to do a rotation about an arbitrary vector with the center of rotation at point p.
167 // It seems to work, but I'm not sure of it's generality.
169 template <typename T>
170 void arda::Math::get_rot_about_point_mat44(arda::Math::Matrix44<T> & M,
171 float angle, arda::Math::Vector3<T> v,
172 arda::Math::Vector3<T> p)
173 {
174 arda::Math::Matrix33f M33(0);
175 get_rot_mat33(M33, angle, v);
176 arda::Math::Vector3f p1 = M33 * p;
178 M[0] = M33[0];
179 M[1] = M33[1];
180 M[2] = M33[2];
181 M[3] = T(0);
183 M[4] = M33[3];
184 M[5] = M33[4];
185 M[6] = M33[5];
186 M[7] = T(0);
188 M[8] = M33[6];
189 M[9] = M33[7];
190 M[10] = M33[8];
191 M[11] = T(0);
193 M[12] = p.x - p1.x;
194 M[13] = p.y - p1.y;
195 M[14] = p.z - p1.z;
196 M[15] = T(1);
197 }
199 #endif