Alterare una mesh piana in modo programmatico con Godot 3.0.2

Mentre gioco con Godot e le mesh (le mesh generate a livello di codice per essere precisi).
Ho trovato qualcosa che credo valga la pena condividere.

Devo dire che non ho trovato un uso della vita reale di questa tecnica, per esempio per generare un heightmap. Eppure credo che possa esistere un modo per farlo.

Come utilizzare SurfaceTool e MeshDataTool

Ho creato un semplice script che dovrebbe consentire di capirlo semplicemente leggendo il codice, è abbastanza semplice una volta che sai come usare questi strumenti.

strumento
estende Spatial

export (int, 1, 512) set di dimensioni var già esistenti _setPlaneSize

func _setPlaneSize (_newval):
	dimensione = _nuovo
	stampare()
	var startt = float (OS.get_ticks_msec ())
	var mdt = MeshDataTool.new ()
	var st = SurfaceTool.new ()
	var plane_mesh = PlaneMesh.new ()
	plane_mesh.subdivide_width = _newval
	plane_mesh.subdivide_depth = _newval
	plane_mesh.size = Vector2 (_newval, _newval)
	st.create_from (plane_mesh, 0)
	var array_plane = st.commit ()
	var error = mdt.create_from_surface (array_plane, 0)
	per i in range (mdt.get_vertex_count ()):
		var vtx = mdt.get_vertex (i)
		vtx.y = randf () * 1
		mdt.set_vertex (i, vtx)
	per s in range (array_plane.get_surface_count ()):
		array_plane.surface_remove (s)
	mdt.commit_to_surface (array_plane)
	st.create_from (array_plane, 0)
	st.generate_normals ()
	$ MeshInstance.mesh = st.commit ()
	var endtt = float (OS.get_ticks_msec ())
	print ("Tempo di esecuzione:% .2f"% ((endtt - startt) / 1000))

#func _ready ():
# _setPlaneSize (dimensione)

Devi posizionare lo script in una scena con i seguenti elementi (stessi nomi o modificare il codice di conseguenza):

Spaziale (allegare script qui)
| – DirectionalLight
| – MeshInstance

Lo script dovrebbe essere collegato al nodo radice e, in realtà, la luce direzionale è necessaria solo per vedere la corretta creazione delle normali.

Una volta fatto dovresti vedere la nuova proprietà "size", quando la imposti il ​​codice genererà una "heightmap", la dimensione che hai stabilito.

Si prega di notare che, a seconda della macchina, potrebbe essere necessario un po 'di tempo per andare oltre i 256 (sul mio PC ION lento ci vogliono in secondi per dimensione: 0,5 x 64, 2 x 128, 13 x 256).

Il ruolo di SurfaceTool

Quindi, per approfondire, st (lo strumento di superficie), può creare una mesh array a partire da una mesh precedentemente generata (può essere di qualsiasi tipo, in questo caso ho usato la mesh piana), in questo modo:

var st = SurfaceTool.new ()
# crea una mesh piana di _newval size
# e la stessa quantità di sottodivisioni
var plane_mesh = PlaneMesh.new () 
plane_mesh.subdivide_width = _newval 
plane_mesh.subdivide_depth = _newval 
plane_mesh.size = Vector2 (_newval, _newval)

# crea un arrayMesh da utilizzare da MeshDataTool
st.create_from (plane_mesh, 0) 
var array_plane = st.commit ()

Lo strumento Mesh Data

Una volta convertito in ArrayMesh, può essere utilizzato da MeshDataTool, in quanto l'altro PlaneTool non può modificare le mesh, ma solo crearle.

Ora che MeshDataTool può posizionare le sue mani sul piano, possiamo lavorare in questo modo per alterare un vertice (l'asse y in questo caso)

# In pratica copiamo la mesh della matrice in MeshDataTool
var error = mdt.create_from_surface (array_plane, 0)
per i in range (mdt.get_vertex_count ()):
# Qui corriamo attraverso tutti i vertici dell'aereo
    var vtx = mdt.get_vertex (i)
# Un valore casuale per modificare la posizione y del nostro vertice
    vtx.y = randf () * 1
# Diciamo al MeshDataTool di modificare il vertice di conseguenza
    mdt.set_vertex (i, vtx)

Generare le normali e posizionare la mesh nel nodetree

Bene, fatto, ora la parte successiva consiste nel rimuovere le mesh precedenti (se ce ne sono) e generare le normali per il nostro piano modificato.

Come crei le normali, beh, godot hanno questa bella caratteristica che ci permette di evitare l'uso della matematica vettoriale, l'annuncio fa tutto per noi, ma devi spostare la mesh sul SurfaceTool (sì, mi chiedo perché non è tutto nello stesso oggetto, invece di avere 2, ma bene) generate_normals () fa tutto.

Quindi, finalmente, prendiamo la mesh appena creata e vogliamo metterla da qualche parte, in modo che chiunque possa vederla, dato che siamo orgogliosi dei genitori (commit () restituisce la mesh finale):

# Per evitare di aggiungere nuove superfici all'istanza mesh
# Ho dovuto scorrere tutte le superfici esistenti e rimuoverle
per s in range (array_plane.get_surface_count ()):
    array_plane.surface_remove (s)

# Quindi siamo pronti a posizionare il piano modificato 
# indietro nell'array originale
mdt.commit_to_surface (array_plane)

# Quest'ultima operazione è necessaria per generare le normali
# senza la necessità di farlo manualmente
st.create_from (array_plane, 0)
st.generate_normals ()

#finalmente, collega la mesh al nodo MeshInstance
$ MeshInstance.mesh = st.commit ()

Posted in 3D, Videogiochi.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.