+ q_m3x3( qcam, cam->transform );
+ v3_copy( cam->pos, cam->transform[3] );
+}
+
+/*
+ * 2) [transform] -> transform_inverse, view matrix
+ */
+VG_STATIC void camera_update_view( camera *cam )
+{
+ m4x4_copy( cam->mtx.v, cam->mtx_prev.v );
+ m4x3_invert_affine( cam->transform, cam->transform_inverse );
+ m4x3_expand( cam->transform_inverse, cam->mtx.v );
+}
+
+/*
+ * 3) [fov,nearz,farz] -> projection matrix
+ */
+VG_STATIC void camera_update_projection( camera *cam )
+{
+ m4x4_copy( cam->mtx.p, cam->mtx_prev.p );
+ m4x4_projection( cam->mtx.p, cam->fov,
+ (float)vg.window_x / (float)vg.window_y,
+ cam->nearz, cam->farz );
+}
+
+/*
+ * 4) [projection matrix, view matrix] -> previous pv, new pv
+ */
+VG_STATIC void camera_finalize( camera *cam )
+{
+ m4x4_copy( cam->mtx.pv, cam->mtx_prev.pv );
+ m4x4_mul( cam->mtx.p, cam->mtx.v, cam->mtx.pv );
+}