From f38069d2c55cd4b3b4c76a4b72321dfa4dd30439 Mon Sep 17 00:00:00 2001 From: hgn Date: Mon, 6 Feb 2023 05:15:59 +0000 Subject: [PATCH] prelim tricks --- player.c | 6 +-- player_skate.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++-- player_skate.h | 9 +++- player_walk.c | 98 +++++++++++++++++++++++++++---------- 4 files changed, 206 insertions(+), 35 deletions(-) diff --git a/player.c b/player.c index c898e6d..85cf916 100644 --- a/player.c +++ b/player.c @@ -265,18 +265,16 @@ PLAYER_API void player__im_gui( player_instance *player ) vg_uictx.cursor[0] = vg.window_x; +#if 0 player__debugtext( 1, "%.2f %.2f %.2f", player->cam.pos[0], player->cam.pos[1], player->cam.pos[2] ); +#endif player__debugtext( 1, "%.2f %.2f %.2f (%.2f)", player->cam.angles[0], player->cam.angles[1], player->cam.angles[2], player->cam.fov); - player__debugtext( 1, "C/K %.2f %.2f (%.2f)", - player->cam_velocity_coefficient_smooth, - player->cam_velocity_constant_smooth, - player->cam_velocity_influence_smooth ); if( _player_im_gui[ player->subsystem ] ) _player_im_gui[ player->subsystem ]( player ); diff --git a/player_skate.c b/player_skate.c index d71e3cb..788bf0b 100644 --- a/player_skate.c +++ b/player_skate.c @@ -712,6 +712,71 @@ VG_STATIC void skate_apply_interface_model( player_instance *player, } } +VG_STATIC void skate_apply_trick_model( player_instance *player ) +{ + struct player_skate *s = &player->_skate; + + v3f Fd, Fs, F; + v3f strength = { 3.7f, 3.6f, 8.0f }; + + v3_muls( s->board_trick_residualv, -4.0f , Fd ); + v3_muls( s->board_trick_residuald, -10.0f, Fs ); + v3_add( Fd, Fs, F ); + v3_mul( strength, F, F ); + + v3_muladds( s->board_trick_residualv, F, k_rb_delta, + s->board_trick_residualv ); + 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( v3_length2( s->state.trick_vel ) < 0.0001f ) + return; + + int carry_on = player->input_jump->button.value; + + /* we assume velocities share a common divisor, in which case the + * interval is the minimum value (if not zero) */ + + float min_rate = 99999.0f; + + for( int i=0; i<3; i++ ) + { + float v = s->state.trick_vel[i]; + if( (v > 0.0f) && (v < min_rate) ) + min_rate = v; + } + + float interval = 1.0f / min_rate, + current = floorf( s->state.trick_time / interval ), + next_end = (current+1.0f) * interval; + + + /* integrate trick velocities */ + v3_muladds( s->state.trick_euler, s->state.trick_vel, k_rb_delta, + s->state.trick_euler ); + + if( !carry_on && (s->state.trick_time + k_rb_delta >= next_end) ) + { + s->state.trick_time = 0.0f; + s->state.trick_euler[0] = roundf( s->state.trick_euler[0] ); + s->state.trick_euler[1] = roundf( s->state.trick_euler[1] ); + s->state.trick_euler[2] = roundf( s->state.trick_euler[2] ); + v3_copy( s->state.trick_vel, s->board_trick_residualv ); + v3_zero( s->state.trick_vel ); + } + + s->state.trick_time += k_rb_delta; + } + else + { + if( s->state.lift_frames == 0 ) + { + } + } +} + VG_STATIC void skate_apply_grab_model( player_instance *player ) { struct player_skate *s = &player->_skate; @@ -855,6 +920,12 @@ VG_STATIC void skate_apply_jump_model( player_instance *player ) s->state.steery_s = -steer[0] * maxspin; s->state.steerx = s->state.steerx_s; + v3_zero( s->state.trick_vel ); + s->state.trick_vel[0] = 3.0f; + s->state.trick_vel[2] = 6.0f; + s->state.trick_time = 0.0f; + s->state.lift_frames ++; + /* FIXME audio events */ #if 0 audio_lock(); @@ -1163,6 +1234,7 @@ VG_STATIC void player__skate_update( player_instance *player ) skate_apply_friction_model( player ); skate_apply_jump_model( player ); skate_apply_air_model( player ); + skate_apply_trick_model( player ); skate_integrate( player ); @@ -1208,16 +1280,24 @@ VG_STATIC void player__skate_im_gui( player_instance *player ) player->rb.w[1], player->rb.w[2] ); - player__debugtext( 1, "activity: %s\n", + player__debugtext( 1, "activity: %s", (const char *[]){ "k_skate_activity_air", "k_skate_activity_ground", "k_skate_activity_grind }" } [s->state.activity] ); - player__debugtext( 1, "steer_s: %5.2f %5.2f [%.2f %.2f]\n", + player__debugtext( 1, "steer_s: %5.2f %5.2f [%.2f %.2f]", s->state.steerx_s, s->state.steery_s, k_steer_ground, k_steer_air ); - player__debugtext( 1, "flip: %.4f %.4f\n", s->state.flip_rate, + player__debugtext( 1, "flip: %.4f %.4f", s->state.flip_rate, s->state.flip_time ); + player__debugtext( 1, "trickv: %.2f %.2f %.2f", + s->state.trick_vel[0], + s->state.trick_vel[1], + s->state.trick_vel[2] ); + player__debugtext( 1, "tricke: %.2f %.2f %.2f", + s->state.trick_euler[0], + s->state.trick_euler[1], + s->state.trick_euler[2] ); } VG_STATIC void player__skate_animate( player_instance *player, @@ -1395,20 +1475,58 @@ VG_STATIC void player__skate_animate( player_instance *player, v3_add( bo, kf_foot_l->co, kf_foot_l->co ); v3_add( bo, kf_foot_r->co, kf_foot_r->co ); +#if 0 m3x3f c; q_m3x3( s->board_rotation, c ); +#endif + + v4f qtotal; + + v4f qtrickr, qyawr, qpitchr, qrollr; + v3f eulerr; + + + + v3_muls( s->board_trick_residuald, VG_TAUf, eulerr ); + + q_axis_angle( qyawr, (v3f){0.0f,1.0f,0.0f}, eulerr[0] * 0.5f ); + q_axis_angle( qpitchr, (v3f){1.0f,0.0f,0.0f}, eulerr[1] ); + q_axis_angle( qrollr, (v3f){0.0f,0.0f,1.0f}, eulerr[2] ); + + q_mul( qpitchr, qrollr, qtrickr ); + q_mul( qyawr, qtrickr, qtrickr ); + q_mul( s->board_rotation, qtrickr, qtotal ); + q_normalize( qtotal ); + + q_mul( qtotal, kf_board->q, kf_board->q ); + v3f d; v3_sub( kf_foot_l->co, bo, d ); - m3x3_mulv( c, d, d ); + q_mulv( qtotal, d, d ); v3_add( bo, d, kf_foot_l->co ); v3_sub( kf_foot_r->co, bo, d ); - m3x3_mulv( c, d, d ); + q_mulv( qtotal, d, d ); v3_add( bo, d, kf_foot_r->co ); q_mul( s->board_rotation, kf_board->q, kf_board->q ); q_normalize( kf_board->q ); + + + /* trick rotation */ + v4f qtrick, qyaw, qpitch, qroll; + v3f euler; + v3_muls( s->state.trick_euler, VG_TAUf, euler ); + + 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( qroll, (v3f){0.0f,0.0f,1.0f}, euler[2] ); + + q_mul( qpitch, qroll, qtrick ); + q_mul( qyaw, qtrick, qtrick ); + q_mul( qtrick, kf_board->q, kf_board->q ); + q_normalize( kf_board->q ); } /* transform */ diff --git a/player_skate.h b/player_skate.h index f0efcf8..1833062 100644 --- a/player_skate.h +++ b/player_skate.h @@ -23,10 +23,15 @@ struct player_skate reverse, slip; + /* tricks */ v3f flip_axis; float flip_time, flip_rate; + v3f trick_vel, /* measured in units of TAU/s */ + trick_euler; /* measured in units of TAU */ + float trick_time; + m3x3f velocity_bias, velocity_bias_pstep; v3f apex; @@ -82,7 +87,9 @@ struct player_skate *anim_ollie, *anim_ollie_reverse, *anim_grabs, *anim_stop; rb_sphere sphere_front, sphere_back; - v3f board_offset; + v3f board_offset, + board_trick_residualv, + board_trick_residuald; v4f board_rotation; float blend_slide, diff --git a/player_walk.c b/player_walk.c index 0503f48..0a6a485 100644 --- a/player_walk.c +++ b/player_walk.c @@ -49,6 +49,7 @@ VG_STATIC void player_walk_generic_to_skate( player_instance *player, player__skate_reset_animator( player ); player__skate_clear_mechanics( player ); rb_update_transform( &player->rb ); + v3_copy( (v3f){0.0f,0.0f,0.0f}, s->state.trick_euler ); if( init == k_skate_activity_air ) player__approximate_best_trajectory( player ); @@ -74,6 +75,33 @@ VG_STATIC void player_walk_drop_in_to_skate( player_instance *player ) v3_copy( init_velocity, s->state.cog_v ); v3_copy( init_velocity, player->rb.v ); v3_copy( init_velocity, player->cam_velocity_smooth ); + v3_copy( (v3f){1.0f,0.0f,0.0f}, s->state.trick_euler ); +} + +VG_STATIC void player_walk_drop_in_overhang_transform( player_instance *player, + float t, + v3f co, v4f q ) +{ + struct player_walk *w = &player->_walk; + + v3f axis; + v3_cross( (v3f){0.0f,1.0f,0.0f}, w->state.drop_in_normal, axis ); + v3_normalize( axis ); + + float a = acosf( w->state.drop_in_normal[1] ) * t; + + q_axis_angle( q, axis, a ); + + float l = t * 0.5f, + heading_angle = w->state.drop_in_angle; + + v3f overhang; + overhang[0] = sinf( heading_angle ) * l; + overhang[1] = 0.28f * l; + overhang[2] = cosf( heading_angle ) * l; + + q_mulv( q, overhang, overhang ); + v3_add( w->state.drop_in_target, overhang, co ); } VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) @@ -153,6 +181,48 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player ) { v3_copy( edge, w->state.drop_in_target ); v3_copy( s1->normal, w->state.drop_in_normal ); + v3_copy( player->rb.co, w->state.drop_in_start ); + + w->state.drop_in_start_angle = player_get_heading_yaw( player ); + w->state.drop_in_angle = atan2f( w->state.drop_in_normal[0], + w->state.drop_in_normal[2] ); + + /* TODO: scan multiple of these? */ + v3f oco; + v4f oq; + player_walk_drop_in_overhang_transform( player, 1.0f, oco, oq ); + + v3f va = {0.0f,0.0f,-k_board_length - 0.3f}, + vb = {0.0f,0.0f, k_board_length + 0.3f}; + + q_mulv( oq, va, va ); + q_mulv( oq, vb, vb ); + v3_add( oco, va, va ); + v3_add( oco, vb, vb ); + + v3f v0; + v3_sub( vb, va, v0 ); + v3_normalize( v0 ); + + ray_hit ray; + ray.dist = k_board_length*2.0f + 0.6f; + + if( ray_world( va, v0, &ray ) ) + { + vg_line( va, vb, VG__RED ); + vg_line_pt3( ray.pos, 0.1f, VG__RED ); + vg_error( "invalidated\n" ); + return 0; + } + + v3_muls( v0, -1.0f, v0 ); + if( ray_world( vb, v0, &ray ) ) + { + vg_line( va, vb, VG__RED ); + vg_line_pt3( ray.pos, 0.1f, VG__RED ); + vg_error( "invalidated\n" ); + return 0; + } player_walk_drop_in_vector( player, player->rb.v ); return 1; @@ -203,11 +273,6 @@ VG_STATIC void player__walk_pre_update( player_instance *player ) w->state.outro_anim = w->anim_drop_in; w->state.outro_start_time = vg.time; w->state.activity = k_walk_activity_immobile; - v3_copy( player->rb.co, w->state.drop_in_start ); - - w->state.drop_in_start_angle = player_get_heading_yaw( player ); - w->state.drop_in_angle = atan2f( w->state.drop_in_normal[0], - w->state.drop_in_normal[2] ); struct player_avatar *av = player->playeravatar; m4x3_mulv( av->sk.final_mtx[ av->id_ik_foot_r ], @@ -506,7 +571,7 @@ VG_STATIC void player__walk_post_update( player_instance *player ) struct player_walk *w = &player->_walk; m4x3f mtx; - m3x3_identity( mtx ); + m3x3_copy( player->rb.to_world, mtx ); v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); @@ -658,27 +723,10 @@ VG_STATIC void player__walk_animate( player_instance *player, if( step_t >= 1.0f ) { v4f final_q; - v3f axis; - v3_cross( (v3f){0.0f,1.0f,0.0f}, w->state.drop_in_normal, axis ); - v3_normalize( axis ); - - float a = acosf( w->state.drop_in_normal[1] ) * dop_t; - - q_axis_angle( final_q, axis, a ); + player_walk_drop_in_overhang_transform( player, dop_t, + player->rb.co, final_q ); q_mul( final_q, dest->root_q, dest->root_q ); - float l = dop_t * 0.5f, - heading_angle = w->state.drop_in_angle; - - v3f overhang; - overhang[0] = sinf( heading_angle ) * l; - overhang[1] = 0.28f * l; - overhang[2] = cosf( heading_angle ) * l; - - q_mulv( final_q, overhang, overhang ); - - v3f overhang_pos; - v3_add( w->state.drop_in_target, overhang, player->rb.co ); v4_copy( dest->root_q, player->rb.q ); v3_muladds( dest->root_co, player->rb.to_world[1], -0.28f * dop_t, dest->root_co ); -- 2.25.1