reverse,
slip;
+ v3f flip_axis;
+ float flip_time,
+ flip_rate;
+
m3x3f velocity_bias,
velocity_bias_pstep;
+ v3f apex;
int lift_frames;
v3f prev_pos;
-
- v3f vl, /* 1st */
- posl; /* 3rd */
+ /* FIXME: Sensible names */
+ v3f vl, /* 1st */
+ posl, dirl; /* 3rd */
}
state,
state_gate_storage;
{
v3f log[50];
v3f n;
+ v3f apex;
u32 log_length;
- float score;
+ float score,
+ land_dist;
enum prediction_type
{
struct grind_edge *best_grind = NULL;
float closest_grind = INFINITY;
- float grind_score = INFINITY,
- air_score = INFINITY;
+ float grind_score = INFINITY,
+ air_score = INFINITY,
+ time_to_impact = 0.0f;
prediction->log_length = 0;
+ v3_copy( pco, prediction->apex );
for( int i=0; i<vg_list_size(prediction->log); i++ )
{
m3x3_mulv( vr, pv, pv );
v3_muladds( pco, pv, pstep, pco );
+
+ if( pco[1] > prediction->apex[1] )
+ v3_copy( pco, prediction->apex );
v3f vdir;
air_score *= 0.1f;
v3_lerp( pco1, pco, t1, prediction->log[ prediction->log_length ++ ] );
+ time_to_impact += t1 * pstep;
break;
}
+ time_to_impact += pstep;
v3_copy( pco, prediction->log[ prediction->log_length ++ ] );
}
prediction->score = INFINITY;
prediction->type = k_prediction_none;
}
+
+ prediction->land_dist = time_to_impact;
}
VG_STATIC
min_score = INFINITY,
max_score = -INFINITY;
+ v3_zero( s->state.apex );
+ s->land_dist = 0.0f;
+
/*
* Search a broad selection of futures
*/
{
min_score = p->score;
best_vmod = vmod;
+ s->land_dist = p->land_dist;
+ v3_copy( p->apex, s->state.apex );
}
if( p->score > max_score )
p->colour <<= 8;
p->colour |= 0xff000000;
}
+
+
+ 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 );
+ }
+ else
+ {
+ s->state.flip_rate = 0.0f;
+ v3_zero( s->state.flip_axis );
+ }
}
/*
v3f spring0, spring1;
skate_get_board_points( player, s, spring1, spring0 );
- int spring_hit0 = skate_simulate_spring( player, s, spring0 ),
- spring_hit1 = skate_simulate_spring( player, s, spring1 );
+ int spring_hit0 = 0, //skate_simulate_spring( player, s, spring0 ),
+ spring_hit1 = 0; //skate_simulate_spring( player, s, spring1 );
v3f animavg, animdelta;
v3_add( spring0, spring1, animavg );
float angle = -atan2f( dy, dx );
q_axis_angle( s->board_rotation, (v3f){1.0f,0.0f,0.0f}, angle );
- int lift_frames_limit = 1;
+ int lift_frames_limit = 6;
/* Surface connection */
if( len == 0 && !(spring_hit0 && spring_hit1) )
float maxspin = k_steer_air * k_rb_delta * k_spin_boost;
s->state.steery_s = -steer[0] * maxspin;
- s->state.steerx_s = steer[1] * s->state.reverse * maxspin;
s->state.steerx = s->state.steerx_s;
- s->state.steery = s->state.steery_s;
-
+
/* FIXME audio events */
#if 0
audio_lock();
v3_muladds( player->rb.v, gravity, k_rb_delta, player->rb.v );
v3_muladds( player->rb.co, player->rb.v, k_rb_delta, player->rb.co );
- v3_lerp( player->rb.w, (v3f){0.0f,0.0f,0.0f}, 0.125f*0.5f, player->rb.w );
+ float decay_rate = 0.5f*0.125f;
+
+ if( s->state.activity == k_skate_activity_air )
+ {
+ float dist = 1.0f-(s->land_dist/4.0f);
+ decay_rate = 0.5f * vg_maxf( dist*dist, 0.0f );
+ }
+
+ v3_lerp( player->rb.w, (v3f){0.0f,0.0f,0.0f}, decay_rate, player->rb.w );
+
if( v3_length2( player->rb.w ) > 0.0f )
{
v4f rotation;
/* integrate steering velocities */
v4f rotate;
- float l = (s->state.activity == k_skate_activity_air)? 0.04f: 0.3f;
+ float l = (s->state.activity == k_skate_activity_air)? 0.04f: 0.24f;
s->state.steery_s = vg_lerpf( s->state.steery_s, s->state.steery, l );
s->state.steerx_s = vg_lerpf( s->state.steerx_s, s->state.steerx, l );
v3_copy( player.rb.v, s->phys.v_prev );
#endif
+ s->state.flip_time += s->state.flip_rate * k_rb_delta;
rb_update_transform( &player->rb );
}
m4x3_mulv( gate->transport, s->state.cog, s->state.cog );
m3x3_mulv( gate->transport, s->state.cog_v, s->state.cog_v );
m3x3_mulv( gate->transport, s->state.throw_v, s->state.throw_v );
+
+ /*camera */
m4x3_mulv( gate->transport, s->state.posl, s->state.posl );
m3x3_mulv( gate->transport, s->state.vl, s->state.vl );
+ m3x3_mulv( gate->transport, s->state.dirl, s->state.dirl );
#if 0
mixedcam_transport( &s->state.cam, gate );
player_debugtext( 1, "steer_s: %5.2f %5.2f [%.2f %.2f]\n",
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,
+ s->state.flip_time );
}
VG_STATIC void player_skate_animate( player_device *dev,
q_mul( dev->pose_root_q, qresidual, dev->pose_root_q );
q_normalize( dev->pose_root_q );
+ v4f qflip;
+ if( (s->state.activity == k_skate_activity_air) &&
+ (fabsf(s->state.flip_rate) > 0.01f) )
+ {
+ float angle = vg_clampf( s->state.flip_time, -1.0f, 1.0f ) * VG_TAUf,
+ distm = s->land_dist * fabsf(s->state.flip_rate) * 3.0f,
+ blend = vg_clampf( 1.0f-distm, 0.0f, 1.0f );
+
+ angle = vg_lerpf( angle, vg_signf(s->state.flip_rate) * VG_TAUf, blend );
+
+ q_axis_angle( qflip, s->state.flip_axis, angle );
+ q_mul( qflip, dev->pose_root_q, dev->pose_root_q );
+ q_normalize( dev->pose_root_q );
+
+ v3f rotation_point, rco;
+ v3_muladds( player->rb.co, player->rb.to_world[1], 0.5f, rotation_point );
+ v3_sub( dev->pose_root_co, rotation_point, rco );
+
+ /* FIXME: q_mul v3 */
+ m3x3f TEMP;
+ q_m3x3( qflip, TEMP );
+ m3x3_mulv( TEMP, rco, rco );
+ v3_add( rco, rotation_point, dev->pose_root_co );
+ }
+
#if 0
if( cl_thirdperson )
{
else
v3_normalize( dir );
+ if( s->state.activity == k_skate_activity_air )
+ dir[1] *= vg_maxf( 0.0f, 1.0f - (s->land_dist/2.0f) );
+ dir[1] *= 0.0f;
+
v3_muladds( origin, dir, -2.0f, target );
- v3_lerp( s->state.posl, target, vg.frame_delta * 12.0f, s->state.posl );
+
+ v3_lerp( s->state.posl, target, vg.frame_delta * 15.0f, s->state.posl );
+ v3_lerp( s->state.dirl, dir, 18.0f*vg.time_delta, s->state.dirl );
v3_copy( s->state.posl, dev->cam_3rd.pos );
- skate_camera_vector_look( &dev->cam_3rd, dir, 1.0f, 0.0f );
- dev->cam_3rd.fov = 100.0f;
+ skate_camera_vector_look( &dev->cam_3rd, s->state.dirl, 1.0f, 0.2f );
}
VG_STATIC void player_skate_post_animate( player_device *dev,
atan2f( inf->dir[0], inf->dir[2] ) );
v3_copy( player->cam.pos, s->state.posl );
+ m3x3f temp;
+ euler_m3x3( player->cam.angles, temp );
+ v3_muls( temp[2], -1.0f, s->state.dirl );
+
rb_update_transform( &player->rb );
v3_muladds( player->rb.co, player->rb.to_world[1], 1.0f, s->state.cog );
v3_copy( player->rb.v, s->state.cog_v );
{
player_skate_update( dev, player );
}
+ else if( ev == k_player_device_event_post_update )
+ {
+ for( int i=0; i<s->prediction_count; i++ )
+ {
+ struct land_prediction *p = &s->predictions[i];
+
+ for( int j=0; j<p->log_length - 1; j ++ )
+ vg_line( p->log[j], p->log[j+1], p->colour );
+
+ vg_line_cross( p->log[p->log_length-1], p->colour, 0.25f );
+
+ v3f p1;
+ v3_add( p->log[p->log_length-1], p->n, p1 );
+ vg_line( p->log[p->log_length-1], p1, 0xffffffff );
+
+ vg_line_pt3( p->apex, 0.02f, 0xffffffff );
+ }
+
+ vg_line_pt3( s->state.apex, 0.200f, 0xff0000ff );
+ vg_line_pt3( s->state.apex, 0.201f, 0xff00ffff );
+ }
else if( ev == k_player_device_event_animate )
{
player_skate_animate( dev, player );