|
| 1 | +import {describe, test, expect} from 'vitest'; |
| 2 | +import {mat4, vec3, quat} from 'gl-matrix'; |
| 3 | +import {fastInvertTransformMat4, fastInvertProjMat4, fastInvertSkewMat4} from './fast_maths'; |
| 4 | + |
| 5 | +function compare_matrix(mat: mat4, matRef: mat4){ |
| 6 | + for (let i=0; i<16; ++i){ |
| 7 | + expect(mat[i]).toBeCloseTo(matRef[i], 6); |
| 8 | + } |
| 9 | +} |
| 10 | + |
| 11 | +describe('fast_maths', () => { |
| 12 | + test('invert a transform matrix', () => { |
| 13 | + const testParams = [{ |
| 14 | + translate: [1, 2, -3], |
| 15 | + scaleXY: 10, |
| 16 | + rotAxis: [5, 6, 7], |
| 17 | + rotAngle: Math.PI / 4 |
| 18 | + },{ |
| 19 | + translate: [0, 0, 0], |
| 20 | + scaleXY: 1, |
| 21 | + rotAxis: [0, 0, 1], |
| 22 | + rotAngle: 0 |
| 23 | + },{ |
| 24 | + translate: [-50, 100, 0.5], |
| 25 | + scaleXY: 0.01, |
| 26 | + rotAxis: [1, 0, 0], |
| 27 | + rotAngle: Math.PI |
| 28 | + },{ |
| 29 | + translate: [1000, -2000, 500], |
| 30 | + scaleXY: 200, |
| 31 | + rotAxis: [0, 1, 0], |
| 32 | + rotAngle: -Math.PI / 6 |
| 33 | + },{ |
| 34 | + translate: [-0.1, 0.2, -0.3], |
| 35 | + scaleXY: 0.5, |
| 36 | + rotAxis: [1, 1, 0], |
| 37 | + rotAngle: Math.PI / 2 |
| 38 | + },{ |
| 39 | + translate: [0, 0, -9999], |
| 40 | + scaleXY: 50, |
| 41 | + rotAxis: [0.3, 0.4, 0.5], |
| 42 | + rotAngle: -0.01 |
| 43 | + },{ |
| 44 | + translate: [42, -7, 13], |
| 45 | + scaleXY: 4, |
| 46 | + rotAxis: [1, -2, 3], |
| 47 | + rotAngle: 2.1 |
| 48 | + }]; |
| 49 | + const m = mat4.create(); |
| 50 | + const mInv = mat4.create(); |
| 51 | + const mInvRef = mat4.create(); |
| 52 | + for (const {translate, scaleXY, rotAxis, rotAngle} of testParams) { |
| 53 | + // translation vector: |
| 54 | + const v = vec3.create(); |
| 55 | + vec3.copy(v, translate); |
| 56 | + |
| 57 | + // scale vector. sx shoule be = sy: |
| 58 | + const s = vec3.create(); |
| 59 | + s[0] = scaleXY; |
| 60 | + s[1] = scaleXY; |
| 61 | + s[2] = 1; |
| 62 | + |
| 63 | + // quaternion: |
| 64 | + const q = quat.create(); |
| 65 | + const axis = vec3.create(); |
| 66 | + vec3.copy(axis, rotAxis); |
| 67 | + vec3.normalize(axis, axis); |
| 68 | + quat.setAxisAngle(q, axis, rotAngle); |
| 69 | + mat4.fromRotationTranslationScale(m, q, v, s); |
| 70 | + |
| 71 | + // compute inv: |
| 72 | + fastInvertTransformMat4(mInv, m); |
| 73 | + |
| 74 | + // compute ref: |
| 75 | + mat4.invert(mInvRef, m); |
| 76 | + |
| 77 | + compare_matrix(mInv, mInvRef); |
| 78 | + }; |
| 79 | + }); |
| 80 | + |
| 81 | + test('invert a projection matrix', () => { |
| 82 | + const testParams = [ |
| 83 | + { |
| 84 | + fov: Math.PI/4, |
| 85 | + aspect: 16/9, |
| 86 | + zNear: 1, |
| 87 | + zFar: 1000 |
| 88 | + }, |
| 89 | + { |
| 90 | + fov: Math.PI/3, |
| 91 | + aspect: 4/3, |
| 92 | + zNear: 10, |
| 93 | + zFar: 10000 |
| 94 | + }, |
| 95 | + { |
| 96 | + fov: Math.PI/8, |
| 97 | + aspect: 1, |
| 98 | + zNear: 1, |
| 99 | + zFar: 10 |
| 100 | + }, |
| 101 | + { |
| 102 | + fov: Math.PI/4, |
| 103 | + aspect: 2, |
| 104 | + zNear: 1, |
| 105 | + zFar: 1000 |
| 106 | + } |
| 107 | + ]; |
| 108 | + const m = mat4.create(); |
| 109 | + const mInv = mat4.create(); |
| 110 | + const mInvRef = mat4.create(); |
| 111 | + for (const {fov, aspect, zNear, zFar} of testParams) { |
| 112 | + mat4.perspective(m, fov, aspect, zNear, zFar); |
| 113 | + // compute inv: |
| 114 | + fastInvertProjMat4(mInv, m); |
| 115 | + // compute ref: |
| 116 | + mat4.invert(mInvRef, m); |
| 117 | + compare_matrix(mInv, mInvRef); |
| 118 | + }; |
| 119 | + }); |
| 120 | + |
| 121 | + test('invert a skew matrix', () => { |
| 122 | + const testParams = [{ |
| 123 | + diag: [1, 1, 1, 1], |
| 124 | + counterDiagXY: [0, 0] |
| 125 | + },{ |
| 126 | + diag: [2, 3, 4, 5], |
| 127 | + counterDiagXY: [0.5, -0.5] |
| 128 | + },{ |
| 129 | + diag: [0.1, 0.2, 0.3, 0.4], |
| 130 | + counterDiagXY: [0.01, -0.01] |
| 131 | + },{ |
| 132 | + diag: [10, 10, 10, 1], |
| 133 | + counterDiagXY: [3, -3] |
| 134 | + },{ |
| 135 | + diag: [1, 1, 1, 1], |
| 136 | + counterDiagXY: [0.9, -0.9] |
| 137 | + },{ |
| 138 | + diag: [100, 200, 50, 1], |
| 139 | + counterDiagXY: [10, 20] |
| 140 | + },{ |
| 141 | + diag: [0.5, 0.5, 0.5, 2], |
| 142 | + counterDiagXY: [0, 0] |
| 143 | + },{ |
| 144 | + diag: [7, 3, 5, 1], |
| 145 | + counterDiagXY: [-2, 1] |
| 146 | + },{ |
| 147 | + diag: [1, 1, 0.01, 1], |
| 148 | + counterDiagXY: [0.5, 0.3] |
| 149 | + },{ |
| 150 | + diag: [4, 8, 2, 1], |
| 151 | + counterDiagXY: [-5, 3] |
| 152 | + },{ |
| 153 | + diag: [0.3, 0.7, 1.5, 1], |
| 154 | + counterDiagXY: [0.1, -0.2] |
| 155 | + }]; |
| 156 | + const m = mat4.create(); |
| 157 | + const mInv = mat4.create(); |
| 158 | + const mInvRef = mat4.create(); |
| 159 | + for(const {diag, counterDiagXY} of testParams) { |
| 160 | + // forge a skew matrix: |
| 161 | + m[0] = diag[0]; |
| 162 | + m[5] = diag[1]; |
| 163 | + m[10] = diag[2]; |
| 164 | + m[15] = diag[3]; |
| 165 | + m[4] = counterDiagXY[0]; |
| 166 | + m[1] = counterDiagXY[1]; |
| 167 | + |
| 168 | + // compute inv: |
| 169 | + fastInvertSkewMat4(mInv, m); |
| 170 | + |
| 171 | + // compute ref: |
| 172 | + mat4.invert(mInvRef, m); |
| 173 | + |
| 174 | + compare_matrix(mInv, mInvRef); |
| 175 | + }; |
| 176 | + }); |
| 177 | +}); |
0 commit comments