# HG changeset patch # User Eris Caffee # Date 1368345937 18000 # Node ID c029247daf0e4347c65fe6646e0ede8062c4392c # Parent e00321d11fe1a547ec759ed3b65e5d6a134049e5 Started new header Transform.h to collect functions that produce transformation matrices. diff -r e00321d11fe1 -r c029247daf0e include/Math.h --- a/include/Math.h Wed May 08 22:50:09 2013 -0500 +++ b/include/Math.h Sun May 12 03:05:37 2013 -0500 @@ -3,6 +3,7 @@ #include "Vector.h" #include "Matrix.h" +#include "Transform.h" /////////////////////////////////////////////////////////////////////////////////// // Notes for improvement @@ -132,15 +133,6 @@ ////////////////////////////////////////////////////////////////////////// - template - void get_rot_mat33(Matrix33 & m, float angle, Vector3 v); - - template - void get_transform_mat44(Matrix33 & m, float angle, Vector3 v, Vector3 o); - - - ////////////////////////////////////////////////////////////////////////// - inline double deg_to_rad(double deg) { return deg * PI_DIV_180; }; inline double rad_to_deg(double rad) { return rad * INV_PI_DIV_180; }; @@ -148,60 +140,5 @@ } // namespace arda -//////////////////////////////////////////////////////////////////////////////// -template -void arda::Math::get_rot_mat33(arda::Math::Matrix33 & m, float angle, arda::Math::Vector3 v) - { - // TODO Replace == comparision of floating point number! - if (0.0 == v.length()) - return; - - // TODO: I should also immediately return identity if angle is a multiple of 2*PI but I'm not - // yet sure how I should I check for that (taking into account floating point imprecision). - - - v.normalize(); - - float c = cos(angle); - float s = sin(angle); - float one_minus_c = 1.0f - c; - - m.assign( - 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 , - 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 , - 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 - ); - } - -//////////////////////////////////////////////////////////////////////////////// -template -void arda::Math::get_transform_mat44(arda::Math::Matrix44 & m, - float angle, arda::Math::Vector3 v, - arda::Math::Vector3 p) - { - arda::Math::Matrix33f m33(0); - get_rot_mat33(m33, angle, v); - arda::Math::Vector3f p1 = m33 * p; - - m[0] = m33[0]; - m[1] = m33[1]; - m[2] = m33[2]; - m[3] = 0.0f; - - m[4] = m33[3]; - m[5] = m33[4]; - m[6] = m33[5]; - m[7] = 0.0f; - - m[8] = m33[6]; - m[9] = m33[7]; - m[10] = m33[8]; - m[11] = 0.0f; - - m[12] = p.x - p1.x; - m[13] = p.y - p1.y; - m[14] = p.z - p1.z; - m[15] = 1.0f; - } #endif diff -r e00321d11fe1 -r c029247daf0e include/Transform.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/Transform.h Sun May 12 03:05:37 2013 -0500 @@ -0,0 +1,200 @@ +#ifndef TRANSFORM_H_ +#define TRANSFORM_H_ + +// Needs Vector.h and Matrix.h, but this file is not intended to be included +// directly. Just include Math.h and everything will be set up correctly. + +namespace arda + { + namespace Math + { + + ////////////////////////////////////////////////////////////////////////// + + // Transformation by distance vector d + template + void get_trans_mat44(arda::Math::Matrix44 & M, arda::Math::Vector4 d); + + // Rotation by angle around vector v + template + void get_rot_mat33(arda::Math::Matrix33 & M, float angle, arda::Math::Vector3 v); + + template + void get_rot_mat44(arda::Math::Matrix44 & M, float angle, arda::Math::Vector3 v); + + // Uniform scaling by factor of s + template + void get_scale_mat44(arda::Math::Matrix44 & M, float s); + + // Non-uniform scaling + template + void get_scale_mat44(arda::Math::Matrix44 & M, arda::Math::Vector3 s); + + // Non-uniform scaling along arbitrary axes + template + void get_scale_mat44(arda::Math::Matrix44 & M, arda::Math::Vector3 s, + arda::Math::Vector3 x, arda::Math::Vector3 y, arda::Math::Vector3 z); + + // Shear ith coordinate with respect to jth coordinate by s. i and j are zero based column indexes. + // (x = 0, y = 1, z = 2) + template + void get_shear_mat44(arda::Math::Matrix44 & M, int i, int j, float s); + + template + void get_transform_mat44(arda::Math::Matrix44 & M, + float angle, arda::Math::Vector3 v, + arda::Math::Vector3 d); + + // + template + void get_rot_about_point_mat44(arda::Math::Matrix33 & M, float angle, arda::Math::Vector3 v, arda::Math::Vector3 p); + + } // namespace Math + + } // namespace arda + + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_trans_mat44(arda::Math::Matrix44 & M, arda::Math::Vector3 d) + { + M.setidentity(); + M.setcol(3, d.x, d.y, d.z, 1); + } + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_rot_mat33(arda::Math::Matrix33 & M, float angle, arda::Math::Vector3 v) + { + // TODO Replace == comparision of floating point number! + if (0.0 == v.length()) { + M.setidentity(); + return; + } + + // TODO: I should also immediately return identity if angle is a multiple of 2*PI but I'm not + // yet sure how I should I check for that (taking into account floating point imprecision). + + + v.normalize(); + + float c = cos(angle); + float s = sin(angle); + float one_minus_c = 1.0f - c; + + M.assign( + 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 , + 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 , + 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 + ); + } + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_rot_mat44(arda::Math::Matrix44 & M, float angle, arda::Math::Vector3 v) + { + arda::Math::Matrix33 M33; + arda::Math::get_rot_mat33(M33, angle, v); + 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); + } + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_scale_mat44(arda::Math::Matrix44 & M, float s) + { + M.setidentity(); + M *= s; + M[15] = 1; + } + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_scale_mat44(arda::Math::Matrix44 & M, arda::Math::Vector3 s) + { + M.setidentity(); + M[0] = s.x; + M[5] = s.y; + M[10] = s.z; + } + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_scale_mat44(arda::Math::Matrix44 & M, arda::Math::Vector3 s, + arda::Math::Vector3 x, arda::Math::Vector3 y, arda::Math::Vector3 z) + { + // TODO Replace == comparision of floating point number! + assert(0 == x.dot(y)); + assert(0 == x.dot(z)); + assert(0 == y.dot(z)); + + arda::Math::Matrix44 F, Ft, S; + F.setcol(0, x.x, x.y, x.z, 0); + F.setcol(1, y.x, y.y, y.z, 0); + F.setcol(2, z.x, z.y, z.z, 0); + F.setcol(3, 0, 0, 0, 1); + + Ft = arda::Math::transpose(F); + arda::Math::get_scale_mat44(S, s); + + M = F * S * Ft; + } + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_shear_mat44(arda::Math::Matrix44 & M, int i, int j, float s) + { + assert(i<3 && i>=0); + assert(j<3 && j>=0); + M.setidentity(); + M[4*j + i] = s; + } + + +//////////////////////////////////////////////////////////////////////////////// +template +void arda::Math::get_transform_mat44(arda::Math::Matrix44 & M, + float angle, arda::Math::Vector3 v, + arda::Math::Vector3 d) + { + arda::Math::Matrix33 M33; + arda::Math::get_rot_mat33(M33, angle, v); + 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); + } + + + +//////////////////////////////////////////////////////////////////////////////// +// I initially wrote this while trying to do a rotation about an arbitrary vector with the center of rotation at point p. +// It seems to work, but I'm not sure of it's generality. + +template +void arda::Math::get_rot_about_point_mat44(arda::Math::Matrix44 & M, + float angle, arda::Math::Vector3 v, + arda::Math::Vector3 p) + { + arda::Math::Matrix33f M33(0); + get_rot_mat33(M33, angle, v); + arda::Math::Vector3f p1 = M33 * p; + + M[0] = M33[0]; + M[1] = M33[1]; + M[2] = M33[2]; + M[3] = 0; + + M[4] = M33[3]; + M[5] = M33[4]; + M[6] = M33[5]; + M[7] = 0; + + M[8] = M33[6]; + M[9] = M33[7]; + M[10] = M33[8]; + M[11] = 0; + + M[12] = p.x - p1.x; + M[13] = p.y - p1.y; + M[14] = p.z - p1.z; + M[15] = 1; + } + +#endif