diff --git a/godot b/godot index 62f56af..f0223ea 160000 --- a/godot +++ b/godot @@ -1 +1 @@ -Subproject commit 62f56af6942438d70c7787770e2cf84c46fea546 +Subproject commit f0223ea8d3389bf7623c1b9213cebba6626a0434 diff --git a/modules/voxel b/modules/voxel index 6cd143d..38ec2f4 160000 --- a/modules/voxel +++ b/modules/voxel @@ -1 +1 @@ -Subproject commit 6cd143d392382612db51d51b46729a3da995847c +Subproject commit 38ec2f43d1419320e9050cde0b235db758cd5d36 diff --git a/modules/world/road_grid.cpp b/modules/world/road_grid.cpp index c4cf3ca..c21b648 100644 --- a/modules/world/road_grid.cpp +++ b/modules/world/road_grid.cpp @@ -528,6 +528,7 @@ void RoadGrid::generate_3d_vertices(Ref curve, Ref noise) d = CLAMP(d, 1.0f, 30.0f); diagram_vertex_heights.write[i] = d; } +#if 0 for (j = 0; j < 3; j++) { for (i = 0; i < map_hedges.size(); i++) { int x1 = map_hedges[i]->a; @@ -538,12 +539,51 @@ void RoadGrid::generate_3d_vertices(Ref curve, Ref noise) diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd; } } +#endif vertices.resize(get_diagram_vertex_count()); for (i = 0; i < vertices.size(); i++) { vertices.write()[i].x = diagram_vertices[i].x; vertices.write()[i].y = diagram_vertex_heights[i]; vertices.write()[i].z = diagram_vertices[i].y; } + smooth_heights(); +} + +void RoadGrid::smooth_heights() +{ + int i; + float ok = true; + while (ok) { + for (i = 0; i < map_hedges.size(); i++) { + int a = map_hedges[i]->a; + int b = map_hedges[i]->b; + Vector3 p1 = vertices[a]; + Vector3 p2 = vertices[b]; + float dst = p1.distance_to(p2); + float h = fabsf(p2.y - p1.y); + if (dst <= 48.0f && h > 0.0f) { + ok = false; + float m = (p1.y + p2.y) * 0.5f; + m = CLAMP(m, 0.0f, 70.0f); + p1.y = m; + p2.y = m; + } else if (h > 0.0f) { + ok = false; + float t = h / dst; + if (t > 0.35) { + ok = false; + float m1 = p1.y + (p2.y - p1.y) / 10.0f; + float m2 = p2.y + (p1.y - p2.y) / 10.0f; + p1.y = m1; + p2.y = m2; + } + } + if (!ok) { + vertices.write()[map_hedges[i]->a] = p1; + vertices.write()[map_hedges[i]->b] = p2; + } + } + } } void RoadGrid::generate_building_positions() @@ -680,6 +720,7 @@ void RoadGrid::save_json(const String &path) f->close(); } } +#if 0 PoolVector RoadGrid::get_site_border(int site) { const struct map_site &msite = map_sites[site]; @@ -716,4 +757,73 @@ PoolVector RoadGrid::get_site_border(int site) assert(msite.polygon_ind.size() == ret.size()); return ret; } +#endif + +PoolVector RoadGrid::get_site_border(int site, float offt) +{ + int k, i; + float height = get_site_avg_height(site); + PoolVector border; + PoolVector poly = get_site_polygon_3d(site); + if (poly.size() == 0) + return PoolVector(); + border.resize(poly.size()); + for (k = 0; k < poly.size(); k++) { + i = k - 1; + if (i < 0) + i += poly.size(); + Vector3 p1 = poly[i]; + Vector3 p2 = poly[k]; + Vector3 p3 = poly[(k + 1) % poly.size()]; + Vector2 p1x(p1.x, p1.z); + Vector2 p2x(p2.x, p2.z); + Vector2 p3x(p2.x, p2.z); + Vector2 p4x(p3.x, p3.z); + Vector2 n1 = (p2x - p1x).tangent().normalized(); + Vector2 n2 = (p4x - p3x).tangent().normalized(); + p1x -= n1 * offt; + p2x -= n1 * offt; + p3x -= n2 * offt; + p4x -= n2 * offt; + Vector2 xp; + if (!Geometry::segment_intersects_segment_2d(p1x, p2x, p3x, p4x, &xp)) + xp = p2x.linear_interpolate(p3x, 0.5) - (n1 + n2).normalized() * offt; + Vector3 tp(xp.x, height, xp.y); + border.write()[k] = tp; + } + return border; +} + +PoolVector RoadGrid::get_site_radial_points(int site, float bofft, float offt) +{ + int i; + float height = get_site_avg_height(site), max_r = 0.0f; + PoolVector poly = get_site_border(site, bofft); + PoolVector ret; + if (poly.size() == 0) + return PoolVector(); + List rpoints; + List::Element *e; + Vector3 center; + for (i = 0; i < poly.size(); i++) + center += poly[i]; + center /= poly.size(); + for (i = 0; i < poly.size(); i++) { + Vector3 ep1 = poly[i]; + Vector3 ep2 = poly[(i + 1) % poly.size()]; + Vector3 d = (ep2 - ep1).normalized(); + rpoints.push_back(ep1); + float dst = ep1.distance_to(ep2); + while (dst > offt) { + ep1 += d * offt; + rpoints.push_back(ep1); + dst -= offt; + } + } + ret.resize(rpoints.size()); + i = 0; + for (e = rpoints.front(); e; e = e->next()) + ret.write()[i++] = e->get(); + return ret; +} diff --git a/modules/world/road_grid.h b/modules/world/road_grid.h index 5d3f320..16a4e02 100644 --- a/modules/world/road_grid.h +++ b/modules/world/road_grid.h @@ -249,6 +249,7 @@ protected: } float grid_width, grid_height; void sort_angle(Vector &sort_data); + void smooth_heights(); public: void build(Ref curve, Ref noise); void draw_debug(Node *drawable, int size_x, int size_y) const; @@ -366,5 +367,7 @@ public: { return map_sites[site].site_type; } + PoolVector get_site_border(int site, float offt); + PoolVector get_site_radial_points(int site, float bofft, float offt); }; #endif diff --git a/modules/world/roads.cpp b/modules/world/roads.cpp index b6934e5..2d23da3 100644 --- a/modules/world/roads.cpp +++ b/modules/world/roads.cpp @@ -564,12 +564,16 @@ void RoadsData::_bind_methods() ClassDB::bind_method(D_METHOD("get_site_polygon_3d", "site"), &RoadsData::get_site_polygon_3d); ClassDB::bind_method(D_METHOD("get_here_sites", "position"), &RoadsData::get_here_sites); ClassDB::bind_method(D_METHOD("get_site_avg_height", "site"), &RoadsData::get_site_avg_height); +#if 0 ClassDB::bind_method(D_METHOD("get_site_border", "site"), &RoadsData::get_site_border); +#endif ClassDB::bind_method(D_METHOD("site_is_town", "site"), &RoadsData::site_is_town); ClassDB::bind_method(D_METHOD("site_is_farm", "site"), &RoadsData::site_is_farm); ClassDB::bind_method(D_METHOD("get_site_count"), &RoadsData::get_site_count); ClassDB::bind_method(D_METHOD("save_json", "path"), &RoadsData::save_json); ClassDB::bind_method(D_METHOD("get_site_type", "site"), &RoadsData::get_site_type); + ClassDB::bind_method(D_METHOD("get_site_border", "site", "offt"), &RoadsData::get_site_border); + ClassDB::bind_method(D_METHOD("get_site_radial_points", "site", "bofft", "offt"), &RoadsData::get_site_radial_points); } void RoadsData::set_noise(Ref noise) { diff --git a/modules/world/roads.h b/modules/world/roads.h index 332f84f..79dbf26 100644 --- a/modules/world/roads.h +++ b/modules/world/roads.h @@ -128,10 +128,12 @@ public: { rg->save_json(path); } +#if 0 inline PoolVector get_site_border(int site) { return rg->get_site_border(site); } +#endif inline int get_site_count() const { return rg->get_site_count(); @@ -140,5 +142,13 @@ public: { return rg->get_site_type(site); } + inline PoolVector get_site_border(int site, float offt) + { + return rg->get_site_border(site, offt); + } + inline PoolVector get_site_radial_points(int site, float bofft, float offt) + { + return rg->get_site_radial_points(site, bofft, offt); + } }; diff --git a/modules/world/spawner.cpp b/modules/world/spawner.cpp index 2cb1627..97a8fa5 100644 --- a/modules/world/spawner.cpp +++ b/modules/world/spawner.cpp @@ -60,7 +60,6 @@ void Spawner::place_scene(const StringName &name, const Transform &place) struct spawn_object obj; obj.xform = place; obj.active = false; - obj.relative = false; obj.instance = -1; PoolVector pos = positions[name]; pos.resize(pos.size() + 1); @@ -72,21 +71,6 @@ void Spawner::place_scene(const StringName &name, const Transform &place) } void Spawner::place_scene_relative(const StringName &name, Node *parent, const Transform &place) { - lock.lock(); - if (scenes.has(name)) { - struct spawn_object obj; - obj.xform = place; - obj.active = false; - obj.relative = true; - obj.instance = -1; - obj.parent_instance = parent->get_instance_id(); - PoolVector pos = positions[name]; - pos.resize(pos.size() + 1); - pos.write()[pos.size() - 1] = obj; - positions[name] = pos; - force_update = true; - } - lock.unlock(); } void Spawner::update_view(Node *node, float distance) { @@ -109,30 +93,17 @@ void Spawner::update_view(Node *node, float distance) int i; PoolVector pos = positions[*key]; for (i = 0; i < pos.size(); i++) { - Spatial *pnode = NULL; - if (pos[i].relative) { - Object *p = ObjectDB::get_instance(pos[i].parent_instance); - pnode = Object::cast_to(p); - assert(pnode); - } if (!pos[i].active) { Transform x = pos[i].xform; Vector3 npos = x.origin; - if (pnode) - npos = pnode->get_global_transform().xform(npos); float d = org.distance_squared_to(x.origin); if (d < distance * distance) { Node *pn = scenes[*key]->instance(); if (pn) { Spatial *sp = Object::cast_to(pn); if (sp) { - if (pnode) { - pnode->add_child(sp); - sp->set_transform(x); - } else { - view->add_child(sp); - sp->set_global_transform(x); - } + view->add_child(sp); + sp->set_global_transform(x); pos.write()[i].instance = sp->get_instance_id(); pos.write()[i].active = true; } else diff --git a/modules/world/spawner.h b/modules/world/spawner.h index 8f0610a..f7e15eb 100644 --- a/modules/world/spawner.h +++ b/modules/world/spawner.h @@ -9,8 +9,6 @@ protected: struct spawn_object { Transform xform; bool active; - bool relative; - int parent_instance; int instance; }; HashMap > positions;