[DirectX11] 028 Mesh Sphere, Mesh Cylinder + 구면 좌표계, 원통 좌표계
Mesh Sphere, Mesh Cylinder
구면 좌표계, 원통 좌표계
목차
Mesh Sphere
구면 좌표계
https://blog.naver.com/qio910/221499166816
https://www.youtube.com/watch?v=5vUSrA9mqJk
https://www.youtube.com/watch?v=ae6kcOBEZK0
MeshSphere.cpp 내에 void MeshSphere::Create() 이 구면 좌표계 그리는 부분이다.
Vector3 p = Vector3
(
(radius * sinf(phi) * cosf(theta)),
(radius * cos(phi)),
(radius * sinf(phi) * sinf(theta))
);
Mesh Sphere
MeshSphere.h
더보기
#pragma once
class MeshSphere : public Mesh
{
public:
MeshSphere(Shader* shader, float radius, UINT stackCount = 20, UINT sliceCount = 20);
~MeshSphere();
private:
void Create() override;
float radius; //구를 그릴 반지름
UINT stackCount; //몇개로 분할해서 그리는가. 높을수록 정밀
UINT sliceCount; //몇개로 분할해서 그리는가. 높을수록 정밀
};
MeshSphere.cpp
더보기
#include "Framework.h"
#include "MeshSphere.h"
MeshSphere::MeshSphere(Shader * shader, float radius, UINT stackCount, UINT sliceCount)
: Mesh(shader), radius(radius), stackCount(stackCount), sliceCount(sliceCount)
{
}
MeshSphere::~MeshSphere()
{
}
void MeshSphere::Create()
{
//구면 좌표계
vector<MeshVertex> v;
v.push_back(MeshVertex(0, radius, 0, 0, 0, 0, 1, 0));//맨 위점
float phiStep = Math::PI / stackCount; // 180도/분할카운트
float thetaStep = Math::PI * 2.0f / sliceCount; // 360도/분할카운트
for (UINT i = 1; i <= stackCount - 1; i++) //맨 위점과 맨 밑점을 제외한 나머지
{
float phi = i * phiStep;
for (UINT k = 0; k <= sliceCount; k++)
{
float theta = k * thetaStep;
Vector3 p = Vector3
(
(radius * sinf(phi) * cosf(theta)),
(radius * cos(phi)),
(radius * sinf(phi) * sinf(theta))
);
Vector3 n;
D3DXVec3Normalize(&n, &p); //위치를 Normalize해서 크기를 1로 만들어 방향 벡터로 사용.
Vector2 uv = Vector2(theta / (Math::PI * 2), phi / Math::PI);
v.push_back(MeshVertex(p.x, p.y, p.z, uv.x, uv.y, n.x, n.y, n.z));
}
}
v.push_back(MeshVertex(0, -radius, 0, 0, 0, 0, -1, 0));//맨 밑점
vertices = new MeshVertex[v.size()];
vertexCount = v.size();
copy(v.begin(), v.end(), stdext::checked_array_iterator<MeshVertex *>(vertices, vertexCount));
vector<UINT> i;
for (UINT k = 1; k <= sliceCount; k++)
{
i.push_back(0);
i.push_back(k + 1);
i.push_back(k);
}
UINT baseIndex = 1;
UINT ringVertexCount = sliceCount + 1;
for (UINT k = 0; k < stackCount - 2; k++)
{
for (UINT j = 0; j < sliceCount; j++)
{
i.push_back(baseIndex + k * ringVertexCount + j);
i.push_back(baseIndex + k * ringVertexCount + j + 1);
i.push_back(baseIndex + (k + 1) * ringVertexCount + j);
i.push_back(baseIndex + (k + 1) * ringVertexCount + j);
i.push_back(baseIndex + k * ringVertexCount + j + 1);
i.push_back(baseIndex + (k + 1) * ringVertexCount + j + 1);
}
}
UINT southPoleIndex = v.size() - 1;
baseIndex = southPoleIndex - ringVertexCount;
for (UINT k = 0; k < sliceCount; k++)
{
i.push_back(southPoleIndex);
i.push_back(baseIndex + k);
i.push_back(baseIndex + k + 1);
}
indices = new UINT[i.size()];
indexCount = i.size();
copy(i.begin(), i.end(), stdext::checked_array_iterator<UINT *>(indices, indexCount));
int a = 0;
}
원통 좌표계
https://blog.naver.com/qio910/221498312675
https://www.youtube.com/watch?v=Y69CuegZIro
Mesh Cylinder
MeshCylinder.h
더보기
#pragma once
class MeshCylinder : public Mesh
{
public:
MeshCylinder(Shader* shader, float radius, float height, UINT stackCount, UINT sliceCount); //위,아래 반지름이 같은 경우 그리기
MeshCylinder(Shader* shader, float topRadius, float bottomRadius, float height, UINT stackCount, UINT sliceCount); //위,아래 반지름이 다른 경우 그리기
~MeshCylinder();
private:
void Create() override;
private:
void BuildTopCap(vector<MeshVertex>& vertices, vector<UINT>& indices);
void BuildBottomCap(vector<MeshVertex>& vertices, vector<UINT>& indices);
private:
float topRadius; //원통 상단 반지름
float bottomRadius;//원통 하단 반지름
float height;
UINT stackCount; //몇개로 분할해서 그리는가. 높을수록 정밀
UINT sliceCount; //몇개로 분할해서 그리는가. 높을수록 정밀
};
MeshCylinder.cpp
더보기
#include "Framework.h"
#include "MeshCylinder.h"
MeshCylinder::MeshCylinder(Shader * shader, float radius, float height, UINT stackCount, UINT sliceCount)
: Mesh(shader), topRadius(radius), bottomRadius(radius), height(height), stackCount(stackCount), sliceCount(sliceCount)
{
}
MeshCylinder::MeshCylinder(Shader * shader, float topRadius, float bottomRadius, float height, UINT stackCount, UINT sliceCount)
: Mesh(shader), topRadius(topRadius), bottomRadius(bottomRadius), height(height), stackCount(stackCount), sliceCount(sliceCount)
{
}
MeshCylinder::~MeshCylinder()
{
}
void MeshCylinder::Create()
{
vector<MeshVertex> v;
float stackHeight = height / (float)stackCount;
float radiusStep = (topRadius - bottomRadius) / (float)stackCount;
UINT ringCount = stackCount + 1;
for (UINT i = 0; i < ringCount; i++)
{
float y = -0.5f * height + i * stackHeight;
float r = bottomRadius + i * radiusStep;
float theta = 2.0f * Math::PI / (float)sliceCount;
for (UINT k = 0; k <= sliceCount; k++)
{
float c = cosf(k * theta);
float s = sinf(k * theta);
MeshVertex vertex;
vertex.Position = Vector3(r * c, y, r * s);
vertex.Uv = Vector2((float)k / (float)sliceCount, 1.0f - (float)i / (float)stackCount);
Vector3 tangent = Vector3(-s, 0.0f, c);
float dr = bottomRadius - topRadius;
Vector3 biTangent = Vector3(dr * c, -height, dr * s);
D3DXVec3Cross(&vertex.Normal, &tangent, &biTangent);
D3DXVec3Normalize(&vertex.Normal, &vertex.Normal);
v.push_back(vertex);
}
}
vector<UINT> i;
UINT ringVertexCount = sliceCount + 1;
for (UINT y = 0; y < stackCount; y++)
{
for (UINT x = 0; x < sliceCount; x++)
{
i.push_back(y * ringVertexCount + x);
i.push_back((y + 1) * ringVertexCount + x);
i.push_back((y + 1) * ringVertexCount + (x + 1));
i.push_back(y * ringVertexCount + x);
i.push_back((y + 1) * ringVertexCount + x + 1);
i.push_back(y * ringVertexCount + x + 1);
}
}
BuildTopCap(v, i);
BuildBottomCap(v, i);
vertices = new MeshVertex[v.size()];
vertexCount = v.size();
copy(v.begin(), v.end(), stdext::checked_array_iterator<MeshVertex *>(vertices, vertexCount));
indices = new UINT[i.size()];
indexCount = i.size();
copy(i.begin(), i.end(), stdext::checked_array_iterator<UINT *>(indices, indexCount));
}
void MeshCylinder::BuildTopCap(vector<MeshVertex>& vertices, vector<UINT>& indices)
{ //원통 상단
float y = 0.5f * height;
float theta = 2.0f * Math::PI / (float)sliceCount;
for (UINT i = 0; i <= sliceCount; i++)
{
float x = topRadius * cosf(i * theta);
float z = topRadius * sinf(i * theta);
float u = x / height + 0.5f;
float v = z / height + 0.5f;
vertices.push_back(MeshVertex(x, y, z, u, v, 0, 1, 0));
}
vertices.push_back(MeshVertex(0, y, 0, 0.5f, 0.5f, 0, 1, 0));
UINT baseIndex = vertices.size() - sliceCount - 2;
UINT centerIndex = vertices.size() - 1;
for (UINT i = 0; i < sliceCount; i++)
{
indices.push_back(centerIndex);
indices.push_back(baseIndex + i + 1);
indices.push_back(baseIndex + i);
}
}
void MeshCylinder::BuildBottomCap(vector<MeshVertex>& vertices, vector<UINT>& indices)
{ //원통 하단
float y = -0.5f * height;
float theta = 2.0f * Math::PI / (float)sliceCount;
for (UINT i = 0; i <= sliceCount; i++)
{
float x = bottomRadius * cosf(i * theta);
float z = bottomRadius * sinf(i * theta);
float u = x / height + 0.5f;
float v = z / height + 0.5f;
vertices.push_back(MeshVertex(x, y, z, u, v, 0, -1, 0));
}
vertices.push_back(MeshVertex(0, y, 0, 0.5f, 0.5f, 0, -1, 0));
UINT baseIndex = vertices.size() - sliceCount - 2;
UINT centerIndex = vertices.size() - 1;
for (UINT i = 0; i < sliceCount; i++)
{
indices.push_back(centerIndex);
indices.push_back(baseIndex + i);
indices.push_back(baseIndex + i + 1);
}
}
Mesh Demo
MeshDemo.h
더보기
#pragma once
#include "Systems/IExecute.h"
class MeshDemo : public IExecute
{
public:
virtual void Initialize() override;
virtual void Ready() override {}
virtual void Destroy() override;
virtual void Update() override;
virtual void PreRender() override {}
virtual void Render() override;
virtual void PostRender() override {}
virtual void ResizeScreen() override {}
private:
void CreateMesh();
private:
Shader* shader;
Vector3 direction = Vector3(-1, -1, 1);
ID3DX11EffectVectorVariable* sDirection;
MeshCube* cube;
MeshCylinder* cylinder[10];
MeshSphere* sphere[10];
MeshGrid* grid;
};
MeshDemo.cpp
더보기
#include "stdafx.h"
#include "MeshDemo.h"
void MeshDemo::Initialize()
{
Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
Context::Get()->GetCamera()->Position(1, 36, -85);
shader = new Shader(L"25_Mesh.fx");
sDirection = shader->AsVector("Direction");
CreateMesh();
}
void MeshDemo::Destroy()
{
SafeDelete(shader);
SafeDelete(cube);
SafeDelete(grid);
for (int i = 0; i < 10; i++)
{
SafeDelete(cylinder[i]);
SafeDelete(sphere[i]);
}
}
void MeshDemo::Update()
{
cube->Update();
grid->Update();
for (int i = 0; i < 10; i++)
{
cylinder[i]->Update();
sphere[i]->Update();
}
}
void MeshDemo::Render()
{
ImGui::SliderFloat3("Direction", direction, -1, +1);
sDirection->SetFloatVector(direction);
static int pass = 0;
ImGui::InputInt("Pass", &pass);
pass %= 2;
cube->Render();
grid->Render();
for (int i = 0; i < 10; i++)
{
cylinder[i]->Pass(pass);
cylinder[i]->Render();
sphere[i]->Pass(pass);
sphere[i]->Render();
}
}
void MeshDemo::CreateMesh()
{
cube = new MeshCube(shader);
cube->Position(0, 5, 0);
cube->Scale(20, 10, 20);
cube->DiffuseMap(L"Stones.png");
grid = new MeshGrid(shader, 6, 6);
grid->Scale(12, 1, 12);
grid->DiffuseMap(L"Floor.png");
//원통 10개, 구 10개 그리기
for (UINT i = 0; i < 5; i++)
{
cylinder[i * 2] = new MeshCylinder(shader, 0.5f, 3.0f, 20, 20);
cylinder[i * 2]->Position(-30, 6, (float)i * 15.0f - 15.0f);
cylinder[i * 2]->Scale(5, 5, 5);
cylinder[i * 2]->DiffuseMap(L"Bricks.png");
cylinder[i * 2 + 1] = new MeshCylinder(shader, 0.5f, 3.0f, 20, 20);
cylinder[i * 2 + 1]->Position(30, 6, (float)i * 15.0f - 15.0f);
cylinder[i * 2 + 1]->Scale(5, 5, 5);
cylinder[i * 2 + 1]->DiffuseMap(L"Bricks.png");
sphere[i * 2] = new MeshSphere(shader, 0.5f, 20, 20);
sphere[i * 2]->Position(-30, 15.5f, (float)i * 15.0f - 15.0f);
sphere[i * 2]->Scale(5, 5, 5);
sphere[i * 2]->DiffuseMap(L"Wall.png");
sphere[i * 2 + 1] = new MeshSphere(shader, 0.5f, 20, 20);
sphere[i * 2 + 1]->Position(30, 15.5f, (float)i * 15.0f - 15.0f);
sphere[i * 2 + 1]->Scale(5, 5, 5);
sphere[i * 2 + 1]->DiffuseMap(L"Wall.png");
}
}
실행화면
'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 031 Framework (0) | 2023.01.30 |
---|---|
[DirectX11] 029~30 Cube Map, Sphere Map (0) | 2023.01.27 |
[DirectX11] 027 Mesh Cube (0) | 2023.01.25 |
[DirectX11] 025~26 Mesh (0) | 2023.01.21 |
[DirectX11] 024 Vertical Raycast (0) | 2023.01.20 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 031 Framework
[DirectX11] 031 Framework
2023.01.30 -
[DirectX11] 029~30 Cube Map, Sphere Map
[DirectX11] 029~30 Cube Map, Sphere Map
2023.01.27 -
[DirectX11] 027 Mesh Cube
[DirectX11] 027 Mesh Cube
2023.01.25 -
[DirectX11] 025~26 Mesh
[DirectX11] 025~26 Mesh
2023.01.21