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