- i64 size;
- mdl_header *header = vg_asset_read_s( path, &size );
-
- /*
- * Check file is valid
- */
- if( !header )
- {
- vg_error( "Could not open '%s'\n", path );
- return NULL;
- }
-
- if( size < sizeof(mdl_header) )
- {
- vg_free( header );
- vg_error( "Invalid file '%s' (too small for header)\n", path );
- return NULL;
- }
-
- if( header->file_length != size )
- {
- vg_error( "Invalid file '%s'"
- "(wrong .file_length, %ub != real file size %ub)\n",
- path, header->file_length, size );
- vg_free( header );
- return NULL;
- }
-
- /*
- * Validate offsets and memory sections, to ensure all arrays are in-bounds,
- * and that they do not overlap.
- */
-
- struct memregion
- {
- const char *desc;
- u32 count, max_count, size, offset;
- }
- regions[] = {
- {
- "Vertices",
- header->vertex_count, MDL_VERT_MAX,
- sizeof(mdl_vert), header->vertex_offset
- },
- {
- "Indices",
- header->indice_count, MDL_INDICE_MAX,
- sizeof(u32), header->indice_offset
- },
- {
- "Submesh",
- header->submesh_count, MDL_SUBMESH_MAX,
- sizeof(mdl_submesh), header->submesh_offset
- },
- {
- "Materials",
- header->material_count, MDL_MATERIAL_MAX,
- sizeof(mdl_material), header->material_offset
- },
- {
- "Nodes",
- header->node_count, MDL_NODE_MAX,
- sizeof(mdl_node), header->node_count
- }
- };
-
- for( int i=0; i<vg_list_size(regions); i++ )
- {
- struct memregion *ri = ®ions[i];
-
- if( ri->count == 0 )
- continue;
-
- if( ri->count > ri->max_count )
- {
- vg_free( header );
- vg_error( "'%s': '%s' buffer exceeds the maximum (%u/%u)\n",
- path, ri->desc, ri->count, ri->max_count );
- return NULL;
- }
-
- if( ri->offset >= header->file_length )
- {
- vg_free( header );
- vg_error( "'%s': '%s' buffer offset is out of range\n",
- path, ri->desc );
- return NULL;
- }
-
- if( ri->offset + ri->size*ri->count > header->file_length )
- {
- vg_free( header );
- vg_error( "'%s': '%s' buffer size is out of range\n",
- path, ri->desc );
- return NULL;
- }
-
- for( int j=0; j<vg_list_size(regions); j++ )
- {
- struct memregion *rj = ®ions[j];
- if( rj->count == 0 )
- continue;
-
- if( ri->offset >= rj->offset &&
- (ri->offset+ri->size*ri->count < rj->offset+rj->size*rj->count))
- {
- vg_free( header );
- vg_error( "'%s': '%s' buffer overlaps '%s'\n",
- path, ri->desc, rj->desc );
- return NULL;
- }
- }
- }
-
- /*
- * Pointer validation TODO(workshop)
- */
-
- /*
- * strings TODO(workshop)
- */
-
- return header;
-}
-
-static void *mdl_baseptr( mdl_header *mdl, u32 offset )
-{
- return (void *)mdl + offset;
-}
-
-static const char *mdl_pstr( mdl_header *mdl, u32 pstr )
-{
- return (const char *)(mdl_baseptr( mdl, mdl->strings_offset )) + pstr;
-}
-
-static mdl_node *mdl_node_from_id( mdl_header *mdl, u32 id )
-{
- return ((mdl_node *)mdl_baseptr( mdl, mdl->node_offset )) + id;
-}
-
-static mdl_node *mdl_node_from_name( mdl_header *mdl, const char *name )
-{
- for( int i=0; i<mdl->node_count; i++ )
- {
- mdl_node *pnode = mdl_node_from_id( mdl, i );
-
- if( !strcmp( name, mdl_pstr( mdl, pnode->pstr_name )) )
- return pnode;
- }
-
- return NULL;
-}
-
-static mdl_submesh *mdl_submesh_from_id( mdl_header *mdl, u32 id )
-{
- if( id >= mdl->submesh_count )
- return NULL;
-
- return ((mdl_submesh *)mdl_baseptr( mdl, mdl->submesh_offset )) + id;
-}
-
-static mdl_submesh *mdl_node_submesh( mdl_header *mdl, mdl_node *node, u32 i )
-{
- if( i >= node->submesh_count )
- return NULL;
-
- return mdl_submesh_from_id( mdl, node->submesh_start+i );
-}
-
-static u32 *mdl_submesh_indices( mdl_header *mdl, mdl_submesh *sm )
-{
- return ((u32 *)mdl_baseptr( mdl, mdl->indice_offset )) + sm->indice_start;
-}
-
-static mdl_vert *mdl_submesh_vertices( mdl_header *mdl, mdl_submesh *sm )
-{
- return ((mdl_vert *)mdl_baseptr(mdl,mdl->vertex_offset)) + sm->vertex_start;
-}
-
-static mdl_material *mdl_material_from_id( mdl_header *mdl, u32 id )
-{
- return ((mdl_material *)mdl_baseptr(mdl,mdl->material_offset)) + id;
-}
-
-static mdl_animation *mdl_animation_from_id( mdl_header *mdl, u32 id )
-{
- return ((mdl_animation *)mdl_baseptr(mdl,mdl->anim_offset)) + id;
-}
-
-static void mdl_node_transform( mdl_node *pnode, m4x3f transform )
-{
- q_m3x3( pnode->q, transform );
- v3_muls( transform[0], pnode->s[0], transform[0] );
- v3_muls( transform[1], pnode->s[1], transform[1] );
- v3_muls( transform[2], pnode->s[2], transform[2] );
- v3_copy( pnode->co, transform[3] );