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