mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-15 08:51:24 +00:00
- added matrix class for moving the GL matrix manipulation out of the engine code.
This commit is contained in:
parent
471f720d95
commit
1ff8ea6a19
6 changed files with 2810 additions and 1 deletions
|
@ -968,6 +968,7 @@ set (PCH_SOURCES
|
|||
common/utility/configfile.cpp
|
||||
common/utility/file_zip.cpp
|
||||
common/utility/resourcefile.cpp
|
||||
common/utility/matrix.cpp
|
||||
)
|
||||
|
||||
if( MSVC )
|
||||
|
|
|
@ -272,7 +272,7 @@ void COMMON_doclearbackground(int numcols, int height)
|
|||
}
|
||||
# endif
|
||||
|
||||
CLEARLINES2D(0, min(ydim, numrows*8+8), editorcolors[16]);
|
||||
CLEARLINES2D(0, min(ydim, height), editorcolors[16]);
|
||||
}
|
||||
|
||||
void COMMON_clearbackground(int numcols, int numrows)
|
||||
|
|
679
source/common/utility/matrix.cpp
Normal file
679
source/common/utility/matrix.cpp
Normal file
|
@ -0,0 +1,679 @@
|
|||
/* --------------------------------------------------
|
||||
|
||||
Lighthouse3D
|
||||
|
||||
VSMatrix - Very Simple Matrix Library
|
||||
|
||||
http://www.lighthouse3d.com/very-simple-libs
|
||||
|
||||
This is a simplified version of VSMatrix that has been adjusted for GZDoom's needs.
|
||||
|
||||
----------------------------------------------------*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include "matrix.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4244) // truncate from double to float
|
||||
#endif
|
||||
|
||||
static inline FLOATTYPE
|
||||
DegToRad(FLOATTYPE degrees)
|
||||
{
|
||||
return (FLOATTYPE)(degrees * (pi::pif() / 180.0f));
|
||||
};
|
||||
|
||||
// sets the square matrix mat to the identity matrix,
|
||||
// size refers to the number of rows (or columns)
|
||||
void
|
||||
VSMatrix::setIdentityMatrix( FLOATTYPE *mat, int size) {
|
||||
|
||||
// fill matrix with 0s
|
||||
for (int i = 0; i < size * size; ++i)
|
||||
mat[i] = 0.0f;
|
||||
|
||||
// fill diagonal with 1s
|
||||
for (int i = 0; i < size; ++i)
|
||||
mat[i + i * size] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// gl LoadIdentity implementation
|
||||
void
|
||||
VSMatrix::loadIdentity()
|
||||
{
|
||||
// fill matrix with 0s
|
||||
for (int i = 0; i < 16; ++i)
|
||||
mMatrix[i] = 0.0f;
|
||||
|
||||
// fill diagonal with 1s
|
||||
for (int i = 0; i < 4; ++i)
|
||||
mMatrix[i + i * 4] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
// gl MultMatrix implementation
|
||||
void
|
||||
VSMatrix::multMatrix(const FLOATTYPE *aMatrix)
|
||||
{
|
||||
|
||||
FLOATTYPE res[16];
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
res[j*4 + i] = 0.0f;
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
res[j*4 + i] += mMatrix[k*4 + i] * aMatrix[j*4 + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(mMatrix, res, 16 * sizeof(FLOATTYPE));
|
||||
}
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
// gl MultMatrix implementation
|
||||
void
|
||||
VSMatrix::multMatrix(const float *aMatrix)
|
||||
{
|
||||
|
||||
FLOATTYPE res[16];
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
res[j * 4 + i] = 0.0f;
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
res[j*4 + i] += mMatrix[k*4 + i] * aMatrix[j*4 + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(mMatrix, res, 16 * sizeof(FLOATTYPE));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// gl LoadMatrix implementation
|
||||
void
|
||||
VSMatrix::loadMatrix(const FLOATTYPE *aMatrix)
|
||||
{
|
||||
memcpy(mMatrix, aMatrix, 16 * sizeof(FLOATTYPE));
|
||||
}
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
// gl LoadMatrix implementation
|
||||
void
|
||||
VSMatrix::loadMatrix(const float *aMatrix)
|
||||
{
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
mMatrix[i] = aMatrix[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// gl Translate implementation
|
||||
void
|
||||
VSMatrix::translate(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z)
|
||||
{
|
||||
mMatrix[12] = mMatrix[0] * x + mMatrix[4] * y + mMatrix[8] * z + mMatrix[12];
|
||||
mMatrix[13] = mMatrix[1] * x + mMatrix[5] * y + mMatrix[9] * z + mMatrix[13];
|
||||
mMatrix[14] = mMatrix[2] * x + mMatrix[6] * y + mMatrix[10] * z + mMatrix[14];
|
||||
}
|
||||
|
||||
|
||||
// gl Scale implementation
|
||||
void
|
||||
VSMatrix::scale(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z)
|
||||
{
|
||||
mMatrix[0] *= x; mMatrix[1] *= x; mMatrix[2] *= x; mMatrix[3] *= x;
|
||||
mMatrix[4] *= y; mMatrix[5] *= y; mMatrix[6] *= y; mMatrix[7] *= y;
|
||||
mMatrix[8] *= z; mMatrix[9] *= z; mMatrix[10] *= z; mMatrix[11] *= z;
|
||||
}
|
||||
|
||||
|
||||
// gl Rotate implementation
|
||||
void
|
||||
VSMatrix::rotate(FLOATTYPE angle, FLOATTYPE x, FLOATTYPE y, FLOATTYPE z)
|
||||
{
|
||||
FLOATTYPE mat[16];
|
||||
FLOATTYPE v[3];
|
||||
|
||||
v[0] = x;
|
||||
v[1] = y;
|
||||
v[2] = z;
|
||||
|
||||
FLOATTYPE radAngle = DegToRad(angle);
|
||||
FLOATTYPE co = cos(radAngle);
|
||||
FLOATTYPE si = sin(radAngle);
|
||||
normalize(v);
|
||||
FLOATTYPE x2 = v[0]*v[0];
|
||||
FLOATTYPE y2 = v[1]*v[1];
|
||||
FLOATTYPE z2 = v[2]*v[2];
|
||||
|
||||
// mat[0] = x2 + (y2 + z2) * co;
|
||||
mat[0] = co + x2 * (1 - co);// + (y2 + z2) * co;
|
||||
mat[4] = v[0] * v[1] * (1 - co) - v[2] * si;
|
||||
mat[8] = v[0] * v[2] * (1 - co) + v[1] * si;
|
||||
mat[12]= 0.0f;
|
||||
|
||||
mat[1] = v[0] * v[1] * (1 - co) + v[2] * si;
|
||||
// mat[5] = y2 + (x2 + z2) * co;
|
||||
mat[5] = co + y2 * (1 - co);
|
||||
mat[9] = v[1] * v[2] * (1 - co) - v[0] * si;
|
||||
mat[13]= 0.0f;
|
||||
|
||||
mat[2] = v[0] * v[2] * (1 - co) - v[1] * si;
|
||||
mat[6] = v[1] * v[2] * (1 - co) + v[0] * si;
|
||||
// mat[10]= z2 + (x2 + y2) * co;
|
||||
mat[10]= co + z2 * (1 - co);
|
||||
mat[14]= 0.0f;
|
||||
|
||||
mat[3] = 0.0f;
|
||||
mat[7] = 0.0f;
|
||||
mat[11]= 0.0f;
|
||||
mat[15]= 1.0f;
|
||||
|
||||
multMatrix(mat);
|
||||
}
|
||||
|
||||
|
||||
// gluLookAt implementation
|
||||
void
|
||||
VSMatrix::lookAt(FLOATTYPE xPos, FLOATTYPE yPos, FLOATTYPE zPos,
|
||||
FLOATTYPE xLook, FLOATTYPE yLook, FLOATTYPE zLook,
|
||||
FLOATTYPE xUp, FLOATTYPE yUp, FLOATTYPE zUp)
|
||||
{
|
||||
FLOATTYPE dir[3], right[3], up[3];
|
||||
|
||||
up[0] = xUp; up[1] = yUp; up[2] = zUp;
|
||||
|
||||
dir[0] = (xLook - xPos);
|
||||
dir[1] = (yLook - yPos);
|
||||
dir[2] = (zLook - zPos);
|
||||
normalize(dir);
|
||||
|
||||
crossProduct(dir,up,right);
|
||||
normalize(right);
|
||||
|
||||
crossProduct(right,dir,up);
|
||||
normalize(up);
|
||||
|
||||
FLOATTYPE m1[16],m2[16];
|
||||
|
||||
m1[0] = right[0];
|
||||
m1[4] = right[1];
|
||||
m1[8] = right[2];
|
||||
m1[12] = 0.0f;
|
||||
|
||||
m1[1] = up[0];
|
||||
m1[5] = up[1];
|
||||
m1[9] = up[2];
|
||||
m1[13] = 0.0f;
|
||||
|
||||
m1[2] = -dir[0];
|
||||
m1[6] = -dir[1];
|
||||
m1[10] = -dir[2];
|
||||
m1[14] = 0.0f;
|
||||
|
||||
m1[3] = 0.0f;
|
||||
m1[7] = 0.0f;
|
||||
m1[11] = 0.0f;
|
||||
m1[15] = 1.0f;
|
||||
|
||||
setIdentityMatrix(m2,4);
|
||||
m2[12] = -xPos;
|
||||
m2[13] = -yPos;
|
||||
m2[14] = -zPos;
|
||||
|
||||
multMatrix(m1);
|
||||
multMatrix(m2);
|
||||
}
|
||||
|
||||
|
||||
// gluPerspective implementation
|
||||
void
|
||||
VSMatrix::perspective(FLOATTYPE fov, FLOATTYPE ratio, FLOATTYPE nearp, FLOATTYPE farp)
|
||||
{
|
||||
FLOATTYPE f = 1.0f / tan (fov * (pi::pif() / 360.0f));
|
||||
|
||||
loadIdentity();
|
||||
mMatrix[0] = f / ratio;
|
||||
mMatrix[1 * 4 + 1] = f;
|
||||
mMatrix[2 * 4 + 2] = (farp + nearp) / (nearp - farp);
|
||||
mMatrix[3 * 4 + 2] = (2.0f * farp * nearp) / (nearp - farp);
|
||||
mMatrix[2 * 4 + 3] = -1.0f;
|
||||
mMatrix[3 * 4 + 3] = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
// gl Ortho implementation
|
||||
void
|
||||
VSMatrix::ortho(FLOATTYPE left, FLOATTYPE right,
|
||||
FLOATTYPE bottom, FLOATTYPE top,
|
||||
FLOATTYPE nearp, FLOATTYPE farp)
|
||||
{
|
||||
loadIdentity();
|
||||
|
||||
mMatrix[0 * 4 + 0] = 2 / (right - left);
|
||||
mMatrix[1 * 4 + 1] = 2 / (top - bottom);
|
||||
mMatrix[2 * 4 + 2] = -2 / (farp - nearp);
|
||||
mMatrix[3 * 4 + 0] = -(right + left) / (right - left);
|
||||
mMatrix[3 * 4 + 1] = -(top + bottom) / (top - bottom);
|
||||
mMatrix[3 * 4 + 2] = -(farp + nearp) / (farp - nearp);
|
||||
}
|
||||
|
||||
|
||||
// gl Frustum implementation
|
||||
void
|
||||
VSMatrix::frustum(FLOATTYPE left, FLOATTYPE right,
|
||||
FLOATTYPE bottom, FLOATTYPE top,
|
||||
FLOATTYPE nearp, FLOATTYPE farp)
|
||||
{
|
||||
FLOATTYPE m[16];
|
||||
|
||||
setIdentityMatrix(m,4);
|
||||
|
||||
m[0 * 4 + 0] = 2 * nearp / (right-left);
|
||||
m[1 * 4 + 1] = 2 * nearp / (top - bottom);
|
||||
m[2 * 4 + 0] = (right + left) / (right - left);
|
||||
m[2 * 4 + 1] = (top + bottom) / (top - bottom);
|
||||
m[2 * 4 + 2] = - (farp + nearp) / (farp - nearp);
|
||||
m[2 * 4 + 3] = -1.0f;
|
||||
m[3 * 4 + 2] = - 2 * farp * nearp / (farp-nearp);
|
||||
m[3 * 4 + 3] = 0.0f;
|
||||
|
||||
multMatrix(m);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// returns a pointer to the requested matrix
|
||||
FLOATTYPE *
|
||||
VSMatrix::get(MatrixTypes aType)
|
||||
{
|
||||
return mMatrix[aType];
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
SEND MATRICES TO OPENGL
|
||||
------------------------------------------------------*/
|
||||
|
||||
// -----------------------------------------------------
|
||||
// AUX functions
|
||||
// -----------------------------------------------------
|
||||
|
||||
|
||||
// Compute res = M * point
|
||||
void
|
||||
VSMatrix::multMatrixPoint(const FLOATTYPE *point, FLOATTYPE *res)
|
||||
{
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
|
||||
res[i] = 0.0f;
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
|
||||
res[i] += point[j] * mMatrix[j*4 + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// res = a cross b;
|
||||
void
|
||||
VSMatrix::crossProduct(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res) {
|
||||
|
||||
res[0] = a[1] * b[2] - b[1] * a[2];
|
||||
res[1] = a[2] * b[0] - b[2] * a[0];
|
||||
res[2] = a[0] * b[1] - b[0] * a[1];
|
||||
}
|
||||
|
||||
|
||||
// returns a . b
|
||||
FLOATTYPE
|
||||
VSMatrix::dotProduct(const FLOATTYPE *a, const FLOATTYPE *b) {
|
||||
|
||||
FLOATTYPE res = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// Normalize a vec3
|
||||
void
|
||||
VSMatrix::normalize(FLOATTYPE *a) {
|
||||
|
||||
FLOATTYPE mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
|
||||
|
||||
a[0] /= mag;
|
||||
a[1] /= mag;
|
||||
a[2] /= mag;
|
||||
}
|
||||
|
||||
|
||||
// res = b - a
|
||||
void
|
||||
VSMatrix::subtract(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res) {
|
||||
|
||||
res[0] = b[0] - a[0];
|
||||
res[1] = b[1] - a[1];
|
||||
res[2] = b[2] - a[2];
|
||||
}
|
||||
|
||||
|
||||
// res = a + b
|
||||
void
|
||||
VSMatrix::add(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res) {
|
||||
|
||||
res[0] = b[0] + a[0];
|
||||
res[1] = b[1] + a[1];
|
||||
res[2] = b[2] + a[2];
|
||||
}
|
||||
|
||||
|
||||
// returns |a|
|
||||
FLOATTYPE
|
||||
VSMatrix::length(const FLOATTYPE *a) {
|
||||
|
||||
return(sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
M3(int i, int j)
|
||||
{
|
||||
return (i*3+j);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// computes the derived normal matrix for the view matrix
|
||||
void
|
||||
VSMatrix::computeNormalMatrix(const FLOATTYPE *aMatrix)
|
||||
{
|
||||
|
||||
double mMat3x3[9];
|
||||
|
||||
mMat3x3[0] = aMatrix[0];
|
||||
mMat3x3[1] = aMatrix[1];
|
||||
mMat3x3[2] = aMatrix[2];
|
||||
|
||||
mMat3x3[3] = aMatrix[4];
|
||||
mMat3x3[4] = aMatrix[5];
|
||||
mMat3x3[5] = aMatrix[6];
|
||||
|
||||
mMat3x3[6] = aMatrix[8];
|
||||
mMat3x3[7] = aMatrix[9];
|
||||
mMat3x3[8] = aMatrix[10];
|
||||
|
||||
double det, invDet;
|
||||
|
||||
det = mMat3x3[0] * (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) +
|
||||
mMat3x3[1] * (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) +
|
||||
mMat3x3[2] * (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]);
|
||||
|
||||
invDet = 1.0/det;
|
||||
|
||||
mMatrix[0] = (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) * invDet;
|
||||
mMatrix[1] = (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) * invDet;
|
||||
mMatrix[2] = (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]) * invDet;
|
||||
mMatrix[3] = 0.0f;
|
||||
mMatrix[4] = (mMat3x3[2] * mMat3x3[7] - mMat3x3[1] * mMat3x3[8]) * invDet;
|
||||
mMatrix[5] = (mMat3x3[0] * mMat3x3[8] - mMat3x3[2] * mMat3x3[6]) * invDet;
|
||||
mMatrix[6] = (mMat3x3[1] * mMat3x3[6] - mMat3x3[7] * mMat3x3[0]) * invDet;
|
||||
mMatrix[7] = 0.0f;
|
||||
mMatrix[8] = (mMat3x3[1] * mMat3x3[5] - mMat3x3[4] * mMat3x3[2]) * invDet;
|
||||
mMatrix[9] = (mMat3x3[2] * mMat3x3[3] - mMat3x3[0] * mMat3x3[5]) * invDet;
|
||||
mMatrix[10] =(mMat3x3[0] * mMat3x3[4] - mMat3x3[3] * mMat3x3[1]) * invDet;
|
||||
mMatrix[11] = 0.0;
|
||||
mMatrix[12] = 0.0;
|
||||
mMatrix[13] = 0.0;
|
||||
mMatrix[14] = 0.0;
|
||||
mMatrix[15] = 1.0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// aux function resMat = resMat * aMatrix
|
||||
void
|
||||
VSMatrix::multMatrix(FLOATTYPE *resMat, const FLOATTYPE *aMatrix)
|
||||
{
|
||||
|
||||
FLOATTYPE res[16];
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
res[j*4 + i] = 0.0f;
|
||||
for (int k = 0; k < 4; ++k)
|
||||
{
|
||||
res[j*4 + i] += resMat[k*4 + i] * aMatrix[j*4 + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(resMat, res, 16 * sizeof(FLOATTYPE));
|
||||
}
|
||||
|
||||
static double mat3Determinant(const FLOATTYPE *mMat3x3)
|
||||
{
|
||||
return mMat3x3[0] * (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) +
|
||||
mMat3x3[1] * (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) +
|
||||
mMat3x3[2] * (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]);
|
||||
}
|
||||
|
||||
static double mat4Determinant(const FLOATTYPE *matrix)
|
||||
{
|
||||
FLOATTYPE mMat3x3_a[9] =
|
||||
{
|
||||
matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_b[9] =
|
||||
{
|
||||
matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_c[9] =
|
||||
{
|
||||
matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_d[9] =
|
||||
{
|
||||
matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2]
|
||||
};
|
||||
|
||||
FLOATTYPE a, b, c, d;
|
||||
FLOATTYPE value;
|
||||
|
||||
a = mat3Determinant(mMat3x3_a);
|
||||
b = mat3Determinant(mMat3x3_b);
|
||||
c = mat3Determinant(mMat3x3_c);
|
||||
d = mat3Determinant(mMat3x3_d);
|
||||
|
||||
value = matrix[0 * 4 + 0] * a;
|
||||
value -= matrix[0 * 4 + 1] * b;
|
||||
value += matrix[0 * 4 + 2] * c;
|
||||
value -= matrix[0 * 4 + 3] * d;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void mat4Adjoint(const FLOATTYPE *matrix, FLOATTYPE *result)
|
||||
{
|
||||
FLOATTYPE mMat3x3_a[9] =
|
||||
{
|
||||
matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_b[9] =
|
||||
{
|
||||
matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_c[9] =
|
||||
{
|
||||
matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[1 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_d[9] =
|
||||
{
|
||||
matrix[1 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[1 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[1 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_e[9] =
|
||||
{
|
||||
matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_f[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_g[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[0 * 4 + 3], matrix[2 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_h[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[2 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[0 * 4 + 1], matrix[2 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[0 * 4 + 2], matrix[2 * 4 + 2], matrix[3 * 4 + 2]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_i[9] =
|
||||
{
|
||||
matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_j[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2],
|
||||
matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_k[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[3 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_l[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[3 * 4 + 0],
|
||||
matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[3 * 4 + 1],
|
||||
matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[3 * 4 + 2]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_m[9] =
|
||||
{
|
||||
matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1],
|
||||
matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2],
|
||||
matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_n[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0],
|
||||
matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2],
|
||||
matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_o[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0],
|
||||
matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1],
|
||||
matrix[0 * 4 + 3], matrix[1 * 4 + 3], matrix[2 * 4 + 3]
|
||||
};
|
||||
|
||||
FLOATTYPE mMat3x3_p[9] =
|
||||
{
|
||||
matrix[0 * 4 + 0], matrix[1 * 4 + 0], matrix[2 * 4 + 0],
|
||||
matrix[0 * 4 + 1], matrix[1 * 4 + 1], matrix[2 * 4 + 1],
|
||||
matrix[0 * 4 + 2], matrix[1 * 4 + 2], matrix[2 * 4 + 2]
|
||||
};
|
||||
|
||||
result[0 * 4 + 0] = mat3Determinant(mMat3x3_a);
|
||||
result[1 * 4 + 0] = -mat3Determinant(mMat3x3_b);
|
||||
result[2 * 4 + 0] = mat3Determinant(mMat3x3_c);
|
||||
result[3 * 4 + 0] = -mat3Determinant(mMat3x3_d);
|
||||
result[0 * 4 + 1] = -mat3Determinant(mMat3x3_e);
|
||||
result[1 * 4 + 1] = mat3Determinant(mMat3x3_f);
|
||||
result[2 * 4 + 1] = -mat3Determinant(mMat3x3_g);
|
||||
result[3 * 4 + 1] = mat3Determinant(mMat3x3_h);
|
||||
result[0 * 4 + 2] = mat3Determinant(mMat3x3_i);
|
||||
result[1 * 4 + 2] = -mat3Determinant(mMat3x3_j);
|
||||
result[2 * 4 + 2] = mat3Determinant(mMat3x3_k);
|
||||
result[3 * 4 + 2] = -mat3Determinant(mMat3x3_l);
|
||||
result[0 * 4 + 3] = -mat3Determinant(mMat3x3_m);
|
||||
result[1 * 4 + 3] = mat3Determinant(mMat3x3_n);
|
||||
result[2 * 4 + 3] = -mat3Determinant(mMat3x3_o);
|
||||
result[3 * 4 + 3] = mat3Determinant(mMat3x3_p);
|
||||
}
|
||||
|
||||
bool VSMatrix::inverseMatrix(VSMatrix &result)
|
||||
{
|
||||
// Calculate mat4 determinant
|
||||
FLOATTYPE det = mat4Determinant(mMatrix);
|
||||
|
||||
// Inverse unknown when determinant is close to zero
|
||||
if (fabs(det) < 1e-15)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
result.mMatrix[i] = FLOATTYPE(0.0);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mat4Adjoint(mMatrix, result.mMatrix);
|
||||
|
||||
FLOATTYPE invDet = FLOATTYPE(1.0) / det;
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
result.mMatrix[i] = result.mMatrix[i] * invDet;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
214
source/common/utility/matrix.h
Normal file
214
source/common/utility/matrix.h
Normal file
|
@ -0,0 +1,214 @@
|
|||
|
||||
// Matrix class based on code from VSML:
|
||||
|
||||
/** ----------------------------------------------------------
|
||||
* \class VSMathLib
|
||||
*
|
||||
* Lighthouse3D
|
||||
*
|
||||
* VSMathLib - Very Simple Matrix Library
|
||||
*
|
||||
* Full documentation at
|
||||
* http://www.lighthouse3d.com/very-simple-libs
|
||||
*
|
||||
* This class aims at easing geometric transforms, camera
|
||||
* placement and projection definition for programmers
|
||||
* working with OpenGL core versions.
|
||||
*
|
||||
*
|
||||
---------------------------------------------------------------*/
|
||||
#ifndef __VSMatrix__
|
||||
#define __VSMatrix__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "vectors.h"
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
typedef double FLOATTYPE;
|
||||
#else
|
||||
typedef float FLOATTYPE;
|
||||
#endif
|
||||
|
||||
class VSMatrix {
|
||||
|
||||
public:
|
||||
|
||||
VSMatrix()
|
||||
{
|
||||
}
|
||||
|
||||
VSMatrix(int)
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
|
||||
void translate(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
|
||||
void scale(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
|
||||
void rotate(FLOATTYPE angle, FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
|
||||
void loadIdentity();
|
||||
#ifdef USE_DOUBLE
|
||||
void multMatrix(const float *aMatrix);
|
||||
#endif
|
||||
void multVector(FLOATTYPE *aVector);
|
||||
void multMatrix(const FLOATTYPE *aMatrix);
|
||||
void multMatrix(const VSMatrix &aMatrix)
|
||||
{
|
||||
multMatrix(aMatrix.mMatrix);
|
||||
}
|
||||
void loadMatrix(const FLOATTYPE *aMatrix);
|
||||
#ifdef USE_DOUBLE
|
||||
void loadMatrix(const float *aMatrix);
|
||||
#endif
|
||||
void lookAt(FLOATTYPE xPos, FLOATTYPE yPos, FLOATTYPE zPos, FLOATTYPE xLook, FLOATTYPE yLook, FLOATTYPE zLook, FLOATTYPE xUp, FLOATTYPE yUp, FLOATTYPE zUp);
|
||||
void perspective(FLOATTYPE fov, FLOATTYPE ratio, FLOATTYPE nearp, FLOATTYPE farp);
|
||||
void ortho(FLOATTYPE left, FLOATTYPE right, FLOATTYPE bottom, FLOATTYPE top, FLOATTYPE nearp=-1.0f, FLOATTYPE farp=1.0f);
|
||||
void frustum(FLOATTYPE left, FLOATTYPE right, FLOATTYPE bottom, FLOATTYPE top, FLOATTYPE nearp, FLOATTYPE farp);
|
||||
void copy(FLOATTYPE * pDest)
|
||||
{
|
||||
memcpy(pDest, mMatrix, 16 * sizeof(FLOATTYPE));
|
||||
}
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
void copy(float * pDest)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
pDest[i] = (float)mMatrix[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const FLOATTYPE *get() const
|
||||
{
|
||||
return mMatrix;
|
||||
}
|
||||
|
||||
void multMatrixPoint(const FLOATTYPE *point, FLOATTYPE *res);
|
||||
|
||||
#ifdef USE_DOUBLE
|
||||
void computeNormalMatrix(const float *aMatrix);
|
||||
#endif
|
||||
void computeNormalMatrix(const FLOATTYPE *aMatrix);
|
||||
void computeNormalMatrix(const VSMatrix &aMatrix)
|
||||
{
|
||||
computeNormalMatrix(aMatrix.mMatrix);
|
||||
}
|
||||
bool inverseMatrix(VSMatrix &result);
|
||||
void transpose();
|
||||
|
||||
protected:
|
||||
static void crossProduct(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res);
|
||||
static FLOATTYPE dotProduct(const FLOATTYPE *a, const FLOATTYPE * b);
|
||||
static void normalize(FLOATTYPE *a);
|
||||
static void subtract(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res);
|
||||
static void add(const FLOATTYPE *a, const FLOATTYPE *b, FLOATTYPE *res);
|
||||
static FLOATTYPE length(const FLOATTYPE *a);
|
||||
static void multMatrix(FLOATTYPE *resMatrix, const FLOATTYPE *aMatrix);
|
||||
|
||||
static void setIdentityMatrix(FLOATTYPE *mat, int size = 4);
|
||||
|
||||
/// The storage for matrices
|
||||
FLOATTYPE mMatrix[16];
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Matrix3x4 // used like a 4x4 matrix with the last row always being (0,0,0,1)
|
||||
{
|
||||
float m[3][4];
|
||||
|
||||
public:
|
||||
|
||||
void MakeIdentity()
|
||||
{
|
||||
memset(m, 0, sizeof(m));
|
||||
m[0][0] = m[1][1] = m[2][2] = 1.f;
|
||||
}
|
||||
|
||||
void Translate(float x, float y, float z)
|
||||
{
|
||||
m[0][3] = m[0][0]*x + m[0][1]*y + m[0][2]*z + m[0][3];
|
||||
m[1][3] = m[1][0]*x + m[1][1]*y + m[1][2]*z + m[1][3];
|
||||
m[2][3] = m[2][0]*x + m[2][1]*y + m[2][2]*z + m[2][3];
|
||||
}
|
||||
|
||||
void Scale(float x, float y, float z)
|
||||
{
|
||||
m[0][0] *=x;
|
||||
m[1][0] *=x;
|
||||
m[2][0] *=x;
|
||||
|
||||
m[0][1] *=y;
|
||||
m[1][1] *=y;
|
||||
m[2][1] *=y;
|
||||
|
||||
m[0][2] *=z;
|
||||
m[1][2] *=z;
|
||||
m[2][2] *=z;
|
||||
}
|
||||
|
||||
void Rotate(float ax, float ay, float az, float angle)
|
||||
{
|
||||
Matrix3x4 m1;
|
||||
|
||||
FVector3 axis(ax, ay, az);
|
||||
axis.MakeUnit();
|
||||
double c = cos(angle * pi::pi()/180.), s = sin(angle * pi::pi()/180.), t = 1 - c;
|
||||
double sx = s*axis.X, sy = s*axis.Y, sz = s*axis.Z;
|
||||
double tx, ty, txx, tyy, u, v;
|
||||
|
||||
tx = t*axis.X;
|
||||
m1.m[0][0] = float( (txx=tx*axis.X) + c );
|
||||
m1.m[0][1] = float( (u=tx*axis.Y) - sz);
|
||||
m1.m[0][2] = float( (v=tx*axis.Z) + sy);
|
||||
|
||||
ty = t*axis.Y;
|
||||
m1.m[1][0] = float( u + sz);
|
||||
m1.m[1][1] = float( (tyy=ty*axis.Y) + c );
|
||||
m1.m[1][2] = float( (u=ty*axis.Z) - sx);
|
||||
|
||||
m1.m[2][0] = float( v - sy);
|
||||
m1.m[2][1] = float( u + sx);
|
||||
m1.m[2][2] = float( (t-txx-tyy) + c );
|
||||
|
||||
m1.m[0][3] = 0.f;
|
||||
m1.m[1][3] = 0.f;
|
||||
m1.m[2][3] = 0.f;
|
||||
|
||||
*this = (*this) * m1;
|
||||
}
|
||||
|
||||
Matrix3x4 operator *(const Matrix3x4 &other)
|
||||
{
|
||||
Matrix3x4 result;
|
||||
|
||||
result.m[0][0] = m[0][0]*other.m[0][0] + m[0][1]*other.m[1][0] + m[0][2]*other.m[2][0];
|
||||
result.m[0][1] = m[0][0]*other.m[0][1] + m[0][1]*other.m[1][1] + m[0][2]*other.m[2][1];
|
||||
result.m[0][2] = m[0][0]*other.m[0][2] + m[0][1]*other.m[1][2] + m[0][2]*other.m[2][2];
|
||||
result.m[0][3] = m[0][0]*other.m[0][3] + m[0][1]*other.m[1][3] + m[0][2]*other.m[2][3] + m[0][3];
|
||||
|
||||
result.m[1][0] = m[1][0]*other.m[0][0] + m[1][1]*other.m[1][0] + m[1][2]*other.m[2][0];
|
||||
result.m[1][1] = m[1][0]*other.m[0][1] + m[1][1]*other.m[1][1] + m[1][2]*other.m[2][1];
|
||||
result.m[1][2] = m[1][0]*other.m[0][2] + m[1][1]*other.m[1][2] + m[1][2]*other.m[2][2];
|
||||
result.m[1][3] = m[1][0]*other.m[0][3] + m[1][1]*other.m[1][3] + m[1][2]*other.m[2][3] + m[1][3];
|
||||
|
||||
result.m[2][0] = m[2][0]*other.m[0][0] + m[2][1]*other.m[1][0] + m[2][2]*other.m[2][0];
|
||||
result.m[2][1] = m[2][0]*other.m[0][1] + m[2][1]*other.m[1][1] + m[2][2]*other.m[2][1];
|
||||
result.m[2][2] = m[2][0]*other.m[0][2] + m[2][1]*other.m[1][2] + m[2][2]*other.m[2][2];
|
||||
result.m[2][3] = m[2][0]*other.m[0][3] + m[2][1]*other.m[1][3] + m[2][2]*other.m[2][3] + m[2][3];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FVector3 operator *(const FVector3 &vec)
|
||||
{
|
||||
FVector3 result;
|
||||
|
||||
result.X = vec.X*m[0][0] + vec.Y*m[0][1] + vec.Z*m[0][2] + m[0][3];
|
||||
result.Y = vec.X*m[1][0] + vec.Y*m[1][1] + vec.Z*m[1][2] + m[1][3];
|
||||
result.Z = vec.X*m[2][0] + vec.Y*m[2][1] + vec.Z*m[2][2] + m[2][3];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
1677
source/common/utility/vectors.h
Normal file
1677
source/common/utility/vectors.h
Normal file
File diff suppressed because it is too large
Load diff
238
source/common/utility/xs_Float.h
Normal file
238
source/common/utility/xs_Float.h
Normal file
|
@ -0,0 +1,238 @@
|
|||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
// xs_Float.h
|
||||
//
|
||||
// Source: "Know Your FPU: Fixing Floating Fast"
|
||||
// http://www.stereopsis.com/sree/fpu2006.html
|
||||
//
|
||||
// xs_CRoundToInt: Round toward nearest, but ties round toward even (just like FISTP)
|
||||
// xs_ToInt: Round toward zero, just like the C (int) cast
|
||||
// xs_FloorToInt: Round down
|
||||
// xs_CeilToInt: Round up
|
||||
// xs_RoundToInt: Round toward nearest, but ties round up
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
#ifndef _xs_FLOAT_H_
|
||||
#define _xs_FLOAT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// ====================================================================================================================
|
||||
// Defines
|
||||
// ====================================================================================================================
|
||||
#ifndef _xs_DEFAULT_CONVERSION
|
||||
#define _xs_DEFAULT_CONVERSION 0
|
||||
#endif //_xs_DEFAULT_CONVERSION
|
||||
|
||||
|
||||
#if __BIG_ENDIAN__
|
||||
#define _xs_iexp_ 0
|
||||
#define _xs_iman_ 1
|
||||
#else
|
||||
#define _xs_iexp_ 1 //intel is little endian
|
||||
#define _xs_iman_ 0
|
||||
#endif //BigEndian_
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define finline inline
|
||||
#else
|
||||
#define finline __forceinline
|
||||
#endif
|
||||
|
||||
typedef double real64;
|
||||
|
||||
|
||||
union _xs_doubleints
|
||||
{
|
||||
real64 val;
|
||||
uint32_t ival[2];
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define _xs_doublecopysgn(a,b) ((int32_t*)&a)[_xs_iexp_]&=~(((int32_t*)&b)[_xs_iexp_]&0x80000000)
|
||||
#define _xs_doubleisnegative(a) ((((int32_t*)&a)[_xs_iexp_])|0x80000000)
|
||||
#endif
|
||||
|
||||
// ====================================================================================================================
|
||||
// Constants
|
||||
// ====================================================================================================================
|
||||
const real64 _xs_doublemagic = real64 (6755399441055744.0); //2^52 * 1.5, uses limited precisicion to floor
|
||||
const real64 _xs_doublemagicdelta = (1.5e-8); //almost .5f = .5f + 1e^(number of exp bit)
|
||||
const real64 _xs_doublemagicroundeps = (.5f-_xs_doublemagicdelta); //almost .5f = .5f - 1e^(number of exp bit)
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// Prototypes
|
||||
// ====================================================================================================================
|
||||
static int32_t xs_CRoundToInt (real64 val, real64 dmr = _xs_doublemagic);
|
||||
static int32_t xs_ToInt (real64 val, real64 dme = -_xs_doublemagicroundeps);
|
||||
static int32_t xs_FloorToInt (real64 val, real64 dme = _xs_doublemagicroundeps);
|
||||
static int32_t xs_CeilToInt (real64 val, real64 dme = _xs_doublemagicroundeps);
|
||||
static int32_t xs_RoundToInt (real64 val);
|
||||
|
||||
//int32_t versions
|
||||
finline static int32_t xs_CRoundToInt (int32_t val) {return val;}
|
||||
finline static int32_t xs_ToInt (int32_t val) {return val;}
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// Fix Class
|
||||
// ====================================================================================================================
|
||||
template <int32_t N> class xs_Fix
|
||||
{
|
||||
public:
|
||||
typedef int32_t Fix;
|
||||
|
||||
// ====================================================================================================================
|
||||
// Basic Conversion from Numbers
|
||||
// ====================================================================================================================
|
||||
finline static Fix ToFix (int32_t val) {return val<<N;}
|
||||
finline static Fix ToFix (real64 val) {return xs_ConvertToFixed(val);}
|
||||
|
||||
// ====================================================================================================================
|
||||
// Basic Conversion to Numbers
|
||||
// ====================================================================================================================
|
||||
finline static real64 ToReal (Fix f) {return real64(f)/real64(1<<N);}
|
||||
finline static int32_t ToInt (Fix f) {return f>>N;}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
// ====================================================================================================================
|
||||
// Helper function - mainly to preserve _xs_DEFAULT_CONVERSION
|
||||
// ====================================================================================================================
|
||||
finline static int32_t xs_ConvertToFixed (real64 val)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt(val, _xs_doublemagic/(1<<N));
|
||||
#else
|
||||
return (long)((val)*(1<<N));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
finline static int32_t xs_ToFixed(int32_t n, real64 val)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt(val, _xs_doublemagic/(1<<n));
|
||||
#else
|
||||
return (long)((val)*(1<<N));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
// Inline implementation
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
finline static int32_t xs_CRoundToInt(real64 val, real64 dmr)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
_xs_doubleints uval;
|
||||
uval.val = val + dmr;
|
||||
return uval.ival[_xs_iman_];
|
||||
#else
|
||||
return int32_t(floor(val+.5));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32_t xs_ToInt(real64 val, real64 dme)
|
||||
{
|
||||
/* unused - something else I tried...
|
||||
_xs_doublecopysgn(dme,val);
|
||||
return xs_CRoundToInt(val+dme);
|
||||
return 0;
|
||||
*/
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
// VC++ 2005's standard cast is a little bit faster than this
|
||||
// magic number code. (Which is pretty amazing!) SSE has the
|
||||
// fastest C-style float->int conversion, but unfortunately,
|
||||
// checking for SSE support every time you need to do a
|
||||
// conversion completely negates its performance advantage.
|
||||
return int32_t(val);
|
||||
#else
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return (val<0) ? xs_CRoundToInt(val-dme) :
|
||||
xs_CRoundToInt(val+dme);
|
||||
#else
|
||||
return int32_t(val);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32_t xs_FloorToInt(real64 val, real64 dme)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt (val - dme);
|
||||
#else
|
||||
return floor(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32_t xs_CeilToInt(real64 val, real64 dme)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt (val + dme);
|
||||
#else
|
||||
return ceil(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32_t xs_RoundToInt(real64 val)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
// Yes, it is important that two fadds be generated, so you cannot override the dmr
|
||||
// passed to xs_CRoundToInt with _xs_doublemagic + _xs_doublemagicdelta. If you do,
|
||||
// you'll end up with Banker's Rounding again.
|
||||
return xs_CRoundToInt (val + _xs_doublemagicdelta);
|
||||
#else
|
||||
return floor(val+.5);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
// Unsigned variants
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
finline static uint32_t xs_CRoundToUInt(real64 val)
|
||||
{
|
||||
return (uint32_t)xs_CRoundToInt(val);
|
||||
}
|
||||
|
||||
finline static uint32_t xs_FloorToUInt(real64 val)
|
||||
{
|
||||
return (uint32_t)xs_FloorToInt(val);
|
||||
}
|
||||
|
||||
finline static uint32_t xs_CeilToUInt(real64 val)
|
||||
{
|
||||
return (uint32_t)xs_CeilToInt(val);
|
||||
}
|
||||
|
||||
finline static uint32_t xs_RoundToUInt(real64 val)
|
||||
{
|
||||
return (uint32_t)xs_RoundToInt(val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
#endif // _xs_FLOAT_H_
|
Loading…
Reference in a new issue