latest
authorhgn <hgodden00@gmail.com>
Mon, 30 May 2022 22:58:19 +0000 (23:58 +0100)
committerhgn <hgodden00@gmail.com>
Mon, 30 May 2022 22:58:19 +0000 (23:58 +0100)
blender_export.py
ik.h [new file with mode: 0644]
main.c
model.h [new file with mode: 0644]
scene.h
textures/gradients.png
textures/sky.png [new file with mode: 0644]

index 05059c267eb11774e4194968ff3d096f2cc7837e..9c01c197e3ace349c010a0d5c3aa469f5f56b5e2 100644 (file)
@@ -92,9 +92,9 @@ def write_model(name):
             v.co[0] = vert.co[0]
             v.co[1] = vert.co[2]
             v.co[2] = -vert.co[1]
-            v.colour[0] = 0.0
-            v.colour[1] = 0.0
-            v.colour[2] = 0.0
+            v.colour[0] = 1.0
+            v.colour[1] = 1.0
+            v.colour[2] = 1.0
             v.colour[3] = 1.0
             vertex_buffer += [v]
             
@@ -139,3 +139,4 @@ def write_model(name):
 write_model( "test" )
 write_model( "free_dev" )
 write_model( "char_dev" )
+write_model( "skydome" )
diff --git a/ik.h b/ik.h
new file mode 100644 (file)
index 0000000..0bbe3b2
--- /dev/null
+++ b/ik.h
@@ -0,0 +1,77 @@
+#include "vg/vg.h"
+
+/*
+ *  Setup basic IK system (2d, 2 bones)
+ *
+ *  + base (m1)
+ *   \
+ *    \ l1
+ *     \
+ *      *(m2)   + pole
+ *     /
+ *    / l2
+ *   + 
+ *   end
+ */
+struct ik_basic
+{
+   v3f base,
+       pole,
+       end;
+
+   float l1, l2;
+};
+
+static void ik_basic( struct ik_basic *ik, m4x3f m1, m4x3f m2 )
+{
+   /* Localize the system into 2d */
+   v3f v0, v1, axis;
+
+   vg_line( ik->base, ik->pole, 0xffffff00 );
+   vg_line( ik->end, ik->pole, 0xffffff00 );
+
+   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 );
+
+   v3f p0, p1, p2;
+   v3_muladds( ik->base, axis, 0.2f, p0 );
+   v3_muladds( ik->base, v0, 0.2f, p1 );
+   v3_muladds( ik->base, v1, 0.2f, p2 );
+   vg_line( ik->base, p0, 0xffff0000 );
+   vg_line( ik->base, p1, 0xff00ff00 );
+   vg_line( ik->base, p2, 0xff0000ff );
+   
+   v2f base = { v3_dot( v0, ik->base ), v3_dot( v1, ik->base ) },
+       end  = { v3_dot( v0, ik->end  ), v3_dot( v1, ik->end  ) },
+       knee;
+
+   /* Compute angles */
+   v2f delta;
+   v2_sub( end, base, delta );
+
+   float 
+      d = vg_clampf( v2_length(delta), fabsf(ik->l1 - ik->l2), 
+            ik->l1+ik->l2-0.00001f ),
+      c = acosf( (ik->l1*ik->l1 + d*d - ik->l2*ik->l2) / (2.0f*ik->l1*d) ),
+      rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
+   
+   knee[0] = sinf(-rot) * ik->l1;
+   knee[1] = cosf(-rot) * ik->l1;
+
+   /* Project back into world coords */
+   v3f world_knee;
+   v3_muladds( ik->base, v0, knee[0], world_knee );
+   v3_muladds( world_knee, v1, knee[1], world_knee );
+
+   /* Create matrices */
+   m4x3_lookat( m1, ik->base, world_knee, axis );
+   m4x3_lookat( m2, world_knee, ik->end, axis );
+
+   vg_line( ik->base, world_knee, 0xff0000ff );
+   vg_line( world_knee, ik->end, 0xff00ff40 );
+}
diff --git a/main.c b/main.c
index e34ca5fff6b823dd7ec08f2cf7b3b81ccf066e7c..8a812289e010d81301a5ce25ec26ef3de5417187 100644 (file)
--- a/main.c
+++ b/main.c
@@ -4,7 +4,7 @@
 /* Resources */
 vg_tex2d tex_norwey = { .path = "textures/norway_foliage.qoi" };
 vg_tex2d tex_grid = { .path = "textures/grid.qoi" };
-vg_tex2d tex_road = { .path = "textures/road.qoi" };
+vg_tex2d tex_sky = { .path = "textures/sky.qoi" };
 vg_tex2d tex_gradients = { .path = "textures/gradients.qoi",
                            .flags = VG_TEXTURE_CLAMP };
 vg_tex2d *texture_list[] =
@@ -12,18 +12,19 @@ vg_tex2d *texture_list[] =
    &tex_norwey,
    &tex_gradients,
    &tex_grid,
-   &tex_road
+   &tex_sky
 };
 
 /* Convars */
 static int freecam = 0;
 static int debugview = 0;
 static int debugsdf = 0;
-static int debugroad = 0;
+static int sv_debugcam = 0;
 
 /* Components */
 #include "road.h"
 #include "scene.h"
+#include "ik.h"
 
 int main( int argc, char *argv[] )
 { 
@@ -32,33 +33,40 @@ int main( int argc, char *argv[] )
 
 m4x3f world_matrix;
 
-#if 0
-v3f player.co;
-v3f player.view;     /* Relative to pos */
-v3f player.v = { 0.0f, 0.0f, -0.2f };
-float player_yaw;
-v2f player.look_dir;
-v3f player.a;
-#endif
-
 static struct gplayer
 {
    v3f co, v, a;
    v4f rot;
+   float vswitch, slip_last;
 
    v3f view;
    v2f look_dir;  /* TEMP */
 
    m4x3f to_world, to_local;
+
+   glmesh mesh;
+   
+   submodel legl,
+            legu,
+            board,
+            torso,
+            wheels;
 }
 player;
 
-road_patch road_main;
-scene test_scene;
-scene world_scene;
-scene player_scene;
-u32 world_terrain_count,
-    world_road_count;
+static struct gworld
+{
+   glmesh skydome;
+   
+   scene foliage,    /* Tree shader */
+         geo,        /* Std shader, collisions */
+         detail;     /* Std shader, no collisions */
+
+   submodel terrain,
+            terrain_rocks,
+            terrain_road;
+}
+world;
 
 static void player_transform_update(void)
 {
@@ -76,6 +84,8 @@ static int reset_player( int argc, char const *argv[] )
    v3_zero( player.co );
    v3_copy( (v3f){ 0.0f, 0.0f, -0.2f }, player.v );
    q_identity( player.rot );
+   player.vswitch = 1.0f;
+   player.slip_last = 0.0f;
 
    player_transform_update();
    return 0;
@@ -90,9 +100,6 @@ void vg_start(void)
 {
    vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
    
-   road_patch_init( &road_main );
-   road_generate( &road_main );
-
    vg_convar_push( (struct vg_convar){
       .name = "freecam",
       .data = &freecam,
@@ -102,24 +109,24 @@ void vg_start(void)
    });
 
    vg_convar_push( (struct vg_convar){
-      .name = "debugview",
-      .data = &debugview,
+      .name = "debugcam",
+      .data = &sv_debugcam,
       .data_type = k_convar_dtype_i32,
       .opt_i32 = { .min=0, .max=1, .clamp=0 },
       .persistent = 1
    });
 
    vg_convar_push( (struct vg_convar){
-      .name = "debugsdf",
-      .data = &debugsdf,
+      .name = "debugview",
+      .data = &debugview,
       .data_type = k_convar_dtype_i32,
-      .opt_i32 = { .min=0, .max=1, .clamp=1 },
+      .opt_i32 = { .min=0, .max=1, .clamp=0 },
       .persistent = 1
    });
 
    vg_convar_push( (struct vg_convar){
-      .name = "debugroad",
-      .data = &debugroad,
+      .name = "debugsdf",
+      .data = &debugsdf,
       .data_type = k_convar_dtype_i32,
       .opt_i32 = { .min=0, .max=1, .clamp=1 },
       .persistent = 1
@@ -133,73 +140,106 @@ void vg_start(void)
    v3f lightDir = { 0.1f, 0.8f, 0.2f };
    v3_normalize( lightDir );
    
-   scene_init( &world_scene );
-   scene_init( &test_scene );
-   scene_init( &player_scene );
-   model *world = vg_asset_read( "models/free_dev.mdl" );
-   model *test = vg_asset_read( "models/test.mdl" );
+   /* Unpack player */
    model *char_dev = vg_asset_read( "models/char_dev.mdl" );
-   scene_add_model( &player_scene, char_dev,
-         submodel_get( char_dev, "joint" ),
-         (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+   model_unpack( char_dev, &player.mesh );
+   player.legl = *submodel_get( char_dev, "legl" );
+   player.legu = *submodel_get( char_dev, "legu" );
+   player.board = *submodel_get( char_dev, "skateboard" );
+   player.torso = *submodel_get( char_dev, "torso" );
+   player.wheels = *submodel_get( char_dev, "wheels" );
    free(char_dev);
+   
+   /* Setup scene */
+   scene_init( &world.geo );
+   scene_init( &world.detail );
+   scene_init( &world.foliage );
+   
+   model *mworld = vg_asset_read( "models/free_dev.mdl" );
+   model *mtest = vg_asset_read( "models/test.mdl" );
 
-   scene_add_model( &world_scene, world, 
-         submodel_get( world, "terrain" ),
+   model *msky = vg_asset_read( "models/skydome.mdl" );
+   model_unpack( msky, &world.skydome );
+   free( msky );
+   
+   scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain" ),
          (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+   scene_copy_slice( &world.geo, &world.terrain );
 
-   int id_tree = submodel_get( test, "tree" ),
-       id_groundcover[] = 
+   scene_add_model( &world.geo, mworld, submodel_get( mworld, "terrain_rocks" ),
+         (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+   scene_copy_slice( &world.geo, &world.terrain_rocks );
+   
+   submodel *ptree = submodel_get( mtest, "tree" ),
+            *pt_groundcover[] = 
        {
-         submodel_get( test, "bush" ),
-         submodel_get( test, "grass" ),
-         submodel_get( test, "blubber" ),
-         submodel_get( test, "blubber" ),
-         submodel_get( test, "blubber" ),
-         submodel_get( test, "grassthin" )
+         submodel_get( mtest, "bush" ),
+         submodel_get( mtest, "bush" ),
+         submodel_get( mtest, "blubber" ),
        };
 
    /* Sprinkle some trees in the terrain areas */
    v3f range;
-   v3_sub( world_scene.bbx[1], world_scene.bbx[0], range );
+   v3_sub( world.geo.bbx[1], world.geo.bbx[0], range );
+   
+#ifdef VG_RELEASE
+   int const ktree_count = 8000,
+             kfoliage_count = 200000;
+#else
+   int const ktree_count = 200,
+             kfoliage_count = 0;
+#endif
 
-   for( int i=0; i<8000; i++ )
+   for( int i=0; i<ktree_count; i++ )
    {
-      v3f pos;
+      v3f pos = { vg_randf(), 0.0f, vg_randf() }, 
+          norm;
+      
+      v3_muladd( world.geo.bbx[0], pos, range, pos );
+      
+      if( sample_scene_height( &world.geo, pos, norm ) )
+      {
+         if( v3_dot( norm, (v3f){ 0.0f, 1.0f, 0.0f } ) > 0.9f )
+         {
+            scene_add_model( &world.foliage, mtest, ptree,
+                  pos, vg_randf() * VG_TAUf, vg_randf() * 0.5f + 0.5f );
+         }
+      }
+   }
 
-      pos[0] = vg_randf();
-      pos[1] = 0.0f;
-      pos[2] = vg_randf();
-      v3_muladd( world_scene.bbx[0], pos, range, pos );
+   for( int i=0; i<kfoliage_count; i++ )
+   {
+      v3f pos = { vg_randf(), 0.0f, vg_randf() }, 
+          norm;
 
-      if( sample_scene_height( &world_scene, pos ) )
+      v3_muladd( world.geo.bbx[0], pos, range, pos );
+      
+      if( sample_scene_height( &world.geo, pos, norm ) )
       {
-         scene_add_model( &test_scene, test, 
-               id_tree,
-               pos, vg_randf() * VG_TAUf, vg_randf() * 0.5f + 0.5f );
+         if( v3_dot( norm, (v3f){ 0.0f, 1.0f, 0.0f } ) > 0.7f )
+         {
+            scene_add_model( &world.foliage, mtest, 
+                  pt_groundcover[rand()%vg_list_size(pt_groundcover)],
+                  pos, vg_randf() * VG_TAUf, vg_randf() * 0.5f + 0.5f );
+         }
       }
    }
 
-   world_terrain_count = world_scene.indice_count;
+   scene_add_model( &world.geo, mworld, submodel_get( mworld, "road" ),
+         (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
+   scene_copy_slice( &world.geo, &world.terrain_road );
 
-   scene_add_model( &world_scene, world, 
-         submodel_get( world, "road" ),
+   scene_add_model( &world.detail, mworld, submodel_get( mworld, "art" ),
          (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
-   world_road_count = world_scene.indice_count-world_terrain_count;
 
-   free( test );
-   free( world );
+   free( mtest );
+   free( mworld );
 
-#if 0
-   scene_compute_occlusion( &test_scene );
-   scene_shadow_gradient( &test_scene, 1, 0.0f, 1.0f );
-   scene_shadow_sphere( &test_scene, (v3f){ 0.0f,4.0f,0.0f},
-         (v4f){1.0f, 2.0f, 0.0f, 0.0f}, lightDir );
-#endif
+   scene_compute_occlusion( &world.foliage );
 
-   scene_upload( &player_scene );
-   scene_upload( &world_scene );
-   scene_upload( &test_scene );
+   scene_upload( &world.foliage );
+   scene_upload( &world.geo );
+   scene_upload( &world.detail );
    
    reset_player( 0, NULL );
    player_transform_update();
@@ -258,10 +298,88 @@ void vg_update(void)
 
       v3_muls( move_vel, 0.75f, move_vel );
       v3_add( move_vel, player.view, player.view );
+   }
+   
 
-      return;
+   static int in_air = 1;
+
+   v3f ground_pos, ground_norm;
+   v3_copy( player.co, ground_pos );
+
+   if( sample_scene_height( &world.geo, ground_pos, ground_norm ) )
+   {
+#if 0
+      v3f localup;
+      m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, localup );
+      v3_normalize(localup);
+      v3_normalize(ground_norm);
+
+      float angle = v3_dot( localup, ground_norm );
+      v3f axis; 
+      v3_cross( localup, ground_norm, axis );
+
+      if( angle < 0.999f && !in_air )
+      {
+         v4f correction;
+         q_axis_angle( correction, axis, acosf(angle) );
+         q_mul( correction, player.rot, player.rot );
+      }
+#endif
    }
    
+   if( freecam )
+      return;
+
+   if( in_air )
+   {
+      v3f pco, pco1, pv;
+      
+      float pstep = timestep*10.0f;
+
+      v3f gravity = { 0.0f, -9.6f, 0.0f };
+      v3_copy( player.co, pco );
+      v3_copy( player.v, pv );
+
+      v3f targetn;
+
+      for( int i=0; i<20; i++ )
+      {
+         v3_copy( pco, pco1 );
+         v3_muladds( pv, gravity, pstep, pv );
+         v3_muladds( pco, pv, pstep, pco );
+
+         vg_line( pco, pco1, i&0x1?0xff000000:0xffffffff );
+         
+         v3f sh;
+         v3_copy( pco, sh );
+         sample_scene_height( &world.geo, sh, targetn );
+
+         if( sh[1] >= pco[1] )
+         {
+            v3f localup;
+            m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, localup );
+
+            float angle = v3_dot( localup, targetn );
+            v3f axis; 
+            v3_cross( localup, targetn, axis );
+
+            if( angle < 0.99f )
+            {
+               v4f correction;
+               q_axis_angle( correction, axis, acosf(angle)*0.1f );
+               q_mul( correction, player.rot, player.rot );
+            }
+
+            break;
+         }
+      }
+
+      if( ground_pos[1] > player.co[1] )
+      {
+         in_air = 0;
+      }
+   }
+
    if( vg_get_button( "forward" ) )
    {
       v3f dir = { 0.0f, 0.0f, -1.0f };
@@ -271,42 +389,47 @@ void vg_update(void)
    }
 
    /* Get front and back contact points */
-   v3f contact_front, contact_back, fwd, fwd1, contact_norm, vup;
+
+   v3f contact_front, contact_back, fwd, fwd1, contact_norm, vup, vside;
+   v3f axis;
 
    m3x3_mulv( player.to_world, (v3f){0.0f,0.0f,-1.0f}, fwd );
-   m3x3_mulv( player.to_world, (v3f){0.03f,0.0f,-1.0f}, fwd1 );
+   m4x3_mulv( player.to_world, (v3f){ 0.15f,0.0f,-1.0f}, contact_norm );
+   m4x3_mulv( player.to_world, (v3f){-0.15f,0.0f,-1.0f}, contact_front );
+   m4x3_mulv( player.to_world, (v3f){ 0.00f,0.0f, 1.0f}, contact_back );
    m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, vup );
-
-   v3_muladds( player.co, fwd, 1.0f, contact_front );
-   v3_muladds( player.co, fwd,-1.0f, contact_back );
-   v3_muladds( player.co, fwd1, 1.0f, contact_norm );
+   m3x3_mulv( player.to_world, (v3f){1.0f,0.0f,0.0f}, vside );
    
-   sample_scene_height( &world_scene, contact_front );
-   sample_scene_height( &world_scene, contact_back );
-   sample_scene_height( &world_scene, contact_norm );
+   int all_contacting = 
+      sample_scene_height( &world.geo, contact_front, NULL ) &&
+      sample_scene_height( &world.geo, contact_back, NULL ) &&
+      sample_scene_height( &world.geo, contact_norm, NULL );
 
    v3f norm;
    v3f v0, v1;
-   v3_sub( contact_back, contact_norm, v0 );
-   v3_sub( contact_front, contact_norm, v1 );
+   v3_sub( contact_norm, contact_front, v0 );
+   v3_sub( contact_back, contact_front, v1 );
    v3_cross( v1, v0, norm );
    v3_normalize( norm );
 
-   v3f gravity = { 0.0f, -9.6f, 0.0f };
-   v3_muladds( player.v, gravity, timestep, player.v );
+   vg_line( contact_norm, contact_front, 0xff00ff00 );
+   vg_line( contact_back, contact_front, 0xff0000ff );
 
-   v3f ground_pos;
-   v3_copy( player.co, ground_pos );
-   sample_scene_height( &world_scene, ground_pos );
+   /* Surface alignment */
+   float angle = v3_dot( vup, norm );
+   v3_cross( vup, norm, axis );
 
-   static int in_air = 1;
-
-   if( in_air )
+   if( angle < 0.999f && !in_air )
    {
-      if( ground_pos[1] > player.co[1] )
-         in_air = 0;
+      v4f correction;
+      q_axis_angle( correction, axis, acosf(angle) );
+      q_mul( correction, player.rot, player.rot );
    }
 
+
+   v3f gravity = { 0.0f, -9.6f, 0.0f };
+   v3_muladds( player.v, gravity, timestep, player.v );
+
    if( !in_air )
    {
       float resistance = v3_dot( norm, player.v );
@@ -329,39 +452,26 @@ void vg_update(void)
    {
       player.co[1] = (contact_front[1]+contact_back[1])*0.5f;
 
-      vg_line( player.co, contact_front, 0xff00ffff );
-      vg_line( player.co, contact_back, 0xff00ffa0 );
-
-      /* Create the 'travel' vector */
-      v3f travel;
-      v3_sub( contact_front, contact_back, travel );
-      v3_normalize( travel );
-
-      /* Apply gravity */
-#if 0
-      float gravity_conversion = -v3_dot( travel, gravity );
-      vel[2] += gravity_conversion * substep;
-#endif
-
-      /* Get localized (rotated) rigidbody forces 
-       *           -z
-       *            ^
-       *           -|-
-       *            |
-       *           +z
-       */
-      
       v3f vel;
       m3x3_mulv( player.to_local, player.v, vel );
 
       /* Calculate local forces */
-      slip = -vel[0] / vel[2];
-      float substep = timestep * 0.2f;
 
+      slip = (-vel[0] / vel[2]) * player.vswitch;
       if( fabsf( slip ) > 1.2f )
-      {
          slip = vg_signf( slip ) * 1.2f;
+
+      
+      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;
+
+      float substep = timestep * 0.2f;
       
       for( int i=0; i<5; i++ )
       {
@@ -384,6 +494,10 @@ void vg_update(void)
    else
    {
       yawamt -= vg_get_axis( "horizontal" ) * 3.6f * timestep;
+
+      v4f pitch;
+      q_axis_angle( pitch, vside, vg_get_axis( "vertical" ) * 3.6f *timestep );
+      q_mul( pitch, player.rot, player.rot );
    }
 
    v4f rotate;
@@ -399,28 +513,42 @@ void vg_update(void)
    v2f ac;
 
    static v3f last_vel = { 0.0f, 0.0f, 0.0f };
-   static v3f bob, bob1;
+   static v3f momentum, bob;
 
    v3_sub( player.v, last_vel, player.a );
    v3_copy( player.v, last_vel );
-   v3_add( bob, player.a, bob );
 
-   bob[0] = vg_clampf( bob[0], -0.4f, 1.0f );
-   bob[1] = vg_clampf( bob[1], -0.4f, 1.3f );
-   bob[2] = vg_clampf( bob[2], -0.4f, 1.0f );
+   v3_add( momentum, player.a, momentum );
+   
+   v3_lerp( momentum, (v3f){0.0f,0.0f,0.0f}, 0.1f, momentum );
+   v3f target;
    
-   v3_lerp( bob, (v3f){ 0.0f, 0.0f, 0.0f }, 0.1f, bob );
-   v3_lerp( bob1, bob, 0.1f, bob1 );
+   momentum[0] = vg_clampf( momentum[0], -2.0f, 2.0f );
+   momentum[1] = vg_clampf( momentum[1], -0.2f, 5.0f );
+   momentum[2] = vg_clampf( momentum[2], -2.0f, 2.0f );
+   v3_copy( momentum, target );
    
+   v3_lerp( bob, target, 0.2f, bob );
+
    /* Head */
-   head[0] =  (-sinf(slip)*0.9f * kheight + bob1[0]*0.6f) * 0.54f;
-   head[1] =  cosf(slip)*0.9f * kheight +-bob1[1]*1.4f;
+   float lslip = fabsf(slip); //vg_minf( 0.4f, slip );
+   head[0] =  0.0f;//(-sinf(lslip)*0.9f * kheight) * 0.44f;
+   head[1] =  (0.3f + cosf(lslip)*0.5f) * kheight;
    head[2] =  0.0f;
 
+   v3f offset;
+   m3x3_mulv( player.to_local, bob, offset );
+   offset[0] *= 0.25f;
+   offset[1] *= -0.25f;
+   offset[2] *= 0.7f;
+   v3_muladds( head, offset, 1.0f, head );
+
+   player_transform_update();
+
    m4x3_mulv( player.to_world, head, head );
    v3_copy( head, player.view );
 
-   player_transform_update();
+   q_normalize(player.rot);
 }
 
 static void debug_grid( v3f at )
@@ -442,12 +570,106 @@ static void debug_grid( v3f at )
    }
 }
 
+static void draw_player(void)
+{
+   mesh_bind( &player.mesh );
+   float const kleg_upper = 0.53f,
+               kleg_lower = 0.5f;
+
+   /* Create IK targets */
+   struct ik_basic ik_leg_l = { .l1 = kleg_upper, .l2 = kleg_lower },
+                   ik_leg_r = { .l1 = kleg_upper, .l2 = kleg_lower };
+
+   v3f butt, fwd;
+
+   m4x3_mulv( player.to_world, (v3f){ 0.0f,0.16f,-0.4f }, ik_leg_r.end );
+   m4x3_mulv( player.to_world, (v3f){ 0.0f,0.16f, 0.3f }, ik_leg_l.end );
+   m4x3_mulv( player.to_world, (v3f){ -0.6f,0.5f,-0.4f }, ik_leg_r.pole );
+   m4x3_mulv( player.to_world, (v3f){ -0.6f,0.5f,0.35f }, ik_leg_l.pole );
+
+   m3x3_mulv( player.to_world, (v3f){ 0.2f,-0.55f,0.0f}, butt );
+   v3_add( butt, player.view, butt );
+
+   m3x3_mulv( player.to_world, (v3f){0.0f,0.0f,-1.0f}, fwd );
+   v3_muladds( butt, fwd, 0.1f, ik_leg_r.base );
+   v3_muladds( butt, fwd,-0.1f, ik_leg_l.base );
+
+   /* Compute IK */
+   m4x3f mleg_l, mknee_l, mleg_r, mknee_r, mboard;
+
+   ik_basic( &ik_leg_r, mleg_r, mknee_r );
+   ik_basic( &ik_leg_l, mleg_l, mknee_l );
+   
+   /* Draw */
+   vg_tex2d_bind( &tex_grid, 0 );
+   scene_tree_sway = 0.0f;
+
+   mesh_bind( &player.mesh );
+   m4x4f mat;
+
+   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 );
+   vg_tex2d_bind( &tex_grid, 0 );
+
+   GLint kuMdl = SHADER_UNIFORM( shader_standard_lit, "uMdl" );
+   
+   float kscale = 0.7f;
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.9f*kscale,0.6f*kscale,0.1f*kscale,1.0f );
+
+   m4x3_expand( player.to_world, mat );
+       glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
+   submodel_draw( &player.board );
+
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.2f*kscale,0.3f*kscale,1.0f*kscale,1.0f );
+   submodel_draw( &player.wheels );
+
+   glEnable(GL_BLEND);
+   glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+   glBlendEquation(GL_FUNC_ADD);
+   glDisable( GL_DEPTH_TEST );
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.2f*kscale,0.3f*kscale,1.0f*kscale,0.2f );
+
+   m4x3_expand( mleg_l, mat );
+       glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
+   submodel_draw( &player.legu );
+
+   m4x3_expand( mknee_l, mat );
+       glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
+   submodel_draw( &player.legl );
+
+   m4x3_expand( mleg_r, mat );
+       glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
+   submodel_draw( &player.legu );
+
+   m4x3_expand( mknee_r, mat );
+       glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
+   submodel_draw( &player.legl );
+
+   m4x3f mbutt;
+   m3x3_copy( player.to_world, mbutt );
+   v3_copy( butt, mbutt[3] );
+
+   m4x3_expand( mbutt, mat );
+       glUniformMatrix4fv( kuMdl, 1, GL_FALSE, (float *)mat );
+   submodel_draw( &player.torso );
+
+   glDisable(GL_BLEND);
+   glEnable( GL_DEPTH_TEST );
+}
+
 void vg_render(void) 
 {
    glViewport( 0,0, vg_window_x, vg_window_y );
 
    glDisable( GL_DEPTH_TEST );
    glClearColor( 0.1f, 0.0f, 0.2f, 1.0f );
+   glClearColor(141.0f/255.0f, 176.0f/255.0f, 215.0f/255.0f,1.0f);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
    v3f pos_inv;
@@ -459,7 +681,7 @@ void vg_render(void)
 
    m4x3_identity( world_matrix );
    m4x3_rotate_x( world_matrix, 
-         freecam? player.look_dir[1]: 0.3f+shake[1]*0.04f );
+         freecam? player.look_dir[1]: 0.5f+shake[1]*0.04f );
    m4x3_rotate_y( world_matrix, player.look_dir[0]+shake[0]*0.02f );
    m4x3_translate( world_matrix, pos_inv );
    
@@ -472,65 +694,101 @@ void vg_render(void)
          0.01f, 1000.0f );
    m4x4_mul( vg_pv, world_4x4, vg_pv );
 
-   if( debugroad )
-      draw_road_patch_dev( &road_main );
-
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
 
-   v3f board_fwd = { 0.0f, 0.0f, -1.0f };
-   v3f board_side = { 1.0f, 0.0f, 0.0f };
+   glEnable( GL_DEPTH_TEST );
+   
+   scene_foliage_shader_use();
+   m4x4f temp1;
+   m4x4_identity( temp1 );
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol, "uMdl" ), 
+         1, GL_FALSE, (float *)temp1 );
 
-   m3x3_mulv( player.to_world, board_fwd, board_fwd );
-   m3x3_mulv( player.to_world, board_side, board_side );
+   vg_tex2d_bind( &tex_norwey, 0 );
+   scene_tree_sway = 0.1f;
 
-   v3f bnw, bne, bse, bsw;
+   scene_bind( &world.foliage );
+   scene_draw( &world.foliage );
+   if( debugsdf )
+      scene_debugsdf( &world.foliage );
    
-   v3_muladds( player.co, board_fwd, 0.75f, bnw );
-   v3_muladds( player.co, board_fwd, -0.75f, bsw );
-   v3_muladds( bnw, board_side,  0.1f, bne );
-   v3_muladds( bnw, board_side, -0.1f, bnw );
-   v3_muladds( bsw, board_side,  0.1f, bse );
-   v3_muladds( bsw, board_side, -0.1f, bsw );
-
-   vg_line( bnw, bne, 0xff00ff00 );
-   vg_line( bne, bse, 0xff00ff00 );
-   vg_line( bse, bsw, 0xff00ff00 );
-   vg_line( bsw, bnw, 0xff00ff00 );
+   SHADER_USE(shader_unlit);
+   m4x4f temp2;
+   m4x4_identity(temp2);
+   //m4x4_translate( temp2, player.co );
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit, "uMdl" ), 
+         1, GL_FALSE, (float *)temp2 );
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_unlit, "uPv" ), 
+         1, GL_FALSE, (float *)vg_pv );
 
-   glEnable( GL_DEPTH_TEST );
+   glUniform1i( SHADER_UNIFORM( shader_unlit, "uTexMain" ), 0 );
+   vg_tex2d_bind( &tex_sky, 0 );
 
-   SHADER_USE( shader_debug_vcol );
-   m4x3f temp;
-   m4x4f temp1;
+   SHADER_USE(shader_standard_lit);
 
-   vg_tex2d_bind( &tex_grid, 0 );
-   scene_tree_sway = 0.0f;
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ), 
+         1, GL_FALSE, (float *)vg_pv );
+   glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 );
 
-   m4x3_identity( temp );
-   m4x3_expand( temp, temp1 );
-       glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol, "uMdl" ), 
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uMdl" ), 
          1, GL_FALSE, (float *)temp1 );
-   scene_draw( &player_scene, -1, 0 );
+
+   vg_tex2d_bind( &tex_grid, 0 );
+
+   scene_bind( &world.geo );
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.2f,0.36f,0.25f,1.0f );
+   submodel_draw( &world.terrain );
+
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.2f,0.2f,0.21f,1.0f );
+   submodel_draw( &world.terrain_rocks );
+
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.4f,0.4f,0.4f,1.0f );
+   submodel_draw( &world.terrain_road );
    
-   m4x3_identity( temp );
-   m4x3_expand( temp, temp1 );
-       glUniformMatrix4fv( SHADER_UNIFORM( shader_debug_vcol, "uMdl" ), 
-         1, GL_FALSE, (float *)temp1 );
+   scene_bind( &world.detail );
+   scene_draw( &world.detail );
 
-   vg_tex2d_bind( &tex_norwey, 0 );
-   scene_tree_sway = 0.1f;
-   scene_draw( &test_scene, -1, 0 );
+   draw_player();
 
-   vg_tex2d_bind( &tex_grid, 0 );
-   scene_tree_sway = 0.0f;
-   scene_draw( &world_scene, world_terrain_count, 0 );
+   glDisable( GL_DEPTH_TEST );
+   vg_lines_drawall( (float *)vg_pv );
+
+   /* Debugger camera */
+   glViewport( 0,0, 512, 512 );
+   glClearColor( 0.1f, 0.0f, 0.2f, 1.0f );
+   glClear( GL_DEPTH_BUFFER_BIT );
+
+   m4x3_identity( world_matrix );
 
-   vg_tex2d_bind( &tex_road, 0 );
-   scene_draw( &world_scene, world_road_count, world_terrain_count );
+   v3f debugcam;
+   v3_negate( player.co, debugcam );
+   debugcam[2] -= 2.0f;
+   debugcam[1] -= 0.7f;
+
+   m4x3_translate( world_matrix, debugcam );
+   m4x3_expand( world_matrix, world_4x4 );
+
+   m4x4_projection( vg_pv, 
+         100.0f,
+         (float)128.0f / (float)128.0f,
+         0.01f, 1000.0f );
+   m4x4_mul( vg_pv, world_4x4, vg_pv );
+
+   if(sv_debugcam)
+   {
+      glEnable( GL_DEPTH_TEST );
+      draw_player();
+   }
 
    glDisable( GL_DEPTH_TEST );
+   vg_lines_drawall( (float *)vg_pv );
+
+   glViewport( 0,0, vg_window_x, vg_window_y );
 }
 
 void vg_ui(void)
diff --git a/model.h b/model.h
new file mode 100644 (file)
index 0000000..2aaf483
--- /dev/null
+++ b/model.h
@@ -0,0 +1,185 @@
+#include "vg/vg.h"
+
+typedef struct model model;
+typedef struct glmesh glmesh;
+typedef struct submodel submodel;
+typedef struct model_vert model_vert;
+typedef struct scene scene;
+typedef struct sdf_primative sdf_primative;
+typedef enum esdf_type esdf_type;
+
+#pragma pack(push,1)
+struct model
+{
+   u32 identifier;
+
+   u32 vertex_count,
+       indice_count,
+       layer_count;
+};
+
+struct sdf_primative
+{
+   v4f origin;   /* xyz, yaw */
+   /* Cone: 
+       x  base scale
+       y  height 
+   */
+   v4f info;
+};
+
+struct submodel
+{
+   u32 indice_start,
+       indice_count,
+       vertex_start,
+       vertex_count;
+   
+   boxf bbx;
+   sdf_primative sdf;
+
+   enum esdf_type
+   {
+      k_sdf_none = 0,
+      k_sdf_cone,
+      k_sdf_sphere,
+      k_sdf_box
+   }
+   sdf_type;
+
+   char name[32];
+};
+
+struct model_vert
+{
+   v3f co,
+       norm;
+   v4f colour;
+   v2f uv;
+};
+#pragma pack(pop)
+
+struct glmesh
+{
+   GLuint vao, vbo, ebo;
+   u32 indice_count;
+};
+
+static void mesh_upload( glmesh *mesh,
+      model_vert *verts, u32 vert_count,
+      u32 *indices, u32 indice_count )
+{
+   glGenVertexArrays( 1, &mesh->vao );
+   glGenBuffers( 1, &mesh->vbo );
+   glGenBuffers( 1, &mesh->ebo );
+   glBindVertexArray( mesh->vao );
+
+   glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
+   glBufferData( GL_ARRAY_BUFFER, vert_count*sizeof(model_vert), 
+         verts, GL_STATIC_DRAW );
+
+   glBindVertexArray( mesh->vao );
+   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
+   glBufferData( GL_ELEMENT_ARRAY_BUFFER, indice_count*sizeof(u32),
+         indices, GL_STATIC_DRAW );
+   
+   glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 
+         sizeof(model_vert), (void*)0 );
+   glEnableVertexAttribArray( 0 );
+
+   glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 
+         sizeof(model_vert), (void *)offsetof(model_vert, norm) );
+   glEnableVertexAttribArray( 1 );
+
+   glVertexAttribPointer( 2, 4, GL_FLOAT, GL_FALSE, 
+         sizeof(model_vert), (void *)offsetof(model_vert, colour) );
+   glEnableVertexAttribArray( 2 );
+
+   glVertexAttribPointer( 3, 2, GL_FLOAT, GL_FALSE, 
+         sizeof(model_vert), (void *)offsetof(model_vert, uv) );
+   glEnableVertexAttribArray( 3 );
+   
+   VG_CHECK_GL();
+   mesh->indice_count = indice_count;
+}
+
+static void mesh_bind( glmesh *mesh )
+{
+   glBindVertexArray( mesh->vao );
+}
+
+static void mesh_drawn( u32 start, u32 count )
+{
+   glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, 
+         (void *)(start*sizeof(u32)) );
+}
+
+static void mesh_draw( glmesh *mesh )
+{
+   mesh_drawn( 0, mesh->indice_count );
+}
+
+/*
+ * Helper functions for file offsets
+ */
+static submodel *model_get_submodel( model *mdl, int id )
+{
+   return ((submodel*)(mdl+1)) + id;
+}
+
+static model_vert *model_vertex_base( model *mdl )
+{
+   return (model_vert *)model_get_submodel( mdl, mdl->layer_count );
+}
+
+static u32 *model_indice_base( model *mdl )
+{
+   return (u32 *)(model_vertex_base( mdl ) + mdl->vertex_count);
+}
+
+static model_vert *submodel_vert_data( model *mdl, submodel *sub )
+{
+   return model_vertex_base(mdl) + sub->vertex_start;
+}
+
+static u32 *submodel_indice_data( model *mdl, submodel *sub )
+{
+   return model_indice_base(mdl) + sub->indice_start;
+}
+
+static submodel *submodel_get( model *mdl, const char *name )
+{
+   for( int i=0; i<mdl->layer_count; i++ )
+   {
+      submodel *pmdl =model_get_submodel(mdl,i);
+
+      if( !strcmp( pmdl->name, name ) )
+         return pmdl;
+   }
+   
+   return NULL;
+}
+
+static void submodel_draw( submodel *sm )
+{
+   mesh_drawn( sm->indice_start, sm->indice_count );
+}
+
+static void model_unpack( model *model, glmesh *mesh )
+{
+   u32 offset = model_get_submodel( model, 0 )->vertex_count;
+
+   for( int i=1; i<model->layer_count; i++ )
+   {
+      submodel *sm = model_get_submodel( model, i );
+      u32 *indices = submodel_indice_data( model, sm );
+
+      for( u32 j=0; j<sm->indice_count; j++ )
+         indices[j] += offset;
+
+      offset += sm->vertex_count;
+   }
+
+   mesh_upload( mesh, model_vertex_base( model ), model->vertex_count,
+                       model_indice_base( model ), model->indice_count );
+}
diff --git a/scene.h b/scene.h
index af9e26add0585bc3d4e1eb4b583547da7c453034..bf61fba9eabe99ba1802e618f9ae55cd464107c6 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -1,66 +1,11 @@
-typedef struct model model;
-typedef struct submodel submodel;
-typedef struct model_vert model_vert;
-typedef struct scene scene;
-typedef struct sdf_primative sdf_primative;
-typedef enum esdf_type esdf_type;
+#include "vg/vg.h"
+#include "model.h"
 
 GLuint tex_dual_noise;
 
-#pragma pack(push,1)
-struct model
-{
-   u32 identifier;
-
-   u32 vertex_count,
-       indice_count,
-       layer_count;
-};
-
-struct sdf_primative
-{
-   v4f origin;   /* xyz, yaw */
-   /* Cone: 
-       x  base scale
-       y  height 
-   */
-   v4f info;
-};
-
-struct submodel
-{
-   u32 indice_start,
-       indice_count,
-       vertex_start,
-       vertex_count;
-   
-   boxf bbx;
-   sdf_primative sdf;
-
-   enum esdf_type
-   {
-      k_sdf_none = 0,
-      k_sdf_cone,
-      k_sdf_sphere,
-      k_sdf_box
-   }
-   sdf_type;
-
-   char name[32];
-};
-
-struct model_vert
-{
-   v3f co,
-       norm;
-   v4f colour;
-   v2f uv;
-};
-#pragma pack(pop)
-
 struct scene
 {
-   GLuint vao, vbo, ebo;
+   glmesh mesh;
 
    model_vert *verts;
    u32 *indices;
@@ -81,6 +26,8 @@ struct scene
 
    u32 shadower_count,
        shadower_cap;
+
+   submodel submesh;
 };
 
 static void scene_init( scene *pscene )
@@ -92,6 +39,8 @@ static void scene_init( scene *pscene )
    pscene->shadowers = NULL;
    pscene->shadower_count = 0;
    pscene->shadower_cap = 0;
+   pscene->submesh.indice_start = 0;
+   pscene->submesh.indice_count = 0;
 
    v3_fill( pscene->bbx[0],  999999.9f );
    v3_fill( pscene->bbx[1], -999999.9f );
@@ -161,12 +110,16 @@ static void scene_init( scene *pscene )
    "return f;"                                        \
 "}"
 
-SHADER_DEFINE( shader_debug_vcol,
-       "layout (location=0) in vec3 a_co;"
-   "layout (location=1) in vec3 a_norm;"
-   "layout (location=2) in vec4 a_colour;"
+#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
+
        "uniform mat4 uPv;"
    "uniform mat4 uMdl;"
    "uniform float uTime;"
@@ -204,7 +157,7 @@ SHADER_DEFINE( shader_debug_vcol,
    "uniform sampler2D uTexMain;"
    "uniform sampler2D uTexGradients;"
    ""
-   /* Include */ SHADER_VALUE_NOISE_3D
+   /*Include*/ SHADER_VALUE_NOISE_3D
    ""
    "in vec4 aColour;"
    "in vec2 aUv;"
@@ -247,9 +200,22 @@ SHADER_DEFINE( shader_debug_vcol,
       "}"
       "if( uMode == 7 )"
       "{"
-         "if( diffuse.a < 0.45 ) discard;"
-         "float lighting = 1.0 - aColour.g;"
+         "if( diffuse.a < 0.2 ) discard;"
+         "float lighting = 1.0 - aColour.g*0.8;"
+   
+         "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 lt = vec3(0.2,0.2,0.2 ) + " 
+                   "vec3(1.0,1.0,0.9)*light1 + "
+                   "vec3(0.1,0.3,0.4 )*light2;"
+
+
          "colour = vec4(vec3(pow(lighting,1.6)*(diffuse.r*0.7+0.5)),1.0);"
+         "colour = vec4(colour.rgb*lt,1.0);"
+
+         "vec2 gradUV = vec2(lighting*1.9,aColour.b*0.8);"
+         "vec4 gradient_sample = texture( uTexGradients, gradUV );"
+         "colour = colour*gradient_sample;"
       "}"
       "if( uMode == 8 )"
       "{"
@@ -258,9 +224,9 @@ SHADER_DEFINE( shader_debug_vcol,
          "light = pow(light,1.6)*(diffuse.r*0.7+0.5);"
          "float r1 = fractalNoise(aCo*0.01);"
          
-         "vec2 gradUV = vec2(light*1.9,r1+aColour.b*0.1);"
+         "vec2 gradUV = vec2(light*1.9,r1+aColour.b);"
          "vec4 gradient_sample = texture( uTexGradients, gradUV );"
-         "colour = aColour*light;"
+         "colour = gradient_sample*light;"
       "}"
 
                "FragColor = colour;"
@@ -270,47 +236,93 @@ SHADER_DEFINE( shader_debug_vcol,
               "uTime", "uSwayAmt", "uMdl" })
 )
 
-/*
- * Helper functions for file offsets
- */
-static submodel *model_get_submodel( model *mdl, int id )
-{
-   return ((submodel*)(mdl+1)) + id;
-}
+SHADER_DEFINE( shader_standard_lit,
 
-static model_vert *model_vertex_base( model *mdl )
-{
-   return (model_vert *)model_get_submodel( mdl, mdl->layer_count );
-}
+   /*Include*/ VERTEX_STANDARD_ATTRIBUTES
 
-static u32 *model_indice_base( model *mdl )
-{
-   return (u32 *)(model_vertex_base( mdl ) + mdl->vertex_count);
-}
+       "uniform mat4 uPv;"
+   "uniform mat4 uMdl;"
+   ""
+   "out vec4 aColour;"
+   "out vec2 aUv;"
+   "out vec3 aNorm;"
+   "out vec3 aCo;"
+   ""
+       "void main()"
+       "{"
+               "gl_Position = uPv * uMdl * vec4( a_co, 1.0 );"
+      "aColour = a_colour;"
+      "aUv = a_uv;"
+      "aNorm = mat3(uMdl) * a_norm;"
+      "aCo = a_co;"
+       "}",
+   /* Fragment */
+       "out vec4 FragColor;"
+       ""
+   "uniform sampler2D uTexMain;"
+   "uniform vec4 uColour;"
+   ""
+   "in vec4 aColour;"
+   "in vec2 aUv;"
+   "in vec3 aNorm;"
+   "in vec3 aCo;"
+   ""
+       "void main()"
+       "{"
+      "vec3 diffuse = texture( uTexMain, aUv ).rgb;"
 
-static model_vert *submodel_vert_data( model *mdl, submodel *sub )
-{
-   return model_vertex_base(mdl) + sub->vertex_start;
-}
+      "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 ) + " 
+                 "vec3(1.0,1.0,0.9)*light1 + "
+                 "vec3(0.1,0.3,0.4 )*light2;"
 
-static u32 *submodel_indice_data( model *mdl, submodel *sub )
-{
-   return model_indice_base(mdl) + sub->indice_start;
-}
+               "FragColor = vec4((diffuse*uColour.rgb),"
+                        "aColour.a*uColour.a);"
+       "}"
+       ,
+       UNIFORMS({ "uColour","uTexMain","uPv","uMdl" })
+)
 
-/* Returns -1 if not found */
-static int submodel_get( model *mdl, const char *name )
-{
-   for( int i=0; i<mdl->layer_count; i++ )
-   {
-      if( !strcmp( model_get_submodel(mdl,i)->name, name ))
-      {
-         return i;
-      }
-   }
-   
-   return -1;
-}
+SHADER_DEFINE( shader_unlit,
+
+   /*Include*/ VERTEX_STANDARD_ATTRIBUTES
+
+       "uniform mat4 uPv;"
+   "uniform mat4 uMdl;"
+   ""
+   "out vec4 aColour;"
+   "out vec2 aUv;"
+   "out vec3 aNorm;"
+   "out vec3 aCo;"
+   ""
+       "void main()"
+       "{"
+               "gl_Position = uPv * uMdl * vec4( a_co, 1.0 );"
+      "aColour = a_colour;"
+      "aUv = a_uv;"
+      "aNorm = mat3(uMdl) * a_norm;"
+      "aCo = a_co;"
+       "}",
+   /* Fragment */
+       "out vec4 FragColor;"
+       ""
+   "uniform sampler2D uTexMain;"
+   "uniform vec4 uColour;"
+   ""
+   "in vec4 aColour;"
+   "in vec2 aUv;"
+   "in vec3 aNorm;"
+   "in vec3 aCo;"
+   ""
+       "void main()"
+       "{"
+      "vec3 diffuse = texture( uTexMain, aUv ).rgb;"
+      "FragColor = vec4(pow(diffuse,vec3(1.0/2.2)),1.0);"
+       "}"
+       ,
+       UNIFORMS({ "uTexMain", "uPv", "uMdl" })
+)
 
 static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount, 
       size_t emsize )
@@ -328,11 +340,9 @@ static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount,
 /* 
  * Append a model into the scene with a given transform
  */
-static void scene_add_model( scene *pscene, model *mdl, int id,
+static void scene_add_model( scene *pscene, model *mdl, submodel *submodel,
       v3f pos, float yaw, float scale )
 {
-   submodel *submodel = model_get_submodel( mdl, id );
-   
    pscene->verts = buffer_reserve( pscene->verts, pscene->vertex_count, 
          &pscene->vertex_cap, submodel->vertex_count, sizeof(model_vert) );
    pscene->indices = buffer_reserve( pscene->indices, pscene->indice_count,
@@ -401,6 +411,14 @@ static void scene_add_model( scene *pscene, model *mdl, int id,
    pscene->indice_count += submodel->indice_count;
 }
 
+static void scene_copy_slice( scene *pscene, submodel *sm )
+{
+   sm->indice_start = pscene->submesh.indice_start;
+   sm->indice_count = pscene->indice_count - sm->indice_start;
+   
+   pscene->submesh.indice_start = pscene->indice_count;
+}
+
 static void scene_shadow_sphere( scene *pscene, v3f sphere, 
       v4f params, v3f lightdir )
 {
@@ -438,19 +456,30 @@ static void scene_shadow_gradient( scene *pscene, int comp,
 }
 
 /* Temporary */
-static int sample_scene_height( scene *pscene, v3f pos )
+static int sample_scene_height( scene *pscene, v3f pos, v3f norm )
 {
    for( int i=0; i<pscene->indice_count/3; i++ )
    {
       u32 *tri = &pscene->indices[i*3];
+
+      float *pA = pscene->verts[tri[0]].co,
+            *pB = pscene->verts[tri[1]].co,
+            *pC = pscene->verts[tri[2]].co;
       
       float height;
-      if( triangle_raycast( 
-            pscene->verts[ tri[0] ].co,
-            pscene->verts[ tri[1] ].co,
-            pscene->verts[ tri[2] ].co, pos, &height ))
+      if( triangle_raycast( pA, pB, pC, pos, &height ))
       {
          pos[1] = height;
+         
+         if( norm )
+         {
+            v3f v0, v1;
+            v3_sub( pA, pB, v0 );
+            v3_sub( pC, pB, v1 );
+            v3_cross( v1, v0, norm );
+            v3_normalize( norm );
+         }
+
          return 1;
       }
    }
@@ -757,37 +786,9 @@ static void scene_compute_occlusion( scene *pscene )
 
 static void scene_upload( scene *pscene )
 {
-   glGenVertexArrays( 1, &pscene->vao );
-   glGenBuffers( 1, &pscene->vbo );
-   glGenBuffers( 1, &pscene->ebo );
-   glBindVertexArray( pscene->vao );
-
-   glBindBuffer( GL_ARRAY_BUFFER, pscene->vbo );
-   glBufferData( GL_ARRAY_BUFFER, pscene->vertex_count*sizeof(model_vert),
-         pscene->verts, GL_STATIC_DRAW );
-
-   glBindVertexArray( pscene->vao );
-   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pscene->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, pscene->indice_count*sizeof(u32),
-         pscene->indices, GL_STATIC_DRAW );
-   
-   glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 
-         sizeof(model_vert), (void*)0 );
-   glEnableVertexAttribArray( 0 );
-
-   glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 
-         sizeof(model_vert), (void *)offsetof(model_vert, norm) );
-   glEnableVertexAttribArray( 1 );
-
-   glVertexAttribPointer( 2, 4, GL_FLOAT, GL_FALSE, 
-         sizeof(model_vert), (void *)offsetof(model_vert, colour) );
-   glEnableVertexAttribArray( 2 );
-
-   glVertexAttribPointer( 3, 2, GL_FLOAT, GL_FALSE, 
-         sizeof(model_vert), (void *)offsetof(model_vert, uv) );
-   glEnableVertexAttribArray( 3 );
-
-   VG_CHECK_GL();
+   mesh_upload( &pscene->mesh,
+         pscene->verts, pscene->vertex_count,
+         pscene->indices, pscene->indice_count );
 
    vg_info( "Scene upload\n" );
    vg_info( "   indices:%u\n", pscene->indice_count );
@@ -795,7 +796,8 @@ static void scene_upload( scene *pscene )
 }
 
 float scene_tree_sway = 0.1f;
-static void scene_draw( scene *pscene, int count, int start )
+
+static void scene_foliage_shader_use(void)
 {
    SHADER_USE( shader_debug_vcol );
 
@@ -815,70 +817,65 @@ static void scene_draw( scene *pscene, int count, int start )
    glUniform1f( SHADER_UNIFORM( shader_debug_vcol, "uTime" ), vg_time );
    glUniform1f( SHADER_UNIFORM( shader_debug_vcol, "uSwayAmt" ), 
          scene_tree_sway );
+}
 
-   glBindVertexArray( pscene->vao );
+static void scene_bind( scene *pscene )
+{
+   mesh_bind( &pscene->mesh );
+}
 
-   if( count == -1 )
-   {
-      glDrawElements( GL_TRIANGLES, pscene->indice_count,
-         GL_UNSIGNED_INT,
-         (void *)0
-      );
-   }
-   else
-   {
-      glDrawElements( GL_TRIANGLES, count,
-         GL_UNSIGNED_INT,
-         (void *)(start*sizeof(u32))
-      );
-   }
+static void scene_draw( scene *pscene )
+{
+   mesh_drawn( 0, pscene->indice_count );
+}
 
-   if( debugsdf )
+static void scene_debugsdf( scene *pscene )
+{
+   for( int i=0; i<pscene->shadower_count; i++ )
    {
-      for( int i=0; i<pscene->shadower_count; i++ )
-      {
-         struct shadower *shadower = &pscene->shadowers[i];
+      struct shadower *shadower = &pscene->shadowers[i];
 
-         v3f base, side;
-         v3_copy( shadower->sdf.origin, base );
-         base[1] -= shadower->sdf.info[1];
-         v3_copy( base, side );
-         side[0] += shadower->sdf.info[0];
+      v3f base, side;
+      v3_copy( shadower->sdf.origin, base );
+      base[1] -= shadower->sdf.info[1];
+      v3_copy( base, side );
+      side[0] += shadower->sdf.info[0];
 
-         vg_line2( shadower->sdf.origin, base, 0xff00ff00, 0xff0000ff );
-         vg_line2( side, base, 0xff00ff00, 0xff0000ff );
-         vg_line( side, shadower->sdf.origin, 0xff00ff00 );
-      }
+      vg_line2( shadower->sdf.origin, base, 0xff00ff00, 0xff0000ff );
+      vg_line2( side, base, 0xff00ff00, 0xff0000ff );
+      vg_line( side, shadower->sdf.origin, 0xff00ff00 );
+   }
 
-      v3f p0 = { pscene->bbx[0][0], pscene->bbx[0][1], pscene->bbx[0][2] },
-          p1 = { pscene->bbx[0][0], pscene->bbx[1][1], pscene->bbx[0][2] }, 
-          p2 = { pscene->bbx[1][0], pscene->bbx[1][1], pscene->bbx[0][2] },
-          p3 = { pscene->bbx[1][0], pscene->bbx[0][1], pscene->bbx[0][2] },
+   v3f p0 = { pscene->bbx[0][0], pscene->bbx[0][1], pscene->bbx[0][2] },
+       p1 = { pscene->bbx[0][0], pscene->bbx[1][1], pscene->bbx[0][2] }, 
+       p2 = { pscene->bbx[1][0], pscene->bbx[1][1], pscene->bbx[0][2] },
+       p3 = { pscene->bbx[1][0], pscene->bbx[0][1], pscene->bbx[0][2] },
 
-          p4 = { pscene->bbx[0][0], pscene->bbx[0][1], pscene->bbx[1][2] },
-          p5 = { pscene->bbx[0][0], pscene->bbx[1][1], pscene->bbx[1][2] }, 
-          p6 = { pscene->bbx[1][0], pscene->bbx[1][1], pscene->bbx[1][2] },
-          p7 = { pscene->bbx[1][0], pscene->bbx[0][1], pscene->bbx[1][2] };
-      
-      u32 col = 0xffff00c8;
-      vg_line( p0, p1, col );
-      vg_line( p1, p2, col );
-      vg_line( p2, p3, col );
-      vg_line( p3, p0, col );
-
-      vg_line( p4, p5, col );
-      vg_line( p5, p6, col );
-      vg_line( p6, p7, col );
-      vg_line( p7, p4, col );
-
-      vg_line( p0, p4, col );
-      vg_line( p1, p5, col );
-      vg_line( p2, p6, col );
-      vg_line( p3, p7, col );
-   }
+       p4 = { pscene->bbx[0][0], pscene->bbx[0][1], pscene->bbx[1][2] },
+       p5 = { pscene->bbx[0][0], pscene->bbx[1][1], pscene->bbx[1][2] }, 
+       p6 = { pscene->bbx[1][0], pscene->bbx[1][1], pscene->bbx[1][2] },
+       p7 = { pscene->bbx[1][0], pscene->bbx[0][1], pscene->bbx[1][2] };
+   
+   u32 col = 0xffff00c8;
+   vg_line( p0, p1, col );
+   vg_line( p1, p2, col );
+   vg_line( p2, p3, col );
+   vg_line( p3, p0, col );
+
+   vg_line( p4, p5, col );
+   vg_line( p5, p6, col );
+   vg_line( p6, p7, col );
+   vg_line( p7, p4, col );
+
+   vg_line( p0, p4, col );
+   vg_line( p1, p5, col );
+   vg_line( p2, p6, col );
+   vg_line( p3, p7, col );
 }
 
 static void scene_register(void)
 {
    SHADER_INIT( shader_debug_vcol );
+   SHADER_INIT( shader_standard_lit );
+   SHADER_INIT( shader_unlit );
 }
index 8b60c3b9f6694db689b8298c138220b9a5817ed8..f596bf6e48eecde007d93e621843624b892c6556 100644 (file)
Binary files a/textures/gradients.png and b/textures/gradients.png differ
diff --git a/textures/sky.png b/textures/sky.png
new file mode 100644 (file)
index 0000000..fb3fb5b
Binary files /dev/null and b/textures/sky.png differ