Odin icon indicating copy to clipboard operation
Odin copied to clipboard

linalg look_at left-handedness issues

Open xzores opened this issue 1 year ago • 1 comments

Context

    Odin:    dev-2024-03-nightly:4c35633e0
    OS:      Windows 11 Home Basic (version: 23H2), build 22631.3296
    CPU:     13th Gen Intel(R) Core(TM) i9-13900HX
    RAM:     32507 MiB
    Backend: LLVM 17.0.1

The problem

In core/math/linalg lib there are many functions that allow a flip_z_axis variable (default true). These works fine (i think) in a right handed coordinate system, but the flip_z_axis is kinda a lie.

Let us have a look at one of them:

@(require_results)
matrix4_look_at_f32 :: proc "contextless" (eye, centre, up: Vector3f32, flip_z_axis : bool) -> (m: Matrix4f32) {
	f := normalize(centre - eye)
	s := normalize(cross(f, up))
	u := cross(s, f)

	fe := dot(f, eye)

	return {
		+s.x, +s.y, +s.z, -dot(s, eye),
		+u.x, +u.y, +u.z, -dot(u, eye),
		-f.x, -f.y, -f.z, +fe if flip_z_axis else -fe,
		   0,    0,    0, 1,
	}
}

Let us have a look at why the matrix4_look_at_f32 is not correct.

One would expect that in a left handed coordinate system where x positive is right, y positive is up and z positive is forward (into the screen) that the matrix : look_at_mat := linalg.matrix4_look_at_f32({0,0,0}, {0,0,1}, {0,1,0}, false); would inded not flip any axis. The output from the operation is shown below:

look_at_mat : matrix[
        -1, 0, 0, 0,
        0, 1,  0, 0,
        0, 0, -1, 0,
        0, 0, 0,  1,
]

It is quite clear to see that the axis was flipped! and as a matter of fact, the matrix with flip_z_axis = true looks the exact same. One might note that the x-axis is also flipped making this a 180 degree rotation and not a flip of the handedness. But here is the weird thing. This will keep a right handed coordinate system right handed and a left handed coordinate system left handed. So the problem might not be that it is inherently incorrect, but it does define the axis the following way: For the right handed coordinate system the coordinates are x-right, y-up, z-back (out of screen). But for the left handed coordinate system the coordinate are x-left, y-up, z-back. Why would it flip x-axis and not the z? It seems weird and I have not found any documentation on what the left-handed vs right-handed coordinates are supossed to be. To me this feels like a design flaw. It seems that flip_z_axis implies that it will be the z-axis that are flipped not the x-axis.

From the operation look_at_mat := linalg.matrix4_look_at_f32({0,0,0}, {0,0,1}, {0,1,0}, false); I would expect the matrix to return the identity matrix. Just like look_at_mat := linalg.matrix4_look_at_f32({0,0,0}, {0,0,-1}, {0,1,0}, true); return the identity matrix for the right handed coordinate system.

There are many functions in the linalg library with the same problem.

xzores avatar Apr 07 '24 14:04 xzores

Please don't use stupid titles.

gingerBill avatar Apr 07 '24 15:04 gingerBill