X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;ds=sidebyside;f=player_skate.c;h=1f99991b1846841b16540ecef2a2e1cd7df8fd49;hb=7398f8a24aaba107bafb5ab5c55141b94e10027b;hp=25f87248e2deb57ae0740f1775e11aefdfd8cac0;hpb=95054f3e156a1cb86d573b11516f2c65fe02679e;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_skate.c b/player_skate.c index 25f8724..1f99991 100644 --- a/player_skate.c +++ b/player_skate.c @@ -11,6 +11,8 @@ VG_STATIC void player__skate_bind( player_instance *player ) struct skeleton *sk = &av->sk; rb_update_transform( &player->rb ); + s->anim_grind = skeleton_get_anim( sk, "pose_grind" ); + s->anim_grind_jump = skeleton_get_anim( sk, "pose_grind_jump" ); s->anim_stand = skeleton_get_anim( sk, "pose_stand" ); s->anim_highg = skeleton_get_anim( sk, "pose_highg" ); s->anim_air = skeleton_get_anim( sk, "pose_air" ); @@ -321,6 +323,8 @@ VG_STATIC int create_jumps_to_hit_target( player_instance *player, m3x3_mulv( player->basis, inf->v, inf->v ); inf->land_dist = d[0] / (cosf(a0)*m); inf->gravity = gravity; + + v3_copy( target, inf->log[inf->log_length ++] ); } if( fabsf(a1-a) < max_angle_delta ){ @@ -332,6 +336,8 @@ VG_STATIC int create_jumps_to_hit_target( player_instance *player, m3x3_mulv( player->basis, inf->v, inf->v ); inf->land_dist = d[0] / (cosf(a1)*m); inf->gravity = gravity; + + v3_copy( target, inf->log[inf->log_length ++] ); } } @@ -401,6 +407,19 @@ void player__approximate_best_trajectory( player_instance *player ) int grind_located = 0; float grind_located_gravity = k_gravity; + + v3f launch_v_bounds[2]; + + for( int i=0; i<2; i++ ){ + v3_copy( player->rb.v, launch_v_bounds[i] ); + float ang = (float[]){ angle_begin, angle_end }[ i ]; + ang *= 0.15f; + + v4f qbias; + q_axis_angle( qbias, axis, ang ); + q_mulv( qbias, launch_v_bounds[i], launch_v_bounds[i] ); + } + for( int m=0;m<=30; m++ ){ jump_info *inf = &s->possible_jumps[ s->possible_jump_count ++ ]; reset_jump_info( inf ); @@ -440,35 +459,59 @@ void player__approximate_best_trajectory( player_instance *player ) v3_add( launch_co, co1, co1 ); float launch_vy = v3_dot( launch_v,basis[1] ); - if( !grind_located && (launch_vy - gravity*t < 0.0f) ){ - v3f closest; + + int search_for_grind = 1; + if( grind_located ) search_for_grind = 0; + if( launch_vy - gravity*t > 0.0f ) search_for_grind = 0; + + /* TODO Cleanup */ + + v3f closest; + if( search_for_grind ){ if( bh_closest_point( world->geo_bh, co1, closest, 1.0f ) != -1 ){ - v3f ve; - v3_copy( launch_v, ve ); - v3_muladds( ve, basis[1], -gravity * t, ve ); + v3f bound[2]; - if( skate_grind_scansq( player, closest, ve, 0.5f, &grind ) ){ - /* check alignment */ - v2f v0 = { v3_dot( ve, basis[0] ), - v3_dot( ve, basis[2] ) }, - v1 = { v3_dot( grind.dir, basis[0] ), - v3_dot( grind.dir, basis[2] ) }; + for( int j=0; j<2; j++ ){ + v3_muls( launch_v_bounds[j], t, bound[j] ); + v3_muladds( bound[j], basis[1], -0.5f*gravity*t*t, bound[j] ); + v3_add( launch_co, bound[j], bound[j] ); + } - v2_normalize( v0 ); - v2_normalize( v1 ); + float minh = vg_minf( bound[0][1], bound[1][1] ), + maxh = vg_maxf( bound[0][1], bound[1][1] ); - float a = v2_dot( v0, v1 ); + vg_info( "%f [%f:%f]\n", closest[1], minh, maxh ); -#if 0 - if( a >= cosf( VG_PIf * /*0.185f*/ 0.02f ) ){ -#endif - grind_located = 1; - grind_located_gravity = inf->gravity; + if( (closest[1] < minh) || (closest[1] > maxh) ){ + search_for_grind = 0; + } + } + else + search_for_grind = 0; + } - vg_success( "Grind located\n" ); -#if 0 - } -#endif + if( search_for_grind ){ + v3f ve; + v3_copy( launch_v, ve ); + v3_muladds( ve, basis[1], -gravity * t, ve ); + + if( skate_grind_scansq( player, closest, ve, 0.5f, &grind ) ){ + /* check alignment */ + v2f v0 = { v3_dot( ve, basis[0] ), + v3_dot( ve, basis[2] ) }, + v1 = { v3_dot( grind.dir, basis[0] ), + v3_dot( grind.dir, basis[2] ) }; + + v2_normalize( v0 ); + v2_normalize( v1 ); + + float a = v2_dot( v0, v1 ); + + if( a >= cosf( VG_PIf * 0.185f ) ){ + grind_located = 1; + grind_located_gravity = inf->gravity; + + vg_success( "Grind located\n" ); } } } @@ -510,6 +553,11 @@ void player__approximate_best_trajectory( player_instance *player ) v3_cross( v0, v1, inf->n ); v3_normalize( inf->n ); #endif + /* TODO: + * grind predictions, we want to FORCE it to land in the correct + * location, taking the cloest endpoint or midpoint to be the + * snapper. + */ inf->type = k_prediction_land; @@ -543,7 +591,16 @@ void player__approximate_best_trajectory( player_instance *player ) int valid_count = create_jumps_to_hit_target( player, grind_jumps, grind.co, - 0.25f*VG_PIf, grind_located_gravity ); + 0.175f*VG_PIf, grind_located_gravity ); + + /* knock out original landing points in the 1m area + * TODO: Make this a konstant */ + for( u32 j=0; jpossible_jump_count; j++ ){ + jump_info *jump = &s->possible_jumps[ j ]; + float dist = v3_dist2( jump->log[jump->log_length-1], grind.co ); + float descale = 1.0f-vg_minf(1.0f,dist); + jump->score += descale*3.0f; + } for( int i=0; igravity * t*t, co0 ); v3_add( launch_co, co0, co0 ); +#if 0 /* rough scan to make sure we dont collide with anything */ for( int j=1; j<=16; j++ ){ t = (float)j*(1.0f/16.0f); @@ -584,6 +642,7 @@ void player__approximate_best_trajectory( player_instance *player ) v3_copy( co1, co0 ); } +#endif v3_copy( grind.n, jump->n ); @@ -595,8 +654,10 @@ void player__approximate_best_trajectory( player_instance *player ) s->possible_jumps[ s->possible_jump_count ++ ] = *jump; +#if 0 continue; invalidated_grind:; +#endif } } @@ -645,6 +706,10 @@ invalidated_grind:; v2_normalize_clamp( steer ); s->state.gravity_bias = best->gravity; + if( best->type == k_prediction_grind ){ + s->state.activity = k_skate_activity_air_to_grind; + } + if( (fabsf(steer[1]) > 0.5f) && (s->land_dist >= 1.5f) ){ s->state.flip_rate = (1.0f/s->land_dist) * vg_signf(steer[1]) * s->state.reverse ; @@ -674,7 +739,7 @@ VG_STATIC void skate_apply_air_model( player_instance *player ) { struct player_skate *s = &player->_skate; - if( s->state.activity_prev != k_skate_activity_air ) + if( s->state.activity_prev > k_skate_activity_air_to_grind ) player__approximate_best_trajectory( player ); float angle = v3_dot( player->rb.to_world[1], s->land_normal ); @@ -710,7 +775,7 @@ VG_STATIC void skate_apply_trick_model( player_instance *player ) v3_muladds( s->board_trick_residuald, s->board_trick_residualv, k_rb_delta, s->board_trick_residuald ); - if( s->state.activity == k_skate_activity_air ){ + if( s->state.activity <= k_skate_activity_air_to_grind ){ if( v3_length2( s->state.trick_vel ) < 0.0001f ) return; @@ -797,7 +862,7 @@ VG_STATIC void skate_apply_steering_model( player_instance *player ) float rate = 26.0f, top = 1.0f; - if( s->state.activity == k_skate_activity_air ){ + if( s->state.activity <= k_skate_activity_air_to_grind ){ rate = 6.0f * fabsf(steer); top = 1.5f; } @@ -861,8 +926,11 @@ VG_STATIC void skate_apply_friction_model( player_instance *player ) s->state.slip = slip; s->state.reverse = -vg_signf(vel[2]); - vel[0] += vg_cfrictf( vel[0], k_friction_lat * k_rb_delta ); - vel[2] += vg_cfrictf( vel[2], k_friction_resistance * k_rb_delta ); + float S = (float)s->grind_cooldown * (1.0f/20.0f); + S = vg_minf( S, 1.0f ); + + vel[0] += vg_cfrictf( vel[0], S * k_friction_lat * k_rb_delta ); + vel[2] += vg_cfrictf( vel[2], S * k_friction_resistance * k_rb_delta ); /* Pushing additive force */ @@ -899,7 +967,7 @@ VG_STATIC void skate_apply_jump_model( player_instance *player ) s->state.charging_jump = player->input_jump->button.value; /* Cannot charge this in air */ - if( s->state.activity == k_skate_activity_air ){ + if( s->state.activity <= k_skate_activity_air_to_grind ){ s->state.charging_jump = 0; return; } @@ -933,25 +1001,25 @@ VG_STATIC void skate_apply_jump_model( player_instance *player ) v3_normalize( jumpdir ); }else{ v3_copy( s->state.up_dir, jumpdir ); + s->state.activity = k_skate_activity_ground; + s->grind_cooldown = 0; + + float tilt = player->input_js1h->axis.value * 0.3f; + tilt *= vg_signf(v3_dot( player->rb.v, s->grind_dir )); + + v4f qtilt; + q_axis_angle( qtilt, s->grind_dir, tilt ); + q_mulv( qtilt, jumpdir, jumpdir ); } float force = k_jump_force*s->state.jump_charge; v3_muladds( player->rb.v, jumpdir, force, player->rb.v ); s->state.jump_charge = 0.0f; s->state.jump_time = vg.time; - s->state.activity = k_skate_activity_air; v2f steer = { player->input_js1h->axis.value, player->input_js1v->axis.value }; v2_normalize_clamp( steer ); - skate_apply_air_model( player ); - -#if 0 - float maxspin = k_steer_air * k_rb_delta * k_spin_boost; - s->state.steery_s = -steer[0] * maxspin; - s->state.steerx = s->state.steerx_s; - s->state.lift_frames ++; -#endif audio_lock(); audio_oneshot_3d( &audio_jumps[rand()%2], player->rb.co, 40.0f, 1.0f ); @@ -1103,7 +1171,7 @@ VG_STATIC void player__skate_pre_update( player_instance *player ) } int trick_id; - if( (s->state.activity == k_skate_activity_air) && + if( (s->state.activity <= k_skate_activity_air_to_grind) && (trick_id = player_skate_trick_input( player )) ) { if( (vg.time - s->state.jump_time) < 0.1f ){ @@ -1130,6 +1198,10 @@ VG_STATIC void player__skate_post_update( player_instance *player ) for( int i=0; ipossible_jump_count; i++ ){ jump_info *jump = &s->possible_jumps[i]; + + if( jump->log_length == 0 ){ + vg_fatal_exit_loop( "assert: jump->log_length == 0\n" ); + } for( int j=0; jlog_length - 1; j ++ ){ float brightness = jump->score*jump->score*jump->score; @@ -1153,7 +1225,7 @@ VG_STATIC void player__skate_post_update( player_instance *player ) audio_lock(); - float air = s->state.activity == k_skate_activity_air? 1.0f: 0.0f, + float air = s->state.activity <= k_skate_activity_air_to_grind? 1.0f: 0.0f, speed = v3_length( player->rb.v ), attn = vg_minf( 1.0f, speed*0.1f ), slide = vg_clampf( fabsf(s->state.slip), 0.0f, 1.0f ), @@ -1420,13 +1492,11 @@ VG_STATIC void skate_adjust_up_direction( player_instance *player ) v3_lerp( s->state.up_dir, target, 8.0f * s->substep_delta, s->state.up_dir ); } - else if( s->state.activity == k_skate_activity_air ) - { + else if( s->state.activity <= k_skate_activity_air_to_grind ){ v3_lerp( s->state.up_dir, player->rb.to_world[1], 8.0f * s->substep_delta, s->state.up_dir ); } - else - { + else{ v3_lerp( s->state.up_dir, player->basis[1], 12.0f * s->substep_delta, s->state.up_dir ); } @@ -1582,7 +1652,6 @@ VG_STATIC void skate_5050_apply( player_instance *player, v3_normalize( axis ); v3_cross( axis, inf_avg.dir, inf_avg.n ); - skate_grind_decay( player, &inf_avg, 1.0f ); @@ -1750,7 +1819,7 @@ VG_STATIC void skate_boardslide_apply( player_instance *player, intersection ); v3_copy( intersection, s->weight_distribution ); - skate_grind_decay( player, inf, 0.1f ); + skate_grind_decay( player, inf, 0.0125f ); skate_grind_friction( player, inf, 0.25f ); /* direction alignment */ @@ -1762,6 +1831,10 @@ VG_STATIC void skate_boardslide_apply( player_instance *player, m3x3_mulv( player->rb.to_world, dir, dir ); m3x3_mulv( player->rb.to_world, perp, perp ); + v4f qbalance; + q_axis_angle( qbalance, dir, local_co[0]*k_grind_balance ); + q_mulv( qbalance, perp, perp ); + rb_effect_spring_target_vector( &player->rb, player->rb.to_world[0], dir, k_grind_spring, k_grind_dampener, @@ -1793,7 +1866,7 @@ VG_STATIC int skate_boardslide_entry( player_instance *player, if( (fabsf(local_co[2]) <= k_board_length) && /* within wood area */ (local_co[1] >= 0.0f) && /* at deck level */ - (fabsf(local_dir[0]) >= 0.5f) ) /* perpendicular to us */ + (fabsf(local_dir[0]) >= 0.25f) ) /* perpendicular to us */ { if( fabsf(v3_dot( player->rb.v, inf->dir )) < k_grind_axel_min_vel ) return 0; @@ -1857,9 +1930,8 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player ) struct player_skate *s = &player->_skate; /* debounces this state manager a little bit */ - if( s->frames_since_activity_change < 10 ) - { - s->frames_since_activity_change ++; + if( s->grind_cooldown < 20 ){ + s->grind_cooldown ++; return k_skate_activity_undefined; } @@ -1871,33 +1943,27 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player ) res_front50 = 0, res_slide = 0; - if( s->state.activity == k_skate_activity_grind_boardslide ) - { + if( s->state.activity == k_skate_activity_grind_boardslide ){ res_slide = skate_boardslide_renew( player, &inf_slide ); } - else if( s->state.activity == k_skate_activity_grind_back50 ) - { + else if( s->state.activity == k_skate_activity_grind_back50 ){ res_back50 = skate_grind_truck_renew( player, 1.0f, &inf_back50 ); res_front50 = skate_grind_truck_entry( player, -1.0f, &inf_front50 ); } - else if( s->state.activity == k_skate_activity_grind_front50 ) - { + else if( s->state.activity == k_skate_activity_grind_front50 ){ res_front50 = skate_grind_truck_renew( player, -1.0f, &inf_front50 ); res_back50 = skate_grind_truck_entry( player, 1.0f, &inf_back50 ); } - else if( s->state.activity == k_skate_activity_grind_5050 ) - { + else if( s->state.activity == k_skate_activity_grind_5050 ){ res_front50 = skate_grind_truck_renew( player, -1.0f, &inf_front50 ); res_back50 = skate_grind_truck_entry( player, 1.0f, &inf_back50 ); } - else - { + else{ res_slide = skate_boardslide_entry( player, &inf_slide ); res_back50 = skate_grind_truck_entry( player, 1.0f, &inf_back50 ); res_front50 = skate_grind_truck_entry( player, -1.0f, &inf_front50 ); - if( res_back50 != res_front50 ) - { + if( res_back50 != res_front50 ){ int wants_to_do_that = fabsf(player->input_js1v->axis.value) >= 0.25f; res_back50 &= wants_to_do_that; @@ -1920,24 +1986,20 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player ) } , new_activity = table[ res_slide << 2 | res_back50 << 1 | res_front50 ]; - if( new_activity == k_skate_activity_undefined ) - { + if( new_activity == k_skate_activity_undefined ){ if( s->state.activity >= k_skate_activity_grind_any ) - s->frames_since_activity_change = 0; + s->grind_cooldown = 5; } - else if( new_activity == k_skate_activity_grind_boardslide ) - { + else if( new_activity == k_skate_activity_grind_boardslide ){ skate_boardslide_apply( player, &inf_slide ); } - else if( new_activity == k_skate_activity_grind_back50 ) - { + else if( new_activity == k_skate_activity_grind_back50 ){ if( s->state.activity != k_skate_activity_grind_back50 ) skate_store_grind_vec( player, &inf_back50 ); skate_grind_truck_apply( player, 1.0f, &inf_back50, 1.0f ); } - else if( new_activity == k_skate_activity_grind_front50 ) - { + else if( new_activity == k_skate_activity_grind_front50 ){ if( s->state.activity != k_skate_activity_grind_front50 ) skate_store_grind_vec( player, &inf_front50 ); @@ -1988,7 +2050,7 @@ VG_STATIC void player__skate_update( player_instance *player ) float slap = 0.0f; - if( s->state.activity == k_skate_activity_air ){ + if( s->state.activity <= k_skate_activity_air_to_grind ){ float min_dist = 0.6f; for( int i=0; i<2; i++ ){ @@ -2000,21 +2062,15 @@ VG_STATIC void player__skate_update( player_instance *player ) } } min_dist -= 0.2f; - float o = vg_clampf( min_dist/0.5f, 0.0f, 1.0f ); - -#if 0 - float jump_t = vg.time - s->state.jump_time; - jump_t = vg_minf( o, 1.0f ); -#endif + float vy = v3_dot( player->basis[1], player->rb.v ); + vy = vg_maxf( 0.0f, vy ); - slap = o*0.3f;//vg_minf((1.0f-fabsf(2.0f*jump_t-1.0f))*8.0f,1.0f) * 0.3f; - wheels[0].pos[1] = slap; - wheels[1].pos[1] = slap; + slap = vg_clampf( (min_dist/0.5f) + vy, 0.0f, 1.0f )*0.3f; } - s->slap = slap; - - + s->state.slap = vg_lerpf( s->state.slap, slap, 10.0f*k_rb_delta ); + wheels[0].pos[1] = s->state.slap; + wheels[1].pos[1] = s->state.slap; @@ -2069,7 +2125,9 @@ VG_STATIC void player__skate_update( player_instance *player ) skate_weight_distribute( player ); } else{ - s->state.activity = k_skate_activity_air; + if( s->state.activity > k_skate_activity_air_to_grind ) + s->state.activity = k_skate_activity_air; + v3_zero( s->weight_distribution ); skate_apply_air_model( player ); } @@ -2110,8 +2168,7 @@ begin_collision:; v4f future_q; v3_muladds( player->rb.co, player->rb.v, s->substep, future_co ); - if( v3_length2( player->rb.w ) > 0.0f ) - { + if( v3_length2( player->rb.w ) > 0.0f ){ v4f rotation; v3f axis; v3_copy( player->rb.w, axis ); @@ -2240,7 +2297,7 @@ begin_collision:; v3_muls( player->rb.to_world[2], -1.0f, mtx[1] ); v3_muls( player->rb.to_world[1], 1.0f, mtx[2] ); v3_muladds( player->rb.to_world[3], player->rb.to_world[1], - grind_radius + k_board_radius*0.25f+slap, mtx[3] ); + grind_radius + k_board_radius*0.25f+s->state.slap, mtx[3] ); rb_ct *cman = &manifold[manifold_len]; @@ -2401,6 +2458,8 @@ begin_collision:; v4f transport_rotation; m3x3_q( gate->transport, transport_rotation ); q_mul( transport_rotation, player->rb.q, player->rb.q ); + q_mul( transport_rotation, s->state.smoothed_rotation, + s->state.smoothed_rotation ); rb_update_transform( &player->rb ); s->state_gate_storage = s->state; @@ -2446,6 +2505,7 @@ VG_STATIC void player__skate_im_gui( player_instance *player ) const char *activity_txt[] = { "air", + "air_to_grind", "ground", "undefined (INVALID)", "grind_any (INVALID)", @@ -2519,6 +2579,8 @@ VG_STATIC void player__skate_animate( player_instance *player, offset[0]=vg_clampf(offset[0],-0.8f,0.8f)*(1.0f-fabsf(s->blend_slide)*0.9f); offset[1]=vg_clampf(offset[1],-0.5f,0.0f); + v3_muls( offset, 0.3f, TEMP_TPV_EXTRA ); + /* * Animation blending * =========================================== @@ -2526,22 +2588,28 @@ VG_STATIC void player__skate_animate( player_instance *player, /* sliding */ { - float desired = vg_clampf( fabsf( s->state.slip ), 0.0f, 1.0f ); + float desired = 0.0f; + if( s->state.activity == k_skate_activity_ground ) + desired = vg_clampf( fabsf( s->state.slip ), 0.0f, 1.0f ); + s->blend_slide = vg_lerpf( s->blend_slide, desired, 2.4f*vg.time_delta); } /* movement information */ { - int iair = s->state.activity == k_skate_activity_air; + int iair = s->state.activity <= k_skate_activity_air_to_grind; float dirz = s->state.reverse > 0.0f? 0.0f: 1.0f, dirx = s->state.slip < 0.0f? 0.0f: 1.0f, fly = iair? 1.0f: 0.0f, wdist= s->weight_distribution[2] / k_board_length; + if( s->state.activity >= k_skate_activity_grind_any ) + wdist = 0.0f; + s->blend_z = vg_lerpf( s->blend_z, dirz, 2.4f*vg.time_delta ); s->blend_x = vg_lerpf( s->blend_x, dirx, 0.6f*vg.time_delta ); - s->blend_fly = vg_lerpf( s->blend_fly, fly, 2.4f*vg.time_delta ); + s->blend_fly = vg_lerpf( s->blend_fly, fly, 3.4f*vg.time_delta ); s->blend_weight= vg_lerpf( s->blend_weight, wdist, 9.0f*vg.time_delta ); } @@ -2608,7 +2676,12 @@ VG_STATIC void player__skate_animate( player_instance *player, mdl_keyframe air_pose[32]; { float target = -player->input_js1h->axis.value; + +#if 1 s->blend_airdir = vg_lerpf( s->blend_airdir, target, 2.4f*vg.time_delta ); +#else + s->blend_airdir = 0.0f; +#endif float air_frame = (s->blend_airdir*0.5f+0.5f) * (15.0f/30.0f); skeleton_sample_anim( sk, s->anim_air, air_frame, apose ); @@ -2634,6 +2707,31 @@ VG_STATIC void player__skate_animate( player_instance *player, skeleton_lerp_pose( sk, ground_pose, air_pose, s->blend_fly, dest->pose ); + + mdl_keyframe grind_pose[32]; + { + /* TODO: factor balance into this sampler */ + float grind_frame = 0.5f; + + if( s->state.activity == k_skate_activity_grind_front50 ){ + grind_frame = 0.0f; + } else if( s->state.activity == k_skate_activity_grind_back50 ){ + grind_frame = 1.0f; + } + + float grind=s->state.activity >= k_skate_activity_grind_any? 1.0f: 0.0f; + s->blend_grind = vg_lerpf( s->blend_grind, grind, 5.0f*vg.time_delta ); + s->blend_grind_balance=vg_lerpf( s->blend_grind_balance, + grind_frame, 5.0f*vg.time_delta ); + + grind_frame = s->blend_grind_balance * (15.0f/30.0f); + + skeleton_sample_anim( sk, s->anim_grind, grind_frame, apose ); + skeleton_sample_anim( sk, s->anim_grind_jump, grind_frame, bpose ); + skeleton_lerp_pose( sk, apose, bpose, s->blend_jump, grind_pose ); + } + skeleton_lerp_pose( sk, dest->pose, grind_pose, s->blend_grind, dest->pose ); + float add_grab_mod = 1.0f - s->blend_fly; /* additive effects */ @@ -2644,16 +2742,41 @@ VG_STATIC void player__skate_animate( player_instance *player, av->id_ik_elbow_l, av->id_ik_elbow_r }; - for( int i=0; ipose[apply_to[i]-1].co[0] += offset[0]*add_grab_mod; dest->pose[apply_to[i]-1].co[2] += offset[2]*add_grab_mod; } - /* angle correction */ - if( v3_length2( s->state.up_dir ) > 0.001f ) - { + if( v3_length2( s->state.up_dir ) > 0.001f ){ + + if( v4_length(s->state.smoothed_rotation) <= 0.1f || + v4_length(s->state.smoothed_rotation) >= 1.1f ){ + vg_warn( "FIX THIS! CARROT\n" ); + v4_copy( player->rb.q, s->state.smoothed_rotation ); + } + v4_lerp( s->state.smoothed_rotation, player->rb.q, 2.0f*vg.frame_delta, + s->state.smoothed_rotation ); + q_normalize( s->state.smoothed_rotation ); + + v3f yaw_ref = {1.0f,0.0f,0.0f}, + yaw_smooth = {1.0f,0.0f,0.0f}; + q_mulv( player->rb.q, yaw_ref, yaw_ref ); + q_mulv( s->state.smoothed_rotation, yaw_smooth, yaw_smooth ); + m3x3_mulv( player->rb.to_local, yaw_smooth, yaw_smooth ); + m3x3_mulv( player->rb.to_local, yaw_ref, yaw_ref ); + + float yaw_counter_rotate = v3_dot(yaw_ref,yaw_smooth); + yaw_counter_rotate = vg_clampf(yaw_counter_rotate,-1.0f,1.0f); + yaw_counter_rotate = acosf( yaw_counter_rotate ); + yaw_counter_rotate *= 1.0f-s->blend_fly; + v3f ndir; m3x3_mulv( player->rb.to_local, s->state.up_dir, ndir ); v3_normalize( ndir ); @@ -2664,23 +2787,30 @@ VG_STATIC void player__skate_animate( player_instance *player, a = acosf( vg_clampf( a, -1.0f, 1.0f ) ); v3f axis; - v4f q; + v4f qfixup, qcounteryaw, qtotal; v3_cross( up, ndir, axis ); - q_axis_angle( q, axis, a ); + q_axis_angle( qfixup, axis, a ); + + q_axis_angle( qcounteryaw, (v3f){0.0f,1.0f,0.0f}, yaw_counter_rotate ); + q_mul( qcounteryaw, qfixup, qtotal ); + q_normalize( qtotal ); mdl_keyframe *kf_hip = &dest->pose[av->id_hip-1]; - - for( int i=0; isk.bones[av->id_hip].co, kf_hip->co, origin ); + + for( int i=0; ipose[apply_to[i]-1]; - v3f v0; - v3_sub( kf->co, kf_hip->co, v0 ); - q_mulv( q, v0, v0 ); - v3_add( v0, kf_hip->co, kf->co ); + v3f v0, co; + v3_add( kf->co, av->sk.bones[apply_to[i]].co, co ); + v3_sub( co, origin, v0 ); + q_mulv( qtotal, v0, v0 ); + v3_add( v0, origin, co ); + v3_sub( co, av->sk.bones[apply_to[i]].co, kf->co ); - q_mul( q, kf->q, kf->q ); + q_mul( qtotal, kf->q, kf->q ); q_normalize( kf->q ); } @@ -2699,7 +2829,7 @@ VG_STATIC void player__skate_animate( player_instance *player, *kf_foot_r = &dest->pose[av->id_ik_foot_r-1], *kf_knee_l = &dest->pose[av->id_ik_knee_l-1], *kf_knee_r = &dest->pose[av->id_ik_knee_r-1], - *kf_hip = &dest->pose[av->id_hip], + *kf_hip = &dest->pose[av->id_hip-1], *kf_wheels[] = { &dest->pose[av->id_wheel_r-1], &dest->pose[av->id_wheel_l-1] }; @@ -2725,15 +2855,23 @@ VG_STATIC void player__skate_animate( player_instance *player, v3f euler; v3_muls( s->state.trick_euler, VG_TAUf, euler ); + float jump_t = vg.time-s->state.jump_time; + + float k=17.0f; + float h = k*jump_t; + float extra = h*exp(1.0-h) * (s->state.jump_dir?1.0f:-1.0f); + extra *= s->state.slap * 4.0f; + q_axis_angle( qyaw, (v3f){0.0f,1.0f,0.0f}, euler[0] * 0.5f ); - q_axis_angle( qpitch, (v3f){1.0f,0.0f,0.0f}, euler[1] ); + q_axis_angle( qpitch, (v3f){1.0f,0.0f,0.0f}, euler[1] + extra ); q_axis_angle( qroll, (v3f){0.0f,0.0f,1.0f}, euler[2] ); - q_mul( qpitch, qroll, qtrick ); - q_mul( qyaw, qtrick, qtrick ); + q_mul( qyaw, qroll, qtrick ); + q_mul( qpitch, qtrick, qtrick ); q_mul( kf_board->q, qtrick, kf_board->q ); q_normalize( kf_board->q ); + /* foot weight distribution */ if( s->blend_weight > 0.0f ){ kf_foot_l->co[2] += s->blend_weight * 0.2f; @@ -2744,13 +2882,19 @@ VG_STATIC void player__skate_animate( player_instance *player, kf_foot_l->co[2] += s->blend_weight * 0.1f; } - kf_foot_l->co[1] += s->slap; - kf_foot_r->co[1] += s->slap; - kf_knee_l->co[1] += s->slap; - kf_knee_r->co[1] += s->slap; - kf_board->co[1] += s->slap; - kf_hip->co[1] += s->slap * 0.25f; - + kf_foot_l->co[1] += s->state.slap; + kf_foot_r->co[1] += s->state.slap; + kf_knee_l->co[1] += s->state.slap; + kf_knee_r->co[1] += s->state.slap; + kf_board->co[1] += s->state.slap; + kf_hip->co[1] += s->state.slap * 0.25f; + + /* + * animation wishlist: + * boardslide/grind jump animations + * when tricking the slap should not appply or less apply + * not animations however DONT target grinds that are vertically down. + */ /* truck rotation */ for( int i=0; i<2; i++ ) @@ -2772,7 +2916,7 @@ VG_STATIC void player__skate_animate( player_instance *player, float substep = vg_clampf( vg.accumulator / VG_TIMESTEP_FIXED, 0.0f, 1.0f ); v4f qflip; - if( (s->state.activity == k_skate_activity_air) && + if( (s->state.activity <= k_skate_activity_air_to_grind) && (fabsf(s->state.flip_rate) > 0.01f) ) { float t = s->state.flip_time; @@ -2819,7 +2963,7 @@ VG_STATIC void player__skate_reset_animator( player_instance *player ) { struct player_skate *s = &player->_skate; - if( s->state.activity == k_skate_activity_air ) + if( s->state.activity <= k_skate_activity_air_to_grind ) s->blend_fly = 1.0f; else s->blend_fly = 0.0f;