gltf mesh/material loading, adjust build script
This commit is contained in:
parent
10b5c0a127
commit
cce005d410
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
build
|
||||
327
assets.d
327
assets.d
@ -4,6 +4,7 @@ import includes;
|
||||
import dlib.aliases;
|
||||
import dlib.util;
|
||||
import dlib.alloc;
|
||||
import dlib.math;
|
||||
|
||||
import std.file;
|
||||
import std.path;
|
||||
@ -86,18 +87,17 @@ struct Material
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
Vec4 color;
|
||||
Vec4 tangent;
|
||||
Vec3 pos;
|
||||
Vec3 normal;
|
||||
Vec2 uv;
|
||||
Vec2 uv2;
|
||||
Vec4 color;
|
||||
Vec4 tangent;
|
||||
Vec3 pos;
|
||||
Vec3 normal;
|
||||
Vec2[2] uv;
|
||||
}
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
Vertex[] vtx;
|
||||
u32 idx;
|
||||
u32[] idx;
|
||||
u32 mat_id;
|
||||
}
|
||||
|
||||
@ -105,6 +105,9 @@ struct Model
|
||||
{
|
||||
Mat4 transform;
|
||||
|
||||
Vertex[] vtx_buf;
|
||||
u32[] idx_buf;
|
||||
|
||||
Mesh[] meshes;
|
||||
Material[] mats;
|
||||
|
||||
@ -345,6 +348,8 @@ LoadGLTF(Arena* arena, string file_name)
|
||||
}
|
||||
|
||||
u64 primitive_count;
|
||||
u64 vtx_count;
|
||||
u64 idx_count;
|
||||
|
||||
for(u64 i = 0; i < data.nodes_count; i += 1)
|
||||
{
|
||||
@ -357,13 +362,30 @@ LoadGLTF(Arena* arena, string file_name)
|
||||
if(node.mesh.primitives[j].type == cgltf_primitive_type_triangles)
|
||||
{
|
||||
primitive_count += 1;
|
||||
|
||||
if(node.mesh.primitives[j].indices != null && node.mesh.primitives[j].indices.buffer_view != null)
|
||||
{
|
||||
idx_count += node.mesh.primitives[j].indices.count;
|
||||
}
|
||||
|
||||
for(u64 k = 0; k < node.mesh.primitives[j].attributes_count; k += 1)
|
||||
{
|
||||
if(node.mesh.primitives[j].attributes[k].type == cgltf_attribute_type_position)
|
||||
{
|
||||
vtx_count += node.mesh.primitives[j].attributes[k].data.count;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.meshes = Alloc!(Mesh)(primitive_count);
|
||||
model.mats = Alloc!(Material)(data.materials_count+1);
|
||||
m_data.tex = Alloc!(ImageData)(data.textures_count+1);
|
||||
model.idx_buf = Alloc!(u32)(idx_count);
|
||||
model.vtx_buf = Alloc!(Vertex)(vtx_count);
|
||||
model.meshes = Alloc!(Mesh)(primitive_count);
|
||||
model.mats = Alloc!(Material)(data.materials_count+1);
|
||||
m_data.tex = Alloc!(ImageData)(data.textures_count+1);
|
||||
|
||||
model.mats[0] = DEFAULT_MATERIAL;
|
||||
|
||||
@ -420,12 +442,297 @@ LoadGLTF(Arena* arena, string file_name)
|
||||
}
|
||||
}
|
||||
|
||||
u64 mesh_index, idx_index;
|
||||
vtx_count = 0;
|
||||
for(u64 i = 0; i < data.nodes_count; i += 1)
|
||||
{
|
||||
cgltf_node* node = &data.nodes[i];
|
||||
cgltf_mesh* mesh = node.mesh;
|
||||
|
||||
if(mesh == null) continue;
|
||||
|
||||
cgltf_float[16] world_transform;
|
||||
cgltf_node_transform_world(node, world_transform.ptr);
|
||||
|
||||
Mat4 world_matrix = Mat4(world_transform);
|
||||
|
||||
for(u64 p = 0; p < mesh.primitives_count; p += 1)
|
||||
{
|
||||
if(mesh.primitives[p].type != cgltf_primitive_type_triangles)
|
||||
{
|
||||
Logf("Unable to process primitive type [%s]", mesh.primitives[p].type);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto prim = mesh.primitives + p;
|
||||
for(u64 j = 0; j < prim.attributes_count; j += 1)
|
||||
{
|
||||
switch(prim.attributes[j].type)
|
||||
{
|
||||
case cgltf_attribute_type_position:
|
||||
{
|
||||
cgltf_accessor* attr = prim.attributes[j].data;
|
||||
|
||||
if(attr.type == cgltf_type_vec3 && attr.component_type == cgltf_component_type_r_32f)
|
||||
{
|
||||
AddMeshVertices(attr, model, mesh_index, &vtx_count);
|
||||
|
||||
f32* buffer = GetGLTFBuffer!(f32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].pos = Vec3(buffer[3*k+0], buffer[3*k+1], buffer[3*k+2]);
|
||||
Transform(&model.meshes[mesh_index].vtx[k].pos, &world_matrix, 1.0);
|
||||
}
|
||||
}
|
||||
else Logf("Format needs to be Vec3 f32, skipping.");
|
||||
} break;
|
||||
case cgltf_attribute_type_normal:
|
||||
{
|
||||
cgltf_accessor* attr = prim.attributes[j].data;
|
||||
|
||||
if(attr.type == cgltf_type_vec3 && attr.component_type == cgltf_component_type_r_32f)
|
||||
{
|
||||
AddMeshVertices(attr, model, mesh_index, &vtx_count);
|
||||
|
||||
f32* buffer = GetGLTFBuffer!(f32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].normal = Vec3(buffer[3*k+0], buffer[3*k+1], buffer[3*k+2]);
|
||||
Transform(&model.meshes[mesh_index].vtx[k].normal, &world_matrix, 1.0);
|
||||
}
|
||||
}
|
||||
else Logf("Format needs to be Vec3 f32, skipping.");
|
||||
} break;
|
||||
case cgltf_attribute_type_tangent:
|
||||
{
|
||||
cgltf_accessor* attr = prim.attributes[j].data;
|
||||
|
||||
if(attr.type == cgltf_type_vec4 && attr.component_type == cgltf_component_type_r_32f)
|
||||
{
|
||||
AddMeshVertices(attr, model, mesh_index, &vtx_count);
|
||||
|
||||
f32* buffer = GetGLTFBuffer!(f32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].tangent = world_matrix * Vec4(buffer[4*k+0], buffer[4*k+1], buffer[4*k+2], buffer[4*k+3]);
|
||||
}
|
||||
}
|
||||
else Logf("Format needs to be Vec4 f32, skipping.");
|
||||
} break;
|
||||
case cgltf_attribute_type_texcoord:
|
||||
{
|
||||
cgltf_accessor* attr = prim.attributes[j].data;
|
||||
|
||||
if(attr.type == cgltf_type_vec2)
|
||||
{
|
||||
AddMeshVertices(attr, model, mesh_index, &vtx_count);
|
||||
|
||||
u32 uv_idx = prim.attributes[j].index;
|
||||
if(uv_idx >= 2)
|
||||
{
|
||||
Logf("Unable to use more than two uvs, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(attr.component_type == cgltf_component_type_r_32f)
|
||||
{
|
||||
f32* buffer = GetGLTFBuffer!(f32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].uv[uv_idx] = Vec2(buffer[2*k+0], buffer[2*k+1]);
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_8u)
|
||||
{
|
||||
u8* buffer = GetGLTFBuffer!(u8)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].uv[uv_idx] = Vec2(cast(f32)(buffer[2*k+0])/255.0, cast(f32)(buffer[2*k+1])/255.0);
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_16u)
|
||||
{
|
||||
u16* buffer = GetGLTFBuffer!(u16)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].uv[uv_idx] = Vec2(cast(f32)(buffer[2*k+0])/65535.0, cast(f32)(buffer[2*k+1])/65535.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logf("Unsupported format [%s] for uv, skipping", attr.component_type);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case cgltf_attribute_type_color:
|
||||
{
|
||||
cgltf_accessor* attr = prim.attributes[j].data;
|
||||
|
||||
if(attr.type == cgltf_type_vec3 || attr.type == cgltf_type_vec4)
|
||||
{
|
||||
AddMeshVertices(attr, model, mesh_index, &vtx_count);
|
||||
|
||||
if(attr.type == cgltf_type_vec3)
|
||||
{
|
||||
if(attr.component_type == cgltf_component_type_r_8u)
|
||||
{
|
||||
u8* buffer = GetGLTFBuffer!(u8)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].color = Vec4(
|
||||
cast(f32)(buffer[k*3+0])/255.0,
|
||||
cast(f32)(buffer[k*3+1])/255.0,
|
||||
cast(f32)(buffer[k*3+2])/255.0,
|
||||
1.0
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_16u)
|
||||
{
|
||||
u16* buffer = GetGLTFBuffer!(u16)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].color = Vec4(
|
||||
cast(f32)(buffer[k*3+0])/65535.0,
|
||||
cast(f32)(buffer[k*3+1])/65535.0,
|
||||
cast(f32)(buffer[k*3+2])/65535.0,
|
||||
1.0
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_32f)
|
||||
{
|
||||
f32* buffer = GetGLTFBuffer!(f32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].color = Vec4(buffer[k*3+0], buffer[k*3+1], buffer[k*3+2], 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logf("Color component type [%s] not supported", attr.component_type);
|
||||
}
|
||||
}
|
||||
else if(attr.type == cgltf_type_vec4)
|
||||
{
|
||||
if(attr.component_type == cgltf_component_type_r_8u)
|
||||
{
|
||||
u8* buffer = GetGLTFBuffer!(u8)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].color = Vec4(
|
||||
cast(f32)(buffer[k*4+0])/255.0,
|
||||
cast(f32)(buffer[k*4+1])/255.0,
|
||||
cast(f32)(buffer[k*4+2])/255.0,
|
||||
cast(f32)(buffer[k*4+3])/255.0
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_16u)
|
||||
{
|
||||
u16* buffer = GetGLTFBuffer!(u16)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].color = Vec4(
|
||||
cast(f32)(buffer[k*4+0])/65535.0,
|
||||
cast(f32)(buffer[k*4+1])/65535.0,
|
||||
cast(f32)(buffer[k*4+2])/65535.0,
|
||||
cast(f32)(buffer[k*4+3])/65535.0
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_32f)
|
||||
{
|
||||
f32* buffer = GetGLTFBuffer!(f32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].vtx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].vtx[k].color = Vec4(buffer[k*4+0], buffer[k*4+1], buffer[k*4+2], buffer[k*4+3]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logf("Color component type [%s] not supported", attr.component_type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(prim.indices != null && prim.indices.buffer_view != null)
|
||||
{
|
||||
cgltf_accessor* attr = prim.indices;
|
||||
|
||||
model.meshes[mesh_index].idx = model.idx_buf[idx_index .. idx_index+attr.count];
|
||||
idx_index += attr.count;
|
||||
|
||||
if(attr.component_type == cgltf_component_type_r_16u)
|
||||
{
|
||||
u16* buffer = GetGLTFBuffer!(u16)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].idx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].idx[k] = cast(u32)buffer[k];
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_8u)
|
||||
{
|
||||
u8* buffer = GetGLTFBuffer!(u8)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].idx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].idx[k] = cast(u32)buffer[k];
|
||||
}
|
||||
}
|
||||
else if(attr.component_type == cgltf_component_type_r_32u)
|
||||
{
|
||||
u32* buffer = GetGLTFBuffer!(u32)(attr);
|
||||
for(u64 k = 0; k < model.meshes[mesh_index].idx.length; k += 1)
|
||||
{
|
||||
model.meshes[mesh_index].idx[k] = buffer[k];
|
||||
}
|
||||
}
|
||||
else Logf("Unsupported index type [%s]", attr.component_type);
|
||||
}
|
||||
else // unindexed mesh (may implement later)
|
||||
{
|
||||
Logf("Unindexed mesh encountered");
|
||||
}
|
||||
|
||||
for(u32 k = 0; k < data.materials_count; k += 1)
|
||||
{
|
||||
if(data.materials + k == prim.material)
|
||||
{
|
||||
model.meshes[mesh_index].mat_id = k+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mesh_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void
|
||||
AddMeshVertices(cgltf_accessor* accessor, Model* model, u64 mesh_index, u64* vtx_count)
|
||||
{
|
||||
if(model.meshes[mesh_index].vtx == null)
|
||||
{
|
||||
model.meshes[mesh_index].vtx = model.vtx_buf[*vtx_count .. *vtx_count+accessor.count];
|
||||
*vtx_count += accessor.count;
|
||||
}
|
||||
}
|
||||
|
||||
T*
|
||||
GetGLTFBuffer(T)(cgltf_accessor* accessor)
|
||||
{
|
||||
return cast(T*)(accessor.buffer_view.buffer.data + accessor.buffer_view.offset/T.sizeof + accessor.offset/T.sizeof);
|
||||
}
|
||||
|
||||
static ImageData
|
||||
GenerateDefaultTexture(u32 x, u32 y)
|
||||
|
||||
20
build.sh
20
build.sh
@ -36,16 +36,16 @@ if ! [ -f "${build}/libstb.a" ]; then
|
||||
fi
|
||||
|
||||
# M3D
|
||||
src="${script_dir}/external/m3d/m3d.c"
|
||||
flags="-std=c99 -Wno-everything -Iexternal/m3d -c -static"
|
||||
obj="${build}/m3d.o"
|
||||
lib="${build}/libm3d.a"
|
||||
|
||||
if ! [ -f "${build}/libm3d.a" ]; then
|
||||
$c_compiler $flags $src $out $obj
|
||||
ar rcs $lib $obj
|
||||
rm $obj
|
||||
fi
|
||||
#src="${script_dir}/external/m3d/m3d.c"
|
||||
#flags="-std=c99 -Wno-everything -Iexternal/m3d -c -static"
|
||||
#obj="${build}/m3d.o"
|
||||
#lib="${build}/libm3d.a"
|
||||
#
|
||||
#if ! [ -f "${build}/libm3d.a" ]; then
|
||||
# $c_compiler $flags $src $out $obj
|
||||
# ar rcs $lib $obj
|
||||
# rm $obj
|
||||
#fi
|
||||
|
||||
# CGLM
|
||||
src="${script_dir}/external/cglm/cglm.c"
|
||||
|
||||
32
math.d
32
math.d
@ -435,6 +435,11 @@ align(16) struct Matrix(T, int D)
|
||||
}
|
||||
}
|
||||
|
||||
this(U)(U x) if(is(U: typeof(this.v)))
|
||||
{
|
||||
this.v = x;
|
||||
}
|
||||
|
||||
@property inout(T)* ptr() inout
|
||||
{
|
||||
return v.ptr;
|
||||
@ -924,6 +929,14 @@ Inverse(Mat4 mat)
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
Transform(Vec3* vec, Mat4* mat, f32 last = 1.0)
|
||||
{
|
||||
Vec4 tvec = Vec4(*vec, last);
|
||||
tvec = *mat * tvec;
|
||||
*vec = tvec.xyz;
|
||||
}
|
||||
|
||||
pragma(inline) f32
|
||||
Lerp(f32 x, f32 y, f32 a)
|
||||
{
|
||||
@ -1129,10 +1142,27 @@ unittest
|
||||
assert(vec == Vec4(1.0, 2.0, 3.0, 4.0));
|
||||
|
||||
Mat2 mat = Mat2(1.0, 0.0, 0.0, 1.0);
|
||||
Mat4 mat4;
|
||||
|
||||
f32[16] floats = 22.0;
|
||||
Mat4 mat4 = Mat4(floats);
|
||||
assert(mat4.v == floats);
|
||||
|
||||
Quat quat = Quat(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
Quat quat2;
|
||||
}
|
||||
|
||||
{
|
||||
Vec3 vec = Vec3(1.0, 2.0, 3.0);
|
||||
Mat4 mat = Mat4(
|
||||
1.0, 1.0, 1.0, 1.0,
|
||||
2.0, 2.0, 2.0, 2.0,
|
||||
3.0, 3.0, 3.0, 3.0,
|
||||
4.0, 4.0, 4.0, 4.0
|
||||
);
|
||||
|
||||
Transform(&vec, &mat, 1.0);
|
||||
|
||||
assert(vec == Vec3(18.0));
|
||||
}
|
||||
}
|
||||
|
||||
4
test.sh
4
test.sh
@ -2,7 +2,9 @@
|
||||
|
||||
name="Test_Runner"
|
||||
|
||||
ldc2 platform.d aliases.d math.d util.d alloc.d assets.d external/xxhash/xxhash.d -P-I/usr/include/freetype2 -L-lfreetype --main --unittest -g --of=$name
|
||||
/bin/bash ./build.sh build
|
||||
|
||||
ldc2 platform.d aliases.d math.d util.d alloc.d assets.d external/xxhash/xxhash.d build/libcglm.a -Xcc=-mno-sse -P-I/usr/include/freetype2 -L-lfreetype --main --unittest -g --of=$name
|
||||
|
||||
rm $name.o
|
||||
./$name
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user