+/*
+ * Copyright (C) Mount0 Software, Harry Godden - All Rights Reserved
+ */
+
#ifndef ANIM_TEST_H
#define ANIM_TEST_H
skeleton_sample_anim( &animtest.skele, animtest.anim_highg, b, bpose );
skeleton_lerp_pose( &animtest.skele, apose, bpose, a, apose );
- skeleton_apply_pose( &animtest.skele, apose, k_anim_apply_defer_ik );
- skeleton_apply_ik_pass( &animtest.skele );
- skeleton_apply_pose( &animtest.skele, apose, k_anim_apply_deffered_only );
- skeleton_apply_inverses( &animtest.skele );
- skeleton_apply_transform( &animtest.skele, transform );
+ skeleton_apply_standard( &animtest.skele, apose, transform );
skeleton_debug( &animtest.skele );
}
vg_tex2d_bind( tex, 0 );
shader_viewchar_uTexMain( 0 );
shader_viewchar_uPv( vg_pv );
+
+ shader_link_standard_ub( _shader_viewchar.id, 2 );
+
glUniformMatrix4x3fv( _uniform_viewchar_uTransforms,
animtest.skele.bone_count,
0,
#ifndef GATE_H
#define GATE_H
-#define VG_3D
-#include "vg/vg.h"
+#include "common.h"
#include "model.h"
#include "render.h"
#include "shaders/gate.h"
static int debugview = 0;
static int sv_debugcam = 0;
static int lightedit = 0;
-static int sv_scene = 2;
+static int sv_scene = 0;
/* Components */
//#define SR_NETWORKED
#include "steam.h"
#include "network.h"
-#include "road.h"
+#include "model.h"
+//#include "road.h"
#include "scene.h"
-#include "ik.h"
+//#include "ik.h"
#include "audio.h"
-#include "terrain.h"
-#include "character.h"
+//#include "terrain.h"
+//#include "character.h"
#include "ragdoll.h"
#include "rigidbody.h"
#include "render.h"
-#include "gate.h"
-#include "water.h"
#include "world.h"
#include "player.h"
#include "physics_test.h"
#include "anim_test.h"
+#include "gate.h"
+#include "water.h"
+
void vg_register(void)
{
shader_blit_register();
shader_standard_register();
shader_vblend_register();
shader_unlit_register();
- shader_viewchar_register();
world_register();
character_register();
if( sv_scene == 0 )
{
- character_load( &player.mdl, "ch_default" );
+ character_load( &player.mdl, "ch_new" );
character_init_ragdoll( &player.mdl );
world_load();
m4x4f world_4x4;
m4x3_expand( player.camera_inverse, world_4x4 );
- gpipeline.fov = freecam? 60.0f: 135.0f; /* 120 */
+ gpipeline.fov = freecam? 60.0f: 125.0f; /* 120 */
m4x4_projection( vg_pv, gpipeline.fov,
(float)vg_window_x / (float)vg_window_y,
0.02f, 2100.0f );
}
else if( sv_scene == 2 )
{
- anim_test_render( &tex_pallet );
+ anim_test_render( &tex_characters );
}
#endif
}
#include "audio.h"
#include "common.h"
#include "world.h"
-#include "character.h"
+//#include "character.h"
+#include "player_model.h"
#include "bvh.h"
/*
v2f board_xy;
float grab;
float pitch;
+ float pushing, push_time;
v3f land_target;
v3f land_target_log[22];
if( !vg_get_button("break") && vg_get_button( "push" ) )
{
- float cycle_time = (vg_time-start_push)*k_push_cycle_rate,
+ player.pushing = 1.0f;
+ player.push_time = vg_time-start_push;
+
+ float cycle_time = player.push_time*k_push_cycle_rate,
amt = k_push_accel * (sinf(cycle_time)*0.5f+0.5f)*ktimestep,
current = v3_length( vel ),
new_vel = vg_minf( current + amt, k_max_push_speed );
+
new_vel -= vg_minf(current, k_max_push_speed);
vel[2] -= new_vel * player.reverse;
}
float grabt = vg_get_axis( "grabr" )*0.5f+0.5f;
player.grab = vg_lerpf( player.grab, grabt, 0.14f );
+ player.pushing = 0.0f;
if( !player.in_air )
{
offset[0] = vg_clampf( offset[0], -0.8f, 0.8f );
offset[1] = vg_clampf( offset[1], -0.5f, 0.0f );
+ offset[1] = 0.0f;
/*
* Player rotation
static float fdirx = 0.0f;
static float fstand = 0.0f;
static float ffly = 0.0f;
+ static float fpush = 0.0f;
float speed = v3_length( player.rb.v );
fstand = vg_lerpf(fstand, 1.0f-vg_clampf(speed*0.03f,0.0f,1.0f),0.1f);
fslide = vg_lerpf(fslide, vg_clampf(lslip,0.0f,1.0f), 0.04f);
- fdirz = vg_lerpf(fdirz, player.reverse > 0.0f? 1.0f: 0.0f, 0.04f );
- fdirx = vg_lerpf(fdirx, player.slip < 0.0f? 1.0f: 0.0f, 0.01f );
+ fdirz = vg_lerpf(fdirz, player.reverse > 0.0f? 0.0f: 1.0f, 0.04f );
+ fdirx = vg_lerpf(fdirx, player.slip < 0.0f? 0.0f: 1.0f, 0.01f );
ffly = vg_lerpf(ffly, player.in_air? 1.0f: 0.0f, 0.04f );
+ fpush = vg_lerpf(fpush, player.pushing, 0.1f );
+
+ float lr = fdirz * (15.0f/30.0f),
+ st = offset[1]*-2.0f,
+ sa = fdirx * (15.0f/30.0f);
+
+ mdl_keyframe apose[32], bpose[32];
+ skeleton_sample_anim( &player.mdl.sk, player.mdl.anim_stand, lr, apose );
+ skeleton_sample_anim( &player.mdl.sk, player.mdl.anim_highg, lr, bpose );
+ skeleton_lerp_pose( &player.mdl.sk, apose, bpose, st, apose );
+ skeleton_sample_anim( &player.mdl.sk, player.mdl.anim_slide, sa, bpose );
+ skeleton_lerp_pose( &player.mdl.sk, apose, bpose, fslide, apose );
+
+ static float fairdir = 0.0f;
+ fairdir = vg_lerpf( fairdir, -vg_get_axis("horizontal"), 0.04f );
+
+ /* air anim */
+ float air_dir = (fairdir*0.5f+0.5f)*(15.0f/30.0f);
+ skeleton_sample_anim( &player.mdl.sk, player.mdl.anim_air, air_dir, bpose );
+ skeleton_lerp_pose( &player.mdl.sk, apose, bpose, ffly, apose );
+
+ /* push anim */
+ skeleton_sample_anim( &player.mdl.sk, player.reverse > 0.0f?
+ player.mdl.anim_push:
+ player.mdl.anim_push_reverse,
+ player.push_time, bpose );
+ skeleton_lerp_pose( &player.mdl.sk, apose, bpose, fpush, apose );
+
+
+ /* additive effects */
+ apose[player.mdl.id_hip-1].co[0] += offset[0];
+ apose[player.mdl.id_hip-1].co[2] += offset[2];
+ apose[player.mdl.id_ik_hand_l-1].co[0] += offset[0];
+ apose[player.mdl.id_ik_hand_l-1].co[2] += offset[2];
+ apose[player.mdl.id_ik_hand_r-1].co[0] += offset[0];
+ apose[player.mdl.id_ik_hand_r-1].co[2] += offset[2];
+ apose[player.mdl.id_ik_elbow_l-1].co[0] += offset[0];
+ apose[player.mdl.id_ik_elbow_l-1].co[2] += offset[2];
+ apose[player.mdl.id_ik_elbow_r-1].co[0] += offset[0];
+ apose[player.mdl.id_ik_elbow_r-1].co[2] += offset[2];
+
+ skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_defer_ik );
+ skeleton_apply_ik_pass( &player.mdl.sk );
+ skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_deffered_only );
+
+ v3_copy( player.mdl.sk.final_mtx[player.mdl.id_head-1][3],
+ player.mdl.cam_pos );
+ skeleton_apply_inverses( &player.mdl.sk );
+ skeleton_apply_transform( &player.mdl.sk, player.rb.to_world );
+
+ skeleton_debug( &player.mdl.sk );
+
+#if 0
character_pose_reset( &player.mdl );
/* TODO */
rhead = vg_lerpf( rhead,
vg_clampf( atan2f(localv[2],-localv[0]),-klook_max,klook_max), 0.04f );
player.mdl.rhead = rhead;
+#endif
}
static void player_camera_update(void)
static void player_animate_death_cam(void)
{
+#if 0
v3f delta;
v3f head_pos;
v3_copy( player.mdl.ragdoll[k_chpart_head].co, head_pos );
player.angles[0] = atan2f( delta[0], -delta[2] );
player.angles[1] = -asinf( delta[1] );
+#endif
}
static void player_animate_camera(void)
{
- v3f offs = { -0.29f, 0.08f, 0.0f };
- m3x3_mulv( player.rb.to_world, offs, offs );
- m4x3_mulv( player.rb.to_world, player.mdl.ik_body.end, player.camera_pos );
- v3_add( offs, player.camera_pos, player.camera_pos );
+ static v3f lerp_cam = {0.0f,0.0f,0.0f};
+ v3f offs = { -0.4f, 0.15f, 0.0f };
+
+ v3_lerp( lerp_cam, player.mdl.cam_pos, 0.8f, lerp_cam );
+ v3_add( lerp_cam, offs, offs );
+ m4x3_mulv( player.rb.to_world, offs, player.camera_pos );
/* Look angles */
v3_lerp( player.vl, player.rb.v, 0.05f, player.vl );
static void draw_player(void)
{
/* Draw */
+#if 0
m4x3_copy( player.rb.to_world, player.mdl.mroot );
if( player.is_dead )
opacity = 0.0f;
character_draw( &player.mdl, opacity, player.camera );
+#endif
+
+ shader_viewchar_use();
+ vg_tex2d_bind( &tex_characters, 0 );
+ shader_viewchar_uTexMain( 0 );
+ shader_viewchar_uCamera( player.camera[3] );
+ shader_viewchar_uPv( vg_pv );
+ shader_link_standard_ub( _shader_viewchar.id, 2 );
+ glUniformMatrix4x3fv( _uniform_viewchar_uTransforms,
+ player.mdl.sk.bone_count,
+ 0,
+ (float *)player.mdl.sk.final_mtx );
+
+ mesh_bind( &player.mdl.mesh );
+ mesh_draw( &player.mdl.mesh );
}
#endif /* PLAYER_H */
--- /dev/null
+#ifndef CHARACTER_H
+#define CHARACTER_H
+
+#include "common.h"
+#include "model.h"
+#include "rigidbody.h"
+#include "render.h"
+#include "skeleton.h"
+#include "shaders/viewchar.h"
+
+vg_tex2d tex_characters = { .path = "textures/ch_gradient.qoi" };
+
+static void character_register(void)
+{
+ shader_viewchar_register();
+}
+
+static void character_init(void)
+{
+ vg_tex2d_init( (vg_tex2d *[]){ &tex_characters }, 1 );
+}
+
+struct character
+{
+ glmesh mesh;
+ struct skeleton sk;
+ struct skeleton_anim *anim_stand,
+ *anim_highg,
+ *anim_slide,
+ *anim_air,
+ *anim_push, *anim_push_reverse;
+
+ u32 id_hip,
+ id_ik_hand_l,
+ id_ik_hand_r,
+ id_ik_elbow_l,
+ id_ik_elbow_r,
+ id_head;
+
+ v3f cam_pos;
+
+ int shoes[2];
+};
+
+static int character_load( struct character *ch, const char *name )
+{
+ char buf[64];
+
+ snprintf( buf, sizeof(buf)-1, "models/%s.mdl", name );
+ mdl_header *src = mdl_load( buf );
+
+ if( !src )
+ return 0;
+
+ int error_count = 0;
+ mdl_unpack_glmesh( src, &ch->mesh );
+
+ if( !error_count )
+ vg_success( "Loaded character file '%s' with no errors\n", name );
+
+ skeleton_setup( &ch->sk, src );
+ ch->anim_stand = skeleton_get_anim( &ch->sk, "pose_stand" );
+ ch->anim_highg = skeleton_get_anim( &ch->sk, "pose_highg" );
+ ch->anim_slide = skeleton_get_anim( &ch->sk, "pose_slide" );
+ ch->anim_air = skeleton_get_anim( &ch->sk, "pose_air" );
+ ch->anim_push = skeleton_get_anim( &ch->sk, "push" );
+ ch->anim_push_reverse = skeleton_get_anim( &ch->sk, "push_reverse" );
+
+ ch->id_hip = skeleton_bone_id( &ch->sk, "hips" );
+ ch->id_ik_hand_l = skeleton_bone_id( &ch->sk, "hand.IK.L" );
+ ch->id_ik_hand_r = skeleton_bone_id( &ch->sk, "hand.IK.R" );
+ ch->id_ik_elbow_l = skeleton_bone_id( &ch->sk, "elbow.L" );
+ ch->id_ik_elbow_r = skeleton_bone_id( &ch->sk, "elbow.R" );
+ ch->id_head = skeleton_bone_id( &ch->sk, "head" );
+
+ free( src );
+ return 1;
+}
+
+static void character_eval( struct character *ch ){}
+static void character_draw( struct character *ch, float temp, m4x3f camera ){}
+static void character_init_ragdoll_joints( struct character *ch ){}
+static void character_init_ragdoll( struct character *ch ){}
+static void character_ragdoll_go( struct character *ch, v3f pos ){}
+static void character_ragdoll_copypose( struct character *ch, v3f v ){}
+static void character_debug_ragdoll( struct character *ch ){}
+static void character_ragdoll_iter( struct character *ch ){}
+
+#endif
out vec4 FragColor;
uniform sampler2D uTexMain;
+uniform vec3 uCamera;
in vec4 aColour;
in vec2 aUv;
vec3 vfrag = texture( uTexMain, aUv ).rgb;
// Lighting
- //vec3 halfview = uCamera - aWorldCo;
- //float fdist = length( halfview );
- //halfview /= fdist;
+ vec3 halfview = uCamera - aWorldCo;
+ float fdist = length( halfview );
+ halfview /= fdist;
- //vfrag = do_light_diffuse( vfrag, aNorm );
- //vfrag = do_light_spec( vfrag, aNorm, halfview, 0.1 );
- //vfrag = do_light_shadowing( vfrag );
- //vfrag = apply_fog( vfrag, fdist );
+ vfrag = do_light_diffuse( vfrag, aNorm );
+ vfrag = do_light_spec( vfrag, aNorm, halfview, 0.1 );
+ vfrag = do_light_shadowing( vfrag );
+ vfrag = apply_fog( vfrag, fdist );
- FragColor = vec4(aNorm,1.0);
+ float opacity = clamp( fdist, 0.1, 1.0 );
+
+ FragColor = vec4(vfrag,opacity);
}
"\n"
" vec3 world_pos = co0*a_weights[0] + co1*a_weights[1] + co2*a_weights[2];\n"
" vec3 world_normal = n0*a_weights[0] + n1*a_weights[1] + n2*a_weights[2];\n"
-"\n"
+" \n"
" gl_Position = uPv * vec4( world_pos, 1.0 );\n"
" aColour = a_colour;\n"
" aUv = a_uv;\n"
"out vec4 FragColor;\n"
"\n"
"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
"\n"
"in vec4 aColour;\n"
"in vec2 aUv;\n"
" return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n"
"}\n"
"\n"
-"#line 12 0 \n"
+"#line 13 0 \n"
"\n"
"void main()\n"
"{\n"
" vec3 vfrag = texture( uTexMain, aUv ).rgb;\n"
"\n"
" // Lighting\n"
-" //vec3 halfview = uCamera - aWorldCo;\n"
-" //float fdist = length( halfview );\n"
-" //halfview /= fdist;\n"
+" vec3 halfview = uCamera - aWorldCo;\n"
+" float fdist = length( halfview );\n"
+" halfview /= fdist;\n"
+"\n"
+" vfrag = do_light_diffuse( vfrag, aNorm );\n"
+" vfrag = do_light_spec( vfrag, aNorm, halfview, 0.1 );\n"
+" vfrag = do_light_shadowing( vfrag );\n"
+" vfrag = apply_fog( vfrag, fdist );\n"
"\n"
-" //vfrag = do_light_diffuse( vfrag, aNorm );\n"
-" //vfrag = do_light_spec( vfrag, aNorm, halfview, 0.1 );\n"
-" //vfrag = do_light_shadowing( vfrag );\n"
-" //vfrag = apply_fog( vfrag, fdist );\n"
+" float opacity = clamp( fdist, 0.1, 1.0 );\n"
"\n"
-" FragColor = vec4(vfrag,1.0);\n"
+" FragColor = vec4(vfrag,opacity);\n"
"}\n"
""},
};
static GLuint _uniform_viewchar_uPv;
static GLuint _uniform_viewchar_uTransforms;
static GLuint _uniform_viewchar_uTexMain;
+static GLuint _uniform_viewchar_uCamera;
static GLuint _uniform_viewchar_g_world_depth;
static void shader_viewchar_uPv(m4x4f m){
glUniformMatrix4fv( _uniform_viewchar_uPv, 1, GL_FALSE, (float *)m );
static void shader_viewchar_uTexMain(int i){
glUniform1i( _uniform_viewchar_uTexMain, i );
}
+static void shader_viewchar_uCamera(v3f v){
+ glUniform3fv( _uniform_viewchar_uCamera, 1, v );
+}
static void shader_viewchar_g_world_depth(int i){
glUniform1i( _uniform_viewchar_g_world_depth, i );
}
_uniform_viewchar_uPv = glGetUniformLocation( _shader_viewchar.id, "uPv" );
_uniform_viewchar_uTransforms = glGetUniformLocation( _shader_viewchar.id, "uTransforms" );
_uniform_viewchar_uTexMain = glGetUniformLocation( _shader_viewchar.id, "uTexMain" );
+ _uniform_viewchar_uCamera = glGetUniformLocation( _shader_viewchar.id, "uCamera" );
_uniform_viewchar_g_world_depth = glGetUniformLocation( _shader_viewchar.id, "g_world_depth" );
}
#endif /* SHADER_viewchar_H */
+/*
+ * Copyright (C) Mount0 Software, Harry Godden - All Rights Reserved
+ */
+
#ifndef SKELETON_H
#define SKELETON_H
int defer;
mdl_keyframe kf;
+
+ char name[16];
}
*bones;
m4x3f *final_mtx;
useless cpu IK bones. */
};
+static u32 skeleton_bone_id( struct skeleton *skele, const char *name )
+{
+ for( u32 i=0; i<skele->bone_count; i++ )
+ {
+ if( !strcmp( skele->bones[i].name, name ))
+ return i;
+ }
+ return 0;
+}
+
/*
* Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
*/
m3x3_transpose( inverse, inverse );
}
+/*
+ * Creates inverse rotation matrices which the IK system uses.
+ */
static void skeleton_create_inverses( struct skeleton *skele )
{
/* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
}
}
+/*
+ * Apply a model matrix to all bones, should be done last
+ */
static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform )
{
- /* bone space inverse matrix */
for( int i=0; i<skele->bone_count; i++ )
{
struct skeleton_bone *sb = &skele->bones[i];
}
}
+/*
+ * Apply an inverse matrix to all bones which maps vertices from bind space into
+ * bone relative positions
+ */
static void skeleton_apply_inverses( struct skeleton *skele )
{
for( int i=0; i<skele->bone_count; i++ )
}
}
+/*
+ * Applies the typical operations that you want for an IK rig:
+ * Pose, IK, Pose(deferred), Inverses, Transform
+ */
+static void skeleton_apply_standard( struct skeleton *skele, mdl_keyframe *pose,
+ m4x3f transform )
+{
+ skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik );
+ skeleton_apply_ik_pass( skele );
+ skeleton_apply_pose( skele, pose, k_anim_apply_deffered_only );
+ skeleton_apply_inverses( skele );
+ skeleton_apply_transform( skele, transform );
+}
+
+/*
+ * Get an animation by name
+ */
static struct skeleton_anim *skeleton_get_anim( struct skeleton *skele,
const char *name )
{
v3_copy( pnode->co, sb->co );
v3_copy( pnode->s, sb->end );
sb->parent = pnode->parent-skeleton_root;
+ strncpy( sb->name, mdl_pstr(mdl,pnode->pstr_name), 15 );
if( is_ik )
{