MeshDataToolの使用
MeshDataTool はジオメトリの生成には使用されません。しかしメッシュをテッセレーションしたり、簡略化したり、または変形するスクリプトを作成する場合など、ジオメトリを動的に変更するのに役立ちます。
MeshDataToolは、ArrayMeshを使用して配列を直接変更するほど高速ではありません。ただし、ArrayMeshよりも多くの情報とメッシュを操作するツールを提供します。 MeshDataToolを使用すると、特定のメッシュアルゴリズムに必要なFace(面)やEdge(エッジ/辺)などのArrayMeshでは使用できないメッシュデータが計算されます。この追加情報が必要ない場合は、ArrayMeshを使用することをお勧めします。
注釈
MeshDataToolは、PrimitiveType Mesh.PRIMITIVE_TRIANGLES を使用するメッシュでのみ使用できます。
create_from_surface() を呼び出して ArrayMesh から MeshDataTool を初期化します。なお MeshDataTool にすでに初期化されたデータがある場合は create_from_surface() を呼び出すとデータがクリアされます。または MeshDataTool を再利用する前に、自分で clear() を呼び出すこともできます。
以下の例では mesh という ArrayMesh がすでに作成されているものとします。メッシュ生成の例については ArrayMesh チュートリアル を参照してください。
var mdt = MeshDataTool.new()
mdt.create_from_surface(mesh, 0)
create_from_surface() は、ArrayMesh の頂点配列を使用して、エッジ用と面用の2つの追加配列を計算し、合計3つの配列を作成します。
エッジは、任意の2つの頂点間の接続です。エッジ配列の各エッジには、それが構成する2つの頂点への参照と、それが含まれる最大2つの面が含まれます。
面は3つの頂点とそれに対応する3つの辺で構成される三角形です。面配列の各面には、その面を構成する3つの頂点と3つの辺への参照が含まれています。
頂点配列には各頂点に接続されたエッジ、面、法線、色、接線、UV、UV2、ボーン、およびウェイトの情報が含まれます。
これらの配列から情報にアクセスするには、get _****() 形式の関数を使用します:
mdt.get_vertex_count() # Returns number of vertices in vertex array.
mdt.get_vertex_faces(0) # Returns array of faces that contain vertex[0].
mdt.get_face_normal(1) # Calculates and returns 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(get_vertex_count):
var vert = mdt.get_vertex(i)
vert *= 2.0 # Scales the vertex by doubling size.
mdt.set_vertex(i, vert)
これらの変更は ArrayMesh 上では実行されません。既存の ArrayMesh を動的に更新する場合は、まず既存のサーフェスを削除してから、 commit_to_surface() を使用して新しいサーフェスを追加します。
mesh.clear_surfaces() # Deletes all of the mesh's surfaces.
mdt.commit_to_surface(mesh)
以下は mesh と呼ばれる球状メッシュを、法線と頂点カラーが更新されたランダムに変形された塊に変換するサンプルです。ベース メッシュの生成方法については 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()
# Push out vertex by noise.
vertex = vertex * (fnl.get_noise_3dv(vertex) * 0.5 + 0.75)
mdt.set_vertex(i, vertex)
# Calculate 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 vertex position using vertex index.
var ap = mdt.get_vertex(a)
var bp = mdt.get_vertex(b)
var cp = mdt.get_vertex(c)
# Calculate face normal.
var n = (bp - cp).cross(ap - bp).normalized()
# Add face normal to current vertex normal.
# 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 vertices one last time to normalize normals and
# set color to normal.
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)