428 lines
12 KiB
C++
428 lines
12 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
||
*
|
||
* ScummVM is the legal property of its developers, whose names
|
||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||
* file distributed with this source distribution.
|
||
*
|
||
* 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/>.
|
||
*
|
||
*/
|
||
|
||
#include "watchmaker/3d/math/llmath.h"
|
||
#include "watchmaker/utils.h"
|
||
|
||
namespace Watchmaker {
|
||
|
||
int32 t3dFloatToInt(t3dF32 nfloat) {
|
||
int32 sint = nfloat;
|
||
// warning("STUBBED: t3dFloatToInt");
|
||
/*
|
||
__asm
|
||
{
|
||
fld nfloat
|
||
fistp sint
|
||
}*/
|
||
return sint;
|
||
}
|
||
|
||
void t3dMatIdentity(t3dM3X3F *d) {
|
||
d->M[1] = d->M[2] = d->M[3] = d->M[5] = d->M[6] = d->M[7] = 0.0;
|
||
d->M[0] = d->M[4] = d->M[8] = 1.0;
|
||
|
||
d->Flags |= T3D_MATRIX_IDENTITY;
|
||
}
|
||
|
||
void t3dMatMul(t3dM3X3F *Dest, t3dM3X3F *a, t3dM3X3F *b) {
|
||
t3dM3X3F Tmp, *d = &Tmp;
|
||
/* t3dM3X3F Tmp,*d=&Tmp;
|
||
int r,c;
|
||
|
||
if (Dest == a || Dest == b)
|
||
d=&Tmp;
|
||
else
|
||
d=Dest;
|
||
|
||
for (r=0; r<3; r++)
|
||
for (c=0; c<3; c++)
|
||
d->M[r][c]=a->M[r][0]*b->M[0][c]+a->M[r][1]*b->M[1][c]+a->M[r][2]*b->M[2][c];*/
|
||
|
||
d->M[0] = (a->M[0] * b->M[0] + a->M[1] * b->M[3] + a->M[2] * b->M[6]);
|
||
d->M[1] = (a->M[0] * b->M[1] + a->M[1] * b->M[4] + a->M[2] * b->M[7]);
|
||
d->M[2] = (a->M[0] * b->M[2] + a->M[1] * b->M[5] + a->M[2] * b->M[8]);
|
||
|
||
d->M[3] = (a->M[3] * b->M[0] + a->M[4] * b->M[3] + a->M[5] * b->M[6]);
|
||
d->M[4] = (a->M[3] * b->M[1] + a->M[4] * b->M[4] + a->M[5] * b->M[7]);
|
||
d->M[5] = (a->M[3] * b->M[2] + a->M[4] * b->M[5] + a->M[5] * b->M[8]);
|
||
|
||
d->M[6] = (a->M[6] * b->M[0] + a->M[7] * b->M[3] + a->M[8] * b->M[6]);
|
||
d->M[7] = (a->M[6] * b->M[1] + a->M[7] * b->M[4] + a->M[8] * b->M[7]);
|
||
d->M[8] = (a->M[6] * b->M[2] + a->M[7] * b->M[5] + a->M[8] * b->M[8]);
|
||
|
||
if (d != Dest)
|
||
t3dMatCopy(Dest, &Tmp);
|
||
|
||
}
|
||
|
||
void t3dMatCopy(t3dM3X3F *d, t3dM3X3F *s) {
|
||
d->M[0] = s->M[0];
|
||
d->M[1] = s->M[1];
|
||
d->M[2] = s->M[2];
|
||
d->M[3] = s->M[3];
|
||
d->M[4] = s->M[4];
|
||
d->M[5] = s->M[5];
|
||
d->M[6] = s->M[6];
|
||
d->M[7] = s->M[7];
|
||
d->M[8] = s->M[8];
|
||
d->Flags = 0;
|
||
}
|
||
|
||
void t3dMatView(t3dM3X3F *dest, t3dV3F *eye, t3dV3F *center) {
|
||
t3dM3X3F *fm = dest;
|
||
t3dM3X3F fmat;
|
||
|
||
// D3DVECTOR from,at,up;
|
||
|
||
if ((!eye) || (!dest)) return;
|
||
|
||
// F
|
||
t3dF32 dx = (t3dF32)(center->x - eye->x);
|
||
t3dF32 dy = (t3dF32)(center->y - eye->y);
|
||
t3dF32 dz = (t3dF32)(center->z - eye->z);
|
||
|
||
t3dF32 dd = (dx * dx + dy * dy + dz * dz);
|
||
if (dd == 0.0)dd = 1.0;
|
||
dd = (float)sqrt((t3dF64)dd); // dd = ||F||
|
||
|
||
t3dF32 d2 = (dz * dz + dx * dx);
|
||
if (d2 == 0.0)d2 = 1.0;
|
||
d2 = (float)sqrt((t3dF64)d2); // |s|
|
||
|
||
t3dF32 fcosa = (dz / d2);
|
||
t3dF32 fsina = (dx / d2);
|
||
fm->M[0] = fcosa;
|
||
fm->M[1] = 0;
|
||
fm->M[2] = -fsina;
|
||
fm->M[3] = 0;
|
||
fm->M[4] = 1;
|
||
fm->M[5] = 0;
|
||
fm->M[6] = fsina;
|
||
fm->M[7] = 0;
|
||
fm->M[8] = fcosa;
|
||
|
||
fcosa = (d2 / dd);
|
||
fsina = (dy / dd);
|
||
fmat.M[0] = 1;
|
||
fmat.M[1] = 0;
|
||
fmat.M[2] = 0;
|
||
fmat.M[3] = 0;
|
||
fmat.M[4] = fcosa;
|
||
fmat.M[5] = -fsina;
|
||
fmat.M[6] = 0;
|
||
fmat.M[7] = fsina;
|
||
fmat.M[8] = fcosa;
|
||
t3dMatMul(dest, &fmat, dest);
|
||
|
||
const float roll = 0.0f;
|
||
fcosa = (t3dF32)cos((-roll) / 180.0f * T3D_PI);
|
||
fsina = (t3dF32)sin((-roll) / 180.0f * T3D_PI);
|
||
fmat.M[0] = fcosa;
|
||
fmat.M[1] = fsina;
|
||
fmat.M[2] = 0;
|
||
fmat.M[3] = -fsina;
|
||
fmat.M[4] = fcosa;
|
||
fmat.M[5] = 0;
|
||
fmat.M[6] = 0;
|
||
fmat.M[7] = 0;
|
||
fmat.M[8] = 1;
|
||
t3dMatMul(dest, &fmat, dest);
|
||
|
||
dest->Flags &= ~T3D_MATRIX_IDENTITY;
|
||
}
|
||
|
||
void t3dVectTransform(t3dV3F *d, t3dV3F *s, t3dM3X3F *mat) {
|
||
t3dV3F Tmp;
|
||
Tmp.x = (s->x * mat->M[0]) + (s->y * mat->M[1]) + (s->z * mat->M[2]);
|
||
Tmp.y = (s->x * mat->M[3]) + (s->y * mat->M[4]) + (s->z * mat->M[5]);
|
||
Tmp.z = (s->x * mat->M[6]) + (s->y * mat->M[7]) + (s->z * mat->M[8]);
|
||
d->x = Tmp.x;
|
||
d->y = Tmp.y;
|
||
d->z = Tmp.z;
|
||
}
|
||
|
||
void t3dVectTransformInv(t3dV3F *d, t3dV3F *s, t3dM3X3F *mat) {
|
||
t3dV3F Tmp;
|
||
Tmp.x = (s->x * mat->M[0]) + (s->y * mat->M[3]) + (s->z * mat->M[6]);
|
||
Tmp.y = (s->x * mat->M[1]) + (s->y * mat->M[4]) + (s->z * mat->M[7]);
|
||
Tmp.z = (s->x * mat->M[2]) + (s->y * mat->M[5]) + (s->z * mat->M[8]);
|
||
d->x = Tmp.x;
|
||
d->y = Tmp.y;
|
||
d->z = Tmp.z;
|
||
}
|
||
|
||
void t3dVectCross(t3dV3F *d, t3dV3F *v2, t3dV3F *v3) {
|
||
t3dV3F Tmp;
|
||
Tmp.x = (v2->y * v3->z) - (v2->z * v3->y);
|
||
Tmp.y = (v2->z * v3->x) - (v2->x * v3->z);
|
||
Tmp.z = (v2->x * v3->y) - (v2->y * v3->x);
|
||
d->x = Tmp.x;
|
||
d->y = Tmp.y;
|
||
d->z = Tmp.z;
|
||
}
|
||
|
||
void t3dVectSub(t3dV3F *d, t3dV3F *a, t3dV3F *b) { // d = a - b
|
||
d->x = a->x - b->x;
|
||
d->y = a->y - b->y;
|
||
d->z = a->z - b->z;
|
||
}
|
||
|
||
void t3dVectAdd(t3dV3F *d, t3dV3F *a, t3dV3F *b) { // d = a - b
|
||
d->x = a->x + b->x;
|
||
d->y = a->y + b->y;
|
||
d->z = a->z + b->z;
|
||
}
|
||
|
||
void t3dVectFill(t3dV3F *d, t3dF32 a) {
|
||
d->x = a;
|
||
d->y = a;
|
||
d->z = a;
|
||
}
|
||
|
||
void t3dVectInit(t3dV3F *d, t3dF32 a1, t3dF32 a2, t3dF32 a3) {
|
||
d->x = a1;
|
||
d->y = a2;
|
||
d->z = a3;
|
||
}
|
||
|
||
void t3dVectCopy(t3dV3F *d, t3dV3F *s) {
|
||
memcpy(d, s, sizeof(t3dV3F));
|
||
}
|
||
|
||
|
||
t3dF32 t3dVectMod(t3dV3F *c) {
|
||
t3dF32 mod = (c->x * c->x + c->y * c->y + c->z * c->z);
|
||
if (mod)
|
||
return (float)sqrt((double)mod);
|
||
else
|
||
return 0.0f;
|
||
}
|
||
|
||
t3dF32 t3dVectDistance(t3dV3F *a, t3dV3F *b) {
|
||
t3dF32 mod;
|
||
t3dV3F c;
|
||
c.x = b->x - a->x;
|
||
c.y = b->y - a->y;
|
||
c.z = b->z - a->z;
|
||
mod = (c.x * c.x + c.y * c.y + c.z * c.z);
|
||
|
||
if (mod)
|
||
return ((float)sqrt((double)mod));
|
||
else
|
||
return 0.0f;
|
||
}
|
||
|
||
t3dF32 t3dVectDot(t3dV3F *a, t3dV3F *b) {
|
||
return (t3dF32)(a->x * b->x + a->y * b->y + a->z * b->z);
|
||
}
|
||
|
||
void t3dMatMulInv(t3dM3X3F *Dest, t3dM3X3F *a, t3dM3X3F *b) {
|
||
t3dM3X3F Tmp, *d = &Tmp;
|
||
|
||
d->M[0] = (a->M[0] * b->M[0] + a->M[1] * b->M[1] + a->M[2] * b->M[2]);
|
||
d->M[1] = (a->M[0] * b->M[3] + a->M[1] * b->M[4] + a->M[2] * b->M[5]);
|
||
d->M[2] = (a->M[0] * b->M[6] + a->M[1] * b->M[7] + a->M[2] * b->M[8]);
|
||
|
||
d->M[3] = (a->M[3] * b->M[0] + a->M[4] * b->M[1] + a->M[5] * b->M[2]);
|
||
d->M[4] = (a->M[3] * b->M[3] + a->M[4] * b->M[4] + a->M[5] * b->M[5]);
|
||
d->M[5] = (a->M[3] * b->M[6] + a->M[4] * b->M[7] + a->M[5] * b->M[8]);
|
||
|
||
d->M[6] = (a->M[6] * b->M[0] + a->M[7] * b->M[1] + a->M[8] * b->M[2]);
|
||
d->M[7] = (a->M[6] * b->M[3] + a->M[7] * b->M[4] + a->M[8] * b->M[5]);
|
||
d->M[8] = (a->M[6] * b->M[6] + a->M[7] * b->M[7] + a->M[8] * b->M[8]);
|
||
|
||
if (d != Dest)
|
||
t3dMatCopy(Dest, &Tmp);
|
||
}
|
||
|
||
void t3dPlaneNormal(t3dNORMAL *n, t3dV3F *p0, t3dV3F *p1, t3dV3F *p2) {
|
||
t3dV3F a, b;
|
||
|
||
t3dVectSub(&a, p1, p0);
|
||
t3dVectSub(&b, p2, p0);
|
||
t3dVectCross(&n->n, &a, &b);
|
||
t3dVectNormalize(&n->n);
|
||
|
||
n->dist = t3dVectDot(&n->n, p0);
|
||
}
|
||
|
||
void t3dVectNormalize(t3dV3F *c) {
|
||
t3dF32 mod = (float)sqrt((double)(c->x * c->x + c->y * c->y + c->z * c->z));
|
||
if (!mod)return;
|
||
mod = 1.0f / mod;
|
||
c->x = c->x * mod;
|
||
c->y = c->y * mod;
|
||
c->z = c->z * mod;
|
||
}
|
||
|
||
void t3dMatRot(t3dM3X3F *matrix, t3dF32 x, t3dF32 y, t3dF32 z) {
|
||
/* t3dF32 cx, cy, cz, sx, sy, sz,sxsy,szsy,szcy,czcy;
|
||
|
||
sx = sin(x);cx = cos(x); // qui ci vorrebbe una FSINCOS in asm
|
||
sy = sin(y);cy = cos(y);
|
||
sz = sin(z);cz = cos(z);
|
||
sxsy=sx*sy;szsy=sz*sy;szcy=sz*cy;czcy=cz*cy;
|
||
matrix->M[0] = czcy + sx*szsy ;
|
||
matrix->M[1] = -szcy + sxsy*cz ;
|
||
matrix->M[2] = cx*sy;
|
||
matrix->M[3] = cx*sz;
|
||
matrix->M[4] = cx*cz;
|
||
matrix->M[5] = -sx;
|
||
matrix->M[6] = -cz*sy + sx*szcy;
|
||
matrix->M[7] = szsy + sx*czcy;
|
||
matrix->M[8] = cx*cy ;*/
|
||
|
||
|
||
t3dM3X3F matrix_x, matrix_y, matrix_z;
|
||
|
||
t3dMatIdentity(&matrix_x);
|
||
t3dMatIdentity(&matrix_y);
|
||
t3dMatIdentity(&matrix_z);
|
||
|
||
/* | 1 0 0 0 | x' = x
|
||
| 0 cos <20> -sin <20> 0 | y' = (cos <20>) * y - (sin <20>) * z
|
||
| 0 sin <20> cos <20> 0 | z' = (sin <20>) * y + (cos <20>) * z
|
||
| 0 0 0 1 |*/
|
||
|
||
matrix_x.M[4] = (float)cos(x);
|
||
matrix_x.M[5] = -(float)sin(x);
|
||
matrix_x.M[7] = (float)sin(x);
|
||
matrix_x.M[8] = (float)cos(x);
|
||
|
||
/* | cos <20> 0 sin <20> 0 | x' = (cos <20>) * x + (sin <20>) * z
|
||
| 0 1 0 0 | y' = y
|
||
| -sin <20> 0 cos <20> 0 | z' = -(sin <20>) * x + (cos <20>) * z
|
||
| 0 0 0 1 |*/
|
||
|
||
matrix_y.M[0] = (float)cos(y);
|
||
matrix_y.M[2] = (float)sin(y);
|
||
matrix_y.M[6] = -(float)sin(y);
|
||
matrix_y.M[8] = (float)cos(y);
|
||
|
||
/* | cos <20> -sin <20> 0 0 | x' = (cos <20>) * x - (sin <20>) * y
|
||
| sin <20> cos <20> 0 0 | y' = (sin <20>) * x + (cos <20>) * y
|
||
| 0 0 1 0 | z' = z
|
||
| 0 0 0 1 |*/
|
||
|
||
matrix_z.M[0] = (float)cos(z);
|
||
matrix_z.M[1] = -(float)sin(z);
|
||
matrix_z.M[3] = (float)sin(z);
|
||
matrix_z.M[4] = (float)cos(z);
|
||
|
||
t3dMatMul(matrix, &matrix_x, &matrix_y);
|
||
t3dMatMul(matrix, matrix, &matrix_z);
|
||
}
|
||
|
||
t3dF32 t3dVectPlaneDistance(t3dV3F start, t3dNORMAL n) {
|
||
return t3dVectDot(&start, &n.n) - n.dist;
|
||
}
|
||
|
||
uint8 t3dVectPlaneIntersection(t3dV3F *inter, t3dV3F start, t3dV3F end, t3dNORMAL n) {
|
||
t3dF32 divi;
|
||
t3dF32 d1 = t3dVectPlaneDistance(start, n);
|
||
t3dF32 d2 = t3dVectPlaneDistance(end, n);
|
||
|
||
if ((d1 < 0) && (d2 < 0))
|
||
return 0;
|
||
else if ((d1 >= 0) && (d2 >= 0))
|
||
return 1;
|
||
|
||
|
||
if ((d1 < 0) && (d2 >= 0)) {
|
||
d2 = d2 - d1;
|
||
divi = -d1 / d2;
|
||
inter->x = start.x + divi * (end.x - start.x);
|
||
inter->y = start.y + divi * (end.y - start.y);
|
||
inter->z = start.z + divi * (end.z - start.z);
|
||
return 2;
|
||
} else {
|
||
d1 = d1 - d2;
|
||
divi = -d2 / d1;
|
||
inter->x = end.x + divi * (start.x - end.x);
|
||
inter->y = end.y + divi * (start.y - end.y);
|
||
inter->z = end.z + divi * (start.z - end.z);
|
||
return 3;
|
||
}
|
||
}
|
||
|
||
uint8 t3dVectTriangleIntersection(t3dV3F *inter, t3dV3F start, t3dV3F end,
|
||
t3dV3F v1, t3dV3F v2, t3dV3F v3, t3dNORMAL n) {
|
||
t3dV3F appo;
|
||
t3dNORMAL normal;
|
||
|
||
if (t3dVectPlaneIntersection(inter, start, end, n) <= 1)
|
||
return 0;
|
||
|
||
t3dVectAdd(&appo, &n.n, &v1);
|
||
t3dPlaneNormal(&normal, &appo, &v1, &v2);
|
||
|
||
if (t3dVectPlaneDistance(*inter, normal) >= 0.0f) {
|
||
t3dVectAdd(&appo, &n.n, &v2);
|
||
t3dPlaneNormal(&normal, &appo, &v2, &v3);
|
||
if (t3dVectPlaneDistance(*inter, normal) >= 0.0f) {
|
||
t3dVectAdd(&appo, &n.n, &v3);
|
||
t3dPlaneNormal(&normal, &appo, &v3, &v1);
|
||
if (t3dVectPlaneDistance(*inter, normal) >= 0.0f)
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
t3dF32 t3dVectSquaredDistance(t3dV3F *a, t3dV3F *b) {
|
||
t3dV3F c;
|
||
c.x = b->x - a->x;
|
||
c.y = b->y - a->y;
|
||
c.z = b->z - a->z;
|
||
|
||
return (c.x * c.x + c.y * c.y + c.z * c.z);
|
||
}
|
||
|
||
t3dF32 t3dPointSquaredDistance(t3dV3F *c) {
|
||
return (c->x * c->x + c->y * c->y + c->z * c->z);
|
||
}
|
||
|
||
void t3dMatReflect(t3dM3X3F *Matrix, t3dV3F *mirrorpos, t3dNORMAL *n) {
|
||
// | 1-2*nx*nx -2*nx*ny -2*nx*nz -2*nx*k |
|
||
// | -2*ny*nx 1-2*ny*ny -2*ny*nz -2*ny*k |
|
||
// | -2*nz*nx -2*nz*ny 1-2*nz*nz -2*nz*k |
|
||
// | 0 0 0 1 |
|
||
|
||
Matrix->M[0] = 1 - 2 * n->n.x * n->n.x;
|
||
Matrix->M[1] = -2 * n->n.x * n->n.y;
|
||
Matrix->M[2] = -2 * n->n.x * n->n.z;
|
||
Matrix->M[3] = -2 * n->n.y * n->n.x;
|
||
Matrix->M[4] = 1 - 2 * n->n.y * n->n.y;
|
||
Matrix->M[5] = -2 * n->n.y * n->n.z;
|
||
Matrix->M[6] = -2 * n->n.z * n->n.x;
|
||
Matrix->M[7] = -2 * n->n.z * n->n.y;
|
||
Matrix->M[8] = 1 - 2 * n->n.z * n->n.z;
|
||
|
||
mirrorpos->x = -2 * n->n.x * n->dist;
|
||
mirrorpos->y = -2 * n->n.y * n->dist;
|
||
mirrorpos->z = -2 * n->n.z * n->dist;
|
||
|
||
}
|
||
|
||
} // End of namespace Watchmaker
|