- Edited
Could someone help me to figure it out what I'm doing wrong using Immediate Mesh to generate a mesh using a height map? They way I'm doing the quads are drawn separately
The script that I'm using to generate the mesh
@tool
extends MeshInstance3D
@onready var immediate_mesh := ImmediateMesh.new()
@onready var noise = FastNoiseLite.new()
@export var width = 32
@export var height = 32
var vertices := PackedVector3Array()
func _ready():
create_mesh()
func create_mesh():
immediate_mesh.clear_surfaces()
for x in range(width):
for y in range(height):
create_quad(x, y)
immediate_mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
for v in vertices.size():
immediate_mesh.surface_add_vertex(vertices[v])
immediate_mesh.surface_end()
self.set_mesh(immediate_mesh)
func create_quad(x, z):
var y = noise.get_noise_2d(x, z) * 16
var vert1
var vert2
var vert3
#triangle 1
vert1 = Vector3(x, y, z)
vert2 = Vector3(x + 1, y, z)
vert3 = Vector3(x + 1, y, z + 1)
vertices.push_back(vert1)
vertices.push_back(vert2)
vertices.push_back(vert3)
#triangle 2
vert1 = Vector3(x, y, z)
vert2 = Vector3(x + 1, y, z + 1)
vert3 = Vector3(x, y, z + 1)
vertices.push_back(vert1)
vertices.push_back(vert2)
vertices.push_back(vert3)
I try to use SurfaceTool as well, but I not knowing how to set up the vertices to use the height map with falloff map.
The script using SurfaceTool
@tool
extends MeshInstance3D
@export var width = 128
@export var height = 128
@export var amplitude = 2
@export var random_island := false
@export var seed = 717844
@export var noise := FastNoiseLite.new()
@export var texture_rect : TextureRect
var height_data = {}
func _ready():
if !random_island:
noise.seed = seed
generate_heightmap()
generate_texture()
generate_mesh()
func evaluate(value : float) -> float:
var a = float(3)
var b = float(2.2)
return pow(value, a) / (pow(value, a) + pow(b - b * value, a))
func generate_heightmap() -> void:
if (random_island):
var rng = RandomNumberGenerator.new()
noise.seed = rng.randi_range(0, 1000000)
print(noise.seed)
for x in range(height):
for y in range (width):
var xv = x / float(width) * 2 - 1;
var yv = y / float(height) * 2 - 1;
var value = maxf(absf(xv), absf(yv));
var noise_value = noise.get_noise_2d(x,y)
var height_value = (noise_value - evaluate(value)) * amplitude
height_data[Vector2(x,y)] = clampf(height_value, 0, 1)
func generate_texture() -> void:
var image := Image.new()
image = Image.create(width, height, false, Image.FORMAT_RGB8)
var texture = ImageTexture.new()
var black = Color(0, 0, 0, 1)
var white = Color(1, 1, 1, 1)
for y in height:
for x in width:
image.set_pixel(x, y, black.lerp(white, height_data[Vector2(x,y)]))
texture = texture.create_from_image(image)
texture_rect.texture = texture
func generate_mesh() -> void:
var plane_mesh = PlaneMesh.new()
plane_mesh.size = Vector2(width,height)
plane_mesh.subdivide_depth = width - 1
plane_mesh.subdivide_width = height - 1
var surface_tool = SurfaceTool.new()
surface_tool.create_from(plane_mesh,0)
var data = surface_tool.commit_to_arrays()
var vertices = data[ArrayMesh.ARRAY_VERTEX]
for z in height:
for x in width:
var indice = z * width + x
#var vertex = vertices[indice]
vertices[indice].y = height_data[Vector2(x,z)]
vertices[indice + 1].y = height_data[Vector2(x,z)]
vertices[indice + 2].y = height_data[Vector2(x,z)]
vertices[indice].y = height_data[Vector2(x,z)]
vertices[indice + 2].y = height_data[Vector2(x,z)]
vertices[indice + 3].y = height_data[Vector2(x,z)]
data[ArrayMesh.ARRAY_VERTEX] = vertices
var array_mesh = ArrayMesh.new()
array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES,data)
surface_tool.create_from(array_mesh,0)
surface_tool.generate_normals()
mesh = surface_tool.commit()