scene을 통해서 material을 순회하면서 파일내부의 모든것을 저장xml을 만들기 위해 tinyxml라이브러리 사용#pragma once
#include "AsTypes.h"
class Converter
{
public:
Converter();
~Converter();
public:
void ReadAssetFile(wstring file);
void ExportModelData(wstring savePath);
void ExportMaterialData(wstring savePath);
private:
void ReadModelData(aiNode* node, int32 index, int32 parent); // Material과 관련된 부분 이외의 정보를 로드하는 함수
void ReadMeshData(aiNode* node, int32 bone);
void WriteModelFile(wstring finalPaht);
private:
void ReadMaterialData(); // Material과 관련된 정보를 로드하는 함수
void WriteMaterialData(wstring finalPath);
string WriteTexture(string saveFolder, string file);
public:
wstring _assetPath = L"../Resources/Assets/";
wstring _modelPath = L"../Resources/Models/";
wstring _texturePath = L"../Resources/Textures/";
private:
shared_ptr<Assimp::Importer> _importer;
const aiScene* _scene;
private:
vector<shared_ptr<asBone>> _bones;
vector<shared_ptr<asMesh>> _meshes;
vector<shared_ptr<asMaterial>> _materials;
};
#include "pch.h"
#include "Converter.h"
#include <filesystem> // c++17부터 지원
#include "Utils.h"
#include "tinyxml2.h"
Converter::Converter()
{
_importer = make_shared<Assimp::Importer>();
}
Converter::~Converter()
{
}
void Converter::ReadAssetFile(wstring file)
{
wstring fileStr = _assetPath + file;
auto p = filesystem::path(fileStr);
assert(filesystem::exists(p));
_scene = _importer->ReadFile(
Utils::ToString(fileStr),
aiProcess_ConvertToLeftHanded |
aiProcess_Triangulate |
aiProcess_GenUVCoords |
aiProcess_GenNormals |
aiProcess_CalcTangentSpace
);
assert(_scene != nullptr);
}
void Converter::ExportModelData(wstring savePath)
{ // 모델 데이터를 추출해서 그 정보를 가지고 와서 별도의 파일을 만드는
wstring finalPath = _modelPath + savePath + L".mesh";
ReadModelData(_scene->mRootNode, -1, -1); // 모델의 모든 노드를 재귀를 통해서 로드하는
WriteModelFile(finalPath); // 메모리에 들고 있던 것들을 최종 타일 형태로 만드는
}
void Converter::ExportMaterialData(wstring savePath)
{
wstring finalPath = _texturePath + savePath + L".xml";
ReadMaterialData();
WriteMaterialData(finalPath);
}
void Converter::ReadModelData(aiNode* node, int32 index, int32 parent)
{
}
void Converter::ReadMeshData(aiNode* node, int32 bone)
{
}
void Converter::WriteModelFile(wstring finalPaht)
{
}
void Converter::ReadMaterialData()
{
for (uint32 i = 0; i < _scene->mNumMaterials; i++)
{
aiMaterial* srcMaterial = _scene->mMaterials[i];
shared_ptr<asMaterial> material = make_shared<asMaterial>();
material->name = srcMaterial->GetName().C_Str();
// Material의 Ambient, Diffuse, Specular, Emissive값 가져오기
aiColor3D color;
// Ambient
srcMaterial->Get(AI_MATKEY_COLOR_AMBIENT, color);
material->ambient = Color(color.r, color.g, color.b, 1.f);
// Diffuse
srcMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color);
material->diffuse = Color(color.r, color.g, color.b, 1.f);
// Specular
srcMaterial->Get(AI_MATKEY_COLOR_SPECULAR, color);
material->specular = Color(color.r, color.g, color.b, 1.f);
srcMaterial->Get(AI_MATKEY_SHININESS, material->specular.w);
// Emissive
srcMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, color);
material->emissive = Color(color.r, color.g, color.b, 1.f);
aiString file;
// DiffuseFile
srcMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &file);
material->diffuseFile = file.C_Str();
// SpecularFile
srcMaterial->GetTexture(aiTextureType_SPECULAR, 0, &file);
material->specularFile = file.C_Str();
// NormalFile
srcMaterial->GetTexture(aiTextureType_NORMALS, 0, &file);
material->normalFile = file.C_Str();
_materials.push_back(material);
}
}
void Converter::WriteMaterialData(wstring finalPath)
{
auto path = filesystem::path(finalPath);
// 폴더가 없으면 폴더 생성
filesystem::create_directory(path.parent_path());
string folder = path.parent_path().string();
shared_ptr<tinyxml2::XMLDocument> document = make_shared<tinyxml2::XMLDocument>();
tinyxml2::XMLDeclaration* decl = document->NewDeclaration();
document->LinkEndChild(decl);
tinyxml2::XMLElement* root = document->NewElement("Materials");
document->LinkEndChild(root);
for (shared_ptr<asMaterial> material : _materials)
{
tinyxml2::XMLElement* node = document->NewElement("Material");
root->LinkEndChild(node);
tinyxml2::XMLElement* element = nullptr;
element = document->NewElement("Name");
element->SetText(material->name.c_str());
node->LinkEndChild(element);
element = document->NewElement("DiffuseFile");
element->SetText(WriteTexture(folder, material->diffuseFile).c_str());
node->LinkEndChild(element);
element = document->NewElement("SpecularFile");
element->SetText(WriteTexture(folder, material->specularFile).c_str());
node->LinkEndChild(element);
element = document->NewElement("NormalFile");
element->SetText(WriteTexture(folder, material->normalFile).c_str());
node->LinkEndChild(element);
element = document->NewElement("Ambient");
element->SetAttribute("R", material->ambient.x);
element->SetAttribute("G", material->ambient.y);
element->SetAttribute("B", material->ambient.z);
element->SetAttribute("A", material->ambient.w);
node->LinkEndChild(element);
element = document->NewElement("Diffuse");
element->SetAttribute("R", material->diffuse.x);
element->SetAttribute("G", material->diffuse.y);
element->SetAttribute("B", material->diffuse.z);
element->SetAttribute("A", material->diffuse.w);
node->LinkEndChild(element);
element = document->NewElement("Specular");
element->SetAttribute("R", material->specular.x);
element->SetAttribute("G", material->specular.y);
element->SetAttribute("B", material->specular.z);
element->SetAttribute("A", material->specular.w);
node->LinkEndChild(element);
element = document->NewElement("Emissive");
element->SetAttribute("R", material->emissive.x);
element->SetAttribute("G", material->emissive.y);
element->SetAttribute("B", material->emissive.z);
element->SetAttribute("A", material->emissive.w);
node->LinkEndChild(element);
}
document->SaveFile(Utils::ToString(finalPath).c_str());
}
string Converter::WriteTexture(string saveFolder, string file)
{
string fileName = filesystem::path(file).filename().string();
string folderName = filesystem::path(saveFolder).filename().string();
// embeddedTexture 가져오는 방법, fbx에 texture가 내장되어 있는 경우
// 웬만하면 텍스처 파일이 따로있는 버전을 사용하는 걸 권장. -> 관리 차원에서 조금 더 편하다
const aiTexture* srcTexture = _scene->GetEmbeddedTexture(file.c_str());
// 사용 권장x
if (srcTexture)
{
string pathStr = saveFolder + fileName;
// 바이너리모드로
if (srcTexture->mHeight == 0)
{
//shared_ptr<FileUtils> file = make_shared<FileUtils>();
//file->Open(Utils::ToWString(pathStr), FileMode::Write);
//file->Write(srcTexture->pcData, srcTexture->mWidth);
}
else
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = srcTexture->mWidth;
desc.Height = srcTexture->mHeight;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_IMMUTABLE;
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = srcTexture->pcData;
ComPtr<ID3D11Texture2D> texture;
HRESULT hr = DEVICE->CreateTexture2D(&desc, &subResource, texture.GetAddressOf());
CHECK(hr);
DirectX::ScratchImage img;
::CaptureTexture(DEVICE.Get(), DC.Get(), texture.Get(), img);
// Save To File, 최신SaveToDDS라는 텍스 라이브러리
hr = DirectX::SaveToDDSFile(*img.GetImages(), DirectX::DDS_FLAGS_NONE, Utils::ToWString(fileName).c_str());
CHECK(hr);
}
}
else // 텍스처 따로 있을 경우
{
// 기존에 있던 Resources/Asset/House/내부에 있는 texture 폴더내부의 texture를 복사해서
string originStr = (filesystem::path(_assetPath) / folderName / file).string(); // 원본 경로
Utils::Replace(originStr, "\\", "/");
// Resources/Textures 에 House폴더를 생성해서 그 안에 texture를 붙여 넣는다.
string pathStr = (filesystem::path(saveFolder) / fileName).string(); // 최종 경로
Utils::Replace(pathStr, "\\", "/");
// WinAPI
::CopyFileA(originStr.c_str(), pathStr.c_str(), false);
}
return fileName;
}
void AssimpTool::Init()
{
{
shared_ptr<Converter> converter = make_shared<Converter>();
// FBX -> Memory
converter->ReadAssetFile(L"House/House.fbx");
// Memory -> CustomData(file)
converter->ExportMaterialData(L"House/House"); // Material 추출
converter->ExportModelData(L"House/House"); // Model 추출
// CUstumData(file) -> Memory
}
{ // Tower 추가
shared_ptr<Converter> converter = make_shared<Converter>();
// FBX -> Memory
converter->ReadAssetFile(L"Tower/Tower.fbx");
// Memory -> CustomData(file)
converter->ExportMaterialData(L"Tower/Tower"); // Material 추출
converter->ExportModelData(L"Tower/Tower"); // Model 추출
// CUstumData(file) -> Memory
}
}
Resources/Texture에 House, Tower라는 폴더가 생성House폴더에는 House.xml파일Tower폴더에는 Tower.xml,Wood_Tower_Col.jpg, Wood_Tower_Nor.jpg 파일 생성xml파일 내부는 아래 사진과 같다


https://free3d.com/ko/3d-model/abandoned-cottage-house-825251.html