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.

MeshDataTool 사용하기

:ref:`MeshDataTool <class_meshdatatool>`은 형상을 생성하는 데 사용되지 않습니다. 그러나 예를 들어 메시를 테셀레이션, 단순화 또는 변형하기 위해 스크립트를 작성하려는 경우 지오메트리를 동적으로 변경하는 데 도움이 됩니다.

MeshDataTool은 :ref:`ArrayMesh <class_arraymesh>`을 사용하여 배열을 직접 변경하는 것만큼 빠르지 않습니다. 그러나 ArrayMesh보다 메쉬 작업에 더 많은 정보와 도구를 제공합니다. MeshDataTool을 사용하면 특정 메시 알고리즘에 필요한 면, 모서리 등 ArrayMesh에서 사용할 수 없는 메시 데이터를 계산합니다. 이 추가 정보가 필요하지 않으면 ArrayMesh를 사용하는 것이 더 나을 수 있습니다.

참고

MeshDataTool은 PrimitiveType ``Mesh.PRIMITIVE_TRIANGLES``를 사용하는 메시에서만 사용할 수 있습니다.

:ref:`create_from_surface() <class_meshdatatool_method_create_from_surface>`를 호출하여 ArrayMesh에서 MeshDataTool을 초기화합니다. MeshDataTool에 이미 초기화된 데이터가 있는 경우 ``create_from_surface()``를 호출하면 해당 데이터가 지워집니다. 또는 MeshDataTool을 재사용하기 전에 :ref:`clear() <class_meshdatatool_method_clear>`을 직접 호출할 수 있습니다.

아래 예에서는 ``mesh``라는 ArrayMesh가 이미 생성되었다고 가정합니다. 메시 생성의 예는 :ref:`ArrayMesh 튜토리얼 <doc_arraymesh>`을 참조하세요.

var mdt = MeshDataTool.new()
mdt.create_from_surface(mesh, 0)

``create_from_surface()``는 ArrayMesh의 정점 배열을 사용하여 두 개의 추가 배열(가장자리용으로 하나, 면용으로 하나)을 계산하여 총 3개의 배열을 만듭니다.

모서리는 두 정점 사이의 연결입니다. 가장자리 배열의 각 가장자리에는 해당 가장자리를 구성하는 두 개의 꼭지점과 그 안에 포함된 최대 두 개의 면에 대한 참조가 포함되어 있습니다.

면은 3개의 꼭지점과 3개의 해당 모서리로 구성된 삼각형입니다. 면 배열의 각 면에는 해당 면을 구성하는 세 개의 정점과 세 개의 가장자리에 대한 참조가 포함되어 있습니다.

정점 배열에는 각 정점과 연결된 가장자리, 면, 법선, 색상, 접선, uv, uv2, 뼈 및 가중치 정보가 포함됩니다.

이러한 배열의 정보에 액세스하려면 get_****() 형식의 함수를 사용합니다.

mdt.get_vertex_count() # Returns the number of vertices in the vertex array.
mdt.get_vertex_faces(0) # Returns an array of faces that contain vertex[0].
mdt.get_face_normal(1) # Calculates and returns the face normal of the second face.
mdt.get_edge_vertex(10, 1) # Returns the second vertex comprising the edge at index 10.

이러한 기능을 사용하여 수행할 작업은 귀하에게 달려 있습니다. 일반적인 사용 사례는 모든 정점을 반복하고 어떤 방식으로든 변환하는 것입니다.

for i in range(mdt.get_vertex_count()):
    var vert = mdt.get_vertex(i)
    vert *= 2.0 # Scales the vertex by doubling its size.
    mdt.set_vertex(i, vert)

이러한 수정은 ArrayMesh에서는 수행되지 않습니다. 기존 ArrayMesh를 동적으로 업데이트하는 경우 :ref:`commit_to_surface() <class_meshdatatool_method_commit_to_surface>`를 사용하여 새 표면을 추가하기 전에 먼저 기존 표면을 삭제하십시오.

mesh.clear_surfaces() # Deletes all of the mesh's surfaces.
mdt.commit_to_surface(mesh)

다음은 ``mesh``라는 구형 메시를 업데이트된 법선과 정점 색상을 갖춘 무작위로 변형된 얼룩으로 바꾸는 완전한 예입니다. 기본 메시를 생성하는 방법은 :ref:`ArrayMesh 튜토리얼 <doc_arraymesh>`을 참조하세요.

extends MeshInstance3D

var fnl = FastNoiseLite.new()
var mdt = MeshDataTool.new()

func _ready():
    fnl.frequency = 0.7

    mdt.create_from_surface(mesh, 0)

    for i in range(mdt.get_vertex_count()):
        var vertex = mdt.get_vertex(i).normalized()
        # Scale the vertices using noise.
        vertex = vertex * (fnl.get_noise_3dv(vertex) * 0.5 + 0.75)
        mdt.set_vertex(i, vertex)

    # Calculate the vertex normals, face-by-face.
    for i in range(mdt.get_face_count()):
        # Get the index in the vertex array.
        var a = mdt.get_face_vertex(i, 0)
        var b = mdt.get_face_vertex(i, 1)
        var c = mdt.get_face_vertex(i, 2)
        # Get the vertex position using the vertex index.
        var ap = mdt.get_vertex(a)
        var bp = mdt.get_vertex(b)
        var cp = mdt.get_vertex(c)
        # Calculate the normal of the face.
        var n = (bp - cp).cross(ap - bp).normalized()
        # Add this face normal to the current vertex normals.
        # This will not result in perfect normals, but it will be close.
        mdt.set_vertex_normal(a, n + mdt.get_vertex_normal(a))
        mdt.set_vertex_normal(b, n + mdt.get_vertex_normal(b))
        mdt.set_vertex_normal(c, n + mdt.get_vertex_normal(c))

    # Run through the vertices one last time to normalize their normals and
    # set the vertex colors to these new normals.
    for i in range(mdt.get_vertex_count()):
        var v = mdt.get_vertex_normal(i).normalized()
        mdt.set_vertex_normal(i, v)
        mdt.set_vertex_color(i, Color(v.x, v.y, v.z))

    mesh.clear_surfaces()
    mdt.commit_to_surface(mesh)