Tests rewrite and Doxygen in src/math

- rewritten tests to use new framework
- updated/reformatted Doxygen
- removed legacy conversions
dev-ui
Piotr Dziwinski 2012-09-11 21:14:32 +02:00
parent efe4f0badd
commit 6c21dceb35
12 changed files with 265 additions and 404 deletions

View File

@ -6,6 +6,7 @@ add_subdirectory(tools)
# Tests # Tests
add_subdirectory(graphics/engine/test) add_subdirectory(graphics/engine/test)
add_subdirectory(math/test)
# Configure options # Configure options

View File

@ -27,5 +27,3 @@
#include "vector.h" #include "vector.h"
#include "matrix.h" #include "matrix.h"
#include "geometry.h" #include "geometry.h"
#include "conv.h"

View File

@ -51,4 +51,3 @@ const float RAD_TO_DEG = 57.29577951308232286465f;
const float LOG_2 = log(2.0f); const float LOG_2 = log(2.0f);
}; // namespace Math }; // namespace Math

View File

@ -1,39 +0,0 @@
/* math/conv.h
Temporary conversion functions for D3DVECTOR and D3DMATRIX */
#pragma once
#include <d3d.h>
#include "vector.h"
#include "matrix.h"
inline D3DVECTOR VEC_TO_D3DVEC(Math::Vector vec)
{
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);
}
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;
}
inline Math::Matrix D3DMAT_TO_MAT(D3DMATRIX mat)
{
Math::Matrix result(mat.m);
result.Transpose();
return result;
}

View File

@ -76,9 +76,11 @@ inline bool IsInsideTriangle(Math::Point a, Math::Point b, Math::Point c, Math::
} }
//! Rotates a point around a center //! Rotates a point around a center
/** \a center center of rotation /**
\a angle angle is in radians (positive is counterclockwise (CCW) ) * \param center center of rotation
\a p the point */ * \param angle angle [radians] (positive is CCW)
* \param p the point to be rotated
*/
inline Math::Point RotatePoint(const Math::Point &center, float angle, const Math::Point &p) inline Math::Point RotatePoint(const Math::Point &center, float angle, const Math::Point &p)
{ {
Math::Point a; Math::Point a;
@ -96,8 +98,10 @@ inline Math::Point RotatePoint(const Math::Point &center, float angle, const Mat
} }
//! Rotates a point around the origin (0,0) //! Rotates a point around the origin (0,0)
/** \a angle angle in radians (positive is counterclockwise (CCW) ) /**
\a p the point */ * \param angle angle [radians] (positive is CCW)
* \param p the point to be rotated
*/
inline Math::Point RotatePoint(float angle, const Math::Point &p) inline Math::Point RotatePoint(float angle, const Math::Point &p)
{ {
float x = p.x*cosf(angle) - p.y*sinf(angle); float x = p.x*cosf(angle) - p.y*sinf(angle);
@ -106,9 +110,11 @@ inline Math::Point RotatePoint(float angle, const Math::Point &p)
return Math::Point(x, y); return Math::Point(x, y);
} }
//! Rotates a vector (dist, 0). //! Rotates a vector (dist, 0)
/** \a angle angle is in radians (positive is counterclockwise (CCW) ) /**
\a dist distance to origin */ * \param angle angle [radians] (positive is CCW)
* \param dist distance to origin
*/
inline Math::Point RotatePoint(float angle, float dist) inline Math::Point RotatePoint(float angle, float dist)
{ {
float x = dist*cosf(angle); float x = dist*cosf(angle);
@ -117,7 +123,12 @@ inline Math::Point RotatePoint(float angle, float dist)
return Math::Point(x, y); return Math::Point(x, y);
} }
//! TODO documentation //! Rotates a point around a center on 2D plane
/**
* \param cx,cy center of rotation
* \param angle angle of rotation [radians] (positive is CCW)
* \param px,py point coordinates to rotate
*/
inline void RotatePoint(float cx, float cy, float angle, float &px, float &py) inline void RotatePoint(float cx, float cy, float angle, float &px, float &py)
{ {
float ax, ay; float ax, ay;
@ -132,11 +143,14 @@ inline void RotatePoint(float cx, float cy, float angle, float &px, float &py)
py = cy+ay; py = cy+ay;
} }
//! Rotates a point around a center in space. //! Rotates a point around a center in space
/** \a center center of rotation /**
\a angleH,angleV rotation angles in radians (positive is counterclockwise (CCW) ) ) * \a angleH is rotation along Y axis (heading) while \a angleV is rotation along X axis (TODO: ?).
\a p the point *
\returns the rotated point */ * \param center center of rotation
* \param angleH,angleV rotation angles [radians] (positive is CCW)
* \param p the point to be rotated
*/
inline void RotatePoint(const Math::Vector &center, float angleH, float angleV, Math::Vector &p) inline void RotatePoint(const Math::Vector &center, float angleH, float angleV, Math::Vector &p)
{ {
p.x -= center.x; p.x -= center.x;
@ -151,11 +165,14 @@ inline void RotatePoint(const Math::Vector &center, float angleH, float angleV,
p = center + b; p = center + b;
} }
//! Rotates a point around a center in space. //! Rotates a point around a center in space
/** \a center center of rotation /**
\a angleH,angleV rotation angles in radians (positive is counterclockwise (CCW) ) ) * The rotation is performed first along Y axis (\a angleH) and then along X axis (\a angleV).
\a p the point *
\returns the rotated point */ * \param center center of rotation
* \param angleH,angleV rotation angles [radians] (positive is CCW)
* \param p the point to be rotated
*/
inline void RotatePoint2(const Math::Vector center, float angleH, float angleV, Math::Vector &p) inline void RotatePoint2(const Math::Vector center, float angleH, float angleV, Math::Vector &p)
{ {
p.x -= center.x; p.x -= center.x;
@ -189,10 +206,12 @@ inline float RotateAngle(float x, float y)
return -atan + 0.5f*PI; return -atan + 0.5f*PI;
} }
//! Calculates the angle between two points and one center //! Calculates the angle between two points and a center
/** \a center the center point /**
\a p1,p2 the two points * \param center the center point
\returns The angle in radians (positive is counterclockwise (CCW) ) */ * \param p1,p2 the two points
* \returns the angle [radians] (positive is CCW)
*/
inline float RotateAngle(const Math::Point &center, const Math::Point &p1, const Math::Point &p2) inline float RotateAngle(const Math::Point &center, const Math::Point &p1, const Math::Point &p2)
{ {
if (PointsEqual(p1, center)) if (PointsEqual(p1, center))
@ -215,9 +234,11 @@ inline float RotateAngle(const Math::Point &center, const Math::Point &p1, const
} }
//! Loads view matrix from the given vectors //! Loads view matrix from the given vectors
/** \a from origin /**
\a at view direction * \param from origin
\a worldUp up vector */ * \param at view direction
* \param worldUp up vector
*/
inline void LoadViewMatrix(Math::Matrix &mat, const Math::Vector &from, inline void LoadViewMatrix(Math::Matrix &mat, const Math::Vector &from,
const Math::Vector &at, const Math::Vector &worldUp) const Math::Vector &at, const Math::Vector &worldUp)
{ {
@ -280,10 +301,12 @@ inline void LoadViewMatrix(Math::Matrix &mat, const Math::Vector &from,
} }
//! Loads a perspective projection matrix //! Loads a perspective projection matrix
/** \a fov field of view in radians /**
\a aspect aspect ratio (width / height) * \param fov field of view in radians
\a nearPlane distance to near cut plane * \param aspect aspect ratio (width / height)
\a farPlane distance to far cut plane */ * \param nearPlane distance to near cut plane
* \param farPlane distance to far cut plane
*/
inline void LoadProjectionMatrix(Math::Matrix &mat, float fov = Math::PI / 2.0f, float aspect = 1.0f, inline void LoadProjectionMatrix(Math::Matrix &mat, float fov = Math::PI / 2.0f, float aspect = 1.0f,
float nearPlane = 1.0f, float farPlane = 1000.0f) float nearPlane = 1.0f, float farPlane = 1000.0f)
{ {
@ -302,9 +325,11 @@ inline void LoadProjectionMatrix(Math::Matrix &mat, float fov = Math::PI / 2.0f,
} }
//! Loads an othogonal projection matrix //! Loads an othogonal projection matrix
/** \a left,right coordinates for left and right vertical clipping planes /**
\a bottom,top coordinates for bottom and top horizontal clipping planes * \param left,right coordinates for left and right vertical clipping planes
\a zNear,zFar distance to nearer and farther depth clipping planes */ * \param bottom,top coordinates for bottom and top horizontal clipping planes
* \param zNear,zFar distance to nearer and farther depth clipping planes
*/
inline void LoadOrthoProjectionMatrix(Math::Matrix &mat, float left, float right, float bottom, float top, inline void LoadOrthoProjectionMatrix(Math::Matrix &mat, float left, float right, float bottom, float top,
float zNear = -1.0f, float zFar = 1.0f) float zNear = -1.0f, float zFar = 1.0f)
{ {
@ -320,7 +345,10 @@ inline void LoadOrthoProjectionMatrix(Math::Matrix &mat, float left, float right
} }
//! Loads a translation matrix from given vector //! Loads a translation matrix from given vector
/** \a trans vector of translation*/ /**
* \param mat result matrix
* \param trans vector of translation
*/
inline void LoadTranslationMatrix(Math::Matrix &mat, const Math::Vector &trans) inline void LoadTranslationMatrix(Math::Matrix &mat, const Math::Vector &trans)
{ {
mat.LoadIdentity(); mat.LoadIdentity();
@ -330,7 +358,10 @@ inline void LoadTranslationMatrix(Math::Matrix &mat, const Math::Vector &trans)
} }
//! Loads a scaling matrix fom given vector //! Loads a scaling matrix fom given vector
/** \a scale vector with scaling factors for X, Y, Z */ /**
* \param mat result matrix
* \param scale vector with scaling factors for X, Y, Z
*/
inline void LoadScaleMatrix(Math::Matrix &mat, const Math::Vector &scale) inline void LoadScaleMatrix(Math::Matrix &mat, const Math::Vector &scale)
{ {
mat.LoadIdentity(); mat.LoadIdentity();
@ -340,7 +371,10 @@ inline void LoadScaleMatrix(Math::Matrix &mat, const Math::Vector &scale)
} }
//! Loads a rotation matrix along the X axis //! Loads a rotation matrix along the X axis
/** \a angle angle in radians */ /**
* \param mat result matrix
* \param angle angle [radians]
*/
inline void LoadRotationXMatrix(Math::Matrix &mat, float angle) inline void LoadRotationXMatrix(Math::Matrix &mat, float angle)
{ {
mat.LoadIdentity(); mat.LoadIdentity();
@ -351,7 +385,10 @@ inline void LoadRotationXMatrix(Math::Matrix &mat, float angle)
} }
//! Loads a rotation matrix along the Y axis //! Loads a rotation matrix along the Y axis
/** \a angle angle in radians */ /**
* \param mat result matrix
* \param angle angle [radians]
*/
inline void LoadRotationYMatrix(Math::Matrix &mat, float angle) inline void LoadRotationYMatrix(Math::Matrix &mat, float angle)
{ {
mat.LoadIdentity(); mat.LoadIdentity();
@ -362,7 +399,10 @@ inline void LoadRotationYMatrix(Math::Matrix &mat, float angle)
} }
//! Loads a rotation matrix along the Z axis //! Loads a rotation matrix along the Z axis
/** \a angle angle in radians */ /**
* \param mat result matrix
* \param angle angle [radians]
*/
inline void LoadRotationZMatrix(Math::Matrix &mat, float angle) inline void LoadRotationZMatrix(Math::Matrix &mat, float angle)
{ {
mat.LoadIdentity(); mat.LoadIdentity();
@ -373,8 +413,11 @@ inline void LoadRotationZMatrix(Math::Matrix &mat, float angle)
} }
//! Loads a rotation matrix along the given axis //! Loads a rotation matrix along the given axis
/** \a dir axis of rotation /**
\a angle angle in radians */ * \param mat result matrix
* \param dir axis of rotation
* \param angle angle [radians]
*/
inline void LoadRotationMatrix(Math::Matrix &mat, const Math::Vector &dir, float angle) inline void LoadRotationMatrix(Math::Matrix &mat, const Math::Vector &dir, float angle)
{ {
float cos = cosf(angle); float cos = cosf(angle);
@ -397,28 +440,28 @@ inline void LoadRotationMatrix(Math::Matrix &mat, const Math::Vector &dir, float
} }
//! Calculates the matrix to make three rotations in the order X, Z and Y //! Calculates the matrix to make three rotations in the order X, Z and Y
inline void LoadRotationXZYMatrix(Math::Matrix &mat, const Math::Vector &angle) inline void LoadRotationXZYMatrix(Math::Matrix &mat, const Math::Vector &angles)
{ {
Math::Matrix temp; Math::Matrix temp;
LoadRotationXMatrix(temp, angle.x); LoadRotationXMatrix(temp, angles.x);
LoadRotationZMatrix(mat, angle.z); LoadRotationZMatrix(mat, angles.z);
mat = Math::MultiplyMatrices(temp, mat); mat = Math::MultiplyMatrices(temp, mat);
LoadRotationYMatrix(temp, angle.y); LoadRotationYMatrix(temp, angles.y);
mat = Math::MultiplyMatrices(temp, mat); mat = Math::MultiplyMatrices(temp, mat);
} }
//! Calculates the matrix to make three rotations in the order Z, X and Y //! Calculates the matrix to make three rotations in the order Z, X and Y
inline void LoadRotationZXYMatrix(Math::Matrix &mat, const Math::Vector &angle) inline void LoadRotationZXYMatrix(Math::Matrix &mat, const Math::Vector &angles)
{ {
Math::Matrix temp; Math::Matrix temp;
LoadRotationZMatrix(temp, angle.z); LoadRotationZMatrix(temp, angles.z);
LoadRotationXMatrix(mat, angle.x); LoadRotationXMatrix(mat, angles.x);
mat = Math::MultiplyMatrices(temp, mat); mat = Math::MultiplyMatrices(temp, mat);
LoadRotationYMatrix(temp, angle.y); LoadRotationYMatrix(temp, angles.y);
mat = Math::MultiplyMatrices(temp, mat); mat = Math::MultiplyMatrices(temp, mat);
} }
@ -430,7 +473,9 @@ inline float DistanceProjected(const Math::Vector &a, const Math::Vector &b)
} }
//! Returns the normal vector to a plane //! Returns the normal vector to a plane
/** \param p1,p2,p3 points defining the plane */ /**
* \param p1,p2,p3 points defining the plane
*/
inline Math::Vector NormalToPlane(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3) inline Math::Vector NormalToPlane(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3)
{ {
Math::Vector u = p3 - p1; Math::Vector u = p3 - p1;
@ -440,16 +485,20 @@ inline Math::Vector NormalToPlane(const Math::Vector &p1, const Math::Vector &p2
} }
//! Returns a point on the line \a p1 - \a p2, in \a dist distance from \a p1 //! Returns a point on the line \a p1 - \a p2, in \a dist distance from \a p1
/** \a p1,p2 line start and end /**
\a dist scaling factor from \a p1, relative to distance between \a p1 and \a p2 */ * \param p1,p2 line start and end
* \param dist scaling factor from \a p1, relative to distance between \a p1 and \a p2
*/
inline Math::Vector SegmentPoint(const Math::Vector &p1, const Math::Vector &p2, float dist) inline Math::Vector SegmentPoint(const Math::Vector &p1, const Math::Vector &p2, float dist)
{ {
return p1 + (p2 - p1) * dist; return p1 + (p2 - p1) * dist;
} }
//! Returns the distance between given point and a plane //! Returns the distance between given point and a plane
/** \param p the point /**
\param a,b,c points defining the plane */ * \param p the point
* \param a,b,c points defining the plane
*/
inline float DistanceToPlane(const Math::Vector &a, const Math::Vector &b, inline float DistanceToPlane(const Math::Vector &a, const Math::Vector &b,
const Math::Vector &c, const Math::Vector &p) const Math::Vector &c, const Math::Vector &p)
{ {
@ -460,8 +509,10 @@ inline float DistanceToPlane(const Math::Vector &a, const Math::Vector &b,
} }
//! Checks if two planes defined by three points are the same //! Checks if two planes defined by three points are the same
/** \a plane1 array of three vectors defining the first plane /**
\a plane2 array of three vectors defining the second plane */ * \param plane1 array of three vectors defining the first plane
* \param plane2 array of three vectors defining the second plane
*/
inline bool IsSamePlane(const Math::Vector (&plane1)[3], const Math::Vector (&plane2)[3]) inline bool IsSamePlane(const Math::Vector (&plane1)[3], const Math::Vector (&plane2)[3])
{ {
Math::Vector n1 = NormalToPlane(plane1[0], plane1[1], plane1[2]); Math::Vector n1 = NormalToPlane(plane1[0], plane1[1], plane1[2]);
@ -479,7 +530,7 @@ inline bool IsSamePlane(const Math::Vector (&plane1)[3], const Math::Vector (&pl
return true; return true;
} }
//! Calculates the intersection "i" right "of" the plane "abc". //! Calculates the intersection "i" right "of" the plane "abc" (TODO: ?)
inline bool Intersect(const Math::Vector &a, const Math::Vector &b, const Math::Vector &c, inline bool Intersect(const Math::Vector &a, const Math::Vector &b, const Math::Vector &c,
const Math::Vector &d, const Math::Vector &e, Math::Vector &i) const Math::Vector &d, const Math::Vector &e, Math::Vector &i)
{ {
@ -502,7 +553,7 @@ inline bool Intersect(const Math::Vector &a, const Math::Vector &b, const Math::
} }
//! Calculates the intersection of the straight line passing through p (x, z) //! 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. */ /** Line is parallel to the y axis, with the plane abc. Returns p.y. (TODO: ?) */
inline bool IntersectY(const Math::Vector &a, const Math::Vector &b, const Math::Vector &c, Math::Vector &p) inline bool IntersectY(const Math::Vector &a, const Math::Vector &b, const Math::Vector &c, Math::Vector &p)
{ {
float d = (b.x-a.x)*(c.z-a.z) - (c.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);
@ -528,15 +579,18 @@ inline Math::Vector LookatPoint(const Math::Vector &eye, float angleH, float ang
return lookat; return lookat;
} }
//! TODO documentation //! Transforms the point \a p by matrix \a m
/** Is equal to multiplying the matrix by the vector (of course without perspective divide). */
inline Math::Vector Transform(const Math::Matrix &m, const Math::Vector &p) inline Math::Vector Transform(const Math::Matrix &m, const Math::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. //! Calculates the projection of the point \a p on a straight line \a a to \a b
/** \a p point to project /**
\a a,b two ends of the line */ * \param point to project
* \param a,b two ends of the line
*/
inline Math::Vector Projection(const Math::Vector &a, const Math::Vector &b, const Math::Vector &p) inline Math::Vector Projection(const Math::Vector &a, const Math::Vector &b, const Math::Vector &p)
{ {
float k = DotProduct(b - a, p - a); float k = DotProduct(b - a, p - a);

View File

@ -33,13 +33,14 @@
namespace Math namespace Math
{ {
/** \struct Matrix math/matrix.h /**
\brief 4x4 matrix * \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[0 ] m[4 ] m[8 ] m[12]
@ -48,16 +49,16 @@ m[2 ] m[6 ] m[10] m[14]
m[3 ] m[7 ] m[11] m[15] m[3 ] m[7 ] m[11] m[15]
\endverbatim \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 * The order of multiplication of matrix and vector is also OpenGL-native
(see the function MatrixVectorMultiply). * (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 struct Matrix
{ {
//! Matrix values in column-major order //! Matrix values in column-major order
@ -78,8 +79,10 @@ struct Matrix
} }
//! Creates the matrix from 2D array //! Creates the matrix from 2D array
/** The array's first index is row, second is column. /**
\a m array with values */ * The array's first index is row, second is column.
* \param m array with values
*/
inline explicit Matrix(const float (&m)[4][4]) inline explicit Matrix(const float (&m)[4][4])
{ {
for (int c = 0; c < 4; ++c) for (int c = 0; c < 4; ++c)
@ -91,11 +94,23 @@ struct Matrix
} }
} }
//! Sets value in given row and col
/**
* \param row row (0 to 3)
* \param col column (0 to 3)
* \param value value
*/
inline void Set(int row, int col, float value) inline void Set(int row, int col, float value)
{ {
m[(col-1)*4+(row-1)] = value; m[(col-1)*4+(row-1)] = value;
} }
//! Returns the value in given row and col
/**
* \param row row (0 to 3)
* \param col column (0 to 3)
* \returns value
*/
inline float Get(int row, int col) inline float Get(int row, int col)
{ {
return m[(col-1)*4+(row-1)]; return m[(col-1)*4+(row-1)];
@ -148,9 +163,11 @@ struct Matrix
} }
//! Calculates the cofactor of the matrix //! Calculates the cofactor of the matrix
/** \a r row (0 to 3) /**
\a c column (0 to 3) * \param r row (0 to 3)
\returns the cofactor */ * \param c column (0 to 3)
* \returns the cofactor
*/
inline float Cofactor(int r, int c) const inline float Cofactor(int r, int c) const
{ {
assert(r >= 0 && r <= 3); assert(r >= 0 && r <= 3);
@ -330,8 +347,10 @@ struct Matrix
} }
//! Calculates the inverse matrix //! Calculates the inverse matrix
/** The determinant of the matrix must not be zero. /**
\returns the inverted matrix */ * The determinant of the matrix must not be zero.
* \returns the inverted matrix
*/
inline Matrix Inverse() const inline Matrix Inverse() const
{ {
float d = Det(); float d = Det();
@ -352,8 +371,10 @@ struct Matrix
} }
//! Calculates the multiplication of this matrix * given matrix //! Calculates the multiplication of this matrix * given matrix
/** \a right right-hand matrix /**
\returns multiplication result */ * \param right right-hand matrix
* \returns multiplication result
*/
inline Matrix Multiply(const Matrix &right) const inline Matrix Multiply(const Matrix &right) const
{ {
float result[16] = { 0.0f }; float result[16] = { 0.0f };

View File

@ -32,14 +32,14 @@
namespace Math namespace Math
{ {
/** \struct Point math/point.h /**
\brief 2D point * \struct Point
* \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 struct Point
{ {

View File

@ -1,33 +1,23 @@
cmake_minimum_required(VERSION 2.8) cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE debug) set(CMAKE_BUILD_TYPE debug)
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wold-style-cast -std=gnu++0x")
add_executable(matrix_test matrix_test.cpp) include_directories(
add_executable(vector_test vector_test.cpp) .
add_executable(geometry_test geometry_test.cpp ../old/math3d.cpp ../old/d3dmath.cpp ../../graphics/d3d/d3dutil.cpp) ../../..
${GTEST_DIR}/include
enable_testing()
add_test(matrix_test ./matrix_test)
add_test(vector_test ./vector_test)
add_test(geometry_test ./geometry_test)
# Change to DirectX SDK directory
include_directories("c:/dxsdk/include")
add_definitions(-DSTRICT -DD3D_OVERLOADS)
# 'make check' will compile the required test programs
# Note that 'make test' will still fail without compiled programs
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS matrix_test vector_test)
# Files to be removed in distclean
set(REMOVE_FILES
CMakeFiles Testing cmake_install.cmake CMakeCache.txt CTestTestfile.cmake Makefile
./matrix_test
./vector_test
./geometry_test
) )
add_custom_target(distclean COMMAND rm -rf ${REMOVE_FILES}) add_executable(matrix_test matrix_test.cpp)
target_link_libraries(matrix_test gtest)
add_executable(vector_test vector_test.cpp)
target_link_libraries(vector_test gtest)
add_executable(geometry_test geometry_test.cpp)
target_link_libraries(geometry_test gtest)
add_test(matrix_test matrix_test)
add_test(vector_test vector_test)
add_test(geometry_test geometry_test)

View File

@ -20,53 +20,41 @@
#include "../func.h" #include "../func.h"
#include "../geometry.h" #include "../geometry.h"
#include "../conv.h"
#include "../../old/math3d.h"
#include "../../old/d3dutil.h"
#include <d3d.h> #include "gtest/gtest.h"
#include <cstdio>
using namespace std;
const float TEST_TOLERANCE = 1e-5; const float TEST_TOLERANCE = 1e-5;
// Test for rewritten function RotateAngle() // Test for rewritten function RotateAngle()
int TestRotateAngle() TEST(GeometryTest, RotateAngleTest)
{ {
if (! Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(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)) EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE));
return __LINE__;
return 0;
} }
// Tests for other altered, complex or uncertain functions // Tests for other altered, complex or uncertain functions
/*
TODO: write meaningful tests with proper test values
int TestAngle() int TestAngle()
{ {
const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805); const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805);
@ -360,42 +348,12 @@ int TestTransform()
return 0; return 0;
} }
int main() */
int main(int argc, char* argv[])
{ {
// Functions to test ::testing::InitGoogleTest(&argc, argv);
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; return RUN_ALL_TESTS();
for (int i = 0; i < TESTS_SIZE; ++i)
{
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");
return 0;
} }

View File

@ -26,13 +26,13 @@
#include "../func.h" #include "../func.h"
#include "../matrix.h" #include "../matrix.h"
#include <cstdio> #include "gtest/gtest.h"
using namespace std;
const float TEST_TOLERANCE = 1e-6; const float TEST_TOLERANCE = 1e-6;
int TestTranspose()
TEST(MatrixTest, TransposeTest)
{ {
const Math::Matrix mat( const Math::Matrix mat(
(float[4][4]) (float[4][4])
@ -56,16 +56,10 @@ int TestTranspose()
Math::Matrix transpose = Math::Transpose(mat); Math::Matrix transpose = Math::Transpose(mat);
if (! Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE)) EXPECT_TRUE(Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE));
{
fprintf(stderr, "Transpose mismatch!\n");
return __LINE__;
}
return 0;
} }
int TestCofactor() TEST(MatrixTest, CofactorTest)
{ {
const Math::Matrix mat1( const Math::Matrix mat1(
(float[4][4]) (float[4][4])
@ -93,12 +87,7 @@ int TestCofactor()
{ {
float ret = mat1.Cofactor(r, c); float ret = mat1.Cofactor(r, c);
float exp = expectedCofactors1.m[4*c+r]; float exp = expectedCofactors1.m[4*c+r];
if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) EXPECT_TRUE(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__;
}
} }
} }
@ -129,19 +118,12 @@ int TestCofactor()
{ {
float ret = mat2.Cofactor(r, c); float ret = mat2.Cofactor(r, c);
float exp = expectedCofactors2.m[4*c+r]; float exp = expectedCofactors2.m[4*c+r];
if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) EXPECT_TRUE(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;
} }
int TestDet() TEST(MatrixTest, DetTest)
{ {
const Math::Matrix mat1( const Math::Matrix mat1(
(float[4][4]) (float[4][4])
@ -156,12 +138,7 @@ int TestDet()
const float expectedDet1 = 4.07415413729671; const float expectedDet1 = 4.07415413729671;
float ret1 = mat1.Det(); float ret1 = mat1.Det();
if (! Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE)) EXPECT_TRUE(Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE));
{
fprintf(stderr, "Det mismatch!\n");
fprintf(stderr, "%f (returned) != %f (expected)\n", ret1, expectedDet1);
return __LINE__;
}
const Math::Matrix mat2( const Math::Matrix mat2(
(float[4][4]) (float[4][4])
@ -176,17 +153,10 @@ int TestDet()
const float expectedDet2 = -6.35122307880942; const float expectedDet2 = -6.35122307880942;
float ret2 = mat2.Det(); float ret2 = mat2.Det();
if (! Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE)) EXPECT_TRUE(Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE));
{
fprintf(stderr, "Det mismatch!\n");
fprintf(stderr, "%f (returned) != %f (expected)\n", ret2, expectedDet2);
return __LINE__;
}
return 0;
} }
int TestInverse() TEST(MatrixTest, InverseTest)
{ {
const Math::Matrix mat1( const Math::Matrix mat1(
(float[4][4]) (float[4][4])
@ -210,11 +180,7 @@ int TestInverse()
Math::Matrix inverse1 = mat1.Inverse(); Math::Matrix inverse1 = mat1.Inverse();
if (! Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE)) EXPECT_TRUE(Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE));
{
fprintf(stderr, "Inverse 1 mismatch!\n");
return __LINE__;
}
const Math::Matrix mat2( const Math::Matrix mat2(
(float[4][4]) (float[4][4])
@ -238,16 +204,10 @@ int TestInverse()
Math::Matrix inverse2 = mat2.Inverse(); Math::Matrix inverse2 = mat2.Inverse();
if (! Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE)) EXPECT_TRUE(Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE));
{
fprintf(stderr, "Inverse 2 mismatch!\n");
return __LINE__;
}
return 0;
} }
int TestMultiply() TEST(MatrixTest, MultiplyTest)
{ {
const Math::Matrix mat1A( const Math::Matrix mat1A(
(float[4][4]) (float[4][4])
@ -280,11 +240,7 @@ int TestMultiply()
); );
Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B); Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B);
if (! Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) ) EXPECT_TRUE(Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE));
{
fprintf(stderr, "Multiply 1 mismath!\n");
return __LINE__;
}
const Math::Matrix mat2A( const Math::Matrix mat2A(
(float[4][4]) (float[4][4])
@ -317,16 +273,10 @@ int TestMultiply()
); );
Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B); Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B);
if (! Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) ) EXPECT_TRUE(Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE));
{
fprintf(stderr, "Multiply 2 mismath!\n");
return __LINE__;
}
return 0;
} }
int TestMultiplyVector() TEST(MatrixTest, MultiplyVectorTest)
{ {
const Math::Matrix mat1( const Math::Matrix mat1(
(float[4][4]) (float[4][4])
@ -343,11 +293,7 @@ int TestMultiplyVector()
const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142); const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142);
Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false); Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false);
if (! Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) ) EXPECT_TRUE(Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE));
{
fprintf(stderr, "Multiply vector 1 mismath!\n");
return __LINE__;
}
const Math::Matrix mat2( const Math::Matrix mat2(
(float[4][4]) (float[4][4])
@ -364,39 +310,13 @@ int TestMultiplyVector()
const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455); const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455);
Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true); Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true);
if (! Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) ) EXPECT_TRUE(Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE));
{
fprintf(stderr, "Multiply vector 2 mismath!\n");
return __LINE__;
}
return 0;
} }
int main() int main(int argc, char* argv[])
{ {
// Functions to test ::testing::InitGoogleTest(&argc, argv);
int (*TESTS[])() =
{
TestTranspose,
TestCofactor,
TestDet,
TestInverse,
TestMultiply,
TestMultiplyVector
};
const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
int result = 0; return RUN_ALL_TESTS();
for (int i = 0; i < TESTS_SIZE; ++i)
{
result = TESTS[i]();
if (result != 0)
return result;
}
fprintf(stderr, "All tests successful\n");
return 0;
} }

View File

@ -26,59 +26,41 @@
#include "../func.h" #include "../func.h"
#include "../vector.h" #include "../vector.h"
#include <cstdio> #include "gtest/gtest.h"
using namespace std;
const float TEST_TOLERANCE = 1e-6; const float TEST_TOLERANCE = 1e-6;
int TestLength()
TEST(VectorTest, LengthTest)
{ {
Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957); Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957);
const float expectedLength = 1.58938001708428; const float expectedLength = 1.58938001708428;
if (! Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE) ) EXPECT_TRUE(Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE));
{
fprintf(stderr, "Length mismatch!\n");
return __LINE__;
}
return 0;
} }
int TestNormalize() TEST(VectorTest, NormalizeTest)
{ {
Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377); Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377);
const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797); const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797);
vec.Normalize(); vec.Normalize();
if (! Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE)) EXPECT_TRUE(Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE));
{
fprintf(stderr, "Normalize mismatch!\n");
return __LINE__;
}
return 0;
} }
int TestDot() TEST(VectorTest, DotTest)
{ {
Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510); Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510);
Math::Vector vecB(-0.0524083951404069, 1.5564932716738220, -0.8971342631500536); 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) ) EXPECT_TRUE(Math::IsEqual(Math::DotProduct(vecA, vecB), expectedDot, TEST_TOLERANCE));
{
fprintf(stderr, "Dot product mismatch!\n");
return __LINE__;
}
return 0;
} }
int TestCross() TEST(VectorTest, CrossTest)
{ {
Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121); Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121);
Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823); Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823);
@ -86,42 +68,14 @@ int TestCross()
Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581); Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581);
Math::Vector expectedReverseCross = -expectedCross; Math::Vector expectedReverseCross = -expectedCross;
if (! Math::VectorsEqual(vecA.CrossMultiply(vecB), expectedCross, TEST_TOLERANCE) ) EXPECT_TRUE(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) ) EXPECT_TRUE(Math::VectorsEqual(vecB.CrossMultiply(vecA), expectedReverseCross, TEST_TOLERANCE));
{
fprintf(stderr, "Reverse cross product mismatch!\n");
return __LINE__;
}
return 0;
} }
int main() int main(int argc, char* argv[])
{ {
// Functions to test ::testing::InitGoogleTest(&argc, argv);
int (*TESTS[])() =
{
TestLength,
TestNormalize,
TestDot,
TestCross
};
const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
int result = 0; return RUN_ALL_TESTS();
for (int i = 0; i < TESTS_SIZE; ++i)
{
result = TESTS[i]();
if (result != 0)
return result;
}
fprintf(stderr, "All tests successful\n");
return 0;
} }

View File

@ -32,16 +32,17 @@
namespace Math namespace Math
{ {
/** \struct Vector math/vector.h /**
\brief 3D (3x1) vector * \struct Vector
* \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 struct Vector
{ {
@ -103,8 +104,10 @@ struct Vector
} }
//! Calculates the cross product with another vector //! Calculates the cross product with another vector
/** \a right right-hand side vector /**
\returns the cross product*/ * \param right right-hand side vector
* \returns the cross product
*/
inline Vector CrossMultiply(const Vector &right) const inline Vector CrossMultiply(const Vector &right) const
{ {
float px = y * right.z - z * right.y; float px = y * right.z - z * right.y;
@ -114,8 +117,10 @@ struct Vector
} }
//! Calculates the dot product with another vector //! Calculates the dot product with another vector
/** \a right right-hand side vector /**
\returns the dot product */ * \param right right-hand side vector
* \returns the dot product
*/
inline float DotMultiply(const Vector &right) const inline float DotMultiply(const Vector &right) const
{ {
return x * right.x + y * right.y + z * right.z; return x * right.x + y * right.y + z * right.z;
@ -218,7 +223,7 @@ struct Vector
return s.str(); return s.str();
} }
}; // struct Point }; // struct Vector
//! Checks if two vectors are equal within given \a tolerance //! Checks if two vectors are equal within given \a tolerance
inline bool VectorsEqual(const Math::Vector &a, const Math::Vector &b, float tolerance = TOLERANCE) inline bool VectorsEqual(const Math::Vector &a, const Math::Vector &b, float tolerance = TOLERANCE)