stuff
[carveJwlIkooP6JGAAIwe30JlM.git] / player.h
1 #ifndef PLAYER_H
2 #define PLAYER_H
3
4 #include "audio.h"
5 #include "common.h"
6 #include "world.h"
7 //#include "character.h"
8 #include "player_model.h"
9 #include "bvh.h"
10
11 /*
12 * Constants
13 */
14
15 static float
16 k_walkspeed = 7.0f, /* no longer used */
17 k_runspeed = 14.0f,
18 k_board_radius = 0.3f,
19 k_board_length = 0.45f,
20 k_board_allowance = 0.04f,
21 k_friction_lat = 8.8f,
22 k_friction_resistance = 0.01f,
23 k_max_push_speed = 16.0f,
24 k_push_accel = 10.0f,
25 k_push_cycle_rate = 8.0f,
26 k_steer_ground = 2.5f,
27 k_steer_air = 3.6f,
28 k_steer_air_lerp = 0.3f,
29 k_pump_force = 0.0f,
30 k_downforce = 5.0f,
31 k_jump_charge_speed = (1.0f/1.0f),
32 k_jump_force = 5.0f,
33 k_pitch_limit = 1.5f,
34 k_look_speed = 2.0f,
35 k_walk_accel = 5.0f,
36 k_walk_friction = 8.0f;
37
38 static int freecam = 0;
39 static int walk_grid_iterations = 1;
40 static float fc_speed = 10.0f;
41
42 static struct gplayer
43 {
44 /* Physics */
45 rigidbody rb, collide_front, collide_back, rb_gate_frame;
46
47 /* TODO: eugh */
48 m3x3f gate_vr_frame, gate_vr_pstep_frame;
49
50 v3f a, v_last, m, bob, vl;
51
52 /* Utility */
53 float vswitch, slip, slip_last,
54 reverse;
55
56 float iY; /* Yaw inertia */
57 int in_air, is_dead, on_board;
58
59 v2f board_xy;
60 float grab;
61 float pitch;
62 float pushing, push_time;
63 float jump;
64 int jump_charge, jump_dir;
65
66 v3f land_target;
67 v3f land_target_log[22];
68 u32 land_target_colours[22];
69 int land_log_count;
70 m3x3f vr,vr_pstep;
71
72 struct character mdl;
73
74 v3f handl_target, handr_target,
75 handl, handr;
76
77 /* Camera */
78 float air_blend;
79
80 v3f camera_pos, smooth_localcam;
81 v2f angles;
82 m4x3f camera, camera_inverse;
83
84 /* animation */
85 double jump_time;
86 float fslide,
87 fdirz, fdirx,
88 fstand,
89 ffly,
90 fpush,
91 fairdir,
92 fsetup,
93 walk_timer,
94 fonboard;
95
96 v3f last_step_pos;
97 int step_phase;
98 }
99 player =
100 {
101 .on_board = 0,
102
103 .collide_front = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f },
104 .collide_back = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f }
105 };
106
107 /*
108 * Player API
109 */
110
111
112 /*
113 * Free camera movement
114 */
115
116 static void player_mouseview(void)
117 {
118 if( gui_want_mouse() )
119 return;
120
121 static v2f mouse_last,
122 view_vel = { 0.0f, 0.0f };
123
124 if( vg_get_button_down( "primary" ) )
125 v2_copy( vg_mouse, mouse_last );
126
127 else if( vg_get_button( "primary" ) )
128 {
129 v2f delta;
130 v2_sub( vg_mouse, mouse_last, delta );
131 v2_copy( vg_mouse, mouse_last );
132
133 v2_muladds( view_vel, delta, 0.001f, view_vel );
134 }
135
136 v2_muladds( view_vel,
137 (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
138 0.05f, view_vel );
139 v2_muls( view_vel, 0.93f, view_vel );
140 v2_add( view_vel, player.angles, player.angles );
141 player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
142 }
143
144 static void player_freecam(void)
145 {
146 player_mouseview();
147
148 float movespeed = fc_speed;
149 v3f lookdir = { 0.0f, 0.0f, -1.0f },
150 sidedir = { 1.0f, 0.0f, 0.0f };
151
152 m3x3_mulv( player.camera, lookdir, lookdir );
153 m3x3_mulv( player.camera, sidedir, sidedir );
154
155 static v3f move_vel = { 0.0f, 0.0f, 0.0f };
156 if( vg_get_button( "forward" ) )
157 v3_muladds( move_vel, lookdir, ktimestep * movespeed, move_vel );
158 if( vg_get_button( "back" ) )
159 v3_muladds( move_vel, lookdir, ktimestep *-movespeed, move_vel );
160 if( vg_get_button( "left" ) )
161 v3_muladds( move_vel, sidedir, ktimestep *-movespeed, move_vel );
162 if( vg_get_button( "right" ) )
163 v3_muladds( move_vel, sidedir, ktimestep * movespeed, move_vel );
164
165 v3_muls( move_vel, 0.7f, move_vel );
166 v3_add( move_vel, player.camera_pos, player.camera_pos );
167 }
168
169 /*
170 * Player Physics Implementation
171 */
172
173 static void apply_gravity( v3f vel, float const timestep )
174 {
175 v3f gravity = { 0.0f, -9.6f, 0.0f };
176 v3_muladds( vel, gravity, timestep, vel );
177 }
178
179 /*
180 * TODO: The angle bias should become greater when launching from a steeper
181 * angle and skewed towords more 'downwards' angles when launching from
182 * shallower trajectories
183 *
184 * it should also be tweaked by the controller left stick being pushed
185 * up or down
186 */
187 static void player_start_air(void)
188 {
189 if( player.in_air )
190 return;
191
192 player.in_air = 1;
193
194 float pstep = ktimestep*10.0f;
195 float best_velocity_delta = -9999.9f;
196 float k_bias = 0.96f;
197
198 v3f axis;
199 v3_cross( player.rb.up, player.rb.v, axis );
200 v3_normalize( axis );
201 player.land_log_count = 0;
202
203 m3x3_identity( player.vr );
204
205 for( int m=-3;m<=12; m++ )
206 {
207 float vmod = ((float)m / 15.0f)*0.09f;
208
209 v3f pco, pco1, pv;
210 v3_copy( player.rb.co, pco );
211 v3_muls( player.rb.v, k_bias, pv );
212
213 /*
214 * Try different 'rotations' of the velocity to find the best possible
215 * landing normal. This conserves magnitude at the expense of slightly
216 * unrealistic results
217 */
218
219 m3x3f vr;
220 v4f vr_q;
221
222 q_axis_angle( vr_q, axis, vmod );
223 q_m3x3( vr_q, vr );
224
225 m3x3_mulv( vr, pv, pv );
226 v3_muladds( pco, pv, pstep, pco );
227
228 for( int i=0; i<50; i++ )
229 {
230 v3_copy( pco, pco1 );
231 apply_gravity( pv, pstep );
232
233 m3x3_mulv( vr, pv, pv );
234 v3_muladds( pco, pv, pstep, pco );
235
236 ray_hit contact;
237 v3f vdir;
238
239 v3_sub( pco, pco1, vdir );
240 contact.dist = v3_length( vdir );
241 v3_divs( vdir, contact.dist, vdir);
242
243 if( ray_world( pco1, vdir, &contact ))
244 {
245 float land_delta = v3_dot( pv, contact.normal );
246 u32 scolour = (u8)(vg_minf(-land_delta * 2.0f, 255.0f));
247
248 /* Bias prediction towords ramps */
249 if( ray_hit_is_ramp( &contact ) )
250 {
251 land_delta *= 0.1f;
252 scolour |= 0x0000a000;
253 }
254
255 if( (land_delta < 0.0f) && (land_delta > best_velocity_delta) )
256 {
257 best_velocity_delta = land_delta;
258
259 v3_copy( contact.pos, player.land_target );
260
261 m3x3_copy( vr, player.vr_pstep );
262 q_axis_angle( vr_q, axis, vmod*0.1f );
263 q_m3x3( vr_q, player.vr );
264 }
265
266 v3_copy( contact.pos,
267 player.land_target_log[player.land_log_count] );
268 player.land_target_colours[player.land_log_count] =
269 0xff000000 | scolour;
270
271 player.land_log_count ++;
272
273 break;
274 }
275 }
276 }
277 }
278
279 static void draw_cross(v3f pos,u32 colour, float scale)
280 {
281 v3f p0, p1;
282 v3_add( (v3f){ scale,0.0f,0.0f}, pos, p0 );
283 v3_add( (v3f){-scale,0.0f,0.0f}, pos, p1 );
284 vg_line( p0, p1, colour );
285 v3_add( (v3f){0.0f, scale,0.0f}, pos, p0 );
286 v3_add( (v3f){0.0f,-scale,0.0f}, pos, p1 );
287 vg_line( p0, p1, colour );
288 v3_add( (v3f){0.0f,0.0f, scale}, pos, p0 );
289 v3_add( (v3f){0.0f,0.0f,-scale}, pos, p1 );
290 vg_line( p0, p1, colour );
291 }
292
293 static void player_physics_control(void)
294 {
295 /*
296 * Computing localized friction forces for controlling the character
297 * Friction across X is significantly more than Z
298 */
299
300 v3f vel;
301 m3x3_mulv( player.rb.to_local, player.rb.v, vel );
302 float slip = 0.0f;
303
304 if( fabsf(vel[2]) > 0.01f )
305 slip = fabsf(-vel[0] / vel[2]) * vg_signf(vel[0]);
306
307 if( fabsf( slip ) > 1.2f )
308 slip = vg_signf( slip ) * 1.2f;
309 player.slip = slip;
310 player.reverse = -vg_signf(vel[2]);
311
312 float substep = ktimestep * 0.2f;
313 float fwd_resistance = (vg_get_button( "break" )? 5.0f: 0.02f) * -substep;
314
315 for( int i=0; i<5; i++ )
316 {
317 vel[2] = stable_force( vel[2], vg_signf( vel[2] ) * fwd_resistance );
318 vel[0] = stable_force( vel[0],
319 vg_signf( vel[0] ) * -k_friction_lat*substep );
320 }
321
322 static double start_push = 0.0;
323 if( vg_get_button_down( "push" ) )
324 start_push = vg_time;
325
326 if( vg_get_button( "jump" ) )
327 {
328 player.jump += ktimestep * k_jump_charge_speed;
329
330 if( !player.jump_charge )
331 player.jump_dir = player.reverse > 0.0f? 1: 0;
332
333 player.jump_charge = 1;
334 }
335
336 if( !vg_get_button("break") && vg_get_button( "push" ) )
337 {
338 player.pushing = 1.0f;
339 player.push_time = vg_time-start_push;
340
341 float cycle_time = player.push_time*k_push_cycle_rate,
342 amt = k_push_accel * (sinf(cycle_time)*0.5f+0.5f)*ktimestep,
343 current = v3_length( vel ),
344 new_vel = vg_minf( current + amt, k_max_push_speed );
345
346 new_vel -= vg_minf(current, k_max_push_speed);
347 vel[2] -= new_vel * player.reverse;
348 }
349
350 /* Pumping */
351 static float previous = 0.0f;
352 float delta = previous - player.grab,
353 pump = delta * k_pump_force*ktimestep;
354 previous = player.grab;
355
356 v3f p1;
357 v3_muladds( player.rb.co, player.rb.up, pump, p1 );
358 vg_line( player.rb.co, p1, 0xff0000ff );
359
360 vel[1] += pump;
361
362
363 m3x3_mulv( player.rb.to_world, vel, player.rb.v );
364
365 float steer = vg_get_axis( "horizontal" );
366 player.iY -= vg_signf(steer)*powf(steer,2.0f) * k_steer_ground * ktimestep;
367
368 v2_lerp( player.board_xy, (v2f){ slip*0.25f, 0.0f },
369 ktimestep*5.0f, player.board_xy);
370 }
371
372 static void player_physics_control_air(void)
373 {
374 m3x3_mulv( player.vr, player.rb.v, player.rb.v );
375 draw_cross( player.land_target, 0xff0000ff, 0.25f );
376
377 ray_hit hit;
378
379 /*
380 * Prediction
381 */
382 float pstep = ktimestep*10.0f;
383
384 v3f pco, pco1, pv;
385 v3_copy( player.rb.co, pco );
386 v3_copy( player.rb.v, pv );
387
388 float time_to_impact = 0.0f;
389 float limiter = 1.0f;
390
391 for( int i=0; i<50; i++ )
392 {
393 v3_copy( pco, pco1 );
394 m3x3_mulv( player.vr_pstep, pv, pv );
395 apply_gravity( pv, pstep );
396 v3_muladds( pco, pv, pstep, pco );
397
398 //vg_line( pco, pco1, i&0x1?0xff000000:0xffffffff );
399
400 ray_hit contact;
401 v3f vdir;
402
403 v3_sub( pco, pco1, vdir );
404 contact.dist = v3_length( vdir );
405 v3_divs( vdir, contact.dist, vdir);
406
407 float orig_dist = contact.dist;
408 if( ray_world( pco1, vdir, &contact ))
409 {
410 float angle = v3_dot( player.rb.up, contact.normal );
411 v3f axis;
412 v3_cross( player.rb.up, contact.normal, axis );
413
414 time_to_impact += (contact.dist/orig_dist)*pstep;
415 limiter = vg_minf( 5.0f, time_to_impact )/5.0f;
416 limiter = 1.0f-limiter;
417 limiter *= limiter;
418 limiter = 1.0f-limiter;
419
420 if( angle < 0.99f )
421 {
422 v4f correction;
423 q_axis_angle( correction, axis, acosf(angle)*0.05f*(1.0f-limiter) );
424 q_mul( correction, player.rb.q, player.rb.q );
425 }
426
427 draw_cross( contact.pos, 0xffff0000, 0.25f );
428 break;
429 }
430 time_to_impact += pstep;
431 }
432
433 player.iY -= vg_get_axis( "horizontal" ) * k_steer_air * ktimestep;
434 {
435 float iX = vg_get_axis( "vertical" ) *
436 player.reverse * k_steer_air * limiter * ktimestep;
437
438 static float siX = 0.0f;
439 siX = vg_lerpf( siX, iX, k_steer_air_lerp );
440
441 v4f rotate;
442 q_axis_angle( rotate, player.rb.right, siX );
443 q_mul( rotate, player.rb.q, player.rb.q );
444 }
445
446 v2f target = {0.0f,0.0f};
447 v2_muladds( target, (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
448 player.grab, target );
449 v2_lerp( player.board_xy, target, ktimestep*3.0f, player.board_xy );
450 }
451
452 static void player_init(void)
453 {
454 rb_init( &player.collide_front );
455 rb_init( &player.collide_back );
456 }
457
458 static void player_walk_physics(void)
459 {
460 rigidbody *rbf = &player.collide_front,
461 *rbb = &player.collide_back;
462
463 m3x3_copy( player.rb.to_world, player.collide_front.to_world );
464 m3x3_copy( player.rb.to_world, player.collide_back.to_world );
465
466 float h0 = 0.3f,
467 h1 = 0.9f;
468
469 m4x3_mulv( player.rb.to_world, (v3f){0.0f,h0,0.0f}, rbf->co );
470 v3_copy( rbf->co, rbf->to_world[3] );
471 m4x3_mulv( player.rb.to_world, (v3f){0.0f,h1,0.0f}, rbb->co );
472 v3_copy( rbb->co, rbb->to_world[3] );
473
474 m4x3_invert_affine( rbf->to_world, rbf->to_local );
475 m4x3_invert_affine( rbb->to_world, rbb->to_local );
476
477 rb_update_bounds( rbf );
478 rb_update_bounds( rbb );
479
480 rb_debug( rbf, 0xff0000ff );
481 rb_debug( rbb, 0xff0000ff );
482
483 rb_ct manifold[64];
484 int len = 0;
485
486 len += rb_sphere_scene( rbf, &world.rb_geo, manifold+len );
487 len += rb_sphere_scene( rbb, &world.rb_geo, manifold+len );
488
489 rb_presolve_contacts( manifold, len );
490
491 for( int j=0; j<5; j++ )
492 {
493 for( int i=0; i<len; i++ )
494 {
495 struct contact *ct = &manifold[i];
496
497 /*normal */
498 float vn = -v3_dot( player.rb.v, ct->n );
499 vn += ct->bias;
500
501 float temp = ct->norm_impulse;
502 ct->norm_impulse = vg_maxf( temp + vn, 0.0f );
503 vn = ct->norm_impulse - temp;
504
505 v3f impulse;
506 v3_muls( ct->n, vn, impulse );
507
508 v3_add( impulse, player.rb.v, player.rb.v );
509
510 /* friction */
511 for( int j=0; j<2; j++ )
512 {
513 float f = k_friction * ct->norm_impulse,
514 vt = v3_dot( player.rb.v, ct->t[j] ),
515 lambda = -vt;
516
517 float temp = ct->tangent_impulse[j];
518 ct->tangent_impulse[j] = vg_clampf( temp + lambda, -f, f );
519 lambda = ct->tangent_impulse[j] - temp;
520
521 v3_muladds( player.rb.v, ct->t[j], lambda, player.rb.v );
522 }
523 }
524 }
525
526 player.in_air = len==0?1:0;
527
528 v3_zero( player.rb.w );
529 q_axis_angle( player.rb.q, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] );
530
531 v3f forward_dir = { sinf(player.angles[0]),0.0f,-cosf(player.angles[0]) };
532
533 v3f p1;
534 v3_muladds( player.rb.co, forward_dir, 2.0f, p1 );
535 vg_line( player.rb.co, p1, 0xff0000ff );
536
537 float move_dead = 0.1f,
538 move = vg_get_axis("grabr")*0.5f + 0.5f - move_dead;
539
540 if( move > 0.0f )
541 {
542 float move_norm = move * (1.0f/(1.0f-move_dead)),
543 speed = vg_lerpf( 0.1f*k_runspeed, k_runspeed, move_norm ),
544 amt = k_walk_accel * ktimestep,
545 zvel = v3_dot( player.rb.v, forward_dir ),
546 new_vel = vg_minf( zvel + amt, speed ),
547 diff = new_vel - vg_minf( zvel, speed );
548
549 v3_muladds( player.rb.v, forward_dir, diff, player.rb.v );
550
551 /* TODO move */
552 float walk_norm = 30.0f/(float)player.mdl.anim_walk->length,
553 run_norm = 30.0f/(float)player.mdl.anim_run->length ;
554
555 player.walk_timer += ktimestep * vg_lerpf( walk_norm,run_norm,move_norm );
556 }
557 else
558 {
559 player.walk_timer = 0.0f;
560 }
561
562 player.rb.v[0] *= 1.0f - (ktimestep*k_walk_friction);
563 player.rb.v[2] *= 1.0f - (ktimestep*k_walk_friction);
564 }
565
566 static void player_physics(void)
567 {
568 /*
569 * Update collision fronts
570 */
571
572 rigidbody *rbf = &player.collide_front,
573 *rbb = &player.collide_back;
574
575 m3x3_copy( player.rb.to_world, player.collide_front.to_world );
576 m3x3_copy( player.rb.to_world, player.collide_back.to_world );
577
578 player.air_blend = vg_lerpf( player.air_blend, player.in_air, 0.1f );
579 float h = player.air_blend*0.2f;
580
581 m4x3_mulv( player.rb.to_world, (v3f){0.0f,h,-k_board_length}, rbf->co );
582 v3_copy( rbf->co, rbf->to_world[3] );
583 m4x3_mulv( player.rb.to_world, (v3f){0.0f,h, k_board_length}, rbb->co );
584 v3_copy( rbb->co, rbb->to_world[3] );
585
586 m4x3_invert_affine( rbf->to_world, rbf->to_local );
587 m4x3_invert_affine( rbb->to_world, rbb->to_local );
588
589 rb_update_bounds( rbf );
590 rb_update_bounds( rbb );
591
592 rb_debug( rbf, 0xff00ffff );
593 rb_debug( rbb, 0xffffff00 );
594
595 rb_ct manifold[64];
596 int len = 0;
597
598 len += rb_sphere_scene( rbf, &world.rb_geo, manifold+len );
599 len += rb_sphere_scene( rbb, &world.rb_geo, manifold+len );
600
601 rb_presolve_contacts( manifold, len );
602 v3f surface_avg = {0.0f, 0.0f, 0.0f};
603
604 if( !len )
605 {
606 player_start_air();
607 }
608 else
609 {
610 for( int i=0; i<len; i++ )
611 {
612 v3_add( manifold[i].n, surface_avg, surface_avg );
613
614 #if 0
615 if( manifold[i].element_id <= world.sm_geo_std_oob.vertex_count )
616 {
617 player.is_dead = 1;
618 character_ragdoll_copypose( &player.mdl, player.rb.v );
619 return;
620 }
621 #endif
622 }
623
624 v3_normalize( surface_avg );
625
626 if( v3_dot( player.rb.v, surface_avg ) > 0.5f )
627 {
628 player_start_air();
629 }
630 else
631 player.in_air = 0;
632 }
633
634 for( int j=0; j<5; j++ )
635 {
636 for( int i=0; i<len; i++ )
637 {
638 struct contact *ct = &manifold[i];
639
640 v3f dv, delta;
641 v3_sub( ct->co, player.rb.co, delta );
642 v3_cross( player.rb.w, delta, dv );
643 v3_add( player.rb.v, dv, dv );
644
645 float vn = -v3_dot( dv, ct->n );
646 vn += ct->bias;
647
648 float temp = ct->norm_impulse;
649 ct->norm_impulse = vg_maxf( temp + vn, 0.0f );
650 vn = ct->norm_impulse - temp;
651
652 v3f impulse;
653 v3_muls( ct->n, vn, impulse );
654
655 if( fabsf(v3_dot( impulse, player.rb.forward )) > 10.0f ||
656 fabsf(v3_dot( impulse, player.rb.up )) > 50.0f )
657 {
658 player.is_dead = 1;
659 character_ragdoll_copypose( &player.mdl, player.rb.v );
660 return;
661 }
662
663 v3_add( impulse, player.rb.v, player.rb.v );
664 v3_cross( delta, impulse, impulse );
665
666 /*
667 * W Impulses are limited to the Y and X axises, we don't really want
668 * roll angular velocities being included.
669 *
670 * Can also tweak the resistance of each axis here by scaling the wx,wy
671 * components.
672 */
673
674 float wy = v3_dot( player.rb.up, impulse ),
675 wx = v3_dot( player.rb.right, impulse )*1.5f;
676
677 v3_muladds( player.rb.w, player.rb.up, wy, player.rb.w );
678 v3_muladds( player.rb.w, player.rb.right, wx, player.rb.w );
679 }
680 }
681
682 float grabt = vg_get_axis( "grabr" )*0.5f+0.5f;
683 player.grab = vg_lerpf( player.grab, grabt, 0.14f );
684 player.pushing = 0.0f;
685
686 if( !player.in_air )
687 {
688 v3f axis;
689 float angle = v3_dot( player.rb.up, surface_avg );
690 v3_cross( player.rb.up, surface_avg, axis );
691
692 //float cz = v3_dot( player.rb.forward, axis );
693 //v3_muls( player.rb.forward, cz, axis );
694
695 if( angle < 0.999f )
696 {
697 v4f correction;
698 q_axis_angle( correction, axis, acosf(angle)*0.3f );
699 q_mul( correction, player.rb.q, player.rb.q );
700 }
701
702 v3_muladds( player.rb.v, player.rb.up,
703 -k_downforce*ktimestep, player.rb.v );
704
705 player_physics_control();
706
707 if( !player.jump_charge && player.jump > 0.2f )
708 {
709 v3f jumpdir;
710
711 /* Launch more up if alignment is up else improve velocity */
712 float aup = fabsf(v3_dot( (v3f){0.0f,1.0f,0.0f}, player.rb.up )),
713 mod = 0.5f,
714 dir = mod + aup*(1.0f-mod);
715
716 v3_copy( player.rb.v, jumpdir );
717 v3_normalize( jumpdir );
718 v3_muls( jumpdir, 1.0f-dir, jumpdir );
719 v3_muladds( jumpdir, player.rb.up, dir, jumpdir );
720 v3_normalize( jumpdir );
721
722 float force = k_jump_force*player.jump;
723 v3_muladds( player.rb.v, jumpdir, force, player.rb.v );
724 player.jump = 0.0f;
725
726 player.jump_time = vg_time;
727
728 audio_lock();
729 audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
730 audio_player_set_position( &audio_player_extra, player.rb.co );
731 audio_player_set_vol( &audio_player_extra, 20.0f );
732 audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%4] );
733 audio_unlock();
734 }
735 }
736 else
737 {
738 player_physics_control_air();
739 }
740
741 if( !player.jump_charge )
742 {
743 player.jump -= k_jump_charge_speed * ktimestep;
744 }
745 player.jump_charge = 0;
746 player.jump = vg_clampf( player.jump, 0.0f, 1.0f );
747 }
748
749 static void player_do_motion(void)
750 {
751 float horizontal = vg_get_axis("horizontal"),
752 vertical = vg_get_axis("vertical");
753
754 if( player.on_board )
755 player_physics();
756 else
757 player_walk_physics();
758
759 /* Integrate velocity */
760 v3f prevco;
761 v3_copy( player.rb.co, prevco );
762
763 apply_gravity( player.rb.v, ktimestep );
764 v3_muladds( player.rb.co, player.rb.v, ktimestep, player.rb.co );
765
766 /* Real angular velocity integration */
767 v3_lerp( player.rb.w, (v3f){0.0f,0.0f,0.0f}, 0.125f, player.rb.w );
768 if( v3_length2( player.rb.w ) > 0.0f )
769 {
770 v4f rotation;
771 v3f axis;
772 v3_copy( player.rb.w, axis );
773
774 float mag = v3_length( axis );
775 v3_divs( axis, mag, axis );
776 q_axis_angle( rotation, axis, mag*k_rb_delta );
777 q_mul( rotation, player.rb.q, player.rb.q );
778 }
779
780 /* Faux angular velocity */
781 v4f rotate;
782
783 static float siY = 0.0f;
784 float lerpq = player.in_air? 0.04f: 0.3f;
785 siY = vg_lerpf( siY, player.iY, lerpq );
786
787 q_axis_angle( rotate, player.rb.up, siY );
788 q_mul( rotate, player.rb.q, player.rb.q );
789 player.iY = 0.0f;
790
791 /*
792 * Gate intersection, by tracing a line over the gate planes
793 */
794 for( int i=0; i<world.routes.gate_count; i++ )
795 {
796 struct route_gate *rg = &world.routes.gates[i];
797 teleport_gate *gate = &rg->gate;
798
799 if( gate_intersect( gate, player.rb.co, prevco ) )
800 {
801 m4x3_mulv( gate->transport, player.rb.co, player.rb.co );
802 m3x3_mulv( gate->transport, player.rb.v, player.rb.v );
803 m3x3_mulv( gate->transport, player.vl, player.vl );
804 m3x3_mulv( gate->transport, player.v_last, player.v_last );
805 m3x3_mulv( gate->transport, player.m, player.m );
806 m3x3_mulv( gate->transport, player.bob, player.bob );
807
808 v4f transport_rotation;
809 m3x3_q( gate->transport, transport_rotation );
810 q_mul( transport_rotation, player.rb.q, player.rb.q );
811
812 world_routes_activate_gate( i );
813 player.rb_gate_frame = player.rb;
814
815 m3x3_copy( player.vr, player.gate_vr_frame );
816 m3x3_copy( player.vr_pstep, player.gate_vr_pstep_frame );
817
818 audio_lock();
819 audio_play_oneshot( &audio_gate_lap, 1.0f );
820 audio_unlock();
821 break;
822 }
823 }
824
825 rb_update_transform( &player.rb );
826 }
827
828 /*
829 * Animation
830 */
831
832 static void player_animate_offboard(void)
833 {
834 mdl_keyframe apose[32], bpose[32];
835 struct skeleton *sk = &player.mdl.sk;
836
837 float walk_norm = (float)player.mdl.anim_walk->length/30.0f,
838 run_norm = (float)player.mdl.anim_run->length/30.0f,
839 t = player.walk_timer,
840 l = vg_get_axis("grabr") * 0.5f + 0.5f;
841
842 skeleton_sample_anim( sk, player.mdl.anim_walk, t*walk_norm, apose );
843 skeleton_sample_anim( sk, player.mdl.anim_run, t*run_norm, bpose );
844
845 skeleton_lerp_pose( sk, apose, bpose, l, apose );
846
847 float idle_walk = vg_minf( l * 10.0f, 1.0f);
848
849 skeleton_sample_anim( sk, player.mdl.anim_idle, vg_time*0.1f, bpose );
850 skeleton_lerp_pose( sk, apose, bpose, 1.0f-idle_walk, apose );
851
852 skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_defer_ik );
853 skeleton_apply_ik_pass( &player.mdl.sk );
854 skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_deffered_only );
855
856 v3_copy( player.mdl.sk.final_mtx[player.mdl.id_head-1][3],
857 player.mdl.cam_pos );
858
859 skeleton_apply_inverses( &player.mdl.sk );
860
861 m4x3f mtx;
862 v4f rot;
863 q_axis_angle( rot, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] - VG_PIf*0.5f );
864 q_m3x3( rot, mtx );
865 v3_copy( player.rb.to_world[3], mtx[3] );
866
867 skeleton_apply_transform( &player.mdl.sk, mtx );
868 skeleton_debug( &player.mdl.sk );
869 }
870
871 static void player_animate(void)
872 {
873 if( !player.on_board )
874 {
875 player_animate_offboard();
876 return;
877 }
878
879 /* Camera position */
880 v3_sub( player.rb.v, player.v_last, player.a );
881 v3_copy( player.rb.v, player.v_last );
882
883 v3_add( player.m, player.a, player.m );
884 v3_lerp( player.m, (v3f){0.0f,0.0f,0.0f}, 0.1f, player.m );
885
886 player.m[0] = vg_clampf( player.m[0], -2.0f, 2.0f );
887 player.m[1] = vg_clampf( player.m[1], -2.0f, 2.0f );
888 player.m[2] = vg_clampf( player.m[2], -2.0f, 2.0f );
889 v3_lerp( player.bob, player.m, 0.2f, player.bob );
890
891 /* Head */
892 float lslip = fabsf(player.slip);
893
894 float kheight = 2.0f,
895 kleg = 0.6f;
896
897 v3f offset;
898 v3_zero( offset );
899 m3x3_mulv( player.rb.to_local, player.bob, offset );
900
901 static float speed_wobble = 0.0f, speed_wobble_2 = 0.0f;
902
903 float kickspeed = vg_clampf(v3_length(player.rb.v)*(1.0f/40.0f), 0.0f, 1.0f);
904 float kicks = (vg_randf()-0.5f)*2.0f*kickspeed;
905 float sign = vg_signf( kicks );
906 speed_wobble = vg_lerpf( speed_wobble, kicks*kicks*sign, 0.1f );
907 speed_wobble_2 = vg_lerpf( speed_wobble_2, speed_wobble, 0.04f );
908
909 offset[0] *= 0.26f;
910 offset[0] += speed_wobble_2*3.0f;
911
912 offset[1] *= -0.3f;
913 offset[2] *= 0.01f;
914
915 offset[0] = vg_clampf( offset[0], -0.8f, 0.8f );
916 offset[1] = vg_clampf( offset[1], -0.5f, 0.0f );
917 offset[1] = 0.0f;
918
919 /*
920 * Animation blending
921 * ===========================================
922 */
923
924 /* scalar blending information */
925 float speed = v3_length( player.rb.v );
926
927 /* sliding */
928 {
929 float desired = vg_clampf( lslip, 0.0f, 1.0f );
930 player.fslide = vg_lerpf( player.fslide, desired, 0.04f );
931 }
932
933 /* movement information */
934 {
935 float dirz = player.reverse > 0.0f? 0.0f: 1.0f,
936 dirx = player.slip < 0.0f? 0.0f: 1.0f,
937 fly = player.in_air? 1.0f: 0.0f;
938
939 player.fdirz = vg_lerpf( player.fdirz, dirz, 0.04f );
940 player.fdirx = vg_lerpf( player.fdirx, dirx, 0.01f );
941 player.ffly = vg_lerpf( player.ffly, fly, 0.04f );
942 }
943
944 struct skeleton *sk = &player.mdl.sk;
945
946 mdl_keyframe apose[32], bpose[32];
947 mdl_keyframe ground_pose[32];
948 {
949 /* when the player is moving fast he will crouch down a little bit */
950 float stand = 1.0f - vg_clampf( speed * 0.03f, 0.0f, 1.0f );
951 player.fstand = vg_lerpf( player.fstand, stand, 0.1f );
952
953 /* stand/crouch */
954 float dir_frame = player.fdirz * (15.0f/30.0f),
955 stand_blend = offset[1]*-2.0f;
956
957 skeleton_sample_anim( sk, player.mdl.anim_stand, dir_frame, apose );
958 skeleton_sample_anim( sk, player.mdl.anim_highg, dir_frame, bpose );
959 skeleton_lerp_pose( sk, apose, bpose, stand_blend, apose );
960
961 /* sliding */
962 float slide_frame = player.fdirx * (15.0f/30.0f);
963 skeleton_sample_anim( sk, player.mdl.anim_slide, slide_frame, bpose );
964 skeleton_lerp_pose( sk, apose, bpose, player.fslide, apose );
965
966 /* pushing */
967 player.fpush = vg_lerpf( player.fpush, player.pushing, 0.1f );
968
969 float pt = player.push_time;
970 if( player.reverse > 0.0f )
971 skeleton_sample_anim( sk, player.mdl.anim_push, pt, bpose );
972 else
973 skeleton_sample_anim( sk, player.mdl.anim_push_reverse, pt, bpose );
974
975 skeleton_lerp_pose( sk, apose, bpose, player.fpush, apose );
976
977 /* trick setup */
978 float jump_start_frame = 14.0f/30.0f;
979 float setup_frame = player.jump * jump_start_frame,
980 setup_blend = vg_minf( player.jump*5.0f, 1.0f );
981
982 float jump_frame = (vg_time - player.jump_time) + jump_start_frame;
983 if( jump_frame >= jump_start_frame && jump_frame <= (40.0f/30.0f) )
984 setup_frame = jump_frame;
985
986 struct skeleton_anim *jump_anim = player.jump_dir?
987 player.mdl.anim_ollie:
988 player.mdl.anim_ollie_reverse;
989
990 skeleton_sample_anim_clamped( sk, jump_anim, setup_frame, bpose );
991 skeleton_lerp_pose( sk, apose, bpose, setup_blend, ground_pose );
992 }
993
994 mdl_keyframe air_pose[32];
995 {
996 float target = -vg_get_axis("horizontal");
997 player.fairdir = vg_lerpf( player.fairdir, target, 0.04f );
998
999 float air_frame = (player.fairdir*0.5f+0.5f) * (15.0f/30.0f);
1000
1001 skeleton_sample_anim( sk, player.mdl.anim_air, air_frame, apose );
1002
1003 static v2f grab_choice;
1004 v2_lerp( grab_choice, (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
1005 0.04f, grab_choice );
1006
1007 float ang = atan2f( grab_choice[0], grab_choice[1] ),
1008 ang_unit = (ang+VG_PIf) * (1.0f/VG_TAUf),
1009 grab_frame = ang_unit * (15.0f/30.0f);
1010
1011 skeleton_sample_anim( sk, player.mdl.anim_grabs, grab_frame, bpose );
1012 skeleton_lerp_pose( sk, apose, bpose, player.grab, air_pose );
1013 }
1014
1015 skeleton_lerp_pose( sk, ground_pose, air_pose, player.ffly, apose );
1016
1017 float add_grab_mod = player.ffly * player.grab;
1018
1019 /* additive effects */
1020 apose[player.mdl.id_hip-1].co[0] += offset[0]*add_grab_mod;
1021 apose[player.mdl.id_hip-1].co[2] += offset[2]*add_grab_mod;
1022 apose[player.mdl.id_ik_hand_l-1].co[0] += offset[0]*add_grab_mod;
1023 apose[player.mdl.id_ik_hand_l-1].co[2] += offset[2]*add_grab_mod;
1024 apose[player.mdl.id_ik_hand_r-1].co[0] += offset[0]*add_grab_mod;
1025 apose[player.mdl.id_ik_hand_r-1].co[2] += offset[2]*add_grab_mod;
1026 apose[player.mdl.id_ik_elbow_l-1].co[0] += offset[0]*add_grab_mod;
1027 apose[player.mdl.id_ik_elbow_l-1].co[2] += offset[2]*add_grab_mod;
1028 apose[player.mdl.id_ik_elbow_r-1].co[0] += offset[0]*add_grab_mod;
1029 apose[player.mdl.id_ik_elbow_r-1].co[2] += offset[2]*add_grab_mod;
1030
1031 skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_defer_ik );
1032 skeleton_apply_ik_pass( &player.mdl.sk );
1033 skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_deffered_only );
1034
1035 v3_copy( player.mdl.sk.final_mtx[player.mdl.id_head-1][3],
1036 player.mdl.cam_pos );
1037 skeleton_apply_inverses( &player.mdl.sk );
1038 skeleton_apply_transform( &player.mdl.sk, player.rb.to_world );
1039
1040 skeleton_debug( &player.mdl.sk );
1041 }
1042
1043 static void player_camera_update(void)
1044 {
1045 /* Update camera matrices */
1046 m4x3_identity( player.camera );
1047 m4x3_rotate_y( player.camera, -player.angles[0] );
1048 m4x3_rotate_x( player.camera, -player.angles[1] );
1049 v3_copy( player.camera_pos, player.camera[3] );
1050 m4x3_invert_affine( player.camera, player.camera_inverse );
1051 }
1052
1053 static void player_animate_death_cam(void)
1054 {
1055 v3f delta;
1056 v3f head_pos;
1057 v3_copy( player.mdl.ragdoll[0].rb.co, head_pos );
1058
1059 v3_sub( head_pos, player.camera_pos, delta );
1060 v3_normalize( delta );
1061
1062 v3f follow_pos;
1063 v3_muladds( head_pos, delta, -2.5f, follow_pos );
1064 v3_lerp( player.camera_pos, follow_pos, 0.1f, player.camera_pos );
1065
1066 /*
1067 * Make sure the camera stays above the ground
1068 */
1069 v3f min_height = {0.0f,1.0f,0.0f};
1070
1071 v3f sample;
1072 v3_add( player.camera_pos, min_height, sample );
1073 ray_hit hit;
1074 hit.dist = min_height[1]*2.0f;
1075
1076 if( ray_world( sample, (v3f){0.0f,-1.0f,0.0f}, &hit ))
1077 v3_add( hit.pos, min_height, player.camera_pos );
1078
1079 player.camera_pos[1] =
1080 vg_maxf( wrender.height + 2.0f, player.camera_pos[1] );
1081
1082 player.angles[0] = atan2f( delta[0], -delta[2] );
1083 player.angles[1] = -asinf( delta[1] );
1084 }
1085
1086 static void player_animate_camera(void)
1087 {
1088 static v3f lerp_cam = {0.0f,0.0f,0.0f};
1089 v3f cam_pos;
1090
1091 player.fonboard = vg_lerpf(player.fonboard, player.on_board, ktimestep*1.0f);
1092
1093 if( player.on_board )
1094 {
1095 v3f offs = { -0.4f, 0.15f, 0.0f };
1096 v3_lerp( lerp_cam, player.mdl.cam_pos, 0.8f, lerp_cam );
1097 v3_add( lerp_cam, offs, cam_pos );
1098
1099 /* Look angles */
1100 v3_lerp( player.vl, player.rb.v, 0.05f, player.vl );
1101
1102 float yaw = atan2f( player.vl[0], -player.vl[2] ),
1103 pitch = atan2f( -player.vl[1],
1104 sqrtf(
1105 player.vl[0]*player.vl[0] + player.vl[2]*player.vl[2]
1106 )) * 0.7f;
1107
1108 player.angles[0] = yaw;
1109 player.angles[1] = vg_lerpf( player.angles[1], pitch + 0.30f,
1110 player.fonboard );
1111
1112 /* Camera shake */
1113 static v2f shake_damp = {0.0f,0.0f};
1114 v2f shake = { vg_randf()-0.5f, vg_randf()-0.5f };
1115 v2_muls( shake, v3_length(player.rb.v)*0.3f
1116 * (1.0f+fabsf(player.slip)), shake);
1117
1118 v2_lerp( shake_damp, shake, 0.01f, shake_damp );
1119 shake_damp[0] *= 0.2f;
1120
1121 v2_muladds( player.angles, shake_damp, 0.1f, player.angles );
1122 m4x3_mulv( player.rb.to_world, cam_pos, player.camera_pos );
1123 }
1124 else
1125 {
1126 float speed = ktimestep * k_look_speed;
1127 player.angles[0] += vg_get_axis( "horizontal" ) * speed;
1128 player.angles[1] += vg_get_axis( "vertical" ) * speed;
1129
1130 player.angles[1] = vg_clampf( player.angles[1],
1131 -k_pitch_limit, k_pitch_limit );
1132
1133 float s = sinf(player.angles[0]) * 0.2f,
1134 c = -cosf(player.angles[0]) * 0.2f;
1135 v3f forward_dir = { s,0.15f,c };
1136
1137
1138 m4x3f mtx;
1139 v4f rot;
1140 q_axis_angle( rot, (v3f){0.0f,1.0f,0.0f},
1141 -player.angles[0] -VG_PIf*0.5f );
1142 q_m3x3( rot, mtx );
1143 v3_copy( player.rb.to_world[3], mtx[3] );
1144
1145 m4x3_mulv( mtx, player.mdl.cam_pos, cam_pos );
1146 v3_add( cam_pos, forward_dir, player.camera_pos );
1147 v3_lerp( player.vl, player.rb.v, 0.3f, player.vl );
1148 }
1149 }
1150
1151 /*
1152 * Audio
1153 */
1154 static void player_audio(void)
1155 {
1156 static int _ding = 0;
1157
1158 int last = _ding;
1159 _ding = glfwGetKey(vg_window, GLFW_KEY_C);
1160
1161 int trigger_ding = 0;
1162 if( _ding && !last )
1163 trigger_ding = 1;
1164
1165 static int _air = 0;
1166
1167 int l2 = _air;
1168 _air = player.in_air;
1169
1170 static double last_revert = -2000.0;
1171
1172
1173
1174
1175 audio_lock();
1176
1177 double revert_delta = vg_time - last_revert;
1178 if( player.on_board && (!_air && l2) && (fabsf(player.slip) > 0.5f) &&
1179 (revert_delta > 0.7) )
1180 {
1181 audio_player_set_position( &audio_player_extra, player.rb.co );
1182 audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
1183 audio_player_set_vol( &audio_player_extra, 2.0f );
1184 audio_player_playclip( &audio_player_extra, &audio_lands[rand()%5] );
1185
1186 last_revert = vg_time;
1187 }
1188
1189 static float air = 0.0f;
1190 air = vg_lerpf(air, player.in_air? 1.0f: 0.0f, 5.0f*ktimestep);
1191
1192 /* Spacial info */
1193 v3f ears = { 1.0f,0.0f,0.0f };
1194 v3f delta;
1195
1196 float *cam = player.camera[3],
1197 *pos = player.rb.co;
1198
1199 if( trigger_ding )
1200 audio_player_playclip( &audio_player_extra, &audio_ding );
1201
1202 audio_player_set_position( &audio_player0, player.rb.co );
1203 audio_player_set_position( &audio_player1, player.rb.co );
1204 audio_player_set_position( &audio_player2, player.rb.co );
1205 audio_player_set_position( &audio_player_gate, world.render_gate_pos );
1206
1207 v3_sub( player.rb.co, player.camera[3], delta );
1208 v3_normalize( delta );
1209 m3x3_mulv( player.camera, ears, ears );
1210
1211 /* TODO, Make function */
1212 v3_copy( ears, vg_audio.listener_ears );
1213 v3_copy( player.camera[3], vg_audio.listener_pos );
1214
1215 /* Tunnel / occlusion */
1216 audio_sample_occlusion( player.camera[3] );
1217
1218 if( freecam || player.is_dead || !player.on_board )
1219 {
1220 audio_player_set_vol( &audio_player0, 0.0f );
1221 audio_player_set_vol( &audio_player1, 0.0f );
1222 audio_player_set_vol( &audio_player2, 0.0f );
1223
1224 int walk_phase = 0;
1225 if( vg_fractf(player.walk_timer) > 0.5f )
1226 walk_phase = 1;
1227 else
1228 walk_phase = 0;
1229
1230 if( (player.step_phase != walk_phase) && !player.in_air )
1231 {
1232 v3_copy( player.rb.co, player.last_step_pos );
1233
1234 audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
1235 audio_player_set_position( &audio_player_extra, player.rb.co );
1236 audio_player_set_vol( &audio_player_extra, 6.0f );
1237 audio_player_playclip( &audio_player_extra,
1238 &audio_footsteps[rand()%4] );
1239 }
1240
1241 player.step_phase = walk_phase;
1242 }
1243 else
1244 {
1245 /* Composite */
1246 float speed = vg_minf(v3_length( player.rb.v )*0.1f,1.0f),
1247 attn = speed,
1248 slide = vg_clampf( fabsf(player.slip), 0.0f, 1.0f ),
1249 vol0 = (1.0f-air)*attn*(1.0f-slide),
1250 vol1 = air *attn,
1251 vol2 = (1.0f-air)*attn*slide;
1252
1253 audio_player_set_vol( &audio_player0, vol0 );
1254 audio_player_set_vol( &audio_player1, vol1 );
1255 audio_player_set_vol( &audio_player2, vol2 );
1256
1257 float reverb_amt = vol0 * audio_occlusion_current * 0.5f;
1258 audio_player_set_pan( &audio_player3, 0.0f );
1259 audio_player_set_vol( &audio_player3, reverb_amt );
1260 }
1261
1262 #if 0
1263 world_audio_update( cam, ears );
1264 #endif
1265 audio_unlock();
1266 }
1267
1268 /*
1269 * Public Endpoints
1270 */
1271 static float *player_cam_pos(void)
1272 {
1273 return player.camera_pos;
1274 }
1275
1276 static int reset_player( int argc, char const *argv[] )
1277 {
1278 struct respawn_point *rp = NULL, *r;
1279
1280 if( argc == 1 )
1281 {
1282 for( int i=0; i<world.spawn_count; i++ )
1283 {
1284 r = &world.spawns[i];
1285 if( !strcmp( r->name, argv[0] ) )
1286 {
1287 rp = r;
1288 break;
1289 }
1290 }
1291
1292 if( !rp )
1293 vg_warn( "No spawn named '%s'\n", argv[0] );
1294 }
1295
1296 if( !rp )
1297 {
1298 float min_dist = INFINITY;
1299
1300 for( int i=0; i<world.spawn_count; i++ )
1301 {
1302 r = &world.spawns[i];
1303 float d = v3_dist2( r->co, player.rb.co );
1304
1305 vg_info( "Dist %s : %f\n", r->name, d );
1306 if( d < min_dist )
1307 {
1308 min_dist = d;
1309 rp = r;
1310 }
1311 }
1312 }
1313
1314 if( !rp )
1315 {
1316 vg_error( "No spawn found\n" );
1317 if( !world.spawn_count )
1318 return 0;
1319
1320 rp = &world.spawns[0];
1321 }
1322
1323 v4_copy( rp->q, player.rb.q );
1324 v3_copy( rp->co, player.rb.co );
1325
1326 player.vswitch = 1.0f;
1327 player.slip_last = 0.0f;
1328 player.is_dead = 0;
1329 player.in_air = 1;
1330 m3x3_identity( player.vr );
1331
1332 player.mdl.shoes[0] = 1;
1333 player.mdl.shoes[1] = 1;
1334
1335 rb_update_transform( &player.rb );
1336 m3x3_mulv( player.rb.to_world, (v3f){ 0.0f, 0.0f, -1.2f }, player.rb.v );
1337 m3x3_identity( player.gate_vr_frame );
1338 m3x3_identity( player.gate_vr_pstep_frame );
1339
1340 player.rb_gate_frame = player.rb;
1341 return 1;
1342 }
1343
1344 static void player_update(void)
1345 {
1346 for( int i=0; i<player.land_log_count; i++ )
1347 draw_cross( player.land_target_log[i],
1348 player.land_target_colours[i], 0.25f);
1349
1350 if( vg_get_axis("grabl")>0.0f)
1351 {
1352 player.rb = player.rb_gate_frame;
1353 m3x3_copy( player.gate_vr_frame, player.vr );
1354 m3x3_copy( player.gate_vr_pstep_frame, player.vr_pstep );
1355 player.is_dead = 0;
1356 player.in_air = 1;
1357 m3x3_identity( player.vr );
1358
1359 player.mdl.shoes[0] = 1;
1360 player.mdl.shoes[1] = 1;
1361
1362 world_routes_notify_reset();
1363 }
1364
1365 if( vg_get_button_down( "switchmode" ) )
1366 {
1367 player.on_board ^= 0x1;
1368 }
1369
1370 if( (glfwGetKey( vg_window, GLFW_KEY_O ) || (player.rb.co[1] < 0.0f)) &&
1371 !player.is_dead)
1372 {
1373 character_ragdoll_copypose( &player.mdl, player.rb.v );
1374 player.is_dead = 1;
1375 }
1376
1377 if( player.is_dead )
1378 {
1379 character_ragdoll_iter( &player.mdl );
1380 character_debug_ragdoll( &player.mdl );
1381
1382 if( !freecam )
1383 player_animate_death_cam();
1384 }
1385 else
1386 {
1387 player_do_motion();
1388 player_animate();
1389
1390 if( !freecam )
1391 player_animate_camera();
1392 }
1393
1394 if( freecam )
1395 player_freecam();
1396
1397 player_camera_update();
1398 player_audio();
1399 }
1400
1401 static void draw_player(void)
1402 {
1403 if( player.is_dead )
1404 character_mimic_ragdoll( &player.mdl );
1405
1406 shader_viewchar_use();
1407 vg_tex2d_bind( &tex_characters, 0 );
1408 shader_viewchar_uTexMain( 0 );
1409 shader_viewchar_uCamera( player.camera[3] );
1410 shader_viewchar_uPv( vg_pv );
1411 shader_link_standard_ub( _shader_viewchar.id, 2 );
1412 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms,
1413 player.mdl.sk.bone_count,
1414 0,
1415 (float *)player.mdl.sk.final_mtx );
1416
1417 mesh_bind( &player.mdl.mesh );
1418 mesh_draw( &player.mdl.mesh );
1419 }
1420
1421 #endif /* PLAYER_H */