// ::Assets::Constants::Start:: const u32 M3D_FILE = CreateMagicValue('3', 'D', 'M', 'O'); const u32 M3D_PREVIEW = CreateMagicValue('P', 'R', 'V', 'W'); const u32 M3D_HEAD = CreateMagicValue('H', 'E', 'A', 'D'); const u32 M3D_END_CHUNK = CreateMagicValue('O', 'M', 'D', '3'); const u32 M3D_ASSET = CreateMagicValue('A', 'S', 'E', 'T'); const u32 M3D_ACTION = CreateMagicValue('A', 'C', 'T', 'N'); const u32 M3D_COL_MAP = CreateMagicValue('C', 'M', 'A', 'P'); const u32 M3D_TEX_MAP = CreateMagicValue('T', 'M', 'A', 'P'); const u32 M3D_VERT = CreateMagicValue('V', 'R', 'T', 'S'); const u32 M3D_BONE = CreateMagicValue('B', 'O', 'N', 'E'); const u32 M3D_MAT = CreateMagicValue('M', 'T', 'R', 'L'); const u32 M3D_PROCEDURAL = CreateMagicValue('P', 'R', 'O', 'C'); const u32 M3D_MESH = CreateMagicValue('M', 'E', 'S', 'H'); const u32 M3D_VOXEL_TYPE = CreateMagicValue('V', 'O', 'X', 'T'); const u32 M3D_VOXEL_DATA = CreateMagicValue('V', 'O', 'X', 'D'); const u32 M3D_SHAPE = CreateMagicValue('S', 'H', 'P', 'E'); const u32 M3D_LABEL = CreateMagicValue('L', 'B', 'L', 'S'); // ::Assets::Constants::Start:: // ::Assets::Globals::Start:: u8 ASSET_PACK[] = { #embed "../assets.sgp" }; static FileHeader File_Header = {0}; static AssetFile Texture_Assets[TEXTURE_ASSET_MAX]; static Asset Texture_Asset_Lookup[TEXTURE_ASSET_MAX]; static AssetFile Shader_Assets[SHADER_ASSET_MAX]; static Asset Shader_Asset_Lookup[SHADER_ASSET_MAX]; static AssetFile Model_Assets[MODEL_ASSET_MAX]; static Asset Model_Asset_Lookup[MODEL_ASSET_MAX]; // TODO(MA): Implement async asset handling static u32 Shader_Asset_Ref_Count[SHADER_ASSET_MAX]; static u32 Texture_Asset_Ref_Count[TEXTURE_ASSET_MAX]; static u32 Model_Asset_Ref_Count[MODEL_ASSET_MAX]; static b32 ASSET_HEADER_LOADED = false; // ::Assets::Global::End:: // ::Assets::Init::Functions::Start:: static void apInit() { MemCpy(&File_Header, ASSET_PACK, sizeof(FileHeader)); Assert(File_Header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic value is incorrect"); MemCpy(Texture_Assets, &ASSET_PACK[File_Header.asset_offsets[TEXTURE_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[TEXTURE_ASSET]); MemCpy(Shader_Assets, &ASSET_PACK[File_Header.asset_offsets[SHADER_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[SHADER_ASSET]); MemCpy(Model_Assets, &ASSET_PACK[File_Header.asset_offsets[MODEL_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[MODEL_ASSET]); ASSET_HEADER_LOADED = true; } // ::Assets::Init::Functions::End:: // ::Assets::Loading::Functions::Start:: static Asset apLoadTexture(TextureAsset asset_id) { if (!ASSET_HEADER_LOADED) { apInit(); } Assert(asset_id < i32(TEXTURE_ASSET_MAX), "LoadTextureAsset failure: asset_id is higher than TEXTURE_ASSET_MAX"); Asset asset = Texture_Asset_Lookup[asset_id]; if (asset.bytes == NULL) { AssetFile *asset_info = Texture_Assets + asset_id; u8 *img = FLMemAlloc(asset_info->len); MemCpy(img, &ASSET_PACK[asset_info->data_offset], asset_info->len); asset.bytes = img; asset.len = asset_info->len; Texture_Asset_Lookup[asset_id] = asset; } return asset; } static Asset apLoadShader(ShaderAsset asset_id) { if (!ASSET_HEADER_LOADED) { apInit(); } Assert(asset_id < SHADER_ASSET_MAX, "LoadShaderAsset failure: asset_id is higher than SHADER_ASSET_MAX"); Asset asset = Shader_Asset_Lookup[asset_id]; if (asset.bytes == NULL) { AssetFile *asset_info = Shader_Assets + asset_id; asset.bytes = FLMemAlloc(asset_info->len); MemCpy(asset.bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len); asset.len = asset_info->len; Shader_Asset_Lookup[asset_id] = asset; } return asset; } static Asset apLoadModel(ModelAsset asset_id) { if (!ASSET_HEADER_LOADED) { apInit(); } Assert(asset_id < MODEL_ASSET_MAX, "apLoadModel failure: asset_id is higher than MODEL_ASSET_MAX"); Asset asset = Model_Asset_Lookup[asset_id]; if (asset.bytes == NULL) { AssetFile *asset_info = Model_Assets + asset_id; asset.bytes = FLMemAlloc(asset_info->len); MemCpy(asset.bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len); asset.len = asset_info->len; Model_Asset_Lookup[asset_id] = asset; } return asset; } static TextureAssetMeta apGetTextureMeta(TextureAsset asset_id) { AssetFile *asset_file = Texture_Assets + asset_id; return asset_file->texture_meta; } static void apUnloadTexture(TextureAsset asset_id) { Asset *asset = Texture_Asset_Lookup + asset_id; if (asset->bytes != NULL) { FLMemFree(asset->bytes); asset->bytes = NULL; asset->len = 0; } } static void apUnloadShader(ShaderAsset asset_id) { Asset *asset = Shader_Asset_Lookup + asset_id; if (asset->bytes != NULL) { FLMemFree(asset->bytes); asset->bytes = NULL; asset->len = 0; } } static void apUnloadModel(ModelAsset asset_id) { Asset *asset = Model_Asset_Lookup + asset_id; if (asset->bytes != NULL) { FLMemFree(asset->bytes); asset->bytes = NULL; asset->len = 0; } } // ::Assets::Loading::Functions::End:: // ::Assets::Models::Functions::Start:: static inline b32 apChkMag(u32 *magic, u32 expected) { return *magic == expected; } // TODO: parse this without the SDK static m3dModel *apParseModel(rawptr data) { m3d_t *m3d = m3d_load(data, NULL, NULL, NULL); m3dModel *model = FLMemAlloc(sizeof(m3dModel)); model->v_count = u64(m3d->numvertex); model->vertices = FLMemAlloc(sizeof(Vertex) * model->v_count); for (u64 i = 0; i < m3d->numvertex; i += 1) { model->vertices[i].pos.x = m3d->vertex[i].x; model->vertices[i].pos.y = m3d->vertex[i].y; model->vertices[i].pos.z = m3d->vertex[i].z; model->vertices[i].pos.w = m3d->vertex[i].w; model->vertices[i].col.r = 0.0f; model->vertices[i].col.g = 1.0f; model->vertices[i].col.b = 0.0f; model->vertices[i].col.a = 0.0f; } model->i_count = u64(m3d->numface * 3); model->indices = FLMemAlloc(sizeof(u32) * model->i_count); for (u64 i = 0; i < m3d->numface; i += 1) { model->indices[i] = m3d->face[i].vertex[0]; model->indices[i+1] = m3d->face[i].vertex[1]; model->indices[i+2] = m3d->face[i].vertex[2]; } m3d_free(m3d); return model; } // ::Assets::Models::Functions::End::