From d57258ae1c5d1d8200f410e80bd51be04f0b493f Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 28 Apr 2012 21:46:26 +0200 Subject: Split math functions; beginning of common structures --- src/graphics/common/color.cpp | 150 ++++++++++++++++++++++++++ src/graphics/common/color.h | 31 ++++++ src/math/const.h | 28 +++++ src/math/func.h | 238 ++++++++++++++++++++++++++++++++++++++++++ src/math/matrix.h | 178 +++++++++++++++++++++++++++++++ src/math/point.h | 19 ++++ src/math/vector.h | 119 +++++++++++++++++++++ 7 files changed, 763 insertions(+) create mode 100644 src/graphics/common/color.cpp create mode 100644 src/graphics/common/color.h create mode 100644 src/math/const.h create mode 100644 src/math/func.h create mode 100644 src/math/matrix.h create mode 100644 src/math/point.h create mode 100644 src/math/vector.h (limited to 'src') diff --git a/src/graphics/common/color.cpp b/src/graphics/common/color.cpp new file mode 100644 index 0000000..35f6596 --- /dev/null +++ b/src/graphics/common/color.cpp @@ -0,0 +1,150 @@ +// * 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/. + +// color.cpp + +#include "color.h" + +// TODO + + +// Returns the color corresponding D3DCOLOR. + +D3DCOLOR RetColor(float intensity) +{ + D3DCOLOR color; + + if ( intensity <= 0.0f ) return 0x00000000; + if ( intensity >= 1.0f ) return 0xffffffff; + + color = (int)(intensity*255.0f)<<24; + color |= (int)(intensity*255.0f)<<16; + color |= (int)(intensity*255.0f)<<8; + color |= (int)(intensity*255.0f); + + return color; +} + +// Returns the color corresponding D3DCOLOR. + +D3DCOLOR RetColor(D3DCOLORVALUE intensity) +{ + D3DCOLOR color; + + color = (int)(intensity.a*255.0f)<<24; + color |= (int)(intensity.r*255.0f)<<16; + color |= (int)(intensity.g*255.0f)<<8; + color |= (int)(intensity.b*255.0f); + + return color; +} + +// Returns the color corresponding D3DCOLORVALUE. + +D3DCOLORVALUE RetColor(D3DCOLOR intensity) +{ + D3DCOLORVALUE color; + + color.r = (float)((intensity>>16)&0xff)/256.0f; + color.g = (float)((intensity>>8 )&0xff)/256.0f; + color.b = (float)((intensity>>0 )&0xff)/256.0f; + color.a = (float)((intensity>>24)&0xff)/256.0f; + + return color; +} + + +// RGB to HSV conversion. + +void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest) +{ + float min, max, delta; + + min = Min(src.r, src.g, src.b); + max = Max(src.r, src.g, src.b); + + dest.v = max; // intensity + + if ( max == 0.0f ) + { + dest.s = 0.0f; // saturation + dest.h = 0.0f; // undefined color! + } + else + { + delta = max-min; + dest.s = delta/max; // saturation + + if ( src.r == max ) // between yellow & magenta + { + dest.h = (src.g-src.b)/delta; + } + else if ( src.g == max ) // between cyan & yellow + { + dest.h = 2.0f+(src.b-src.r)/delta; + } + else // between magenta & cyan + { + dest.h = 4.0f+(src.r-src.g)/delta; + } + + dest.h *= 60.0f; // in degrees + if ( dest.h < 0.0f ) dest.h += 360.0f; + dest.h /= 360.0f; // 0..1 + } +} + +// HSV to RGB conversion. + +void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest) +{ + int i; + float f,v,p,q,t; + + src.h = Norm(src.h)*360.0f; + src.s = Norm(src.s); + src.v = Norm(src.v); + + if ( src.s == 0.0f ) // zero saturation? + { + dest.r = src.v; + dest.g = src.v; + dest.b = src.v; // gray + } + else + { + if ( src.h == 360.0f ) src.h = 0.0f; + src.h /= 60.0f; + i = (int)src.h; // integer part (0 .. 5) + f = src.h-i; // fractional part + + v = src.v; + p = src.v*(1.0f-src.s); + q = src.v*(1.0f-(src.s*f)); + t = src.v*(1.0f-(src.s*(1.0f-f))); + + switch (i) + { + case 0: dest.r=v; dest.g=t; dest.b=p; break; + case 1: dest.r=q; dest.g=v; dest.b=p; break; + case 2: dest.r=p; dest.g=v; dest.b=t; break; + case 3: dest.r=p; dest.g=q; dest.b=v; break; + case 4: dest.r=t; dest.g=p; dest.b=v; break; + case 5: dest.r=v; dest.g=p; dest.b=q; break; + } + } +} + diff --git a/src/graphics/common/color.h b/src/graphics/common/color.h new file mode 100644 index 0000000..9d6114a --- /dev/null +++ b/src/graphics/common/color.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/. + +// color.h + +// TODO +struct Color +{ +}; + +#pragma once + +D3DCOLOR RetColor(float intensity); +D3DCOLOR RetColor(D3DCOLORVALUE intensity); +D3DCOLORVALUE RetColor(D3DCOLOR intensity); + +void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest); +void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest); 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 +#include + +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 + +/* 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 + +/* + 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 -- cgit v1.2.3-1-g7c22