From 0f2eee0b24b09449258c755988707c69c9cd991d Mon Sep 17 00:00:00 2001 From: shenlei Date: Tue, 22 Sep 2026 20:02:15 +0900 Subject: [PATCH] port/common: platform-independent D3DX8 math layer D3DXVECTOR2/3/4, D3DXMATRIX, D3DXQUATERNION, D3DXPLANE, D3DXCOLOR with d3dx8math.inl operator semantics, plus the D3DX* functions the 2V3 slice logic uses. Covered by port.common; port_gate passes on macOS, Android, iOS and Windows (mingw). Co-Authored-By: Claude Opus 5 --- docs/PORT-PLAN.md | 10 +- extension/src/port/common/D3DXMath.cpp | 304 ++++++++++++++++++ extension/src/port/common/D3DXMath.h | 413 +++++++++++++++++++++++++ extension/tests/port_common_test.cpp | 49 +++ 4 files changed, 775 insertions(+), 1 deletion(-) create mode 100644 extension/src/port/common/D3DXMath.cpp create mode 100644 extension/src/port/common/D3DXMath.h diff --git a/docs/PORT-PLAN.md b/docs/PORT-PLAN.md index 8e76094a..79a6ed99 100644 --- a/docs/PORT-PLAN.md +++ b/docs/PORT-PLAN.md @@ -126,7 +126,15 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 单独构建;每个 `port/**.h` 独立编译两次的门禁 `port_header_gate`;`port.common` 测试。编译宏取 40250 发布版 `Metin2Distribute.exe` 的 `Distribute|Win32` 配置:所有库 `NDEBUG`,GameLib 加 `USE_LOD`,UserInterface 加 `USE_LOD;_DISTRIBUTE`;不定义 `WIN32`。 -- 未完成:D3DX 数学层、闭包头文件照抄(步骤 2)、platform 接口骨架(步骤 4)。 +- 已完成:D3DX 数学层 `port/common/D3DXMath.{h,cpp}`。内容包括: + - 基础结构 `D3DVECTOR`/`D3DCOLORVALUE`/`D3DMATRIX`; + - 类型 `D3DXVECTOR2/3/4`、`D3DXMATRIX`、`D3DXQUATERNION`、`D3DXPLANE`、`D3DXCOLOR`,运算符照 `d3dx8math.inl` + (例如 `v / f` 实现为乘以 `1/f`); + - 2V3 切片用到的 `D3DXVec*`、`D3DXMatrix*`、`D3DXQuaternion*` 函数,采用行向量、左手旋转、D3DX 的乘法顺序; + 后续单元用到新函数时再按需补。 + + 这一层不包含 D3D8 渲染枚举和结构(`D3DLIGHT8`、`D3DRS_*` 等),它们归 platform 层。测试在 `port.common` 里。 +- 未完成:闭包头文件照抄(步骤 2)、platform 接口骨架(步骤 4)。 | 平台 | port_gate | | --- | --- | diff --git a/extension/src/port/common/D3DXMath.cpp b/extension/src/port/common/D3DXMath.cpp new file mode 100644 index 00000000..c5d776ad --- /dev/null +++ b/extension/src/port/common/D3DXMath.cpp @@ -0,0 +1,304 @@ +#include "D3DXMath.h" + +D3DXMATRIX& D3DXMATRIX::operator*=(const D3DXMATRIX& mat) +{ + D3DXMatrixMultiply(this, this, &mat); + return *this; +} + +D3DXMATRIX D3DXMATRIX::operator*(const D3DXMATRIX& mat) const +{ + D3DXMATRIX matT; + D3DXMatrixMultiply(&matT, this, &mat); + return matT; +} + +BOOL D3DXMATRIX::operator==(const D3DXMATRIX& mat) const +{ + for (int i = 0; i < 16; ++i) + if ((&_11)[i] != (&mat._11)[i]) + return FALSE; + return TRUE; +} + +D3DXQUATERNION& D3DXQUATERNION::operator*=(const D3DXQUATERNION& q) +{ + D3DXQuaternionMultiply(this, this, &q); + return *this; +} + +D3DXQUATERNION D3DXQUATERNION::operator*(const D3DXQUATERNION& q) const +{ + D3DXQUATERNION qT; + D3DXQuaternionMultiply(&qT, this, &q); + return qT; +} + +D3DXVECTOR2* D3DXVec2Normalize(D3DXVECTOR2* pOut, const D3DXVECTOR2* pV) +{ + const FLOAT norm = D3DXVec2Length(pV); + if (!norm) + { + pOut->x = 0.0f; + pOut->y = 0.0f; + } + else + { + pOut->x = pV->x / norm; + pOut->y = pV->y / norm; + } + return pOut; +} + +D3DXVECTOR3* D3DXVec3Normalize(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV) +{ + const FLOAT norm = D3DXVec3Length(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; +} + +D3DXVECTOR4* D3DXVec3Transform(D3DXVECTOR4* pOut, const D3DXVECTOR3* pV, const D3DXMATRIX* pM) +{ + D3DXVECTOR4 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; +} + +D3DXVECTOR3* D3DXVec3TransformCoord(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV, const D3DXMATRIX* pM) +{ + const FLOAT norm = pM->m[0][3] * pV->x + pM->m[1][3] * pV->y + pM->m[2][3] * pV->z + pM->m[3][3]; + D3DXVECTOR3 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]) / 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; +} + +D3DXVECTOR3* D3DXVec3TransformNormal(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV, const D3DXMATRIX* pM) +{ + D3DXVECTOR3 out; + out.x = pM->m[0][0] * pV->x + pM->m[1][0] * pV->y + pM->m[2][0] * pV->z; + out.y = pM->m[0][1] * pV->x + pM->m[1][1] * pV->y + pM->m[2][1] * pV->z; + out.z = pM->m[0][2] * pV->x + pM->m[1][2] * pV->y + pM->m[2][2] * pV->z; + *pOut = out; + return pOut; +} + +D3DXMATRIX* D3DXMatrixMultiply(D3DXMATRIX* pOut, const D3DXMATRIX* pM1, const D3DXMATRIX* pM2) +{ + D3DXMATRIX 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; +} + +D3DXMATRIX* D3DXMatrixTranspose(D3DXMATRIX* pOut, const D3DXMATRIX* pM) +{ + D3DXMATRIX out; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + out.m[i][j] = pM->m[j][i]; + *pOut = out; + return pOut; +} + +D3DXMATRIX* D3DXMatrixInverse(D3DXMATRIX* pOut, FLOAT* pDeterminant, const D3DXMATRIX* pM) +{ + const float* a = &pM->_11; + float inv[16]; + inv[0] = a[5] * a[10] * a[15] - a[5] * a[11] * a[14] - a[9] * a[6] * a[15] + a[9] * a[7] * a[14] + a[13] * a[6] * a[11] - a[13] * a[7] * a[10]; + inv[4] = -a[4] * a[10] * a[15] + a[4] * a[11] * a[14] + a[8] * a[6] * a[15] - a[8] * a[7] * a[14] - a[12] * a[6] * a[11] + a[12] * a[7] * a[10]; + inv[8] = a[4] * a[9] * a[15] - a[4] * a[11] * a[13] - a[8] * a[5] * a[15] + a[8] * a[7] * a[13] + a[12] * a[5] * a[11] - a[12] * a[7] * a[9]; + inv[12] = -a[4] * a[9] * a[14] + a[4] * a[10] * a[13] + a[8] * a[5] * a[14] - a[8] * a[6] * a[13] - a[12] * a[5] * a[10] + a[12] * a[6] * a[9]; + inv[1] = -a[1] * a[10] * a[15] + a[1] * a[11] * a[14] + a[9] * a[2] * a[15] - a[9] * a[3] * a[14] - a[13] * a[2] * a[11] + a[13] * a[3] * a[10]; + inv[5] = a[0] * a[10] * a[15] - a[0] * a[11] * a[14] - a[8] * a[2] * a[15] + a[8] * a[3] * a[14] + a[12] * a[2] * a[11] - a[12] * a[3] * a[10]; + inv[9] = -a[0] * a[9] * a[15] + a[0] * a[11] * a[13] + a[8] * a[1] * a[15] - a[8] * a[3] * a[13] - a[12] * a[1] * a[11] + a[12] * a[3] * a[9]; + inv[13] = a[0] * a[9] * a[14] - a[0] * a[10] * a[13] - a[8] * a[1] * a[14] + a[8] * a[2] * a[13] + a[12] * a[1] * a[10] - a[12] * a[2] * a[9]; + inv[2] = a[1] * a[6] * a[15] - a[1] * a[7] * a[14] - a[5] * a[2] * a[15] + a[5] * a[3] * a[14] + a[13] * a[2] * a[7] - a[13] * a[3] * a[6]; + inv[6] = -a[0] * a[6] * a[15] + a[0] * a[7] * a[14] + a[4] * a[2] * a[15] - a[4] * a[3] * a[14] - a[12] * a[2] * a[7] + a[12] * a[3] * a[6]; + inv[10] = a[0] * a[5] * a[15] - a[0] * a[7] * a[13] - a[4] * a[1] * a[15] + a[4] * a[3] * a[13] + a[12] * a[1] * a[7] - a[12] * a[3] * a[5]; + inv[14] = -a[0] * a[5] * a[14] + a[0] * a[6] * a[13] + a[4] * a[1] * a[14] - a[4] * a[2] * a[13] - a[12] * a[1] * a[6] + a[12] * a[2] * a[5]; + inv[3] = -a[1] * a[6] * a[11] + a[1] * a[7] * a[10] + a[5] * a[2] * a[11] - a[5] * a[3] * a[10] - a[9] * a[2] * a[7] + a[9] * a[3] * a[6]; + inv[7] = a[0] * a[6] * a[11] - a[0] * a[7] * a[10] - a[4] * a[2] * a[11] + a[4] * a[3] * a[10] + a[8] * a[2] * a[7] - a[8] * a[3] * a[6]; + inv[11] = -a[0] * a[5] * a[11] + a[0] * a[7] * a[9] + a[4] * a[1] * a[11] - a[4] * a[3] * a[9] - a[8] * a[1] * a[7] + a[8] * a[3] * a[5]; + inv[15] = a[0] * a[5] * a[10] - a[0] * a[6] * a[9] - a[4] * a[1] * a[10] + a[4] * a[2] * a[9] + a[8] * a[1] * a[6] - a[8] * a[2] * a[5]; + + const float det = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12]; + if (pDeterminant) + *pDeterminant = det; + if (det == 0.0f) + return nullptr; + + const float invDet = 1.0f / det; + for (int i = 0; i < 16; ++i) + (&pOut->_11)[i] = inv[i] * invDet; + return pOut; +} + +D3DXMATRIX* D3DXMatrixScaling(D3DXMATRIX* pOut, FLOAT sx, FLOAT sy, FLOAT sz) +{ + D3DXMatrixIdentity(pOut); + pOut->m[0][0] = sx; + pOut->m[1][1] = sy; + pOut->m[2][2] = sz; + return pOut; +} + +D3DXMATRIX* D3DXMatrixTranslation(D3DXMATRIX* pOut, FLOAT x, FLOAT y, FLOAT z) +{ + D3DXMatrixIdentity(pOut); + pOut->m[3][0] = x; + pOut->m[3][1] = y; + pOut->m[3][2] = z; + return pOut; +} + +D3DXMATRIX* D3DXMatrixRotationX(D3DXMATRIX* pOut, FLOAT angle) +{ + const FLOAT s = sinf(angle), c = cosf(angle); + D3DXMatrixIdentity(pOut); + pOut->m[1][1] = c; + pOut->m[1][2] = s; + pOut->m[2][1] = -s; + pOut->m[2][2] = c; + return pOut; +} + +D3DXMATRIX* D3DXMatrixRotationY(D3DXMATRIX* pOut, FLOAT angle) +{ + const FLOAT s = sinf(angle), c = cosf(angle); + D3DXMatrixIdentity(pOut); + pOut->m[0][0] = c; + pOut->m[0][2] = -s; + pOut->m[2][0] = s; + pOut->m[2][2] = c; + return pOut; +} + +D3DXMATRIX* D3DXMatrixRotationZ(D3DXMATRIX* pOut, FLOAT angle) +{ + const FLOAT s = sinf(angle), c = cosf(angle); + D3DXMatrixIdentity(pOut); + pOut->m[0][0] = c; + pOut->m[0][1] = s; + pOut->m[1][0] = -s; + pOut->m[1][1] = c; + return pOut; +} + +D3DXMATRIX* D3DXMatrixRotationAxis(D3DXMATRIX* pOut, const D3DXVECTOR3* pV, FLOAT angle) +{ + D3DXVECTOR3 v; + D3DXVec3Normalize(&v, pV); + const FLOAT s = sinf(angle), c = cosf(angle), cdiff = 1.0f - c; + D3DXMatrixIdentity(pOut); + pOut->m[0][0] = cdiff * v.x * v.x + c; + pOut->m[1][0] = cdiff * v.x * v.y - s * v.z; + pOut->m[2][0] = cdiff * v.x * v.z + s * v.y; + pOut->m[0][1] = cdiff * v.y * v.x + s * v.z; + pOut->m[1][1] = cdiff * v.y * v.y + c; + pOut->m[2][1] = cdiff * v.y * v.z - s * v.x; + pOut->m[0][2] = cdiff * v.z * v.x - s * v.y; + pOut->m[1][2] = cdiff * v.z * v.y + s * v.x; + pOut->m[2][2] = cdiff * v.z * v.z + c; + return pOut; +} + +D3DXMATRIX* D3DXMatrixRotationQuaternion(D3DXMATRIX* pOut, const D3DXQUATERNION* pQ) +{ + D3DXMatrixIdentity(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; +} + +// Roll about Z, then pitch about X, then yaw about Y (row vectors: M = Rz * Rx * Ry). +D3DXMATRIX* D3DXMatrixRotationYawPitchRoll(D3DXMATRIX* pOut, FLOAT yaw, FLOAT pitch, FLOAT roll) +{ + D3DXMATRIX z, x, y; + D3DXMatrixRotationZ(&z, roll); + D3DXMatrixRotationX(&x, pitch); + D3DXMatrixRotationY(&y, yaw); + D3DXMatrixMultiply(pOut, &z, &x); + D3DXMatrixMultiply(pOut, pOut, &y); + return pOut; +} + +// D3DX order: the result is the rotation pQ1 followed by pQ2 (the product pQ2 * pQ1). +D3DXQUATERNION* D3DXQuaternionMultiply(D3DXQUATERNION* pOut, const D3DXQUATERNION* pQ1, const D3DXQUATERNION* pQ2) +{ + D3DXQUATERNION out; + out.x = pQ2->w * pQ1->x + pQ2->x * pQ1->w + pQ2->y * pQ1->z - pQ2->z * pQ1->y; + out.y = pQ2->w * pQ1->y - pQ2->x * pQ1->z + pQ2->y * pQ1->w + pQ2->z * pQ1->x; + out.z = pQ2->w * pQ1->z + pQ2->x * pQ1->y - pQ2->y * pQ1->x + pQ2->z * pQ1->w; + out.w = pQ2->w * pQ1->w - pQ2->x * pQ1->x - pQ2->y * pQ1->y - pQ2->z * pQ1->z; + *pOut = out; + return pOut; +} + +D3DXQUATERNION* D3DXQuaternionNormalize(D3DXQUATERNION* pOut, const D3DXQUATERNION* pQ) +{ + const FLOAT norm = sqrtf(pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w); + if (!norm) + { + pOut->x = pOut->y = pOut->z = pOut->w = 0.0f; + } + else + { + pOut->x = pQ->x / norm; + pOut->y = pQ->y / norm; + pOut->z = pQ->z / norm; + pOut->w = pQ->w / norm; + } + return pOut; +} + +D3DXQUATERNION* D3DXQuaternionRotationAxis(D3DXQUATERNION* pOut, const D3DXVECTOR3* pV, FLOAT angle) +{ + D3DXVECTOR3 v; + D3DXVec3Normalize(&v, pV); + const FLOAT s = sinf(angle / 2.0f); + pOut->x = s * v.x; + pOut->y = s * v.y; + pOut->z = s * v.z; + pOut->w = cosf(angle / 2.0f); + return pOut; +} + +D3DXQUATERNION* D3DXQuaternionRotationYawPitchRoll(D3DXQUATERNION* pOut, FLOAT yaw, FLOAT pitch, FLOAT roll) +{ + const FLOAT syaw = sinf(yaw / 2.0f), cyaw = cosf(yaw / 2.0f); + const FLOAT spitch = sinf(pitch / 2.0f), cpitch = cosf(pitch / 2.0f); + const FLOAT sroll = sinf(roll / 2.0f), croll = cosf(roll / 2.0f); + pOut->x = syaw * cpitch * sroll + cyaw * spitch * croll; + pOut->y = syaw * cpitch * croll - cyaw * spitch * sroll; + pOut->z = cyaw * cpitch * sroll - syaw * spitch * croll; + pOut->w = cyaw * cpitch * croll + syaw * spitch * sroll; + return pOut; +} diff --git a/extension/src/port/common/D3DXMath.h b/extension/src/port/common/D3DXMath.h new file mode 100644 index 00000000..163acd23 --- /dev/null +++ b/extension/src/port/common/D3DXMath.h @@ -0,0 +1,413 @@ +#pragma once +// Platform-independent D3DX8 math (d3dx8math.h/.inl) for ported 40250 logic: GameLib/UserInterface +// use these types as data (TPixelPosition is a D3DXVECTOR3), not only for rendering. Operators keep +// the d3dx8math.inl formulas and evaluation order (e.g. `v / f` multiplies by `1.0f / f`); the +// D3DX* functions follow the documented D3DX conventions (row vectors, left-handed rotations). +// Functions are added on demand as ported units call them. + +#include "Win32Types.h" + +#include + +#define D3DX_PI ((FLOAT)3.141592654f) +#define D3DX_1BYPI ((FLOAT)0.318309886f) +#define D3DXToRadian(degree) ((degree) * (D3DX_PI / 180.0f)) +#define D3DXToDegree(radian) ((radian) * (180.0f / D3DX_PI)) + +typedef DWORD D3DCOLOR; + +typedef struct _D3DVECTOR +{ + float x; + float y; + float z; +} D3DVECTOR; + +typedef struct _D3DCOLORVALUE +{ + float r; + float g; + float b; + float a; +} D3DCOLORVALUE; + +typedef struct _D3DMATRIX +{ + union + { + struct + { + float _11, _12, _13, _14; + float _21, _22, _23, _24; + float _31, _32, _33, _34; + float _41, _42, _43, _44; + }; + float m[4][4]; + }; +} D3DMATRIX; + +struct D3DXVECTOR2 +{ + D3DXVECTOR2() {} + D3DXVECTOR2(const FLOAT* pf) : x(pf[0]), y(pf[1]) {} + D3DXVECTOR2(FLOAT fx, FLOAT fy) : x(fx), y(fy) {} + + operator FLOAT*() { return &x; } + operator const FLOAT*() const { return &x; } + + D3DXVECTOR2& operator+=(const D3DXVECTOR2& v) { x += v.x; y += v.y; return *this; } + D3DXVECTOR2& operator-=(const D3DXVECTOR2& v) { x -= v.x; y -= v.y; return *this; } + D3DXVECTOR2& operator*=(FLOAT f) { x *= f; y *= f; return *this; } + D3DXVECTOR2& operator/=(FLOAT f) { FLOAT fInv = 1.0f / f; x *= fInv; y *= fInv; return *this; } + + D3DXVECTOR2 operator+() const { return *this; } + D3DXVECTOR2 operator-() const { return D3DXVECTOR2(-x, -y); } + + D3DXVECTOR2 operator+(const D3DXVECTOR2& v) const { return D3DXVECTOR2(x + v.x, y + v.y); } + D3DXVECTOR2 operator-(const D3DXVECTOR2& v) const { return D3DXVECTOR2(x - v.x, y - v.y); } + D3DXVECTOR2 operator*(FLOAT f) const { return D3DXVECTOR2(x * f, y * f); } + D3DXVECTOR2 operator/(FLOAT f) const { FLOAT fInv = 1.0f / f; return D3DXVECTOR2(x * fInv, y * fInv); } + friend D3DXVECTOR2 operator*(FLOAT f, const D3DXVECTOR2& v) { return D3DXVECTOR2(f * v.x, f * v.y); } + + BOOL operator==(const D3DXVECTOR2& v) const { return x == v.x && y == v.y; } + BOOL operator!=(const D3DXVECTOR2& v) const { return x != v.x || y != v.y; } + + FLOAT x, y; +}; + +struct D3DXVECTOR3 : public D3DVECTOR +{ + D3DXVECTOR3() {} + D3DXVECTOR3(const FLOAT* pf) { x = pf[0]; y = pf[1]; z = pf[2]; } + D3DXVECTOR3(const D3DVECTOR& v) { x = v.x; y = v.y; z = v.z; } + D3DXVECTOR3(FLOAT fx, FLOAT fy, FLOAT fz) { x = fx; y = fy; z = fz; } + + operator FLOAT*() { return &x; } + operator const FLOAT*() const { return &x; } + + D3DXVECTOR3& operator+=(const D3DXVECTOR3& v) { x += v.x; y += v.y; z += v.z; return *this; } + D3DXVECTOR3& operator-=(const D3DXVECTOR3& v) { x -= v.x; y -= v.y; z -= v.z; return *this; } + D3DXVECTOR3& operator*=(FLOAT f) { x *= f; y *= f; z *= f; return *this; } + D3DXVECTOR3& operator/=(FLOAT f) { FLOAT fInv = 1.0f / f; x *= fInv; y *= fInv; z *= fInv; return *this; } + + D3DXVECTOR3 operator+() const { return *this; } + D3DXVECTOR3 operator-() const { return D3DXVECTOR3(-x, -y, -z); } + + D3DXVECTOR3 operator+(const D3DXVECTOR3& v) const { return D3DXVECTOR3(x + v.x, y + v.y, z + v.z); } + D3DXVECTOR3 operator-(const D3DXVECTOR3& v) const { return D3DXVECTOR3(x - v.x, y - v.y, z - v.z); } + D3DXVECTOR3 operator*(FLOAT f) const { return D3DXVECTOR3(x * f, y * f, z * f); } + D3DXVECTOR3 operator/(FLOAT f) const { FLOAT fInv = 1.0f / f; return D3DXVECTOR3(x * fInv, y * fInv, z * fInv); } + friend D3DXVECTOR3 operator*(FLOAT f, const D3DXVECTOR3& v) { return D3DXVECTOR3(f * v.x, f * v.y, f * v.z); } + + BOOL operator==(const D3DXVECTOR3& v) const { return x == v.x && y == v.y && z == v.z; } + BOOL operator!=(const D3DXVECTOR3& v) const { return x != v.x || y != v.y || z != v.z; } +}; + +struct D3DXVECTOR4 +{ + D3DXVECTOR4() {} + D3DXVECTOR4(const FLOAT* pf) : x(pf[0]), y(pf[1]), z(pf[2]), w(pf[3]) {} + D3DXVECTOR4(FLOAT fx, FLOAT fy, FLOAT fz, FLOAT fw) : x(fx), y(fy), z(fz), w(fw) {} + + operator FLOAT*() { return &x; } + operator const FLOAT*() const { return &x; } + + D3DXVECTOR4& operator+=(const D3DXVECTOR4& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; } + D3DXVECTOR4& operator-=(const D3DXVECTOR4& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; } + D3DXVECTOR4& operator*=(FLOAT f) { x *= f; y *= f; z *= f; w *= f; return *this; } + D3DXVECTOR4& operator/=(FLOAT f) { FLOAT fInv = 1.0f / f; x *= fInv; y *= fInv; z *= fInv; w *= fInv; return *this; } + + D3DXVECTOR4 operator+() const { return *this; } + D3DXVECTOR4 operator-() const { return D3DXVECTOR4(-x, -y, -z, -w); } + + D3DXVECTOR4 operator+(const D3DXVECTOR4& v) const { return D3DXVECTOR4(x + v.x, y + v.y, z + v.z, w + v.w); } + D3DXVECTOR4 operator-(const D3DXVECTOR4& v) const { return D3DXVECTOR4(x - v.x, y - v.y, z - v.z, w - v.w); } + D3DXVECTOR4 operator*(FLOAT f) const { return D3DXVECTOR4(x * f, y * f, z * f, w * f); } + D3DXVECTOR4 operator/(FLOAT f) const { FLOAT fInv = 1.0f / f; return D3DXVECTOR4(x * fInv, y * fInv, z * fInv, w * fInv); } + friend D3DXVECTOR4 operator*(FLOAT f, const D3DXVECTOR4& v) { return D3DXVECTOR4(f * v.x, f * v.y, f * v.z, f * v.w); } + + BOOL operator==(const D3DXVECTOR4& v) const { return x == v.x && y == v.y && z == v.z && w == v.w; } + BOOL operator!=(const D3DXVECTOR4& v) const { return x != v.x || y != v.y || z != v.z || w != v.w; } + + FLOAT x, y, z, w; +}; + +struct D3DXMATRIX : public D3DMATRIX +{ + D3DXMATRIX() {} + D3DXMATRIX(const FLOAT* pf) { for (int i = 0; i < 16; ++i) (&_11)[i] = pf[i]; } + D3DXMATRIX(const D3DMATRIX& mat) : D3DMATRIX(mat) {} + D3DXMATRIX(FLOAT f11, FLOAT f12, FLOAT f13, FLOAT f14, + FLOAT f21, FLOAT f22, FLOAT f23, FLOAT f24, + FLOAT f31, FLOAT f32, FLOAT f33, FLOAT f34, + FLOAT f41, FLOAT f42, FLOAT f43, FLOAT f44) + { + _11 = f11; _12 = f12; _13 = f13; _14 = f14; + _21 = f21; _22 = f22; _23 = f23; _24 = f24; + _31 = f31; _32 = f32; _33 = f33; _34 = f34; + _41 = f41; _42 = f42; _43 = f43; _44 = f44; + } + + FLOAT& operator()(UINT iRow, UINT iCol) { return m[iRow][iCol]; } + FLOAT operator()(UINT iRow, UINT iCol) const { return m[iRow][iCol]; } + + operator FLOAT*() { return &_11; } + operator const FLOAT*() const { return &_11; } + + D3DXMATRIX& operator*=(const D3DXMATRIX& mat); + D3DXMATRIX& operator+=(const D3DXMATRIX& mat) { for (int i = 0; i < 16; ++i) (&_11)[i] += (&mat._11)[i]; return *this; } + D3DXMATRIX& operator-=(const D3DXMATRIX& mat) { for (int i = 0; i < 16; ++i) (&_11)[i] -= (&mat._11)[i]; return *this; } + D3DXMATRIX& operator*=(FLOAT f) { for (int i = 0; i < 16; ++i) (&_11)[i] *= f; return *this; } + D3DXMATRIX& operator/=(FLOAT f) { FLOAT fInv = 1.0f / f; for (int i = 0; i < 16; ++i) (&_11)[i] *= fInv; return *this; } + + D3DXMATRIX operator+() const { return *this; } + D3DXMATRIX operator-() const { D3DXMATRIX r; for (int i = 0; i < 16; ++i) (&r._11)[i] = -(&_11)[i]; return r; } + + D3DXMATRIX operator*(const D3DXMATRIX& mat) const; + D3DXMATRIX operator+(const D3DXMATRIX& mat) const { D3DXMATRIX r(*this); return r += mat; } + D3DXMATRIX operator-(const D3DXMATRIX& mat) const { D3DXMATRIX r(*this); return r -= mat; } + D3DXMATRIX operator*(FLOAT f) const { D3DXMATRIX r(*this); return r *= f; } + D3DXMATRIX operator/(FLOAT f) const { D3DXMATRIX r(*this); return r /= f; } + friend D3DXMATRIX operator*(FLOAT f, const D3DXMATRIX& mat) { D3DXMATRIX r(mat); return r *= f; } + + BOOL operator==(const D3DXMATRIX& mat) const; + BOOL operator!=(const D3DXMATRIX& mat) const { return !(*this == mat); } +}; + +struct D3DXQUATERNION +{ + D3DXQUATERNION() {} + D3DXQUATERNION(const FLOAT* pf) : x(pf[0]), y(pf[1]), z(pf[2]), w(pf[3]) {} + D3DXQUATERNION(FLOAT fx, FLOAT fy, FLOAT fz, FLOAT fw) : x(fx), y(fy), z(fz), w(fw) {} + + operator FLOAT*() { return &x; } + operator const FLOAT*() const { return &x; } + + D3DXQUATERNION& operator+=(const D3DXQUATERNION& q) { x += q.x; y += q.y; z += q.z; w += q.w; return *this; } + D3DXQUATERNION& operator-=(const D3DXQUATERNION& q) { x -= q.x; y -= q.y; z -= q.z; w -= q.w; return *this; } + D3DXQUATERNION& operator*=(const D3DXQUATERNION& q); + D3DXQUATERNION& operator*=(FLOAT f) { x *= f; y *= f; z *= f; w *= f; return *this; } + D3DXQUATERNION& operator/=(FLOAT f) { FLOAT fInv = 1.0f / f; x *= fInv; y *= fInv; z *= fInv; w *= fInv; return *this; } + + D3DXQUATERNION operator+() const { return *this; } + D3DXQUATERNION operator-() const { return D3DXQUATERNION(-x, -y, -z, -w); } + + D3DXQUATERNION operator+(const D3DXQUATERNION& q) const { return D3DXQUATERNION(x + q.x, y + q.y, z + q.z, w + q.w); } + D3DXQUATERNION operator-(const D3DXQUATERNION& q) const { return D3DXQUATERNION(x - q.x, y - q.y, z - q.z, w - q.w); } + D3DXQUATERNION operator*(const D3DXQUATERNION& q) const; + D3DXQUATERNION operator*(FLOAT f) const { return D3DXQUATERNION(x * f, y * f, z * f, w * f); } + D3DXQUATERNION operator/(FLOAT f) const { FLOAT fInv = 1.0f / f; return D3DXQUATERNION(x * fInv, y * fInv, z * fInv, w * fInv); } + friend D3DXQUATERNION operator*(FLOAT f, const D3DXQUATERNION& q) { return D3DXQUATERNION(f * q.x, f * q.y, f * q.z, f * q.w); } + + BOOL operator==(const D3DXQUATERNION& q) const { return x == q.x && y == q.y && z == q.z && w == q.w; } + BOOL operator!=(const D3DXQUATERNION& q) const { return x != q.x || y != q.y || z != q.z || w != q.w; } + + FLOAT x, y, z, w; +}; + +struct D3DXPLANE +{ + D3DXPLANE() {} + D3DXPLANE(const FLOAT* pf) : a(pf[0]), b(pf[1]), c(pf[2]), d(pf[3]) {} + D3DXPLANE(FLOAT fa, FLOAT fb, FLOAT fc, FLOAT fd) : a(fa), b(fb), c(fc), d(fd) {} + + operator FLOAT*() { return &a; } + operator const FLOAT*() const { return &a; } + + D3DXPLANE operator+() const { return *this; } + D3DXPLANE operator-() const { return D3DXPLANE(-a, -b, -c, -d); } + + BOOL operator==(const D3DXPLANE& p) const { return a == p.a && b == p.b && c == p.c && d == p.d; } + BOOL operator!=(const D3DXPLANE& p) const { return a != p.a || b != p.b || c != p.c || d != p.d; } + + FLOAT a, b, c, d; +}; + +struct D3DXCOLOR +{ + D3DXCOLOR() {} + D3DXCOLOR(DWORD argb) + { + const FLOAT f = 1.0f / 255.0f; + r = f * (FLOAT)(unsigned char)(argb >> 16); + g = f * (FLOAT)(unsigned char)(argb >> 8); + b = f * (FLOAT)(unsigned char)(argb >> 0); + a = f * (FLOAT)(unsigned char)(argb >> 24); + } + D3DXCOLOR(const FLOAT* pf) : r(pf[0]), g(pf[1]), b(pf[2]), a(pf[3]) {} + D3DXCOLOR(const D3DCOLORVALUE& c) : r(c.r), g(c.g), b(c.b), a(c.a) {} + D3DXCOLOR(FLOAT fr, FLOAT fg, FLOAT fb, FLOAT fa) : r(fr), g(fg), b(fb), a(fa) {} + + operator DWORD() const + { + DWORD dwR = r >= 1.0f ? 0xff : r <= 0.0f ? 0x00 : (DWORD)(r * 255.0f + 0.5f); + DWORD dwG = g >= 1.0f ? 0xff : g <= 0.0f ? 0x00 : (DWORD)(g * 255.0f + 0.5f); + DWORD dwB = b >= 1.0f ? 0xff : b <= 0.0f ? 0x00 : (DWORD)(b * 255.0f + 0.5f); + DWORD dwA = a >= 1.0f ? 0xff : a <= 0.0f ? 0x00 : (DWORD)(a * 255.0f + 0.5f); + return (dwA << 24) | (dwR << 16) | (dwG << 8) | dwB; + } + + operator FLOAT*() { return &r; } + operator const FLOAT*() const { return &r; } + operator D3DCOLORVALUE*() { return (D3DCOLORVALUE*)&r; } + operator const D3DCOLORVALUE*() const { return (const D3DCOLORVALUE*)&r; } + operator D3DCOLORVALUE&() { return *((D3DCOLORVALUE*)&r); } + operator const D3DCOLORVALUE&() const { return *((const D3DCOLORVALUE*)&r); } + + D3DXCOLOR& operator+=(const D3DXCOLOR& c) { r += c.r; g += c.g; b += c.b; a += c.a; return *this; } + D3DXCOLOR& operator-=(const D3DXCOLOR& c) { r -= c.r; g -= c.g; b -= c.b; a -= c.a; return *this; } + D3DXCOLOR& operator*=(FLOAT f) { r *= f; g *= f; b *= f; a *= f; return *this; } + D3DXCOLOR& operator/=(FLOAT f) { FLOAT fInv = 1.0f / f; r *= fInv; g *= fInv; b *= fInv; a *= fInv; return *this; } + + D3DXCOLOR operator+() const { return *this; } + D3DXCOLOR operator-() const { return D3DXCOLOR(-r, -g, -b, -a); } + + D3DXCOLOR operator+(const D3DXCOLOR& c) const { return D3DXCOLOR(r + c.r, g + c.g, b + c.b, a + c.a); } + D3DXCOLOR operator-(const D3DXCOLOR& c) const { return D3DXCOLOR(r - c.r, g - c.g, b - c.b, a - c.a); } + D3DXCOLOR operator*(FLOAT f) const { return D3DXCOLOR(r * f, g * f, b * f, a * f); } + D3DXCOLOR operator/(FLOAT f) const { FLOAT fInv = 1.0f / f; return D3DXCOLOR(r * fInv, g * fInv, b * fInv, a * fInv); } + friend D3DXCOLOR operator*(FLOAT f, const D3DXCOLOR& c) { return D3DXCOLOR(f * c.r, f * c.g, f * c.b, f * c.a); } + + BOOL operator==(const D3DXCOLOR& c) const { return r == c.r && g == c.g && b == c.b && a == c.a; } + BOOL operator!=(const D3DXCOLOR& c) const { return r != c.r || g != c.g || b != c.b || a != c.a; } + + FLOAT r, g, b, a; +}; + +static_assert(sizeof(D3DXVECTOR2) == 8 && sizeof(D3DXVECTOR3) == 12 && sizeof(D3DXVECTOR4) == 16, "D3DX vector layout"); +static_assert(sizeof(D3DXMATRIX) == 64 && sizeof(D3DXQUATERNION) == 16 && sizeof(D3DXCOLOR) == 16, "D3DX layout"); +static_assert(sizeof(D3DXPLANE) == 16 && sizeof(D3DCOLORVALUE) == 16, "D3DX layout"); + +// --- D3DXVECTOR2 --- +inline FLOAT D3DXVec2Length(const D3DXVECTOR2* pV) { return sqrtf(pV->x * pV->x + pV->y * pV->y); } +inline FLOAT D3DXVec2LengthSq(const D3DXVECTOR2* pV) { return pV->x * pV->x + pV->y * pV->y; } +inline FLOAT D3DXVec2Dot(const D3DXVECTOR2* pV1, const D3DXVECTOR2* pV2) { return pV1->x * pV2->x + pV1->y * pV2->y; } +inline D3DXVECTOR2* D3DXVec2Add(D3DXVECTOR2* pOut, const D3DXVECTOR2* pV1, const D3DXVECTOR2* pV2) +{ + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + return pOut; +} +inline D3DXVECTOR2* D3DXVec2Subtract(D3DXVECTOR2* pOut, const D3DXVECTOR2* pV1, const D3DXVECTOR2* pV2) +{ + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + return pOut; +} +inline D3DXVECTOR2* D3DXVec2Scale(D3DXVECTOR2* pOut, const D3DXVECTOR2* pV, FLOAT s) +{ + pOut->x = pV->x * s; + pOut->y = pV->y * s; + return pOut; +} +D3DXVECTOR2* D3DXVec2Normalize(D3DXVECTOR2* pOut, const D3DXVECTOR2* pV); + +// --- D3DXVECTOR3 --- +inline FLOAT D3DXVec3Length(const D3DXVECTOR3* pV) { return sqrtf(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z); } +inline FLOAT D3DXVec3LengthSq(const D3DXVECTOR3* pV) { return pV->x * pV->x + pV->y * pV->y + pV->z * pV->z; } +inline FLOAT D3DXVec3Dot(const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2) +{ + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} +inline D3DXVECTOR3* D3DXVec3Cross(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2) +{ + D3DXVECTOR3 v; + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + *pOut = v; + return pOut; +} +inline D3DXVECTOR3* D3DXVec3Add(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2) +{ + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + pOut->z = pV1->z + pV2->z; + return pOut; +} +inline D3DXVECTOR3* D3DXVec3Subtract(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2) +{ + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} +inline D3DXVECTOR3* D3DXVec3Minimize(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2) +{ + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z < pV2->z ? pV1->z : pV2->z; + return pOut; +} +inline D3DXVECTOR3* D3DXVec3Maximize(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2) +{ + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z > pV2->z ? pV1->z : pV2->z; + return pOut; +} +inline D3DXVECTOR3* D3DXVec3Scale(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV, FLOAT s) +{ + pOut->x = pV->x * s; + pOut->y = pV->y * s; + pOut->z = pV->z * s; + return pOut; +} +inline D3DXVECTOR3* D3DXVec3Lerp(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV1, const D3DXVECTOR3* pV2, FLOAT s) +{ + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + pOut->z = pV1->z + s * (pV2->z - pV1->z); + return pOut; +} +D3DXVECTOR3* D3DXVec3Normalize(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV); +D3DXVECTOR4* D3DXVec3Transform(D3DXVECTOR4* pOut, const D3DXVECTOR3* pV, const D3DXMATRIX* pM); +D3DXVECTOR3* D3DXVec3TransformCoord(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV, const D3DXMATRIX* pM); +D3DXVECTOR3* D3DXVec3TransformNormal(D3DXVECTOR3* pOut, const D3DXVECTOR3* pV, const D3DXMATRIX* pM); + +// --- D3DXMATRIX --- +inline D3DXMATRIX* D3DXMatrixIdentity(D3DXMATRIX* pOut) +{ + pOut->m[0][1] = pOut->m[0][2] = pOut->m[0][3] = + pOut->m[1][0] = pOut->m[1][2] = pOut->m[1][3] = + pOut->m[2][0] = pOut->m[2][1] = pOut->m[2][3] = + pOut->m[3][0] = pOut->m[3][1] = pOut->m[3][2] = 0.0f; + pOut->m[0][0] = pOut->m[1][1] = pOut->m[2][2] = pOut->m[3][3] = 1.0f; + return pOut; +} +inline BOOL D3DXMatrixIsIdentity(const D3DXMATRIX* pM) +{ + return pM->m[0][0] == 1.0f && pM->m[0][1] == 0.0f && pM->m[0][2] == 0.0f && pM->m[0][3] == 0.0f && + pM->m[1][0] == 0.0f && pM->m[1][1] == 1.0f && pM->m[1][2] == 0.0f && pM->m[1][3] == 0.0f && + pM->m[2][0] == 0.0f && pM->m[2][1] == 0.0f && pM->m[2][2] == 1.0f && pM->m[2][3] == 0.0f && + pM->m[3][0] == 0.0f && pM->m[3][1] == 0.0f && pM->m[3][2] == 0.0f && pM->m[3][3] == 1.0f; +} +D3DXMATRIX* D3DXMatrixMultiply(D3DXMATRIX* pOut, const D3DXMATRIX* pM1, const D3DXMATRIX* pM2); +D3DXMATRIX* D3DXMatrixTranspose(D3DXMATRIX* pOut, const D3DXMATRIX* pM); +D3DXMATRIX* D3DXMatrixInverse(D3DXMATRIX* pOut, FLOAT* pDeterminant, const D3DXMATRIX* pM); +D3DXMATRIX* D3DXMatrixScaling(D3DXMATRIX* pOut, FLOAT sx, FLOAT sy, FLOAT sz); +D3DXMATRIX* D3DXMatrixTranslation(D3DXMATRIX* pOut, FLOAT x, FLOAT y, FLOAT z); +D3DXMATRIX* D3DXMatrixRotationX(D3DXMATRIX* pOut, FLOAT angle); +D3DXMATRIX* D3DXMatrixRotationY(D3DXMATRIX* pOut, FLOAT angle); +D3DXMATRIX* D3DXMatrixRotationZ(D3DXMATRIX* pOut, FLOAT angle); +D3DXMATRIX* D3DXMatrixRotationAxis(D3DXMATRIX* pOut, const D3DXVECTOR3* pV, FLOAT angle); +D3DXMATRIX* D3DXMatrixRotationQuaternion(D3DXMATRIX* pOut, const D3DXQUATERNION* pQ); +D3DXMATRIX* D3DXMatrixRotationYawPitchRoll(D3DXMATRIX* pOut, FLOAT yaw, FLOAT pitch, FLOAT roll); + +// --- D3DXQUATERNION --- +inline D3DXQUATERNION* D3DXQuaternionIdentity(D3DXQUATERNION* pOut) +{ + pOut->x = pOut->y = pOut->z = 0.0f; + pOut->w = 1.0f; + return pOut; +} +D3DXQUATERNION* D3DXQuaternionMultiply(D3DXQUATERNION* pOut, const D3DXQUATERNION* pQ1, const D3DXQUATERNION* pQ2); +D3DXQUATERNION* D3DXQuaternionNormalize(D3DXQUATERNION* pOut, const D3DXQUATERNION* pQ); +D3DXQUATERNION* D3DXQuaternionRotationAxis(D3DXQUATERNION* pOut, const D3DXVECTOR3* pV, FLOAT angle); +D3DXQUATERNION* D3DXQuaternionRotationYawPitchRoll(D3DXQUATERNION* pOut, FLOAT yaw, FLOAT pitch, FLOAT roll); + +// --- D3DXPLANE --- +inline FLOAT D3DXPlaneDotCoord(const D3DXPLANE* pP, const D3DXVECTOR3* pV) +{ + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d; +} diff --git a/extension/tests/port_common_test.cpp b/extension/tests/port_common_test.cpp index dfb14d5a..399f644c 100644 --- a/extension/tests/port_common_test.cpp +++ b/extension/tests/port_common_test.cpp @@ -1,6 +1,8 @@ // port/common: Win32 widths and MSVC CRT semantics the ported 40250 logic relies on. #include "common/StdAfx.h" +#include "common/D3DXMath.h" +#include #include #include @@ -48,6 +50,53 @@ int main() const DWORD b = timeGetTime(); CHECK(static_cast(b - a) < 1000); + // D3DX8 math: row vectors, left-handed rotations, D3DX multiply order. + const auto near = [](float x, float y) { return std::fabs(x - y) < 1e-5f; }; + D3DXVECTOR3 v(3.0f, 0.0f, 4.0f); + CHECK(D3DXVec3Length(&v) == 5.0f && D3DXVec3LengthSq(&v) == 25.0f); + D3DXVECTOR3 n; + D3DXVec3Normalize(&n, &v); + CHECK(near(n.x, 0.6f) && n.y == 0.0f && near(n.z, 0.8f)); + D3DXVECTOR3 zero(0.0f, 0.0f, 0.0f); + D3DXVec3Normalize(&n, &zero); + CHECK(n == zero); + CHECK((v / 2.0f) == D3DXVECTOR3(1.5f, 0.0f, 2.0f) && (2.0f * v) == D3DXVECTOR3(6.0f, 0.0f, 8.0f)); + CHECK(near(D3DXToRadian(180.0f), D3DX_PI) && near(D3DXToDegree(D3DX_PI / 2.0f), 90.0f)); + + D3DXMATRIX rz, tr, m; + D3DXMatrixRotationZ(&rz, D3DX_PI / 2.0f); // x axis -> +y + D3DXVECTOR3 p(1.0f, 0.0f, 0.0f), q; + D3DXVec3TransformCoord(&q, &p, &rz); + CHECK(near(q.x, 0.0f) && near(q.y, 1.0f) && near(q.z, 0.0f)); + D3DXMatrixTranslation(&tr, 10.0f, 20.0f, 30.0f); + m = rz * tr; // rotate, then translate + D3DXVec3TransformCoord(&q, &p, &m); + CHECK(near(q.x, 10.0f) && near(q.y, 21.0f) && near(q.z, 30.0f)); + D3DXMATRIX inv, id; + CHECK(D3DXMatrixInverse(&inv, nullptr, &m) != nullptr); + D3DXMatrixMultiply(&id, &m, &inv); + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + CHECK(near(id.m[i][j], i == j ? 1.0f : 0.0f)); + + D3DXQUATERNION qz; + D3DXVECTOR3 zAxis(0.0f, 0.0f, 1.0f); + D3DXQuaternionRotationAxis(&qz, &zAxis, D3DX_PI / 2.0f); + D3DXMATRIX mq; + D3DXMatrixRotationQuaternion(&mq, &qz); + for (int i = 0; i < 16; ++i) + CHECK(near((&mq._11)[i], (&rz._11)[i])); + D3DXMATRIX ypr, ypr2; + D3DXQUATERNION qypr; + D3DXMatrixRotationYawPitchRoll(&ypr, 0.3f, 0.5f, 0.7f); + D3DXQuaternionRotationYawPitchRoll(&qypr, 0.3f, 0.5f, 0.7f); + D3DXMatrixRotationQuaternion(&ypr2, &qypr); + for (int i = 0; i < 16; ++i) + CHECK(near((&ypr._11)[i], (&ypr2._11)[i])); + + CHECK(static_cast(D3DXCOLOR(0xFF804020u)) == 0xFF804020u); + CHECK(static_cast(D3DXCOLOR(2.0f, -1.0f, 0.5f, 1.0f)) == 0xFFFF0080u); + if (g_failures) return EXIT_FAILURE; std::puts("port_common_test: ok");