holdout poses
[carveJwlIkooP6JGAAIwe30JlM.git] / player.h
1 #ifndef PLAYER_H
2 #define PLAYER_H
3
4 #include "player_api.h"
5
6 #include "player_common.h"
7 #include "player_walk.h"
8 #include "player_skate.h"
9 //#include "player_dead.h"
10
11 struct player_instance
12 {
13 /* transform definition */
14 rigidbody rb;
15 v3f angles;
16
17 /*
18 * Camera management
19 * ---------------------------
20 */
21 camera cam; /* output final camera */
22
23 enum camera_mode
24 {
25 k_cam_firstperson = 0,
26 k_cam_thirdperson = 1
27 }
28 camera_mode;
29 float camera_type_blend;
30
31
32 v3f fpv_offset, /* expressed relative to rigidbody */
33 tpv_offset,
34 fpv_viewpoint, /* expressed relative to neck bone inverse final */
35 fpv_offset_smooth,
36 fpv_viewpoint_smooth,
37 tpv_offset_smooth,
38 tpv_lpf,
39 cam_velocity_smooth;
40
41 float cam_velocity_influence,
42 cam_velocity_coefficient,
43 cam_velocity_constant,
44 cam_velocity_coefficient_smooth,
45 cam_velocity_constant_smooth,
46 cam_velocity_influence_smooth,
47 cam_land_punch,
48 cam_land_punch_v;
49
50 teleport_gate *gate_waiting;
51
52 /*
53 * Input
54 * --------------------------------
55 */
56 struct input_binding *input_js1h,
57 *input_js1v,
58 *input_js2h,
59 *input_js2v,
60 *input_jump,
61 *input_push,
62 *input_walk,
63 *input_walkh,
64 *input_walkv,
65 *input_use,
66 *input_reset,
67 *input_grab,
68 *input_camera;
69
70 /*
71 * Animation
72 * --------------------------------------------------
73 */
74
75 struct player_avatar *playeravatar;
76 glmesh *playermesh;
77 struct player_ragdoll ragdoll;
78 vg_tex2d *playertex;
79
80 player_pose holdout_pose;
81 float holdout_time;
82
83 /*
84 * Subsystems
85 * -------------------------------------------------
86 */
87
88 enum player_subsystem
89 {
90 k_player_subsystem_walk = 0,
91 k_player_subsystem_skate = 1,
92 k_player_subsystem_dead = 2
93 }
94 subsystem;
95
96 struct player_skate _skate;
97 struct player_walk _walk;
98 //struct player_dead _dead;
99 };
100
101 /*
102 * Gameloop tables
103 * ---------------------------------------------------------
104 */
105
106 VG_STATIC
107 void (*_player_bind[])( player_instance *player ) =
108 {
109 player__walk_bind,
110 player__skate_bind,
111 NULL
112 };
113
114 VG_STATIC
115 void (*_player_reset[])( player_instance *player, struct respawn_point *rp ) =
116 {
117 NULL,
118 player__skate_reset,
119 NULL
120 };
121
122 VG_STATIC
123 void (*_player_pre_update[])( player_instance *player ) =
124 {
125 player__walk_pre_update,
126 player__skate_pre_update,
127 NULL
128 };
129
130 VG_STATIC
131 void( *_player_update[])( player_instance *player ) =
132 {
133 player__walk_update,
134 player__skate_update,
135 NULL
136 };
137
138 VG_STATIC
139 void( *_player_post_update[])( player_instance *player ) =
140 {
141 player__walk_post_update,
142 player__skate_post_update,
143 NULL
144 };
145
146 VG_STATIC
147 void( *_player_im_gui[])( player_instance *player ) =
148 {
149 player__walk_im_gui,
150 player__skate_im_gui,
151 NULL
152 };
153
154 VG_STATIC
155 void( *_player_animate[])( player_instance *player, player_animation *dest ) =
156 {
157 player__walk_animate,
158 player__skate_animate,
159 NULL
160 };
161
162 VG_STATIC
163 void( *_player_post_animate[])( player_instance *player ) =
164 {
165 player__walk_post_animate,
166 player__skate_post_animate,
167 NULL
168 };
169
170 /* implementation */
171
172 #include "player.c"
173 #include "player_common.c"
174 #include "player_walk.c"
175 #include "player_skate.c"
176 //#include "player_dead.c"
177
178 #endif /* PLAYER_H */
179
180
181 #if 0
182 /*
183 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
184 */
185
186 #define PLAYER_H
187 #ifndef PLAYER_H
188 #define PLAYER_H
189
190 #define PLAYER_REWIND_FRAMES 60*4
191
192 #include "conf.h"
193 #include "audio.h"
194 #include "common.h"
195 #include "world.h"
196 #include "skeleton.h"
197 #include "bvh.h"
198
199
200 /*
201 * -----------------------------------------------------------------------------
202 * Memory
203 * -----------------------------------------------------------------------------
204 */
205
206 VG_STATIC struct gplayer
207 {
208 rigidbody rb, rb_frame;
209 v3f co, angles; /* used as transfer between controllers */
210
211 enum player_controller
212 {
213 k_player_controller_walk,
214 k_player_controller_skate,
215 k_player_controller_ragdoll,
216 k_player_controller_mountain_skate,
217 k_player_controller_snowboard,
218 k_player_controller_drive
219 }
220 controller,
221 controller_frame;
222
223 m4x3f visual_transform,
224 inv_visual_transform;
225
226 int is_dead, death_tick_allowance, rewinding;
227 int rewind_sound_wait;
228
229
230 v3f handl_target, handr_target,
231 handl, handr;
232
233 /* Input */
234 struct input_binding *input_js1h,
235 *input_js1v,
236 *input_js2h,
237 *input_js2v,
238 *input_jump,
239 *input_push,
240 *input_walk,
241 *input_walkh,
242 *input_walkv,
243 *input_switch_mode,
244 *input_reset,
245 *input_grab;
246
247 /* Camera */
248 float air_time;
249 v3f camera_pos, smooth_localcam;
250
251 struct rewind_frame
252 {
253 v3f pos;
254 v3f ang;
255 }
256 *rewind_buffer;
257 u32 rewind_incrementer,
258 rewind_length;
259
260 float rewind_time, rewind_total_length, rewind_predicted_time;
261 double diag_rewind_start, diag_rewind_time;
262 float dist_accum;
263
264 /* animation */
265 double jump_time;
266 float fslide,
267 fdirz, fdirx,
268 fstand,
269 ffly,
270 fpush,
271 fairdir,
272 fsetup,
273 walk_timer,
274 fjump,
275 fonboard,
276 frun,
277 fgrind;
278
279 v3f board_offset;
280 v4f board_rotation;
281
282 float walk;
283 int step_phase;
284 enum mdl_surface_prop surface_prop;
285
286 /* player model */
287 struct player_model
288 {
289 glmesh player_meshes[3];
290
291 mdl_context meta;
292 struct skeleton sk;
293 struct skeleton_anim *anim_stand,
294 *anim_highg,
295 *anim_slide,
296 *anim_air,
297 *anim_push, *anim_push_reverse,
298 *anim_ollie, *anim_ollie_reverse,
299 *anim_grabs, *anim_stop,
300 *anim_walk, *anim_run, *anim_idle,
301 *anim_jump;
302
303 u32 id_hip,
304 id_ik_hand_l,
305 id_ik_hand_r,
306 id_ik_elbow_l,
307 id_ik_elbow_r,
308 id_head,
309 id_ik_foot_l,
310 id_ik_foot_r,
311 id_board;
312
313 v3f cam_pos;
314
315 struct ragdoll_part
316 {
317 u32 bone_id;
318 //v3f offset;
319
320 /* Collider transform relative to bone */
321 m4x3f collider_mtx,
322 inv_collider_mtx;
323
324 u32 use_limits;
325 v3f limits[2];
326
327 rigidbody rb;
328 u32 parent;
329 u32 colour;
330 }
331 ragdoll[32];
332 u32 ragdoll_count;
333
334 rb_constr_pos position_constraints[32];
335 u32 position_constraints_count;
336
337 rb_constr_swingtwist cone_constraints[32];
338 u32 cone_constraints_count;
339
340 int shoes[2];
341 }
342 mdl;
343 }
344 player__OLD
345
346 #if 0
347 =
348 {
349 .collide_front = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f },
350 .collide_back = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f }
351 }
352 #endif
353
354 ;
355
356 /*
357 * API
358 */
359 VG_STATIC float *player_get_pos(void);
360 VG_STATIC void player_kill(void);
361 VG_STATIC float *player_cam_pos(void);
362 VG_STATIC void player_save_frame(void);
363 VG_STATIC void player_restore_frame(void);
364 VG_STATIC void player_save_rewind_frame(void);
365
366 /*
367 * Submodules
368 */
369 VG_STATIC void player_mouseview(void);
370
371 #include "player_physics.h"
372 #include "player_physics_skate.h"
373 #include "player_physics_walk.h"
374 #include "player_ragdoll.h"
375 #include "player_model.h"
376 #include "player_animation.h"
377 #include "player_audio.h"
378
379 /*
380 * player_physics_<INTERFACE>_<SUB-INTERFACE>
381 *
382 *
383 *
384 */
385
386 /*
387 * -----------------------------------------------------------------------------
388 * Events
389 * -----------------------------------------------------------------------------
390 */
391 VG_STATIC int kill_player( int argc, char const *argv[] );
392 VG_STATIC int reset_player( int argc, char const *argv[] );
393 VG_STATIC void reset_player_poll( int argc, char const *argv[] );
394
395 VG_STATIC void player_init(void) /* 1 */
396 {
397 #if 0
398 player.input_js1h = vg_create_named_input( "steer-h", k_input_type_axis );
399 player.input_js1v = vg_create_named_input( "steer-v", k_input_type_axis );
400 player.input_grab = vg_create_named_input( "grab", k_input_type_axis_norm );
401 player.input_js2h = vg_create_named_input( "grab-h", k_input_type_axis );
402 player.input_js2v = vg_create_named_input( "grab-v", k_input_type_axis );
403 player.input_jump = vg_create_named_input( "jump", k_input_type_button );
404 player.input_push = vg_create_named_input( "push", k_input_type_button );
405 player.input_walk = vg_create_named_input( "walk", k_input_type_button );
406
407 player.input_walkh = vg_create_named_input( "walk-h",
408 k_input_type_axis );
409 player.input_walkv = vg_create_named_input( "walk-v",
410 k_input_type_axis );
411
412
413 player.input_switch_mode = vg_create_named_input( "switch-mode",
414 k_input_type_button );
415 player.input_reset = vg_create_named_input( "reset", k_input_type_button );
416
417 const char *default_cfg[] =
418 {
419 "bind steer-h gp-ls-h",
420 "bind -steer-h a",
421 "bind +steer-h d",
422
423 "bind steer-v gp-ls-v",
424 "bind -steer-v w",
425 "bind +steer-v s",
426
427 "bind grab gp-rt",
428 "bind +grab shift",
429 "bind grab-h gp-rs-h",
430 "bind grab-v gp-rs-v",
431
432 "bind jump space",
433 "bind jump gp-a",
434
435 "bind push gp-b",
436 "bind push w",
437
438 "bind walk shift",
439 "bind walk gp-ls",
440
441 "bind walk-h gp-ls-h",
442 "bind walk-v -gp-ls-v",
443 "bind +walk-h d",
444 "bind -walk-h a",
445 "bind +walk-v w",
446 "bind -walk-v s",
447
448 "bind reset gp-lb",
449 "bind reset r",
450
451 "bind switch-mode gp-y",
452 "bind switch-mode e",
453 };
454
455 for( int i=0; i<vg_list_size(default_cfg); i++ )
456 vg_execute_console_input(default_cfg[i]);
457 #endif
458
459 rb_init( &player.rb );
460
461 VG_VAR_F32( k_walkspeed );
462 VG_VAR_F32( k_stopspeed );
463 VG_VAR_F32( k_airspeed );
464 VG_VAR_F32( k_walk_friction );
465 VG_VAR_F32( k_walk_air_accel );
466 VG_VAR_F32( k_runspeed );
467 VG_VAR_F32( k_walk_accel );
468
469 VG_VAR_I32( freecam );
470 VG_VAR_I32( cl_thirdperson );
471 VG_VAR_F32_PERSISTENT( fc_speed );
472
473 /* TODO: NOT PERSISTENT */
474 VG_VAR_F32( k_ragdoll_limit_scale );
475 VG_VAR_I32( k_ragdoll_div );
476 VG_VAR_I32( k_ragdoll_debug_collider );
477 VG_VAR_I32( k_ragdoll_debug_constraints );
478
479 VG_VAR_F32( k_friction_lat );
480
481 VG_VAR_F32( k_cog_spring );
482 VG_VAR_F32( k_cog_damp );
483
484 VG_VAR_F32( k_cog_mass_ratio );
485 VG_VAR_F32( k_downforce );
486
487 VG_VAR_F32( k_spring_force );
488 VG_VAR_F32( k_spring_dampener );
489 VG_VAR_F32( k_spring_angular );
490
491 VG_VAR_F32( k_mmthrow_scale );
492 VG_VAR_F32( k_mmcollect_lat );
493 VG_VAR_F32( k_mmcollect_vert );
494 VG_VAR_F32( k_mmdecay );
495
496 vg_function_push( (struct vg_cmd){
497 .name = "reset",
498 .function = reset_player,
499 .poll_suggest = reset_player_poll
500 });
501
502 vg_function_push( (struct vg_cmd){
503 .name = "kill",
504 .function = kill_player
505 });
506
507 /* HACK */
508 rb_register_cvar();
509
510 player.rewind_length = 0;
511 player.rewind_buffer =
512 vg_linear_alloc( vg_mem.rtmemory,
513 sizeof(struct rewind_frame) * PLAYER_REWIND_FRAMES );
514
515 player_model_init();
516 }
517
518 VG_STATIC void player_save_rewind_frame(void)
519 {
520 if( player.rewind_length < PLAYER_REWIND_FRAMES )
521 {
522 struct rewind_frame *fr =
523 &player.rewind_buffer[ player.rewind_length ++ ];
524
525 v2_copy( player.angles, fr->ang );
526 v3_copy( player.camera_pos, fr->pos );
527
528 player.rewind_incrementer = 0;
529
530 if( player.rewind_length > 1 )
531 {
532 player.rewind_total_length +=
533 v3_dist( player.rewind_buffer[player.rewind_length-1].pos,
534 player.rewind_buffer[player.rewind_length-2].pos );
535 }
536 }
537 }
538
539
540 /* disaster */
541 VG_STATIC int menu_enabled(void);
542 #include "menu.h"
543
544 VG_STATIC void player_do_motion(void);
545 /*
546 * Free camera movement
547 */
548 VG_STATIC void player_mouseview(void)
549 {
550 if( menu_enabled() )
551 return;
552
553 v2_muladds( player.angles, vg.mouse_delta, 0.0025f, player.angles );
554
555 if( vg_input.controller_should_use_trackpad_look )
556 {
557 static v2f last_input;
558 static v2f vel;
559 static v2f vel_smooth;
560
561 v2f input = { player.input_js2h->axis.value,
562 player.input_js2v->axis.value };
563
564 if( (v2_length2(last_input) > 0.001f) && (v2_length2(input) > 0.001f) )
565 {
566 v2_sub( input, last_input, vel );
567 v2_muls( vel, 1.0f/vg.time_delta, vel );
568 }
569 else
570 {
571 v2_zero( vel );
572 }
573
574 v2_lerp( vel_smooth, vel, vg.time_delta*8.0f, vel_smooth );
575
576 v2_muladds( player.angles, vel_smooth, vg.time_delta, player.angles );
577 v2_copy( input, last_input );
578 }
579 else
580 {
581 player.angles[0] += player.input_js2h->axis.value * vg.time_delta * 4.0f;
582 player.angles[1] += player.input_js2v->axis.value * vg.time_delta * 4.0f;
583 }
584
585 player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
586 }
587
588 /* Deal with input etc */
589 VG_STATIC void player_update_pre(void)
590 {
591
592 {
593 v3f ra, rb, rx;
594 v3_copy( main_camera.pos, ra );
595 v3_muladds( ra, main_camera.transform[2], -10.0f, rb );
596
597 float t;
598 if( spherecast_world( ra, rb, 0.4f, &t, rx ) != -1 )
599 {
600 m4x3f mtx;
601 m3x3_identity( mtx );
602 v3_lerp( ra, rb, t, mtx[3] );
603
604 debug_sphere( mtx, 0.4f, 0xff00ff00 );
605
606 v3f x1;
607 v3_muladds( mtx[3], rx, 0.4f, x1 );
608 vg_line( mtx[3], x1, 0xffffffff );
609 }
610 }
611
612 #if 0
613
614 vg_line_pt3( phys->cog, 0.10f, 0xffffffff );
615 vg_line_pt3( phys->cog, 0.09f, 0xffffffff );
616 vg_line_pt3( phys->cog, 0.08f, 0xffffffff );
617 vg_line( phys->cog, phys->rb.co, 0xff000000 );
618
619 v3f spring_end;
620 v3f throw_end, p0, p1;
621 v3_muladds( phys->rb.co, phys->rb.up, 1.0f, spring_end );
622 v3_muladds( spring_end, phys->throw_v, 1.0f, throw_end );
623 v3_muladds( spring_end, player.debug_mmcollect_lat, 1.0f, p0 );
624 v3_muladds( spring_end, player.debug_mmcollect_vert, 1.0f, p1 );
625 vg_line( spring_end, throw_end, VG__RED );
626 vg_line( spring_end, p0, VG__GREEN );
627 vg_line( spring_end, p1, VG__BLUE );
628 #endif
629
630 if( player.rewinding )
631 return;
632
633 if( vg_input_button_down( player.input_reset ) && !menu_enabled() )
634 {
635 double delta = world.time - world.last_use;
636
637 if( (delta <= RESET_MAX_TIME) && (world.last_use != 0.0) )
638 {
639 player.rewinding = 1;
640 player.rewind_sound_wait = 1;
641 player.rewind_time = (float)player.rewind_length - 0.0001f;
642 player_save_rewind_frame();
643 audio_lock();
644 audio_play_oneshot( &audio_rewind[0], 1.0f );
645 audio_unlock();
646
647 /* based on analytical testing. DONT CHANGE!
648 *
649 * time taken: y = (x^(4/5)) * 74.5
650 * inverse : x = (2/149)^(4/5) * y^(4/5)
651 */
652
653 float constant = powf( 2.0f/149.0f, 4.0f/5.0f ),
654 curve = powf( player.rewind_total_length, 4.0f/5.0f );
655
656 player.rewind_predicted_time = constant * curve;
657 player.diag_rewind_start = vg.time;
658 player.diag_rewind_time = player.rewind_time;
659
660 player.is_dead = 0;
661 player.death_tick_allowance = 30;
662 player_restore_frame();
663
664 if( player.controller == k_player_controller_walk )
665 {
666 player.angles[0] = atan2f( -player.rb.forward[2],
667 -player.rb.forward[0] );
668 }
669
670 player.mdl.shoes[0] = 1;
671 player.mdl.shoes[1] = 1;
672
673 world_routes_notify_reset();
674
675 /* apply 1 frame of movement */
676 player_do_motion();
677 }
678 else
679 {
680 if( player.is_dead )
681 {
682 reset_player( 0, NULL );
683 }
684 else
685 {
686 /* cant do that */
687 audio_lock();
688 audio_play_oneshot( &audio_rewind[4], 1.0f );
689 audio_unlock();
690 }
691 }
692 }
693
694 if( vg_input_button_down( player.input_switch_mode ) && !menu_enabled() )
695 {
696 audio_lock();
697
698 #if 0
699 if( phys->controller == k_player_controller_walk )
700 {
701 phys->controller = k_player_controller_skate;
702
703 v3_muladds( phys->rb.v, phys->rb.forward, 0.2f, phys->rb.v );
704 audio_play_oneshot( &audio_lands[6], 1.0f );
705 }
706 else if( phys->controller == k_player_controller_skate )
707 {
708 phys->controller = k_player_controller_walk;
709
710 audio_play_oneshot( &audio_lands[5], 1.0f );
711 }
712 #endif
713
714 audio_unlock();
715 }
716
717 if( player.controller == k_player_controller_walk )
718 player_mouseview();
719 }
720
721 VG_STATIC void player_update_fixed(void) /* 2 */
722 {
723 if( player.rewinding )
724 return;
725
726 if( player.death_tick_allowance )
727 player.death_tick_allowance --;
728
729 if( player.is_dead )
730 {
731 player_ragdoll_iter();
732 }
733 else
734 {
735 player.rewind_incrementer ++;
736
737 if( player.rewind_incrementer > (u32)(0.25/VG_TIMESTEP_FIXED) )
738 {
739 player_save_rewind_frame();
740 }
741
742 player_do_motion();
743 }
744 }
745
746 VG_STATIC void player_update_post(void)
747 {
748 #if 0
749 for( int i=0; i<player.prediction_count; i++ )
750 {
751 struct land_prediction *p = &player.predictions[i];
752
753 for( int j=0; j<p->log_length - 1; j ++ )
754 vg_line( p->log[j], p->log[j+1], p->colour );
755
756 vg_line_cross( p->log[p->log_length-1], p->colour, 0.25f );
757
758 v3f p1;
759 v3_add( p->log[p->log_length-1], p->n, p1 );
760 vg_line( p->log[p->log_length-1], p1, 0xffffffff );
761 }
762 #endif
763
764 #if 0
765 if( player.is_dead )
766 {
767 player_debug_ragdoll();
768
769 if( !freecam )
770 player_animate_death_cam();
771 }
772 else
773 {
774 player_animate();
775
776 if( !freecam )
777 {
778 if( cl_thirdperson )
779 player_animate_camera_thirdperson();
780 else
781 player_animate_camera();
782 }
783 }
784
785 if( freecam )
786 #endif
787 player_freecam();
788
789 /* CAMERA POSITIONING: LAYER 0 */
790 v2_copy( player.angles, main_camera.angles );
791 v3_copy( player.camera_pos, main_camera.pos );
792
793 #if 0
794 if( player.rewinding )
795 {
796 if( player.rewind_time <= 0.0f )
797 {
798 double taken = vg.time - player.diag_rewind_start;
799 vg_success( "Rewind took (rt, pl, tl): %f, %f, %f\n",
800 taken, player.diag_rewind_time,
801 player.rewind_total_length );
802
803 player.rewinding = 0;
804 player.rewind_length = 1;
805 player.rewind_total_length = 0.0f;
806 player.rewind_incrementer = 0;
807 world.sky_target_rate = 1.0;
808 }
809 else
810 {
811 world.sky_target_rate = -100.0;
812 assert( player.rewind_length > 0 );
813
814 v2f override_angles;
815 v3f override_pos;
816
817 float budget = vg.time_delta,
818 overall_length = player.rewind_length;
819
820 world_routes_rollback_time( player.rewind_time / overall_length );
821
822 for( int i=0; (i<10)&&(player.rewind_time>0.0f)&&(budget>0.0f); i ++ )
823 {
824 /* Interpolate frames */
825 int i0 = floorf( player.rewind_time ),
826 i1 = VG_MIN( i0+1, player.rewind_length-1 );
827
828 struct rewind_frame *fr = &player.rewind_buffer[i0],
829 *fr1 = &player.rewind_buffer[i1];
830
831 float dist = vg_maxf( v3_dist( fr->pos, fr1->pos ), 0.001f ),
832 subl = vg_fractf( player.rewind_time ) + 0.001f,
833
834 sramp= 3.0f-(1.0f/(0.4f+0.4f*player.rewind_time)),
835 speed = sramp*28.0f + 0.5f*player.rewind_time,
836 mod = speed * (budget / dist),
837
838 advl = vg_minf( mod, subl ),
839 advt = (advl / mod) * budget;
840
841 player.dist_accum += speed * advt;
842 player.rewind_time -= advl;
843 budget -= advt;
844 }
845
846 player.rewind_time = vg_maxf( 0.0f, player.rewind_time );
847
848 float current_time = vg.time - player.diag_rewind_start,
849 remaining = player.rewind_predicted_time - current_time;
850
851 if( player.rewind_sound_wait )
852 {
853 if( player.rewind_predicted_time >= 6.5f )
854 {
855 if( remaining <= 6.5f )
856 {
857 audio_lock();
858 audio_play_oneshot( &audio_rewind[3], 1.0f );
859 audio_unlock();
860 player.rewind_sound_wait = 0;
861 }
862 }
863 else if( player.rewind_predicted_time >= 2.5f )
864 {
865 if( remaining <= 2.5f )
866 {
867 audio_lock();
868 audio_play_oneshot( &audio_rewind[2], 1.0f );
869 audio_unlock();
870 player.rewind_sound_wait = 0;
871 }
872 }
873 else if( player.rewind_predicted_time >= 1.5f )
874 {
875 if( remaining <= 1.5f )
876 {
877 audio_lock();
878 audio_play_oneshot( &audio_rewind[1], 1.0f );
879 audio_unlock();
880 player.rewind_sound_wait = 0;
881 }
882 }
883 }
884
885 int i0 = floorf( player.rewind_time ),
886 i1 = VG_MIN( i0+1, player.rewind_length-1 );
887
888 struct rewind_frame *fr = &player.rewind_buffer[i0],
889 *fr1 = &player.rewind_buffer[i1];
890
891 float sub = vg_fractf(player.rewind_time);
892
893 v3_lerp( fr->pos, fr1->pos, sub, override_pos );
894 override_angles[0] = vg_alerpf( fr->ang[0], fr1->ang[0], sub );
895 override_angles[1] = vg_lerpf ( fr->ang[1], fr1->ang[1], sub );
896
897 /* CAMERA POSITIONING: LAYER 1 */
898 float blend = (4.0f-player.rewind_time) * 0.25f,
899 c = vg_clampf( blend, 0.0f, 1.0f );
900
901 main_camera.angles[0] =
902 vg_alerpf(override_angles[0], player.angles[0], c);
903 main_camera.angles[1] =
904 vg_lerpf (override_angles[1], player.angles[1], c);
905 v3_lerp( override_pos, player.camera_pos, c, main_camera.pos );
906 }
907 }
908 #endif
909
910 camera_update_transform( &main_camera );
911 player_audio();
912 }
913
914 VG_STATIC void draw_player( camera *cam )
915 {
916 if( player.is_dead )
917 player_model_copy_ragdoll();
918
919 shader_viewchar_use();
920 vg_tex2d_bind( &tex_characters, 0 );
921 shader_viewchar_uTexMain( 0 );
922 shader_viewchar_uCamera( cam->transform[3] );
923 shader_viewchar_uPv( cam->mtx.pv );
924 shader_link_standard_ub( _shader_viewchar.id, 2 );
925 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms,
926 player.mdl.sk.bone_count,
927 0,
928 (float *)player.mdl.sk.final_mtx );
929
930 mesh_bind( &player.mdl.player_meshes[cl_playermdl_id] );
931 mesh_draw( &player.mdl.player_meshes[cl_playermdl_id] );
932 }
933
934 VG_STATIC void player_do_motion(void)
935 {
936 if( world.water.enabled )
937 {
938 if( (player.rb.co[1] < 0.0f) && !player.is_dead )
939 {
940 audio_lock();
941 audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
942 audio_player_set_position( &audio_player_extra, player.rb.co );
943 audio_player_set_vol( &audio_player_extra, 20.0f );
944 audio_player_playclip( &audio_player_extra, &audio_splash );
945 audio_unlock();
946
947 player_kill();
948 }
949 }
950
951 v3f prevco;
952 v3_copy( player.rb.co, prevco );
953
954 if( player.controller == k_player_controller_skate )
955 {
956 #if 0
957 player_skate_update();
958 #endif
959 }
960 else
961 player_walk_physics( &player_walky );
962
963
964 /* Real angular velocity integration */
965 #if 0
966 v3_lerp( phys->rb.w, (v3f){0.0f,0.0f,0.0f}, 0.125f*0.5f, phys->rb.w );
967 if( v3_length2( phys->rb.w ) > 0.0f )
968 {
969 v4f rotation;
970 v3f axis;
971 v3_copy( phys->rb.w, axis );
972
973 float mag = v3_length( axis );
974 v3_divs( axis, mag, axis );
975 q_axis_angle( rotation, axis, mag*k_rb_delta );
976 q_mul( rotation, phys->rb.q, phys->rb.q );
977 }
978
979 /* Faux angular velocity */
980 v4f rotate;
981
982 float lerpq = (player_skate.activity == k_skate_activity_air)? 0.04f: 0.3f;
983 phys->siY = vg_lerpf( phys->siY, phys->iY, lerpq );
984
985 q_axis_angle( rotate, phys->rb.up, phys->siY );
986 q_mul( rotate, phys->rb.q, phys->rb.q );
987 phys->iY = 0.0f;
988 #endif
989
990 /*
991 * Gate intersection, by tracing a line over the gate planes
992 */
993 #if 0
994 for( int i=0; i<world.gate_count; i++ )
995 {
996 struct route_gate *rg = &world.gates[i];
997 teleport_gate *gate = &rg->gate;
998
999 if( gate_intersect( gate, phys->rb.co, prevco ) )
1000 {
1001 m4x3_mulv( gate->transport, phys->rb.co, phys->rb.co );
1002 m4x3_mulv( gate->transport, phys->cog, phys->cog );
1003 m3x3_mulv( gate->transport, phys->cog_v, phys->cog_v );
1004 m3x3_mulv( gate->transport, phys->rb.v, phys->rb.v );
1005 m3x3_mulv( gate->transport, phys->vl, phys->vl );
1006 m3x3_mulv( gate->transport, phys->v_last, phys->v_last );
1007 m3x3_mulv( gate->transport, phys->m, phys->m );
1008 m3x3_mulv( gate->transport, phys->bob, phys->bob );
1009
1010 /* Pre-emptively edit the camera matrices so that the motion vectors
1011 * are correct */
1012 m4x3f transport_i;
1013 m4x4f transport_4;
1014 m4x3_invert_affine( gate->transport, transport_i );
1015 m4x3_expand( transport_i, transport_4 );
1016 m4x4_mul( main_camera.mtx.pv, transport_4, main_camera.mtx.pv );
1017 m4x4_mul( main_camera.mtx.v, transport_4, main_camera.mtx.v );
1018
1019 v4f transport_rotation;
1020 m3x3_q( gate->transport, transport_rotation );
1021 q_mul( transport_rotation, phys->rb.q, phys->rb.q );
1022
1023 world_routes_activate_gate( i );
1024
1025 if( phys->controller == k_player_controller_walk )
1026 {
1027 v3f fwd_dir = {cosf(player.angles[0]),
1028 0.0f,
1029 sinf(player.angles[0])};
1030 m3x3_mulv( gate->transport, fwd_dir, fwd_dir );
1031
1032 player.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] );
1033 }
1034
1035 player.rewind_length = 0;
1036 player.rewind_total_length = 0.0f;
1037 player.rewind_incrementer = 10000;
1038 player_save_frame();
1039
1040 audio_lock();
1041 audio_play_oneshot( &audio_gate_pass, 1.0f );
1042 audio_unlock();
1043 break;
1044 }
1045 }
1046 #endif
1047
1048 rb_update_transform( &player.rb );
1049 }
1050
1051 /*
1052 * -----------------------------------------------------------------------------
1053 * API implementation
1054 * -----------------------------------------------------------------------------
1055 */
1056
1057 VG_STATIC float *player_get_pos(void)
1058 {
1059 return player.rb.co;
1060 }
1061
1062 VG_STATIC void player_kill(void)
1063 {
1064 if( player.death_tick_allowance == 0 )
1065 {
1066 player.is_dead = 1;
1067 player_ragdoll_copy_model( player.rb.v );
1068 }
1069 }
1070
1071 VG_STATIC float *player_cam_pos(void)
1072 {
1073 return player.camera_pos;
1074 }
1075
1076
1077 VG_STATIC void player_save_frame(void)
1078 {
1079 player.controller_frame = player.controller;
1080
1081 /* TODO <interface>->save() */
1082 }
1083
1084 VG_STATIC void player_restore_frame(void)
1085 {
1086 player.controller = player.controller_frame;
1087
1088 /* TODO <interface>->load() */
1089 }
1090
1091 #endif /* PLAYER_H */
1092 #endif