1 #ifndef PLAYER_COMMON_C
2 #define PLAYER_COMMON_C
4 #include "ent_skateshop.h"
8 #include "vg/vg_perlin.h"
10 VG_STATIC
void player_vector_angles( v3f angles
, v3f v
, float C
, float k
)
12 float yaw
= atan2f( v
[0], -v
[2] ),
27 VG_STATIC
float player_get_heading_yaw( player_instance
*player
)
30 q_mulv( player
->rb
.q
, (v3f
){ 0.0f
,0.0f
,1.0f
}, xz
);
31 m3x3_mulv( player
->invbasis
, xz
, xz
);
32 return atan2f( xz
[0], xz
[2] );
35 VG_STATIC
void player_camera_portal_correction( player_instance
*player
)
37 if( player
->gate_waiting
){
38 /* construct plane equation for reciever gate */
40 q_mulv( player
->gate_waiting
->q
[1], (v3f
){0.0f
,0.0f
,1.0f
}, plane
);
41 plane
[3] = v3_dot( plane
, player
->gate_waiting
->co
[1] );
43 /* check camera polarity */
44 if( v3_dot( player
->cam
.pos
, plane
) < plane
[3] ) {
45 vg_success( "Plane cleared\n" );
46 player_apply_transport_to_cam( player
->gate_waiting
->transport
);
47 player
->gate_waiting
= NULL
;
48 player
->viewable_world
= world_current_instance();
51 /* de-transform camera and player back */
53 m4x3_invert_affine( player
->gate_waiting
->transport
, inverse
);
54 m4x3_mulv( inverse
, player
->cam
.pos
, player
->cam
.pos
);
56 struct skeleton
*sk
= &player
->playeravatar
->sk
;
57 skeleton_apply_transform( sk
, inverse
);
62 VG_STATIC
void player__cam_iterate( player_instance
*player
)
64 struct player_avatar
*av
= player
->playeravatar
;
66 if( player
->subsystem
== k_player_subsystem_walk
){
67 v3_copy( (v3f
){-0.1f
,1.8f
,0.0f
}, player
->fpv_viewpoint
);
68 v3_copy( (v3f
){0.0f
,0.0f
,0.0f
}, player
->fpv_offset
);
69 v3_copy( (v3f
){0.0f
,1.4f
,0.0f
}, player
->tpv_offset
);
72 v3_copy( (v3f
){-0.15f
,1.75f
,0.0f
}, player
->fpv_viewpoint
);
74 v3_copy( (v3f
){-0.35f
,0.0f
,0.0f
}, player
->fpv_offset
);
76 v3_copy( (v3f
){0.0f
,0.0f
,0.0f
}, player
->fpv_offset
);
77 v3_copy( (v3f
){0.0f
,1.4f
,0.0f
}, player
->tpv_offset
);
78 v3_add( player
->tpv_offset_extra
, 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
.time_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
.time_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
.time_frame_delta
* 8.0f
);
102 enum camera_mode target_mode
= player
->camera_mode
;
104 if( player
->subsystem
== k_player_subsystem_dead
)
105 target_mode
= k_cam_thirdperson
;
107 player
->camera_type_blend
=
108 vg_lerpf( player
->camera_type_blend
,
109 (target_mode
== k_cam_firstperson
)? 1.0f
: 0.0f
,
110 5.0f
* vg
.time_frame_delta
);
112 v3_lerp( player
->fpv_viewpoint_smooth
, player
->fpv_viewpoint
,
113 vg
.time_frame_delta
* 8.0f
, player
->fpv_viewpoint_smooth
);
115 v3_lerp( player
->fpv_offset_smooth
, player
->fpv_offset
,
116 vg
.time_frame_delta
* 8.0f
, player
->fpv_offset_smooth
);
118 v3_lerp( player
->tpv_offset_smooth
, player
->tpv_offset
,
119 vg
.time_frame_delta
* 8.0f
, player
->tpv_offset_smooth
);
121 /* fov -- simple blend */
122 float fov_skate
= vg_lerpf( 97.0f
, 135.0f
, k_fov
),
123 fov_walk
= vg_lerpf( 90.0f
, 110.0f
, k_fov
);
125 player
->cam
.fov
= vg_lerpf( fov_walk
, fov_skate
, player
->camera_type_blend
);
128 * first person camera
132 v3f fpv_pos
, fpv_offset
;
133 m4x3_mulv( av
->sk
.final_mtx
[ av
->id_head
-1 ],
134 player
->fpv_viewpoint_smooth
, fpv_pos
);
135 m3x3_mulv( player
->rb
.to_world
, player
->fpv_offset_smooth
, fpv_offset
);
136 v3_add( fpv_offset
, fpv_pos
, fpv_pos
);
140 v3_lerp( player
->cam_velocity_smooth
, player
->rb
.v
, 4.0f
*vg
.time_frame_delta
,
141 player
->cam_velocity_smooth
);
144 m3x3_mulv( player
->invbasis
, player
->cam_velocity_smooth
, velocity_local
);
145 player_vector_angles( velocity_angles
, velocity_local
,
146 player
->cam_velocity_coefficient_smooth
,
147 player
->cam_velocity_constant_smooth
);
149 float inf_fpv
= player
->cam_velocity_influence_smooth
*
150 player
->camera_type_blend
,
151 inf_tpv
= player
->cam_velocity_influence_smooth
*
152 (1.0f
-player
->camera_type_blend
);
154 camera_lerp_angles( player
->angles
, velocity_angles
,
159 * Third person camera
162 /* no idea what this technique is called, it acts like clamped position based
163 * on some derivative of where the final camera would end up ....
165 * it is done in the local basis then transformed back */
168 v3_muls( player
->rb
.v
, 0.4f
*vg
.time_frame_delta
, future
);
169 m3x3_mulv( player
->invbasis
, future
, future
);
171 v3f camera_follow_dir
=
172 { -sinf( player
->angles
[0] ) * cosf( player
->angles
[1] ),
173 sinf( player
->angles
[1] ),
174 cosf( player
->angles
[0] ) * cosf( player
->angles
[1] ) };
177 v3_sub( camera_follow_dir
, future
, v0
);
180 v3_copy( player
->angles
, follow_angles
);
181 follow_angles
[0] = atan2f( -v0
[0], v0
[2] );
182 follow_angles
[1] = 0.3f
+ velocity_angles
[1] * 0.2f
;
184 float ya
= atan2f( -velocity_local
[1], 30.0f
);
186 follow_angles
[1] = 0.3f
+ ya
;
187 camera_lerp_angles( player
->angles
, follow_angles
,
193 rb_extrapolate( &player
->rb
, pco
, pq
);
194 v3_lerp( player
->tpv_lpf
, pco
, 20.0f
*vg
.time_frame_delta
, player
->tpv_lpf
);
196 /* now move into world */
197 v3f tpv_pos
, tpv_offset
, tpv_origin
;
200 q_mulv( pq
, player
->tpv_offset_smooth
, tpv_origin
);
201 v3_add( tpv_origin
, player
->tpv_lpf
, tpv_origin
);
204 m3x3_mulv( player
->basis
, camera_follow_dir
, camera_follow_dir
);
205 v3_muls( camera_follow_dir
, 1.8f
, tpv_offset
);
206 v3_muladds( tpv_offset
, player
->cam_velocity_smooth
, -0.025f
, tpv_offset
);
208 v3_add( tpv_origin
, tpv_offset
, tpv_pos
);
210 if( spherecast_world( world_current_instance(), tpv_origin
, tpv_pos
,
211 0.2f
, &t
, n
) != -1 ){
212 v3_lerp( tpv_origin
, tpv_pos
, t
, tpv_pos
);
218 v3_lerp( tpv_pos
, fpv_pos
, player
->camera_type_blend
, player
->cam
.pos
);
219 v3_copy( player
->angles
, player
->cam
.angles
);
222 f32 speed
= v3_length(player
->rb
.v
),
223 strength
= k_cam_shake_strength
* speed
;
224 player
->cam_trackshake
+= speed
*k_cam_shake_trackspeed
*vg
.time_frame_delta
;
226 v2f rnd
= {perlin1d( player
->cam_trackshake
, 1.0f
, 4, 20 ),
227 perlin1d( player
->cam_trackshake
, 1.0f
, 4, 63 ) };
228 v2_muladds( player
->cam
.angles
, rnd
, strength
, player
->cam
.angles
);
231 v3_muls( player
->cam_land_punch_v
, -k_cam_damp
, Fd
);
232 v3_muls( player
->cam_land_punch
, -k_cam_spring
, Fs
);
233 v3_muladds( player
->cam_land_punch
, player
->cam_land_punch_v
,
234 vg
.time_frame_delta
, player
->cam_land_punch
);
236 v3_muladds( player
->cam_land_punch_v
, F
, vg
.time_frame_delta
,
237 player
->cam_land_punch_v
);
238 v3_add( player
->cam_land_punch
, player
->cam
.pos
, player
->cam
.pos
);
240 /* override camera */
241 player
->cam
.angles
[0] =
242 vg_alerpf( player
->cam
.angles
[0], player
->cam_override_angles
[0],
243 player
->cam_override_strength
);
244 player
->cam
.angles
[1] =
245 vg_lerpf ( player
->cam
.angles
[1], player
->cam_override_angles
[1],
246 player
->cam_override_strength
);
247 v3_lerp( player
->cam
.pos
, player
->cam_override_pos
,
248 player
->cam_override_strength
, player
->cam
.pos
);
249 player
->cam
.fov
= vg_lerpf( player
->cam
.fov
, player
->cam_override_fov
,
250 player
->cam_override_strength
);
253 if( k_cinema
>= 0.0001f
){
254 ent_camera
*cam
= NULL
;
255 f32 min_dist
= k_cinema
;
257 world_instance
*world
= player
->viewable_world
;
258 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_camera
); i
++ ){
259 ent_camera
*c
= mdl_arritm(&world
->ent_camera
,i
);
261 f32 dist
= v3_dist( c
->transform
.co
, player
->rb
.co
);
263 if( dist
< min_dist
){
270 player
->cam
.fov
= cam
->fov
;
271 v3_copy( cam
->transform
.co
, player
->cam
.pos
);
274 mdl_transform_vector( &cam
->transform
, (v3f
){0.0f
,-1.0f
,0.0f
}, v0
);
275 else v3_sub( player
->rb
.co
, cam
->transform
.co
, v0
);
276 m3x3_mulv( player
->invbasis
, v0
, v0
);
277 player_vector_angles( player
->cam
.angles
, v0
, 1.0f
, 0.0f
);
281 /* portal transitions */
282 player_camera_portal_correction( player
);
285 VG_STATIC
void player_look( player_instance
*player
, v3f angles
)
287 if( vg_ui
.wants_mouse
) return;
289 float sensitivity
= 1.0f
-menu
.factive
;
294 v2_copy( vg
.mouse_delta
, mouse_input
);
295 if( k_invert_y
) mouse_input
[1] *= -1.0f
;
296 v2_muladds( angles
, mouse_input
, 0.0025f
* sensitivity
, angles
);
299 joystick_state( k_srjoystick_look
, jlook
);
301 angles
[0] += jlook
[0] * vg
.time_delta
* 4.0f
* sensitivity
;
302 float input_y
= jlook
[1] * vg
.time_delta
* 4.0f
;
303 if( k_invert_y
) input_y
*= -1.0f
;
305 angles
[1] += input_y
* sensitivity
;
306 angles
[1] = vg_clampf( angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
309 #endif /* PLAYER_COMMON_C */