DirectX
7.4 도형 기하구조
Awesome Red Tomato
2022. 1. 6. 11:03
- 원기둥 메시

생성하는 원기둥 중심은 원첨이고 y축 방향으로 서 있는 형태다. 모든 정점은 '고리'들에 있다. 더미의 개수가 stackCount라고 할 때 고리들은 총 stackCount + 1개이다.
그리고 각 고리는 sliceCount개의 고유한 정점들로 구성된다. 인접한 고리들의 반지름 차이는

이다. 최하단 고리가 0번째 라고 할 때, i번째 고리의 반지름은

이고, 높이는

가 된다. 여기서 △h는 더미 하나당 높이고 h는 원기둥의 높이이다.
그럼 여기서 조각의 정점 좌표와 인덱스는 아래와 같이 될 것이다.


GeometryGenerator::MeshData GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, uint32_t sliceCount, uint32_t stackCount)
{
MeshData meshData;
// 더미 높이
float stackHeight = height / stackCount;
// 반지름 변화량
float radiusStep = (topRadius - bottomRadius) / stackCount;
// 고리 개수
uint32_t ringCount = stackCount + 1;
for (uint32_t i = 0; i < ringCount; i++)
{
// 최하단 + i층 더미 높이
float y = -0.5f * height + (i * stackHeight);
float r = bottomRadius + (i * radiusStep);
// 조각의 각도 변화량
float dTheta = XM_2PI / sliceCount;
for (uint32_t j = 0; j <= sliceCount; j++)
{
Vertex vertex;
float c = cosf(j * dTheta);
float s = sinf(j * dTheta);
// 정점 좌표
vertex.Position = XMFLOAT3(r * c, y, r * s);
// // 텍스처 좌표
vertex.TexC.x = (float)j / sliceCount;
vertex.TexC.y = 1.0f - (float)i / stackCount;
// 단위길이 벡터
vertex.TangentU = XMFLOAT3(-s, 0.0f, c);
float dr = bottomRadius - topRadius;
XMFLOAT3 bitangent(dr * c, -height, dr * s);
XMVECTOR T = XMLoadFloat3(&vertex.TangentU);
XMVECTOR B = XMLoadFloat3(&bitangent);
XMVECTOR N = XMVector3Normalize(XMVector3Cross(T, B));
XMStoreFloat3(&vertex.Normal, N);
meshData.Vertices.push_back(vertex);
}
}
// 한 고리의 첫 정점과 마지막 정점의 위치가 같지만 텍스처 좌표는 다르므로
// 서로 다른 정점으로 간주해야 한다. 그래서 총 정점 = 고리개수 + 1
uint32_t ringVertexCount = sliceCount + 1;
for (uint32_t i = 0; i < stackCount; ++i)
{
for (uint32_t j = 0; j <= sliceCount; ++j)
{
meshData.Indices32.push_back(i * ringVertexCount + j);
meshData.Indices32.push_back((i + 1) * ringVertexCount + j);
meshData.Indices32.push_back((i + 1) * ringVertexCount + (j + 1));
meshData.Indices32.push_back(i * ringVertexCount + j);
meshData.Indices32.push_back((i + 1) * ringVertexCount + j + 1);
meshData.Indices32.push_back(i * ringVertexCount + j + 1);
}
}
BuildCylinderTopCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData);
BuildCylinderBottomCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData);
return meshData;
}
나머지 메시는 생략...
구 메시(측지구 메시)는 차후 작성 예정