9fd660bbd0ac1c133191b3f8685fa1c3b35e62ab
[vg.git] / vg_camera.h
1 #pragma once
2 #include "vg_m.h"
3
4 typedef struct vg_camera vg_camera;
5 struct vg_camera{
6 /* Input */
7 v3f angles;
8 v3f pos;
9 f32 fov, nearz, farz;
10
11 /* Output */
12 m4x3f transform,
13 transform_inverse;
14
15 struct vg_camera_mtx{
16 m4x4f p,
17 v,
18 pv;
19 }
20 mtx,
21 mtx_prev;
22 };
23
24 static void vg_camera_lerp_angles( v3f a, v3f b, f32 t, v3f d ){
25 d[0] = vg_alerpf( a[0], b[0], t );
26 d[1] = vg_lerpf( a[1], b[1], t );
27 d[2] = vg_lerpf( a[2], b[2], t );
28 }
29
30 /* lerp position, fov, and angles */
31 static void vg_camera_lerp( vg_camera *a, vg_camera *b, f32 t, vg_camera *d ){
32 v3_lerp( a->pos, b->pos, t, d->pos );
33 vg_camera_lerp_angles( a->angles, b->angles, t, d->angles );
34 d->fov = vg_lerpf( a->fov, b->fov, t );
35 }
36
37 static void vg_camera_copy( vg_camera *a, vg_camera *d ){
38 v3_copy( a->pos, d->pos );
39 v3_copy( a->angles, d->angles );
40 d->fov = a->fov;
41 }
42
43 static void vg_m4x3_transform_camera( m4x3f m, vg_camera *cam ){
44 m4x3_mulv( m, cam->pos, cam->pos );
45
46 v3f v0;
47 v3_angles_vector( cam->angles, v0 );
48 m3x3_mulv( m, v0, v0 );
49 v3_normalize( v0 );
50 v3_angles( v0, cam->angles );
51 }
52
53 /*
54 * 1) [angles, pos] -> transform
55 */
56 static void vg_camera_update_transform( vg_camera *cam ){
57 v4f qyaw, qpitch, qcam;
58 q_axis_angle( qyaw, (v3f){ 0.0f, 1.0f, 0.0f }, -cam->angles[0] );
59 q_axis_angle( qpitch, (v3f){ 1.0f, 0.0f, 0.0f }, -cam->angles[1] );
60
61 q_mul( qyaw, qpitch, qcam );
62 q_m3x3( qcam, cam->transform );
63 v3_copy( cam->pos, cam->transform[3] );
64 }
65
66 /*
67 * 2) [transform] -> transform_inverse, view matrix
68 */
69 static void vg_camera_update_view( vg_camera *cam ){
70 m4x4_copy( cam->mtx.v, cam->mtx_prev.v );
71 m4x3_invert_affine( cam->transform, cam->transform_inverse );
72 m4x3_expand( cam->transform_inverse, cam->mtx.v );
73 }
74
75 /*
76 * 3) [fov,nearz,farz] -> projection matrix
77 */
78 static void vg_camera_update_projection( vg_camera *cam ){
79 m4x4_copy( cam->mtx.p, cam->mtx_prev.p );
80 m4x4_projection( cam->mtx.p, cam->fov,
81 (float)vg.window_x / (float)vg.window_y,
82 cam->nearz, cam->farz );
83 }
84
85 /*
86 * 4) [projection matrix, view matrix] -> previous pv, new pv
87 */
88 static void vg_camera_finalize( vg_camera *cam ){
89 m4x4_copy( cam->mtx.pv, cam->mtx_prev.pv );
90 m4x4_mul( cam->mtx.p, cam->mtx.v, cam->mtx.pv );
91 }