소년코딩

레이어(Layer)

FbxLayer 클래스는 FBX SDK 레이어 메커니즘을 구현하는 기본 클래스입니다. FBX에서는 메쉬의 표면을 덮는 레이어라는 개념을 사용합니다. 만약 박스가 하나 있고, 이 박스를 포장지로 덮는다면 이 포장지는 FBX에서의 레이어같은 역할을 합니다.

레이어(FbxLayer)는 아래와 같은 많은 레이어 요소(FbxLayerElement)를 포함할 수 있습니다.

  • Normals (FbxLayerElementNormal)
  • Binormals (FbxLayerElementBinormal)
  • Tangents (FbxLayerElementTangent)
  • Uvs (FbxLayerElementUV)
  • More...

레이어 요소(Layer Element)

예를 들어 메쉬의 노말 벡터는 FbxLayerElementNormal의 인스턴스로 정의됩니다.

FbxMesh::GetElementNormal() 멤버 함수로 접근 가능합니다.

// 정점 노말을 읽는 함수
vec3 ReadNormal(const FbxMesh* mesh, int controlPointIndex, int vertexCounter)
{
  if (mesh->GetElementNormalCount() < 1) // 노말의 개수를 센다.
    std::cout << "No normals!" << std::endl;

  const FbxGeometryElementNormal* vertexNormal = mesh->GetElementNormal(0); // 노말 획득
  vec3 result; // 노말 벡터를 저장할 벡터

  // ...
}

/* 생략 */
vec3* positions = nullptr;  // 정점 위치 리스트
ProcessControlPoints(mesh); // 제어점으로부터 위치 리스트를 채운다.
unsigned int triCount = mesh->GetPolygonCount(); // 메쉬의 삼각형 개수를 가져온다.
unsigned int vertexCount = 0; // 정점의 개수

for(unsigned int i = 0; i < triCount; ++i) // 삼각형의 개수
{
  for(unsigned int j = 0; j < 3; ++j) // 삼각형은 세 개의 정점으로 구성
  {
    int controlPointIndex = mesh->GetPolygonVertex(i, j); // 제어점 인덱스를 가져온다.

    vec3& position = positions[controlPointIndex];  // 현재 정점에 대한 위치

    vec3 normal = ReadNormal(mesh, controlPointIndex, vertexCounter); // 노말 벡터

    vertexCount++; // 정점의 개수++
  }
}

노말과 같은 레이어 요소는 아래와 같은 다양한 방법으로 메쉬에 표면에 매핑 될 수 있습니다.

  • 제어점(control point): eByControlPoint
  • polygon vertex: eByPolygonVertex
  • etc...

매핑 모드는 FbxLayerElement::GetMappingMode() 멤버 함수로 알 수 있습니다.

// 정점 노말을 읽는 함수
vec3 ReadNormal(const FbxMesh* mesh, int controlPointIndex, int vertexCounter)
{
  if (mesh->GetElementNormalCount() < 1) // 노말의 개수를 센다.
    std::cout << "No normals!" << std::endl;

  const FbxGeometryElementNormal* vertexNormal = mesh->GetElementNormal(0); // 노말 획득
  vec3 result; // 노말 벡터를 저장할 벡터

  switch(vertexNormal->GetMappingMode) // 매핑 모드
  {
    case FbxGeometryElement::eByControlPoint:
      // control point mapping
      break;
    case FbxGeometryElement::eByPolygonVertex:
      // polygon vertex mapping
  }

  return result;
}

제어점(control point): eByControlPoint에 매핑된 경우

각 제어점(정점)마다 하나의 매핑 좌표가 있음울 의미합니다.

노말 벡터의 배열과 제어점의 배열이 주어지면 노말 벡터의 배열이 제어점의 배열로 참조되는 방법을 알 수 있습니다.

참조되는 방법은 GetReferenceMode() 멤버 함수로 알 수 있으며, 아래와 같은 참조 모드를 가지고 있습니다.

  • FbxLayerElement::eDirect : 이것은 n 번째 요소에 대한 매핑 정보가 FbxLayerElementTemplate::mDirectArray서의 n번째 위치에서 발견되었음을 나타냅니다.
  • FbxLayerElement::eIndexToDirect : 이것은 FbxLayerElementTemplate::mIndexArray의 각 요소에 FbxLayerElementTemplate::mDirectArray의 요소를 나타내는 인덱스가 있음을 나타냅니다.
  • etc..
// 정점 노말을 읽는 함수
vec3 ReadNormal(const FbxMesh* mesh, int controlPointIndex, int vertexCounter)
{
  if (mesh->GetElementNormalCount() < 1) // 노말의 개수를 센다.
    std::cout << "No normals!" << std::endl;

  const FbxGeometryElementNormal* vertexNormal = mesh->GetElementNormal(0); // 노말 획득
  vec3 result; // 노말 벡터를 저장할 벡터

  switch(vertexNormal->GetMappingMode) // 매핑 모드
  {
    case FbxGeometryElement::eByControlPoint:
      // control point mapping
      switch (vertexNormal->GetReferenceMode())
          {
            case FbxGeometryElement::eDirect:
            {
               result.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(controlPointIndex).mData[0]);
               result.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(controlPointIndex).mData[1]);
               result.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(controlPointIndex).mData[2]);
            }
            break;

            case FbxGeometryElement::eIndexToDirect:
            {
               int index = vertexNormal->GetIndexArray().GetAt(controlPointIndex); // 인덱스를 얻어온다.
               result.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[0]);
               result.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[1]);
               result.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[2]);
            }
            break;
    break;

    case FbxGeometryElement::eByPolygonVertex:
      // polygon vertex mapping
  }

  return result;
}

polygon vertex: eByPolygonVertex에 매핑된 경우

각 꼭지점(정점)마다 하나의 매핑 좌표가 있음울 의미합니다.

switch(vertexNormal->GetMappingMode) // 매핑 모드
{
  case FbxGeometryElement::eByControlPoint:
    // control point mapping
    switch (vertexNormal->GetReferenceMode())
    {
      /* 생략 */
  break;

  case FbxGeometryElement::eByPolygonVertex:
    // polygon vertex mapping
    switch (vertexNormal->GetReferenceMode())
        {
        case FbxGeometryElement::eDirect:
        {
            result.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(vertexCounter).mData[0]);
            result.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(vertexCounter).mData[1]);
            result.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(vertexCounter).mData[2]);
        }
        break;

        case FbxGeometryElement::eIndexToDirect:
        {
            int index = vertexNormal->GetIndexArray().GetAt(vertexCounter); // 인덱스를 얻어온다.
            result.x = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[0]);
            result.y = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[1]);
            result.z = static_cast<float>(vertexNormal->GetDirectArray().GetAt(index).mData[2]);
        }
        break;
  break;
}

fbx

댓글 로드 중…

블로그 정보

소년코딩 - 소년코딩

소년코딩, 자바스크립트, C++, 물리, 게임 코딩 이야기

최근에 게시된 이야기