first version of obj parser
This commit is contained in:
parent
d290e3131c
commit
0765cc5e3b
279
assets.d
279
assets.d
@ -23,7 +23,7 @@ const u32 MODEL_VERSION = 2;
|
|||||||
enum AssetType : u32
|
enum AssetType : u32
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
ModelM3D,
|
ModelObj,
|
||||||
Shader,
|
Shader,
|
||||||
Texture,
|
Texture,
|
||||||
}
|
}
|
||||||
@ -69,70 +69,10 @@ struct ModelData
|
|||||||
TextureInfo[] textures;
|
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
|
struct MaterialData
|
||||||
{
|
{
|
||||||
Vec4[MatColor.max] colors;
|
string name;
|
||||||
|
Vec3[MatColor.max] colors;
|
||||||
string[MatMap.max] maps;
|
string[MatMap.max] maps;
|
||||||
f32[MatFloat.max] props = 0.0;
|
f32[MatFloat.max] props = 0.0;
|
||||||
IllumModel illum;
|
IllumModel illum;
|
||||||
@ -212,23 +152,83 @@ enum MatProp
|
|||||||
NormalMap,
|
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;
|
bool Asset_Pack_Opened = false;
|
||||||
|
|
||||||
MatProp
|
MatProp
|
||||||
GetMapProp(u8[] str)
|
GetMatProp(string str)
|
||||||
{
|
{
|
||||||
string s = ConvToStr!(u8)(str);
|
switch(str) with(MatProp)
|
||||||
switch(s) with(MatProp)
|
|
||||||
{
|
{
|
||||||
|
// Vec3
|
||||||
case "Ka": return Ambient;
|
case "Ka": return Ambient;
|
||||||
case "Kd": return Albedo;
|
case "Kd": return Albedo;
|
||||||
case "Ks": return Specular;
|
case "Ks": return Specular;
|
||||||
case "Ns": return SpecularExp;
|
|
||||||
case "d": return Dissolve;
|
|
||||||
case "Tr": return Transparency;
|
|
||||||
case "Tf": return Transmission;
|
case "Tf": return Transmission;
|
||||||
case "Ni": return OpticalDensity;
|
case "Ke": return Emissive;
|
||||||
|
// Illum
|
||||||
case "illum": return Illumination;
|
case "illum": return Illumination;
|
||||||
|
// string
|
||||||
case "map_Ka": return AmbientMap;
|
case "map_Ka": return AmbientMap;
|
||||||
case "map_Kd": return AlbedoMap;
|
case "map_Kd": return AlbedoMap;
|
||||||
case "map_Ks": return SpecularMap;
|
case "map_Ks": return SpecularMap;
|
||||||
@ -236,95 +236,102 @@ GetMapProp(u8[] str)
|
|||||||
case "map_d": return AlphaMap;
|
case "map_d": return AlphaMap;
|
||||||
case "map_bump":
|
case "map_bump":
|
||||||
case "bump": return BumpMap;
|
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 "disp": return DisplacementMap;
|
||||||
case "decal": return Stencil;
|
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 "Pr": return Roughness;
|
||||||
case "map_Pr": return RoughnessMap;
|
|
||||||
case "Pm": return Metallic;
|
case "Pm": return Metallic;
|
||||||
case "map_Pm": return MetallicMap;
|
|
||||||
case "Pc": return ClearcoatThickness;
|
case "Pc": return ClearcoatThickness;
|
||||||
case "Pcr": return ClearcoatRoughness;
|
case "Pcr": return ClearcoatRoughness;
|
||||||
case "Ke": return Emissive;
|
|
||||||
case "map_Ke": return EmissiveMap;
|
|
||||||
case "aniso": return Anisotropy;
|
case "aniso": return Anisotropy;
|
||||||
case "anisor": return AnisotropyMap;
|
case "Ps": return Sheen;
|
||||||
case "norm": return NormalMap;
|
|
||||||
default: return None;
|
default: return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
M3DColor(u32 type)
|
|
||||||
{
|
|
||||||
return type == m3dp_Kd ||
|
|
||||||
type == m3dp_Ka ||
|
|
||||||
type == m3dp_Ks ||
|
|
||||||
type == m3dp_Ke ||
|
|
||||||
type == m3dp_Tf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MatColor
|
MatColor
|
||||||
M3DMatColor(u32 type)
|
GetMatColor(MatProp prop)
|
||||||
{
|
{
|
||||||
switch(type) with(MatColor)
|
switch(prop) with(MatProp)
|
||||||
{
|
{
|
||||||
case m3dp_Kd: return Albedo;
|
case Ambient: return MatColor.Ambient;
|
||||||
case m3dp_Ka: return Ambient;
|
case Albedo: return MatColor.Albedo;
|
||||||
case m3dp_Ks: return Specular;
|
case Specular: return MatColor.Specular;
|
||||||
case m3dp_Ke: return Emissive;
|
case Transmission: return MatColor.Transmission;
|
||||||
case m3dp_Tf: return Transmission;
|
case Emissive: return MatColor.Emissive;
|
||||||
default: assert(false, "Unknown M3D MatColor");
|
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
|
MatFloat
|
||||||
M3DMatFloat(u32 type)
|
GetMatFloat(MatProp prop)
|
||||||
{
|
{
|
||||||
switch(type) with(MatFloat)
|
switch(prop) with(MatProp)
|
||||||
{
|
{
|
||||||
case m3dp_Ns: return SpecularExp;
|
case SpecularExp: return MatFloat.SpecularExp;
|
||||||
case m3dp_Km: return Bump;
|
case Transparency:
|
||||||
case m3dp_d: return Alpha;
|
case Dissolve: return MatFloat.Alpha;
|
||||||
case m3dp_Pr: return Roughness;
|
case OpticalDensity: return MatFloat.OpticalDensity;
|
||||||
case m3dp_Pm: return Metallic;
|
case Roughness: return MatFloat.Roughness;
|
||||||
case m3dp_Ps: return Sheen;
|
case Metallic: return MatFloat.Metallic;
|
||||||
case m3dp_Ni: return OpticalDensity;
|
case ClearcoatThickness: return MatFloat.ClearcoatThickness;
|
||||||
case m3dp_Nt: return FaceThickness;
|
case ClearcoatRoughness: return MatFloat.ClearcoatRoughness;
|
||||||
default: assert(false);
|
case Anisotropy: return MatFloat.Anisotropy;
|
||||||
|
case Sheen: return MatFloat.Sheen;
|
||||||
|
default: assert(false, "Unknown MatProp to MatFloat conversion");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
MatMap
|
||||||
M3DMap(u32 type)
|
GetMatMap(MatProp prop)
|
||||||
{
|
{
|
||||||
return type == m3dp_map_Kd ||
|
switch(prop) with(MatProp)
|
||||||
type == m3dp_map_Ka ||
|
{
|
||||||
type == m3dp_map_Ks ||
|
case AmbientMap: return MatMap.Ambient;
|
||||||
type == m3dp_map_Ns ||
|
case AlbedoMap: return MatMap.Albedo;
|
||||||
type == m3dp_map_Ke ||
|
case SpecularMap: return MatMap.Specular;
|
||||||
type == m3dp_map_Tf ||
|
case SpecularHighlightMap: return MatMap.SpecularHighlight;
|
||||||
type == m3dp_map_Km ||
|
case AlphaMap: return MatMap.Alpha;
|
||||||
type == m3dp_map_D ||
|
case BumpMap: return MatMap.Bump;
|
||||||
type == m3dp_map_N ||
|
case RoughnessMap: return MatMap.Roughness;
|
||||||
type == m3dp_map_Pr ||
|
case MetallicMap: return MatMap.Metallic;
|
||||||
type == m3dp_map_Pm ||
|
case EmissiveMap: return MatMap.Emissive;
|
||||||
type == m3dp_map_Ps ||
|
case SheenMap: return MatMap.Sheen;
|
||||||
type == m3dp_map_Ni ||
|
case NormalMap: return MatMap.Normal;
|
||||||
type == m3dp_map_Nt;
|
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
|
debug
|
||||||
@ -494,7 +501,7 @@ else
|
|||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
MatProp prop = GetMapProp(cast(u8[])r"Ka");
|
MatProp prop = GetMatProp("Ka");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
external/m3d/m3d.c
vendored
3
external/m3d/m3d.c
vendored
@ -1,3 +0,0 @@
|
|||||||
#define M3D_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "m3d.h"
|
|
||||||
6574
external/m3d/m3d.h
vendored
6574
external/m3d/m3d.h
vendored
File diff suppressed because it is too large
Load Diff
11
includes.c
11
includes.c
@ -1,4 +1,4 @@
|
|||||||
#pragma attribute(push, nogc, nothrow)
|
//#pragma attribute(push, nogc, nothrow)
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
# include <xcb/xcb.h>
|
# include <xcb/xcb.h>
|
||||||
@ -16,13 +16,10 @@
|
|||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
|
||||||
#include "external/stb/stb_image.h"
|
#include "external/stb/stb_image.h"
|
||||||
|
|
||||||
#define M3D_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include "external/m3d/m3d.h"
|
|
||||||
|
|
||||||
#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 TINYOBJ_LOADER_C_IMPLEMENTATION
|
||||||
|
#include "external/tinyobjloader/tinyobj_loader_c.h"
|
||||||
|
|||||||
315
packer.d
315
packer.d
@ -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.stdio;
|
||||||
import std.string;
|
import std.string;
|
||||||
import std.file;
|
import std.file;
|
||||||
@ -6,10 +12,10 @@ import std.path;
|
|||||||
import std.traits;
|
import std.traits;
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
import std.json;
|
import std.conv;
|
||||||
|
import std.array;
|
||||||
|
|
||||||
AssetType[string] Lookup = [
|
AssetType[string] Lookup = [
|
||||||
".m3d": AT.ModelM3D,
|
|
||||||
".obj": AT.ModelObj,
|
".obj": AT.ModelObj,
|
||||||
".png": AT.Texture,
|
".png": AT.Texture,
|
||||||
".jpg": AT.Texture,
|
".jpg": AT.Texture,
|
||||||
@ -25,10 +31,30 @@ struct Texture
|
|||||||
u32 ch;
|
u32 ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MeshGroup
|
||||||
|
{
|
||||||
|
u32 start;
|
||||||
|
u32 length;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MeshIdx
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 v, n, uv;
|
||||||
|
};
|
||||||
|
u32[3] arr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct Model
|
struct Model
|
||||||
{
|
{
|
||||||
|
Vertex[] v;
|
||||||
|
u32[] idx;
|
||||||
MaterialData[] mats;
|
MaterialData[] mats;
|
||||||
|
MeshGroup[] meshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 g_asset_count = 0;
|
u64 g_asset_count = 0;
|
||||||
@ -222,29 +248,286 @@ InitModelHeader()
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
Model
|
string[][]
|
||||||
ConvertM3D(u8[] data)
|
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;
|
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];
|
string[][] tokens = TokenizeLines(data);
|
||||||
foreach(mat; mats)
|
|
||||||
{
|
|
||||||
MaterialData matd;
|
|
||||||
m3dp_t[] props = mat.prop[0 .. mat.numprop];
|
|
||||||
|
|
||||||
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;
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
3
test.sh
3
test.sh
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
name="Test_Runner"
|
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
|
rm $name.o
|
||||||
./$name
|
./$name
|
||||||
rm $name
|
rm $name
|
||||||
|
|||||||
340
test/sponza.mtl
Executable file
340
test/sponza.mtl
Executable 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
154707
test/sponza.obj
Executable file
File diff suppressed because it is too large
Load Diff
11
util.d
11
util.d
@ -123,6 +123,17 @@ GB(u64 v)
|
|||||||
return MB(v) * 1024;
|
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
|
pragma(inline) void
|
||||||
ConvertColor(Vec4 *dst, u32 src)
|
ConvertColor(Vec4 *dst, u32 src)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user