chaos caused by async
[carveJwlIkooP6JGAAIwe30JlM.git] / model.h
diff --git a/model.h b/model.h
index b7e0e96e6f43a512cb52e5282f767ce699ef2d65..8f90d128ad0a9637edb7a2624eed66ee1c2cc35b 100644 (file)
--- a/model.h
+++ b/model.h
@@ -7,6 +7,7 @@
 
 #include "common.h"
 
+#define MDL_VERSION_NR 100
 
 enum mdl_shader
 {
@@ -14,7 +15,9 @@ enum mdl_shader
    k_shader_standard_cutout         = 1,
    k_shader_terrain_blend           = 2,
    k_shader_standard_vertex_blend   = 3,
-   k_shader_water                   = 4
+   k_shader_water                   = 4,
+   k_shader_invisible               = 5,
+   k_shader_boundary                = 6
 };
 
 enum mdl_surface_prop
@@ -28,10 +31,12 @@ enum mdl_surface_prop
 
 enum material_flag
 {
-   k_material_flag_skate_surface    = 0x1,
-   k_material_flag_collision        = 0x2,
-   k_material_flag_grow_grass       = 0x4,
-   k_material_flag_grind_surface    = 0x8
+   k_material_flag_skate_target     = 0x00000001,
+   k_material_flag_collision        = 0x00000002,
+   k_material_flag_grow_grass       = 0x00000004,
+   k_material_flag_grindable        = 0x00000008,
+   k_material_flag_invisible        = 0x00000010,
+   k_material_flag_boundary         = 0x00000020
 };
 
 #pragma pack(push,1)
@@ -72,17 +77,6 @@ struct mdl_transform
    v4f q;
 };
 
-struct mdl_submesh
-{
-   u32 indice_start,
-       indice_count,
-       vertex_start,
-       vertex_count;
-
-   boxf bbx;
-   u32 material_id;
-};
-
 struct mdl_material
 {
    u32 pstr_name,
@@ -115,9 +109,9 @@ struct mdl_bone
 
 enum bone_flag
 {
-   k_bone_flag_deform               = 0x1,
-   k_bone_flag_ik                   = 0x2,
-   k_bone_flag_cone_constraint      = 0x4
+   k_bone_flag_deform               = 0x00000001,
+   k_bone_flag_ik                   = 0x00000002,
+   k_bone_flag_cone_constraint      = 0x00000004
 };
 
 enum bone_collider
@@ -144,13 +138,30 @@ struct mdl_animation
    u32 offset;
 };
 
+struct mdl_submesh
+{
+   u32 indice_start,
+       indice_count,
+       vertex_start,
+       vertex_count;
+
+   boxf bbx;
+   u16 material_id, flags;
+};
+
+enum esubmesh_flags
+{
+   k_submesh_flag_none     = 0x0000,
+   k_submesh_flag_consumed = 0x0001
+};
+
 struct mdl_mesh
 {
    mdl_transform transform;
    u32 submesh_start,
        submesh_count,
        pstr_name,
-       flags,
+       entity_id,    /* upper 16 bits: type, lower 16 bits: index */
        armature_id;
 };
 
@@ -164,7 +175,7 @@ struct mdl_file
 struct mdl_texture
 {
    mdl_file file;
-   u32 type;
+   u32 glname;
 };
 
 struct mdl_array
@@ -209,10 +220,12 @@ struct mdl_context
 
    /* mesh buffers */
    verts,
-   indices,
+   indices;
+
+   u32 pack_base_offset;
    
    /* pack data */
-   pack;
+   //pack;
 };
 
 
@@ -220,26 +233,61 @@ VG_STATIC void mdl_load_fatal_corrupt( mdl_context *mdl )
 {
    fclose( mdl->file );
    vg_file_print_invalid( mdl->file );
-   vg_fatal_exit_loop( "Corrupt model" );
+   vg_fatal_error( "Corrupt model" );
 }
 
 /*
  * Model implementation
  */
 
-VG_STATIC void mdl_load_array_file( mdl_context *mdl, mdl_array_ptr *ptr,
-                                    mdl_array *arr, void *lin_alloc )
+VG_STATIC u32 mdl_query_array_size( mdl_array *arr )
 {
    if( arr->item_count ){
       u32 size = arr->item_size*arr->item_count;
-      ptr->data = vg_linear_alloc( lin_alloc, vg_align8(size) );
+      return vg_align8(size);
+   }
+   else
+      return 0;
+}
 
+VG_STATIC const char *mdl_pstr( mdl_context *mdl, u32 pstr );
+VG_STATIC 
+void mdl_fread_pack_file( mdl_context *mdl, mdl_file *info, void *dst )
+{
+   if( !info->pack_size ){
+      vg_warn( "path: %s\n", mdl_pstr( mdl, info->pstr_path ) );
+      vg_fatal_error( "Packed file is only a header; it is not packed" );
+   }
+
+   fseek( mdl->file, mdl->pack_base_offset+info->pack_offset, SEEK_SET );
+   u64 l = fread( dst, info->pack_size, 1, mdl->file );
+
+   if( l != 1 )
+      mdl_load_fatal_corrupt( mdl );
+}
+
+/* TODO: Rename these */
+VG_STATIC 
+void mdl_load_array_file_buffer( mdl_context *mdl, mdl_array *arr, 
+                                 void *buffer )
+{
+   if( arr->item_count ){
       fseek( mdl->file, arr->file_offset, SEEK_SET );
-      u64 l = fread( ptr->data, arr->item_size*arr->item_count, 1, mdl->file );
+      u64 l = fread( buffer, arr->item_size*arr->item_count, 1, mdl->file );
 
       if( l != 1 )
          mdl_load_fatal_corrupt( mdl );
    }
+}
+
+VG_STATIC void mdl_load_array_file( mdl_context *mdl, mdl_array_ptr *ptr,
+                                    mdl_array *arr, void *lin_alloc )
+{
+   if( arr->item_count ){
+      u32 size = arr->item_size*arr->item_count;
+      ptr->data = vg_linear_alloc( lin_alloc, vg_align8(size) );
+      mdl_load_array_file_buffer( mdl, arr, ptr->data );
+   }
    else
       ptr->data = NULL;
 
@@ -257,22 +305,34 @@ VG_STATIC u32 mdl_arrcount( mdl_array_ptr *arr )
    return arr->count;
 }
 
-VG_STATIC int mdl_load_array( mdl_context *mdl, mdl_array_ptr *ptr,
-                              const char *name, void *lin_alloc )
+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) ){
-         mdl_load_array_file( mdl, ptr, arr, lin_alloc );
-         return 1;
+         return arr;
       }
    }
 
-   ptr->data = NULL;
-   ptr->count = 0;
-   ptr->stride = 0;
-   return 0;
+   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 )
@@ -306,11 +366,6 @@ VG_STATIC int mdl_load_animation_block( mdl_context *mdl, void *lin_alloc )
    return mdl_load_array( mdl, &mdl->keyframes, "mdl_keyframe", lin_alloc );
 }
 
-VG_STATIC int mdl_load_pack_block( mdl_context *mdl, void *lin_alloc )
-{
-   return mdl_load_array( mdl, &mdl->pack, "pack", lin_alloc );
-}
-
 /*
  * if calling mdl_open, and the file does not exist, the game will fatal quit
  */
@@ -321,14 +376,26 @@ VG_STATIC void mdl_open( mdl_context *mdl, const char *path, void *lin_alloc )
 
    if( !mdl->file ){
       vg_error( "mdl_open('%s'): %s\n", path, strerror(errno) );
-      vg_fatal_exit_loop( "see above for details" );
+      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;
 }
 
 /*
@@ -456,38 +523,90 @@ VG_STATIC void mdl_draw_submesh( mdl_submesh *sm )
    mesh_drawn( sm->indice_start, sm->indice_count );
 }
 
-/* WARNING: Destructive! Only use this once and then discard the context. */
-VG_STATIC void mdl_unpack_glmesh( mdl_context *mdl, glmesh *mesh )
+VG_STATIC mdl_mesh *mdl_find_mesh( mdl_context *mdl, const char *name )
 {
-   if( !mdl->submeshs.count )
-      vg_fatal_exit_loop( "Tried to unpack empty model file" );
+   for( u32 i=0; i<mdl_arrcount( &mdl->meshs ); i++ ){
+      mdl_mesh *mesh = mdl_arritm( &mdl->meshs, i );
+      if( !strcmp( name, mdl_pstr( mdl, mesh->pstr_name ))){
+         return mesh;
+      }
+   }
+   return NULL;
+}
 
-   mdl_submesh *sm = mdl_arritm( &mdl->submeshs, 0 );
-   u32 offset = sm->vertex_count;
+struct payload_glmesh_load{
+   mdl_vert *verts;
+   u32 *indices;
 
-   for( u32 i=1; i<mdl_arrcount( &mdl->submeshs ); i++ ){
-      mdl_submesh *sm = mdl_arritm( &mdl->submeshs, i );
-      u32 *indices    = mdl_arritm( &mdl->indices, sm->indice_start );
+   u32 vertex_count,
+       indice_count;
 
-      for( u32 j=0; j<sm->indice_count; j++ )
-         indices[j] += offset;
+   glmesh *mesh;
+};
 
-      offset += sm->vertex_count;
-   }
+VG_STATIC void async_mdl_load_glmesh( void *payload, u32 size )
+{
+   struct payload_glmesh_load *job = payload;
 
-   mesh_upload( mesh, mdl->verts.data, mdl->verts.count,
-                      mdl->indices.data, mdl->indices.count );
+   mesh_upload( job->mesh, job->verts, job->vertex_count,
+                           job->indices, job->indice_count );
 }
 
-VG_STATIC mdl_mesh *mdl_find_mesh( mdl_context *mdl, const char *name )
+VG_STATIC void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh )
 {
-   for( u32 i=0; i<mdl_arrcount( &mdl->meshs ); i++ ){
-      mdl_mesh *mesh = mdl_arritm( &mdl->meshs, i );
-      if( !strcmp( name, mdl_pstr( mdl, mesh->pstr_name ))){
-         return mesh;
+   mdl_array *arr_vertices = mdl_find_array( mdl, "mdl_vert" );
+   mdl_array *arr_indices = mdl_find_array( mdl, "mdl_indice" );
+
+   if( arr_vertices && arr_indices ){
+      u32 size_verts   = vg_align8(mdl_query_array_size( arr_vertices )),
+          size_indices = vg_align8(mdl_query_array_size( arr_indices )),
+          size_hdr     = vg_align8(sizeof(struct payload_glmesh_load)),
+          total        = size_hdr + size_verts + size_indices;
+
+      vg_async_item *call = vg_async_alloc( total );
+      struct payload_glmesh_load *job = call->payload;
+
+      u8 *payload = call->payload;
+
+      job->mesh = mesh;
+      job->verts = (void*)(payload + size_hdr);
+      job->indices = (void*)(payload + size_hdr + size_verts);
+      job->vertex_count = arr_vertices->item_count;
+      job->indice_count = arr_indices->item_count;
+
+      mdl_load_array_file_buffer( mdl, arr_vertices, job->verts );
+      mdl_load_array_file_buffer( mdl, arr_indices, job->indices );
+
+      /*
+       * Unpack the indices (if there are meshes)
+       * ---------------------------------------------------------
+       */
+
+      if( mdl_arrcount( &mdl->submeshs ) ){
+         mdl_submesh *sm = mdl_arritm( &mdl->submeshs, 0 );
+         u32 offset = sm->vertex_count;
+
+         for( u32 i=1; i<mdl_arrcount( &mdl->submeshs ); i++ ){
+            mdl_submesh *sm = mdl_arritm( &mdl->submeshs, i );
+            u32 *indices    = job->indices + sm->indice_start;
+
+            for( u32 j=0; j<sm->indice_count; j++ )
+               indices[j] += offset;
+
+            offset += sm->vertex_count;
+         }
       }
+
+      /* 
+       * Dispatch 
+       * -------------------------
+       */
+
+      vg_async_dispatch( call, async_mdl_load_glmesh );
+   }
+   else{
+      vg_fatal_error( "no vertex/indice data\n" );
    }
-   return NULL;
 }
  
 #endif