Files

639 lines
18 KiB
C++
Raw Permalink Normal View History

2025-05-13 02:46:21 +03:00
#include "ResourceManager.h"
#include "render/IMaterial.h"
namespace LifeGraphics
{
struct VMFHEADER
{
int fileVersion;
int fileSignature;
int expPosition;
int expNormal;
int expTexcoord;
int expTangent;
int expBiNormal;
int expVertexColor;
int expSkin;
int vertexCount;
int faceCount;
int bonesCount;
int vertexSize;
};
/*void ResourceManager::getMaterial(String& path, IMaterial** material)
{
pugi::xml_document doc;
char* data;
Core::IFile* file = getFileSystem()->GetFile(path);
Core::IDataStream* stm = file->OpenRead();
data = new char[stm->length()];
stm->Read(data, stm->length());
doc.load_buffer(data, stm->length());
printf("%s\n", doc.child("LifeMaterial").attribute("Emissive").value());
stm->Close();
}*/
ResourceManager::ResourceManager()
{
lastId = 0;
lastTimeUpdated = 0.0f;
updatePeriod = 5.0f;
LifeCore::RootFolder* root = new LifeCore::RootFolder();
root->Name = String(_text("root"));
fileSystem = new LifeCore::IFileSystem(root);
fileSystem->StorageName = String(_text("root"));
shaderDefines[EF_LIGHTING] = "DEF_LIGHTING";
shaderDefines[EF_NORMAL_MAP] = "DEF_NORMAL_MAP";
shaderDefines[EF_PARALLAX_MAP] = "DEF_PARALLAX_MAP";
shaderDefines[EF_ENVIRONMENT_MAP] = "DEF_ENVIRONMENT_MAP";
shaderDefines[EF_SPECULAR_MAP] = "DEF_SPECULAR_MAP";
shaderDefines[EF_EMISSIVE_MAP] = "DEF_EMISSIVE_MAP";
shaderDefines[EF_G_BUFFER_PREPASS] = "DEF_G_PREPASS";
shaderDefines[EF_SKINNING] = "DEF_SKINNING";
shaderDefines[EF_LINEAR_DEPTH] = "DEF_LINEAR_DEPTH";
shaderDefines[EF_ALPHA_TEST] = "DEF_ALPHA_TEST";
shaderCompiler = new ShaderGraphCompilerHLSL();
shaderFactory = IShaderGraphNodeFactory::me();
IShaderFactorySource::Register(shaderFactory);
IShaderGraph* defaultGraph = new IShaderGraph(shaderFactory);
IShaderGraphNode* mat = defaultGraph->AddNode("Material");
IShaderGraphNode* mat_diffuse = defaultGraph->AddNode("ConstFloat4");
IShaderGraphNodePort* port_diffuse = mat->GetInputPortByName("Diffuse");
port_diffuse->MakeLink(port_diffuse, mat_diffuse->GetOutputPortByID(0));
LifeCore::IProperty* diffuse;
if(mat_diffuse->GetPropertyByAttribute("Name", "Value", &diffuse)){
diffuse->Set(LifeMath::float4(0,1,0,1));
}
defaultMaterial = new IMaterial(defaultGraph, shaderCompiler);
}
ResourceManager::~ResourceManager()
{
}
void ResourceManager::CollectGarbage(float dt)
{
}
void ResourceManager::ReleaseResources()
{
shaderDefines.clear();
for(UINT i = 0; i< contentProviders.size(); i++)
{
delete contentProviders[i];
}
delete fileSystem;
textureCache.Release();
vsCache.Release();
psCache.Release();
}
void ResourceManager::initialize()
{
}
long ResourceManager::NextID()
{
return lastId++;
}
void ResourceManager::SetCentralDirectory(const String& dir)
{
centralDir = dir;
LifeCore::IContentProvider* fsProvider = new LifeCore::IFSContentProvider(dir);
MountContentProvider(fsProvider, String(_text("root")));
}
IShader* ResourceManager::getShader(IMaterial* material, int adFlags, SHADER_TYPE type)
{
assert(false && "getShader is obsolete!\n");
/*int flags = adFlags;
if(material->normalMapping)
flags |= EF_NORMAL_MAP;
if(material->lighting)
flags |= EF_LIGHTING;
if(material->environmentReflection)
flags |= EF_ENVIRONMENT_MAP;
if(material->bSpecularMapping)
flags |= EF_SPECULAR_MAP;
if(material->AlphaTest)
flags |= EF_ALPHA_TEST;
if(type == ST_PS)
return GetPixelShader(flags);
else
return GetVertexShader(flags);*/
return nullptr;
}
IMaterial* ResourceManager::getDefaultMaterial()
{
return defaultMaterial;
assert(false && "getDefaultMaterial is obsolete!\n");
/*if(!DefaultMaterial)
{
DefaultMaterial = new IMaterial();
memset(DefaultMaterial,0, sizeof(IMaterial));
DefaultMaterial->castShadows = false;
DefaultMaterial->diffuseMap = GetTexture(AS_STRING("root/Data/Textures/NoTex.dds"));
setupMaterialShaders(EF_LIGHTING, DefaultMaterial);
}*/
}
LifeCore::IFileSystem* ResourceManager::getFileSystem()
{
return fileSystem;
}
void ResourceManager::MountContentProvider(LifeCore::IContentProvider* prov, const String& mountPoint)
{
contentProviders.push_back(prov);
fileSystem->GetRootFolder()->AddFolder(prov->getFileSystem()->GetRootFolder());
LifeCore::CLog::me()->Write(String(_text("Mount point is not used! SHOULD BE FIXED!\nResourceManager::MountContentProvider at")));
LifeCore::CLog::me()->Write(mountPoint.c_str());
}
texture_ptr ResourceManager::GetTexture(const String& path)
{
if(path == STR(""))
return nullptr;
String name = GetFileName(path, _text("/"));
texture_ptr ptr;
if(textureCache.GetResource(name, ptr))
return ptr.ptr();
else
{
LifeCore::IFile* texFile;
ResourceManager::me()->getFileSystem()->GetFile(path, &texFile);
LifeCore::IDataStreamPtr stm = texFile->OpenRead();
ITexture2D* texture = CG::me()->GetRenderer()->LoadTexture2D(stm);
texture->Name = name;
texture_ptr texPtr(texture);
textureCache.push_back(texPtr);
return texPtr;
}
}
void ResourceManager::ReadBitmap(String& path, void** pOut, IBitmapInfo** info)
{
LifeCore::IFile* file;
ResourceManager::me()->getFileSystem()->GetFile(path, &file);
LifeCore::IDataStreamPtr stm = file->OpenRead();
BITMAPFILEHEADER bitmapFileHeader;
BITMAPINFOHEADER bitmapInfoHeader;
//read the bitmap file header
stm->Read(&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
//verify that this is a bmp file by check bitmap id
if (bitmapFileHeader.bfType !=0x4D42)
{
return;
}
//read the bitmap info header
stm->Read(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
//move file point to the begging of bitmap data
stm->Seek(bitmapFileHeader.bfOffBits);
//allocate enough memory for the bitmap image data
char* data = new char[bitmapInfoHeader.biWidth * bitmapInfoHeader.biHeight * bitmapInfoHeader.biBitCount / 8];
//read in the bitmap image data
stm->Read(data, bitmapInfoHeader.biWidth * bitmapInfoHeader.biHeight * bitmapInfoHeader.biBitCount / 8);
IBitmapInfo* i = new IBitmapInfo();
i->Width = bitmapInfoHeader.biWidth;
i->Height = bitmapInfoHeader.biHeight;
i->Bpp = bitmapInfoHeader.biBitCount / 8;
*(pOut) = data;
*(info) = i;
}
IShader* ResourceManager::GetPixelShader(int compileFlags)
{
String shaderPath(_text("Core.psh"));
char name[16];
_itoa_s(compileFlags, name, 10);
String sName(name);
//create defines list
std::vector<IMacroDefine> defines;
for(std::map<EFFECT_FLAGS, std::string>::iterator it = shaderDefines.begin(); it != shaderDefines.end(); it++)
{
if((compileFlags & it->first) != 0)
{
defines.push_back(IMacroDefine(it->second));
}
}
resource_ptr<IShader> ptr;
if(psCache.GetResource(sName, ptr))
return ptr.ptr();
else
{
LifeCore::IFile* file;
ResourceManager::me()->getFileSystem()->GetFile(STR("root/Data/Shaders/") + shaderPath, &file);
LifeCore::IDataStreamPtr stm = file->OpenRead();
IShader* s = CG::me()->GetRenderer()->CompilePixelShader(stm, &defines);
ptr.resetPtr(s);
ptr->Name = sName;
psCache.push_back(ptr);
return ptr.ptr();
}
defines.clear();
}
IShader* ResourceManager::GetVertexShader(int compileFlags)
{
String shaderPath(_text("Core.vsh"));
char name[16];
_itoa_s(compileFlags, name, 10);
String sName(name);
//create defines list
std::vector<IMacroDefine> defines;
for(std::map<EFFECT_FLAGS, std::string>::iterator it = shaderDefines.begin(); it != shaderDefines.end(); it++)
{
if((compileFlags & it->first) != 0)
{
defines.push_back(IMacroDefine(it->second));
}
}
resource_ptr<IShader> ptr;
if(vsCache.GetResource(sName, ptr))
return ptr.ptr();
else
{
LifeCore::IFile* file;
ResourceManager::me()->getFileSystem()->GetFile(STR("root/Data/Shaders/") + shaderPath, &file);
LifeCore::IDataStreamPtr stm = file->OpenRead();
IShader* s = CG::me()->GetRenderer()->CompileVertexShader(stm, &defines);
ptr.resetPtr(s);
ptr->Name = sName;
vsCache.push_back(ptr);
return ptr.ptr();
}
defines.clear();
}
IMesh* ResourceManager::GetMesh(const String& path)
{
LifeCore::IFile* file;
ResourceManager::me()->getFileSystem()->GetFile(path, &file);
printf("Trololo %s\n", file->FileName.c_str());
LifeCore::IDataStreamPtr stm = file->OpenRead();
printf("Trololo %i\n", stm->Length());
VMFHEADER header;
stm->Read(&header, sizeof(VMFHEADER));
char* vertexData = new char[header.vertexCount * header.vertexSize];
stm->Read(vertexData, header.vertexCount * header.vertexSize);
bool computeBoundingBox = true;
LifeCore::BoundingBox3D bbox;
if(computeBoundingBox)
{
float* ptr = reinterpret_cast<float*>(vertexData);
float minX = ptr[0];
float minY = ptr[1];
float minZ = ptr[2];
float maxX = minX;
float maxY = minY;
float maxZ = minZ;
for(int i = 0; i< header.vertexCount; i++)
{
ptr = reinterpret_cast<float*>(vertexData + (header.vertexSize * i));
if(minX > ptr[0])
minX = ptr[0];
if(minY > ptr[1])
minY = ptr[1];
if(minZ > ptr[2])
minZ = ptr[2];
if(maxX < ptr[0])
maxX = ptr[0];
if(maxY < ptr[1])
maxY = ptr[1];
if(maxZ < ptr[2])
maxZ = ptr[2];
}
bbox.resize(LifeMath::float3(minX, minY, minZ), LifeMath::float3(maxX, maxY, maxZ));
}
int submeshCount= 0;
stm->Read(&submeshCount, 4);
int* submeshData = new int[2*submeshCount];
stm->Read(submeshData, 2*submeshCount*4);
//IShader* vs = GetVertexShader(EFFECT_FLAGS::EF_LIGHTING);
//IShader* ps = GetPixelShader(EFFECT_FLAGS::EF_LIGHTING);
int isShortIndices = 0;
stm->Read(&isShortIndices, 4);
int indexSize = isShortIndices == 1 ? 2 : 4;
char* indexData = new char[header.faceCount * 3 * indexSize];
stm->Read(indexData, header.faceCount * 3 * indexSize);
Skeleton sk;
if(header.expSkin)
{
sk.BonesCount = header.bonesCount;
//add system root bone
Bone* b = new Bone(-1, "Root", -2);
QuatIdentity(b->LocalTransform.Rotation);
b->LocalTransform.Translation = LifeMath::float3(0.0f,0.0f,0.0f);
QuatIdentity(b->BaseTransform.Rotation);
b->BaseTransform.Translation = LifeMath::float3(0.0f,0.0f,0.0f);
Mat4x4Identity(&b->TransformMatrix);
Mat4x4Identity(&b->AbsoluteMatrix);
sk.AddBone(b);
//read bones hierarchy
for (int j = 0; j < header.bonesCount; j++)
{
int bId;
stm->Read(&bId, sizeof(int));
int pId;
stm->Read(&pId, sizeof(int));
char b_nChars[33];
stm->Read(b_nChars, 33);
std::string bName = std::string(b_nChars);
Bone* b = new Bone(bId, bName, pId);
sk.AddBone(b);
}
sk.rebuildLinks();
for (int j = 0; j < header.bonesCount; j++)
{
int bId;
stm->Read(&bId, sizeof(int));
LifeMath::float3 pos;
stm->Read(&pos, sizeof(LifeMath::float3));
LifeMath::Quaternion rot;
stm->Read(&rot, sizeof(LifeMath::Quaternion));
BoneTransform transform;
transform.Translation = pos;
transform.Rotation = rot;
transform.boneId = bId;
Bone* cBone = sk.GetBone(bId);
cBone->BaseTransform = transform;
if (bId == 0)
{
cBone->LocalTransform = transform;
cBone->InitialTransform = transform;
cBone->BaseTransform = transform;
}
else
{
BoneTransform pt = cBone->Parent->BaseTransform;
//LifeMath::float4x4 mParent = Matrix4x4.Invert(Matrix4x4.RotationQuaternion(pt.Rotation) * Matrix4x4.Translation(pt.Translation));
LifeMath::float4x4 mParent = pt.GetMatrixInvert();
LifeMath::float4x4 mBone = transform.GetMatrix();
LifeMath::float4x4 mabs = mBone * mParent;
LifeMath::float3 pos2, scl2;
LifeMath::Quaternion rot2;
LifeMath::Mat4x4Decompose(mabs, pos2, scl2, rot2);
BoneTransform bt;
bt.Translation = pos2;
bt.Rotation = rot2;
bt.boneId = bId;
//cBone->LocalTransform = bt;
cBone->LocalTransform = bt;
cBone->InitialTransform = transform;
cBone->BaseTransform = transform;
}
}
}
texture_ptr defaultTex = GetTexture("root/Data/Textures/basic_floor_s.dds");
texture_ptr defaultNorm = GetTexture("root/Data/Textures/basic_floor_s_ddn.dds");
GeometrySubset* subsets = new GeometrySubset[submeshCount];
for(int i = 0; i< submeshCount; i++)
{
subsets[i].Offset = submeshData[i * 2 + 0];
subsets[i].Length = submeshData[i * 2 + 1];
printf("Has skin: %i\n", header.expSkin);
/*if(header.expSkin)
setupMaterialShaders(EF_LIGHTING | EF_SKINNING, &subsets[i].material);
else
setupMaterialShaders(EF_LIGHTING, &subsets[i].material);
subsets[i].material.diffuseMap = defaultTex;
subsets[i].material.normalMap = defaultNorm;*/
}
IVertexBuffer* vb = CG::me()->GetRenderer()->CreateVertexBuffer(header.vertexCount * header.vertexSize, vertexData, header.vertexSize);
delete[] vertexData;
IIndexBuffer* ib = CG::me()->GetRenderer()->CreateIndexBuffer(header.faceCount * 3 * indexSize,indexData, isShortIndices);
delete[] indexData;
delete[] submeshData;
IInputElement* elements;
int numElements = 5;
if(header.expSkin)
{
numElements = 7;
elements = new IInputElement[numElements];
elements[0] = IInputElement("POSITION", 0, 0, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[1] = IInputElement("TEXCOORD", 0, 12, FORMAT_R32G32_FLOAT, 0, 0, 0);
elements[2] = IInputElement("NORMAL", 0, 20, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[3] = IInputElement("TANGENT", 0, 32, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[4] = IInputElement("BINORMAL", 0, 44, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[5] = IInputElement("BLENDINDICES", 0, 56, FORMAT_R32G32B32A32_FLOAT, 0, 0, 0);
elements[6] = IInputElement("BLENDWEIGHT", 0, 72, FORMAT_R32G32B32A32_FLOAT, 0, 0, 0);
}
else
{
elements = new IInputElement[numElements];
elements[0] = IInputElement("POSITION", 0, 0, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[1] = IInputElement("TEXCOORD", 0, 12, FORMAT_R32G32_FLOAT, 0, 0, 0);
elements[2] = IInputElement("NORMAL", 0, 20, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[3] = IInputElement("TANGENT", 0, 32, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
elements[4] = IInputElement("BINORMAL", 0, 44, FORMAT_R32G32B32_FLOAT, 0, 0, 0);
}
IShader* ds;
if(header.expSkin)
ds = GetVertexShader(EF_LIGHTING | EF_SKINNING);
else
ds = GetVertexShader(EF_LIGHTING);
IInputLayout* layout = CG::me()->GetRenderer()->CreateInputLayout(elements, numElements, ds);
delete[] elements;
IMesh* mesh = new IMesh(vb, ib, subsets, layout, header.expSkin, bbox, file->FileName);
mesh->Id = NextID();
mesh->subsetCount = submeshCount;
if(header.expSkin)
{
mesh->skin.bonesCount = header.bonesCount;
sk.UpdateTransform();
mesh->skin.skeleton = sk;
mesh->skin.controller.skeleton = &mesh->skin.skeleton;
}
return mesh;
}
void ResourceManager::setupMaterialShaders(int shaderFlags, IMaterial* material)
{
//printf("OMGNAH");
// material->pixelShader = GetPixelShader(shaderFlags);
// material->vertexShader = GetVertexShader(shaderFlags);
assert(false && "setupMaterialShaders is obsolete!");
//material->g_buffer_pass_ps = GetPixelShader(shaderFlags | EF_G_BUFFER_PREPASS);
//material->g_buffer_pass_vs = GetVertexShader(shaderFlags | EF_G_BUFFER_PREPASS);
}
Light* ResourceManager::CreatePointLight(const LifeMath::float3& position, float range)
{
Light* l = new Light(LT_POINT);
l->getTransform()->SetPosition(position);
l->setRange(range);
l->Id = NextID();
return l;
}
Light* ResourceManager::CreateDirectionalLight(const LifeMath::float3& direction)
{
Light* l = new Light(LT_DIRECTIONAL);
l->setDirection(direction);
l->Id = NextID();
return l;
}
Light* ResourceManager::CreateSpotLight(const LifeMath::float3& position, const LifeMath::float3& direction, float range, float innerAngle, float outerAngle)
{
Light* l = new Light(LT_SPOT);
l->getTransform()->SetPosition(position);
l->setRange(range);
l->setInnerAngle(innerAngle);
l->setOuterAngle(outerAngle);
l->setDirection(direction);
l->Id = NextID();
return l;
}
IShader* ResourceManager::CompileUserShaderPS(const String& path)
{
LifeCore::IFile* file;
if(SC_OK == ResourceManager::me()->getFileSystem()->GetFile(STR("root/Data/Shaders/") + path, &file))
{
//CLog::me()->
LifeCore::IDataStreamPtr stm = file->OpenRead();
IShader* s = CG::me()->GetRenderer()->CompilePixelShader(stm);
s->Name = GetFileName(path, String(_text("/")));
return s;
}
return 0;
}
IShader* ResourceManager::CompileUserShaderVS(const String& path)
{
LifeCore::IFile* file;
ResourceManager::me()->getFileSystem()->GetFile(STR("root/Data/Shaders/") + path, &file);
LifeCore::IDataStreamPtr stm = file->OpenRead();
IShader* s = CG::me()->GetRenderer()->CompileVertexShader(stm);
s->Name = GetFileName(path, String(_text("/")));
return s;
}
IShader* ResourceManager::CompileUserShaderPS(const char* pData, int length)
{
IShader* s = CG::me()->GetRenderer()->CompilePixelShader(pData, length);
s->Name = STR("system_ps");
return s;
}
IShader* ResourceManager::CompileUserShaderVS(const char* pData, int length)
{
IShader* s = CG::me()->GetRenderer()->CompileVertexShader(pData, length);
s->Name = STR("system_vs");
return s;
}
AnimationTrack* ResourceManager::LoadAnimatrionTrack(String& path)
{
LifeCore::IFile* file;
ResourceManager::me()->getFileSystem()->GetFile(path, &file);
LifeCore::IDataStreamPtr stm = file->OpenRead();
float sampleRate;
int framesCount, BonesCount;
stm->Read(&BonesCount, sizeof(int));
stm->Read(&framesCount, sizeof(int));
AnimationTrack* animationTrack = new AnimationTrack(framesCount);
animationTrack->Name = GetFileName(path, String(_text("/")));
int sr;
stm->Read(&sr, sizeof(int));
sampleRate = (float)sr;
//add all frames
for (int j = 0; j < framesCount; j++)
{
AnimationFrame frame((float)j / sampleRate);
frame.name = j;
//read bones keys
for (int i = 0; i < BonesCount; i++)
{
int bId;
stm->Read(&bId, sizeof(int));
BoneTransform transform;
stm->Read(&transform.Translation, sizeof(LifeMath::float3));
stm->Read(&transform.Rotation, sizeof(LifeMath::Quaternion));
transform.boneId = bId;
frame.addBoneTransform(transform);
}
animationTrack->setFrame(frame, j);
}
animationTrack->TrackTime = (float)(framesCount-1) / sampleRate;
return animationTrack;
}
}