extends Node export var trailer_house: PackedScene export var palace: PackedScene export var car: PackedScene onready var obj_names = { "palace": palace, "trailer_house": trailer_house } var done = false class radial_grid: var radial_points = [] var max_r = 0.0 var grid = [] var width: int = 0 var height: int = 0 var nodes = [] func build(poly, center): var height = center.y max_r = 0.0 for p in range(poly.size()): var ep1 = poly[p] ep1.y = height var ep2 = poly[(p + 1) % poly.size()] ep2.y = height var d = (ep2 - ep1).normalized() radial_points.push_back(ep1) var dst = ep1.distance_to(ep2) while dst > 32: ep1 += d * 32 radial_points.push_back(ep1) dst -= 32 for p in range(radial_points.size()): var ep = radial_points[p] var dst = ep.distance_to(center) if max_r < dst: max_r = dst width = radial_points.size() height = int(max_r / 32) grid.resize(width * height) for p in range(width): var start = radial_points[p] var end = center var step = (end - start).normalized() * (end - start).length() / float(height + 1) var val = start for q in range(height): grid[p * height + q] = {"position": val, "node": null} func get_grid_node(x, y): return grid[x * height + y].node func set_grid_node(x, y, node): if !node in nodes: nodes.push_back(node) grid[x * height + y].node = node func place_grid(aabb: AABB, node) -> void: for u in range(width): for v in range(height): if aabb.has_point(grid[u * height + v].position): set_grid_node(u, v, node) func get_pos(x, y): return grid[x * height + y].position onready var grid = radial_grid.new() func debug_poly(poly): for k in range(poly.size()): var p1 = poly[k] var p2 = poly[(k + 1) % poly.size()] var l = p1.distance_to(p2) var d = (p2 - p1).normalized() var pt = p1 while l > 0.0: for e in range(0, 30, 2): var mi = MeshInstance.new() mi.mesh = CubeMesh.new() get_tree().root.add_child(mi) mi.global_transform.origin = pt + Vector3(0, e, 0) pt += d * 5.0 l -= 5.0 func calc_border(poly, offt): var height = RoadsData.get_site_avg_height(0) var border = [] border.resize(poly.size()) for k in range(poly.size()): var i = k - 1 if i < 0: i += poly.size() var p1 = poly[i] var p2 = poly[k] var p3 = poly[(k + 1) % poly.size()] var p1x = Vector2(p1.x, p1.z) var p2x = Vector2(p2.x, p2.z) var p3x = Vector2(p2.x, p2.z) var p4x = Vector2(p3.x, p3.z) var n1 = (p2x - p1x).tangent().normalized() var n2 = (p4x - p3x).tangent().normalized() p1x -= n1 * offt p2x -= n1 * offt p3x -= n2 * offt p4x -= n2 * offt var xp = Geometry.segment_intersects_segment_2d(p1x, p2x, p3x, p4x) if !xp: xp = p2x.linear_interpolate(p3x, 0.5) - (n1 + n2).normalized() * offt var tp = Vector3(xp.x, height, xp.y) border[k] = tp return border var towns = 0 func setup_town(site): if !RoadsData.site_is_town(site): print("site ", site, " type: ", RoadsData.get_site_type(site)) return var poly = RoadsData.get_site_polygon_3d(site) var height = RoadsData.get_site_avg_height(site) var border2 = calc_border(poly, 60) var aabbs = [] var poly2 = [] poly2.resize(border2.size()) for p in range(border2.size()): poly2[p] = Vector2(border2[p].x, border2[p].z) var center = Vector3() for p in poly: center += p center /= poly.size() center.y = height grid.build(border2, center) var radial_points = grid.radial_points var max_r = 0.0 for p in range(radial_points.size()): var ep = radial_points[p] var dst = ep.distance_to(center) if max_r < dst: max_r = dst for p in range(radial_points.size()): var ep = radial_points[p] var d = (center - ep).normalized() var dst = ep.distance_to(center) print(dst) if dst < 64.0 + 12 + 8 + 4: continue var step = 16.0 var pstart = ep while dst > 0.0: var ok = true if !Geometry.is_point_in_polygon(Vector2(pstart.x, pstart.z), poly2): ok = false if ok: for b in aabbs: if b.has_point(pstart): ok = false if ok: var xform = Transform(Basis(), pstart).looking_at(pstart + d, Vector3.UP) stream_obj("trailer_house", xform) var aabb = AABB(pstart, Vector3()) aabb = aabb.grow(20) aabbs.push_back(aabb) print("placed to: ", pstart) pstart = pstart + d * step dst -= step towns += 1 func setup_first_town(): assert(!done) var poly = RoadsData.get_site_polygon_3d(0) var height = RoadsData.get_site_avg_height(0) var border = calc_border(poly, 32) var border1a = calc_border(poly, 42) var border2 = calc_border(poly, 60) var poly2 = [] poly2.resize(border2.size()) for p in range(border2.size()): poly2[p] = Vector2(border2[p].x, border2[p].z) var center = Vector3() for p in poly: center += p center /= poly.size() center.y = height grid.build(border2, center) var radial_points = grid.radial_points var max_r = 0.0 for p in range(radial_points.size()): var ep = radial_points[p] var dst = ep.distance_to(center) if max_r < dst: max_r = dst var u = radial_points.size() var v = int(max_r / 32) var grid = [] grid.resize(u * v) for p in range(u): var start = radial_points[p] var end = center var step = (end - start).normalized() * (end - start).length() / float(v + 1) var val = start for q in range(v): grid[p * v + q] = {"position": val} var aabbs = [] var palace_aabb = AABB(center, Vector3()) palace_aabb = palace_aabb.grow(48) print(palace_aabb) aabbs.push_back(palace_aabb) stream_obj("palace", Transform(Basis(), center)) for p in range(radial_points.size()): var ep = radial_points[p] var d = (center - ep).normalized() var dst = ep.distance_to(center) print(dst) if dst < 64.0 + 12 + 8 + 4: continue var step = 16.0 var pstart = ep while dst > 0.0: var ok = true if !Geometry.is_point_in_polygon(Vector2(pstart.x, pstart.z), poly2): ok = false if ok: for b in aabbs: if b.has_point(pstart): ok = false if ok: var xform = Transform(Basis(), pstart).looking_at(pstart + d, Vector3.UP) stream_obj("trailer_house", xform) var aabb = AABB(pstart, Vector3()) aabb = aabb.grow(20) aabbs.push_back(aabb) print("placed to: ", pstart) pstart = pstart + d * step dst -= step towns += 1 done = true func _ready(): for k in obj_names.keys(): Spawner.add_scene(k, obj_names[k]) # Called every frame. 'delta' is the elapsed time since the previous frame. var delay = 3.0 var state = 0 func _process(delta): match state: 0: delay -= delta if delay < 0: state = 1 1: Spawner.update_view(self, 300) var sc = get_tree().root var viewport: = get_viewport() if !viewport: return var cam: = viewport.get_camera() if !cam: return var cam_xform: = cam.global_transform func stream_obj(obj: String, xform: Transform): Spawner.place_scene(obj, xform) func _physics_process(delta): var cam = get_viewport().get_camera() if !cam: return match state: 1: var space_state = get_viewport().get_world().direct_space_state # probaly should not be here for n in get_tree().get_nodes_in_group("spawn"): var ok = false if !n.is_in_group("keep"): var where = n.get_global_transform().origin var from = where var to = where from.y -= 8.0 to.y += 8.0 var result = space_state.intersect_ray(from, to) if result.empty() || !result.has("collider"): continue if result.collider: n.global_transform.origin = result.position ok = true if ok || n.is_in_group("keep"): if n.is_in_group("male"): characters.replace_character(n, "male", ["cmdq", "marker", "hurtboxes", "student"]) elif n.is_in_group("female"): characters.replace_character(n, "female", ["cmdq", "marker", "hurtboxes", "student"]) elif n.is_in_group("car"): var c = car.instance() var p = get_tree().root p.add_child(c) c.global_transform = n.global_transform n.queue_free()