X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=model.c;h=19f45f2d0466c8d3c55e1aca8160595b6e242431;hb=refs%2Fheads%2Fmaster;hp=b8bacf280eac9863a5e5c8fcec4d240887196fde;hpb=93790b71d3a89724255dc73239e38c08ad4bbac7;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/model.c b/model.c deleted file mode 100644 index b8bacf2..0000000 --- a/model.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved - */ - -#pragma once - -#include "vg/vg_io.h" -#include "vg/vg_async.h" -#include "vg/vg_tex.h" -#include "vg/vg_msg.h" -#include "vg/vg_string.h" -#include -#include -#include -#include "model.h" -#include "render.h" - -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 - */ - -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, u32 stride ) -{ - if( arr->item_count ) - { - fseek( mdl->file, arr->file_offset, SEEK_SET ); - - if( stride == arr->item_size ) - { - u64 l = fread( buffer, arr->item_size*arr->item_count, 1, mdl->file ); - if( l != 1 ) mdl_load_fatal_corrupt( mdl ); - } - else - { - vg_warn( "Applying alignment fixup to array @%p [%u -> %u] x %u\n", - buffer, arr->item_size, stride, arr->item_count ); - - if( stride > arr->item_size ) - memset( buffer, 0, stride*arr->item_count ); - - u32 read_size = VG_MIN( stride, arr->item_size ); - - for( u32 i=0; iitem_count; i++ ) - { - u64 l = fread( buffer+i*stride, read_size, 1, mdl->file ); - if( stride < arr->item_size ) - fseek( mdl->file, arr->item_size-stride, SEEK_CUR ); - - 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, u32 stride ) -{ - if( arr->item_count ) - { - u32 size = stride*arr->item_count; - ptr->data = vg_linear_alloc( lin_alloc, vg_align8(size) ); - mdl_load_array_file_buffer( mdl, arr, ptr->data, stride ); - } - else - { - ptr->data = NULL; - } - - ptr->stride = stride; - ptr->count = arr->item_count; -} - -void *mdl_arritm( mdl_array_ptr *arr, u32 index ) -{ - return ((u8 *)arr->data) + index*arr->stride; -} - -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; -} - -int _mdl_load_array( mdl_context *mdl, mdl_array_ptr *ptr, - const char *name, void *lin_alloc, u32 stride ) -{ - mdl_array *arr = mdl_find_array( mdl, name ); - - if( arr ) - { - mdl_load_array_file( mdl, ptr, arr, lin_alloc, stride ); - return 1; - } - else - { - ptr->data = NULL; - ptr->count = 0; - ptr->stride = 0; - return 0; - } -} - -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; -} - -int mdl_load_metadata_block( mdl_context *mdl, void *lin_alloc ) -{ - int success = 1; - - success &= _mdl_load_array( mdl, &mdl->strings, "strings", lin_alloc, 1 ); - 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->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 ); - - success &= mdl_load_materials( mdl, lin_alloc ); - - return success; -} - -int mdl_load_animation_block( mdl_context *mdl, void *lin_alloc ) -{ - return MDL_LOAD_ARRAY( mdl, &mdl->keyframes, mdl_keyframe, lin_alloc ); -} - -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 ); - - 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) ); - - 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 } ); - - return props; -} - -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 } ); - 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} ); - return props; -} - -void *mdl_shader_cubemapped( vg_msg *msg, void *alloc ) -{ - 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} ); - return props; -} - -bool _mdl_legacy_v105_properties( struct mdl_material_v105 *mat, vg_msg *dst ) -{ - vg_msg_wkvnum( dst, "tex_diffuse", k_vg_msg_u32, 1, &mat->tex_diffuse ); - - if( mat->shader == k_shader_cubemap ) - { - vg_msg_wkvnum( dst, "cubemap", k_vg_msg_u32, 1, &mat->tex_none0 ); - vg_msg_wkvnum( dst, "tint", k_vg_msg_f32, 4, mat->colour ); - } - else if( mat->shader == k_shader_terrain_blend ) - { - vg_msg_wkvnum( dst, "sand_colour", k_vg_msg_f32, 4, mat->colour ); - vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 ); - } - else if( mat->shader == k_shader_standard_vertex_blend ) - { - vg_msg_wkvnum( dst, "blend_offset", k_vg_msg_f32, 2, mat->colour1 ); - } - else if( mat->shader == k_shader_water ) - { - vg_msg_wkvnum( dst, "shore_colour", k_vg_msg_f32, 4, mat->colour ); - vg_msg_wkvnum( dst, "deep_colour", k_vg_msg_f32, 4, mat->colour1 ); - } - - return 1; -} - -int mdl_load_materials( mdl_context *mdl, void *lin_alloc ) -{ - MDL_LOAD_ARRAY( mdl, &mdl->materials, mdl_material, lin_alloc ); - -#if (MDL_VERSION_MIN <= 105) - /* load legacy material data into scratch */ - mdl_array_ptr legacy_materials; - if( mdl->info.version <= 105 ) - { - _mdl_load_array( mdl, &legacy_materials, "mdl_material", vg_mem.scratch, - sizeof(struct mdl_material_v105) ); - } -#endif - - mdl_array_ptr data; - _mdl_load_array( mdl, &data, "shader_data", vg_mem.scratch, 1 ); - - for( u32 i=0; imaterials); i ++ ) - { - mdl_material *mat = mdl_arritm( &mdl->materials, i ); - vg_msg msg; - -#if (MDL_VERSION_MIN <= 105) - u8 legacy_buf[512]; - if( mdl->info.version <= 105 ) - { - vg_msg_init( &msg, legacy_buf, sizeof(legacy_buf) ); - _mdl_legacy_v105_properties( mdl_arritm( &legacy_materials,i ), &msg ); - vg_msg_init( &msg, legacy_buf, msg.cur.co ); - } - else -#endif - { - vg_msg_init( &msg, data.data + mat->props.kvs.offset, - mat->props.kvs.size ); - } - - if( mat->shader == k_shader_standard || - mat->shader == k_shader_standard_cutout || - mat->shader == k_shader_foliage || - mat->shader == k_shader_fxglow ) - { - mat->props.compiled = mdl_shader_standard( &msg, lin_alloc ); - } - else if( mat->shader == k_shader_standard_vertex_blend ) - { - mat->props.compiled = mdl_shader_vertex_blend( &msg, lin_alloc ); - } - else if( mat->shader == k_shader_cubemap ) - { - mat->props.compiled = mdl_shader_cubemapped( &msg, lin_alloc ); - } - else if( mat->shader == k_shader_terrain_blend ) - { - mat->props.compiled = mdl_shader_terrain( &msg, lin_alloc ); - } - else if( mat->shader == k_shader_water ) - { - mat->props.compiled = mdl_shader_water( &msg, lin_alloc ); - } - else - mat->props.compiled = NULL; - } - - return 1; -} - -/* - * if calling mdl_open, and the file does not exist, the game will fatal quit - */ -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, - sizeof(mdl_array) ); - - 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 - */ -void mdl_close( mdl_context *mdl ) -{ - fclose( mdl->file ); - mdl->file = NULL; -} - -/* useful things you can do with the model */ - -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] ); -} - -const char *mdl_pstr( mdl_context *mdl, u32 pstr ) -{ - return ((char *)mdl_arritm( &mdl->strings, pstr )) + 4; -} - - -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; -} - -/* - * Simple mesh interface for OpenGL - * ---------------------------------------------------------------------------- - */ - -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 ); - 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; -} - -void mesh_bind( glmesh *mesh ) -{ - glBindVertexArray( mesh->vao ); -} - -void mesh_drawn( u32 start, u32 count ) -{ - glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_INT, - (void *)(start*sizeof(u32)) ); -} - -void mesh_draw( glmesh *mesh ) -{ - mesh_drawn( 0, mesh->indice_count ); -} - -void mesh_free( glmesh *mesh ) -{ - if( mesh->loaded ) - { - glDeleteVertexArrays( 1, &mesh->vao ); - glDeleteBuffers( 1, &mesh->ebo ); - glDeleteBuffers( 1, &mesh->vbo ); - mesh->loaded = 0; - } -} - -void mdl_draw_submesh( mdl_submesh *sm ) -{ - mesh_drawn( sm->indice_start, sm->indice_count ); -} - -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 _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 ); -} - -void mdl_async_load_glmesh( mdl_context *mdl, glmesh *mesh, u32 *fixup_table ) -{ - 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(sizeof(mdl_vert)*arr_vertices->item_count), - size_indices = vg_align8(sizeof(mdl_indice)*arr_indices->item_count), - 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, sizeof(mdl_vert) ); - mdl_load_array_file_buffer( mdl, arr_indices, job->indices, - sizeof(mdl_indice) ); - - if( fixup_table ) - { - for( u32 i=0; ivertex_count; i ++ ) - { - mdl_vert *vert = &job->verts[i]; - - for( u32 j=0; j<4; j++ ) - { - vert->groups[j] = fixup_table[vert->groups[j]]; - } - } - } - - /* - * 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, _sync_mdl_load_glmesh ); - } - else - { - vg_fatal_error( "no vertex/indice data\n" ); - } -} - -/* uploads the glmesh, and textures. everything is saved into the mdl_context */ -void mdl_async_full_load_std( mdl_context *mdl ) -{ - mdl_async_load_glmesh( mdl, &mdl->mesh, NULL ); - - 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 ); - } -}