From ebed57aa22b772211387a5561f995eee8f5faed1 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Tue, 26 Jun 2012 22:23:05 +0200 Subject: Whitespace and language change - changed tabs to spaces and DOS line endings to Unix (except in CBot and metafile) - changed language to English - fixed #include in d3dengine.h --- src/math/const.h | 32 +- src/math/conv.h | 26 +- src/math/func.h | 156 +++++----- src/math/geometry.h | 496 +++++++++++++++---------------- src/math/intpoint.h | 10 +- src/math/matrix.h | 630 ++++++++++++++++++++-------------------- src/math/point.h | 216 +++++++------- src/math/test/geometry_test.cpp | 472 +++++++++++++++--------------- src/math/test/matrix_test.cpp | 612 +++++++++++++++++++------------------- src/math/test/vector_test.cpp | 132 ++++----- src/math/vector.h | 332 ++++++++++----------- 11 files changed, 1557 insertions(+), 1557 deletions(-) (limited to 'src/math') diff --git a/src/math/const.h b/src/math/const.h index 6721284..dd7ab0f 100644 --- a/src/math/const.h +++ b/src/math/const.h @@ -24,27 +24,27 @@ // Math module namespace namespace Math { - /* @{ */ // start of group +/* @{ */ // start of group - //! Tolerance level -- minimum accepted float value - const float TOLERANCE = 1e-6f; +//! Tolerance level -- minimum accepted float value +const float TOLERANCE = 1e-6f; - //! Very small number (used in testing/returning some values) - const float VERY_SMALL = 1e-6f; - //! Very big number (used in testing/returning some values) - const float VERY_BIG = 1e6f; +//! Very small number (used in testing/returning some values) +const float VERY_SMALL = 1e-6f; +//! Very big number (used in testing/returning some values) +const float VERY_BIG = 1e6f; - //! Huge number - const float HUGE = 1.0e+38f; +//! Huge number +const float HUGE = 1.0e+38f; - //! PI - const float PI = 3.14159265358979323846f; +//! PI +const float PI = 3.14159265358979323846f; - //! Degrees to radians multiplier - const float DEG_TO_RAD = 0.01745329251994329547f; - //! Radians to degrees multiplier - const float RAD_TO_DEG = 57.29577951308232286465f; +//! Degrees to radians multiplier +const float DEG_TO_RAD = 0.01745329251994329547f; +//! Radians to degrees multiplier +const float RAD_TO_DEG = 57.29577951308232286465f; - /* @} */ // end of group +/* @} */ // end of group }; // namespace Math diff --git a/src/math/conv.h b/src/math/conv.h index bb6700b..43e6fbd 100644 --- a/src/math/conv.h +++ b/src/math/conv.h @@ -11,29 +11,29 @@ inline D3DVECTOR VEC_TO_D3DVEC(Math::Vector vec) { - return D3DVECTOR(vec.x, vec.y, vec.z); + return D3DVECTOR(vec.x, vec.y, vec.z); } inline Math::Vector D3DVEC_TO_VEC(D3DVECTOR vec) { - return Math::Vector(vec.x, vec.y, vec.z); + return Math::Vector(vec.x, vec.y, vec.z); } inline D3DMATRIX MAT_TO_D3DMAT(Math::Matrix mat) { - D3DMATRIX result; - mat.Transpose(); - for (int r = 0; r < 4; ++r) - { - for (int c = 0; c < 16; ++c) - result.m[r][c] = mat.m[4*c+r]; - } - return result; + D3DMATRIX result; + mat.Transpose(); + for (int r = 0; r < 4; ++r) + { + for (int c = 0; c < 16; ++c) + result.m[r][c] = mat.m[4*c+r]; + } + return result; } inline Math::Matrix D3DMAT_TO_MAT(D3DMATRIX mat) { - Math::Matrix result(mat.m); - result.Transpose(); - return result; + Math::Matrix result(mat.m); + result.Transpose(); + return result; } diff --git a/src/math/func.h b/src/math/func.h index 212f7c1..8f0e4ab 100644 --- a/src/math/func.h +++ b/src/math/func.h @@ -16,7 +16,7 @@ // * along with this program. If not, see http://www.gnu.org/licenses/. /** @defgroup MathFuncModule math/func.h - Contains common math functions. + Contains common math functions. */ #pragma once @@ -36,146 +36,146 @@ namespace Math //! Compares \a a and \a b within \a tolerance inline bool IsEqual(float a, float b, float tolerance = TOLERANCE) { - return fabs(a - b) < tolerance; + return fabs(a - b) < tolerance; } //! Compares \a a to zero within \a tolerance inline bool IsZero(float a, float tolerance = TOLERANCE) { - return IsEqual(a, 0.0f, tolerance); + return IsEqual(a, 0.0f, tolerance); } //! Minimum inline float Min(float a, float b) { - if ( a <= b ) return a; - else return b; + if ( a <= b ) return a; + else return b; } inline float Min(float a, float b, float c) { - return Min( Min(a, b), c ); + return Min( Min(a, b), c ); } inline float Min(float a, float b, float c, float d) { - return Min( Min(a, b), Min(c, d) ); + return Min( Min(a, b), Min(c, d) ); } inline float Min(float a, float b, float c, float d, float e) { - return Min( Min(a, b), Min(c, d), e ); + return Min( Min(a, b), Min(c, d), e ); } //! Maximum inline float Max(float a, float b) { - if ( a >= b ) return a; - else return b; + if ( a >= b ) return a; + else return b; } inline float Max(float a, float b, float c) { - return Max( Max(a, b), c ); + return Max( Max(a, b), c ); } inline float Max(float a, float b, float c, float d) { - return Max( Max(a, b), Max(c, d) ); + return Max( Max(a, b), Max(c, d) ); } inline float Max(float a, float b, float c, float d, float e) { - return Max( Max(a, b), Max(c, d), e ); + return Max( Max(a, b), Max(c, d), e ); } //! Returns the normalized value (0 .. 1) inline float Norm(float a) { - if ( a < 0.0f ) return 0.0f; - if ( a > 1.0f ) return 1.0f; - return a; + if ( a < 0.0f ) return 0.0f; + if ( a > 1.0f ) return 1.0f; + return a; } //! Swaps two integers inline void Swap(int &a, int &b) { - int c = a; - a = b; - b = c; + int c = a; + a = b; + b = c; } //! Swaps two real numbers inline void Swap(float &a, float &b) { - float c = a; - a = b; - b = c; + float c = a; + a = b; + b = c; } //! Returns the modulo of a floating point number /** Mod(8.1, 4) = 0.1 - Mod(n, 1) = fractional part of n */ + Mod(n, 1) = fractional part of n */ inline float Mod(float a, float m) { - return a - ((int)(a/m))*m; + return a - ((int)(a/m))*m; } //! Returns a random value between 0 and 1. inline float Rand() { - return (float)rand()/RAND_MAX; + return (float)rand()/RAND_MAX; } //! Returns a normalized angle, that is in other words between 0 and 2 * PI inline float NormAngle(float angle) { - angle = Mod(angle, PI*2.0f); - if ( angle < 0.0f ) - return PI*2.0f + angle; + angle = Mod(angle, PI*2.0f); + if ( angle < 0.0f ) + return PI*2.0f + angle; - return angle; + return angle; } //! Test if a angle is between two terminals inline bool TestAngle(float angle, float min, float max) { - angle = NormAngle(angle); - min = NormAngle(min); - max = NormAngle(max); + angle = NormAngle(angle); + min = NormAngle(min); + max = NormAngle(max); - if ( min > max ) - return ( angle <= max || angle >= min ); + if ( min > max ) + return ( angle <= max || angle >= min ); - return ( angle >= min && angle <= max ); + return ( angle >= min && angle <= max ); } //! Calculates a value (radians) proportional between a and b (degrees) inline float PropAngle(int a, int b, float p) { - float aa = (float)a * DEG_TO_RAD; - float bb = (float)b * DEG_TO_RAD; + float aa = (float)a * DEG_TO_RAD; + float bb = (float)b * DEG_TO_RAD; - return aa+p*(bb-aa); + return aa+p*(bb-aa); } //! Calculates the angle to rotate the angle \a a to the angle \a g /** A positive angle is counterclockwise (CCW). */ inline float Direction(float a, float g) { - a = NormAngle(a); - g = NormAngle(g); + a = NormAngle(a); + g = NormAngle(g); - if ( a < g ) - { - if ( a+PI*2.0f-g < g-a ) a += PI*2.0f; - } - else - { - if ( g+PI*2.0f-a < a-g ) g += PI*2.0f; - } + if ( a < g ) + { + if ( a+PI*2.0f-g < g-a ) a += PI*2.0f; + } + else + { + if ( g+PI*2.0f-a < a-g ) g += PI*2.0f; + } - return g-a; + return g-a; } //! Managing the dead zone of a joystick. @@ -187,33 +187,33 @@ inline float Direction(float a, float g) out: -1 0 0 1\endverbatim */ inline float Neutral(float value, float dead) { - if ( fabs(value) <= dead ) - { - return 0.0f; - } - else - { - if ( value > 0.0f ) return (value-dead)/(1.0f-dead); - else return (value+dead)/(1.0f-dead); - } + if ( fabs(value) <= dead ) + { + return 0.0f; + } + else + { + if ( value > 0.0f ) return (value-dead)/(1.0f-dead); + else return (value+dead)/(1.0f-dead); + } } //! Gently advances a desired value from its current value /** Over time, the progression is more rapid. */ inline float Smooth(float actual, float hope, float time) { - float future = actual + (hope-actual)*time; + float future = actual + (hope-actual)*time; - if ( hope > actual ) - { - if ( future > hope ) future = hope; - } - if ( hope < actual ) - { - if ( future < hope ) future = hope; - } + if ( hope > actual ) + { + if ( future > hope ) future = hope; + } + if ( hope < actual ) + { + if ( future < hope ) future = hope; + } - return future; + return future; } //! Bounces any movement @@ -230,16 +230,16 @@ inline float Smooth(float actual, float hope, float time) |<---->|middle\endverbatim */ inline float Bounce(float progress, float middle = 0.3f, float bounce = 0.4f) { - if ( progress < middle ) - { - progress = progress/middle; // 0..1 - return 0.5f+sinf(progress*PI-PI/2.0f)/2.0f; - } - else - { - progress = (progress-middle)/(1.0f-middle); // 0..1 - return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*PI)*(bounce/2.0f); - } + if ( progress < middle ) + { + progress = progress/middle; // 0..1 + return 0.5f+sinf(progress*PI-PI/2.0f)/2.0f; + } + else + { + progress = (progress-middle)/(1.0f-middle); // 0..1 + return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*PI)*(bounce/2.0f); + } } /* @} */ // end of group diff --git a/src/math/geometry.h b/src/math/geometry.h index 5654dad..2f937e5 100644 --- a/src/math/geometry.h +++ b/src/math/geometry.h @@ -42,40 +42,40 @@ namespace Math //! Returns py up on the line \a a - \a b inline float MidPoint(const Point &a, const Point &b, float px) { - if (IsEqual(a.x, b.x)) - { - if (a.y < b.y) - return HUGE; - else - return -HUGE; - } - return (b.y-a.y) * (px-a.x) / (b.x-a.x) + a.y; + if (IsEqual(a.x, b.x)) + { + if (a.y < b.y) + return HUGE; + else + return -HUGE; + } + return (b.y-a.y) * (px-a.x) / (b.x-a.x) + a.y; } //! Tests whether the point \a p is inside the triangle (\a a,\a b,\a c) inline bool IsInsideTriangle(Point a, Point b, Point c, Point p) { - float n, m; + float n, m; - if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false; - if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false; - if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false; - if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false; + if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false; + if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false; + if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false; + if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false; - if ( a.x > b.x ) Swap(a,b); - if ( a.x > c.x ) Swap(a,c); - if ( c.x < a.x ) Swap(c,a); - if ( c.x < b.x ) Swap(c,b); + if ( a.x > b.x ) Swap(a,b); + if ( a.x > c.x ) Swap(a,c); + if ( c.x < a.x ) Swap(c,a); + if ( c.x < b.x ) Swap(c,b); - n = MidPoint(a, b, p.x); - m = MidPoint(a, c, p.x); - if ( (n>p.y||p.y>m) && (np.y||p.y>m) && (np.y||p.y>m) && (np.y||p.y>m) && (n= 0.0f)) - return -atan + 2.5f*PI; - else - return -atan + 0.5f*PI; + if ((y < 0.0f) && (x >= 0.0f)) + return -atan + 2.5f*PI; + else + return -atan + 0.5f*PI; } //! Calculates the angle between two points and one center /** \a center the center point \a p1,p2 the two points - \returns The angle in radians (positive is counterclockwise (CCW) ) */ + \returns The angle in radians (positive is counterclockwise (CCW) ) */ inline float RotateAngle(const Point ¢er, const Point &p1, const Point &p2) { - if (PointsEqual(p1, center)) - return 0; + if (PointsEqual(p1, center)) + return 0; - if (PointsEqual(p2, center)) - return 0; + if (PointsEqual(p2, center)) + return 0; - float a1 = asinf((p1.y - center.y) / Distance(p1, center)); - float a2 = asinf((p2.y - center.y) / Distance(p2, center)); + float a1 = asinf((p1.y - center.y) / Distance(p1, center)); + float a2 = asinf((p2.y - center.y) / Distance(p2, center)); - if (p1.x < center.x) a1 = PI - a1; - if (p2.x < center.x) a2 = PI - a2; + if (p1.x < center.x) a1 = PI - a1; + if (p2.x < center.x) a2 = PI - a2; - float a = a2 - a1; - if (a < 0) - a += 2.0f*PI; + float a = a2 - a1; + if (a < 0) + a += 2.0f*PI; - return a; + return a; } //! Loads view matrix from the given vectors @@ -223,62 +223,62 @@ inline float RotateAngle(const Point ¢er, const Point &p1, const Point &p2) \a worldUp up vector */ inline void LoadViewMatrix(Matrix &mat, const Vector &from, const Vector &at, const Vector &worldUp) { - // Get the z basis vector, which points straight ahead. This is the - // difference from the eyepoint to the lookat point. - Vector view = at - from; + // Get the z basis vector, which points straight ahead. This is the + // difference from the eyepoint to the lookat point. + Vector view = at - from; - float length = view.Length(); - assert(! IsZero(length) ); + float length = view.Length(); + assert(! IsZero(length) ); - // Normalize the z basis vector - view /= length; + // Normalize the z basis vector + view /= length; - // Get the dot product, and calculate the projection of the z basis - // vector onto the up vector. The projection is the y basis vector. - float dotProduct = DotProduct(worldUp, view); + // Get the dot product, and calculate the projection of the z basis + // vector onto the up vector. The projection is the y basis vector. + float dotProduct = DotProduct(worldUp, view); - Vector up = worldUp - dotProduct * view; + Vector up = worldUp - dotProduct * view; - // If this vector has near-zero length because the input specified a - // bogus up vector, let's try a default up vector - if ( IsZero(length = up.Length()) ) - { - up = Vector(0.0f, 1.0f, 0.0f) - view.y * view; - - // If we still have near-zero length, resort to a different axis. + // If this vector has near-zero length because the input specified a + // bogus up vector, let's try a default up vector if ( IsZero(length = up.Length()) ) { - up = Vector(0.0f, 0.0f, 1.0f) - view.z * view; + up = Vector(0.0f, 1.0f, 0.0f) - view.y * view; + + // If we still have near-zero length, resort to a different axis. + if ( IsZero(length = up.Length()) ) + { + up = Vector(0.0f, 0.0f, 1.0f) - view.z * view; - assert(! IsZero(up.Length()) ); + assert(! IsZero(up.Length()) ); + } } - } - - // Normalize the y basis vector - up /= length; - - // The x basis vector is found simply with the cross product of the y - // and z basis vectors - Vector right = CrossProduct(up, view); - - // Start building the matrix. The first three rows contains the basis - // vectors used to rotate the view to point at the lookat point - mat.LoadIdentity(); - - /* (1,1) */ mat.m[0 ] = right.x; - /* (2,1) */ mat.m[1 ] = up.x; - /* (3,1) */ mat.m[2 ] = view.x; - /* (1,2) */ mat.m[4 ] = right.y; - /* (2,2) */ mat.m[5 ] = up.y; - /* (3,2) */ mat.m[6 ] = view.y; - /* (1,3) */ mat.m[8 ] = right.z; - /* (2,3) */ mat.m[9 ] = up.z; - /* (3,3) */ mat.m[10] = view.z; - - // Do the translation values (rotations are still about the eyepoint) - /* (1,4) */ mat.m[12] = -DotProduct(from, right); - /* (2,4) */ mat.m[13] = -DotProduct(from, up); - /* (3,4) */ mat.m[14] = -DotProduct(from, view); + + // Normalize the y basis vector + up /= length; + + // The x basis vector is found simply with the cross product of the y + // and z basis vectors + Vector right = CrossProduct(up, view); + + // Start building the matrix. The first three rows contains the basis + // vectors used to rotate the view to point at the lookat point + mat.LoadIdentity(); + + /* (1,1) */ mat.m[0 ] = right.x; + /* (2,1) */ mat.m[1 ] = up.x; + /* (3,1) */ mat.m[2 ] = view.x; + /* (1,2) */ mat.m[4 ] = right.y; + /* (2,2) */ mat.m[5 ] = up.y; + /* (3,2) */ mat.m[6 ] = view.y; + /* (1,3) */ mat.m[8 ] = right.z; + /* (2,3) */ mat.m[9 ] = up.z; + /* (3,3) */ mat.m[10] = view.z; + + // Do the translation values (rotations are still about the eyepoint) + /* (1,4) */ mat.m[12] = -DotProduct(from, right); + /* (2,4) */ mat.m[13] = -DotProduct(from, up); + /* (3,4) */ mat.m[14] = -DotProduct(from, view); } //! Loads a perspective projection matrix @@ -289,73 +289,73 @@ inline void LoadViewMatrix(Matrix &mat, const Vector &from, const Vector &at, co inline void LoadProjectionMatrix(Matrix &mat, float fov = 1.570795f, float aspect = 1.0f, float nearPlane = 1.0f, float farPlane = 1000.0f) { - assert(fabs(farPlane - nearPlane) >= 0.01f); - assert(fabs(sin(fov / 2)) >= 0.01f); + assert(fabs(farPlane - nearPlane) >= 0.01f); + assert(fabs(sin(fov / 2)) >= 0.01f); - float w = aspect * (cosf(fov / 2) / sinf(fov / 2)); - float h = 1.0f * (cosf(fov / 2) / sinf(fov / 2)); - float q = farPlane / (farPlane - nearPlane); + float w = aspect * (cosf(fov / 2) / sinf(fov / 2)); + float h = 1.0f * (cosf(fov / 2) / sinf(fov / 2)); + float q = farPlane / (farPlane - nearPlane); - mat.LoadZero(); + mat.LoadZero(); - /* (1,1) */ mat.m[0 ] = w; - /* (2,2) */ mat.m[5 ] = h; - /* (3,3) */ mat.m[10] = q; - /* (4,3) */ mat.m[11] = 1.0f; - /* (3,4) */ mat.m[14] = -q * nearPlane; + /* (1,1) */ mat.m[0 ] = w; + /* (2,2) */ mat.m[5 ] = h; + /* (3,3) */ mat.m[10] = q; + /* (4,3) */ mat.m[11] = 1.0f; + /* (3,4) */ mat.m[14] = -q * nearPlane; } //! Loads a translation matrix from given vector /** \a trans vector of translation*/ inline void LoadTranslationMatrix(Matrix &mat, const Vector &trans) { - mat.LoadIdentity(); - /* (1,4) */ mat.m[12] = trans.x; - /* (2,4) */ mat.m[13] = trans.y; - /* (3,4) */ mat.m[14] = trans.z; + mat.LoadIdentity(); + /* (1,4) */ mat.m[12] = trans.x; + /* (2,4) */ mat.m[13] = trans.y; + /* (3,4) */ mat.m[14] = trans.z; } //! Loads a scaling matrix fom given vector /** \a scale vector with scaling factors for X, Y, Z */ inline void LoadScaleMatrix(Matrix &mat, const Vector &scale) { - mat.LoadIdentity(); - /* (1,1) */ mat.m[0 ] = scale.x; - /* (2,2) */ mat.m[5 ] = scale.y; - /* (3,3) */ mat.m[10] = scale.z; + mat.LoadIdentity(); + /* (1,1) */ mat.m[0 ] = scale.x; + /* (2,2) */ mat.m[5 ] = scale.y; + /* (3,3) */ mat.m[10] = scale.z; } //! Loads a rotation matrix along the X axis /** \a angle angle in radians */ inline void LoadRotationXMatrix(Matrix &mat, float angle) { - mat.LoadIdentity(); - /* (2,2) */ mat.m[5 ] = cosf(angle); - /* (3,2) */ mat.m[6 ] = sinf(angle); - /* (2,3) */ mat.m[9 ] = -sinf(angle); - /* (3,3) */ mat.m[10] = cosf(angle); + mat.LoadIdentity(); + /* (2,2) */ mat.m[5 ] = cosf(angle); + /* (3,2) */ mat.m[6 ] = sinf(angle); + /* (2,3) */ mat.m[9 ] = -sinf(angle); + /* (3,3) */ mat.m[10] = cosf(angle); } //! Loads a rotation matrix along the Y axis /** \a angle angle in radians */ inline void LoadRotationYMatrix(Matrix &mat, float angle) { - mat.LoadIdentity(); - /* (1,1) */ mat.m[0 ] = cosf(angle); - /* (3,1) */ mat.m[2 ] = -sinf(angle); - /* (1,3) */ mat.m[8 ] = sinf(angle); - /* (3,3) */ mat.m[10] = cosf(angle); + mat.LoadIdentity(); + /* (1,1) */ mat.m[0 ] = cosf(angle); + /* (3,1) */ mat.m[2 ] = -sinf(angle); + /* (1,3) */ mat.m[8 ] = sinf(angle); + /* (3,3) */ mat.m[10] = cosf(angle); } //! Loads a rotation matrix along the Z axis /** \a angle angle in radians */ inline void LoadRotationZMatrix(Matrix &mat, float angle) { - mat.LoadIdentity(); - /* (1,1) */ mat.m[0 ] = cosf(angle); - /* (2,1) */ mat.m[1 ] = sinf(angle); - /* (1,2) */ mat.m[4 ] = -sinf(angle); - /* (2,2) */ mat.m[5 ] = cosf(angle); + mat.LoadIdentity(); + /* (1,1) */ mat.m[0 ] = cosf(angle); + /* (2,1) */ mat.m[1 ] = sinf(angle); + /* (1,2) */ mat.m[4 ] = -sinf(angle); + /* (2,2) */ mat.m[5 ] = cosf(angle); } //! Loads a rotation matrix along the given axis @@ -363,66 +363,66 @@ inline void LoadRotationZMatrix(Matrix &mat, float angle) \a angle angle in radians */ inline void LoadRotationMatrix(Matrix &mat, const Vector &dir, float angle) { - float cos = cosf(angle); - float sin = sinf(angle); - Vector v = Normalize(dir); + float cos = cosf(angle); + float sin = sinf(angle); + Vector v = Normalize(dir); - mat.LoadIdentity(); + mat.LoadIdentity(); - /* (1,1) */ mat.m[0 ] = (v.x * v.x) * (1.0f - cos) + cos; - /* (2,1) */ mat.m[1 ] = (v.x * v.y) * (1.0f - cos) - (v.z * sin); - /* (3,1) */ mat.m[2 ] = (v.x * v.z) * (1.0f - cos) + (v.y * sin); + /* (1,1) */ mat.m[0 ] = (v.x * v.x) * (1.0f - cos) + cos; + /* (2,1) */ mat.m[1 ] = (v.x * v.y) * (1.0f - cos) - (v.z * sin); + /* (3,1) */ mat.m[2 ] = (v.x * v.z) * (1.0f - cos) + (v.y * sin); - /* (1,2) */ mat.m[4 ] = (v.y * v.x) * (1.0f - cos) + (v.z * sin); - /* (2,2) */ mat.m[5 ] = (v.y * v.y) * (1.0f - cos) + cos ; - /* (3,2) */ mat.m[6 ] = (v.y * v.z) * (1.0f - cos) - (v.x * sin); + /* (1,2) */ mat.m[4 ] = (v.y * v.x) * (1.0f - cos) + (v.z * sin); + /* (2,2) */ mat.m[5 ] = (v.y * v.y) * (1.0f - cos) + cos ; + /* (3,2) */ mat.m[6 ] = (v.y * v.z) * (1.0f - cos) - (v.x * sin); - /* (1,3) */ mat.m[8 ] = (v.z * v.x) * (1.0f - cos) - (v.y * sin); - /* (2,3) */ mat.m[9 ] = (v.z * v.y) * (1.0f - cos) + (v.x * sin); - /* (3,3) */ mat.m[10] = (v.z * v.z) * (1.0f - cos) + cos; + /* (1,3) */ mat.m[8 ] = (v.z * v.x) * (1.0f - cos) - (v.y * sin); + /* (2,3) */ mat.m[9 ] = (v.z * v.y) * (1.0f - cos) + (v.x * sin); + /* (3,3) */ mat.m[10] = (v.z * v.z) * (1.0f - cos) + cos; } //! Calculates the matrix to make three rotations in the order X, Z and Y inline void LoadRotationXZYMatrix(Matrix &mat, const Vector &angle) { - Matrix temp; - LoadRotationXMatrix(temp, angle.x); + Matrix temp; + LoadRotationXMatrix(temp, angle.x); - LoadRotationZMatrix(mat, angle.z); - mat = Math::MultiplyMatrices(temp, mat); + LoadRotationZMatrix(mat, angle.z); + mat = Math::MultiplyMatrices(temp, mat); - LoadRotationYMatrix(temp, angle.y); - mat = Math::MultiplyMatrices(temp, mat); + LoadRotationYMatrix(temp, angle.y); + mat = Math::MultiplyMatrices(temp, mat); } //! Calculates the matrix to make three rotations in the order Z, X and Y inline void LoadRotationZXYMatrix(Matrix &mat, const Vector &angle) { - Matrix temp; - LoadRotationZMatrix(temp, angle.z); + Matrix temp; + LoadRotationZMatrix(temp, angle.z); - LoadRotationXMatrix(mat, angle.x); - mat = Math::MultiplyMatrices(temp, mat); + LoadRotationXMatrix(mat, angle.x); + mat = Math::MultiplyMatrices(temp, mat); - LoadRotationYMatrix(temp, angle.y); - mat = Math::MultiplyMatrices(temp, mat); + LoadRotationYMatrix(temp, angle.y); + mat = Math::MultiplyMatrices(temp, mat); } //! Returns the distance between projections on XZ plane of two vectors inline float DistanceProjected(const Vector &a, const Vector &b) { - return sqrtf( (a.x-b.x)*(a.x-b.x) + - (a.z-b.z)*(a.z-b.z) ); + return sqrtf( (a.x-b.x)*(a.x-b.x) + + (a.z-b.z)*(a.z-b.z) ); } //! Returns the normal vector to a plane /** \param p1,p2,p3 points defining the plane */ inline Vector NormalToPlane(const Vector &p1, const Vector &p2, const Vector &p3) { - Vector u = p3 - p1; - Vector v = p2 - p1; + Vector u = p3 - p1; + Vector v = p2 - p1; - return Normalize(CrossProduct(u, v)); + return Normalize(CrossProduct(u, v)); } //! Returns a point on the line \a p1 - \a p2, in \a dist distance from \a p1 @@ -430,7 +430,7 @@ inline Vector NormalToPlane(const Vector &p1, const Vector &p2, const Vector &p3 \a dist scaling factor from \a p1, relative to distance between \a p1 and \a p2 */ inline Vector SegmentPoint(const Vector &p1, const Vector &p2, float dist) { - return p1 + (p2 - p1) * dist; + return p1 + (p2 - p1) * dist; } //! Returns the distance between given point and a plane @@ -438,10 +438,10 @@ inline Vector SegmentPoint(const Vector &p1, const Vector &p2, float dist) \param a,b,c points defining the plane */ inline float DistanceToPlane(const Vector &a, const Vector &b, const Vector &c, const Vector &p) { - Vector n = NormalToPlane(a, b, c); - float d = -(n.x*a.x + n.y*a.y + n.z*a.z); + Vector n = NormalToPlane(a, b, c); + float d = -(n.x*a.x + n.y*a.y + n.z*a.z); - return fabs(n.x*p.x + n.y*p.y + n.z*p.z + d); + return fabs(n.x*p.x + n.y*p.y + n.z*p.z + d); } //! Checks if two planes defined by three points are the same @@ -449,73 +449,73 @@ inline float DistanceToPlane(const Vector &a, const Vector &b, const Vector &c, \a plane2 array of three vectors defining the second plane */ inline bool IsSamePlane(const Vector (&plane1)[3], const Vector (&plane2)[3]) { - Vector n1 = NormalToPlane(plane1[0], plane1[1], plane1[2]); - Vector n2 = NormalToPlane(plane2[0], plane2[1], plane2[2]); + Vector n1 = NormalToPlane(plane1[0], plane1[1], plane1[2]); + Vector n2 = NormalToPlane(plane2[0], plane2[1], plane2[2]); - if ( fabs(n1.x-n2.x) > 0.1f || - fabs(n1.y-n2.y) > 0.1f || - fabs(n1.z-n2.z) > 0.1f ) - return false; + if ( fabs(n1.x-n2.x) > 0.1f || + fabs(n1.y-n2.y) > 0.1f || + fabs(n1.z-n2.z) > 0.1f ) + return false; - float dist = DistanceToPlane(plane1[0], plane1[1], plane1[2], plane2[0]); - if ( dist > 0.1f ) - return false; + float dist = DistanceToPlane(plane1[0], plane1[1], plane1[2], plane2[0]); + if ( dist > 0.1f ) + return false; - return true; + return true; } //! Calculates the intersection "i" right "of" the plane "abc". inline bool Intersect(const Vector &a, const Vector &b, const Vector &c, const Vector &d, const Vector &e, Vector &i) { - float d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) - - (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) + - (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y)); + float d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) - + (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) + + (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y)); - float d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) - - (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) + - (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y)); + float d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) - + (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) + + (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y)); - if (d2 == 0) - return false; + if (d2 == 0) + return false; - i.x = d.x + d1/d2*(e.x-d.x); - i.y = d.y + d1/d2*(e.y-d.y); - i.z = d.z + d1/d2*(e.z-d.z); + i.x = d.x + d1/d2*(e.x-d.x); + i.y = d.y + d1/d2*(e.y-d.y); + i.z = d.z + d1/d2*(e.z-d.z); - return true; + return true; } //! Calculates the intersection of the straight line passing through p (x, z) /** Line is parallel to the y axis, with the plane abc. Returns p.y. */ inline bool IntersectY(const Vector &a, const Vector &b, const Vector &c, Vector &p) { - float d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z); - float d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z); - float d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z); + float d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z); + float d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z); + float d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z); - if (d == 0.0f) - return false; + if (d == 0.0f) + return false; - p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y); + p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y); - return true; + return true; } //! Calculates the end point inline Vector LookatPoint(const Vector &eye, float angleH, float angleV, float length) { - Vector lookat = eye; - lookat.z += length; + Vector lookat = eye; + lookat.z += length; - RotatePoint(eye, angleH, angleV, lookat); + RotatePoint(eye, angleH, angleV, lookat); - return lookat; + return lookat; } //! TODO documentation inline Vector Transform(const Matrix &m, const Vector &p) { - return MatrixVectorMultiply(m, p); + return MatrixVectorMultiply(m, p); } //! Calculates the projection of the point \a p on a straight line \a a to \a b. @@ -523,28 +523,28 @@ inline Vector Transform(const Matrix &m, const Vector &p) \a a,b two ends of the line */ inline Vector Projection(const Vector &a, const Vector &b, const Vector &p) { - float k = DotProduct(b - a, p - a); - k /= DotProduct(b - a, b - a); + float k = DotProduct(b - a, p - a); + k /= DotProduct(b - a, b - a); - return a + k*(b-a); + return a + k*(b-a); } //! Calculates point of view to look at a center two angles and a distance inline Vector RotateView(Vector center, float angleH, float angleV, float dist) { - Matrix mat1, mat2; - LoadRotationZMatrix(mat1, -angleV); - LoadRotationYMatrix(mat2, -angleH); + Matrix mat1, mat2; + LoadRotationZMatrix(mat1, -angleV); + LoadRotationYMatrix(mat2, -angleH); - Matrix mat = MultiplyMatrices(mat2, mat1); + Matrix mat = MultiplyMatrices(mat2, mat1); - Vector eye; - eye.x = 0.0f+dist; - eye.y = 0.0f; - eye.z = 0.0f; - eye = Transform(mat, eye); + Vector eye; + eye.x = 0.0f+dist; + eye.y = 0.0f; + eye.z = 0.0f; + eye = Transform(mat, eye); - return eye+center; + return eye+center; } /* @} */ // end of group diff --git a/src/math/intpoint.h b/src/math/intpoint.h index cbfee2d..a760bc2 100644 --- a/src/math/intpoint.h +++ b/src/math/intpoint.h @@ -31,12 +31,12 @@ namespace Math { */ struct IntPoint { - //! X coord - long x; - //! Y coord - long y; + //! X coord + long x; + //! Y coord + long y; - IntPoint(long aX = 0, long aY = 0) : x(aX), y(aY) {} + IntPoint(long aX = 0, long aY = 0) : x(aX), y(aY) {} }; /* @} */ // end of group diff --git a/src/math/matrix.h b/src/math/matrix.h index 35871cf..9b29f46 100644 --- a/src/math/matrix.h +++ b/src/math/matrix.h @@ -37,356 +37,356 @@ namespace Math /** \struct Matrix math/matrix.h \brief 4x4 matrix - Represents an universal 4x4 matrix that can be used in OpenGL and DirectX engines. - Contains the required methods for operating on matrices (inverting, multiplying, etc.). + Represents an universal 4x4 matrix that can be used in OpenGL and DirectX engines. + Contains the required methods for operating on matrices (inverting, multiplying, etc.). - The internal representation is a 16-value table in column-major order, thus: + The internal representation is a 16-value table in column-major order, thus: - \verbatim + \verbatim m[0 ] m[4 ] m[8 ] m[12] m[1 ] m[5 ] m[9 ] m[13] m[2 ] m[6 ] m[10] m[14] m[3 ] m[7 ] m[11] m[15] \endverbatim - This representation is native to OpenGL; DirectX requires transposing the matrix. + This representation is native to OpenGL; DirectX requires transposing the matrix. - The order of multiplication of matrix and vector is also OpenGL-native - (see the function MatrixVectorMultiply). + The order of multiplication of matrix and vector is also OpenGL-native + (see the function MatrixVectorMultiply). - All methods are made inline to maximize optimization. + All methods are made inline to maximize optimization. - Unit tests for the structure and related functions are in module: math/test/matrix_test.cpp. + Unit tests for the structure and related functions are in module: math/test/matrix_test.cpp. **/ struct Matrix { - //! Matrix values in column-major order - float m[16]; - - //! Creates the indentity matrix - inline Matrix() - { - LoadIdentity(); - } - - //! Creates the matrix from 1D array - /** \a m matrix values in column-major order */ - inline explicit Matrix(const float (&m)[16]) - { - for (int i = 0; i < 16; ++i) - this->m[i] = m[i]; - } - - //! Creates the matrix from 2D array - /** The array's first index is row, second is column. - \a m array with values */ - inline explicit Matrix(const float (&m)[4][4]) - { - for (int c = 0; c < 4; ++c) + //! Matrix values in column-major order + float m[16]; + + //! Creates the indentity matrix + inline Matrix() { - for (int r = 0; r < 4; ++r) - { - this->m[4*c+r] = m[r][c]; - } + LoadIdentity(); } - } - inline void Set(int row, int col, float value) - { - m[(col-1)*4+(row-1)] = value; - } + //! Creates the matrix from 1D array + /** \a m matrix values in column-major order */ + inline explicit Matrix(const float (&m)[16]) + { + for (int i = 0; i < 16; ++i) + this->m[i] = m[i]; + } - inline float Get(int row, int col) - { - return m[(col-1)*4+(row-1)]; - } + //! Creates the matrix from 2D array + /** The array's first index is row, second is column. + \a m array with values */ + inline explicit Matrix(const float (&m)[4][4]) + { + for (int c = 0; c < 4; ++c) + { + for (int r = 0; r < 4; ++r) + { + this->m[4*c+r] = m[r][c]; + } + } + } - //! Loads the zero matrix - inline void LoadZero() - { - for (int i = 0; i < 16; ++i) - m[i] = 0.0f; - } - - //! Loads the identity matrix - inline void LoadIdentity() - { - LoadZero(); - /* (1,1) */ m[0 ] = 1.0f; - /* (2,2) */ m[5 ] = 1.0f; - /* (3,3) */ m[10] = 1.0f; - /* (4,4) */ m[15] = 1.0f; - } - - //! Transposes the matrix - inline void Transpose() - { - /* (2,1) <-> (1,2) */ Swap(m[1 ], m[4 ]); - /* (3,1) <-> (1,3) */ Swap(m[2 ], m[8 ]); - /* (4,1) <-> (1,4) */ Swap(m[3 ], m[12]); - /* (3,2) <-> (2,3) */ Swap(m[6 ], m[9 ]); - /* (4,2) <-> (2,4) */ Swap(m[7 ], m[13]); - /* (4,3) <-> (3,4) */ Swap(m[11], m[14]); - } - - //! Calculates the determinant of the matrix - /** \returns the determinant */ - inline float Det() const - { - float result = 0.0f; - for (int i = 0; i < 4; ++i) + inline void Set(int row, int col, float value) { - result += m[i] * Cofactor(i, 0); + m[(col-1)*4+(row-1)] = value; } - return result; - } - //! Calculates the cofactor of the matrix - /** \a r row (0 to 3) - \a c column (0 to 3) - \returns the cofactor */ - inline float Cofactor(int r, int c) const - { - assert(r >= 0 && r <= 3); - assert(c >= 0 && c <= 3); + inline float Get(int row, int col) + { + return m[(col-1)*4+(row-1)]; + } - float result = 0.0f; + //! Loads the zero matrix + inline void LoadZero() + { + for (int i = 0; i < 16; ++i) + m[i] = 0.0f; + } - /* That looks horrible, I know. But it's fast :) */ + //! Loads the identity matrix + inline void LoadIdentity() + { + LoadZero(); + /* (1,1) */ m[0 ] = 1.0f; + /* (2,2) */ m[5 ] = 1.0f; + /* (3,3) */ m[10] = 1.0f; + /* (4,4) */ m[15] = 1.0f; + } - switch (4*r + c) + //! Transposes the matrix + inline void Transpose() { - // r=0, c=0 - /* 05 09 13 - 06 10 14 - 07 11 15 */ - case 0: - result = + m[5 ] * (m[10] * m[15] - m[14] * m[11]) - - m[9 ] * (m[6 ] * m[15] - m[14] * m[7 ]) - + m[13] * (m[6 ] * m[11] - m[10] * m[7 ]); - break; - - // r=0, c=1 - /* 01 09 13 - 02 10 14 - 03 11 15 */ - case 1: - result = - m[1 ] * (m[10] * m[15] - m[14] * m[11]) - + m[9 ] * (m[2 ] * m[15] - m[14] * m[3 ]) - - m[13] * (m[2 ] * m[11] - m[10] * m[3 ]); - break; - - // r=0, c=2 - /* 01 05 13 - 02 06 14 - 03 07 15 */ - case 2: - result = + m[1 ] * (m[6 ] * m[15] - m[14] * m[7 ]) - - m[5 ] * (m[2 ] * m[15] - m[14] * m[3 ]) - + m[13] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); - break; - - // r=0, c=3 - /* 01 05 09 - 02 06 10 - 03 07 11 */ - case 3: - result = - m[1 ] * (m[6 ] * m[11] - m[10] * m[7 ]) - + m[5 ] * (m[2 ] * m[11] - m[10] * m[3 ]) - - m[9 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); - break; - - // r=1, c=0 - /* 04 08 12 - 06 10 14 - 07 11 15 */ - case 4: - result = - m[4 ] * (m[10] * m[15] - m[14] * m[11]) - + m[8 ] * (m[6 ] * m[15] - m[14] * m[7 ]) - - m[12] * (m[6 ] * m[11] - m[10] * m[7 ]); - break; - - // r=1, c=1 - /* 00 08 12 - 02 10 14 - 03 11 15 */ - case 5: - result = + m[0 ] * (m[10] * m[15] - m[14] * m[11]) - - m[8 ] * (m[2 ] * m[15] - m[14] * m[3 ]) - + m[12] * (m[2 ] * m[11] - m[10] * m[3 ]); - break; - - // r=1, c=2 - /* 00 04 12 - 02 06 14 - 03 07 15 */ - case 6: - result = - m[0 ] * (m[6 ] * m[15] - m[14] * m[7 ]) - + m[4 ] * (m[2 ] * m[15] - m[14] * m[3 ]) - - m[12] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); - break; - - // r=1, c=3 - /* 00 04 08 - 02 06 10 - 03 07 11 */ - case 7: - result = + m[0 ] * (m[6 ] * m[11] - m[10] * m[7 ]) - - m[4 ] * (m[2 ] * m[11] - m[10] * m[3 ]) - + m[8 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); - break; - - // r=2, c=0 - /* 04 08 12 - 05 09 13 - 07 11 15 */ - case 8: - result = + m[4 ] * (m[9 ] * m[15] - m[13] * m[11]) - - m[8 ] * (m[5 ] * m[15] - m[13] * m[7 ]) - + m[12] * (m[5 ] * m[11] - m[9 ] * m[7 ]); - break; - - // r=2, c=1 - /* 00 08 12 - 01 09 13 - 03 11 15 */ - case 9: - result = - m[0 ] * (m[9 ] * m[15] - m[13] * m[11]) - + m[8 ] * (m[1 ] * m[15] - m[13] * m[3 ]) - - m[12] * (m[1 ] * m[11] - m[9 ] * m[3 ]); - break; - - // r=2, c=2 - /* 00 04 12 - 01 05 13 - 03 07 15 */ - case 10: - result = + m[0 ] * (m[5 ] * m[15] - m[13] * m[7 ]) - - m[4 ] * (m[1 ] * m[15] - m[13] * m[3 ]) - + m[12] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]); - break; - - // r=2, c=3 - /* 00 04 08 - 01 05 09 - 03 07 11 */ - case 11: - result = - m[0 ] * (m[5 ] * m[11] - m[9 ] * m[7 ]) - + m[4 ] * (m[1 ] * m[11] - m[9 ] * m[3 ]) - - m[8 ] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]); - break; - - // r=3, c=0 - /* 04 08 12 - 05 09 13 - 06 10 14 */ - case 12: - result = - m[4 ] * (m[9 ] * m[14] - m[13] * m[10]) - + m[8 ] * (m[5 ] * m[14] - m[13] * m[6 ]) - - m[12] * (m[5 ] * m[10] - m[9 ] * m[6 ]); - break; - - // r=3, c=1 - /* 00 08 12 - 01 09 13 - 02 10 14 */ - case 13: - result = + m[0 ] * (m[9 ] * m[14] - m[13] * m[10]) - - m[8 ] * (m[1 ] * m[14] - m[13] * m[2 ]) - + m[12] * (m[1 ] * m[10] - m[9 ] * m[2 ]); - break; - - // r=3, c=2 - /* 00 04 12 - 01 05 13 - 02 06 14 */ - case 14: - result = - m[0 ] * (m[5 ] * m[14] - m[13] * m[6 ]) - + m[4 ] * (m[1 ] * m[14] - m[13] * m[2 ]) - - m[12] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]); - break; - - // r=3, c=3 - /* 00 04 08 - 01 05 09 - 02 06 10 */ - case 15: - result = + m[0 ] * (m[5 ] * m[10] - m[9 ] * m[6 ]) - - m[4 ] * (m[1 ] * m[10] - m[9 ] * m[2 ]) - + m[8 ] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]); - break; - - default: - break; + /* (2,1) <-> (1,2) */ Swap(m[1 ], m[4 ]); + /* (3,1) <-> (1,3) */ Swap(m[2 ], m[8 ]); + /* (4,1) <-> (1,4) */ Swap(m[3 ], m[12]); + /* (3,2) <-> (2,3) */ Swap(m[6 ], m[9 ]); + /* (4,2) <-> (2,4) */ Swap(m[7 ], m[13]); + /* (4,3) <-> (3,4) */ Swap(m[11], m[14]); } - return result; - } + //! Calculates the determinant of the matrix + /** \returns the determinant */ + inline float Det() const + { + float result = 0.0f; + for (int i = 0; i < 4; ++i) + { + result += m[i] * Cofactor(i, 0); + } + return result; + } - //! Calculates the inverse matrix - /** The determinant of the matrix must not be zero. - \returns the inverted matrix */ - inline Matrix Inverse() const - { - float d = Det(); - assert(! IsZero(d)); + //! Calculates the cofactor of the matrix + /** \a r row (0 to 3) + \a c column (0 to 3) + \returns the cofactor */ + inline float Cofactor(int r, int c) const + { + assert(r >= 0 && r <= 3); + assert(c >= 0 && c <= 3); - float result[16] = { 0.0f }; + float result = 0.0f; - for (int r = 0; r < 4; ++r) - { - for (int c = 0; c < 4; ++c) - { - // Already transposed! - result[4*r+c] = (1.0f / d) * Cofactor(r, c); - } - } + /* That looks horrible, I know. But it's fast :) */ - return Matrix(result); - } + switch (4*r + c) + { + // r=0, c=0 + /* 05 09 13 + 06 10 14 + 07 11 15 */ + case 0: + result = + m[5 ] * (m[10] * m[15] - m[14] * m[11]) + - m[9 ] * (m[6 ] * m[15] - m[14] * m[7 ]) + + m[13] * (m[6 ] * m[11] - m[10] * m[7 ]); + break; + + // r=0, c=1 + /* 01 09 13 + 02 10 14 + 03 11 15 */ + case 1: + result = - m[1 ] * (m[10] * m[15] - m[14] * m[11]) + + m[9 ] * (m[2 ] * m[15] - m[14] * m[3 ]) + - m[13] * (m[2 ] * m[11] - m[10] * m[3 ]); + break; + + // r=0, c=2 + /* 01 05 13 + 02 06 14 + 03 07 15 */ + case 2: + result = + m[1 ] * (m[6 ] * m[15] - m[14] * m[7 ]) + - m[5 ] * (m[2 ] * m[15] - m[14] * m[3 ]) + + m[13] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); + break; + + // r=0, c=3 + /* 01 05 09 + 02 06 10 + 03 07 11 */ + case 3: + result = - m[1 ] * (m[6 ] * m[11] - m[10] * m[7 ]) + + m[5 ] * (m[2 ] * m[11] - m[10] * m[3 ]) + - m[9 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); + break; + + // r=1, c=0 + /* 04 08 12 + 06 10 14 + 07 11 15 */ + case 4: + result = - m[4 ] * (m[10] * m[15] - m[14] * m[11]) + + m[8 ] * (m[6 ] * m[15] - m[14] * m[7 ]) + - m[12] * (m[6 ] * m[11] - m[10] * m[7 ]); + break; + + // r=1, c=1 + /* 00 08 12 + 02 10 14 + 03 11 15 */ + case 5: + result = + m[0 ] * (m[10] * m[15] - m[14] * m[11]) + - m[8 ] * (m[2 ] * m[15] - m[14] * m[3 ]) + + m[12] * (m[2 ] * m[11] - m[10] * m[3 ]); + break; + + // r=1, c=2 + /* 00 04 12 + 02 06 14 + 03 07 15 */ + case 6: + result = - m[0 ] * (m[6 ] * m[15] - m[14] * m[7 ]) + + m[4 ] * (m[2 ] * m[15] - m[14] * m[3 ]) + - m[12] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); + break; + + // r=1, c=3 + /* 00 04 08 + 02 06 10 + 03 07 11 */ + case 7: + result = + m[0 ] * (m[6 ] * m[11] - m[10] * m[7 ]) + - m[4 ] * (m[2 ] * m[11] - m[10] * m[3 ]) + + m[8 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]); + break; + + // r=2, c=0 + /* 04 08 12 + 05 09 13 + 07 11 15 */ + case 8: + result = + m[4 ] * (m[9 ] * m[15] - m[13] * m[11]) + - m[8 ] * (m[5 ] * m[15] - m[13] * m[7 ]) + + m[12] * (m[5 ] * m[11] - m[9 ] * m[7 ]); + break; + + // r=2, c=1 + /* 00 08 12 + 01 09 13 + 03 11 15 */ + case 9: + result = - m[0 ] * (m[9 ] * m[15] - m[13] * m[11]) + + m[8 ] * (m[1 ] * m[15] - m[13] * m[3 ]) + - m[12] * (m[1 ] * m[11] - m[9 ] * m[3 ]); + break; + + // r=2, c=2 + /* 00 04 12 + 01 05 13 + 03 07 15 */ + case 10: + result = + m[0 ] * (m[5 ] * m[15] - m[13] * m[7 ]) + - m[4 ] * (m[1 ] * m[15] - m[13] * m[3 ]) + + m[12] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]); + break; + + // r=2, c=3 + /* 00 04 08 + 01 05 09 + 03 07 11 */ + case 11: + result = - m[0 ] * (m[5 ] * m[11] - m[9 ] * m[7 ]) + + m[4 ] * (m[1 ] * m[11] - m[9 ] * m[3 ]) + - m[8 ] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]); + break; + + // r=3, c=0 + /* 04 08 12 + 05 09 13 + 06 10 14 */ + case 12: + result = - m[4 ] * (m[9 ] * m[14] - m[13] * m[10]) + + m[8 ] * (m[5 ] * m[14] - m[13] * m[6 ]) + - m[12] * (m[5 ] * m[10] - m[9 ] * m[6 ]); + break; + + // r=3, c=1 + /* 00 08 12 + 01 09 13 + 02 10 14 */ + case 13: + result = + m[0 ] * (m[9 ] * m[14] - m[13] * m[10]) + - m[8 ] * (m[1 ] * m[14] - m[13] * m[2 ]) + + m[12] * (m[1 ] * m[10] - m[9 ] * m[2 ]); + break; + + // r=3, c=2 + /* 00 04 12 + 01 05 13 + 02 06 14 */ + case 14: + result = - m[0 ] * (m[5 ] * m[14] - m[13] * m[6 ]) + + m[4 ] * (m[1 ] * m[14] - m[13] * m[2 ]) + - m[12] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]); + break; + + // r=3, c=3 + /* 00 04 08 + 01 05 09 + 02 06 10 */ + case 15: + result = + m[0 ] * (m[5 ] * m[10] - m[9 ] * m[6 ]) + - m[4 ] * (m[1 ] * m[10] - m[9 ] * m[2 ]) + + m[8 ] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]); + break; + + default: + break; + } - //! Calculates the multiplication of this matrix * given matrix - /** \a right right-hand matrix - \returns multiplication result */ - inline Matrix Multiply(const Matrix &right) const - { - float result[16] = { 0.0f }; + return result; + } - for (int c = 0; c < 4; ++c) + //! Calculates the inverse matrix + /** The determinant of the matrix must not be zero. + \returns the inverted matrix */ + inline Matrix Inverse() const { - for (int r = 0; r < 4; ++r) - { - result[4*c+r] = 0.0f; - for (int i = 0; i < 4; ++i) + float d = Det(); + assert(! IsZero(d)); + + float result[16] = { 0.0f }; + + for (int r = 0; r < 4; ++r) { - result[4*c+r] += m[4*i+r] * right.m[4*c+i]; + for (int c = 0; c < 4; ++c) + { + // Already transposed! + result[4*r+c] = (1.0f / d) * Cofactor(r, c); + } } - } + + return Matrix(result); } - return Matrix(result); - } + //! Calculates the multiplication of this matrix * given matrix + /** \a right right-hand matrix + \returns multiplication result */ + inline Matrix Multiply(const Matrix &right) const + { + float result[16] = { 0.0f }; + + for (int c = 0; c < 4; ++c) + { + for (int r = 0; r < 4; ++r) + { + result[4*c+r] = 0.0f; + for (int i = 0; i < 4; ++i) + { + result[4*c+r] += m[4*i+r] * right.m[4*c+i]; + } + } + } + + return Matrix(result); + } }; // struct Matrix //! Checks if two matrices are equal within given \a tolerance inline bool MatricesEqual(const Matrix &m1, const Matrix &m2, - float tolerance = TOLERANCE) + float tolerance = TOLERANCE) { - for (int i = 0; i < 16; ++i) - { - if (! IsEqual(m1.m[i], m2.m[i], tolerance)) - return false; - } + for (int i = 0; i < 16; ++i) + { + if (! IsEqual(m1.m[i], m2.m[i], tolerance)) + return false; + } - return true; + return true; } //! Convenience function for getting transposed matrix inline Matrix Transpose(const Matrix &m) { - Matrix result = m; - result.Transpose(); - return result; + Matrix result = m; + result.Transpose(); + return result; } //! Convenience function for multiplying a matrix @@ -395,7 +395,7 @@ inline Matrix Transpose(const Matrix &m) \returns multiplied matrices */ inline Matrix MultiplyMatrices(const Matrix &left, const Matrix &right) { - return left.Multiply(right); + return left.Multiply(right); } //! Calculates the result of multiplying m * v @@ -405,27 +405,27 @@ inline Matrix MultiplyMatrices(const Matrix &left, const Matrix &right) [ m.m[2 ] m.m[6 ] m.m[10] m.m[14] ] * [ v.z ] [ m.m[3 ] m.m[7 ] m.m[11] m.m[15] ] [ 1 ] \endverbatim - The result, a 4x1 vector is then converted to 3x1 by dividing - x,y,z coords by the fourth coord (w). */ + The result, a 4x1 vector is then converted to 3x1 by dividing + x,y,z coords by the fourth coord (w). */ inline Vector MatrixVectorMultiply(const Matrix &m, const Vector &v, bool wDivide = false) { - float x = v.x * m.m[0 ] + v.y * m.m[4 ] + v.z * m.m[8 ] + m.m[12]; - float y = v.x * m.m[1 ] + v.y * m.m[5 ] + v.z * m.m[9 ] + m.m[13]; - float z = v.x * m.m[2 ] + v.y * m.m[6 ] + v.z * m.m[10] + m.m[14]; + float x = v.x * m.m[0 ] + v.y * m.m[4 ] + v.z * m.m[8 ] + m.m[12]; + float y = v.x * m.m[1 ] + v.y * m.m[5 ] + v.z * m.m[9 ] + m.m[13]; + float z = v.x * m.m[2 ] + v.y * m.m[6 ] + v.z * m.m[10] + m.m[14]; - if (!wDivide) - return Vector(x, y, z); + if (!wDivide) + return Vector(x, y, z); - float w = v.x * m.m[3 ] + v.y * m.m[7 ] + v.z * m.m[11] + m.m[15]; + float w = v.x * m.m[3 ] + v.y * m.m[7 ] + v.z * m.m[11] + m.m[15]; - if (IsZero(w)) - return Vector(x, y, z); + if (IsZero(w)) + return Vector(x, y, z); - x /= w; - y /= w; - z /= w; + x /= w; + y /= w; + z /= w; - return Vector(x, y, z); + return Vector(x, y, z); } /* @} */ // end of group diff --git a/src/math/point.h b/src/math/point.h index fdb3051..84be190 100644 --- a/src/math/point.h +++ b/src/math/point.h @@ -12,10 +12,10 @@ // * GNU General Public License for more details. // * // * You should have received a copy of the GNU General Public License -// * along with this program. If not, see http://www.gnu.org/licenses/. +// * along with this program. If not, see http://www.gnu.org/licenses/. /** @defgroup MathPointModule math/point.h - Contains the Point struct and related functions. + Contains the Point struct and related functions. */ #pragma once @@ -35,111 +35,111 @@ namespace Math /** \struct Point math/point.h \brief 2D point - Represents a 2D point (x, y). - Contains the required methods for operating on points. + Represents a 2D point (x, y). + Contains the required methods for operating on points. - All methods are made inline to maximize optimization. + All methods are made inline to maximize optimization. */ struct Point { - //! X coord - float x; - //! Y coord - float y; - - //! Constructs a zero point: (0,0) - inline Point() - { - LoadZero(); - } - - //! Constructs a point from given coords: (x,y) - inline explicit Point(float x, float y) - { - this->x = x; - this->y = y; - } - - //! Sets the zero point: (0,0) - inline void LoadZero() - { - x = y = 0.0f; - } - - //! Returns the distance from (0,0) to the point (x,y) - inline float Length() - { - return sqrtf(x*x + y*y); - } - - //! Returns the inverted point - inline Point operator-() const - { - return Point(-x, -y); - } - - //! Adds the given point - inline const Point& operator+=(const Point &right) - { - x += right.x; - y += right.y; - return *this; - } - - //! Adds two points - inline friend const Point operator+(const Point &left, const Point &right) - { - return Point(left.x + right.x, left.y + right.y); - } - - //! Subtracts the given vector - inline const Point& operator-=(const Point &right) - { - x -= right.x; - y -= right.y; - return *this; - } - - //! Subtracts two points - inline friend const Point operator-(const Point &left, const Point &right) - { - return Point(left.x - right.x, left.y - right.y); - } - - //! Multiplies by given scalar - inline const Point& operator*=(const float &right) - { - x *= right; - y *= right; - return *this; - } - - //! Multiplies point by scalar - inline friend const Point operator*(const float &left, const Point &right) - { - return Point(left * right.x, left * right.y); - } - - //! Multiplies point by scalar - inline friend const Point operator*(const Point &left, const float &right) - { - return Point(left.x * right, left.y * right); - } - - //! Divides by given scalar - inline const Point& operator/=(const float &right) - { - x /= right; - y /= right; - return *this; - } - - //! Divides point by scalar - inline friend const Point operator/(const Point &left, const float &right) - { - return Point(left.x / right, left.y / right); - } + //! X coord + float x; + //! Y coord + float y; + + //! Constructs a zero point: (0,0) + inline Point() + { + LoadZero(); + } + + //! Constructs a point from given coords: (x,y) + inline explicit Point(float x, float y) + { + this->x = x; + this->y = y; + } + + //! Sets the zero point: (0,0) + inline void LoadZero() + { + x = y = 0.0f; + } + + //! Returns the distance from (0,0) to the point (x,y) + inline float Length() + { + return sqrtf(x*x + y*y); + } + + //! Returns the inverted point + inline Point operator-() const + { + return Point(-x, -y); + } + + //! Adds the given point + inline const Point& operator+=(const Point &right) + { + x += right.x; + y += right.y; + return *this; + } + + //! Adds two points + inline friend const Point operator+(const Point &left, const Point &right) + { + return Point(left.x + right.x, left.y + right.y); + } + + //! Subtracts the given vector + inline const Point& operator-=(const Point &right) + { + x -= right.x; + y -= right.y; + return *this; + } + + //! Subtracts two points + inline friend const Point operator-(const Point &left, const Point &right) + { + return Point(left.x - right.x, left.y - right.y); + } + + //! Multiplies by given scalar + inline const Point& operator*=(const float &right) + { + x *= right; + y *= right; + return *this; + } + + //! Multiplies point by scalar + inline friend const Point operator*(const float &left, const Point &right) + { + return Point(left * right.x, left * right.y); + } + + //! Multiplies point by scalar + inline friend const Point operator*(const Point &left, const float &right) + { + return Point(left.x * right, left.y * right); + } + + //! Divides by given scalar + inline const Point& operator/=(const float &right) + { + x /= right; + y /= right; + return *this; + } + + //! Divides point by scalar + inline friend const Point operator/(const Point &left, const float &right) + { + return Point(left.x / right, left.y / right); + } }; // struct Point @@ -147,23 +147,23 @@ struct Point //! Checks if two vectors are equal within given \a tolerance inline bool PointsEqual(const Point &a, const Point &b, float tolerance = TOLERANCE) { - return IsEqual(a.x, b.x, tolerance) && IsEqual(a.y, b.y, tolerance); + return IsEqual(a.x, b.x, tolerance) && IsEqual(a.y, b.y, tolerance); } //! Permutes two points inline void Swap(Point &a, Point &b) { - Point c; + Point c; - c = a; - a = b; - b = c; + c = a; + a = b; + b = c; } //! Returns the distance between two points inline float Distance(const Point &a, const Point &b) { - return sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); + return sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } /* @} */ // end of group diff --git a/src/math/test/geometry_test.cpp b/src/math/test/geometry_test.cpp index d6dbd9b..07fa2cf 100644 --- a/src/math/test/geometry_test.cpp +++ b/src/math/test/geometry_test.cpp @@ -35,367 +35,367 @@ const float TEST_TOLERANCE = 1e-5; // Test for rewritten function RotateAngle() int TestRotateAngle() { - if (! Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(1.0f, 0.0f), 0.0f, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(1.0f, 0.0f), 0.0f, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(1.0f, 1.0f), 0.25f * Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(1.0f, 1.0f), 0.25f * Math::PI, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(0.0f, 2.0f), 0.5f * Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(0.0f, 2.0f), 0.5f * Math::PI, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(-0.5f, 0.5f), 0.75f * Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(-0.5f, 0.5f), 0.75f * Math::PI, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(-1.0f, 0.0f), Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(-1.0f, 0.0f), Math::PI, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(-1.0f, -1.0f), 1.25f * Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(-1.0f, -1.0f), 1.25f * Math::PI, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(0.0f, -2.0f), 1.5f * Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(0.0f, -2.0f), 1.5f * Math::PI, TEST_TOLERANCE)) + return __LINE__; - if (! Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE)) - return __LINE__; + if (! Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } // Tests for other altered, complex or uncertain functions int TestAngle() { - const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805); - const Math::Vector v(-1.231228742001907, -1.720549809950561, -0.690468438834111); + const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805); + const Math::Vector v(-1.231228742001907, -1.720549809950561, -0.690468438834111); - float mathResult = Math::Angle(u, v); - float oldMathResult = Angle(VEC_TO_D3DVEC(u), VEC_TO_D3DVEC(v)); + float mathResult = Math::Angle(u, v); + float oldMathResult = Angle(VEC_TO_D3DVEC(u), VEC_TO_D3DVEC(v)); - if (! Math::IsEqual(mathResult, oldMathResult, TEST_TOLERANCE) ) - return __LINE__; + if (! Math::IsEqual(mathResult, oldMathResult, TEST_TOLERANCE) ) + return __LINE__; - return 0; + return 0; } int TestRotateView() { - const Math::Vector center(0.617909142705555, 0.896939729454538, -0.615041943652284); - const float angleH = 44.5; - const float angleV = 12.3; - const float dist = 34.76; + const Math::Vector center(0.617909142705555, 0.896939729454538, -0.615041943652284); + const float angleH = 44.5; + const float angleV = 12.3; + const float dist = 34.76; - Math::Vector mathResult = Math::RotateView(center, angleH, angleV, dist); - Math::Vector oldMathResult = D3DVEC_TO_VEC(RotateView(VEC_TO_D3DVEC(center), angleH, angleV, dist)); + Math::Vector mathResult = Math::RotateView(center, angleH, angleV, dist); + Math::Vector oldMathResult = D3DVEC_TO_VEC(RotateView(VEC_TO_D3DVEC(center), angleH, angleV, dist)); - if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLookatPoint() { - const Math::Vector eye(-2.451183170579471, 0.241270270546559, -0.490677411454893); - const float angleH = 48.4; - const float angleV = 32.4; - const float length = 74.44; + const Math::Vector eye(-2.451183170579471, 0.241270270546559, -0.490677411454893); + const float angleH = 48.4; + const float angleV = 32.4; + const float length = 74.44; - Math::Vector mathResult = Math::LookatPoint(eye, angleH, angleV, length); - Math::Vector oldMathResult = D3DVEC_TO_VEC(LookatPoint(VEC_TO_D3DVEC(eye), angleH, angleV, length)); + Math::Vector mathResult = Math::LookatPoint(eye, angleH, angleV, length); + Math::Vector oldMathResult = D3DVEC_TO_VEC(LookatPoint(VEC_TO_D3DVEC(eye), angleH, angleV, length)); - if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestProjection() { - const Math::Vector a(0.852064846846319, -0.794279497087496, -0.655779805476688); - const Math::Vector b(-0.245838834102304, -0.841115596038861, 0.470457161487799); - const Math::Vector p(2.289326061164255, -0.505511362271196, 0.660204551169491); + const Math::Vector a(0.852064846846319, -0.794279497087496, -0.655779805476688); + const Math::Vector b(-0.245838834102304, -0.841115596038861, 0.470457161487799); + const Math::Vector p(2.289326061164255, -0.505511362271196, 0.660204551169491); - Math::Vector mathResult = Math::Projection(a, b, p); - Math::Vector oldMathResult = D3DVEC_TO_VEC(Projection(VEC_TO_D3DVEC(a), VEC_TO_D3DVEC(b), VEC_TO_D3DVEC(p))); + Math::Vector mathResult = Math::Projection(a, b, p); + Math::Vector oldMathResult = D3DVEC_TO_VEC(Projection(VEC_TO_D3DVEC(a), VEC_TO_D3DVEC(b), VEC_TO_D3DVEC(p))); - if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadViewMatrix() { - const Math::Vector from(2.5646013154868874, -0.6058794133917031, -0.0441195127419744); - const Math::Vector at(0.728044925765569, -0.206343977871841, 2.543158236935463); - const Math::Vector worldUp(-1.893738133660711, -1.009584441407070, 0.521745988225582); - - Math::Matrix mathResult; - Math::LoadViewMatrix(mathResult, from, at, worldUp); - - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DVECTOR fromD3D = VEC_TO_D3DVEC(from); - D3DVECTOR atD3D = VEC_TO_D3DVEC(at); - D3DVECTOR worldUpD3D = VEC_TO_D3DVEC(worldUp); - D3DUtil_SetViewMatrix(mat, fromD3D, atD3D, worldUpD3D); - oldMathResult = D3DMAT_TO_MAT(mat); - } - - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; - - return 0; + const Math::Vector from(2.5646013154868874, -0.6058794133917031, -0.0441195127419744); + const Math::Vector at(0.728044925765569, -0.206343977871841, 2.543158236935463); + const Math::Vector worldUp(-1.893738133660711, -1.009584441407070, 0.521745988225582); + + Math::Matrix mathResult; + Math::LoadViewMatrix(mathResult, from, at, worldUp); + + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DVECTOR fromD3D = VEC_TO_D3DVEC(from); + D3DVECTOR atD3D = VEC_TO_D3DVEC(at); + D3DVECTOR worldUpD3D = VEC_TO_D3DVEC(worldUp); + D3DUtil_SetViewMatrix(mat, fromD3D, atD3D, worldUpD3D); + oldMathResult = D3DMAT_TO_MAT(mat); + } + + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; } int TestLoadProjectionMatrix() { - const float fov = 76.3f; - const float aspect = 0.891f; - const float nearPlane = 12.3f; - const float farPlane = 1238.9f; + const float fov = 76.3f; + const float aspect = 0.891f; + const float nearPlane = 12.3f; + const float farPlane = 1238.9f; - Math::Matrix mathResult; - Math::LoadProjectionMatrix(mathResult, fov, aspect, nearPlane, farPlane); + Math::Matrix mathResult; + Math::LoadProjectionMatrix(mathResult, fov, aspect, nearPlane, farPlane); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DUtil_SetProjectionMatrix(mat, fov, aspect, nearPlane, farPlane); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetProjectionMatrix(mat, fov, aspect, nearPlane, farPlane); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadTranslationMatrix() { - const Math::Vector translation(-0.3631590720995237, 1.6976327614875211, 0.0148815191502145); + const Math::Vector translation(-0.3631590720995237, 1.6976327614875211, 0.0148815191502145); - Math::Matrix mathResult; - Math::LoadTranslationMatrix(mathResult, translation); + Math::Matrix mathResult; + Math::LoadTranslationMatrix(mathResult, translation); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DUtil_SetTranslateMatrix(mat, translation.x, translation.y, translation.z); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetTranslateMatrix(mat, translation.x, translation.y, translation.z); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadScaleMatrix() { - const Math::Vector scale(0.612236460285503, -0.635566935025364, -0.254321375332065); + const Math::Vector scale(0.612236460285503, -0.635566935025364, -0.254321375332065); - Math::Matrix mathResult; - Math::LoadScaleMatrix(mathResult, scale); + Math::Matrix mathResult; + Math::LoadScaleMatrix(mathResult, scale); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DUtil_SetScaleMatrix(mat, scale.x, scale.y, scale.z); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetScaleMatrix(mat, scale.x, scale.y, scale.z); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadRotationXMatrix() { - const float angle = 0.513790685774275; + const float angle = 0.513790685774275; - Math::Matrix mathResult; - Math::LoadRotationXMatrix(mathResult, angle); + Math::Matrix mathResult; + Math::LoadRotationXMatrix(mathResult, angle); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DUtil_SetRotateXMatrix(mat, angle); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetRotateXMatrix(mat, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadRotationYMatrix() { - const float angle = -0.569166650127303; + const float angle = -0.569166650127303; - Math::Matrix mathResult; - Math::LoadRotationYMatrix(mathResult, angle); + Math::Matrix mathResult; + Math::LoadRotationYMatrix(mathResult, angle); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DUtil_SetRotateYMatrix(mat, angle); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetRotateYMatrix(mat, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadRotationZMatrix() { - const float angle = 0.380448034347452; + const float angle = 0.380448034347452; - Math::Matrix mathResult; - Math::LoadRotationZMatrix(mathResult, angle); + Math::Matrix mathResult; + Math::LoadRotationZMatrix(mathResult, angle); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DUtil_SetRotateZMatrix(mat, angle); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DUtil_SetRotateZMatrix(mat, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadRotationMatrix() { - const float angle = -0.987747190637790; - const Math::Vector dir(-0.113024727688331, -0.781265998072571, 1.838972397076884); + const float angle = -0.987747190637790; + const Math::Vector dir(-0.113024727688331, -0.781265998072571, 1.838972397076884); - Math::Matrix mathResult; - Math::LoadRotationMatrix(mathResult, dir, angle); + Math::Matrix mathResult; + Math::LoadRotationMatrix(mathResult, dir, angle); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - D3DVECTOR dirD3D = VEC_TO_D3DVEC(dir); - D3DUtil_SetRotationMatrix(mat, dirD3D, angle); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + D3DVECTOR dirD3D = VEC_TO_D3DVEC(dir); + D3DUtil_SetRotationMatrix(mat, dirD3D, angle); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadRotationXZYMatrix() { - const Math::Vector angles(-0.841366567984597, -0.100543315396357, 1.610647811559988); + const Math::Vector angles(-0.841366567984597, -0.100543315396357, 1.610647811559988); - Math::Matrix mathResult; - Math::LoadRotationXZYMatrix(mathResult, angles); + Math::Matrix mathResult; + Math::LoadRotationXZYMatrix(mathResult, angles); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - MatRotateXZY(mat, VEC_TO_D3DVEC(angles)); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + MatRotateXZY(mat, VEC_TO_D3DVEC(angles)); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestLoadRotationZXYMatrix() { - const Math::Vector angles(0.275558495480206, -0.224328265970090, 0.943077216574253); + const Math::Vector angles(0.275558495480206, -0.224328265970090, 0.943077216574253); - Math::Matrix mathResult; - Math::LoadRotationZXYMatrix(mathResult, angles); + Math::Matrix mathResult; + Math::LoadRotationZXYMatrix(mathResult, angles); - Math::Matrix oldMathResult; - { - D3DMATRIX mat; - MatRotateZXY(mat, VEC_TO_D3DVEC(angles)); - oldMathResult = D3DMAT_TO_MAT(mat); - } + Math::Matrix oldMathResult; + { + D3DMATRIX mat; + MatRotateZXY(mat, VEC_TO_D3DVEC(angles)); + oldMathResult = D3DMAT_TO_MAT(mat); + } - if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; + if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; - return 0; + return 0; } int TestTransform() { - Math::Matrix transformMatrix( - (float[4][4]) - { - { -0.9282074720977896, 0.6794734970319730, -1.3234304946882685, 0.0925294727863890 }, - { -0.0395527963683484, 0.2897634352353881, 1.9144398570315440, -1.4062267508968478 }, - { 0.9133323625282361, -0.6741836434774530, -0.2188812951424338, -1.0089184339952666 }, - { 0.0f, 0.0f, 0.0f, 1.0f } - } - ); - Math::Vector vector(-0.314596433318370, -0.622681232583150, -0.371307535743574); - - Math::Vector mathResult = Math::Transform(transformMatrix, vector); - Math::Vector oldMathResult = Transform(transformMatrix, vector); - - if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) - return __LINE__; - - return 0; + Math::Matrix transformMatrix( + (float[4][4]) + { + { -0.9282074720977896, 0.6794734970319730, -1.3234304946882685, 0.0925294727863890 }, + { -0.0395527963683484, 0.2897634352353881, 1.9144398570315440, -1.4062267508968478 }, + { 0.9133323625282361, -0.6741836434774530, -0.2188812951424338, -1.0089184339952666 }, + { 0.0f, 0.0f, 0.0f, 1.0f } + } + ); + Math::Vector vector(-0.314596433318370, -0.622681232583150, -0.371307535743574); + + Math::Vector mathResult = Math::Transform(transformMatrix, vector); + Math::Vector oldMathResult = Transform(transformMatrix, vector); + + if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE)) + return __LINE__; + + return 0; } int main() { - // Functions to test - int (*TESTS[])() = - { - TestRotateAngle, - TestAngle, - TestRotateView, - TestLookatPoint, - TestProjection, - TestLoadViewMatrix, - TestLoadProjectionMatrix, - TestLoadTranslationMatrix, - TestLoadScaleMatrix, - TestLoadRotationXMatrix, - TestLoadRotationYMatrix, - TestLoadRotationZMatrix, - TestLoadRotationMatrix, - TestLoadRotationXZYMatrix, - TestLoadRotationZXYMatrix, - TestTransform - }; - const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS); - - int result = 0; - for (int i = 0; i < TESTS_SIZE; ++i) - { - result = TESTS[i](); - if (result != 0) + // Functions to test + int (*TESTS[])() = + { + TestRotateAngle, + TestAngle, + TestRotateView, + TestLookatPoint, + TestProjection, + TestLoadViewMatrix, + TestLoadProjectionMatrix, + TestLoadTranslationMatrix, + TestLoadScaleMatrix, + TestLoadRotationXMatrix, + TestLoadRotationYMatrix, + TestLoadRotationZMatrix, + TestLoadRotationMatrix, + TestLoadRotationXZYMatrix, + TestLoadRotationZXYMatrix, + TestTransform + }; + const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS); + + int result = 0; + for (int i = 0; i < TESTS_SIZE; ++i) { - fprintf(stderr, "Test function %d failed at line %d\n", i+1, result); - return result; + result = TESTS[i](); + if (result != 0) + { + fprintf(stderr, "Test function %d failed at line %d\n", i+1, result); + return result; + } } - } - fprintf(stderr, "All tests successful\n"); + fprintf(stderr, "All tests successful\n"); - return 0; + return 0; } diff --git a/src/math/test/matrix_test.cpp b/src/math/test/matrix_test.cpp index 95f1ed7..663234c 100644 --- a/src/math/test/matrix_test.cpp +++ b/src/math/test/matrix_test.cpp @@ -16,11 +16,11 @@ // math/test/matrix_test.cpp -/* Unit tests for Matrix struct - - Test data was randomly generated and the expected results - calculated using GNU Octave. +/* + Unit tests for Matrix struct + Test data was randomly generated and the expected results + calculated using GNU Octave. */ #include "../func.h" @@ -34,369 +34,369 @@ const float TEST_TOLERANCE = 1e-6; int TestTranspose() { - const Math::Matrix mat( - (float[4][4]) - { - { -0.07011674491203920, 1.26145596067429810, 2.09476603598066902, 0.35560176915570696 }, - { -1.34075615966224704, 1.17988499016709314, 0.00601713429241016, -0.75213676977972566 }, - { 0.59186722295223981, 0.88089224074765293, 0.70994467464257294, 0.36730385425340212 }, - { -0.95649396555068111, 0.75912182022565566, 1.34883305778387186, -1.34957997578168754 } - } - ); - - const Math::Matrix expectedTranspose( - (float[4][4]) + const Math::Matrix mat( + (float[4][4]) + { + { -0.07011674491203920, 1.26145596067429810, 2.09476603598066902, 0.35560176915570696 }, + { -1.34075615966224704, 1.17988499016709314, 0.00601713429241016, -0.75213676977972566 }, + { 0.59186722295223981, 0.88089224074765293, 0.70994467464257294, 0.36730385425340212 }, + { -0.95649396555068111, 0.75912182022565566, 1.34883305778387186, -1.34957997578168754 } + } + ); + + const Math::Matrix expectedTranspose( + (float[4][4]) + { + { -0.07011674491203920, -1.34075615966224704, 0.59186722295223981, -0.95649396555068111 }, + { 1.26145596067429810, 1.17988499016709314, 0.88089224074765293, 0.75912182022565566 }, + { 2.09476603598066902, 0.00601713429241016, 0.70994467464257294, 1.34883305778387186 }, + { 0.35560176915570696, -0.75213676977972566, 0.36730385425340212, -1.34957997578168754 } + } + ); + + Math::Matrix transpose = Math::Transpose(mat); + + if (! Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE)) { - { -0.07011674491203920, -1.34075615966224704, 0.59186722295223981, -0.95649396555068111 }, - { 1.26145596067429810, 1.17988499016709314, 0.88089224074765293, 0.75912182022565566 }, - { 2.09476603598066902, 0.00601713429241016, 0.70994467464257294, 1.34883305778387186 }, - { 0.35560176915570696, -0.75213676977972566, 0.36730385425340212, -1.34957997578168754 } + fprintf(stderr, "Transpose mismatch!\n"); + return __LINE__; } - ); - - Math::Matrix transpose = Math::Transpose(mat); - if (! Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE)) - { - fprintf(stderr, "Transpose mismatch!\n"); - return __LINE__; - } - - return 0; + return 0; } int TestCofactor() { - const Math::Matrix mat1( - (float[4][4]) - { - { 0.610630320796245, 1.059932357918312, -1.581674311378210, 1.782214448453331 }, - { 0.191028848211526, -0.813898708757524, 1.516114203870644, 0.395202639476002 }, - { 0.335142750345279, -0.346586619596529, 0.545382042472336, -0.879268918923072 }, - { 1.417588151657198, 1.450841789070141, 0.219080104196171, 0.378724047481655 } - } - ); - - const Math::Matrix expectedCofactors1( - (float[4][4]) - { - { -2.402679369186782, 2.282452509293019, 1.722732204057644, -0.746939701104385 }, - { -0.687677756877654, 1.168949180331164, -0.985354966837796, -1.334071111592705 }, - { -5.115621958424845, 4.229724770159009, 2.529000630782808, 1.481632618355891 }, - { 0.147480897398694, -2.140677680337111, -1.207189492265546, 0.151236920408051 } - } - ); - - for (int r = 0; r < 4; ++r) - { - for (int c = 0; c < 4; ++c) - { - float ret = mat1.Cofactor(r, c); - float exp = expectedCofactors1.m[4*c+r]; - if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) - { - fprintf(stderr, "Cofactors 1 mismatch!\n"); - fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp); - return __LINE__; - } - } - } - - const Math::Matrix mat2( - (float[4][4]) - { - { 0.9845099464982393, -0.9091233416532389, -0.6272243714245945, 0.4645001858944354 }, - { -0.1333308471483736, 0.9128181433725897, -1.0937461393836190, 0.3180936795928376 }, - { -0.0654324396846289, 0.1014641705415945, 1.5107709042683430, -0.0240560430414690 }, - { 0.0179638644093347, -1.0695585982782767, -0.1741250853101032, 1.0803106709464336 } - } - ); - - const Math::Matrix expectedCofactors2( - (float[4][4]) + const Math::Matrix mat1( + (float[4][4]) + { + { 0.610630320796245, 1.059932357918312, -1.581674311378210, 1.782214448453331 }, + { 0.191028848211526, -0.813898708757524, 1.516114203870644, 0.395202639476002 }, + { 0.335142750345279, -0.346586619596529, 0.545382042472336, -0.879268918923072 }, + { 1.417588151657198, 1.450841789070141, 0.219080104196171, 0.378724047481655 } + } + ); + + const Math::Matrix expectedCofactors1( + (float[4][4]) + { + { -2.402679369186782, 2.282452509293019, 1.722732204057644, -0.746939701104385 }, + { -0.687677756877654, 1.168949180331164, -0.985354966837796, -1.334071111592705 }, + { -5.115621958424845, 4.229724770159009, 2.529000630782808, 1.481632618355891 }, + { 0.147480897398694, -2.140677680337111, -1.207189492265546, 0.151236920408051 } + } + ); + + for (int r = 0; r < 4; ++r) { - { 2.0861102207614466, 0.2989010779528912, 0.0746276150537432, 0.2732659822656097 }, - { 0.6850002886584565, 1.5513169659641379, -0.0503743176545917, 1.5163672441575642 }, - { 1.2385556680997216, 1.1827709562505695, 1.2282813085138962, 1.3483789679871401 }, - { -1.0710790241539783, -0.5589604503588883, 0.0100959837872308, 1.1897872684455839 } + for (int c = 0; c < 4; ++c) + { + float ret = mat1.Cofactor(r, c); + float exp = expectedCofactors1.m[4*c+r]; + if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) + { + fprintf(stderr, "Cofactors 1 mismatch!\n"); + fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp); + return __LINE__; + } + } } - ); - - for (int r = 0; r < 4; ++r) - { - for (int c = 0; c < 4; ++c) + const Math::Matrix mat2( + (float[4][4]) + { + { 0.9845099464982393, -0.9091233416532389, -0.6272243714245945, 0.4645001858944354 }, + { -0.1333308471483736, 0.9128181433725897, -1.0937461393836190, 0.3180936795928376 }, + { -0.0654324396846289, 0.1014641705415945, 1.5107709042683430, -0.0240560430414690 }, + { 0.0179638644093347, -1.0695585982782767, -0.1741250853101032, 1.0803106709464336 } + } + ); + + const Math::Matrix expectedCofactors2( + (float[4][4]) + { + { 2.0861102207614466, 0.2989010779528912, 0.0746276150537432, 0.2732659822656097 }, + { 0.6850002886584565, 1.5513169659641379, -0.0503743176545917, 1.5163672441575642 }, + { 1.2385556680997216, 1.1827709562505695, 1.2282813085138962, 1.3483789679871401 }, + { -1.0710790241539783, -0.5589604503588883, 0.0100959837872308, 1.1897872684455839 } + } + ); + + + for (int r = 0; r < 4; ++r) { - float ret = mat2.Cofactor(r, c); - float exp = expectedCofactors2.m[4*c+r]; - if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) - { - fprintf(stderr, "Cofactors 2 mismatch!\n"); - fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp); - return __LINE__; - } + for (int c = 0; c < 4; ++c) + { + float ret = mat2.Cofactor(r, c); + float exp = expectedCofactors2.m[4*c+r]; + if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) + { + fprintf(stderr, "Cofactors 2 mismatch!\n"); + fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp); + return __LINE__; + } + } } - } - return 0; + return 0; } int TestDet() { - const Math::Matrix mat1( - (float[4][4]) + const Math::Matrix mat1( + (float[4][4]) + { + { -0.95880162984708284, 0.24004047608997131, -0.78172309932665407, -0.11604124457222834 }, + { -0.36230592086261376, -0.75778166876017261, 0.33041059404631740, -1.06001391941094836 }, + { 0.00260215210936187, 1.27485610196385113, -0.26149859846418033, -0.59669701186364876 }, + { 0.36899429848485432, 3.01720896813933104, 2.10311476609438719, -1.68627076626448269 } + } + ); + + const float expectedDet1 = 4.07415413729671; + + float ret1 = mat1.Det(); + if (! Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE)) { - { -0.95880162984708284, 0.24004047608997131, -0.78172309932665407, -0.11604124457222834 }, - { -0.36230592086261376, -0.75778166876017261, 0.33041059404631740, -1.06001391941094836 }, - { 0.00260215210936187, 1.27485610196385113, -0.26149859846418033, -0.59669701186364876 }, - { 0.36899429848485432, 3.01720896813933104, 2.10311476609438719, -1.68627076626448269 } + fprintf(stderr, "Det mismatch!\n"); + fprintf(stderr, "%f (returned) != %f (expected)\n", ret1, expectedDet1); + return __LINE__; } - ); - const float expectedDet1 = 4.07415413729671; + const Math::Matrix mat2( + (float[4][4]) + { + { -1.0860073221346871, 0.9150354098189495, -0.2723201933559999, 0.2922832160271507 }, + { -1.0248331304801788, -2.5081237461125205, -1.0277123574586633, -0.2254690663329798 }, + { -1.4227635282899367, -0.0403846809122684, 0.9216148477171653, 1.2517067488015878 }, + { -0.1160254467152022, 0.8270675274393656, 1.0327218739781614, -0.3674886870220400 } + } + ); - float ret1 = mat1.Det(); - if (! Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE)) - { - fprintf(stderr, "Det mismatch!\n"); - fprintf(stderr, "%f (returned) != %f (expected)\n", ret1, expectedDet1); - return __LINE__; - } + const float expectedDet2 = -6.35122307880942; - const Math::Matrix mat2( - (float[4][4]) + float ret2 = mat2.Det(); + if (! Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE)) { - { -1.0860073221346871, 0.9150354098189495, -0.2723201933559999, 0.2922832160271507 }, - { -1.0248331304801788, -2.5081237461125205, -1.0277123574586633, -0.2254690663329798 }, - { -1.4227635282899367, -0.0403846809122684, 0.9216148477171653, 1.2517067488015878 }, - { -0.1160254467152022, 0.8270675274393656, 1.0327218739781614, -0.3674886870220400 } + fprintf(stderr, "Det mismatch!\n"); + fprintf(stderr, "%f (returned) != %f (expected)\n", ret2, expectedDet2); + return __LINE__; } - ); - const float expectedDet2 = -6.35122307880942; - - float ret2 = mat2.Det(); - if (! Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE)) - { - fprintf(stderr, "Det mismatch!\n"); - fprintf(stderr, "%f (returned) != %f (expected)\n", ret2, expectedDet2); - return __LINE__; - } - - return 0; + return 0; } int TestInverse() { - const Math::Matrix mat1( - (float[4][4]) - { - { -2.2829352811514658, -0.9103222363187888, 0.2792976509411680, -0.7984393573193174 }, - { 2.4823665798689589, -0.0599056759070980, 0.3832364352926366, -1.6404257204372739 }, - { -0.3841952272526398, -0.8377700696457873, -0.3416328338427138, 1.1746577275723329 }, - { 0.1746031241954947, -0.4952532117949962, 0.2155084379835037, -1.6586460437329220 } - } - ); - - const Math::Matrix expectedInverse1( - (float[4][4]) - { - { -0.119472603171041, 0.331675963276297, 0.187516809009720, -0.137720814290806 }, - { -0.387591686166085, -0.487284946727583, -0.798527541290274, 0.102991635972060 }, - { 2.601905603425902, 2.606899016264679, -0.528006148839176, -4.204703326522837 }, - { 0.441220327151392, 0.519128136207318, 0.189567009205522, -1.194469716136194 } - } - ); - - Math::Matrix inverse1 = mat1.Inverse(); - - if (! Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE)) - { - fprintf(stderr, "Inverse 1 mismatch!\n"); - return __LINE__; - } - - const Math::Matrix mat2( - (float[4][4]) + const Math::Matrix mat1( + (float[4][4]) + { + { -2.2829352811514658, -0.9103222363187888, 0.2792976509411680, -0.7984393573193174 }, + { 2.4823665798689589, -0.0599056759070980, 0.3832364352926366, -1.6404257204372739 }, + { -0.3841952272526398, -0.8377700696457873, -0.3416328338427138, 1.1746577275723329 }, + { 0.1746031241954947, -0.4952532117949962, 0.2155084379835037, -1.6586460437329220 } + } + ); + + const Math::Matrix expectedInverse1( + (float[4][4]) + { + { -0.119472603171041, 0.331675963276297, 0.187516809009720, -0.137720814290806 }, + { -0.387591686166085, -0.487284946727583, -0.798527541290274, 0.102991635972060 }, + { 2.601905603425902, 2.606899016264679, -0.528006148839176, -4.204703326522837 }, + { 0.441220327151392, 0.519128136207318, 0.189567009205522, -1.194469716136194 } + } + ); + + Math::Matrix inverse1 = mat1.Inverse(); + + if (! Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE)) { - { -0.05464332404298505, -0.64357755258235749, -0.13017671677619302, -0.56742332785888006 }, - { 0.29048383600458222, -0.91517047043724875, 0.84517524415561684, 0.51628195547960565 }, - { 0.00946488004480186, -0.89077382212689293, 0.73565573766341397, -0.15932513521840930 }, - { -1.01244718912499132, -0.27840911963972276, -0.39189681211309862, 1.18315064340192055 } + fprintf(stderr, "Inverse 1 mismatch!\n"); + return __LINE__; } - ); - const Math::Matrix expectedInverse2( - (float[4][4]) + const Math::Matrix mat2( + (float[4][4]) + { + { -0.05464332404298505, -0.64357755258235749, -0.13017671677619302, -0.56742332785888006 }, + { 0.29048383600458222, -0.91517047043724875, 0.84517524415561684, 0.51628195547960565 }, + { 0.00946488004480186, -0.89077382212689293, 0.73565573766341397, -0.15932513521840930 }, + { -1.01244718912499132, -0.27840911963972276, -0.39189681211309862, 1.18315064340192055 } + } + ); + + const Math::Matrix expectedInverse2( + (float[4][4]) + { + { 0.771302711132012, 1.587542278361995, -2.003075114445104, -0.592574156227379 }, + { -1.208929259769431, -0.786598967848473, 0.607335305808052, -0.154759693303324 }, + { -1.500037668208218, -0.774300278997914, 1.917800427261255, -0.123268572651291 }, + { -0.121314770937944, 0.916925149209746, -0.935924950785014, 0.260875394250671 } + } + ); + + Math::Matrix inverse2 = mat2.Inverse(); + + if (! Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE)) { - { 0.771302711132012, 1.587542278361995, -2.003075114445104, -0.592574156227379 }, - { -1.208929259769431, -0.786598967848473, 0.607335305808052, -0.154759693303324 }, - { -1.500037668208218, -0.774300278997914, 1.917800427261255, -0.123268572651291 }, - { -0.121314770937944, 0.916925149209746, -0.935924950785014, 0.260875394250671 } + fprintf(stderr, "Inverse 2 mismatch!\n"); + return __LINE__; } - ); - Math::Matrix inverse2 = mat2.Inverse(); - - if (! Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE)) - { - fprintf(stderr, "Inverse 2 mismatch!\n"); - return __LINE__; - } - - return 0; + return 0; } int TestMultiply() { - const Math::Matrix mat1A( - (float[4][4]) - { - { 0.6561727049162027, -1.4180263627131411, -0.8271026046117423, 2.3919331748512578 }, - { -0.6035665535146352, 0.0150827348790615, -0.7090794192822540, 0.9057604704594814 }, - { -0.9871045001223655, -0.4980646811455065, 0.3806177002298990, 0.1520583649240934 }, - { -0.2721911170792712, 0.7627928194552067, -0.1504091336784158, 0.9747545351840121 } - } - ); - - const Math::Matrix mat1B( - (float[4][4]) - { - { -0.2643735892448818, -0.7542994492819621, 0.6082322350568750, 0.0581733424861419 }, - { 1.0293246070431237, 0.1979285388251341, -0.2932031385332818, 0.8838407179018929 }, - { 0.3448687251553114, 0.5031654871245456, 0.7554693012922442, -0.4845315903845708 }, - { -1.8662838497278593, -0.7843850624747805, 0.1389026096476257, -1.3686415408300689 } - } - ); - - const Math::Matrix expectedMultiply1( - (float[4][4]) - { - { -6.382352236417988, -3.067984733682130, 0.522270304251466, -4.088079444498280 }, - { -1.759853366848825, -0.608994052024491, -0.781406179437379, -0.917870775786188 }, - { -0.404226802169062, 0.718232546720114, -0.145688356880835, -0.890167707987175 }, - { -1.013918490922430, -0.483971504099758, -0.367442194643757, -0.602858486133615 } - } - ); - - Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B); - if (! Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) ) - { - fprintf(stderr, "Multiply 1 mismath!\n"); - return __LINE__; - } - - const Math::Matrix mat2A( - (float[4][4]) + const Math::Matrix mat1A( + (float[4][4]) + { + { 0.6561727049162027, -1.4180263627131411, -0.8271026046117423, 2.3919331748512578 }, + { -0.6035665535146352, 0.0150827348790615, -0.7090794192822540, 0.9057604704594814 }, + { -0.9871045001223655, -0.4980646811455065, 0.3806177002298990, 0.1520583649240934 }, + { -0.2721911170792712, 0.7627928194552067, -0.1504091336784158, 0.9747545351840121 } + } + ); + + const Math::Matrix mat1B( + (float[4][4]) + { + { -0.2643735892448818, -0.7542994492819621, 0.6082322350568750, 0.0581733424861419 }, + { 1.0293246070431237, 0.1979285388251341, -0.2932031385332818, 0.8838407179018929 }, + { 0.3448687251553114, 0.5031654871245456, 0.7554693012922442, -0.4845315903845708 }, + { -1.8662838497278593, -0.7843850624747805, 0.1389026096476257, -1.3686415408300689 } + } + ); + + const Math::Matrix expectedMultiply1( + (float[4][4]) + { + { -6.382352236417988, -3.067984733682130, 0.522270304251466, -4.088079444498280 }, + { -1.759853366848825, -0.608994052024491, -0.781406179437379, -0.917870775786188 }, + { -0.404226802169062, 0.718232546720114, -0.145688356880835, -0.890167707987175 }, + { -1.013918490922430, -0.483971504099758, -0.367442194643757, -0.602858486133615 } + } + ); + + Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B); + if (! Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) ) { - { 0.8697203025776754, 2.1259475710644935, 1.7856691009707812, -2.1563963348328126 }, - { 1.5888074489288735, -0.0794849733953615, 0.7307782768677457, 0.7943129159612630 }, - { 0.2859761537233830, -0.6231231890384962, -0.0496743172880377, -0.8137857518646087 }, - { 1.2670547229512983, -0.5305171374831831, -0.4987412674062375, -1.1257327113869595 } - } - ); - - const Math::Matrix mat2B( - (float[4][4]) - { - { 1.1321105701165317, 0.1759563504574463, -2.0675778912000418, 1.4840339814245538 }, - { -1.5117280888829916, -0.0933013188828093, -0.2079262944351640, 0.9575727579539316 }, - { 0.3615378398970173, 1.2465163589027248, 1.1326150997082589, 0.9921208694352303 }, - { -0.7357104529373861, -0.4774022005969588, -0.2118739096676499, 1.1427567093270703 } + fprintf(stderr, "Multiply 1 mismath!\n"); + return __LINE__; } - ); - const Math::Matrix expectedMultiply2( - (float[4][4]) + const Math::Matrix mat2A( + (float[4][4]) + { + { 0.8697203025776754, 2.1259475710644935, 1.7856691009707812, -2.1563963348328126 }, + { 1.5888074489288735, -0.0794849733953615, 0.7307782768677457, 0.7943129159612630 }, + { 0.2859761537233830, -0.6231231890384962, -0.0496743172880377, -0.8137857518646087 }, + { 1.2670547229512983, -0.5305171374831831, -0.4987412674062375, -1.1257327113869595 } + } + ); + + const Math::Matrix mat2B( + (float[4][4]) + { + { 1.1321105701165317, 0.1759563504574463, -2.0675778912000418, 1.4840339814245538 }, + { -1.5117280888829916, -0.0933013188828093, -0.2079262944351640, 0.9575727579539316 }, + { 0.3615378398970173, 1.2465163589027248, 1.1326150997082589, 0.9921208694352303 }, + { -0.7357104529373861, -0.4774022005969588, -0.2118739096676499, 1.1427567093270703 } + } + ); + + const Math::Matrix expectedMultiply2( + (float[4][4]) + { + { 0.00283516267056338, 3.21001319965989307, 0.23910503934370686, 2.63380716363006107 }, + { 1.59868505822469742, 0.81869715594617765, -2.60905981088293570, 3.91445839239110294 }, + { 1.84650099286297942, 0.43504079532852930, -0.34555619012424243, -1.15152951542451487 }, + { 2.88434318563174585, 0.18818239851585700, -2.83579436909308980, -0.40890672198610400 } + } + ); + + Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B); + if (! Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) ) { - { 0.00283516267056338, 3.21001319965989307, 0.23910503934370686, 2.63380716363006107 }, - { 1.59868505822469742, 0.81869715594617765, -2.60905981088293570, 3.91445839239110294 }, - { 1.84650099286297942, 0.43504079532852930, -0.34555619012424243, -1.15152951542451487 }, - { 2.88434318563174585, 0.18818239851585700, -2.83579436909308980, -0.40890672198610400 } + fprintf(stderr, "Multiply 2 mismath!\n"); + return __LINE__; } - ); - - Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B); - if (! Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) ) - { - fprintf(stderr, "Multiply 2 mismath!\n"); - return __LINE__; - } - return 0; + return 0; } int TestMultiplyVector() { - const Math::Matrix mat1( - (float[4][4]) + const Math::Matrix mat1( + (float[4][4]) + { + { 0.188562846910008, -0.015148651460679, 0.394512304108827, 0.906910631257135 }, + { -0.297506779519667, 0.940119328178913, 0.970957796752517, 0.310559318965526 }, + { -0.819770525290873, -2.316574438778879, 0.155756069319732, -0.855661405742964 }, + { 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000 } + } + ); + + const Math::Vector vec1(-0.824708565156661, -1.598287748103842, -0.422498044734181); + + const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142); + + Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false); + if (! Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) ) { - { 0.188562846910008, -0.015148651460679, 0.394512304108827, 0.906910631257135 }, - { -0.297506779519667, 0.940119328178913, 0.970957796752517, 0.310559318965526 }, - { -0.819770525290873, -2.316574438778879, 0.155756069319732, -0.855661405742964 }, - { 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000 } + fprintf(stderr, "Multiply vector 1 mismath!\n"); + return __LINE__; } - ); - const Math::Vector vec1(-0.824708565156661, -1.598287748103842, -0.422498044734181); + const Math::Matrix mat2( + (float[4][4]) + { + { -0.63287117038834284, 0.55148060401816856, -0.02042395559467368, -1.50367083897656850 }, + { 0.69629042156335297, 0.12982747869796774, -1.16250029235919405, 1.19084447253756909 }, + { 0.44164132914357224, -0.15169304045662041, -0.00880583574621390, -0.55817802940035310 }, + { 0.95680476533530789, -1.51912346889253125, -0.74209769406615944, -0.20938988867903682 } + } + ); - const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142); + const Math::Vector vec2(0.330987381051962, 1.494375516393466, 1.483422335561857); - Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false); - if (! Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) ) - { - fprintf(stderr, "Multiply vector 1 mismath!\n"); - return __LINE__; - } + const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455); - const Math::Matrix mat2( - (float[4][4]) + Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true); + if (! Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) ) { - { -0.63287117038834284, 0.55148060401816856, -0.02042395559467368, -1.50367083897656850 }, - { 0.69629042156335297, 0.12982747869796774, -1.16250029235919405, 1.19084447253756909 }, - { 0.44164132914357224, -0.15169304045662041, -0.00880583574621390, -0.55817802940035310 }, - { 0.95680476533530789, -1.51912346889253125, -0.74209769406615944, -0.20938988867903682 } + fprintf(stderr, "Multiply vector 2 mismath!\n"); + return __LINE__; } - ); - const Math::Vector vec2(0.330987381051962, 1.494375516393466, 1.483422335561857); - - const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455); - - Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true); - if (! Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) ) - { - fprintf(stderr, "Multiply vector 2 mismath!\n"); - return __LINE__; - } - - return 0; + return 0; } int main() { - // Functions to test - int (*TESTS[])() = - { - TestTranspose, - TestCofactor, - TestDet, - TestInverse, - TestMultiply, - TestMultiplyVector - }; - const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS); - - int result = 0; - for (int i = 0; i < TESTS_SIZE; ++i) - { - result = TESTS[i](); - if (result != 0) - return result; - } - - fprintf(stderr, "All tests successful\n"); - - return 0; + // Functions to test + int (*TESTS[])() = + { + TestTranspose, + TestCofactor, + TestDet, + TestInverse, + TestMultiply, + TestMultiplyVector + }; + const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS); + + int result = 0; + for (int i = 0; i < TESTS_SIZE; ++i) + { + result = TESTS[i](); + if (result != 0) + return result; + } + + fprintf(stderr, "All tests successful\n"); + + return 0; } diff --git a/src/math/test/vector_test.cpp b/src/math/test/vector_test.cpp index d2bf231..899a580 100644 --- a/src/math/test/vector_test.cpp +++ b/src/math/test/vector_test.cpp @@ -16,11 +16,11 @@ // math/test/vector_test.cpp -/* Unit tests for Vector struct - - Test data was randomly generated and the expected results - calculated using GNU Octave. +/* + Unit tests for Vector struct + Test data was randomly generated and the expected results + calculated using GNU Octave. */ #include "../func.h" @@ -34,94 +34,94 @@ const float TEST_TOLERANCE = 1e-6; int TestLength() { - Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957); - const float expectedLength = 1.58938001708428; + Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957); + const float expectedLength = 1.58938001708428; - if (! Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE) ) - { - fprintf(stderr, "Length mismatch!\n"); - return __LINE__; - } + if (! Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE) ) + { + fprintf(stderr, "Length mismatch!\n"); + return __LINE__; + } - return 0; + return 0; } int TestNormalize() { - Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377); - const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797); + Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377); + const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797); - vec.Normalize(); + vec.Normalize(); - if (! Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE)) - { - fprintf(stderr, "Normalize mismatch!\n"); - return __LINE__; - } + if (! Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE)) + { + fprintf(stderr, "Normalize mismatch!\n"); + return __LINE__; + } - return 0; + return 0; } int TestDot() { - Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510); - Math::Vector vecB(-0.0524083951404069, 1.5564932716738220, -0.8971342631500536); + Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510); + Math::Vector vecB(-0.0524083951404069, 1.5564932716738220, -0.8971342631500536); - float expectedDot = -0.238988896477326; + float expectedDot = -0.238988896477326; - if (! Math::IsEqual(Math::DotProduct(vecA, vecB), expectedDot, TEST_TOLERANCE) ) - { - fprintf(stderr, "Dot product mismatch!\n"); - return __LINE__; - } + if (! Math::IsEqual(Math::DotProduct(vecA, vecB), expectedDot, TEST_TOLERANCE) ) + { + fprintf(stderr, "Dot product mismatch!\n"); + return __LINE__; + } - return 0; + return 0; } int TestCross() { - Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121); - Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823); + Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121); + Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823); - Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581); - Math::Vector expectedReverseCross = -expectedCross; + Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581); + Math::Vector expectedReverseCross = -expectedCross; - if (! Math::VectorsEqual(vecA.CrossMultiply(vecB), expectedCross, TEST_TOLERANCE) ) - { - fprintf(stderr, "Cross product mismatch!\n"); - return __LINE__; - } + if (! Math::VectorsEqual(vecA.CrossMultiply(vecB), expectedCross, TEST_TOLERANCE) ) + { + fprintf(stderr, "Cross product mismatch!\n"); + return __LINE__; + } - if (! Math::VectorsEqual(vecB.CrossMultiply(vecA), expectedReverseCross, TEST_TOLERANCE) ) - { - fprintf(stderr, "Reverse cross product mismatch!\n"); - return __LINE__; - } + if (! Math::VectorsEqual(vecB.CrossMultiply(vecA), expectedReverseCross, TEST_TOLERANCE) ) + { + fprintf(stderr, "Reverse cross product mismatch!\n"); + return __LINE__; + } - return 0; + return 0; } int main() { - // Functions to test - int (*TESTS[])() = - { - TestLength, - TestNormalize, - TestDot, - TestCross - }; - const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS); - - int result = 0; - for (int i = 0; i < TESTS_SIZE; ++i) - { - result = TESTS[i](); - if (result != 0) - return result; - } - - fprintf(stderr, "All tests successful\n"); - - return 0; + // Functions to test + int (*TESTS[])() = + { + TestLength, + TestNormalize, + TestDot, + TestCross + }; + const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS); + + int result = 0; + for (int i = 0; i < TESTS_SIZE; ++i) + { + result = TESTS[i](); + if (result != 0) + return result; + } + + fprintf(stderr, "All tests successful\n"); + + return 0; } diff --git a/src/math/vector.h b/src/math/vector.h index fd9aa52..3c756f2 100644 --- a/src/math/vector.h +++ b/src/math/vector.h @@ -35,209 +35,209 @@ namespace Math /** \struct Vector math/vector.h \brief 3D (3x1) vector - Represents a universal 3x1 vector that can be used in OpenGL and DirectX engines. - Contains the required methods for operating on vectors. + Represents a universal 3x1 vector that can be used in OpenGL and DirectX engines. + Contains the required methods for operating on vectors. - All methods are made inline to maximize optimization. + All methods are made inline to maximize optimization. - Unit tests for the structure and related functions are in module: math/test/vector_test.cpp. + Unit tests for the structure and related functions are in module: math/test/vector_test.cpp. */ struct Vector { - //! X - 1st coord - float x; - //! Y - 2nd coord - float y; - //! Z - 3rd coord - float z; - - //! Creates a zero vector (0, 0, 0) - inline Vector() - { - LoadZero(); - } - - //! Creates a vector from given values - inline explicit Vector(float x, float y, float z) - { - this->x = x; - this->y = y; - this->z = z; - } - - //! Loads the zero vector (0, 0, 0) - inline void LoadZero() - { - x = y = z = 0.0f; - } - - //! Returns the vector length - inline float Length() const - { - return sqrtf(x*x + y*y + z*z); - } - - //! Normalizes the vector - inline void Normalize() - { - float l = Length(); - if (IsZero(l)) - return; - - x /= l; - y /= l; - z /= l; - } - - //! Calculates the cross product with another vector - /** \a right right-hand side vector - \returns the cross product*/ - inline Vector CrossMultiply(const Vector &right) const - { - float px = y * right.z - z * right.y; - float py = z * right.x - x * right.z; - float pz = x * right.y - y * right.x; - return Vector(px, py, pz); - } - - //! Calculates the dot product with another vector - /** \a right right-hand side vector - \returns the dot product */ - inline float DotMultiply(const Vector &right) const - { - return x * right.x + y * right.y + z * right.z; - } - - //! Returns the cosine of angle between this and another vector - inline float CosAngle(const Vector &right) const - { - return DotMultiply(right) / (Length() * right.Length()); - } - - //! Returns angle (in radians) between this and another vector - inline float Angle(const Vector &right) const - { - return acos(CosAngle(right)); - } - - - /* Operators */ - - //! Returns the inverted vector - inline Vector operator-() const - { - return Vector(-x, -y, -z); - } - - //! Adds the given vector - inline const Vector& operator+=(const Vector &right) - { - x += right.x; - y += right.y; - z += right.z; - return *this; - } - - //! Adds two vectors - inline friend const Vector operator+(const Vector &left, const Vector &right) - { - return Vector(left.x + right.x, left.y + right.y, left.z + right.z); - } - - //! Subtracts the given vector - inline const Vector& operator-=(const Vector &right) - { - x -= right.x; - y -= right.y; - z -= right.z; - return *this; - } - - //! Subtracts two vectors - inline friend const Vector operator-(const Vector &left, const Vector &right) - { - return Vector(left.x - right.x, left.y - right.y, left.z - right.z); - } - - //! Multiplies by given scalar - inline const Vector& operator*=(const float &right) - { - x *= right; - y *= right; - z *= right; - return *this; - } - - //! Multiplies vector by scalar - inline friend const Vector operator*(const float &left, const Vector &right) - { - return Vector(left * right.x, left * right.y, left * right.z); - } - - //! Multiplies vector by scalar - inline friend const Vector operator*(const Vector &left, const float &right) - { - return Vector(left.x * right, left.y * right, left.z * right); - } - - //! Divides by given scalar - inline const Vector& operator/=(const float &right) - { - x /= right; - y /= right; - z /= right; - return *this; - } - - //! Divides vector by scalar - inline friend const Vector operator/(const Vector &left, const float &right) - { - return Vector(left.x / right, left.y / right, left.z / right); - } + //! X - 1st coord + float x; + //! Y - 2nd coord + float y; + //! Z - 3rd coord + float z; + + //! Creates a zero vector (0, 0, 0) + inline Vector() + { + LoadZero(); + } + + //! Creates a vector from given values + inline explicit Vector(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + } + + //! Loads the zero vector (0, 0, 0) + inline void LoadZero() + { + x = y = z = 0.0f; + } + + //! Returns the vector length + inline float Length() const + { + return sqrtf(x*x + y*y + z*z); + } + + //! Normalizes the vector + inline void Normalize() + { + float l = Length(); + if (IsZero(l)) + return; + + x /= l; + y /= l; + z /= l; + } + + //! Calculates the cross product with another vector + /** \a right right-hand side vector + \returns the cross product*/ + inline Vector CrossMultiply(const Vector &right) const + { + float px = y * right.z - z * right.y; + float py = z * right.x - x * right.z; + float pz = x * right.y - y * right.x; + return Vector(px, py, pz); + } + + //! Calculates the dot product with another vector + /** \a right right-hand side vector + \returns the dot product */ + inline float DotMultiply(const Vector &right) const + { + return x * right.x + y * right.y + z * right.z; + } + + //! Returns the cosine of angle between this and another vector + inline float CosAngle(const Vector &right) const + { + return DotMultiply(right) / (Length() * right.Length()); + } + + //! Returns angle (in radians) between this and another vector + inline float Angle(const Vector &right) const + { + return acos(CosAngle(right)); + } + + + /* Operators */ + + //! Returns the inverted vector + inline Vector operator-() const + { + return Vector(-x, -y, -z); + } + + //! Adds the given vector + inline const Vector& operator+=(const Vector &right) + { + x += right.x; + y += right.y; + z += right.z; + return *this; + } + + //! Adds two vectors + inline friend const Vector operator+(const Vector &left, const Vector &right) + { + return Vector(left.x + right.x, left.y + right.y, left.z + right.z); + } + + //! Subtracts the given vector + inline const Vector& operator-=(const Vector &right) + { + x -= right.x; + y -= right.y; + z -= right.z; + return *this; + } + + //! Subtracts two vectors + inline friend const Vector operator-(const Vector &left, const Vector &right) + { + return Vector(left.x - right.x, left.y - right.y, left.z - right.z); + } + + //! Multiplies by given scalar + inline const Vector& operator*=(const float &right) + { + x *= right; + y *= right; + z *= right; + return *this; + } + + //! Multiplies vector by scalar + inline friend const Vector operator*(const float &left, const Vector &right) + { + return Vector(left * right.x, left * right.y, left * right.z); + } + + //! Multiplies vector by scalar + inline friend const Vector operator*(const Vector &left, const float &right) + { + return Vector(left.x * right, left.y * right, left.z * right); + } + + //! Divides by given scalar + inline const Vector& operator/=(const float &right) + { + x /= right; + y /= right; + z /= right; + return *this; + } + + //! Divides vector by scalar + inline friend const Vector operator/(const Vector &left, const float &right) + { + return Vector(left.x / right, left.y / right, left.z / right); + } }; // struct Point //! Checks if two vectors are equal within given \a tolerance inline bool VectorsEqual(const Vector &a, const Vector &b, float tolerance = TOLERANCE) { - return IsEqual(a.x, b.x, tolerance) - && IsEqual(a.y, b.y, tolerance) - && IsEqual(a.z, b.z, tolerance); + return IsEqual(a.x, b.x, tolerance) + && IsEqual(a.y, b.y, tolerance) + && IsEqual(a.z, b.z, tolerance); } //! Convenience function for getting normalized vector inline Vector Normalize(const Vector &v) { - Vector result = v; - result.Normalize(); - return result; + Vector result = v; + result.Normalize(); + return result; } //! Convenience function for calculating dot product inline float DotProduct(const Vector &left, const Vector &right) { - return left.DotMultiply(right); + return left.DotMultiply(right); } //! Convenience function for calculating cross product inline Vector CrossProduct(const Vector &left, const Vector &right) { - return left.CrossMultiply(right); + return left.CrossMultiply(right); } //! Convenience function for calculating angle (in radians) between two vectors inline float Angle(const Vector &a, const Vector &b) { - return a.Angle(b); + return a.Angle(b); } //! Returns the distance between the ends of two vectors inline float Distance(const Vector &a, const Vector &b) { - return sqrtf( (a.x-b.x)*(a.x-b.x) + - (a.y-b.y)*(a.y-b.y) + - (a.z-b.z)*(a.z-b.z) ); + return sqrtf( (a.x-b.x)*(a.x-b.x) + + (a.y-b.y)*(a.y-b.y) + + (a.z-b.z)*(a.z-b.z) ); } /* @} */ // end of group -- cgit v1.2.3-1-g7c22