rework mesh/materials and start gltf loading

This commit is contained in:
Matthew 2025-11-11 07:59:43 +11:00
parent 50b9ce9ee8
commit 9bc34ca4b9
6 changed files with 7367 additions and 55 deletions

View File

@ -88,6 +88,12 @@ struct AssetInfo
AssetType type;
}
struct Mesh
{
Vertex[] vtx;
u32[] idx;
}
struct MeshPart
{
u64 start;
@ -97,15 +103,28 @@ struct MeshPart
struct ModelData
{
string name;
Vertex[] vtx;
u32[] idx;
Mesh[] meshes;
MaterialData[] mats;
MeshPart[] parts;
}
struct MaterialMap
{
u32 texture_id;
Vec4 color;
f32 value;
}
struct Material
{
u32 shader_id;
MaterialMap[] maps;
Vec4 params;
}
struct MaterialData
{
string name;
Vec3[MatColor.max] colors;
string[MatMap.max] maps;
f32[MatFloat.max] props = 0.0;
@ -133,6 +152,7 @@ struct Vertex
Vec3 pos;
Vec3 normal;
Vec2 uv;
Vec2 uv2;
}
enum IllumModel : u32

7228
external/cgltf/cgltf.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -24,3 +24,6 @@
#define CGLM_FORCE_DEPTH_ZERO_TO_ONE
#include "external/cglm/cglm.h"
#define CGLTF_IMPLEMENTATION
#include "external/cgltf/cgltf.h"

145
packer.d
View File

@ -5,6 +5,7 @@ import dlib.util;
import dlib.aliases;
import dlib.assets;
import dlib.platform;
import dlib.alloc;
import std.stdio;
import std.string;
@ -79,9 +80,9 @@ union MeshIdx
{
struct
{
u32 v, uv, n;
u32 v, uv, n, t;
};
u32[3] arr;
u32[4] arr;
}
struct Model
@ -451,9 +452,20 @@ TokenizeLines(u8[] data)
u8[]
OpenFile(string file_name)
{
File f = File(file_name, "rb");
u8[] data = new u8[f.size()];
File f;
u8[] data;
try
{
f = File(file_name, "rb");
data = new u8[f.size()];
f.rawRead(data);
}
catch(Exception e)
{
data = null;
}
f.close();
return data;
@ -494,14 +506,14 @@ ConvertObj(string file_name)
Vec3[] positions = new Vec3[vcount];
Vec3[] normals = new Vec3[ncount];
Vec2[] uvs = new Vec2[uvcount];
MeshIdx[][] idx = [];
MeshIdx[3][][] idx = [];
MaterialData[] mtls = [];
vcount = 0;
ncount = 0;
uvcount = 0;
MeshIdx[] part_idx = [];
MeshIdx[3][] part_idx = [];
for(u64 i = 0; i < tokens.length; i += 1)
{
if(tokens[i][0] == "#") continue;
@ -536,17 +548,18 @@ ConvertObj(string file_name)
if(tokens[i].length == 4)
{
MeshIdx[3] face;
for(u64 j = 1; j < tokens[i].length; j += 1)
{
string[] parts = tokens[i][j].split('/');
if(sep_count == 0)
{
part_idx ~= MeshIdx(v: to!u32(parts[0]));
face[j-1] = MeshIdx(v: to!u32(parts[0]));
}
if(sep_count == 1)
{
part_idx ~= MeshIdx(v: to!u32(parts[0]), uv: to!u32(parts[1]));
face[j-1] = MeshIdx(v: to!u32(parts[0]), uv: to!u32(parts[1]));
}
if(sep_count == 2)
{
@ -557,9 +570,11 @@ ConvertObj(string file_name)
mesh_idx.arr[ipart] = to!u32(part);
}
part_idx ~= mesh_idx;
face[j-1] = mesh_idx;
}
}
part_idx ~= face;
}
else assert(false, "Only triangles or quads supported for mesh face");
@ -569,7 +584,6 @@ ConvertObj(string file_name)
if(tokens[i][0] == "g" && part_idx.length > 0)
{
idx ~= part_idx;
Logf("%s %s", idx.length, part_idx.length);
part_idx = [];
continue;
}
@ -645,69 +659,110 @@ ConvertObj(string file_name)
face_count += part.length;
}
positions = Deduplicate(positions, idx, 0);
uvs = Deduplicate(uvs, idx, 1);
normals = Deduplicate(normals, idx, 2);
ModelData md = {
name: baseName(file_name, ".obj"),
vtx: new Vertex[face_count*3],
meshes: [
{ vtx: new Vertex[face_count*3] },
]
};
Logf("%s %s", (Vertex.sizeof * md.vtx.length), (positions.length*Vec3.sizeof + uvs.length*Vec2.sizeof + normals.length*Vec3.sizeof));
u64 vtx_count = 0;
foreach(part; idx)
{
for(u64 i = 0; i < part.length; i += 1)
{
MeshIdx* mi = part.ptr + i;
for(u64 j = 0; j < 3; j += 1)
{
MeshIdx* mi = part[i].ptr + j;
if(mi.v ) md.meshes[0].vtx[vtx_count+j].pos = positions[mi.v-1];
if(mi.n ) md.meshes[0].vtx[vtx_count+j].normal = normals[mi.n-1];
if(mi.uv) md.meshes[0].vtx[vtx_count+j].uv = uvs[mi.uv-1];
}
if(mi.v ) md.vtx[vtx_count].pos = positions[mi.v-1];
if(mi.n ) md.vtx[vtx_count].normal = normals[mi.n-1];
if(mi.uv) md.vtx[vtx_count].uv = uvs[mi.uv-1];
vtx_count += 1;
vtx_count += 3;
}
}
return model;
}
T[]
Deduplicate(T)(T[] values, MeshIdx[][] indices, u32 arr_idx)
extern (C) cgltf_result
GLTFLoadCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, const(char)* path, cgltf_size* size, void** data)
{
u64 dup_count;
for(u64 i = 0; i < values.length; i += 1)
{
for(u64 j = i+1; j < values.length; j += 1)
{
if(values[i] == values[j])
{
dup_count += 1;
u8[] file_data = OpenFile(ConvToStr(path[0 .. strlen(path)]));
Logf("before");
values[j .. $] = values[j+1 .. values.length-1];
Logf("after");
if(file_data == null) return cgltf_result_io_error;
foreach(ref part; indices)
{
for(u64 k = 0; k < part.length; k += 1)
{
if(part[k].arr[arr_idx] > j+1)
{
part[k].arr[arr_idx] -= 1;
*size = cast(cgltf_size)file_data.length;
*data = Alloc!(u8)(file_data).ptr;
return cgltf_result_success;
}
if(part[k].arr[arr_idx] == j+1)
extern (C) void
GLTFFreeCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, void* data, cgltf_size size)
{
part[k].arr[arr_idx] = cast(u32)(i+1);
}
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;
}
}
}
return values[0 .. values.length-dup_count];
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

View File

@ -2,7 +2,7 @@
name="Test_Runner"
ldc2 platform.d aliases.d math.d util.d alloc.d assets.d packer.d external/xxhash/xxhash.d -P-I/usr/include/freetype2 -L-lfreetype --main --unittest --of=$name
ldc2 platform.d aliases.d math.d util.d alloc.d assets.d packer.d external/xxhash/xxhash.d -P-I/usr/include/freetype2 -L-lfreetype --main --unittest -g --of=$name
rm $name.o
./$name

10
util.d
View File

@ -66,11 +66,17 @@ CastArr(T, U)(U[] input_array)
}
void
Logf(Args...)(string fmt, Args args)
Debugf(Args...)(string fmt, Args args)
{
debug Logf(fmt, args, "[DEBUG]: ");
}
void
Logf(Args...)(string fmt, Args args, string prefix = "[INFO]: ")
{
try
{
write("[INFO]: ");
write(prefix);
writefln(fmt, args);
}
catch (Exception e)