타워 대신에 탱크fbx 파일을 통해 탱크를 로드해보자
AssimpTool Class에서 fbx 파일을 가져와서 Material과 Model로 Export 해주고 이를 받아와서 화면에 띄워주자
AssimpTool.cpp
void AssimpTool::Init()
{
{
shared_ptr<Converter> converter = make_shared<Converter>();
// FBX -> Memory
converter->ReadAssetFile(L"Tank/Tank.fbx");
//Memory -> CustomData (File)
converter->ExportMaterialData(L"Tank/Tank");
converter->ExportModelData(L"Tank/Tank");
//CustomData (File) -> Memory
}
}
이렇게 해서 실행해주면 mesh와 xml 파일이 생기게 된다.
그리고 다시 StaticMeshDemo 클래스에서 우리가 저장해준 형식 탱크를 가져와서 ModelRenderer를 통해 화면에 띄워주자
StaticMeshDemo.cpp
void StaticMeshDemo::Init()
{
RESOURCES->Init();
_shader = make_shared<Shader>(L"15. ModelDemo.fx");
// Camera
_camera = make_shared<GameObject>();
_camera->GetOrAddTransform()->SetPosition(Vec3{ 0.f, 0.f, -5.f });
_camera->AddComponent(make_shared<Camera>());
_camera->AddComponent(make_shared<CameraScript>());
//CreateTower();
CreateTank();
RENDER->Init(_shader);
}
void StaticMeshDemo::CreateTank()
{
// CustomData -> Memory
shared_ptr<class Model> m1 = make_shared<Model>();
m1->ReadModel(L"Tank/Tank");
m1->ReadMaterial(L"Tank/Tank");
_obj = make_shared<GameObject>();
_obj->GetOrAddTransform()->SetPosition(Vec3(0, 0, 50));
_obj->GetOrAddTransform()->SetScale(Vec3(0.1f));
_obj->AddComponent(make_shared<ModelRenderer>(_shader));
{
_obj->GetModelRenderer()->SetModel(m1);
_obj->GetModelRenderer()->SetPass(1);
}
}
이렇게 해주면 이제 탱크가 화면에 나온다.
보면 탱크와 비슷하지만 조금 이상하다는 것을 알 수 있다. 이렇게 되는 이유는 우리가 Bone 즉 노드에 대한 정보를 활용하지 않고 그냥 화면에 띄워주기만 했기때문이다. 지금 각 노드의 좌표가 루트로 향하는 좌표로 바꿔져있지만 지금은 그 좌표를 쓰고 있지 않기 때문에 이 개별노드를 배치할 때 처리를 해주어야 한다.
일단 쉐이더쪽에 각 뼈대의 Transform을 받아줄 수 있도록 Matrix를 조장할 수 있는 버퍼를 선언해주고 이 쉐이더로 값을 넣을 수 있게 RenderManager에 구조체와 버퍼를 선언 및 초기화해주고 데이터를 할당해주는 함수를 만들어주자.
RenderManager.h
#pragma once
#include "ConstantBuffer.h"
class Shader;
struct GlobalDesc
{
Matrix V = Matrix::Identity;
Matrix P = Matrix::Identity;
Matrix VP = Matrix::Identity;
Matrix VInv = Matrix::Identity;
};
struct TransformDesc
{
Matrix W = Matrix::Identity;
};
//Light
struct LightDesc
{
Color ambient = Color(1.f, 1.f, 1.f, 1.f);
Color diffuse = Color(1.f, 1.f, 1.f, 1.f);
Color specular = Color(1.f, 1.f, 1.f, 1.f);
Color emissive = Color(1.f, 1.f, 1.f, 1.f);
Vec3 direction;
float padding0;
};
struct MaterialDesc
{
Color ambient = Color(0.f, 0.f, 0.f, 1.f);
Color diffuse = Color(1.f, 1.f, 1.f, 1.f);
Color specular = Color(0.f, 0.f, 0.f, 1.f);
Color emissive = Color(0.f, 0.f, 0.f, 1.f);
};
//Bone
#define MAX_BONE_TRANSFORMS 50
struct BoneDesc
{
Matrix transforms[MAX_BONE_TRANSFORMS];
};
class RenderManager
{
DECLARE_SINGLE(RenderManager);
public:
void Init(shared_ptr<Shader> shader);
void Update();
void PushGlobalData(const Matrix& view, const Matrix& projection);
void PushTransformData(const TransformDesc& desc);
void PushLightData(const LightDesc& desc);
void PushMaterialData(const MaterialDesc& desc);
void PushBoneData(const BoneDesc& desc);
private:
shared_ptr<Shader> _shader;
//프레임마다 한번만 세팅
GlobalDesc _globalDesc;
shared_ptr<ConstantBuffer<GlobalDesc>> _globalBuffer;
//정보넘겨주기
ComPtr<ID3DX11EffectConstantBuffer> _globalEffectBuffer;
TransformDesc _transformDesc;
shared_ptr<ConstantBuffer<TransformDesc>> _transformBuffer;
//정보넘겨주기
ComPtr<ID3DX11EffectConstantBuffer> _transformEffectBuffer;
LightDesc _lightDesc;
shared_ptr<ConstantBuffer<LightDesc>> _lightBuffer;
ComPtr<ID3DX11EffectConstantBuffer> _lightEffectBuffer;
MaterialDesc _materialDesc;
shared_ptr<ConstantBuffer<MaterialDesc>> _materialBuffer;
ComPtr<ID3DX11EffectConstantBuffer> _materialEffectBuffer;
BoneDesc _boneDesc;
shared_ptr<ConstantBuffer<BoneDesc>> _boneBuffer;
ComPtr<ID3DX11EffectConstantBuffer> _boneEffectBuffer;
};
RenderManager.cpp
void RenderManager::Init(shared_ptr<Shader> shader)
{
_shader = shader;
_globalBuffer = make_shared<ConstantBuffer<GlobalDesc>>();
_globalBuffer->Create();
_globalEffectBuffer = _shader->GetConstantBuffer("GlobalBuffer");
_transformBuffer = make_shared<ConstantBuffer<TransformDesc>>();
_transformBuffer->Create();
_transformEffectBuffer = _shader->GetConstantBuffer("TransformBuffer");
_lightBuffer = make_shared<ConstantBuffer<LightDesc>>();
_lightBuffer->Create();
_lightEffectBuffer = _shader->GetConstantBuffer("LightBuffer");
_materialBuffer = make_shared<ConstantBuffer<MaterialDesc>>();
_materialBuffer->Create();
_materialEffectBuffer = _shader->GetConstantBuffer("MaterialBuffer");
_boneBuffer = make_shared<ConstantBuffer<BoneDesc>>();
_boneBuffer->Create();
_boneEffectBuffer = _shader->GetConstantBuffer("BoneBuffer");
}
void RenderManager::PushBoneData(const BoneDesc& desc)
{
_boneDesc = desc;
_boneBuffer->CopyData(_boneDesc);
_boneEffectBuffer->SetConstantBuffer(_boneBuffer->GetComPtr().Get());
}
이제 이 Bone의 매트릭스를 곱해줘서 로컬좌표계로 가도록 처리해주자
ModelDemo.fx
#define MAX_MODEL_TRANSFORMS 50
cbuffer BoneBuffer
{
matrix BoneTransform[MAX_MODEL_TRANSFORMS];
};
uint BoneIndex;
MeshOutput VS(VertexTextureNormalTangent input)
{
MeshOutput output;
output.position = mul(input.position, BoneTransform[BoneIndex]);
output.position = mul(output.position, W);
output.worldPosition = output.position.xyz;
output.position = mul(output.position, VP);
output.uv = input.uv;
//회전만 고려
output.normal = mul(input.normal, (float3x3) W);
output.tangent = mul(input.tangent, (float3x3) W);
return output;
}
이렇게 해주면 이제 탱크모양이 정상적으로 나오게된다.
처음에 쉐이더에 들어가는 좌표는 우리가 Converter 클래스를 통해 가져온 Vertex 이다. 즉, 각 물체의 정점정보를 전달하고 있는 것이다. 이 좌표는 자기자신을 기준으로 하는 좌표계이다.
처음에 중심에 모여있던 이유는 각 계층별로 루트노드가 기준이 아니라 그냥 자기자신의 좌표를 바탕으로 원점에 배치가 되기 때문에 모든 계층이 겹쳐서 보였던 것이다. 그래서 이것을 바꿔주기 위해 VertexShader 단계에서 루트에서부터 타고오면서 자신의 부모의 좌표를 통해 계산된 자신의 Transform의 좌표를 통해 계산해주었다.
이렇게 해주어야 원래 루트를 기준으로 하는 로컬좌표를 계산해준 것으로 정해준 모양대로 출력될 수 있는 것이다.
'게임공부 > Directx11' 카테고리의 다른 글
[Directx11][C++][3D]13. 애니메이션(이론& 스키닝) (1) | 2024.09.16 |
---|---|
[Directx11][C++][3D]12. ImGUI (4) | 2024.09.15 |
[Directx11][C++][3D]9. Assimp(Bone & Model) (0) | 2024.09.14 |
[Directx11][C++][3D]8. Assimp(Material) (0) | 2024.09.14 |
[Directx11][C++][3D]7. Assimp(이론 및 설정) (0) | 2024.09.09 |