Add basic quaternion struct

This commit is contained in:
Alex Selimov 2026-07-25 21:49:59 -04:00
parent 8045b97838
commit 861f638ea6

View file

@ -85,6 +85,32 @@ pub fn vec3MulMat3(comptime T: type, a: Vec3(T), b: Mat3(T)) Vec3(T) {
};
}
// Uses the Quaternion definition of q = w + xi + yj + zk
// and with i^2 = j^2 = k^2 = ijk = -1
// I grabbed a lot of this math from https://imadrahmoune.com/rotations-with-quaternions/
pub fn Quat(comptime T: type) type {
return struct {
w: T,
x: T,
y: T,
z: T,
pub fn mag(q: Quat(T)) T {
return std.math.sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
}
pub fn normalized(q: Quat(T)) Quat(T) {
const magnitude = q.mag();
return .{
.x = q.x / magnitude,
.y = q.y / magnitude,
.z = q.z / magnitude,
.w = q.w / magnitude,
};
}
};
}
test "vec3Add adds properly" {
const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 };
const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 };
@ -209,3 +235,25 @@ test "vec3 mul mat3 works" {
try std.testing.expect(c.y == 3);
try std.testing.expect(c.z == 5);
}
test "quat magnitude" {
const q: Quat(f32) = .{ .x = 1.0, .y = 2.0, .z = 3.0, .w = 4.0 };
try std.testing.expect(std.math.approxEqAbs(f32, q.mag(), std.math.sqrt(30.0), 1e-7));
}
test "quat normalized" {
const q: Quat(f32) = .{ .x = 1.0, .y = 2.0, .z = 3.0, .w = 4.0 };
const expected: Quat(f32) = .{
.x = 1.0 / std.math.sqrt(30.0),
.y = 2.0 / std.math.sqrt(30.0),
.z = 3.0 / std.math.sqrt(30.0),
.w = 4.0 / std.math.sqrt(30.0),
};
const normalized = q.normalized();
try std.testing.expect(std.math.approxEqAbs(f32, normalized.x, expected.x, 1e-7));
try std.testing.expect(std.math.approxEqAbs(f32, normalized.y, expected.y, 1e-7));
try std.testing.expect(std.math.approxEqAbs(f32, normalized.z, expected.z, 1e-7));
try std.testing.expect(std.math.approxEqAbs(f32, normalized.w, expected.w, 1e-7));
}