509 lines
8.6 KiB
D
509 lines
8.6 KiB
D
module dlib.assets;
|
|
|
|
import includes;
|
|
import dlib.aliases;
|
|
import dlib.util;
|
|
import dlib.alloc;
|
|
|
|
import std.file;
|
|
import std.stdio;
|
|
import std.exception;
|
|
|
|
File Asset_File;
|
|
|
|
FileHeader Asset_Header;
|
|
|
|
AssetInfo[] Asset_Info;
|
|
|
|
u8[][] Asset_Data;
|
|
|
|
const u32 FILE_VERSION = 3;
|
|
const u32 MODEL_VERSION = 2;
|
|
|
|
enum AssetType : u32
|
|
{
|
|
None,
|
|
ModelObj,
|
|
Shader,
|
|
Texture,
|
|
}
|
|
|
|
alias AT = AssetType;
|
|
|
|
struct FileHeader
|
|
{
|
|
u32 magic;
|
|
u32 file_version;
|
|
u64 asset_count;
|
|
u64 asset_info_offset;
|
|
}
|
|
|
|
struct ModelHeader
|
|
{
|
|
u32 magic;
|
|
u32 model_version;
|
|
u64 vertex_count;
|
|
u64 vertex_offset;
|
|
u64 index_count;
|
|
u64 index_offset;
|
|
u64 material_count;
|
|
u64 material_offset;
|
|
u64 texture_count;
|
|
u64 texture_offset;
|
|
}
|
|
|
|
struct Vertex
|
|
{
|
|
Vec4 color;
|
|
Vec4 tangent;
|
|
Vec3 pos;
|
|
Vec3 normal;
|
|
Vec2 uv;
|
|
}
|
|
|
|
struct ModelData
|
|
{
|
|
Vertex[] vertices;
|
|
u32[] indices;
|
|
MaterialData[] materials;
|
|
TextureInfo[] textures;
|
|
}
|
|
|
|
struct MaterialData
|
|
{
|
|
string name;
|
|
Vec3[MatColor.max] colors;
|
|
string[MatMap.max] maps;
|
|
f32[MatFloat.max] props = 0.0;
|
|
IllumModel illum;
|
|
}
|
|
|
|
struct TextureInfo
|
|
{
|
|
string name;
|
|
u32 id;
|
|
}
|
|
|
|
struct TextureHeader
|
|
{
|
|
u64 str_length;
|
|
u64 str_offset;
|
|
u32 texture_id;
|
|
}
|
|
|
|
struct ModelMeta
|
|
{
|
|
u64 index_count;
|
|
}
|
|
|
|
struct TexData
|
|
{
|
|
void* data;
|
|
TexMeta meta;
|
|
}
|
|
|
|
struct TexMeta
|
|
{
|
|
u32 w;
|
|
u32 h;
|
|
u32 ch;
|
|
}
|
|
|
|
struct AssetInfo
|
|
{
|
|
u64 hash;
|
|
u64 offset;
|
|
u64 length;
|
|
AssetType type;
|
|
}
|
|
|
|
enum MatProp
|
|
{
|
|
None,
|
|
Ambient,
|
|
Albedo,
|
|
Specular,
|
|
SpecularExp,
|
|
Dissolve, // Transparency 1.0 -> opaque
|
|
Transparency, // Transparency 0.0 -> opaque
|
|
Transmission,
|
|
OpticalDensity,
|
|
Illumination,
|
|
AmbientMap,
|
|
AlbedoMap,
|
|
SpecularMap,
|
|
SpecularHighlightMap,
|
|
AlphaMap,
|
|
BumpMap,
|
|
DisplacementMap,
|
|
Stencil,
|
|
Roughness,
|
|
RoughnessMap,
|
|
Metallic,
|
|
MetallicMap,
|
|
Sheen,
|
|
SheenMap,
|
|
ClearcoatThickness,
|
|
ClearcoatRoughness,
|
|
Emissive,
|
|
EmissiveMap,
|
|
Anisotropy,
|
|
AnisotropyMap,
|
|
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
|
|
GetMatProp(string str)
|
|
{
|
|
switch(str) with(MatProp)
|
|
{
|
|
// Vec3
|
|
case "Ka": return Ambient;
|
|
case "Kd": return Albedo;
|
|
case "Ks": return Specular;
|
|
case "Tf": return Transmission;
|
|
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;
|
|
case "map_Ns": return SpecularHighlightMap;
|
|
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 "Pm": return Metallic;
|
|
case "Pc": return ClearcoatThickness;
|
|
case "Pcr": return ClearcoatRoughness;
|
|
case "aniso": return Anisotropy;
|
|
case "Ps": return Sheen;
|
|
|
|
default: return None;
|
|
}
|
|
}
|
|
|
|
MatColor
|
|
GetMatColor(MatProp prop)
|
|
{
|
|
switch(prop) with(MatProp)
|
|
{
|
|
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");
|
|
}
|
|
}
|
|
|
|
MatFloat
|
|
GetMatFloat(MatProp prop)
|
|
{
|
|
switch(prop) with(MatProp)
|
|
{
|
|
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");
|
|
}
|
|
}
|
|
|
|
MatMap
|
|
GetMatMap(MatProp prop)
|
|
{
|
|
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
|
|
{
|
|
void
|
|
SetAssetsDir(string dir)
|
|
{
|
|
assert(ChDir(dir));
|
|
}
|
|
|
|
u8[]
|
|
LoadAssetData(Arena* arena, string name)
|
|
{
|
|
File f;
|
|
try
|
|
{
|
|
f = File(name, "rb");
|
|
}
|
|
catch (ErrnoException e)
|
|
{
|
|
assert(false, "Unable to open file");
|
|
}
|
|
|
|
u8[] mem = Alloc!(u8)(arena, f.size());
|
|
return f.rawRead(mem);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
void
|
|
OpenAssetPack(string file_path)
|
|
{
|
|
if(!Asset_Pack_Opened)
|
|
{
|
|
bool success = true;
|
|
|
|
// TODO: replace this with something that doesn't throw an exception and figure out if this is the best way to handle thing (probably isnt)
|
|
try
|
|
{
|
|
Asset_File = File(file_path, "rb");
|
|
}
|
|
catch (ErrnoException e)
|
|
{
|
|
Logf("OpenAssetPack failure: Unable to open file %s", file_path);
|
|
assert(false, "Unable to open asset pack file");
|
|
}
|
|
|
|
FileHeader[1] header_arr;
|
|
|
|
Asset_File.rawRead(header_arr);
|
|
|
|
Asset_Header = header_arr[0];
|
|
|
|
Asset_Info = Alloc!(AssetInfo)(Asset_Header.asset_count);
|
|
Asset_Data = Alloc!(u8[])(Asset_Header.asset_count);
|
|
|
|
assert(Asset_Header.file_version == FILE_VERSION, "OpenAssetPack failure: file version incorrect");
|
|
|
|
Asset_File.seek(Asset_Header.asset_info_offset);
|
|
|
|
Asset_File.rawRead(Asset_Info);
|
|
}
|
|
}
|
|
|
|
pragma(inline) void
|
|
CheckAssetPack()
|
|
{
|
|
assert(Asset_Pack_Opened);
|
|
}
|
|
|
|
AssetInfo
|
|
GetAssetInfo(string name)
|
|
{
|
|
CheckAssetPack();
|
|
|
|
u64 hash = Hash(name);
|
|
|
|
AssetInfo asset_info;
|
|
foreach(i, info; Asset_Info)
|
|
{
|
|
if(info.hash == hash)
|
|
{
|
|
asset_info = info;
|
|
break;
|
|
}
|
|
}
|
|
|
|
assert(asset_info.hash != 0, "GetAssetInfo failure: unable to find matching asset");
|
|
|
|
return asset_info;
|
|
}
|
|
|
|
u8[]
|
|
LoadAssetData(Arena* arena, string name)
|
|
{
|
|
CheckAssetPack();
|
|
|
|
u64 hash = Hash(name);
|
|
u8[] data = null;
|
|
|
|
foreach(i, info; Asset_Info)
|
|
{
|
|
if(info.hash == hash)
|
|
{
|
|
data = Alloc!(u8)(arena, info.length);
|
|
Asset_File.seek(info.offset);
|
|
Asset_File.rawRead(data);
|
|
assert(data != null && data.length == info.length, "LoadAssetData failure: Asset data loaded incorrectly");
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
u8[]
|
|
LoadAssetData(string name)
|
|
{
|
|
CheckAssetPack();
|
|
|
|
u64 hash = Hash(name);
|
|
u8[] data = null;
|
|
|
|
foreach(i, info; Asset_Info)
|
|
{
|
|
if(info.hash == hash)
|
|
{
|
|
if(Asset_Data[i].ptr == null)
|
|
{
|
|
Asset_Data[i] = Alloc!(u8)(info.length);
|
|
Asset_File.seek(info.offset);
|
|
Asset_File.rawRead(Asset_Data[i]);
|
|
assert(Asset_Data[i] != null && Asset_Data[i].length == info.length, "LoadAssetData failure: Asset data loaded incorrectly.");
|
|
}
|
|
|
|
data = Asset_Data[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
void
|
|
UnloadAssetData(string name)
|
|
{
|
|
u64 hash = Hash(name);
|
|
|
|
foreach(i, info; Asset_Info)
|
|
{
|
|
if(info.hash == hash)
|
|
{
|
|
if(Asset_Data[i] != null)
|
|
{
|
|
Free(Asset_Data[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
{
|
|
{
|
|
MatProp prop = GetMatProp("Ka");
|
|
}
|
|
}
|
|
|
|
|