19 const float inv = 1.f / len;
31inline float clampf(
float v,
float lo,
float hi) {
32 return std::max(lo, std::min(hi,
v));
35inline float lerpf(
float a,
float b,
float t) {
return a + (
b -
a) * t; }
37inline void slerpQuat(
float ax,
float ay,
float az,
float aw,
float bx,
float by,
float bz,
float bw,
38 float t,
float &ox,
float &oy,
float &oz,
float &ow) {
39 float cosTheta = ax * bx + ay * by + az * bz + aw * bw;
47 if (cosTheta > 0.9995f) {
48 ox =
lerpf(ax, bx, t);
49 oy =
lerpf(ay, by, t);
50 oz =
lerpf(az, bz, t);
51 ow =
lerpf(aw, bw, t);
52 const float len = std::sqrt(ox * ox + oy * oy + oz * oz + ow * ow);
54 const float inv = 1.f / len;
62 const float theta = std::acos(
clampf(cosTheta, -1.f, 1.f));
63 const float sinTheta = std::sin(theta);
64 const float w0 = std::sin((1.f - t) * theta) / sinTheta;
65 const float w1 = std::sin(t * theta) / sinTheta;
66 ox = ax * w0 + bx * w1;
67 oy = ay * w0 + by * w1;
68 oz = az * w0 + bz * w1;
69 ow = aw * w0 + bw * w1;
81 slerpQuat(
a.qx,
a.qy,
a.qz,
a.qw,
b.qx,
b.qy,
b.qz,
b.qw, t, out.
qx, out.
qy, out.
qz, out.
qw);
91inline float length2(
float x,
float z) {
return std::sqrt(
x *
x +
z *
z); }
98 float m[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
105 const float x2 =
x +
x, y2 =
y +
y, z2 =
z +
z;
106 const float xx =
x * x2, xy =
x * y2, xz =
x * z2;
107 const float yy =
y * y2, yz =
y * z2, zz =
z * z2;
108 const float wx =
w * x2, wy =
w * y2, wz =
w * z2;
110 out.
m[0] = (1.f - (yy + zz)) * t.
sx;
111 out.
m[1] = (xy + wz) * t.
sx;
112 out.
m[2] = (xz - wy) * t.
sx;
114 out.
m[4] = (xy - wz) * t.
sy;
115 out.
m[5] = (1.f - (xx + zz)) * t.
sy;
116 out.
m[6] = (yz + wx) * t.
sy;
118 out.
m[8] = (xz + wy) * t.
sz;
119 out.
m[9] = (yz - wx) * t.
sz;
120 out.
m[10] = (1.f - (xx + yy)) * t.
sz;
131 for (
int col = 0; col < 4; ++col) {
132 for (
int row = 0; row < 4; ++row) {
133 out.
m[col * 4 + row] =
a.m[0 * 4 + row] *
b.m[col * 4 + 0] +
134 a.m[1 * 4 + row] *
b.m[col * 4 + 1] +
135 a.m[2 * 4 + row] *
b.m[col * 4 + 2] +
136 a.m[3 * 4 + row] *
b.m[col * 4 + 3];
143 ox =
m[0] *
x +
m[4] *
y +
m[8] *
z +
m[12];
144 oy =
m[1] *
x +
m[5] *
y +
m[9] *
z +
m[13];
145 oz =
m[2] *
x +
m[6] *
y +
m[10] *
z +
m[14];
TransformTRS blendTRS(const TransformTRS &a, const TransformTRS &b, float t)
void slerpQuat(float ax, float ay, float az, float aw, float bx, float by, float bz, float bw, float t, float &ox, float &oy, float &oz, float &ow)
void yawToForward(float yaw, float &fx, float &fz)
Rotate unit +Z by yaw (radians) around Y — used for planar facing.
float length2(float x, float z)
float lerpf(float a, float b, float t)
float clampf(float v, float lo, float hi)
Column-major 4x4 matrix (OpenGL / glTF / Assimp-compatible layout). Elements: m[col * 4 + row].
static Mat4 fromTRS(const TransformTRS &t)
void transformPoint(float x, float y, float z, float &ox, float &oy, float &oz) const
static Mat4 mul(const Mat4 &a, const Mat4 &b)