Modifique una malla de plano programáticamente con Godot 3.0.2

Como estoy jugando con Godot y mallas (mallas generadas por programación para ser precisos).
He encontrado algo que creo que vale la pena compartir.

Tengo que mencionar que no he encontrado un uso de la vida real de esta técnica, por ejemplo, para generar un mapa. Sin embargo, creo que puede existir una manera de hacerlo.

Cómo usar SurfaceTool y MeshDataTool

He creado un script simple que debería permitir comprenderlo simplemente leyendo el código, es bastante simple una vez que sepas cómo usar esas herramientas.

herramienta
extiende espacial

export (int, 1, 512) onready var size setget _setPlaneSize

func _setPlaneSize (_newval):
	tamaño = _newval
	impresión()
	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)
	para i en rango (mdt.get_vertex_count ()):
		var vtx = mdt.get_vertex (i)
		vtx.y = randf () * 1
		mdt.set_vertex (i, vtx)
	para s en rango (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 ("Tiempo de ejecución:% .2f"% ((endtt - startt) / 1000))

#func _ready ():
# _setPlaneSize (tamaño)

Debe colocar el script en una escena con los siguientes elementos (los mismos nombres o cambiar el código en consecuencia):

Spatial (adjuntar script aquí)
| – DirectionalLight
| – MeshInstance

El script debe adjuntarse al nodo raíz, y en realidad, la luz direccional es necesaria solo para ver la creación correcta de las normales.

Una vez hecho esto, debería ver la nueva propiedad "tamaño", cuando la configure, el código generará un "mapa de alturas", el tamaño que ha establecido.

Tenga en cuenta que, dependiendo de su máquina, puede llevar un tiempo ir más allá de 256 (en mi PC lenta ION se tarda en segundos por tamaño: 0.5 x 64, 2 x 128, 13 x 256).

El papel de SurfaceTool

Entonces, para profundizar, st (la herramienta de superficie) puede crear una malla de matriz a partir de una malla generada previamente (puede ser de cualquier tipo, en este caso he usado la malla de plano), de esta manera:

var st = SurfaceTool.new ()
# crear una malla plana de _nuevo tamaño
# y la misma cantidad de subdivisiones
var plane_mesh = PlaneMesh.new () 
plane_mesh.subdivide_width = _newval 
plane_mesh.subdivide_depth = _newval 
plane_mesh.size = Vector2 (_newval, _newval)

# crear un arrayMesh para ser utilizado por MeshDataTool
st.create_from (plane_mesh, 0) 
var array_plane = st.commit ()

La herramienta de datos de malla

Una vez convertido en un ArrayMesh, puede ser utilizado por MeshDataTool, ya que el otro, el PlaneTool, no puede modificar mallas, simplemente créelos.

Ahora que MeshDataTool puede poner sus manos en el plano, podemos trabajar de esta manera para alterar algunos vértices (el eje y en este caso)

# En la práctica, copiamos la matriz de malla en MeshDataTool
var error = mdt.create_from_surface (array_plane, 0)
para i en rango (mdt.get_vertex_count ()):
# Aquí corremos a través de todos los vértices del avión
    var vtx = mdt.get_vertex (i)
# Un valor aleatorio para modificar la posición y de nuestro vértice
    vtx.y = randf () * 1
# Le decimos a MeshDataTool que modifique el vértice en consecuencia
    mdt.set_vertex (i, vtx)

Generando normales y colocando la malla en el árbol node

Bien, casi hecho, ahora la siguiente parte consiste en eliminar las mallas anteriores (si las hay) y generar las normales para nuestro plano modificado.

¿Cómo se crean las normales, bueno, Dios mío tiene esta buena característica que nos permite evitar el uso de vectores de matemáticas, ad lo hace todo por nosotros, pero tienes que mover la malla de nuevo a SurfaceTool (sí, me pregunto por qué no es todo en el mismo objeto, en lugar de tener 2, pero bueno) generate_normals () lo hace todo.

Luego, finalmente, tomamos nuestra malla recién creada y queremos ponerla en algún lugar, para que todos puedan verla, ya que somos padres orgullosos (commit () devuelve la malla final):

# Para evitar agregar nuevas superficies a la instancia de malla
# Tuve que recorrer todas las superficies existentes y eliminarlas
para s en rango (array_plane.get_surface_count ()):
    array_plane.surface_remove (s)

# Entonces estamos listos para colocar el plano modificado 
# de vuelta a la matriz original
mdt.commit_to_surface (array_plane)

# Este último paso es necesario para generar las normales
# sin la necesidad de hacerlo manualmente
st.create_from (array_plane, 0)
st.generate_normals ()

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

Posted in 3D, Videojuegos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.