#include "player_model.h"
#include "player_device_common.h"
+VG_STATIC
struct player_device_skate
{
struct
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
{
v2f wobble;
float debug_normal_pressure;
-};
+ u32 device_id_walk;
+}
+localplayer_device_skate;
-VG_STATIC void player_skate_bind( player_interface *player,
- player_attachment *at )
+VG_STATIC void player_skate_bind( player_device *dev,
+ player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
struct player_avatar *av = player->playeravatar;
struct skeleton *sk = &av->sk;
s->anim_ollie = skeleton_get_anim( sk, "ollie" );
s->anim_ollie_reverse = skeleton_get_anim( sk, "ollie_reverse" );
s->anim_grabs = skeleton_get_anim( sk, "grabs" );
-}
-VG_STATIC void player_skate_pre_update( player_interface *player,
- player_attachment *at )
-{
+ s->device_id_walk = player_get_device( player, "walk" );
}
/*
return closest_edge;
}
-VG_STATIC int skate_grind_collide( player_interface *player,
- player_attachment *at, rb_ct *contact )
+VG_STATIC int skate_grind_collide( player_device *dev,
+ player_interface *player,
+ rb_ct *contact )
{
v3f p0, p1, c0, c1;
v3_muladds( player->rb.co, player->rb.to_world[2], 0.5f, p0 );
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 );
}
-VG_STATIC void player_skate_update( player_interface *player,
- player_attachment *at )
+VG_STATIC void player_skate_update( player_device *dev,
+ player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
v3_copy( player->rb.co, s->state.prev_pos );
s->state.activity_prev = s->state.activity;
interface_manifold = manifold;
grind_manifold = manifold + interface_len;
- int grind_len = skate_grind_collide( player, at, grind_manifold );
+ int grind_len = skate_grind_collide( dev, player, grind_manifold );
for( int i=0; i<interface_len+grind_len; i ++ )
{
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 );
#endif
}
}
-VG_STATIC void player_skate_post_update( player_interface *player,
- player_attachment *at )
-{
-}
-
-VG_STATIC void player_skate_ui( player_interface *player,
- player_attachment *at )
+VG_STATIC void player_skate_ui( player_device *dev, player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
/* FIXME: Compression */
player_debugtext( 1, "V: %5.2f %5.2f %5.2f",player->rb.v[0],
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_interface *player,
- player_attachment *at )
+VG_STATIC void player_skate_animate( player_device *dev,
+ player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
struct player_avatar *av = player->playeravatar;
struct skeleton *sk = &av->sk;
skeleton_lerp_pose( sk, apose, bpose, s->state.grabbing, air_pose );
}
- skeleton_lerp_pose( sk, ground_pose, air_pose, s->blend_fly, at->pose );
+ skeleton_lerp_pose( sk, ground_pose, air_pose, s->blend_fly, dev->pose );
float add_grab_mod = 1.0f - s->blend_fly;
for( int i=0; i<vg_list_size(apply_to); i ++ )
{
- at->pose[apply_to[i]-1].co[0] += offset[0]*add_grab_mod;
- at->pose[apply_to[i]-1].co[2] += offset[2]*add_grab_mod;
+ dev->pose[apply_to[i]-1].co[0] += offset[0]*add_grab_mod;
+ dev->pose[apply_to[i]-1].co[2] += offset[2]*add_grab_mod;
}
- mdl_keyframe *kf_board = &at->pose[av->id_board-1],
- *kf_foot_l = &at->pose[av->id_ik_foot_l-1],
- *kf_foot_r = &at->pose[av->id_ik_foot_r-1];
+ mdl_keyframe *kf_board = &dev->pose[av->id_board-1],
+ *kf_foot_l = &dev->pose[av->id_ik_foot_l-1],
+ *kf_foot_r = &dev->pose[av->id_ik_foot_r-1];
v3f bo;
v3_muls( s->board_offset, add_grab_mod, bo );
}
/* transform */
- rb_extrapolate( &player->rb, at->pose_root_co, at->pose_root_q );
+ rb_extrapolate( &player->rb, dev->pose_root_co, dev->pose_root_q );
- v3_muladds( at->pose_root_co, player->rb.to_world[1], -0.28f,
- at->pose_root_co );
+ v3_muladds( dev->pose_root_co, player->rb.to_world[1], -0.28f,
+ dev->pose_root_co );
v4f qresy, qresx, qresidual;
m3x3f mtx_residual;
q_mul( qresy, qresx, qresidual );
q_normalize( qresidual );
- q_mul( at->pose_root_q, qresidual, at->pose_root_q );
- q_normalize( at->pose_root_q );
+ 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 )
cam->angles[1] = pitch;
}
-VG_STATIC void skate_camera_firstperson( player_interface *player,
- player_attachment *at )
+VG_STATIC void skate_camera_firstperson( player_device *dev,
+ player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
struct player_avatar *av = player->playeravatar;
/* FIXME: viewpoint entity */
v3f vp = {-0.1f,1.8f,0.0f};
- m4x3_mulv( av->sk.final_mtx[ av->id_head-1 ], vp, at->cam_1st.pos );
+ m4x3_mulv( av->sk.final_mtx[ av->id_head-1 ], vp, dev->cam_1st.pos );
- v3_zero( at->cam_1st.angles );
- at->cam_1st.fov = 119.0f;
+ v3_zero( dev->cam_1st.angles );
+ dev->cam_1st.fov = 119.0f;
v3f flat_dir,
vel_dir,
v3_lerp( flat_dir, vel_dir, vg_clampf( tti / 2.0f, 0.4f, 1.0f ), look_dir );
v3_lerp( s->state.vl, look_dir, 4.0f*vg.time_delta, s->state.vl );
- skate_camera_vector_look( &at->cam_1st, s->state.vl, 1.0f, 0.25f );
+ skate_camera_vector_look( &dev->cam_1st, s->state.vl, 1.0f, 0.25f );
}
-VG_STATIC void skate_camera_thirdperson( player_interface *player,
- player_attachment *at )
+VG_STATIC void skate_camera_thirdperson( player_device *dev,
+ player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
struct player_avatar *av = player->playeravatar;
v3f origin, dir, target;
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_copy( s->state.posl, at->cam_3rd.pos );
- skate_camera_vector_look( &at->cam_3rd, dir, 1.0f, 0.0f );
- at->cam_3rd.fov = 100.0f;
+ 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, s->state.dirl, 1.0f, 0.2f );
}
-VG_STATIC void player_skate_post_animate( player_interface *player,
- player_attachment *at )
+VG_STATIC void player_skate_post_animate( player_device *dev,
+ player_interface *player )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
struct player_avatar *av = player->playeravatar;
- v3_zero( at->cam_1st.pos );
- v3_zero( at->cam_1st.angles );
- at->cam_1st.fov = 90.0f;
+ v3_zero( dev->cam_1st.pos );
+ v3_zero( dev->cam_1st.angles );
+ dev->cam_1st.fov = 90.0f;
- skate_camera_thirdperson( player, at );
- skate_camera_firstperson( player, at );
+ skate_camera_thirdperson( dev, player );
+ skate_camera_firstperson( dev, player );
/* FIXME: Organize this. Its int wrong fucking place */
v3f vp0 = {0.0f,0.1f, 0.6f},
m4x3_mulv( av->sk.final_mtx[ av->id_board ], vp1, TEMP_BOARD_1 );
}
-VG_STATIC void player_skate_transport( player_interface *player,
- player_attachment *at,
- teleport_gate *gate )
-{
-}
-
-VG_STATIC void player_skate_reset( player_interface *player,
- player_attachment *at,
+VG_STATIC void player_skate_reset( player_device *dev,
+ player_interface *player,
struct respawn_point *rp )
{
- struct player_device_skate *s = at->storage;
+ struct player_device_skate *s = dev->storage;
v3_muladds( player->rb.co, player->rb.to_world[1], 1.0f, s->state.cog );
#if 0
#endif
}
+VG_STATIC int player_skate_event( player_device *dev, player_interface *player,
+ enum player_device_event_type ev,
+ void *data )
+{
+ struct player_device_skate *s = dev->storage;
+
+ if( ev == k_player_device_event_bind )
+ player_skate_bind( dev, player );
+ else if( ev == k_player_device_event_respawn )
+ player_skate_reset( dev, player, data );
+ else if( ev == k_player_device_event_pre_update )
+ {
+ if( vg_input_button_down( player->input_use ) )
+ {
+ struct device_transition_walk inf;
+ v3_copy( player->cam.angles, inf.angles );
+ inf.angles[2] = 0.0f;
+
+ player_transition_to_device( player, s->device_id_walk, &inf );
+ return 1;
+ }
+ }
+ else if( ev == k_player_device_event_custom_transition )
+ {
+ /* transition coming in from walking */
+ struct device_transition_skateboard *inf = data;
+
+ q_axis_angle( player->rb.q, (v3f){0.0f,1.0f,0.0f},
+ 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 );
+ }
+ else if( ev == k_player_device_event_update )
+ {
+ 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 );
+ }
+ else if( ev == k_player_device_event_post_animate )
+ {
+ player_skate_post_animate( dev, player );
+ }
+ else if( ev == k_player_device_event_debug_ui )
+ {
+ player_skate_ui( dev, player );
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
VG_STATIC player_device player_device_skate =
{
- .pre_update = player_skate_pre_update,
- .update = player_skate_update,
- .post_update = player_skate_post_update,
- .animate = player_skate_animate,
- .post_animate = player_skate_post_animate,
- .debug_ui = player_skate_ui,
- .bind = player_skate_bind,
- .reset = player_skate_reset
+ .name = "skateboard",
+ .event = player_skate_event,
+ .storage = &localplayer_device_skate
};
#endif /* PLAYER_DEVICE_SKATE_H */