dlib/assets.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");
}
}