{ &player_skate.anim_push_reverse, "push_reverse" },
{ &player_skate.anim_ollie, "ollie" },
{ &player_skate.anim_ollie_reverse,"ollie_reverse" },
- { &player_skate.anim_grabs, "grabs" }
+ { &player_skate.anim_grabs, "grabs" },
+ { &player_skate.anim_handplant, "handplant" }
};
for( u32 i=0; i<vg_list_size(bindings); i++ )
}
}
+static void skate_apply_handplant_model(void){
+ struct player_skate_state *state = &player_skate.state;
+ if( localplayer.rb.to_world[1][1] < -0.1f ) return;
+ if( localplayer.rb.to_world[1][1] > 0.6f ) return;
+ if( !( button_press(k_srbind_skid) || (fabsf(state->skid)>0.1f)) ) return;
+
+ v3f lco = { 0.0f, -0.2f, -state->reverse },
+ co, dir;
+ m4x3_mulv( localplayer.rb.to_world, lco, co );
+ v3_muls( localplayer.rb.to_world[2], state->reverse, dir );
+ vg_line_arrow( co, dir, 0.13f, 0xff000000 );
+
+ ray_hit hit = { .dist = 2.0f };
+ if( ray_world( world_current_instance(), co, dir,
+ &hit, k_material_flag_ghosts )) {
+ vg_line( co, hit.pos, 0xff000000 );
+ vg_line_point( hit.pos, 0.1f, 0xff000000 );
+
+ if( hit.normal[1] < 0.7f ) return;
+ if( hit.dist < 0.95f ) return;
+
+ state->activity = k_skate_activity_handplant;
+ state->handplant_t = 0.0f;
+ v3_copy( localplayer.rb.co, state->store_co );
+ v3_copy( localplayer.rb.v, state->air_init_v );
+ v4_copy( localplayer.rb.q, state->store_q );
+ v3_copy( state->cog, state->store_cog );
+ v3_copy( state->cog_v, state->store_cog_v );
+ v4_copy( state->smoothed_rotation, state->store_smoothed );
+ }
+}
+
static void skate_apply_pump_model(void){
struct player_skate_state *state = &player_skate.state;
static void player__skate_pre_update(void){
struct player_skate_state *state = &player_skate.state;
+ if( state->activity == k_skate_activity_handplant ){
+ state->handplant_t += vg.time_delta;
+ mdl_keyframe hpose[32];
+
+ int end = !skeleton_sample_anim_clamped(
+ &localplayer.skeleton, player_skate.anim_handplant,
+ state->handplant_t, hpose );
+
+ if( state->reverse < 0.0f )
+ player_mirror_pose( hpose, hpose );
+
+ mdl_keyframe *kf_world = &hpose[ localplayer.id_world -1 ];
+ m4x3f world, mmdl, world_view;
+ q_m3x3( kf_world->q, world );
+ v3_copy( kf_world->co, world[3] );
+
+ /* original mtx */
+ q_m3x3( state->store_q, mmdl );
+ v3_copy( state->store_co, mmdl[3] );
+ m4x3_mul( mmdl, world, world_view );
+
+ vg_line_arrow( world_view[3], world_view[0], 1.0f, 0xff0000ff );
+ vg_line_arrow( world_view[3], world_view[1], 1.0f, 0xff00ff00 );
+ vg_line_arrow( world_view[3], world_view[2], 1.0f, 0xffff0000 );
+
+ m4x3f invworld;
+ m4x3_invert_affine( world, invworld );
+ m4x3_mul( mmdl, invworld, world_view );
+
+ v3_copy( world_view[3], localplayer.rb.co );
+ m3x3_q( world_view, localplayer.rb.q );
+
+ /* new * old^-1 = transfer function */
+ m4x3f transfer;
+ m4x3_invert_affine( mmdl, transfer );
+ m4x3_mul( world_view, transfer, transfer );
+
+ m3x3_mulv( transfer, state->air_init_v, localplayer.rb.v );
+ m3x3_mulv( transfer, state->store_cog_v, state->cog_v );
+ m4x3_mulv( transfer, state->store_cog, state->cog );
+ v3_muladds( state->cog, localplayer.rb.to_world[1],
+ -state->handplant_t*0.5f, state->cog );
+
+ v4f qtransfer;
+ m3x3_q( transfer, qtransfer );
+ q_mul( qtransfer, state->store_smoothed, state->smoothed_rotation );
+ q_normalize( state->smoothed_rotation );
+ rb_update_transform( &localplayer.rb );
+
+ if( end ){
+ state->activity = k_skate_activity_air;
+ }
+ else return;
+ }
+
if( button_down( k_srbind_use ) ){
localplayer.subsystem = k_player_subsystem_walk;
struct player_skate_state *state = &player_skate.state;
world_instance *world = world_current_instance();
+ if( state->activity == k_skate_activity_handplant ){
+ return;
+ }
+
if( world->water.enabled ){
if( localplayer.rb.co[1]+0.25f < world->water.height ){
player__networked_sfx( k_player_subsystem_walk, 32,
skate_adjust_up_direction();
skate_apply_cog_model();
skate_apply_jump_model();
+ skate_apply_handplant_model();
skate_apply_grab_model();
skate_apply_trick_model();
skate_apply_pump_model();
"air",
"air_to_grind",
"ground",
+ "handplant",
"undefined (INVALID)",
"grind_any (INVALID)",
"grind_boardslide",
vg_line_arrow( localplayer.rb.co, p2, 0.5f, VG__PINK );
}
else q_identity( animator->qfixuptotal );
- rb_extrapolate( &localplayer.rb, animator->root_co, animator->root_q );
- v3_copy( localplayer.rb.v, animator->root_v );
+
+ if( state->activity == k_skate_activity_handplant ){
+ v3_copy( state->store_co, animator->root_co );
+ v4_copy( state->store_q, animator->root_q );
+ v3_zero( animator->root_v );
+ }
+ else {
+ rb_extrapolate( &localplayer.rb, animator->root_co, animator->root_q );
+ v3_copy( localplayer.rb.v, animator->root_v );
+ }
+
+ animator->handplant_t = state->handplant_t;
}
static void player__skate_pose( void *_animator, player_pose *pose ){
skeleton_sample_anim( sk, player_skate.anim_slide, slide_frame, bpose );
mdl_keyframe mirrored[32];
- for( u32 i=1; i<sk->bone_count; i ++ ){
-
- mdl_keyframe *dest = &mirrored[i-1];
- u8 mapping = localplayer.skeleton_mirror[i];
-
- if( mapping ) *dest = bpose[mapping-1]; /* R */
- else *dest = bpose[i-1]; /* L */
-
- dest->co[2] *= -1.0f;
- dest->q[0] *= -1.0f;
- dest->q[1] *= -1.0f;
- }
+ player_mirror_pose( bpose, mirrored );
skeleton_lerp_pose( sk, bpose, mirrored, animator->z, bpose );
-
-
-
-
-
skeleton_lerp_pose( sk, apose, bpose, animator->slide, apose );
if( animator->reverse > 0.0f ){
pose->keyframes[apply_to[i]-1].co[2] += animator->offset[2]*add_grab_mod;
}
+#if 1
/* angle 'correction' */
v3f origin;
v3_add( sk->bones[localplayer.id_hip].co, kf_hip->co, origin );
keyframe_rotate_around( kf, origin, sk->bones[apply_to[i]].co,
animator->qfixuptotal );
}
+#endif
+
+ if( animator->activity == k_skate_activity_handplant ){
+ mdl_keyframe hpose[32];
+ skeleton_sample_anim_clamped( sk, player_skate.anim_handplant,
+ animator->handplant_t, hpose );
+ if( animator->reverse < 0.0f )
+ player_mirror_pose( hpose, hpose );
+
+ mdl_keyframe *kf_world = &hpose[ localplayer.id_world -1 ];
+ m4x3f world, mmdl, world_view;
+ q_m3x3( kf_world->q, world );
+ v3_copy( kf_world->co, world[3] );
+
+ q_m3x3( pose->root_q, mmdl );
+ v3_copy( pose->root_co, mmdl[3] );
+
+ m4x3_mul( mmdl, world, world_view );
+
+ vg_line_arrow( world_view[3], world_view[0], 1.0f, 0xff0000ff );
+ vg_line_arrow( world_view[3], world_view[1], 1.0f, 0xff00ff00 );
+ vg_line_arrow( world_view[3], world_view[2], 1.0f, 0xffff0000 );
+
+ m4x3f invworld;
+ m4x3_invert_affine( world, invworld );
+ m4x3_mul( mmdl, invworld, world_view );
+
+ m3x3_q( world_view, pose->root_q );
+ v3_copy( world_view[3], pose->root_co );
+
+ f32 t = animator->handplant_t,
+ frames = player_skate.anim_handplant->length-1,
+ length = frames / player_skate.anim_handplant->rate,
+ end_dist = vg_minf( t, length - t )/k_anim_transition,
+ blend = vg_smoothstepf( vg_minf(1,end_dist) );
+
+ skeleton_lerp_pose( sk, pose->keyframes, hpose, blend, pose->keyframes );
+ }
+
+
+
+
/* trick rotation */
v4f qtrick, qyaw, qpitch, qroll;
q_mul( q, kf_wheels[i]->q, kf_wheels[i]->q );
q_normalize( kf_wheels[i]->q );
}
-
+
+#if 1
{
mdl_keyframe
*kf_head = &pose->keyframes[localplayer.id_head-1],
sk->bones[skidders[i]].co, qskid );
}
}
+#endif
}
static void player__skate_effects( void *_animator, m4x3f *final_mtx,
k_skate_activity_air,
k_skate_activity_air_to_grind,
k_skate_activity_ground,
+ k_skate_activity_handplant,
k_skate_activity_undefined,
k_skate_activity_grind_any,
k_skate_activity_grind_boardslide,
v4f smoothed_rotation;
f32 velocity_limit, grind_y_start, skid;
+ f32 handplant_t;
+
+ v3f store_cog_v, store_cog, store_co;
+ v4f store_smoothed, store_q;
}
state;
f32 jump_charge;
- /* linear anims */
- f32 push_time, jump_time;
+ /* linear anims. TODO: we can union a bunch of variables here depending
+ * on activity. */
+ f32 push_time, jump_time, handplant_t;
u8 jump_dir;
u8 trick_type;
u8 activity;
*anim_air, *anim_grind, *anim_grind_jump,
*anim_push, *anim_push_reverse,
*anim_ollie, *anim_ollie_reverse,
- *anim_grabs, *anim_stop;
+ *anim_grabs, *anim_stop,
+ *anim_handplant;
/* vectors representing the direction of the axels in localspace */
v3f truckv0[2];
k_board_end_radius = 0.1f,
k_board_radius = 0.14f, /* 0.07 */
- k_grind_balance = -40.0f;
+ k_grind_balance = -40.0f,
+ k_anim_transition = 0.12f;
static void player__skate_register(void){
VG_VAR_F32( k_grind_dampener, flags=VG_VAR_CHEAT );
VG_VAR_F32( k_mmcollect_vert, flags=VG_VAR_CHEAT );
VG_VAR_F32( k_mmdecay, flags=VG_VAR_CHEAT );
VG_VAR_F32( k_mmthrow_steer, flags=VG_VAR_CHEAT );
+ VG_VAR_F32( k_anim_transition, flags=VG_VAR_CHEAT );
}
static void player__skate_bind (void);