deltaphc / raylib-rs

Rust bindings for raylib
Other
751 stars 134 forks source link

Why is matrix multiplication backwards ? #182

Open karshan opened 5 months ago

karshan commented 5 months ago

The implementation in https://github.com/deltaphc/raylib-rs/blob/master/raylib/src/core/math.rs#L1901 is backwards. (i.e. if you want to compute a b, you need to use the expression b a when using raylib-rs)

e.g.

A = [ 1, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 ] // (m0 = 1; all other m_ = 0)

B = [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] // (m1 = 1; all other m_ = 0)

Then in raylib-rs A B = B; but A B should = 0 (the zero matrix).

I'm assuming m1 is representing row 1 column 0 based on the implementation of Matrix::translate()

(this is also true in raylib so maybe this might not be considered a bug, https://github.com/raysan5/raylib/issues/3039, but the rotate_x/y/z are inconsistent with raylib)

karshan commented 5 months ago

I did a bit of digging and I think several Matrix related functions are all wrong. One simple example is Matrix::rotate_z.

This is the implementation in raylib-rs

    pub fn rotate_z(angle: f32) -> Matrix {
        let mut result = Matrix::identity();

        let cosres = angle.cos();
        let sinres = angle.sin();

        result.m0 = cosres;
        result.m1 = -sinres;
        result.m4 = sinres;
        result.m5 = cosres;
        result
    }

And this is the implementation in raylib

RMAPI Matrix MatrixRotateZ(float angle)
{
    Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f,
                      0.0f, 1.0f, 0.0f, 0.0f,
                      0.0f, 0.0f, 1.0f, 0.0f,
                      0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity()

    float cosres = cosf(angle);
    float sinres = sinf(angle);

    result.m0 = cosres;
    result.m1 = sinres;
    result.m4 = -sinres;
    result.m5 = cosres;

    return result;
}

Notice how m1 and m4 are off by a factor of -1.