haxiomic / vector-math

Shader-math in haxe: library for GLSL vector operations, complete with swizzles and all
MIT License
39 stars 7 forks source link

matrix inverse & transpose #1

Closed shakesoda closed 3 years ago

shakesoda commented 3 years ago

It'd be really handy to bring in GLSL ES 3.0's inverse & transpose functions, they're very useful.

(btw, thanks for publishing this, I'm experimenting with swapping the vector math in my game out with this and results so far are promising)

haxiomic commented 3 years ago

@shakesoda totally agree :), I'll add those in pretty soon, likely at some point next week (I'll add outerProduct and determinant too). If you get to inverse and transpose before me I'm happy to accept a PR for them

Super keen to hear how you get on with the swap

shakesoda commented 3 years ago

sounds great, and things are behaving well with the library swap. performance and memory usage are comparable (now that I've worked out the remaining bugs, mostly from minor differences in behavior, such as normalize not guarding against 0 and copying instead of operating in place).

I ended up adding a sanity checked normalize for my own convenience, but that's about all. I tried out the f32 flag and my hl/jit build crashes - haven't run an hl/c build yet, but I think it was recently fixed in the jit and I just need to update.

@:overload(function(v: Float): Float {})
@:overload(function(v: Vec2): Vec2 {})
@:overload(function(v: Vec3): Vec3 {})
@:overload(function(v: Vec4): Vec4 {})
macro function checked_normalize(v) return useCurrentPos(
    switch mapVecType(v) {
        case 1: macro $v == 0 ? 0.0 : 1.0;
        default: macro {
            final len2: Float = $v.dot($v);
            len2 == 0 ? $v.clone() : $v / Math.sqrt(len2);
        }
    }
);

here's debug stage working: image

haxiomic commented 3 years ago

Your game looks awesome! What are you using for rendering out of interest?

The spec doesn't explicitly set the behavior for normalizing a zero vector but after some testing it seems like returning 0.0 is a common implementation and sensible enough so I've made this the default (https://github.com/haxiomic/vector-math/commit/62b0591a0f8281c007825c4de53a03d2a7099b8c)

Not sure what's causing the crash on hl – I ran the tests with hl + vector-math-f32 and it seemed happy, curious to hear if you get to the bottom of it! update: there's some bug in hashlink 1.10 jit when using Single: normalize(vec2(3, 4)).length() -> 0.0 \o/. Updated to hl 1.12 and it works

shakesoda commented 3 years ago

Thanks! I'm currently rendering with OpenGL 4.3. I want to do some internal redesigns and maybe move it to Vulkan, but that's for another day.

Checking the normalize will prevent a lot of headaches, and thanks for checking out the hl issue - I think it was hl issue 411 and/or 412, I'll update and try again. ~It's a minor hassle to do that on my end since I've got local patches (hl 244, wasn't merged) to the modules, so I've been putting that off.~ update: no more crash on latest HL ~, although there are some visual bugs I need to investigate (looks like my bug, not yours)~ more update: goofed an else - everything is fine.

hansagames commented 3 years ago

Any progress in inverse ?. :)

shakesoda commented 3 years ago

here's one if you need it now

function mat4_inverse(m: Mat4): Mat4 {
    final a00 = m[0][0];
    final a01 = m[0][1];
    final a02 = m[0][2];
    final a03 = m[0][3];

    final a10 = m[1][0];
    final a11 = m[1][1];
    final a12 = m[1][2];
    final a13 = m[1][3];

    final a20 = m[2][0];
    final a21 = m[2][1];
    final a22 = m[2][2];
    final a23 = m[2][3];

    final a30 = m[3][0];
    final a31 = m[3][1];
    final a32 = m[3][2];
    final a33 = m[3][3];

    final b00 = a00 * a11 - a01 * a10;
    final b01 = a00 * a12 - a02 * a10;
    final b02 = a00 * a13 - a03 * a10;
    final b03 = a01 * a12 - a02 * a11;
    final b04 = a01 * a13 - a03 * a11;
    final b05 = a02 * a13 - a03 * a12;
    final b06 = a20 * a31 - a21 * a30;
    final b07 = a20 * a32 - a22 * a30;
    final b08 = a20 * a33 - a23 * a30;
    final b09 = a21 * a32 - a22 * a31;
    final b10 = a21 * a33 - a23 * a31;
    final b11 = a22 * a33 - a23 * a32;

    final det = 1.0 / (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);

    return mat4(
        (a11 * b11 - a12 * b10 + a13 * b09) * det,
        (a02 * b10 - a01 * b11 - a03 * b09) * det,
        (a31 * b05 - a32 * b04 + a33 * b03) * det,
        (a22 * b04 - a21 * b05 - a23 * b03) * det,
        (a12 * b08 - a10 * b11 - a13 * b07) * det,
        (a00 * b11 - a02 * b08 + a03 * b07) * det,
        (a32 * b02 - a30 * b05 - a33 * b01) * det,
        (a20 * b05 - a22 * b02 + a23 * b01) * det,
        (a10 * b10 - a11 * b08 + a13 * b06) * det,
        (a01 * b08 - a00 * b10 - a03 * b06) * det,
        (a30 * b04 - a31 * b02 + a33 * b00) * det,
        (a21 * b02 - a20 * b04 - a23 * b00) * det,
        (a11 * b07 - a10 * b09 - a12 * b06) * det,
        (a00 * b09 - a01 * b07 + a02 * b06) * det,
        (a31 * b01 - a30 * b03 - a32 * b00) * det,
        (a20 * b03 - a21 * b01 + a22 * b00) * det
    );
}
haxiomic commented 3 years ago

Just added new methods transpose, determinant, inverse and adjoint along with validation tests and published 1.5.0 to haxelib (used glMatrix as a reference)