added models to asset packing, basic vertex loading implemented

This commit is contained in:
Matthew 2025-05-23 08:20:39 +10:00
parent 60ca4c06ae
commit b642955c8d
16 changed files with 223 additions and 8 deletions

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 728 KiB

After

Width:  |  Height:  |  Size: 728 KiB

View File

Before

Width:  |  Height:  |  Size: 961 KiB

After

Width:  |  Height:  |  Size: 961 KiB

View File

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 340 KiB

After

Width:  |  Height:  |  Size: 340 KiB

View File

Before

Width:  |  Height:  |  Size: 204 KiB

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -1,3 +1,27 @@
// ::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::
@ -14,9 +38,13 @@ 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;
@ -37,6 +65,8 @@ static void apInit()
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;
}
@ -95,6 +125,29 @@ static Asset apLoadShader(ShaderAsset asset_id)
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;
@ -123,4 +176,63 @@ static void apUnloadShader(ShaderAsset asset_id)
}
}
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::

View File

@ -59,6 +59,9 @@ typedef enum SoundAssetTag_e : u32
typedef enum ModelAsset_e : u32
{
MODEL_YODA,
MODEL_BLOCK_CHAR,
MODEL_ASSET_MAX,
} ModelAsset;
@ -123,12 +126,18 @@ static void apInit();
static Asset apLoadTexture(TextureAsset asset_id);
static Asset apLoadShader(ShaderAsset asset_id);
static Asset apLoadModel(ModelAsset asset_id);
static TextureAssetMeta apGetTextureMeta(TextureAsset asset_id);
static void apUnloadTexture(TextureAsset asset_id);
static void apUnloadShader(ShaderAsset asset_id);
static void apUnloadModel(ModelAsset asset_id);
// ::Assets::Util::Functions::Header::
// TODO(MA): Implement async asset handling
static inline b32 apMarkUnloaded(AssetType type, u32 index);
static inline void apMarkLoaded(AssetType type, u32 index);
// ::Assets::Models::Functions::Header::
static m3dModel *apParseModel(rawptr data);

View File

@ -24,7 +24,6 @@
#include "stb/stb_image.h"
#include "xxhash/xxhash.h"
#include "fastlz/fastlz.h"
#include "m3d/m3d.h"
#include "renderer.h"
#include "game.h"

View File

@ -42,8 +42,14 @@ const FileMapping g_Texture_File_Map[] = {
{ .file_name = "hog.jpg", .ix = HOG },
};
const FileMapping g_Model_File_Map[] = {
{ .file_name = "yoda.m3d", .ix = MODEL_YODA },
{ .file_name = "test_char.m3d", .ix = MODEL_BLOCK_CHAR },
};
c8 *g_Shader_File_Names[SHADER_ASSET_MAX] = {0};
c8 *g_Texture_File_Names[TEXTURE_ASSET_MAX] = {0};
c8 *g_Model_File_Names[MODEL_ASSET_MAX] = {0};
// ::Packer::Globals::End::
@ -74,6 +80,17 @@ void SetArrayLookups()
{
Assert(g_Texture_File_Names[i] != NULL, "Texture file name is null");
}
for (i32 i = 0; i < Len(g_Model_File_Map); i++)
{
FileMapping file_mapping = g_Model_File_Map[i];
g_Model_File_Names[file_mapping.ix] = file_mapping.file_name;
}
for (int i = 0; i < MODEL_ASSET_MAX; i++)
{
Assert(g_Model_File_Names[i] != NULL, "Model file name is null");
}
}
i32 WriteHeader(pFile file, FileHeader *header)
@ -101,14 +118,40 @@ void MoveToShaderDir(c8 **return_dir)
void MoveToTextureDir(c8 **return_dir)
{
if (pDirIsVisible("assets"))
if (pDirIsVisible("textures"))
{
Assert(pDirNavigate("./assets") == 0, "Unable to change to assets directory");
Assert(pDirNavigate("./textures") == 0, "Unable to change to textures directory");
*return_dir = "..";
}
else if (pDirIsVisible("assets"))
{
Assert(pDirNavigate("./assets/textures") == 0, "Unable to change to assets directory");
*return_dir = "../..";
}
else if (pDirIsVisible("shaders"))
{
Assert(pDirNavigate("../assets") == 0, "Unable to change to assets directory");
Assert(pDirNavigate("../assets/textures") == 0, "Unable to change to assets directory");
*return_dir = "../build";
}
else
Assert(false, "Unable to find assets directory");
}
void MoveToModelDir(c8 **return_dir)
{
if (pDirIsVisible("models"))
{
Assert(pDirNavigate("./models") == 0, "Unable to change to models directory");
*return_dir = "..";
}
else if (pDirIsVisible("assets"))
{
Assert(pDirNavigate("./assets/models") == 0, "Unable to change to assets directory");
*return_dir = "../..";
}
else if (pDirIsVisible("shaders"))
{
Assert(pDirNavigate("../assets/models") == 0, "Unable to change to assets directory");
*return_dir = "../build";
}
else
@ -228,7 +271,7 @@ void PackFiles(Arena *arena, FileHeader *header)
}
u64 loaded_length = u64(w * h * ch);
u64 prev_offset = data_offset;
data_offset += pFileWrite(file, data_offset, image_bytes, loaded_length);
@ -245,8 +288,36 @@ void PackFiles(Arena *arena, FileHeader *header)
pFileClose(asset_file);
}
Assert(pDirNavigate(return_dir) == 0, "Unable to return to previous directory");
MoveToModelDir(&return_dir);
AssetFile *model_assets = MakeArray(arena, AssetFile, MODEL_ASSET_MAX);
for (u32 i = 0; i < MODEL_ASSET_MAX; i++)
{
c8 *asset_name = g_Model_File_Names[i];
Printfln("Packing file: %s...", asset_name);
pFile asset_file = pFileOpen(asset_name, pFS_READ);
u64 file_size = pFileLength(asset_file);
u8 *file_data = MakeArray(arena, u8, file_size);
pFileRead(asset_file, 0, file_data, file_size);
u64 prev_offset = data_offset;
data_offset += pFileWrite(file, data_offset, file_data, file_size);
Assert((data_offset - prev_offset) == file_size, "File write size invalid");
model_assets[i].data_offset = prev_offset;
model_assets[i].len = file_size;
pFileClose(asset_file);
}
pFileWrite(file, header->asset_offsets[SHADER_ASSET], shader_assets, sizeof(AssetFile)*SHADER_ASSET_MAX);
pFileWrite(file, header->asset_offsets[TEXTURE_ASSET], texture_assets, sizeof(AssetFile)*TEXTURE_ASSET_MAX);
pFileWrite(file, header->asset_offsets[MODEL_ASSET], model_assets, sizeof(AssetFile)*MODEL_ASSET_MAX);
pDirNavigate(return_dir);
}
@ -262,7 +333,6 @@ static inline void TestAssetIsCorrect(Arena *arena, c8 *file_name, AssetFile *fi
pFile asset_file = pFileOpen(file_name, pFS_READ);
u64 size = pFileLength(asset_file);
u8 *file_data = MakeArray(arena, u8, size);
u64 write_count = pFileRead(asset_file, 0, file_data, size);
Assert(write_count == size, "Incorrect asset size retrieved");
@ -356,6 +426,14 @@ void TestAssetPack(Arena *arena)
{
TestAssetIsCorrect(arena, g_Texture_File_Names[i], &files[TEXTURE_ASSET][i], TEXTURE_ASSET, file);
}
pDirNavigate(return_dir);
MoveToModelDir(&return_dir);
for (u32 i = 0; i < MODEL_ASSET_MAX; i++)
{
TestAssetIsCorrect(arena, g_Model_File_Names[i], &files[MODEL_ASSET][i], MODEL_ASSET, file);
}
}
// ::Packer::Tests::Functions::End::

View File

@ -14,6 +14,8 @@
#define STB_IMAGE_IMPLEMENTATION
#define M3D_IMPLEMENTATION
#include "shared_types.h"
#include "platform/platform.h"
#include "util.h"
@ -26,6 +28,7 @@
#include "stb/stb_image.h"
#include "xxhash/xxhash.h"
#include "fastlz/fastlz.h"
#include "m3d/m3d.h"
#include "renderer.h"
#include "game.h"
@ -53,6 +56,7 @@ i32 WriteHeader(pFile file, FileHeader *header);
void PackFiles(Arena *arena, FileHeader *header);
void MoveToTextureDir(c8 **return_dir);
void MoveToShaderDir(c8 **return_dir);
void MoveToModelDir(c8 **return_dir);
// ::Packer::Tests::Functions::Header::

View File

@ -141,3 +141,16 @@ typedef f64 dMat2[4];
typedef f64 dMat3[9];
typedef f64 dMat4[16];
typedef struct Vertex
{
Vec4 pos;
Vec4 col;
} Vertex;
typedef struct m3dModel
{
Vertex *vertices;
u32 *indices;
u64 v_count;
u64 i_count;
} m3dModel;

View File

@ -465,10 +465,10 @@ VkVertexInputAttributeDescription pbr_input_descriptions[] = {
{ .binding = 1, .location = 1, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(rPBRVertex, col) },
};
VkPipelineVertexInputStateCreationInfo pbr_vertex_input_info = {
VkPipelineVertexInputStateCreateInfo pbr_vertex_input_info = {
.sType = STYPE(PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO),
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &pbr_vertex_bind_desc,
.pVertexBindingDescriptions = &pbr_input_bind_desc,
.vertexAttributeDescriptionCount = Len(pbr_input_descriptions),
.pVertexAttributeDescriptions = pbr_input_descriptions,
};