typedef struct player_attachment player_attachment;
typedef mdl_keyframe player_pose[32];
+#define PLAYER_DEVICE_API VG_STATIC
+
struct player_interface
{
rigidbody rb;
{
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,
*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 */
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 )
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[] =
{
"bind use gp-y",
"bind use e",
+ "bind camera c"
};
for( int i=0; i<vg_list_size(default_cfg); i++ )
player->playermesh = mesh;
}
+/* FIXME: Seperate concepts for binding and equip.
+ */
VG_STATIC void player_use_device( player_interface *player, player_device *dev,
void *storage )
{
{
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 );
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 )
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 );
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 );