feat(host): vendor PyroWave + minimal Granite subset as crates/pyrowave-sys
Phase 0 of design/pyrowave-codec-plan.md — the opt-in wired-LAN ultra-low- latency codec. Vendored at upstream 509e4f88 (API 0.4.0, Granite 44362775, volk + vulkan-headers pins in PUNKTFUNK-VENDOR.txt), pruned to the 6.6 MB the standalone no-renderer build needs; scripts/vendor-pyrowave.sh reproduces the tree (a pin bump is protocol-affecting, plan §4.2). build.rs drives the wrapper CMakeLists (static archives incl. a static C-API lib upstream only ships shared) + bindgen over pyrowave.h; Linux and Windows only, empty stub elsewhere (Apple gets a native Metal port, §4.7). Offline-safe by construction: no network, no system lib, vendored Vulkan headers — same model as the opus dep (flatpak builder has no network). Phase-0 validation on .21 (RTX 5070 Ti, driver 610.43.03): - upstream pyrowave-c-test + interop test (incl. dmabuf/DRM-modifier Vulkan<->Vulkan) pass, from the pristine AND the pruned tree - GPU kernel times at ~1.6 bpp noise: encode/decode 0.090/0.042 ms @800p, 0.146/0.067 @1080p, 0.226/0.103 @1440p, 0.477/0.201 @4K — order of magnitude under NVENC's 1-2 ms retrieve, CBR lands within ~100 B of target - cargo test -p pyrowave-sys green (static link + API-version pin check) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2017-2026 Hans-Kristian Arntzen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "muglm.hpp"
|
||||
#include <limits>
|
||||
|
||||
namespace muglm
|
||||
{
|
||||
mat4 mat4_cast(const quat &q);
|
||||
mat_affine mat_affine_cast(const quat &q);
|
||||
mat3 mat3_cast(const quat &q);
|
||||
mat4 translate(const vec3 &v);
|
||||
mat4 scale(const vec3 &v);
|
||||
mat_affine translate_affine(const vec3 &v);
|
||||
mat_affine scale_affine(const vec3 &v);
|
||||
mat2 inverse(const mat2 &m);
|
||||
mat3 inverse(const mat3 &m);
|
||||
mat4 inverse(const mat4 &m);
|
||||
|
||||
float determinant(const mat2 &m);
|
||||
float determinant(const mat3 &m);
|
||||
|
||||
constexpr float InfiniteFarPlane = std::numeric_limits<float>::max();
|
||||
mat4 perspective(float fovy, float aspect, float near, float far);
|
||||
mat4 frustum(float left, float right, float bottom, float top, float near, float far);
|
||||
|
||||
// Orthogonal projection cannot have infinite far-plane.
|
||||
mat4 ortho(float left, float right, float bottom, float top, float near, float far);
|
||||
|
||||
void decompose(const mat4 &m, vec3 &scale, quat &rot, vec3 &trans);
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
/* Copyright (c) 2017-2026 Hans-Kristian Arntzen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "matrix_helper.hpp"
|
||||
#include "muglm_impl.hpp"
|
||||
#include "simd_headers.hpp"
|
||||
|
||||
namespace muglm
|
||||
{
|
||||
mat3 mat3_cast(const quat &q_)
|
||||
{
|
||||
auto &q = q_.as_vec4();
|
||||
|
||||
mat3 res(1.0f);
|
||||
float qxx = q.x * q.x;
|
||||
float qyy = q.y * q.y;
|
||||
float qzz = q.z * q.z;
|
||||
float qxz = q.x * q.z;
|
||||
float qxy = q.x * q.y;
|
||||
float qyz = q.y * q.z;
|
||||
float qwx = q.w * q.x;
|
||||
float qwy = q.w * q.y;
|
||||
float qwz = q.w * q.z;
|
||||
|
||||
res[0][0] = 1.0f - 2.0f * (qyy + qzz);
|
||||
res[0][1] = 2.0f * (qxy + qwz);
|
||||
res[0][2] = 2.0f * (qxz - qwy);
|
||||
|
||||
res[1][0] = 2.0f * (qxy - qwz);
|
||||
res[1][1] = 1.0f - 2.0f * (qxx + qzz);
|
||||
res[1][2] = 2.0f * (qyz + qwx);
|
||||
|
||||
res[2][0] = 2.0f * (qxz + qwy);
|
||||
res[2][1] = 2.0f * (qyz - qwx);
|
||||
res[2][2] = 1.0f - 2.0f * (qxx + qyy);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
mat4 mat4_cast(const quat &q)
|
||||
{
|
||||
return mat4(mat3_cast(q));
|
||||
}
|
||||
|
||||
mat_affine mat_affine_cast(const quat &q)
|
||||
{
|
||||
return mat_affine(mat3_cast(q));
|
||||
}
|
||||
|
||||
mat4 translate(const vec3 &v)
|
||||
{
|
||||
return mat4(
|
||||
vec4(1.0f, 0.0f, 0.0f, 0.0f),
|
||||
vec4(0.0f, 1.0f, 0.0f, 0.0f),
|
||||
vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
||||
vec4(v, 1.0f));
|
||||
}
|
||||
|
||||
mat4 scale(const vec3 &v)
|
||||
{
|
||||
return mat4(
|
||||
vec4(v.x, 0.0f, 0.0f, 0.0f),
|
||||
vec4(0.0f, v.y, 0.0f, 0.0f),
|
||||
vec4(0.0f, 0.0f, v.z, 0.0f),
|
||||
vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
mat_affine translate_affine(const vec3 &v)
|
||||
{
|
||||
return mat_affine(
|
||||
vec4(1.0f, 0.0f, 0.0f, v.x),
|
||||
vec4(0.0f, 1.0f, 0.0f, v.y),
|
||||
vec4(0.0f, 0.0f, 1.0f, v.z));
|
||||
}
|
||||
|
||||
mat_affine scale_affine(const vec3 &v)
|
||||
{
|
||||
return mat_affine(
|
||||
vec4(v.x, 0.0f, 0.0f, 0.0f),
|
||||
vec4(0.0f, v.y, 0.0f, 0.0f),
|
||||
vec4(0.0f, 0.0f, v.z, 0.0f));
|
||||
}
|
||||
|
||||
float determinant(const mat2 &m)
|
||||
{
|
||||
return m[0][0] * m[1][1] - m[1][0] * m[0][1];
|
||||
}
|
||||
|
||||
mat2 inverse(const mat2 &m)
|
||||
{
|
||||
float OneOverDeterminant = 1.0f / determinant(m);
|
||||
|
||||
mat2 Inverse(
|
||||
vec2(m[1][1] * OneOverDeterminant,
|
||||
-m[0][1] * OneOverDeterminant),
|
||||
vec2(-m[1][0] * OneOverDeterminant,
|
||||
m[0][0] * OneOverDeterminant));
|
||||
|
||||
return Inverse;
|
||||
}
|
||||
|
||||
float determinant(const mat3 &m)
|
||||
{
|
||||
return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
|
||||
- m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
|
||||
+ m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
|
||||
}
|
||||
|
||||
mat3 inverse(const mat3 &m)
|
||||
{
|
||||
float OneOverDeterminant = 1.0f / determinant(m);
|
||||
|
||||
mat3 Inverse;
|
||||
Inverse[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant;
|
||||
Inverse[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant;
|
||||
Inverse[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant;
|
||||
Inverse[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant;
|
||||
Inverse[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant;
|
||||
Inverse[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant;
|
||||
Inverse[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant;
|
||||
Inverse[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant;
|
||||
Inverse[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant;
|
||||
|
||||
return Inverse;
|
||||
}
|
||||
|
||||
mat4 inverse(const mat4 &m)
|
||||
{
|
||||
float Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||
float Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
||||
float Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
||||
|
||||
float Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
||||
float Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
float Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
||||
|
||||
float Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
||||
float Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
||||
float Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
||||
|
||||
float Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
||||
float Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
||||
float Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
||||
|
||||
float Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
||||
float Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
||||
float Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
||||
|
||||
float Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
||||
float Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
||||
float Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
||||
|
||||
vec4 Fac0(Coef00, Coef00, Coef02, Coef03);
|
||||
vec4 Fac1(Coef04, Coef04, Coef06, Coef07);
|
||||
vec4 Fac2(Coef08, Coef08, Coef10, Coef11);
|
||||
vec4 Fac3(Coef12, Coef12, Coef14, Coef15);
|
||||
vec4 Fac4(Coef16, Coef16, Coef18, Coef19);
|
||||
vec4 Fac5(Coef20, Coef20, Coef22, Coef23);
|
||||
|
||||
vec4 Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
|
||||
vec4 Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
|
||||
vec4 Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
|
||||
vec4 Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
|
||||
|
||||
vec4 Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
|
||||
vec4 Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
|
||||
vec4 Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
|
||||
vec4 Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
|
||||
|
||||
vec4 SignA(+1, -1, +1, -1);
|
||||
vec4 SignB(-1, +1, -1, +1);
|
||||
mat4 Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB);
|
||||
|
||||
vec4 Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
|
||||
|
||||
vec4 Dot0(m[0] * Row0);
|
||||
float Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w);
|
||||
|
||||
float OneOverDeterminant = 1.0f / Dot1;
|
||||
|
||||
return Inverse * OneOverDeterminant;
|
||||
}
|
||||
|
||||
void decompose(const mat4 &m, vec3 &scale, quat &rotation, vec3 &trans)
|
||||
{
|
||||
vec4 rot;
|
||||
|
||||
// Make a lot of assumptions.
|
||||
// We don't need skew, nor perspective.
|
||||
|
||||
// Isolate translation.
|
||||
trans = m[3].xyz();
|
||||
|
||||
vec3 cols[3];
|
||||
cols[0] = m[0].xyz();
|
||||
cols[1] = m[1].xyz();
|
||||
cols[2] = m[2].xyz();
|
||||
|
||||
scale.x = length(cols[0]);
|
||||
scale.y = length(cols[1]);
|
||||
scale.z = length(cols[2]);
|
||||
|
||||
// Isolate scale.
|
||||
cols[0] /= scale.x;
|
||||
cols[1] /= scale.y;
|
||||
cols[2] /= scale.z;
|
||||
|
||||
vec3 pdum3 = cross(cols[1], cols[2]);
|
||||
if (dot(cols[0], pdum3) < 0.0f)
|
||||
{
|
||||
scale = -scale;
|
||||
cols[0] = -cols[0];
|
||||
cols[1] = -cols[1];
|
||||
cols[2] = -cols[2];
|
||||
}
|
||||
|
||||
int i, j, k = 0;
|
||||
float root, trace = cols[0].x + cols[1].y + cols[2].z;
|
||||
if (trace > 0.0f)
|
||||
{
|
||||
root = sqrt(trace + 1.0f);
|
||||
rot.w = 0.5f * root;
|
||||
root = 0.5f / root;
|
||||
rot.x = root * (cols[1].z - cols[2].y);
|
||||
rot.y = root * (cols[2].x - cols[0].z);
|
||||
rot.z = root * (cols[0].y - cols[1].x);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const int Next[3] = {1, 2, 0};
|
||||
|
||||
i = 0;
|
||||
if (cols[1].y > cols[0].x) i = 1;
|
||||
if (cols[2].z > cols[i][i]) i = 2;
|
||||
|
||||
j = Next[i];
|
||||
k = Next[j];
|
||||
|
||||
root = sqrt(cols[i][i] - cols[j][j] - cols[k][k] + 1.0f);
|
||||
|
||||
rot[i] = 0.5f * root;
|
||||
root = 0.5f / root;
|
||||
rot[j] = root * (cols[i][j] + cols[j][i]);
|
||||
rot[k] = root * (cols[i][k] + cols[k][i]);
|
||||
rot.w = root * (cols[j][k] - cols[k][j]);
|
||||
}
|
||||
|
||||
rotation = quat(rot);
|
||||
}
|
||||
|
||||
mat4 ortho(float left, float right, float bottom, float top, float near, float far)
|
||||
{
|
||||
mat4 result(1.0f);
|
||||
result[0][0] = 2.0f / (right - left);
|
||||
result[1][1] = 2.0f / (top - bottom);
|
||||
result[3][0] = -(right + left) / (right - left);
|
||||
result[3][1] = -(top + bottom) / (top - bottom);
|
||||
|
||||
result[2][2] = 1.0f / (far - near);
|
||||
result[3][2] = 1.0f + near / (far - near);
|
||||
|
||||
result[0].y *= -1.0f;
|
||||
result[1].y *= -1.0f;
|
||||
result[2].y *= -1.0f;
|
||||
result[3].y *= -1.0f;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
mat4 frustum(float left, float right, float bottom, float top, float near, float far)
|
||||
{
|
||||
mat4 result(0.0f);
|
||||
result[0][0] = (2.0f * near) / (right - left);
|
||||
result[1][1] = (2.0f * near) / (top - bottom);
|
||||
result[2][0] = (right + left) / (right - left);
|
||||
result[2][1] = (top + bottom) / (top - bottom);
|
||||
|
||||
// Inverse Z
|
||||
if (far == InfiniteFarPlane)
|
||||
{
|
||||
result[3][2] = -near;
|
||||
}
|
||||
else
|
||||
{
|
||||
result[2][2] = -1.0f - far / (near - far);
|
||||
result[3][2] = -(far * near) / (near - far);
|
||||
}
|
||||
|
||||
result[2][3] = -1.0f;
|
||||
|
||||
// Y-flip so we don't have to bother with negative viewport heights.
|
||||
result[0].y *= -1.0f;
|
||||
result[1].y *= -1.0f;
|
||||
result[2].y *= -1.0f;
|
||||
result[3].y *= -1.0f;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
mat4 perspective(float fovy, float aspect, float near, float far)
|
||||
{
|
||||
float tanHalfFovy = tan(fovy / 2.0f);
|
||||
|
||||
mat4 result(0.0f);
|
||||
result[0][0] = 1.0f / (aspect * tanHalfFovy);
|
||||
result[1][1] = 1.0f / (tanHalfFovy);
|
||||
|
||||
// Inverse Z
|
||||
if (far == InfiniteFarPlane)
|
||||
{
|
||||
result[3][2] = near;
|
||||
}
|
||||
else
|
||||
{
|
||||
result[2][2] = -1.0f - far / (near - far);
|
||||
result[3][2] = -(far * near) / (near - far);
|
||||
}
|
||||
|
||||
result[2][3] = -1.0f;
|
||||
|
||||
// Y-flip so we don't have to bother with negative viewport heights.
|
||||
result[0].y *= -1.0f;
|
||||
result[1].y *= -1.0f;
|
||||
result[2].y *= -1.0f;
|
||||
result[3].y *= -1.0f;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void transpose(mat4 &dst, const mat4 &src)
|
||||
{
|
||||
#if __SSE__
|
||||
__m128 r0 = _mm_loadu_ps(src[0].data);
|
||||
__m128 r1 = _mm_loadu_ps(src[1].data);
|
||||
__m128 r2 = _mm_loadu_ps(src[2].data);
|
||||
__m128 r3 = _mm_loadu_ps(src[3].data);
|
||||
_MM_TRANSPOSE4_PS(r0, r1, r2, r3);
|
||||
_mm_storeu_ps(dst[0].data, r0);
|
||||
_mm_storeu_ps(dst[1].data, r1);
|
||||
_mm_storeu_ps(dst[2].data, r2);
|
||||
_mm_storeu_ps(dst[3].data, r3);
|
||||
#elif defined(__ARM_NEON)
|
||||
float32x4x4_t a = vld4q_f32(src[0].data);
|
||||
vst1q_f32(dst[0].data, a.val[0]);
|
||||
vst1q_f32(dst[1].data, a.val[1]);
|
||||
vst1q_f32(dst[2].data, a.val[2]);
|
||||
vst1q_f32(dst[3].data, a.val[3]);
|
||||
#else
|
||||
dst = transpose(src);
|
||||
#endif
|
||||
}
|
||||
|
||||
void transpose_to_affine(vec4 dst[3], const mat4 &src)
|
||||
{
|
||||
#if __SSE__
|
||||
__m128 r0 = _mm_loadu_ps(src[0].data);
|
||||
__m128 r1 = _mm_loadu_ps(src[1].data);
|
||||
__m128 r2 = _mm_loadu_ps(src[2].data);
|
||||
__m128 r3 = _mm_loadu_ps(src[3].data);
|
||||
_MM_TRANSPOSE4_PS(r0, r1, r2, r3);
|
||||
_mm_storeu_ps(dst[0].data, r0);
|
||||
_mm_storeu_ps(dst[1].data, r1);
|
||||
_mm_storeu_ps(dst[2].data, r2);
|
||||
#elif defined(__ARM_NEON)
|
||||
float32x4x4_t a = vld4q_f32(src[0].data);
|
||||
vst1q_f32(dst[0].data, a.val[0]);
|
||||
vst1q_f32(dst[1].data, a.val[1]);
|
||||
vst1q_f32(dst[2].data, a.val[2]);
|
||||
#else
|
||||
mat4 m = transpose(src);
|
||||
for (int i = 0; i < 3; i++)
|
||||
dst[i] = m[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
void transpose_from_affine(mat4 &dst, const vec4 src[3])
|
||||
{
|
||||
#if __SSE__
|
||||
__m128 r0 = _mm_loadu_ps(src[0].data);
|
||||
__m128 r1 = _mm_loadu_ps(src[1].data);
|
||||
__m128 r2 = _mm_loadu_ps(src[2].data);
|
||||
__m128 r3 = _mm_set_ps(1, 0, 0, 0);
|
||||
_MM_TRANSPOSE4_PS(r0, r1, r2, r3);
|
||||
_mm_storeu_ps(dst[0].data, r0);
|
||||
_mm_storeu_ps(dst[1].data, r1);
|
||||
_mm_storeu_ps(dst[2].data, r2);
|
||||
_mm_storeu_ps(dst[3].data, r3);
|
||||
#elif defined(__ARM_NEON)
|
||||
alignas(16) static const float r3_data[] = { 0, 0, 0, 1 };
|
||||
float32x4_t r0 = vld1q_f32(src[0].data);
|
||||
float32x4_t r1 = vld1q_f32(src[1].data);
|
||||
float32x4_t r2 = vld1q_f32(src[2].data);
|
||||
float32x4_t r3 = vld1q_f32(r3_data);
|
||||
float32x4x4_t r = { r0, r1, r2, r3 };
|
||||
vst4q_f32(dst[0].data, r);
|
||||
#else
|
||||
mat4 m = transpose(src);
|
||||
for (int i = 0; i < 3; i++)
|
||||
dst[i] = m[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
void mat_affine::to_mat4(muglm::mat4 &m) const
|
||||
{
|
||||
transpose_from_affine(m, vec);
|
||||
}
|
||||
|
||||
mat4 mat_affine::to_mat4() const
|
||||
{
|
||||
mat4 m;
|
||||
to_mat4(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
float mat_affine::get_uniform_scale() const
|
||||
{
|
||||
return length(vec[0].xyz());
|
||||
}
|
||||
|
||||
vec3 mat_affine::get_translation() const
|
||||
{
|
||||
// this * vec4(0, 0, 0, 1)
|
||||
return { vec[0].w, vec[1].w, vec[2].w };
|
||||
}
|
||||
|
||||
vec3 mat_affine::get_forward() const
|
||||
{
|
||||
// this * vec4(0, 0, -1, 0).
|
||||
return { -vec[0].z, -vec[1].z, -vec[2].z };
|
||||
}
|
||||
|
||||
vec3 mat_affine::get_right() const
|
||||
{
|
||||
return { vec[0].x, vec[1].x, vec[2].x };
|
||||
}
|
||||
|
||||
vec3 mat_affine::get_up() const
|
||||
{
|
||||
return { vec[0].y, vec[1].y, vec[2].y };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,993 @@
|
||||
/* Copyright (c) 2017-2026 Hans-Kristian Arntzen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace muglm
|
||||
{
|
||||
template <typename T> struct tvec2;
|
||||
template <typename T> struct tvec3;
|
||||
template <typename T> struct tvec4;
|
||||
template <typename T> struct tmat2;
|
||||
template <typename T> struct tmat3;
|
||||
template <typename T> struct tmat4;
|
||||
|
||||
template <typename T>
|
||||
struct tvec2
|
||||
{
|
||||
tvec2() = default;
|
||||
tvec2(const tvec2 &) = default;
|
||||
tvec2 &operator=(const tvec2 &) = default;
|
||||
|
||||
explicit inline tvec2(T v) noexcept
|
||||
{
|
||||
x = v;
|
||||
y = v;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
explicit inline tvec2(const tvec2<U> &u) noexcept
|
||||
{
|
||||
x = T(u.x);
|
||||
y = T(u.y);
|
||||
}
|
||||
|
||||
inline tvec2(T x_, T y_) noexcept
|
||||
{
|
||||
x = x_;
|
||||
y = y_;
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
T data[2];
|
||||
struct
|
||||
{
|
||||
T x, y;
|
||||
};
|
||||
};
|
||||
|
||||
inline T &operator[](size_t index)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
inline const T &operator[](size_t index) const
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
inline tvec2 xx() const;
|
||||
inline tvec2 xy() const;
|
||||
inline tvec2 yx() const;
|
||||
inline tvec2 yy() const;
|
||||
|
||||
inline tvec3<T> xxx() const;
|
||||
inline tvec3<T> xxy() const;
|
||||
inline tvec3<T> xyx() const;
|
||||
inline tvec3<T> xyy() const;
|
||||
inline tvec3<T> yxx() const;
|
||||
inline tvec3<T> yxy() const;
|
||||
inline tvec3<T> yyx() const;
|
||||
inline tvec3<T> yyy() const;
|
||||
|
||||
inline tvec4<T> xxxx() const;
|
||||
inline tvec4<T> xxxy() const;
|
||||
inline tvec4<T> xxyx() const;
|
||||
inline tvec4<T> xxyy() const;
|
||||
inline tvec4<T> xyxx() const;
|
||||
inline tvec4<T> xyxy() const;
|
||||
inline tvec4<T> xyyx() const;
|
||||
inline tvec4<T> xyyy() const;
|
||||
inline tvec4<T> yxxx() const;
|
||||
inline tvec4<T> yxxy() const;
|
||||
inline tvec4<T> yxyx() const;
|
||||
inline tvec4<T> yxyy() const;
|
||||
inline tvec4<T> yyxx() const;
|
||||
inline tvec4<T> yyxy() const;
|
||||
inline tvec4<T> yyyx() const;
|
||||
inline tvec4<T> yyyy() const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tvec3
|
||||
{
|
||||
tvec3() = default;
|
||||
tvec3(const tvec3 &) = default;
|
||||
tvec3 &operator=(const tvec3 &) = default;
|
||||
|
||||
template <typename U>
|
||||
explicit inline tvec3(const tvec3<U> &u) noexcept
|
||||
{
|
||||
x = T(u.x);
|
||||
y = T(u.y);
|
||||
z = T(u.z);
|
||||
}
|
||||
|
||||
inline tvec3(const tvec2<T> &a, T b) noexcept
|
||||
{
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = b;
|
||||
}
|
||||
|
||||
inline tvec3(T a, const tvec2<T> &b) noexcept
|
||||
{
|
||||
x = a;
|
||||
y = b.x;
|
||||
z = b.y;
|
||||
}
|
||||
|
||||
explicit inline tvec3(T v) noexcept
|
||||
{
|
||||
x = v;
|
||||
y = v;
|
||||
z = v;
|
||||
}
|
||||
|
||||
inline tvec3(T x_, T y_, T z_) noexcept
|
||||
{
|
||||
x = x_;
|
||||
y = y_;
|
||||
z = z_;
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
T data[3];
|
||||
struct
|
||||
{
|
||||
T x, y, z;
|
||||
};
|
||||
};
|
||||
|
||||
inline T &operator[](size_t index)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
inline const T &operator[](size_t index) const
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
inline tvec2<T> xx() const;
|
||||
inline tvec2<T> xy() const;
|
||||
inline tvec2<T> xz() const;
|
||||
inline tvec2<T> yx() const;
|
||||
inline tvec2<T> yy() const;
|
||||
inline tvec2<T> yz() const;
|
||||
inline tvec2<T> zx() const;
|
||||
inline tvec2<T> zy() const;
|
||||
inline tvec2<T> zz() const;
|
||||
|
||||
inline tvec3<T> xxx() const;
|
||||
inline tvec3<T> xxy() const;
|
||||
inline tvec3<T> xxz() const;
|
||||
inline tvec3<T> xyx() const;
|
||||
inline tvec3<T> xyy() const;
|
||||
inline tvec3<T> xyz() const;
|
||||
inline tvec3<T> xzx() const;
|
||||
inline tvec3<T> xzy() const;
|
||||
inline tvec3<T> xzz() const;
|
||||
inline tvec3<T> yxx() const;
|
||||
inline tvec3<T> yxy() const;
|
||||
inline tvec3<T> yxz() const;
|
||||
inline tvec3<T> yyx() const;
|
||||
inline tvec3<T> yyy() const;
|
||||
inline tvec3<T> yyz() const;
|
||||
inline tvec3<T> yzx() const;
|
||||
inline tvec3<T> yzy() const;
|
||||
inline tvec3<T> yzz() const;
|
||||
inline tvec3<T> zxx() const;
|
||||
inline tvec3<T> zxy() const;
|
||||
inline tvec3<T> zxz() const;
|
||||
inline tvec3<T> zyx() const;
|
||||
inline tvec3<T> zyy() const;
|
||||
inline tvec3<T> zyz() const;
|
||||
inline tvec3<T> zzx() const;
|
||||
inline tvec3<T> zzy() const;
|
||||
inline tvec3<T> zzz() const;
|
||||
|
||||
inline tvec4<T> xxxx() const;
|
||||
inline tvec4<T> xxxy() const;
|
||||
inline tvec4<T> xxxz() const;
|
||||
inline tvec4<T> xxyx() const;
|
||||
inline tvec4<T> xxyy() const;
|
||||
inline tvec4<T> xxyz() const;
|
||||
inline tvec4<T> xxzx() const;
|
||||
inline tvec4<T> xxzy() const;
|
||||
inline tvec4<T> xxzz() const;
|
||||
inline tvec4<T> xyxx() const;
|
||||
inline tvec4<T> xyxy() const;
|
||||
inline tvec4<T> xyxz() const;
|
||||
inline tvec4<T> xyyx() const;
|
||||
inline tvec4<T> xyyy() const;
|
||||
inline tvec4<T> xyyz() const;
|
||||
inline tvec4<T> xyzx() const;
|
||||
inline tvec4<T> xyzy() const;
|
||||
inline tvec4<T> xyzz() const;
|
||||
inline tvec4<T> xzxx() const;
|
||||
inline tvec4<T> xzxy() const;
|
||||
inline tvec4<T> xzxz() const;
|
||||
inline tvec4<T> xzyx() const;
|
||||
inline tvec4<T> xzyy() const;
|
||||
inline tvec4<T> xzyz() const;
|
||||
inline tvec4<T> xzzx() const;
|
||||
inline tvec4<T> xzzy() const;
|
||||
inline tvec4<T> xzzz() const;
|
||||
inline tvec4<T> yxxx() const;
|
||||
inline tvec4<T> yxxy() const;
|
||||
inline tvec4<T> yxxz() const;
|
||||
inline tvec4<T> yxyx() const;
|
||||
inline tvec4<T> yxyy() const;
|
||||
inline tvec4<T> yxyz() const;
|
||||
inline tvec4<T> yxzx() const;
|
||||
inline tvec4<T> yxzy() const;
|
||||
inline tvec4<T> yxzz() const;
|
||||
inline tvec4<T> yyxx() const;
|
||||
inline tvec4<T> yyxy() const;
|
||||
inline tvec4<T> yyxz() const;
|
||||
inline tvec4<T> yyyx() const;
|
||||
inline tvec4<T> yyyy() const;
|
||||
inline tvec4<T> yyyz() const;
|
||||
inline tvec4<T> yyzx() const;
|
||||
inline tvec4<T> yyzy() const;
|
||||
inline tvec4<T> yyzz() const;
|
||||
inline tvec4<T> yzxx() const;
|
||||
inline tvec4<T> yzxy() const;
|
||||
inline tvec4<T> yzxz() const;
|
||||
inline tvec4<T> yzyx() const;
|
||||
inline tvec4<T> yzyy() const;
|
||||
inline tvec4<T> yzyz() const;
|
||||
inline tvec4<T> yzzx() const;
|
||||
inline tvec4<T> yzzy() const;
|
||||
inline tvec4<T> yzzz() const;
|
||||
inline tvec4<T> zxxx() const;
|
||||
inline tvec4<T> zxxy() const;
|
||||
inline tvec4<T> zxxz() const;
|
||||
inline tvec4<T> zxyx() const;
|
||||
inline tvec4<T> zxyy() const;
|
||||
inline tvec4<T> zxyz() const;
|
||||
inline tvec4<T> zxzx() const;
|
||||
inline tvec4<T> zxzy() const;
|
||||
inline tvec4<T> zxzz() const;
|
||||
inline tvec4<T> zyxx() const;
|
||||
inline tvec4<T> zyxy() const;
|
||||
inline tvec4<T> zyxz() const;
|
||||
inline tvec4<T> zyyx() const;
|
||||
inline tvec4<T> zyyy() const;
|
||||
inline tvec4<T> zyyz() const;
|
||||
inline tvec4<T> zyzx() const;
|
||||
inline tvec4<T> zyzy() const;
|
||||
inline tvec4<T> zyzz() const;
|
||||
inline tvec4<T> zzxx() const;
|
||||
inline tvec4<T> zzxy() const;
|
||||
inline tvec4<T> zzxz() const;
|
||||
inline tvec4<T> zzyx() const;
|
||||
inline tvec4<T> zzyy() const;
|
||||
inline tvec4<T> zzyz() const;
|
||||
inline tvec4<T> zzzx() const;
|
||||
inline tvec4<T> zzzy() const;
|
||||
inline tvec4<T> zzzz() const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tvec4
|
||||
{
|
||||
tvec4() = default;
|
||||
tvec4(const tvec4 &) = default;
|
||||
tvec4 &operator=(const tvec4 &) = default;
|
||||
|
||||
template <typename U>
|
||||
explicit inline tvec4(const tvec4<U> &u) noexcept
|
||||
{
|
||||
x = T(u.x);
|
||||
y = T(u.y);
|
||||
z = T(u.z);
|
||||
w = T(u.w);
|
||||
}
|
||||
|
||||
inline tvec4(const tvec2<T> &a, const tvec2<T> &b) noexcept
|
||||
{
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = b.x;
|
||||
w = b.y;
|
||||
}
|
||||
|
||||
inline tvec4(const tvec3<T> &a, T b) noexcept
|
||||
{
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
w = b;
|
||||
}
|
||||
|
||||
inline tvec4(T a, const tvec3<T> &b) noexcept
|
||||
{
|
||||
x = a;
|
||||
y = b.x;
|
||||
z = b.y;
|
||||
w = b.z;
|
||||
}
|
||||
|
||||
inline tvec4(const tvec2<T> &a, T b, T c) noexcept
|
||||
{
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = b;
|
||||
w = c;
|
||||
}
|
||||
|
||||
inline tvec4(T a, const tvec2<T> &b, T c) noexcept
|
||||
{
|
||||
x = a;
|
||||
y = b.x;
|
||||
z = b.y;
|
||||
w = c;
|
||||
}
|
||||
|
||||
inline tvec4(T a, T b, const tvec2<T> &c) noexcept
|
||||
{
|
||||
x = a;
|
||||
y = b;
|
||||
z = c.x;
|
||||
w = c.y;
|
||||
}
|
||||
|
||||
explicit inline tvec4(T v) noexcept
|
||||
{
|
||||
x = v;
|
||||
y = v;
|
||||
z = v;
|
||||
w = v;
|
||||
}
|
||||
|
||||
inline tvec4(T x_, T y_, T z_, T w_) noexcept
|
||||
{
|
||||
x = x_;
|
||||
y = y_;
|
||||
z = z_;
|
||||
w = w_;
|
||||
}
|
||||
|
||||
inline T &operator[](size_t index)
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
inline const T &operator[](size_t index) const
|
||||
{
|
||||
return data[index];
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
T data[4];
|
||||
struct
|
||||
{
|
||||
T x, y, z, w;
|
||||
};
|
||||
};
|
||||
|
||||
inline tvec2<T> xx() const;
|
||||
inline tvec2<T> xy() const;
|
||||
inline tvec2<T> xz() const;
|
||||
inline tvec2<T> xw() const;
|
||||
inline tvec2<T> yx() const;
|
||||
inline tvec2<T> yy() const;
|
||||
inline tvec2<T> yz() const;
|
||||
inline tvec2<T> yw() const;
|
||||
inline tvec2<T> zx() const;
|
||||
inline tvec2<T> zy() const;
|
||||
inline tvec2<T> zz() const;
|
||||
inline tvec2<T> zw() const;
|
||||
inline tvec2<T> wx() const;
|
||||
inline tvec2<T> wy() const;
|
||||
inline tvec2<T> wz() const;
|
||||
inline tvec2<T> ww() const;
|
||||
|
||||
inline tvec3<T> xxx() const;
|
||||
inline tvec3<T> xxy() const;
|
||||
inline tvec3<T> xxz() const;
|
||||
inline tvec3<T> xxw() const;
|
||||
inline tvec3<T> xyx() const;
|
||||
inline tvec3<T> xyy() const;
|
||||
inline tvec3<T> xyz() const;
|
||||
inline tvec3<T> xyw() const;
|
||||
inline tvec3<T> xzx() const;
|
||||
inline tvec3<T> xzy() const;
|
||||
inline tvec3<T> xzz() const;
|
||||
inline tvec3<T> xzw() const;
|
||||
inline tvec3<T> xwx() const;
|
||||
inline tvec3<T> xwy() const;
|
||||
inline tvec3<T> xwz() const;
|
||||
inline tvec3<T> xww() const;
|
||||
inline tvec3<T> yxx() const;
|
||||
inline tvec3<T> yxy() const;
|
||||
inline tvec3<T> yxz() const;
|
||||
inline tvec3<T> yxw() const;
|
||||
inline tvec3<T> yyx() const;
|
||||
inline tvec3<T> yyy() const;
|
||||
inline tvec3<T> yyz() const;
|
||||
inline tvec3<T> yyw() const;
|
||||
inline tvec3<T> yzx() const;
|
||||
inline tvec3<T> yzy() const;
|
||||
inline tvec3<T> yzz() const;
|
||||
inline tvec3<T> yzw() const;
|
||||
inline tvec3<T> ywx() const;
|
||||
inline tvec3<T> ywy() const;
|
||||
inline tvec3<T> ywz() const;
|
||||
inline tvec3<T> yww() const;
|
||||
inline tvec3<T> zxx() const;
|
||||
inline tvec3<T> zxy() const;
|
||||
inline tvec3<T> zxz() const;
|
||||
inline tvec3<T> zxw() const;
|
||||
inline tvec3<T> zyx() const;
|
||||
inline tvec3<T> zyy() const;
|
||||
inline tvec3<T> zyz() const;
|
||||
inline tvec3<T> zyw() const;
|
||||
inline tvec3<T> zzx() const;
|
||||
inline tvec3<T> zzy() const;
|
||||
inline tvec3<T> zzz() const;
|
||||
inline tvec3<T> zzw() const;
|
||||
inline tvec3<T> zwx() const;
|
||||
inline tvec3<T> zwy() const;
|
||||
inline tvec3<T> zwz() const;
|
||||
inline tvec3<T> zww() const;
|
||||
inline tvec3<T> wxx() const;
|
||||
inline tvec3<T> wxy() const;
|
||||
inline tvec3<T> wxz() const;
|
||||
inline tvec3<T> wxw() const;
|
||||
inline tvec3<T> wyx() const;
|
||||
inline tvec3<T> wyy() const;
|
||||
inline tvec3<T> wyz() const;
|
||||
inline tvec3<T> wyw() const;
|
||||
inline tvec3<T> wzx() const;
|
||||
inline tvec3<T> wzy() const;
|
||||
inline tvec3<T> wzz() const;
|
||||
inline tvec3<T> wzw() const;
|
||||
inline tvec3<T> wwx() const;
|
||||
inline tvec3<T> wwy() const;
|
||||
inline tvec3<T> wwz() const;
|
||||
inline tvec3<T> www() const;
|
||||
|
||||
inline tvec4 xxxx() const;
|
||||
inline tvec4 xxxy() const;
|
||||
inline tvec4 xxxz() const;
|
||||
inline tvec4 xxxw() const;
|
||||
inline tvec4 xxyx() const;
|
||||
inline tvec4 xxyy() const;
|
||||
inline tvec4 xxyz() const;
|
||||
inline tvec4 xxyw() const;
|
||||
inline tvec4 xxzx() const;
|
||||
inline tvec4 xxzy() const;
|
||||
inline tvec4 xxzz() const;
|
||||
inline tvec4 xxzw() const;
|
||||
inline tvec4 xxwx() const;
|
||||
inline tvec4 xxwy() const;
|
||||
inline tvec4 xxwz() const;
|
||||
inline tvec4 xxww() const;
|
||||
inline tvec4 xyxx() const;
|
||||
inline tvec4 xyxy() const;
|
||||
inline tvec4 xyxz() const;
|
||||
inline tvec4 xyxw() const;
|
||||
inline tvec4 xyyx() const;
|
||||
inline tvec4 xyyy() const;
|
||||
inline tvec4 xyyz() const;
|
||||
inline tvec4 xyyw() const;
|
||||
inline tvec4 xyzx() const;
|
||||
inline tvec4 xyzy() const;
|
||||
inline tvec4 xyzz() const;
|
||||
inline tvec4 xyzw() const;
|
||||
inline tvec4 xywx() const;
|
||||
inline tvec4 xywy() const;
|
||||
inline tvec4 xywz() const;
|
||||
inline tvec4 xyww() const;
|
||||
inline tvec4 xzxx() const;
|
||||
inline tvec4 xzxy() const;
|
||||
inline tvec4 xzxz() const;
|
||||
inline tvec4 xzxw() const;
|
||||
inline tvec4 xzyx() const;
|
||||
inline tvec4 xzyy() const;
|
||||
inline tvec4 xzyz() const;
|
||||
inline tvec4 xzyw() const;
|
||||
inline tvec4 xzzx() const;
|
||||
inline tvec4 xzzy() const;
|
||||
inline tvec4 xzzz() const;
|
||||
inline tvec4 xzzw() const;
|
||||
inline tvec4 xzwx() const;
|
||||
inline tvec4 xzwy() const;
|
||||
inline tvec4 xzwz() const;
|
||||
inline tvec4 xzww() const;
|
||||
inline tvec4 xwxx() const;
|
||||
inline tvec4 xwxy() const;
|
||||
inline tvec4 xwxz() const;
|
||||
inline tvec4 xwxw() const;
|
||||
inline tvec4 xwyx() const;
|
||||
inline tvec4 xwyy() const;
|
||||
inline tvec4 xwyz() const;
|
||||
inline tvec4 xwyw() const;
|
||||
inline tvec4 xwzx() const;
|
||||
inline tvec4 xwzy() const;
|
||||
inline tvec4 xwzz() const;
|
||||
inline tvec4 xwzw() const;
|
||||
inline tvec4 xwwx() const;
|
||||
inline tvec4 xwwy() const;
|
||||
inline tvec4 xwwz() const;
|
||||
inline tvec4 xwww() const;
|
||||
inline tvec4 yxxx() const;
|
||||
inline tvec4 yxxy() const;
|
||||
inline tvec4 yxxz() const;
|
||||
inline tvec4 yxxw() const;
|
||||
inline tvec4 yxyx() const;
|
||||
inline tvec4 yxyy() const;
|
||||
inline tvec4 yxyz() const;
|
||||
inline tvec4 yxyw() const;
|
||||
inline tvec4 yxzx() const;
|
||||
inline tvec4 yxzy() const;
|
||||
inline tvec4 yxzz() const;
|
||||
inline tvec4 yxzw() const;
|
||||
inline tvec4 yxwx() const;
|
||||
inline tvec4 yxwy() const;
|
||||
inline tvec4 yxwz() const;
|
||||
inline tvec4 yxww() const;
|
||||
inline tvec4 yyxx() const;
|
||||
inline tvec4 yyxy() const;
|
||||
inline tvec4 yyxz() const;
|
||||
inline tvec4 yyxw() const;
|
||||
inline tvec4 yyyx() const;
|
||||
inline tvec4 yyyy() const;
|
||||
inline tvec4 yyyz() const;
|
||||
inline tvec4 yyyw() const;
|
||||
inline tvec4 yyzx() const;
|
||||
inline tvec4 yyzy() const;
|
||||
inline tvec4 yyzz() const;
|
||||
inline tvec4 yyzw() const;
|
||||
inline tvec4 yywx() const;
|
||||
inline tvec4 yywy() const;
|
||||
inline tvec4 yywz() const;
|
||||
inline tvec4 yyww() const;
|
||||
inline tvec4 yzxx() const;
|
||||
inline tvec4 yzxy() const;
|
||||
inline tvec4 yzxz() const;
|
||||
inline tvec4 yzxw() const;
|
||||
inline tvec4 yzyx() const;
|
||||
inline tvec4 yzyy() const;
|
||||
inline tvec4 yzyz() const;
|
||||
inline tvec4 yzyw() const;
|
||||
inline tvec4 yzzx() const;
|
||||
inline tvec4 yzzy() const;
|
||||
inline tvec4 yzzz() const;
|
||||
inline tvec4 yzzw() const;
|
||||
inline tvec4 yzwx() const;
|
||||
inline tvec4 yzwy() const;
|
||||
inline tvec4 yzwz() const;
|
||||
inline tvec4 yzww() const;
|
||||
inline tvec4 ywxx() const;
|
||||
inline tvec4 ywxy() const;
|
||||
inline tvec4 ywxz() const;
|
||||
inline tvec4 ywxw() const;
|
||||
inline tvec4 ywyx() const;
|
||||
inline tvec4 ywyy() const;
|
||||
inline tvec4 ywyz() const;
|
||||
inline tvec4 ywyw() const;
|
||||
inline tvec4 ywzx() const;
|
||||
inline tvec4 ywzy() const;
|
||||
inline tvec4 ywzz() const;
|
||||
inline tvec4 ywzw() const;
|
||||
inline tvec4 ywwx() const;
|
||||
inline tvec4 ywwy() const;
|
||||
inline tvec4 ywwz() const;
|
||||
inline tvec4 ywww() const;
|
||||
inline tvec4 zxxx() const;
|
||||
inline tvec4 zxxy() const;
|
||||
inline tvec4 zxxz() const;
|
||||
inline tvec4 zxxw() const;
|
||||
inline tvec4 zxyx() const;
|
||||
inline tvec4 zxyy() const;
|
||||
inline tvec4 zxyz() const;
|
||||
inline tvec4 zxyw() const;
|
||||
inline tvec4 zxzx() const;
|
||||
inline tvec4 zxzy() const;
|
||||
inline tvec4 zxzz() const;
|
||||
inline tvec4 zxzw() const;
|
||||
inline tvec4 zxwx() const;
|
||||
inline tvec4 zxwy() const;
|
||||
inline tvec4 zxwz() const;
|
||||
inline tvec4 zxww() const;
|
||||
inline tvec4 zyxx() const;
|
||||
inline tvec4 zyxy() const;
|
||||
inline tvec4 zyxz() const;
|
||||
inline tvec4 zyxw() const;
|
||||
inline tvec4 zyyx() const;
|
||||
inline tvec4 zyyy() const;
|
||||
inline tvec4 zyyz() const;
|
||||
inline tvec4 zyyw() const;
|
||||
inline tvec4 zyzx() const;
|
||||
inline tvec4 zyzy() const;
|
||||
inline tvec4 zyzz() const;
|
||||
inline tvec4 zyzw() const;
|
||||
inline tvec4 zywx() const;
|
||||
inline tvec4 zywy() const;
|
||||
inline tvec4 zywz() const;
|
||||
inline tvec4 zyww() const;
|
||||
inline tvec4 zzxx() const;
|
||||
inline tvec4 zzxy() const;
|
||||
inline tvec4 zzxz() const;
|
||||
inline tvec4 zzxw() const;
|
||||
inline tvec4 zzyx() const;
|
||||
inline tvec4 zzyy() const;
|
||||
inline tvec4 zzyz() const;
|
||||
inline tvec4 zzyw() const;
|
||||
inline tvec4 zzzx() const;
|
||||
inline tvec4 zzzy() const;
|
||||
inline tvec4 zzzz() const;
|
||||
inline tvec4 zzzw() const;
|
||||
inline tvec4 zzwx() const;
|
||||
inline tvec4 zzwy() const;
|
||||
inline tvec4 zzwz() const;
|
||||
inline tvec4 zzww() const;
|
||||
inline tvec4 zwxx() const;
|
||||
inline tvec4 zwxy() const;
|
||||
inline tvec4 zwxz() const;
|
||||
inline tvec4 zwxw() const;
|
||||
inline tvec4 zwyx() const;
|
||||
inline tvec4 zwyy() const;
|
||||
inline tvec4 zwyz() const;
|
||||
inline tvec4 zwyw() const;
|
||||
inline tvec4 zwzx() const;
|
||||
inline tvec4 zwzy() const;
|
||||
inline tvec4 zwzz() const;
|
||||
inline tvec4 zwzw() const;
|
||||
inline tvec4 zwwx() const;
|
||||
inline tvec4 zwwy() const;
|
||||
inline tvec4 zwwz() const;
|
||||
inline tvec4 zwww() const;
|
||||
inline tvec4 wxxx() const;
|
||||
inline tvec4 wxxy() const;
|
||||
inline tvec4 wxxz() const;
|
||||
inline tvec4 wxxw() const;
|
||||
inline tvec4 wxyx() const;
|
||||
inline tvec4 wxyy() const;
|
||||
inline tvec4 wxyz() const;
|
||||
inline tvec4 wxyw() const;
|
||||
inline tvec4 wxzx() const;
|
||||
inline tvec4 wxzy() const;
|
||||
inline tvec4 wxzz() const;
|
||||
inline tvec4 wxzw() const;
|
||||
inline tvec4 wxwx() const;
|
||||
inline tvec4 wxwy() const;
|
||||
inline tvec4 wxwz() const;
|
||||
inline tvec4 wxww() const;
|
||||
inline tvec4 wyxx() const;
|
||||
inline tvec4 wyxy() const;
|
||||
inline tvec4 wyxz() const;
|
||||
inline tvec4 wyxw() const;
|
||||
inline tvec4 wyyx() const;
|
||||
inline tvec4 wyyy() const;
|
||||
inline tvec4 wyyz() const;
|
||||
inline tvec4 wyyw() const;
|
||||
inline tvec4 wyzx() const;
|
||||
inline tvec4 wyzy() const;
|
||||
inline tvec4 wyzz() const;
|
||||
inline tvec4 wyzw() const;
|
||||
inline tvec4 wywx() const;
|
||||
inline tvec4 wywy() const;
|
||||
inline tvec4 wywz() const;
|
||||
inline tvec4 wyww() const;
|
||||
inline tvec4 wzxx() const;
|
||||
inline tvec4 wzxy() const;
|
||||
inline tvec4 wzxz() const;
|
||||
inline tvec4 wzxw() const;
|
||||
inline tvec4 wzyx() const;
|
||||
inline tvec4 wzyy() const;
|
||||
inline tvec4 wzyz() const;
|
||||
inline tvec4 wzyw() const;
|
||||
inline tvec4 wzzx() const;
|
||||
inline tvec4 wzzy() const;
|
||||
inline tvec4 wzzz() const;
|
||||
inline tvec4 wzzw() const;
|
||||
inline tvec4 wzwx() const;
|
||||
inline tvec4 wzwy() const;
|
||||
inline tvec4 wzwz() const;
|
||||
inline tvec4 wzww() const;
|
||||
inline tvec4 wwxx() const;
|
||||
inline tvec4 wwxy() const;
|
||||
inline tvec4 wwxz() const;
|
||||
inline tvec4 wwxw() const;
|
||||
inline tvec4 wwyx() const;
|
||||
inline tvec4 wwyy() const;
|
||||
inline tvec4 wwyz() const;
|
||||
inline tvec4 wwyw() const;
|
||||
inline tvec4 wwzx() const;
|
||||
inline tvec4 wwzy() const;
|
||||
inline tvec4 wwzz() const;
|
||||
inline tvec4 wwzw() const;
|
||||
inline tvec4 wwwx() const;
|
||||
inline tvec4 wwwy() const;
|
||||
inline tvec4 wwwz() const;
|
||||
inline tvec4 wwww() const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tmat2
|
||||
{
|
||||
tmat2() = default;
|
||||
tmat2(const tmat2 &) = default;
|
||||
tmat2 &operator=(const tmat2 &) = default;
|
||||
|
||||
explicit inline tmat2(T v) noexcept
|
||||
{
|
||||
vec[0] = tvec2<T>(v, T(0));
|
||||
vec[1] = tvec2<T>(T(0), v);
|
||||
}
|
||||
|
||||
inline tmat2(const tvec2<T> &a, const tvec2<T> &b) noexcept
|
||||
{
|
||||
vec[0] = a;
|
||||
vec[1] = b;
|
||||
}
|
||||
|
||||
inline tvec2<T> &operator[](size_t index)
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
inline const tvec2<T> &operator[](size_t index) const
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
private:
|
||||
tvec2<T> vec[2];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tmat3
|
||||
{
|
||||
tmat3() = default;
|
||||
tmat3(const tmat3 &) = default;
|
||||
tmat3 &operator=(const tmat3 &) = default;
|
||||
|
||||
explicit inline tmat3(T v) noexcept
|
||||
{
|
||||
vec[0] = tvec3<T>(v, T(0), T(0));
|
||||
vec[1] = tvec3<T>(T(0), v, T(0));
|
||||
vec[2] = tvec3<T>(T(0), T(0), v);
|
||||
}
|
||||
|
||||
inline tmat3(const tvec3<T> &a, const tvec3<T> &b, const tvec3<T> &c) noexcept
|
||||
{
|
||||
vec[0] = a;
|
||||
vec[1] = b;
|
||||
vec[2] = c;
|
||||
}
|
||||
|
||||
explicit inline tmat3(const tmat4<T> &m) noexcept
|
||||
{
|
||||
for (int col = 0; col < 3; col++)
|
||||
for (int row = 0; row < 3; row++)
|
||||
vec[col][row] = m[col][row];
|
||||
}
|
||||
|
||||
inline tvec3<T> &operator[](size_t index)
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
inline const tvec3<T> &operator[](size_t index) const
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
private:
|
||||
tvec3<T> vec[3];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tmat4
|
||||
{
|
||||
tmat4() = default;
|
||||
tmat4(const tmat4 &) = default;
|
||||
tmat4 &operator=(const tmat4 &) = default;
|
||||
|
||||
explicit inline tmat4(T v) noexcept
|
||||
{
|
||||
vec[0] = tvec4<T>(v, T(0), T(0), T(0));
|
||||
vec[1] = tvec4<T>(T(0), v, T(0), T(0));
|
||||
vec[2] = tvec4<T>(T(0), T(0), v, T(0));
|
||||
vec[3] = tvec4<T>(T(0), T(0), T(0), v);
|
||||
}
|
||||
|
||||
explicit inline tmat4(const tmat3<T> &m) noexcept
|
||||
{
|
||||
vec[0] = tvec4<T>(m[0], T(0));
|
||||
vec[1] = tvec4<T>(m[1], T(0));
|
||||
vec[2] = tvec4<T>(m[2], T(0));
|
||||
vec[3] = tvec4<T>(T(0), T(0), T(0), T(1));
|
||||
}
|
||||
|
||||
inline tmat4(const tvec4<T> &a, const tvec4<T> &b, const tvec4<T> &c, const tvec4<T> &d) noexcept
|
||||
{
|
||||
vec[0] = a;
|
||||
vec[1] = b;
|
||||
vec[2] = c;
|
||||
vec[3] = d;
|
||||
}
|
||||
|
||||
inline tvec4<T> &operator[](size_t index)
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
inline const tvec4<T> &operator[](size_t index) const
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
private:
|
||||
tvec4<T> vec[4];
|
||||
};
|
||||
|
||||
using uint = uint32_t;
|
||||
using vec2 = tvec2<float>;
|
||||
using vec3 = tvec3<float>;
|
||||
using vec4 = tvec4<float>;
|
||||
using mat2 = tmat2<float>;
|
||||
using mat3 = tmat3<float>;
|
||||
using mat4 = tmat4<float>;
|
||||
|
||||
using dvec2 = tvec2<double>;
|
||||
using dvec3 = tvec3<double>;
|
||||
using dvec4 = tvec4<double>;
|
||||
using dmat2 = tmat2<double>;
|
||||
using dmat3 = tmat3<double>;
|
||||
using dmat4 = tmat4<double>;
|
||||
|
||||
using ivec2 = tvec2<int32_t>;
|
||||
using ivec3 = tvec3<int32_t>;
|
||||
using ivec4 = tvec4<int32_t>;
|
||||
using uvec2 = tvec2<uint32_t>;
|
||||
using uvec3 = tvec3<uint32_t>;
|
||||
using uvec4 = tvec4<uint32_t>;
|
||||
|
||||
using u16vec2 = tvec2<uint16_t>;
|
||||
using u16vec3 = tvec3<uint16_t>;
|
||||
using u16vec4 = tvec4<uint16_t>;
|
||||
using i16vec2 = tvec2<int16_t>;
|
||||
using i16vec3 = tvec3<int16_t>;
|
||||
using i16vec4 = tvec4<int16_t>;
|
||||
|
||||
using u8vec2 = tvec2<uint8_t>;
|
||||
using u8vec3 = tvec3<uint8_t>;
|
||||
using u8vec4 = tvec4<uint8_t>;
|
||||
using i8vec2 = tvec2<int8_t>;
|
||||
using i8vec3 = tvec3<int8_t>;
|
||||
using i8vec4 = tvec4<int8_t>;
|
||||
|
||||
using bvec2 = tvec2<bool>;
|
||||
using bvec3 = tvec3<bool>;
|
||||
using bvec4 = tvec4<bool>;
|
||||
|
||||
void transpose(mat4 &dst, const mat4 &src);
|
||||
void transpose_to_affine(vec4 dst[3], const mat4 &src);
|
||||
|
||||
struct mat_affine
|
||||
{
|
||||
mat_affine() = default;
|
||||
mat_affine(const mat_affine &) = default;
|
||||
mat_affine &operator=(const mat_affine &) = default;
|
||||
|
||||
explicit inline mat_affine(const mat4 &m)
|
||||
{
|
||||
transpose_to_affine(vec, m);
|
||||
}
|
||||
|
||||
explicit inline mat_affine(const mat3 &m)
|
||||
: vec{{m[0][0], m[1][0], m[2][0], 0.0f},
|
||||
{m[0][1], m[1][1], m[2][1], 0.0f},
|
||||
{m[0][2], m[1][2], m[2][2], 0.0f}}
|
||||
{
|
||||
}
|
||||
|
||||
explicit inline mat_affine(float v)
|
||||
: vec{{v, 0, 0, 0}, {0, v, 0, 0}, {0, 0, v, 0}}
|
||||
{
|
||||
}
|
||||
|
||||
inline mat_affine(const vec4 &r0, const vec4 &r1, const vec4 &r2)
|
||||
: vec{r0, r1, r2}
|
||||
{
|
||||
}
|
||||
|
||||
inline vec4 &operator[](size_t index)
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
inline const vec4 &operator[](size_t index) const
|
||||
{
|
||||
return vec[index];
|
||||
}
|
||||
|
||||
float get_uniform_scale() const;
|
||||
vec3 get_translation() const;
|
||||
// Based on identity view pointing to -Z axis, Y up.
|
||||
vec3 get_forward() const;
|
||||
vec3 get_right() const;
|
||||
vec3 get_up() const;
|
||||
|
||||
mat4 to_mat4() const;
|
||||
void to_mat4(mat4 &m) const;
|
||||
|
||||
inline mat3 to_mat3() const
|
||||
{
|
||||
return {
|
||||
vec3(vec[0][0], vec[1][0], vec[2][0]),
|
||||
vec3(vec[0][1], vec[1][1], vec[2][1]),
|
||||
vec3(vec[0][2], vec[1][2], vec[2][2]),
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
vec4 vec[3];
|
||||
};
|
||||
|
||||
struct quat : private vec4
|
||||
{
|
||||
quat() = default;
|
||||
quat(const quat &) = default;
|
||||
quat(float w_, float x_, float y_, float z_)
|
||||
: vec4(x_, y_, z_, w_)
|
||||
{}
|
||||
|
||||
explicit inline quat(const vec4 &v)
|
||||
: vec4(v)
|
||||
{}
|
||||
|
||||
inline quat(float w_, const vec3 &v_)
|
||||
: vec4(v_, w_)
|
||||
{}
|
||||
|
||||
inline const vec4 &as_vec4() const
|
||||
{
|
||||
return *static_cast<const vec4 *>(this);
|
||||
}
|
||||
|
||||
quat &operator=(const quat &) = default;
|
||||
|
||||
using vec4::x;
|
||||
using vec4::y;
|
||||
using vec4::z;
|
||||
using vec4::w;
|
||||
};
|
||||
|
||||
template <typename T> constexpr inline T pi() { return T(3.1415926535897932384626433832795028841971); }
|
||||
template <typename T> constexpr inline T half_pi() { return T(0.5) * pi<T>(); }
|
||||
template <typename T> constexpr inline T one_over_root_two() { return T(0.7071067811865476); }
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,251 @@
|
||||
/* Copyright (c) 2017-2026 Hans-Kristian Arntzen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "muglm_impl.hpp"
|
||||
#include "matrix_helper.hpp"
|
||||
#include "simd.hpp"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "aabb.hpp"
|
||||
|
||||
using namespace muglm;
|
||||
|
||||
#define MATH_ASSERT(x) do { \
|
||||
if (!bool(x)) \
|
||||
abort(); \
|
||||
} while(0)
|
||||
|
||||
template <typename T>
|
||||
static void assert_equal_epsilon(const T &a, const T &b, float epsilon = 0.0001f)
|
||||
{
|
||||
MATH_ASSERT(all(lessThanEqual(abs(a - b), T(epsilon))));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void assert_equal(const T &a, const T &b)
|
||||
{
|
||||
MATH_ASSERT(all(equal(a, b)));
|
||||
}
|
||||
|
||||
static void assert_equal_epsilon(const mat2 &a, const mat2 &b, float epsilon = 0.0001f)
|
||||
{
|
||||
assert_equal_epsilon(a[0], b[0], epsilon);
|
||||
assert_equal_epsilon(a[1], b[1], epsilon);
|
||||
}
|
||||
|
||||
static void assert_equal_epsilon(const mat3 &a, const mat3 &b, float epsilon = 0.0001f)
|
||||
{
|
||||
assert_equal_epsilon(a[0], b[0], epsilon);
|
||||
assert_equal_epsilon(a[1], b[1], epsilon);
|
||||
assert_equal_epsilon(a[2], b[2], epsilon);
|
||||
}
|
||||
|
||||
static void assert_equal_epsilon(const mat4 &a, const mat4 &b, float epsilon = 0.0001f)
|
||||
{
|
||||
assert_equal_epsilon(a[0], b[0], epsilon);
|
||||
assert_equal_epsilon(a[1], b[1], epsilon);
|
||||
assert_equal_epsilon(a[2], b[2], epsilon);
|
||||
assert_equal_epsilon(a[3], b[3], epsilon);
|
||||
}
|
||||
|
||||
static void assert_equal_epsilon(const mat_affine &a, const mat_affine &b, float epsilon = 0.0001f)
|
||||
{
|
||||
assert_equal_epsilon(a[0], b[0], epsilon);
|
||||
assert_equal_epsilon(a[1], b[1], epsilon);
|
||||
assert_equal_epsilon(a[2], b[2], epsilon);
|
||||
}
|
||||
|
||||
static void assert_equal(const mat2 &a, const mat2 &b)
|
||||
{
|
||||
assert_equal_epsilon(a, b, 0.0f);
|
||||
}
|
||||
|
||||
static void assert_equal(const mat3 &a, const mat3 &b)
|
||||
{
|
||||
assert_equal_epsilon(a, b, 0.0f);
|
||||
}
|
||||
|
||||
static void assert_equal(const mat4 &a, const mat4 &b)
|
||||
{
|
||||
assert_equal_epsilon(a, b, 0.0f);
|
||||
}
|
||||
|
||||
static void test_mat2()
|
||||
{
|
||||
mat2 m(vec2(2.0f, 0.5f), vec2(8.0f, 4.0f));
|
||||
mat2 inv_m = inverse(m);
|
||||
mat2 mul0 = m * inv_m;
|
||||
mat2 mul1 = inv_m * m;
|
||||
assert_equal_epsilon(mul0, mat2(1.0f));
|
||||
assert_equal_epsilon(mul1, mat2(1.0f));
|
||||
assert_equal(transpose(transpose(m)), m);
|
||||
}
|
||||
|
||||
static void test_mat3()
|
||||
{
|
||||
mat3 m(vec3(2.0f, 0.5f, -3.0f), vec3(8.0f, 4.0f, 0.25f), vec3(-20.0f, 5.0f, 1.0f));
|
||||
mat3 inv_m = inverse(m);
|
||||
mat3 mul0 = m * inv_m;
|
||||
mat3 mul1 = inv_m * m;
|
||||
assert_equal_epsilon(mul0, mat3(1.0f));
|
||||
assert_equal_epsilon(mul1, mat3(1.0f));
|
||||
assert_equal(transpose(transpose(m)), m);
|
||||
}
|
||||
|
||||
static void test_mat4()
|
||||
{
|
||||
mat4 m(vec4(2.0f, 0.5f, -3.0f, 1.0f), vec4(8.0f, 4.0f, 0.25f, 8.0f), vec4(8.0f, -20.0f, 5.0f, 1.0f), vec4(0.0f, 1.0f, 2.0f, 3.0f));
|
||||
mat4 inv_m = inverse(m);
|
||||
mat4 mul0 = m * inv_m;
|
||||
mat4 mul1 = inv_m * m;
|
||||
assert_equal_epsilon(mul0, mat4(1.0f));
|
||||
assert_equal_epsilon(mul1, mat4(1.0f));
|
||||
assert_equal(transpose(transpose(m)), m);
|
||||
}
|
||||
|
||||
static void test_quat()
|
||||
{
|
||||
// X
|
||||
{
|
||||
quat q = angleAxis(half_pi<float>(), vec3(0.0f, 0.0f, 1.0f));
|
||||
vec3 y = q * vec3(1.0f, 0.0f, 0.0f);
|
||||
assert_equal_epsilon(y, vec3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
quat half_q = angleAxis(0.5f * half_pi<float>(), vec3(0.0f, 0.0f, 1.0f));
|
||||
q = half_q * half_q;
|
||||
y = q * vec3(1.0f, 0.0f, 0.0f);
|
||||
assert_equal_epsilon(y, vec3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
|
||||
// Y
|
||||
{
|
||||
quat q = angleAxis(half_pi<float>(), vec3(0.0f, 1.0f, 0.0f));
|
||||
vec3 y = q * vec3(1.0f, 0.0f, 0.0f);
|
||||
assert_equal_epsilon(y, vec3(0.0f, 0.0f, -1.0f));
|
||||
|
||||
quat half_q = angleAxis(0.5f * half_pi<float>(), vec3(0.0f, 1.0f, 0.0f));
|
||||
q = half_q * half_q;
|
||||
y = q * vec3(1.0f, 0.0f, 0.0f);
|
||||
assert_equal_epsilon(y, vec3(0.0f, 0.0f, -1.0f));
|
||||
}
|
||||
|
||||
assert_equal_epsilon(mat3_cast(quat(1.0f, 0.0f, 0.0f, 0.0f)), mat3(1.0f));
|
||||
assert_equal_epsilon(mat4_cast(quat(1.0f, 0.0f, 0.0f, 0.0f)), mat4(1.0f));
|
||||
}
|
||||
|
||||
static void test_decompose()
|
||||
{
|
||||
vec3 scaling(4.0f, -3.0f, 2.0f);
|
||||
quat rotate = angleAxis(0.543f, vec3(0.1f, 0.2f, -0.9f));
|
||||
vec3 trans(5.0f, 4.0f, 2.0f);
|
||||
|
||||
mat4 original = translate(trans) * mat4_cast(rotate) * scale(scaling);
|
||||
|
||||
vec3 s, t;
|
||||
quat r;
|
||||
decompose(original, s, r, t);
|
||||
|
||||
mat4 reconstructed = translate(t) * mat4_cast(r) * scale(s);
|
||||
assert_equal_epsilon(original, reconstructed);
|
||||
}
|
||||
|
||||
static void test_transpose()
|
||||
{
|
||||
mat4 original(vec4(1, 2, 3, 4), vec4(5, 6, 7, 8), vec4(9, 10, 11, 12), vec4(13, 14, 15, 16));
|
||||
mat4 transposed = transpose(original);
|
||||
mat_affine aff{original};
|
||||
|
||||
const mat4 expected_transposed(
|
||||
vec4(1, 5, 9, 13),
|
||||
vec4(2, 6, 10, 14),
|
||||
vec4(3, 7, 11, 15),
|
||||
vec4(4, 8, 12, 16));
|
||||
|
||||
mat_affine expected_aff;
|
||||
for (int i = 0; i < 3; i++)
|
||||
expected_aff[i] = expected_transposed[i];
|
||||
|
||||
assert_equal_epsilon(expected_transposed, transposed, 0.0f);
|
||||
assert_equal_epsilon(expected_aff, aff, 0.0f);
|
||||
}
|
||||
|
||||
static void test_affine()
|
||||
{
|
||||
mat4 a(vec4(1, 2, 3, 0), vec4(5, 6, 7, 0),
|
||||
vec4(9, 10, 11, 0), vec4(13, 14, 15, 1));
|
||||
mat4 b(vec4(17, 18, 19, 0), vec4(21, 22, 23, 0),
|
||||
vec4(25, 26, 27, 0), vec4(29, 30, 31, 1));
|
||||
|
||||
mat4 c = a * b;
|
||||
mat_affine aff_c(c);
|
||||
mat_affine aff_a(a);
|
||||
mat_affine aff_b(b);
|
||||
|
||||
mat_affine res;
|
||||
Granite::SIMD::mul(res, aff_a, aff_b);
|
||||
assert_equal_epsilon(res, aff_c, 0.0f);
|
||||
}
|
||||
|
||||
static void test_affine_mul()
|
||||
{
|
||||
mat4 a(vec4(1, 2, 3, 0), vec4(5, 6, 7, 0),
|
||||
vec4(9, 10, 11, 0), vec4(13, 14, 15, 1));
|
||||
vec4 b(1, 2, 3, 1);
|
||||
|
||||
mat_affine aff_a(a);
|
||||
|
||||
vec4 ref = a * b;
|
||||
vec4 res4, res_affine;
|
||||
Granite::SIMD::mul(res4, a, b);
|
||||
Granite::SIMD::mul(res_affine, aff_a, b);
|
||||
|
||||
assert_equal_epsilon(ref, res4, 0.0f);
|
||||
assert_equal_epsilon(ref, res_affine, 0.0f);
|
||||
}
|
||||
|
||||
static void test_aabb_transform()
|
||||
{
|
||||
mat4 m(vec4(1, 2, 3, 0), vec4(5, 6, 7, 0),
|
||||
vec4(9, 10, 11, 0), vec4(13, 14, 15, 1));
|
||||
|
||||
Granite::AABB aabb{vec3(-1, -2, -4), vec3(3, 7, 4)};
|
||||
|
||||
Granite::AABB reference_aabb, affine_aabb;
|
||||
Granite::SIMD::transform_aabb(reference_aabb, aabb, m);
|
||||
Granite::SIMD::transform_aabb(affine_aabb, aabb, mat_affine(m));
|
||||
|
||||
assert_equal_epsilon(reference_aabb.get_maximum4(), affine_aabb.get_maximum4(), 0.0f);
|
||||
assert_equal_epsilon(reference_aabb.get_minimum4(), affine_aabb.get_minimum4(), 0.0f);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_mat2();
|
||||
test_mat3();
|
||||
test_mat4();
|
||||
test_quat();
|
||||
test_decompose();
|
||||
test_transpose();
|
||||
test_affine();
|
||||
test_affine_mul();
|
||||
test_aabb_transform();
|
||||
}
|
||||
Reference in New Issue
Block a user