🔍 1. 탱크 모델을 로드해보자

✅ AssimpTool을 이용한 데이터 추출

void AssimpTool::Init()
{
	shared_ptr<Converter> converter = make_shared<Converter>();
	converter->ReadAssetFile(L"Tank/Tank.fbx");
	converter->ExportMaterialData(L"Tank/Tank");
	converter->ExportModelData(L"Tank/Tank");
}

실행하면 .mesh, .xml 형식의 커스텀 바이너리/텍스트 파일이 생성됩니다. 이는 FBX로부터 추출한 모델 및 머티리얼 정보를 우리 엔진 형식으로 저장한 결과입니다.


🧱 2. StaticMeshDemo에서 탱크 출력해보기

void StaticMeshDemo::CreateTank()
{
	shared_ptr<Model> model = make_shared<Model>();
	model->ReadModel(L"Tank/Tank");
	model->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(model);
	_obj->GetModelRenderer()->SetPass(1); // 와이어프레임 출력용
}

이제 실행하면 화면에 탱크가 출력됩니다. 하지만 모양이 이상하게 왜곡되어 중앙에 몰려 있는 듯한 모습이 보입니다.


❗ 문제의 원인: 계층 구조 무시

탱크 모델은 여러 개의 메시로 구성되어 있으며, 각 메시들은 Bone(Node)를 기준으로 좌표계가 설정되어 있습니다.
하지만 현재 우리는 Bone 정보를 사용하지 않고 메시를 출력했기 때문에, 각 파츠가 자신의 로컬 좌표계 기준으로만 출력되어 모두 원점에 겹쳐보이게 된 것입니다.


🧠 3. 계층 구조를 고려한 Bone Transform 처리

✅ Shader에 BoneBuffer 선언

#define MAX_MODEL_TRANSFORMS 50

cbuffer BoneBuffer
{
	matrix BoneTransforms[MAX_MODEL_TRANSFORMS];
};

uint BoneIndex;

각 메시가 어느 Bone에 소속되어 있는지 알려주는 인덱스를 통해, 메시 출력 전에 해당 Bone의 루트 기준 Transform 행렬을 곱해줍니다.


✅ RenderManager에 Bone 처리 시스템 추가

struct BoneDesc { Matrix transform[50]; };

void RenderManager::PushBoneData(const BoneDesc& desc)
{
	_boneDesc = desc;
	_boneBuffer->CopyData(_boneDesc);
	_boneEffectBuffer->SetConstantBuffer(_boneBuffer->GetComPtr().Get());
}

✅ ModelRenderer에서 Bone 정보 GPU에 전달

BoneDesc boneDesc;
for (uint32 i = 0; i < _model->GetBoneCount(); i++)
{
	auto bone = _model->GetBoneByIndex(i);
	boneDesc.transform[i] = bone->transform;
}
RENDER->PushBoneData(boneDesc);

// 메시 그리기 시 BoneIndex 전달
_shader->GetScalar("BoneIndex")->SetInt(mesh->boneIndex);

이제 GPU는 BoneIndexBoneTransforms를 바탕으로 로컬 좌표를 루트 기준으로 보정할 수 있게 됩니다.


✅ Vertex Shader에서 좌표 보정

output.position = mul(input.position, BoneTransforms[BoneIndex]); // 루트 기준 보정
output.position = mul(output.position, W); // 월드 변환
output.position = mul(output.position, VP); // 뷰 & 프로젝션

✅ 결과: 정상 출력된 탱크 모델

이제 탱크는 모든 파츠가 본래의 위치와 계층 구조를 지켜 올바르게 배치된 모습으로 출력됩니다.
포신, 바퀴, 차체 등이 각각의 노드에 따라 위치가 조정되어 계층적 구조가 표현된 결과입니다.


🔁 복기: 좌표계와 정점 정보의 관계

  • Converter::ReadMeshData()의 정점은 자기 자신을 기준으로 한 로컬 좌표계를 따릅니다.
  • Converter::ReadModelData()에서 구한 bone->transform = bone->transform * parentTransform루트를 기준으로 하는 좌표계로의 변환 행렬입니다.
  • 이를 쉐이더에 넘겨 VertexShader에서 한 번 곱해줌으로써, 정점들을 정확한 위치에 배치하게 됩니다.

profile
李家네_공부방

0개의 댓글