7 VG_STATIC
void player_walk_drop_in_vector( player_instance
*player
, v3f vec
)
9 struct player_walk
*w
= &player
->_walk
;
12 v3_cross( player
->basis
[1], w
->state
.drop_in_normal
, axis
);
13 v3_cross( axis
, w
->state
.drop_in_normal
, init_dir
);
14 v3_normalize( init_dir
);
15 v3_muls( init_dir
, 7.0f
, vec
);
18 VG_STATIC
float player_xyspeed2( player_instance
*player
)
21 v3_muladds( player
->rb
.v
, player
->basis
[1],
22 -v3_dot( player
->basis
[1], player
->rb
.v
), xy
);
24 return v3_length2(xy
);
27 VG_STATIC
void player_walk_generic_to_skate( player_instance
*player
,
28 enum skate_activity init
,
31 player
->subsystem
= k_player_subsystem_skate
;
33 struct player_walk
*w
= &player
->_walk
;
34 struct player_skate
*s
= &player
->_skate
;
38 if( player_xyspeed2(player
) < 0.1f
* 0.1f
)
39 q_mulv( player
->rb
.q
, (v3f
){0.0f
,0.0f
,1.6f
}, v
);
41 v3_copy( player
->rb
.v
, v
);
43 s
->state
.activity_prev
= k_skate_activity_ground
;
44 s
->state
.activity
= init
;
49 m3x3_mulv( player
->invbasis
, dir
, dir
);
51 q_axis_angle( player
->rb
.q
, (v3f
){0.0f
,1.0f
,0.0f
}, atan2f(-dir
[0],-dir
[2]) );
52 q_mul( player
->qbasis
, player
->rb
.q
, player
->rb
.q
);
53 q_normalize( player
->rb
.q
);
55 q_mulv( player
->rb
.q
, (v3f
){0.0f
,1.0f
,0.0f
}, s
->state
.cog
);
56 v3_add( s
->state
.cog
, player
->rb
.co
, s
->state
.cog
);
58 v3_copy( v
, s
->state
.cog_v
);
59 v3_copy( v
, player
->rb
.v
);
61 player__skate_reset_animator( player
);
62 player__skate_clear_mechanics( player
);
63 rb_update_transform( &player
->rb
);
64 v3_copy( (v3f
){yaw
,0.0f
,0.0f
}, s
->state
.trick_euler
);
66 if( init
== k_skate_activity_air
)
67 player__approximate_best_trajectory( player
);
70 VG_STATIC
void player_walk_drop_in_to_skate( player_instance
*player
)
73 player
->subsystem
= k_player_subsystem_skate
;
75 struct player_walk
*w
= &player
->_walk
;
76 struct player_skate
*s
= &player
->_skate
;
77 s
->state
.activity_prev
= k_skate_activity_ground
;
78 s
->state
.activity
= k_skate_activity_ground
;
80 player__skate_clear_mechanics( player
);
81 player__skate_reset_animator( player
);
84 player_walk_drop_in_vector( player
, init_velocity
);
86 rb_update_transform( &player
->rb
);
87 v3_muladds( player
->rb
.co
, player
->rb
.to_world
[1], 1.0f
, s
->state
.cog
);
88 v3_copy( init_velocity
, s
->state
.cog_v
);
89 v3_copy( init_velocity
, player
->rb
.v
);
90 v3_copy( init_velocity
, player
->cam_velocity_smooth
);
91 v3_copy( (v3f
){1.0f
,0.0f
,0.0f
}, s
->state
.trick_euler
);
94 VG_STATIC
void player_walk_drop_in_overhang_transform( player_instance
*player
,
98 struct player_walk
*w
= &player
->_walk
;
101 v3_cross( player
->basis
[1], w
->state
.drop_in_normal
, axis
);
102 v3_normalize( axis
);
104 float a
= acosf( w
->state
.drop_in_normal
[1] ) * t
;
106 q_axis_angle( q
, axis
, a
);
109 heading_angle
= w
->state
.drop_in_angle
;
112 overhang
[0] = sinf( heading_angle
) * l
;
113 overhang
[1] = 0.28f
* l
;
114 overhang
[2] = cosf( heading_angle
) * l
;
116 q_mulv( q
, overhang
, overhang
);
117 v3_add( w
->state
.drop_in_target
, overhang
, co
);
120 VG_STATIC
int player_walk_scan_for_drop_in( player_instance
*player
)
122 struct player_walk
*w
= &player
->_walk
;
123 world_instance
*world
= world_current_instance();
126 q_mulv( player
->rb
.q
, (v3f
){0.0f
,0.0f
,1.0f
}, dir
);
127 v3_muladds( player
->rb
.co
, player
->rb
.to_world
[1], -1.0f
, center
);
130 int sample_count
= 0;
132 for( int i
=0; i
<20; i
++ )
134 float t
= (float)i
* (1.0f
/19.0f
),
135 s
= sinf( t
* VG_PIf
* 0.25f
),
136 c
= cosf( t
* VG_PIf
* 0.25f
);
139 v3_muls ( player
->rb
.to_world
[1], -c
, ray_dir
);
140 v3_muladds( ray_dir
, dir
, -s
, ray_dir
);
141 v3_muladds( center
, ray_dir
, -2.0f
, pos
);
143 ray_hit
*ray
= &samples
[ sample_count
];
146 if( ray_world( world
, pos
, ray_dir
, ray
) )
148 vg_line( pos
, ray
->pos
, VG__RED
);
149 vg_line_pt3( ray
->pos
, 0.025f
, VG__BLACK
);
155 float min_a
= 0.70710678118654752f
;
156 ray_hit
*candidate
= NULL
;
158 if( sample_count
>= 2 )
160 for( int i
=0; i
<sample_count
-1; i
++ )
162 ray_hit
*s0
= &samples
[i
],
165 float a
= v3_dot( s0
->normal
, s1
->normal
);
167 if( (a
< min_a
) && (a
>= -0.1f
) && (s0
->normal
[1]>s1
->normal
[1]) )
179 ray_hit
*s0
= candidate
,
182 vg_line( s0
->pos
, s1
->pos
, VG__WHITE
);
184 v3_copy( s0
->normal
, pa
);
185 v3_copy( s1
->normal
, pb
);
186 v3_cross( player
->rb
.to_world
[1], dir
, pc
);
189 pa
[3] = v3_dot( pa
, s0
->pos
);
190 pb
[3] = v3_dot( pb
, s1
->pos
);
191 pc
[3] = v3_dot( pc
, player
->rb
.co
);
194 if( plane_intersect3( pa
, pb
, pc
, edge
) )
196 v3_copy( edge
, w
->state
.drop_in_target
);
197 v3_copy( s1
->normal
, w
->state
.drop_in_normal
);
198 v3_copy( player
->rb
.co
, w
->state
.drop_in_start
);
200 w
->state
.drop_in_start_angle
= player_get_heading_yaw( player
);
201 w
->state
.drop_in_angle
= atan2f( w
->state
.drop_in_normal
[0],
202 w
->state
.drop_in_normal
[2] );
204 /* TODO: scan multiple of these? */
207 player_walk_drop_in_overhang_transform( player
, 1.0f
, oco
, oq
);
209 v3f va
= {0.0f
,0.0f
,-k_board_length
- 0.3f
},
210 vb
= {0.0f
,0.0f
, k_board_length
+ 0.3f
};
212 q_mulv( oq
, va
, va
);
213 q_mulv( oq
, vb
, vb
);
214 v3_add( oco
, va
, va
);
215 v3_add( oco
, vb
, vb
);
218 v3_sub( vb
, va
, v0
);
222 ray
.dist
= k_board_length
*2.0f
+ 0.6f
;
224 if( ray_world( world
, va
, v0
, &ray
) )
226 vg_line( va
, vb
, VG__RED
);
227 vg_line_pt3( ray
.pos
, 0.1f
, VG__RED
);
228 vg_error( "invalidated\n" );
232 v3_muls( v0
, -1.0f
, v0
);
233 if( ray_world( world
, vb
, v0
, &ray
) )
235 vg_line( va
, vb
, VG__RED
);
236 vg_line_pt3( ray
.pos
, 0.1f
, VG__RED
);
237 vg_error( "invalidated\n" );
241 player_walk_drop_in_vector( player
, player
->rb
.v
);
246 vg_error( "failed to find intersection of drop in\n" );
253 VG_STATIC
void player__walk_pre_update( player_instance
*player
)
255 struct player_walk
*w
= &player
->_walk
;
257 if( !player
->immobile
)
258 player_look( player
, player
->angles
);
260 if( w
->state
.outro_anim
){
261 float outro_length
= (float)w
->state
.outro_anim
->length
/
262 w
->state
.outro_anim
->rate
,
263 outro_time
= vg
.time
- w
->state
.outro_start_time
;
265 if( outro_time
>= outro_length
){
266 w
->state
.outro_anim
= NULL
;
267 if( w
->state
.outro_type
== k_walk_outro_drop_in
){
268 player_walk_drop_in_to_skate( player
);
270 else if( w
->state
.outro_type
== k_walk_outro_jump_to_air
){
271 player_walk_generic_to_skate( player
, k_skate_activity_air
, 0.0f
);
274 player_walk_generic_to_skate( player
,
275 k_skate_activity_ground
, 1.0f
);
281 else if( button_down( k_srbind_use
) && !player
->immobile
){
282 if( v3_dist2( player
->rb
.co
, gzoomer
.obj
.rb
.co
) <= 4.0f
*4.0f
){
283 player
->subsystem
= k_player_subsystem_drive
;
286 if( !player_get_player_board(player
) )
289 if( w
->state
.activity
== k_walk_activity_ground
){
290 if( player_walk_scan_for_drop_in( player
) ){
291 w
->state
.outro_type
= k_walk_outro_drop_in
;
292 w
->state
.outro_anim
= w
->anim_drop_in
;
293 w
->state
.outro_start_time
= vg
.time
;
294 player
->immobile
= 1;
296 struct player_avatar
*av
= player
->playeravatar
;
297 m4x3_mulv( av
->sk
.final_mtx
[ av
->id_ik_foot_r
],
298 av
->sk
.bones
[ av
->id_ik_foot_r
].co
,
299 w
->state
.drop_in_foot_anchor
);
302 w
->state
.outro_type
= k_walk_outro_regular
;
303 w
->state
.outro_anim
= w
->anim_intro
;
304 w
->state
.outro_start_time
= vg
.time
;
305 w
->state
.activity
= k_walk_activity_lockedmove
;
307 if( player_xyspeed2(player
) < 0.1f
* 0.1f
)
308 q_mulv( player
->rb
.q
, (v3f
){0.0f
,0.0f
,1.6f
}, player
->rb
.v
);
312 w
->state
.outro_type
= k_walk_outro_jump_to_air
;
313 w
->state
.outro_anim
= w
->anim_jump_to_air
;
314 w
->state
.outro_start_time
= vg
.time
;
321 VG_STATIC
int player_walk_normal_standable( player_instance
*player
, v3f n
)
323 return v3_dot( n
, player
->basis
[1] ) > 0.70710678118f
;
326 VG_STATIC
void player_accelerate( v3f v
, v3f movedir
, float speed
, float accel
)
328 float currentspeed
= v3_dot( v
, movedir
),
329 addspeed
= speed
- currentspeed
;
334 float accelspeed
= accel
* k_rb_delta
* speed
;
336 if( accelspeed
> addspeed
)
337 accelspeed
= addspeed
;
339 v3_muladds( v
, movedir
, accelspeed
, v
);
342 VG_STATIC
void player_friction( v3f v
)
344 float speed
= v3_length( v
),
346 control
= vg_maxf( speed
, k_stopspeed
);
351 drop
+= control
* k_walk_friction
* k_rb_delta
;
353 float newspeed
= vg_maxf( 0.0f
, speed
- drop
);
356 v3_muls( v
, newspeed
, v
);
359 VG_STATIC
void player__walk_update( player_instance
*player
)
361 struct player_walk
*w
= &player
->_walk
;
362 v3_copy( player
->rb
.co
, w
->state
.prev_pos
);
364 enum walk_activity prev_state
= w
->state
.activity
;
366 if( player
->immobile
)
369 w
->collider
.height
= 2.0f
;
370 w
->collider
.radius
= 0.3f
;
373 m3x3_copy( player
->rb
.to_world
, mtx
);
374 v3_add( player
->rb
.co
, player
->basis
[1], mtx
[3] );
376 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__WHITE
);
381 float yaw
= player
->angles
[0];
383 v3f forward_dir
= { -sinf(yaw
), 0.0f
, cosf(yaw
) };
384 v3f right_dir
= { forward_dir
[2], 0.0f
, -forward_dir
[0] };
386 m3x3_mulv( player
->basis
, forward_dir
, forward_dir
);
387 m3x3_mulv( player
->basis
, right_dir
, right_dir
);
390 joystick_state( k_srjoystick_steer
, steer
);
392 w
->move_speed
= v2_length( steer
);
393 world_instance
*world
= world_current_instance();
396 * Collision detection
399 len
= rb_capsule__scene( mtx
, &w
->collider
, NULL
,
400 &world
->rb_geo
.inf
.scene
, manifold
);
401 rb_manifold_filter_coplanar( manifold
, len
, 0.01f
);
402 len
= rb_manifold_apply_filtered( manifold
, len
);
404 v3f surface_avg
= { 0.0f
, 0.0f
, 0.0f
};
406 if( w
->state
.activity
!= k_walk_activity_lockedmove
)
407 w
->state
.activity
= k_walk_activity_air
;
409 w
->surface
= k_surface_prop_concrete
;
411 for( int i
=0; i
<len
; i
++ ){
412 struct contact
*ct
= &manifold
[i
];
413 rb_debug_contact( ct
);
415 if( player_walk_normal_standable( player
, ct
->n
) ){
416 if( w
->state
.activity
!= k_walk_activity_lockedmove
)
417 w
->state
.activity
= k_walk_activity_ground
;
419 v3_add( surface_avg
, ct
->n
, surface_avg
);
421 struct world_surface
*surf
= world_contact_surface( world
, ct
);
422 if( surf
->info
.surface_prop
> w
->surface
)
423 w
->surface
= surf
->info
.surface_prop
;
426 rb_prepare_contact( ct
, k_rb_delta
);
432 float accel_speed
= 0.0f
, nominal_speed
= 0.0f
;
435 v3_muls( right_dir
, steer
[0], movedir
);
436 v3_muladds( movedir
, forward_dir
, steer
[1], movedir
);
438 if( w
->state
.activity
== k_walk_activity_ground
){
439 v3_normalize( surface_avg
);
442 rb_tangent_basis( surface_avg
, tx
, ty
);
444 if( v2_length2(steer
) > 0.001f
){
445 /* clip movement to the surface */
446 float d
= v3_dot(surface_avg
,movedir
);
447 v3_muladds( movedir
, surface_avg
, -d
, movedir
);
450 accel_speed
= k_walk_accel
;
451 nominal_speed
= k_walkspeed
;
454 if( button_down( k_srbind_jump
) ){
455 float d
= v3_dot( player
->basis
[1], player
->rb
.v
);
456 v3_muladds( player
->rb
.v
, player
->basis
[1], -d
, player
->rb
.v
);
457 v3_muladds( player
->rb
.v
, player
->basis
[1], 5.0f
, player
->rb
.v
);
458 w
->state
.activity
= k_walk_activity_air
;
459 prev_state
= k_walk_activity_air
;
460 accel_speed
= k_walk_air_accel
;
461 nominal_speed
= k_airspeed
;
464 player_friction( player
->rb
.v
);
468 accel_speed
= k_walk_air_accel
;
469 nominal_speed
= k_airspeed
;
472 if( v2_length2( steer
) > 0.001f
){
473 player_accelerate( player
->rb
.v
, movedir
, nominal_speed
, accel_speed
);
474 v3_normalize( movedir
);
478 * Resolve velocity constraints
480 for( int j
=0; j
<5; j
++ ){
481 for( int i
=0; i
<len
; i
++ ){
482 struct contact
*ct
= &manifold
[i
];
485 float vn
= -v3_dot( player
->rb
.v
, ct
->n
);
487 float temp
= ct
->norm_impulse
;
488 ct
->norm_impulse
= vg_maxf( temp
+ vn
, 0.0f
);
489 vn
= ct
->norm_impulse
- temp
;
491 v3_muladds( player
->rb
.v
, ct
->n
, vn
, player
->rb
.v
);
496 if( w
->state
.activity
== k_walk_activity_ground
||
497 prev_state
== k_walk_activity_ground
){
498 float max_dist
= 0.4f
;
501 v3_copy( player
->rb
.co
, pa
);
502 v3_muladds( pa
, player
->basis
[1], w
->collider
.radius
+ max_dist
, pa
);
503 v3_muladds( pa
, player
->basis
[1], -max_dist
* 2.0f
, pb
);
504 vg_line( pa
, pb
, 0xff000000 );
508 if( spherecast_world( world
, pa
, pb
, w
->collider
.radius
, &t
, n
) != -1 ){
509 if( player_walk_normal_standable( player
, n
) ){
510 v3_lerp( pa
, pb
, t
, player
->rb
.co
);
511 v3_muladds( player
->rb
.co
, player
->basis
[1],
512 -w
->collider
.radius
- k_penetration_slop
,
514 w
->state
.activity
= k_walk_activity_ground
;
516 float d
= -v3_dot(n
,player
->rb
.v
),
517 g
= -k_gravity
* k_rb_delta
;
518 v3_muladds( player
->rb
.v
, n
, d
, player
->rb
.v
);
519 v3_muladds( player
->rb
.v
, player
->basis
[1], g
, player
->rb
.v
);
528 rb_depenetrate( manifold
, len
, dt
);
529 v3_add( dt
, player
->rb
.co
, player
->rb
.co
);
532 if( w
->state
.activity
== k_walk_activity_air
){
533 v3_muladds( player
->rb
.v
, player
->basis
[1], -k_gravity
*k_rb_delta
,
537 v3_muladds( player
->rb
.co
, player
->rb
.v
, k_rb_delta
, player
->rb
.co
);
538 v3_add( player
->rb
.co
, player
->basis
[1], mtx
[3] );
539 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__GREEN
);
543 * ---------------------------------------------------
548 lwr_offs
= { 0.0f
, w
->collider
.radius
, 0.0f
};
550 v3_add( lwr_offs
, w
->state
.prev_pos
, lwr_prev
);
551 v3_add( lwr_offs
, player
->rb
.co
, lwr_now
);
554 v3_sub( player
->rb
.co
, w
->state
.prev_pos
, movedelta
);
556 float movedist
= v3_length( movedelta
);
558 if( movedist
> 0.3f
){
559 float t
, sr
= w
->collider
.radius
-0.04f
;
562 if( spherecast_world( world
, lwr_prev
, lwr_now
, sr
, &t
, n
) != -1 ){
563 v3_lerp( lwr_prev
, lwr_now
, vg_maxf(0.01f
,t
), player
->rb
.co
);
564 player
->rb
.co
[1] -= w
->collider
.radius
;
565 rb_update_transform( &player
->rb
);
567 v3_add( player
->rb
.co
, player
->basis
[1], mtx
[3] );
568 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__RED
);
573 world_intersect_gates( world
, player
->rb
.co
, w
->state
.prev_pos
);
575 m4x3_mulv( gate
->transport
, player
->rb
.co
, player
->rb
.co
);
576 m3x3_mulv( gate
->transport
, player
->rb
.v
, player
->rb
.v
);
578 v4f transport_rotation
;
579 m3x3_q( gate
->transport
, transport_rotation
);
580 q_mul( transport_rotation
, player
->rb
.q
, player
->rb
.q
);
582 rb_update_transform( &player
->rb
);
584 w
->state_gate_storage
= w
->state
;
585 player__pass_gate( player
, gate
);
587 rb_update_transform( &player
->rb
);
590 VG_STATIC
void player__walk_restore( player_instance
*player
)
592 struct player_walk
*w
= &player
->_walk
;
593 w
->state
= w
->state_gate_storage
;
596 VG_STATIC
void player__walk_post_update( player_instance
*player
)
598 struct player_walk
*w
= &player
->_walk
;
601 m3x3_copy( player
->rb
.to_world
, mtx
);
602 v3_add( player
->rb
.co
, player
->basis
[1], mtx
[3] );
604 float substep
= vg
.time_fixed_extrapolate
;
605 v3_muladds( mtx
[3], player
->rb
.v
, k_rb_delta
*substep
, mtx
[3] );
606 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__YELOW
);
609 /* Calculate header */
611 if( player_xyspeed2(player
) > 0.1f
*0.1f
)
614 m3x3_mulv( player
->invbasis
, player
->rb
.v
, v_xy
);
615 float a
= atan2f( v_xy
[0], v_xy
[2] );
617 q_axis_angle( player
->rb
.q
, (v3f
){0.0f
,1.0f
,0.0f
}, a
);
618 q_mul( player
->qbasis
, player
->rb
.q
, player
->rb
.q
);
619 q_normalize( player
->rb
.q
);
622 vg_line_pt3( w
->state
.drop_in_target
, 0.1f
, VG__GREEN
);
624 v3_muladds( w
->state
.drop_in_target
, w
->state
.drop_in_normal
, 0.3f
, p1
);
625 vg_line( w
->state
.drop_in_target
, p1
, VG__GREEN
);
626 v3_muladds( w
->state
.drop_in_target
, player
->rb
.to_world
[1], 0.3f
, p1
);
627 vg_line( w
->state
.drop_in_target
, p1
, VG__GREEN
);
629 vg_line( w
->state
.drop_in_target
, w
->state
.drop_in_foot_anchor
, VG__WHITE
);
630 vg_line_pt3( w
->state
.drop_in_foot_anchor
, 0.08f
, VG__PINK
);
633 float a
= player_get_heading_yaw( player
);
637 m3x3_mulv( player
->basis
, p1
, p1
);
639 v3_add( player
->rb
.co
, p1
, p1
);
640 vg_line( player
->rb
.co
, p1
, VG__PINK
);
644 if( vg_fractf(w
->walk_timer
) > 0.5f
)
649 if( (w
->step_phase
!= walk_phase
) &&
650 (w
->state
.activity
== k_walk_activity_ground
) )
653 if( w
->surface
== k_surface_prop_concrete
){
655 &audio_footsteps
[vg_randu32()%vg_list_size(audio_footsteps
)],
656 player
->rb
.co
, 40.0f
, 1.0f
659 else if( w
->surface
== k_surface_prop_grass
){
661 &audio_footsteps_grass
[vg_randu32()%vg_list_size(audio_footsteps_grass
)],
662 player
->rb
.co
, 40.0f
, 1.0f
665 else if( w
->surface
== k_surface_prop_wood
){
667 &audio_footsteps_wood
[vg_randu32()%vg_list_size(audio_footsteps_wood
)],
668 player
->rb
.co
, 40.0f
, 1.0f
674 w
->step_phase
= walk_phase
;
677 VG_STATIC
void player__walk_animate( player_instance
*player
,
678 player_animation
*dest
)
680 struct player_walk
*w
= &player
->_walk
;
681 struct skeleton
*sk
= &player
->playeravatar
->sk
;
684 float fly
= (w
->state
.activity
== k_walk_activity_air
)? 1.0f
: 0.0f
,
687 if( w
->state
.activity
== k_walk_activity_air
)
692 w
->blend_fly
= vg_lerpf( w
->blend_fly
, fly
, rate
*vg
.time_delta
);
693 w
->blend_run
= vg_lerpf( w
->blend_run
, w
->move_speed
, 2.0f
*vg
.time_delta
);
696 player_pose apose
, bpose
;
698 if( w
->move_speed
> 0.025f
){
700 float walk_norm
= 30.0f
/(float)w
->anim_walk
->length
,
701 run_norm
= 30.0f
/(float)w
->anim_run
->length
,
702 walk_adv
= vg_lerpf( walk_norm
, run_norm
, w
->move_speed
);
704 w
->walk_timer
+= walk_adv
* vg
.time_delta
;
707 w
->walk_timer
= 0.0f
;
710 float walk_norm
= (float)w
->anim_walk
->length
/30.0f
,
711 run_norm
= (float)w
->anim_run
->length
/30.0f
,
713 l
= vg_clampf( w
->blend_run
*15.0f
, 0.0f
, 1.0f
),
714 idle_walk
= vg_clampf( (w
->blend_run
-0.1f
)/(1.0f
-0.1f
), 0.0f
, 1.0f
);
717 skeleton_sample_anim( sk
, w
->anim_walk
, t
*walk_norm
, apose
);
718 skeleton_sample_anim( sk
, w
->anim_run
, t
*run_norm
, bpose
);
720 skeleton_lerp_pose( sk
, apose
, bpose
, l
, apose
);
723 skeleton_sample_anim( sk
, w
->anim_idle
, vg
.time
*0.1f
, bpose
);
724 skeleton_lerp_pose( sk
, apose
, bpose
, 1.0f
-idle_walk
, apose
);
727 skeleton_sample_anim( sk
, w
->anim_jump
, vg
.time
*0.6f
, bpose
);
728 skeleton_lerp_pose( sk
, apose
, bpose
, w
->blend_fly
, apose
);
730 /* Create transform */
731 rb_extrapolate( &player
->rb
, dest
->root_co
, dest
->root_q
);
733 float walk_yaw
= player_get_heading_yaw( player
);
735 if( w
->state
.outro_anim
){
736 struct player_avatar
*av
= player
->playeravatar
;
737 float outro_length
= (float)w
->state
.outro_anim
->length
/
738 w
->state
.outro_anim
->rate
,
739 outro_time
= vg
.time
- w
->state
.outro_start_time
,
740 outro_t
= outro_time
/ outro_length
;
742 /* TODO: Compression */
743 skeleton_sample_anim_clamped( sk
, w
->state
.outro_anim
,
745 skeleton_lerp_pose( sk
, apose
, bpose
, outro_t
* 10.0f
, dest
->pose
);
747 if( w
->state
.outro_type
== k_walk_outro_drop_in
){
748 float inv_rate
= 1.0f
/ w
->state
.outro_anim
->rate
,
749 anim_frames
= w
->state
.outro_anim
->length
* inv_rate
,
750 step_frames
= 12.0f
* inv_rate
,
751 commit_frames
= 6.0f
* inv_rate
,
752 drop_frames
= anim_frames
- step_frames
,
753 step_t
= vg_minf( 1.0f
, outro_time
/ step_frames
),
754 remaind_time
= vg_maxf( 0.0f
, outro_time
- step_frames
),
755 dop_t
= vg_minf( 1.0f
, remaind_time
/ drop_frames
),
756 commit_t
= vg_minf( 1.0f
, remaind_time
/ commit_frames
);
758 walk_yaw
= vg_alerpf( w
->state
.drop_in_start_angle
,
759 w
->state
.drop_in_angle
, step_t
);
761 v3_lerp( w
->state
.drop_in_start
, w
->state
.drop_in_target
,
762 step_t
, player
->rb
.co
);
763 q_axis_angle( dest
->root_q
, (v3f
){0.0f
,1.0f
,0.0f
}, walk_yaw
+ VG_PIf
);
765 m4x3f transform
, inverse
;
766 q_m3x3( dest
->root_q
, transform
);
767 v3_copy( dest
->root_co
, transform
[3] );
768 m4x3_invert_affine( transform
, inverse
);
771 m4x3_mulv( inverse
, w
->state
.drop_in_foot_anchor
, anchored_pos
);
773 v3_lerp( dest
->pose
[ av
->id_ik_foot_r
-1 ].co
, anchored_pos
,
775 dest
->pose
[ av
->id_ik_foot_r
-1 ].co
);
778 /* the drop in bit */
779 if( step_t
>= 1.0f
){
781 player_walk_drop_in_overhang_transform( player
, dop_t
,
782 player
->rb
.co
, final_q
);
783 q_mul( final_q
, dest
->root_q
, dest
->root_q
);
785 v4_copy( dest
->root_q
, player
->rb
.q
);
786 v3_muladds( dest
->root_co
, player
->rb
.to_world
[1],
787 -0.1f
* dop_t
, dest
->root_co
);
789 skeleton_copy_pose( sk
, dest
->pose
, player
->holdout_pose
);
790 player
->holdout_time
= 1.0f
;
795 v3_muladds( dest
->root_co
, player
->rb
.to_world
[1],
796 -0.1f
* outro_t
, dest
->root_co
);
798 skeleton_copy_pose( sk
, dest
->pose
, player
->holdout_pose
);
799 player
->holdout_time
= 1.0f
;
803 skeleton_copy_pose( sk
, apose
, dest
->pose
);
806 q_axis_angle( dest
->root_q
, (v3f
){0.0f
,1.0f
,0.0f
}, walk_yaw
+ VG_PIf
);
807 q_mul( player
->qbasis
, dest
->root_q
, dest
->root_q
);
808 q_normalize( dest
->root_q
);
811 VG_STATIC
void player__walk_post_animate( player_instance
*player
)
816 struct player_walk
*w
= &player
->_walk
;
817 struct player_avatar
*av
= player
->playeravatar
;
819 if( w
->state
.outro_anim
)
821 float outro_length
= (float)w
->state
.outro_anim
->length
/
822 w
->state
.outro_anim
->rate
,
823 outro_time
= vg
.time
- w
->state
.outro_start_time
,
824 outro_t
= outro_time
/ outro_length
;
826 player
->cam_velocity_influence
= outro_t
;
829 player
->cam_velocity_influence
= 0.0f
;
833 VG_STATIC
void player__walk_im_gui( player_instance
*player
)
835 struct player_walk
*w
= &player
->_walk
;
836 player__debugtext( 1, "V: %5.2f %5.2f %5.2f",player
->rb
.v
[0],
839 player__debugtext( 1, "CO: %5.2f %5.2f %5.2f",player
->rb
.co
[0],
842 player__debugtext( 1, "activity: %s\n",
843 (const char *[]){ "k_walk_activity_air",
844 "k_walk_activity_ground",
845 "k_walk_activity_sleep",
846 "k_walk_activity_lockedmove" }
847 [w
->state
.activity
] );
848 player__debugtext( 1, "surface: %s\n",
849 (const char *[]){ "concrete",
856 if( w
->state
.outro_anim
){
857 float outro_length
= (float)w
->state
.outro_anim
->length
/
858 w
->state
.outro_anim
->rate
,
859 outro_time
= vg
.time
- w
->state
.outro_start_time
;
860 player__debugtext( 1, "outro time: %f / %f", outro_time
, outro_length
);
864 VG_STATIC
void player__walk_bind( player_instance
*player
)
866 struct player_walk
*w
= &player
->_walk
;
867 struct player_avatar
*av
= player
->playeravatar
;
868 struct skeleton
*sk
= &av
->sk
;
870 w
->anim_idle
= skeleton_get_anim( sk
, "idle_cycle+y" );
871 w
->anim_walk
= skeleton_get_anim( sk
, "walk+y" );
872 w
->anim_run
= skeleton_get_anim( sk
, "run+y" );
873 w
->anim_jump
= skeleton_get_anim( sk
, "jump+y" );
874 w
->anim_jump_to_air
= skeleton_get_anim( sk
, "jump_to_air" );
875 w
->anim_drop_in
= skeleton_get_anim( sk
, "drop_in" );
876 w
->anim_intro
= skeleton_get_anim( sk
, "into_skate" );
879 VG_STATIC
void player__walk_transition( player_instance
*player
, v3f angles
)
881 struct player_walk
*w
= &player
->_walk
;
882 w
->state
.activity
= k_walk_activity_air
;
884 v3f fwd
= { 0.0f
, 0.0f
, 1.0f
};
885 q_mulv( player
->rb
.q
, fwd
, fwd
);
886 m3x3_mulv( player
->invbasis
, fwd
, fwd
);
888 q_axis_angle( player
->rb
.q
, (v3f
){0.0f
,1.0f
,0.0f
}, atan2f(fwd
[0], fwd
[2]) );
889 q_mul( player
->qbasis
, player
->rb
.q
, player
->rb
.q
);
890 q_normalize( player
->rb
.q
);
892 rb_update_transform( &player
->rb
);
895 VG_STATIC
void player__walk_reset( player_instance
*player
, ent_spawn
*rp
)
897 struct player_walk
*w
= &player
->_walk
;
898 w
->state
.activity
= k_walk_activity_air
;
899 w
->state
.outro_type
= k_walk_outro_none
;
900 w
->state
.outro_anim
= NULL
;
901 w
->state
.outro_start_time
= 0.0;
904 #endif /* PLAYER_DEVICE_WALK_H */