DirectX

7.4 도형 기하구조

Awesome Red Tomato 2022. 1. 6. 11:03
  1. 원기둥 메시

조각이 8개, 더미가 3개, 고리가 4개인 원기둥

생성하는 원기둥 중심은 원첨이고 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;
}

나머지 메시는 생략...

 

구 메시(측지구 메시)는 차후 작성 예정