7 //#include "character.h"
8 #include "player_model.h"
17 k_board_radius
= 0.3f
,
18 k_board_length
= 0.45f
,
19 k_board_allowance
= 0.04f
,
20 k_friction_lat
= 8.8f
,
21 k_friction_resistance
= 0.01f
,
22 k_max_push_speed
= 16.0f
,
24 k_push_cycle_rate
= 8.0f
,
25 k_steer_ground
= 2.5f
,
27 k_steer_air_lerp
= 0.3f
,
28 k_pump_force
= 000.0f
,
30 k_jump_charge_speed
= (1.0f
/1.0f
),
33 static int freecam
= 0;
34 static int walk_grid_iterations
= 1;
35 static float fc_speed
= 10.0f
;
40 rigidbody rb
, collide_front
, collide_back
, rb_gate_frame
;
42 v3f a
, v_last
, m
, bob
, vl
;
45 float vswitch
, slip
, slip_last
,
48 float iY
; /* Yaw inertia */
49 int in_air
, is_dead
, on_board
;
54 float pushing
, push_time
;
59 v3f land_target_log
[22];
60 u32 land_target_colours
[22];
66 v3f handl_target
, handr_target
,
72 v3f camera_pos
, smooth_localcam
;
74 m4x3f camera
, camera_inverse
;
90 .collide_front
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
},
91 .collide_back
= { .type
= k_rb_shape_sphere
, .inf
.sphere
.radius
= 0.3f
}
100 * Free camera movement
103 static void player_mouseview(void)
105 if( gui_want_mouse() )
108 static v2f mouse_last
,
109 view_vel
= { 0.0f
, 0.0f
};
111 if( vg_get_button_down( "primary" ) )
112 v2_copy( vg_mouse
, mouse_last
);
114 else if( vg_get_button( "primary" ) )
117 v2_sub( vg_mouse
, mouse_last
, delta
);
118 v2_copy( vg_mouse
, mouse_last
);
120 v2_muladds( view_vel
, delta
, 0.001f
, view_vel
);
123 v2_muladds( view_vel
,
124 (v2f
){ vg_get_axis("h1"), vg_get_axis("v1") },
126 v2_muls( view_vel
, 0.93f
, view_vel
);
127 v2_add( view_vel
, player
.angles
, player
.angles
);
128 player
.angles
[1] = vg_clampf( player
.angles
[1], -VG_PIf
*0.5f
, VG_PIf
*0.5f
);
131 static void player_freecam(void)
135 float movespeed
= fc_speed
;
136 v3f lookdir
= { 0.0f
, 0.0f
, -1.0f
},
137 sidedir
= { 1.0f
, 0.0f
, 0.0f
};
139 m3x3_mulv( player
.camera
, lookdir
, lookdir
);
140 m3x3_mulv( player
.camera
, sidedir
, sidedir
);
142 static v3f move_vel
= { 0.0f
, 0.0f
, 0.0f
};
143 if( vg_get_button( "forward" ) )
144 v3_muladds( move_vel
, lookdir
, ktimestep
* movespeed
, move_vel
);
145 if( vg_get_button( "back" ) )
146 v3_muladds( move_vel
, lookdir
, ktimestep
*-movespeed
, move_vel
);
147 if( vg_get_button( "left" ) )
148 v3_muladds( move_vel
, sidedir
, ktimestep
*-movespeed
, move_vel
);
149 if( vg_get_button( "right" ) )
150 v3_muladds( move_vel
, sidedir
, ktimestep
* movespeed
, move_vel
);
152 v3_muls( move_vel
, 0.7f
, move_vel
);
153 v3_add( move_vel
, player
.camera_pos
, player
.camera_pos
);
157 * Player Physics Implementation
160 static void apply_gravity( v3f vel
, float const timestep
)
162 v3f gravity
= { 0.0f
, -9.6f
, 0.0f
};
163 v3_muladds( vel
, gravity
, timestep
, vel
);
167 * TODO: The angle bias should become greater when launching from a steeper
168 * angle and skewed towords more 'downwards' angles when launching from
169 * shallower trajectories
171 * it should also be tweaked by the controller left stick being pushed
174 static void player_start_air(void)
181 float pstep
= ktimestep
*10.0f
;
182 float best_velocity_delta
= -9999.9f
;
183 float k_bias
= 0.96f
;
186 v3_cross( player
.rb
.up
, player
.rb
.v
, axis
);
187 v3_normalize( axis
);
188 player
.land_log_count
= 0;
190 m3x3_identity( player
.vr
);
192 for( int m
=-3;m
<=12; m
++ )
194 float vmod
= ((float)m
/ 15.0f
)*0.09f
;
197 v3_copy( player
.rb
.co
, pco
);
198 v3_muls( player
.rb
.v
, k_bias
, pv
);
201 * Try different 'rotations' of the velocity to find the best possible
202 * landing normal. This conserves magnitude at the expense of slightly
203 * unrealistic results
209 q_axis_angle( vr_q
, axis
, vmod
);
212 m3x3_mulv( vr
, pv
, pv
);
213 v3_muladds( pco
, pv
, pstep
, pco
);
215 for( int i
=0; i
<50; i
++ )
217 v3_copy( pco
, pco1
);
218 apply_gravity( pv
, pstep
);
220 m3x3_mulv( vr
, pv
, pv
);
221 v3_muladds( pco
, pv
, pstep
, pco
);
226 v3_sub( pco
, pco1
, vdir
);
227 contact
.dist
= v3_length( vdir
);
228 v3_divs( vdir
, contact
.dist
, vdir
);
230 if( ray_world( pco1
, vdir
, &contact
))
232 float land_delta
= v3_dot( pv
, contact
.normal
);
233 u32 scolour
= (u8
)(vg_minf(-land_delta
* 2.0f
, 255.0f
));
235 /* Bias prediction towords ramps */
236 if( ray_hit_is_ramp( &contact
) )
239 scolour
|= 0x0000a000;
242 if( (land_delta
< 0.0f
) && (land_delta
> best_velocity_delta
) )
244 best_velocity_delta
= land_delta
;
246 v3_copy( contact
.pos
, player
.land_target
);
248 m3x3_copy( vr
, player
.vr_pstep
);
249 q_axis_angle( vr_q
, axis
, vmod
*0.1f
);
250 q_m3x3( vr_q
, player
.vr
);
253 v3_copy( contact
.pos
,
254 player
.land_target_log
[player
.land_log_count
] );
255 player
.land_target_colours
[player
.land_log_count
] =
256 0xff000000 | scolour
;
258 player
.land_log_count
++;
266 static void draw_cross(v3f pos
,u32 colour
, float scale
)
269 v3_add( (v3f
){ scale
,0.0f
,0.0f
}, pos
, p0
);
270 v3_add( (v3f
){-scale
,0.0f
,0.0f
}, pos
, p1
);
271 vg_line( p0
, p1
, colour
);
272 v3_add( (v3f
){0.0f
, scale
,0.0f
}, pos
, p0
);
273 v3_add( (v3f
){0.0f
,-scale
,0.0f
}, pos
, p1
);
274 vg_line( p0
, p1
, colour
);
275 v3_add( (v3f
){0.0f
,0.0f
, scale
}, pos
, p0
);
276 v3_add( (v3f
){0.0f
,0.0f
,-scale
}, pos
, p1
);
277 vg_line( p0
, p1
, colour
);
280 static void player_physics_control(void)
283 * Computing localized friction forces for controlling the character
284 * Friction across X is significantly more than Z
288 m3x3_mulv( player
.rb
.to_local
, player
.rb
.v
, vel
);
291 if( fabsf(vel
[2]) > 0.01f
)
292 slip
= fabsf(-vel
[0] / vel
[2]) * vg_signf(vel
[0]);
294 if( fabsf( slip
) > 1.2f
)
295 slip
= vg_signf( slip
) * 1.2f
;
297 player
.reverse
= -vg_signf(vel
[2]);
299 float substep
= ktimestep
* 0.2f
;
300 float fwd_resistance
= (vg_get_button( "break" )? 5.0f
: 0.02f
) * -substep
;
302 for( int i
=0; i
<5; i
++ )
304 vel
[2] = stable_force( vel
[2], vg_signf( vel
[2] ) * fwd_resistance
);
305 vel
[0] = stable_force( vel
[0],
306 vg_signf( vel
[0] ) * -k_friction_lat
*substep
);
309 static double start_push
= 0.0;
310 if( vg_get_button_down( "push" ) )
311 start_push
= vg_time
;
313 if( vg_get_button( "jump" ) )
315 player
.jump
+= ktimestep
* k_jump_charge_speed
;
316 player
.jump_charge
= 1;
319 if( !vg_get_button("break") && vg_get_button( "push" ) )
321 player
.pushing
= 1.0f
;
322 player
.push_time
= vg_time
-start_push
;
324 float cycle_time
= player
.push_time
*k_push_cycle_rate
,
325 amt
= k_push_accel
* (sinf(cycle_time
)*0.5f
+0.5f
)*ktimestep
,
326 current
= v3_length( vel
),
327 new_vel
= vg_minf( current
+ amt
, k_max_push_speed
);
329 new_vel
-= vg_minf(current
, k_max_push_speed
);
330 vel
[2] -= new_vel
* player
.reverse
;
334 static float previous
= 0.0f
;
335 float delta
= previous
- player
.grab
,
336 pump
= delta
* k_pump_force
*ktimestep
;
337 previous
= player
.grab
;
340 v3_muladds( player
.rb
.co
, player
.rb
.up
, pump
, p1
);
341 vg_line( player
.rb
.co
, p1
, 0xff0000ff );
346 m3x3_mulv( player
.rb
.to_world
, vel
, player
.rb
.v
);
348 float steer
= vg_get_axis( "horizontal" );
349 player
.iY
-= vg_signf(steer
)*powf(steer
,2.0f
) * k_steer_ground
* ktimestep
;
351 v2_lerp( player
.board_xy
, (v2f
){ slip
*0.25f
, 0.0f
},
352 ktimestep
*5.0f
, player
.board_xy
);
355 static void player_physics_control_air(void)
357 m3x3_mulv( player
.vr
, player
.rb
.v
, player
.rb
.v
);
358 draw_cross( player
.land_target
, 0xff0000ff, 0.25f
);
365 float pstep
= ktimestep
*10.0f
;
368 v3_copy( player
.rb
.co
, pco
);
369 v3_copy( player
.rb
.v
, pv
);
371 float time_to_impact
= 0.0f
;
372 float limiter
= 1.0f
;
374 for( int i
=0; i
<50; i
++ )
376 v3_copy( pco
, pco1
);
377 m3x3_mulv( player
.vr_pstep
, pv
, pv
);
378 apply_gravity( pv
, pstep
);
379 v3_muladds( pco
, pv
, pstep
, pco
);
381 //vg_line( pco, pco1, i&0x1?0xff000000:0xffffffff );
386 v3_sub( pco
, pco1
, vdir
);
387 contact
.dist
= v3_length( vdir
);
388 v3_divs( vdir
, contact
.dist
, vdir
);
390 float orig_dist
= contact
.dist
;
391 if( ray_world( pco1
, vdir
, &contact
))
393 float angle
= v3_dot( player
.rb
.up
, contact
.normal
);
395 v3_cross( player
.rb
.up
, contact
.normal
, axis
);
397 time_to_impact
+= (contact
.dist
/orig_dist
)*pstep
;
398 limiter
= vg_minf( 5.0f
, time_to_impact
)/5.0f
;
399 limiter
= 1.0f
-limiter
;
401 limiter
= 1.0f
-limiter
;
406 q_axis_angle( correction
, axis
, acosf(angle
)*0.05f
*(1.0f
-limiter
) );
407 q_mul( correction
, player
.rb
.q
, player
.rb
.q
);
410 draw_cross( contact
.pos
, 0xffff0000, 0.25f
);
413 time_to_impact
+= pstep
;
416 player
.iY
-= vg_get_axis( "horizontal" ) * k_steer_air
* ktimestep
;
418 float iX
= vg_get_axis( "vertical" ) *
419 player
.reverse
* k_steer_air
* limiter
* ktimestep
;
421 static float siX
= 0.0f
;
422 siX
= vg_lerpf( siX
, iX
, k_steer_air_lerp
);
425 q_axis_angle( rotate
, player
.rb
.right
, siX
);
426 q_mul( rotate
, player
.rb
.q
, player
.rb
.q
);
429 v2f target
= {0.0f
,0.0f
};
430 v2_muladds( target
, (v2f
){ vg_get_axis("h1"), vg_get_axis("v1") },
431 player
.grab
, target
);
432 v2_lerp( player
.board_xy
, target
, ktimestep
*3.0f
, player
.board_xy
);
435 static void player_init(void)
437 rb_init( &player
.collide_front
);
438 rb_init( &player
.collide_back
);
441 static void player_physics(void)
444 * Update collision fronts
447 rigidbody
*rbf
= &player
.collide_front
,
448 *rbb
= &player
.collide_back
;
450 m3x3_copy( player
.rb
.to_world
, player
.collide_front
.to_world
);
451 m3x3_copy( player
.rb
.to_world
, player
.collide_back
.to_world
);
453 player
.air_blend
= vg_lerpf( player
.air_blend
, player
.in_air
, 0.1f
);
454 float h
= player
.air_blend
*0.2f
;
456 m4x3_mulv( player
.rb
.to_world
, (v3f
){0.0f
,h
,-k_board_length
}, rbf
->co
);
457 v3_copy( rbf
->co
, rbf
->to_world
[3] );
458 m4x3_mulv( player
.rb
.to_world
, (v3f
){0.0f
,h
, k_board_length
}, rbb
->co
);
459 v3_copy( rbb
->co
, rbb
->to_world
[3] );
461 m4x3_invert_affine( rbf
->to_world
, rbf
->to_local
);
462 m4x3_invert_affine( rbb
->to_world
, rbb
->to_local
);
464 rb_update_bounds( rbf
);
465 rb_update_bounds( rbb
);
467 rb_debug( rbf
, 0xff00ffff );
468 rb_debug( rbb
, 0xffffff00 );
473 len
+= rb_sphere_scene( rbf
, &world
.rb_geo
, manifold
+len
);
474 len
+= rb_sphere_scene( rbb
, &world
.rb_geo
, manifold
+len
);
476 rb_presolve_contacts( manifold
, len
);
477 v3f surface_avg
= {0.0f
, 0.0f
, 0.0f
};
485 for( int i
=0; i
<len
; i
++ )
487 v3_add( manifold
[i
].n
, surface_avg
, surface_avg
);
490 if( manifold
[i
].element_id
<= world
.sm_geo_std_oob
.vertex_count
)
493 character_ragdoll_copypose( &player
.mdl
, player
.rb
.v
);
499 v3_normalize( surface_avg
);
501 if( v3_dot( player
.rb
.v
, surface_avg
) > 0.5f
)
509 for( int j
=0; j
<5; j
++ )
511 for( int i
=0; i
<len
; i
++ )
513 struct contact
*ct
= &manifold
[i
];
516 v3_sub( ct
->co
, player
.rb
.co
, delta
);
517 v3_cross( player
.rb
.w
, delta
, dv
);
518 v3_add( player
.rb
.v
, dv
, dv
);
520 float vn
= -v3_dot( dv
, ct
->n
);
523 float temp
= ct
->norm_impulse
;
524 ct
->norm_impulse
= vg_maxf( temp
+ vn
, 0.0f
);
525 vn
= ct
->norm_impulse
- temp
;
528 v3_muls( ct
->n
, vn
, impulse
);
530 if( fabsf(v3_dot( impulse
, player
.rb
.forward
)) > 10.0f
||
531 fabsf(v3_dot( impulse
, player
.rb
.up
)) > 50.0f
)
534 character_ragdoll_copypose( &player
.mdl
, player
.rb
.v
);
538 v3_add( impulse
, player
.rb
.v
, player
.rb
.v
);
539 v3_cross( delta
, impulse
, impulse
);
542 * W Impulses are limited to the Y and X axises, we don't really want
543 * roll angular velocities being included.
545 * Can also tweak the resistance of each axis here by scaling the wx,wy
549 float wy
= v3_dot( player
.rb
.up
, impulse
),
550 wx
= v3_dot( player
.rb
.right
, impulse
)*1.5f
;
552 v3_muladds( player
.rb
.w
, player
.rb
.up
, wy
, player
.rb
.w
);
553 v3_muladds( player
.rb
.w
, player
.rb
.right
, wx
, player
.rb
.w
);
557 float grabt
= vg_get_axis( "grabr" )*0.5f
+0.5f
;
558 player
.grab
= vg_lerpf( player
.grab
, grabt
, 0.14f
);
559 player
.pushing
= 0.0f
;
564 float angle
= v3_dot( player
.rb
.up
, surface_avg
);
565 v3_cross( player
.rb
.up
, surface_avg
, axis
);
567 //float cz = v3_dot( player.rb.forward, axis );
568 //v3_muls( player.rb.forward, cz, axis );
573 q_axis_angle( correction
, axis
, acosf(angle
)*0.3f
);
574 q_mul( correction
, player
.rb
.q
, player
.rb
.q
);
577 v3_muladds( player
.rb
.v
, player
.rb
.up
,
578 -k_downforce
*ktimestep
, player
.rb
.v
);
580 player_physics_control();
582 if( !player
.jump_charge
&& player
.jump
> 0.2f
)
584 v3_muladds( player
.rb
.v
, player
.rb
.up
, k_jump_force
*player
.jump
,
587 player
.jump_time
= vg_time
;
592 player_physics_control_air();
595 if( !player
.jump_charge
)
597 player
.jump
-= k_jump_charge_speed
* ktimestep
;
599 player
.jump_charge
= 0;
600 player
.jump
= vg_clampf( player
.jump
, 0.0f
, 1.0f
);
603 static void player_do_motion(void)
605 float horizontal
= vg_get_axis("horizontal"),
606 vertical
= vg_get_axis("vertical");
610 /* Integrate velocity */
612 v3_copy( player
.rb
.co
, prevco
);
614 apply_gravity( player
.rb
.v
, ktimestep
);
615 v3_muladds( player
.rb
.co
, player
.rb
.v
, ktimestep
, player
.rb
.co
);
617 /* Real angular velocity integration */
618 v3_lerp( player
.rb
.w
, (v3f
){0.0f
,0.0f
,0.0f
}, 0.125f
, player
.rb
.w
);
619 if( v3_length2( player
.rb
.w
) > 0.0f
)
623 v3_copy( player
.rb
.w
, axis
);
625 float mag
= v3_length( axis
);
626 v3_divs( axis
, mag
, axis
);
627 q_axis_angle( rotation
, axis
, mag
*k_rb_delta
);
628 q_mul( rotation
, player
.rb
.q
, player
.rb
.q
);
631 /* Faux angular velocity */
634 static float siY
= 0.0f
;
635 float lerpq
= player
.in_air
? 0.04f
: 0.3f
;
636 siY
= vg_lerpf( siY
, player
.iY
, lerpq
);
638 q_axis_angle( rotate
, player
.rb
.up
, siY
);
639 q_mul( rotate
, player
.rb
.q
, player
.rb
.q
);
643 * Gate intersection, by tracing a line over the gate planes
645 for( int i
=0; i
<world
.routes
.gate_count
; i
++ )
647 struct route_gate
*rg
= &world
.routes
.gates
[i
];
648 teleport_gate
*gate
= &rg
->gate
;
650 if( gate_intersect( gate
, player
.rb
.co
, prevco
) )
652 m4x3_mulv( gate
->transport
, player
.rb
.co
, player
.rb
.co
);
653 m3x3_mulv( gate
->transport
, player
.rb
.v
, player
.rb
.v
);
654 m3x3_mulv( gate
->transport
, player
.vl
, player
.vl
);
655 m3x3_mulv( gate
->transport
, player
.v_last
, player
.v_last
);
656 m3x3_mulv( gate
->transport
, player
.m
, player
.m
);
657 m3x3_mulv( gate
->transport
, player
.bob
, player
.bob
);
659 v4f transport_rotation
;
660 m3x3_q( gate
->transport
, transport_rotation
);
661 q_mul( transport_rotation
, player
.rb
.q
, player
.rb
.q
);
663 world_routes_activate_gate( i
);
664 player
.rb_gate_frame
= player
.rb
;
669 rb_update_transform( &player
.rb
);
676 static void player_animate(void)
678 /* Camera position */
679 v3_sub( player
.rb
.v
, player
.v_last
, player
.a
);
680 v3_copy( player
.rb
.v
, player
.v_last
);
682 v3_add( player
.m
, player
.a
, player
.m
);
683 v3_lerp( player
.m
, (v3f
){0.0f
,0.0f
,0.0f
}, 0.1f
, player
.m
);
685 player
.m
[0] = vg_clampf( player
.m
[0], -2.0f
, 2.0f
);
686 player
.m
[1] = vg_clampf( player
.m
[1], -2.0f
, 2.0f
);
687 player
.m
[2] = vg_clampf( player
.m
[2], -2.0f
, 2.0f
);
688 v3_lerp( player
.bob
, player
.m
, 0.2f
, player
.bob
);
691 float lslip
= fabsf(player
.slip
);
693 float kheight
= 2.0f
,
698 m3x3_mulv( player
.rb
.to_local
, player
.bob
, offset
);
700 static float speed_wobble
= 0.0f
, speed_wobble_2
= 0.0f
;
702 float kickspeed
= vg_clampf(v3_length(player
.rb
.v
)*(1.0f
/40.0f
), 0.0f
, 1.0f
);
703 float kicks
= (vg_randf()-0.5f
)*2.0f
*kickspeed
;
704 float sign
= vg_signf( kicks
);
705 speed_wobble
= vg_lerpf( speed_wobble
, kicks
*kicks
*sign
, 0.1f
);
706 speed_wobble_2
= vg_lerpf( speed_wobble_2
, speed_wobble
, 0.04f
);
709 offset
[0] += speed_wobble_2
*3.0f
;
714 offset
[0] = vg_clampf( offset
[0], -0.8f
, 0.8f
);
715 offset
[1] = vg_clampf( offset
[1], -0.5f
, 0.0f
);
720 * ===========================================
723 /* scalar blending information */
724 float speed
= v3_length( player
.rb
.v
);
728 float desired
= vg_clampf( lslip
, 0.0f
, 1.0f
);
729 player
.fslide
= vg_lerpf( player
.fslide
, desired
, 0.04f
);
732 /* movement information */
734 float dirz
= player
.reverse
> 0.0f
? 0.0f
: 1.0f
,
735 dirx
= player
.slip
< 0.0f
? 0.0f
: 1.0f
,
736 fly
= player
.in_air
? 1.0f
: 0.0f
;
738 player
.fdirz
= vg_lerpf( player
.fdirz
, dirz
, 0.04f
);
739 player
.fdirx
= vg_lerpf( player
.fdirx
, dirx
, 0.01f
);
740 player
.ffly
= vg_lerpf( player
.ffly
, fly
, 0.04f
);
743 struct skeleton
*sk
= &player
.mdl
.sk
;
745 mdl_keyframe apose
[32], bpose
[32];
746 mdl_keyframe ground_pose
[32];
748 /* when the player is moving fast he will crouch down a little bit */
749 float stand
= 1.0f
- vg_clampf( speed
* 0.03f
, 0.0f
, 1.0f
);
750 player
.fstand
= vg_lerpf( player
.fstand
, stand
, 0.1f
);
753 float dir_frame
= player
.fdirz
* (15.0f
/30.0f
),
754 stand_blend
= offset
[1]*-2.0f
;
756 skeleton_sample_anim( sk
, player
.mdl
.anim_stand
, dir_frame
, apose
);
757 skeleton_sample_anim( sk
, player
.mdl
.anim_highg
, dir_frame
, bpose
);
758 skeleton_lerp_pose( sk
, apose
, bpose
, stand_blend
, apose
);
761 float slide_frame
= player
.fdirx
* (15.0f
/30.0f
);
762 skeleton_sample_anim( sk
, player
.mdl
.anim_slide
, slide_frame
, bpose
);
763 skeleton_lerp_pose( sk
, apose
, bpose
, player
.fslide
, apose
);
766 player
.fpush
= vg_lerpf( player
.fpush
, player
.pushing
, 0.1f
);
768 float pt
= player
.push_time
;
769 if( player
.reverse
> 0.0f
)
770 skeleton_sample_anim( sk
, player
.mdl
.anim_push
, pt
, bpose
);
772 skeleton_sample_anim( sk
, player
.mdl
.anim_push_reverse
, pt
, bpose
);
774 skeleton_lerp_pose( sk
, apose
, bpose
, player
.fpush
, apose
);
777 float setup_frame
= player
.jump
* (12.0f
/30.0f
),
778 setup_blend
= vg_minf( player
.jump
*5.0f
, 1.0f
);
780 float jump_frame
= (vg_time
- player
.jump_time
) + (12.0f
/30.0f
);
781 if( jump_frame
>= (12.0f
/30.0f
) && jump_frame
<= (40.0f
/30.0f
) )
782 setup_frame
= jump_frame
;
784 skeleton_sample_anim_clamped( sk
, player
.mdl
.anim_ollie
,
785 setup_frame
, bpose
);
786 skeleton_lerp_pose( sk
, apose
, bpose
, setup_blend
, ground_pose
);
789 mdl_keyframe air_pose
[32];
791 float target
= -vg_get_axis("horizontal");
792 player
.fairdir
= vg_lerpf( player
.fairdir
, target
, 0.04f
);
794 float air_frame
= (player
.fairdir
*0.5f
+0.5f
) * (15.0f
/30.0f
);
796 skeleton_sample_anim( sk
, player
.mdl
.anim_air
, air_frame
, air_pose
);
799 skeleton_lerp_pose( sk
, ground_pose
, air_pose
, player
.ffly
, apose
);
801 /* additive effects */
802 apose
[player
.mdl
.id_hip
-1].co
[0] += offset
[0];
803 apose
[player
.mdl
.id_hip
-1].co
[2] += offset
[2];
804 apose
[player
.mdl
.id_ik_hand_l
-1].co
[0] += offset
[0];
805 apose
[player
.mdl
.id_ik_hand_l
-1].co
[2] += offset
[2];
806 apose
[player
.mdl
.id_ik_hand_r
-1].co
[0] += offset
[0];
807 apose
[player
.mdl
.id_ik_hand_r
-1].co
[2] += offset
[2];
808 apose
[player
.mdl
.id_ik_elbow_l
-1].co
[0] += offset
[0];
809 apose
[player
.mdl
.id_ik_elbow_l
-1].co
[2] += offset
[2];
810 apose
[player
.mdl
.id_ik_elbow_r
-1].co
[0] += offset
[0];
811 apose
[player
.mdl
.id_ik_elbow_r
-1].co
[2] += offset
[2];
813 skeleton_apply_pose( &player
.mdl
.sk
, apose
, k_anim_apply_defer_ik
);
814 skeleton_apply_ik_pass( &player
.mdl
.sk
);
815 skeleton_apply_pose( &player
.mdl
.sk
, apose
, k_anim_apply_deffered_only
);
817 v3_copy( player
.mdl
.sk
.final_mtx
[player
.mdl
.id_head
-1][3],
818 player
.mdl
.cam_pos
);
819 skeleton_apply_inverses( &player
.mdl
.sk
);
820 skeleton_apply_transform( &player
.mdl
.sk
, player
.rb
.to_world
);
822 skeleton_debug( &player
.mdl
.sk
);
825 static void player_camera_update(void)
827 /* Update camera matrices */
828 m4x3_identity( player
.camera
);
829 m4x3_rotate_y( player
.camera
, -player
.angles
[0] );
830 m4x3_rotate_x( player
.camera
, -player
.angles
[1] );
831 v3_copy( player
.camera_pos
, player
.camera
[3] );
832 m4x3_invert_affine( player
.camera
, player
.camera_inverse
);
835 static void player_animate_death_cam(void)
839 v3_copy( player
.mdl
.ragdoll
[0].rb
.co
, head_pos
);
841 v3_sub( head_pos
, player
.camera_pos
, delta
);
842 v3_normalize( delta
);
845 v3_muladds( head_pos
, delta
, -2.5f
, follow_pos
);
846 v3_lerp( player
.camera_pos
, follow_pos
, 0.1f
, player
.camera_pos
);
849 * Make sure the camera stays above the ground
851 v3f min_height
= {0.0f
,1.0f
,0.0f
};
854 v3_add( player
.camera_pos
, min_height
, sample
);
856 hit
.dist
= min_height
[1]*2.0f
;
858 if( ray_world( sample
, (v3f
){0.0f
,-1.0f
,0.0f
}, &hit
))
859 v3_add( hit
.pos
, min_height
, player
.camera_pos
);
861 player
.camera_pos
[1] =
862 vg_maxf( wrender
.height
+ 2.0f
, player
.camera_pos
[1] );
864 player
.angles
[0] = atan2f( delta
[0], -delta
[2] );
865 player
.angles
[1] = -asinf( delta
[1] );
868 static void player_animate_camera(void)
870 static v3f lerp_cam
= {0.0f
,0.0f
,0.0f
};
871 v3f offs
= { -0.4f
, 0.15f
, 0.0f
};
873 v3_lerp( lerp_cam
, player
.mdl
.cam_pos
, 0.8f
, lerp_cam
);
874 v3_add( lerp_cam
, offs
, offs
);
875 m4x3_mulv( player
.rb
.to_world
, offs
, player
.camera_pos
);
878 v3_lerp( player
.vl
, player
.rb
.v
, 0.05f
, player
.vl
);
880 float yaw
= atan2f( player
.vl
[0], -player
.vl
[2] ),
881 pitch
= atan2f( -player
.vl
[1],
883 player
.vl
[0]*player
.vl
[0] + player
.vl
[2]*player
.vl
[2]
886 player
.angles
[0] = yaw
;
887 player
.angles
[1] = pitch
+ 0.30f
;
890 static v2f shake_damp
= {0.0f
,0.0f
};
891 v2f shake
= { vg_randf()-0.5f
, vg_randf()-0.5f
};
892 v2_muls( shake
, v3_length(player
.rb
.v
)*0.3f
893 * (1.0f
+fabsf(player
.slip
)), shake
);
895 v2_lerp( shake_damp
, shake
, 0.01f
, shake_damp
);
896 shake_damp
[0] *= 0.2f
;
898 v2_muladds( player
.angles
, shake_damp
, 0.1f
, player
.angles
);
904 static void player_audio(void)
906 float speed
= vg_minf(v3_length( player
.rb
.v
)*0.1f
,1.0f
),
907 attn
= v3_dist( player
.rb
.co
, player
.camera
[3] )+1.0f
;
908 attn
= (1.0f
/(attn
*attn
)) * speed
;
910 static float air
= 0.0f
;
911 air
= vg_lerpf(air
, player
.in_air
? 1.0f
: 0.0f
, 0.7f
);
913 v3f ears
= { 1.0f
,0.0f
,0.0f
};
916 v3_sub( player
.rb
.co
, player
.camera
[3], delta
);
917 v3_normalize( delta
);
918 m3x3_mulv( player
.camera
, ears
, ears
);
920 float pan
= v3_dot( ears
, delta
);
921 audio_player0
.pan
= pan
;
922 audio_player1
.pan
= pan
;
923 audio_player2
.pan
= pan
;
927 audio_player0
.vol
= 0.0f
;
928 audio_player1
.vol
= 0.0f
;
929 audio_player2
.vol
= 0.0f
;
935 audio_player0
.vol
= 0.0f
;
936 audio_player1
.vol
= 0.0f
;
937 audio_player2
.vol
= 0.0f
;
941 float slide
= vg_clampf( fabsf(player
.slip
), 0.0f
, 1.0f
);
942 audio_player0
.vol
= (1.0f
-air
)*attn
*(1.0f
-slide
);
943 audio_player1
.vol
= air
*attn
;
944 audio_player2
.vol
= (1.0f
-air
)*attn
*slide
;
952 static float *player_cam_pos(void)
954 return player
.camera_pos
;
957 static int reset_player( int argc
, char const *argv
[] )
959 struct respawn_point
*rp
= NULL
, *r
;
963 for( int i
=0; i
<world
.spawn_count
; i
++ )
965 r
= &world
.spawns
[i
];
966 if( !strcmp( r
->name
, argv
[0] ) )
974 vg_warn( "No spawn named '%s'\n", argv
[0] );
979 float min_dist
= INFINITY
;
981 for( int i
=0; i
<world
.spawn_count
; i
++ )
983 r
= &world
.spawns
[i
];
984 float d
= v3_dist2( r
->co
, player
.rb
.co
);
986 vg_info( "Dist %s : %f\n", r
->name
, d
);
997 vg_error( "No spawn found\n" );
998 if( !world
.spawn_count
)
1001 rp
= &world
.spawns
[0];
1004 v4_copy( rp
->q
, player
.rb
.q
);
1005 v3_copy( rp
->co
, player
.rb
.co
);
1007 player
.vswitch
= 1.0f
;
1008 player
.slip_last
= 0.0f
;
1011 m3x3_identity( player
.vr
);
1013 player
.mdl
.shoes
[0] = 1;
1014 player
.mdl
.shoes
[1] = 1;
1016 rb_update_transform( &player
.rb
);
1017 m3x3_mulv( player
.rb
.to_world
, (v3f
){ 0.0f
, 0.0f
, -1.2f
}, player
.rb
.v
);
1019 player
.rb_gate_frame
= player
.rb
;
1023 static void player_update(void)
1025 for( int i
=0; i
<player
.land_log_count
; i
++ )
1026 draw_cross( player
.land_target_log
[i
],
1027 player
.land_target_colours
[i
], 0.25f
);
1029 if( vg_get_axis("grabl")>0.0f
)
1031 player
.rb
= player
.rb_gate_frame
;
1034 m3x3_identity( player
.vr
);
1036 player
.mdl
.shoes
[0] = 1;
1037 player
.mdl
.shoes
[1] = 1;
1039 world_routes_notify_reset();
1042 if( vg_get_button_down( "switchmode" ) )
1044 player
.on_board
^= 0x1;
1047 if( glfwGetKey( vg_window
, GLFW_KEY_O
) )
1049 character_ragdoll_copypose( &player
.mdl
, player
.rb
.v
);
1053 if( player
.is_dead
)
1055 character_ragdoll_iter( &player
.mdl
);
1056 character_debug_ragdoll( &player
.mdl
);
1059 player_animate_death_cam();
1063 if( player
.on_board
)
1069 player_animate_camera();
1076 player_camera_update();
1080 static void draw_player(void)
1082 if( player
.is_dead
)
1083 character_mimic_ragdoll( &player
.mdl
);
1085 shader_viewchar_use();
1086 vg_tex2d_bind( &tex_characters
, 0 );
1087 shader_viewchar_uTexMain( 0 );
1088 shader_viewchar_uCamera( player
.camera
[3] );
1089 shader_viewchar_uPv( vg_pv
);
1090 shader_link_standard_ub( _shader_viewchar
.id
, 2 );
1091 glUniformMatrix4x3fv( _uniform_viewchar_uTransforms
,
1092 player
.mdl
.sk
.bone_count
,
1094 (float *)player
.mdl
.sk
.final_mtx
);
1096 mesh_bind( &player
.mdl
.mesh
);
1097 mesh_draw( &player
.mdl
.mesh
);
1100 #endif /* PLAYER_H */