머티리얼을 조정하면서 조정된 데이터를 TinyXML2로 저장하고, 로드해보자.
TinyXml2는 데이터를 Xml형태로 내보내거나, Xml형태의 데이터를 읽어오는 C++의 라이브러리이다.
라이브러리리의 설치는 엄청 간단한데,
https://github.com/leethomason/tinyxml2
GitHub - leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other p
TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs. - GitHub - leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser tha...
github.com
위 GitHub링크에 들어가서 TinyXml2 를 받아서. 헤더와 cpp파일을 선언해서 그대로 사용하면 된다.

이제 Material을 저장하고 불러오는 함수를 작성해보자.
#pragma once
class Material
{
private:
enum MapType
{
DIFFUSE, SPECULAR, NORMAL
};
public:
Material(wstring shaderFile);
~Material();
void GUIRender();
void Set();
void SetShader(wstring shaderFile);
void SetDiffuseMap(wstring textureFile);
void SetSpecularMap(wstring textureFile);
void SetNormalMap(wstring textureFile);
void Save(string file);
void Load(string file);
MaterialBuffer::Data* GetBuffer() { return buffer->GetData(); }
string GetName() { return name; }
void SetName(string name) { this->name = name; }
private:
void SelectShader();
void SelectMap(string name, MapType mapType);
void UnselectMap(MapType mapType);
void SaveDialog();
void LoadDialog();
private:
string name;
string editName;
string file;
string shaderFile;
VertexShader* vertexShader;
PixelShader* pixelShader;
Texture* diffuseMap = nullptr;
Texture* specularMap = nullptr;
Texture* normalMap = nullptr;
MaterialBuffer* buffer;
};
원래 사용하던 Material에서 Save, Load, SaveDialog, LoadDialog를 추가하고,
저장할 때 사용하는 변수인 이름을 저장할 file이라는 변수를 추가한다.
void Material::Save(string file)
{
tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument();
tinyxml2::XMLElement* material = document->NewElement("Material");
material->SetAttribute("Name", name.c_str());
material->SetAttribute("Shader", shaderFile.c_str());
document->InsertFirstChild(material);
tinyxml2::XMLElement* texture = document->NewElement("Texture");
tinyxml2::XMLElement* map = document->NewElement("DiffsueMap");
string textureFile = ToString(diffuseMap->GetFile());
map->SetAttribute("DM", textureFile.c_str());
texture->InsertEndChild(map);
map = document->NewElement("SpecularMap");
textureFile = ToString(specularMap->GetFile());
map->SetAttribute("SM", textureFile.c_str());
texture->InsertEndChild(map);
map = document->NewElement("NormalMap");
textureFile = ToString(normalMap->GetFile());
map->SetAttribute("NM", textureFile.c_str());
texture->InsertEndChild(map);
material->InsertEndChild(texture);
tinyxml2::XMLElement* property = document->NewElement("Property");
tinyxml2::XMLElement* diffuse = document->NewElement("Diffuse");
diffuse->SetAttribute("R", buffer->GetData()->diffuse.x);
diffuse->SetAttribute("G", buffer->GetData()->diffuse.y);
diffuse->SetAttribute("B", buffer->GetData()->diffuse.z);
diffuse->SetAttribute("A", buffer->GetData()->diffuse.w);
property->InsertEndChild(diffuse);
tinyxml2::XMLElement* specular = document->NewElement("Specular");
specular->SetAttribute("R", buffer->GetData()->specular.x);
specular->SetAttribute("G", buffer->GetData()->specular.y);
specular->SetAttribute("B", buffer->GetData()->specular.z);
specular->SetAttribute("A", buffer->GetData()->specular.w);
property->InsertEndChild(specular);
tinyxml2::XMLElement* ambient = document->NewElement("Ambient");
ambient->SetAttribute("R", buffer->GetData()->ambient.x);
ambient->SetAttribute("G", buffer->GetData()->ambient.y);
ambient->SetAttribute("B", buffer->GetData()->ambient.z);
ambient->SetAttribute("A", buffer->GetData()->ambient.w);
property->InsertEndChild(ambient);
tinyxml2::XMLElement* emissive = document->NewElement("Emissive");
emissive->SetAttribute("R", buffer->GetData()->emissive.x);
emissive->SetAttribute("G", buffer->GetData()->emissive.y);
emissive->SetAttribute("B", buffer->GetData()->emissive.z);
emissive->SetAttribute("A", buffer->GetData()->emissive.w);
property->InsertEndChild(emissive);
property->SetAttribute("Shininess", buffer->GetData()->shininess);
property->SetAttribute("HasNormalMap", buffer->GetData()->hasNormalMap);
material->InsertEndChild(property);
document->SaveFile(file.c_str());
delete document;
}
tinyXml를 사용하여 데이터를 저장하는 방식을 지정한다.
Save에 지정된 경로에 현재 Material데이터를 저장하는 함수이다.
TinyXml의 사용법은 Git사이트의 ReadMe파일 참조.
void Material::Load(string file)
{
this->file = file;
tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument();
document->LoadFile(file.c_str());
tinyxml2::XMLElement* material = document->FirstChildElement();
name = material->Attribute("Name");
shaderFile = material->Attribute("Shader");
SetShader(ToWString(shaderFile));
tinyxml2::XMLElement* texture = material->FirstChildElement();
tinyxml2::XMLElement* dm = texture->FirstChildElement();
string textureFile = dm->Attribute("DM");
SetDiffuseMap(ToWString(textureFile));
tinyxml2::XMLElement* sm = dm->NextSiblingElement();
textureFile = sm->Attribute("SM");
SetSpecularMap(ToWString(textureFile));
tinyxml2::XMLElement* nm = sm->NextSiblingElement();
textureFile = nm->Attribute("NM");
SetNormalMap(ToWString(textureFile));
tinyxml2::XMLElement* property = texture->NextSiblingElement();
buffer->GetData()->shininess = property->FloatAttribute("Shininess");
buffer->GetData()->hasNormalMap = property->IntAttribute("HasNormalMap");
tinyxml2::XMLElement* diffuse = property->FirstChildElement();
buffer->GetData()->diffuse.x = diffuse->FloatAttribute("R");
buffer->GetData()->diffuse.y = diffuse->FloatAttribute("G");
buffer->GetData()->diffuse.z = diffuse->FloatAttribute("B");
buffer->GetData()->diffuse.w = diffuse->FloatAttribute("A");
tinyxml2::XMLElement* specular = diffuse->NextSiblingElement();
buffer->GetData()->specular.x = specular->FloatAttribute("R");
buffer->GetData()->specular.y = specular->FloatAttribute("G");
buffer->GetData()->specular.z = specular->FloatAttribute("B");
buffer->GetData()->specular.w = specular->FloatAttribute("A");
tinyxml2::XMLElement* ambient = specular->NextSiblingElement();
buffer->GetData()->ambient.x = ambient->FloatAttribute("R");
buffer->GetData()->ambient.y = ambient->FloatAttribute("G");
buffer->GetData()->ambient.z = ambient->FloatAttribute("B");
buffer->GetData()->ambient.w = ambient->FloatAttribute("A");
tinyxml2::XMLElement* emissive = ambient->NextSiblingElement();
buffer->GetData()->emissive.x = emissive->FloatAttribute("R");
buffer->GetData()->emissive.y = emissive->FloatAttribute("G");
buffer->GetData()->emissive.z = emissive->FloatAttribute("B");
buffer->GetData()->emissive.w = emissive->FloatAttribute("A");
delete document;
}
데이터를 Load하는 함수이다.
지정된 file경로의 파일을 열어서
순서대로 지정된 이름의 항목들을 가져오는 함수이다.
데이터를 가져와서 지정된 데이터를 원하는 항목에 기입하는 형태의 함수이다.
void Material::SaveDialog()
{
string key = "Save";
if (ImGui::Button(key.c_str()))
{
if (file.empty())
Save("TextData/Materials/" + name + ".mat");
else
Save(file);
}
ImGui::SameLine();
key = "SaveAs";
if(ImGui::Button(key.c_str()))
DIALOG->OpenDialog(key.c_str(), key.c_str(), ".mat", ".");
if (DIALOG->Display(key.c_str()))
{
if (DIALOG->IsOk())
{
string file = DIALOG->GetFilePathName();
Save(file);
}
DIALOG->Close();
}
}
void Material::LoadDialog()
{
string key = "Load";
if (ImGui::Button(key.c_str()))
DIALOG->OpenDialog(key.c_str(), key.c_str(), ".mat", ".");
if (DIALOG->Display(key.c_str()))
{
if (DIALOG->IsOk())
{
string file = DIALOG->GetFilePathName();
Load(file);
}
DIALOG->Close();
}
}
Save와 Load Dialog이다.
각각 ImGui의 OpenDisplay함수를 사용하여 원하는 데이터를 지정하고 저장할 수 있게 하였다.
void Material::GUIRender()
{
string title = name + "_Material";
if (ImGui::TreeNode(title.c_str()))
{
char str[128];
strcpy_s(str, 128, editName.c_str());
ImGui::InputText("Name", str, 128);
editName = str;
ImGui::SameLine();
if (ImGui::Button("Edit"))
name = editName;
SelectShader();
ImGui::Text(shaderFile.c_str());
ImGui::ColorEdit3("Diffuse", (float*)&buffer->GetData()->diffuse);
ImGui::ColorEdit3("Specular", (float*)&buffer->GetData()->specular);
ImGui::ColorEdit3("Ambient", (float*)&buffer->GetData()->ambient);
ImGui::ColorEdit3("Emissive", (float*)&buffer->GetData()->emissive);
ImGui::SliderFloat("Shininess", (float*)&buffer->GetData()->shininess, 1, 50);
SelectMap("DM", DIFFUSE);
ImGui::SameLine();
UnselectMap(DIFFUSE);
SelectMap("SM", SPECULAR);
ImGui::SameLine();
UnselectMap(SPECULAR);
SelectMap("NM", NORMAL);
ImGui::SameLine();
UnselectMap(NORMAL);
SaveDialog();
LoadDialog();
ImGui::TreePop();
}
}
그 이후에 GUIRneder()의 항목 안에 집어넣으면 끝난다.

'서울게임아카데미 교육과정 6개월 국비과정' 카테고리의 다른 글
20231030 19일차 간단한 Shooting게임 만들기 (0) | 2023.10.30 |
---|---|
20231027 18일차 3DObjectCollision 원과 구, 캡슐의 충돌 (0) | 2023.10.27 |
20231025 16일차 라이팅맵 조정, 라이브러리 정리 (0) | 2023.10.25 |
20231024 15일차 구체 재작, 라이팅구현3(NormalMap) (0) | 2023.10.24 |
20231020 13일차 카메라 움직임 구현, 라이팅구현1 (0) | 2023.10.22 |