[openGL] object loading

나우히즈·2024년 10월 8일

Graphics

목록 보기
10/17

서론

이전 포스팅에서 이야기했듯, 프로그래머가 일일히 버텍스를 찍어 오브젝트를 만드는것은 불편한 일이다. 이를 위해 모델링 프로그램을 활용한다. blender, maya와 같은 프로그램으로 오브젝트를 만들 수 있는데, 수 많은 모델링 프로그램들이 각기 다른 폼의 모델링 파일을 만들어낸다.

만들어진 파일을 사용하기 위해서는 각 파일에 맞는 파서(parser)를 제작하여 읽어들여야하지만 수 많은 형태의 파서를 제작하기란 쉬운 일이 아니다.

이를 위해 외부 라이브러리를 링크하여 모델링 파일을 읽어들여서 물체를 로딩해보도록 하자


Assimp

사용해볼 라이브러리는 assimp 라는 asset importer.

  • Open Asset Import Library (줄여서 assimp)
  • 매우 다양한 3D 모델 파일을 지원
  • Cross-platform
  • C / C++ interface

이 assimp라는 라이브러리를 통해 모델링 파일을 읽어들여서 렌더해보도록 하자.

scene tree

3D 그래픽스에서 Scene Tree(씬 트리)는 복잡한 3D 장면을 효율적으로 관리하고 조직하기 위해 계층 구조로 구성된 데이터 구조이다. 이 구조를 통해 장면(Scene) 내의 오브젝트, 빛, 카메라, 애니메이션 등을 직관적이고 효율적으로 관리할 수 있다.

Scene Tree는 주로 노드들로 이루어지며, 각 노드는 특정 3D 객체를 나타내거나 그룹화된 하위 객체들을 포함할 수 있다. 이 트리는 부모-자식 관계를 기반으로 한 계층 구조로 구성되어 있으며, 이로 인해 한 객체의 변형(위치, 회전, 스케일)이 해당 객체의 자식 객체들에도 영향을 미치는 변환 전파(Transformation propagation)가 가능하다.

Scene Tree의 주요 개념

  1. 노드(Node): Scene Tree의 기본 단위로, 3D 객체(메시), 빛, 카메라 등 모든 장면의 요소를 표현한다. 노드는 자체 변환(위치, 회전, 크기)과 자식 노드를 가질 수 있다.

  2. 부모-자식 관계(Parent-Child Relationship): 노드 간의 계층 구조를 통해 부모 노드의 변환이 자식 노드에 자동으로 적용된다. 예를 들어, 부모 노드가 회전하면 그 자식 노드들도 함께 회전합니다. 이를 통해 복잡한 장면에서 개체 간의 관계를 쉽게 관리할 수 있다. 예를 들어 캐릭터를 모델링한다고 할 때, 팔이 움직이면 손도 같이 움직여지듯, 팔-손이 부모-자식 관계를 가진다.

    • 루트 노드(Root Node): Scene Tree의 최상위 노드로, 모든 장면의 요소들은 이 루트 노드를 통해 연결된다. 보통 장면(scene)을 나타내는 추상적인 노드이다.
    • 자식 노드(Child Node): 부모 노드에 연결된 하위 노드들. 자식 노드는 자신의 부모 노드의 변환에 영향받음.
  3. 변환 전파(Transformation Propagation): 부모 노드의 위치, 회전, 스케일과 같은 변환이 자식 노드들에게 전파된다.

  4. 월드 좌표계(World Space)와 로컬 좌표계(Local Space):

    • 각 노드는 자신의 로컬 좌표계에서 위치, 회전, 크기를 가진다.
    • 부모 노드의 변환이 적용되어 최종적으로 월드 좌표계에서의 위치가 결정.
  5. 그룹화(Grouping): 여러 개체를 하나의 부모 노드로 묶어서 관리한다. 예를 들어, 자동차를 구성하는 여러 부품을 하나의 부모 노드로 묶어 자동차 전체를 하나의 객체처럼 다룰 수 있음.

Scene Tree와 관련된 알고리즘

트리 순회(Tree Traversal)

: Scene Tree의 노드를 처리할 때는 일반적으로 트리 순회 알고리즘이 사용됩니다. 보통 깊이 우선 탐색(DFS)을 사용하여 노드를 방문하고 변환을 적용합니다.

프러스텀 컬링(Frustum Culling)

: Scene Tree를 사용하면 시야에 보이지 않는 객체들을 빠르게 무시할 수 있습니다. 트리 구조에서 상위 노드가 화면에 보이지 않으면 그 자식 노드들도 모두 무시할 수 있기 때문에 렌더링 성능을 최적화하는 데 도움이 됩니다.

네, Assimp(Open Asset Import Library)도 3D 모델 파일을 읽을 때 씬 트리(Scene Tree) 구조를 사용합니다. Assimp는 다양한 3D 파일 형식을 로드하고 처리할 수 있는 라이브러리로, 3D 모델 데이터뿐만 아니라 장면의 계층적 구조도 제공합니다.

Assimp에서 로드된 모델은 aiScene이라는 구조로 표현되며, 이 구조 안에는 aiNode를 기반으로 한 계층적 트리가 포함됩니다. 이 aiNode들은 부모-자식 관계를 형성하며, 각각의 노드는 메쉬, 변환 정보, 자식 노드 등을 포함할 수 있습니다.

Assimp의 Scene Tree 구조

  1. aiScene:

    • Assimp의 전체 장면을 표현하는 구조체로, 모델의 메쉬, 재질, 텍스처, 애니메이션 등을 포함.
    • 장면의 최상위 루트 노드는 mRootNode로, 씬 트리의 루트 역할을 함.
  2. aiNode:

    • aiScene 내부에 있는 노드로, 씬 트리의 계층 구조를 형성.
    • aiNode는 자신의 변환 행렬(transformation matrix)을 가지고 있으며, 부모 노드의 변환을 상속받음.
    • aiNode는 여러 자식 노드들을 가짐. 즉, 복잡한 계층 구조를 나타낼 수 있다.
  3. aiMesh:

    • aiNode는 메쉬 정보를 포함할 수 있는데, 이 메쉬는 노드가 가지는 3D 모델 데이터이다.
    • 노드의 변환은 메쉬에 영향을 미쳐, 월드 좌표계에서 최종 위치가 결정됨.
  4. Transform Propagation:

    • 각 노드는 자신의 로컬 변환을 가지고 있고, 이 변환은 부모 노드로부터 상속됩니다. 부모 노드의 변환이 자식 노드에게 전파되어 최종 월드 좌표계에서의 위치와 상태를 결정함.

Assimp가 지원하는 다양한 파일 형식(예: FBX, OBJ)도 이러한 씬 트리 구조를 따르기 때문에, Assimp를 사용하여 다양한 형식의 모델을 로드할 때도 일관된 방식으로 처리하자.


assimp로 오브젝트 읽어들이기

  • assimp::Importer로 오브젝트 파일 read 하기.

  • RootNode 부터 읽어들임.

  • RootNode가 가진 메쉬 정보를 차례로 읽음

  • 읽은 메쉬 정보를 std::vector<mesh> 컨테이너로 묶어 각 요소에 VAO, VBO, EBO 저장

  • 이후 RootNode의 자식 노드에 대해 재귀적으로 위 과정 반복.

  • 모든 노드에 대해 읽었다면, 읽어들인 메쉬 정보들을 차례로 Draw.

  • 텍스쳐의 경우, std::vector<material> 컨테이너로 씬을 구성하는 매쉬들의 재질 정보를 담는다.

  • 각 메쉬에 해당하는 재질 diffuse, specular 텍스처를 불러와 컨테이너에 담기.

  • 매쉬를 구성한 후, 매쉬의 mesh->mMaterialIndex 에 해당하는 텍스처로 재질 값 set.

  • 텍스처는 프로그램의 유니폼으로 바인드하여 쉐이더로 보내야하므로 텍스처를 사용할 프로그램에 세팅

  • 모델 Draw.

0개의 댓글