Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

결과 시험하기

이 튜토리얼에서는 ArrayMesh 사용의 기본 사항을 제시합니다.

이를 위해 최대 5개의 매개변수를 사용하는 add_surface_from_arrays() 함수를 사용합니다. 처음 두 개는 필수이고 마지막 세 개는 선택 사항입니다.

첫 번째 매개변수는 주어진 정점을 기반으로 프리미티브를 정렬하는 방법(예: 삼각형, 선, 점 등을 나타내는지 여부)을 GPU에 지시하는 OpenGL 개념인 ``PrimitiveType``입니다. 사용 가능한 옵션은 :ref:`Mesh.PrimitiveType <enum_Mesh_PrimitiveType>`을 참조하세요.

두 번째 파라미터 ``arrays``는 메쉬 정보를 저장하는 실제 Array입니다. 배열은 빈 괄호 ``[]``로 구성된 일반 Godot 배열입니다. 표면을 구축하는 데 사용될 각 정보 유형에 대해 ``Packed**Array``(예: PackedVector3Array, PackedInt32Array 등)를 저장합니다.

arrays``의 공통 요소는 ``arrays 내에서 가져야 하는 위치와 함께 아래에 나열되어 있습니다. 전체 목록은 :ref:`Mesh.ArrayType <enum_Mesh_ArrayType>`을 참조하세요.

인덱스

Mesh.ArrayType 열거형

배열 패턴(Array pattern)

0

ARRAY_VERTEX

PoolVector2Array: Vector2 오브젝트의 배열.

1

ARRAY_NORMAL

Vector3

2

ARRAY_TANGENT

PackedFloat32Array 또는 PackedFloat64Array 플로트 4개 그룹. 처음 3개의 부동 소수점은 접선을 결정하고 마지막 부동 소수점은 종법선 방향을 -1 또는 1로 결정합니다.

3

ARRAY_COLOR

Array

4

ARRAY_TEX_UV

PoolVector2Array: Vector2 오브젝트의 배열.

5

ARRAY_TEX_UV2

PoolVector2Array: Vector2 오브젝트의 배열.

10

ARRAY_BONES

PackedFloat32Array 4개 부동소수점 그룹 또는 PackedInt32Array 4개 정수 그룹. 각 그룹은 특정 정점에 영향을 미치는 4개 뼈의 인덱스를 나열합니다.

11

ARRAY_WEIGHTS

PackedFloat32Array 또는 PackedFloat64Array 플로트 4개 그룹. 각 부동 소수점은 지정된 정점에서 ``ARRAY_BONES``의 해당 뼈대가 갖는 가중치의 양을 나열합니다.

12

ARRAY_INDEX

Array

대부분의 경우 메시를 생성할 때 정점 위치로 정의합니다. 따라서 일반적으로 정점 배열(인덱스 0)은 필수인 반면, 인덱스 배열(인덱스 12)은 선택 사항이며 포함된 경우에만 사용됩니다. 정점 배열 없이 인덱스 배열만 사용하여 메쉬를 만드는 것도 가능하지만 이는 이 튜토리얼의 범위를 벗어납니다.

다른 모든 배열은 정점에 대한 정보를 전달합니다. 이는 선택 사항이며 포함된 경우에만 사용됩니다. 이러한 배열 중 일부(예: ARRAY_COLOR)는 정점에 대한 추가 정보를 제공하기 위해 정점당 하나의 항목을 사용합니다. 정점 배열과 크기가 동일해야 합니다. 다른 배열(예: ARRAY_TANGENT)은 4개의 항목을 사용하여 단일 정점을 설명합니다. 이는 정점 배열보다 정확히 4배 커야 합니다.

일반적인 사용의 경우 :ref:`add_surface_from_arrays() <class_arraymesh_method_add_surface_from_arrays>`의 마지막 세 매개 변수는 일반적으로 비어 있습니다.

결과 시험하기

편집기에서 :ref:`MeshInstance3D <class_meshinstance3d>`을 생성하고 인스펙터에 :ref:`ArrayMesh <class_arraymesh>`를 추가합니다. 일반적으로 편집기에서 ArrayMesh를 추가하는 것은 유용하지 않지만 이 경우 ArrayMesh를 생성하지 않고도 코드에서 액세스할 수 있습니다.

노드에 스크립트를 추가하기.

_ready() 아래에서 새 어레이를 생성합니다.

var surface_array = []

이는 표면 정보를 보관하는 배열이 됩니다. 표면에 필요한 모든 데이터 배열을 보관하게 됩니다. Godot는 크기가 ``Mesh.ARRAY_MAX``일 것으로 예상하므로 그에 맞게 크기를 조정하세요.

var surface_array = []
surface_array.resize(Mesh.ARRAY_MAX)

다음으로 사용할 각 데이터 유형에 대한 배열을 만듭니다.

var verts = PackedVector3Array()
var uvs = PackedVector2Array()
var normals = PackedVector3Array()
var indices = PackedInt32Array()

데이터 배열을 형상으로 채웠으면 각 배열을 ``surface_array``에 추가한 다음 메시에 커밋하여 메시를 생성할 수 있습니다.

surface_array[Mesh.ARRAY_VERTEX] = verts
surface_array[Mesh.ARRAY_TEX_UV] = uvs
surface_array[Mesh.ARRAY_NORMAL] = normals
surface_array[Mesh.ARRAY_INDEX] = indices

# No blendshapes, lods, or compression used.
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)

참고

이 예에서는 ``Mesh.PRIMITIVE_TRIANGLES``를 사용했지만 메시에서 사용 가능한 모든 기본 유형을 사용할 수 있습니다.

전체 코드를 종합하면 다음과 같습니다.

extends MeshInstance3D

func _ready():
    var surface_array = []
    surface_array.resize(Mesh.ARRAY_MAX)

    # PackedVector**Arrays for mesh construction.
    var verts = PackedVector3Array()
    var uvs = PackedVector2Array()
    var normals = PackedVector3Array()
    var indices = PackedInt32Array()

    #######################################
    ## Insert code here to generate mesh ##
    #######################################

    # Assign arrays to surface array.
    surface_array[Mesh.ARRAY_VERTEX] = verts
    surface_array[Mesh.ARRAY_TEX_UV] = uvs
    surface_array[Mesh.ARRAY_NORMAL] = normals
    surface_array[Mesh.ARRAY_INDEX] = indices

    # Create mesh surface from mesh array.
    # No blendshapes, lods, or compression used.
    mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)

중간에 들어가는 코드는 원하는 대로 지정할 수 있습니다. 아래에서는 직사각형으로 시작하여 모양을 생성하는 몇 가지 예제 코드를 제시합니다.

PCK 파일 생성하기

``Mesh.PRIMITIVE_TRIANGLES``를 사용하여 렌더링하므로 삼각형으로 직사각형을 구성합니다.

직사각형은 4개의 꼭지점을 공유하는 두 개의 삼각형으로 구성됩니다. 이 예에서는 아래와 같이 너비와 길이가 1인 ``(0, 0, 0)``에 왼쪽 상단 지점이 있는 직사각형을 만듭니다.

4개의 꼭지점을 공유하는 두 개의 삼각형으로 구성된 직사각형입니다.

이 직사각형을 그리려면 verts 배열에서 각 꼭지점의 좌표를 정의하십시오.

verts = PackedVector3Array([
        Vector3(0, 0, 0),
        Vector3(0, 0, 1),
        Vector3(1, 0, 0),
        Vector3(1, 0, 1),
    ])

uvs 배열은 텍스처의 일부가 메시에 들어가야 하는 위치를 설명하는 데 도움이 됩니다. 값 범위는 0에서 1까지입니다. 텍스처에 따라 이 값을 변경할 수 있습니다.

uvs = PackedVector2Array([
        Vector2(0, 0),
        Vector2(1, 0),
        Vector2(0, 1),
        Vector2(1, 1),
    ])

normals 배열은 정점이 향하는 방향을 설명하는 데 사용되며 조명 계산에 사용됩니다. 이 예에서는 기본적으로 Vector3.UP 방향을 사용합니다.

normals = PackedVector3Array([
        Vector3.UP,
        Vector3.UP,
        Vector3.UP,
        Vector3.UP,
    ])

indices 배열은 정점이 그려지는 순서를 정의합니다. Godot는 시계 방향 방향으로 렌더링합니다. 이는 우리가 그리려는 삼각형의 꼭지점을 시계 방향 순서로 지정해야 한다는 의미입니다.

예를 들어, 첫 번째 삼각형을 그리려면 정점 (0, 0, 0), (1, 0, 0), (0, 0, 1)``를 순서대로 그려야 합니다. 이는 ``verts 배열에 vert[0], vert[2], vert[1], 즉 인덱스 0, 2, 1을 그리는 것과 같습니다. 이러한 인덱스 값은 indices 배열이 정의하는 것입니다.

인덱스

x[index]

x[index]

x[index]

0

(0, 0, 0)

(0, 0)

벡터

1

(0, 0, 1)

(1, 0)

벡터

2

(1, 0, 0)

(0, 1)

벡터

3

(1, 0, 1)

(1, 1)

벡터

indices = PackedInt32Array([
        0, 2, 1, # Draw the first triangle.
        2, 3, 1, # Draw the second triangle.
    ])

종합하면 직사각형 생성 코드는 다음과 같습니다.

extends MeshInstance3D

func _ready():

  # Insert setting up the PackedVector**Arrays here.

  verts = PackedVector3Array([
          Vector3(0, 0, 0),
          Vector3(0, 0, 1),
          Vector3(1, 0, 0),
          Vector3(1, 0, 1),
      ])

  uvs = PackedVector2Array([
          Vector2(0, 0),
          Vector2(1, 0),
          Vector2(0, 1),
          Vector2(1, 1),
      ])

  normals = PackedVector3Array([
          Vector3.UP,
          Vector3.UP,
          Vector3.UP,
          Vector3.UP,
      ])

  indices = PackedInt32Array([
          0, 2, 1,
          2, 3, 1,
      ])

  # Insert committing to the ArrayMesh here.

더 복잡한 예를 보려면 아래의 구 생성 섹션을 참조하세요.

스프라이트 만들기

다음은 구를 생성하기 위한 샘플 코드입니다. 코드는 GDScript로 제공되지만 코드를 생성하는 접근 방식에 있어 Godot의 특별한 내용은 없습니다. 이 구현은 특별히 ArrayMesh와 관련이 없으며 구를 생성하는 일반적인 접근 방식일 뿐입니다. 이해하는 데 어려움이 있거나 일반적인 절차 형상에 대해 자세히 알아보고 싶다면 온라인에서 찾을 수 있는 튜토리얼을 사용할 수 있습니다.

extends MeshInstance3D

var rings = 50
var radial_segments = 50
var radius = 1

func _ready():

    # Insert setting up the PackedVector**Arrays here.

    # Vertex indices.
    var thisrow = 0
    var prevrow = 0
    var point = 0

    # Loop over rings.
    for i in range(rings + 1):
        var v = float(i) / rings
        var w = sin(PI * v)
        var y = cos(PI * v)

        # Loop over segments in ring.
        for j in range(radial_segments + 1):
            var u = float(j) / radial_segments
            var x = sin(u * PI * 2.0)
            var z = cos(u * PI * 2.0)
            var vert = Vector3(x * radius * w, y * radius, z * radius * w)
            verts.append(vert)
            normals.append(vert.normalized())
            uvs.append(Vector2(u, v))
            point += 1

            # Create triangles in ring using indices.
            if i > 0 and j > 0:
                indices.append(prevrow + j - 1)
                indices.append(prevrow + j)
                indices.append(thisrow + j - 1)

                indices.append(prevrow + j)
                indices.append(thisrow + j)
                indices.append(thisrow + j - 1)

        prevrow = thisrow
        thisrow = point

  # Insert committing to the ArrayMesh here.

저장하기

마지막으로 ResourceSaver 클래스를 사용하여 ArrayMesh를 저장할 수 있습니다. 이는 메시를 생성한 다음 나중에 다시 생성할 필요 없이 사용하려는 경우에 유용합니다.

# Saves mesh to a .tres file with compression enabled.
ResourceSaver.save(mesh, "res://sphere.tres", ResourceSaver.FLAG_COMPRESS)