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