Files
bluflame/aiwaz/Demo/BLUImporter/BLUImporter.cpp
2026-04-18 22:31:51 +02:00

397 lines
14 KiB
C++

#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<string8, 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<string8, 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<string8, ITransformationAnimation*>::iterator lk_AnimIter = lr_Result.m_Animations.begin();
for (; lk_AnimIter != lr_Result.m_Animations.end(); ++lk_AnimIter)
{
std::map<string8, 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!");
// 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<VertexElement> 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<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)));
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<string8, BluImportedGeometryBuffer>::iterator lk_Iter = m_GeometryBuffers.begin();
for (; lk_Iter != m_GeometryBuffers.end(); ++lk_Iter)
{
BluImportedGeometryBuffer meshInfo = lk_Iter->second;
std::map<string8, IShader*>::iterator shader = m_Shaders.find(meshInfo.m_MaterialName);
std::map<string8, IShaderParameterCollection*>::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;
}