728x90
Framework(솔루션) -> Model.cpp, h
더보기
#include "Framework.h"
#include "Model.h"
#include "Utilities/BinaryFile.h"
Model::Model()
{
}
Model::~Model()
{
for (ModelBone* bone : bones)
SafeDelete(bone);
for (ModelMesh* mesh : meshes)
SafeDelete(mesh);
}
void Model::ReadMesh(wstring file)
{
file = L"../../_Models/" + file + L".mesh";
BinaryReader* r = new BinaryReader(file);
UINT count = 0;
count = r->UInt();
for (UINT i = 0; i < count; i++)
{
ModelBone* bone = new ModelBone();
bone->index = r->Int();
bone->name = String::ToWString(r->String());
bone->parentIndex = r->Int();
bone->transform = r->Matrix();
bones.push_back(bone);
}
count = r->UInt();
for (UINT i = 0; i < count; i++)
{
ModelMesh* mesh = new ModelMesh();
mesh->boneIndex = r->Int();
//VertexData
{
UINT count = r->UInt();
vector<Model::VertexModel> vertices;
vertices.assign(count, Model::VertexModel());
void* ptr = (void*)&(vertices[0]);
r->Byte(&ptr, sizeof(Model::VertexModel) * count);
mesh->vertices = new Model::VertexModel[count];
mesh->vertexCount = count;
copy
(
vertices.begin(), vertices.end(),
stdext::checked_array_iterator<Model::VertexModel*>(mesh->vertices, count)
);
}
//IndexData
{
UINT count = r->UInt();
vector<UINT> indices;
indices.assign(count, sizeof(UINT));
void* ptr = (void*)&(indices[0]);
r->Byte(&ptr, sizeof(UINT) * count);
mesh->indices = new UINT[count];
mesh->indexCount = count;
copy
(
indices.begin(), indices.end(),
stdext::checked_array_iterator<UINT*>(mesh->indices, count)
);
}
//MeshPart::DrawCall에 사용될 값
UINT partCount = r->UInt();
for (UINT k = 0; k < partCount; k++)
{
ModelMeshPart* meshPart = new ModelMeshPart();
meshPart->materialName = String::ToWString(r->String());
meshPart->startVertex = r->UInt();
meshPart->vertexCount = r->UInt();
meshPart->startIndex = r->UInt();
meshPart->indexCount = r->UInt();
mesh->meshParts.push_back(meshPart);
}
meshes.push_back(mesh);
}
SafeDelete(r);
BindBone();
BindMesh();
}
void Model::BindBone()
{
root = bones[0]; //root Bone
for (ModelBone* bone : bones)
{
//부모가 없다면
if (bone->parentIndex > -1)
{
bone->parent = bones[bone->parentIndex];
bone->parent->childs.push_back(bone);
}
else
bone->parent = NULL;
}
}
void Model::BindMesh()
{
//모델이 보유한 Mesh(덩어리) 개수만큼 돌면서
for (ModelMesh* mesh : meshes)
{
mesh->bone = bones[mesh->boneIndex]; //이 Mesh가 참조할 뽄을 저장
mesh->Binding(this);
}
}
ModelBone * Model::BoneByName(wstring name)
{
for (ModelBone* bone : bones)
{
if (name == bone->Name())
return bone;
}
return NULL;
}
#pragma once
#define MAX_MODEL_TRANSFORMS 250
class ModelBone;
class ModelMesh;
class ModelMeshPart;
class Model
{
public:
friend class ModelRender;
struct VertexModel;
private:
Model();
~Model();
private:
//.mesh 파일 불러오기
void ReadMesh(wstring file);
private:
//부모, 자식 관계가 맺어진 bone을 bones에 저장
void BindBone();
//이 모델이 가진 Mesh(덩어리)를 meshes에 저장
void BindMesh();
public:
UINT BoneCount() { return bones.size(); }
vector<ModelBone*>& Bones() { return bones; }
ModelBone* BoneByIndex(UINT index) { return bones[index]; }
ModelBone* BoneByName(wstring name);
UINT MeshCount() { return meshes.size(); }
vector<ModelMesh*>& Meshes() { return meshes; }
ModelMesh* MeshByIndex(UINT index) { return meshes[index]; }
public:
struct VertexModel
{
Vector3 Position;
Vector2 Uv;
Vector3 Normal;
Vector3 Tangent; //NormalMapping
Vector4 BlendIndices; //Animation Skinning
Vector4 BlendWeights;
VertexModel()
{
Position = Vector3(0, 0, 0);
Uv = Vector2(0, 0);
Normal = Vector3(0, 0, 0);
Tangent = Vector3(0, 0, 0);
BlendIndices = Vector4(0, 0, 0, 0);
BlendWeights = Vector4(0, 0, 0, 0);
}
};
private:
ModelBone* root;
vector<ModelBone*> bones;
vector<ModelMesh*> meshes;
};
Framework(솔루션) -> ModelMesh.cpp, h
더보기
#include "Framework.h"
#include "ModelMesh.h"
ModelBone::ModelBone()
{
}
ModelBone::~ModelBone()
{
}
///////////////////////////////////////////////////////////////////////////////
ModelMesh::ModelMesh()
{
boneBuffer = new ConstantBuffer(&boneDesc, sizeof(BoneDesc));
}
ModelMesh::~ModelMesh()
{
SafeDelete(transform);
SafeDelete(perframe);
SafeDeleteArray(vertices);
SafeDeleteArray(indices);
SafeDelete(vertexBuffer);
SafeDelete(indexBuffer);
SafeDelete(boneBuffer);
for (ModelMeshPart* part : meshParts)
SafeDelete(part);
}
void ModelMesh::Binding(Model * model)
{
vertexBuffer = new VertexBuffer(vertices, vertexCount, sizeof(Model::VertexModel));
indexBuffer = new IndexBuffer(indices, indexCount);
for (ModelMeshPart* part : meshParts)
part->Binding(model);
}
void ModelMesh::Pass(UINT val)
{
for (ModelMeshPart* part : meshParts)
part->Pass(val);
}
void ModelMesh::SetShader(Shader * shader)
{
this->shader = shader;
SafeDelete(transform);
transform = new Transform(shader);
SafeDelete(perframe);
perframe = new PerFrame(shader);
sBoneBuffer = shader->AsConstantBuffer("CB_Bones");
for (ModelMeshPart* part : meshParts)
part->SetShader(shader);
}
void ModelMesh::Update()
{
boneDesc.BoneIndex = boneIndex;
perframe->Update();
transform->Update();
for (ModelMeshPart* part : meshParts)
part->Update();
}
void ModelMesh::Render()
{
boneBuffer->Render();
sBoneBuffer->SetConstantBuffer(boneBuffer->Buffer());
perframe->Render();
transform->Render();
vertexBuffer->Render();
indexBuffer->Render();
D3D::GetDC()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
for (ModelMeshPart* part : meshParts)
part->Render();
}
void ModelMesh::Transforms(Matrix * transforms)
{
memcpy(boneDesc.Transforms, transforms, sizeof(Matrix) * MAX_MODEL_TRANSFORMS);
}
void ModelMesh::SetTransform(Transform * transform)
{
this->transform->Set(transform);
}
///////////////////////////////////////////////////////////////////////////////
ModelMeshPart::ModelMeshPart()
{
}
ModelMeshPart::~ModelMeshPart()
{
}
void ModelMeshPart::Update()
{
}
void ModelMeshPart::Render()
{
shader->DrawIndexed(0, pass, indexCount, startIndex);
}
void ModelMeshPart::Binding(Model * model)
{
}
void ModelMeshPart::SetShader(Shader* shader)
{
this->shader = shader;
}
#pragma once
class ModelBone
{
public:
friend class Model;
private:
ModelBone();
~ModelBone();
public:
int Index() { return index; }
int ParentIndex() { return parentIndex; }
ModelBone* Parent() { return parent; }
wstring Name() { return name; }
Matrix& Transform() { return transform; }
void Transform(Matrix& matrix) { transform = matrix; }
vector<ModelBone*>& Childs() { return childs; }
private:
int index;
wstring name;
int parentIndex;
ModelBone* parent;
Matrix transform;
vector<ModelBone*> childs;
};
///////////////////////////////////////////////////////////////////////////////
class ModelMesh
{
public:
friend class Model;
private:
ModelMesh();
~ModelMesh();
//vBuffer, iBuffer 생성, (MeshPart들의 Material 할당)
void Binding(Model* model);
public:
//pass 변경 시 하위 MeshPart들에게 모두 적용
void Pass(UINT val);
//Shader 변경 시 transform, perframe 다시 생성
void SetShader(Shader* shader);
//ModelRender에서 반복문 내부에서 호출될 함수
void Update();
//vBuffer, iBuffer, cBuffer 쉐이더로 밀어주기
void Render();
//Get
int BoneIndex() { return boneIndex; }
class ModelBone* Bone() { return bone; }
//모델의 개별 Bone을 받아서 boneBuffer::Transforms[] 변수에 세팅해주는 역할
void Transforms(Matrix* transforms);
void SetTransform(Transform* transform);
private:
struct BoneDesc
{
Matrix Transforms[MAX_MODEL_TRANSFORMS]; //Bone의 개별 위치
UINT BoneIndex;
float Padding[3];
} boneDesc;
private:
Shader* shader;
Transform* transform = NULL; //모델의 대표 위치
PerFrame* perframe = NULL; //VP
int boneIndex; //메쉬가 참조할 Bone번호
ModelBone* bone; //메쉬가 붙을 Bone
//IA
VertexBuffer* vertexBuffer;
UINT vertexCount;
Model::VertexModel* vertices;
IndexBuffer* indexBuffer;
UINT indexCount;
UINT* indices;
ConstantBuffer* boneBuffer;
ID3DX11EffectConstantBuffer* sBoneBuffer;
vector<class ModelMeshPart*> meshParts;
};
///////////////////////////////////////////////////////////////////////////////
class ModelMeshPart
{
public:
friend class Model;
friend class ModelMesh;
private:
ModelMeshPart();
~ModelMeshPart();
void Update();
void Render();
//모델이 가진 Material을 MeshPart에 저장해주기
void Binding(Model* model);
//shader 멤버 변수에 저장
void SetShader(Shader* shader);
void Pass(UINT val) { pass = val; }
private:
Shader* shader;
UINT pass = 0;
wstring materialName;
UINT startVertex;
UINT vertexCount;
UINT startIndex;
UINT indexCount;
};
Framework(솔루션) -> ModelRender.cpp, h
더보기
#include "Framework.h"
#include "ModelRender.h"
ModelRender::ModelRender(Shader * shader)
: shader(shader)
{
model = new Model();
transform = new Transform(shader);
}
ModelRender::~ModelRender()
{
SafeDelete(model);
SafeDelete(transform);
}
void ModelRender::Update()
{
if (bRead == true)
{
bRead = false;
for (ModelMesh* mesh : model->Meshes())
mesh->SetShader(shader);
UpdateTransforms();
}
for (ModelMesh* mesh : model->Meshes())
mesh->Update();
}
void ModelRender::Render()
{
static int index = -1;
ImGui::InputInt("Index", &index);
if (index >= model->MeshCount())
index = -1;
if (index < 0)
{
for (ModelMesh* mesh : model->Meshes())
{
mesh->SetTransform(transform);
mesh->Render();
}
}
else
{
ModelMesh* mesh = model->MeshByIndex(index);
mesh->SetTransform(transform);
mesh->Render();
}
}
void ModelRender::ReadMesh(wstring file)
{
bRead = true;
model->ReadMesh(file);
}
void ModelRender::Pass(UINT pass)
{
for (ModelMesh* mesh : model->Meshes())
mesh->Pass(pass);
}
void ModelRender::UpdateTransforms()
{
for (UINT i = 0; i < model->BoneCount(); i++)
{
ModelBone* bone = model->BoneByIndex(i);
transforms[i] = bone->Transform();
}
for (ModelMesh* mesh : model->Meshes())
mesh->Transforms(transforms);
}
#pragma once
class ModelRender
{
public:
ModelRender(Shader* shader);
~ModelRender();
//ModelMesh::Update()
void Update();
//ModelMesh::Render()
void Render();
public:
void ReadMesh(wstring file); //model->Read();
Transform* GetTransform() { return transform; } //모델 대표 위치 리턴
Model* GetModel() { return model; }
void Pass(UINT pass);
private:
//모델이 가진 모든 bone을 transforms[]로 복사
void UpdateTransforms();
private:
bool bRead = false; //ReadFile이 수행된 후 true
Shader* shader;
Model* model;
Transform* transform; //모델 대표 위치
Matrix transforms[MAX_MODEL_TRANSFORMS]; //관계를 가진 개별Bone
};
ModelEditor(솔루션) -> ModelDemo.cpp. h
더보기
#include "stdafx.h"
#include "ModelDemo.h"
#include "Converter.h"
void ModelDemo::Initialize()
{
shader = new Shader(L"17_Model.fxo");
Tank();
Kachujin();
sky = new CubeSky(L"Environment/SnowCube1024.dds");
planeShader = new Shader(L"15_Mesh.fxo");
plane = new MeshPlane(planeShader, 6, 6);
plane->GetTransform()->Scale(12, 1, 12);
plane->DiffuseMap(L"Floor.png");
}
void ModelDemo::Destroy()
{
SafeDelete(shader);
SafeDelete(sky);
SafeDelete(planeShader);
SafeDelete(plane);
SafeDelete(tank);
SafeDelete(kachujin);
}
void ModelDemo::Update()
{
static Vector3 LightDirection = Vector3(-1, -1, +1);
ImGui::SliderFloat3("LightDirection", LightDirection, -1, 1);
shader->AsVector("LightDirection")->SetFloatVector(LightDirection);
planeShader->AsVector("LightDirection")->SetFloatVector(LightDirection);
static UINT Pass = 0;
ImGui::InputInt("Pass", (int*)&Pass);
Pass %= 2;
sky->Update();
plane->Update();
if (tank != NULL)
{
tank->Pass(Pass);
tank->Update();
}
if (kachujin != NULL)
{
kachujin->Pass(Pass);
kachujin->Update();
}
}
void ModelDemo::Render()
{
sky->Render();
plane->Render();
if (tank != NULL)
tank->Render();
if (kachujin != NULL)
kachujin->Render();
}
void ModelDemo::Tank()
{
tank = new ModelRender(shader);
tank->ReadMesh(L"Tank/Tank");
}
void ModelDemo::Kachujin()
{
kachujin = new ModelRender(shader);
kachujin->ReadMesh(L"Kachujin/Mesh");
kachujin->GetTransform()->Position(5, 0, 0);
kachujin->GetTransform()->Scale(0.01f, 0.01f, 0.01f);
}
#pragma once
#include "Systems/IExecute.h"
class ModelDemo : public IExecute
{
public:
virtual void Initialize() override;
virtual void Destroy() override;
virtual void Update() override;
virtual void PreRender() override {};
virtual void Render() override;
virtual void PostRender() override {};
virtual void ResizeScreen() override {};
private:
void Tank();
void Kachujin();
private:
Shader* shader;
ModelRender* tank = NULL;
ModelRender* kachujin = NULL;
CubeSky* sky;
Shader* planeShader;
MeshPlane* plane;
};
실행
보충
[1/2] ~ [2/2] 전체 흐름은 다음과 같이 순서를 가짐
1. ModelEditor 솔루션 안에 있는 ExportFile class 에서 해당 모델 파일(Fbx)을 바이너리 파일로 만들어 버림
2. Framework 솔루션 Model 필터안에 있는 3개의 Model 관련 클래스에서 바이너리 파일을 읽고 렌더링 할 수 있게 셋팅 및 쉐이더에 값 넘기는 코드 작성
3. ModelEditor 솔루션 ModelDemo를 통해서 확인을 하는데 해당 모델들은 ModelRender 으로 선언해서 모델을 출력
Model.cpp : 바이너리 파일을 읽고 값을 ModelMesh 클래스에 셋팅
ModelMesh : Model 통해서만 접근이 가능하고 별도의 3가지 클래스가 내부적으로 선언
-> ModelBone : Mesh의 월드 관련
-> ModelMesh : Mesh 관련 버퍼 및 출력 쉐이더에 값을 셋팅 관련
-> ModelMeshPart : 마테리얼 관련
ModelRender : model, modelmesh 클래스통해서 mesh 바이너리 읽고 셋팅을 해서 최종적으로 렌더링 하는 클래스
'DirectX > DirectX 3D_(구)' 카테고리의 다른 글
19_ModelMaterial [2/2] (0) | 2021.07.19 |
---|---|
19_ModelMaterial [1/2] (0) | 2021.07.17 |
18_ModelEditor [1/2] (0) | 2021.07.13 |
17_Framework (Transform, PerFrame, Renderer) (0) | 2021.07.13 |
17_Framework (Buffer + hlsl) (0) | 2021.07.07 |