#include "vec.h"

#define DEPTH_MAX 255

M4x4f lookat(V3f eye, V3f target, V3f up) {
  V3f z = V3(V3f, f32, target.x, target.y, target.z, eye.x, eye.y, eye.z);
  normalise_v3(z);
  V3f x = cross_product(up, z);
  normalise_v3(x);
  V3f y = cross_product(z, x);
  normalise_v3(y);

  M4x4f rotation = mat4x4_identity;
  rotation.row0.x = x.x;
  rotation.row0.y = x.y;
  rotation.row0.z = x.z;
  rotation.row1.x = y.x;
  rotation.row1.y = y.y;
  rotation.row1.z = y.z;
  rotation.row2.x = z.x;
  rotation.row2.y = z.y;
  rotation.row2.z = z.z;

  M4x4f translation = mat4x4_identity;
  translation.row0.w = -(eye.x);
  translation.row1.w = -(eye.y);
  translation.row2.w = -(eye.z);

  return mat4x4_mul(rotation, translation);
}

M4x4f projection(f32 coeff) {
  // clang-format off
  return (M4x4f){
    .row0 = {1.0f, 0.0f,  0.0f, 0.0f},
    .row1 = {0.0f, 1.0f,  0.0f, 0.0f},
    .row2 = {0.0f, 0.0f,  1.0f, 0.0f},
    .row3 = {0.0f, 0.0f, coeff, 1.0f},
  };
  // clang-format on
}

M4x4f viewport(f32 x, f32 y, u64 w, u64 h) {
  M4x4f output = mat4x4_identity;

  f32 half_width = (f32)w * 0.5f;
  f32 half_height = (f32)h * 0.5f;
  f32 half_depth = (f32)DEPTH_MAX * 0.5f;

  output.row0.x = half_width;
  output.row0.w = x + half_width;
  output.row1.y = half_height;
  output.row1.w = y + half_height;
  output.row2.z = output.row2.w = half_depth;

  return output;
}
