MeshDataToolの使用¶
The MeshDataTool is not used to generate geometry. But it is helpful for dynamically altering geometry, for example if you want to write a script to tessellate, simplify, or deform meshes.
MeshDataToolは、ArrayMeshを使用して配列を直接変更するほど高速ではありません。ただし、ArrayMeshよりも多くの情報とメッシュを操作するツールを提供します。 MeshDataToolを使用すると、特定のメッシュアルゴリズムに必要なFace(面)やEdge(エッジ/辺)などのArrayMeshでは使用できないメッシュデータが計算されます。この追加情報が必要ない場合は、ArrayMeshを使用することをお勧めします。
注釈
MeshDataToolは、PrimitiveType Mesh.PRIMITIVE_TRIANGLES
を使用するメッシュでのみ使用できます。
例として、ArrayMeshチュートリアル で生成されたメッシュを変形するプロセスを見てみましょう。
メッシュが mesh
という名前のArrayMeshに保存されていると仮定します。次に、create_from_surface()
を呼び出して、mesh
からMeshDataToolを初期化します。 MeshDataToolで初期化されたデータが既にある場合、create_from_surface()
を呼び出すとデータがクリアされます。または、MeshDataToolを再利用する前に、自分で `` clear()`` を呼び出すことができます
var mdt = MeshDataTool.new()
mdt.create_from_surface(mesh)
create_from_surface()
は、ArrayMeshの頂点配列を使用して、エッジ用と面用の2つの追加配列を計算します。
エッジは、任意の2つの頂点間の接続です。エッジ配列の各エッジには、それが構成する2つの頂点への参照と、それが含まれる最大2つの面が含まれます。
A face is a triangle made up of three vertices and three corresponding edges. Each face in the face array contains a reference to the three vertices and three edges it is composed of.
頂点配列には、各頂点に接続されたエッジ、面、法線、色、接線、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.
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)
最後に、commit_to_surface()
はArrayMeshに新しいサーフェスを追加します。したがって、既存のArrayMeshを動的に更新する場合は、新しいサーフェスを追加する前に既存のサーフェスを削除してください。
mesh.surface_remove(0) # Deletes the first surface of the mesh.
mdt.commit_to_surface(mesh)
以下は、新しい法線と頂点の色で完全な脈動するブロブを作成する完全な例です。
extends MeshInstance
var sn = OpenSimplexNoise.new()
var mdt = MeshDataTool.new()
func _ready():
sn.period = 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 * (sn.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.surface_remove(0)
mdt.commit_to_surface(mesh)