From 5057afb71329100ab0cfb8cad3862c364637feb3 Mon Sep 17 00:00:00 2001 From: hgn Date: Wed, 15 Feb 2023 21:08:31 +0000 Subject: [PATCH] im making a note here, huge success --- player_skate.c | 320 ++++++++++++++++--------------------------------- player_skate.h | 12 +- 2 files changed, 117 insertions(+), 215 deletions(-) diff --git a/player_skate.c b/player_skate.c index 9609b7f..df3d424 100644 --- a/player_skate.c +++ b/player_skate.c @@ -596,258 +596,144 @@ VG_STATIC int skate_grind_scansq( player_instance *player, v3f pos, #endif -/* - * - * Prediction system - * - * - */ - -/* - * Trace a path given a velocity rotation. - * - * TODO: this MIGHT be worth doing RK4 on the gravity field. - */ -VG_STATIC void skate_score_biased_path( v3f co, v3f v, m3x3f vr, - struct land_prediction *prediction ) +VG_STATIC +void player__approximate_best_trajectory( player_instance *player ) { - float pstep = VG_TIMESTEP_FIXED * 10.0f; - float k_bias = 0.96f; - - v3f pco, pco1, pv; - v3_copy( co, pco ); - v3_muls( v, k_bias, pv ); - - m3x3_mulv( vr, pv, pv ); - v3_muladds( pco, pv, pstep, pco ); - - struct grind_edge *best_grind = NULL; - float closest_grind = INFINITY; + struct player_skate *s = &player->_skate; + float k_trace_delta = k_rb_delta * 10.0f; - float grind_score = INFINITY, - air_score = INFINITY, - time_to_impact = 0.0f; + s->state.air_start = vg.time; + v3_copy( player->rb.v, s->state.air_init_v ); + v3_copy( player->rb.co, s->state.air_init_co ); - v3f ground_normal, - grind_normal; + s->prediction_count = 0; - v3_copy( (v3f){0.0f,1.0f,0.0f}, ground_normal ); - v3_copy( (v3f){0.0f,1.0f,0.0f}, grind_normal ); + v3f axis; + v3_cross( player->rb.v, player->rb.to_world[1], axis ); + v3_normalize( axis ); - prediction->log_length = 0; - v3_copy( pco, prediction->apex ); + /* at high slopes, Y component is low */ + float angle_begin = -(1.0f-fabsf( player->rb.to_world[1][1] )), + angle_end = 1.0f; - for( int i=0; ilog); i++ ) + for( int m=0;m<=15; m++ ) { - v3_copy( pco, pco1 ); - - pv[1] += -k_gravity * pstep; + struct land_prediction *p = &s->predictions[ s->prediction_count ++ ]; - m3x3_mulv( vr, pv, pv ); - v3_muladds( pco, pv, pstep, pco ); + p->log_length = 0; + p->land_dist = 0.0f; + v3_zero( p->apex ); + p->type = k_prediction_none; - if( pco[1] > prediction->apex[1] ) - v3_copy( pco, prediction->apex ); - - v3f vdir; + v3f launch_co, launch_v, co0, co1; + v3_copy( player->rb.co, launch_co ); + v3_copy( player->rb.v, launch_v ); + v3_copy( launch_co, co0 ); - v3_sub( pco, pco1, vdir ); + float vt = (float)m * (1.0f/15.0f), + ang = vg_lerpf( angle_begin, angle_end, vt ) * 0.15f; - float l = v3_length( vdir ); - v3_muls( vdir, 1.0f/l, vdir ); + v4f qbias; + q_axis_angle( qbias, axis, ang ); + q_mulv( qbias, launch_v, launch_v ); + v3_copy( launch_v, p->v ); -#if 0 - v3f c0, c1; - struct grind_edge *ge = skate_collect_grind_edge( pco, pco1, - c0, c1, 0.4f ); - - if( ge && (v3_dot((v3f){0.0f,1.0f,0.0f},vdir) < -0.2f ) ) + for( int i=1; i<=50; i++ ) { - float d2 = v3_dist2( c0, c1 ); - if( d2 < closest_grind ) - { - closest_grind = d2; - best_grind = ge; - grind_score = closest_grind * 0.05f; - } - } -#endif + float t = (float)i * k_trace_delta; - /* TODO: binary search grind once we find it, do not need to - * recompute scansq, or collision. only distance - */ + v3_muls( launch_v, t, co1 ); + co1[1] += -0.5f * k_gravity * t*t; + v3_add( launch_co, co1, co1 ); - v3f closest; - if( bh_closest_point( world.geo_bh, pco, closest, k_board_length ) != -1 ) - { - struct grind_info inf; - if( skate_grind_scansq( closest, vdir, 0.5f, &inf ) ) - { - float score = -v3_dot( pv, inf.n ) * 0.06f; + float t1; + v3f n; - if( (score > 0.0f) && (score < grind_score) ) - { - grind_score = score; - } + int idx = spherecast_world( co0, co1, k_board_radius, &t1, n ); + if( idx != -1 ) + { + v3_copy( n, p->n ); + v3_lerp( co0, co1, t1, p->log[ p->log_length ++ ] ); + p->type = k_prediction_land; + + v3f ve; + v3_copy( launch_v, ve ); + ve[1] -= k_gravity * t; + p->score = -v3_dot( ve, n ); + p->land_dist = t + k_trace_delta * t1; + break; } - } - - v3f n1; - float t1; - int idx = spherecast_world( pco1, pco, 0.4f, &t1, n1 ); - if( idx != -1 ) - { - v3_copy( n1, ground_normal ); - air_score = -v3_dot( pv, n1 ); - - u32 vert_index = world.scene_geo->arrindices[ idx*3 ]; - struct world_material *mat = world_tri_index_material( vert_index ); - - /* Bias prediction towords ramps */ - if( mat->info.flags & k_material_flag_skate_surface ) - air_score *= 0.1f; - - v3_lerp( pco1, pco, t1, prediction->log[ prediction->log_length ++ ] ); - time_to_impact += t1 * pstep; - break; + v3_copy( co1, p->log[ p->log_length ++ ] ); + v3_copy( co1, co0 ); } - time_to_impact += pstep; - v3_copy( pco, prediction->log[ prediction->log_length ++ ] ); - } - - if( grind_score < air_score ) - { - prediction->score = grind_score; - prediction->type = k_prediction_grind; - v3_copy( grind_normal, prediction->n ); + if( p->type == k_prediction_none ) + s->prediction_count --; } - else if( air_score < INFINITY ) - { - prediction->score = air_score; - prediction->type = k_prediction_land; - v3_copy( ground_normal, prediction->n ); - } - else - { - prediction->score = INFINITY; - prediction->type = k_prediction_none; - } - - prediction->land_dist = time_to_impact; -} -VG_STATIC -void player__approximate_best_trajectory( player_instance *player ) -{ - struct player_skate *s = &player->_skate; - - float pstep = VG_TIMESTEP_FIXED * 10.0f; - float best_velocity_delta = -9999.9f; - - v3f axis; - v3_cross( player->rb.to_world[1], player->rb.v, axis ); - v3_normalize( axis ); + float score_min = INFINITY, + score_max = -INFINITY; - s->prediction_count = 0; - m3x3_identity( s->state.velocity_bias ); - - float best_vmod = 0.0f, - min_score = INFINITY, - max_score = -INFINITY; - - v3_zero( s->state.apex ); - v3_copy( (v3f){0.0f,1.0f,0.0f}, s->land_normal ); - /* TODO: Make part of state */ + struct land_prediction *best = NULL; - s->land_dist = 0.0f; - - /* - * Search a broad selection of futures - */ - for( int m=-3;m<=12; m++ ) + for( int i=0; iprediction_count; i ++ ) { - struct land_prediction *p = &s->predictions[ s->prediction_count ++ ]; - - float vmod = ((float)m / 15.0f)*0.09f; - - m3x3f bias; - v4f bias_q; - - q_axis_angle( bias_q, axis, vmod ); - q_m3x3( bias_q, bias ); - - skate_score_biased_path( player->rb.co, player->rb.v, bias, p ); - - if( p->type != k_prediction_none ) - { - if( p->score < min_score ) - { - min_score = p->score; - best_vmod = vmod; - s->land_dist = p->land_dist; - v3_copy( p->apex, s->state.apex ); - v3_copy( p->n, s->land_normal ); + struct land_prediction *p = &s->predictions[i]; - /* TODO: Store this as pointer? */ - } + if( p->score < score_min ) + best = p; - if( p->score > max_score ) - max_score = p->score; - } + score_min = vg_minf( score_min, p->score ); + score_max = vg_maxf( score_max, p->score ); } - v4f vr_q; - q_axis_angle( vr_q, axis, best_vmod*0.1f ); - q_m3x3( vr_q, s->state.velocity_bias ); - - q_axis_angle( vr_q, axis, best_vmod ); - q_m3x3( vr_q, s->state.velocity_bias_pstep ); - - /* - * Logging - */ for( int i=0; iprediction_count; i ++ ) { struct land_prediction *p = &s->predictions[i]; + float s = p->score; - float l = p->score; + s -= score_min; + s /= (score_max-score_min); + s = 1.0f - s; - if( l < 0.0f ) - { - vg_error( "negative score! (%f)\n", l ); - } - - l -= min_score; - l /= (max_score-min_score); - l = 1.0f - l; + p->score = s; + p->colour = s * 255.0f; - p->score = l; - p->colour = l * 255.0f; - - if( p->type == k_prediction_land ) + if( p == best ) + p->colour <<= 16; + else if( p->type == k_prediction_land ) p->colour <<= 8; p->colour |= 0xff000000; } + if( best ) + { + v3_copy( best->n, s->land_normal ); + v3_copy( best->v, player->rb.v ); + s->land_dist = best->land_dist; - v2f steer = { player->input_js1h->axis.value, - player->input_js1v->axis.value }; - v2_normalize_clamp( steer ); + v2f steer = { player->input_js1h->axis.value, + player->input_js1v->axis.value }; + v2_normalize_clamp( steer ); - if( (fabsf(steer[1]) > 0.5f) && (s->land_dist >= 1.0f) ) - { - s->state.flip_rate = (1.0f/s->land_dist) * vg_signf(steer[1]) * - s->state.reverse ; - s->state.flip_time = 0.0f; - v3_copy( player->rb.to_world[0], s->state.flip_axis ); + 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 ; + s->state.flip_time = 0.0f; + v3_copy( player->rb.to_world[0], s->state.flip_axis ); + } + else + { + s->state.flip_rate = 0.0f; + v3_zero( s->state.flip_axis ); + } } else { - s->state.flip_rate = 0.0f; - v3_zero( s->state.flip_axis ); + v3_copy( (v3f){0.0f,1.0f,0.0f}, s->land_normal ); } } @@ -867,9 +753,9 @@ VG_STATIC void skate_apply_air_model( player_instance *player ) if( s->state.activity_prev != k_skate_activity_air ) player__approximate_best_trajectory( player ); +#if 0 m3x3_mulv( s->state.velocity_bias, player->rb.v, player->rb.v ); -#if 0 ray_hit hit; /* * Prediction @@ -1063,6 +949,12 @@ VG_STATIC void skate_apply_steering_model( player_instance *player ) top = 1.5f; } + else if( s->state.manual_direction ) + { + rate = 35.0f; + top = 1.5f; + } + else if( s->state.activity >= k_skate_activity_grind_any ) { rate *= fabsf(steer_scaled); @@ -1414,7 +1306,9 @@ VG_STATIC void player__skate_post_update( player_instance *player ) vg_line_pt3( p->apex, 0.02f, 0xffffffff ); } +#if 0 vg_line_pt3( s->state.apex, 0.030f, 0xff0000ff ); +#endif } /* @@ -2243,13 +2137,10 @@ begin_collision:; } rb_update_transform( &player->rb ); - - v3f gravity = { 0.0f, -9.6f, 0.0f }; - v3_muladds( player->rb.v, gravity, s->substep_delta, player->rb.v ); + player->rb.v[1] += -k_gravity * s->substep_delta; s->substep -= s->substep_delta; - rb_ct manifold[128]; int manifold_len = 0; @@ -2259,7 +2150,6 @@ begin_collision:; */ m4x3_mulv( player->rb.to_world, s->state.head_position, head_wp1 ); -#if 0 float t; v3f n; if( (v3_dist2( head_wp0, head_wp1 ) > 0.001f) && @@ -2271,7 +2161,6 @@ begin_collision:; player__dead_transition( player ); return; } -#endif /* * Phase 1: Regular collision detection @@ -2875,8 +2764,11 @@ VG_STATIC void player__skate_clear_mechanics( player_instance *player ) s->state.slip = 0.0f; v3_copy( player->rb.co, s->state.prev_pos ); +#if 0 m3x3_identity( s->state.velocity_bias ); m3x3_identity( s->state.velocity_bias_pstep ); +#endif + v3_zero( s->state.throw_v ); v3_zero( s->state.trick_vel ); v3_zero( s->state.trick_euler ); diff --git a/player_skate.h b/player_skate.h index 37c90dc..e54754e 100644 --- a/player_skate.h +++ b/player_skate.h @@ -43,9 +43,12 @@ struct player_skate trick_euler; /* measured in units of TAU */ float trick_time; +#if 0 m3x3f velocity_bias, velocity_bias_pstep; v3f apex; +#endif + v3f up_dir; v3f head_position; @@ -60,12 +63,17 @@ struct player_skate int charging_jump, jump_dir; float jump_charge; - double jump_time; + double jump_time; double start_push, cur_push; v3f prev_pos; + + /* initial launch conditions */ + double air_start; + v3f air_init_v, + air_init_co; } state, state_gate_storage; @@ -105,6 +113,8 @@ struct player_skate v3f log[50]; v3f n; v3f apex; + v3f v; + int log_length; float score, land_dist; -- 2.25.1