1 #ifndef PLAYER_COMMON_C
2 #define PLAYER_COMMON_C
6 VG_STATIC
void player_vector_angles( v3f angles
, v3f v
, float C
, float k
)
8 float yaw
= atan2f( v
[0], -v
[2] ),
22 VG_STATIC
float player_get_heading_yaw( player_instance
*player
)
25 q_mulv( player
->rb
.q
, (v3f
){ 0.0f
,0.0f
,1.0f
}, xz
);
26 return atan2f( xz
[0], xz
[2] );
29 VG_STATIC
void player_camera_portal_correction( player_instance
*player
)
31 if( player
->gate_waiting
)
33 /* construct plane equation for reciever gate */
35 v3_copy( player
->gate_waiting
->recv_to_world
[2], plane
);
36 plane
[3] = v3_dot( plane
, player
->gate_waiting
->recv_to_world
[3] );
38 /* check camera polarity */
39 if( v3_dot( player
->cam
.pos
, plane
) < plane
[3] )
41 vg_success( "Plane cleared\n" );
42 player_apply_transport_to_cam( player
->gate_waiting
->transport
);
43 player
->gate_waiting
= NULL
;
47 /* de-transform camera and player back */
49 m4x3_invert_affine( player
->gate_waiting
->transport
, inverse
);
50 m4x3_mulv( inverse
, player
->cam
.pos
, player
->cam
.pos
);
52 /* TODO: Find robust method for this */
53 v3f fwd_dir
= { cosf(player
->cam
.angles
[0]),
55 sinf(player
->cam
.angles
[0])};
56 m3x3_mulv( inverse
, fwd_dir
, fwd_dir
);
57 player
->cam
.angles
[0] = atan2f( fwd_dir
[2], fwd_dir
[0] );
59 struct skeleton
*sk
= &player
->playeravatar
->sk
;
60 skeleton_apply_transform( sk
, inverse
);
65 VG_STATIC
void player__cam_iterate( player_instance
*player
)
67 struct player_avatar
*av
= player
->playeravatar
;
69 if( player
->subsystem
== k_player_subsystem_walk
)
71 v3_copy( (v3f
){-0.1f
,1.8f
,0.0f
}, player
->fpv_viewpoint
);
72 v3_copy( (v3f
){0.0f
,0.0f
,0.0f
}, player
->fpv_offset
);
73 v3_copy( (v3f
){0.0f
,1.4f
,0.0f
}, player
->tpv_offset
);
77 v3_copy( (v3f
){0.0f
,1.8f
,0.0f
}, player
->fpv_viewpoint
);
78 v3_copy( (v3f
){-0.35f
,0.0f
,0.0f
}, player
->fpv_offset
);
79 v3_copy( (v3f
){0.0f
,1.4f
,0.0f
}, player
->tpv_offset
);
82 player
->cam_velocity_constant
= 0.25f
;
83 player
->cam_velocity_coefficient
= 0.7f
;
87 player
->cam_velocity_influence_smooth
= vg_lerpf(
88 player
->cam_velocity_influence_smooth
,
89 player
->cam_velocity_influence
,
90 vg
.frame_delta
* 8.0f
);
92 player
->cam_velocity_coefficient_smooth
= vg_lerpf(
93 player
->cam_velocity_coefficient_smooth
,
94 player
->cam_velocity_coefficient
,
95 vg
.frame_delta
* 8.0f
);
97 player
->cam_velocity_constant_smooth
= vg_lerpf(
98 player
->cam_velocity_constant_smooth
,
99 player
->cam_velocity_constant
,
100 vg
.frame_delta
* 8.0f
);
102 player
->camera_type_blend
=
103 vg_lerpf( player
->camera_type_blend
,
104 (player
->camera_mode
== k_cam_firstperson
)? 1.0f
: 0.0f
,
105 5.0f
* vg
.frame_delta
);
107 v3_lerp( player
->fpv_viewpoint_smooth
, player
->fpv_viewpoint
,
108 vg
.frame_delta
* 8.0f
, player
->fpv_viewpoint_smooth
);
110 v3_lerp( player
->fpv_offset_smooth
, player
->fpv_offset
,
111 vg
.frame_delta
* 8.0f
, player
->fpv_offset_smooth
);
113 v3_lerp( player
->tpv_offset_smooth
, player
->tpv_offset
,
114 vg
.frame_delta
* 8.0f
, player
->tpv_offset_smooth
);
116 /* fov -- simple blend */
117 player
->cam
.fov
= vg_lerpf( 97.0f
, 118.0f
, player
->camera_type_blend
);
120 * first person camera
124 v3f fpv_pos
, fpv_offset
;
125 m4x3_mulv( av
->sk
.final_mtx
[ av
->id_head
-1 ],
126 player
->fpv_viewpoint_smooth
, fpv_pos
);
127 m3x3_mulv( player
->rb
.to_world
, player
->fpv_offset_smooth
, fpv_offset
);
128 v3_add( fpv_offset
, fpv_pos
, fpv_pos
);
132 v3_lerp( player
->cam_velocity_smooth
, player
->rb
.v
, 4.0f
*vg
.frame_delta
,
133 player
->cam_velocity_smooth
);
134 player_vector_angles( velocity_angles
, player
->cam_velocity_smooth
,
135 player
->cam_velocity_coefficient_smooth
,
136 player
->cam_velocity_constant_smooth
);
138 float inf_fpv
= player
->cam_velocity_influence_smooth
*
139 player
->camera_type_blend
,
140 inf_tpv
= player
->cam_velocity_influence_smooth
*
141 (1.0f
-player
->camera_type_blend
);
143 camera_lerp_angles( player
->angles
, velocity_angles
,
148 * Third person camera
151 /* no idea what this technique is called, it acts like clamped position based
152 * on some derivative of where the final camera would end up .... */
155 v3_muls( player
->rb
.v
, 0.4f
*vg
.frame_delta
, future
);
157 v3f camera_follow_dir
=
158 { -sinf( player
->angles
[0] ) * cosf( player
->angles
[1] ),
159 sinf( player
->angles
[1] ),
160 cosf( player
->angles
[0] ) * cosf( player
->angles
[1] ) };
163 v3_sub( camera_follow_dir
, future
, v0
);
166 v3_copy( player
->angles
, follow_angles
);
167 follow_angles
[0] = atan2f( -v0
[0], v0
[2] );
168 follow_angles
[1] = 0.3f
+ velocity_angles
[1] * 0.2f
;
172 -player
->cam_velocity_smooth
[1],
176 follow_angles
[1] = 0.3f
+ ya
;
178 camera_lerp_angles( player
->angles
, follow_angles
,
184 rb_extrapolate( &player
->rb
, pco
, pq
);
185 v3_lerp( player
->tpv_lpf
, pco
, 20.0f
*vg
.frame_delta
, player
->tpv_lpf
);
187 v3f tpv_pos
, tpv_offset
;
188 v3_muladds( player
->tpv_lpf
, camera_follow_dir
, 1.8f
, tpv_pos
);
189 q_mulv( pq
, player
->tpv_offset_smooth
, tpv_offset
);
190 v3_add( tpv_offset
, tpv_pos
, tpv_pos
);
191 v3_muladds( tpv_pos
, player
->cam_velocity_smooth
, -0.025f
, tpv_pos
);
198 v3_lerp( tpv_pos
, fpv_pos
, player
->camera_type_blend
, player
->cam
.pos
);
199 v3_copy( player
->angles
, player
->cam
.angles
);
205 v3_lerp( player
->follow_pos
, player
->follow_pos_target
,
206 vg
.frame_delta
* 15.0f
, player
->follow_pos
);
207 camera_lerp_angles( player
->follow_angles
, player
->follow_angles_target
,
208 vg
.frame_delta
* 18.0f
, player
->follow_angles
);
213 v3_lerp( player
->fpv_offset
, player
->fpv_offset_target
,
214 vg
.frame_delta
* 6.0f
, player
->fpv_offset
);
217 * Mix follow / override cameras
219 player
->camera_type_blend
=
220 vg_lerpf( player
->camera_type_blend
,
221 (player
->camera_mode
== k_cam_firstperson
)? 1.0f
: 0.0f
,
222 5.0f
* vg
.frame_delta
);
223 float t
= player
->camera_type_blend
;
226 v3_lerp( player
->follow_pos
, player
->override_pos
,
227 player
->cam_position_override_strength
, p1
);
228 camera_lerp_angles( player
->follow_angles
, player
->override_angles
,
229 player
->cam_angles_override_strength
, a1
);
231 v3_copy( player
->fpv_pos
, p0
);
232 v3_copy( player
->fpv_angles
, a0
);
234 v3_lerp( p0
, p1
, player
->camera_type_blend
, player
->cam
.pos
);
235 camera_lerp_angles( a0
, a1
, player
->camera_type_blend
, player
->cam
.angles
);
242 float Fd
= -player
->cam_land_punch_v
* k_cam_damp
,
243 Fs
= -player
->cam_land_punch
* k_cam_spring
;
244 player
->cam_land_punch
+= player
->cam_land_punch_v
* vg
.frame_delta
;
245 player
->cam_land_punch_v
+= ( Fd
+ Fs
) * vg
.frame_delta
;
246 player
->cam
.angles
[1] += player
->cam_land_punch
;
249 /* portal transitions */
250 player_camera_portal_correction( player
);
254 VG_STATIC
void player_set_follower_subject( player_instance
*player
,
258 v3_sub( subj
, player
->follow_pos
, dir
);
260 if( v3_length2( dir
) < 0.1f
*0.1f
)
261 v3_copy( (v3f
){ 0.0f
, 0.0f
, 1.0f
}, dir
); /* FIXME */
267 v3_muladds( subj
, dir
, -2.0f
, player
->follow_pos_target
);
268 player_vector_angles( player
->follow_angles_target
, dir
, 1.0f
, 0.2f
);
272 VG_STATIC
void player_look( player_instance
*player
, v3f angles
)
275 v2_muladds( angles
, vg
.mouse_delta
, 0.0025f
, angles
);
277 if( vg_input
.controller_should_use_trackpad_look
)
279 static v2f last_input
;
281 static v2f vel_smooth
;
283 v2f input
= { player
->input_js2h
->axis
.value
,
284 player
->input_js2v
->axis
.value
};
286 if( (v2_length2(last_input
) > 0.001f
) && (v2_length2(input
) > 0.001f
) )
288 v2_sub( input
, last_input
, vel
);
289 v2_muls( vel
, 1.0f
/vg
.time_delta
, vel
);
296 v2_lerp( vel_smooth
, vel
, vg
.time_delta
*8.0f
, vel_smooth
);
298 v2_muladds( angles
, vel_smooth
, vg
.time_delta
, angles
);
299 v2_copy( input
, last_input
);
303 angles
[0] += player
->input_js2h
->axis
.value
* vg
.time_delta
* 4.0f
;
304 angles
[1] += player
->input_js2v
->axis
.value
* vg
.time_delta
* 4.0f
;
307 angles
[1] = vg_clampf( angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
310 #endif /* PLAYER_COMMON_C */