[DirectX11] 039~40 Model Material
글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자입니다
목차
Model Material
Shader | |
25_Mesh.fx 38_Model.fx |
|
Framework | |
Model | |
Model.h .cpp ModelMesh.h .cpp ModelRender.h .cpp |
|
Renders | |
Material.h. cpp | |
ModelEditor | |
Demo | |
ModelDemo.h .cpp | |
Writer | |
Converter.h .cpp | |
ExportFile.h .cpp Type.h |
VS 단축키
- Ctrl + Space = 자동완성
https://assimp.sourceforge.net/lib_html/materials.html
Type
Type.h 추가부분
더보기
#pragma once
#include "stdafx.h"
struct asBone
{
int Index;
string Name;
int Parent;
Matrix Transform;
};
struct asMesh
{
string Name;
int BoneIndex;
aiMesh* Mesh;
string MaterialName;
vector<Model::ModelVertex> Vertices;
vector<UINT> Indices;
};
struct asMaterial
{
string Name;
Color Ambient;
Color Diffuse;
Color Specular;
Color Emissive;
string DiffuseFile;
string SpecularFile;
string NormalFile;
};
struct asMaterial 부분 추가
struct asMaterial
{
string Name;
Color Ambient;
Color Diffuse;
Color Specular;
Color Emissive;
string DiffuseFile;
string SpecularFile;
string NormalFile;
};
Converter
Converter.h
더보기
#pragma once
#include "stdafx.h"
class Converter
{
public:
Converter();
~Converter();
void ReadFile(wstring file);
public:
void ExportMesh(wstring savePath);
private:
void ReadBoneData(aiNode* node, int index, int parent);
void ReadMeshData(aiNode* node, int bone);
void WriteMeshData(wstring savePath);
public:
void ExportMaterial(wstring savePath, bool bOverwrite = true);
private:
void ReadMaterialData();
void WriteMaterialData(wstring savePath);
string WriteTexture(string saveFolder, string file);
private:
wstring file;
Assimp::Importer* importer;
const aiScene* scene;
vector<struct asBone *> bones;
vector<struct asMesh *> meshes;
vector<struct asMaterial *> materials;
};
Converter.cpp
더보기
#include "stdafx.h"
#include "Converter.h"
#include "Types.h"
#include "Utilities/BinaryFile.h"
#include "Utilities/Xml.h"
Converter::Converter()
{
importer = new Assimp::Importer();
}
Converter::~Converter()
{
SafeDelete(importer);
}
void Converter::ReadFile(wstring file)
{
this->file = L"../../_Assets/" + file;
scene = importer->ReadFile
(
String::ToString(this->file),
aiProcess_ConvertToLeftHanded
| aiProcess_Triangulate
| aiProcess_GenUVCoords
| aiProcess_GenNormals
| aiProcess_CalcTangentSpace
);
assert(scene != NULL);
}
void Converter::ExportMesh(wstring savePath)
{
savePath = L"../../_Models/" + savePath + L".mesh";
ReadBoneData(scene->mRootNode, -1, -1);
WriteMeshData(savePath);
}
void Converter::ReadBoneData(aiNode * node, int index, int parent)
{
asBone* bone = new asBone();
bone->Index = index;
bone->Parent = parent;
bone->Name = node->mName.C_Str();
Matrix transform(node->mTransformation[0]);
D3DXMatrixTranspose(&bone->Transform, &transform);
Matrix matParent;
if (parent < 0)
D3DXMatrixIdentity(&matParent);
else
matParent = bones[parent]->Transform;
bone->Transform = bone->Transform * matParent;
bones.push_back(bone);
ReadMeshData(node, index);
for (UINT i = 0; i < node->mNumChildren; i++)
ReadBoneData(node->mChildren[i], bones.size(), index);
}
void Converter::ReadMeshData(aiNode * node, int bone)
{
if (node->mNumMeshes < 1) return;
asMesh* mesh = new asMesh();
mesh->Name = node->mName.C_Str();
mesh->BoneIndex = bone;
for (UINT i = 0; i < node->mNumMeshes; i++)
{
UINT index = node->mMeshes[i];
aiMesh* srcMesh = scene->mMeshes[index];
aiMaterial* material = scene->mMaterials[srcMesh->mMaterialIndex];
mesh->MaterialName = material->GetName().C_Str();
UINT startVertex = mesh->Vertices.size();
for (UINT v = 0; v < srcMesh->mNumVertices; v++)
{
Model::ModelVertex vertex;
memcpy(&vertex.Position, &srcMesh->mVertices[v], sizeof(Vector3));
if (srcMesh->HasTextureCoords(0))
memcpy(&vertex.Uv, &srcMesh->mTextureCoords[0][v], sizeof(Vector2));
if(srcMesh->HasNormals())
memcpy(&vertex.Normal, &srcMesh->mNormals[v], sizeof(Vector3));
mesh->Vertices.push_back(vertex);
}
for (UINT f = 0; f < srcMesh->mNumFaces; f++)
{
aiFace& face = srcMesh->mFaces[f];
for (UINT k = 0; k < face.mNumIndices; k++)
mesh->Indices.push_back(face.mIndices[k] + startVertex);
}
meshes.push_back(mesh);
}
}
void Converter::WriteMeshData(wstring savePath)
{
Path::CreateFolders(Path::GetDirectoryName(savePath));
BinaryWriter* w = new BinaryWriter();
w->Open(savePath);
w->UInt(bones.size());
for (asBone* bone : bones)
{
w->Int(bone->Index);
w->String(bone->Name);
w->Int(bone->Parent);
w->Matrix(bone->Transform);
SafeDelete(bone);
}
w->UInt(meshes.size());
for (asMesh* meshData : meshes)
{
w->String(meshData->Name);
w->Int(meshData->BoneIndex);
w->String(meshData->MaterialName);
w->UInt(meshData->Vertices.size());
w->Byte(&meshData->Vertices[0], sizeof(Model::ModelVertex) * meshData->Vertices.size());
w->UInt(meshData->Indices.size());
w->Byte(&meshData->Indices[0], sizeof(UINT) * meshData->Indices.size());
SafeDelete(meshData);
}
w->Close(); //Binary 닫아줌. 안 닫으면 파일 접근불가.
SafeDelete(w);
}
void Converter::ExportMaterial(wstring savePath, bool bOverwrite)
{
savePath = L"../../_Texture/" + savePath + L".material";
if (bOverwrite == false)
{
if (Path::ExistFile(savePath) == true)
return; //파일이 있다면 밑의 코드를 수행하지 않겠다.
}
ReadMaterialData();
WriteMaterialData(savePath);
}
void Converter::ReadMaterialData()
{
for (UINT i = 0; i < scene->mNumMaterials; i++)
{
aiMaterial* srcMaterial = scene->mMaterials[i];
asMaterial* material = new asMaterial();
material->Name = srcMaterial->GetName().C_Str();
aiColor3D color;
srcMaterial->Get(AI_MATKEY_COLOR_AMBIENT, color);
material->Ambient = Color(color.r, color.g, color.b, 1.0f);
srcMaterial->Get(AI_MATKEY_COLOR_AMBIENT, color);
material->Diffuse = Color(color.r, color.g, color.b, 1.0f);
srcMaterial->Get(AI_MATKEY_COLOR_AMBIENT, color);
material->Specular = Color(color.r, color.g, color.b, 1.0f);
srcMaterial->Get(AI_MATKEY_SHININESS, material->Specular.a);
material->Emissive = Color(color.r, color.g, color.b, 1.0f);
aiString file;
srcMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &file);
material->DiffuseFile = file.C_Str();
srcMaterial->GetTexture(aiTextureType_SPECULAR, 0, &file);
material->SpecularFile = file.C_Str();
srcMaterial->GetTexture(aiTextureType_NORMALS, 0, &file);
material->NormalFile = file.C_Str();
materials.push_back(material);
}
}
void Converter::WriteMaterialData(wstring savePath)
{
string folder = String::ToString(Path::GetDirectoryName(savePath));//경로에서 Directory명만 빼와 String으로 변경
string file = String::ToString(Path::GetFileName(savePath));//경로에서 File명만 빼워 String으로 변경
Path::CreateFolders(folder);
Xml::XMLDocument* document = new Xml::XMLDocument();
Xml::XMLDeclaration* decl = document->NewDeclaration();
document->LinkEndChild(decl);
Xml::XMLElement* root = document->NewElement("Materials");
root->SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
root->SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
document->LinkEndChild(root);
for (asMaterial* material : materials)
{
Xml::XMLElement* node = document->NewElement("Material");
root->LinkEndChild(node);
Xml::XMLElement* element = NULL;
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.r);
element->SetAttribute("G", material->Ambient.g);
element->SetAttribute("B", material->Ambient.b);
element->SetAttribute("A", material->Ambient.a);
node->LinkEndChild(element);
element = document->NewElement("Diffuse");
element->SetAttribute("R", material->Diffuse.r);
element->SetAttribute("G", material->Diffuse.g);
element->SetAttribute("B", material->Diffuse.b);
element->SetAttribute("A", material->Diffuse.a);
node->LinkEndChild(element);
element = document->NewElement("Specular");
element->SetAttribute("R", material->Specular.r);
element->SetAttribute("G", material->Specular.g);
element->SetAttribute("B", material->Specular.b);
element->SetAttribute("A", material->Specular.a);
node->LinkEndChild(element);
element = document->NewElement("Emissive");
element->SetAttribute("R", material->Emissive.r);
element->SetAttribute("G", material->Emissive.g);
element->SetAttribute("B", material->Emissive.b);
element->SetAttribute("A", material->Emissive.a);
node->LinkEndChild(element);
SafeDelete(material);
}
document->SaveFile((folder + file).c_str());
SafeDelete(document);
}
string Converter::WriteTexture(string saveFolder, string file)
{
if (file.length() < 1) return "";
string fileName = Path::GetFileName(file);
const aiTexture* texture = scene->GetEmbeddedTexture(file.c_str());
string path = "";
if (texture != NULL)
{
path = saveFolder + fileName;
if (texture->mHeight < 1)
{
BinaryWriter w;
w.Open(String::ToWString(path));
w.Byte(texture->pcData, texture->mWidth);
w.Close();
}
else
{
D3D11_TEXTURE2D_DESC destDesc;
ZeroMemory(&destDesc, sizeof(D3D11_TEXTURE2D_DESC));
destDesc.Width = texture->mWidth;
destDesc.Height = texture->mHeight;
destDesc.MipLevels = 1;
destDesc.ArraySize = 1;
destDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
destDesc.SampleDesc.Count = 1;
destDesc.SampleDesc.Quality = 0;
destDesc.Usage = D3D11_USAGE_IMMUTABLE;
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = texture->pcData;
ID3D11Texture2D* dest;
HRESULT hr;
hr = D3D::GetDevice()->CreateTexture2D(&destDesc, &subResource, &dest);
assert(SUCCEEDED(hr));
D3DX11SaveTextureToFileA(D3D::GetDC(), dest, D3DX11_IFF_PNG, saveFolder.c_str());
}
}
else
{
string directory = Path::GetDirectoryName(String::ToString(this->file));
string origin = directory + file;
String::Replace(&origin, "\\", "/");
if (Path::ExistFile(origin) == false)
return "";
path = saveFolder + fileName;
CopyFileA(origin.c_str(), path.c_str(), FALSE);
String::Replace(&path, "../../_Textures/", "");
}
return Path::GetFileName(path);
}
Kachujin 추가
ExportFile.h .cpp
ModelDemo.h .cpp
에 기존의 Airplane, Tower, Tank와 같이 추가
실행화면
'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
PDB 파일을 찾거나 열 수 없습니다. 오류 해결 (0) | 2023.02.08 |
---|---|
[DirectX11] 041 Animation Skinning (0) | 2023.02.08 |
[DirectX11] 038 Model Render (0) | 2023.02.06 |
[DirectX11] 037 Model Reader (0) | 2023.02.05 |
[DirectX11] 034~36 Model Editor (0) | 2023.02.01 |
댓글
이 글 공유하기
다른 글
-
PDB 파일을 찾거나 열 수 없습니다. 오류 해결
PDB 파일을 찾거나 열 수 없습니다. 오류 해결
2023.02.08 -
[DirectX11] 041 Animation Skinning
[DirectX11] 041 Animation Skinning
2023.02.08 -
[DirectX11] 038 Model Render
[DirectX11] 038 Model Render
2023.02.06 -
[DirectX11] 037 Model Reader
[DirectX11] 037 Model Reader
2023.02.05