fclose( ctx->fp );
ctx->fp = NULL;
}
+
+/* compiler
+ * ---------------------------------------------------------------------- */
+
+struct af_compiler_iter
+{
+ u32 i, j;
+ af_compiler_index *index;
+ af_compiler_item *current_item;
+ void *data;
+};
+
+static void af_init_iterator( struct af_compiler_iter *iter, af_compiler_index *index )
+{
+ iter->i = 0;
+ iter->j = 0;
+ iter->index = index;
+ iter->current_item = NULL;
+ iter->data = NULL;
+}
+
+static bool af_next( struct af_compiler_iter *iter )
+{
+ if( iter->i == 0 )
+ {
+ if( iter->index->first == NULL )
+ return 0;
+ iter->current_item = iter->index->first;
+ }
+
+ if( iter->j >= iter->current_item->count )
+ {
+ if( iter->current_item->next == NULL )
+ return 0;
+
+ iter->current_item = iter->current_item->next;
+ iter->j = 0;
+ }
+
+ iter->data = iter->current_item->data + (iter->j * iter->index->element_size);
+ iter->j ++;
+ iter->i ++;
+ return 1;
+}
+
+af_compiler_item *af_compiler_allocate_items( af_compiler *compiler, af_compiler_index *index, u32 count )
+{
+ af_compiler_item *entry = vg_linear_alloc( compiler->allocator, sizeof(af_compiler_item) );
+ entry->next = NULL;
+
+ u32 data_size = count * index->element_size;
+ index->element_count += count;
+
+ entry->data = vg_linear_alloc( compiler->allocator, data_size );
+ entry->count = count;
+
+ for( u32 i=0; i<data_size; i ++ )
+ ((u8 *)entry->data)[i] = 0xab;
+
+ if( index->last )
+ index->last->next = entry;
+ index->last = entry;
+
+ if( !index->first )
+ index->first = entry;
+
+ return entry;
+}
+
+static void af_compiler_init_index( af_compiler_index *index, const char *alias, u32 element_size )
+{
+ VG_ASSERT( element_size );
+ vg_strncpy( alias, index->name, sizeof(index->name), k_strncpy_overflow_fatal );
+ index->element_size = element_size;
+ index->element_count = 0;
+ index->first = NULL;
+ index->last = NULL;
+}
+
+af_compiler_index *af_compiler_create_index( af_compiler *compiler, const char *alias, u32 element_size )
+{
+ af_compiler_item *item = af_compiler_allocate_items( compiler, &compiler->index, 1 );
+ af_compiler_index *index = item->data;
+ af_compiler_init_index( index, alias, element_size );
+ return index;
+}
+
+u32 af_compile_string( af_compiler *compiler, const char *string )
+{
+ u32 string_hash = vg_strdjb2( string );
+
+ // TODO: Hash table against existing strings (low priority)
+
+ u32 offset = offset = compiler->strings_index->element_count;
+ u32 bytes = vg_align4( strlen( string )+1 + 4 );
+ af_compiler_item *item = af_compiler_allocate_items( compiler, compiler->strings_index, bytes );
+ *((u32 *)item->data) = string_hash;
+ strcpy( item->data+4, string );
+ return offset;
+}
+
+void af_compiler_init( af_compiler *compiler, void *allocator )
+{
+ compiler->allocator = allocator;
+ af_compiler_init_index( &compiler->index, "index", sizeof(af_compiler_index) );
+ compiler->strings_index = af_compiler_create_index( compiler, "strings", 1 );
+ af_compile_string( compiler, "nul" );
+}
+
+static void af_write_bin( af_compiler *compiler, void *data, u32 data_len, u32 padding )
+{
+ if( data )
+ {
+ fwrite( data, data_len, 1, compiler->fp );
+ compiler->file_offset += data_len;
+ }
+
+ if( padding )
+ {
+ while( compiler->file_offset % padding )
+ {
+ const u8 pad_byte = 0xac;
+ fwrite( &pad_byte, 1, 1, compiler->fp );
+ compiler->file_offset ++;
+ }
+ }
+}
+
+af_compiler_index *af_get_or_make_index( af_compiler *compiler, const char *alias, u32 element_size )
+{
+ struct af_compiler_iter iter;
+ af_init_iterator( &iter, &compiler->index );
+ while( af_next( &iter ) )
+ {
+ af_compiler_index *index = iter.data;
+
+ if( !strcmp( index->name, alias ) )
+ {
+ return index;
+ }
+ }
+
+ return af_compiler_create_index( compiler, alias, element_size );
+}
+
+bool af_write( af_compiler *compiler, const char *path, u32 version )
+{
+ u32 indices_to_write = 0;
+
+ struct af_compiler_iter iter;
+ af_init_iterator( &iter, &compiler->index );
+ while( af_next( &iter ) )
+ {
+ af_compiler_index *index = iter.data;
+
+ if( index->element_count )
+ indices_to_write ++;
+ }
+
+ u32 header_size = vg_align8( sizeof( array_file_header ) );
+ u32 index_size = vg_align8( sizeof( array_file_meta ) * indices_to_write );
+
+ compiler->fp = fopen( path, "wb" );
+ if( !compiler->fp )
+ return 0;
+ compiler->file_offset = 0;
+
+ array_file_header header;
+ header.version = version;
+ header.index.file_offset = header_size;
+ header.index.item_count = indices_to_write;
+ header.index.item_size = sizeof(array_file_meta);
+ strcpy( header.index.name, "index" );
+ af_write_bin( compiler, &header, sizeof(array_file_header), 8 );
+
+ /* write index */
+ u32 file_offset = header_size + index_size;
+ af_init_iterator( &iter, &compiler->index );
+ while( af_next( &iter ) )
+ {
+ af_compiler_index *index = iter.data;
+
+ if( index->element_count )
+ {
+ array_file_meta meta;
+ strcpy( meta.name, index->name );
+ meta.item_count = index->element_count;
+ meta.item_size = index->element_size;
+ meta.file_offset = file_offset;
+
+ file_offset += vg_align8( meta.item_size*meta.item_count );
+ af_write_bin( compiler, &meta, sizeof(array_file_meta), 0 );
+ }
+ }
+ af_write_bin( compiler, NULL, 0, 8 );
+
+
+ af_init_iterator( &iter, &compiler->index );
+ while( af_next( &iter ) )
+ {
+ af_compiler_index *index = iter.data;
+
+ if( index->element_count )
+ {
+ struct af_compiler_iter item_iter;
+ af_init_iterator( &item_iter, index );
+
+ while( af_next( &item_iter ) )
+ af_write_bin( compiler, item_iter.data, index->element_size, 0 );
+
+ af_write_bin( compiler, NULL, 0, 8 );
+ }
+ }
+
+ fclose( compiler->fp );
+ return 1;
+}
mdl_context *mdl = &_board_maker.template_mdl;
mdl_open( mdl, mdl_path, _board_maker.template_heap );
mdl_load_metadata_block( mdl, _board_maker.template_heap );
+
+ /* we need this for compiling it back down */
+ mdl_load_mesh_block( mdl, _board_maker.template_heap );
+ AF_LOAD_ARRAY_STRUCT( &mdl->af, &_board_maker.template_mdl_markers, ent_marker, _board_maker.template_heap );
+
mdl_async_full_load_std( mdl, NULL );
mdl_close( mdl );
vg_async_call( _async_board_maker_init_finish, NULL, 0 );
}
+static void _board_maker_export(void)
+{
+ mdl_compiler compiler;
+ mdl_compiler_init( &compiler );
+
+ qoi_desc desc = {
+ .width = 512,
+ .height = 512,
+ .channels = 3,
+ .colorspace = QOI_SRGB
+ };
+
+ void *raw_data = malloc( 512*512*3 ),
+ *qoi_data = malloc( vg_query_qoi_storage_size( &desc ) );
+
+ vg_framebuffer_bind( &_board_maker.compositor_fb, 1.0f );
+ glReadBuffer( GL_COLOR_ATTACHMENT0 );
+ glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, raw_data );
+
+ i32 qoi_len;
+ if( !vg_encode_qoi2( raw_data, &desc, qoi_data, &qoi_len ) )
+ {
+ free( raw_data );
+ free( qoi_data );
+ return;
+ }
+
+ u32 onetex = mdl_compiler_compile_texture_qoi( &compiler, "Maker Tex", qoi_data, qoi_len );
+
+ free( raw_data );
+ free( qoi_data );
+
+ u8 shader_buf[ 512 ];
+ vg_msg shader_kvs;
+ vg_msg_init( &shader_kvs, shader_buf, sizeof(shader_buf) );
+ vg_msg_wkvnum( &shader_kvs, "tex_diffuse", k_vg_msg_u32, 1, &onetex );
+
+ u32 onemat = mdl_compiler_start_material( &compiler, "Maker Mat" );
+ mdl_compiler_push_shaderdata( &compiler, k_shader_standard, &shader_kvs );
+
+ for( u32 i=0; i<_board_maker.template_mdl.mesh_count; i ++ )
+ {
+ mdl_mesh *ref_mesh = &_board_maker.template_mdl.meshes[i];
+ if( mdl_entity_id_type( ref_mesh->entity_id ) != k_ent_marker )
+ continue;
+
+ mdl_submesh *ref_submesh = &_board_maker.template_mdl.submeshes[ ref_mesh->submesh_start ];
+
+ u32 ref_marker_index = mdl_entity_id_id( ref_mesh->entity_id );
+ ent_marker *ref_marker = af_arritm( &_board_maker.template_mdl_markers, ref_marker_index );
+ const char *ref_marker_alias = af_str( &_board_maker.template_mdl.af, ref_marker->pstr_alias );
+
+ ent_marker copy_marker = *ref_marker;
+ copy_marker.pstr_alias = af_compile_string( &compiler.af, ref_marker_alias );
+
+ u32 new_marker_id = mdl_compiler_push_entity( &compiler, k_ent_marker,
+ "ent_marker", ©_marker, sizeof(ent_marker) );
+ mdl_compiler_start_mesh( &compiler, "<board_maker>", new_marker_id, 0 );
+ mdl_compiler_start_submesh( &compiler, onemat, 0 );
+ mdl_compiler_push_meshdata( &compiler, _board_maker.template_mdl.verts + ref_submesh->vertex_start,
+ ref_submesh->vertex_count,
+ _board_maker.template_mdl.indices + ref_submesh->indice_start,
+ ref_submesh->indice_count );
+ }
+
+ af_write( &compiler.af, "/tmp/hello.mdl", MDL_VERSION_NR );
+ mdl_compiler_free( &compiler );
+}
+
/* update loop */
void _board_maker_pre_update(void)
{
_board_maker.state = k_board_maker_state_loading_image;
}
}
+ else if( _board_maker.state == k_board_maker_state_export )
+ {
+ _board_maker_export();
+ _board_maker.state = k_board_maker_state_none;
+ }
}
//vg_camera temp;
q_axis_angle( qy, (v3f){0,1,0}, vg.time*0.2f );
q_mul( qx, qy, qq );
q_normalize( qq );
- q_m3x3( qq, root_mmdl );
+ q_m3x3( qq, root_mmdl );
v3_copy( _board_maker.origin, root_mmdl[3] );
if( quit_me )
{
- if( world_clear_event( k_world_event_board_maker ) )
- _board_maker_close();
+ _board_maker.state = k_board_maker_state_export;
+
+ //if( world_clear_event( k_world_event_board_maker ) )
+ // _board_maker_close();
}
}
/*
- * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ * Copyright (C) 2021-2025 Mt.ZERO Software, Harry Godden - All Rights Reserved
*/
#pragma once
vg_fatal_exit();
}
- fseek( mdl->af.fp, mdl->pack_base_offset+info->pack_offset, SEEK_SET );
+ fseek( mdl->af.fp, mdl->pack_base_offset + info->pack_offset, SEEK_SET );
u64 l = fread( dst, info->pack_size, 1, mdl->af.fp );
if( l != 1 )
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 );
+ 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) );
-
+ 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 } );
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 } );
+ 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} );
+ 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;
}
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} );
+ 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;
}
array_file_ptr legacy_materials;
if( mdl->version <= 105 )
{
- af_load_array( &mdl->af, &legacy_materials, "mdl_material",
- vg_mem.scratch, sizeof(struct mdl_material_v105) );
+ af_load_array( &mdl->af, &legacy_materials, "mdl_material", vg_mem.scratch, sizeof(struct mdl_material_v105) );
}
#endif
mdl->version = mdl->af.header.version;
array_file_meta *pack = af_find_array( &mdl->af, "pack" );
- if( pack ) mdl->pack_base_offset = pack->file_offset;
- else mdl->pack_base_offset = 0;
+ if( pack )
+ mdl->pack_base_offset = pack->file_offset;
+ else
+ mdl->pack_base_offset = 0;
}
/*
*/
#ifdef VG_3D
-static void mesh_upload( glmesh *mesh,
- mdl_vert *verts, u32 vert_count,
- u32 *indices, u32 indice_count )
+static void mesh_upload( glmesh *mesh, mdl_vert *verts, u32 vert_count, u32 *indices, u32 indice_count )
{
glGenVertexArrays( 1, &mesh->vao );
glGenBuffers( 1, &mesh->vbo );
glBindVertexArray( mesh->vao );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
- glBufferData( GL_ELEMENT_ARRAY_BUFFER, indice_count*sizeof(u32),
- indices, GL_STATIC_DRAW );
+ glBufferData( GL_ELEMENT_ARRAY_BUFFER, indice_count*sizeof(u32), indices, GL_STATIC_DRAW );
/* 0: coordinates */
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
glEnableVertexAttribArray( 0 );
/* 1: normal */
- glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE,
- stride, (void *)offsetof(mdl_vert, norm) );
+ glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, stride, (void *)offsetof(mdl_vert, norm) );
glEnableVertexAttribArray( 1 );
/* 2: uv */
- glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE,
- stride, (void *)offsetof(mdl_vert, uv) );
+ glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, stride, (void *)offsetof(mdl_vert, uv) );
glEnableVertexAttribArray( 2 );
/* 3: colour */
- glVertexAttribPointer( 3, 4, GL_UNSIGNED_BYTE, GL_TRUE,
- stride, (void *)offsetof(mdl_vert, colour) );
+ glVertexAttribPointer( 3, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (void *)offsetof(mdl_vert, colour) );
glEnableVertexAttribArray( 3 );
/* 4: weights */
- glVertexAttribPointer( 4, 4, GL_UNSIGNED_SHORT, GL_TRUE,
- stride, (void *)offsetof(mdl_vert, weights) );
+ glVertexAttribPointer( 4, 4, GL_UNSIGNED_SHORT, GL_TRUE, stride, (void *)offsetof(mdl_vert, weights) );
glEnableVertexAttribArray( 4 );
/* 5: groups */
- glVertexAttribIPointer( 5, 4, GL_UNSIGNED_BYTE,
- stride, (void *)offsetof(mdl_vert, groups) );
+ glVertexAttribIPointer( 5, 4, GL_UNSIGNED_BYTE, stride, (void *)offsetof(mdl_vert, groups) );
glEnableVertexAttribArray( 5 );
mesh->indice_count = indice_count;
void mesh_drawn( u32 start, u32 count )
{
- glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT,
- (void *)(start*sizeof(u32)) );
+ glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(start*sizeof(u32)) );
}
void mesh_draw( glmesh *mesh )
static void _sync_mdl_load_glmesh( void *payload, u32 size )
{
struct payload_glmesh_load *job = payload;
- mesh_upload( job->mesh, job->verts, job->vertex_count,
- job->indices, job->indice_count );
+ mesh_upload( job->mesh, job->verts, job->vertex_count, job->indices, job->indice_count );
}
void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table )
job->vertex_count = arr_vertices->item_count;
job->indice_count = arr_indices->item_count;
- af_load_array_file_buffer( &mdl->af, arr_vertices,
- job->verts, sizeof(mdl_vert) );
- af_load_array_file_buffer( &mdl->af, arr_indices, job->indices,
- sizeof(mdl_indice) );
+ af_load_array_file_buffer( &mdl->af, arr_vertices, job->verts, sizeof(mdl_vert) );
+ af_load_array_file_buffer( &mdl->af, arr_indices, job->indices, sizeof(mdl_indice) );
if( fixup_table )
{
}
#endif
+
+void mdl_compiler_init( mdl_compiler *compiler )
+{
+ af_compiler_init( &compiler->af, _vg_create_linear_allocator( NULL, 10*1024*1024, VG_MEMORY_SYSTEM, "MDL Compile" ) );
+ compiler->meshes = af_compiler_create_index( &compiler->af, "mdl_mesh", sizeof(mdl_mesh) );
+ compiler->submeshes = af_compiler_create_index( &compiler->af, "mdl_submesh", sizeof(mdl_submesh) );
+ compiler->vertices = af_compiler_create_index( &compiler->af, "mdl_vert", sizeof(mdl_vert) );
+ compiler->indices = af_compiler_create_index( &compiler->af, "mdl_indice", sizeof(u32) );
+ compiler->bones = af_compiler_create_index( &compiler->af, "mdl_bone", sizeof(mdl_bone) );
+ compiler->materials = af_compiler_create_index( &compiler->af, "mdl_material", sizeof(mdl_material) );
+ compiler->shader_data = af_compiler_create_index( &compiler->af, "shader_data", 1 );
+ compiler->armatures = af_compiler_create_index( &compiler->af, "mdl_armature", sizeof(mdl_armature) );
+ compiler->textures = af_compiler_create_index( &compiler->af, "mdl_texture", sizeof(mdl_texture) );
+ compiler->pack_data = af_compiler_create_index( &compiler->af, "pack", 1 );
+}
+
+u32 mdl_compiler_push_entity( mdl_compiler *compiler, u32 entity_type, const char *entity_type_string,
+ void *data, u32 data_size )
+{
+ af_compiler_index *index = af_get_or_make_index( &compiler->af, entity_type_string, data_size );
+
+ u32 index_part = index->element_count,
+ id = (entity_type & 0xfffff)<<16 | (index_part & 0xfffff); //TODO
+
+ af_compiler_item *item = af_compiler_allocate_items( &compiler->af, index, 1 );
+ memcpy( item->data, data, data_size );
+ return id;
+}
+
+void mdl_compiler_start_mesh( mdl_compiler *compiler, const char *name, u32 associated_entity, u32 associated_armature )
+{
+ mdl_mesh *mesh = af_compiler_allocate_items( &compiler->af, compiler->meshes, 1 )->data;
+ transform_identity( &mesh->transform );
+ mesh->submesh_start = compiler->submeshes->element_count;
+ mesh->submesh_count = 0;
+ mesh->pstr_name = af_compile_string( &compiler->af, name );
+ mesh->entity_id = associated_entity;
+ mesh->armature_id = associated_armature;
+}
+
+void mdl_compiler_start_submesh( mdl_compiler *compiler, u32 material_id, u32 flags )
+{
+ mdl_mesh *current_mesh = compiler->meshes->last->data;
+ current_mesh->submesh_count ++;
+
+ mdl_submesh *sm = af_compiler_allocate_items( &compiler->af, compiler->submeshes, 1 )->data;
+ sm->indice_start = compiler->indices->element_count;
+ sm->vertex_start = compiler->vertices->element_count;
+ sm->indice_count = 0;
+ sm->vertex_count = 0;
+ sm->material_id = material_id;
+ sm->flags = flags;
+ box_init_inf( sm->bbx );
+}
+
+void mdl_compiler_push_meshdata( mdl_compiler *compiler, mdl_vert *vertex_buffer, u32 vertex_count,
+ u32 *indice_buffer, u32 indice_count )
+{
+ mdl_submesh *current_submesh = compiler->submeshes->last->data;
+ current_submesh->vertex_count += vertex_count;
+ current_submesh->indice_count += indice_count;
+
+ mdl_vert *dest_verts = af_compiler_allocate_items( &compiler->af, compiler->vertices, vertex_count )->data;
+ u32 *dest_indices = af_compiler_allocate_items( &compiler->af, compiler->indices, indice_count )->data;
+
+ for( u32 i=0; i<vertex_count; i ++ )
+ box_addpt( current_submesh->bbx, vertex_buffer[i].co );
+
+ memcpy( dest_verts, vertex_buffer, vertex_count * sizeof(mdl_vert) );
+ memcpy( dest_indices, indice_buffer, indice_count * sizeof(u32) );
+}
+
+static void mdl_compiler_pack_data( mdl_compiler *compiler, const char *path, void *data,
+ u32 data_length, mdl_file *out_file )
+{
+ out_file->pstr_path = af_compile_string( &compiler->af, path );
+ out_file->pack_offset = compiler->pack_data->element_count;
+ out_file->pack_size = data_length;
+
+ void *dest = af_compiler_allocate_items( &compiler->af, compiler->pack_data, vg_align16(data_length) )->data;
+ memcpy( dest, data, data_length );
+}
+
+u32 mdl_compiler_start_material( mdl_compiler *compiler, const char *name )
+{
+ u32 material_id = compiler->materials->element_count + 1;
+
+ mdl_material *material = af_compiler_allocate_items( &compiler->af, compiler->materials, 1 )->data;
+ material->pstr_name = af_compile_string( &compiler->af, name );
+ material->shader = 0;
+ material->flags = 0;
+ material->surface_prop = 0;
+ material->props.kvs.offset = 0;
+ material->props.kvs.size = 0;
+
+ return material_id;
+}
+
+void mdl_compiler_set_surface_info( mdl_compiler *compiler, u32 flags, u32 surface_prop )
+{
+ mdl_material *current_material = compiler->materials->last->data;
+ current_material->flags = flags;
+ current_material->surface_prop = surface_prop;
+}
+
+u32 mdl_compiler_compile_texture_qoi( mdl_compiler *compiler, const char *name, void *data, u32 data_len )
+{
+ u32 texture_id = compiler->textures->element_count + 1;
+
+ mdl_texture *texture = af_compiler_allocate_items( &compiler->af, compiler->textures, 1 )->data;
+ texture->glname = 0;
+ mdl_compiler_pack_data( compiler, name, data, data_len, &texture->file );
+ return texture_id;
+}
+
+void mdl_compiler_push_shaderdata( mdl_compiler *compiler, u32 shader_id, vg_msg *shader_kvs )
+{
+ mdl_material *current_material = compiler->materials->last->data;
+ current_material->shader = shader_id;
+ current_material->props.kvs.offset = compiler->shader_data->element_count;
+ current_material->props.kvs.size = shader_kvs->cur.co;
+
+ void *dest = af_compiler_allocate_items( &compiler->af, compiler->shader_data, vg_align8(shader_kvs->cur.co) )->data;
+ memcpy( dest, shader_kvs->buf, shader_kvs->cur.co );
+}
+
+void mdl_compiler_free( mdl_compiler *compiler )
+{
+ vg_allocator_free( compiler->af.allocator );
+}