Using ImmediateMesh

O ImmediateMesh é uma ferramenta prática para criar geometria dinâmica usando uma API no estilo do OpenGL 1.x. Isso o torna tanto acessível de usar quanto eficiente para malhas que precisam ser atualizadas a cada frame.

Gerar geometria complexa (com vários milhares de vértices) com essa ferramenta é ineficiente, mesmo que seja feito apenas uma vez. Em vez disso, ela foi projetada para gerar geometria simples que muda a cada frame.

Primeiro, você precisa criar um MeshInstance3D e adicionar um ImmediateMesh a ele no Inspetor.

Em seguida, adicione um script ao MeshInstance3D. O código para o ImmediateMesh deve ser colocado na função _process() se você quiser que ele seja atualizado a cada frame, ou na função _ready() se quiser criar a malha apenas uma vez e não atualizá-la. Se você gerar uma superfície apenas uma vez, o ImmediateMesh é tão eficiente quanto qualquer outro tipo de malha, pois a malha gerada é armazenada em cache e reutilizada.

Para começar a gerar geometria, você deve chamar surface_begin(). surface_begin() recebe um PrimitiveType como argumento. O PrimitiveType instrui a GPU sobre como organizar a primitiva com base nos vértices fornecidos, seja em triângulos, linhas, pontos etc. Uma lista completa pode ser encontrada na página de referência da classe Mesh.

Depois de chamar surface_begin(), você está pronto para começar a adicionar vértices. Os vértices são adicionados um por vez. Primeiro, você adiciona os atributos específicos do vértice, como normais ou UVs, usando surface_set_****() (por exemplo, surface_set_normal()). Em seguida, você chama surface_add_vertex() para adicionar um vértice com esses atributos. Por exemplo:

# Add a vertex with normal and uv.
surface_set_normal(Vector3(0, 1, 0))
surface_set_uv(Vector2(1, 1))
surface_add_vertex(Vector3(0, 0, 1))

Apenas os atributos adicionados antes da chamada de surface_add_vertex() serão incluídos naquele vértice. Se você adicionar um atributo duas vezes antes de chamar surface_add_vertex(), apenas a segunda chamada será usada.

Por fim, após adicionar todos os seus vértices, chame surface_end() para sinalizar que terminou de gerar a superfície. Você pode chamar surface_begin() e surface_end() várias vezes para gerar múltiplas superfícies para a malha.

The example code below draws a single triangle in the _ready() function.

extends MeshInstance3D

func _ready():
    # Begin draw.
    mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)

    # Prepare attributes for add_vertex.
    mesh.surface_set_normal(Vector3(0, 0, 1))
    mesh.surface_set_uv(Vector2(0, 0))
    # Call last for each vertex, adds the above attributes.
    mesh.surface_add_vertex(Vector3(-1, -1, 0))

    mesh.surface_set_normal(Vector3(0, 0, 1))
    mesh.surface_set_uv(Vector2(0, 1))
    mesh.surface_add_vertex(Vector3(-1, 1, 0))

    mesh.surface_set_normal(Vector3(0, 0, 1))
    mesh.surface_set_uv(Vector2(1, 1))
    mesh.surface_add_vertex(Vector3(1, 1, 0))

    # End drawing.
    mesh.surface_end()

O ImmediateMesh também pode ser usado entre frames. Cada vez que você chama surface_begin() e surface_end(), uma nova superfície é adicionada ao ImmediateMesh. Se quiser recriar a malha do zero a cada frame, chame clear_surfaces() antes de chamar surface_begin().

extends MeshInstance3D

func _process(delta):

    # Clean up before drawing.
    mesh.clear_surfaces()

    # Begin draw.
    mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)

    # Draw mesh.

    # End drawing.
    mesh.surface_end()

O código acima criará e desenhará dinamicamente uma única superfície em cada quadro.