+ v3_lerp( cc->tpv_offset_smooth, cc->tpv_offset,
+ vg.time_frame_delta * 8.0f, cc->tpv_offset_smooth );
+
+ /* fov -- simple blend */
+ float fov_skate = vg_lerpf( 97.0f, 135.0f, k_fov ),
+ fov_walk = vg_lerpf( 90.0f, 110.0f, k_fov );
+
+ localplayer.cam.fov = vg_lerpf( fov_walk, fov_skate, cc->camera_type_blend );
+
+ /*
+ * first person camera
+ */
+
+ /* position */
+ v3f fpv_pos, fpv_offset;
+ m4x3_mulv( localplayer.final_mtx[ av->id_head-1 ],
+ cc->fpv_viewpoint_smooth, fpv_pos );
+ m3x3_mulv( localplayer.rb.to_world, cc->fpv_offset_smooth, fpv_offset );
+ v3_add( fpv_offset, fpv_pos, fpv_pos );
+
+ /* angles */
+ v3f velocity_angles;
+ v3_lerp( cc->cam_velocity_smooth, localplayer.rb.v, 4.0f*vg.time_frame_delta,
+ cc->cam_velocity_smooth );
+
+ v3f velocity_local;
+ m3x3_mulv( localplayer.invbasis, cc->cam_velocity_smooth, velocity_local );
+ player_vector_angles( velocity_angles, velocity_local,
+ localplayer.cam_velocity_coefficient_smooth,
+ localplayer.cam_velocity_constant_smooth );
+
+ float inf_fpv = localplayer.cam_velocity_influence_smooth *
+ cc->camera_type_blend,
+ inf_tpv = localplayer.cam_velocity_influence_smooth *
+ (1.0f-cc->camera_type_blend);
+
+ camera_lerp_angles( localplayer.angles, velocity_angles,
+ inf_fpv,
+ localplayer.angles );
+
+ /*
+ * Third person camera
+ */
+
+ /* no idea what this technique is called, it acts like clamped position based
+ * on some derivative of where the final camera would end up ....
+ *
+ * it is done in the local basis then transformed back */
+
+ v3f future;
+ v3_muls( localplayer.rb.v, 0.4f*vg.time_frame_delta, future );
+ m3x3_mulv( localplayer.invbasis, future, future );
+
+ v3f camera_follow_dir =
+ { -sinf( localplayer.angles[0] ) * cosf( localplayer.angles[1] ),
+ sinf( localplayer.angles[1] ),
+ cosf( localplayer.angles[0] ) * cosf( localplayer.angles[1] ) };
+
+ v3f v0;
+ v3_sub( camera_follow_dir, future, v0 );