another api change
[carveJwlIkooP6JGAAIwe30JlM.git] / player_interface.h
index 54173455e9be62569a9b68cb23037761a41bc2ae..e0830c1c25100f2893b108f8c36e94098999760c 100644 (file)
@@ -13,6 +13,8 @@ typedef struct player_interface  player_interface;
 typedef struct player_attachment player_attachment;
 typedef mdl_keyframe player_pose[32];
 
+#define PLAYER_DEVICE_API VG_STATIC
+
 struct player_interface
 {
    rigidbody rb;
@@ -22,8 +24,33 @@ struct player_interface
    {
       player_device *device;
       void          *storage;
+
+      /* animation driven */
+      player_pose    pose;
+      v3f            pose_root_co;
+      v4f            pose_root_q;
+      camera         cam_1st, cam_3rd;
+   }
+   dev,
+   dev_previous;
+
+   enum camera_mode
+   {
+      k_camera_mode_firstperson,
+      k_camera_mode_thirdperson
    }
-   dev;
+   camera_mode;
+
+   float camera_type_blend;
+
+   /* TODO: have an automated system for crossing the thirdperson camera 
+    * across portal boundaries. if it fails the check with the gate plane, then
+    * transform root_co and root_q, as well as final camera, BACK across the 
+    * division, using the inverse of the transport matrix
+    */
+
+   int   device_blend;
+   float device_blend_time;
 
    struct input_binding *input_js1h,
                         *input_js1v,
@@ -36,13 +63,23 @@ struct player_interface
                         *input_walkv,
                         *input_use,
                         *input_reset,
-                        *input_grab;
+                        *input_grab,
+                        *input_camera;
 
+#if 0
    v3f prev_position;
+#endif
 
    struct player_avatar  *playeravatar;
    glmesh                *playermesh;
    struct player_ragdoll  ragdoll;
+
+
+   /* FIXME: eventually store animation state here when we have more than 1
+    *        player. since currently its written into the avatar
+    *
+    * struct avatar_anim_state anim_state;
+    */
 };
 
 /* FIXME: yo */
@@ -51,26 +88,71 @@ vg_tex2d tex_characters = { .path = "textures/ch_gradient.qoi" };
 struct player_device
 {
    void (* bind )      ( player_interface *player, player_attachment *at );
+
+   /*
+    * Regular updates
+    */
    void (* pre_update) ( player_interface *player, player_attachment *at );
    void (* update)     ( player_interface *player, player_attachment *at );
    void (* post_update)( player_interface *player, player_attachment *at );
-   void (* pose)       ( player_interface *player, player_attachment *at, 
-                            player_pose pose, m4x3f transform );
-
-   void (* get_camera) ( player_interface *player, player_attachment *at, 
-                            camera *cam );
 
-   void (* attatch )   ( player_interface *player, player_attachment *at, 
-                            void *storage );
+#if 0
+   /* 
+    * Get current pose, and root transform
+    */
+   void (* pose)       ( player_interface *player, player_attachment *at, 
+                            player_pose pose, v3f root_co, v4f root_q );
+#endif
 
+   /*
+    * Use this to fill out animation state
+    */
+   void (* animate) ( player_interface *player, player_attachment *at );
+
+   /* Get current camera, required fields to be filled are:
+    *    fov
+    *    pos
+    *    angles
+    *
+    * They may be blended with other systems
+    */
+   void (* post_animate) ( player_interface *player, player_attachment *at );
+
+   /*
+     This is called when a player is forced back to a spawnpoint.
+    */
    void (* reset )     ( player_interface *player, player_attachment *at,
                            struct respawn_point *spawn );
 
-   void (* store_state)( player_interface *player, player_attachment *at );
-   void (* load_state) ( player_interface *player, player_attachment *at );
+   /*
+    * make calls into player_debugtext( .. ) in this function
+    */
    void (* debug_ui)   ( player_interface *player, player_attachment *at );
+
+#if 0
+   /*
+    * Called when going through a gate, it should modify any direction and 
+    * position sensitive things, as well as store context here. it may be
+    * restored later.
+    */
    void (* gate_transport)( player_interface *player, player_attachment *at,
                             teleport_gate *gate );
+#endif
+
+   /*
+    * Load the state previously saved when gate_transport was called
+    */
+   void (* load_state) ( player_interface *player, player_attachment *at );
+
+
+
+
+#if 0
+   void (* store_state)( player_interface *player, player_attachment *at );
+   void (* attatch )   ( player_interface *player, player_attachment *at, 
+                            void *storage );
+#endif
+
 };
 
 VG_STATIC void player_interface_create_player( player_interface *inst )
@@ -91,6 +173,7 @@ VG_STATIC void player_interface_create_player( player_interface *inst )
    inst->input_walkv= vg_create_named_input( "walk-v",  k_input_type_axis );
    inst->input_use  = vg_create_named_input( "use",     k_input_type_button );
    inst->input_reset= vg_create_named_input( "reset",   k_input_type_button );
+   inst->input_camera=vg_create_named_input( "camera",  k_input_type_button );
 
    const char *default_cfg[] = 
    {
@@ -128,6 +211,7 @@ VG_STATIC void player_interface_create_player( player_interface *inst )
 
       "bind use gp-y",
       "bind use e",
+      "bind camera c"
    };
 
    for( int i=0; i<vg_list_size(default_cfg); i++ )
@@ -153,6 +237,8 @@ VG_STATIC void player_use_mesh( player_interface *player, glmesh *mesh )
    player->playermesh = mesh;
 }
 
+/* FIXME: Seperate concepts for binding and equip.
+ */
 VG_STATIC void player_use_device( player_interface *player, player_device *dev,
                                   void *storage )
 {
@@ -166,7 +252,17 @@ VG_STATIC void player_pre_update( player_interface *player )
 {
    assert( player->dev.device );
 
+   if( vg_input_button_down( player->input_camera ) )
+   {
+      if( player->camera_mode == k_camera_mode_firstperson )
+         player->camera_mode = k_camera_mode_thirdperson;
+      else
+         player->camera_mode = k_camera_mode_firstperson;
+   }
+
+#if 0
    v3_copy( player->rb.co, player->prev_position );
+#endif
 
    if( player->dev.device->pre_update )
       player->dev.device->pre_update( player, &player->dev );
@@ -194,66 +290,79 @@ VG_STATIC void player_apply_transport_to_cam( m4x3f transport )
    m4x4_mul( main_camera.mtx.v,  transport_4, main_camera.mtx.v );
 }
 
-VG_STATIC void player_post_update( player_interface *player )
+/*
+ * Applies gate transport to a player_interface
+ */
+PLAYER_DEVICE_API 
+void player_pass_gate( player_interface *player, teleport_gate *gate )
 {
-   /* FIXME: Applies to main_camera directly! */
    
+}
+
+VG_STATIC void player_post_update( player_interface *player )
+{
    assert( player->dev.device );
 
    if( player->dev.device->post_update )
       player->dev.device->post_update( player, &player->dev );
-
-   /* FIXME: only need to test against the visible gate....
-    *        OR... bvh */
-
-   for( int i=0; i<world.gate_count; i++ )
-   {
-      struct route_gate *rg = &world.gates[i];
-      teleport_gate *gate = &rg->gate;
-
-      if( gate_intersect( gate, player->rb.co, player->prev_position ) )
-      {
-         player->dev.device->gate_transport( player, &player->dev, gate );
-         v3_copy( player->rb.co, player->prev_position );
-      }
-   }
-   
-#if 0
-   camera_update_transform( &player->cam );
-   camera_update_view( &player->cam );
-   camera_update_projection( &player->cam );
-   camera_finalize( &player->cam );
-#endif
 }
 
-#if 0
 VG_STATIC void player_pre_render( player_interface *player )
 {
-   assert( player->dev.device );
+   player->dev.device->animate( player, &player->dev );
 
-   if( player->dev.device->pre_render )
-      player->dev.device->pre_render( player );
-}
-#endif
+   /* TODO: eventually, blending code goes here */
 
-VG_STATIC void player_pre_render( player_interface *player )
-{
-   player_pose pose;
    m4x3f transform;
-
-   player->dev.device->pose( player, &player->dev, pose, transform );
+   q_m3x3( player->dev.pose_root_q, transform );
+   v3_copy( player->dev.pose_root_co, transform[3] );
 
    struct skeleton *sk = &player->playeravatar->sk;
 
-   skeleton_apply_pose( sk, pose, k_anim_apply_defer_ik );
+   skeleton_apply_pose( sk, player->dev.pose, k_anim_apply_defer_ik );
    skeleton_apply_ik_pass( sk );
-   skeleton_apply_pose( sk, pose, k_anim_apply_deffered_only );
+   skeleton_apply_pose( sk, player->dev.pose, k_anim_apply_deffered_only );
    skeleton_apply_inverses( sk );
    skeleton_apply_transform( sk, transform );
    skeleton_debug( sk );
 
-   player->dev.device->get_camera( player, &player->dev, &player->cam );
-   /* TODO: if dead copy ragdoll.. . */
+#if 0
+   if( player->dev.device->pose )
+   {
+      player->dev.device->pose( player, &player->dev, pose, transform );
+
+      struct skeleton *sk = &player->playeravatar->sk;
+
+      skeleton_apply_pose( sk, pose, k_anim_apply_defer_ik );
+      skeleton_apply_ik_pass( sk );
+      skeleton_apply_pose( sk, pose, k_anim_apply_deffered_only );
+      skeleton_apply_inverses( sk );
+      skeleton_apply_transform( sk, transform );
+      skeleton_debug( sk );
+   }
+#endif
+
+   player->dev.device->post_animate( player, &player->dev );
+
+   /* TODO: eventually, blending code goes here */
+
+   float camera_blend_target = 1.0f;
+   if( player->camera_mode == k_camera_mode_firstperson )
+      camera_blend_target = 0.0f;
+
+   player->camera_type_blend = vg_lerpf( player->camera_type_blend, 
+                                         camera_blend_target,
+                                         5.0f * vg.frame_delta );
+
+   float t = player->camera_type_blend;
+   camera_lerp( &player->dev.cam_1st, &player->dev.cam_3rd, t, &player->cam );
+
+
+#if 0
+   v3_copy( player->dev.cam_1st.pos,    player->cam.pos );
+   v3_copy( player->dev.cam_1st.angles, player->cam.angles );
+   player->cam.fov = player->dev.cam_1st.fov;
+#endif
 }
 
 VG_STATIC void player_render( camera *cam, player_interface *player )
@@ -311,7 +420,9 @@ VG_STATIC void player_spawn( player_interface *player,
                              struct respawn_point *rp )
 {
    v3_copy( rp->co, player->rb.co );
+#if 0
    v3_copy( rp->co, player->prev_position );
+#endif
    v3_zero( player->rb.v );
    v3_zero( player->rb.w );
    q_identity( player->rb.q );
@@ -321,10 +432,17 @@ VG_STATIC void player_spawn( player_interface *player,
       player->dev.device->reset( player, &player->dev, rp );
 }
 
+
+VG_STATIC void player_kill( player_interface *player )
+{
+   
+}
+
 /*
  * Apply per render-frame mouse look from player to angles
  */
-VG_STATIC void player_look( player_interface *player, v3f angles )
+PLAYER_DEVICE_API
+void player_look( player_interface *player, v3f angles )
 {
    angles[2] = 0.0f;
    v2_muladds( angles, vg.mouse_delta, 0.0025f, angles );