X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_skate.c;h=446c4bff10a37ba932eb8a808ad6e1c0fd28461d;hb=6e29d444f89478d5965fc652373272e5d70e84e4;hp=7a661cfc894554daf21d595e30a94b897825f471;hpb=6e9b9e12e1f9da0419cd4d89707c7d599512d3b8;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_skate.c b/player_skate.c index 7a661cf..446c4bf 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" ); @@ -405,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 ); @@ -427,7 +442,6 @@ void player__approximate_best_trajectory( player_instance *player ) q_axis_angle( qbias, player->rb.to_world[1], yaw_bias ); q_mulv( qbias, launch_v, launch_v ); - float gravity_bias = vg_lerpf( 0.85f, 1.4f, vt ), gravity = k_gravity * gravity_bias; inf->gravity = gravity; @@ -444,35 +458,73 @@ 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 ); - 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] ) }; + float min_dist = 0.75f; + min_dist *= min_dist; - v2_normalize( v0 ); - v2_normalize( v1 ); + if( v3_dist2( closest, launch_co ) < min_dist ) + search_for_grind = 0; - float a = v2_dot( v0, v1 ); + v3f bound[2]; -#if 0 - if( a >= cosf( VG_PIf * /*0.185f*/ 0.02f ) ){ -#endif - grind_located = 1; - grind_located_gravity = inf->gravity; + 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] ); + } - vg_success( "Grind located\n" ); -#if 0 - } -#endif + float limh = vg_minf( 2.0f, t ), + minh = vg_minf( bound[0][1], bound[1][1] )-limh, + maxh = vg_maxf( bound[0][1], bound[1][1] )+limh; + + if( (closest[1] < minh) || (closest[1] > maxh) ){ + search_for_grind = 0; + } + } + else + search_for_grind = 0; + } + + 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 ); + + float a_min = cosf( VG_PIf * 0.185f ); + if( s->grind_cooldown ) + a_min = cosf( VG_PIf * 0.05f ); + + /* check speed */ + if( (fabsf(v3_dot( ve, grind.dir ))>=k_grind_axel_min_vel) && + (a >= a_min) ) + { + grind_located = 1; + grind_located_gravity = inf->gravity; + + vg_success( "Grind located\n" ); } } } @@ -491,7 +543,10 @@ void player__approximate_best_trajectory( player_instance *player ) float t1; v3f n; - int idx = spherecast_world( world, co0, co1, k_board_radius, &t1, n ); + float scan_radius = k_board_radius; + scan_radius *= vg_clampf( t, 0.02f, 1.0f ); + + int idx = spherecast_world( world, co0, co1, scan_radius, &t1, n ); if( idx != -1 ){ v3f co; v3_lerp( co0, co1, t1, co ); @@ -959,8 +1014,8 @@ VG_STATIC void skate_apply_jump_model( player_instance *player ) v3_normalize( jumpdir ); }else{ v3_copy( s->state.up_dir, jumpdir ); + s->grind_cooldown = 30; 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 )); @@ -969,12 +1024,15 @@ VG_STATIC void skate_apply_jump_model( player_instance *player ) q_axis_angle( qtilt, s->grind_dir, tilt ); q_mulv( qtilt, jumpdir, jumpdir ); } + s->surface_cooldown = 10; 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; + vg_success( PRINTF_v3f( jumpdir ) ); + v2f steer = { player->input_js1h->axis.value, player->input_js1v->axis.value }; v2_normalize_clamp( steer ); @@ -1073,8 +1131,12 @@ VG_STATIC void skate_integrate( player_instance *player ) decay_rate_y = 1.0f; if( s->state.activity >= k_skate_activity_grind_any ){ +#if 0 decay_rate = 1.0f-vg_lerpf( 3.0f, 20.0f, s->grind_strength ) * k_rb_delta; decay_rate_y = decay_rate; +#endif + decay_rate = 1.0f-(40.0f*k_rb_delta); + decay_rate_y = 1.0f-(10.0f*k_rb_delta); } float wx = v3_dot( player->rb.w, player->rb.to_world[0] ) * decay_rate, @@ -1177,24 +1239,23 @@ VG_STATIC void player__skate_post_update( player_instance *player ) vg_line_pt3( jump->apex, 0.02f, 0xffffffff ); } -#if 0 - vg_line_pt3( s->state.apex, 0.030f, 0xff0000ff ); -#endif - audio_lock(); 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 ), + slide = vg_clampf( fabsf(s->state.slip), 0.0f, 1.0f ); + if( s->state.activity >= k_skate_activity_grind_any ){ + slide = 0.0f; + } + + float vol_main = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ), vol_air = sqrtf( air *attn * 0.5f ), vol_slide = sqrtf( (1.0f-air)*attn*slide * 0.25f ); const u32 flags = AUDIO_FLAG_SPACIAL_3D|AUDIO_FLAG_LOOP; - if( !s->aud_main ) - s->aud_main = audio_request_channel( &audio_board[0], flags ); if( !s->aud_air ) s->aud_air = audio_request_channel( &audio_board[1], flags ); @@ -1206,16 +1267,68 @@ VG_STATIC void player__skate_post_update( player_instance *player ) /* brrrrrrrrrrrt sound for tiles and stuff * --------------------------------------------------------*/ float sidechain_amt = 0.0f, - hz = speed * 2.0f; + hz = vg_maxf( speed * 2.0f, 2.0f ); - if( s->surface == k_surface_prop_tiles ) + if( (s->surface == k_surface_prop_tiles) && + (s->state.activity < k_skate_activity_grind_any) ) sidechain_amt = 1.0f; else sidechain_amt = 0.0f; audio_set_lfo_frequency( 0, hz ); audio_set_lfo_wave( 0, k_lfo_polynomial_bipolar, - vg_lerpf( 250.0f, 80.0f, attn ) ); + vg_lerpf( 250.0f, 80.0f, attn ) ); + + if( s->sample_change_cooldown > 0.0f ){ + s->sample_change_cooldown -= vg.frame_delta; + } + else{ + int sample_type = k_skate_sample_concrete; + + if( s->state.activity == k_skate_activity_grind_5050 ){ + if( s->surface == k_surface_prop_metal ) + sample_type = k_skate_sample_metal_scrape_generic; + else + sample_type = k_skate_sample_concrete_scrape_metal; + } + else if( (s->state.activity == k_skate_activity_grind_back50) || + (s->state.activity == k_skate_activity_grind_front50) ){ + + float d = v3_dot( player->rb.to_world[2], s->grind_dir ); + + if( s->surface == k_surface_prop_metal ){ + sample_type = k_skate_sample_metal_scrape_generic; + } + else{ + if( d > 0.70710678118654752f ) + sample_type = k_skate_sample_concrete_scrape_wood; + else + sample_type = k_skate_sample_concrete_scrape_metal; + } + } + else if( s->state.activity == k_skate_activity_grind_boardslide ){ + if( s->surface == k_surface_prop_metal ) + sample_type = k_skate_sample_metal_scrape_generic; + else + sample_type = k_skate_sample_concrete_scrape_wood; + } + + audio_clip *relevant_samples[] = { + &audio_board[0], + &audio_board[0], /* TODO? */ + &audio_board[7], + &audio_board[6], + &audio_board[5] + }; + + if( (s->main_sample_type != sample_type) || (!s->aud_main) ){ + s->aud_main = + audio_channel_crossfade( s->aud_main, relevant_samples[sample_type], + 0.06f, flags ); + s->sample_change_cooldown = 0.1f; + s->main_sample_type = sample_type; + } + } if( s->aud_main ){ s->aud_main->colour = 0x00103efe; @@ -1610,7 +1723,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 ); @@ -1778,7 +1890,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 */ @@ -1790,6 +1902,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, @@ -1885,8 +2001,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->grind_cooldown < 20 ){ - s->grind_cooldown ++; + if( s->grind_cooldown ){ + s->grind_cooldown --; return k_skate_activity_undefined; } @@ -1941,26 +2057,22 @@ 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 0 - if( s->state.activity >= k_skate_activity_grind_any ) - s->frames_since_activity_change = 0; -#endif + if( new_activity == k_skate_activity_undefined ){ + if( s->state.activity >= k_skate_activity_grind_any ){ + s->grind_cooldown = 15; + s->surface_cooldown = 10; + } } - 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 ); @@ -2027,14 +2139,11 @@ VG_STATIC void player__skate_update( player_instance *player ) vy = vg_maxf( 0.0f, vy ); slap = vg_clampf( (min_dist/0.5f) + vy, 0.0f, 1.0f )*0.3f; - - wheels[0].pos[1] = slap; - wheels[1].pos[1] = slap; } - 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; @@ -2050,8 +2159,12 @@ VG_STATIC void player__skate_update( player_instance *player ) v3_zero( s->surface_picture ); - for( int i=0; iwheel_contacts[i]; + } /* check if we can enter or continue grind */ enum skate_activity grindable_activity = skate_availible_grind( player ); @@ -2075,11 +2188,32 @@ VG_STATIC void player__skate_update( player_instance *player ) v3_add( normal, s->surface_picture, s->surface_picture ); contact_count ++; + s->wheel_contacts[i] = 1; + } + else{ + s->wheel_contacts[i] = 0; } m3x3_mulv( player->rb.to_local, axel, s->truckv0[i] ); } + if( s->surface_cooldown ){ + s->surface_cooldown --; + contact_count = 0; + } + + if( (prev_contacts[0]+prev_contacts[1] == 1) && (contact_count == 2) ){ + audio_lock(); + for( int i=0; i<2; i++ ){ + if( !prev_contacts[i] ){ + v3f co; + m4x3_mulv( player->rb.to_world, wheels[i].pos, co ); + audio_oneshot_3d( &audio_taps[rand()%4], co, 40.0f, 0.75f ); + } + } + audio_unlock(); + } + if( contact_count ){ s->state.activity = k_skate_activity_ground; s->state.gravity_bias = k_gravity; @@ -2132,8 +2266,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 ); @@ -2262,7 +2395,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]; @@ -2280,13 +2413,15 @@ begin_collision:; debug_capsule( mtx, capsule.radius, capsule.height, VG__WHITE ); /* add limits */ - for( int i=0; ilimit_count; i++ ){ - struct grind_limit *limit = &s->limits[i]; - rb_ct *ct = &manifold[ manifold_len ++ ]; - m4x3_mulv( player->rb.to_world, limit->ra, ct->co ); - m3x3_mulv( player->rb.to_world, limit->n, ct->n ); - ct->p = limit->p; - ct->type = k_contact_type_default; + if( s->state.activity >= k_skate_activity_grind_any ){ + for( int i=0; ilimit_count; i++ ){ + struct grind_limit *limit = &s->limits[i]; + rb_ct *ct = &manifold[ manifold_len ++ ]; + m4x3_mulv( player->rb.to_world, limit->ra, ct->co ); + m3x3_mulv( player->rb.to_world, limit->n, ct->n ); + ct->p = limit->p; + ct->type = k_contact_type_default; + } } /* @@ -2423,6 +2558,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; @@ -2473,8 +2610,6 @@ VG_STATIC void player__skate_im_gui( player_instance *player ) "undefined (INVALID)", "grind_any (INVALID)", "grind_boardslide", - "grind_noseslide", - "grind_tailslide", "grind_back50", "grind_front50", "grind_5050" @@ -2542,6 +2677,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 * =========================================== @@ -2549,7 +2686,10 @@ 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); } @@ -2562,9 +2702,12 @@ VG_STATIC void player__skate_animate( player_instance *player, 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 ); } @@ -2631,7 +2774,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 ); @@ -2657,6 +2805,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 */ @@ -2667,16 +2840,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 ); @@ -2687,23 +2885,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 ); } @@ -2722,7 +2927,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] }; @@ -2748,15 +2953,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; @@ -2767,13 +2980,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++ ) @@ -2860,7 +3079,6 @@ VG_STATIC void player__skate_clear_mechanics( player_instance *player ) { struct player_skate *s = &player->_skate; s->state.jump_charge = 0.0f; - s->state.lift_frames = 0; s->state.flip_rate = 0.0f; #if 0 s->state.steery = 0.0f;