#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 );