807 lines
22 KiB
C++
807 lines
22 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/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Code originated from Wine sources.
|
|
* Copyright (C) 2008 David Adam
|
|
* Copyright (C) 2008 Luis Busquets
|
|
* Copyright (C) 2008 Jérôme Gardou
|
|
* Copyright (C) 2008 Philip Nilsson
|
|
* Copyright (C) 2008 Henri Verbeet
|
|
*/
|
|
|
|
#include "engines/wintermute/base/gfx/xmath.h"
|
|
|
|
namespace Wintermute {
|
|
|
|
DXVector2::DXVector2() {
|
|
}
|
|
|
|
DXVector2::DXVector2(const float *pf) {
|
|
if (!pf)
|
|
return;
|
|
_x = pf[0];
|
|
_y = pf[1];
|
|
}
|
|
|
|
DXVector2::DXVector2(float fx, float fy) {
|
|
_x = fx;
|
|
_y = fy;
|
|
}
|
|
|
|
DXVector2::operator float* () {
|
|
return (float *)&_x;
|
|
}
|
|
|
|
DXVector2::operator const float* () const {
|
|
return (const float *)&_x;
|
|
}
|
|
|
|
DXVector2 &DXVector2::operator += (const DXVector2 &v) {
|
|
_x += v._x;
|
|
_y += v._y;
|
|
return *this;
|
|
}
|
|
|
|
DXVector2 &DXVector2::operator -= (const DXVector2 &v) {
|
|
_x -= v._x;
|
|
_y -= v._y;
|
|
return *this;
|
|
}
|
|
|
|
DXVector2 &DXVector2::operator *= (float f) {
|
|
_x *= f;
|
|
_y *= f;
|
|
return *this;
|
|
}
|
|
|
|
DXVector2 &DXVector2::operator /= (float f) {
|
|
_x /= f;
|
|
_y /= f;
|
|
return *this;
|
|
}
|
|
|
|
DXVector2 DXVector2::operator + () const {
|
|
return *this;
|
|
}
|
|
|
|
DXVector2 DXVector2::operator - () const {
|
|
return DXVector2(-_x, -_y);
|
|
}
|
|
|
|
DXVector2 DXVector2::operator + (const DXVector2 &v) const {
|
|
return DXVector2(_x + v._x, _y + v._y);
|
|
}
|
|
|
|
DXVector2 DXVector2::operator - (const DXVector2 &v) const {
|
|
return DXVector2(_x - v._x, _y - v._y);
|
|
}
|
|
|
|
DXVector2 DXVector2::operator * (float f) const {
|
|
return DXVector2(_x * f, _y * f);
|
|
}
|
|
|
|
DXVector2 DXVector2::operator / (float f) const {
|
|
return DXVector2(_x / f, _y / f);
|
|
}
|
|
|
|
DXVector2 operator * (float f, const DXVector2 &v) {
|
|
return DXVector2(f * v._x, f * v._y);
|
|
}
|
|
|
|
bool DXVector2::operator == (const DXVector2 &v) const {
|
|
return _x == v._x && _y == v._y;
|
|
}
|
|
|
|
bool DXVector2::operator != (const DXVector2 &v) const {
|
|
return _x != v._x || _y != v._y;
|
|
}
|
|
|
|
DXVector3::DXVector3(const float *pf) {
|
|
_x = pf[0];
|
|
_y = pf[1];
|
|
_z = pf[2];
|
|
}
|
|
|
|
DXVector3::DXVector3(float fx, float fy, float fz) {
|
|
_x = fx;
|
|
_y = fy;
|
|
_z = fz;
|
|
}
|
|
|
|
DXVector3::operator float* () {
|
|
return (float *)&_x;
|
|
}
|
|
|
|
DXVector3::operator const float* () const {
|
|
return (const float *)&_x;
|
|
}
|
|
|
|
DXVector3 &DXVector3::operator += (const DXVector3 &v) {
|
|
_x += v._x;
|
|
_y += v._y;
|
|
_z += v._z;
|
|
return *this;
|
|
}
|
|
|
|
DXVector3 &DXVector3::operator -= (const DXVector3 &v) {
|
|
_x -= v._x;
|
|
_y -= v._y;
|
|
_z -= v._z;
|
|
return *this;
|
|
}
|
|
|
|
DXVector3 &DXVector3::operator *= (float f) {
|
|
_x *= f;
|
|
_y *= f;
|
|
_z *= f;
|
|
return *this;
|
|
}
|
|
|
|
DXVector3 &DXVector3::operator /= (float f) {
|
|
_x /= f;
|
|
_y /= f;
|
|
_z /= f;
|
|
return *this;
|
|
}
|
|
|
|
DXVector3 DXVector3::operator + () const {
|
|
return *this;
|
|
}
|
|
|
|
DXVector3 DXVector3::operator - () const {
|
|
return DXVector3(-_x, -_y, -_z);
|
|
}
|
|
|
|
DXVector3 DXVector3::operator + (const DXVector3 &v) const {
|
|
return DXVector3(_x + v._x, _y + v._y, _z + v._z);
|
|
}
|
|
|
|
DXVector3 DXVector3::operator - (const DXVector3 &v) const {
|
|
return DXVector3(_x - v._x, _y - v._y, _z - v._z);
|
|
}
|
|
|
|
DXVector3 DXVector3::operator * (float f) const {
|
|
return DXVector3(_x * f, _y * f, _z * f);
|
|
}
|
|
|
|
DXVector3 DXVector3::operator / (float f) const {
|
|
return DXVector3(_x / f, _y / f, _z / f);
|
|
}
|
|
|
|
DXVector3 operator * (float f, const DXVector3 &v) {
|
|
return DXVector3(f * v._x, f * v._y, f * v._z);
|
|
}
|
|
|
|
bool DXVector3::operator == (const DXVector3 &v) const {
|
|
return _x == v._x && _y == v._y && _z == v._z;
|
|
}
|
|
|
|
bool DXVector3::operator != (const DXVector3 &v) const {
|
|
return _x != v._x || _y != v._y || _z != v._z;
|
|
}
|
|
|
|
DXVector4::DXVector4(const float *pf) {
|
|
_x = pf[0];
|
|
_y = pf[1];
|
|
_z = pf[2];
|
|
_w = pf[3];
|
|
}
|
|
|
|
DXVector4::DXVector4(float fx, float fy, float fz, float fw) {
|
|
_x = fx;
|
|
_y = fy;
|
|
_z = fz;
|
|
_w = fw;
|
|
}
|
|
|
|
DXVector4::operator float* () {
|
|
return (float *)&_x;
|
|
}
|
|
|
|
DXVector4::operator const float* () const {
|
|
return (const float *)&_x;
|
|
}
|
|
|
|
DXMatrix::DXMatrix(const float *pf) {
|
|
memcpy(&matrix._11, pf, sizeof(DXMatrix::matrix));
|
|
}
|
|
|
|
float &DXMatrix::operator () (uint32 row, uint32 col) {
|
|
return _m[row][col];
|
|
}
|
|
|
|
DXMatrix::operator float* () {
|
|
return (float *)&matrix._11;
|
|
}
|
|
|
|
DXMatrix::operator const float* () const {
|
|
return (const float *)&matrix._11;
|
|
}
|
|
|
|
DXMatrix DXMatrix::operator * (const DXMatrix &mat) const {
|
|
DXMatrix buf;
|
|
DXMatrixMultiply(&buf, this, &mat);
|
|
return buf;
|
|
}
|
|
|
|
DXQuaternion::DXQuaternion(const float *pf) {
|
|
_x = pf[0];
|
|
_y = pf[1];
|
|
_z = pf[2];
|
|
_w = pf[3];
|
|
}
|
|
|
|
DXQuaternion::DXQuaternion(float fx, float fy, float fz, float fw) {
|
|
_x = fx;
|
|
_y = fy;
|
|
_z = fz;
|
|
_w = fw;
|
|
}
|
|
|
|
DXQuaternion::operator float* () {
|
|
return (float *)&_x;
|
|
}
|
|
|
|
DXQuaternion::operator const float* () const {
|
|
return (const float *)&_x;
|
|
}
|
|
|
|
DXPlane::DXPlane(float fa, float fb, float fc, float fd) {
|
|
_a = fa;
|
|
_b = fb;
|
|
_c = fc;
|
|
_d = fd;
|
|
}
|
|
|
|
DXMatrix *DXMatrixTranspose(DXMatrix *pout, const DXMatrix *pm) {
|
|
uint32 i, j;
|
|
DXMatrix m;
|
|
|
|
m = *pm;
|
|
|
|
for (i = 0; i < 4; ++i)
|
|
for (j = 0; j < 4; ++j) pout->_m[i][j] = m._m[j][i];
|
|
|
|
return pout;
|
|
}
|
|
|
|
DXQuaternion *DXQuaternionRotationMatrix(DXQuaternion *out, const DXMatrix *m) {
|
|
float s, trace;
|
|
|
|
trace = m->_m[0][0] + m->_m[1][1] + m->_m[2][2] + 1.0f;
|
|
if (trace > 1.0f) {
|
|
s = 2.0f * sqrtf(trace);
|
|
out->_x = (m->_m[1][2] - m->_m[2][1]) / s;
|
|
out->_y = (m->_m[2][0] - m->_m[0][2]) / s;
|
|
out->_z = (m->_m[0][1] - m->_m[1][0]) / s;
|
|
out->_w = 0.25f * s;
|
|
} else {
|
|
int i, maxi = 0;
|
|
|
|
for (i = 1; i < 3; i++) {
|
|
if (m->_m[i][i] > m->_m[maxi][maxi])
|
|
maxi = i;
|
|
}
|
|
|
|
switch (maxi) {
|
|
case 0:
|
|
s = 2.0f * sqrtf(1.0f + m->_m[0][0] - m->_m[1][1] - m->_m[2][2]);
|
|
out->_x = 0.25f * s;
|
|
out->_y = (m->_m[0][1] + m->_m[1][0]) / s;
|
|
out->_z = (m->_m[0][2] + m->_m[2][0]) / s;
|
|
out->_w = (m->_m[1][2] - m->_m[2][1]) / s;
|
|
break;
|
|
|
|
case 1:
|
|
s = 2.0f * sqrtf(1.0f + m->_m[1][1] - m->_m[0][0] - m->_m[2][2]);
|
|
out->_x = (m->_m[0][1] + m->_m[1][0]) / s;
|
|
out->_y = 0.25f * s;
|
|
out->_z = (m->_m[1][2] + m->_m[2][1]) / s;
|
|
out->_w = (m->_m[2][0] - m->_m[0][2]) / s;
|
|
break;
|
|
|
|
case 2:
|
|
s = 2.0f * sqrtf(1.0f + m->_m[2][2] - m->_m[0][0] - m->_m[1][1]);
|
|
out->_x = (m->_m[0][2] + m->_m[2][0]) / s;
|
|
out->_y = (m->_m[1][2] + m->_m[2][1]) / s;
|
|
out->_z = 0.25f * s;
|
|
out->_w = (m->_m[0][1] - m->_m[1][0]) / s;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
DXMatrix *DXMatrixPerspectiveFovLH(DXMatrix *pout,float fovy, float aspect, float zn, float zf) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = 1.0f / (aspect * tanf(fovy / 2.0f));
|
|
pout->_m[1][1] = 1.0f / tanf(fovy / 2.0f);
|
|
pout->_m[2][2] = zf / (zf - zn);
|
|
pout->_m[2][3] = 1.0f;
|
|
pout->_m[3][2] = (zf * zn) / (zn - zf);
|
|
pout->_m[3][3] = 0.0f;
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixPerspectiveFovRH(DXMatrix *pout, float fovy, float aspect, float zn, float zf) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = 1.0f / (aspect * tanf(fovy / 2.0f));
|
|
pout->_m[1][1] = 1.0f / tanf(fovy / 2.0f);
|
|
pout->_m[2][2] = zf / (zn - zf);
|
|
pout->_m[2][3] = -1.0f;
|
|
pout->_m[3][2] = (zf * zn) / (zn - zf);
|
|
pout->_m[3][3] = 0.0f;
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixInverse(DXMatrix *pout, float *pdeterminant, const DXMatrix *pm) {
|
|
float det, t[3], v[16];
|
|
int i, j;
|
|
|
|
t[0] = pm->_m[2][2] * pm->_m[3][3] - pm->_m[2][3] * pm->_m[3][2];
|
|
t[1] = pm->_m[1][2] * pm->_m[3][3] - pm->_m[1][3] * pm->_m[3][2];
|
|
t[2] = pm->_m[1][2] * pm->_m[2][3] - pm->_m[1][3] * pm->_m[2][2];
|
|
v[0] = pm->_m[1][1] * t[0] - pm->_m[2][1] * t[1] + pm->_m[3][1] * t[2];
|
|
v[4] = -pm->_m[1][0] * t[0] + pm->_m[2][0] * t[1] - pm->_m[3][0] * t[2];
|
|
|
|
t[0] = pm->_m[1][0] * pm->_m[2][1] - pm->_m[2][0] * pm->_m[1][1];
|
|
t[1] = pm->_m[1][0] * pm->_m[3][1] - pm->_m[3][0] * pm->_m[1][1];
|
|
t[2] = pm->_m[2][0] * pm->_m[3][1] - pm->_m[3][0] * pm->_m[2][1];
|
|
v[8] = pm->_m[3][3] * t[0] - pm->_m[2][3] * t[1] + pm->_m[1][3] * t[2];
|
|
v[12] = -pm->_m[3][2] * t[0] + pm->_m[2][2] * t[1] - pm->_m[1][2] * t[2];
|
|
|
|
det = pm->_m[0][0] * v[0] + pm->_m[0][1] * v[4] + pm->_m[0][2] * v[8] + pm->_m[0][3] * v[12];
|
|
if (det == 0.0f)
|
|
return nullptr;
|
|
if (pdeterminant)
|
|
*pdeterminant = det;
|
|
|
|
t[0] = pm->_m[2][2] * pm->_m[3][3] - pm->_m[2][3] * pm->_m[3][2];
|
|
t[1] = pm->_m[0][2] * pm->_m[3][3] - pm->_m[0][3] * pm->_m[3][2];
|
|
t[2] = pm->_m[0][2] * pm->_m[2][3] - pm->_m[0][3] * pm->_m[2][2];
|
|
v[1] = -pm->_m[0][1] * t[0] + pm->_m[2][1] * t[1] - pm->_m[3][1] * t[2];
|
|
v[5] = pm->_m[0][0] * t[0] - pm->_m[2][0] * t[1] + pm->_m[3][0] * t[2];
|
|
|
|
t[0] = pm->_m[0][0] * pm->_m[2][1] - pm->_m[2][0] * pm->_m[0][1];
|
|
t[1] = pm->_m[3][0] * pm->_m[0][1] - pm->_m[0][0] * pm->_m[3][1];
|
|
t[2] = pm->_m[2][0] * pm->_m[3][1] - pm->_m[3][0] * pm->_m[2][1];
|
|
v[9] = -pm->_m[3][3] * t[0] - pm->_m[2][3] * t[1]- pm->_m[0][3] * t[2];
|
|
v[13] = pm->_m[3][2] * t[0] + pm->_m[2][2] * t[1] + pm->_m[0][2] * t[2];
|
|
|
|
t[0] = pm->_m[1][2] * pm->_m[3][3] - pm->_m[1][3] * pm->_m[3][2];
|
|
t[1] = pm->_m[0][2] * pm->_m[3][3] - pm->_m[0][3] * pm->_m[3][2];
|
|
t[2] = pm->_m[0][2] * pm->_m[1][3] - pm->_m[0][3] * pm->_m[1][2];
|
|
v[2] = pm->_m[0][1] * t[0] - pm->_m[1][1] * t[1] + pm->_m[3][1] * t[2];
|
|
v[6] = -pm->_m[0][0] * t[0] + pm->_m[1][0] * t[1] - pm->_m[3][0] * t[2];
|
|
|
|
t[0] = pm->_m[0][0] * pm->_m[1][1] - pm->_m[1][0] * pm->_m[0][1];
|
|
t[1] = pm->_m[3][0] * pm->_m[0][1] - pm->_m[0][0] * pm->_m[3][1];
|
|
t[2] = pm->_m[1][0] * pm->_m[3][1] - pm->_m[3][0] * pm->_m[1][1];
|
|
v[10] = pm->_m[3][3] * t[0] + pm->_m[1][3] * t[1] + pm->_m[0][3] * t[2];
|
|
v[14] = -pm->_m[3][2] * t[0] - pm->_m[1][2] * t[1] - pm->_m[0][2] * t[2];
|
|
|
|
t[0] = pm->_m[1][2] * pm->_m[2][3] - pm->_m[1][3] * pm->_m[2][2];
|
|
t[1] = pm->_m[0][2] * pm->_m[2][3] - pm->_m[0][3] * pm->_m[2][2];
|
|
t[2] = pm->_m[0][2] * pm->_m[1][3] - pm->_m[0][3] * pm->_m[1][2];
|
|
v[3] = -pm->_m[0][1] * t[0] + pm->_m[1][1] * t[1] - pm->_m[2][1] * t[2];
|
|
v[7] = pm->_m[0][0] * t[0] - pm->_m[1][0] * t[1] + pm->_m[2][0] * t[2];
|
|
|
|
v[11] = -pm->_m[0][0] * (pm->_m[1][1] * pm->_m[2][3] - pm->_m[1][3] * pm->_m[2][1]) +
|
|
pm->_m[1][0] * (pm->_m[0][1] * pm->_m[2][3] - pm->_m[0][3] * pm->_m[2][1]) -
|
|
pm->_m[2][0] * (pm->_m[0][1] * pm->_m[1][3] - pm->_m[0][3] * pm->_m[1][1]);
|
|
|
|
v[15] = pm->_m[0][0] * (pm->_m[1][1] * pm->_m[2][2] - pm->_m[1][2] * pm->_m[2][1]) -
|
|
pm->_m[1][0] * (pm->_m[0][1] * pm->_m[2][2] - pm->_m[0][2] * pm->_m[2][1]) +
|
|
pm->_m[2][0] * (pm->_m[0][1] * pm->_m[1][2] - pm->_m[0][2] * pm->_m[1][1]);
|
|
|
|
det = 1.0f / det;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
for (j = 0; j < 4; j++)
|
|
pout->_m[i][j] = v[4 * i + j] * det;
|
|
|
|
return pout;
|
|
}
|
|
|
|
DXPlane *DXPlaneFromPointNormal(DXPlane *pout, const DXVector3 *pvpoint, const DXVector3 *pvnormal) {
|
|
pout->_a = pvnormal->_x;
|
|
pout->_b = pvnormal->_y;
|
|
pout->_c = pvnormal->_z;
|
|
pout->_d = -DXVec3Dot(pvpoint, pvnormal);
|
|
return pout;
|
|
}
|
|
|
|
DXPlane *DXPlaneFromPoints(DXPlane *pout, const DXVector3 *pv1, const DXVector3 *pv2, const DXVector3 *pv3) {
|
|
DXVector3 edge1, edge2, normal, Nnormal;
|
|
|
|
edge1._x = 0.0f; edge1._y = 0.0f; edge1._z = 0.0f;
|
|
edge2._x = 0.0f; edge2._y = 0.0f; edge2._z = 0.0f;
|
|
DXVec3Subtract(&edge1, pv2, pv1);
|
|
DXVec3Subtract(&edge2, pv3, pv1);
|
|
DXVec3Cross(&normal, &edge1, &edge2);
|
|
DXVec3Normalize(&Nnormal, &normal);
|
|
DXPlaneFromPointNormal(pout, pv1, &Nnormal);
|
|
return pout;
|
|
}
|
|
|
|
DXVector3 *DXPlaneIntersectLine(DXVector3 *pout, const DXPlane *pp, const DXVector3 *pv1, const DXVector3 *pv2) {
|
|
DXVector3 direction, normal;
|
|
float dot, temp;
|
|
|
|
normal._x = pp->_a;
|
|
normal._y = pp->_b;
|
|
normal._z = pp->_c;
|
|
direction._x = pv2->_x - pv1->_x;
|
|
direction._y = pv2->_y - pv1->_y;
|
|
direction._z = pv2->_z - pv1->_z;
|
|
dot = DXVec3Dot(&normal, &direction);
|
|
if (!dot)
|
|
return nullptr;
|
|
temp = (pp->_d + DXVec3Dot(&normal, pv1) ) / dot;
|
|
pout->_x = pv1->_x - temp * direction._x;
|
|
pout->_y = pv1->_y - temp * direction._y;
|
|
pout->_z = pv1->_z - temp * direction._z;
|
|
return pout;
|
|
}
|
|
|
|
DXVector3 *DXVec3Normalize(DXVector3 *pout, const DXVector3 *pv) {
|
|
float norm;
|
|
|
|
norm = DXVec3Length(pv);
|
|
if (!norm) {
|
|
pout->_x = 0.0f;
|
|
pout->_y = 0.0f;
|
|
pout->_z = 0.0f;
|
|
} else {
|
|
pout->_x = pv->_x / norm;
|
|
pout->_y = pv->_y / norm;
|
|
pout->_z = pv->_z / norm;
|
|
}
|
|
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixTranslation(DXMatrix *pout, float x, float y, float z) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[3][0] = x;
|
|
pout->_m[3][1] = y;
|
|
pout->_m[3][2] = z;
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixScaling(DXMatrix *pout, float sx, float sy, float sz) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = sx;
|
|
pout->_m[1][1] = sy;
|
|
pout->_m[2][2] = sz;
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixRotationY(DXMatrix *pout, float angle) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = cosf(angle);
|
|
pout->_m[2][2] = cosf(angle);
|
|
pout->_m[0][2] = -sinf(angle);
|
|
pout->_m[2][0] = sinf(angle);
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixRotationZ(DXMatrix *pout, float angle) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = cosf(angle);
|
|
pout->_m[1][1] = cosf(angle);
|
|
pout->_m[0][1] = sinf(angle);
|
|
pout->_m[1][0] = -sinf(angle);
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixRotationYawPitchRoll(DXMatrix *out, float yaw, float pitch, float roll) {
|
|
float sroll, croll, spitch, cpitch, syaw, cyaw;
|
|
|
|
sroll = sinf(roll);
|
|
croll = cosf(roll);
|
|
spitch = sinf(pitch);
|
|
cpitch = cosf(pitch);
|
|
syaw = sinf(yaw);
|
|
cyaw = cosf(yaw);
|
|
|
|
out->_m[0][0] = sroll * spitch * syaw + croll * cyaw;
|
|
out->_m[0][1] = sroll * cpitch;
|
|
out->_m[0][2] = sroll * spitch * cyaw - croll * syaw;
|
|
out->_m[0][3] = 0.0f;
|
|
out->_m[1][0] = croll * spitch * syaw - sroll * cyaw;
|
|
out->_m[1][1] = croll * cpitch;
|
|
out->_m[1][2] = croll * spitch * cyaw + sroll * syaw;
|
|
out->_m[1][3] = 0.0f;
|
|
out->_m[2][0] = cpitch * syaw;
|
|
out->_m[2][1] = -spitch;
|
|
out->_m[2][2] = cpitch * cyaw;
|
|
out->_m[2][3] = 0.0f;
|
|
out->_m[3][0] = 0.0f;
|
|
out->_m[3][1] = 0.0f;
|
|
out->_m[3][2] = 0.0f;
|
|
out->_m[3][3] = 1.0f;
|
|
|
|
return out;
|
|
}
|
|
|
|
DXMatrix *DXMatrixRotationQuaternion(DXMatrix *pout, const DXQuaternion *pq) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = 1.0f - 2.0f * (pq->_y * pq->_y + pq->_z * pq->_z);
|
|
pout->_m[0][1] = 2.0f * (pq->_x *pq->_y + pq->_z * pq->_w);
|
|
pout->_m[0][2] = 2.0f * (pq->_x * pq->_z - pq->_y * pq->_w);
|
|
pout->_m[1][0] = 2.0f * (pq->_x * pq->_y - pq->_z * pq->_w);
|
|
pout->_m[1][1] = 1.0f - 2.0f * (pq->_x * pq->_x + pq->_z * pq->_z);
|
|
pout->_m[1][2] = 2.0f * (pq->_y *pq->_z + pq->_x *pq->_w);
|
|
pout->_m[2][0] = 2.0f * (pq->_x * pq->_z + pq->_y * pq->_w);
|
|
pout->_m[2][1] = 2.0f * (pq->_y *pq->_z - pq->_x *pq->_w);
|
|
pout->_m[2][2] = 1.0f - 2.0f * (pq->_x * pq->_x + pq->_y * pq->_y);
|
|
return pout;
|
|
}
|
|
|
|
DXQuaternion *DXQuaternionSlerp(DXQuaternion *out, const DXQuaternion *q1, const DXQuaternion *q2, float t) {
|
|
float dot, temp;
|
|
|
|
temp = 1.0f - t;
|
|
dot = DXQuaternionDot(q1, q2);
|
|
if (dot < 0.0f) {
|
|
t = -t;
|
|
dot = -dot;
|
|
}
|
|
|
|
if (1.0f - dot > 0.001f) {
|
|
float theta = acosf(dot);
|
|
temp = sinf(theta * temp) / sinf(theta);
|
|
t = sinf(theta * t) / sinf(theta);
|
|
}
|
|
|
|
out->_x = temp * q1->_x + t * q2->_x;
|
|
out->_y = temp * q1->_y + t * q2->_y;
|
|
out->_z = temp * q1->_z + t * q2->_z;
|
|
out->_w = temp * q1->_w + t * q2->_w;
|
|
|
|
return out;
|
|
}
|
|
|
|
float DXQuaternionDot(const DXVector4 *pq1, const DXVector4 *pq2) {
|
|
return (pq1->_x) * (pq2->_x) + (pq1->_y) * (pq2->_y) + (pq1->_z) * (pq2->_z) + (pq1->_w) * (pq2->_w);
|
|
}
|
|
|
|
DXVector4 *DXVec3Transform(DXVector4 *pout, const DXVector3 *pv, const DXMatrix *pm) {
|
|
DXVector4 out;
|
|
|
|
out._x = pm->_m[0][0] * pv->_x + pm->_m[1][0] * pv->_y + pm->_m[2][0] * pv->_z + pm->_m[3][0];
|
|
out._y = pm->_m[0][1] * pv->_x + pm->_m[1][1] * pv->_y + pm->_m[2][1] * pv->_z + pm->_m[3][1];
|
|
out._z = pm->_m[0][2] * pv->_x + pm->_m[1][2] * pv->_y + pm->_m[2][2] * pv->_z + pm->_m[3][2];
|
|
out._w = pm->_m[0][3] * pv->_x + pm->_m[1][3] * pv->_y + pm->_m[2][3] * pv->_z + pm->_m[3][3];
|
|
*pout = out;
|
|
return pout;
|
|
}
|
|
|
|
DXVector3 *DXVec3TransformCoord(DXVector3 *pout, const DXVector3 *pv, const DXMatrix *pm) {
|
|
DXVector3 out;
|
|
|
|
float norm = pm->_m[0][3] * pv->_x + pm->_m[1][3] * pv->_y + pm->_m[2][3] *pv->_z + pm->_m[3][3];
|
|
|
|
out._x = (pm->_m[0][0] * pv->_x + pm->_m[1][0] * pv->_y + pm->_m[2][0] * pv->_z + pm->_m[3][0]) / norm;
|
|
out._y = (pm->_m[0][1] * pv->_x + pm->_m[1][1] * pv->_y + pm->_m[2][1] * pv->_z + pm->_m[3][1]) / norm;
|
|
out._z = (pm->_m[0][2] * pv->_x + pm->_m[1][2] * pv->_y + pm->_m[2][2] * pv->_z + pm->_m[3][2]) / norm;
|
|
|
|
*pout = out;
|
|
|
|
return pout;
|
|
}
|
|
|
|
DXVector3 *DXVec3TransformNormal(DXVector3 *pout, const DXVector3 *pv, const DXMatrix *pm) {
|
|
const DXVector3 v = *pv;
|
|
|
|
pout->_x = pm->_m[0][0] * v._x + pm->_m[1][0] * v._y + pm->_m[2][0] * v._z;
|
|
pout->_y = pm->_m[0][1] * v._x + pm->_m[1][1] * v._y + pm->_m[2][1] * v._z;
|
|
pout->_z = pm->_m[0][2] * v._x + pm->_m[1][2] * v._y + pm->_m[2][2] * v._z;
|
|
return pout;
|
|
}
|
|
|
|
DXVector4 *DXVec4Transform(DXVector4 *pout, const DXVector4 *pv, const DXMatrix *pm) {
|
|
DXVector4 out;
|
|
|
|
out._x = pm->_m[0][0] * pv->_x + pm->_m[1][0] * pv->_y + pm->_m[2][0] * pv->_z + pm->_m[3][0] * pv->_w;
|
|
out._y = pm->_m[0][1] * pv->_x + pm->_m[1][1] * pv->_y + pm->_m[2][1] * pv->_z + pm->_m[3][1] * pv->_w;
|
|
out._z = pm->_m[0][2] * pv->_x + pm->_m[1][2] * pv->_y + pm->_m[2][2] * pv->_z + pm->_m[3][2] * pv->_w;
|
|
out._w = pm->_m[0][3] * pv->_x + pm->_m[1][3] * pv->_y + pm->_m[2][3] * pv->_z + pm->_m[3][3] * pv->_w;
|
|
*pout = out;
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixMultiply(DXMatrix *pout, const DXMatrix *pm1, const DXMatrix *pm2) {
|
|
DXMatrix out;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int j = 0; j < 4; j++) {
|
|
out._m[i][j] = pm1->_m[i][0] * pm2->_m[0][j] + pm1->_m[i][1] * pm2->_m[1][j] + pm1->_m[i][2] * pm2->_m[2][j] + pm1->_m[i][3] * pm2->_m[3][j];
|
|
}
|
|
}
|
|
|
|
*pout = out;
|
|
return pout;
|
|
}
|
|
|
|
DXVector3 *DXVec3Project(DXVector3 *pout, const DXVector3 *pv, const DXViewport *pviewport,
|
|
const DXMatrix *pprojection, const DXMatrix *pview, const DXMatrix *pworld) {
|
|
DXMatrix m;
|
|
|
|
DXMatrixIdentity(&m);
|
|
if (pworld)
|
|
DXMatrixMultiply(&m, &m, pworld);
|
|
if (pview)
|
|
DXMatrixMultiply(&m, &m, pview);
|
|
if (pprojection)
|
|
DXMatrixMultiply(&m, &m, pprojection);
|
|
|
|
DXVec3TransformCoord(pout, pv, &m);
|
|
|
|
if (pviewport) {
|
|
pout->_x = pviewport->_x + (1.0f + pout->_x) * pviewport->_width / 2.0f;
|
|
pout->_y = pviewport->_y + (1.0f - pout->_y) * pviewport->_height / 2.0f;
|
|
pout->_z = pviewport->_minZ + pout->_z * (pviewport->_maxZ - pviewport->_minZ);
|
|
}
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixLookAtLH(DXMatrix *out, const DXVector3 *eye, const DXVector3 *at, const DXVector3 *up) {
|
|
DXVector3 right, upn, vec;
|
|
|
|
DXVec3Subtract(&vec, at, eye);
|
|
DXVec3Normalize(&vec, &vec);
|
|
DXVec3Cross(&right, up, &vec);
|
|
DXVec3Cross(&upn, &vec, &right);
|
|
DXVec3Normalize(&right, &right);
|
|
DXVec3Normalize(&upn, &upn);
|
|
out->_m[0][0] = right._x;
|
|
out->_m[1][0] = right._y;
|
|
out->_m[2][0] = right._z;
|
|
out->_m[3][0] = -DXVec3Dot(&right, eye);
|
|
out->_m[0][1] = upn._x;
|
|
out->_m[1][1] = upn._y;
|
|
out->_m[2][1] = upn._z;
|
|
out->_m[3][1] = -DXVec3Dot(&upn, eye);
|
|
out->_m[0][2] = vec._x;
|
|
out->_m[1][2] = vec._y;
|
|
out->_m[2][2] = vec._z;
|
|
out->_m[3][2] = -DXVec3Dot(&vec, eye);
|
|
out->_m[0][3] = 0.0f;
|
|
out->_m[1][3] = 0.0f;
|
|
out->_m[2][3] = 0.0f;
|
|
out->_m[3][3] = 1.0f;
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
DXMatrix *DXMatrixLookAtRH(DXMatrix *out, const DXVector3 *eye, const DXVector3 *at, const DXVector3 *up) {
|
|
DXVector3 right, upn, vec;
|
|
|
|
DXVec3Subtract(&vec, at, eye);
|
|
DXVec3Normalize(&vec, &vec);
|
|
DXVec3Cross(&right, up, &vec);
|
|
DXVec3Cross(&upn, &vec, &right);
|
|
DXVec3Normalize(&right, &right);
|
|
DXVec3Normalize(&upn, &upn);
|
|
out->_m[0][0] = -right._x;
|
|
out->_m[1][0] = -right._y;
|
|
out->_m[2][0] = -right._z;
|
|
out->_m[3][0] = DXVec3Dot(&right, eye);
|
|
out->_m[0][1] = upn._x;
|
|
out->_m[1][1] = upn._y;
|
|
out->_m[2][1] = upn._z;
|
|
out->_m[3][1] = -DXVec3Dot(&upn, eye);
|
|
out->_m[0][2] = -vec._x;
|
|
out->_m[1][2] = -vec._y;
|
|
out->_m[2][2] = -vec._z;
|
|
out->_m[3][2] = DXVec3Dot(&vec, eye);
|
|
out->_m[0][3] = 0.0f;
|
|
out->_m[1][3] = 0.0f;
|
|
out->_m[2][3] = 0.0f;
|
|
out->_m[3][3] = 1.0f;
|
|
|
|
return out;
|
|
}
|
|
|
|
DXMatrix *DXMatrixOrthoLH(DXMatrix *pout, float w, float h, float zn, float zf) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = 2.0f / w;
|
|
pout->_m[1][1] = 2.0f / h;
|
|
pout->_m[2][2] = 1.0f / (zf - zn);
|
|
pout->_m[3][2] = zn / (zn - zf);
|
|
return pout;
|
|
}
|
|
|
|
DXMatrix *DXMatrixOrthoOffCenterLH(DXMatrix *pout, float l, float r, float b, float t, float zn, float zf) {
|
|
DXMatrixIdentity(pout);
|
|
pout->_m[0][0] = 2.0f / (r - l);
|
|
pout->_m[1][1] = 2.0f / (t - b);
|
|
pout->_m[2][2] = 1.0f / (zf -zn);
|
|
pout->_m[3][0] = -1.0f - 2.0f * l / (r - l);
|
|
pout->_m[3][1] = 1.0f + 2.0f * t / (b - t);
|
|
pout->_m[3][2] = zn / (zn -zf);
|
|
return pout;
|
|
}
|
|
|
|
DXPlane *DXPlaneNormalize(DXPlane *out, const DXPlane *p) {
|
|
float norm;
|
|
|
|
norm = sqrtf(p->_a * p->_a + p->_b * p->_b + p->_c * p->_c);
|
|
if (norm) {
|
|
out->_a = p->_a / norm;
|
|
out->_b = p->_b / norm;
|
|
out->_c = p->_c / norm;
|
|
out->_d = p->_d / norm;
|
|
} else {
|
|
out->_a = 0.0f;
|
|
out->_b = 0.0f;
|
|
out->_c = 0.0f;
|
|
out->_d = 0.0f;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
DXMatrix *DXMatrixShadow(DXMatrix *pout, const DXVector4 *plight, const DXPlane *pplane) {
|
|
DXPlane nplane;
|
|
float dot;
|
|
|
|
DXPlaneNormalize(&nplane, pplane);
|
|
dot = DXPlaneDot(&nplane, plight);
|
|
pout->_m[0][0] = dot - nplane._a * plight->_x;
|
|
pout->_m[0][1] = -nplane._a * plight->_y;
|
|
pout->_m[0][2] = -nplane._a * plight->_z;
|
|
pout->_m[0][3] = -nplane._a * plight->_w;
|
|
pout->_m[1][0] = -nplane._b * plight->_x;
|
|
pout->_m[1][1] = dot - nplane._b * plight->_y;
|
|
pout->_m[1][2] = -nplane._b * plight->_z;
|
|
pout->_m[1][3] = -nplane._b * plight->_w;
|
|
pout->_m[2][0] = -nplane._c * plight->_x;
|
|
pout->_m[2][1] = -nplane._c * plight->_y;
|
|
pout->_m[2][2] = dot - nplane._c * plight->_z;
|
|
pout->_m[2][3] = -nplane._c * plight->_w;
|
|
pout->_m[3][0] = -nplane._d * plight->_x;
|
|
pout->_m[3][1] = -nplane._d * plight->_y;
|
|
pout->_m[3][2] = -nplane._d * plight->_z;
|
|
pout->_m[3][3] = dot - nplane._d * plight->_w;
|
|
return pout;
|
|
}
|
|
|
|
DXVector2 *DXVec2TransformCoord(DXVector2 *pout, const DXVector2 *pv, const DXMatrix *pm) {
|
|
DXVector2 v;
|
|
float norm;
|
|
|
|
v = *pv;
|
|
norm = pm->_m[0][3] * pv->_x + pm->_m[1][3] * pv->_y + pm->_m[3][3];
|
|
|
|
pout->_x = (pm->_m[0][0] * v._x + pm->_m[1][0] * v._y + pm->_m[3][0]) / norm;
|
|
pout->_y = (pm->_m[0][1] * v._x + pm->_m[1][1] * v._y + pm->_m[3][1]) / norm;
|
|
|
|
return pout;
|
|
}
|
|
|
|
} // End of namespace Wintermute
|