응애맘마조
230623 강의 본문
어제는 obj나 fbx 파일을 로드를 하는데 필요한 Mesh를 로드를 하는데 덮어쓰기가 되어 하나만 표시가 되는 문제가 발생하여 해결하지 못했지만 오늘은 해결했습니다.
MakeHierarchy 함수 내의 반복문을 수정했습니다. MakeMesh 함수 내부에서 int 변수에 node->mMeshes[i]로 번호를 다시 넣고 current를 for문 밖에서 안으로 넣었습니다.
이후에 로드를 하게 되면 정상적으로 파일이 출력되는 것을 확인할 수 있습니다.
#pragma once
class Main : public Scene
{
private:
Camera* Cam;
Grid* grid;
Actor* temp;
string file;
Assimp::Importer importer;
const aiScene* scene;
public:
Main();
~Main();
virtual void Init() override;
virtual void Release() override;
virtual void Update() override;
virtual void LateUpdate() override;
virtual void Render() override;
virtual void PreRender() override;
virtual void ResizeScreen() override;
void MakeHierarchy(aiNode* node, GameObject* node2);
void MakeMesh(aiNode* node, GameObject* node2);
void MakeMaterial();
};
#include "stdafx.h"
#include "Main.h"
Main::Main()
{
}
Main::~Main()
{
}
void Main::Init()
{
Cam = Camera::Create();
Cam->LoadFile("Cam.xml");
Camera::main = Cam;
Cam->width = App.GetWidth();
Cam->height = App.GetHeight();
Cam->viewport.width = App.GetWidth();
Cam->viewport.height = App.GetHeight();
grid = Grid::Create();
temp = Actor::Create();
}
void Main::Release()
{
}
void Main::Update()
{
ImGui::Begin("Hierarchy");
Cam->RenderHierarchy();
temp->RenderHierarchy();
grid->RenderHierarchy();
ImGui::End();
if (GUI->FileImGui("ModelImporter", "ModelImporter",
".fbx,.obj,.x", "../Assets"))
{
file = ImGuiFileDialog::Instance()->GetCurrentFileName();
string path = "../Assets/" + file;
importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
scene = importer.ReadFile
(
path,
aiProcess_ConvertToLeftHanded
| aiProcess_Triangulate
| aiProcess_GenUVCoords
| aiProcess_GenNormals
| aiProcess_CalcTangentSpace
);
assert(scene != NULL and "Import Error");
temp->ReleaseMember();
MakeMaterial();
GameObject* empty = GameObject::Create("empty");
temp->AddChild(empty);
MakeHierarchy(scene->mRootNode, empty);
importer.FreeScene();
}
Camera::ControlMainCam();
Cam->Update();
grid->Update();
temp->Update();
}
void Main::LateUpdate()
{
}
void Main::PreRender()
{
}
void Main::Render()
{
Cam->Set();
grid->Render();
temp->Render();
}
void Main::ResizeScreen()
{
}
void Main::MakeHierarchy(aiNode* node, GameObject* node2)
{
MakeMesh(node, node2);
for (int i = 0; i < node->mNumChildren; i++)
{
GameObject* child = GameObject::Create(node->mChildren[i]->mName.C_Str());
node2->AddChild(child);
MakeHierarchy(node->mChildren[i], child);
}
}
void Main::MakeMesh(aiNode* node, GameObject* node2)
{
for (int i = 0; i < node->mNumMeshes; i++)
{
int index = node->mMeshes[i];
aiMesh* mesh = scene->mMeshes[index];
aiMaterial* mtl = scene->mMaterials[mesh->mMaterialIndex];
string mtlFile = mtl->GetName().C_Str();
int tok = file.find_last_of(".");
string filePath = file.substr(0, tok) + "/";
mtlFile = filePath + mtlFile + ".mtl";
GameObject* Current = node2;
if (i != 0)
{
Current = GameObject::Create(node2->name + "meshObject" + to_string(i));
node2->AddChild(Current);
}
Current->shader = RESOURCE->shaders.Load("3.Cube.hlsl");
Current->material =new Material();
Current->material->LoadFile(mtlFile);
Current->mesh = make_shared<Mesh>();
Current->mesh->byteWidth = sizeof(VertexPTN);
Current->mesh->primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
Current->mesh->vertexType = VertexType::PTN;
Current->mesh->vertexCount = mesh->mNumVertices;
Current->mesh->vertices = new VertexPTN[mesh->mNumVertices];
//Current->mesh->indexCount =
vector<UINT> indexList;
for (int j = 0; j < mesh->mNumVertices; j++)
{
VertexPTN* vertex = (VertexPTN*)Current->mesh->vertices;
//aiVector3D
//텍스쳐 좌표가 있다면
if (mesh->HasTextureCoords(0))
{
vertex[j].uv.x =mesh->mTextureCoords[0][j].x;
vertex[j].uv.y =mesh->mTextureCoords[0][j].y;
}
if (mesh->HasNormals())
{
vertex[j].normal.x = mesh->mNormals[j].x;
vertex[j].normal.y = mesh->mNormals[j].y;
vertex[j].normal.z = mesh->mNormals[j].z;
}
if (mesh->HasPositions())
{
vertex[j].position.x = mesh->mVertices[j].x;
vertex[j].position.y = mesh->mVertices[j].y;
vertex[j].position.z = mesh->mVertices[j].z;
}
}
for (int j = 0; j < mesh->mNumFaces; j++)
{
for (int k = 0; k < mesh->mFaces[j].mNumIndices; k++)
{
indexList.push_back(mesh->mFaces[j].mIndices[k]);
}
}
Current->mesh->indexCount = indexList.size();
Current->mesh->indices = new UINT[indexList.size()];
copy(indexList.begin(), indexList.end(),
stdext::checked_array_iterator<UINT*>
(Current->mesh->indices, indexList.size()));
Current->mesh->Reset();
{
int tok = file.find_last_of(".");
string checkPath = "../Contents/Mesh/" + file.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string filePath = file.substr(0, tok) + "/";
string meshFile = mesh->mName.C_Str();
Current->mesh->file = filePath + meshFile + ".mesh";
Current->mesh->SaveFile(Current->mesh->file);
}
}
}
void Main::MakeMaterial()
{
for (int i = 0; i < scene->mNumMaterials; i++)
{
aiMaterial* srcMtl = scene->mMaterials[i];
Material* destMtl = new Material();
aiColor3D tempColor;
destMtl->file = srcMtl->GetName().C_Str();
//ambient
srcMtl->Get(AI_MATKEY_COLOR_AMBIENT, tempColor);
destMtl->ambient.x = tempColor.r;
destMtl->ambient.y = tempColor.g;
destMtl->ambient.z = tempColor.b;
//diffuse
srcMtl->Get(AI_MATKEY_COLOR_DIFFUSE, tempColor);
destMtl->diffuse.x = tempColor.r;
destMtl->diffuse.y = tempColor.g;
destMtl->diffuse.z = tempColor.b;
//specular
srcMtl->Get(AI_MATKEY_COLOR_SPECULAR, tempColor);
destMtl->specular.x = tempColor.r;
destMtl->specular.y = tempColor.g;
destMtl->specular.z = tempColor.b;
//emissive
srcMtl->Get(AI_MATKEY_COLOR_EMISSIVE, tempColor);
destMtl->emissive.x = tempColor.r;
destMtl->emissive.y = tempColor.g;
destMtl->emissive.z = tempColor.b;
//Shininess
srcMtl->Get(AI_MATKEY_SHININESS, destMtl->shininess);
//opacity
srcMtl->Get(AI_MATKEY_OPACITY, destMtl->opacity);
//Normal
{
aiString aifile;
string TextureFile;
aiReturn texFound;
texFound = srcMtl->GetTexture(aiTextureType_NORMALS, 0, &aifile);
TextureFile = aifile.C_Str();
size_t index = TextureFile.find_last_of('/');
TextureFile = TextureFile.substr(index + 1, TextureFile.length());
//텍스쳐가 있다.
if (texFound == AI_SUCCESS && file != "")
{
destMtl->ambient.w = 1.0f;
destMtl->normalMap = make_shared<Texture>();
size_t tok = file.find_last_of(".");
string checkPath = "../Contents/Texture/" + file.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string orgin = "../Assets/" + TextureFile;
string copy = "../Contents/Texture/" + file.substr(0, tok) + "/" + TextureFile;
bool isCheck = true;
CopyFileA(orgin.c_str(), copy.c_str(), isCheck);
destMtl->normalMap->LoadFile(file.substr(0, tok) + "/" + TextureFile);
}
}
//Diffuse
{
aiString aifile;
string TextureFile;
aiReturn texFound;
texFound = srcMtl->GetTexture(aiTextureType_DIFFUSE, 0, &aifile);
TextureFile = aifile.C_Str();
size_t index = TextureFile.find_last_of('/');
TextureFile = TextureFile.substr(index + 1, TextureFile.length());
//텍스쳐가 있다.
if (texFound == AI_SUCCESS && file != "")
{
destMtl->diffuse.w = 1.0f;
destMtl->diffuseMap = make_shared<Texture>();
size_t tok = file.find_last_of(".");
string checkPath = "../Contents/Texture/" + file.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string orgin = "../Assets/" + TextureFile;
string copy = "../Contents/Texture/" + file.substr(0, tok) + "/" + TextureFile;
bool isCheck = true;
CopyFileA(orgin.c_str(), copy.c_str(), isCheck);
destMtl->diffuseMap->LoadFile(file.substr(0, tok) + "/" + TextureFile);
}
}
//specular
{
aiString aifile;
string TextureFile;
aiReturn texFound;
texFound = srcMtl->GetTexture(aiTextureType_SPECULAR, 0, &aifile);
TextureFile = aifile.C_Str();
size_t index = TextureFile.find_last_of('/');
TextureFile = TextureFile.substr(index + 1, TextureFile.length());
//텍스쳐가 있다.
if (texFound == AI_SUCCESS && file != "")
{
destMtl->specular.w = 1.0f;
destMtl->specularMap = make_shared<Texture>();
size_t tok = file.find_last_of(".");
string checkPath = "../Contents/Texture/" + file.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string orgin = "../Assets/" + TextureFile;
string copy = "../Contents/Texture/" + file.substr(0, tok) + "/" + TextureFile;
bool isCheck = true;
CopyFileA(orgin.c_str(), copy.c_str(), isCheck);
destMtl->specularMap->LoadFile(file.substr(0, tok) + "/" + TextureFile);
}
}
//emissive
{
aiString aifile;
string TextureFile;
aiReturn texFound;
texFound = srcMtl->GetTexture(aiTextureType_EMISSIVE, 0, &aifile);
TextureFile = aifile.C_Str();
size_t index = TextureFile.find_last_of('/');
TextureFile = TextureFile.substr(index + 1, TextureFile.length());
//텍스쳐가 있다.
if (texFound == AI_SUCCESS && file != "")
{
destMtl->emissive.w = 1.0f;
destMtl->emissiveMap = make_shared<Texture>();
size_t tok = file.find_last_of(".");
string checkPath = "../Contents/Texture/" + file.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string orgin = "../Assets/" + TextureFile;
string copy = "../Contents/Texture/" + file.substr(0, tok) + "/" + TextureFile;
bool isCheck = true;
CopyFileA(orgin.c_str(), copy.c_str(), isCheck);
destMtl->emissiveMap->LoadFile(file.substr(0, tok) + "/" + TextureFile);
}
}
size_t tok = file.find_last_of(".");
string checkPath = "../Contents/Material/" + file.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string filePath = file.substr(0, tok) + "/";
destMtl->file = filePath + destMtl->file + ".mtl";
destMtl->SaveFile(destMtl->file);
}
}
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR param, int command)
{
App.SetAppName(L"ObjLoader");
App.SetInstance(instance);
WIN->Create();
D3D->Create();
Main * main = new Main();
main->Init();
int wParam = (int)WIN->Run(main);
main->Release();
SafeDelete(main);
D3D->DeleteSingleton();
WIN->DeleteSingleton();
return wParam;
}
오늘의 헤더와 cpp 파일입니다. 여기에 이어 ads를 추가해서 파일에 색상을 추가하는 강의를 했었습니다. 여기에 어제까지의 문제였던 Actor를 저장 시도의 경우 코드가 터지는 일이 생겼는데 각각의 Mesh 파일과 경로를 같이 잡아야 해결이 되었습니다.
로드 시 색상이 입혀진 모습을 볼 수 있습니다. 하지만 아직 Normal은 하지 않았기 때문에 확대할 경우 픽셀처럼 깨지는 현상이 나타났습니다. 이는 다음 주 강의에서 해결한다고 했습니다.
다음 주에 애니메이션 효과를 구현하고 스키닝으로 자연스러운 모습으로 만든다고 했습니다.
읽어주셔서 감사합니다.