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