I’m trying to create a mountain system from a heightmap, based on this example: https://www.youtube.com/watch?v=fEG_cnRQ1HI
The idea is simple:
- Create a MeshInstance3D with a PlaneMesh of WidthDepth vertices (8080 in my case), create a Shader for the mesh, read the heightmap image from it, and for each level of grey, modify the vertex Y coordinates
- In the MeshInstance3D (as a child of it), create a StaticBody3D with a child CollisionShape3D, add a script to the parent MeshInstance3D, which will build a collision shape, based on the same heightmap image as used in the Shader
But in my project, this not works as expected. I have indeed a more or less matching collision shape, but it contains several important differences, which turn it unusable because not reliable (see screenshot below).
Below is the code of my script:
extends MeshInstance3D
@onready var colShape = $StaticBody3D/CollisionShape3D
@export var chunk_size = 2.0
@export var height_ratio = 0.5
@export var colShape_size_ratio = 0.5#0.1
var img = Image.new()
var shape = HeightMapShape3D.new()
# Called when the node enters the scene tree for the first time.
func _ready():
colShape.shape = shape
mesh.size = Vector2(chunk_size, chunk_size)
update_terrain(height_ratio, colShape_size_ratio)
func update_terrain(_height_ratio, _colShape_size_ratio):
mesh.material.set("shader_parameters/height", _height_ratio)
img.load("res://assets/models/mountains/heightmap.png")
img.convert(Image.FORMAT_RF)
img.resize(img.get_width() * _colShape_size_ratio, img.get_height() * _colShape_size_ratio)
var data = img.get_data().to_float32_array()
for i in range(0, data.size()):
data[i] *= _height_ratio
shape.map_width = img.get_width()
shape.map_depth = img.get_height()
shape.map_data = data
var scale_ratio = chunk_size / float(img.get_width())
colShape.scale = Vector3(scale_ratio, 1, scale_ratio)
And here is the heightmap image I’m using:
I suspect that the ghost artifacts in my collision shape may come from a conversion issue, something like the collision shape is created 3 times due to the RGB values, but I cannot find how and where. I tried to convert the image to grayscale, or use a .exr format as suggested in the above video, but no way.
Can someone explain me what I’m doing wrong?