+ ptr->count = arr->item_count;
+ ptr->stride = arr->item_size;
+}
+
+VG_STATIC void *mdl_arritm( mdl_array_ptr *arr, u32 index )
+{
+ return ((u8 *)arr->data) + index*arr->stride;
+}
+
+VG_STATIC u32 mdl_arrcount( mdl_array_ptr *arr )
+{
+ return arr->count;
+}
+
+VG_STATIC mdl_array *mdl_find_array( mdl_context *mdl, const char *name )
+{
+ for( u32 i=0; i<mdl_arrcount(&mdl->index); i++ ){
+ mdl_array *arr = mdl_arritm( &mdl->index, i );
+
+ if( !strncmp(arr->name,name,16) ){
+ return arr;
+ }
+ }
+
+ return NULL;
+}
+
+VG_STATIC int mdl_load_array( mdl_context *mdl, mdl_array_ptr *ptr,
+ const char *name, void *lin_alloc )
+{
+ mdl_array *arr = mdl_find_array( mdl, name );
+
+ if( arr ){
+ mdl_load_array_file( mdl, ptr, arr, lin_alloc );
+ return 1;
+ }
+ else{
+ ptr->data = NULL;
+ ptr->count = 0;
+ ptr->stride = 0;
+ return 0;
+ }
+}
+
+VG_STATIC int mdl_load_mesh_block( mdl_context *mdl, void *lin_alloc )
+{
+ int success = 1;
+
+ success &= mdl_load_array( mdl, &mdl->verts, "mdl_vert", lin_alloc );
+ success &= mdl_load_array( mdl, &mdl->indices, "mdl_indice", lin_alloc );
+
+ return success;
+}
+
+VG_STATIC int mdl_load_metadata_block( mdl_context *mdl, void *lin_alloc )
+{
+ int success = 1;
+
+ success &= mdl_load_array( mdl, &mdl->strings, "strings", lin_alloc );
+ 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 );
+
+ return success;
+}
+
+VG_STATIC int mdl_load_animation_block( mdl_context *mdl, void *lin_alloc )
+{
+ return mdl_load_array( mdl, &mdl->keyframes, "mdl_keyframe", lin_alloc );
+}
+
+/*
+ * if calling mdl_open, and the file does not exist, the game will fatal quit
+ */
+VG_STATIC void mdl_open( mdl_context *mdl, const char *path, void *lin_alloc )
+{
+ memset( mdl, 0, sizeof( mdl_context ) );
+ mdl->file = fopen( path, "rb" );
+
+ if( !mdl->file ){
+ vg_error( "mdl_open('%s'): %s\n", path, strerror(errno) );
+ vg_fatal_error( "see above for details" );
+ }
+
+ u64 l = fread( &mdl->info, sizeof(mdl_header), 1, mdl->file );
+ if( l != 1 )
+ mdl_load_fatal_corrupt( mdl );
+
+ if( mdl->info.version != MDL_VERSION_NR ){
+ vg_warn( "For model: %s\n", path );
+ vg_warn( " version: %u (current: %u)\n", mdl->info.version,
+ MDL_VERSION_NR );
+
+ vg_fatal_error( "Legacy model version incompatable" );
+ }
+
+ mdl_load_array_file( mdl, &mdl->index, &mdl->info.index, lin_alloc );
+
+ mdl_array *pack = mdl_find_array( mdl, "pack" );
+ if( pack ) mdl->pack_base_offset = pack->file_offset;
+ else mdl->pack_base_offset = 0;
+}
+
+/*
+ * close file handle
+ */
+VG_STATIC void mdl_close( mdl_context *mdl )
+{
+ fclose( mdl->file );
+ mdl->file = NULL;
+}
+
+/* useful things you can do with the model */
+
+VG_STATIC void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx )
+{
+ q_m3x3( transform->q, mtx );
+ v3_muls( mtx[0], transform->s[0], mtx[0] );
+ v3_muls( mtx[1], transform->s[1], mtx[1] );
+ v3_muls( mtx[2], transform->s[2], mtx[2] );
+ v3_copy( transform->co, mtx[3] );
+}
+
+VG_STATIC const char *mdl_pstr( mdl_context *mdl, u32 pstr )
+{
+ return mdl_arritm( &mdl->strings, pstr );
+}