/* =========================================================================== Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 BFG Edition Source Code. If not, see . In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #ifndef __JOINTTRANSFORM_H__ #define __JOINTTRANSFORM_H__ /* =============================================================================== Joint Quaternion =============================================================================== */ class idJointQuat { public: const float * ToFloatPtr() const { return q.ToFloatPtr(); } float * ToFloatPtr() { return q.ToFloatPtr(); } idQuat q; idVec3 t; float w; }; // offsets for SIMD code #define JOINTQUAT_SIZE (8*4) // sizeof( idJointQuat ) #define JOINTQUAT_SIZE_SHIFT 5 // log2( sizeof( idJointQuat ) ) #define JOINTQUAT_Q_OFFSET (0*4) // offsetof( idJointQuat, q ) #define JOINTQUAT_T_OFFSET (4*4) // offsetof( idJointQuat, t ) assert_sizeof( idJointQuat, JOINTQUAT_SIZE ); assert_sizeof( idJointQuat, (1< epsilon ) { return false; } } return true; } /* ======================== idJointMat::operator== ======================== */ ID_INLINE bool idJointMat::operator==( const idJointMat &a ) const { return Compare( a ); } /* ======================== idJointMat::operator!= ======================== */ ID_INLINE bool idJointMat::operator!=( const idJointMat &a ) const { return !Compare( a ); } /* ======================== idJointMat::Identity ======================== */ ID_INLINE void idJointMat::Identity() { mat[0 * 4 + 0] = 1.0f; mat[0 * 4 + 1] = 0.0f; mat[0 * 4 + 2] = 0.0f; mat[0 * 4 + 3] = 0.0f; mat[1 * 4 + 0] = 0.0f; mat[1 * 4 + 1] = 1.0f; mat[1 * 4 + 2] = 0.0f; mat[1 * 4 + 3] = 0.0f; mat[2 * 4 + 0] = 0.0f; mat[2 * 4 + 1] = 0.0f; mat[2 * 4 + 2] = 1.0f; mat[2 * 4 + 3] = 0.0f; } /* ======================== idJointMat::Invert ======================== */ ID_INLINE void idJointMat::Invert() { float tmp[3]; // negate inverse rotated translation part tmp[0] = mat[0 * 4 + 0] * mat[0 * 4 + 3] + mat[1 * 4 + 0] * mat[1 * 4 + 3] + mat[2 * 4 + 0] * mat[2 * 4 + 3]; tmp[1] = mat[0 * 4 + 1] * mat[0 * 4 + 3] + mat[1 * 4 + 1] * mat[1 * 4 + 3] + mat[2 * 4 + 1] * mat[2 * 4 + 3]; tmp[2] = mat[0 * 4 + 2] * mat[0 * 4 + 3] + mat[1 * 4 + 2] * mat[1 * 4 + 3] + mat[2 * 4 + 2] * mat[2 * 4 + 3]; mat[0 * 4 + 3] = -tmp[0]; mat[1 * 4 + 3] = -tmp[1]; mat[2 * 4 + 3] = -tmp[2]; // transpose rotation part tmp[0] = mat[0 * 4 + 1]; mat[0 * 4 + 1] = mat[1 * 4 + 0]; mat[1 * 4 + 0] = tmp[0]; tmp[1] = mat[0 * 4 + 2]; mat[0 * 4 + 2] = mat[2 * 4 + 0]; mat[2 * 4 + 0] = tmp[1]; tmp[2] = mat[1 * 4 + 2]; mat[1 * 4 + 2] = mat[2 * 4 + 1]; mat[2 * 4 + 1] = tmp[2]; } /* ======================== idJointMat::ToMat3 ======================== */ ID_INLINE idMat3 idJointMat::ToMat3() const { return idMat3( mat[0 * 4 + 0], mat[1 * 4 + 0], mat[2 * 4 + 0], mat[0 * 4 + 1], mat[1 * 4 + 1], mat[2 * 4 + 1], mat[0 * 4 + 2], mat[1 * 4 + 2], mat[2 * 4 + 2] ); } /* ======================== idJointMat::ToMat4 ======================== */ ID_INLINE idMat4 idJointMat::ToMat4() const { return idMat4( mat[0 * 4 + 0], mat[0 * 4 + 1], mat[0 * 4 + 2], mat[0 * 4 + 3], mat[1 * 4 + 0], mat[1 * 4 + 1], mat[1 * 4 + 2], mat[1 * 4 + 3], mat[2 * 4 + 0], mat[2 * 4 + 1], mat[2 * 4 + 2], mat[2 * 4 + 3], 0.0f, 0.0f, 0.0f, 1.0f ); } /* ======================== idJointMat::FromMat4 ======================== */ ID_INLINE void idJointMat::FromMat4( const idMat4 & m ) { mat[0*4+0] = m[0][0], mat[0*4+1] = m[0][1], mat[0*4+2] = m[0][2], mat[0*4+3] = m[0][3]; mat[1*4+0] = m[1][0], mat[1*4+1] = m[1][1], mat[1*4+2] = m[1][2], mat[1*4+3] = m[1][3]; mat[2*4+0] = m[2][0], mat[2*4+1] = m[2][1], mat[2*4+2] = m[2][2], mat[2*4+3] = m[2][3]; assert( m[3][0] == 0.0f ); assert( m[3][1] == 0.0f ); assert( m[3][2] == 0.0f ); assert( m[3][3] == 1.0f ); } /* ======================== idJointMat::ToVec3 ======================== */ ID_INLINE idVec3 idJointMat::ToVec3() const { return idVec3( mat[0 * 4 + 3], mat[1 * 4 + 3], mat[2 * 4 + 3] ); } /* ======================== idJointMat::Transform ======================== */ ID_INLINE void idJointMat::Transform( idVec3 &result, const idVec3 &v ) const { result.x = mat[0 * 4 + 0] * v.x + mat[0 * 4 + 1] * v.y + mat[0 * 4 + 2] * v.z + mat[0 * 4 + 3]; result.y = mat[1 * 4 + 0] * v.x + mat[1 * 4 + 1] * v.y + mat[1 * 4 + 2] * v.z + mat[1 * 4 + 3]; result.z = mat[2 * 4 + 0] * v.x + mat[2 * 4 + 1] * v.y + mat[2 * 4 + 2] * v.z + mat[2 * 4 + 3]; } /* ======================== idJointMat::Rotate ======================== */ ID_INLINE void idJointMat::Rotate( idVec3 &result, const idVec3 &v ) const { result.x = mat[0 * 4 + 0] * v.x + mat[0 * 4 + 1] * v.y + mat[0 * 4 + 2] * v.z; result.y = mat[1 * 4 + 0] * v.x + mat[1 * 4 + 1] * v.y + mat[1 * 4 + 2] * v.z; result.z = mat[2 * 4 + 0] * v.x + mat[2 * 4 + 1] * v.y + mat[2 * 4 + 2] * v.z; } /* ======================== idJointMat::Mul ======================== */ ID_INLINE void idJointMat::Mul( idJointMat &result, const idJointMat &mat, const float s ) { result.mat[0 * 4 + 0] = s * mat.mat[0 * 4 + 0]; result.mat[0 * 4 + 1] = s * mat.mat[0 * 4 + 1]; result.mat[0 * 4 + 2] = s * mat.mat[0 * 4 + 2]; result.mat[0 * 4 + 3] = s * mat.mat[0 * 4 + 3]; result.mat[1 * 4 + 0] = s * mat.mat[1 * 4 + 0]; result.mat[1 * 4 + 1] = s * mat.mat[1 * 4 + 1]; result.mat[1 * 4 + 2] = s * mat.mat[1 * 4 + 2]; result.mat[1 * 4 + 3] = s * mat.mat[1 * 4 + 3]; result.mat[2 * 4 + 0] = s * mat.mat[2 * 4 + 0]; result.mat[2 * 4 + 1] = s * mat.mat[2 * 4 + 1]; result.mat[2 * 4 + 2] = s * mat.mat[2 * 4 + 2]; result.mat[2 * 4 + 3] = s * mat.mat[2 * 4 + 3]; } /* ======================== idJointMat::Mad ======================== */ ID_INLINE void idJointMat::Mad( idJointMat &result, const idJointMat &mat, const float s ) { result.mat[0 * 4 + 0] += s * mat.mat[0 * 4 + 0]; result.mat[0 * 4 + 1] += s * mat.mat[0 * 4 + 1]; result.mat[0 * 4 + 2] += s * mat.mat[0 * 4 + 2]; result.mat[0 * 4 + 3] += s * mat.mat[0 * 4 + 3]; result.mat[1 * 4 + 0] += s * mat.mat[1 * 4 + 0]; result.mat[1 * 4 + 1] += s * mat.mat[1 * 4 + 1]; result.mat[1 * 4 + 2] += s * mat.mat[1 * 4 + 2]; result.mat[1 * 4 + 3] += s * mat.mat[1 * 4 + 3]; result.mat[2 * 4 + 0] += s * mat.mat[2 * 4 + 0]; result.mat[2 * 4 + 1] += s * mat.mat[2 * 4 + 1]; result.mat[2 * 4 + 2] += s * mat.mat[2 * 4 + 2]; result.mat[2 * 4 + 3] += s * mat.mat[2 * 4 + 3]; } /* ======================== idJointMat::Multiply ======================== */ ID_INLINE void idJointMat::Multiply( idJointMat &result, const idJointMat &m1, const idJointMat &m2 ) { result.mat[0 * 4 + 0] = m1.mat[0 * 4 + 0] * m2.mat[0 * 4 + 0] + m1.mat[0 * 4 + 1] * m2.mat[1 * 4 + 0] + m1.mat[0 * 4 + 2] * m2.mat[2 * 4 + 0]; result.mat[0 * 4 + 1] = m1.mat[0 * 4 + 0] * m2.mat[0 * 4 + 1] + m1.mat[0 * 4 + 1] * m2.mat[1 * 4 + 1] + m1.mat[0 * 4 + 2] * m2.mat[2 * 4 + 1]; result.mat[0 * 4 + 2] = m1.mat[0 * 4 + 0] * m2.mat[0 * 4 + 2] + m1.mat[0 * 4 + 1] * m2.mat[1 * 4 + 2] + m1.mat[0 * 4 + 2] * m2.mat[2 * 4 + 2]; result.mat[0 * 4 + 3] = m1.mat[0 * 4 + 0] * m2.mat[0 * 4 + 3] + m1.mat[0 * 4 + 1] * m2.mat[1 * 4 + 3] + m1.mat[0 * 4 + 2] * m2.mat[2 * 4 + 3] + m1.mat[0 * 4 + 3]; result.mat[1 * 4 + 0] = m1.mat[1 * 4 + 0] * m2.mat[0 * 4 + 0] + m1.mat[1 * 4 + 1] * m2.mat[1 * 4 + 0] + m1.mat[1 * 4 + 2] * m2.mat[2 * 4 + 0]; result.mat[1 * 4 + 1] = m1.mat[1 * 4 + 0] * m2.mat[0 * 4 + 1] + m1.mat[1 * 4 + 1] * m2.mat[1 * 4 + 1] + m1.mat[1 * 4 + 2] * m2.mat[2 * 4 + 1]; result.mat[1 * 4 + 2] = m1.mat[1 * 4 + 0] * m2.mat[0 * 4 + 2] + m1.mat[1 * 4 + 1] * m2.mat[1 * 4 + 2] + m1.mat[1 * 4 + 2] * m2.mat[2 * 4 + 2]; result.mat[1 * 4 + 3] = m1.mat[1 * 4 + 0] * m2.mat[0 * 4 + 3] + m1.mat[1 * 4 + 1] * m2.mat[1 * 4 + 3] + m1.mat[1 * 4 + 2] * m2.mat[2 * 4 + 3] + m1.mat[1 * 4 + 3]; result.mat[2 * 4 + 0] = m1.mat[2 * 4 + 0] * m2.mat[0 * 4 + 0] + m1.mat[2 * 4 + 1] * m2.mat[1 * 4 + 0] + m1.mat[2 * 4 + 2] * m2.mat[2 * 4 + 0]; result.mat[2 * 4 + 1] = m1.mat[2 * 4 + 0] * m2.mat[0 * 4 + 1] + m1.mat[2 * 4 + 1] * m2.mat[1 * 4 + 1] + m1.mat[2 * 4 + 2] * m2.mat[2 * 4 + 1]; result.mat[2 * 4 + 2] = m1.mat[2 * 4 + 0] * m2.mat[0 * 4 + 2] + m1.mat[2 * 4 + 1] * m2.mat[1 * 4 + 2] + m1.mat[2 * 4 + 2] * m2.mat[2 * 4 + 2]; result.mat[2 * 4 + 3] = m1.mat[2 * 4 + 0] * m2.mat[0 * 4 + 3] + m1.mat[2 * 4 + 1] * m2.mat[1 * 4 + 3] + m1.mat[2 * 4 + 2] * m2.mat[2 * 4 + 3] + m1.mat[2 * 4 + 3]; } /* ======================== idJointMat::InverseMultiply ======================== */ ID_INLINE void idJointMat::InverseMultiply( idJointMat &result, const idJointMat &m1, const idJointMat &m2 ) { float dst[3]; result.mat[0 * 4 + 0] = m1.mat[0 * 4 + 0] * m2.mat[0 * 4 + 0] + m1.mat[0 * 4 + 1] * m2.mat[0 * 4 + 1] + m1.mat[0 * 4 + 2] * m2.mat[0 * 4 + 2]; result.mat[0 * 4 + 1] = m1.mat[0 * 4 + 0] * m2.mat[1 * 4 + 0] + m1.mat[0 * 4 + 1] * m2.mat[1 * 4 + 1] + m1.mat[0 * 4 + 2] * m2.mat[1 * 4 + 2]; result.mat[0 * 4 + 2] = m1.mat[0 * 4 + 0] * m2.mat[2 * 4 + 0] + m1.mat[0 * 4 + 1] * m2.mat[2 * 4 + 1] + m1.mat[0 * 4 + 2] * m2.mat[2 * 4 + 2]; result.mat[1 * 4 + 0] = m1.mat[1 * 4 + 0] * m2.mat[0 * 4 + 0] + m1.mat[1 * 4 + 1] * m2.mat[0 * 4 + 1] + m1.mat[1 * 4 + 2] * m2.mat[0 * 4 + 2]; result.mat[1 * 4 + 1] = m1.mat[1 * 4 + 0] * m2.mat[1 * 4 + 0] + m1.mat[1 * 4 + 1] * m2.mat[1 * 4 + 1] + m1.mat[1 * 4 + 2] * m2.mat[1 * 4 + 2]; result.mat[1 * 4 + 2] = m1.mat[1 * 4 + 0] * m2.mat[2 * 4 + 0] + m1.mat[1 * 4 + 1] * m2.mat[2 * 4 + 1] + m1.mat[1 * 4 + 2] * m2.mat[2 * 4 + 2]; result.mat[2 * 4 + 0] = m1.mat[2 * 4 + 0] * m2.mat[0 * 4 + 0] + m1.mat[2 * 4 + 1] * m2.mat[0 * 4 + 1] + m1.mat[2 * 4 + 2] * m2.mat[0 * 4 + 2]; result.mat[2 * 4 + 1] = m1.mat[2 * 4 + 0] * m2.mat[1 * 4 + 0] + m1.mat[2 * 4 + 1] * m2.mat[1 * 4 + 1] + m1.mat[2 * 4 + 2] * m2.mat[1 * 4 + 2]; result.mat[2 * 4 + 2] = m1.mat[2 * 4 + 0] * m2.mat[2 * 4 + 0] + m1.mat[2 * 4 + 1] * m2.mat[2 * 4 + 1] + m1.mat[2 * 4 + 2] * m2.mat[2 * 4 + 2]; dst[0] = - ( m2.mat[0 * 4 + 0] * m2.mat[0 * 4 + 3] + m2.mat[1 * 4 + 0] * m2.mat[1 * 4 + 3] + m2.mat[2 * 4 + 0] * m2.mat[2 * 4 + 3] ); dst[1] = - ( m2.mat[0 * 4 + 1] * m2.mat[0 * 4 + 3] + m2.mat[1 * 4 + 1] * m2.mat[1 * 4 + 3] + m2.mat[2 * 4 + 1] * m2.mat[2 * 4 + 3] ); dst[2] = - ( m2.mat[0 * 4 + 2] * m2.mat[0 * 4 + 3] + m2.mat[1 * 4 + 2] * m2.mat[1 * 4 + 3] + m2.mat[2 * 4 + 2] * m2.mat[2 * 4 + 3] ); result.mat[0 * 4 + 3] = m1.mat[0 * 4 + 0] * dst[0] + m1.mat[0 * 4 + 1] * dst[1] + m1.mat[0 * 4 + 2] * dst[2] + m1.mat[0 * 4 + 3]; result.mat[1 * 4 + 3] = m1.mat[1 * 4 + 0] * dst[0] + m1.mat[1 * 4 + 1] * dst[1] + m1.mat[1 * 4 + 2] * dst[2] + m1.mat[1 * 4 + 3]; result.mat[2 * 4 + 3] = m1.mat[2 * 4 + 0] * dst[0] + m1.mat[2 * 4 + 1] * dst[1] + m1.mat[2 * 4 + 2] * dst[2] + m1.mat[2 * 4 + 3]; } #endif /* !__JOINTTRANSFORM_H__ */