changes before deleting code

This commit is contained in:
Matthew 2025-11-14 08:53:24 +11:00
parent 9bc34ca4b9
commit 70e3c135cf
3 changed files with 315 additions and 298 deletions

173
assets.d
View File

@ -17,47 +17,33 @@ AssetInfo[] Asset_Info;
u8[][] Asset_Data; u8[][] Asset_Data;
__gshared u8[] DEFAULT_TEXTURE = GenerateDefaultTexture(32, 32);
const u32 FILE_VERSION = 3; const u32 FILE_VERSION = 3;
const u32 MODEL_VERSION = 2; const u32 MODEL_VERSION = 2;
// TODO:
// Alignment?
/************************* /*************************
****** FILE PACKER ****** ****** FILE PACKER ******
*************************/ *************************/
struct FileHeader struct FileHeader
{
u32 magic;
u32 file_version;
u64 asset_count;
u64 asset_info_offset;
DirHeader base_dir;
}
struct DirHeader
{ {
u32 magic; u32 magic;
u32 file_version; u64 hash;
u64 dir_count;
u64 asset_count; u64 asset_count;
u64 asset_info_offset;
}
struct ModelHeader
{
u32 magic;
u32 model_version;
u64 vertex_count;
u64 vertex_offset;
u64 index_count;
u64 index_offset;
u64 material_count;
u64 material_offset;
}
struct PackedMaterial
{
StringID name;
Vec3[MatColor.max] colors;
StringHeader[MatMap.max] maps;
}
struct PackedModel
{
StringID name;
PackedMaterial[] mats;
Vertex[] vtx;
u32[] idx;
string[] strs;
} }
/************************* /*************************
@ -100,11 +86,11 @@ struct MeshPart
u64 length; u64 length;
} }
struct ModelData struct Model
{ {
string name; string name;
Mesh[] meshes; Mesh[] meshes;
MaterialData[] mats; Material[] mats;
} }
struct MaterialMap struct MaterialMap
@ -121,22 +107,18 @@ struct Material
Vec4 params; Vec4 params;
} }
struct MaterialData
{
string name;
Vec3[MatColor.max] colors;
string[MatMap.max] maps;
f32[MatFloat.max] props = 0.0;
IllumModel illum;
}
struct StringHeader struct StringHeader
{ {
u32 id; u32 id;
u32 length; u32 length;
} }
struct AssetData
{
AssetType type;
u8[] data;
}
/************************ /************************
*** ASSET STRUCTURES *** *** ASSET STRUCTURES ***
************************/ ************************/
@ -247,6 +229,24 @@ debug
return f.rawRead(mem); return f.rawRead(mem);
} }
extern (C) cgltf_result
GLTFLoadCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, const(char)* path, cgltf_size* size, void** data)
{
u8[] file_data = OpenFile(ConvToStr(path[0 .. strlen(path)]));
if(file_data == null) return cgltf_result_io_error;
*size = cast(cgltf_size)file_data.length;
*data = Alloc!(u8)(file_data).ptr;
return cgltf_result_success;
}
extern (C) void
GLTFFreeCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, void* data, cgltf_size size)
{
Free(data[0 .. size]);
}
} }
else else
{ {
@ -384,18 +384,85 @@ else
} }
} }
PackedModel static u8[]
Convert(Arena* arena, ModelData* md) GenerateDefaultTexture(u64 x, u64 y)
{ {
PackedModel packed = { u64 tex_size = x*y*4;
name: 0, u8[] placeholder_tex = new u8[tex_size];
strs: Alloc!(string)(arena, 1+md.mats.length),
};
packed.strs[0] = Alloc(arena, md.name); u8[4] magenta = [255, 0, 255, 255];
u8[4] black = [0, 0, 0, 255];
u64 half = tex_size/2;
for(u64 i = 0; i < tex_size; i += 32)
{
bool swap = i <= half;
for(u64 j = 0; j < 16; j += 4)
{
placeholder_tex[i+j .. i+j+4] = !swap ? magenta[0 .. $] : black[0 .. $];
placeholder_tex[i+j+16 .. i+j+16+4] = !swap ? black[0 .. $] : magenta[0 .. $];
}
}
return packed; return placeholder_tex;
} }
Model
LoadGLTF(Arena* arena, string file_name)
{
Model model;
u8[] file_data; // = OpenFile(file_name);
cgltf_options opts;
cgltf_data* data;
opts.file.read = &GLTFLoadCallback;
opts.file.release = &GLTFFreeCallback;
cgltf_result result = cgltf_parse(&opts, file_data.ptr, file_data.length, &data);
if(result == cgltf_result_success)
{
result = cgltf_load_buffers(&opts, data, file_name.ptr);
if(result != cgltf_result_success)
{
Logf("%s Failure: Unable to load buffers", __FUNCTION__);
}
u64 primitive_count;
for(u64 i = 0; i < data.nodes_count; i += 1)
{
cgltf_node* node = &data.nodes[i];
if(node.mesh == null) continue;
for(u64 j = 0; j < node.mesh.primitives_count; j += 1)
{
if(node.mesh.primitives[j].type == cgltf_primitive_type_triangles)
{
primitive_count += 1;
}
}
}
model.meshes = Alloc!(Mesh)(arena, primitive_count);
model.mats = Alloc!(Material)(arena, data.materials_count+1);
// Make and load default material into model.mats[0]
string file_path = GetFilePath(file_name);
for(u64 i = 0; i < data.materials_count; i += 1)
{
// model.mats[i+1] = default_material;
if(data.materials[i].has_pbr_metallic_roughness)
{
}
}
}
return model;
}

414
packer.d
View File

@ -85,15 +85,14 @@ union MeshIdx
u32[4] arr; u32[4] arr;
} }
struct Model struct DirEntry
{ {
Vertex[] v; string dir;
u32[] idx; string[] files;
MaterialData[] mats; DirEntry[] sub_dirs;
} }
u64 g_asset_count = 0; u64 g_asset_count = 0;
string[] g_file_names = [];
Texture[] g_model_textures = []; Texture[] g_model_textures = [];
/************************************************** /**************************************************
@ -102,13 +101,12 @@ Texture[] g_model_textures = [];
void main(string[] argv) void main(string[] argv)
{ {
bool pack = false; string assets_dir = null;
bool out_dir = false; string asset_pack_path = null;
string font_file;
for(u64 i = 0; i < argv.length; i += 1) for(u64 i = 0; i < argv.length; i += 1)
{ {
if(argv[i] == "-dir" && i+1 < argv.length) if(argv[i] == "-out" && i+1 < argv.length)
{ {
if(!exists(argv[i+1])) if(!exists(argv[i+1]))
{ {
@ -120,20 +118,28 @@ void main(string[] argv)
assert(false, "Out directory is not a directory"); assert(false, "Out directory is not a directory");
} }
chdir(argv[i+1]); asset_pack_path = argv[i+1];
out_dir = true;
i += 1; i += 1;
continue; continue;
} }
if(argv[i] == "-pack") if(argv[i] == "-assets")
{ {
pack = true; if(!exists(argv[i+1]))
{
assert(false, "Assets directory not found");
}
assets_dir = argv[i+1];
i += 1;
continue;
} }
} }
if(!out_dir) if(asset_pack_path != null)
{ {
if(!Cwd!(string)().endsWith("build")) if(!Cwd!(string)().endsWith("build"))
{ {
@ -144,16 +150,157 @@ void main(string[] argv)
if(exists("build") && isDir("build")) if(exists("build") && isDir("build"))
{ {
chdir("build"); assets_pack_path = "./build/assets.sgp";
} }
else assert(false, "Unable to make default build directory"); else assert(false, "Unable to make default build directory");
} }
} }
if(assets_dir == null)
{
assert(false, "No assets directory provided");
}
if(pack) if(pack)
{ {
PackFile(); PackFile(assets_pack_path, assets_dir);
debug TestFile(); debug TestFile(assets_pack_path, assets_dir);
}
}
void
ScanDir(DirEntry* entry, string dir)
{
string cwd = Cwd!(string)();
foreach(string e; dirEntries(dir, SpanMode.shallow))
{
if(e == ".." || e == ".") continue;
if(isDir(e))
{
entry.sub_dirs ~= DirEntry(e, []. []);
}
if(isFile(e))
{
entry.files ~= e;
}
}
for(u64 i = 0; i < entry.sub_dirs.length; i += 1)
{
ScanDir(&entry.sub_dirs[i], entry.sub_dirs[i].dir);
}
}
void
PackFile(string file_path, string assets_dir)
{
string cwd = Cwd!(string)();
File ap = File(file_path, "wb");
ChDir(assets_dir);
DirEntry base_dir = [
{
dir: "",
files: [],
sub_dirs: [],
},
];
ScanDir(&base_dir, ".");
FileHeader h = InitHeader(g_asset_count);
ap.rawWrite([h]);
u64 offset = FileHeader.sizeof + (AssetInfo.sizeof * g_asset_count);
AssetInfo[] asset_info;
foreach(file; g_file_names)
{
AssetType type = AT.None;
foreach(extension, t; Lookup)
{
if (file.endsWith(extension))
{
type = t;
break;
}
}
assert(type != AT.None, "Asset Type is none, offending file " ~ file);
auto f = File(file, "rb");
u64 length = cast(u64)f.size();
string base_name = chompPrefix(file, "./");
AssetInfo info = {
hash: Hash(base_name),
offset: offset,
length: length,
type: type,
};
auto data = f.rawRead(new u8[length]);
assert(length == data.length, "rawRead failure: data length returned doesn't match");
ap.seek(offset);
ap.rawWrite(data);
offset += length;
asset_info ~= info;
f.close();
}
ap.seek(FileHeader.sizeof);
ap.rawWrite(asset_info);
ap.flush();
ap.close();
ChDir(cwd);
}
void
TestFile(string file_path, string assets_dir)
{
File ap = File(file_path, "rb");
scope(exit)
{
ap.flush();
ap.close();
}
FileHeader file_header = ap.rawRead(new FileHeader[1])[0];
FileHeader test_header = InitHeader(g_asset_count);
assert(file_header == test_header, "TestFile failure: Header is incorrect");
AssetInfo[] file_info = ap.rawRead(new AssetInfo[g_asset_count]);
assert(file_info.length == file_header.asset_count, "TestFile failure: Incorrect AssetInfo length returned");
u64 asset_index = 0;
foreach(i, file; g_file_names)
{
scope(exit) asset_index += 1;
AssetInfo* info = file_info.ptr + asset_index;
File asset = File(file, "rb");
u8[] data = asset.rawRead(new u8[asset.size()]);
assert(data.length == info.length, "TestFile failure: File length read is incorrect");
string base_name = chompPrefix(file, "./");
assert(Hash(base_name) == info.hash, "TestFile failure: File hash is incorrect");
ap.seek(info.offset);
u8[] pack_data = ap.rawRead(new u8[info.length]);
assert(equal!((a, b) => a == b)(data[], pack_data[]), "TestFile failure: Asset data does not match file data");
} }
} }
@ -276,115 +423,6 @@ GetMatColor(string str)
return GetMatColor(GetMatProp(str)); return GetMatColor(GetMatProp(str));
} }
void
PackFile()
{
File ap = File("./assets.sgp", "wb");
scope(exit)
{
ap.flush();
ap.close();
chdir("../build");
}
chdir("../assets");
foreach(string file; dirEntries(".", SpanMode.depth))
{
if (isDir(file)) continue;
g_file_names ~= file;
g_asset_count += 1;
}
FileHeader h = InitHeader(g_asset_count);
ap.rawWrite([h]);
u64 offset = FileHeader.sizeof + (AssetInfo.sizeof * g_asset_count);
AssetInfo[] asset_info;
foreach(file; g_file_names)
{
AssetType type = AT.None;
foreach(extension, t; Lookup)
{
if (file.endsWith(extension))
{
type = t;
break;
}
}
assert(type != AT.None, "Asset Type is none, offending file " ~ file);
auto f = File(file, "rb");
u64 length = cast(u64)f.size();
string base_name = chompPrefix(file, "./");
AssetInfo info = {
hash: Hash(base_name),
offset: offset,
length: length,
type: type,
};
auto data = f.rawRead(new u8[length]);
assert(length == data.length, "rawRead failure: data length returned doesn't match");
ap.seek(offset);
ap.rawWrite(data);
offset += length;
asset_info ~= info;
f.close();
}
ap.seek(FileHeader.sizeof);
ap.rawWrite(asset_info);
}
void
TestFile()
{
File ap = File("assets.sgp", "rb");
scope(exit)
{
ap.flush();
ap.close();
chdir("../build");
}
FileHeader file_header = ap.rawRead(new FileHeader[1])[0];
FileHeader test_header = InitHeader(g_asset_count);
assert(file_header == test_header, "TestFile failure: Header is incorrect");
AssetInfo[] file_info = ap.rawRead(new AssetInfo[g_asset_count]);
assert(file_info.length == file_header.asset_count, "TestFile failure: Incorrect AssetInfo length returned");
chdir("../assets");
u64 asset_index = 0;
foreach(i, file; g_file_names)
{
scope(exit) asset_index += 1;
AssetInfo* info = file_info.ptr + asset_index;
File asset = File(file, "rb");
u8[] data = asset.rawRead(new u8[asset.size()]);
assert(data.length == info.length, "TestFile failure: File length read is incorrect");
string base_name = chompPrefix(file, "./");
assert(Hash(base_name) == info.hash, "TestFile failure: File hash is incorrect");
ap.seek(info.offset);
u8[] pack_data = ap.rawRead(new u8[info.length]);
assert(equal!((a, b) => a == b)(data[], pack_data[]), "TestFile failure: Asset data does not match file data");
}
}
static u32 static u32
MagicValue(string str) MagicValue(string str)
@ -406,17 +444,6 @@ InitHeader(u64 asset_count)
return header; return header;
} }
static ModelHeader
InitModelHeader()
{
ModelHeader header = {
magic: MagicValue("stgm"),
model_version: MODEL_VERSION,
};
return header;
}
string[][] string[][]
TokenizeLines(u8[] data) TokenizeLines(u8[] data)
{ {
@ -471,13 +498,12 @@ OpenFile(string file_name)
return data; return data;
} }
/*
Model Model
ConvertObj(string file_name) ConvertObj(string file_name)
{ {
/* // TODO:
TODO: // - Deduplicate vertices
- Deduplicate vertices
*/
u8[] data = OpenFile(file_name); u8[] data = OpenFile(file_name);
@ -687,109 +713,7 @@ ConvertObj(string file_name)
return model; return model;
} }
*/
extern (C) cgltf_result
GLTFLoadCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, const(char)* path, cgltf_size* size, void** data)
{
u8[] file_data = OpenFile(ConvToStr(path[0 .. strlen(path)]));
if(file_data == null) return cgltf_result_io_error;
*size = cast(cgltf_size)file_data.length;
*data = Alloc!(u8)(file_data).ptr;
return cgltf_result_success;
}
extern (C) void
GLTFFreeCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, void* data, cgltf_size size)
{
Free(data[0 .. size]);
}
ModelData
LoadGLTF(string file_name)
{
ModelData model;
u8[] file_data = OpenFile(file_name);
cgltf_options opts;
cgltf_data* data;
opts.file.read = &GLTFLoadCallback;
opts.file.release = &GLTFFreeCallback;
cgltf_result result = cgltf_parse(&opts, file_data.ptr, file_data.length, &data);
if(result == cgltf_result_success)
{
result = cgltf_load_buffers(&opts, data, file_name.ptr);
if(result != cgltf_result_success)
{
Logf("%s Failure: Unable to load buffers", __FUNCTION__);
}
u64 primitive_count;
for(u64 i = 0; i < data.nodes_count; i += 1)
{
cgltf_node* node = &data.nodes[i];
if(node.mesh == null) continue;
for(u64 j = 0; j < mesh.primitives_count; j += 1)
{
if(mesh.primitives[j].type == cgltf_primtive_type_triangles)
{
primitive_count += 1;
}
}
}
model.meshes = new Mesh[primitive_count];
model.mats = new MaterialData[data.materials_count+1];
// Make and load default material into model.mats[0]
string file_path = GetFilePath(file_name);
for(u64 i = 0; i < data.materials_count; i += 1)
{
// model.mats[i+1] = default_material;
if(data.materials[i].has_pbr_metallic_roughness)
{
}
}
}
}
string
GetFilePath(string file_name)
{
string result = file_name;
for(u64 i = file_name.length-1; i64(i) >= 0; i -= 1)
{
version(Windows)
{
char ch = '\\';
}
else
{
char ch = '/';
}
if(file_name[i] == ch)
{
result = file_name[0 .. i+1];
break;
}
}
return result;
}
pragma(inline) f32 pragma(inline) f32
ToF32(string str) ToF32(string str)
@ -818,7 +742,7 @@ CheckWhiteSpace(u8 ch)
unittest unittest
{ {
{ // Obj test { // Obj test
Model model = ConvertObj("./test/sponza.obj"); //Model model = ConvertObj("./test/sponza.obj");
} }
{ {

26
util.d
View File

@ -154,6 +154,32 @@ ConvertColor(Vec4 *dst, u32 src)
} }
} }
string
GetFilePath(string file_name)
{
string result = file_name;
for(u64 i = file_name.length-1; i64(i) >= 0; i -= 1)
{
version(Windows)
{
char ch = '\\';
}
else
{
char ch = '/';
}
if(file_name[i] == ch)
{
result = file_name[0 .. i+1];
break;
}
}
return result;
}
pragma(inline) void pragma(inline) void
Convert(Vec4* dst, u32 src) Convert(Vec4* dst, u32 src)
{ {