From 8696388eec2c04c53680c380c9e75b8e8ede14f2 Mon Sep 17 00:00:00 2001 From: Shon Ferguson <shonferg@users.sourceforge.net> Date: Sat, 13 May 2006 09:33:21 +0000 Subject: [PATCH] Moved math-related structures to nif_math files and began porting operations to member functions. --- NIF_Blocks.h | 4 + NIF_IO.cpp | 56 ---- NIF_IO.h | 11 - nif_attrs.h | 1 + nif_math.cpp | 365 +++++++++++++++------- nif_math.h | 734 +++++++++++++++++++++++++++++++++++++++++++- niflib.h | 568 +--------------------------------- niflib_internal.cpp | 54 ++++ niflib_internal.h | 107 +++++++ 9 files changed, 1149 insertions(+), 751 deletions(-) diff --git a/NIF_Blocks.h b/NIF_Blocks.h index c1d1c3a1..5583a82c 100644 --- a/NIF_Blocks.h +++ b/NIF_Blocks.h @@ -60,14 +60,18 @@ const int SkinDataInternal = -3; class AControllable : public ABlock { public: + static const Type TYPE; AControllable(); void Init() {} bool IsControllable() const { return true; } ~AControllable() {} }; +const Type AControllable::TYPE("AControllable", &ABlock::TYPE); + class ANode : public AControllable, public INode { public: + static const Type TYPE; ANode(); void Init() { //Start the bind pose at an identity matrix diff --git a/NIF_IO.cpp b/NIF_IO.cpp index e608867c..a34448ab 100644 --- a/NIF_IO.cpp +++ b/NIF_IO.cpp @@ -355,10 +355,6 @@ void NifStream( TexCoord const & val, ostream& out, uint version ) { WriteFloat( val.v, out ); }; -ostream & operator<<( ostream & out, TexCoord const & val ) { - return out << "(" << setw(6) << val.u << "," << setw(6) << val.v << ")"; -} - //Triangle void NifStream( Triangle & val, istream& in, uint version ) { val.v1 = ReadUShort( in ); @@ -372,10 +368,6 @@ void NifStream( Triangle const & val, ostream& out, uint version ) { WriteUShort( val.v3, out ); }; -ostream & operator<<( ostream & out, Triangle const & val ) { - return out << "{" << setw(6) << val.v1 << "," << setw(6) << val.v2 << "," << setw(6) << val.v3 << "}"; -} - //Vector3 void NifStream( Vector3 & val, istream& in, uint version ) { val.x = ReadFloat( in ); @@ -389,10 +381,6 @@ void NifStream( Vector3 const & val, ostream& out, uint version ) { WriteFloat( val.z, out ); }; -ostream & operator<<( ostream & out, Vector3 const & val ) { - return out << "(" << setw(6) << val.x << "," << setw(6) << val.y << "," << setw(6) << val.z << ")"; -} - //Float2 void NifStream( Float2 & val, istream& in, uint version ) { val.data[0] = ReadFloat( in ); @@ -404,10 +392,6 @@ void NifStream( Float2 const & val, ostream& out, uint version ) { WriteFloat( val.data[1], out ); }; -ostream & operator<<( ostream & out, Float2 const & val ) { - return out << "{" << setw(6) << val.data[0] << "," << setw(6) << val.data[1] << "}"; -} - //Matrix22 void NifStream( Matrix22 & val, istream& in, uint version ) { for (int c = 0; c < 2; ++c) { @@ -425,13 +409,6 @@ void NifStream( Matrix22 const & val, ostream& out, uint version ) { } } -ostream & operator<<( ostream & out, Matrix22 const & val ) { - out << endl - << " |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << " |" << endl - << " |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << " |"; - return out; -} - //Float3 void NifStream( Float3 & val, istream& in, uint version ) { val.data[0] = ReadFloat( in ); @@ -445,10 +422,6 @@ void NifStream( Float3 const & val, ostream& out, uint version ) { WriteFloat( val.data[2], out ); }; -ostream & operator<<( ostream & out, Float3 const & val ) { - return out << "{" << setw(6) << val.data[0] << "," << setw(6) << val.data[1] << "," << setw(6) << val.data[2] << "}"; -} - //Matrix33 void NifStream( Matrix33 & val, istream& in, uint version ) { for (int c = 0; c < 3; ++c) { @@ -466,14 +439,6 @@ void NifStream( Matrix33 const & val, ostream& out, uint version ) { } } -ostream & operator<<( ostream & out, Matrix33 const & val ) { - out << endl - << " |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << "," << setw(6) << val[0][2] << " |" << endl - << " |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << "," << setw(6) << val[1][2] << " |" << endl - << " |" << setw(6) << val[2][0] << "," << setw(6) << val[2][1] << "," << setw(6) << val[2][2] << " |"; - return out; -} - //Float4 void NifStream( Float4 & val, istream& in, uint version ) { val.data[0] = ReadFloat( in ); @@ -489,10 +454,6 @@ void NifStream( Float4 const & val, ostream& out, uint version ) { WriteFloat( val.data[4], out ); }; -ostream & operator<<( ostream & out, Float4 const & val ) { - return out << "{" << setw(6) << val.data[0] << "," << setw(6) << val.data[1] << "," << setw(6) << val.data[2] << "," << setw(6) << val.data[3] << "}"; -} - //Matrix44 void NifStream( Matrix44 & val, istream& in, uint version ) { for (int c = 0; c < 4; ++c) { @@ -510,15 +471,6 @@ void NifStream( Matrix44 const & val, ostream& out, uint version ) { } } -ostream & operator<<( ostream & out, Matrix44 const & val ) { - out << endl - << " |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << "," << setw(6) << val[0][2] << "," << setw(6) << val[0][3] << " |" << endl - << " |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << "," << setw(6) << val[1][2] << "," << setw(6) << val[1][3] << " |" << endl - << " |" << setw(6) << val[2][0] << "," << setw(6) << val[2][1] << "," << setw(6) << val[2][2] << "," << setw(6) << val[2][3] << " |" << endl - << " |" << setw(6) << val[3][0] << "," << setw(6) << val[3][1] << "," << setw(6) << val[3][2] << "," << setw(6) << val[3][3] << " |"; - return out; -} - //Color4 void NifStream( Color4 & val, istream& in, uint version ) { val.r = ReadFloat( in ); @@ -534,10 +486,6 @@ void NifStream( Color4 const & val, ostream& out, uint version ) { WriteFloat( val.a, out ); }; -ostream & operator<<( ostream & out, Color4 const & val ) { - return out << "R:" << setw(6) << val.r << " G:" << setw(6) << val.g << " B:" << setw(6) << val.b << " A:" << setw(6) << val.a << "}"; -} - //Quaternion void NifStream( Quaternion & val, istream& in, uint version ) { val.w = ReadFloat( in ); @@ -553,10 +501,6 @@ void NifStream( Quaternion const & val, ostream& out, uint version ) { WriteFloat( val.z, out ); }; -ostream & operator<<( ostream & out, Quaternion const & val ) { - return out << "[" << setw(6) << val.w << ",(" << setw(6) << val.x << "," << setw(6) << val.y << "," << setw(6) << val.z << ")]"; -} - //BoundingBox void NifStream( BoundingBox & val, istream& in, uint version ) { NifStream( val.isUsed, in, version ); diff --git a/NIF_IO.h b/NIF_IO.h index 83a6116d..f5366640 100644 --- a/NIF_IO.h +++ b/NIF_IO.h @@ -140,57 +140,46 @@ ostream & operator<<( ostream & out, HeaderString const & val ); //TexCoord void NifStream( TexCoord & val, istream& in, uint version = 0 ); void NifStream( TexCoord const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, TexCoord const & val ); //Triangle void NifStream( Triangle & val, istream& in, uint version = 0 ); void NifStream( Triangle const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Triangle const & val ); //Vector3 void NifStream( Vector3 & val, istream& in, uint version = 0 ); void NifStream( Vector3 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Vector3 const & val ); //Float2 void NifStream( Float2 & val, istream& in, uint version = 0 ); void NifStream( Float2 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Float2 const & val ); //Matrix22 void NifStream( Matrix22 & val, istream& in, uint version = 0 ); void NifStream( Matrix22 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Matrix22 const & val ); //Float3 void NifStream( Float3 & val, istream& in, uint version = 0 ); void NifStream( Float3 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Float3 const & val ); //Matrix33 void NifStream( Matrix33 & val, istream& in, uint version = 0 ); void NifStream( Matrix33 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Matrix33 const & val ); //Float4 void NifStream( Float4 & val, istream& in, uint version = 0 ); void NifStream( Float4 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Float4 const & val ); //Matrix44 void NifStream( Matrix44 & val, istream& in, uint version = 0 ); void NifStream( Matrix44 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Matrix44 const & val ); //Color4 void NifStream( Color4 & val, istream& in, uint version = 0 ); void NifStream( Color4 const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Color4 const & val ); //Quaternion void NifStream( Quaternion & val, istream& in, uint version = 0 ); void NifStream( Quaternion const & val, ostream& out, uint version = 0 ); -ostream & operator<<( ostream & out, Quaternion const & val ); //BoundingBox void NifStream( BoundingBox & val, istream& in, uint version = 0 ); diff --git a/nif_attrs.h b/nif_attrs.h index f37033a5..1b1b392a 100644 --- a/nif_attrs.h +++ b/nif_attrs.h @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #define endl "\r\n" + class IntAttr : public AAttr { public: IntAttr( string const & name, IBlock * owner, int * data ) : AAttr( name, owner ), _data(data) {} diff --git a/nif_math.cpp b/nif_math.cpp index 99a177ad..583aec2c 100644 --- a/nif_math.cpp +++ b/nif_math.cpp @@ -32,6 +32,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "nif_math.h" +#include <iomanip> void PrintMatrix33( Matrix33 const & m, ostream & out ) { out << endl @@ -70,52 +71,6 @@ void SetIdentity44( Matrix44 & m ) { m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f; } -//Vector3 MatrixToEuler( Matrix33 & m ) {} - -Quaternion MatrixToQuat( Matrix33 const & m ) { - Quaternion quat; - float tr, s, q[4]; - int i, j, k; - - int nxt[3] = {1, 2, 0}; - - // compute the trace of the matrix - tr = m[0][0] + m[1][1] + m[2][2]; - - // check if the trace is positive or negative - if (tr > 0.0) { - s = sqrt (tr + 1.0f); - quat.w = s / 2.0f; - s = 0.5f / s; - quat.x = (m[1][2] - m[2][1]) * s; - quat.y = (m[2][0] - m[0][2]) * s; - quat.z = (m[0][1] - m[1][0]) * s; - } - else { - // trace is negative - i = 0; - if ( m[1][1] > m[0][0]) - i = 1; - if ( m[2][2] > m[i][i] ) - i = 2; - j = nxt[i]; - k = nxt[j]; - - s = sqrt( ( m[i][i] - (m[j][j] + m[k][k]) ) + 1.0f ); - q[i] = s * 0.5f; - if (s != 0.0f) s = 0.5f / s; - q[3] = (m[j][k] - m[k][j]) * s; - q[j] = (m[i][j] + m[j][i]) * s; - q[k] = (m[i][k] + m[k][i]) * s; - quat.x = q[0]; - quat.y= q[1]; - quat.z = q[2]; - quat.w = q[3]; - } - - return quat; -} - Matrix33 MultMatrix33( Matrix33 const & a, Matrix33 const & b ) { Matrix33 result; for (int i = 0; i < 3; i++) { @@ -211,13 +166,196 @@ Matrix44 InverseMatrix44( Matrix44 const & m ) { return result; } -void QuatToMatrix( Quaternion const & quat, ostream & out ) { - Matrix33 m; +/* + * Vector3 Methods + */ + +float Vector3::Magnitude() const { + return sqrt( x * x + y * y + z * z ); +} + +Vector3 Vector3::Normalized() const { + Vector3 v(*this); + float m = Magnitude(); + return Vector3( + x / m, //x + y / m, //y + z / m //z + ); +} + +Vector3 Vector3::operator+( const Vector3 & rh) const { + Vector3 v(*this); + v += rh; + return v; +} + +Vector3 & Vector3::operator+=( const Vector3 & rh ) { + x += rh.x; + y += rh.y; + z += rh.z; + + return *this; +} + +Vector3 Vector3::operator-( const Vector3 & rh) const { + Vector3 v(*this); + v -= rh; + return v; +} + +Vector3 & Vector3::operator-=( const Vector3 & rh ) { + x -= rh.x; + y -= rh.y; + z -= rh.z; + + return *this; +} + +Vector3 Vector3::operator*( const float & rh) const { + Vector3 v(*this); + v *= rh; + return v; +} + +Vector3 & Vector3::operator*=( const float & rh) { + x *= rh; + y *= rh; + z *= rh; + + return *this; +} + +Vector3 Vector3::operator/( const float & rh ) const { + Vector3 v(*this); + v /= rh; + return v; +} + +Vector3 & Vector3::operator/=( const float & rh ) { + x /= rh; + y /= rh; + z /= rh; + + return *this; +} + +bool Vector3::operator==( const Vector3 & rh) const { + if (rh.x == x && rh.y == y && rh.z == z) + return true; + else + return false; +} + +float Vector3::DotProduct( const Vector3 & rh) const { + return x * rh.x + y * rh.y + z * rh.z; +} + +Vector3 Vector3::CrossProduct( const Vector3 & rh) const { + return Vector3( + y * rh.z - z * rh.y, //x + z * rh.x - x * rh.z, //y + x * rh.y - y * rh.x //z + ); +} + +//Vector3 Vector3::operator*( const Matrix44 & rh) const { +// return rh * (*this); +//} +// +//Vector & Vector3::operator*=( const Matrix44 & rh) { +// *this = rh * (*this); +// return *this; +//} + +/* + * Matrix33 Methods + */ + +Quaternion Matrix33::AsQuaternion() { + Quaternion quat; + float tr, s, q[4]; + int i, j, k; + + int nxt[3] = {1, 2, 0}; + + Matrix33 & m = *this; - float w = quat.w; - float x = quat.x; - float y = quat.y; - float z = quat.z; + // compute the trace of the matrix + tr = m[0][0] + m[1][1] + m[2][2]; + + // check if the trace is positive or negative + if (tr > 0.0) { + s = sqrt (tr + 1.0f); + quat.w = s / 2.0f; + s = 0.5f / s; + quat.x = (m[1][2] - m[2][1]) * s; + quat.y = (m[2][0] - m[0][2]) * s; + quat.z = (m[0][1] - m[1][0]) * s; + } + else { + // trace is negative + i = 0; + if ( m[1][1] > m[0][0]) + i = 1; + if ( m[2][2] > m[i][i] ) + i = 2; + j = nxt[i]; + k = nxt[j]; + + s = sqrt( ( m[i][i] - (m[j][j] + m[k][k]) ) + 1.0f ); + q[i] = s * 0.5f; + if (s != 0.0f) s = 0.5f / s; + q[3] = (m[j][k] - m[k][j]) * s; + q[j] = (m[i][j] + m[j][i]) * s; + q[k] = (m[i][k] + m[k][i]) * s; + quat.x = q[0]; + quat.y= q[1]; + quat.z = q[2]; + quat.w = q[3]; + } + + return quat; +} + +/* + * Matrix44 Methods + */ + +Matrix44::Matrix44() { + *this = IDENTITY44; +} + +/* + * Quaternion Methods + */ + +Float3 Quaternion::AsEulerYawPitchRoll() { + float yaw, pitch, roll; + + if ( x*y + z*w == 0.5 ) { + //North Pole + yaw = 2 * atan2(x,w); + pitch = asin(2*x*y + 2*z*w); + roll = 0.0f; + } + else if ( x*y + z*w == -0.5 ) { + //South Pole + yaw = -2 * atan2(x,w); + pitch = asin(2*x*y + 2*z*w); + roll = 0.0f; + } + else { + yaw = atan2(2*y*w-2*x*z , 1 - 2*y*y - 2*z*z); + pitch = asin(2*x*y + 2*z*w); + roll = atan2(2*x*w-2*y*z , 1 - 2*x*x - 2*z*z); + } + + return Float3( yaw, pitch, roll ); +} + +Matrix33 Quaternion::AsMatrix() { + Matrix33 m; float w2 = w * w; float x2 = x * x; @@ -236,65 +374,76 @@ void QuatToMatrix( Quaternion const & quat, ostream & out ) { m[2][1] = 2.0f*y*z + 2.0f*w*x; m[2][2] = w2 - x2 - y2 + z2; + return m; + + //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; + + //float pi = 3.141592653589793f; + //out << " Euler Angles:" << endl + // << " X: " << atan2( m[1][2], m[2][2] ) / pi * 180.0 << endl + // << " Y: " << asin( -m[0][2] ) / pi * 180.0 << endl + // << " Z: " << atan2( m[0][1], m[0][0] ) / pi * 180.0 << endl; +} + +/* + * ostream functions for printing with cout + */ + +ostream & operator<<( ostream & out, TexCoord const & val ) { + return out << "(" << setw(6) << val.u << "," << setw(6) << val.v << ")"; +} + +ostream & operator<<( ostream & out, Triangle const & val ) { + return out << "{" << setw(6) << val.v1 << "," << setw(6) << val.v2 << "," << setw(6) << val.v3 << "}"; +} + +ostream & operator<<( ostream & out, Vector3 const & val ) { + return out << "(" << setw(6) << val.x << "," << setw(6) << val.y << "," << setw(6) << val.z << ")"; +} + +ostream & operator<<( ostream & out, Float2 const & val ) { + return out << "{" << setw(6) << val.data[0] << "," << setw(6) << val.data[1] << "}"; +} + +ostream & operator<<( ostream & out, Matrix22 const & val ) { 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; - - float pi = 3.141592653589793f; - out << " Euler Angles:" << endl - << " X: " << atan2( m[1][2], m[2][2] ) / pi * 180.0 << endl - << " Y: " << asin( -m[0][2] ) / pi * 180.0 << endl - << " Z: " << atan2( m[0][1], m[0][0] ) / pi * 180.0 << endl; -} - -void QuatToEuler( Quaternion const & quat, ostream & out ) { - float w = quat.w; - float x = quat.x; - float y = quat.y; - float z = quat.z; - -//heading = atan2(2*qy*qw-2*qx*qz , 1 - 2*qy2 - 2*qz2) -//attitude = asin(2*qx*qy + 2*qz*qw) -//bank = atan2(2*qx*qw-2*qy*qz , 1 - 2*qx2 - 2*qz2) -// -//except when qx*qy + qz*qw = 0.5 (north pole) -//which gives: -//heading = 2 * atan2(x,w) -//bank = 0 -//and when qx*qy + qz*qw = -0.5 (south pole) -//which gives: -//heading = -2 * atan2(x,w) -//bank = 0 - - float h, a, b; - float pi = 3.141592653589793f; + << " |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << " |" << endl + << " |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << " |"; + return out; +} - if ( x*y + z*w == 0.5 ) { - //North Pole - h = 2 * atan2(x,w); - a = asin(2*x*y + 2*z*w); - b = 0.0f; - } - else if ( x*y + z*w == -0.5 ) { - //South Pole - h = -2 * atan2(x,w); - a = asin(2*x*y + 2*z*w); - b = 0.0f; - } - else { - h = atan2(2*y*w-2*x*z , 1 - 2*y*y - 2*z*z); - a = asin(2*x*y + 2*z*w); - b = atan2(2*x*w-2*y*z , 1 - 2*x*x - 2*z*z); - } +ostream & operator<<( ostream & out, Float3 const & val ) { + return out << "{" << setw(6) << val.data[0] << "," << setw(6) << val.data[1] << "," << setw(6) << val.data[2] << "}"; +} - h = h / pi * 180; - a = a / pi * 180; - b = b / pi * 180; +ostream & operator<<( ostream & out, Matrix33 const & val ) { + out << endl + << " |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << "," << setw(6) << val[0][2] << " |" << endl + << " |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << "," << setw(6) << val[1][2] << " |" << endl + << " |" << setw(6) << val[2][0] << "," << setw(6) << val[2][1] << "," << setw(6) << val[2][2] << " |"; + return out; +} + +ostream & operator<<( ostream & out, Float4 const & val ) { + return out << "{" << setw(6) << val.data[0] << "," << setw(6) << val.data[1] << "," << setw(6) << val.data[2] << "," << setw(6) << val.data[3] << "}"; +} +ostream & operator<<( ostream & out, Matrix44 const & val ) { out << endl - << " Heading: " << h << endl - << " Attitude: " << a << endl - << " Bank: " << b << endl; - + << " |" << setw(6) << val[0][0] << "," << setw(6) << val[0][1] << "," << setw(6) << val[0][2] << "," << setw(6) << val[0][3] << " |" << endl + << " |" << setw(6) << val[1][0] << "," << setw(6) << val[1][1] << "," << setw(6) << val[1][2] << "," << setw(6) << val[1][3] << " |" << endl + << " |" << setw(6) << val[2][0] << "," << setw(6) << val[2][1] << "," << setw(6) << val[2][2] << "," << setw(6) << val[2][3] << " |" << endl + << " |" << setw(6) << val[3][0] << "," << setw(6) << val[3][1] << "," << setw(6) << val[3][2] << "," << setw(6) << val[3][3] << " |"; + return out; +} + +ostream & operator<<( ostream & out, Color4 const & val ) { + return out << "R:" << setw(6) << val.r << " G:" << setw(6) << val.g << " B:" << setw(6) << val.b << " A:" << setw(6) << val.a << "}"; +} + +ostream & operator<<( ostream & out, Quaternion const & val ) { + return out << "[" << setw(6) << val.w << ",(" << setw(6) << val.x << "," << setw(6) << val.y << "," << setw(6) << val.z << ")]"; } diff --git a/nif_math.h b/nif_math.h index 8d30a887..7642c4e5 100644 --- a/nif_math.h +++ b/nif_math.h @@ -36,17 +36,734 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <cmath> #include <iostream> -#include "niflib.h" -#include "NIF_IO.h" +//#include "NIF_IO.h" using namespace std; -//struct Quat { -// float w, x, y, z; -//}; +#ifndef PI +#define PI 3.14159265358979323846f +#endif + +//Forward declarations +struct TexCoord; +struct Triangle; +struct Vector3; +struct Color4; +struct Quaternion; +struct Float2; +struct Matrix22; +struct Float3; +struct Matrix33; +struct Float4; +struct Matrix44; + +/*! Stores 2D texture coordinates – two floating point variables, u and v. */ +struct TexCoord { + float u; /*!< The U value in this coordinate pair. */ + float v; /*!< The V value in this coordinate pair. */ + + /*! Default constructor */ + TexCoord() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param u The value to set U to. + * \param v The value to set V to. + */ + TexCoord(float u, float v) { + this->u = u; + this->v = v; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param u The value to set U to. + * \param v The value to set V to. + */ + void Set(float u, float v) { + this->u = u; + this->v = v; + } +}; + +/*! Represents a triangle face formed between three vertices referenced by number */ +struct Triangle { + short v1; /*!< The index of the first vertex. */ + short v2; /*!< The index of the second vertex. */ + short v3; /*!< The index of the third vertex. */ + + /*! Default constructor */ + Triangle() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param v1 The index of the first vertex. + * \param v2 The index of the second vertex. + * \param v3 The index of the third vertex. + */ + Triangle(short v1, short v2, short v3) { + this->v1 = v1; + this->v2 = v2; + this->v3 = v3; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param v1 The index of the first vertex. + * \param v2 The index of the second vertex. + * \param v3 The index of the third vertex. + */ + void Set(short v1, short v2, short v3) { + this->v1 = v1; + this->v2 = v2; + this->v3 = v3; + } + + /*! The bracket operator makes it possible to use this structure like a C++ array. + * \param n The index into the data array. Should be 0, 1, or 2. + * \return The value at the given array index by reference so it can be read or set via the bracket operator. + */ + short & operator[](int n) { + switch (n) { + case 0: return v1; break; + case 1: return v2; break; + case 2: return v3; break; + default: throw std::out_of_range("Index out of range for Triangle"); + }; + } + short operator[](int n) const { + switch (n) { + case 0: return v1; break; + case 1: return v2; break; + case 2: return v3; break; + default: throw std::out_of_range("Index out of range for Triangle"); + }; + } +}; + +/*!Represents a position or direction in 3D space*/ +struct Vector3 { + float x; /*!< The X component of this vector. */ + float y; /*!< The Y component of this vector. */ + float z; /*!< The Z component of this vector. */ + + /*!Default constructor.*/ + Vector3() { x = y = z = 0.0f; } + + /*! This constructor can be used to set all values in this structure during initialization + * \param x The value to set X to. + * \param y The value to set Y to. + * \param z The value to set Z to. + */ + Vector3(float x, float y, float z) { + this->x = x; + this->y = y; + this->z = z; + } + + /*! This constructor can be used to initialize this Vector3 with another Vector3 + * \param v The Vector3 to construct this one from + */ + Vector3( const Vector3 & v) { x = v.x; y = v.y; z = v.z; } + + /*! Destructor */ + ~Vector3() {} + + /*! This function can be used to set all values in the structure at the same time. + * \param x The value to set X to. + * \param y The value to set Y to. + * \param z The value to set Z to. + */ + void Set(float x, float y, float z) { + this->x = x; + this->y = y; + this->z = z; + } + + /* This function calculates the magnitude of this vector + * \return the magnitude of the vector; its length. + */ + float Magnitude() const; + + /* This function returns a normalization of this vector. A vecctor pointing in the same + * direction but with a magnitude, or length, of 1. + */ + Vector3 Normalized() const; + + /* Allows the addition of vectors. Each component, x, y, y, is added with + * the same component of the other vector. + * \return The result of the addition. + */ + Vector3 operator+( const Vector3 & rh ) const; + + /* Adds the two vectors and then sets the result to the left-hand vector. + * \return This vector is returned. + */ + Vector3 & operator+=( const Vector3 & rh ); + + /* Allows the subtraction of vectors. Each component, x, y, y, is subtracted from + * the same component of the other vector. + * \return The result of the subtraction. + */ + Vector3 operator-( const Vector3 & rh ) const; + + /* This operator subtracts the two vectors and then sets the result to the left-hand vector. + * \return This vector is returned. + */ + Vector3 & operator-=( const Vector3 & rh); + + /* Allows scaler multiplication, that is multipying all components of the + * vector, x, y and z, by the same number. + * \return The result of the multiplication. + */ + Vector3 operator*( const float & rh) const; //Scalar Multiply + + /* Multipies a vector by a scalar and then sets the result to the left-hand vector. + * \return This vector is returned. + */ + Vector3 & operator*=( const float & rh ); + + /* Allows scaler division, that is dividing all components of the + * vector, x, y and z, by the same number. + * \return The result of the division. + */ + Vector3 operator/( const float & rh ) const; + + /* Divides a vector by a scalar and then sets the result to the left-hand vector. + * \return This vector is returned. + */ + Vector3 & operator/=( const float & rh ); + + /* Sets the components of this Vector3 to those of another Vector3 + * \return This vector is returned. + */ + Vector3 & operator=( const Vector3 & v ) { x = v.x; y = v.y; z = v.z; return *this; } + + /* Tests the equality of two Vector3 structures. Vectors are considered equal if all + * three components are equal. + */ + bool operator==( const Vector3 & rh ) const; + + /* Computes the dot product of two vectors; the angle between two vectors. + * \param rh The vector to perform the dot product with + * \return The angle in radians between this vector and the one given + */ + float DotProduct( const Vector3 & rh ) const; + + /* Computes the cross product of two vectors; a vector perpendicular to both of them. + * \param The vector to perform the cross product with + * \return A vector perpendicular to this vector and the one given + */ + Vector3 CrossProduct( const Vector3 & rh) const; //Cross Product + + + ///* Multiplies this Vector with a 4x4 matrix + // * \param The 4x4 matrix to multiply this vector with. + // * \return The new vector resulting from the multiplication. + // */ + //Vector3 operator*( const Matrix44 & rh ) const; + + ///* Multiplies this Vector with a 4x4 matrix and sets the result to itself + // * \param The 4x4 matrix to multiply this vector with. + // * \return This vector is returned. + // */ + //Vector3 & operator*=( const Matrix44 & rh ); + + friend ostream & operator<<( ostream & out, const Vector3 & rh ); +}; + +/* Stores two floating point numbers. Used as a row of a Matrix22 */ +struct Float2 { + float data[2]; /*!< The two floating point numbers stored as an array. */ + + /*! The bracket operator makes it possible to use this structure like a C++ array. + * \param n The index into the data array. Should be 0 or 1. + * \return The value at the given array index by reference so it can be read or set via the bracket operator. + */ + float & operator[](int n) { + return data[n]; + } + float operator[](int n) const { + return data[n]; + } + + /*! Default constructor. */ + Float2() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param f1 The value to set the first floating point number to. + * \param f2 The value to set the second floating point number to. + */ + Float2( float f1, float f2 ) { + data[0] = f1; + data[1] = f2; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param f1 The value to set the first floating point number to. + * \param f2 The value to set the second floating point number to. + */ + void Set( float f1, float f2 ) { + data[0] = f1; + data[1] = f2; + } + + //Python Operator Overloads + float __getitem__(int n) { + if (n > 1 || n < 0) + throw std::out_of_range("Index out of range for MatrixRow3"); + return data[n]; + } + void __setitem__(int n, float value) { + if (n > 1 || n < 0) + throw std::out_of_range("Index out of range for MatrixRow3"); + data[n] = value; + } +}; + +/*! Stores a 2 by 2 matrix used for bump maps. */ +struct Matrix22 { + Float2 rows[2]; /*!< The two rows of Float2 structures which hold two floating point numbers each. */ + + /*! The bracket operator makes it possible to use this structure like a 2x2 C++ array. + * \param n The index into the row array. Should be 0 or 1. + * \return The Float2 structure for the given row index by reference so it can be read or set via the bracket operator. + */ + Float2 & operator[](int n) { + return rows[n]; + } + const Float2 & operator[](int n) const { + return rows[n]; + } + + /*! Default Constructor */ + Matrix22() {} + + /*! This constructor can be used to set all values in this matrix during initialization + * \param m11 The value to set at row 1, column 1. + * \param m12 The value to set at row 1, column 2. + * \param m21 The value to set at row 2, column 1. + * \param m22 The value to set at row 2, column 2. + */ + Matrix22( + float m11, float m12, + float m21, float m22 + ) { + rows[0][0] = m11; rows[0][1] = m12; + rows[1][0] = m21; rows[1][1] = m22; + } + + /*! This function can be used to set all values in this matrix at the same time. + * \param m11 The value to set at row 1, column 1. + * \param m12 The value to set at row 1, column 2. + * \param m21 The value to set at row 2, column 1. + * \param m22 The value to set at row 2, column 2. + */ + void Set( + float m11, float m12, + float m21, float m22 + ) { + rows[0][0] = m11; rows[0][1] = m12; + rows[1][0] = m21; rows[1][1] = m22; + } + + Quaternion AsQuaternion(); + + //Python Operator Overloads + Float2 & __getitem__(int n) { + if (n > 1 || n < 0) + throw std::out_of_range("Index out of range for MatrixRow3"); + return rows[n]; + } +}; + +/* Stores three floating point numbers. Used as a row of a Matrix33 and to store the data in attr_vector3 and attr_color3 type attributes. */ +struct Float3 { + float data[3]; /*!< The three floating point numbers stored as an array. */ + + /*! The bracket operator makes it possible to use this structure like a C++ array. + * \param n The index into the data array. Should be 0, 1, or 2. + * \return The value at the given array index by reference so it can be read or set via the bracket operator. + */ + float & operator[](int n) { + return data[n]; + } + float operator[](int n) const { + return data[n]; + } + + /*!Default constructor.*/ + Float3() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param f1 The value to set the first floating point number to. + * \param f2 The value to set the second floating point number to. + * \param f3 The value to set the third floating point number to. + */ + Float3( float f1, float f2, float f3 ) { + data[0] = f1; + data[1] = f2; + data[2] = f3; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param f1 The value to set the first floating point number to. + * \param f2 The value to set the second floating point number to. + * \param f3 The value to set the third floating point number to. + */ + void Set( float f1, float f2, float f3 ) { + data[0] = f1; + data[1] = f2; + data[2] = f3; + } + + //Python Operator Overloads + float __getitem__(int n) { + if (n > 2 || n < 0) + throw std::out_of_range("Index out of range for Float3"); + return data[n]; + } + void __setitem__(int n, float value) { + if (n > 2 || n < 0) + throw std::out_of_range("Index out of range for Float3"); + data[n] = value; + } +}; + +/*! Stores a 3 by 3 matrix used for rotation. */ +struct Matrix33 { + Float3 rows[3]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ + + /*! The bracket operator makes it possible to use this structure like a 3x3 C++ array. + * \param n The index into the row array. Should be 0, 1, or 2. + * \return The Float3 structure for the given row index by reference so it can be read or set via the bracket operator. + */ + Float3 & operator[](int n) { + return rows[n]; + } + const Float3 & operator[](int n) const { + return rows[n]; + } + + /*! Default constructor. */ + Matrix33() {} + + /*! This constructor can be used to set all values in this matrix during initialization + * \param m11 The value to set at row 1, column 1. + * \param m12 The value to set at row 1, column 2. + * \param m13 The value to set at row 1, column 3. + * \param m21 The value to set at row 2, column 1. + * \param m22 The value to set at row 2, column 2. + * \param m23 The value to set at row 2, column 3. + * \param m31 The value to set at row 3, column 1. + * \param m32 The value to set at row 3, column 2. + * \param m33 The value to set at row 3, column 3. + */ + Matrix33( + float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33 + ) { + rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; + rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; + rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; + } + + /*! This function can be used to set all values in this matrix at the same time. + * \param m11 The value to set at row 1, column 1. + * \param m12 The value to set at row 1, column 2. + * \param m13 The value to set at row 1, column 3. + * \param m21 The value to set at row 2, column 1. + * \param m22 The value to set at row 2, column 2. + * \param m23 The value to set at row 2, column 3. + * \param m31 The value to set at row 3, column 1. + * \param m32 The value to set at row 3, column 2. + * \param m33 The value to set at row 3, column 3. + */ + void Set( + float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33 + ) { + rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; + rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; + rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; + } + + Quaternion AsQuaternion(); + + void AsFloatArr( float out[3][3] ) { + out[0][0] = rows[0][0]; out[0][1] = rows[0][1]; out[0][2] = rows[0][2]; + out[1][0] = rows[1][0]; out[1][1] = rows[1][1]; out[1][2] = rows[1][2]; + out[2][0] = rows[2][0]; out[2][1] = rows[2][1]; out[2][2] = rows[2][2]; + } + + //Python Operator Overloads + Float3 & __getitem__(int n) { + if (n > 2 || n < 0) + throw std::out_of_range("Index out of range for MatrixRow3"); + return rows[n]; + } +}; + +/* Stores four floating point numbers. Used as a row of a Matrix44. */ +struct Float4 { + float data[4]; /*!< The four floating point numbers stored as an array. */ + + /*! The bracket operator makes it possible to use this structure like a C++ array. + * \param n The index into the data array. Should be 0, 1, 2, or 3. + * \return The value at the given array index by reference so it can be read or set via the bracket operator. + */ + float & operator[](int n) { + return data[n]; + } + float operator[](int n) const { + return data[n]; + } + + /*! Default Constructor.*/ + Float4() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param f1 The value to set the first floating point number to. + * \param f2 The value to set the second floating point number to. + * \param f3 The value to set the third floating point number to. + * \param f4 The value to set the fourth floating point number to. + */ + Float4( float f1, float f2, float f3, float f4 ) { + data[0] = f1; + data[1] = f2; + data[3] = f3; + data[4] = f4; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param f1 The value to set the first floating point number to. + * \param f2 The value to set the second floating point number to. + * \param f3 The value to set the third floating point number to. + * \param f4 The value to set the fourth floating point number to. + */ + void Set( float f1, float f2, float f3, float f4 ) { + data[0] = f1; + data[1] = f2; + data[3] = f3; + data[4] = f4; + } + + //Python Operator Overloads + float __getitem__(int n) { + if (n > 3 || n < 0) + throw std::out_of_range("Index out of range for Float4"); + return data[n]; + } + void __setitem__(int n, float value) { + if (n > 3 || n < 0) + throw std::out_of_range("Index out of range for Float4"); + data[n] = value; + } +}; + +/*! Stores a 4 by 4 matrix used for combined transformations. */ +struct Matrix44 { + Float4 rows[4]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ + + /*! The bracket operator makes it possible to use this structure like a 4x4 C++ array. + * \param n The index into the row array. Should be 0, 1, 2, or 3. + * \return The Float4 structure for the given row index by reference so it can be read or set via the bracket operator. + */ + Float4 & operator[](int n) { + return rows[n]; + } + Float4 const & operator[](int n) const { + return rows[n]; + } + + /*! Default constructor. Initializes Matrix to Identity. */ + Matrix44(); + + /*! Copy constructor. Initializes Matrix to another Matrix44. + * \param The matrix to initialize this one to. + */ + Matrix44( const Matrix44 & m ) { memcpy(rows, m.rows, sizeof(Float4) * 4); } + + /*! This constructor can be used to set all values in this matrix during initialization + * \param m11 The value to set at row 1, column 1. + * \param m12 The value to set at row 1, column 2. + * \param m13 The value to set at row 1, column 3. + * \param m14 The value to set at row 1, column 4. + * \param m21 The value to set at row 2, column 1. + * \param m22 The value to set at row 2, column 2. + * \param m23 The value to set at row 2, column 3. + * \param m24 The value to set at row 2, column 4. + * \param m31 The value to set at row 3, column 1. + * \param m32 The value to set at row 3, column 2. + * \param m33 The value to set at row 3, column 3. + * \param m34 The value to set at row 3, column 4. + * \param m41 The value to set at row 4, column 1. + * \param m42 The value to set at row 4, column 2. + * \param m43 The value to set at row 4, column 3. + * \param m44 The value to set at row 4, column 4. + */ + Matrix44( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44 + ) { + rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14; + rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24; + rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34; + rows[3][0] = m41; rows[3][1] = m42; rows[3][2] = m43; rows[3][3] = m44; + } + + /*! This function can be used to set all values in this matrix at the same time. + * \param m11 The value to set at row 1, column 1. + * \param m12 The value to set at row 1, column 2. + * \param m13 The value to set at row 1, column 3. + * \param m14 The value to set at row 1, column 4. + * \param m21 The value to set at row 2, column 1. + * \param m22 The value to set at row 2, column 2. + * \param m23 The value to set at row 2, column 3. + * \param m24 The value to set at row 2, column 4. + * \param m31 The value to set at row 3, column 1. + * \param m32 The value to set at row 3, column 2. + * \param m33 The value to set at row 3, column 3. + * \param m34 The value to set at row 3, column 4. + * \param m41 The value to set at row 4, column 1. + * \param m42 The value to set at row 4, column 2. + * \param m43 The value to set at row 4, column 3. + * \param m44 The value to set at row 4, column 4. + */ + void Set( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44 + ) { + rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14; + rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24; + rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34; + rows[3][0] = m41; rows[3][1] = m42; rows[3][2] = m43; rows[3][3] = m44; + } + + //undocumented + void AsFloatArr( float out[4][4] ) { + out[0][0] = rows[0][0]; out[0][1] = rows[0][1]; out[0][2] = rows[0][2]; out[0][3] = rows[0][3]; + out[1][0] = rows[1][0]; out[1][1] = rows[1][1]; out[1][2] = rows[1][2]; out[1][3] = rows[1][3]; + out[2][0] = rows[2][0]; out[2][1] = rows[2][1]; out[2][2] = rows[2][2]; out[2][3] = rows[2][3]; + out[3][0] = rows[3][0]; out[3][1] = rows[3][1]; out[3][2] = rows[3][2]; out[3][3] = rows[3][3]; + } + + //Python Operator Overloads + Float4 & __getitem__(int n) { + if (n > 3 || n < 0) + throw std::out_of_range("Index out of range for Matrix44"); + return rows[n]; + } +}; + +/*! The 4x4 identity matrix */ +const Matrix44 IDENTITY44( 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f ); + +/*! Stores a color along with alpha translucency */ +struct Color4 { + float r; /*!< The red component of this color. Should be between 0.0f and 1.0f. */ + float g; /*!< The green component of this color. Should be between 0.0f and 1.0f. */ + float b; /*!< The blue component of this color. Should be between 0.0f and 1.0f. */ + float a; /*!< The alpha translucency component of this color. Should be between 0.0f and 1.0f. */ + + /*! Default constructor */ + Color4() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param r The value to set the red component of this color to. Should be between 0.0f and 1.0f. + * \param g The value to set the green component of this color to. Should be between 0.0f and 1.0f. + * \param b The value to set the blue component of this color to. Should be between 0.0f and 1.0f. + * \param a The value to set the alpha translucency component of this color to. Should be between 0.0f and 1.0f. + */ + Color4(float r, float g, float b, float a = 1.0f) { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param r The value to set the red component of this color to. Should be between 0.0f and 1.0f. + * \param g The value to set the green component of this color to. Should be between 0.0f and 1.0f. + * \param b The value to set the blue component of this color to. Should be between 0.0f and 1.0f. + * \param a The value to set the alpha translucency component of this color to. Should be between 0.0f and 1.0f. + */ + void Set(float r, float g, float b, float a = 1.0f) { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + } +}; + +/*! Represents a quaternion - a 4D extention of complex numbers used as an alternitive to matrices to represent rotation.*/ +struct Quaternion { + float w; /*!< The W scalar component of this Quaternion. */ + float x; /*!< The X vector component of this Quaternion. */ + float y; /*!< The Y vector component of this Quaternion. */ + float z; /*!< The Z vector component of this Quaternion. */ + + /*! Default constructor. */ + Quaternion() {} + + /*! This constructor can be used to set all values in this structure during initialization + * \param w The value to set the W scalar component of this quaternion to. + * \param x The value to set the X vector component of this quaternion to. + * \param y The value to set the Y vector component of this quaternion to. + * \param z The value to set the Z vector component of this quaternion to. + */ + Quaternion(float w, float x, float y, float z) { + this->w = w; + this->x = x; + this->y = y; + this->z = z; + } + + /*! This function can be used to set all values in the structure at the same time. + * \param w The value to set the W scalar component of this quaternion to. + * \param x The value to set the X vector component of this quaternion to. + * \param y The value to set the Y vector component of this quaternion to. + * \param z The value to set the Z vector component of this quaternion to. + */ + void Set(float w, float x, float y, float z) { + this->w = w; + this->x = x; + this->y = y; + this->z = z; + } + + /*! This function returns a 3x3 matrix representation of the rotation stored in this quaternion. + * \return a Matrix33 structure with an equivalent rotation to this quaternion. + */ + Matrix33 AsMatrix(); + + /*! This function returns a Euler Angle representation of the rotation stored in this quaternion. + * The angles returned correspond to yaw, pitch, and roll and are in radiens. + * \return a Float3 structure with the first value containing the yaw, the second the pitch, + * and the third the roll. The values are in radians. + */ + Float3 AsEulerYawPitchRoll(); +}; + +//--ostream functions for printing with cout--// + +ostream & operator<<( ostream & out, TexCoord const & val ); +ostream & operator<<( ostream & out, Triangle const & val ); +ostream & operator<<( ostream & out, Float2 const & val ); +ostream & operator<<( ostream & out, Matrix22 const & val ); +ostream & operator<<( ostream & out, Float3 const & val ); +ostream & operator<<( ostream & out, Matrix33 const & val ); +ostream & operator<<( ostream & out, Float4 const & val ); +ostream & operator<<( ostream & out, Matrix44 const & val ); +ostream & operator<<( ostream & out, Color4 const & val ); +ostream & operator<<( ostream & out, Quaternion const & val ); + + -void QuatToMatrix( Quaternion const & quat, ostream & out ); -void QuatToEuler( Quaternion const & quat, ostream & out ); -Vector3 MultVector3( Vector3 const & a, Vector3 const & b); Matrix33 MultMatrix33( Matrix33 const & a, Matrix33 const & b ); Matrix44 MultMatrix44( Matrix44 const & a, Matrix44 const & b ); float DetMatrix33( Matrix33 const & m ); @@ -57,6 +774,5 @@ 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 ); #endif diff --git a/niflib.h b/niflib.h index 46034722..8f04580c 100644 --- a/niflib.h +++ b/niflib.h @@ -47,6 +47,7 @@ POSSIBILITY OF SUCH DAMAGE. */ #include <vector> #include <list> #include <map> +#include "nif_math.h" using namespace std; //--Forward Declarations of Classes & Structs--// @@ -798,573 +799,6 @@ IPosData const * QueryPosData ( blk_ref const & block ); //--Simple Structures--// -/*! Stores 2D texture coordinates – two floating point variables, u and v. */ -struct TexCoord { - float u; /*!< The U value in this coordinate pair. */ - float v; /*!< The V value in this coordinate pair. */ - - /*! Default constructor */ - TexCoord() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param u The value to set U to. - * \param v The value to set V to. - */ - TexCoord(float u, float v) { - this->u = u; - this->v = v; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param u The value to set U to. - * \param v The value to set V to. - */ - void Set(float u, float v) { - this->u = u; - this->v = v; - } -}; - -/*! Represents a triangle face formed between three vertices referenced by number */ -struct Triangle { - short v1; /*!< The index of the first vertex. */ - short v2; /*!< The index of the second vertex. */ - short v3; /*!< The index of the third vertex. */ - - /*! Default constructor */ - Triangle() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param v1 The index of the first vertex. - * \param v2 The index of the second vertex. - * \param v3 The index of the third vertex. - */ - Triangle(short v1, short v2, short v3) { - this->v1 = v1; - this->v2 = v2; - this->v3 = v3; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param v1 The index of the first vertex. - * \param v2 The index of the second vertex. - * \param v3 The index of the third vertex. - */ - void Set(short v1, short v2, short v3) { - this->v1 = v1; - this->v2 = v2; - this->v3 = v3; - } - - /*! The bracket operator makes it possible to use this structure like a C++ array. - * \param n The index into the data array. Should be 0, 1, or 2. - * \return The value at the given array index by reference so it can be read or set via the bracket operator. - */ - short & operator[](int n) { - switch (n) { - case 0: return v1; break; - case 1: return v2; break; - case 2: return v3; break; - default: throw std::out_of_range("Index out of range for Triangle"); - }; - } - short operator[](int n) const { - switch (n) { - case 0: return v1; break; - case 1: return v2; break; - case 2: return v3; break; - default: throw std::out_of_range("Index out of range for Triangle"); - }; - } -}; - -/*!Represents a position or direction in 3D space*/ -struct Vector3 { - float x; /*!< The X component of this vector. */ - float y; /*!< The Y component of this vector. */ - float z; /*!< The Z component of this vector. */ - - /*!Default constructor.*/ - Vector3() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param x The value to set X to. - * \param y The value to set Y to. - * \param z The value to set Z to. - */ - Vector3(float x, float y, float z) { - this->x = x; - this->y = y; - this->z = z; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param x The value to set X to. - * \param y The value to set Y to. - * \param z The value to set Z to. - */ - void Set(float x, float y, float z) { - this->x = x; - this->y = y; - this->z = z; - } -}; - -/* Stores two floating point numbers. Used as a row of a Matrix22 */ -struct Float2 { - float data[2]; /*!< The two floating point numbers stored as an array. */ - - /*! The bracket operator makes it possible to use this structure like a C++ array. - * \param n The index into the data array. Should be 0 or 1. - * \return The value at the given array index by reference so it can be read or set via the bracket operator. - */ - float & operator[](int n) { - return data[n]; - } - float operator[](int n) const { - return data[n]; - } - - /*! Default constructor. */ - Float2() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param f1 The value to set the first floating point number to. - * \param f2 The value to set the second floating point number to. - */ - Float2( float f1, float f2 ) { - data[0] = f1; - data[1] = f2; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param f1 The value to set the first floating point number to. - * \param f2 The value to set the second floating point number to. - */ - void Set( float f1, float f2 ) { - data[0] = f1; - data[1] = f2; - } - - //Python Operator Overloads - float __getitem__(int n) { - if (n > 1 || n < 0) - throw std::out_of_range("Index out of range for MatrixRow3"); - return data[n]; - } - void __setitem__(int n, float value) { - if (n > 1 || n < 0) - throw std::out_of_range("Index out of range for MatrixRow3"); - data[n] = value; - } -}; - -/*! Stores a 2 by 2 matrix used for bump maps. */ -struct Matrix22 { - Float2 rows[2]; /*!< The two rows of Float2 structures which hold two floating point numbers each. */ - - /*! The bracket operator makes it possible to use this structure like a 2x2 C++ array. - * \param n The index into the row array. Should be 0 or 1. - * \return The Float2 structure for the given row index by reference so it can be read or set via the bracket operator. - */ - Float2 & operator[](int n) { - return rows[n]; - } - const Float2 & operator[](int n) const { - return rows[n]; - } - - /*! Default Constructor */ - Matrix22() {} - - /*! This constructor can be used to set all values in this matrix during initialization - * \param m11 The value to set at row 1, column 1. - * \param m12 The value to set at row 1, column 2. - * \param m21 The value to set at row 2, column 1. - * \param m22 The value to set at row 2, column 2. - */ - Matrix22( - float m11, float m12, - float m21, float m22 - ) { - rows[0][0] = m11; rows[0][1] = m12; - rows[1][0] = m21; rows[1][1] = m22; - } - - /*! This function can be used to set all values in this matrix at the same time. - * \param m11 The value to set at row 1, column 1. - * \param m12 The value to set at row 1, column 2. - * \param m21 The value to set at row 2, column 1. - * \param m22 The value to set at row 2, column 2. - */ - void Set( - float m11, float m12, - float m21, float m22 - ) { - rows[0][0] = m11; rows[0][1] = m12; - rows[1][0] = m21; rows[1][1] = m22; - } - - //Python Operator Overloads - Float2 & __getitem__(int n) { - if (n > 1 || n < 0) - throw std::out_of_range("Index out of range for MatrixRow3"); - return rows[n]; - } -}; - -/* Stores three floating point numbers. Used as a row of a Matrix33 and to store the data in attr_vector3 and attr_color3 type attributes. */ -struct Float3 { - float data[3]; /*!< The three floating point numbers stored as an array. */ - - /*! The bracket operator makes it possible to use this structure like a C++ array. - * \param n The index into the data array. Should be 0, 1, or 2. - * \return The value at the given array index by reference so it can be read or set via the bracket operator. - */ - float & operator[](int n) { - return data[n]; - } - float operator[](int n) const { - return data[n]; - } - - /*!Default constructor.*/ - Float3() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param f1 The value to set the first floating point number to. - * \param f2 The value to set the second floating point number to. - * \param f3 The value to set the third floating point number to. - */ - Float3( float f1, float f2, float f3 ) { - data[0] = f1; - data[1] = f2; - data[2] = f3; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param f1 The value to set the first floating point number to. - * \param f2 The value to set the second floating point number to. - * \param f3 The value to set the third floating point number to. - */ - void Set( float f1, float f2, float f3 ) { - data[0] = f1; - data[1] = f2; - data[2] = f3; - } - - //Python Operator Overloads - float __getitem__(int n) { - if (n > 2 || n < 0) - throw std::out_of_range("Index out of range for Float3"); - return data[n]; - } - void __setitem__(int n, float value) { - if (n > 2 || n < 0) - throw std::out_of_range("Index out of range for Float3"); - data[n] = value; - } -}; - -/*! Stores a 3 by 3 matrix used for rotation. */ -struct Matrix33 { - Float3 rows[3]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ - - /*! The bracket operator makes it possible to use this structure like a 3x3 C++ array. - * \param n The index into the row array. Should be 0, 1, or 2. - * \return The Float3 structure for the given row index by reference so it can be read or set via the bracket operator. - */ - Float3 & operator[](int n) { - return rows[n]; - } - const Float3 & operator[](int n) const { - return rows[n]; - } - - /*! Default constructor. */ - Matrix33() {} - - /*! This constructor can be used to set all values in this matrix during initialization - * \param m11 The value to set at row 1, column 1. - * \param m12 The value to set at row 1, column 2. - * \param m13 The value to set at row 1, column 3. - * \param m21 The value to set at row 2, column 1. - * \param m22 The value to set at row 2, column 2. - * \param m23 The value to set at row 2, column 3. - * \param m31 The value to set at row 3, column 1. - * \param m32 The value to set at row 3, column 2. - * \param m33 The value to set at row 3, column 3. - */ - Matrix33( - float m11, float m12, float m13, - float m21, float m22, float m23, - float m31, float m32, float m33 - ) { - rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; - rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; - rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; - } - - /*! This function can be used to set all values in this matrix at the same time. - * \param m11 The value to set at row 1, column 1. - * \param m12 The value to set at row 1, column 2. - * \param m13 The value to set at row 1, column 3. - * \param m21 The value to set at row 2, column 1. - * \param m22 The value to set at row 2, column 2. - * \param m23 The value to set at row 2, column 3. - * \param m31 The value to set at row 3, column 1. - * \param m32 The value to set at row 3, column 2. - * \param m33 The value to set at row 3, column 3. - */ - void Set( - float m11, float m12, float m13, - float m21, float m22, float m23, - float m31, float m32, float m33 - ) { - rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; - rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; - rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; - } - - void AsFloatArr( float out[3][3] ) { - out[0][0] = rows[0][0]; out[0][1] = rows[0][1]; out[0][2] = rows[0][2]; - out[1][0] = rows[1][0]; out[1][1] = rows[1][1]; out[1][2] = rows[1][2]; - out[2][0] = rows[2][0]; out[2][1] = rows[2][1]; out[2][2] = rows[2][2]; - } - - //Python Operator Overloads - Float3 & __getitem__(int n) { - if (n > 2 || n < 0) - throw std::out_of_range("Index out of range for MatrixRow3"); - return rows[n]; - } -}; - -/* Stores four floating point numbers. Used as a row of a Matrix44. */ -struct Float4 { - float data[4]; /*!< The four floating point numbers stored as an array. */ - - /*! The bracket operator makes it possible to use this structure like a C++ array. - * \param n The index into the data array. Should be 0, 1, 2, or 3. - * \return The value at the given array index by reference so it can be read or set via the bracket operator. - */ - float & operator[](int n) { - return data[n]; - } - float operator[](int n) const { - return data[n]; - } - - /*! Default Constructor.*/ - Float4() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param f1 The value to set the first floating point number to. - * \param f2 The value to set the second floating point number to. - * \param f3 The value to set the third floating point number to. - * \param f4 The value to set the fourth floating point number to. - */ - Float4( float f1, float f2, float f3, float f4 ) { - data[0] = f1; - data[1] = f2; - data[3] = f3; - data[4] = f4; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param f1 The value to set the first floating point number to. - * \param f2 The value to set the second floating point number to. - * \param f3 The value to set the third floating point number to. - * \param f4 The value to set the fourth floating point number to. - */ - void Set( float f1, float f2, float f3, float f4 ) { - data[0] = f1; - data[1] = f2; - data[3] = f3; - data[4] = f4; - } - - //Python Operator Overloads - float __getitem__(int n) { - if (n > 3 || n < 0) - throw std::out_of_range("Index out of range for Float4"); - return data[n]; - } - void __setitem__(int n, float value) { - if (n > 3 || n < 0) - throw std::out_of_range("Index out of range for Float4"); - data[n] = value; - } -}; - -/*! Stores a 4 by 4 matrix used for combined transformations. */ -struct Matrix44 { - Float4 rows[4]; /*!< The three rows of Float3 structures which hold three floating point numbers each. */ - - /*! The bracket operator makes it possible to use this structure like a 4x4 C++ array. - * \param n The index into the row array. Should be 0, 1, 2, or 3. - * \return The Float4 structure for the given row index by reference so it can be read or set via the bracket operator. - */ - Float4 & operator[](int n) { - return rows[n]; - } - Float4 const & operator[](int n) const { - return rows[n]; - } - - /*! Default constructor. */ - Matrix44() {} - - /*! This constructor can be used to set all values in this matrix during initialization - * \param m11 The value to set at row 1, column 1. - * \param m12 The value to set at row 1, column 2. - * \param m13 The value to set at row 1, column 3. - * \param m14 The value to set at row 1, column 4. - * \param m21 The value to set at row 2, column 1. - * \param m22 The value to set at row 2, column 2. - * \param m23 The value to set at row 2, column 3. - * \param m24 The value to set at row 2, column 4. - * \param m31 The value to set at row 3, column 1. - * \param m32 The value to set at row 3, column 2. - * \param m33 The value to set at row 3, column 3. - * \param m34 The value to set at row 3, column 4. - * \param m41 The value to set at row 4, column 1. - * \param m42 The value to set at row 4, column 2. - * \param m43 The value to set at row 4, column 3. - * \param m44 The value to set at row 4, column 4. - */ - Matrix44( - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44 - ) { - rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14; - rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24; - rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34; - rows[3][0] = m41; rows[3][1] = m42; rows[3][2] = m43; rows[3][3] = m44; - } - - /*! This function can be used to set all values in this matrix at the same time. - * \param m11 The value to set at row 1, column 1. - * \param m12 The value to set at row 1, column 2. - * \param m13 The value to set at row 1, column 3. - * \param m14 The value to set at row 1, column 4. - * \param m21 The value to set at row 2, column 1. - * \param m22 The value to set at row 2, column 2. - * \param m23 The value to set at row 2, column 3. - * \param m24 The value to set at row 2, column 4. - * \param m31 The value to set at row 3, column 1. - * \param m32 The value to set at row 3, column 2. - * \param m33 The value to set at row 3, column 3. - * \param m34 The value to set at row 3, column 4. - * \param m41 The value to set at row 4, column 1. - * \param m42 The value to set at row 4, column 2. - * \param m43 The value to set at row 4, column 3. - * \param m44 The value to set at row 4, column 4. - */ - void Set( - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44 - ) { - rows[0][0] = m11; rows[0][1] = m12; rows[0][2] = m13; rows[0][3] = m14; - rows[1][0] = m21; rows[1][1] = m22; rows[1][2] = m23; rows[1][3] = m24; - rows[2][0] = m31; rows[2][1] = m32; rows[2][2] = m33; rows[2][3] = m34; - rows[3][0] = m41; rows[3][1] = m42; rows[3][2] = m43; rows[3][3] = m44; - } - - //undocumented - void AsFloatArr( float out[4][4] ) { - out[0][0] = rows[0][0]; out[0][1] = rows[0][1]; out[0][2] = rows[0][2]; out[0][3] = rows[0][3]; - out[1][0] = rows[1][0]; out[1][1] = rows[1][1]; out[1][2] = rows[1][2]; out[1][3] = rows[1][3]; - out[2][0] = rows[2][0]; out[2][1] = rows[2][1]; out[2][2] = rows[2][2]; out[2][3] = rows[2][3]; - out[3][0] = rows[3][0]; out[3][1] = rows[3][1]; out[3][2] = rows[3][2]; out[3][3] = rows[3][3]; - } - - //Python Operator Overloads - Float4 & __getitem__(int n) { - if (n > 3 || n < 0) - throw std::out_of_range("Index out of range for Matrix44"); - return rows[n]; - } -}; - -/*! Stores a color along with alpha translucency */ -struct Color4 { - float r; /*!< The red component of this color. Should be between 0.0f and 1.0f. */ - float g; /*!< The green component of this color. Should be between 0.0f and 1.0f. */ - float b; /*!< The blue component of this color. Should be between 0.0f and 1.0f. */ - float a; /*!< The alpha translucency component of this color. Should be between 0.0f and 1.0f. */ - - /*! Default constructor */ - Color4() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param r The value to set the red component of this color to. Should be between 0.0f and 1.0f. - * \param g The value to set the green component of this color to. Should be between 0.0f and 1.0f. - * \param b The value to set the blue component of this color to. Should be between 0.0f and 1.0f. - * \param a The value to set the alpha translucency component of this color to. Should be between 0.0f and 1.0f. - */ - Color4(float r, float g, float b, float a = 1.0f) { - this->r = r; - this->g = g; - this->b = b; - this->a = a; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param r The value to set the red component of this color to. Should be between 0.0f and 1.0f. - * \param g The value to set the green component of this color to. Should be between 0.0f and 1.0f. - * \param b The value to set the blue component of this color to. Should be between 0.0f and 1.0f. - * \param a The value to set the alpha translucency component of this color to. Should be between 0.0f and 1.0f. - */ - void Set(float r, float g, float b, float a = 1.0f) { - this->r = r; - this->g = g; - this->b = b; - this->a = a; - } -}; - -/*! Represents a quaternion - a 4D extention of complex numbers used as an alternitive to matrices to represent rotation.*/ -struct Quaternion { - float w; /*!< The W scalar component of this Quaternion. */ - float x; /*!< The X vector component of this Quaternion. */ - float y; /*!< The Y vector component of this Quaternion. */ - float z; /*!< The Z vector component of this Quaternion. */ - - /*! Default constructor. */ - Quaternion() {} - - /*! This constructor can be used to set all values in this structure during initialization - * \param w The value to set the W scalar component of this quaternion to. - * \param x The value to set the X vector component of this quaternion to. - * \param y The value to set the Y vector component of this quaternion to. - * \param z The value to set the Z vector component of this quaternion to. - */ - Quaternion(float w, float x, float y, float z) { - this->w = w; - this->x = x; - this->y = y; - this->z = z; - } - - /*! This function can be used to set all values in the structure at the same time. - * \param w The value to set the W scalar component of this quaternion to. - * \param x The value to set the X vector component of this quaternion to. - * \param y The value to set the Y vector component of this quaternion to. - * \param z The value to set the Z vector component of this quaternion to. - */ - void Set(float w, float x, float y, float z) { - this->w = w; - this->x = x; - this->y = y; - this->z = z; - } -}; - /*! Represents a bounding box - the smallest rectangular shape that a particular node can fit inside. */ struct BoundingBox { bool isUsed; /*!< Determines whether this bounding box is used or not. If this value is true, the other members of this structure are significant. If false, they are ignored. */ diff --git a/niflib_internal.cpp b/niflib_internal.cpp index 6436e0f3..831f55f0 100644 --- a/niflib_internal.cpp +++ b/niflib_internal.cpp @@ -34,6 +34,60 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "niflib_internal.h" extern unsigned int blocks_in_memory; +const Type ABlock::TYPE("ABlock", NULL ); + +/* + * Type Methods + */ + +bool Type::IsSameType( const Type & compare_to ) const { + return &compare_to == this; +} + +bool Type::IsDerivedType( const Type & compare_to ) const { + + const Type * search = this; + while ( search != NULL ) { + if ( search == &compare_to ) { + return true; + } + search = search->base_type; + } + return false; +} + +/* + * NiObject Methods + */ + +bool NiObject::IsSameType( const Type & compare_to) const { + return GetType().IsSameType( compare_to ); +} + +bool NiObject::IsSameType( const NiObject * object ) const { + return GetType().IsSameType( object->GetType() ); +} + +bool NiObject::IsDerivedType( const Type & compare_to) const { + return GetType().IsDerivedType( compare_to ); +} + +bool NiObject::IsDerivedType( const NiObject * object ) const { + return GetType().IsDerivedType( object->GetType() ); +} + +void NiObject::AddRef() { + ++_ref_count; +} + +void NiObject::SubtractRef() { + --_ref_count; + + if ( _ref_count < 1 ) { + delete this; + } +} + /*********************************************************** * ABlock methods diff --git a/niflib_internal.h b/niflib_internal.h index a7973037..aa004493 100644 --- a/niflib_internal.h +++ b/niflib_internal.h @@ -84,12 +84,119 @@ protected: IBlock * _owner; }; +/** + * Run Time Type Inforamtion Class + */ +class Type { +public: + Type (const string & type_name, const Type * base_type ); + ~Type(); + + string GetTypeName() const; + + bool IsSameType ( const Type & compare_to ) const; + bool IsDerivedType ( const Type & compare_to ) const; +private: + string name; + const Type * base_type; +}; + +/** + * Smart Pointer Template + */ +template <class T> class Ref { +public: + Ref( T * object = NULL ); + Ref(const Ref & ref_to_copy ); + + operator T*() const; + T& operator*() const; + T* operator->() const; + + Ref & operator=( T * object ); + Ref & operator=( const Ref & ref ); + + bool operator==(T * object) const; + bool operator!=(T * object) const; + bool operator==(const Ref & ref) const; + bool operator!=(const Ref & ref) const; + +protected: + //The shared object + T* _object; +}; + + + +/** + * Base Object class from which all other objects derive + */ + +class NiObject { +public: + NiObject(); + ~NiObject(); + //Run-Time Type Information + static const Type TYPE; + virtual const Type & GetType() const { return TYPE; }; + bool IsSameType( const Type & compare_to ) const; + bool IsSameType( const NiObject * object ) const; + bool IsDerivedType (const Type & compare_to ) const; + bool IsDerivedType( const NiObject * objct ) const; + + //Streaming Functions + virtual void Read( istream& in, unsigned int version ) {}; + virtual void Write( ostream& out, unsigned int version ) const {}; + //TODO Register objects in list + //TODO Link up objects from previously created list + + //Reference Counting + void AddRef(); //Should not be called directly + void SubtractRef(); //Should not be called directly + unsigned int GetNumRefs() { return _ref_count; } + +private: + unsigned int _ref_count; +}; + +/* + * Casting Templates + */ + +template <class T> T* StaticCast( NiObject * object ) { + return (T*)object; +} + +template <class T> const T* SaticCast (const NiObject * object) { + return (const T*)object; +} + +template <class T> T* DynamicCast( NiObject * object ) { + if ( object->IsDerivedType(T::TYPE) ) { + return (T*)object; + } else { + return NULL; + } +} + +template <class T> const T* DynamicCast( const NiObject * object ) { + if ( object->IsDerivedType(T::TYPE) ) { + return (const T*)object; + } else { + return NULL; + } +} + + +const Type NiObject::TYPE("NiObject", NULL ); + //Internal Abstract Block Class class ABlock : public IBlock { public: ABlock(); ~ABlock(); + static const Type TYPE; blk_ref Clone( unsigned int version = 0xFFFFFFFF ); //void AddAttr( AttrType type, string const & name, unsigned int first_ver = 0, unsigned int last_ver = 0xFFFFFFFF ); attr_ref GetAttr(string const & attr_name) const; -- GitLab