#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 )
{
{
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 );
}
}
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;
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;
}
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
*/