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