extends MeshInstance3D

@export var resolution_scaling = 1   
@export var height_scale = 500 * resolution_scaling


func _ready():
	DebugDraw3D.debug_enabled = true
	create_mesh()
	set_material()
	

func create_mesh():
	var heightmap_texture = ResourceLoader.load("res://Rolling Hills Height Map 1k/Rolling Hills Height Map.png")
	var heightmap_image: Image = heightmap_texture.get_image()
	heightmap_image.convert(Image.FORMAT_RF)
	var st = SurfaceTool.new()
	st.begin(Mesh.PRIMITIVE_TRIANGLES)
	for i in range(-(heightmap_image.get_height() / resolution_scaling / 2), heightmap_image.get_height() / resolution_scaling / 2):
		for j in range(-(heightmap_image.get_width() / resolution_scaling / 2), heightmap_image.get_width() / resolution_scaling / 2):
			create_quad(st, Vector2(i, j), heightmap_image)
	
	st.index()
	
	mesh = st.commit()

func set_material():
	var material = StandardMaterial3D.new()
	material.vertex_color_use_as_albedo = true
	set_surface_override_material(0, material)

func create_quad(st: SurfaceTool, position: Vector2, heightmap_image: Image):
	var height1 = heightmap_image.get_pixel((position.x + 1) * resolution_scaling + heightmap_image.get_width() / 2, position.y * resolution_scaling + heightmap_image.get_height() / 2)
	var vertexPosition1 = Vector3(position.x * resolution_scaling + resolution_scaling, height1.get_luminance() * height_scale, position.y * resolution_scaling )
	var height2 = heightmap_image.get_pixel(position.x * resolution_scaling + heightmap_image.get_width() / 2, (position.y + 1) * resolution_scaling + heightmap_image.get_height() / 2)
	var vertexPosition2 = Vector3(position.x * resolution_scaling , height2.get_luminance() * height_scale, position.y  * resolution_scaling + resolution_scaling)
	var height3 = heightmap_image.get_pixel(position.x * resolution_scaling + heightmap_image.get_width() / 2, position.y * resolution_scaling + heightmap_image.get_height() / 2)
	var vertexPosition3 = Vector3(position.x * resolution_scaling , height3.get_luminance() * height_scale, position.y * resolution_scaling )
	var height4 = heightmap_image.get_pixel((position.x + 1) * resolution_scaling + heightmap_image.get_width() / 2, (position.y + 1) * resolution_scaling + heightmap_image.get_height() / 2)
	var vertexPosition4 = Vector3(position.x * resolution_scaling + resolution_scaling, height4.get_luminance() * height_scale, position.y * resolution_scaling + resolution_scaling)
	var height5 = heightmap_image.get_pixel(position.x * resolution_scaling + heightmap_image.get_width() / 2, (position.y + 1) * resolution_scaling + heightmap_image.get_height() / 2)
	var vertexPosition5 = Vector3(position.x * resolution_scaling, height5.get_luminance() * height_scale, position.y * resolution_scaling + resolution_scaling)
	var height6 = heightmap_image.get_pixel((position.x + 1) * resolution_scaling + heightmap_image.get_width() / 2, position.y * resolution_scaling + heightmap_image.get_height() / 2)
	var vertexPosition6 = Vector3(position.x * resolution_scaling + resolution_scaling, height6.get_luminance() * height_scale, position.y * resolution_scaling)
	var normal1 = -Vector3(vertexPosition2 - vertexPosition1).cross(Vector3(vertexPosition3 - vertexPosition1)).normalized()
	var normal2 = -Vector3(vertexPosition5 - vertexPosition4).cross(Vector3(vertexPosition6 - vertexPosition4)).normalized()
	st.set_color(Color.from_rgba8(normal1.x * 255, normal1.y * 255, normal1.z * 255))
	st.set_normal(normal1.normalized())
	st.add_vertex(vertexPosition1)
	st.set_color(Color.from_rgba8(normal1.x * 255, normal1.y * 255, normal1.z * 255))
	st.set_normal(normal1.normalized())
	st.add_vertex(vertexPosition2)
	st.set_color(Color.from_rgba8(normal1.x * 255, normal1.y * 255, normal1.z * 255))
	st.set_normal(normal1.normalized())
	st.add_vertex(vertexPosition3)
	st.set_color(Color.from_rgba8(normal2.x * 255, normal2.y * 255, normal2.z * 255))
	st.set_normal(normal2.normalized())
	st.add_vertex(vertexPosition4)
	st.set_color(Color.from_rgba8(normal2.x * 255, normal2.y * 255, normal2.z * 255))
	st.set_normal(normal2.normalized())
	st.add_vertex(vertexPosition5)
	st.set_color(Color.from_rgba8(normal2.x * 255, normal2.y * 255, normal2.z * 255))
	st.set_normal(normal2.normalized())
	st.add_vertex(vertexPosition6)

func _process(delta):
	if Input.is_action_pressed("ShowNormals"):
		if mesh == null:
			return
		for surface_index in mesh.get_surface_count():
			var arrays = mesh.surface_get_arrays(surface_index)
			if arrays.size() == 0:
				continue

			var vertices = arrays[Mesh.ARRAY_VERTEX]
			var normals = arrays[Mesh.ARRAY_NORMAL]
			for i in vertices.size():
				DebugDraw3D.draw_line(vertices[i], normals[i] + vertices[i] , Color.from_rgba8(normals[i].x * 255, normals[i].y * 255, normals[i].z * 255))
		
	
