From 90ce63bcd81f9f2f0faf5ce8f27fc8dc249d8390 Mon Sep 17 00:00:00 2001 From: Amorilia <amorilia@users.sourceforge.net> Date: Fri, 9 Dec 2005 22:18:54 +0000 Subject: [PATCH] Added a function to calculate an X-aligned bone matrix from the bone vector and the bone roll, which is convenient to have for the Blender exporter. --- nif_math.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++- nif_math.h | 6 ++++ niflib.h | 2 ++ 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/nif_math.cpp b/nif_math.cpp index 64f9658f..c1bf2b61 100644 --- a/nif_math.cpp +++ b/nif_math.cpp @@ -33,13 +33,21 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "nif_math.h" -void PrintMatrix( Matrix33 const & m, ostream & out ) { +void PrintMatrix33( Matrix33 const & m, ostream & out ) { out << endl << " |" << setw(8) << m[0][0] << "," << setw(8) << m[0][1] << "," << setw(8) << m[0][2] << " |" << endl << " |" << setw(8) << m[1][0] << "," << setw(8) << m[1][1] << "," << setw(8) << m[1][2] << " |" << endl << " |" << setw(8) << m[2][0] << "," << setw(8) << m[2][1] << "," << setw(8) << m[2][2] << " |" <<endl; } +void PrintMatrix44( Matrix44 const & m, ostream & out ) { + out << endl + << " |" << setw(8) << m[0][0] << "," << setw(8) << m[0][1] << "," << setw(8) << m[0][2] << setw(8) << m[0][3] << " |" << endl + << " |" << setw(8) << m[1][0] << "," << setw(8) << m[1][1] << "," << setw(8) << m[1][2] << setw(8) << m[1][3] << " |" << endl + << " |" << setw(8) << m[2][0] << "," << setw(8) << m[2][1] << "," << setw(8) << m[2][2] << setw(8) << m[2][3] << " |" << endl + << " |" << setw(8) << m[3][0] << "," << setw(8) << m[3][1] << "," << setw(8) << m[3][2] << setw(8) << m[3][3] << " |" << endl; +} + Vector3 MultVector3( Vector3 const & a, Vector3 const & b ) { Vector3 answer; answer.x = a.y * b.z - a.z * b.y; @@ -290,3 +298,75 @@ void QuatToEuler( Quaternion const & quat, ostream & out ) { << " Bank: " << b << endl; } + +float Length(Vector3 const & a) { + return sqrt(a.x*a.x + a.y*a.y + a.z*a.z); +} + +Vector3 Normalize(Vector3 const & a) { + float l = Length(a); + return Vector3(a.x/l, a.y/l, a.z/l); +} + +float DotProduct(Vector3 const & a, Vector3 const & b) { + return a.x*b.x + a.y*b.y + a.z*b.z; +} + +Vector3 CrossProduct(Vector3 const & a, Vector3 const & b) { + return Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); +} + +float Angle(Vector3 const & a, Vector3 const & b) { + float pi = 3.141592653589793f; + float s = Length(a) * Length(b); + float f = DotProduct(a, b) / s; + if (f >= 1.0f) return 0.0f; + if (f <= -1.0f) return pi / 2.0f; + return atan(-f / sqrt(1.0f - f * f)) + pi / 2.0f; +} + +Matrix44 RotateMatrix44( Vector3 const & axis, float angle) { + float vx = axis.x; + float vy = axis.y; + float vz = axis.z; + float vx2 = vx * vx; + float vy2 = vy * vy; + float vz2 = vz * vz; + float cs = cos(angle); + float sn = sin(angle); + float co1 = 1.0f - cs; + return Matrix44( + vx2 * co1 + cs, vx * vy * co1 + vz * sn, vz * vx * co1 - vy * sn, 0.0f, + vx * vy * co1 - vz * sn, vy2 * co1 + cs, vy * vz * co1 + vx * sn, 0.0f, + vz * vx * co1 + vy * sn, vy * vz * co1 - vx * sn, vz2 * co1 + cs, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} + +Matrix44 BoneToMatrix44( Vector3 const & bone_vec, float roll ) { + float theta; + Matrix44 bMatrix, rMatrix, result; + + Vector3 target(1.0f, 0.0f, 0.0f); + Vector3 nor = Normalize(bone_vec); + Vector3 axis = CrossProduct(target, nor); + if (DotProduct(axis, axis) > 0.0000000000001) { + axis = Normalize(axis); + theta = acos(DotProduct(target, nor)); + bMatrix = RotateMatrix44(axis, theta); + } else { + float updown; + if (DotProduct(target, nor) > 0.0) updown = 1.0f; + else updown = -1.0f; + bMatrix = Matrix44( + updown, 0.0f, 0.0f, 0.0f, + 0.0f, updown, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + }; + rMatrix = RotateMatrix44(nor, roll); + result = MultMatrix44(bMatrix, rMatrix); + result[3][0] = bone_vec.x; + result[3][1] = bone_vec.y; + result[3][2] = bone_vec.z; + return result; +} diff --git a/nif_math.h b/nif_math.h index b07db031..52504446 100644 --- a/nif_math.h +++ b/nif_math.h @@ -56,6 +56,12 @@ Matrix44 InverseMatrix44( Matrix44 const & m ); void SetIdentity33( Matrix33 & m ); void SetIdentity44( Matrix44 & m ); void PrintMatrix33( Matrix33 const & m, ostream & out ); +void PrintMatrix44( Matrix44 const & m, ostream & out ); Quaternion MatrixToQuat( Matrix33 const & m ); +Vector3 Normalize(Vector3 const & a); +float DotProduct(Vector3 const & a, Vector3 const & b); +Vector3 CrossProduct(Vector3 const & a, Vector3 const & b); // = MultVector3 +float Angle(Vector3 const & a, Vector3 const & b); +Matrix44 BoneToMatrix44( Vector3 const & bone_vec, float roll ); #endif diff --git a/niflib.h b/niflib.h index 486e59cb..f4e2460a 100644 --- a/niflib.h +++ b/niflib.h @@ -425,6 +425,8 @@ struct Matrix44 { } }; +// Bone calculation helper function from the nif_math module. +Matrix44 BoneToMatrix44( Vector3 const & bone_vec, float roll ); struct Color { float r, g, b, a; -- GitLab