6 VG_STATIC
void player_walk_transfer_to_skate( player_instance
*player
,
7 enum skate_activity init
)
9 struct player_walk
*w
= &player
->_walk
;
13 v3_copy( player
->rb
.v
, xy_speed
);
16 if( v3_length2( xy_speed
) < 0.1f
* 0.1f
)
18 v
[0] = -sinf( -w
->state
.angles
[0] );
20 v
[2] = -cosf( -w
->state
.angles
[0] );
21 v3_muls( v
, 1.6f
, v
);
24 v3_copy( player
->rb
.v
, v
);
26 player
->subsystem
= k_player_subsystem_skate
;
27 player__skate_transition( player
, v
, init
);
31 VG_STATIC
void player__walk_pre_update( player_instance
*player
)
33 struct player_walk
*w
= &player
->_walk
;
34 player_look( player
, w
->state
.angles
);
36 if( w
->state
.outro_anim
)
38 float outro_length
= (float)w
->state
.outro_anim
->length
/
39 w
->state
.outro_anim
->rate
,
40 outro_time
= vg
.time
- w
->state
.outro_start_time
;
42 if( outro_time
>= outro_length
)
44 w
->state
.outro_anim
= NULL
;
45 player_walk_transfer_to_skate( player
, k_skate_activity_air
);
49 else if( vg_input_button_down( player
->input_use
) )
51 if( w
->state
.activity
== k_walk_activity_ground
)
53 player_walk_transfer_to_skate( player
, k_skate_activity_ground
);
57 w
->state
.outro_anim
= w
->anim_jump_to_air
;
58 w
->state
.outro_start_time
= vg
.time
;
59 v3_copy( player
->cam
.pos
, player
->follow_pos
);
60 v3_copy( player
->cam
.angles
, player
->follow_angles
);
66 VG_STATIC
int player_walk_normal_standable( v3f n
)
68 return n
[1] > 0.70710678118f
;
71 VG_STATIC
void player_accelerate( v3f v
, v3f movedir
, float speed
, float accel
)
73 float currentspeed
= v3_dot( v
, movedir
),
74 addspeed
= speed
- currentspeed
;
79 float accelspeed
= accel
* k_rb_delta
* speed
;
81 if( accelspeed
> addspeed
)
82 accelspeed
= addspeed
;
84 v3_muladds( v
, movedir
, accelspeed
, v
);
87 VG_STATIC
void player_friction( v3f v
)
89 float speed
= v3_length( v
),
91 control
= vg_maxf( speed
, k_stopspeed
);
96 drop
+= control
* k_walk_friction
* k_rb_delta
;
98 float newspeed
= vg_maxf( 0.0f
, speed
- drop
);
101 v3_muls( v
, newspeed
, v
);
104 VG_STATIC
void player__walk_update( player_instance
*player
)
106 struct player_walk
*w
= &player
->_walk
;
107 v3_copy( player
->rb
.co
, w
->state
.prev_pos
);
109 w
->collider
.height
= 2.0f
;
110 w
->collider
.radius
= 0.3f
;
113 m3x3_identity( mtx
);
114 v3_add( player
->rb
.co
, (v3f
){0.0f
, 1.0f
, 0.0f
}, mtx
[3] );
116 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__WHITE
);
121 float yaw
= w
->state
.angles
[0];
123 v3f forward_dir
= { sinf(yaw
), 0.0f
, -cosf(yaw
) };
124 v3f right_dir
= { -forward_dir
[2], 0.0f
, forward_dir
[0] };
126 v2f walk
= { player
->input_walkh
->axis
.value
,
127 player
->input_walkv
->axis
.value
};
129 if( v2_length2(walk
) > 0.001f
)
130 v2_normalize_clamp( walk
);
132 w
->move_speed
= v2_length( walk
);
135 * Collision detection
137 len
= rb_capsule__scene( mtx
, &w
->collider
, NULL
,
138 &world
.rb_geo
.inf
.scene
, manifold
);
139 rb_manifold_filter_coplanar( manifold
, len
, 0.01f
);
140 len
= rb_manifold_apply_filtered( manifold
, len
);
142 v3f surface_avg
= { 0.0f
, 0.0f
, 0.0f
};
143 w
->state
.activity
= k_walk_activity_air
;
145 for( int i
=0; i
<len
; i
++ )
147 struct contact
*ct
= &manifold
[i
];
148 rb_debug_contact( ct
);
150 if( player_walk_normal_standable( ct
->n
) )
152 w
->state
.activity
= k_walk_activity_ground
;
153 v3_add( surface_avg
, ct
->n
, surface_avg
);
156 rb_prepare_contact( ct
);
162 float accel_speed
= 0.0f
, nominal_speed
= 0.0f
;
164 v3_muls( right_dir
, walk
[0], movedir
);
165 v3_muladds( movedir
, forward_dir
, walk
[1], movedir
);
167 if( w
->state
.activity
== k_walk_activity_ground
)
169 v3_normalize( surface_avg
);
172 rb_tangent_basis( surface_avg
, tx
, ty
);
174 if( v2_length2(walk
) > 0.001f
)
176 /* clip movement to the surface */
177 float d
= v3_dot(surface_avg
,movedir
);
178 v3_muladds( movedir
, surface_avg
, -d
, movedir
);
181 accel_speed
= k_walk_accel
;
182 nominal_speed
= k_walkspeed
;
185 if( player
->input_jump
->button
.value
)
187 player
->rb
.v
[1] = 5.0f
;
188 w
->state
.activity
= k_walk_activity_air
;
189 accel_speed
= k_walk_air_accel
;
190 nominal_speed
= k_airspeed
;
194 player_friction( player
->rb
.v
);
196 struct world_material
*surface_mat
= world_contact_material(manifold
);
197 w
->surface
= surface_mat
->info
.surface_prop
;
202 accel_speed
= k_walk_air_accel
;
203 nominal_speed
= k_airspeed
;
206 if( v2_length2(walk
) > 0.001f
)
208 player_accelerate( player
->rb
.v
, movedir
, nominal_speed
, accel_speed
);
209 v3_normalize( movedir
);
213 * Resolve velocity constraints
215 for( int j
=0; j
<5; j
++ )
217 for( int i
=0; i
<len
; i
++ )
219 struct contact
*ct
= &manifold
[i
];
222 float vn
= -v3_dot( player
->rb
.v
, ct
->n
);
224 float temp
= ct
->norm_impulse
;
225 ct
->norm_impulse
= vg_maxf( temp
+ vn
, 0.0f
);
226 vn
= ct
->norm_impulse
- temp
;
228 v3_muladds( player
->rb
.v
, ct
->n
, vn
, player
->rb
.v
);
237 for( int j
=0; j
<8; j
++ )
239 for( int i
=0; i
<len
; i
++ )
241 struct contact
*ct
= &manifold
[i
];
243 float resolved_amt
= v3_dot( ct
->n
, dt
),
244 remaining
= (ct
->p
-k_penetration_slop
) - resolved_amt
,
245 apply
= vg_maxf( remaining
, 0.0f
) * 0.3f
;
247 v3_muladds( dt
, ct
->n
, apply
, dt
);
250 v3_add( dt
, player
->rb
.co
, player
->rb
.co
);
252 /* TODO: Stepping......
254 * ideas; walkgrid style steps
257 if( w
->state
.activity
== k_walk_activity_ground
)
260 float max_dist
= 0.4f
;
263 v3_copy( player
->rb
.co
, pa
);
264 pa
[1] += w
->collider
.radius
+ max_dist
;
266 v3_muladds( pa
, (v3f
){0.0f
,1.0f
,0.0f
}, -max_dist
* 2.0f
, pb
);
267 vg_line( pa
, pb
, 0xff000000 );
271 if( spherecast_world( pa
, pb
, w
->collider
.radius
, &t
, n
) != -1 )
273 if( player_walk_normal_standable( n
) )
275 v3_lerp( pa
, pb
, t
, player
->rb
.co
);
276 player
->rb
.co
[1] -= w
->collider
.radius
;
284 if( w
->state
.activity
== k_walk_activity_air
)
285 player
->rb
.v
[1] += -k_gravity
* k_rb_delta
;
287 v3_muladds( player
->rb
.co
, player
->rb
.v
, k_rb_delta
, player
->rb
.co
);
290 v3_add( player
->rb
.co
, (v3f
){0.0f
, 1.0f
, 0.0f
}, mtx
[3] );
291 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__GREEN
);
295 * ---------------------------------------------------
300 lwr_offs
= { 0.0f
, w
->collider
.radius
, 0.0f
};
302 v3_add( lwr_offs
, w
->state
.prev_pos
, lwr_prev
);
303 v3_add( lwr_offs
, player
->rb
.co
, lwr_now
);
306 v3_sub( player
->rb
.co
, w
->state
.prev_pos
, movedelta
);
308 float movedist
= v3_length( movedelta
);
310 if( movedist
> 0.3f
)
312 float t
, sr
= w
->collider
.radius
-0.04f
;
315 if( spherecast_world( lwr_prev
, lwr_now
, sr
, &t
, n
) != -1 )
317 v3_lerp( lwr_prev
, lwr_now
, vg_maxf(0.01f
,t
), player
->rb
.co
);
318 player
->rb
.co
[1] -= w
->collider
.radius
;
319 rb_update_transform( &player
->rb
);
321 v3_add( player
->rb
.co
, (v3f
){0.0f
, 1.0f
, 0.0f
}, mtx
[3] );
322 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__RED
);
327 if( (gate
= world_intersect_gates( player
->rb
.co
, w
->state
.prev_pos
)) )
329 m4x3_mulv( gate
->transport
, player
->rb
.co
, player
->rb
.co
);
330 m3x3_mulv( gate
->transport
, player
->rb
.v
, player
->rb
.v
);
331 rb_update_transform( &player
->rb
);
333 /* analytical rotation of yaw */
334 v3f fwd_dir
= { cosf(w
->state
.angles
[0]),
336 sinf(w
->state
.angles
[0])};
337 m3x3_mulv( gate
->transport
, fwd_dir
, fwd_dir
);
338 w
->state
.angles
[0] = atan2f( fwd_dir
[2], fwd_dir
[0] );
340 w
->state_gate_storage
= w
->state
;
341 player__pass_gate( player
, gate
);
345 VG_STATIC
void player__walk_post_update( player_instance
*player
)
347 struct player_walk
*w
= &player
->_walk
;
350 m3x3_identity( mtx
);
351 v3_add( player
->rb
.co
, (v3f
){0.0f
, 1.0f
, 0.0f
}, mtx
[3] );
353 float substep
= vg_clampf( vg
.accumulator
/ k_rb_delta
, 0.0f
, 1.0f
);
354 v3_muladds( mtx
[3], player
->rb
.v
, k_rb_delta
*substep
, mtx
[3] );
355 debug_capsule( mtx
, w
->collider
.radius
, w
->collider
.height
, VG__YELOW
);
358 /* Calculate header */
361 v3_copy( player
->rb
.v
, xy_speed
);
364 if( v3_length2( xy_speed
) > 0.1f
* 0.1f
)
365 w
->state
.heading_angle
= atan2f( player
->rb
.v
[0], player
->rb
.v
[2] );
368 VG_STATIC
void player__walk_animate( player_instance
*player
,
369 player_animation
*dest
)
371 struct player_walk
*w
= &player
->_walk
;
372 struct skeleton
*sk
= &player
->playeravatar
->sk
;
375 float fly
= (w
->state
.activity
== k_walk_activity_air
)? 1.0f
: 0.0f
,
378 if( w
->state
.activity
== k_walk_activity_air
)
383 w
->blend_fly
= vg_lerpf( w
->blend_fly
, fly
, rate
*vg
.time_delta
);
384 w
->blend_run
= vg_lerpf( w
->blend_run
,
386 (1.0f
+ player
->input_walk
->button
.value
*0.5f
),
387 2.0f
*vg
.time_delta
);
390 player_pose apose
, bpose
;
392 if( w
->move_speed
> 0.025f
)
395 float walk_norm
= 30.0f
/(float)w
->anim_walk
->length
,
396 run_norm
= 30.0f
/(float)w
->anim_run
->length
,
397 walk_adv
= vg_lerpf( walk_norm
, run_norm
, w
->move_speed
);
399 w
->walk_timer
+= walk_adv
* vg
.time_delta
;
403 w
->walk_timer
= 0.0f
;
406 float walk_norm
= (float)w
->anim_walk
->length
/30.0f
,
407 run_norm
= (float)w
->anim_run
->length
/30.0f
,
409 l
= vg_clampf( w
->blend_run
*15.0f
, 0.0f
, 1.0f
),
410 idle_walk
= vg_clampf( (w
->blend_run
-0.1f
)/(1.0f
-0.1f
), 0.0f
, 1.0f
);
413 skeleton_sample_anim( sk
, w
->anim_walk
, t
*walk_norm
, apose
);
414 skeleton_sample_anim( sk
, w
->anim_run
, t
*run_norm
, bpose
);
416 skeleton_lerp_pose( sk
, apose
, bpose
, l
, apose
);
419 skeleton_sample_anim( sk
, w
->anim_idle
, vg
.time
*0.1f
, bpose
);
420 skeleton_lerp_pose( sk
, apose
, bpose
, 1.0f
-idle_walk
, apose
);
423 skeleton_sample_anim( sk
, w
->anim_jump
, vg
.time
*0.6f
, bpose
);
424 skeleton_lerp_pose( sk
, apose
, bpose
, w
->blend_fly
, apose
);
426 /* Create transform */
427 rb_extrapolate( &player
->rb
, dest
->root_co
, dest
->root_q
);
429 float walk_yaw
= w
->state
.heading_angle
+ VG_PIf
*0.5f
;
431 if( w
->state
.outro_anim
)
433 float outro_length
= (float)w
->state
.outro_anim
->length
/
434 w
->state
.outro_anim
->rate
,
435 outro_time
= vg
.time
- w
->state
.outro_start_time
,
436 outro_t
= outro_time
/ outro_length
;
438 walk_yaw
+= -VG_PIf
*0.5f
*outro_t
;
440 /* TODO: Compression */
441 v3_muladds( dest
->root_co
, player
->rb
.to_world
[1],
442 -0.28f
* outro_t
, dest
->root_co
);
444 skeleton_sample_anim_clamped( sk
, w
->state
.outro_anim
,
446 skeleton_lerp_pose( sk
, apose
, bpose
, outro_t
* 10.0f
, dest
->pose
);
450 skeleton_copy_pose( sk
, apose
, dest
->pose
);
453 q_axis_angle( dest
->root_q
, (v3f
){0.0f
,1.0f
,0.0f
}, walk_yaw
);
456 VG_STATIC
void player__walk_post_animate( player_instance
*player
)
461 struct player_walk
*w
= &player
->_walk
;
462 struct player_avatar
*av
= player
->playeravatar
;
466 euler_m3x3( w
->state
.angles
, angles
);
468 v3f cast_dir
, origin
;
470 v3_add( player
->rb
.co
, (v3f
){0.0f
,2.0f
,0.0f
}, origin
);
472 v3_muladds( origin
, angles
[2], 2.0f
, player
->override_pos
);
473 v3_muladds( player
->override_pos
, angles
[0], 0.5f
, player
->override_pos
);
477 if( spherecast_world( origin
, player
->override_pos
, 0.1f
, &t
, n
) != -1 )
478 v3_lerp( origin
, player
->override_pos
, t
, player
->override_pos
);
479 v3_copy( w
->state
.angles
, player
->override_angles
);
482 /* FIXME: viewpoint entity */
483 v3f vp
= {-0.1f
,1.8f
,0.0f
};
484 m4x3_mulv( av
->sk
.final_mtx
[ av
->id_head
-1 ], vp
, player
->fpv_pos
);
485 v3_copy( w
->state
.angles
, player
->fpv_angles
);
487 /* FIXME: Organize this. Its int wrong fucking place */
488 v3f vp0
= {0.0f
,0.1f
, 0.6f
},
489 vp1
= {0.0f
,0.1f
,-0.6f
};
491 if( w
->state
.outro_anim
)
493 float outro_length
= (float)w
->state
.outro_anim
->length
/
494 w
->state
.outro_anim
->rate
,
495 outro_time
= vg
.time
- w
->state
.outro_start_time
,
496 outro_t
= outro_time
/ outro_length
;
498 /* FIXME: Compression */
499 v3_add( player
->rb
.co
, (v3f
){0.0f
,1.35f
,0.0f
}, origin
);
500 player_set_follower_subject( player
, origin
);
502 player
->cam_angles_override_strength
= 1.0f
-outro_t
;
503 player
->cam_position_override_strength
= 1.0f
-outro_t
;
507 player_vector_angles( fpv_angles
, player
->rb
.v
, 1.0f
, 0.25f
);
508 v3_lerp( player
->fpv_angles
,fpv_angles
, outro_t
, player
->fpv_angles
);
512 player
->cam_angles_override_strength
= 1.0f
;
513 player
->cam_position_override_strength
= 1.0f
;
516 m4x3_mulv( av
->sk
.final_mtx
[ av
->id_board
], vp0
, TEMP_BOARD_0
);
517 m4x3_mulv( av
->sk
.final_mtx
[ av
->id_board
], vp1
, TEMP_BOARD_1
);
521 VG_STATIC
void player__walk_im_gui( player_instance
*player
)
523 struct player_walk
*w
= &player
->_walk
;
524 player__debugtext( 1, "V: %5.2f %5.2f %5.2f",player
->rb
.v
[0],
527 player__debugtext( 1, "CO: %5.2f %5.2f %5.2f",player
->rb
.co
[0],
530 player__debugtext( 1, "activity: %s\n",
531 (const char *[]){ "k_walk_activity_air",
532 "k_walk_activity_ground",
533 "k_walk_activity_sleep" }
534 [w
->state
.activity
] );
536 if( w
->state
.outro_anim
)
538 float outro_length
= (float)w
->state
.outro_anim
->length
/
539 w
->state
.outro_anim
->rate
,
540 outro_time
= vg
.time
- w
->state
.outro_start_time
;
541 player__debugtext( 1, "outro time: %f / %f", outro_time
, outro_length
);
545 VG_STATIC
void player__walk_bind( player_instance
*player
)
547 struct player_walk
*w
= &player
->_walk
;
548 struct player_avatar
*av
= player
->playeravatar
;
549 struct skeleton
*sk
= &av
->sk
;
551 w
->anim_idle
= skeleton_get_anim( sk
, "idle_cycle" );
552 w
->anim_walk
= skeleton_get_anim( sk
, "walk" );
553 w
->anim_run
= skeleton_get_anim( sk
, "run" );
554 w
->anim_jump
= skeleton_get_anim( sk
, "jump" );
555 w
->anim_jump_to_air
= skeleton_get_anim( sk
, "jump_to_air" );
558 VG_STATIC
void player__walk_transition( player_instance
*player
, v3f angles
)
560 struct player_walk
*w
= &player
->_walk
;
561 v3_copy( angles
, w
->state
.angles
);
564 #endif /* PLAYER_DEVICE_WALK_H */