[D3D] Assimp - Bone, Mesh

vector·2025년 11월 24일

Bone, Mesh 데이터 가져오기

  • 루트부터 재귀를 통해서 정보를 읽어오기

Convert.cpp - RoadModelData()

  • 모든 노드를 순회하면서 각 노드 하나하나를 Bone로 저장
  • 각 노드의 transformParent기준인 상대좌표이기에, Root기준인 로컬 좌표로 변환
  • RoadMeshData()를 불러주고, 재귀를 통해서 모든 노드 순회
void Converter::ReadModelData(aiNode* node, int32 index, int32 parent)
{
	// 노드 하나하나를 Bone뼈대라고 생각하고 저장하면서 진행
	shared_ptr<asBone> bone = make_shared<asBone>();
	bone->index = index;
	bone->parent = parent;
	bone->name = node->mName.C_Str();

	// transform추출 - node->mTransformation의 주소받아주기
	// 첫번째 주소를 받으면 4x4를 복사해주는 방식
	Matrix transform(node->mTransformation[0]);
	// FBX포맷에서 순서가 뒤바뀌어 있기에 한번 Transpose() 해줌
	bone->transform = transform.Transpose();
	// -> parent기준의 좌표값 (Relative Transform)

	// Root(Local) 기준 - 
	// 재귀를 통해서 상위 parent의 transform이 모두 local상태로 변환 해준 상태이기에 새롭게 구하는 bone의 transform만 변환해주면 된다
	Matrix matParent = Matrix::Identity;
	if (parent >= 0)
		matParent = _bones[parent]->transform;

	// Local (Root) Transform
	bone->transform = bone->transform * matParent;

	_bones.push_back(bone);

	// Mesh
	ReadMeshData(node, index);


	// 재귀 함수
	for (uint32 i = 0; i < node->mNumChildren; i++)
		ReadModelData(node->mChildren[i], _bones.size(), index);
}

Converter.cpp - RoadMeshData()

  • 메쉬의 경우 서브메쉬로 나눠져 있는 경우가 있기에, 서브메쉬로 나누지말고 하나의 메쉬로 관리하는 방식으로 진행
void Converter::ReadMeshData(aiNode* node, int32 bone)
{
	if (node->mNumMeshes < 1)
		return;

	shared_ptr<asMesh> mesh = make_shared<asMesh>();
	mesh->name = node->mName.C_Str();
	mesh->boneIndex = bone;

	for (uint32 i = 0; i < node->mNumMeshes; i++)
	{
		// Scene에서 Mesh번호
		uint32 index = node->mMeshes[i];
		const aiMesh* srcMesh = _scene->mMeshes[index];

		// Material Name - Mesh와 Material의 관계도를 위해서
		const aiMaterial* material = _scene->mMaterials[srcMesh->mMaterialIndex];
		mesh->materialName = material->GetName().C_Str();

		// 시작 정점번호 (서브매쉬를 구분하기 위해서)
		const uint32 startVertex = mesh->vertices.size();

		for (uint32 v = 0; v < srcMesh->mNumVertices; v++)
		{
			// Vertex
			VertexType vertex;
			::memcpy(&vertex.position, &srcMesh->mVertices[v], sizeof(Vec3));

			// UV
			if (srcMesh->HasTextureCoords(0))
				::memcpy(&vertex.uv, &srcMesh->mTextureCoords[0][v], sizeof(Vec2));

			// Normal
			if (srcMesh->HasNormals())
				::memcpy(&vertex.normal, &srcMesh->mNormals[v], sizeof(Vec3));

			mesh->vertices.push_back(vertex);
		}

		// Index

		for (uint32 f = 0; f < srcMesh->mNumFaces; f++)
		{
			aiFace& face = srcMesh->mFaces[f];

			for (uint32 k = 0; k < face.mNumIndices; k++)
				mesh->indices.push_back(face.mIndices[k] + startVertex);
		}
	}

	_meshes.push_back(mesh);
}

참고 강의

https://www.inflearn.com/courses/lecture?courseId=329791&type=LECTURE&unitId=161140&tab=curriculum&subtitleLanguage=ko

profile
게임 클라이언트 프로그래머 준비중 (공부 및 기록용)

0개의 댓글