import { Mat4 } from "../math/Mat4"
import { Vec3 } from "../math/Vec3"

/** First-person camera. Orientation is Euler yaw/pitch (no roll), which is all
 *  an FPS needs and avoids gimbal bookkeeping. */
export type Camera = {
  position: Vec3
  /** Rotation around +Y, radians. 0 looks toward -Z; increasing turns right. */
  yaw: number
  /** Look up/down, radians. Positive looks up. Clamp near +-pi/2 to avoid flip. */
  pitch: number
  /** Vertical field of view, radians. */
  fov: number
}

export namespace Camera {
  /** Unit forward direction implied by yaw/pitch. */
  export function forward(cam: Camera): Vec3 {
    const cp = Math.cos(cam.pitch)
    return {
      x: cp * Math.sin(cam.yaw),
      y: Math.sin(cam.pitch),
      z: -cp * Math.cos(cam.yaw),
    }
  }

  /** Combined projection * view matrix for the given viewport aspect ratio.
   *  Near/far are fixed; far only needs to exceed the fog distance, and is set
   *  wide enough to reach the outdoor world's distant peaks. */
  export function viewProjection(cam: Camera, aspect: number): Mat4 {
    const eye = cam.position
    const view = Mat4.lookAt(eye, Vec3.add(eye, forward(cam)), { x: 0, y: 1, z: 0 })
    const proj = Mat4.perspective(cam.fov, aspect, 0.05, 260)
    return Mat4.multiply(proj, view)
  }
}
