}
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
*/
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,
--- /dev/null
+#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 */
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,
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; i<vg_list_size( at->pose ); 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};
cam->fov = 119.0f;
skate_camera_vector_look( cam, vd, 1.0f, 0.0f );
+#endif
}
VG_STATIC void player_dead_transport( player_interface *player,
.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 */
#include "player_interface.h"
#include "skeleton.h"
#include "player_model.h"
+#include "player_device_common.h"
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;
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 */
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,
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;
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;
for( int i=0; i<vg_list_size(apply_to); i ++ )
{
- pose[apply_to[i]-1].co[0] += offset[0]*add_grab_mod;
- pose[apply_to[i]-1].co[2] += offset[2]*add_grab_mod;
+ at->pose[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 );
}
/* 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;
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 )
}
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,
//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},
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,
{
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 =
.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
};
struct
{
v3f angles;
+ v3f prev_pos;
enum walk_activity
{
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;
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 );
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;
/* 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 =
.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 */
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++ )
{
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;
+ 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 );
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 )
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 );
* 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 );
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
*/
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 );
/* --------------------- */
return 0;
}
+/*
+ * Intersect all gates in the world
+ */
+VG_STATIC teleport_gate *world_intersect_gates( v3f pos, v3f last )
+{
+ 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, pos, last ) )
+ return gate;
+ }
+
+ return NULL;
+}
+
#endif /* WORLD_GATE_H */