1. Material 가져오기
먼저 _scene을 통해 material을 반복문을 통해 순회 하면서 만들어준 구조체 내부의 변수에 다 저장해준 다음 벡터에도 저장해주자. 그 다음 xml파일을 만들어 줄텐데 이때는 tinyxml 라이브러리를 사용해서 만들어주자
Converter.h
#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);
void ReadMeshData(aiNode* node, int32 bone);
void WriteModelFile(wstring finalPath);
private:
void ReadMaterialData();
void WriteMaterialData(wstring finalPath);
string WriteTexture(string saveFolder, string file);
private:
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;
};
Converter.cpp
#include "pch.h"
#include "Converter.h"
#include "filesystem"
#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 = std::filesystem::path(fileStr);
assert(std::filesystem::exists(p));
_scene = _importer->ReadFile(
Utils::ToString(fileStr),
aiProcess_ConvertToLeftHanded |
aiProcess_Triangulate | //삼각형 단위만 파싱
aiProcess_GenUVCoords | //uv좌표 생성
aiProcess_GenNormals | //노멀 매핑
aiProcess_CalcTangentSpace
);
assert(_scene != nullptr);
}
void Converter::ExportModelData(wstring savePath)
{
wstring finalPath = _modelPath + savePath + L".mesh";
ReadModelData(_scene->mRootNode, -1, -1); //메모리 -> CustomData
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 finalPath)
{
}
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();
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.0f);
aiString file;
// Diffuse Texture
srcMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &file);
material->diffuseFile = file.C_Str();
// Specular Texture
srcMaterial->GetTexture(aiTextureType_SPECULAR, 0, &file);
material->specularFile = file.C_Str();
// Normal Texture
srcMaterial->GetTexture(aiTextureType_NORMALS, 0, &file);
material->normalFile = file.C_Str();
_materials.push_back(material);
}
}
void Converter::WriteMaterialData(wstring finalPath)
{
std::wcout << L"저장 경로: " << finalPath << std::endl;
//tinyxml 사용
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)
{
return "";
}
이렇게 해준 다음 코드가 실행되는 메인코드에 경로를 넣어주면 설정해준 경로에 xml 파일이 생긴다.
AssimpTool.cpp
#include "pch.h"
#include "AssimpTool.h"
#include "Converter.h"
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");
converter->ExportModelData(L"House/House");
//CustomData (File) -> Memory
}
}
void AssimpTool::Update()
{
}
void AssimpTool::Render()
{
}
그리고 텍스처를 가져온 뒤에 같은 경로에 저장해주는 로직을 완성해주자. 만약 fbx안에 내장된 텍스처가 있다면 메모리로 가져온 다음 파일로 저장해주면 된다. 만약 Texture 폴더가 따로 있다면 그 폴더에 있는 파일을 가져와서 해당경로에 복사해주면 된다.
Converter.cpp
void Converter::WriteMaterialData(wstring finalPath)
{
std::wcout << L"저장 경로: " << finalPath << std::endl;
//tinyxml 사용
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();
//fbx에 texture가 내장되어있는 경우
const aiTexture* srcTexture = _scene->GetEmbeddedTexture(file.c_str());
//메모리로 가져온 다음 파일로 저장
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
hr = DirectX::SaveToDDSFile(*img.GetImages(), DirectX::DDS_FLAGS_NONE, Utils::ToWString(fileName).c_str());
CHECK(hr);
}
}
else
{
//원본경로
string originStr = (filesystem::path(_assetPath) / folderName / file).string();
Utils::Replace(originStr, "\\", "/");
//최종경로
string pathStr = (filesystem::path(saveFolder) / fileName).string();
Utils::Replace(pathStr, "\\", "/");
//WinAPI
::CopyFileA(originStr.c_str(), pathStr.c_str(), false);
}
return fileName;
}
이렇게 해주면 Texture도 해당경로의 폴더에 같이 저장된다.
'게임공부 > Directx11' 카테고리의 다른 글
[Directx11][C++][3D]10. Assimp(Model) (0) | 2024.09.14 |
---|---|
[Directx11][C++][3D]9. Assimp(Bone & Model) (0) | 2024.09.14 |
[Directx11][C++][3D]7. Assimp(이론 및 설정) (0) | 2024.09.09 |
[Directx11][C++][3D]6. Normal Mapping (4) | 2024.09.07 |
[Directx11][C++][3D]5. 빛 통합,Material (0) | 2024.09.06 |