summaryrefslogtreecommitdiffstats
path: root/src/math
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-04-28 21:46:26 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-04-28 21:46:26 +0200
commitd57258ae1c5d1d8200f410e80bd51be04f0b493f (patch)
tree7458516813fadc2d743fabd6cb59a40279ed138d /src/math
parent449cc186d5b8117d74ba22d6173497d00939f5f1 (diff)
downloadcolobot-d57258ae1c5d1d8200f410e80bd51be04f0b493f.tar.gz
colobot-d57258ae1c5d1d8200f410e80bd51be04f0b493f.tar.bz2
colobot-d57258ae1c5d1d8200f410e80bd51be04f0b493f.zip
Split math functions; beginning of common structures
Diffstat (limited to 'src/math')
-rw-r--r--src/math/const.h28
-rw-r--r--src/math/func.h238
-rw-r--r--src/math/matrix.h178
-rw-r--r--src/math/point.h19
-rw-r--r--src/math/vector.h119
5 files changed, 582 insertions, 0 deletions
diff --git a/src/math/const.h b/src/math/const.h
new file mode 100644
index 0000000..9e4504f
--- /dev/null
+++ b/src/math/const.h
@@ -0,0 +1,28 @@
+// math/const.h
+
+/* Math constants */
+
+#pragma once
+
+// Math module namespace
+namespace Math
+{
+ //! Tolerance level -- minimum accepted float value
+ const float TOLERANCE = 1e-6f;
+
+ //! PI
+ const float PI = 3.14159265358979323846f;
+ //! 2 * PI
+ const float PI_MUL_2 = 6.28318530717958623200f;
+ //! PI / 2
+ const float PI_DIV_2 = 1.57079632679489655800f;
+ //! PI / 4
+ const float PI_DIV_4 = 0.78539816339744827900f;
+ //! 1 / PI
+ const float INV_PI = 0.31830988618379069122f;
+
+ //! Degrees to radians multiplier
+ const float DEG_TO_RAD = 0.01745329251994329547f;
+ //! Radians to degrees multiplier
+ const FLOAT RAD_TO_DEG = 57.29577951308232286465f;
+};
diff --git a/src/math/func.h b/src/math/func.h
new file mode 100644
index 0000000..2e43d24
--- /dev/null
+++ b/src/math/func.h
@@ -0,0 +1,238 @@
+// math/func.h
+
+/* Common math functions */
+
+#pragma once
+
+#include "const.h"
+
+#include <cmath>
+#include <cstdlib>
+
+namespace Math
+{
+
+//! Compares a and b within TOLERANCE
+bool IsEqual(float a, float b)
+{
+ return Abs(a - b) < TOLERANCE;
+}
+
+//! Minimum
+inline float Min(float a, float b)
+{
+ if ( a <= b ) return a;
+ else return b;
+}
+
+inline float Min(float a, float b, float 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) );
+}
+
+inline float Min(float a, float b, float c, float d, float 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;
+}
+
+inline float Max(float a, float b, float 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) );
+}
+
+inline float Max(float a, float b, float c, float d, float 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;
+}
+
+//! Returns the absolute value
+inline float Abs(float a)
+{
+ return (float)fabs(a);
+}
+
+//! Swaps two integers
+inline void Swap(int &a, int &b)
+{
+ int c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+//! Swaps two real numbers
+inline void Swap(float &a, float &b)
+{
+ float c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+//! Permutes two points
+inline void Swap(Point &a, Point &b)
+{
+ Point c;
+
+ 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 */
+inline float Mod(float a, float m)
+{
+ return a - ((int)(a/m))*m;
+}
+
+//! Returns a normalized angle, that is in other words between 0 and 2 * PI
+inline float NormAngle(float angle)
+{
+ angle = Mod(angle, PI_MUL_2);
+ if ( angle < 0.0f )
+ return PI_MUL_2 + 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);
+
+ if ( min > max )
+ return ( angle <= max || angle >= min );
+
+ return ( angle >= min && angle <= max );
+}
+
+//! 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);
+
+ 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;
+}
+
+//! Returns a random value between 0 and 1.
+inline float Rand()
+{
+ return (float)rand()/RAND_MAX;
+}
+
+
+//! Managing the dead zone of a joystick.
+/**
+ in: -1 0 1
+ --|-------|----o----|-------|-->
+ <---->
+ dead
+ out: -1 0 0 1 */
+float Neutral(float value, float dead)
+{
+ if ( Abs(value) <= dead )
+ {
+ return 0.0f;
+ }
+ else
+ {
+ if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
+ else return (value+dead)/(1.0f-dead);
+ }
+}
+
+
+//! Calculates a value (radians) proportional between a and b (degrees)
+float Prop(int a, int b, float p)
+{
+ float aa = (float)a * DEG_TO_RAD;
+ float bb = (float)b * DEG_TO_RAD;
+
+ return aa+p*(bb-aa);
+}
+
+//! Gently advances a desired value from its current value
+/** Over time, the progression is more rapid. */
+float Smooth(float actual, float hope, float time)
+{
+ float future = actual + (hope-actual)*time;
+
+ if ( hope > actual )
+ {
+ if ( future > hope ) future = hope;
+ }
+ if ( hope < actual )
+ {
+ if ( future < hope ) future = hope;
+ }
+
+ return future;
+}
+
+
+//! Bounces any movement
+/** out
+ |
+ 1+------o-------o---
+ | o | o o | | bounce
+ | o | o---|---
+ | o | |
+ | o | |
+ -o------|-------+----> progress
+ 0| | 1
+ |<---->|middle */
+inline float Bounce(float progress, float middle, float bounce)
+{
+ 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);
+ }
+}
diff --git a/src/math/matrix.h b/src/math/matrix.h
new file mode 100644
index 0000000..463ff0f
--- /dev/null
+++ b/src/math/matrix.h
@@ -0,0 +1,178 @@
+// math/matrix.h
+
+/* Matrix struct and functions */
+
+#pragma once
+
+#include "const.h"
+
+#include <cmath>
+
+/* TODO
+
+ void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle);
+ void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle);
+
+*/
+
+// Math module namespace
+namespace Math
+{
+
+/** 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.).
+
+ All methods are made inline to maximize optimization.
+
+ **/
+struct Matrix
+{
+ //! Matrix values in row-major format
+ float m[16];
+
+ //! Creates the indentity matrix
+ inline Matrix()
+ {
+ LoadIdentity();
+ }
+
+ //! Creates the matrix from given values
+ /** \a m values in row-major format */
+ inline Matrix(float m[16])
+ {
+ this->m = m;
+ }
+
+ //! 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();
+ m[0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
+ }
+
+ //! Calculates the determinant of the matrix
+ /** \returns the determinant */
+ float Det() const
+ {
+ float result = 0.0f;
+ for (int i = 0; i < 4; ++i)
+ {
+ result += m[0][i] * Cofactor(0, i);
+ }
+ return result;
+ }
+
+ //! Transposes the matrix
+ void Transpose()
+ {
+ Matrix temp = *this;
+ for (int r = 0; r < 4; ++r)
+ {
+ for (int c = 0; c < 4; ++c)
+ {
+ m[r][c] = temp.m[c][r];
+ }
+ }
+ }
+
+ //! Calculates the cofactor of the matrix
+ /** \a r row (0 to 3)
+ \a c column (0 to 3)
+ \returns the cofactor or 0.0f if invalid r, c given*/
+ float Cofactor(int r, int c) const
+ {
+ if ((r < 0) || (r > 3) || (c < 0) || (c > 3))
+ return 0.0f;
+
+ float tab[3][3];
+ int tabR = 0;
+ for (int r = 0; r < 4; ++r)
+ {
+ if (r == i) continue;
+ int tabC = 0;
+ for (int c = 0; c < 4; ++c)
+ {
+ if (c == j) continue;
+ tab[tabR][tabC] = m[r][c];
+ ++tabC;
+ }
+ ++tabR;
+ }
+
+ float result = tab[0][0] * (tab[1][1] * tab[2][2] - tab[1][2] * tab[2][1])
+ - tab[0][1] * (tab[1][0] * tab[2][2] - tab[1][2] * tab[2][0])
+ + tab[0][2] * (tab[1][0] * tab[2][1] - tab[1][1] * tab[2][0]);
+
+ if ((i + j) % 2 == 0)
+ result = -result;
+
+ return result;
+ }
+
+ //! Inverts the matrix
+ inline void Invert()
+ {
+ float d = Det();
+ if (fabs(d) <= Math::TOLERANCE)
+ return;
+
+ Matrix temp = *this;
+ for (int r = 0; r < 4; ++r)
+ {
+ for (int c = 0; c < 4; ++c)
+ {
+ m[r][c] = (1.0f / d) * temp.Cofactor(r, c);
+ }
+ }
+
+ Tranpose();
+ }
+
+ //! Multiplies the matrix with the given matrix
+ /** \a right right-hand matrix */
+ inline void Multiply(const Matrix &right)
+ {
+ Matrix left = *this;
+ for (int r = 0; r < 4; ++r)
+ {
+ for (int c = 0; c < 4; ++c)
+ {
+ m[r][c] = 0.0;
+ for (int i = 0; i < 4; ++i)
+ {
+ m[r][c] += left.m[r][i] * right.m[i][c];
+ }
+ }
+ }
+ }
+};
+
+//! Convenience function for inverting a matrix
+/** \a m input matrix
+ \a result result -- inverted matrix */
+void InvertMatrix(const Matrix &m, Matrix &result)
+{
+ result = m;
+ result.Invert();
+}
+
+//! Convenience function for multiplying a matrix
+/** \a left left-hand matrix
+ \a right right-hand matrix
+ \a result result -- multiplied matrices */*
+void MultiplyMatrices(const Matrix &left, const Matrix &right, Matrix &result)
+{
+ result = left;
+ result.Multiply(right);
+}
+
+}; // namespace Math
diff --git a/src/math/point.h b/src/math/point.h
new file mode 100644
index 0000000..49b84a0
--- /dev/null
+++ b/src/math/point.h
@@ -0,0 +1,19 @@
+#pragma once
+
+/* TODO
+FPOINT RotatePoint(FPOINT center, float angle, FPOINT p);
+FPOINT RotatePoint(float angle, FPOINT p);
+FPOINT RotatePoint(float angle, float dist);
+void RotatePoint(float cx, float cy, float angle, float &px, float &py);
+void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
+void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
+float Length(FPOINT a, FPOINT b);
+
+float RotateAngle(float x, float y);
+float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2);
+float MidPoint(FPOINT a, FPOINT b, float px);
+BOOL IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p);
+
+BOOL LineFunction(FPOINT p1, FPOINT p2, float &a, float &b);
+
+*/ \ No newline at end of file
diff --git a/src/math/vector.h b/src/math/vector.h
new file mode 100644
index 0000000..f514a00
--- /dev/null
+++ b/src/math/vector.h
@@ -0,0 +1,119 @@
+// math/vector.h
+
+/* Vector struct and functions */
+
+#pragma once
+
+#include "const.h"
+
+#include <cmath>
+
+/*
+ TODO
+
+HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc, D3DMATRIX& mat)
+
+float Length(const D3DVECTOR &a, const D3DVECTOR &b);
+float Length2d(const D3DVECTOR &a, const D3DVECTOR &b);
+float Angle( D3DVECTOR u, D3DVECTOR v );
+D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v );
+D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 );
+D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p);
+D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p);
+
+D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist);
+
+BOOL Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i);
+BOOL IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p);
+
+
+D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist);
+D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length );
+
+void MappingObject( D3DVERTEX2* pVertices, int nb, float scale );
+void SmoothObject( D3DVERTEX2* pVertices, int nb );
+
+float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &c, const D3DVECTOR &p);
+BOOL IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2);
+ */
+
+// Math module namespace
+namespace Math
+{
+
+/** 4x1 Vector
+
+ Represents an universal 4x1 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.
+
+ */
+struct Vector
+{
+ //! X - 1st coord
+ float x;
+ //! Y - 2nd coord
+ float y;
+ //! Z - 3rd coord
+ float z;
+ //! W - 4th coord
+ float w;
+
+ //! Creates an identity vector (0, 0, 0, 1)
+ Vector()
+ {
+ LoadIdentity();
+ }
+
+ //! Creates a vector from given values
+ Vector(float x, float y, float z, float w = 1.0f)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->w = w;
+ }
+
+ //! Loads the identity vector (0, 0, 0, 1)
+ void LoadIdentity()
+ {
+ x = y = z = 0.0f;
+ w = 1.0f;
+ }
+
+ //! Loads the zero vector (0, 0, 0, 0)
+ void LoadZero()
+ {
+ x = y = z = w = 0.0f;
+ }
+
+ //! Returns the vector length
+ float Length() const
+ {
+ return sqrt(x*x + y*y + z*z + w*w);
+ }
+
+ //! Normalizes the vector
+ void Normalize()
+ {
+
+ }
+
+ const Vector3D& operator-();
+ const Vector3D& operator+=(const Vector3D &vector);
+ const Vector3D& operator-=(const Vector3D &vector);
+ const Vector3D& operator*=(double value);
+ const Vector3D& operator/=(double value);
+
+ friend Vector3D operator+(const Vector3D &left, const Vector3D &right);
+ friend Vector3D operator-(const Vector3D &left, const Vector3D &right);
+ friend Vector3D operator*(double left, const Vector3D &right);
+ friend Vector3D operator*(const Vector3D &left, double right);
+ friend Vector3D operator/(const Vector3D &left, double right);
+
+ friend Vector3D crossProduct(const Vector3D &left, const Vector3D &right);
+ friend double dotProduct(const Vector3D &left, const Vector3D &right);
+ friend double cosAngle(const Vector3D &vector1, const Vector3D &vector2);
+ friend double angle(const Vector3D &vector1, const Vector3D &vector2);
+}; \ No newline at end of file