this repo has no description
at in-one-weekend 182 lines 7.8 kB view raw
1// ============================================================================== 2// 3// Collection of useful functions building on top of, and extending, core zmath. 4// https://github.com/michal-z/zig-gamedev/tree/main/libs/zmath 5// 6// ------------------------------------------------------------------------------ 7// 1. Matrix functions 8// ------------------------------------------------------------------------------ 9// 10// As an example, in a left handed Y-up system: 11// getAxisX is equivalent to the right vector 12// getAxisY is equivalent to the up vector 13// getAxisZ is equivalent to the forward vector 14// 15// getTranslationVec(m: Mat) Vec 16// getAxisX(m: Mat) Vec 17// getAxisY(m: Mat) Vec 18// getAxisZ(m: Mat) Vec 19// 20// ============================================================================== 21 22const zm = @import("zmath.zig"); 23const std = @import("std"); 24const math = std.math; 25const expect = std.testing.expect; 26 27pub fn getTranslationVec(m: zm.Mat) zm.Vec { 28 var translation = m[3]; 29 translation[3] = 0; 30 return translation; 31} 32 33pub fn getScaleVec(m: zm.Mat) zm.Vec { 34 const scale_x = zm.length3(zm.f32x4(m[0][0], m[1][0], m[2][0], 0))[0]; 35 const scale_y = zm.length3(zm.f32x4(m[0][1], m[1][1], m[2][1], 0))[0]; 36 const scale_z = zm.length3(zm.f32x4(m[0][2], m[1][2], m[2][2], 0))[0]; 37 return zm.f32x4(scale_x, scale_y, scale_z, 0); 38} 39 40pub fn getRotationQuat(_m: zm.Mat) zm.Quat { 41 // Ortho normalize given matrix. 42 const c1 = zm.normalize3(zm.f32x4(_m[0][0], _m[1][0], _m[2][0], 0)); 43 const c2 = zm.normalize3(zm.f32x4(_m[0][1], _m[1][1], _m[2][1], 0)); 44 const c3 = zm.normalize3(zm.f32x4(_m[0][2], _m[1][2], _m[2][2], 0)); 45 var m = _m; 46 m[0][0] = c1[0]; 47 m[1][0] = c1[1]; 48 m[2][0] = c1[2]; 49 m[0][1] = c2[0]; 50 m[1][1] = c2[1]; 51 m[2][1] = c2[2]; 52 m[0][2] = c3[0]; 53 m[1][2] = c3[1]; 54 m[2][2] = c3[2]; 55 56 // Extract rotation 57 return zm.quatFromMat(m); 58} 59 60pub fn getAxisX(m: zm.Mat) zm.Vec { 61 return zm.normalize3(zm.f32x4(m[0][0], m[0][1], m[0][2], 0.0)); 62} 63 64pub fn getAxisY(m: zm.Mat) zm.Vec { 65 return zm.normalize3(zm.f32x4(m[1][0], m[1][1], m[1][2], 0.0)); 66} 67 68pub fn getAxisZ(m: zm.Mat) zm.Vec { 69 return zm.normalize3(zm.f32x4(m[2][0], m[2][1], m[2][2], 0.0)); 70} 71 72test "zmath.util.mat.translation" { 73 // zig fmt: off 74 const mat_data = [18]f32{ 75 1.0, 76 2.0, 3.0, 4.0, 5.0, 77 6.0, 7.0, 8.0, 9.0, 78 10.0,11.0, 12.0,13.0, 79 14.0, 15.0, 16.0, 17.0, 80 18.0, 81 }; 82 // zig fmt: on 83 const mat = zm.loadMat(mat_data[1..]); 84 const translation = getTranslationVec(mat); 85 try expect(zm.approxEqAbs(translation, zm.f32x4(14.0, 15.0, 16.0, 0.0), 0.0001)); 86} 87 88test "zmath.util.mat.scale" { 89 const mat = zm.mul(zm.scaling(3, 4, 5), zm.translation(6, 7, 8)); 90 const scale = getScaleVec(mat); 91 try expect(zm.approxEqAbs(scale, zm.f32x4(3.0, 4.0, 5.0, 0.0), 0.0001)); 92} 93 94test "zmath.util.mat.rotation" { 95 const rotate_origin = zm.matFromRollPitchYaw(0.1, 1.2, 2.3); 96 const mat = zm.mul(zm.mul(rotate_origin, zm.scaling(3, 4, 5)), zm.translation(6, 7, 8)); 97 const rotate_get = getRotationQuat(mat); 98 const v0 = zm.mul(zm.f32x4s(1), rotate_origin); 99 const v1 = zm.mul(zm.f32x4s(1), zm.quatToMat(rotate_get)); 100 try expect(zm.approxEqAbs(v0, v1, 0.0001)); 101} 102 103test "zmath.util.mat.z_vec" { 104 const degToRad = std.math.degreesToRadians; 105 var identity = zm.identity(); 106 var z_vec = getAxisZ(identity); 107 try expect(zm.approxEqAbs(z_vec, zm.f32x4(0.0, 0.0, 1.0, 0), 0.0001)); 108 const rot_yaw = zm.rotationY(degToRad(f32, 90)); 109 identity = zm.mul(identity, rot_yaw); 110 z_vec = getAxisZ(identity); 111 try expect(zm.approxEqAbs(z_vec, zm.f32x4(1.0, 0.0, 0.0, 0), 0.0001)); 112} 113 114test "zmath.util.mat.y_vec" { 115 const degToRad = std.math.degreesToRadians; 116 var identity = zm.identity(); 117 var y_vec = getAxisY(identity); 118 try expect(zm.approxEqAbs(y_vec, zm.f32x4(0.0, 1.0, 0.0, 0), 0.01)); 119 const rot_yaw = zm.rotationY(degToRad(f32, 90)); 120 identity = zm.mul(identity, rot_yaw); 121 y_vec = getAxisY(identity); 122 try expect(zm.approxEqAbs(y_vec, zm.f32x4(0.0, 1.0, 0.0, 0), 0.01)); 123 const rot_pitch = zm.rotationX(degToRad(f32, 90)); 124 identity = zm.mul(identity, rot_pitch); 125 y_vec = getAxisY(identity); 126 try expect(zm.approxEqAbs(y_vec, zm.f32x4(0.0, 0.0, 1.0, 0), 0.01)); 127} 128 129test "zmath.util.mat.right" { 130 const degToRad = std.math.degreesToRadians; 131 var identity = zm.identity(); 132 var right = getAxisX(identity); 133 try expect(zm.approxEqAbs(right, zm.f32x4(1.0, 0.0, 0.0, 0), 0.01)); 134 const rot_yaw = zm.rotationY(degToRad(f32, 90)); 135 identity = zm.mul(identity, rot_yaw); 136 right = getAxisX(identity); 137 try expect(zm.approxEqAbs(right, zm.f32x4(0.0, 0.0, -1.0, 0), 0.01)); 138 const rot_pitch = zm.rotationX(degToRad(f32, 90)); 139 identity = zm.mul(identity, rot_pitch); 140 right = getAxisX(identity); 141 try expect(zm.approxEqAbs(right, zm.f32x4(0.0, 1.0, 0.0, 0), 0.01)); 142} 143 144// ------------------------------------------------------------------------------ 145// This software is available under 2 licenses -- choose whichever you prefer. 146// ------------------------------------------------------------------------------ 147// ALTERNATIVE A - MIT License 148// Copyright (c) 2022 Michal Ziulek and Contributors 149// Permission is hereby granted, free of charge, to any person obtaining identity copy of 150// this software and associated documentation files (the "Software"), to deal in 151// the Software without restriction, including without limitation the rights to 152// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 153// of the Software, and to permit persons to whom the Software is furnished to do 154// so, subject to the following conditions: 155// The above copyright notice and this permission notice shall be included in all 156// copies or substantial portions of the Software. 157// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 159// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 160// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 161// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 162// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 163// SOFTWARE. 164// ------------------------------------------------------------------------------ 165// ALTERNATIVE B - Public Domain (www.unlicense.org) 166// This is free and unencumbered software released into the public domain. 167// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 168// software, either in source code form or as identity compiled binary, for any purpose, 169// commercial or non-commercial, and by any means. 170// In jurisdictions that recognize copyright laws, the author or authors of this 171// software dedicate any and all copyright interest in the software to the public 172// domain. We make this dedication for the benefit of the public at large and to 173// the detriment of our heirs and successors. We intend this dedication to be an 174// overt act of relinquishment in perpetuity of all present and future rights to 175// this software under copyright law. 176// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 179// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 180// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 181// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 182// ------------------------------------------------------------------------------