import glm
# We assume all the spaces up to and including view space to feature a Y-axis pointing upwards.
# Screen space in Vulkan, however, has the +Y-axis pointing downwards, +X to the left, and +Z into the screen.
# We are staying in right-handed (RH) coordinate systems throughout ALL the spaces.
# Therefore, we are representing the coordinates from here on -- actually exactly BETWEEN View Space and
# Clip Space -- in a coordinate system which is rotated 180 around X, having Y point down, still RH.
let rotateAroundXFrom_RH_Yup_to_RH_Ydown*: Mat4[float32] =
mat4f( vec4f(1.float32, 0, 0, 0)
, -vec4f(0.float32, 1, 0, 0)
, -vec4f(0.float32, 0, 1, 0)
, vec4f(0.float32, 0, 0, 1)
)
let rotateAroundXFrom_RH_Yup_to_RH_Ydown_Inverse* = inverse rotateAroundXFrom_RH_Yup_to_RH_Ydown
proc ortho*(left, right, bottom, top, near, far: float32): Mat4f =
var m = mat4[float32](1.0)
let
rl = right - left
tb = top - bottom
fn = far - near
m[0][0] = 2.float32 / rl
m[1][1] = 2.float32 / tb
m[2][2] = 1.float32 / fn
m[3][0] = -(right + left) / rl
m[3][1] = -(top + bottom) / tb
m[3][2] = -(near) / fn
result = m * rotateAroundXFrom_RH_Yup_to_RH_Ydown_Inverse
proc lookAtRH*( eye
, center
, up: Vec3[float32]
): Mat4[float32] =
let
f = normalize(center - eye)
s = normalize(cross(f, up))
u = cross(s, f)
result[0][0] = s.x
result[1][0] = s.y
result[2][0] = s.z
result[0][1] = u.x
result[1][1] = u.y
result[2][1] = u.z
result[0][2] = -f.x
result[1][2] = -f.y
result[2][2] = -f.z
result[3][0] = -dot(s, eye)
result[3][1] = -dot(u, eye)
result[3][2] = dot(f, eye)
proc perspectiveLH*[T]( fovy, aspect, zNear, zFar:T): Mat4[T] =
let tanHalfFovy = tan(fovy / T(2))
result = mat4[T](0.0)
result[0,0] = T(1) / (aspect * tanHalfFovy)
result[1,1] = T(1) / (tanHalfFovy)
result[2,2] = (zFar + zNear) / (zFar - zNear)
result[2,3] = T(1)
result[3,2] = - (T(2) * zFar * zNear) / (zFar - zNear)
proc perspectiveRH*[T]( fovy, aspect, zNear, zFar:T): Mat4f =
let tanHalfFovy = tan(fovy / T(2))
result = mat4[T](0.0)
result[0,0] = T(1) / (aspect * tanHalfFovy)
result[1,1] = T(1) / (tanHalfFovy)
result[2,3] = T(-1)
result[2,2] = -(zFar + zNear) / (zFar - zNear)
result[3,2] = -(T(2) * zFar * zNear) / (zFar - zNear)