@@ -4,6 +4,7 @@ const mach = @import("../main.zig");
44const testing = mach .testing ;
55const math = mach .math ;
66const vec = @import ("vec.zig" );
7+ const quat = @import ("quat.zig" );
78
89pub 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