#include "stdafx.h" #include "BLUImporter.h" #include "IFileSystem.h" #include "IResourceFactory.h" BluImporter::BluImporter(IEngine& argEngine) : m_Engine(argEngine) { } BluImportResult BluImporter::Load(const string16& argFileName) { BluImportResult lr_Result; m_CurrentPath = lr_Result.m_FileName = argFileName; int li_Pos = m_CurrentPath.rfind(_T("/")); if (li_Pos >= 0) m_CurrentPath = m_CurrentPath.substr(0, li_Pos + 1); else m_CurrentPath = _T(""); IFile* lr_File_ = m_Engine.get_FileSystem().Open(argFileName); if (lr_File_ == NULL) return lr_Result; char* lc_CurrentPos_ = lr_File_->get_Buffer(); try { // header std::string ls_FileTag = lr_File_->ReadString(); if (ls_FileTag != "BLUF") throw; int li_FileVersion = lr_File_->ReadInt(); // sections while (!lr_File_->IsEof()) { BluSectionType::Enumeration le_ObjectType = (BluSectionType::Enumeration)lr_File_->ReadInt(); if (le_ObjectType > BluSectionType::LastKnownType) throw _T("BLUImporter: Unknown object section detected."); std::string ls_ObjectName = lr_File_->ReadString(); if (ls_ObjectName.empty()) throw _T("BLUImporter: Objectname not set."); // content switch (le_ObjectType) { case BluSectionType::Mesh: this->ImportMesh(lr_File_, ls_ObjectName, lr_Result); break; case BluSectionType::Material: this->ImportMaterial(lr_File_, ls_ObjectName, lr_Result); break; case BluSectionType::Bone: this->ImportBone(lr_File_, ls_ObjectName, lr_Result); break; case BluSectionType::Animation: this->ImportAnimation(lr_File_, ls_ObjectName, lr_Result); break; } } // build bone hierarchy std::map::iterator lk_BonesIter = lr_Result.m_Bones.begin(); for (; lk_BonesIter != lr_Result.m_Bones.end(); ++lk_BonesIter) { BluImportedBone lr_Bone = lk_BonesIter->second; std::map::iterator lk_Found = lr_Result.m_Bones.find(lr_Bone.m_ParentName); if (lk_Found != lr_Result.m_Bones.end()) lr_Bone.m_Bone->set_Parent(lk_Found->second.m_Bone); } // add bone animations to bones std::map::iterator lk_AnimIter = lr_Result.m_Animations.begin(); for (; lk_AnimIter != lr_Result.m_Animations.end(); ++lk_AnimIter) { std::map::iterator lk_Found = lr_Result.m_Bones.find(lk_AnimIter->first); if (lk_Found != lr_Result.m_Bones.end()) { lk_Found->second.m_Bone->set_TransformationAnimation(lk_AnimIter->second); } } // collapse bone map to super parent bones only lk_BonesIter = lr_Result.m_Bones.begin(); for (; lk_BonesIter != lr_Result.m_Bones.end();) if (!lk_BonesIter->second.m_ParentName.empty()) lk_BonesIter = lr_Result.m_Bones.erase(lk_BonesIter); else { // create the boneindexlist structure while we are here lk_BonesIter->second.m_Bone->get_BoneIndexList(); ++lk_BonesIter; } if (lr_Result.m_Bones.size() > 1) throw _T("BLUImporter: Only one bone root allowed!"); // Create a default BoneController if (!lr_Result.m_Bones.empty()) { lr_Result.m_BoneController = &m_Engine.get_ResourceFactory().CreateOrFindBoneController(); lr_Result.m_BoneController->Initialize(*lr_Result.m_Bones.begin()->second.m_Bone); float lf_MaxDuration = 0.0f; for (lk_AnimIter = lr_Result.m_Animations.begin(); lk_AnimIter != lr_Result.m_Animations.end(); ++lk_AnimIter) lf_MaxDuration = lf_MaxDuration < lk_AnimIter->second->get_Duration() ? lk_AnimIter->second->get_Duration() : lf_MaxDuration; lr_Result.m_BoneController->RegisterSequence(L"all", 0.0f, lf_MaxDuration, true); } delete lr_File_; } catch (...) { delete lr_File_; throw; } lr_Result.m_SuccessfullyLoaded = true; return lr_Result; } BluModel BluImporter::Load(IEngine& argEngine, const string16& argFileName) { BluImporter lk_Importer(argEngine); BluImportResult lk_Result = lk_Importer.Load(argFileName); if (lk_Result.m_SuccessfullyLoaded) return lk_Result.GenerateRootCommandNode(argEngine); return BluModel(); } void BluImporter::ImportMesh(IFile* argFile, std::string argObjectName, BluImportResult& argResult) { std::string ls_MaterialName = argFile->ReadString(); unsigned int li_VertexCount = argFile->ReadInt(); int li_VertexElementCount = argFile->ReadInt(); unsigned int lui_VertexStride = 0; std::vector lk_VertexElements; for (int i = 0; i < li_VertexElementCount; ++i) { int vertexElementOldId = argFile->ReadInt(); VertexElement vertexElement(VertexElement::Position); switch (vertexElementOldId) { case 1: vertexElement = VertexElement(VertexElement::Position); break; case 3: vertexElement = VertexElement(VertexElement::Normal); break; case 8: vertexElement = VertexElement(VertexElement::Texture2D); break; case 11: vertexElement = VertexElement(VertexElement::Tangent); break; case 13: vertexElement = VertexElement(VertexElement::BlendIndices); break; case 14: vertexElement = VertexElement(VertexElement::BlendWeight); break; } lk_VertexElements.push_back(vertexElement); lui_VertexStride += vertexElement.m_Size; } ScopedBuffer lr_VertexData((char*)argFile->ReadDataArray(li_VertexCount * lui_VertexStride)); unsigned int li_IndexCount = argFile->ReadInt(); ScopedBuffer lr_IndexData((unsigned int*)argFile->ReadDataArray(li_IndexCount * sizeof(unsigned int))); string8 uniqueName = std::to_string8(argResult.m_FileName) + "." + argObjectName; IGeometryBuffer* lr_GeometryBuffer_ = &m_Engine.get_ResourceFactory().CreateOrFindGeometryBuffer(); lr_GeometryBuffer_->set_PrimitiveTopology(PrimitiveTopology::TriangleList); lr_GeometryBuffer_->SetVertexData(li_VertexCount, lui_VertexStride, (void*)lr_VertexData.Detach(), lk_VertexElements, false); lr_GeometryBuffer_->SetIndexData(li_IndexCount, (unsigned int*)lr_IndexData.Detach(), false); lr_GeometryBuffer_->ConvertToAdjacency(); BluImportedGeometryBuffer lr_Mesh; lr_Mesh.m_GeometryBuffer = lr_GeometryBuffer_; lr_Mesh.m_MaterialName = std::to_string8(argResult.m_FileName) + "." + ls_MaterialName; argResult.m_GeometryBuffers[uniqueName] = lr_Mesh; } void BluImporter::ImportMaterial(IFile* argFile, std::string argObjectName, BluImportResult& argResult) { string16 ls_DiffuseTexture = this->ConvertPath(argFile->ReadString()); string16 ls_SpecularTexture = this->ConvertPath(argFile->ReadString()); string16 ls_NormalTexture = this->ConvertPath(argFile->ReadString()); string16 ls_GlowTexture = this->ConvertPath(argFile->ReadString()); string16 ls_ReflectionTexture = this->ConvertPath(argFile->ReadString()); // not used yet D3DXVECTOR4 lk_AmbientColor; lk_AmbientColor.x = argFile->ReadFloat() / 255.0f; lk_AmbientColor.y = argFile->ReadFloat() / 255.0f; lk_AmbientColor.z = argFile->ReadFloat() / 255.0f; lk_AmbientColor.w = argFile->ReadFloat() / 255.0f; D3DXVECTOR4 lk_DiffuseColor; lk_DiffuseColor.x = argFile->ReadFloat() / 255.0f; lk_DiffuseColor.y = argFile->ReadFloat() / 255.0f; lk_DiffuseColor.z = argFile->ReadFloat() / 255.0f; lk_DiffuseColor.w = argFile->ReadFloat() / 255.0f; D3DXVECTOR4 lk_SpecularColor; lk_SpecularColor.x = argFile->ReadFloat() / 255.0f; lk_SpecularColor.y = argFile->ReadFloat() / 255.0f; lk_SpecularColor.z = argFile->ReadFloat() / 255.0f; lk_SpecularColor.w = argFile->ReadFloat() / 255.0f; D3DXVECTOR4 lk_EmissiveColor; lk_EmissiveColor.x = argFile->ReadFloat() / 255.0f; lk_EmissiveColor.y = argFile->ReadFloat() / 255.0f; lk_EmissiveColor.z = argFile->ReadFloat() / 255.0f; lk_EmissiveColor.w = argFile->ReadFloat() / 255.0f; float lf_SpecularLevel = argFile->ReadFloat(); float lf_Glossiness = argFile->ReadFloat(); string8 uniqueName = std::to_string8(argResult.m_FileName) + "." + argObjectName; IShaderParameterCollection* material = &m_Engine.get_ResourceFactory().CreateOrFindShaderParameterCollection(uniqueName); material->SetParameter("AmbientColor", lk_AmbientColor); material->SetParameter("DiffuseColor", lk_DiffuseColor); material->SetParameter("SpecularColor", lk_SpecularColor * lf_Glossiness); material->SetParameter("EmissiveColor", lk_EmissiveColor); material->SetParameter("Shininess", lf_SpecularLevel); IShader* modelShader = &m_Engine.get_ResourceFactory().CreateOrFindShader(uniqueName); modelShader->LoadFromFile(L"Data/NormalOutput.fxo"); if (argResult.m_Bones.empty()) modelShader->set_TechniqueName("Render"); else modelShader->set_TechniqueName("Render"); argResult.m_Shaders[uniqueName] = modelShader; IShaderParameterCollection* params = &m_Engine.get_ResourceFactory().CreateOrFindShaderParameterCollection(uniqueName); if (!ls_DiffuseTexture.empty()) { ITexture& tex = m_Engine.get_ResourceFactory().CreateOrFindTexture(std::to_string8(ls_DiffuseTexture)); if (m_Engine.get_ResourceFactory().HasCreatedResource()) tex.LoadFromFile(L"Data/Wall.jpg");//ls_DiffuseTexture); params->SetParameter("Diffuse", tex); } if (!ls_SpecularTexture.empty()) { ITexture& tex = m_Engine.get_ResourceFactory().CreateOrFindTexture(std::to_string8(ls_SpecularTexture)); if (m_Engine.get_ResourceFactory().HasCreatedResource()) tex.LoadFromFile(ls_SpecularTexture); params->SetParameter("Specular", tex); } if (!ls_NormalTexture.empty()) { ITexture& tex = m_Engine.get_ResourceFactory().CreateOrFindTexture(std::to_string8(ls_NormalTexture)); if (m_Engine.get_ResourceFactory().HasCreatedResource()) tex.LoadFromFile(ls_NormalTexture); params->SetParameter("Normal", tex); } if (!ls_GlowTexture.empty()) { ITexture& tex = m_Engine.get_ResourceFactory().CreateOrFindTexture(std::to_string8(ls_GlowTexture)); if (m_Engine.get_ResourceFactory().HasCreatedResource()) tex.LoadFromFile(ls_GlowTexture); params->SetParameter("Glow", tex); } argResult.m_Parameters[uniqueName] = params; } void BluImporter::ImportBone(IFile* argFile, std::string argObjectName, BluImportResult& argResult) { std::string ls_ParentBoneName = argFile->ReadString(); // translation float lf_TransX = argFile->ReadFloat(); float lf_TransY = argFile->ReadFloat(); float lf_TransZ = argFile->ReadFloat(); // rotation float lf_RotX = argFile->ReadFloat(); float lf_RotY = argFile->ReadFloat(); float lf_RotZ = argFile->ReadFloat(); float lf_RotW = argFile->ReadFloat(); // scale float lf_ScaleX = argFile->ReadFloat(); float lf_ScaleY = argFile->ReadFloat(); float lf_ScaleZ = argFile->ReadFloat(); string8 uniqueName = std::to_string8(argResult.m_FileName) + "." + argObjectName; string8 uniqueParentName; if (!ls_ParentBoneName.empty()) uniqueParentName = std::to_string8(argResult.m_FileName) +"." + ls_ParentBoneName; IBone& lr_Bone = m_Engine.get_ResourceFactory().CreateOrFindBone(uniqueName); lr_Bone.Initialize(std::to_string16(uniqueName), argResult.m_Bones.size(), D3DXVECTOR3(lf_TransX, lf_TransY, lf_TransZ), D3DXVECTOR3(lf_ScaleX, lf_ScaleY, lf_ScaleZ), D3DXQUATERNION(lf_RotX, lf_RotY, lf_RotZ, lf_RotW)); BluImportedBone lr_BluBone; lr_BluBone.m_Bone = &lr_Bone; lr_BluBone.m_ParentName = uniqueParentName; argResult.m_Bones[uniqueName] = lr_BluBone; } void BluImporter::ImportAnimation(IFile* argFile, std::string argObjectName, BluImportResult& argResult) { string8 uniqueName = std::to_string8(argResult.m_FileName) + "." + argObjectName; ITransformationAnimation* lr_Ta_ = &m_Engine.get_ResourceFactory().CreateTransformationAnimation(); unsigned int lui_PositionElementCount = argFile->ReadInt(); for (unsigned int i = 0; i < lui_PositionElementCount; ++i) { float lf_Time = argFile->ReadFloat(); float lf_X = argFile->ReadFloat(); float lf_Y = argFile->ReadFloat(); float lf_Z = argFile->ReadFloat(); lr_Ta_->AddKeyFrame(KeyFrame(KeyFrameTarget::Position, D3DXVECTOR3(lf_X, lf_Y, lf_Z), lf_Time)); } unsigned int lui_ScaleElementCount = argFile->ReadInt(); for (unsigned int i = 0; i < lui_ScaleElementCount; ++i) { float lf_Time = argFile->ReadFloat(); float lf_X = argFile->ReadFloat(); float lf_Y = argFile->ReadFloat(); float lf_Z = argFile->ReadFloat(); lr_Ta_->AddKeyFrame(KeyFrame(KeyFrameTarget::Scale, D3DXVECTOR3(lf_X, lf_Y, lf_Z), lf_Time)); } unsigned int lui_RotationElementCount = argFile->ReadInt(); for (unsigned int i = 0; i < lui_RotationElementCount; ++i) { float lf_Time = argFile->ReadFloat(); float lf_X = argFile->ReadFloat(); float lf_Y = argFile->ReadFloat(); float lf_Z = argFile->ReadFloat(); lr_Ta_->AddKeyFrame(KeyFrame(KeyFrameTarget::Rotation, D3DXVECTOR3(lf_X, lf_Y, lf_Z), lf_Time)); } argResult.m_Animations[uniqueName] = lr_Ta_; } ////////////////////////////////////////////////////////////////////////// BluModel BluImportResult::GenerateRootCommandNode(IEngine& argEngine) { IResourceFactory& factory = argEngine.get_ResourceFactory(); IRenderCommandNode& rootNode = factory.CreateRenderCommandNode(); ITransformation& transformation = factory.CreateOrFindTransformation(); transformation.set_TransformationBindings(TransformationBindings::CreateDefault()); if (!m_Bones.empty()) m_Bones.begin()->second.m_Bone->GetTransformationAtTime(0.0f, D3DXMATRIX()); if (m_BoneController != NULL) { AddToNode(rootNode, m_BoneController); m_BoneController->PlaySequence(L"all"); } // Create sub nodes std::map::iterator lk_Iter = m_GeometryBuffers.begin(); for (; lk_Iter != m_GeometryBuffers.end(); ++lk_Iter) { BluImportedGeometryBuffer meshInfo = lk_Iter->second; std::map::iterator shader = m_Shaders.find(meshInfo.m_MaterialName); std::map::iterator parameter = m_Parameters.find(meshInfo.m_MaterialName); if (shader != m_Shaders.end() && parameter != m_Parameters.end()) { IRenderCommandNode& subNode = factory.CreateRenderCommandNode(); AddToNode(subNode, shader->second); AddToNode(subNode, transformation); AddToNode(subNode, parameter->second); AddToNode(subNode, meshInfo.m_GeometryBuffer); AddToNode(rootNode, subNode); } } BluModel result; result.RootNode = &rootNode; result.RootTransformation = &transformation; result.BoneController = m_BoneController; return result; }