X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_interface.h;h=e0830c1c25100f2893b108f8c36e94098999760c;hb=ff8fcac9582d07bc1ccbf08421d6ffec1758a755;hp=c890166d93cbe30ca5b03146852e953af96c023a;hpb=2ab1c45f664daf5a452fd212c89dcfd918f7dd81;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_interface.h b/player_interface.h index c890166..e0830c1 100644 --- a/player_interface.h +++ b/player_interface.h @@ -4,6 +4,8 @@ #include "model.h" #include "camera.h" #include "rigidbody.h" +#include "player_ragdoll.h" +#include "player_model.h" #include "world.h" typedef struct player_device player_device; @@ -11,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; @@ -20,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, + dev_previous; + + enum camera_mode + { + k_camera_mode_firstperson, + k_camera_mode_thirdperson + } + 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, @@ -34,29 +63,96 @@ 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 */ +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 ); - 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 ) @@ -77,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[] = { @@ -114,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; irb.to_local ); } +VG_STATIC void player_use_avatar( player_interface *player, + struct player_avatar *av ) +{ + player->playeravatar = av; + player_setup_ragdoll_from_avatar( &player->ragdoll, av ); +} + +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 ) { player->dev.device = dev; player->dev.storage = storage; + + player->dev.device->bind( player, &player->dev ); } 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 ); } @@ -150,33 +276,112 @@ VG_STATIC void player_update( player_interface *player ) player->dev.device->update( player, &player->dev ); } +VG_STATIC void player_apply_transport_to_cam( m4x3f transport ) +{ + /* FIXME: Applies to main_camera directly! */ + + /* Pre-emptively edit the camera matrices so that the motion vectors + * are correct */ + m4x3f transport_i; + m4x4f transport_4; + m4x3_invert_affine( transport, transport_i ); + m4x3_expand( transport_i, transport_4 ); + m4x4_mul( main_camera.mtx.pv, transport_4, main_camera.mtx.pv ); + m4x4_mul( main_camera.mtx.v, transport_4, main_camera.mtx.v ); +} + +/* + * Applies gate transport to a player_interface + */ +PLAYER_DEVICE_API +void player_pass_gate( player_interface *player, teleport_gate *gate ) +{ + +} + 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 ); - - if( player->dev.device->get_camera ) - player->dev.device->get_camera( player, &player->dev, &player->cam ); -#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 ); -} + /* TODO: eventually, blending code goes here */ + + m4x3f 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, player->dev.pose, k_anim_apply_defer_ik ); + skeleton_apply_ik_pass( sk ); + skeleton_apply_pose( sk, player->dev.pose, k_anim_apply_deffered_only ); + skeleton_apply_inverses( sk ); + skeleton_apply_transform( sk, transform ); + skeleton_debug( sk ); + +#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 ) +{ + shader_viewchar_use(); + vg_tex2d_bind( &tex_characters, 0 ); + shader_viewchar_uTexMain( 0 ); + shader_viewchar_uCamera( cam->transform[3] ); + shader_viewchar_uPv( cam->mtx.pv ); + shader_link_standard_ub( _shader_viewchar.id, 2 ); + glUniformMatrix4x3fv( _uniform_viewchar_uTransforms, + player->playeravatar->sk.bone_count, + 0, + (float *)player->playeravatar->sk.final_mtx ); + + mesh_bind( player->playermesh ); + mesh_draw( player->playermesh ); +} + VG_STATIC void player_debugtext( int size, const char *fmt, ... ) { char buffer[ 1024 ]; @@ -198,11 +403,12 @@ VG_STATIC void player_ui( player_interface *player ) { vg_uictx.cursor[0] = vg.window_x - 200; vg_uictx.cursor[1] = 0; - vg_uictx.cursor[2] = 0; + vg_uictx.cursor[2] = 200; vg_uictx.cursor[3] = 200; struct ui_vert *b = ui_fill_rect( vg_uictx.cursor, 0x70000000 ); + vg_uictx.cursor[0] = vg.window_x; player->dev.device->debug_ui( player, &player->dev ); b[2].co[1] = vg_uictx.cursor[1]; @@ -214,15 +420,29 @@ 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 ); + rb_update_transform( &player->rb ); + + if( player->dev.device->reset ) + 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 );