summaryrefslogtreecommitdiffstats
path: root/src/math
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-05-03 13:35:32 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-05-03 13:35:32 +0200
commitf67a62fb28c882b1650b827730bac72f404e2c47 (patch)
tree18ea8d7a826ed304250e16ceadca181ef4771259 /src/math
parentea442a887d562e95fa91186a4333c830ab5543e7 (diff)
downloadcolobot-f67a62fb28c882b1650b827730bac72f404e2c47.tar.gz
colobot-f67a62fb28c882b1650b827730bac72f404e2c47.tar.bz2
colobot-f67a62fb28c882b1650b827730bac72f404e2c47.zip
Structs continued
Diffstat (limited to 'src/math')
-rw-r--r--src/math/all.h31
-rw-r--r--src/math/matrix.h43
-rw-r--r--src/math/point.h160
-rw-r--r--src/math/vector.h157
4 files changed, 332 insertions, 59 deletions
diff --git a/src/math/all.h b/src/math/all.h
new file mode 100644
index 0000000..fb6f7d4
--- /dev/null
+++ b/src/math/all.h
@@ -0,0 +1,31 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * 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/.
+
+/** @defgroup MathAllModule math/all.h
+ Includes all other math module headers.
+ */
+
+#pragma once
+
+/* @{ */ // start of group
+
+#include "const.h"
+#include "func.h"
+#include "point.h"
+#include "vector.h"
+#include "matrix.h"
+
+/* @} */ // end of group
diff --git a/src/math/matrix.h b/src/math/matrix.h
index 96fb00e..3b1be01 100644
--- a/src/math/matrix.h
+++ b/src/math/matrix.h
@@ -71,7 +71,7 @@ struct Matrix
//! Creates the matrix from 1D array
/** \a m matrix values in column-major order */
- inline Matrix(const float (&m)[16])
+ inline explicit Matrix(const float (&m)[16])
{
for (int i = 0; i < 16; ++i)
this->m[i] = m[i];
@@ -80,7 +80,7 @@ struct Matrix
//! Creates the matrix from 2D array
/** The array's first index is row, second is column.
\a m array with values */
- inline Matrix(const float (&m)[4][4])
+ inline explicit Matrix(const float (&m)[4][4])
{
for (int c = 0; c < 4; ++c)
{
@@ -547,7 +547,21 @@ struct Matrix
temp.LoadRotationY(angle.y);
this->Multiply(temp);
}
-};
+
+}; // struct Matrix
+
+//! Checks if two matrices are equal within given \a tolerance
+inline bool MatricesEqual(const Matrix &m1, const Matrix &m2,
+ float tolerance = TOLERANCE)
+{
+ for (int i = 0; i < 16; ++i)
+ {
+ if (! IsEqual(m1.m[i], m2.m[i], tolerance))
+ return false;
+ }
+
+ return true;
+}
//! Convenience function for getting transposed matrix
inline Matrix Transpose(const Matrix &m)
@@ -592,17 +606,22 @@ inline Vector MatrixVectorMultiply(const Matrix &m, const Vector &v)
return Vector(x, y, z);
}
-//! Checks if two matrices are equal within given \a tolerance
-inline bool MatricesEqual(const Matrix &m1, const Matrix &m2,
- float tolerance = TOLERANCE)
+//! Calculation point of view to look at a center two angles and a distance
+inline Vector RotateView(const Vector &center, float angleH, float angleV, float dist)
{
- for (int i = 0; i < 16; ++i)
- {
- if (! IsEqual(m1.m[i], m2.m[i], tolerance))
- return false;
- }
+ Matrix mat1, mat2, mat;
- return true;
+ mat1.LoadRotationZ(-angleV);
+ mat2.LoadRotationY(-angleH);
+ mat = MultiplyMatrices(mat1, mat2);
+
+ Vector eye;
+ eye.x = 0.0f+dist;
+ eye.y = 0.0f;
+ eye.z = 0.0f;
+ eye = MatrixVectorMultiply(mat, eye);
+
+ return eye + center;
}
/* @} */ // end of group
diff --git a/src/math/point.h b/src/math/point.h
index 8b9dcba..7000138 100644
--- a/src/math/point.h
+++ b/src/math/point.h
@@ -26,17 +26,6 @@
#include <cmath>
-/* 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);
-
- float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2);
-
- */
-
// Math module namespace
namespace Math
{
@@ -66,7 +55,7 @@ struct Point
}
//! Constructs a point from given coords: (x,y)
- inline Point(float x, float y)
+ inline explicit Point(float x, float y)
{
this->x = x;
this->y = y;
@@ -81,9 +70,85 @@ struct Point
//! Returns the distance from (0,0) to the point (x,y)
inline float Length()
{
- return std::sqrt(x*x + y*y);
+ return sqrt(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
+
+
+//! 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);
+}
//! Permutes two points
inline void Swap(Point &a, Point &b)
@@ -161,6 +226,73 @@ inline bool IsInsideTriangle(Point a, Point b, Point c, const Point &p)
return true;
}
+//! Rotates a point around a center
+/** \a center center of rotation
+ \a angle angle is in radians (positive is counterclockwise (CCW) )
+ \a p the point */
+inline Point RotatePoint(const Point &center, float angle, const Point &p)
+{
+ Point a;
+ a.x = p.x-center.x;
+ a.y = p.y-center.y;
+
+ Point b;
+ b.x = a.x*cosf(angle) - a.y*sinf(angle);
+ b.y = a.x*sinf(angle) + a.y*cosf(angle);
+
+ b.x += center.x;
+ b.y += center.y;
+
+ return b;
+}
+
+//! Rotates a point around the origin (0,0)
+/** \a angle angle in radians (positive is counterclockwise (CCW) )
+ \a p the point */
+inline Point RotatePoint(float angle, const Point &p)
+{
+ float x = p.x*cosf(angle) - p.y*sinf(angle);
+ float y = p.x*sinf(angle) + p.y*cosf(angle);
+
+ return Point(x, y);
+}
+
+//! Rotates a vector (dist, 0).
+/** \a angle angle is in radians (positive is counterclockwise (CCW) )
+ \a dist distance to origin */
+inline Point RotatePoint(float angle, float dist)
+{
+ float x = dist*cosf(angle);
+ float y = dist*sinf(angle);
+
+ return Point(x, y);
+}
+
+//! 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) ) */
+inline float RotateAngle(const Point &center, const Point &p1, const Point &p2)
+{
+ if (PointsEqual(p1, 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));
+
+ if (p1.x < center.x) a1 = PI - a1;
+ if (p2.x < center.x) a2 = PI - a2;
+
+ float a = a2 - a1;
+ if (a < 0)
+ a += PI_MUL_2;
+
+ return a;
+}
+
/* @} */ // end of group
}; // namespace Math
diff --git a/src/math/vector.h b/src/math/vector.h
index 455042b..48db4c2 100644
--- a/src/math/vector.h
+++ b/src/math/vector.h
@@ -26,20 +26,6 @@
#include <cmath>
-/*
- TODO
-
-void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
-void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
-
-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 );
-
- */
-
// Math module namespace
namespace Math
{
@@ -73,7 +59,7 @@ struct Vector
}
//! Creates a vector from given values
- inline Vector(float x, float y, float z)
+ inline explicit Vector(float x, float y, float z)
{
this->x = x;
this->y = y;
@@ -135,6 +121,9 @@ struct Vector
return acos(CosAngle(right));
}
+
+ /* Operators */
+
//! Returns the inverted vector
inline Vector operator-() const
{
@@ -206,7 +195,16 @@ struct Vector
{
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);
+}
//! Convenience function for getting normalized vector
inline Vector Normalize(const Vector &v)
@@ -234,27 +232,19 @@ inline float Angle(const Vector &a, const Vector &b)
return a.Angle(b);
}
-//! 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);
-}
-
//! Returns the distance between two points
inline float Distance(const Vector &a, const Vector &b)
{
- return std::sqrt( (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 sqrt( (a.x-b.x)*(a.x-b.x) +
+ (a.y-b.y)*(a.y-b.y) +
+ (a.z-b.z)*(a.z-b.z) );
}
//! Returns the distance between projections on XZ plane of two vectors
inline float DistanceProjected(const Vector &a, const Vector &b)
{
- return std::sqrt( (a.x-b.x)*(a.x-b.x) +
- (a.z-b.z)*(a.z-b.z) );
+ return sqrt( (a.x-b.x)*(a.x-b.x) +
+ (a.z-b.z)*(a.z-b.z) );
}
//! Returns the normal vector to a plane
@@ -275,7 +265,7 @@ inline float DistanceToPlane(const Vector &a, const Vector &b, const Vector &c,
Vector n = NormalToPlane(a, b, c);
float d = -(n.x*a.x + n.y*a.y + n.z*a.z);
- return std::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
@@ -286,9 +276,9 @@ 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]);
- if ( std::fabs(n1.x-n2.x) > 0.1f ||
- std::fabs(n1.y-n2.y) > 0.1f ||
- std::fabs(n1.z-n2.z) > 0.1f )
+ 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]);
@@ -317,6 +307,107 @@ inline Vector SegmentPoint(const Vector &p1, const Vector &p2, float dist)
return p1 + (p2 - p1) * dist;
}
+//! 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 p the point
+ \returns the rotated point */
+inline Vector RotatePoint(const Vector &center, float angleH, float angleV, Vector p)
+{
+ Vector a, b;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
+ b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+
+ float x = center.x+b.x;
+ float y = center.y+b.y;
+ float z = center.z+b.z;
+
+ return Vector(x, y, z);
+}
+
+//! 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 p the point
+ \returns the rotated point */
+inline Vector RotatePoint2(const Vector center, float angleH, float angleV, Vector p)
+{
+ Vector a, b;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ a.y = p.y;
+ a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+
+ b.x = a.x;
+ b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
+ b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
+
+ float x = center.x+b.x;
+ float y = center.y+b.y;
+ float z = center.z+b.z;
+
+ return Vector(x, y, z);
+}
+
+//! 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 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;
+
+ 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;
+}
+
+//! 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);
+
+ if (d == 0.0f)
+ return false;
+
+ p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
+
+ return true;
+}
+
+//! Calculates the end point
+inline Vector LookatPoint(const Vector &eye, float angleH, float angleV, float length)
+{
+
+ Vector lookat = eye;
+ lookat.z += length;
+
+ RotatePoint(eye, angleH, angleV, lookat);
+
+ return lookat;
+}
+
/* @} */ // end of group
}; // namespace Math