+ /* Update camera matrices */
+ m4x3_identity( player.camera );
+ m4x3_rotate_y( player.camera, -player.angles[0] );
+ m4x3_rotate_x( player.camera, -player.angles[1] );
+ v3_copy( player.camera_pos, player.camera[3] );
+ m4x3_invert_affine( player.camera, player.camera_inverse );
+}
+
+static void player_animate_death_cam(void)
+{
+ v3f delta;
+ v3f head_pos;
+ v3_copy( player.mdl.ragdoll[k_chpart_head].co, head_pos );
+
+ v3_sub( head_pos, player.camera_pos, delta );
+ v3_normalize( delta );
+
+ v3f follow_pos;
+ v3_muladds( head_pos, delta, -2.5f, follow_pos );
+ v3_lerp( player.camera_pos, follow_pos, 0.1f, player.camera_pos );
+
+ /*
+ * Make sure the camera stays above the ground
+ */
+ v3f min_height = {0.0f,1.0f,0.0f};
+
+ v3f sample;
+ v3_add( player.camera_pos, min_height, sample );
+ ray_hit hit;
+ hit.dist = min_height[1]*2.0f;
+
+ if( ray_world( sample, (v3f){0.0f,-1.0f,0.0f}, &hit ))
+ v3_add( hit.pos, min_height, player.camera_pos );
+
+ player.camera_pos[1] =
+ vg_maxf( wrender.height + 2.0f, player.camera_pos[1] );
+
+ player.angles[0] = atan2f( delta[0], -delta[2] );
+ player.angles[1] = -asinf( delta[1] );
+}
+
+static void player_animate_camera(void)
+{
+ v3f offs = { -0.29f, 0.08f, 0.0f };
+ m3x3_mulv( player.rb.to_world, offs, offs );
+ m4x3_mulv( player.rb.to_world, player.mdl.ik_body.end, player.camera_pos );
+ v3_add( offs, player.camera_pos, player.camera_pos );
+
+ /* Look angles */
+ v3_lerp( player.vl, player.rb.v, 0.05f, player.vl );
+
+ float yaw = atan2f( player.vl[0], -player.vl[2] ),
+ pitch = atan2f( -player.vl[1],
+ sqrtf(
+ player.vl[0]*player.vl[0] + player.vl[2]*player.vl[2]
+ )) * 0.7f;
+
+ player.angles[0] = yaw;
+ player.angles[1] = pitch + 0.30f;
+
+ /* Camera shake */
+ static v2f shake_damp = {0.0f,0.0f};
+ v2f shake = { vg_randf()-0.5f, vg_randf()-0.5f };
+ v2_muls( shake, v3_length(player.rb.v)*0.3f
+ * (1.0f+fabsf(player.slip)), shake);
+
+ v2_lerp( shake_damp, shake, 0.01f, shake_damp );
+ shake_damp[0] *= 0.2f;
+
+ v2_muladds( player.angles, shake_damp, 0.1f, player.angles );
+}
+
+/*
+ * Audio
+ */
+static void player_audio(void)
+{
+ float speed = vg_minf(v3_length( player.rb.v )*0.1f,1.0f),
+ attn = v3_dist( player.rb.co, player.camera[3] )+1.0f;
+ attn = (1.0f/(attn*attn)) * speed;
+
+ static float air = 0.0f;
+ air = vg_lerpf(air, player.in_air? 1.0f: 0.0f, 0.7f);
+
+ v3f ears = { 1.0f,0.0f,0.0f };
+ v3f delta;
+
+ v3_sub( player.rb.co, player.camera[3], delta );
+ v3_normalize( delta );
+ m3x3_mulv( player.camera, ears, ears );
+
+ float pan = v3_dot( ears, delta );
+ audio_player0.pan = pan;
+ audio_player1.pan = pan;
+ audio_player2.pan = pan;