odin-lang / Odin

Odin Programming Language
https://odin-lang.org
BSD 3-Clause "New" or "Revised" License
6.6k stars 576 forks source link

Raylib with `-define:RAYLIB_USE_LINALG=false` does not work with recent addition of raymath #3252

Closed laytan closed 6 months ago

laytan commented 6 months ago

An API like raymath was recently added to the raylib package that calls into the linalg package. But with -define:RAYLIB_USE_LINALG=false this obviously fails to compile.

laytan commented 6 months ago

2 solutions that come to mind:

  1. Drop the RAYLIB_USE_LINALG configuration, always use linalg instead
  2. Put raymath in a when block over this config and bind to the actual raymath procs in the false case
gingerBill commented 6 months ago

It's probably better to just use linalg for everything.

laytan commented 6 months ago

Agreed, but, the linalg types still don't work right, I made a gist porting a raylib example here: https://gist.github.com/laytan/8c1dbe6c96d78045f95524da26237765

It contains a raymath.odin that should replace the vendor/raylib/raymath.odin, it just adds a when block around it and loads the needed procedures from raylib.

The example looks like this (correct) with -define:RAYLIB_USE_LINALG=false:

https://github.com/odin-lang/Odin/assets/20369598/456c29fe-66ed-4343-b7d2-b4d315f103da

But, without that define, it looks like this:

https://github.com/odin-lang/Odin/assets/20369598/d3483500-5e8f-4be9-a84d-52710c701461

karl-zylinski commented 6 months ago

I think the above might be due to more Matrix alignment issues? DrawMeshInstanced uses a multi-pointer of rl.Matrix. Will the multi-pointer also be affected by the same alignment issues that we saw in those structs you fixed previously @gingerBill?

thePHTest commented 6 months ago

Note that USE_LINALG also causes issues with rl.DrawMesh, which also has a rl.Matrix parameter.

gingerBill commented 6 months ago

I don't understand how alignment would effect anything. If something is 16 byte aligned, it also means it is 4 byte aligned.

thePHTest commented 6 months ago

It differences are from differing matrix conventions.

With linalg:

t := raylib.MatrixTranslate(3.0, 0.0, 0.0)
fmt.println(t)
fmt.println(transmute([16]f32)t)
matrix[1, 0, 0, 3; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 0, 0, 1]

Without linalg

Matrix{m0 = 1, m4 = 0, m8 = 0, m12 = 3, m1 = 0, m5 = 1, m9 = 0, m13 = 0, m2 = 0, m6 = 0, m10 = 1, m14 = 0, m3 = 0, m7 = 0, m11 = 0, m15 = 1}
[1, 0, 0, 3, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
gingerBill commented 6 months ago

I have figured out the problem now.

Raylib uses row-major matrices internally, but transposes at the last moment before uploading to the GPU.

It's kind of crazy the decisions that they made, but oh well.

The "solution" is to heavily document everything and tell people to only use linalg procedures if they remember to linalg.transpose the matrices, or do row_vector * row_matrix everywhere.

laytan commented 6 months ago

You are correct, reimplementing the functions I needed in the example to do the same thing but transposed made the example work correctly, so raymath.odin needs to be changed to do this everywhere.

laytan commented 6 months ago

Works now, with the recent addition of #row_major matrices 🚀