+ else{
+ v3_copy( (v3f){-0.15f,1.75f,0.0f}, cc->fpv_viewpoint );
+ v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
+
+ f32 h = vg_lerpf( 0.4f, 1.4f, k_cam_height );
+ v3_copy( (v3f){0.0f,h,0.0f}, cc->tpv_offset );
+ v3_add( cc->tpv_offset_extra, cc->tpv_offset, cc->tpv_offset );
+ }
+
+ localplayer.cam_velocity_constant = 0.25f;
+ localplayer.cam_velocity_coefficient = 0.7f;
+
+ /* lerping */
+
+ if( localplayer.cam_dist_smooth == 0.0f ){
+ localplayer.cam_dist_smooth = localplayer.cam_dist;
+ }
+ else {
+ localplayer.cam_dist_smooth = vg_lerpf(
+ localplayer.cam_dist_smooth,
+ localplayer.cam_dist,
+ vg.time_frame_delta * 8.0f );
+ }
+
+ localplayer.cam_velocity_influence_smooth = vg_lerpf(
+ localplayer.cam_velocity_influence_smooth,
+ localplayer.cam_velocity_influence,
+ vg.time_frame_delta * 8.0f );
+
+ localplayer.cam_velocity_coefficient_smooth = vg_lerpf(
+ localplayer.cam_velocity_coefficient_smooth,
+ localplayer.cam_velocity_coefficient,
+ vg.time_frame_delta * 8.0f );
+
+ localplayer.cam_velocity_constant_smooth = vg_lerpf(
+ localplayer.cam_velocity_constant_smooth,
+ localplayer.cam_velocity_constant,
+ vg.time_frame_delta * 8.0f );
+
+ enum camera_mode target_mode = cc->camera_mode;
+
+ if( localplayer.subsystem == k_player_subsystem_dead )
+ target_mode = k_cam_thirdperson;
+
+ cc->camera_type_blend =
+ vg_lerpf( cc->camera_type_blend,
+ (target_mode == k_cam_firstperson)? 1.0f: 0.0f,
+ 5.0f * vg.time_frame_delta );
+
+ v3_lerp( cc->fpv_viewpoint_smooth, cc->fpv_viewpoint,
+ vg.time_frame_delta * 8.0f, cc->fpv_viewpoint_smooth );
+
+ v3_lerp( cc->fpv_offset_smooth, cc->fpv_offset,
+ vg.time_frame_delta * 8.0f, cc->fpv_offset_smooth );
+
+ 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[ localplayer.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 );
+
+ v3_angles( cc->cam_velocity_smooth, velocity_angles );
+ velocity_angles[1] *= localplayer.cam_velocity_coefficient_smooth;
+ velocity_angles[1] += 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);
+
+ vg_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 );
+
+ 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 );
+
+ v3f follow_angles;
+ v3_copy( localplayer.angles, follow_angles );
+ follow_angles[0] = atan2f( -v0[0], v0[2] );
+ follow_angles[1] = 0.3f + velocity_angles[1] * 0.2f;
+
+ float ya = atan2f( -cc->cam_velocity_smooth[1], 30.0f );
+
+ follow_angles[1] = 0.3f + ya;
+ vg_camera_lerp_angles( localplayer.angles, follow_angles,
+ inf_tpv,
+ localplayer.angles );
+
+ v3f pco;
+ v4f pq;
+ rb_extrapolate( &localplayer.rb, pco, pq );
+ v3_muladds( pco, localplayer.holdout_pose.root_co,
+ localplayer.holdout_time, pco );
+ v3_lerp( cc->tpv_lpf, pco, 20.0f*vg.time_frame_delta, cc->tpv_lpf );
+
+ /* now move into world */
+ v3f tpv_pos, tpv_offset, tpv_origin;
+
+ /* TODO: whats up with CC and not CC but both sets of variables are doing
+ * the same ideas just saved in different places?
+ */
+ /* origin */
+ q_mulv( pq, cc->tpv_offset_smooth, tpv_origin );
+ v3_add( tpv_origin, cc->tpv_lpf, tpv_origin );
+
+ /* offset */
+ v3_muls( camera_follow_dir, localplayer.cam_dist_smooth, tpv_offset );
+ v3_muladds( tpv_offset, cc->cam_velocity_smooth, -0.025f, tpv_offset );
+
+ v3_add( tpv_origin, tpv_offset, tpv_pos );
+
+#if 0
+ if( localplayer.subsystem == k_player_subsystem_walk )