change shader properties to be vg_msg based
[carveJwlIkooP6JGAAIwe30JlM.git] / model.c
diff --git a/model.c b/model.c
index a04f5d5152cb2a2e922214a7e1c7aafaaac49082..b8bacf280eac9863a5e5c8fcec4d240887196fde 100644 (file)
--- a/model.c
+++ b/model.c
@@ -4,13 +4,16 @@
 
 #pragma once
 
-#include "model.h"
 #include "vg/vg_io.h"
 #include "vg/vg_async.h"
 #include "vg/vg_tex.h"
+#include "vg/vg_msg.h"
+#include "vg/vg_string.h"
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
+#include "model.h"
+#include "render.h"
 
 static void mdl_load_fatal_corrupt( mdl_context *mdl )
 {
@@ -54,12 +57,18 @@ static void mdl_load_array_file_buffer( mdl_context *mdl, mdl_array *arr,
       {
          vg_warn( "Applying alignment fixup to array @%p [%u -> %u] x %u\n", 
                   buffer, arr->item_size, stride, arr->item_count );
-         if( stride < arr->item_size )
-            vg_fatal_error( "not safe\n" );
+
+         if( stride > arr->item_size )
+            memset( buffer, 0, stride*arr->item_count );
+
+         u32 read_size = VG_MIN( stride, arr->item_size );
 
          for( u32 i=0; i<arr->item_count; i++ )
          {
-            u64 l = fread( buffer+i*stride, arr->item_size, 1, mdl->file );
+            u64 l = fread( buffer+i*stride, read_size, 1, mdl->file );
+            if( stride < arr->item_size )
+               fseek( mdl->file, arr->item_size-stride, SEEK_CUR );
+
             if( l != 1 ) mdl_load_fatal_corrupt( mdl );
          }
       }
@@ -69,12 +78,6 @@ static void mdl_load_array_file_buffer( mdl_context *mdl, mdl_array *arr,
 static void mdl_load_array_file( mdl_context *mdl, mdl_array_ptr *ptr, 
                                  mdl_array *arr, void *lin_alloc, u32 stride )
 {
-   if( stride < arr->item_size )
-   {
-      vg_error( "Structure max: %u. Got: %u\n", stride, arr->item_size );
-      vg_fatal_error( "not safe\n" );
-   }
-
    if( arr->item_count )
    {
       u32 size = stride*arr->item_count;
@@ -149,12 +152,13 @@ int mdl_load_metadata_block( mdl_context *mdl, void *lin_alloc )
    success &= _mdl_load_array( mdl, &mdl->strings, "strings", lin_alloc, 1 );
    success &= MDL_LOAD_ARRAY( mdl, &mdl->meshs,     mdl_mesh,     lin_alloc );
    success &= MDL_LOAD_ARRAY( mdl, &mdl->submeshs,  mdl_submesh,  lin_alloc );
-   success &= MDL_LOAD_ARRAY( mdl, &mdl->materials, mdl_material, lin_alloc );
    success &= MDL_LOAD_ARRAY( mdl, &mdl->textures,  mdl_texture,  lin_alloc );
    success &= MDL_LOAD_ARRAY( mdl, &mdl->armatures, mdl_armature, lin_alloc );
    success &= MDL_LOAD_ARRAY( mdl, &mdl->bones,     mdl_bone,     lin_alloc );
    success &= MDL_LOAD_ARRAY( mdl, &mdl->animations,mdl_animation,lin_alloc );
 
+   success &= mdl_load_materials( mdl, lin_alloc );
+
    return success;
 }
 
@@ -163,6 +167,172 @@ int mdl_load_animation_block( mdl_context *mdl, void *lin_alloc )
    return MDL_LOAD_ARRAY( mdl, &mdl->keyframes, mdl_keyframe, lin_alloc );
 }
 
+void *mdl_shader_standard( vg_msg *msg, void *alloc )
+{
+   struct shader_props_standard *props = 
+      vg_linear_alloc( alloc, sizeof(struct shader_props_standard) );
+
+   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse,
+                     NULL );
+
+   return props;
+}
+
+void *mdl_shader_terrain( vg_msg *msg, void *alloc )
+{
+   struct shader_props_terrain *props = 
+      vg_linear_alloc( alloc, sizeof(struct shader_props_terrain) );
+
+   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse,
+                     NULL );
+   vg_msg_getkvvecf( msg, "sand_colour", k_vg_msg_v4f, 
+                     props->sand_colour, (v4f){ 0.79, 0.63, 0.48, 1.0 } );
+   vg_msg_getkvvecf( msg, "blend_offset", k_vg_msg_v2f,
+                     props->blend_offset, (v2f){ 0.5, 0.0 } );
+
+   return props;
+}
+
+void *mdl_shader_vertex_blend( vg_msg *msg, void *alloc )
+{
+   struct shader_props_vertex_blend *props = 
+      vg_linear_alloc( alloc, sizeof(struct shader_props_vertex_blend) );
+
+   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse,
+                     NULL );
+   vg_msg_getkvvecf( msg, "blend_offset", k_vg_msg_v2f,
+                     props->blend_offset, (v2f){ 0.5, 0.0 } );
+   return props;
+}
+
+void *mdl_shader_water( vg_msg *msg, void *alloc )
+{
+   struct shader_props_water *props = 
+      vg_linear_alloc( alloc, sizeof(struct shader_props_water) );
+
+   vg_msg_getkvvecf( msg, "shore_colour", k_vg_msg_v4f,
+                     props->shore_colour, (v4f){0.03,0.32,0.61,1.0} );
+   vg_msg_getkvvecf( msg, "deep_colour", k_vg_msg_v4f,
+                     props->deep_colour, (v4f){0.0,0.006,0.03,1.0} );
+   vg_msg_getkvintg( msg, "fog_scale", k_vg_msg_f32, &props->fog_scale,
+                     (f32[]){0.04} );
+   vg_msg_getkvintg( msg, "fresnel", k_vg_msg_f32, &props->fresnel,
+                     (f32[]){5.0} );
+   vg_msg_getkvintg( msg, "water_scale", k_vg_msg_f32, &props->water_sale,
+                     (f32[]){ 0.008 } );
+   vg_msg_getkvvecf( msg, "wave_speed", k_vg_msg_v4f,
+                     props->wave_speed, (v4f){0.008,0.006,0.003,0.03} );
+   return props;
+}
+
+void *mdl_shader_cubemapped( vg_msg *msg, void *alloc )
+{
+   struct shader_props_cubemapped *props = 
+      vg_linear_alloc( alloc, sizeof(struct shader_props_cubemapped) );
+
+   vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse,
+                     NULL );
+   vg_msg_getkvintg( msg, "cubemap_entity", k_vg_msg_u32, 
+                     &props->cubemap_entity, NULL );
+   vg_msg_getkvvecf( msg, "tint", k_vg_msg_v4f,
+                     props->tint, (v4f){1.0,1.0,1.0,1.0} );
+   return props;
+}
+
+bool _mdl_legacy_v105_properties( struct mdl_material_v105 *mat, vg_msg *dst )
+{
+   vg_msg_wkvnum( dst, "tex_diffuse", k_vg_msg_u32, 1, &mat->tex_diffuse );
+
+   if( mat->shader == k_shader_cubemap )
+   {
+      vg_msg_wkvnum( dst, "cubemap", k_vg_msg_u32, 1, &mat->tex_none0 );
+      vg_msg_wkvnum( dst, "tint", k_vg_msg_f32, 4, mat->colour );
+   }
+   else if( mat->shader == k_shader_terrain_blend )
+   {
+      vg_msg_wkvnum( dst, "sand_colour", k_vg_msg_f32, 4, mat->colour );
+      vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 );
+   }
+   else if( mat->shader == k_shader_standard_vertex_blend )
+   {
+      vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 );
+   }
+   else if( mat->shader == k_shader_water )
+   {
+      vg_msg_wkvnum( dst, "shore_colour", k_vg_msg_f32, 4, mat->colour );
+      vg_msg_wkvnum( dst, "deep_colour", k_vg_msg_f32, 4, mat->colour1 );
+   }
+
+   return 1;
+}
+
+int mdl_load_materials( mdl_context *mdl, void *lin_alloc )
+{
+   MDL_LOAD_ARRAY( mdl, &mdl->materials, mdl_material, lin_alloc );
+
+#if (MDL_VERSION_MIN <= 105)
+   /* load legacy material data into scratch */
+   mdl_array_ptr legacy_materials;
+   if( mdl->info.version <= 105 )
+   {
+      _mdl_load_array( mdl, &legacy_materials, "mdl_material", vg_mem.scratch,
+                       sizeof(struct mdl_material_v105) );
+   }
+#endif
+
+   mdl_array_ptr data;
+   _mdl_load_array( mdl, &data, "shader_data", vg_mem.scratch, 1 );
+
+   for( u32 i=0; i<mdl_arrcount(&mdl->materials); i ++ )
+   {
+      mdl_material *mat = mdl_arritm( &mdl->materials, i );
+      vg_msg msg;
+
+#if (MDL_VERSION_MIN <= 105)
+      u8 legacy_buf[512];
+      if( mdl->info.version <= 105 )
+      {
+         vg_msg_init( &msg, legacy_buf, sizeof(legacy_buf) );
+         _mdl_legacy_v105_properties( mdl_arritm( &legacy_materials,i ), &msg );
+         vg_msg_init( &msg, legacy_buf, msg.cur.co );
+      }
+      else
+#endif
+      {
+         vg_msg_init( &msg, data.data + mat->props.kvs.offset, 
+                      mat->props.kvs.size );
+      }
+
+      if( mat->shader == k_shader_standard || 
+          mat->shader == k_shader_standard_cutout || 
+          mat->shader == k_shader_foliage ||
+          mat->shader == k_shader_fxglow )
+      {
+         mat->props.compiled = mdl_shader_standard( &msg, lin_alloc );
+      }
+      else if( mat->shader == k_shader_standard_vertex_blend )
+      {
+         mat->props.compiled = mdl_shader_vertex_blend( &msg, lin_alloc );
+      }
+      else if( mat->shader == k_shader_cubemap )
+      {
+         mat->props.compiled = mdl_shader_cubemapped( &msg, lin_alloc );
+      }
+      else if( mat->shader == k_shader_terrain_blend )
+      {
+         mat->props.compiled = mdl_shader_terrain( &msg, lin_alloc );
+      }
+      else if( mat->shader == k_shader_water )
+      {
+         mat->props.compiled = mdl_shader_water( &msg, lin_alloc );
+      }
+      else
+         mat->props.compiled = NULL;
+   }
+
+   return 1;
+}
+
 /*
  * if calling mdl_open, and the file does not exist, the game will fatal quit
  */