#include "stdafx.h" #include "BLUImporter.h" #include "IFileSystem.h" #include "IResourceFactory.h" #include "IGeometryBuffer.h" #include "IMaterial.h" #include "IBone.h" #include "ITransformationAnimation.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; } } // put materials to GeometryBuffers std::map::iterator lk_Iter = lr_Result.m_GeometryBuffers.begin(); for (; lk_Iter != lr_Result.m_GeometryBuffers.end(); ++lk_Iter) { BluImportedGeometryBuffer lr_Mesh = lk_Iter->second; std::map::iterator lk_Found = lr_Result.m_Materials.find(lr_Mesh.m_MaterialName); if (lk_Found != lr_Result.m_Materials.end()) lr_Mesh.m_GeometryBuffer->set_Material(lk_Found->second); } // 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!"); // when we have bones, try to register the bones shadercallback to all materials // also create a default BoneController if (!lr_Result.m_Bones.empty()) { std::map::iterator lk_MatIter = lr_Result.m_Materials.begin(); for (; lk_MatIter != lr_Result.m_Materials.end(); ++lk_MatIter) { const std::D3DXVECTOR4& lk_SubMaterials = lk_MatIter->second->get_SubMaterials(); for (unsigned int i = 0; i < lk_SubMaterials.size(); ++i) lk_SubMaterials[i]->ShaderProgram->SetShaderCallbackUsage(_T("bones"), lr_Result.m_Bones.begin()->second.m_Bone); } lr_Result.m_BoneController = new BoneController(m_Engine, 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; } IRenderable* BluImporter::Load(IEngine* argEngine, const string16& argFileName, IMaterial* argOverrideMaterial) { BluImporter lk_Importer(argEngine); BluImportResult lk_Result = lk_Importer.Load(argFileName); if (lk_Result.m_SuccessfullyLoaded) return lk_Result.GenerateRootRenderable(argEngine, argOverrideMaterial); return NULL; } 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::D3DXVECTOR4 lk_VertexElements; for (int i = 0; i < li_VertexElementCount; ++i) { VertexElement::Enumeration le_VertexElement = (VertexElement::Enumeration)argFile->ReadInt(); lui_VertexStride += VertexElement::get_Size(le_VertexElement); lk_VertexElements.push_back(le_VertexElement); } 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))); string16 ls_UniqueName = argResult.m_FileName + _T(".") + std::to_string16(argObjectName); IGeometryBuffer* lr_GeometryBuffer_ = m_Engine.get_ResourceFactory()->CreateGeometryBuffer(); lr_GeometryBuffer_->set_PrimitiveTopology(PrimitiveTopology::TriangleList); lr_GeometryBuffer_->SetVertexData((void*)lr_VertexData.Detach(), li_VertexCount, lk_VertexElements, GeometryBufferUsage::Static, true); lr_GeometryBuffer_->SetIndexData((unsigned int*)lr_IndexData.Detach(), li_IndexCount, GeometryBufferUsage::Static, true); BluImportedGeometryBuffer lr_Mesh; lr_Mesh.m_GeometryBuffer = lr_GeometryBuffer_; lr_Mesh.m_MaterialName = argResult.m_FileName + _T(".") + std::to_string16(ls_MaterialName); argResult.m_GeometryBuffers[ls_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(); string16 ls_UniqueName = argResult.m_FileName + _T(".") + std::to_string16(argObjectName); IMaterial* lr_Material_ = m_Engine.get_ResourceFactory()->TryGetOrCreateMaterial(ls_UniqueName.c_str()); SubMaterial* lr_SubMaterial_ = new SubMaterial(); lr_Material_->AddSubMaterial(lr_SubMaterial_); lr_SubMaterial_->Ambient = lk_AmbientColor; lr_SubMaterial_->Diffuse = lk_DiffuseColor; lr_SubMaterial_->Specular = lk_SpecularColor * lf_Glossiness; lr_SubMaterial_->Emissive = lk_EmissiveColor; lr_SubMaterial_->Shininess = lf_SpecularLevel; IShader* lr_VertexShader_ = NULL; if (ls_NormalTexture.empty()) lr_VertexShader_ = m_Engine.get_ResourceFactory()->TryGetOrCreateShader(_T("Common/Phong_simple.vs"), ShaderType::Vertex, _T("Common/Phong_simple.vs")); else if (argResult.m_Bones.empty()) lr_VertexShader_ = m_Engine.get_ResourceFactory()->TryGetOrCreateShader(_T("Common/Phong.vs"), ShaderType::Vertex, _T("Common/Phong.vs")); else lr_VertexShader_ = m_Engine.get_ResourceFactory()->TryGetOrCreateShader(_T("Common/PhongBones.vs"), ShaderType::Vertex, _T("Common/PhongBones.vs")); IShader* lr_PixelShader_ = NULL; if (ls_NormalTexture.empty()) lr_PixelShader_ = m_Engine.get_ResourceFactory()->TryGetOrCreateShader(_T("Common/Phong_simple.ps"), ShaderType::Pixel, _T("Common/Phong_simple.ps")); else lr_PixelShader_ = m_Engine.get_ResourceFactory()->TryGetOrCreateShader(_T("Common/Phon.ps"), ShaderType::Pixel, _T("Common/Phong.ps")); std::D3DXVECTOR4 lk_Shaders; lk_Shaders.push_back(lr_VertexShader_); lk_Shaders.push_back(lr_PixelShader_); lr_SubMaterial_->ShaderProgram = m_Engine.get_ResourceFactory()->CreateShaderProgram(lk_Shaders); if (!ls_DiffuseTexture.empty()) lr_SubMaterial_->Textures[0].Texture = m_Engine.get_ResourceFactory()->TryGetOrCreateTexture(ls_DiffuseTexture.c_str(), ls_DiffuseTexture.c_str()); if (!ls_SpecularTexture.empty()) lr_SubMaterial_->Textures[1].Texture = m_Engine.get_ResourceFactory()->TryGetOrCreateTexture(ls_SpecularTexture.c_str(), ls_SpecularTexture.c_str()); if (!ls_NormalTexture.empty()) lr_SubMaterial_->Textures[2].Texture = m_Engine.get_ResourceFactory()->TryGetOrCreateTexture(ls_NormalTexture.c_str(), ls_NormalTexture.c_str()); if (!ls_GlowTexture.empty()) lr_SubMaterial_->Textures[3].Texture = m_Engine.get_ResourceFactory()->TryGetOrCreateTexture(ls_GlowTexture.c_str(), ls_GlowTexture.c_str()); argResult.m_Materials[ls_UniqueName] = lr_Material_; } 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(); string16 ls_UniqueName = argResult.m_FileName + _T(".") + std::to_string16(argObjectName); string16 ls_UniqueParentName; if (!ls_ParentBoneName.empty()) ls_UniqueParentName = argResult.m_FileName + _T(".") + std::to_string16(ls_ParentBoneName); IBone* lr_Bone_ = m_Engine.get_ResourceFactory()->CreateBone(ls_UniqueName.c_str(), argResult.m_Bones.size(), D3DXVECTOR4(lf_TransX, lf_TransY, lf_TransZ, 1.0f), D3DXVECTOR4(lf_ScaleX, lf_ScaleY, lf_ScaleZ, 1.0f), D3DXQUATERNION(lf_RotX, lf_RotY, lf_RotZ, lf_RotW, 1.0f)); BluImportedBone lr_Bone; lr_Bone.m_Bone = lr_Bone_; lr_Bone.m_ParentName = ls_UniqueParentName; argResult.m_Bones[ls_UniqueName] = lr_Bone; } void BluImporter::ImportAnimation(IFile* argFile, std::string argObjectName, BluImportResult& argResult) { string16 ls_UniqueName = argResult.m_FileName + _T(".") + std::to_string16(argObjectName); ITransformationAnimation* lr_Ta_ = m_Engine.get_ResourceFactory()->TryGetOrCreateTransformationAnimation(ls_UniqueName.c_str()); 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, D3DXVECTOR4(lf_X, lf_Y, lf_Z, 1.0f), 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, D3DXVECTOR4(lf_X, lf_Y, lf_Z, 1.0f), 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, D3DXVECTOR4(lf_X, lf_Y, lf_Z, 1.0f), lf_Time)); } argResult.m_Animations[ls_UniqueName] = lr_Ta_; } ////////////////////////////////////////////////////////////////////////// IRenderable* BluImportResult::GenerateRootRenderable(IEngine* argEngine, IMaterial* argOverrideMaterial) { IResourceFactory* lr_Factory_ = argEngine->get_ResourceFactory(); IRenderable* lr_ResultRenderable_ = lr_Factory_->CreateRenderable(); std::map::iterator lk_Iter = m_GeometryBuffers.begin(); for (; lk_Iter != m_GeometryBuffers.end(); ++lk_Iter) { BluImportedGeometryBuffer lr_Mesh = lk_Iter->second; if (argOverrideMaterial != NULL) lr_Mesh.m_GeometryBuffer->set_Material(argOverrideMaterial); lr_ResultRenderable_->AddRenderable(dynamic_cast(lr_Mesh.m_GeometryBuffer)); } if (!m_Bones.empty()) m_Bones.begin()->second.m_Bone->GetTransformationAtTime(0.0f, Matrix()); if (m_BoneController != NULL) { lr_ResultRenderable_->AddController(m_BoneController); // you can also clone it for instancing reasons :) m_BoneController->PlaySequence(L"all"); } return lr_ResultRenderable_; }