Files
scummvm-cursorfix/engines/wintermute/base/gfx/xmath.cpp
2026-02-02 04:50:13 +01:00

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