From f2b1bba5a9fe2b0bede6792a34965987902c41aa Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Sat, 16 Sep 2023 13:49:51 -0400 Subject: Update world gen logic Place rocks and trees, and check normal of surface to not place objects on surfaces that are too steep. --- scripts/level_gen.gd | 108 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 44 deletions(-) (limited to 'scripts/level_gen.gd') diff --git a/scripts/level_gen.gd b/scripts/level_gen.gd index 91a4813..184ed26 100644 --- a/scripts/level_gen.gd +++ b/scripts/level_gen.gd @@ -1,26 +1,30 @@ extends Node3D -@export var width: int = 16 -@export var height: int = 16 -@export var depth: int = 16 +@export var width: int = 20 +@export var height: int = 10 +@export var depth: int = 20 @export var scale_x: int = 10 -@export var scale_y: int = 10 +@export var scale_y: int = 6 @export var scale_z: int = 10 -@export var radius: int = 4 +@export var radius: int = 5 + +@export var smooth_normal: bool = false var map_grid: Array[float] = [] +var random = RandomNumberGenerator.new() func map_grid_get(x: int, y: int, z: int): return map_grid[z*height*width + y*width + x] func gen_map_grid(): map_grid.resize(width*height*depth) - map_grid.fill(10.0) + map_grid.fill(1.0) var noise = FastNoiseLite.new() noise.noise_type = FastNoiseLite.TYPE_SIMPLEX - noise.frequency = 0.04 + noise.frequency = 0.06 + noise.set_seed(0xDEADBEEF) for z in depth: for x in width: var mid_x = x - width/2.0 @@ -29,16 +33,20 @@ func gen_map_grid(): var pos_radius = pos_vec.length() var multiplier = 1.0 / (max(1, pos_radius - radius)) var gen_h = noise.get_noise_2d(x, z) - gen_h = remap(gen_h, -1, 1, 0, height/2.0) - gen_h = int(gen_h*multiplier) + gen_h = remap(gen_h, -1, 1, 0, height) + gen_h = int(gen_h*multiplier*0.5) for y in gen_h: - map_grid[z*height*width + y*width + x] = -1.0 + map_grid[z*height*width + y*width + x] = -100.0 -func add_normal(p: Vector3, tri_index: int, triangles: PackedInt32Array, vertices: PackedVector3Array, normal_list: Array[Vector4]): - var new_tri_index = 0 +func add_normal(tri_index: int, triangles: PackedInt32Array, vertices: PackedVector3Array, normal_list: Array[Vector4]): + var new_tri_index: int = 0 while new_tri_index < len(triangles): - if floor(new_tri_index/3) == floor(tri_index/3): + @warning_ignore("integer_division") + var tri_index_1:int = int(new_tri_index/3) + @warning_ignore("integer_division") + var tri_index_2:int = int(tri_index/3) + if tri_index_1 == tri_index_2: new_tri_index += 3 continue @@ -57,8 +65,33 @@ func add_normal(p: Vector3, tri_index: int, triangles: PackedInt32Array, vertice new_tri_index += 3 +func place_objects(num_objects: int, object: PackedScene): + var space = get_world_3d().direct_space_state + var object_num: int = 0 + while object_num < num_objects: + var cast_pos = Vector3(random.randf_range(0, width*scale_x), height*scale_y, random.randf_range(0, depth*scale_z)) + var cast_dest = Vector3(cast_pos.x, 0, cast_pos.z) + var query = PhysicsRayQueryParameters3D.create(cast_pos, cast_dest) + var result = space.intersect_ray(query) + + if result: + # If the object is water, don't place anything + if result.collider == $Water: + continue + + # Don't spawn objects on hills that are too steep + if result.normal.dot(Vector3(0, 1, 0)) < 0.8: + continue + + var pos = result.position + var new_tree = object.instantiate() + new_tree.position = pos + add_child(new_tree) + object_num += 1 + # Called when the node enters the scene tree for the first time. func _ready(): + random.randomize() gen_map_grid() var vertices = PackedVector3Array() var normals = PackedVector3Array() @@ -89,7 +122,7 @@ func _ready(): for i in grid.size(): if grid[i][0] >= width or grid[i][1] >= height or grid[i][2] >= depth or \ grid[i][0] < 0 or grid[i][1] < 0 or grid[i][2] < 0: - cell.value[i] = 10.0 + cell.value[i] = 1.0 else: cell.value[i] = map_grid_get(grid[i][0], grid[i][1], grid[i][2]) cell.position[i] = Vector3(grid[i][0]*scale_x, grid[i][1]*scale_y, grid[i][2]*scale_z) @@ -105,30 +138,28 @@ func _ready(): var p1 = vertices[triangles[tri_index + 0]] var p2 = vertices[triangles[tri_index + 1]] var p3 = vertices[triangles[tri_index + 2]] - var normal = (p2 - p1).cross(p3 - p1).normalized(); + var normal = (p2 - p3).cross(p1 - p3).normalized(); var normal_4 = Vector4(normal.x, normal.y, normal.z, 1) normal_list[triangles[tri_index + 0]] += normal_4 normal_list[triangles[tri_index + 1]] += normal_4 normal_list[triangles[tri_index + 2]] += normal_4 tri_index += 3 - - tri_index = 0 - while tri_index < len(triangles): - var p1 = vertices[triangles[tri_index + 0]] - var p2 = vertices[triangles[tri_index + 1]] - var p3 = vertices[triangles[tri_index + 2]] - add_normal(p1, tri_index+0, triangles, vertices, normal_list) - add_normal(p2, tri_index+1, triangles, vertices, normal_list) - add_normal(p3, tri_index+2, triangles, vertices, normal_list) - tri_index += 3 + + if smooth_normal: + tri_index = 0 + while tri_index < len(triangles): + add_normal(tri_index+0, triangles, vertices, normal_list) + add_normal(tri_index+1, triangles, vertices, normal_list) + add_normal(tri_index+2, triangles, vertices, normal_list) + tri_index += 3 for normal in normal_list: var real_normal = Vector3(normal.x, normal.y, normal.z) / normal.w - normals.push_back(real_normal) + normals.push_back(real_normal.normalized()) + # Create the Mesh - print("Lengths are ", len(vertices), " ", len(normals)) arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays) - var material = preload("res://materials/terrain.tres") + #var material = preload("res://materials/terrain.tres") #arr_mesh.surface_set_material(0, material) var m = MeshInstance3D.new() m.mesh = arr_mesh @@ -145,24 +176,13 @@ func _ready(): add_child(static_body) var tree_prefab = preload("res://prefab/tree.tscn") - - var space = get_world_3d().direct_space_state - - var random = RandomNumberGenerator.new() - random.randomize() var num_trees = random.randi_range(5, 15) - for i in num_trees: - var cast_pos = Vector3(random.randf_range(0, width*scale_x), height*scale_y, random.randf_range(0, depth*scale_z)) - var cast_dest = Vector3(cast_pos.x, 0, cast_pos.z) - var query = PhysicsRayQueryParameters3D.create(cast_pos, cast_dest) - var result = space.intersect_ray(query) - - if result: - var pos = result.position - var new_tree = tree_prefab.instantiate() - new_tree.position = pos - add_child(new_tree) + var rock_prefab = preload("res://prefab/rock.tscn") + var num_rocks = random.randi_range(5, 15) + + place_objects(num_trees, tree_prefab) + place_objects(num_rocks, rock_prefab) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta): -- cgit