From f67a62fb28c882b1650b827730bac72f404e2c47 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 3 May 2012 13:35:32 +0200 Subject: Structs continued --- src/math/all.h | 31 +++++++++++ src/math/matrix.h | 43 +++++++++++---- src/math/point.h | 160 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/math/vector.h | 157 ++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 332 insertions(+), 59 deletions(-) create mode 100644 src/math/all.h (limited to 'src/math') 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 ¢er, 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 -/* 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 ¢er, 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 ¢er, 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 -/* - 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 ¢er, 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 -- cgit v1.2.3-1-g7c22