+VG_STATIC void skate_camera_firstperson( player_device *dev,
+ player_interface *player )
+{
+ 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, dev->cam_1st.pos );
+
+ v3_zero( dev->cam_1st.angles );
+ dev->cam_1st.fov = 119.0f;
+
+ v3f flat_dir,
+ vel_dir,
+ look_dir;
+
+ v3_copy( player->rb.v, vel_dir );
+ //v3_normalize( vel_dir );
+
+ float tti = s->land_dist;
+ v3f norm;
+ v3_copy( s->land_normal, norm );
+
+ if( s->state.activity == k_skate_activity_ground )
+ {
+ tti = 0.0f;
+ v3_copy( player->rb.to_world[1], norm );
+ }
+
+ v3_muladds( vel_dir, norm, -v3_dot(vel_dir,norm), flat_dir );
+ //v3_normalize( flat_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( &dev->cam_1st, s->state.vl, 1.0f, 0.25f );
+}
+
+VG_STATIC void skate_camera_thirdperson( player_device *dev,
+ player_interface *player )
+{
+ struct player_device_skate *s = dev->storage;
+ struct player_avatar *av = player->playeravatar;
+
+ v3f origin, dir, target;
+ v3_copy( player->rb.co, origin );
+ v3_add( origin, (v3f){0.0f,1.35f,0.0f}, origin );
+ v3_sub( origin, s->state.posl, dir );
+
+ if( v3_length2( dir ) < 0.1f*0.1f )
+ v3_copy( (v3f){ 0.0f, 0.0f, 1.0f }, dir ); /* FIXME */
+ 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 * 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_device *dev,
+ player_interface *player )
+{
+ struct player_device_skate *s = dev->storage;
+ struct player_avatar *av = player->playeravatar;
+
+ v3_zero( dev->cam_1st.pos );
+ v3_zero( dev->cam_1st.angles );
+ dev->cam_1st.fov = 90.0f;
+
+ 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},
+ vp1 = {0.0f,0.1f,-0.6f};
+
+ m4x3_mulv( av->sk.final_mtx[ av->id_board ], vp0, TEMP_BOARD_0 );
+ m4x3_mulv( av->sk.final_mtx[ av->id_board ], vp1, TEMP_BOARD_1 );
+}
+
+VG_STATIC void player_skate_reset( player_device *dev,
+ player_interface *player,
+ struct respawn_point *rp )
+{
+ struct player_device_skate *s = dev->storage;
+ v3_muladds( player->rb.co, player->rb.to_world[1], 1.0f, s->state.cog );
+
+#if 0
+ mixedcam_reset( player, &s->state.cam );
+#endif
+}
+
+VG_STATIC int player_skate_event( player_device *dev, player_interface *player,
+ enum player_device_event_type ev,
+ void *data )