From: hgn Date: Sun, 29 Jan 2023 10:58:02 +0000 (+0000) Subject: another api change X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;ds=inline;h=ff8fcac9582d07bc1ccbf08421d6ffec1758a755;p=carveJwlIkooP6JGAAIwe30JlM.git another api change --- diff --git a/camera.h b/camera.h index e818e8f..dbacc26 100644 --- a/camera.h +++ b/camera.h @@ -27,6 +27,15 @@ struct camera } VG_STATIC main_camera; +VG_STATIC void camera_lerp( camera *a, camera *b, float t, camera *d ) +{ + v3_lerp( a->pos, b->pos, t, d->pos ); + d->angles[0] = vg_alerpf( a->angles[0], b->angles[0], t ); + d->angles[1] = vg_lerpf( a->angles[1], b->angles[1], t ); + d->angles[2] = vg_lerpf( a->angles[2], b->angles[2], t ); + d->fov = vg_lerpf( a->fov, b->fov, t ); +} + /* * 1) [angles, pos] -> transform */ diff --git a/common.h b/common.h index ff52267..6b10d8b 100644 --- a/common.h +++ b/common.h @@ -136,7 +136,7 @@ VG_STATIC float VG_STATIC float k_walkspeed = 10.0f, - k_airspeed = 2.0f, + k_airspeed = 1.2f, k_stopspeed = 4.0f, k_walk_accel = 10.0f, k_walk_air_accel = 7.0f, diff --git a/maps_src/mp_gridmap.mdl b/maps_src/mp_gridmap.mdl index a742af3..7efdc8a 100644 Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ diff --git a/player_device_common.h b/player_device_common.h new file mode 100644 index 0000000..6e468eb --- /dev/null +++ b/player_device_common.h @@ -0,0 +1,131 @@ +#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 */ diff --git a/player_device_dead.h b/player_device_dead.h index 848e8ec..9a0ed20 100644 --- a/player_device_dead.h +++ b/player_device_dead.h @@ -23,7 +23,6 @@ VG_STATIC void player_dead_update( player_interface *player, VG_STATIC void player_dead_post_update( player_interface *player, player_attachment *at ) { - copy_ragdoll_pose_to_avatar( &player->ragdoll, player->playeravatar ); } VG_STATIC void player_dead_ui( player_interface *player, @@ -38,22 +37,35 @@ VG_STATIC void player_dead_bind( player_interface *player, player->rb.v ); } -VG_STATIC void player_dead_pose( player_interface *player, - player_attachment *at, - player_pose pose, m4x3f transform ) +/* FIXME: This should be an optional function */ +VG_STATIC void player_dead_animate( player_interface *player, + player_attachment *at ) { + v3_zero( at->pose_root_co ); + q_identity( at->pose_root_q ); + + for( int i=0; ipose ); i ++ ) + { + v3_zero( at->pose[i].co ); + v3_fill( at->pose[i].s, 1.0f ); + q_identity( at->pose[i].q ); + } } -/* FIXME: player_device_common */ -VG_STATIC void player_skate_get_camera( player_interface *player, - player_attachment *at, camera *cam ); -VG_STATIC void skate_camera_vector_look( camera *cam, v3f v, float C, float k ); - -VG_STATIC void player_dead_get_camera( player_interface *player, - player_attachment *at, camera *cam ) +VG_STATIC void player_dead_post_animate( player_interface *player, + player_attachment *at ) { struct player_avatar *av = player->playeravatar; + v3_zero( at->cam_1st.pos ); + v3_zero( at->cam_1st.angles ); + at->cam_1st.fov = 90.0f; + + /* FIXME: This overwrites pose blending, however, do we need to blend with + * this device, anyway? */ + copy_ragdoll_pose_to_avatar( &player->ragdoll, player->playeravatar ); + +#if 0 v3f vp = {-0.1f,1.8f,0.0f}, vd = {-1.0f,0.0f,0.0f}; @@ -64,6 +76,7 @@ VG_STATIC void player_dead_get_camera( player_interface *player, cam->fov = 119.0f; skate_camera_vector_look( cam, vd, 1.0f, 0.0f ); +#endif } VG_STATIC void player_dead_transport( player_interface *player, @@ -77,12 +90,12 @@ VG_STATIC player_device player_device_dead = .pre_update = player_dead_pre_update, .update = player_dead_update, .post_update = player_dead_post_update, - .get_camera = player_dead_get_camera, + .animate = player_dead_animate, + .post_animate = player_dead_post_animate, .debug_ui = player_dead_ui, .bind = player_dead_bind, #if 0 .pose = player_dead_pose, #endif - .gate_transport= player_dead_transport }; #endif /* PLAYER_DEVICE_DEAD_H */ diff --git a/player_device_skate.h b/player_device_skate.h index 3d5b079..04a2da1 100644 --- a/player_device_skate.h +++ b/player_device_skate.h @@ -4,6 +4,7 @@ #include "player_interface.h" #include "skeleton.h" #include "player_model.h" +#include "player_device_common.h" struct player_device_skate { @@ -43,8 +44,9 @@ struct player_device_skate double start_push, cur_push; - v3f vl, follow_cam_pos; - struct teleport_gate *follow_cam_gate; + struct mixedcam_state cam; + + v3f prev_pos; } state, state_gate_storage; @@ -1101,6 +1103,7 @@ VG_STATIC void player_skate_update( player_interface *player, player_attachment *at ) { struct player_device_skate *s = at->storage; + v3_copy( player->rb.co, s->state.prev_pos ); s->state.activity_prev = s->state.activity; /* Setup colliders */ @@ -1158,6 +1161,27 @@ VG_STATIC void player_skate_update( player_interface *player, vg_line_pt3( s->state.cog, 0.14f, VG__WHITE ); vg_line( player->rb.co, s->state.cog, VG__RED ); + + + teleport_gate *gate; + if( (gate = world_intersect_gates( player->rb.co, s->state.prev_pos )) ) + { + m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); + m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); + m4x3_mulv( gate->transport, s->state.cog, s->state.cog ); + m3x3_mulv( gate->transport, s->state.cog_v, s->state.cog_v ); + m3x3_mulv( gate->transport, s->state.throw_v, s->state.throw_v ); + + mixedcam_transport( &s->state.cam, gate ); + + v4f transport_rotation; + m3x3_q( gate->transport, transport_rotation ); + q_mul( transport_rotation, player->rb.q, player->rb.q ); + rb_update_transform( &player->rb ); + + s->state_gate_storage = s->state; + player_pass_gate( player, gate ); + } } VG_STATIC void player_skate_post_update( player_interface *player, @@ -1191,14 +1215,8 @@ VG_STATIC void player_skate_ui( player_interface *player, k_steer_ground, k_steer_air ); } -VG_STATIC void skate_camera_thirdperson_nextpos( player_interface *player, - struct player_device_skate *s, - struct player_avatar *av, - v3f next_pos, v3f d ); - -VG_STATIC void player_skate_pose( player_interface *player, - player_attachment *at, - player_pose pose, m4x3f transform ) +VG_STATIC void player_skate_animate( player_interface *player, + player_attachment *at ) { struct player_device_skate *s = at->storage; struct player_avatar *av = player->playeravatar; @@ -1363,7 +1381,7 @@ VG_STATIC void player_skate_pose( player_interface *player, skeleton_lerp_pose( sk, apose, bpose, s->state.grabbing, air_pose ); } - skeleton_lerp_pose( sk, ground_pose, air_pose, s->blend_fly, pose ); + skeleton_lerp_pose( sk, ground_pose, air_pose, s->blend_fly, at->pose ); float add_grab_mod = 1.0f - s->blend_fly; @@ -1377,13 +1395,13 @@ VG_STATIC void player_skate_pose( player_interface *player, for( int i=0; ipose[apply_to[i]-1].co[0] += offset[0]*add_grab_mod; + at->pose[apply_to[i]-1].co[2] += offset[2]*add_grab_mod; } - mdl_keyframe *kf_board = &pose[av->id_board-1], - *kf_foot_l = &pose[av->id_ik_foot_l-1], - *kf_foot_r = &pose[av->id_ik_foot_r-1]; + mdl_keyframe *kf_board = &at->pose[av->id_board-1], + *kf_foot_l = &at->pose[av->id_ik_foot_l-1], + *kf_foot_r = &at->pose[av->id_ik_foot_r-1]; v3f bo; v3_muls( s->board_offset, add_grab_mod, bo ); @@ -1409,9 +1427,10 @@ VG_STATIC void player_skate_pose( player_interface *player, } /* transform */ - rb_extrapolate_transform( &player->rb, transform ); + rb_extrapolate( &player->rb, at->pose_root_co, at->pose_root_q ); - v3_muladds( transform[3], player->rb.to_world[1], -0.28f, transform[3] ); + v3_muladds( at->pose_root_co, player->rb.to_world[1], -0.28f, + at->pose_root_co ); v4f qresy, qresx, qresidual; m3x3f mtx_residual; @@ -1420,22 +1439,21 @@ VG_STATIC void player_skate_pose( player_interface *player, q_axis_angle( qresx, player->rb.to_world[0], s->state.steerx_s*substep ); q_mul( qresy, qresx, qresidual ); - q_m3x3( qresidual, mtx_residual ); - m3x3_mul( transform, mtx_residual, transform ); + q_normalize( qresidual ); + q_mul( at->pose_root_q, qresidual, at->pose_root_q ); + q_normalize( at->pose_root_q ); - if( cl_thirdperson && s->state.follow_cam_gate ) +#if 0 + if( cl_thirdperson ) { - v3f next_pos, d, _; - skate_camera_thirdperson_nextpos( player, s, av, next_pos, d ); - - if( !gate_intersect_plane( s->state.follow_cam_gate, - next_pos, s->state.follow_cam_pos, _ ) ) + if( !followcam_will_hit_gate( player, &s->state.cam ) ) { m4x3f inverse; - m4x3_invert_affine( s->state.follow_cam_gate->transport, inverse ); + m4x3_invert_affine( s->state.cam.gate->transport, inverse ); m4x3_mul( inverse, transform, transform ); } } +#endif } VG_STATIC void skate_camera_vector_look( camera *cam, v3f v, float C, float k ) @@ -1455,15 +1473,17 @@ VG_STATIC void skate_camera_vector_look( camera *cam, v3f v, float C, float k ) } VG_STATIC void skate_camera_firstperson( player_interface *player, - struct player_device_skate *s, - struct player_avatar *av, camera *cam ) + player_attachment *at ) { + struct player_device_skate *s = at->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, cam->pos ); + m4x3_mulv( av->sk.final_mtx[ av->id_head-1 ], vp, at->cam_1st.pos ); - v3_zero( cam->angles ); - cam->fov = 119.0f; + v3_zero( at->cam_1st.angles ); + at->cam_1st.fov = 119.0f; v3f flat_dir, vel_dir, @@ -1486,84 +1506,57 @@ VG_STATIC void skate_camera_firstperson( player_interface *player, //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( cam, s->state.vl, 0.7f, 0.5f ); -} - -/* this is a little yucky but needs to be done so we can use this 'prediction' - * in the pose function. its unfortunate. too bad - * - * FIXME: Can do better with FREEDOM MODE + api ordering. - */ -VG_STATIC void skate_camera_thirdperson_nextpos( player_interface *player, - struct player_device_skate *s, - struct player_avatar *av, - v3f next_pos, v3f d ) -{ - v3f origin, target; - - if( s->state.follow_cam_gate ) - { - m4x3f inverse; - m4x3_invert_affine( s->state.follow_cam_gate->transport, inverse ); - m4x3_mulv( inverse, player->rb.co, origin ); - } - else - { - v3_copy( player->rb.co, origin ); - } - - v3_add( origin, (v3f){0.0f,1.35f,0.0f}, origin ); - v3_sub( origin, s->state.follow_cam_pos, d ); - - if( v3_length2( d ) < 0.1f*0.1f ) - v3_copy( (v3f){ 0.0f, 0.0f, 1.0f }, d ); - else - v3_normalize( d ); + v3_lerp( s->state.cam.vl, look_dir, 4.0f*vg.time_delta, s->state.cam.vl ); - v3_muladds( origin, d, -2.0f, target ); - v3_lerp( s->state.follow_cam_pos, target, vg.frame_delta * 12.0f, next_pos ); + skate_camera_vector_look( &at->cam_1st, s->state.cam.vl, 0.7f, 0.5f ); } +#if 0 VG_STATIC void skate_camera_thirdperson( player_interface *player, struct player_device_skate *s, struct player_avatar *av, camera *cam ) { v3f prev_pos, cam_look_dir, d; - v3_copy( s->state.follow_cam_pos, prev_pos ); - skate_camera_thirdperson_nextpos( player, s, av, s->state.follow_cam_pos, d); + v3_copy( s->state.cam.pos, prev_pos ); + skate_camera_thirdperson_nextpos( player, s, av, s->state.cam.pos, d); - if( s->state.follow_cam_gate ) + if( s->state.cam.gate ) { v2f _; - if( gate_intersect_plane( s->state.follow_cam_gate, - s->state.follow_cam_pos, prev_pos, _ ) ) + if( gate_intersect_plane( s->state.cam.gate, + s->state.cam.pos, prev_pos, _ ) ) { - m4x3_mulv( s->state.follow_cam_gate->transport, - s->state.follow_cam_pos, s->state.follow_cam_pos ); - m3x3_mulv( s->state.follow_cam_gate->transport, d, d ); - player_apply_transport_to_cam( s->state.follow_cam_gate->transport ); + m4x3_mulv( s->state.cam.gate->transport, + s->state.cam.pos, s->state.cam.pos ); + m3x3_mulv( s->state.cam.gate->transport, d, d ); + player_apply_transport_to_cam( s->state.cam.gate->transport ); - s->state.follow_cam_gate = NULL; + s->state.cam.gate = NULL; } } skate_camera_vector_look( cam, d, 1.0f, 0.0f ); - v3_copy( s->state.follow_cam_pos, cam->pos ); + v3_copy( s->state.cam.pos, cam->pos ); } +#endif -VG_STATIC void player_skate_get_camera( player_interface *player, - player_attachment *at, camera *cam ) +VG_STATIC void player_skate_post_animate( player_interface *player, + player_attachment *at ) { struct player_device_skate *s = at->storage; struct player_avatar *av = player->playeravatar; + v3_zero( at->cam_1st.pos ); + v3_zero( at->cam_1st.angles ); + at->cam_1st.fov = 90.0f; + +#if 0 if( cl_thirdperson ) skate_camera_thirdperson( player, s, av, cam ); else - skate_camera_firstperson( player, s, av, cam ); +#endif + skate_camera_firstperson( player, at ); /* FIXME: Organize this. Its int wrong fucking place */ v3f vp0 = {0.0f,0.1f, 0.6f}, @@ -1577,27 +1570,6 @@ VG_STATIC void player_skate_transport( player_interface *player, player_attachment *at, teleport_gate *gate ) { - struct player_device_skate *s = at->storage; - - m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); - m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); - m4x3_mulv( gate->transport, s->state.cog, s->state.cog ); - m3x3_mulv( gate->transport, s->state.cog_v, s->state.cog_v ); - m3x3_mulv( gate->transport, s->state.vl, s->state.vl ); - m3x3_mulv( gate->transport, s->state.throw_v, s->state.throw_v ); - - v4f transport_rotation; - m3x3_q( gate->transport, transport_rotation ); - q_mul( transport_rotation, player->rb.q, player->rb.q ); - rb_update_transform( &player->rb ); - - s->state.follow_cam_gate = gate; - s->state_gate_storage = s->state; - - if( !cl_thirdperson ) - { - player_apply_transport_to_cam( gate->transport ); - } } VG_STATIC void player_skate_reset( player_interface *player, @@ -1606,7 +1578,8 @@ VG_STATIC void player_skate_reset( player_interface *player, { struct player_device_skate *s = at->storage; v3_muladds( player->rb.co, player->rb.to_world[1], 1.0f, s->state.cog ); - s->state.follow_cam_gate = NULL; + + mixedcam_reset( player, &s->state.cam ); } VG_STATIC player_device player_device_skate = @@ -1614,11 +1587,10 @@ VG_STATIC player_device player_device_skate = .pre_update = player_skate_pre_update, .update = player_skate_update, .post_update = player_skate_post_update, - .get_camera = player_skate_get_camera, + .animate = player_skate_animate, + .post_animate = player_skate_post_animate, .debug_ui = player_skate_ui, .bind = player_skate_bind, - .pose = player_skate_pose, - .gate_transport= player_skate_transport, .reset = player_skate_reset }; diff --git a/player_device_walk.h b/player_device_walk.h index 94f4368..3b30d06 100644 --- a/player_device_walk.h +++ b/player_device_walk.h @@ -12,6 +12,7 @@ struct player_device_walk struct { v3f angles; + v3f prev_pos; enum walk_activity { @@ -99,6 +100,8 @@ VG_STATIC void player_walk_update( player_interface *player, player_attachment *at ) { struct player_device_walk *w = at->storage; + v3_copy( player->rb.co, w->state.prev_pos ); + w->collider.height = 2.0f; w->collider.radius = 0.3f; @@ -283,31 +286,21 @@ VG_STATIC void player_walk_update( player_interface *player, v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); debug_capsule( mtx, w->collider.radius, w->collider.height, VG__GREEN ); -} - -VG_STATIC void player_walk_post_update( player_interface *player, - player_attachment *at ) -{ - struct player_device_walk *w = at->storage; - - m4x3f mtx; - m3x3_identity( mtx ); - v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); - - float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); - v3_muladds( mtx[3], player->rb.v, k_rb_delta*substep, mtx[3] ); - debug_capsule( mtx, w->collider.radius, w->collider.height, VG__YELOW ); - + /* + * CCD routine + * --------------------------------------------------- + * + */ v3f lwr_prev, lwr_now, lwr_offs = { 0.0f, w->collider.radius, 0.0f }; - v3_add( lwr_offs, player->prev_position, lwr_prev ); + v3_add( lwr_offs, w->state.prev_pos, lwr_prev ); v3_add( lwr_offs, player->rb.co, lwr_now ); v3f movedelta; - v3_sub( player->rb.co, player->prev_position, movedelta ); + v3_sub( player->rb.co, w->state.prev_pos, movedelta ); float movedist = v3_length( movedelta ); @@ -326,35 +319,49 @@ VG_STATIC void player_walk_post_update( player_interface *player, debug_capsule( mtx, w->collider.radius, w->collider.height, VG__RED ); } } -} -VG_STATIC void player_walk_ui( player_interface *player, - player_attachment *at ) -{ - player_debugtext( 1, "V: %5.2f %5.2f %5.2f",player->rb.v[0], - player->rb.v[1], - player->rb.v[2] ); - player_debugtext( 1, "CO: %5.2f %5.2f %5.2f",player->rb.co[0], - player->rb.co[1], - player->rb.co[2] ); + teleport_gate *gate; + if( (gate = world_intersect_gates( player->rb.co, w->state.prev_pos )) ) + { + struct player_device_walk *w = at->storage; + + m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); + m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); + rb_update_transform( &player->rb ); + + /* analytical rotation of yaw */ + v3f fwd_dir = { cosf(w->state.angles[0]), + 0.0f, + sinf(w->state.angles[0])}; + m3x3_mulv( gate->transport, fwd_dir, fwd_dir ); + w->state.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] ); + + w->state_gate_storage = w->state; + player_pass_gate( player, gate ); + } } -VG_STATIC void player_walk_bind( player_interface *player, - player_attachment *at ) +VG_STATIC void player_walk_post_update( player_interface *player, + player_attachment *at ) { struct player_device_walk *w = at->storage; - struct player_avatar *av = player->playeravatar; - struct skeleton *sk = &av->sk; - w->anim_idle = skeleton_get_anim( sk, "idle_cycle" ); - w->anim_walk = skeleton_get_anim( sk, "walk" ); - w->anim_run = skeleton_get_anim( sk, "run" ); - w->anim_jump = skeleton_get_anim( sk, "jump" ); + m4x3f mtx; + m3x3_identity( mtx ); + v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] ); + + float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); + v3_muladds( mtx[3], player->rb.v, k_rb_delta*substep, mtx[3] ); + debug_capsule( mtx, w->collider.radius, w->collider.height, VG__YELOW ); + +#if 0 + player_apply_transport_to_cam( gate->transport ); +#endif + } -VG_STATIC void player_walk_pose( player_interface *player, - player_attachment *at, - player_pose pose, m4x3f transform ) +VG_STATIC void player_walk_animate( player_interface *player, + player_attachment *at ) { struct player_device_walk *w = at->storage; struct skeleton *sk = &player->playeravatar->sk; @@ -409,49 +416,73 @@ VG_STATIC void player_walk_pose( player_interface *player, /* air */ skeleton_sample_anim( sk, w->anim_jump, vg.time*0.6f, bpose ); - skeleton_lerp_pose( sk, apose, bpose, w->blend_fly, pose ); - - /* Create transform matrix */ - m3x3f rotation_mtx; - v4f rot; - q_axis_angle( rot, (v3f){0.0f,1.0f,0.0f}, -w->state.angles[0]-VG_PIf*0.5f ); - q_m3x3( rot, rotation_mtx ); + skeleton_lerp_pose( sk, apose, bpose, w->blend_fly, at->pose ); - rb_extrapolate_transform( &player->rb, transform ); - m3x3_copy( rotation_mtx, transform ); + /* Create transform */ + rb_extrapolate( &player->rb, at->pose_root_co, at->pose_root_q ); + q_axis_angle( at->pose_root_q, (v3f){0.0f,1.0f,0.0f}, + -w->state.angles[0]-VG_PIf*0.5f ); } -VG_STATIC void player_walk_get_camera( player_interface *player, - player_attachment *at, camera *cam ) +VG_STATIC void player_walk_post_animate( player_interface *player, + player_attachment *at ) { + /* + * Camera + */ struct player_device_walk *w = at->storage; struct player_avatar *av = player->playeravatar; + /* 3RD */ + m3x3f angles; + euler_m3x3( w->state.angles, angles ); + + v3f cast_dir, origin; + + v3_add( player->rb.co, (v3f){0.0f,2.0f,0.0f}, origin ); + + v3_muladds( origin, angles[2], 2.0f, at->cam_3rd.pos ); + v3_muladds( at->cam_3rd.pos, angles[0], 0.5f, at->cam_3rd.pos ); + + float t; + v3f n; + if( spherecast_world( origin, at->cam_3rd.pos, 0.1f, &t, n ) != -1 ) + v3_lerp( origin, at->cam_3rd.pos, t, at->cam_3rd.pos ); + v3_copy( w->state.angles, at->cam_3rd.angles ); + at->cam_3rd.fov = 90.0f; + + + /* 1ST */ /* FIXME: viewpoint entity */ v3f vp = {-0.1f,1.8f,0.0f}; - m4x3_mulv( av->sk.final_mtx[ av->id_head-1 ], vp, cam->pos ); - v3_copy( w->state.angles, cam->angles ); - cam->fov = 90.0f; + m4x3_mulv( av->sk.final_mtx[ av->id_head-1 ], vp, at->cam_1st.pos ); + v3_copy( w->state.angles, at->cam_1st.angles ); + at->cam_1st.fov = 90.0f; } -VG_STATIC void player_walk_transport( player_interface *player, - player_attachment *at, - teleport_gate *gate ) -{ - struct player_device_walk *w = at->storage; - m4x3_mulv( gate->transport, player->rb.co, player->rb.co ); - m3x3_mulv( gate->transport, player->rb.v, player->rb.v ); +VG_STATIC void player_walk_ui( player_interface *player, + player_attachment *at ) +{ + player_debugtext( 1, "V: %5.2f %5.2f %5.2f",player->rb.v[0], + player->rb.v[1], + player->rb.v[2] ); + player_debugtext( 1, "CO: %5.2f %5.2f %5.2f",player->rb.co[0], + player->rb.co[1], + player->rb.co[2] ); +} - /* analytical rotation of yaw */ - v3f fwd_dir = { cosf(w->state.angles[0]), - 0.0f, - sinf(w->state.angles[0])}; - m3x3_mulv( gate->transport, fwd_dir, fwd_dir ); - w->state.angles[0] = atan2f( fwd_dir[2], fwd_dir[0] ); +VG_STATIC void player_walk_bind( player_interface *player, + player_attachment *at ) +{ + struct player_device_walk *w = at->storage; + struct player_avatar *av = player->playeravatar; + struct skeleton *sk = &av->sk; - w->state_gate_storage = w->state; - player_apply_transport_to_cam( gate->transport ); + w->anim_idle = skeleton_get_anim( sk, "idle_cycle" ); + w->anim_walk = skeleton_get_anim( sk, "walk" ); + w->anim_run = skeleton_get_anim( sk, "run" ); + w->anim_jump = skeleton_get_anim( sk, "jump" ); } VG_STATIC player_device player_device_walk = @@ -459,11 +490,10 @@ VG_STATIC player_device player_device_walk = .pre_update = player_walk_pre_update, .update = player_walk_update, .post_update = player_walk_post_update, - .get_camera = player_walk_get_camera, .debug_ui = player_walk_ui, .bind = player_walk_bind, - .pose = player_walk_pose, - .gate_transport= player_walk_transport + .animate = player_walk_animate, + .post_animate = player_walk_post_animate }; #endif /* PLAYER_DEVICE_WALK_H */ diff --git a/player_interface.h b/player_interface.h index acd9e1e..e0830c1 100644 --- a/player_interface.h +++ b/player_interface.h @@ -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; idev.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 ); @@ -196,57 +290,43 @@ 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; igate; - - 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; + q_m3x3( player->dev.pose_root_q, transform ); + v3_copy( player->dev.pose_root_co, transform[3] ); + + struct skeleton *sk = &player->playeravatar->sk; - /* FIXME: Give devices more control over these render stages, and have - * 'API calls' - * for this kindof crap instead of it dictating order... */ + 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 ); @@ -260,9 +340,29 @@ VG_STATIC void player_pre_render( player_interface *player ) skeleton_apply_transform( sk, transform ); skeleton_debug( sk ); } +#endif + + player->dev.device->post_animate( player, &player->dev ); - player->dev.device->get_camera( player, &player->dev, &player->cam ); - /* TODO: if dead copy ragdoll.. . */ + /* 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 ) @@ -320,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 ); @@ -330,6 +432,7 @@ VG_STATIC void player_spawn( player_interface *player, player->dev.device->reset( player, &player->dev, rp ); } + VG_STATIC void player_kill( player_interface *player ) { @@ -338,7 +441,8 @@ 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 ); diff --git a/rigidbody.h b/rigidbody.h index d2ce949..ad4b600 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -404,6 +404,7 @@ VG_STATIC void rb_update_transform( rigidbody *rb ) * Extrapolate rigidbody into a transform based on vg accumulator. * Useful for rendering */ +__attribute__ ((deprecated)) VG_STATIC void rb_extrapolate_transform( rigidbody *rb, m4x3f transform ) { float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); @@ -434,6 +435,30 @@ VG_STATIC void rb_extrapolate_transform( rigidbody *rb, m4x3f transform ) v3_copy( co, transform[3] ); } +VG_STATIC void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) +{ + float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f ); + + v3_muladds( rb->co, rb->v, k_rb_delta*substep, co ); + + if( v3_length2( rb->w ) > 0.0f ) + { + v4f rotation; + v3f axis; + v3_copy( rb->w, axis ); + + float mag = v3_length( axis ); + v3_divs( axis, mag, axis ); + q_axis_angle( rotation, axis, mag*k_rb_delta*substep ); + q_mul( rotation, rb->q, q ); + q_normalize( q ); + } + else + { + v4_copy( rb->q, q ); + } +} + /* * Initialize rigidbody and calculate masses, inertia */ diff --git a/skaterift.c b/skaterift.c index 0d3ff70..3923ca0 100644 --- a/skaterift.c +++ b/skaterift.c @@ -251,7 +251,7 @@ VG_STATIC void vg_load(void) player_use_avatar( &localplayer, &localplayer_avatar ); player_use_mesh( &localplayer, &localplayer_meshes[0] ); player_use_device( &localplayer, &player_device_walk, &localplayer_walk ); - player_use_device( &localplayer, &player_device_skate, &localplayer_skate ); + //player_use_device( &localplayer, &player_device_skate, &localplayer_skate ); /* --------------------- */ diff --git a/world_gate.h b/world_gate.h index f83cd87..1bf8afe 100644 --- a/world_gate.h +++ b/world_gate.h @@ -211,4 +211,21 @@ VG_STATIC int gate_intersect( teleport_gate *gate, v3f pos, v3f last ) return 0; } +/* + * Intersect all gates in the world + */ +VG_STATIC teleport_gate *world_intersect_gates( v3f pos, v3f last ) +{ + for( int i=0; igate; + + if( gate_intersect( gate, pos, last ) ) + return gate; + } + + return NULL; +} + #endif /* WORLD_GATE_H */