X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=model.h;h=aade46aa21ddd00c341c552d71669bc20f1fbd00;hb=HEAD;hp=c28455d1faf4689d8cda17b7e7185f9fe24b55fe;hpb=22f62f001f21d1b91fefd9fc495c122d9ddf205a;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/model.h b/model.h deleted file mode 100644 index c28455d..0000000 --- a/model.h +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved - */ - -#ifndef MODEL_H -#define MODEL_H - -#include "skaterift.h" - -#define MDL_VERSION_MIN 101 -#define MDL_VERSION_NR 102 - -enum mdl_shader{ - k_shader_standard = 0, - k_shader_standard_cutout = 1, - k_shader_terrain_blend = 2, - k_shader_standard_vertex_blend = 3, - k_shader_water = 4, - k_shader_invisible = 5, - k_shader_boundary = 6, - k_shader_fxglow = 7, - k_shader_cubemap = 8, - k_shader_override = 30000 -}; - -enum mdl_surface_prop{ - k_surface_prop_concrete = 0, - k_surface_prop_wood = 1, - k_surface_prop_grass = 2, - k_surface_prop_tiles = 3, - k_surface_prop_metal = 4 -}; - -enum material_flag{ - k_material_flag_skate_target = 0x0001, - k_material_flag_collision = 0x0002, - k_material_flag_grow_grass = 0x0004, - k_material_flag_grindable = 0x0008, - k_material_flag_invisible = 0x0010, - k_material_flag_boundary = 0x0020, - k_material_flag_preview_visibile = 0x0040, - k_material_flag_walking = 0x0080, - - k_material_flag_ghosts = - k_material_flag_boundary| - k_material_flag_invisible| - k_material_flag_walking -}; - -#pragma pack(push,1) - -/* 48 byte */ -struct mdl_vert -{ - v3f co, /* 3*32 */ - norm; /* 3*32 */ - v2f uv; /* 2*32 */ - - u8 colour[4]; /* 4*8 */ - u16 weights[4];/* 4*16 */ - u8 groups[4]; /* 4*8 */ -}; - -#pragma pack(pop) - -typedef struct mdl_context mdl_context; -typedef struct mdl_array_ptr mdl_array_ptr; -typedef struct mdl_vert mdl_vert; -typedef struct mdl_transform mdl_transform; -typedef struct mdl_submesh mdl_submesh; -typedef struct mdl_material mdl_material; -typedef struct mdl_bone mdl_bone; -typedef struct mdl_armature mdl_armature; -typedef struct mdl_animation mdl_animation; -typedef struct mdl_transform mdl_keyframe; -typedef struct mdl_mesh mdl_mesh; -typedef struct mdl_file mdl_file; -typedef struct mdl_texture mdl_texture; -typedef struct mdl_array mdl_array; -typedef struct mdl_header mdl_header; - -typedef struct glmesh glmesh; -struct glmesh -{ - GLuint vao, vbo, ebo; - u32 indice_count; - u32 loaded; -}; - -struct mdl_transform -{ - v3f co, s; - v4f q; -}; - -static void transform_identity( mdl_transform *transform ) -{ - v3_zero( transform->co ); - q_identity( transform->q ); - v3_fill( transform->s, 1.0f ); -} - -static void mdl_transform_vector( mdl_transform *transform, v3f vec, v3f dest ) -{ - v3_mul( transform->s, vec, dest ); - q_mulv( transform->q, dest, dest ); -} - -static void mdl_transform_point( mdl_transform *transform, v3f co, v3f dest ) -{ - mdl_transform_vector( transform, co, dest ); - v3_add( transform->co, dest, dest ); -} - -static void mdl_transform_mul( mdl_transform *a, mdl_transform *b, - mdl_transform *d ) -{ - mdl_transform_point( a, b->co, d->co ); - q_mul( a->q, b->q, d->q ); - q_normalize( d->q ); - v3_mul( a->s, b->s, d->s ); -} - -struct mdl_material -{ - u32 pstr_name, - shader, - flags, - surface_prop; - - v4f colour, - colour1; - - u32 tex_diffuse, - tex_none0, - tex_none1; -}; - -struct mdl_bone -{ - v3f co, end; - u32 parent, - collider, - ik_target, - ik_pole, - flags, - pstr_name; - - boxf hitbox; - v3f conevx, conevy, coneva; - float conet; -}; - -enum bone_flag -{ - k_bone_flag_deform = 0x00000001, - k_bone_flag_ik = 0x00000002, - k_bone_flag_cone_constraint = 0x00000004 -}; - -enum bone_collider -{ - k_bone_collider_none = 0, - k_bone_collider_box = 1, - k_bone_collider_capsule = 2 -}; - -struct mdl_armature -{ - mdl_transform transform; - u32 bone_start, - bone_count, - anim_start, - anim_count; -}; - -struct mdl_animation -{ - u32 pstr_name, - length; - float rate; - 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, - entity_id, /* upper 16 bits: type, lower 16 bits: index */ - armature_id; -}; - -struct mdl_file -{ - u32 pstr_path, - pack_offset, - pack_size; -}; - -struct mdl_texture -{ - mdl_file file; - u32 glname; -}; - -struct mdl_array -{ - u32 file_offset, - item_count, - item_size; - - char name[16]; -}; - -struct mdl_header -{ - u32 version; - mdl_array index; -}; - -struct mdl_context{ - FILE *file; - mdl_header info; - - struct mdl_array_ptr{ - void *data; - u32 count, stride; - } - index, - - /* metadata */ - strings, - meshs, - submeshs, - materials, - textures, - armatures, - bones, - animations, - - /* animation buffers */ - keyframes, - - /* mesh buffers */ - verts, - indices; - u32 pack_base_offset; - - /* runtime */ - glmesh mesh; -}; - - -static void mdl_load_fatal_corrupt( mdl_context *mdl ) -{ - fclose( mdl->file ); - vg_file_print_invalid( mdl->file ); - vg_fatal_error( "Corrupt model" ); -} - -/* - * Model implementation - */ - -static u32 mdl_query_array_size( mdl_array *arr ) -{ - if( arr->item_count ){ - u32 size = arr->item_size*arr->item_count; - return vg_align8(size); - } - else return 0; -} - -static const char *mdl_pstr( mdl_context *mdl, u32 pstr ); -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 */ -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( buffer, arr->item_size*arr->item_count, 1, mdl->file ); - - 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 ) -{ - 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; - - ptr->count = arr->item_count; - ptr->stride = arr->item_size; -} - -static void *mdl_arritm( mdl_array_ptr *arr, u32 index ) -{ - return ((u8 *)arr->data) + index*arr->stride; -} - -static u32 mdl_arrcount( mdl_array_ptr *arr ) -{ - return arr->count; -} - -static mdl_array *mdl_find_array( mdl_context *mdl, const char *name ) -{ - for( u32 i=0; iindex); i++ ){ - mdl_array *arr = mdl_arritm( &mdl->index, i ); - - if( !strncmp(arr->name,name,16) ){ - return arr; - } - } - - return NULL; -} - -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; - } -} - -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; -} - -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; -} - -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 - */ -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_MIN ){ - vg_warn( "For model: %s\n", path ); - vg_warn( " version: %u (min: %u, current: %u)\n", - mdl->info.version, MDL_VERSION_MIN, 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 - */ -static void mdl_close( mdl_context *mdl ) -{ - fclose( mdl->file ); - mdl->file = NULL; -} - -/* useful things you can do with the model */ - -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] ); -} - -static const char *mdl_pstr( mdl_context *mdl, u32 pstr ) -{ - return ((char *)mdl_arritm( &mdl->strings, pstr )) + 4; -} - - -static int -mdl_pstreq( mdl_context *mdl, u32 pstr, const char *str, u32 djb2 ) -{ - u32 hash = *((u32 *)mdl_arritm( &mdl->strings, pstr )); - if( hash == djb2 ){ - if( !strcmp( str, mdl_pstr( mdl, pstr ))) return 1; - else return 0; - } - else return 0; -} - -#define MDL_CONST_PSTREQ( MDL, Q, CONSTSTR )\ - mdl_pstreq( MDL, Q, CONSTSTR, vg_strdjb2( CONSTSTR ) ) - -/* - * Simple mesh interface for OpenGL - * ---------------------------------------------------------------------------- - */ - -static void mesh_upload( glmesh *mesh, - mdl_vert *verts, u32 vert_count, - u32 *indices, u32 indice_count ) -{ - //assert( mesh->loaded == 0 ); - - glGenVertexArrays( 1, &mesh->vao ); - glGenBuffers( 1, &mesh->vbo ); - glGenBuffers( 1, &mesh->ebo ); - glBindVertexArray( mesh->vao ); - - size_t stride = sizeof(mdl_vert); - - glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo ); - glBufferData( GL_ARRAY_BUFFER, vert_count*stride, verts, GL_STATIC_DRAW ); - - glBindVertexArray( mesh->vao ); - glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo ); - 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) ); - glEnableVertexAttribArray( 1 ); - - /* 2: 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) ); - glEnableVertexAttribArray( 3 ); - - /* 4: 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) ); - glEnableVertexAttribArray( 5 ); - - VG_CHECK_GL_ERR(); - - mesh->indice_count = indice_count; - mesh->loaded = 1; -} - -static void mesh_bind( glmesh *mesh ) -{ - glBindVertexArray( mesh->vao ); -} - -static void mesh_drawn( u32 start, u32 count ) -{ - glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, - (void *)(start*sizeof(u32)) ); -} - -static void mesh_draw( glmesh *mesh ) -{ - mesh_drawn( 0, mesh->indice_count ); -} - -static void mesh_free( glmesh *mesh ) -{ - if( mesh->loaded ){ - glDeleteVertexArrays( 1, &mesh->vao ); - glDeleteBuffers( 1, &mesh->ebo ); - glDeleteBuffers( 1, &mesh->vbo ); - mesh->loaded = 0; - } -} - -static void mdl_draw_submesh( mdl_submesh *sm ) -{ - mesh_drawn( sm->indice_start, sm->indice_count ); -} - -static mdl_mesh *mdl_find_mesh( mdl_context *mdl, const char *name ) -{ - for( u32 i=0; imeshs ); i++ ){ - mdl_mesh *mesh = mdl_arritm( &mdl->meshs, i ); - if( !strcmp( name, mdl_pstr( mdl, mesh->pstr_name ))){ - return mesh; - } - } - return NULL; -} - -struct payload_glmesh_load{ - mdl_vert *verts; - u32 *indices; - - u32 vertex_count, - indice_count; - - glmesh *mesh; -}; - -static void async_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 ); -} - -/* TODO: Find out if this needs deprecating in favour of the new full loader */ -static void mdl_async_load_glmesh( mdl_context *mdl, glmesh *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; isubmeshs ); i++ ){ - mdl_submesh *sm = mdl_arritm( &mdl->submeshs, i ); - u32 *indices = job->indices + sm->indice_start; - - for( u32 j=0; jindice_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" ); - } -} - -/* uploads the glmesh, and textures. everything is saved into the mdl_context */ -static void mdl_async_full_load_std( mdl_context *mdl ){ - mdl_async_load_glmesh( mdl, &mdl->mesh ); - - for( u32 i=0; itextures ); i ++ ){ - vg_linear_clear( vg_mem.scratch ); - mdl_texture *tex = mdl_arritm( &mdl->textures, i ); - - void *data = vg_linear_alloc( vg_mem.scratch, tex->file.pack_size ); - mdl_fread_pack_file( mdl, &tex->file, data ); - - vg_tex2d_load_qoi_async( data, tex->file.pack_size, - VG_TEX2D_CLAMP|VG_TEX2D_NEAREST, &tex->glname ); - } -} - -#endif