}
}
+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;
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();
skate_apply_friction_model( player );
skate_apply_jump_model( player );
skate_apply_air_model( player );
+ skate_apply_trick_model( player );
skate_integrate( 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,
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 */
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 );
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 )
{
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;
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 ],
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 );
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 );