new characters and anim blending
authorhgn <hgodden00@gmail.com>
Tue, 7 Jun 2022 21:08:13 +0000 (22:08 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 7 Jun 2022 21:08:13 +0000 (22:08 +0100)
character.h
ik_emulate.py [new file with mode: 0644]
main.c
model.h
scene.h
textures/ch_gradient.png

index 27430b444b6eb343e8af6d305c5f780c6b9415b0..762511ffa61af735b80e84c16fc6461db108febe 100644 (file)
@@ -5,6 +5,52 @@
 #include "model.h"
 #include "ik.h"
 
+SHADER_DEFINE( shader_player,
+
+   /*Include*/ VERTEX_STANDARD_ATTRIBUTES
+
+       "uniform mat4 uPv;"
+   "uniform mat4x3 uMdl;"
+   "uniform vec3 uOpacityLight;"
+   ""
+   "out vec4 aColour;"
+   "out vec2 aUv;"
+   "out vec3 aNorm;"
+   "out vec3 aCo;"
+   "out float aOpacity;"
+   ""
+       "void main()"
+       "{"
+      "vec3 world_pos = uMdl * vec4(a_co,1.0);"
+               "gl_Position = uPv * vec4(world_pos,1.0);"
+
+      "aColour = a_colour;"
+      "aUv = a_uv;"
+      "aNorm = mat3(uMdl) * a_norm;"
+      "aCo = a_co;"
+      "aOpacity = 1.0-(gl_Position.y+0.5);"
+       "}",
+   /* Fragment */
+       "out vec4 FragColor;"
+       ""
+   "uniform sampler2D uTexMain;"
+   "uniform vec4 uColour;"
+   ""
+   "in vec4 aColour;"
+   "in vec2 aUv;"
+   "in vec3 aNorm;"
+   "in vec3 aCo;"
+   "in float aOpacity;"
+   ""
+       "void main()"
+       "{"
+      "vec3 diffuse = texture( uTexMain, aUv ).rgb;"
+      "FragColor = vec4(pow(diffuse,vec3(1.0)),aOpacity);"
+       "}"
+       ,
+       UNIFORMS({ "uTexMain", "uPv", "uMdl", "uOpacityLight" })
+)
+
 #define FOREACH_PART(FN) \
    FN( body0 ) \
    FN( body1 ) \
@@ -22,7 +68,8 @@
    FN( leg_r0 ) \
    FN( leg_r1 ) \
    FN( foot_r ) \
-   FN( wheels ) \
+   FN( wf ) \
+   FN( wb ) \
    FN( board ) \
 
 #define MAKE_ENUM(ENUM) k_chpart_##ENUM,
@@ -59,10 +106,12 @@ struct character
    struct ik_basic ik_arm_l, ik_arm_r,
                    ik_leg_l, ik_leg_r,
                    ik_body;
+   v3f cam_pos;
 
    v4f qhead;
    float rhip, rcollar, /* twist of hip and collar controls,
                            these act in the local +y axis of the part */
+         rhead,
          rfootl, rfootr,
          rhandl, rhandr;
 
@@ -135,6 +184,9 @@ static int character_load( struct character *ch, const char *name )
    character_offset( ch, k_chpart_body0, k_chpart_leg_r0 );
    character_offset( ch, k_chpart_leg_r0, k_chpart_leg_r1 );
    character_offset( ch, k_chpart_leg_r1, k_chpart_foot_r );
+   
+   character_offset( ch, k_chpart_board, k_chpart_wb );
+   character_offset( ch, k_chpart_board, k_chpart_wf );
 
    ch->ik_arm_l.l1 = v3_length( ch->offsets[ k_chpart_arm_l1 ] );
    ch->ik_arm_l.l2 = v3_length( ch->offsets[ k_chpart_hand_l ] );
@@ -210,13 +262,182 @@ static void character_eval( struct character *ch )
    m4x3_mulv( mats[k_chpart_body1], offs[k_chpart_neck], 
          mats[k_chpart_neck][3] );
 
-   m3x3_copy( mats[k_chpart_neck], mats[k_chpart_head] );
+   v4f qhead;
+   q_axis_angle( qhead, (v3f){ 0.0f,1.0f,0.0f }, ch->rhead );
+   q_m3x3( qhead, mats[k_chpart_head] );
+   //m3x3_mul( mats[k_chpart_neck], mats[k_chpart_head], mats[k_chpart_head] );
    m4x3_mulv( mats[k_chpart_neck], offs[k_chpart_head], mats[k_chpart_head][3]);
 
    for( int i=0; i<PART_COUNT; i++ )
       m4x3_mul( ch->mroot, ch->matrices[i], ch->matrices[i] );
 }
 
+#define B3D_CO( X, Y, Z ) (v3f){ X, Z, -Y }
+
+struct character_rig_lower
+{
+   v3f b0, b1, p, fr, fl, pl, pr, hl, hr, apl, apr, cam;
+};
+
+static struct character_rig_lower character_pose_aero =
+{
+  .b0 =  {0.0721f, 0.8167f, 0.1365f},
+  .b1 =  {-0.0773f, 1.1559f, -0.1699f},
+  .p =   {0.0421f, 1.1430f, 0.2803f},
+  .fr =  {0.0535f, 0.1312f, -0.3647f},
+  .fl =  {-0.0605f, 0.1464f, 0.2917f},
+  .pl =  {-0.1704f, 0.6889f, -0.4017f},
+  .pr =  {0.0672f, 0.7598f, -0.5963f},
+  .hl =  {-0.2153f, 0.7195f, -0.1345f},
+  .hr =  {0.1974f, 0.7940f, -0.3522f},
+  .apl = {-0.2008f, 0.9546f, 0.3687f},
+  .apr = {0.3133f, 0.9299f, 0.0181f},
+  .cam = {-0.3394f, 1.2661f, 0.2936f}
+};
+
+static struct character_rig_lower character_pose_slide =
+{
+  .b0 =  {0.6732f, 0.5565f, -0.0000f},
+  .b1 =  {0.8116f, 1.0547f, 0.0613f},
+  .p =   {1.0404f, 0.7907f, 0.0186f},
+  .fr =  {-0.0030f, 0.1366f, -0.4461f},
+  .fl =  {-0.0030f, 0.1366f, 0.3480f},
+  .pl =  {-0.0887f, 0.8229f, 0.3826f},
+  .pr =  {-0.0887f, 0.8229f, -0.4621f},
+  .hl =  {0.7749f, 0.5545f, 0.5310f},
+  .hr =  {0.5844f, 1.2445f, -0.5456f},
+  .apl = {1.0999f, 0.5390f, 0.2398f},
+  .apr = {0.9816f, 0.9536f, -0.5463f},
+  .cam = {0.9888f, 1.4037f, 0.6081f}
+};
+
+static struct character_rig_lower character_pose_slide1 =
+{
+  .b0 =  {-0.2385f, 0.6403f, 0.1368f},
+  .b1 =  {-0.5151f, 1.1351f, 0.1380f},
+  .p =   {-0.1158f, 1.2118f, 0.3895f},
+  .fr =  {-0.0030f, 0.1323f, -0.3190f},
+  .fl =  {-0.0030f, 0.1323f, 0.5797f},
+  .pl =  {-0.6568f, 0.4305f, 0.2069f},
+  .pr =  {-0.6850f, 0.2740f, -0.2969f},
+  .hl =  {-0.7029f, 0.6132f, 0.2972f},
+  .hr =  {-0.2572f, 1.0104f, -0.4770f},
+  .apl = {-0.4808f, 0.8480f, 0.3731f},
+  .apr = {-0.0836f, 1.0480f, -0.1201f},
+  .cam = {-1.0508f, 1.0769f, 0.0528f}
+};
+
+static struct character_rig_lower character_pose_aero_reverse =
+{
+  .b0 =  {0.0616f, 0.8167f, -0.1415f},
+  .b1 =  {0.0148f, 1.1559f, 0.1861f},
+  .p =   {0.0558f, 1.1430f, -0.2779f},
+  .fr =  {0.0535f, 0.1312f, -0.3647f},
+  .fl =  {0.0730f, 0.1464f, 0.2917f},
+  .pl =  {-0.2073f, 0.6889f, 0.3839f},
+  .pr =  {-0.3584f, 0.4069f, 0.1032f},
+  .hl =  {0.1567f, 0.7195f, 0.1997f},
+  .hr =  {-0.3055f, 0.7940f, 0.2639f},
+  .apl = {0.3143f, 0.9546f, -0.2784f},
+  .apr = {-0.2885f, 0.9299f, -0.1236f},
+  .cam = {-0.3394f, 1.2661f, -0.2936f}
+};
+
+static struct character_rig_lower character_pose_stand =
+{
+  .b0 =  {0.1877f, 1.0663f, 0.0063f},
+  .b1 =  {0.0499f, 1.5564f, -0.0584f},
+  .p =   {0.5982f, 1.2810f, 0.0842f},
+  .fr =  {0.0535f, 0.1312f, -0.3647f},
+  .fl =  {0.0354f, 0.1464f, 0.2917f},
+  .pl =  {-0.4325f, 0.6889f, 0.1823f},
+  .pr =  {-0.4794f, 0.7598f, -0.3610f},
+  .hl =  {0.0498f, 1.0058f, 0.2317f},
+  .hr =  {0.0188f, 0.9786f, -0.2725f},
+  .apl = {0.2898f, 1.3453f, 0.2303f},
+  .apr = {0.5273f, 1.2876f, -0.1848f},
+  .cam = {-0.3477f, 1.5884f, -0.0019f}
+};
+
+static struct character_rig_lower character_pose_fly =
+{
+  .b0 =  {0.2995f, 0.6819f, -0.1369f},
+  .b1 =  {0.1618f, 1.1720f, -0.2016f},
+  .p =   {0.7477f, 0.9173f, -0.1885f},
+  .fr =  {0.0535f, 0.1312f, -0.3647f},
+  .fl =  {0.0354f, 0.1464f, 0.2917f},
+  .pl =  {-0.2930f, 0.4849f, 0.5307f},
+  .pr =  {-0.4754f, 0.4124f, -0.4874f},
+  .hl =  {0.2650f, 1.1897f, 0.4626f},
+  .hr =  {0.2494f, 1.2059f, -0.7985f},
+  .apl = {0.5165f, 1.0990f, 0.1655f},
+  .apr = {0.6759f, 1.0661f, -0.6014f},
+  .cam = {-0.2727f, 1.2606f, 0.3564f}
+};
+
+static void character_rig_lower_blend( struct character *ch, 
+      struct character_rig_lower *pose, float q )
+{
+   v3_muladds( ch->ik_body.base, pose->b0, q, ch->ik_body.base );
+   v3_muladds( ch->ik_body.end, pose->b1, q, ch->ik_body.end );
+   v3_muladds( ch->ik_body.pole, pose->p, q, ch->ik_body.pole );
+   v3_muladds( ch->ik_leg_l.end, pose->fl, q, ch->ik_leg_l.end );
+   v3_muladds( ch->ik_leg_l.pole, pose->pl, q, ch->ik_leg_l.pole );
+   v3_muladds( ch->ik_leg_r.end, pose->fr, q, ch->ik_leg_r.end );
+   v3_muladds( ch->ik_leg_r.pole, pose->pr, q, ch->ik_leg_r.pole );
+   v3_muladds( ch->ik_arm_l.pole, pose->apl, q, ch->ik_arm_l.pole );
+   v3_muladds( ch->ik_arm_r.pole, pose->apr, q, ch->ik_arm_r.pole );
+   v3_muladds( ch->ik_arm_l.end, pose->hl, q, ch->ik_arm_l.end );
+   v3_muladds( ch->ik_arm_r.end, pose->hr, q, ch->ik_arm_r.end );
+   v3_muladds( ch->cam_pos, pose->cam, q, ch->cam_pos );
+}
+
+static void character_pose_with_tilt( struct character *ch, v3f cog,
+      struct character_rig_lower *pose, float q )
+{
+   struct character_rig_lower npose;
+   float dip = vg_clampf(cog[1], -1.0f, 0.3f) * 0.35f,
+         tilt = vg_clampf(cog[2], -1.0f, 1.0f) * 0.3f;
+
+   v4f rz; m4x3f tr;
+   q_axis_angle( rz, (v3f){0.0f,0.0f,1.0f}, -cog[0]*0.6f );
+   q_m3x3( rz, tr );
+   v3_copy( (v3f){0.0f,dip,tilt}, tr[3] );
+
+   m4x3_mulv( tr, pose->b0, npose.b0 );
+   m4x3_mulv( tr, pose->b1, npose.b1 );
+   m4x3_mulv( tr, pose->p, npose.p );
+   m4x3_mulv( tr, pose->pl, npose.pl );
+   m4x3_mulv( tr, pose->pr, npose.pr );
+   m4x3_mulv( tr, pose->hl, npose.hl );
+   m4x3_mulv( tr, pose->hr, npose.hr );
+   m4x3_mulv( tr, pose->apl, npose.apl );
+   m4x3_mulv( tr, pose->apr, npose.apr );
+
+   v3_copy( pose->fr, npose.fr );
+   v3_copy( pose->fl, npose.fl );
+   v3_copy( pose->cam, npose.cam );
+   
+   character_rig_lower_blend( ch, &npose, q );
+}
+
+static void zero_ik_basic( struct ik_basic *ik )
+{
+   v3_zero( ik->base );
+   v3_zero( ik->end );
+   v3_zero( ik->pole );
+}
+
+static void character_pose_reset( struct character *ch )
+{
+   zero_ik_basic( &ch->ik_body );
+   zero_ik_basic( &ch->ik_leg_l );
+   zero_ik_basic( &ch->ik_leg_r );
+   zero_ik_basic( &ch->ik_arm_l );
+   zero_ik_basic( &ch->ik_arm_r );
+   v3_zero( ch->cam_pos );
+}
+
 static void character_testpose( struct character *ch, float t )
 {
    /* Body */
@@ -275,23 +496,39 @@ static void character_testpose( struct character *ch, float t )
    q_identity( ch->qhead );
 
    m4x3_identity( ch->matrices[k_chpart_board] );
-   m4x3_identity( ch->matrices[k_chpart_wheels] );
+   m4x3_identity( ch->matrices[k_chpart_wb] );
+   m4x3_identity( ch->matrices[k_chpart_wf] );
 }
 
-static void character_draw( struct character *ch, int temp )
+static void character_draw( struct character *ch )
 {
-   mesh_bind( &ch->mesh );
+   SHADER_USE(shader_player);
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_player, "uPv" ), 
+         1, GL_FALSE, (float *)vg_pv );
+
+   glUniform1i( SHADER_UNIFORM( shader_player, "uTexMain" ), 0 );
+   glUniform3fv( SHADER_UNIFORM( shader_player, "uOpacityLight" ), 1,
+         ch->matrices[k_chpart_neck][3] );
 
+   GLint kuMdl = SHADER_UNIFORM( shader_player, "uMdl" );
+   
    glEnable( GL_CULL_FACE );
    glCullFace( GL_BACK );
 
+   mesh_bind( &ch->mesh );
+
    for( int i=0; i<PART_COUNT; i++ )
    {
-      glUniformMatrix4x3fv( temp, 1, GL_FALSE, (float *)ch->matrices[i] );
+      glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)ch->matrices[i] );
       submodel_draw( &ch->parts[i] );
    }
 }
 
+static void character_shader_register(void)
+{
+   SHADER_INIT(shader_player);
+}
+
 #undef FOREACH_PART
 #undef MAKE_ENUM
 #undef MAKE_STRING
diff --git a/ik_emulate.py b/ik_emulate.py
new file mode 100644 (file)
index 0000000..0ee3cae
--- /dev/null
@@ -0,0 +1,338 @@
+import bpy
+from math import *
+
+def v2_sub( a, b, d ):
+   d[0] = a[0]-b[0]
+   d[1] = a[1]-b[1]
+
+def v3_sub( a, b, d ):
+   d[0] = a[0]-b[0]
+   d[1] = a[1]-b[1]
+   d[2] = a[2]-b[2]
+
+def v3_cross( a, b, d ):
+   d[0] = a[1]*b[2] - a[2]*b[1]
+   d[1] = a[2]*b[0] - a[0]*b[2]
+   d[2] = a[0]*b[1] - a[1]*b[0]
+
+def v3_muladds( a, b, s, d ):
+   d[0] = a[0]+b[0]*s
+   d[1] = a[1]+b[1]*s
+   d[2] = a[2]+b[2]*s
+
+def v3_muls( a, s, d ):
+   d[0] = a[0]*s
+   d[1] = a[1]*s
+   d[2] = a[2]*s
+
+def v3_copy( a, b ):
+   b[0] = a[0]
+   b[1] = a[1]
+   b[2] = a[2]
+
+def v3_zero( a ):
+   a[0] = 0.0
+   a[1] = 0.0
+   a[2] = 0.0
+
+def v3_negate( a, b ):
+   b[0] = -a[0]
+   b[1] = -a[1]
+   b[2] = -a[2]
+
+def v3_dot( a, b ):
+   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
+
+def v2_dot( a, b ):
+   return a[0]*b[0] + a[1]*b[1]
+
+def v2_length2( a ):
+   return v2_dot( a, a )
+
+def v3_length2( a ):
+   return v3_dot( a, a )
+
+def v3_length( a ):
+   return sqrt( v3_length2(a) )
+
+def v2_length( a ):
+   return sqrt( v2_length2(a) )
+
+def v3_normalize( a ):
+   v3_muls( a, 1.0 / v3_length( a ), a )
+
+def m3x3_identity( a ):
+   a[0][0] = 1.0
+   a[0][1] = 0.0
+   a[0][2] = 0.0
+   a[1][0] = 0.0
+   a[1][1] = 1.0
+   a[1][2] = 0.0
+   a[2][0] = 0.0
+   a[2][1] = 0.0
+   a[2][2] = 1.0
+
+def m4x3_mul( a, b, d ):
+   a00 = a[0][0]
+   a01 = a[0][1]
+   a02 = a[0][2]
+   a10 = a[1][0]
+   a11 = a[1][1]
+   a12 = a[1][2]
+   a20 = a[2][0]
+   a21 = a[2][1]
+   a22 = a[2][2]
+   a30 = a[3][0]
+   a31 = a[3][1]
+   a32 = a[3][2]
+   b00 = b[0][0]
+   b01 = b[0][1]
+   b02 = b[0][2]
+   b10 = b[1][0]
+   b11 = b[1][1]
+   b12 = b[1][2]
+   b20 = b[2][0]
+   b21 = b[2][1]
+   b22 = b[2][2]
+   b30 = b[3][0]
+   b31 = b[3][1]
+   b32 = b[3][2]
+
+   d[0][0] = a00*b00 + a10*b01 + a20*b02
+   d[0][1] = a01*b00 + a11*b01 + a21*b02
+   d[0][2] = a02*b00 + a12*b01 + a22*b02
+   d[1][0] = a00*b10 + a10*b11 + a20*b12
+   d[1][1] = a01*b10 + a11*b11 + a21*b12
+   d[1][2] = a02*b10 + a12*b11 + a22*b12
+   d[2][0] = a00*b20 + a10*b21 + a20*b22
+   d[2][1] = a01*b20 + a11*b21 + a21*b22
+   d[2][2] = a02*b20 + a12*b21 + a22*b22
+   d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30
+   d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31
+   d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32
+
+def m4x3_mulv( m, v, d ):
+   res = [0,0,0]
+   res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]
+   res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]
+   res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]
+   v3_copy( res, d )
+
+def vg_clampf( a, minf, maxf ):
+   return max( min(maxf,a), minf )
+
+class ik_basic_t():
+   def __init__(_):
+      _.base = [0,0,0]
+      _.pole = [0,0,0]
+      _.end = [0,0,0]
+      _.l1 = 0
+      _.l2 = 0
+
+k_ikX = 0
+k_iknX = 1
+k_ikY = 2
+k_iknY = 3
+k_ikZ = 4
+k_iknZ = 5
+
+def ik_track_to( m, pos, target, axis, fwd, up ):
+   dirr = [0,0,0]
+   other = [0,0,0]
+   v3_sub( target, pos, dirr )
+   v3_normalize(dirr)
+   v3_cross(dirr,axis,other)
+
+   if fwd == k_ikX and up == k_ikY:
+      v3_copy( axis, m[0] )
+      v3_copy( dirr, m[1] )
+      v3_copy( other, m[2] )
+   if fwd == k_ikY and up == k_ikX:
+      v3_negate( axis, m[2] )
+      v3_copy( dirr, m[1] )
+      v3_negate( other, m[0] )
+   if fwd == k_ikY and up == k_iknX:
+      v3_negate( axis, m[2] )
+      v3_negate( dirr, m[1] )
+      v3_copy( other, m[0] )
+   if fwd == k_ikZ and up == k_ikY:
+      v3_copy( axis, m[1] )
+      v3_copy( dirr, m[2] )
+      v3_negate( other, m[0] )
+   if fwd == k_iknZ and up == k_ikY:
+      v3_negate( axis, m[1] )
+      v3_negate( dirr, m[2] )
+      v3_negate( other, m[0] )
+   v3_copy( pos, m[3] )
+
+def ik_basic( ik, m1, m2, fwd, up ):
+   v0 = [0,0,0]
+   v1 = [0,0,0]
+   axis = [0,0,0]
+
+   v3_sub( ik.base, ik.pole, v0 )
+   v3_sub( ik.end, ik.pole, v1 )
+
+   v3_cross( v0, v1, axis )
+   v3_normalize( v0 )
+   v3_normalize( axis )
+   v3_cross( axis, v0, v1 )
+
+   base = [ v3_dot(v0,ik.base), v3_dot(v1,ik.base) ]
+   end = [ v3_dot(v0,ik.end), v3_dot(v1,ik.end) ]
+   knee = [0,0]
+   delta = [0,0]
+   
+   v2_sub( end, base, delta )
+
+   d = vg_clampf( v2_length(delta), abs(ik.l1-ik.l2), ik.l1+ik.l2-0.00001)
+   c = acos( (ik.l1*ik.l1 + d*d - ik.l2*ik.l2) / (2.0*ik.l1*d) )
+   rot = atan2( delta[1], delta[0] ) + c - 3.14159265/2.0
+
+   knee[0] = sin(-rot) * ik.l1
+   knee[1] = cos(-rot) * ik.l1
+
+   world_knee = [0,0,0]
+   v3_muladds( ik.base, v0, knee[0], world_knee )
+   v3_muladds( world_knee, v1, knee[1], world_knee )
+
+   ik_track_to( m1, ik.base, world_knee, axis, fwd, up )
+   ik_track_to( m2, world_knee, ik.end, axis, fwd, up )
+
+def get_location_obj( obj, v ):
+   v[0] =  obj.location[0]
+   v[1] =  obj.location[2]
+   v[2] = -obj.location[1]
+
+def get_location( obj, v ):
+   v[0] =  obj.matrix_world.translation[0]
+   v[1] =  obj.matrix_world.translation[2]
+   v[2] = -obj.matrix_world.translation[1]
+
+def matrix_ready( a ):
+   b2gl =  [[1.0,0.0,0.0],[0.0,0.0,-1.0],[0.0,1.0,0.0],[0.0,0.0,0.0]]
+   fixer = [[1.0,0.0,0.0],[0.0,0.0,1.0],[0.0,-1.0,0.0],[0.0,0.0,0.0]]
+   m4x3_mul( a, b2gl, a )
+   m4x3_mul( fixer, a, a )
+
+   a[0][3] = 0.0
+   a[1][3] = 0.0
+   a[2][3] = 0.0
+   a[3][3] = 1.0
+
+def make_offset( n1, n2, v ):
+   a = [0,0,0]
+   b = [0,0,0]
+
+   get_location_obj( bpy.data.objects[n1], a )
+   get_location_obj( bpy.data.objects[n2], b )
+
+   v3_sub( b, a, v )
+
+def get_dist( n1, n2 ):
+   c = [0,0,0]
+   make_offset( n1, n2, c )
+   return v3_length( c )
+
+# Measure distances
+ik_body = ik_basic_t()
+ik_body.l1 = get_dist( "ch_default_body0", "ch_default_body1" )
+ik_body.l2 = get_dist( "ch_default_body1", "ch_default_neck" )
+
+ik_arm_l = ik_basic_t()
+ik_arm_l.l1 = get_dist( "ch_default_arm_l0", "ch_default_arm_l1" )
+ik_arm_l.l2 = get_dist( "ch_default_arm_l1", "ch_default_hand_l" )
+ik_arm_r = ik_basic_t()
+ik_arm_r.l1 = get_dist( "ch_default_arm_r0", "ch_default_arm_r1" )
+ik_arm_r.l2 = get_dist( "ch_default_arm_r1", "ch_default_hand_r" )
+
+ik_leg_l = ik_basic_t()
+ik_leg_l.l1 = get_dist( "ch_default_leg_l0", "ch_default_leg_l1" )
+ik_leg_l.l2 = get_dist( "ch_default_leg_l1", "ch_default_foot_l" )
+ik_leg_r = ik_basic_t()
+ik_leg_r.l1 = get_dist( "ch_default_leg_r0", "ch_default_leg_r1" )
+ik_leg_r.l2 = get_dist( "ch_default_leg_r1", "ch_default_foot_r" )
+
+offs_arm_l = [0,0,0]
+offs_arm_r = [0,0,0]
+offs_leg_l = [0,0,0]
+offs_leg_r = [0,0,0]
+make_offset( "ch_default_body1", "ch_default_arm_l0", offs_arm_l )
+make_offset( "ch_default_body1", "ch_default_arm_r0", offs_arm_r )
+make_offset( "ch_default_body0", "ch_default_leg_l0", offs_leg_l )
+make_offset( "ch_default_body0", "ch_default_leg_r0", offs_leg_r )
+
+# character_eval() clone
+#
+cam_pos = [0,0,0]
+
+get_location( bpy.data.objects["BODY0"], ik_body.base )
+get_location( bpy.data.objects["BODY1"], ik_body.end )
+get_location( bpy.data.objects["POLE"], ik_body.pole )
+get_location( bpy.data.objects["FOOT_L"], ik_leg_l.end )
+get_location( bpy.data.objects["POLE_LEG_L"], ik_leg_l.pole )
+get_location( bpy.data.objects["FOOT_R"], ik_leg_r.end )
+get_location( bpy.data.objects["POLE_LEG_R"], ik_leg_r.pole )
+get_location( bpy.data.objects["HAND_L"], ik_arm_l.end )
+get_location( bpy.data.objects["POLE_ARM_L"], ik_arm_l.pole )
+get_location( bpy.data.objects["HAND_R"], ik_arm_r.end )
+get_location( bpy.data.objects["POLE_ARM_R"], ik_arm_r.pole )
+get_location( bpy.data.objects["CAMERA"], cam_pos )
+
+m1 = [[0,0,0,0] for _ in range(4)]
+m2 = [[0,0,0,0] for _ in range(4)]
+
+ik_basic( ik_body, m1, m2, k_ikY, k_ikX )
+
+m4x3_mulv( m2, offs_arm_l, ik_arm_l.base )
+m4x3_mulv( m2, offs_arm_r, ik_arm_r.base )
+m4x3_mulv( m1, offs_leg_l, ik_leg_l.base )
+m4x3_mulv( m1, offs_leg_r, ik_leg_r.base )
+
+matrix_ready(m1)
+matrix_ready(m2)
+bpy.data.objects["_body0"].matrix_world = m1
+bpy.data.objects["_body1"].matrix_world = m2
+
+# Arms and legs ik
+ik_basic( ik_arm_l, m1, m2, k_ikZ, k_ikY )
+matrix_ready(m1)
+matrix_ready(m2)
+bpy.data.objects["_arm_l0"].matrix_world = m1
+bpy.data.objects["_arm_l1"].matrix_world = m2
+
+ik_basic( ik_arm_r, m1, m2, k_iknZ, k_ikY )
+matrix_ready(m1)
+matrix_ready(m2)
+bpy.data.objects["_arm_r0"].matrix_world = m1
+bpy.data.objects["_arm_r1"].matrix_world = m2
+
+ik_basic( ik_leg_l, m1, m2, k_ikY, k_iknX )
+matrix_ready(m1)
+matrix_ready(m2)
+bpy.data.objects["_leg_l0"].matrix_world = m1
+bpy.data.objects["_leg_l1"].matrix_world = m2
+
+ik_basic( ik_leg_r, m1, m2, k_ikY, k_iknX )
+matrix_ready(m1)
+matrix_ready(m2)
+bpy.data.objects["_leg_r0"].matrix_world = m1
+bpy.data.objects["_leg_r1"].matrix_world = m2
+
+def strv3( v ):
+   return '{'+ F"{v[0]:.4f}f, {v[1]:.4f}f, {v[2]:.4f}f" + '}'
+
+print( F"""
+  .b0 =  {strv3(ik_body.base)},
+  .b1 =  {strv3(ik_body.end)},
+  .p =   {strv3(ik_body.pole)},
+  .fr =  {strv3(ik_leg_r.end)},
+  .fl =  {strv3(ik_leg_l.end)},
+  .pl =  {strv3(ik_leg_l.pole)},
+  .pr =  {strv3(ik_leg_r.pole)},
+  .hl =  {strv3(ik_arm_l.end)},
+  .hr =  {strv3(ik_arm_r.end)},
+  .apl = {strv3(ik_arm_l.pole)},
+  .apr = {strv3(ik_arm_r.pole)},
+  .cam = {strv3(cam_pos)}
+""")
diff --git a/main.c b/main.c
index fffa94b4c39de97d9a5c5a546c7ea9b16d8c0a65..6c1714c76d9b50076e6e42c32431aa935c762bae 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,4 +1,5 @@
 #define VG_3D
+#define VG_FRAMEBUFFER_RESIZE 1
 #include "vg/vg.h"
 
 /* Resources */
@@ -20,6 +21,31 @@ vg_tex2d *texture_list[] =
    &tex_pallet
 };
 
+SHADER_DEFINE( shader_blit,
+   "layout (location=0) in vec2 a_co;"
+   "out vec2 aUv;"
+   ""
+       "void main()"
+       "{"
+               "gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);"
+      "aUv = a_co;"
+       "}",
+
+   /* Fragment */
+       "out vec4 FragColor;"
+       ""
+   "uniform sampler2D uTexMain;"
+   ""
+   "in vec2 aUv;"
+   ""
+       "void main()"
+       "{"
+      "FragColor = texture( uTexMain, aUv );"
+       "}"
+       ,
+       UNIFORMS({ "uTexMain" })
+)
+
 /* Convars */
 static int freecam = 0;
 static int debugview = 0;
@@ -47,7 +73,8 @@ static struct gplayer
    /* Physics */
    v3f co, v, a;
    v4f rot;
-   float vswitch, slip, slip_last;
+   float vswitch, slip, slip_last,
+         reverse;
 
    float iY;   /* Yaw inertia */
    int in_air;
@@ -113,6 +140,15 @@ static struct gworld
 }
 world;
 
+static struct grender
+{
+   GLuint fb_background,
+          rgb_background;
+
+   glmesh fsquad;
+}
+render;
+
 static void player_transform_update(void)
 {
    q_m3x3( player.rot, player.to_world );
@@ -136,6 +172,8 @@ static int reset_player( int argc, char const *argv[] )
 void vg_register(void)
 {
    scene_register();
+   character_shader_register();
+   SHADER_INIT( shader_blit );
 }
 
 void vg_start(void)
@@ -306,6 +344,38 @@ void vg_start(void)
    
    reset_player( 0, NULL );
    player_transform_update();
+
+   /* Create framebuffers */
+   glGenFramebuffers( 1, &render.fb_background );
+   glBindFramebuffer( GL_FRAMEBUFFER, render.fb_background );
+
+   glGenTextures( 1, &render.rgb_background );
+   glBindTexture( GL_TEXTURE_2D, render.rgb_background );
+   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 
+         0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+   glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
+         GL_TEXTURE_2D, 
+         render.rgb_background, 0);
+
+   {
+      float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
+                       0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
+
+      glGenVertexArrays( 1, &render.fsquad.vao );
+      glGenBuffers( 1, &render.fsquad.vbo );
+      glGenBuffers( 1, &render.fsquad.ebo );
+      glBindVertexArray( render.fsquad.vao );
+      glBindBuffer( GL_ARRAY_BUFFER, render.fsquad.vbo );
+      glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
+      glBindVertexArray( render.fsquad.vao );
+      glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 
+            sizeof(float)*2, (void*)0 );
+      glEnableVertexAttribArray( 0 );
+      VG_CHECK_GL();
+   }
 }
 
 static float ktimestep = 1.0f/60.0f;
@@ -386,7 +456,7 @@ static void player_start_air(void)
 
    for( int m=0;m<=5; m++ )
    {
-      float vmod = ((float)m / 5.0f)*0.15f;
+      float vmod = ((float)m / 5.0f)*0.09f;
 
       v3f pco, pco1, pv;
       v3_copy( player.co, pco );
@@ -474,11 +544,12 @@ static void player_physics_ground(void)
     */
    v3f contact_front, contact_back, fwd, fwd1, contact_norm, vup, vside,
        axis;
-
+   
+   float klength = 0.65f;
    m3x3_mulv( player.to_world, (v3f){ 0.0f, 0.0f,-1.0f}, fwd );
-   m4x3_mulv( player.to_world, (v3f){ 0.15f,0.0f,-0.6f}, contact_norm );
-   m4x3_mulv( player.to_world, (v3f){-0.15f,0.0f,-0.6f}, contact_front );
-   m4x3_mulv( player.to_world, (v3f){ 0.00f,0.0f, 0.6f}, contact_back );
+   m4x3_mulv( player.to_world, (v3f){ 0.15f,0.0f,-klength}, contact_norm );
+   m4x3_mulv( player.to_world, (v3f){-0.15f,0.0f,-klength}, contact_front );
+   m4x3_mulv( player.to_world, (v3f){ 0.00f,0.0f, klength}, contact_back );
    m3x3_mulv( player.to_world, (v3f){ 0.0f, 1.0f, 0.0f}, vup );
    m3x3_mulv( player.to_world, (v3f){ 1.0f, 0.0f, 0.0f}, vside );
 
@@ -539,24 +610,13 @@ static void player_physics_ground(void)
 
    /* Calculate local forces */
 
-   slip = (-vel[0] / vel[2]) * player.vswitch;
+   slip = fabsf(-vel[0] / vel[2]) * vg_signf(vel[0]);
    if( fabsf( slip ) > 1.2f )
       slip = vg_signf( slip ) * 1.2f;
    player.slip = slip;
-
-#if 0
-   if( player.slip_last*slip < 0.0f && fabsf(slip) > 0.7f )
-   {
-      vg_warn( "SWITCH\n" );
-      player.vswitch = -player.vswitch;
-      slip = -slip;
-   }
-
-   player.slip_last = slip;
-#endif
+   player.reverse = -vg_signf(vel[2]);
 
    float substep = ktimestep * 0.2f;
-   
    for( int i=0; i<5; i++ )
    {
       if( fabsf(vel[2]) >= 0.02f*substep )
@@ -705,7 +765,12 @@ static void player_update(void)
    v4f rotate; v3f vup = {0.0f,1.0f,0.0f};
    m3x3_mulv( player.to_world, vup, vup );
 
-   q_axis_angle( rotate, vup, player.iY );
+   static float siY = 0.0f;
+
+   float lerpq = player.in_air? 0.04f: 0.3f;
+   siY = vg_lerpf( siY, player.iY, lerpq );
+
+   q_axis_angle( rotate, vup, siY );
    q_mul( rotate, player.rot, player.rot );
 
    player.look_dir[0] = atan2f( player.v[0], -player.v[2] );
@@ -812,6 +877,73 @@ static void player_animate(void)
    head[1] = vg_clampf( head[1], 0.3f, kheight );
 
    v3_copy( head, player.view );
+   v3f camoffs = {-0.2f,-0.6f,0.00f};
+   v3_add( player.view, camoffs, player.view );
+
+
+   /* 
+    * Animation blending
+    * ===========================================
+    */
+
+   static float fslide = 0.0f;
+   static float fdirz = 0.0f;
+   static float fdirx = 0.0f;
+   static float fstand = 0.0f;
+   static float ffly = 0.0f;
+
+   float speed = v3_length( player.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+fabsf(offset[0])*0.2f,
+            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.04f );
+   ffly = vg_lerpf(ffly, player.in_air?           1.0f: 0.0f, 0.04f );
+
+   character_pose_reset( &player.mdl );
+
+   float amt_air = ffly*ffly,
+         amt_ground = 1.0f-amt_air,
+         amt_std = (1.0f-fslide) * amt_ground,
+         amt_stand = amt_std * fstand,
+         amt_aero = amt_std * (1.0f-fstand),
+         amt_slide = amt_ground * fslide;
+
+   character_pose_with_tilt( &player.mdl, offset,
+         &character_pose_stand, amt_stand );
+
+   character_pose_with_tilt( &player.mdl, offset, 
+         &character_pose_aero, amt_aero * fdirz );
+   character_pose_with_tilt( &player.mdl, offset, 
+         &character_pose_aero_reverse, amt_aero * (1.0f-fdirz) );
+
+   character_pose_with_tilt( &player.mdl, offset, 
+         &character_pose_slide, amt_slide*fdirx );
+   character_pose_with_tilt( &player.mdl, offset, 
+         &character_pose_slide1, amt_slide*(1.0f-fdirx) );
+
+   character_pose_with_tilt( &player.mdl, (v3f){0.0f,0.0f,0.0f},
+         &character_pose_fly, amt_air );
+
+
+
+   v3_copy( player.mdl.cam_pos, player.view );
+   v3_muladds( player.view, offset, 0.7f, player.view );
+   player.view[1] = vg_clampf( player.view[1], 0.3f, kheight );
+
+
+   /* 
+    * Additive effects
+    * ==========================
+    */
+   struct ik_basic *arm_l = &player.mdl.ik_arm_l,
+                   *arm_r = &player.mdl.ik_arm_r;
+
+   v3f localv;
+   m3x3_mulv( player.to_local, player.v, localv );
+   v3_muladds( arm_l->end, localv, -0.01f, arm_l->end );
+   v3_muladds( arm_r->end, localv, -0.01f, arm_r->end );
 
    /* New board transformation */
    v4f board_rotation; v3f board_location;
@@ -831,6 +963,82 @@ static void player_animate(void)
    v3_add( (v3f){0.0f,0.5f,0.0f}, board_location, board_location );
    v3_copy( board_location, mboard[3] );
 
+
+   float wheel_r = offset[0]*-0.4f;
+   v4f qwheel;
+   q_axis_angle( qwheel, (v3f){0.0f,1.0f,0.0f}, wheel_r );
+   
+   q_m3x3( qwheel, player.mdl.matrices[k_chpart_wb] );
+
+   m3x3_transpose( player.mdl.matrices[k_chpart_wb],
+                   player.mdl.matrices[k_chpart_wf] );
+   v3_copy( player.mdl.offsets[k_chpart_wb], 
+         player.mdl.matrices[k_chpart_wb][3] );
+   v3_copy( player.mdl.offsets[k_chpart_wf], 
+         player.mdl.matrices[k_chpart_wf][3] );
+   
+   m4x3_mul( mboard, player.mdl.matrices[k_chpart_wb],
+                     player.mdl.matrices[k_chpart_wb] );
+   m4x3_mul( mboard, player.mdl.matrices[k_chpart_wf],
+                     player.mdl.matrices[k_chpart_wf] );
+
+   m4x3_mulv( mboard, player.mdl.ik_leg_l.end, player.mdl.ik_leg_l.end );
+   m4x3_mulv( mboard, player.mdl.ik_leg_r.end, player.mdl.ik_leg_r.end );
+
+
+   v3_copy( player.mdl.ik_arm_l.end, player.handl_target );
+   v3_copy( player.mdl.ik_arm_r.end, player.handr_target );
+
+   if( 1||player.in_air )
+   {
+      float tuck = player.board_xy[1],
+            tuck_amt = fabsf( tuck ) * (1.0f-fabsf(player.board_xy[0]));
+      
+      float crouch = player.grab*0.3f;
+      v3_muladds( player.mdl.ik_body.base, (v3f){0.0f,-1.0f,0.0f}, 
+            crouch, player.mdl.ik_body.base );
+      v3_muladds( player.mdl.ik_body.end, (v3f){0.0f,-1.0f,0.0f}, 
+            crouch*1.2f, player.mdl.ik_body.end );
+
+      if( tuck < 0.0f )
+      {
+         //foot_l *= 1.0f-tuck_amt*1.5f;
+
+         if( player.grab > 0.1f )
+         {
+            m4x3_mulv( mboard, (v3f){0.1f,0.14f,0.6f}, 
+                  player.handl_target );
+         }
+      }
+      else
+      {
+         //foot_r *= 1.0f-tuck_amt*1.4f;
+
+         if( player.grab > 0.1f )
+         {
+            m4x3_mulv( mboard, (v3f){0.1f,0.14f,-0.6f}, 
+                  player.handr_target );
+         }
+      }
+   }
+
+   v3_lerp( player.handl, player.handl_target, 0.1f, player.handl );
+   v3_lerp( player.handr, player.handr_target, 0.1f, player.handr );
+
+   v3_copy( player.handl, player.mdl.ik_arm_l.end );
+   v3_copy( player.handr, player.mdl.ik_arm_r.end );
+
+   /* Head rotation */
+
+   static float rhead = 0.0f;
+   rhead = vg_lerpf( rhead,
+         vg_clampf(atan2f( localv[2], -localv[0] ),-1.0f,1.0f), 0.04f );
+   player.mdl.rhead = rhead;
+
+
+#if 0
+   return;
+
    /* In the air, the dude should grab with the side thats highest,
     * while also sliding the same foot downwards a bit */
 
@@ -887,10 +1095,10 @@ static void player_animate(void)
    v3_add( pole, (v3f){ 1.0f, 0.0f, 0.0f }, pole );
 
    v3_copy( player.view, collar );
-   v3_add( (v3f){ 0.2f,-0.45f,0.0f}, collar, hips );
+   v3_add( (v3f){ 0.2f,-0.55f,0.0f}, collar, hips );
    
-   player.mdl.rhip = sinf(vg_time);
-   player.mdl.rcollar = sinf(vg_time)*0.5f;
+   player.mdl.rhip = 0.0f;//-1.0f;//sinf(vg_time);
+   player.mdl.rcollar = 0.0f;//-0.5f;//sinf(vg_time)*0.5f;
 
    struct ik_basic *ik_leg_l = &player.mdl.ik_leg_l,
                    *ik_leg_r = &player.mdl.ik_leg_r,
@@ -924,97 +1132,31 @@ static void player_animate(void)
       v3_normalize( nv );
       v3_muladds( player.view, nv, -3.0f, player.view );
    }
-   
-   v3f camoffs = {-0.3f,0.0f,0.3f};
-   v3_add( player.view, camoffs, player.view );
 
    m4x3_copy( mboard, player.mdl.matrices[k_chpart_wheels] );
+#endif
 }
 
 static void draw_player(void)
 {
    /* Draw */
-   SHADER_USE(shader_standard_lit);
-
-       glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ), 
-         1, GL_FALSE, (float *)vg_pv );
-   glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 );
-
-   GLint kuMdl = SHADER_UNIFORM( shader_standard_lit, "uMdl" );
-   
-#if 0
-   float kscale = 0.7f;
-   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
-         0.35f*kscale,0.35f*kscale,0.35f*kscale,1.0f );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mboard );
-   submodel_draw( &player.board );
-
-   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
-         0.7f*kscale,0.7f*kscale,0.7f*kscale,1.0f );
-   submodel_draw( &player.wheels );
-
-   glEnable(GL_BLEND);
-   glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-   glBlendEquation(GL_FUNC_ADD);
-   glDisable( GL_DEPTH_TEST );
-#endif
-#if 0
-   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
-         0.2f*kscale,0.8f*kscale,0.4f*kscale,0.14f );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mfoot_l );
-   submodel_draw( &player.foot_l );
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mfoot_r );
-   submodel_draw( &player.foot_r );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mleg_l );
-   submodel_draw( &player.leg_l0 );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mknee_l );
-   submodel_draw( &player.leg_l1 );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mleg_r );
-   submodel_draw( &player.leg_r0 );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mknee_r );
-   submodel_draw( &player.leg_r1 );
-
-   /* arms */
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.marm_l );
-   submodel_draw( &player.arm_l0 );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.melbow_l );
-   submodel_draw( &player.arm_l1 );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.marm_r );
-   submodel_draw( &player.arm_r0 );
-
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.melbow_r );
-   submodel_draw( &player.arm_r1 );
-
-   /* body */
-       glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)player.mbutt );
-   submodel_draw( &player.body );
-
-   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
-         0.2f*kscale,0.2f*kscale,0.2f*kscale,0.14f );
-   submodel_draw( &player.head );
-
-   glDisable(GL_BLEND);
-   glEnable( GL_DEPTH_TEST );
-#endif
-
    vg_tex2d_bind( &tex_pallet, 0 );
-   //m4x3_identity( player.mdl.mroot );
-   //character_testpose( &player.mdl, vg_time );
+
    m4x3_copy( player.to_world, player.mdl.mroot );
    character_eval( &player.mdl );
-   character_draw( &player.mdl, kuMdl );
+   character_draw( &player.mdl );
+}
+
+static void vg_framebuffer_resize( int w, int h )
+{
+   glBindTexture( GL_TEXTURE_2D, render.rgb_background );
+   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, 
+         GL_RGB, GL_UNSIGNED_BYTE, NULL );
 }
 
 void vg_render(void) 
 {
+   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
    glViewport( 0,0, vg_window_x, vg_window_y );
 
    glDisable( GL_DEPTH_TEST );
@@ -1023,9 +1165,16 @@ void vg_render(void)
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
    v3f pos_inv;
-   m4x3_mulv( player.to_world, player.view, pos_inv );
+   static v3f cam_lerped = {0.0f,0.0f,0.0f};
+   v3_lerp( cam_lerped, player.view, 0.08f, cam_lerped );
+
+   m4x3_mulv( player.to_world, cam_lerped, pos_inv );
    v3_negate( pos_inv, pos_inv );
 
+   static float vertical_lerp = 0.0f;
+   vertical_lerp = vg_lerpf( vertical_lerp, pos_inv[1], 1.0f );
+   v3f final = { pos_inv[0], vertical_lerp, pos_inv[2] };
+
    float speed = v3_length( player.v );
    v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f };
    v3_muls( shake, speed*0.01f, shake );
@@ -1037,12 +1186,12 @@ void vg_render(void)
          0.6f+shake[1]*0.04f+player.look_dir[1] );
 
    m4x3_rotate_y( world_matrix, player.look_dir[0]+shake[0]*0.02f );
-   m4x3_translate( world_matrix, pos_inv );
+   m4x3_translate( world_matrix, final );
    
    m4x4f world_4x4;
    m4x3_expand( world_matrix, world_4x4 );
    m4x4_projection( vg_pv, 
-         freecam? 90.0f: 130.0f,
+         freecam? 90.0f: 120.0f,
          (float)vg_window_x / (float)vg_window_y, 
          0.01f, 1000.0f );
    m4x4_mul( vg_pv, world_4x4, vg_pv );
@@ -1115,8 +1264,47 @@ void vg_render(void)
    scene_bind( &world.detail );
    scene_draw( &world.detail );
 
+
+   
+   /* Copy the RGB of what we have into the background buffer */
+   glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
+   glBindFramebuffer( GL_DRAW_FRAMEBUFFER, render.fb_background );
+   glBlitFramebuffer( 0,0, vg_window_x, vg_window_y, 
+                      0,0, vg_window_x, vg_window_y,
+                      GL_COLOR_BUFFER_BIT,
+                      GL_LINEAR );
+   
+   /* Clear out the colour buffer, but keep depth */
+   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+   glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+
+#if 0
+   glClear( GL_COLOR_BUFFER_BIT );
+#else
+   glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+#endif
+
    draw_player();
 
+   /* Draw back in the background */
+   glEnable(GL_BLEND);
+   glDisable(GL_DEPTH_TEST);
+   glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
+   glBlendEquation(GL_FUNC_ADD);
+   
+   SHADER_USE( shader_blit );
+
+   glUniform1i( SHADER_UNIFORM(shader_blit,"uTexMain"), 0 );
+   glActiveTexture(GL_TEXTURE0);
+   glBindTexture( GL_TEXTURE_2D, render.rgb_background );
+
+   glBindVertexArray( render.fsquad.vao );
+   glDrawArrays( GL_TRIANGLES, 0, 6 );
+
+   glDisable(GL_BLEND);
+
+
+   /* Other shite */
    glDisable( GL_DEPTH_TEST );
    vg_lines_drawall( (float *)vg_pv );
 
diff --git a/model.h b/model.h
index a1bf8ec24b70aa358abbe7f451c0cc20f196e7d3..648554118ea613aedabd18582a301fbe3ef330b1 100644 (file)
--- a/model.h
+++ b/model.h
@@ -69,6 +69,12 @@ struct glmesh
    u32 indice_count;
 };
 
+#define VERTEX_STANDARD_ATTRIBUTES                    \
+       "layout (location=0) in vec3 a_co;"                \
+   "layout (location=1) in vec3 a_norm;"              \
+   "layout (location=2) in vec4 a_colour;"            \
+   "layout (location=3) in vec2 a_uv;"
+
 static void mesh_upload( glmesh *mesh,
       model_vert *verts, u32 vert_count,
       u32 *indices, u32 indice_count )
diff --git a/scene.h b/scene.h
index 4a0c1203d3b18e6715d64efc77373f9bd3529f3f..88981b661845ff2d7262ab73a37449a3099eff2d 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -110,12 +110,6 @@ static void scene_init( scene *pscene )
    "return f;"                                        \
 "}"
 
-#define VERTEX_STANDARD_ATTRIBUTES                    \
-       "layout (location=0) in vec3 a_co;"                \
-   "layout (location=1) in vec3 a_norm;"              \
-   "layout (location=2) in vec4 a_colour;"            \
-   "layout (location=3) in vec2 a_uv;"
-
 SHADER_DEFINE( shader_debug_vcol,
 
    /*Include*/ VERTEX_STANDARD_ATTRIBUTES
@@ -269,12 +263,8 @@ SHADER_DEFINE( shader_standard_lit,
    ""
        "void main()"
        "{"
-      "float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));"
-      "float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));"
-
-      "vec3 diffuse = texture( uTexMain, aUv +vec2(0.0,light1)*0.1 ).rgb;"
+      "vec3 diffuse = texture( uTexMain, aUv ).rgb;"
 
-#if 0
       "float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));"
       "float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));"
       "diffuse += vec3(0.2,0.2,0.2 ) + " 
@@ -283,8 +273,6 @@ SHADER_DEFINE( shader_standard_lit,
 
                "FragColor = vec4((diffuse*uColour.rgb),"
                         "aColour.a*uColour.a);"
-#endif
-      "FragColor = vec4(diffuse,1.0);"
        "}"
        ,
        UNIFORMS({ "uColour","uTexMain","uPv","uMdl" })
index 0ae8520ce66707355664e9a2da1ec50369a86cc5..d81172eb2931674cae6266cc576cb042f281400a 100644 (file)
Binary files a/textures/ch_gradient.png and b/textures/ch_gradient.png differ