Geometría procedural

Existen muchas formas de generar geometría de manera procedural en Godot. En esta serie de tutoriales exploraremos algunas de ellas. Cada técnica tiene sus propias ventajas y desventajas, por lo que es mejor comprender cada una y cómo puede ser útil en una situación determinada.

¿Qué es geometría?

La geometría es una forma elegante de decir formas. En los gráficos por ordenador, la geometría se representa típicamente por una serie de posiciones llamadas "vértices". En Godot, la geometría es representada por Meshes.

¿Qué es una Mesh?

Muchas cosas en Godot tienen un mesh en su nombre: el Mesh, el ArrayMesh, el MeshInstance, el MultiMesh, y el MultiMeshInstance. Aunque todos están relacionados, tienen usos ligeramente diferentes.

Meshes y ArrayMeshes son recursos que se dibujan usando un nodo de MeshInstance. Recursos como Meshes y ArrayMeshes no pueden ser añadidos a la escena directamente. Un MeshInstance representa una instancia de un mesh en tu escena. Puedes reutilizar una solo mesh en múltiples MeshInstance para que se dibuje en diferentes partes de tu escena con diferentes materiales o transformaciones (escala, rotación, posición, etc.).

Si vas a dibujar el mismo objeto muchas veces, puede ser útil usar una MultiMesh con una MultiMeshInstance. La MultiMeshInstance dibuja mallas miles de veces muy asequibles. Se aprovecha de la instanciación del hardware para hacerlo. El inconveniente de usar una MultiMeshInstance es que se limita a un material para todas las instancias. Utiliza un array de instancias para almacenar diferentes colores y transformaciones para cada instancia, pero todas las instancias utilizan el mismo material.

Qué es una Mesh

Un Mesh está compuesto de una o más caras. Una cara es un conjunto compuesto de múltiples sub-arrays que contienen vértices, normales, UVs, etc. Normalmente el proceso de construcción de superficies y mallas está oculto para el usuario en el VisualServer, pero con ArrayMeshes, el usuario puede construir una Mesh manualmente pasando un array que contiene la información de la superficie.

Caras

Cada superficie tiene su propio material. Alternativamente, puedes sobrescribir el material para todas las superficies en la malla cuando utilizas una instancia de malla (MeshInstance) utilizando la propiedad material_override.

Array de las caras

El arreglo de superficies (surface array) es un arreglo de longitud ArrayMesh.ARRAY_MAX. Cada posición en el arreglo está llenada con un sub-array que contiene información por vértice. Por ejemplo, el array ubicado en ArrayMesh.ARRAY_NORMAL es un PoolVector3Array de normales de vértices. Consulta Mesh.ArrayType para obtener más información.

El array de superficie puede ser indexado o no indexado. Crear un array no indexado es tan fácil como no asignar un array en el índice ArrayMesh.ARRAY_INDEX. Un array no indexado almacena información única de vértices para cada triángulo, lo que significa que cuando dos triángulos comparten un vértice, el vértice se duplica en el array. Un array con superficie indexada sólo almacena información de vértices para cada vértice único y luego también almacena un array de índices que traza el mapa de cómo construir los triángulos a partir del array de vértices. En general, el uso de un array indexado es más rápido, pero significa que hay que compartir los datos de vértices entre los triángulos, lo que no siempre es deseado (por ejemplo, cuando se quieren utilizar normales por cara).

Herramientas

Godot ofrece diferentes formas de acceder y trabajar con geometría. Se proporcionará más información sobre cada una de ellas en los siguientes tutoriales.

ArrayMesh

El recurso ArrayMesh extiende el Mesh para añadir unas cuantas funciones diferentes de calidad de vida, y lo más importante, la capacidad de construir una superficie de Mesh a través de scripts.

Para más información sobre ArrayMesh, lee ArrayMesh tutorial.

MeshDataTool

El MeshDataTool es un recurso que convierte los datos del Mesh en arrays de vértices, caras y bordes que pueden ser modificados en tiempo de ejecución.

Para más información sobre MeshDataTool, lee MeshDataTool tutorial.

SurfaceTool

La clase SurfaceTool permite la creación de mallas utilizando una interfaz estilo "OpenGL 1.x immediate mode".

Para más información sobre SurfaceTool, por favor lee el SurfaceTool tutorial.

ImmediateGeometry

ImmediateGeometry es un nodo que utiliza una interfaz de estilo "modo inmediato" (al igual que SurfaceTool) para dibujar objetos. La diferencia entre ImmediateGeometry y SurfaceTool es que ImmediateGeometry es un nodo en sí mismo que se puede agregar al árbol de escena y se dibuja directamente desde el código, mientras que SurfaceTool genera una malla que debe agregarse a una instancia de malla (MeshInstance) para poder verse.

ImmediateGeometry es útil para prototipos debido a su API directa, pero es lento porque la geometría se reconstruye en cada cuadro. Es especialmente útil para agregar geometría simple para depuración visual (por ejemplo, al dibujar líneas para visualizar raycasts de físicas, etc.).

Para más información sobre ImmediateGeometry, por favor lee el ImmediateGeometry tutorial.

¿Cuál método debería usar?

El enfoque que elijas depende de lo que estés tratando de hacer y de qué tipo de procedimiento te sientas más cómodo.

Tanto SurfaceTool como ArrayMesh son excelentes para generar geometría estática (meshes) que no cambian con el tiempo.

Usar un ArrayMesh es ligeramente más rápido que usar una SurfaceTool, pero la API es más desafiante. Además, SurfaceTool tiene algunos métodos de calidad de vida como generate_normals() e index().

ImmediateGeometry regenera el mesh en cada cuadro, por lo que es mucho más lento que ArrayMesh o SurfaceTool. Sin embargo, si necesitas que la geometría cambie cada cuadro igualmente, proporciona una interfaz mucho más fácil que puede ser incluso un poco más rápida que la generación de un ArrayMesh en cada cuadro.

El MeshDataTool no es rápido, pero te da acceso a todo tipo de propiedades del mesh que no consigues con los otros (bordes, caras, etc.). Es increíblemente útil cuando se necesita ese tipo de datos para transformar la malla, pero no es una buena idea utilizarlo si esa información no es necesaria. El MeshDataTool se utiliza mejor si se va a utilizar un algoritmo que requiere el acceso al array de caras o bordes.