본문 바로가기
3D 프로그래밍 수업(일부비공개)

심화 수업13일차 - mesh2

by MY블로그 2023. 5. 8.

개발자들이 매쉬를 다룰때는 이미구현되어있는 것들을 사용함.

때문에 기존에있는 메쉬를 저장하거나 불러오는 함수를 만들 것.

 

극좌표 (세타,반지름)

현재우리가쓰는 각도는 데카르트좌표

원둘레좌표 = 극좌표

구표면의좌표 = (세타,파이,반지름)

세타 = 위도

파이 = 경도

위에서부터의각도가 경도

아래서부터의각도가 위도

 

구면좌표

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

 

구면좌표계 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 구면좌표계(球面座標係, spherical coordinate system)는 3차원 공간 상의 점들을 나타내는 좌표계의 하나로, 보통 ( r , ϕ , θ ) {\displaystyle (r,\phi ,\theta )} 로 나타낸다.

ko.wikipedia.org

 

 

과제 : 구체그리기 (구면좌표이용, 선이나 점을 이용한다)

 

 

당일 수업 정리

2DFrameWork / GameObject / Member / Mesh.h
#pragma once
class Mesh
{
    friend class GameObject;
private:
    ID3D11Buffer*           vertexBuffer; // 버텍스버퍼 주소 담을 변수
    ID3D11Buffer*           indexBuffer; // 인덱스버퍼 주소 담을 변수

    D3D_PRIMITIVE_TOPOLOGY  primitiveTopology; // 점그리는 방식넣을 변수
    VertexType              vertexType; // 정점 타입 넣는 변수
    UINT                    byteWidth;

    UINT*                   indices; // 인덱스 연결
    UINT                    indexCount; // 인덱스 카운트
    void*                   vertices; // 정점을 담을 void* 형 변수 (어떤자료형이담길지모르니)
    UINT                    vertexCount; // 정점 카운트
public:
    string                  file; // 파일 불러오고 저장할 문자열 변수 (파일 이름)
public:
    Mesh(); // 생성자
    ~Mesh(); // 소멸자
    void Set(); // D3D 셋
    void LoadFile(string file); // 파일 불러오기
    void SaveFile(string file); // 파일 저장하기
};
2DFrameWork / GameObject / Member / Mesh.cpp
#include "framework.h"

Mesh::Mesh() // 생성자
{
    vertexType = VertexType::P; // 열거형중에 P(0)으로 타입 설정
    primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; // 토폴로지. 정점을 점찍는 형식으로
    vertexCount = 360 * 180; // 원형을 그리기위한 정점 갯수 = 360도(가로,혹은 세로의 원을) 180도 회전시키면 구형이되기때문에
    byteWidth = sizeof(VertexP); // VertexP 내부에 정점 position 변수있음 (Vector3 형태/구면좌표용)
    VertexP* Vertex = new VertexP[vertexCount]; // 동적할당, Vertex 변수에 360*180개 배열 할당.

    indexCount = 360 * 180; // 인덱스 카운트 = 정점 갯수
    indices = new UINT[indexCount]; // UINT = Unsigned Int 

    for (int i = 0; i < 180; i++) // 먼저안쪽포문에서 평면 원형으로 정점만들고 180도 회전시켜 구체정점 만든다
    {
        for (int j = 0; j < 360; j++) // 구면 좌표사용
        {
          // 구면 좌표계 에서 직교좌표계로 변경하는 공식을 사용한다.
          // sin cos tan = simplemath 사용
            Vertex[i * 360 + j].position = Vector3(
              sin(i * TORADIAN) * cos(j * TORADIAN),
              sin(i * TORADIAN) * sin(j * TORADIAN),
              cos(i * TORADIAN) 
            );
        }
    }
    for (int i = 0; i < 180; i++)
    {
      for (int j = 0; j < 360; j++)
      {
        indices[i * 360 + j] = i * 360 + j;
      }
    }
    vertices = Vertex;

    //CreateVertexBuffer 정점버퍼 생성
    {
        D3D11_BUFFER_DESC desc;
        desc = { 0 };
        desc.Usage = D3D11_USAGE_DEFAULT;
        desc.ByteWidth = byteWidth * vertexCount;
        desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

        D3D11_SUBRESOURCE_DATA data = { 0 };
        data.pSysMem = vertices;

        HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, &data, &vertexBuffer);
        assert(SUCCEEDED(hr));
    }

    //Create Index Buffer 인덱스(목록)버퍼 생성
    {
        D3D11_BUFFER_DESC desc;
        ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
        desc.ByteWidth = sizeof(UINT) * indexCount;
        desc.BindFlags = D3D11_BIND_INDEX_BUFFER;

        D3D11_SUBRESOURCE_DATA data = { 0 };
        data.pSysMem = indices;

        HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, &data, &indexBuffer);
        assert(SUCCEEDED(hr));
    }
}

Mesh::~Mesh() // 소멸자
{
}

void Mesh::Set()
{
    UINT offset = 0;
    D3D->GetDC()->IASetVertexBuffers(0,
        1,
        &vertexBuffer,
        &byteWidth,
        &offset);
    D3D->GetDC()->IASetPrimitiveTopology(primitiveTopology);
    D3D->GetDC()->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
}

void Mesh::LoadFile(string file) // 파일 불러오기
{
    this->file = file; // 선택한 파일
    BinaryReader in; // 이진법으로 읽기
    wstring path = L"../Contents/Mesh/" + Util::ToWString(file); // 경로 (..) 상위경로에서 순서대로 접근
    in.Open(path); // 경로 열기

    //읽기전
    switch (vertexType) 
    { // 읽기전에 버텍스 타입이 정해져있다면 먼저 삭제해야 한다. 정보가 없다면 아래진행
    case VertexType::P:
        if (vertices)delete[](VertexP*)vertices;
        break;
    case VertexType::PC:
        if (vertices)delete[](VertexPC*)vertices;
        break;
    case VertexType::PCN:
        if (vertices)delete[](VertexPCN*)vertices;
        break;
    case VertexType::PTN:
        if (vertices)delete[](VertexPTN*)vertices;
        break;
    case VertexType::MODEL:
        if (vertices)delete[](VertexModel*)vertices;
        break;
    case VertexType::TERRAIN:
        if (vertices)delete[](VertexTerrain*)vertices;
        break;
    case VertexType::PT:
        if (vertices)delete[](VertexPT*)vertices;
        break;
    case VertexType::PS:
        if (vertices)delete[](VertexPS*)vertices;
        break;
    case VertexType::PSV:
        if (vertices)delete[](VertexPSV*)vertices;
        break;
    } // 먼저 정보가 있는것이 사제 되었다면 아래진행.

    // 파일에 기록된 정보를 순서대로 읽는다.
    vertexType = (VertexType)in.UInt(); // 1. 파일의 정점타입
    primitiveTopology = (D3D_PRIMITIVE_TOPOLOGY)in.UInt(); // 2. 토폴로지 정점그리는 방식
    byteWidth = in.UInt(); // 바이트위드
    vertexCount = in.UInt(); // 정점카운트
    indexCount = in.UInt(); // 인덱스카운트

    SafeDeleteArray(indices); // 일단 먼저 들어있던 indices를 해제해주고
    indices = new UINT[indexCount]; // 열린파일의 정보로 재할당 해준다.

    // 먼저있던 정보가 어디의 어떤 정보인지 모르는 상태이기때문에
    // 원하는 정보를 읽기 위해서는 기존에 있는 뭔지모를 정보를 삭제해주고 읽어야한다!

    //읽고난후
    switch (vertexType)
    { // 읽기전에 삭제를 했다면 읽고난후에는 각 정보들을 할당해 주어야 한다!
      case VertexType::P: // P 타입은 정점의 위치정보만
      {
          vertices = new VertexP[vertexCount];
          VertexP* vertex = (VertexP*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
          }
          break;
      }

      case VertexType::PC: // PC 타입은 정점의 위치 + 색상
      {
          vertices = new VertexPC[vertexCount];
          VertexPC* vertex = (VertexPC*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].color = in.color3f();
          }
          break;
      }
      case VertexType::PCN: // PCN 타입은 정점의 위치 + 색상 + 노멀? 아직노멀이뭔지는 모르겠다.
      {
          vertices = new VertexPCN[vertexCount];
          VertexPCN* vertex = (VertexPCN*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].color = in.color3f();
              vertex[i].normal = in.vector3();
          }
          break;
      }
      case VertexType::PTN: // PTN 타입은 정점의 위치 + UV + 노멀 ... 아래쪽부터는 아직 모르는 부분들많음 생략
      {
          vertices = new VertexPTN[vertexCount];
          VertexPTN* vertex = (VertexPTN*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].uv = in.vector2();
              vertex[i].normal = in.vector3();
          }
          break;
      }
      case VertexType::MODEL:
      {
          vertices = new VertexModel[vertexCount];
          VertexModel* vertex = (VertexModel*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].uv = in.vector2();
              vertex[i].normal = in.vector3();
              vertex[i].tangent = in.vector3();
              vertex[i].indices = in.vector4();
              vertex[i].weights = in.vector4();
          }
          break;
      }
      case VertexType::TERRAIN:
      {
          vertices = new VertexTerrain[vertexCount];
          VertexTerrain* vertex = (VertexTerrain*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].uv = in.vector2();
              vertex[i].normal = in.vector3();
              vertex[i].weights = in.Float();
          }
          break;
      }
      case VertexType::PT:
      {
          vertices = new VertexPT[vertexCount];
          VertexPT* vertex = (VertexPT*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].uv = in.vector2();
          }
          break;
      }
      case VertexType::PS:
      {
          vertices = new VertexPS[vertexCount];
          VertexPS* vertex = (VertexPS*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].size = in.vector2();
          }
          break;
      }
      case VertexType::PSV:
      {
          vertices = new VertexPSV[vertexCount];
          VertexPSV* vertex = (VertexPSV*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              vertex[i].position = in.vector3();
              vertex[i].size = in.vector2();
              vertex[i].velocity = in.vector3();
          }
          break;
      }
    }// 스위치문 끝
    for (UINT i = 0; i < indexCount; i++)
    {
        indices[i] = in.UInt();
    }
    in.Close();

    SafeRelease(vertexBuffer);
    SafeRelease(indexBuffer);
    //CreateVertexBuffer 다읽고 정점 버퍼 생성
    {
        D3D11_BUFFER_DESC desc;
        desc = { 0 };
        desc.Usage = D3D11_USAGE_DEFAULT;
        desc.ByteWidth = byteWidth * vertexCount;
        desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

        D3D11_SUBRESOURCE_DATA data = { 0 };
        data.pSysMem = vertices;

        HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, &data, &vertexBuffer);
        assert(SUCCEEDED(hr));
    }

    //Create Index Buffer 다읽고 인덱스 버퍼 생성
    {
        D3D11_BUFFER_DESC desc;
        ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
        desc.ByteWidth = sizeof(UINT) * indexCount;
        desc.BindFlags = D3D11_BIND_INDEX_BUFFER;

        D3D11_SUBRESOURCE_DATA data = { 0 };
        data.pSysMem = indices;

        HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, &data, &indexBuffer);
        assert(SUCCEEDED(hr));
    }

}

void Mesh::SaveFile(string file) // 파일 저장 하기 (내보내기)
{ // 파일 읽기와 비슷하다. 읽기는 in, 저장(내보내기)는 out 내보낼때는 버퍼생성은 없다!
    this->file = file;

    BinaryWriter out;
    wstring path = L"../Contents/Mesh/" + Util::ToWString(file);
    out.Open(path);

    out.UInt((UINT)vertexType);
    out.UInt((UINT)primitiveTopology);
    out.UInt(byteWidth);
    out.UInt(vertexCount);
    out.UInt(indexCount);

    switch (vertexType)
    {
      case VertexType::P:
      {
          VertexP* vertex = (VertexP*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
          }
          break;
      }

      case VertexType::PC:
      {
          VertexPC* vertex = (VertexPC*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.color3f(vertex[i].color);
          }
          break;
      }
      case VertexType::PCN:
      {
          VertexPCN* vertex = (VertexPCN*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.color3f(vertex[i].color);
              out.vector3(vertex[i].normal);
          }
          break;
      }
      case VertexType::PTN:
      {
          VertexPTN* vertex = (VertexPTN*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.vector2(vertex[i].uv);
              out.vector3(vertex[i].normal);
          }
          break;
      }
      case VertexType::MODEL:
      {
          VertexModel* vertex = (VertexModel*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.vector2(vertex[i].uv);
              out.vector3(vertex[i].normal);
              out.vector3(vertex[i].tangent);
              out.vector4(vertex[i].indices);
              out.vector4(vertex[i].weights);
          }
          break;
      }
      case VertexType::TERRAIN:
      {
          VertexTerrain* vertex = (VertexTerrain*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.vector2(vertex[i].uv);
              out.vector3(vertex[i].normal);
              out.Float(vertex[i].weights);
          }
          break;
      }
      case VertexType::PT:
      {
          VertexPT* vertex = (VertexPT*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.vector2(vertex[i].uv);
          }
          break;
      }
      case VertexType::PS:
      {
          VertexPS* vertex = (VertexPS*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.vector2(vertex[i].size);
          }
          break;
      }
      case VertexType::PSV:
      {
          VertexPSV* vertex = (VertexPSV*)vertices;
          for (UINT i = 0; i < vertexCount; i++)
          {
              out.vector3(vertex[i].position);
              out.vector2(vertex[i].size);
              out.vector3(vertex[i].velocity);
          }
          break;
      }
    }//스위치문 끝
    for (UINT i = 0; i < indexCount; i++)
    {
        out.UInt(indices[i]);
    }
    out.Close();
}

댓글