first version of obj parser

This commit is contained in:
Matthew 2025-11-08 18:32:52 +11:00
parent d290e3131c
commit 0765cc5e3b
9 changed files with 155514 additions and 6745 deletions

279
assets.d
View File

@ -23,7 +23,7 @@ const u32 MODEL_VERSION = 2;
enum AssetType : u32
{
None,
ModelM3D,
ModelObj,
Shader,
Texture,
}
@ -69,70 +69,10 @@ struct ModelData
TextureInfo[] textures;
}
enum IllumModel : u32
{
Color = 0,
ColorAmbient,
Highlight,
ReflectionRayTrace,
GlassRayTrace,
FresnelRayTrace,
RefractionRayTrace,
RefractionFresnelRayTrace,
Reflection,
Glass,
ShadowsInvis,
}
enum MatColor : u32
{
Ambient,
Albedo,
Specular,
Transmission,
Emissive,
Max,
}
enum MatFloat : u32
{
SpecularExp,
Alpha,
OpticalDensity,
Roughness,
Metallic,
ClearcoatThickness,
ClearcoatRoughness,
Anisotropy,
Bump,
FaceThickness,
Sheen,
Max,
}
enum MatMap : u32
{
Ambient,
Albedo,
Specular,
SpecularHighlight,
Alpha,
Bump,
Displacement,
Roughness,
Metallic,
Emissive,
Anisotropy,
Normal,
Max,
}
struct MaterialData
{
Vec4[MatColor.max] colors;
string name;
Vec3[MatColor.max] colors;
string[MatMap.max] maps;
f32[MatFloat.max] props = 0.0;
IllumModel illum;
@ -212,23 +152,83 @@ enum MatProp
NormalMap,
}
enum IllumModel : u32
{
Color = 0,
ColorAmbient,
Highlight,
ReflectionRayTrace,
GlassRayTrace,
FresnelRayTrace,
RefractionRayTrace,
RefractionFresnelRayTrace,
Reflection,
Glass,
ShadowsInvis,
}
enum MatColor : u32
{
Ambient,
Albedo,
Specular,
Transmission,
Emissive,
Max,
}
enum MatFloat : u32
{
SpecularExp,
Alpha,
OpticalDensity,
Roughness,
Metallic,
ClearcoatThickness,
ClearcoatRoughness,
Anisotropy,
Sheen,
Max,
}
enum MatMap : u32
{
Ambient,
Albedo,
Specular,
SpecularHighlight,
Alpha,
Bump,
Displacement,
Roughness,
Metallic,
Emissive,
Anisotropy,
Normal,
Sheen,
Stencil,
Max,
}
bool Asset_Pack_Opened = false;
MatProp
GetMapProp(u8[] str)
GetMatProp(string str)
{
string s = ConvToStr!(u8)(str);
switch(s) with(MatProp)
switch(str) with(MatProp)
{
// Vec3
case "Ka": return Ambient;
case "Kd": return Albedo;
case "Ks": return Specular;
case "Ns": return SpecularExp;
case "d": return Dissolve;
case "Tr": return Transparency;
case "Tf": return Transmission;
case "Ni": return OpticalDensity;
case "Ke": return Emissive;
// Illum
case "illum": return Illumination;
// string
case "map_Ka": return AmbientMap;
case "map_Kd": return AlbedoMap;
case "map_Ks": return SpecularMap;
@ -236,95 +236,102 @@ GetMapProp(u8[] str)
case "map_d": return AlphaMap;
case "map_bump":
case "bump": return BumpMap;
case "map_Pr": return RoughnessMap;
case "map_Pm": return MetallicMap;
case "map_Ke": return EmissiveMap;
case "map_Ps": return SheenMap;
case "norm": return NormalMap;
case "anisor": return AnisotropyMap;
case "disp": return DisplacementMap;
case "decal": return Stencil;
// f32
case "Ns": return SpecularExp;
case "d": return Dissolve;
case "Tr": return Transparency;
case "Ni": return OpticalDensity;
case "Pr": return Roughness;
case "map_Pr": return RoughnessMap;
case "Pm": return Metallic;
case "map_Pm": return MetallicMap;
case "Pc": return ClearcoatThickness;
case "Pcr": return ClearcoatRoughness;
case "Ke": return Emissive;
case "map_Ke": return EmissiveMap;
case "aniso": return Anisotropy;
case "anisor": return AnisotropyMap;
case "norm": return NormalMap;
case "Ps": return Sheen;
default: return None;
}
}
bool
M3DColor(u32 type)
{
return type == m3dp_Kd ||
type == m3dp_Ka ||
type == m3dp_Ks ||
type == m3dp_Ke ||
type == m3dp_Tf;
}
MatColor
M3DMatColor(u32 type)
GetMatColor(MatProp prop)
{
switch(type) with(MatColor)
switch(prop) with(MatProp)
{
case m3dp_Kd: return Albedo;
case m3dp_Ka: return Ambient;
case m3dp_Ks: return Specular;
case m3dp_Ke: return Emissive;
case m3dp_Tf: return Transmission;
default: assert(false, "Unknown M3D MatColor");
case Ambient: return MatColor.Ambient;
case Albedo: return MatColor.Albedo;
case Specular: return MatColor.Specular;
case Transmission: return MatColor.Transmission;
case Emissive: return MatColor.Emissive;
default: assert(false, "Unknown MatProp to MatColor conversion");
}
}
bool
M3DFloat(u32 type)
{
return type == m3dp_Ns ||
type == m3dp_Km ||
type == m3dp_d ||
type == m3dp_Pr ||
type == m3dp_Pm ||
type == m3dp_Ps ||
type == m3dp_Ni ||
type == m3dp_Nt;
}
MatFloat
M3DMatFloat(u32 type)
GetMatFloat(MatProp prop)
{
switch(type) with(MatFloat)
switch(prop) with(MatProp)
{
case m3dp_Ns: return SpecularExp;
case m3dp_Km: return Bump;
case m3dp_d: return Alpha;
case m3dp_Pr: return Roughness;
case m3dp_Pm: return Metallic;
case m3dp_Ps: return Sheen;
case m3dp_Ni: return OpticalDensity;
case m3dp_Nt: return FaceThickness;
default: assert(false);
case SpecularExp: return MatFloat.SpecularExp;
case Transparency:
case Dissolve: return MatFloat.Alpha;
case OpticalDensity: return MatFloat.OpticalDensity;
case Roughness: return MatFloat.Roughness;
case Metallic: return MatFloat.Metallic;
case ClearcoatThickness: return MatFloat.ClearcoatThickness;
case ClearcoatRoughness: return MatFloat.ClearcoatRoughness;
case Anisotropy: return MatFloat.Anisotropy;
case Sheen: return MatFloat.Sheen;
default: assert(false, "Unknown MatProp to MatFloat conversion");
}
}
bool
M3DMap(u32 type)
MatMap
GetMatMap(MatProp prop)
{
return type == m3dp_map_Kd ||
type == m3dp_map_Ka ||
type == m3dp_map_Ks ||
type == m3dp_map_Ns ||
type == m3dp_map_Ke ||
type == m3dp_map_Tf ||
type == m3dp_map_Km ||
type == m3dp_map_D ||
type == m3dp_map_N ||
type == m3dp_map_Pr ||
type == m3dp_map_Pm ||
type == m3dp_map_Ps ||
type == m3dp_map_Ni ||
type == m3dp_map_Nt;
switch(prop) with(MatProp)
{
case AmbientMap: return MatMap.Ambient;
case AlbedoMap: return MatMap.Albedo;
case SpecularMap: return MatMap.Specular;
case SpecularHighlightMap: return MatMap.SpecularHighlight;
case AlphaMap: return MatMap.Alpha;
case BumpMap: return MatMap.Bump;
case RoughnessMap: return MatMap.Roughness;
case MetallicMap: return MatMap.Metallic;
case EmissiveMap: return MatMap.Emissive;
case SheenMap: return MatMap.Sheen;
case NormalMap: return MatMap.Normal;
case AnisotropyMap: return MatMap.Anisotropy;
case DisplacementMap: return MatMap.Displacement;
case Stencil: return MatMap.Ambient;
default: assert(false, "Unknown MatProp to MatMap conversion");
}
}
MatMap
GetMatMap(string str)
{
return GetMatMap(GetMatProp(str));
}
MatFloat
GetMatFloat(string str)
{
return GetMatFloat(GetMatProp(str));
}
MatColor
GetMatColor(string str)
{
return GetMatColor(GetMatProp(str));
}
debug
@ -494,7 +501,7 @@ else
unittest
{
{
MatProp prop = GetMapProp(cast(u8[])r"Ka");
MatProp prop = GetMatProp("Ka");
}
}

3
external/m3d/m3d.c vendored
View File

@ -1,3 +0,0 @@
#define M3D_IMPLEMENTATION
#include "m3d.h"

6574
external/m3d/m3d.h vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#pragma attribute(push, nogc, nothrow)
//#pragma attribute(push, nogc, nothrow)
#ifdef __linux__
# include <xcb/xcb.h>
@ -16,13 +16,10 @@
#include <xmmintrin.h>
#define STB_IMAGE_IMPLEMENTATION
#include "external/stb/stb_image.h"
#define M3D_IMPLEMENTATION
#include "external/m3d/m3d.h"
#define CGLM_FORCE_DEPTH_ZERO_TO_ONE
#include "external/cglm/cglm.h"
#define TINYOBJ_LOADER_C_IMPLEMENTATION
#include "external/tinyobjloader/tinyobj_loader_c.h"

315
packer.d
View File

@ -1,4 +1,10 @@
import dlib;
module dlib.packer;
import includes;
import dlib.util;
import dlib.aliases;
import dlib.assets;
import std.stdio;
import std.string;
import std.file;
@ -6,10 +12,10 @@ import std.path;
import std.traits;
import std.algorithm.comparison;
import core.memory;
import std.json;
import std.conv;
import std.array;
AssetType[string] Lookup = [
".m3d": AT.ModelM3D,
".obj": AT.ModelObj,
".png": AT.Texture,
".jpg": AT.Texture,
@ -25,10 +31,30 @@ struct Texture
u32 ch;
}
struct MeshGroup
{
u32 start;
u32 length;
}
struct MeshIdx
{
union
{
struct
{
u32 v, n, uv;
};
u32[3] arr;
};
}
struct Model
{
Vertex[] v;
u32[] idx;
MaterialData[] mats;
MeshGroup[] meshes;
}
u64 g_asset_count = 0;
@ -222,29 +248,286 @@ InitModelHeader()
return header;
}
Model
ConvertM3D(u8[] data)
string[][]
TokenizeLines(u8[] data)
{
string[][] tokens = [];
string[] line_tokens = [];
u64 start = -1;
for(u64 i = 0; i < data.length; i += 1)
{
if(i64(start) != -1 && CheckWhiteSpace(data[i]))
{
line_tokens ~= ConvString(data[start .. i]);
start = -1;
}
if(data[i] == '\n')
{
tokens ~= line_tokens;
line_tokens = [];
continue;
}
if(i64(start) == -1 && !CheckWhiteSpace(data[i]))
{
start = i;
continue;
}
}
return tokens;
}
u8[]
OpenFile(string file_name)
{
File f = File(file_name, "rb");
u8[] data = new u8[f.size()];
f.rawRead(data);
f.close();
return data;
}
Model
ConvertObj(string file_name)
{
import std.array;
u8[] data = OpenFile(file_name);
Model model;
m3d_t* m3d = m3d_load(data.ptr, null, null, null);
u64 vcount, uvcount, ncount, fcount, gcount, mcount;
m3dm_t[] mats = m3d.material[0 .. m3d.nummaterial];
foreach(mat; mats)
{
MaterialData matd;
m3dp_t[] props = mat.prop[0 .. mat.numprop];
string[][] tokens = TokenizeLines(data);
foreach(prop; props)
for(u64 i = 0; i < tokens.length; i += 1)
{
switch(prop.type)
if(tokens[i].length == 0) continue;
switch(tokens[i][0])
{
case m3dp_Kd:
case "v": vcount += 1; break;
case "vt": uvcount += 1; break;
case "vn": ncount += 1; break;
case "f": fcount += 1; break;
case "g": gcount += 1; break;
case "usemtl": mcount += 1; break;
default: break;
}
}
Vec3[] positions = new Vec3[vcount];
Vec3[] normals = new Vec3[ncount];
Vec2[] uvs = new Vec2[uvcount];
MeshGroup[] groups = new MeshGroup[gcount];
Vertex[] vtx = new Vertex[fcount];
MeshIdx[][] idx = [];
MaterialData[] mtls = [];
vcount = 0;
ncount = 0;
uvcount = 0;
MeshIdx[] part_idx = [];
for(u64 i = 0; i < tokens.length; i += 1)
{
if(tokens[i][0] == "#") continue;
if(tokens[i][0] == "v")
{
if(tokens[i].length < 4) assert(false, "OBJ file error, not enough points for case [v]");
positions[vcount++] = Vec3(ToF32(tokens[i][1]), ToF32(tokens[i][2]), ToF32(tokens[i][3]));
continue;
}
if(tokens[i][0] == "vn")
{
if(tokens[i].length < 4) assert(false, "OBJ file error, not enough points for case [vn]");
normals[ncount++] = Vec3(ToF32(tokens[i][1]), ToF32(tokens[i][2]), ToF32(tokens[i][3]));
continue;
}
if(tokens[i][0] == "vt")
{
if(tokens[i].length < 3) assert(false, "OBJ file error, not enough points for case [vt]");
uvs[uvcount++] = Vec2(ToF32(tokens[i][1]), ToF32(tokens[i][2]));
continue;
}
if(tokens[i][0] == "f")
{
u32 sep_count = StrCharCount(tokens[i][1], '/');
if(tokens[i].length == 4)
{
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]));
}
if(sep_count == 1)
{
part_idx ~= MeshIdx(v: to!u32(parts[0]), uv: to!u32(parts[1]));
}
if(sep_count == 2)
{
MeshIdx mesh_idx;
foreach(ipart, part; parts)
{
if(part == "") continue;
mesh_idx.arr[ipart] = to!u32(part);
}
part_idx ~= mesh_idx;
}
}
}
else assert(false, "Only triangles or quads supported for mesh face");
continue;
}
if(tokens[i][0] == "g" && part_idx.length > 0)
{
idx ~= part_idx;
part_idx = [];
continue;
}
if(tokens[i][0] == "mtllib")
{
u8[] mtl_data = OpenFile(GetFilePath(file_name) ~ tokens[i][1]);
MaterialData* mtl = null;
string[][] mtl_tokens = TokenizeLines(mtl_data);
for(u64 j = 0; j < mtl_tokens.length; j += 1)
{
if(mtl_tokens[j].length == 0)
{
if(mtl)
{
mtls ~= *mtl;
mtl = null;
}
continue;
}
if(mtl_tokens[j][0] == "newmtl")
{
mtl = new MaterialData;
mtl.name = mtl_tokens[j][1];
continue;
}
if(!mtl) continue;
switch(mtl_tokens[j][0])
{
case "Ka", "Kd", "Ks", "Tf", "Ke":
{
mtl.colors[GetMatColor(mtl_tokens[j][0])] = Vec3(ToF32(mtl_tokens[j][1]), ToF32(mtl_tokens[j][2]), ToF32(mtl_tokens[j][3]));
} break;
case "Ns", "d", "Tr", "Ni", "Pr", "Pm", "Pc", "Pcr", "aniso", "Ps":
{
f32 v = ToF32(mtl_tokens[j][1]);
if(mtl_tokens[j][1] == "Tr")
{
v = 1.0 - v;
}
mtl.props[GetMatFloat(mtl_tokens[j][0])] = v;
} break;
case "map_Ka", "map_Kd", "map_Ks", "map_Ns", "map_d", "map_bump", "anisor",
"bump", "map_Pr", "map_Pm", "map_Ke", "map_Ps", "norm", "disp", "decal":
{
mtl.maps[GetMatMap(mtl_tokens[j][0])] = mtl_tokens[j][1];
} break;
case "illum":
{
mtl.illum = cast(IllumModel)(to!(u32)(mtl_tokens[j][1]));
} break;
default: break;
}
}
if(mtl)
{
mtls ~= *mtl;
mtl = null;
}
}
}
}
assert(mtls[mtls.length-1].name == "sp_zid_vani");
return model;
}
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
ToF32(string str)
{
return to!(f32)(str);
}
pragma(inline) string
ConvString(u8[] bytes)
{
return (cast(immutable(char)*)bytes.ptr)[0 .. bytes.length];
}
pragma(inline) bool
CheckWhiteSpace(u8 ch)
{
return ch == ' ' ||
ch == '\t'||
ch == '\n'||
ch == 0x0D||
ch == 0x0A||
ch == 0x0B||
ch == 0x0C;
}
unittest
{
{ // Obj test
Model model = ConvertObj("./test/sponza.obj");
}
}

View File

@ -2,7 +2,8 @@
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 --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 --of=$name
rm $name.o
./$name
rm $name

340
test/sponza.mtl Executable file
View File

@ -0,0 +1,340 @@
# Blender 4.5.3 LTS MTL File: 'None'
# www.blender.org
newmtl sp_00_luk_mal1
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 01_St_kp.JPG
map_Bump 01_St_kp-bump.jpg
newmtl sp_00_luk_mali
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd sp_luk.JPG
map_Bump sp_luk-bump.JPG
newmtl sp_00_pod
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd KAMEN.JPG
map_Bump KAMEN-bump.jpg
newmtl sp_00_prozor
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd prozor1.JPG
map_Bump prozor1.JPG
newmtl sp_00_stup
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 01_STUB.JPG
map_Bump 01_STUB-bump.jpg
newmtl sp_00_svod
Ks 0.031895 0.031895 0.031895
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
Pr 0.968377
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd KAMEN-stup.JPG
map_Bump KAMEN-stup.jpg
newmtl sp_00_vrata_kock
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.858579
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd vrata_ko.JPG
map_Bump vrata_ko.JPG
newmtl sp_00_vrata_krug
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.858579
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd vrata_kr.JPG
map_Bump vrata_kr.JPG
newmtl sp_00_zid
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd KAMEN.JPG
map_Bump KAMEN-bump.jpg
newmtl sp_01_luk_a
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd sp_luk.JPG
map_Bump sp_luk-bump.JPG
newmtl sp_01_stub
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 01_STUB.JPG
map_Bump 01_STUB-bump.jpg
newmtl sp_01_stub_baza
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 01_S_ba.JPG
map_Bump 01_S_BA.JPG
newmtl sp_01_stub_baza_
Kd 0.784314 0.784314 0.784314
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.858579
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
newmtl sp_01_stub_kut
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 01_STUB.JPG
map_Bump 01_STUB-bump.jpg
newmtl sp_01_stup
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd x01_st.JPG
newmtl sp_01_stup_baza
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 01_S_ba.JPG
map_Bump 01_S_BA.JPG
newmtl sp_02_reljef
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd reljef.JPG
map_Bump reljef-bump.jpg
newmtl sp_svod_kapitel
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 00_skap.JPG
map_Bump 00_skap.JPG
newmtl sp_vijenac
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd 00_skap.JPG
map_Bump 00_SKAP.JPG
newmtl sp_zid_vani
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
Pr 0.776393
Pm 0.000000
Ps 0.000000
Pc 0.000000
Pcr 0.030000
aniso 0.000000
anisor 0.000000
Tf 1.000000 1.000000 1.000000
map_Kd KAMEN.JPG
map_Bump KAMEN-bump.jpg

154707
test/sponza.obj Executable file

File diff suppressed because it is too large Load Diff

11
util.d
View File

@ -123,6 +123,17 @@ GB(u64 v)
return MB(v) * 1024;
};
u32
StrCharCount(T)(T str, u8 ch) if(is(T: string) || is(T: u8[]) || is(T: char[]))
{
u32 count = 0;
for(u64 i = 0; i < str.length; i += 1)
{
count += cast(u8)str[i] == ch;
}
return count;
}
pragma(inline) void
ConvertColor(Vec4 *dst, u32 src)
{