Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | Macryc |
Hi Guys
In Godot 4, I’m trying to build a mesh from a heightmap. Using the code below, I trying to parse the image, which is a noise image.
I keep getting the error 'Nonexistent function ‘lock()’ in base Image.
When I go var heightmap = noiseImage.get_data()
instead, i get the same error, only it reads: Nonexistent function lock() in base PackedByteArray. What am I doing wrong?
func _ready():
var noiseImage = Image.new()
noiseImage.load("res://231.jpg")
width = noiseImage.get_width()
height = noiseImage.get_height()
var heightmap = noiseImage
heightmap.lock()
for x in range(width):
for y in range(height):
heightData[Vector2(x,y)] = heightmap.get_pixel(x,y).r*20
heightmap.unlock()
The lock/unlock methods have been removed in Godot 4.0. Is there any issue if you just remove them?
Ninfur | 2022-05-05 18:15
Weird, they’re still in the docs.
Anyway, removed them and the code runs through but no geometry gets created.
Also, I can see an error in debug at the line which commits the mesh, the error reads: E _ready: Required virtual method Mesh::_get_surface_count must be overridden before calling.
I’m using this code I found online, which makes sense and ‘should work’ when you read it:
extends Node3D
@onready var width;
@onready var height;
var heightData = {}
var vertices = PackedVector3Array()
var UVs = PackedVector2Array()
var normals = PackedVector3Array()
var tmpMesh = Mesh.new()
func _ready():
var noiseImage = load("res://231.jpg")
width = noiseImage.get_width()
height = noiseImage.get_height()
var heightmap = noiseImage
for x in range(0,width):
for y in range(0,height):
heightData[Vector2(x,y)] = heightmap.get_pixel(x,y).r*20
# generate terrain
for x in range(0,width-1):
for y in range(0,height-1):
createQuad(x,y)
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
st.set_material(load("res://new_standard_material_3d.tres"))
for v in vertices.size():
st.set_color(Color(1,1,1))
st.set_uv(UVs[v])
st.set_normal(normals[v])
st.add_vertex(vertices[v])
st.commit(tmpMesh)
$MeshInstance3D.mesh = tmpMesh
func createQuad(x,y):
var vert1 # vertex positions (Vector2)
var vert2
var vert3
var side1 # sides of each triangle (Vector3)
var side2
var normal # normal for each triangle (Vector3)
# triangle 1
vert1 = Vector3(x,heightData[Vector2(x,y)],-y)
vert2 = Vector3(x,heightData[Vector2(x,y+1)],-y-1)
vert3 = Vector3(x+1,heightData[Vector2(x+1,y+1)],-y-1)
vertices.push_back(vert1)
vertices.push_back(vert2)
vertices.push_back(vert3)
UVs.push_back(Vector2(vert1.x/10, -vert1.z/10))
UVs.push_back(Vector2(vert2.x/10, -vert2.z/10))
UVs.push_back(Vector2(vert3.x/10, -vert3.z/10))
side1 = vert2-vert1
side2 = vert2-vert3
normal = side1.cross(side2)
for i in range(0,3):
normals.push_back(normal)
# triangle 2
vert1 = Vector3(x,heightData[Vector2(x,y)],-y)
vert2 = Vector3(x+1,heightData[Vector2(x+1,y+1)],-y-1)
vert3 = Vector3(x+1,heightData[Vector2(x+1,y)],-y)
vertices.push_back(vert1)
vertices.push_back(vert2)
vertices.push_back(vert3)
UVs.push_back(Vector2(vert1.x/10, -vert1.z/10))
UVs.push_back(Vector2(vert2.x/10, -vert2.z/10))
UVs.push_back(Vector2(vert3.x/10, -vert3.z/10))
side1 = vert2-vert1
side2 = vert2-vert3
normal = side1.cross(side2)
for i in range(0,3):
normals.push_back(normal)
Macryc | 2022-05-05 18:53
Did you find any solution?
zkmark | 2023-01-13 18:35