raylib-rs icon indicating copy to clipboard operation
raylib-rs copied to clipboard

Why is matrix multiplication backwards ?

Open karshan opened this issue 2 years ago • 1 comments

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 avatar Apr 07 '24 21:04 karshan

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.

karshan avatar Apr 09 '24 00:04 karshan