글의 요약 설명 부분. 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

     

    Assimp: Material System

    General All materials are stored in an array of aiMaterial inside the aiScene. Each aiMesh refers to one material by its index in the array. Due to the vastly diverging definitions and usages of material parameters there is no hard definition of a material

    assimp.sourceforge.net


     

    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와 같이 추가 

     

     


     

    실행화면