added models to asset packing, basic vertex loading implemented
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 728 KiB After Width: | Height: | Size: 728 KiB |
|
Before Width: | Height: | Size: 961 KiB After Width: | Height: | Size: 961 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 340 KiB After Width: | Height: | Size: 340 KiB |
|
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 204 KiB |
112
src/assets.c
@ -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::
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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"
|
||||
|
||||
88
src/packer.c
@ -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::
|
||||
|
||||
@ -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::
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||