foot alignment
authorhgn <hgodden00@gmail.com>
Sat, 11 Jun 2022 14:34:20 +0000 (15:34 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 11 Jun 2022 14:34:20 +0000 (15:34 +0100)
character.h
main.c

index 51f2c16231af84491768951623b1b5a953250e23..70c1727a8c68308002c34ad7cb9b57edfd47846d 100644 (file)
@@ -205,6 +205,37 @@ static int character_load( struct character *ch, const char *name )
    return 1;
 }
 
+static void align_to_board( struct character *ch, enum character_part id )
+{
+   /* Calculate rotation between board and feet */
+   m4x3f *mats = ch->matrices;
+
+   v3f foot_pos, foot_fwd, foot_target, board_norm, board_origin;
+   v3_copy( mats[id][3], foot_pos );
+   m3x3_mulv( mats[id], (v3f){1.0f,0.0f,0.0f}, foot_fwd );
+   v3_add( foot_fwd, foot_pos, foot_target );
+
+   m3x3_mulv( mats[k_chpart_board], (v3f){0.0f,1.0f,0.0f}, board_norm );
+   m4x3_mulv( mats[k_chpart_board], (v3f){0.0f,0.13f,0.0f}, board_origin ); 
+
+   vg_line( foot_pos, foot_target, 0xff00ff00 );
+
+   v3f v0;
+   v3_sub( board_origin, foot_target, v0 );
+   float t = v3_dot( v0, board_norm ) / board_norm[1];
+   foot_target[1] += t;
+   vg_line( foot_pos, foot_target, 0xff00ffff );
+   
+   v3_sub( foot_target, foot_pos, foot_target );
+   v3_normalize( foot_target );
+   float ang = acosf( v3_dot( foot_target, foot_fwd ) );
+
+   v4f qcorrection; m3x3f correction;
+   q_axis_angle( qcorrection, (v3f){0.0f,0.0f,1.0f}, -ang );
+   q_m3x3( qcorrection, correction );
+   m3x3_mul( mats[id], correction, mats[id] );
+}
+
 static void character_eval( struct character *ch )
 {
    m4x3f *mats = ch->matrices;
@@ -240,14 +271,6 @@ static void character_eval( struct character *ch )
          k_ikY, k_iknX );
    ik_basic( &ch->ik_leg_r, mats[k_chpart_leg_r0], mats[k_chpart_leg_r1],
          k_ikY, k_iknX );
-
-   /* Feet */
-   m3x3_copy( mats[k_chpart_leg_l1], mats[k_chpart_foot_l] );
-   m3x3_copy( mats[k_chpart_leg_r1], mats[k_chpart_foot_r] );
-   m4x3_mulv( mats[k_chpart_leg_l1], offs[k_chpart_foot_l], 
-         mats[k_chpart_foot_l][3] );
-   m4x3_mulv( mats[k_chpart_leg_r1], offs[k_chpart_foot_r], 
-         mats[k_chpart_foot_r][3] );
    
    /* Hands */
    m3x3_copy( mats[k_chpart_arm_l1], mats[k_chpart_hand_l] );
@@ -268,6 +291,17 @@ static void character_eval( struct character *ch )
    //m3x3_mul( mats[k_chpart_neck], mats[k_chpart_head], mats[k_chpart_head] );
    m4x3_mulv( mats[k_chpart_neck], offs[k_chpart_head], mats[k_chpart_head][3]);
 
+   /* Feet */
+   m3x3_copy( mats[k_chpart_leg_l1], mats[k_chpart_foot_l] );
+   m3x3_copy( mats[k_chpart_leg_r1], mats[k_chpart_foot_r] );
+   m4x3_mulv( mats[k_chpart_leg_l1], offs[k_chpart_foot_l], 
+         mats[k_chpart_foot_l][3] );
+   m4x3_mulv( mats[k_chpart_leg_r1], offs[k_chpart_foot_r], 
+         mats[k_chpart_foot_r][3] );
+
+   align_to_board( ch, k_chpart_foot_l );
+   align_to_board( ch, k_chpart_foot_r );
+   
    for( int i=0; i<PART_COUNT; i++ )
       m4x3_mul( ch->mroot, ch->matrices[i], ch->matrices[i] );
 }
diff --git a/main.c b/main.c
index 69d4df93e5c0dd2501bef4f9f3dd256188c90110..61f0a584dd137bff175213a381b34a64d648c5b4 100644 (file)
--- a/main.c
+++ b/main.c
@@ -460,6 +460,16 @@ static int sample_if_resistant( v3f pos )
    return 0;
 }
 
+static float stable_force( float current, float diff )
+{
+   float new = current + diff;
+
+   if( new * current < 0.0f )
+      return 0.0f;
+
+   return new;
+}
+
 static void player_physics_ground(void)
 {
    /* 
@@ -543,10 +553,8 @@ static void player_physics_ground(void)
    float substep = ktimestep * 0.2f;
    for( int i=0; i<5; i++ )
    {
-      if( fabsf(vel[2]) >= 0.02f*substep )
-         vel[2] += vg_signf( vel[2] ) * -0.02f * substep;
-      if( fabsf(vel[0]) >= 7.0f*substep )
-         vel[0] += vg_signf( vel[0] ) * -7.0f * substep;
+      vel[2] = stable_force( vel[2], vg_signf( vel[2] ) * -0.02f*substep );
+      vel[0] = stable_force( vel[0], vg_signf( vel[0] ) * -7.0f *substep );
    }
    
    m3x3_mulv( player.to_world, vel, player.v );
@@ -558,6 +566,10 @@ static void player_physics_ground(void)
    
    float steer = vg_get_axis( "horizontal" );
    player.iY -= vg_signf(steer)*powf(steer,2.0f) * 1.5f * ktimestep;
+   
+   /* Too much lean and it starts to look like a snowboard here */
+   v2_lerp( player.board_xy, (v2f){ slip*0.25f, 0.0f }, 
+         ktimestep*5.0f, player.board_xy);
 }
 
 static void draw_cross(v3f pos,u32 colour)
@@ -644,6 +656,11 @@ static void player_physics_air(void)
    }
 
    player.iY -= vg_get_axis( "horizontal" ) * 3.6f * ktimestep;
+   
+   v2f target = {0.0f,0.0f};
+   v2_muladds( target, (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
+               player.grab, target );
+   v2_lerp( player.board_xy, target, ktimestep*3.0f, player.board_xy );
 }
 
 static void player_animate(void);
@@ -837,10 +854,6 @@ static void player_animate(void)
 
    /* New board transformation */
    v4f board_rotation; v3f board_location;
-   
-   /* TODO: Move this out of animate into update */
-   v2_lerp( player.board_xy, (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
-         ktimestep*3.0f, player.board_xy );
 
    v4f rz, rx;
    q_axis_angle( rz, (v3f){ 0.0f, 0.0f, 1.0f }, player.board_xy[0] );