moved some stuff
[carveJwlIkooP6JGAAIwe30JlM.git] / player.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #ifndef PLAYER_H
6 #define PLAYER_H
7
8 #define PLAYER_REWIND_FRAMES 60*4
9
10 #include "audio.h"
11 #include "common.h"
12 #include "world.h"
13 #include "skeleton.h"
14 #include "bvh.h"
15
16 static float
17 k_walkspeed = 20.0f, /* no longer used */
18 k_runspeed = 20.0f,
19 k_board_radius = 0.3f,
20 k_board_length = 0.45f,
21 k_board_allowance = 0.04f,
22 //k_friction_lat = 8.8f,
23 k_friction_lat = 12.0f,
24 k_friction_resistance = 0.01f,
25 k_max_push_speed = 16.0f,
26 k_push_accel = 10.0f,
27 k_push_cycle_rate = 8.0f,
28 k_steer_ground = 2.5f,
29 k_steer_air = 3.6f,
30 k_steer_air_lerp = 0.3f,
31 k_pump_force = 0.0f,
32 k_downforce = 5.0f,
33 k_walk_downforce = 8.0f,
34 k_jump_charge_speed = (1.0f/1.0f),
35 k_jump_force = 5.0f,
36 k_pitch_limit = 1.5f,
37 k_look_speed = 2.0f,
38 k_walk_accel = 150.0f,
39 k_walk_friction = 8.0f;
40
41 static int freecam = 0;
42 static int walk_grid_iterations = 1;
43 static float fc_speed = 10.0f;
44
45 /*
46 * -----------------------------------------------------------------------------
47 * Memory
48 * -----------------------------------------------------------------------------
49 */
50
51 static struct gplayer
52 {
53 /* Physics */
54 rigidbody collide_front, collide_back;
55
56 struct player_phys
57 {
58 rigidbody rb, rb_gate_frame;
59 float iY, siY; /* Yaw inertia */
60
61 v3f a, v_last, m, bob, vl;
62
63 /* Utility */
64 float vswitch, slip, slip_last,
65 reverse;
66
67 float grab, jump, pushing, push_time;
68 double start_push;
69 int in_air, on_board, jump_charge, jump_dir;
70
71 m3x3f vr,vr_pstep;
72 }
73 phys,
74 phys_gate_frame;
75
76 m4x3f visual_transform,
77 inv_visual_transform;
78
79 int is_dead, death_tick_allowance, rewinding;
80 int rewind_sound_wait;
81
82 v3f land_target;
83 v3f land_target_log[22];
84 u32 land_target_colours[22];
85 int land_log_count;
86
87 v3f handl_target, handr_target,
88 handl, handr;
89
90 /* Camera */
91 float air_blend;
92 float air_time;
93
94 v3f camera_pos, smooth_localcam;
95 v2f angles;
96
97 struct rewind_frame
98 {
99 v3f pos;
100 v2f ang;
101 }
102 *rewind_buffer;
103 u32 rewind_incrementer,
104 rewind_length;
105
106 float rewind_time, rewind_total_length, rewind_predicted_time;
107 double diag_rewind_start, diag_rewind_time;
108 float dist_accum;
109
110 /* animation */
111 double jump_time;
112 float fslide,
113 fdirz, fdirx,
114 fstand,
115 ffly,
116 fpush,
117 fairdir,
118 fsetup,
119 walk_timer,
120 fjump,
121 fonboard,
122 frun;
123
124 float walk;
125 int step_phase;
126
127 /* player model */
128 struct player_model
129 {
130 glmesh mesh;
131 struct skeleton sk;
132 struct skeleton_anim *anim_stand,
133 *anim_highg,
134 *anim_slide,
135 *anim_air,
136 *anim_push, *anim_push_reverse,
137 *anim_ollie, *anim_ollie_reverse,
138 *anim_grabs, *anim_stop,
139 *anim_walk, *anim_run, *anim_idle,
140 *anim_jump;
141
142 u32 id_hip,
143 id_ik_hand_l,
144 id_ik_hand_r,
145 id_ik_elbow_l,
146 id_ik_elbow_r,
147 id_head;
148
149 v3f cam_pos;
150
151 struct ragdoll_part
152 {
153 u32 bone_id;
154 v3f offset;
155
156 u32 use_limits;
157 v3f limits[2];
158
159 rigidbody rb;
160 u32 parent;
161 }
162 *ragdoll;
163 u32 ragdoll_count;
164
165 int shoes[2];
166 }
167 mdl;
168 }
169 player =
170 {
171 .collide_front = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f },
172 .collide_back = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f }
173 };
174
175 /*
176 * API
177 */
178 static float *player_get_pos(void);
179 static void player_kill(void);
180 static float *player_cam_pos(void);
181 static void player_save_frame(void);
182 static void player_restore_frame(void);
183 static void player_save_rewind_frame(void);
184
185 /*
186 * Submodules
187 */
188 #include "player_physics.h"
189 #include "player_ragdoll.h"
190 #include "player_model.h"
191 #include "player_animation.h"
192 #include "player_audio.h"
193
194 /*
195 * -----------------------------------------------------------------------------
196 * Events
197 * -----------------------------------------------------------------------------
198 */
199
200 static void player_init(void) /* 1 */
201 {
202 rb_init( &player.phys.rb );
203 rb_init( &player.collide_front );
204 rb_init( &player.collide_back );
205
206 vg_convar_push( (struct vg_convar){
207 .name = "walk_speed",
208 .data = &k_walkspeed,
209 .data_type = k_convar_dtype_f32,
210 .opt_f32 = { .clamp = 0 },
211 .persistent = 1
212 });
213
214 vg_convar_push( (struct vg_convar){
215 .name = "run_speed",
216 .data = &k_runspeed,
217 .data_type = k_convar_dtype_f32,
218 .opt_f32 = { .clamp = 0 },
219 .persistent = 1
220 });
221
222 vg_convar_push( (struct vg_convar){
223 .name = "walk_accel",
224 .data = &k_walk_accel,
225 .data_type = k_convar_dtype_f32,
226 .opt_f32 = { .clamp = 0 },
227 .persistent = 1
228 });
229
230 vg_convar_push( (struct vg_convar){
231 .name = "fc",
232 .data = &freecam,
233 .data_type = k_convar_dtype_i32,
234 .opt_i32 = { .min=0, .max=1, .clamp=1 },
235 .persistent = 1
236 });
237
238 vg_convar_push( (struct vg_convar){
239 .name = "fcs",
240 .data = &fc_speed,
241 .data_type = k_convar_dtype_f32,
242 .opt_f32 = { .clamp = 0 },
243 .persistent = 1
244 });
245
246 vg_function_push( (struct vg_cmd){
247 .name = "reset",
248 .function = reset_player
249 });
250
251 player.rewind_length = 0;
252 player.rewind_buffer = vg_alloc( sizeof(struct rewind_frame)
253 * PLAYER_REWIND_FRAMES );
254
255 /* other systems */
256 vg_loader_highwater( player_model_init, player_model_free, NULL );
257 }
258
259 static void player_save_rewind_frame(void)
260 {
261 if( player.rewind_length < PLAYER_REWIND_FRAMES )
262 {
263 struct rewind_frame *fr =
264 &player.rewind_buffer[ player.rewind_length ++ ];
265
266 v2_copy( player.angles, fr->ang );
267 v3_copy( player.camera_pos, fr->pos );
268
269 player.rewind_incrementer = 0;
270
271 if( player.rewind_length > 1 )
272 {
273 player.rewind_total_length +=
274 v3_dist( player.rewind_buffer[player.rewind_length-1].pos,
275 player.rewind_buffer[player.rewind_length-2].pos );
276 }
277 }
278 }
279
280 /* Deal with input etc */
281 static void player_update_pre(void)
282 {
283 struct player_phys *phys = &player.phys;
284
285 if( player.rewinding )
286 {
287 return;
288 }
289
290 if( vg_get_button_down( "reset" ) )
291 {
292 double delta = world_routes.time - world_routes.last_use;
293
294 if( delta <= RESET_MAX_TIME )
295 {
296 player.rewinding = 1;
297 player.rewind_sound_wait = 1;
298 player.rewind_time = (float)player.rewind_length - 0.0001f;
299 player_save_rewind_frame();
300 audio_lock();
301 audio_play_oneshot( &audio_rewind[0], 1.0f );
302 audio_unlock();
303
304 /* based on analytical testing. DONT CHANGE!
305 *
306 * time taken: y = (x^(4/5)) * 74.5
307 * inverse : x = (2/149)^(4/5) * y^(4/5)
308 */
309
310 float constant = powf( 2.0f/149.0f, 4.0f/5.0f ),
311 curve = powf( player.rewind_total_length, 4.0f/5.0f );
312
313 player.rewind_predicted_time = constant * curve;
314 player.diag_rewind_start = vg.time;
315 player.diag_rewind_time = player.rewind_time;
316
317 player.is_dead = 0;
318 player.death_tick_allowance = 30;
319 player_restore_frame();
320
321 if( !phys->on_board )
322 {
323 player.angles[0] = atan2f( -phys->rb.forward[2],
324 -phys->rb.forward[0] );
325 }
326
327 player.mdl.shoes[0] = 1;
328 player.mdl.shoes[1] = 1;
329
330 world_routes_notify_reset();
331
332 /* apply 1 frame of movement */
333 player_do_motion();
334 }
335 }
336
337 if( vg_get_button_down( "switchmode" ) )
338 {
339 phys->on_board ^= 0x1;
340
341 audio_lock();
342 if( phys->on_board )
343 {
344 v3_muladds( phys->rb.v, phys->rb.forward, 0.2f, phys->rb.v );
345 audio_play_oneshot( &audio_lands[6], 1.0f );
346 }
347 else
348 {
349 audio_play_oneshot( &audio_lands[5], 1.0f );
350 }
351
352 audio_unlock();
353 }
354 }
355
356 static void player_update_fixed(void) /* 2 */
357 {
358 if( player.rewinding )
359 return;
360
361 if( player.death_tick_allowance )
362 player.death_tick_allowance --;
363
364 struct player_phys *phys = &player.phys;
365
366 if( player.is_dead )
367 {
368 player_ragdoll_iter();
369 }
370 else
371 {
372 player.rewind_incrementer ++;
373
374 if( player.rewind_incrementer > (u32)(0.25/VG_TIMESTEP_FIXED) )
375 {
376 player_save_rewind_frame();
377 }
378
379 player_do_motion();
380 }
381 }
382
383 static void player_update_post(void)
384 {
385 for( int i=0; i<player.land_log_count; i++ )
386 vg_line_cross( player.land_target_log[i],
387 player.land_target_colours[i], 0.25f);
388
389 if( player.is_dead )
390 {
391 player_debug_ragdoll();
392
393 if( !freecam )
394 player_animate_death_cam();
395 }
396 else
397 {
398 player_animate();
399
400 if( !freecam )
401 player_animate_camera();
402 }
403
404 if( freecam )
405 player_freecam();
406
407
408 /* CAMERA POSITIONING: LAYER 0 */
409 v2_copy( player.angles, camera_angles );
410 v3_copy( player.camera_pos, camera_pos );
411
412 if( player.rewinding )
413 {
414 if( player.rewind_time <= 0.0f )
415 {
416 double taken = vg.time - player.diag_rewind_start;
417 vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
418 taken, player.diag_rewind_time,
419 player.rewind_total_length );
420
421 player.rewinding = 0;
422 player.rewind_length = 1;
423 player.rewind_total_length = 0.0f;
424 player.rewind_incrementer = 0;
425 world.sky_target_rate = 1.0;
426 }
427 else
428 {
429 world.sky_target_rate = -100.0;
430 assert( player.rewind_length > 0 );
431
432 v2f override_angles;
433 v3f override_pos;
434
435 float budget = vg.time_delta,
436 overall_length = player.rewind_length;
437
438 world_routes_rollback_time( player.rewind_time / overall_length );
439
440 for( int i=0; (i<10)&&(player.rewind_time>0.0f)&&(budget>0.0f); i ++ )
441 {
442 /* Interpolate frames */
443 int i0 = floorf( player.rewind_time ),
444 i1 = VG_MIN( i0+1, player.rewind_length-1 );
445
446 struct rewind_frame *fr = &player.rewind_buffer[i0],
447 *fr1 = &player.rewind_buffer[i1];
448
449 float dist = vg_maxf( v3_dist( fr->pos, fr1->pos ), 0.001f ),
450 subl = vg_fractf( player.rewind_time ) + 0.001f,
451
452 sramp= 3.0f-(1.0f/(0.4f+0.4f*player.rewind_time)),
453 speed = sramp*28.0f + 0.5f*player.rewind_time,
454 mod = speed * (budget / dist),
455
456 advl = vg_minf( mod, subl ),
457 advt = (advl / mod) * budget;
458
459 player.dist_accum += speed * advt;
460 player.rewind_time -= advl;
461 budget -= advt;
462 }
463
464 #if 0
465 if( player.dist_accum >= 5.0f )
466 {
467 audio_lock();
468 audio_player_playclip( &audio_rewind_player, &audio_rewind[4] );
469 audio_unlock();
470
471 player.dist_accum -= 5.0f;
472 }
473 #endif
474
475 player.rewind_time = vg_maxf( 0.0f, player.rewind_time );
476
477 float current_time = vg.time - player.diag_rewind_start,
478 remaining = player.rewind_predicted_time - current_time;
479
480 if( player.rewind_sound_wait )
481 {
482 if( player.rewind_predicted_time >= 6.5f )
483 {
484 if( remaining <= 6.5f )
485 {
486 audio_lock();
487 audio_play_oneshot( &audio_rewind[3], 1.0f );
488 audio_unlock();
489 player.rewind_sound_wait = 0;
490 }
491 }
492 else if( player.rewind_predicted_time >= 2.5f )
493 {
494 if( remaining <= 2.5f )
495 {
496 audio_lock();
497 audio_play_oneshot( &audio_rewind[2], 1.0f );
498 audio_unlock();
499 player.rewind_sound_wait = 0;
500 }
501 }
502 else if( player.rewind_predicted_time >= 1.5f )
503 {
504 if( remaining <= 1.5f )
505 {
506 audio_lock();
507 audio_play_oneshot( &audio_rewind[1], 1.0f );
508 audio_unlock();
509 player.rewind_sound_wait = 0;
510 }
511 }
512
513
514 }
515
516 int i0 = floorf( player.rewind_time ),
517 i1 = VG_MIN( i0+1, player.rewind_length-1 );
518
519 struct rewind_frame *fr = &player.rewind_buffer[i0],
520 *fr1 = &player.rewind_buffer[i1];
521
522 float sub = vg_fractf(player.rewind_time);
523
524 v3_lerp( fr->pos, fr1->pos, sub, override_pos );
525 override_angles[0] = vg_alerpf( fr->ang[0], fr1->ang[0], sub );
526 override_angles[1] = vg_lerpf ( fr->ang[1], fr1->ang[1], sub );
527
528 /* CAMERA POSITIONING: LAYER 1 */
529 float blend = (4.0f-player.rewind_time) * 0.25f,
530 c = vg_clampf( blend, 0.0f, 1.0f );
531
532 camera_angles[0] = vg_alerpf(override_angles[0], player.angles[0], c);
533 camera_angles[1] = vg_lerpf (override_angles[1], player.angles[1], c);
534 v3_lerp( override_pos, player.camera_pos, c, camera_pos );
535 }
536 }
537
538 camera_update();
539 player_audio();
540 }
541
542 static void draw_player( m4x3f cam )
543 {
544 if( player.is_dead )
545 player_model_copy_ragdoll();
546
547 shader_viewchar_use();
548 vg_tex2d_bind( &tex_characters, 0 );
549 shader_viewchar_uTexMain( 0 );
550 shader_viewchar_uCamera( cam[3] );
551 shader_viewchar_uPv( vg.pv );
552 shader_link_standard_ub( _shader_viewchar.id, 2 );
553 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms,
554 player.mdl.sk.bone_count,
555 0,
556 (float *)player.mdl.sk.final_mtx );
557
558 mesh_bind( &player.mdl.mesh );
559 mesh_draw( &player.mdl.mesh );
560 }
561
562 /*
563 * -----------------------------------------------------------------------------
564 * API implementation
565 * -----------------------------------------------------------------------------
566 */
567
568 static float *player_get_pos(void)
569 {
570 return player.phys.rb.co;
571 }
572
573 static void player_kill(void)
574 {
575 if( player.death_tick_allowance == 0 )
576 {
577 player.is_dead = 1;
578 player_ragdoll_copy_model( player.phys.rb.v );
579 }
580 }
581
582 static float *player_cam_pos(void)
583 {
584 return player.camera_pos;
585 }
586
587
588 #endif /* PLAYER_H */