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