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