Split math functions; beginning of common structures

dev-ui
Piotr Dziwinski 2012-04-28 21:46:26 +02:00
parent 449cc186d5
commit d57258ae1c
7 changed files with 763 additions and 0 deletions

View File

@ -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;
}
}
}

View File

@ -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);

28
src/math/const.h Normal file
View File

@ -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;
};

238
src/math/func.h Normal file
View File

@ -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);
}
}

178
src/math/matrix.h Normal file
View File

@ -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

19
src/math/point.h Normal file
View File

@ -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);
*/

119
src/math/vector.h Normal file
View File

@ -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);
};