Skip to content

Commit 9749cd9

Browse files
Keerpichemidoots
authored andcommitted
Add matrix rotation by quaternion
1 parent 6fd6a8f commit 9749cd9

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

src/math/mat.zig

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const mach = @import("../main.zig");
44
const testing = mach.testing;
55
const math = mach.math;
66
const vec = @import("vec.zig");
7+
const quat = @import("quat.zig");
78

89
pub fn Mat2x2(
910
comptime Scalar: type,
@@ -439,6 +440,22 @@ pub fn Mat4x4(
439440
);
440441
}
441442

443+
//https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/jay.htm
444+
//Requires a normalized quaternion
445+
pub inline fn rotateByQuaternion(quaternion: quat.Quat(T)) Matrix {
446+
const qx = quaternion.v.x();
447+
const qy = quaternion.v.y();
448+
const qz = quaternion.v.z();
449+
const qw = quaternion.v.w();
450+
451+
return Matrix.init(
452+
&RowVec.init(1 - 2 * qy * qy - 2 * qz * qz, 2 * qx * qy - 2 * qz * qw, 2 * qx * qz + 2 * qy * qw, 0),
453+
&RowVec.init(2 * qx * qy + 2 * qz * qw, 1 - 2 * qx * qx - 2 * qz * qz, 2 * qy * qz - 2 * qx * qw, 0),
454+
&RowVec.init(2 * qx * qz - 2 * qy * qw, 2 * qy * qz + 2 * qx * qw, 1 - 2 * qx * qx - 2 * qy * qy, 0),
455+
&RowVec.init(0, 0, 0, 1),
456+
);
457+
}
458+
442459
/// Constructs a 2D projection matrix, aka. an orthographic projection matrix.
443460
///
444461
/// First, a cuboid is defined with the parameters:
@@ -1196,3 +1213,17 @@ test "projection2D_model_to_clip_space" {
11961213
try testing.expect(math.Vec4, math.vec4(1, 0, 1, 1)).eql(mvp.mul(&math.Mat4x4.rotateY(math.degreesToRadians(90))).mulVec(&math.vec4(0, 0, 50, 1)));
11971214
try testing.expect(math.Vec4, math.vec4(0, 0, 0.5, 1)).eql(mvp.mul(&math.Mat4x4.rotateZ(math.degreesToRadians(90))).mulVec(&math.vec4(0, 0, 50, 1)));
11981215
}
1216+
1217+
test "quaternion_rotation" {
1218+
const expected = math.Mat4x4.init(
1219+
&math.vec4(0.7716905, 0.5519065, 0.3160585, 0),
1220+
&math.vec4(-0.0782971, -0.4107276, 0.9083900, 0),
1221+
&math.vec4(0.6311602, -0.7257425, -0.2737419, 0),
1222+
&math.vec4(0, 0, 0, 1),
1223+
);
1224+
1225+
const q = math.Quat.fromAxisAngle(math.vec3(0.9182788, 0.1770672, 0.3541344), 4.2384558);
1226+
const result = math.Mat4x4.rotateByQuaternion(q.normalize());
1227+
1228+
try testing.expect(bool, true).eql(expected.eqlApprox(&result, 0.0000002));
1229+
}

0 commit comments

Comments
 (0)