383 lines
14 KiB
C++
383 lines
14 KiB
C++
#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<string16, BluImportedGeometryBuffer>::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<string16, IMaterial*>::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<string16, BluImportedBone>::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<string16, BluImportedBone>::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<string16, ITransformationAnimation*>::iterator lk_AnimIter = lr_Result.m_Animations.begin();
|
|
for (; lk_AnimIter != lr_Result.m_Animations.end(); ++lk_AnimIter)
|
|
{
|
|
std::map<string16, BluImportedBone>::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<string16, IMaterial*>::iterator lk_MatIter = lr_Result.m_Materials.begin();
|
|
for (; lk_MatIter != lr_Result.m_Materials.end(); ++lk_MatIter)
|
|
{
|
|
const std::D3DXVECTOR4<SubMaterial*>& 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<VertexElement::Enumeration> 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<char> lr_VertexData((char*)argFile->ReadDataArray(li_VertexCount * lui_VertexStride));
|
|
|
|
unsigned int li_IndexCount = argFile->ReadInt();
|
|
ScopedBuffer<unsigned int> 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<IShader*> 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<string16, BluImportedGeometryBuffer>::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<IRenderable*>(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_;
|
|
}
|