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