Initial commit
This commit is contained in:
575
engines/qdengine/qdcore/qd_d3dutils.cpp
Normal file
575
engines/qdengine/qdcore/qd_d3dutils.cpp
Normal file
@@ -0,0 +1,575 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Note: Must Define D3D_OVERLOADS to get C++ version of MATRIX3D
|
||||
#include "qdengine/qdcore/qd_d3dutils.h"
|
||||
|
||||
//набор своих функций, потому что те, что представлены в xMath.h
|
||||
//не удовлетворяют потребностям
|
||||
//я порой такой требовательный, что самому страшно.
|
||||
namespace QDEngine {
|
||||
|
||||
namespace vector_helpers {
|
||||
inline VALUE3D
|
||||
SquareMagnitude(const Vect3f &v) {
|
||||
return v.x * v.x + v.y * v.y + v.z * v.z;
|
||||
}
|
||||
|
||||
inline VALUE3D
|
||||
Magnitude(const Vect3f &v) {
|
||||
return (VALUE3D) sqrt(SquareMagnitude(v));
|
||||
}
|
||||
|
||||
|
||||
inline Vect3f
|
||||
Normalize(const Vect3f &v) {
|
||||
return v / Magnitude(v);
|
||||
}
|
||||
|
||||
inline VALUE3D DotProduct(const Vect3f &v1, const Vect3f &v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
inline Vect3f
|
||||
CrossProduct(const Vect3f &v1, const Vect3f &v2) {
|
||||
Vect3f result;
|
||||
|
||||
result[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
||||
result[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
||||
result[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//угол между векторами лежащими в плоскости ХОУ
|
||||
//иначе ее применять НЕЛЬЗЯ
|
||||
float VectorAngle(const Vect3f &v1, const Vect3f &v2) {
|
||||
return float(atan2(v2.y, v2.x) - atan2(v1.y, v1.x));
|
||||
}
|
||||
|
||||
}//vector_helpers
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ZeroMatrix
|
||||
** Purpose: sets D3D matrix to all 0's
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
ZeroMatrix() {
|
||||
MATRIX3D ret;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
ret(i, j) = 0.0f;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} // end ZeroMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: IdentityMatrix
|
||||
** Purpose: sets D3D matrix to Identiy (1's on diagonal, zero's elsewhere)
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
IdentityMatrix() {
|
||||
MATRIX3D ret;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
ret(i, j) = 0.0f;
|
||||
}
|
||||
ret(i, i) = 1.0f;
|
||||
}
|
||||
return ret;
|
||||
} // end IdentityMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ProjectionMatrix
|
||||
** Purpose: sets Projection matrix from fov, near and far planes
|
||||
** Notes:
|
||||
** 1. fov is in radians.
|
||||
** 2. See Blinn, "A Trip Down the Graphics Pipeline" pg 188 for details.
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
ProjectionMatrix(const float near_plane,
|
||||
const float far_plane,
|
||||
const float fov) {
|
||||
float c = (float) cos(fov * 0.5);
|
||||
float s = (float) sin(fov * 0.5);
|
||||
float Q = s / (1.0f - near_plane / far_plane);
|
||||
|
||||
MATRIX3D ret = ZeroMatrix();
|
||||
ret(0, 0) = c;
|
||||
ret(1, 1) = c;
|
||||
ret(2, 2) = Q;
|
||||
ret(3, 2) = -Q * near_plane;
|
||||
ret(2, 3) = s;
|
||||
return ret;
|
||||
} // end ProjectionMatrix
|
||||
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ViewMatrix
|
||||
** Purpose: Controls where the camara is.
|
||||
** Notes:
|
||||
** 1. Note the roll parameter is in radians and rools the viewpoint
|
||||
** around the viewing direction
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D ViewMatrixByDir(const Vect3f &from,
|
||||
const Vect3f &view_dir,
|
||||
const Vect3f &world_up,
|
||||
const Vect3f &cam_up) {
|
||||
MATRIX3D view = IdentityMatrix();
|
||||
//view_dir - Это ось Z в системе координат камеры
|
||||
Vect3f zAxis = view_dir;
|
||||
|
||||
//ось Х в правой системе координат
|
||||
Vect3f xAxis = vector_helpers::CrossProduct(zAxis, world_up);
|
||||
xAxis = vector_helpers::Normalize(xAxis);
|
||||
|
||||
Vect3f yAxis = vector_helpers::CrossProduct(zAxis, xAxis);
|
||||
|
||||
view(0, 0) = xAxis.x;
|
||||
view(1, 0) = xAxis.y;
|
||||
view(2, 0) = xAxis.z;
|
||||
|
||||
view(0, 1) = yAxis.x;
|
||||
view(1, 1) = yAxis.y;
|
||||
view(2, 1) = yAxis.z;
|
||||
|
||||
view(0, 2) = zAxis.x;
|
||||
view(1, 2) = zAxis.y;
|
||||
view(2, 2) = zAxis.z;
|
||||
|
||||
view(3, 0) = -vector_helpers::DotProduct(xAxis, from);
|
||||
view(3, 1) = -vector_helpers::DotProduct(cam_up, from);
|
||||
view(3, 2) = -vector_helpers::DotProduct(zAxis, from);
|
||||
/*
|
||||
* после всех вычислений верх камеры имеет с верхом мира угол небольше 90 градусов,
|
||||
* что по сути своей не всегда правильно. Для того, чтобы вычислить правильно поворот
|
||||
* вокруг оси Z используем up и cam_up. Где cam_up - это верх камеры, который должен
|
||||
* быть у неё после поворота.
|
||||
* Перед тем как вычислить угол переводим оба вектора в координаты камеры, тогда они
|
||||
* будут лежать в плоскости ХОУ. вычисляем угол и поворачиваем.
|
||||
*/
|
||||
|
||||
|
||||
//переводим в координаты камеры, чтобы получить
|
||||
//плоскую картинку и пользоваться atan2
|
||||
float r = vector_helpers::VectorAngle(TransformVector(cam_up, view),
|
||||
TransformVector(yAxis, view));
|
||||
|
||||
view = MatrixMult(RotateZMatrix(-r), view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
MATRIX3D
|
||||
ViewMatrix(const Vect3f &from,
|
||||
const Vect3f &at,
|
||||
const Vect3f &world_up,
|
||||
const Vect3f &cam_up) {
|
||||
|
||||
Vect3f view_dir = vector_helpers::Normalize(at - from);
|
||||
return ViewMatrixByDir(from, view_dir, world_up, cam_up);
|
||||
} // end ViewMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: RotateXMatrix
|
||||
** Purpose: Rotate matrix about X axis
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
RotateXMatrix(const float rads) {
|
||||
float cosine = (float) cos(rads);
|
||||
float sine = (float) sin(rads);
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(1, 1) = cosine;
|
||||
ret(2, 2) = -cosine;
|
||||
ret(1, 2) = sine;
|
||||
ret(2, 1) = sine;
|
||||
return ret;
|
||||
} // end RotateXMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: RotateYMatrix
|
||||
** Purpose: Rotate matrix about Y axis
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
RotateYMatrix(const float rads) {
|
||||
float const cosine = (float) cos(rads);
|
||||
float const sine = (float) sin(rads);
|
||||
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(0, 0) = cosine;
|
||||
ret(2, 2) = -cosine;
|
||||
|
||||
ret(0, 2) = sine;
|
||||
ret(2, 0) = sine;
|
||||
|
||||
return ret;
|
||||
} // end RotateY
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: RotateZMatrix
|
||||
** Purpose: Rotate matrix about Z axis
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
RotateZMatrix(const float rads) {
|
||||
float const cosine = (float) cos(rads);
|
||||
float const sine = (float) sin(rads);
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(0, 0) = cosine;
|
||||
ret(1, 1) = -cosine;
|
||||
|
||||
ret(0, 1) = sine;
|
||||
ret(1, 0) = sine;
|
||||
return ret;
|
||||
} // end RotateZMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: TranslateMatrix
|
||||
** Purpose: Returns matrix to translate by (dx, dy, dz)
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
TranslateMatrix(const float dx, const float dy, const float dz) {
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(3, 0) = dx;
|
||||
ret(3, 1) = dy;
|
||||
ret(3, 2) = dz;
|
||||
return ret;
|
||||
} // end TranslateMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: TranslateMatrix
|
||||
** Purpose: Returns matrix to translate by v
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
TranslateMatrix(const Vect3f &v) {
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(3, 0) = v[0];
|
||||
ret(3, 1) = v[1];
|
||||
ret(3, 2) = v[2];
|
||||
return ret;
|
||||
} // end TranslateMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ScaleMatrix
|
||||
** Purpose: scale matrix (uniform)
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
ScaleMatrix(const float size) {
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(0, 0) = size;
|
||||
ret(1, 1) = size;
|
||||
ret(2, 2) = size;
|
||||
return ret;
|
||||
} // end ScaleMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ScaleMatrix
|
||||
** Purpose: scale matrix
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
ScaleMatrix(const float a, const float b, const float c) {
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(0, 0) = a;
|
||||
ret(1, 1) = b;
|
||||
ret(2, 2) = c;
|
||||
return ret;
|
||||
} // end ScaleMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ScaleMatrix
|
||||
** Purpose: scale matrix
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
ScaleMatrix(const Vect3f &v) {
|
||||
MATRIX3D ret = IdentityMatrix();
|
||||
ret(0, 0) = v.x;
|
||||
ret(1, 1) = v.y;
|
||||
ret(2, 2) = v.z;
|
||||
return ret;
|
||||
} // end ScaleMatrix
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: MatrixMult
|
||||
** Purpose: [C] = [A] * [B]
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
MatrixMult(const MATRIX3D &a, const MATRIX3D &b) {
|
||||
MATRIX3D ret = ZeroMatrix();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
ret(i, j) += a(k, j) * b(i, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} // end MatrixMult
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: TransformVector
|
||||
** Purpose: V' = V * [M]
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Vect3f
|
||||
TransformVector(const Vect3f &v, const MATRIX3D &m) {
|
||||
float hvec[4] = {0.f};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
hvec[i] = 0.0f;
|
||||
// for (int j=0; j<3; j++) {
|
||||
// hvec[i] += v[j] * m(j, i);
|
||||
// }
|
||||
// hvec[i] += m(3, i);
|
||||
hvec[i] = v[0] * m(0, i)
|
||||
+ v[1] * m(1, i)
|
||||
+ v[2] * m(2, i)
|
||||
+ m(3, i);
|
||||
}
|
||||
return Vect3f(hvec[0] / hvec[3], hvec[1] / hvec[3], hvec[2] / hvec[3]);
|
||||
} // end TransformVector
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: TransformNormal
|
||||
** Purpose: N' = N * [M]
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Vect3f
|
||||
TransformNormal(const Vect3f &v, const MATRIX3D &mat) {
|
||||
MATRIX3D m;
|
||||
|
||||
m = MatrixInverse(mat);
|
||||
m = MatrixTranspose(m);
|
||||
return TransformVector(v, m);
|
||||
} // end TransformNormal
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: MatrixInverse
|
||||
** Purpose: Creates the inverse of a 4x4 matrix
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void lubksb(MATRIX3D &a, int *indx, float *b);
|
||||
static void ludcmp(MATRIX3D &a, int *indx, float *d);
|
||||
|
||||
MATRIX3D
|
||||
MatrixInverse(const MATRIX3D &m) {
|
||||
MATRIX3D n, y;
|
||||
int i, j, indx[4];
|
||||
float d, col[4];
|
||||
|
||||
n = m;
|
||||
ludcmp(n, indx, &d);
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
col[i] = 0.0f;
|
||||
}
|
||||
col[j] = 1.0f;
|
||||
lubksb(n, indx, col);
|
||||
for (i = 0; i < 4; i++) {
|
||||
y(i, j) = col[i];
|
||||
}
|
||||
}
|
||||
return y;
|
||||
} // end MatrixInverse
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: lubksb
|
||||
** Purpose: backward subsitution
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
lubksb(MATRIX3D &a, int *indx, float *b) {
|
||||
int i, j, ii = -1, ip;
|
||||
float sum;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ip = indx[i];
|
||||
sum = b[ip];
|
||||
b[ip] = b[i];
|
||||
if (ii >= 0) {
|
||||
for (j = ii; j <= i - 1; j++) {
|
||||
sum -= a(i, j) * b[j];
|
||||
}
|
||||
} else if (sum != 0.0) {
|
||||
ii = i;
|
||||
}
|
||||
b[i] = sum;
|
||||
}
|
||||
for (i = 3; i >= 0; i--) {
|
||||
sum = b[i];
|
||||
for (j = i + 1; j < 4; j++) {
|
||||
sum -= a(i, j) * b[j];
|
||||
}
|
||||
b[i] = sum / a(i, i);
|
||||
}
|
||||
} // end lubksb
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: ludcmp
|
||||
** Purpose: LU decomposition
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
ludcmp(MATRIX3D &a, int *indx, float *d) {
|
||||
float vv[4]; /* implicit scale for each row */
|
||||
float big, dum, sum, tmp;
|
||||
int i, imax = 0, j, k;
|
||||
|
||||
*d = 1.0f;
|
||||
for (i = 0; i < 4; i++) {
|
||||
big = 0.0f;
|
||||
for (j = 0; j < 4; j++) {
|
||||
if ((tmp = (float) fabs(a(i, j))) > big) {
|
||||
big = tmp;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (big == 0.0f) {
|
||||
printf("ludcmp(): singular matrix found...\n");
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
vv[i] = 1.0f / big;
|
||||
}
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < j; i++) {
|
||||
sum = a(i, j);
|
||||
for (k = 0; k < i; k++) {
|
||||
sum -= a(i, k) * a(k, j);
|
||||
}
|
||||
a(i, j) = sum;
|
||||
}
|
||||
big = 0.0f;
|
||||
for (i = j; i < 4; i++) {
|
||||
sum = a(i, j);
|
||||
for (k = 0; k < j; k++) {
|
||||
sum -= a(i, k) * a(k, j);
|
||||
}
|
||||
a(i, j) = sum;
|
||||
if ((dum = vv[i] * (float)fabs(sum)) >= big) {
|
||||
big = dum;
|
||||
imax = i;
|
||||
}
|
||||
}
|
||||
if (j != imax) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
dum = a(imax, k);
|
||||
a(imax, k) = a(j, k);
|
||||
a(j, k) = dum;
|
||||
}
|
||||
*d = -(*d);
|
||||
vv[imax] = vv[j];
|
||||
}
|
||||
indx[j] = imax;
|
||||
if (a(j, j) == 0.0f) {
|
||||
a(j, j) = 1.0e-20f; /* can be 0.0 also... */
|
||||
}
|
||||
if (j != 3) {
|
||||
dum = 1.0f / a(j, j);
|
||||
for (i = j + 1; i < 4; i++) {
|
||||
a(i, j) *= dum;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end ludcmp
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** Name: Matrix Transpose
|
||||
** Purpose: [M] = [M]'
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MATRIX3D
|
||||
MatrixTranspose(const MATRIX3D &m) {
|
||||
MATRIX3D ret;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
ret(i, j) = m(j, i);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} // end MatrixTranspose
|
||||
|
||||
/*
|
||||
Class Methods
|
||||
*/
|
||||
|
||||
/*
|
||||
**-----------------------------------------------------------------------------
|
||||
** end of File
|
||||
**-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
} // namespace QDEngine
|
||||
Reference in New Issue
Block a user