#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 defines; for(std::map::iterator it = shaderDefines.begin(); it != shaderDefines.end(); it++) { if((compileFlags & it->first) != 0) { defines.push_back(IMacroDefine(it->second)); } } resource_ptr 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 defines; for(std::map::iterator it = shaderDefines.begin(); it != shaderDefines.end(); it++) { if((compileFlags & it->first) != 0) { defines.push_back(IMacroDefine(it->second)); } } resource_ptr 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(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(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; } }