// Note: some of those procedures are already implemented in the language's Math module, but for the sake of keeping the examples close to the C version, we'll be using the ones below.
// Ported from "HandmadeMath.h", available at https://github.com/floooh/sokol-samples/blob/master/sapp/HandmadeMath.h).
#import "Math";

persp_mat4 :: (fov: float, aspect: float, near: float, far: float) -> Matrix4 {
    m := Matrix4_Identity;
    t := tan(fov * (PI / 360));
    m.coef[0][0] = 1.0 / t;
    m.coef[1][1] = aspect / t;
    m.coef[2][3] = -1.0;
    m.coef[2][2] = (near + far) / (near - far);
    m.coef[3][2] = (2.0 * near * far) / (near - far);
    m.coef[3][3] = 0;
    return m;
}
lookat_mat4 :: (eye: Vector3, center: Vector3, up: Vector3) -> Matrix4 {
    m: Matrix4;
    f := normalize(center - eye);
    s := normalize(cross(f, up));
    u := cross(s, f);

    m.coef[0][0] = s.x;
    m.coef[0][1] = u.x;
    m.coef[0][2] = -f.x;

    m.coef[1][0] = s.y;
    m.coef[1][1] = u.y;
    m.coef[1][2] = -f.y;

    m.coef[2][0] = s.z;
    m.coef[2][1] = u.z;
    m.coef[2][2] = -f.z;

    m.coef[3][0] = -dot(s, eye);
    m.coef[3][1] = -dot(u, eye);
    m.coef[3][2] = dot(f, eye);
    m.coef[3][3] = 1.0;

    return m;
}
multiply_mat4 :: (left: Matrix4, right: Matrix4) -> Matrix4 {
    m: Matrix4;
    for col : 0 .. 3 {
        for row : 0 .. 3 {
            m.coef[col][row] = left.coef[0][row] * right.coef[col][0] +
                               left.coef[1][row] * right.coef[col][1] +
                               left.coef[2][row] * right.coef[col][2] +
                               left.coef[3][row] * right.coef[col][3];
        }
    }
    return m;
}
rotate_mat4 :: (angle: float, axis_unorm: Vector3) -> Matrix4 {
    m := Matrix4_Identity;

    axis := normalize(axis_unorm);
    sin_theta := sin(radians(angle));
    cos_theta := cos(radians(angle));
    cos_value := 1.0 - cos_theta;

    m.coef[0][0] = (axis.x * axis.x * cos_value) + cos_theta;
    m.coef[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta);
    m.coef[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta);
    m.coef[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta);
    m.coef[1][1] = (axis.y * axis.y * cos_value) + cos_theta;
    m.coef[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta);
    m.coef[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta);
    m.coef[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta);
    m.coef[2][2] = (axis.z * axis.z * cos_value) + cos_theta;

    return m;
}
translate_mat4 :: (translation: Vector3) -> Matrix4 {
    m := Matrix4_Identity;
    m.coef[3][0] = translation.x;
    m.coef[3][1] = translation.y;
    m.coef[3][2] = translation.z;
    return m;
}
radians :: (degrees: float) -> float { return degrees * TAU / 360.0; }
