rework mesh/materials and start gltf loading
This commit is contained in:
parent
50b9ce9ee8
commit
9bc34ca4b9
26
assets.d
26
assets.d
@ -88,6 +88,12 @@ struct AssetInfo
|
|||||||
AssetType type;
|
AssetType type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Mesh
|
||||||
|
{
|
||||||
|
Vertex[] vtx;
|
||||||
|
u32[] idx;
|
||||||
|
}
|
||||||
|
|
||||||
struct MeshPart
|
struct MeshPart
|
||||||
{
|
{
|
||||||
u64 start;
|
u64 start;
|
||||||
@ -97,15 +103,28 @@ struct MeshPart
|
|||||||
struct ModelData
|
struct ModelData
|
||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
Vertex[] vtx;
|
Mesh[] meshes;
|
||||||
u32[] idx;
|
|
||||||
MaterialData[] mats;
|
MaterialData[] mats;
|
||||||
MeshPart[] parts;
|
}
|
||||||
|
|
||||||
|
struct MaterialMap
|
||||||
|
{
|
||||||
|
u32 texture_id;
|
||||||
|
Vec4 color;
|
||||||
|
f32 value;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Material
|
||||||
|
{
|
||||||
|
u32 shader_id;
|
||||||
|
MaterialMap[] maps;
|
||||||
|
Vec4 params;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MaterialData
|
struct MaterialData
|
||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
Vec3[MatColor.max] colors;
|
Vec3[MatColor.max] colors;
|
||||||
string[MatMap.max] maps;
|
string[MatMap.max] maps;
|
||||||
f32[MatFloat.max] props = 0.0;
|
f32[MatFloat.max] props = 0.0;
|
||||||
@ -133,6 +152,7 @@ struct Vertex
|
|||||||
Vec3 pos;
|
Vec3 pos;
|
||||||
Vec3 normal;
|
Vec3 normal;
|
||||||
Vec2 uv;
|
Vec2 uv;
|
||||||
|
Vec2 uv2;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IllumModel : u32
|
enum IllumModel : u32
|
||||||
|
|||||||
7228
external/cgltf/cgltf.h
vendored
Normal file
7228
external/cgltf/cgltf.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -24,3 +24,6 @@
|
|||||||
#define CGLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define CGLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include "external/cglm/cglm.h"
|
#include "external/cglm/cglm.h"
|
||||||
|
|
||||||
|
#define CGLTF_IMPLEMENTATION
|
||||||
|
#include "external/cgltf/cgltf.h"
|
||||||
|
|
||||||
|
|||||||
153
packer.d
153
packer.d
@ -5,6 +5,7 @@ import dlib.util;
|
|||||||
import dlib.aliases;
|
import dlib.aliases;
|
||||||
import dlib.assets;
|
import dlib.assets;
|
||||||
import dlib.platform;
|
import dlib.platform;
|
||||||
|
import dlib.alloc;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.string;
|
import std.string;
|
||||||
@ -79,9 +80,9 @@ union MeshIdx
|
|||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 v, uv, n;
|
u32 v, uv, n, t;
|
||||||
};
|
};
|
||||||
u32[3] arr;
|
u32[4] arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Model
|
struct Model
|
||||||
@ -451,9 +452,20 @@ TokenizeLines(u8[] data)
|
|||||||
u8[]
|
u8[]
|
||||||
OpenFile(string file_name)
|
OpenFile(string file_name)
|
||||||
{
|
{
|
||||||
File f = File(file_name, "rb");
|
File f;
|
||||||
u8[] data = new u8[f.size()];
|
u8[] data;
|
||||||
f.rawRead(data);
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
f = File(file_name, "rb");
|
||||||
|
data = new u8[f.size()];
|
||||||
|
f.rawRead(data);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -494,14 +506,14 @@ ConvertObj(string file_name)
|
|||||||
Vec3[] positions = new Vec3[vcount];
|
Vec3[] positions = new Vec3[vcount];
|
||||||
Vec3[] normals = new Vec3[ncount];
|
Vec3[] normals = new Vec3[ncount];
|
||||||
Vec2[] uvs = new Vec2[uvcount];
|
Vec2[] uvs = new Vec2[uvcount];
|
||||||
MeshIdx[][] idx = [];
|
MeshIdx[3][][] idx = [];
|
||||||
MaterialData[] mtls = [];
|
MaterialData[] mtls = [];
|
||||||
|
|
||||||
vcount = 0;
|
vcount = 0;
|
||||||
ncount = 0;
|
ncount = 0;
|
||||||
uvcount = 0;
|
uvcount = 0;
|
||||||
|
|
||||||
MeshIdx[] part_idx = [];
|
MeshIdx[3][] part_idx = [];
|
||||||
for(u64 i = 0; i < tokens.length; i += 1)
|
for(u64 i = 0; i < tokens.length; i += 1)
|
||||||
{
|
{
|
||||||
if(tokens[i][0] == "#") continue;
|
if(tokens[i][0] == "#") continue;
|
||||||
@ -536,17 +548,18 @@ ConvertObj(string file_name)
|
|||||||
|
|
||||||
if(tokens[i].length == 4)
|
if(tokens[i].length == 4)
|
||||||
{
|
{
|
||||||
|
MeshIdx[3] face;
|
||||||
for(u64 j = 1; j < tokens[i].length; j += 1)
|
for(u64 j = 1; j < tokens[i].length; j += 1)
|
||||||
{
|
{
|
||||||
string[] parts = tokens[i][j].split('/');
|
string[] parts = tokens[i][j].split('/');
|
||||||
|
|
||||||
if(sep_count == 0)
|
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)
|
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)
|
if(sep_count == 2)
|
||||||
{
|
{
|
||||||
@ -557,9 +570,11 @@ ConvertObj(string file_name)
|
|||||||
mesh_idx.arr[ipart] = to!u32(part);
|
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");
|
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)
|
if(tokens[i][0] == "g" && part_idx.length > 0)
|
||||||
{
|
{
|
||||||
idx ~= part_idx;
|
idx ~= part_idx;
|
||||||
Logf("%s %s", idx.length, part_idx.length);
|
|
||||||
part_idx = [];
|
part_idx = [];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -645,69 +659,110 @@ ConvertObj(string file_name)
|
|||||||
face_count += part.length;
|
face_count += part.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
positions = Deduplicate(positions, idx, 0);
|
|
||||||
uvs = Deduplicate(uvs, idx, 1);
|
|
||||||
normals = Deduplicate(normals, idx, 2);
|
|
||||||
|
|
||||||
ModelData md = {
|
ModelData md = {
|
||||||
name: baseName(file_name, ".obj"),
|
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;
|
u64 vtx_count = 0;
|
||||||
foreach(part; idx)
|
foreach(part; idx)
|
||||||
{
|
{
|
||||||
for(u64 i = 0; i < part.length; i += 1)
|
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];
|
vtx_count += 3;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
T[]
|
extern (C) cgltf_result
|
||||||
Deduplicate(T)(T[] values, MeshIdx[][] indices, u32 arr_idx)
|
GLTFLoadCallback(cgltf_memory_options* memory_opts, cgltf_file_options* file_opts, const(char)* path, cgltf_size* size, void** data)
|
||||||
{
|
{
|
||||||
u64 dup_count;
|
u8[] file_data = OpenFile(ConvToStr(path[0 .. strlen(path)]));
|
||||||
for(u64 i = 0; i < values.length; i += 1)
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
for(u64 j = i+1; j < values.length; j += 1)
|
result = cgltf_load_buffers(&opts, data, file_name.ptr);
|
||||||
|
if(result != cgltf_result_success)
|
||||||
{
|
{
|
||||||
if(values[i] == values[j])
|
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)
|
||||||
{
|
{
|
||||||
dup_count += 1;
|
if(mesh.primitives[j].type == cgltf_primtive_type_triangles)
|
||||||
|
|
||||||
Logf("before");
|
|
||||||
values[j .. $] = values[j+1 .. values.length-1];
|
|
||||||
Logf("after");
|
|
||||||
|
|
||||||
foreach(ref part; indices)
|
|
||||||
{
|
{
|
||||||
for(u64 k = 0; k < part.length; k += 1)
|
primitive_count += 1;
|
||||||
{
|
|
||||||
if(part[k].arr[arr_idx] > j+1)
|
|
||||||
{
|
|
||||||
part[k].arr[arr_idx] -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(part[k].arr[arr_idx] == j+1)
|
|
||||||
{
|
|
||||||
part[k].arr[arr_idx] = cast(u32)(i+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
|
string
|
||||||
|
|||||||
2
test.sh
2
test.sh
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
name="Test_Runner"
|
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
|
rm $name.o
|
||||||
./$name
|
./$name
|
||||||
|
|||||||
10
util.d
10
util.d
@ -66,11 +66,17 @@ CastArr(T, U)(U[] input_array)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
try
|
||||||
{
|
{
|
||||||
write("[INFO]: ");
|
write(prefix);
|
||||||
writefln(fmt, args);
|
writefln(fmt, args);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user