+#ifndef PLAYER_DEVICE_COMMON_H
+#define PLAYER_DEVICE_COMMON_H
+
+#define VG_GAME
+#include "vg/vg.h"
+#include "common.h"
+#include "player_interface.h"
+
+struct mixedcam_state
+{
+ v3f vl, vt, pos, post, dir;
+ struct teleport_gate *gate;
+};
+
+/*
+ * this is a little yucky but needs to be done so we can use this 'prediction'
+ * in the pose function. its unfortunate. too bad
+ */
+VG_STATIC void followcam_nextpos( player_interface *player,
+ struct mixedcam_state *mc,
+ v3f next_pos, v3f d )
+{
+}
+
+
+VG_STATIC int followcam_will_hit_gate( player_interface *player,
+ struct mixedcam_state *mc )
+{
+ if( mc->gate )
+ {
+ v3f next_pos, d, _;
+ followcam_nextpos( player, mc, next_pos, d );
+
+ return gate_intersect_plane( mc->gate, next_pos, mc->pos, _ );
+ }
+
+ return 0;
+}
+
+VG_STATIC void mixedcam_transport( struct mixedcam_state *mc,
+ teleport_gate *gate )
+{
+ m3x3_mulv( gate->transport, mc->vl, mc->vl );
+ mc->gate = gate;
+
+#if 0
+ if( !cl_thirdperson )
+ player_apply_transport_to_cam( gate->transport );
+#endif
+}
+
+VG_STATIC void mixedcam_reset( player_interface *player,
+ struct mixedcam_state *mc )
+{
+ mc->gate = NULL;
+}
+
+
+VG_STATIC void mixedcam_set_targets( struct mixedcam_state *mc, v3f v, v3f co )
+{
+ v3_copy( v, mc->vt );
+ v3_copy( co, mc->post );
+}
+
+
+VG_STATIC void mixedcam_iterate_firstperson_frame( player_interface *player,
+ struct mixedcam_state *mc )
+{
+ v3_lerp( mc->vl, mc->vt, 4.0f*vg.time_delta, mc->vl );
+}
+
+VG_STATIC void mixedcam_iterate_thirdperson_frame( player_interface *player,
+ struct mixedcam_state *mc )
+{
+ v3f prev_pos, origin, target, dir;
+
+ v3_copy( mc->pos, prev_pos );
+
+ if( mc->gate )
+ {
+ m4x3f inverse;
+ m4x3_invert_affine( mc->gate->transport, inverse );
+ m4x3_mulv( inverse, mc->post, origin );
+ }
+ else
+ {
+ v3_copy( mc->post, origin );
+ }
+
+ /* TODO: Remove? */
+ v3_add( origin, (v3f){0.0f,1.35f,0.0f}, origin );
+ v3_sub( origin, mc->pos, dir );
+
+ if( v3_length2( dir ) < 0.1f*0.1f )
+ v3_copy( (v3f){ 0.0f, 0.0f, 1.0f }, dir ); /* FIXME */
+ else
+ v3_normalize( dir );
+
+ v3_muladds( origin, dir, -2.0f, target );
+ v3_lerp( mc->pos, target, vg.frame_delta * 12.0f, mc->pos );
+ v3_copy( dir, mc->dir );
+
+ if( mc->gate )
+ {
+ v2f _;
+ if( gate_intersect_plane( mc->gate, mc->pos, prev_pos, _ ) )
+ {
+ m4x3_mulv( mc->gate->transport, mc->pos, mc->pos );
+ m3x3_mulv( mc->gate->transport, mc->dir, mc->dir );
+ //player_apply_transport_to_cam( mc->gate->transport );
+
+ mc->gate = NULL;
+ }
+ }
+}
+
+VG_STATIC void mixedcam_iterate_frame( player_interface *player,
+ struct mixedcam_state *mc )
+{
+ if( cl_thirdperson )
+ mixedcam_iterate_thirdperson_frame( player, mc );
+ else
+ mixedcam_iterate_firstperson_frame( player, mc );
+}
+
+VG_STATIC void mixedcam_get_camera( struct mixedcam_state *mc )
+{
+
+}
+
+#endif /* PLAYER_DEVICE_COMMON_H */