cam rework
[carveJwlIkooP6JGAAIwe30JlM.git] / player_common.c
index 69d35aba2c3edc60dd30ecdaea3870884ac342c4..3f8e7b11db12265c18f960de6076805572c95302 100644 (file)
@@ -3,7 +3,111 @@
 
 #include "player.h"
 
-void player_look( player_instance *player, v3f angles )
+VG_STATIC void player_vector_angles( v3f angles, v3f v, float C, float k )
+{
+   float yaw = atan2f( v[0], -v[2] ),
+       pitch = atan2f
+               ( 
+                   -v[1], 
+                   sqrtf
+                   (
+                     v[0]*v[0] + v[2]*v[2]
+                   )
+               ) * C + k;
+
+   angles[0] = yaw;
+   angles[1] = pitch;
+}
+
+VG_STATIC void player_camera_portal_correction( player_instance *player )
+{
+   if( player->gate_waiting )
+   {
+      /* construct plane equation for reciever gate */
+      v4f plane;
+      v3_copy( player->gate_waiting->recv_to_world[2], plane );
+      plane[3] = v3_dot( plane, player->gate_waiting->recv_to_world[3] );
+
+      /* check camera polarity */
+      if( v3_dot( player->cam.pos, plane ) < plane[3] ) 
+      {
+         vg_success( "Plane cleared\n" );
+         player_apply_transport_to_cam( player->gate_waiting->transport );
+         player->gate_waiting = NULL;
+      }
+      else
+      {
+         /* de-transform camera and player back */
+         m4x3f inverse;
+         m4x3_invert_affine( player->gate_waiting->transport, inverse );
+         m4x3_mulv( inverse, player->cam.pos, player->cam.pos );
+
+         /* TODO: Find robust method for this */
+         v3f fwd_dir = { cosf(player->cam.angles[0]),
+                         0.0f,
+                         sinf(player->cam.angles[0])};
+         m3x3_mulv( inverse, fwd_dir, fwd_dir );
+         player->cam.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] );
+
+         struct skeleton *sk = &player->playeravatar->sk;
+         skeleton_apply_transform( sk, inverse );
+      }
+   }
+}
+
+VG_STATIC void player__cam_iterate( player_instance *player )
+{
+   struct player_avatar *av = player->playeravatar;
+
+   v3_lerp( player->follow_pos, player->follow_pos_target, 
+            vg.frame_delta * 15.0f, player->follow_pos );
+   camera_lerp_angles( player->follow_angles, player->follow_angles_target,
+            vg.frame_delta * 18.0f, player->follow_angles );
+
+   /* Blending */
+   player->camera_type_blend = 
+      vg_lerpf( player->camera_type_blend, 
+                (player->camera_mode == k_cam_firstperson)? 1.0f: 0.0f,
+                5.0f * vg.frame_delta );
+   float t = player->camera_type_blend;
+
+   v3f p0, p1, a0, a1;
+   v3_lerp( player->follow_pos, player->override_pos, 
+            player->cam_position_override_strength, p1 );
+   camera_lerp_angles( player->follow_angles, player->override_angles,
+            player->cam_angles_override_strength, a1 );
+
+   v3_copy( player->fpv_pos, p0 );
+   v3_copy( player->fpv_angles, a0 );
+
+   v3_lerp( p0, p1, player->camera_type_blend, player->cam.pos );
+   camera_lerp_angles( a0, a1, player->camera_type_blend, player->cam.angles );
+
+   /* FIXME: cl_fov */
+   player->cam.fov = vg_lerpf( 118.0f, 90.0f, player->camera_type_blend );
+
+   /* portal transitions */
+   player_camera_portal_correction( player );
+}
+
+VG_STATIC void player_set_follower_subject( player_instance *player, 
+                                            v3f subj )
+{
+   v3f dir;
+   v3_sub( subj, player->follow_pos, dir );
+   
+   if( v3_length2( dir ) < 0.1f*0.1f )
+      v3_copy( (v3f){ 0.0f, 0.0f, 1.0f }, dir );   /* FIXME */
+   else
+      v3_normalize( dir );
+
+   dir[1] *= 0.0f;
+
+   v3_muladds( subj, dir, -2.0f, player->follow_pos_target );
+   player_vector_angles( player->follow_angles_target, dir, 1.0f, 0.2f );
+}
+
+VG_STATIC void player_look( player_instance *player, v3f angles )
 {
    angles[2] = 0.0f;
    v2_muladds( angles, vg.mouse_delta, 0.0025f, angles );