Mesh Sphere, Mesh Cylinder

구면 좌표계, 원통 좌표계

 

목차

     

     


     

     

    Mesh Sphere

     

     


    구면 좌표계

     

    https://ko.wikipedia.org/wiki/%EA%B5%AC%EB%A9%B4%EC%A2%8C%ED%91%9C%EA%B3%84#/media/%ED%8C%8C%EC%9D%BC:Spherical_coordinate.gif

     

     

    https://blog.naver.com/qio910/221499166816

     

    구면 좌표계(Spherical Coordinate System)

    이전 공부 구면 좌표계(Spherical coordinate system)는 3차원 공간의 한 점을 (r, θ, φ)로 나타냅니다....

    blog.naver.com

    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

     

    원통 좌표계(Cylindrical Coordinate System)

    이전 공부 다음 공부 원통 좌표계(cylindrical coordinate system)는 3차원 공간의 한 점을 (r, θ, z)로 ...

    blog.naver.com

    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