diff --git a/godot b/godot index 2b5d89e..3ca8003 160000 --- a/godot +++ b/godot @@ -1 +1 @@ -Subproject commit 2b5d89e6350e586242f3397b48e72f743ff5b143 +Subproject commit 3ca80031995c8f4d312fcb4c955b83163d30b656 diff --git a/modules/world/road_grid.cpp b/modules/world/road_grid.cpp index 5d5f05f..91776d2 100644 --- a/modules/world/road_grid.cpp +++ b/modules/world/road_grid.cpp @@ -32,8 +32,10 @@ Dictionary RoadGrid::build_diagram(int npatches, int center_count, int center_st float sa = rnd->randf() * 2.0 * Math_PI; int i, bad = 0, cx, cp; while (centers.size() < center_count) { - int center_x = CLAMP(center_step * (int)((rnd->randi() % spread) - spread / 2), -dim, dim); - int center_y = CLAMP(center_step * (int)((rnd->randi() % spread) - spread / 2), -dim, dim); + int center_x = center_step * (int)((rnd->randi() % spread) - spread / 2); + int center_y = center_step * (int)((rnd->randi() % spread) - spread / 2); + center_x = CLAMP(center_x, -dim, dim); + center_y = CLAMP(center_y, -dim, dim); Vector2i c(center_x, center_y); if (centers.find(c) < 0) { centers.push_back(c); @@ -114,9 +116,10 @@ bool RoadGrid::segment_intersects_rect(const Vector2 &a, const Vector2 &b, const return true; } +/* This is heavy when rendered on top of 3D viewport! */ void RoadGrid::draw_debug(Node *drawable, int size_x, int size_y) const { - int i, j; + int i, j, k; CanvasItem *ci = Object::cast_to(drawable); if (!ci) return; @@ -138,11 +141,10 @@ void RoadGrid::draw_debug(Node *drawable, int size_x, int size_y) const Rect2i g = rect_to_grid(bounds); for (i = g.position.y - 1; i < g.position.y + g.size.y + 1; i++) { for (j = g.position.x - 1; j < g.position.x + g.size.x + 1; j++) { - if (hedge_grid.has(j) && hedge_grid[j].has(i)) { - List items = hedge_grid[j][i]; - List::Element *e; - for (e = items.front(); e; e = e->next()) { - struct half_edge *he = e->get(); + if (hedge_grid.has(j, i)) { + const Vector &items = hedge_grid.get(j, i); + for (k = 0; k < items.size(); k++) { + struct half_edge *he = items[k]; assert(he->a >= 0); assert(he->b >= 0); @@ -215,6 +217,8 @@ void RoadGrid::process_diagram(const Dictionary &diagram) printf("start processing sites\n"); for (i = 0; i < sites.size(); i++) { struct map_site site; + /* We use Dictionary to build native structure only once, + * then we use native data. */ const Dictionary &site_data = sites[i]; const Array &graphedges = site_data["graphedges"]; printf("processing site: %d\n", i); @@ -256,7 +260,7 @@ void RoadGrid::process_diagram(const Dictionary &diagram) printf("processing done, sites count: %d\n", map_sites.size()); } -void RoadGrid::build(Ref curve, Ref noise) +void RoadGrid::build(Ref curve, Ref noise) { rnd.instance(); rnd->randomize(); @@ -274,7 +278,8 @@ void RoadGrid::build(Ref curve, Ref noise) printf("building 3rd dimention\n"); diagram_vertex_heights.resize(diagram_vertices.size()); for (i = 0; i < diagram_vertices.size(); i++) { - float n = noise->get_noise_2dv(diagram_vertices[i]); + const Vector2 &v = diagram_vertices[i]; + float n = noise->get_noise_2d(v.x, v.y); float t = (n + 1.0f) * 0.5f; float d = MAX(1.0f, curve->interpolate_baked(t)); d = CLAMP(d, 1.0f, 30.0f); @@ -303,25 +308,21 @@ void RoadGrid::build(Ref curve, Ref noise) Vector2 RoadGrid::get_influence(int x, int y, float radius) const { int rd = (int)(radius / grid_width) + 1; - List hlist; - List::Element *e; + Vector hlist; + const List::Element *e; int i = 0, j = 0; for (i = -rd; i < rd + 1; i++) for (j = -rd; j < rd + 1; j++) { - List tmp; - if (hedge_grid.has(x / grid_width + i) && hedge_grid[x / grid_width + i].has(y / grid_height + j)) { - tmp = hedge_grid[x / grid_width + i][y / grid_height + j]; - for (e = tmp.front(); e; e = e->next()) { - struct half_edge *d = e->get(); - hlist.push_back(d); - } + if (hedge_grid.has(x / grid_width + i, y / grid_height + j)) { + const Vector &tmp = hedge_grid.get(x / grid_width + i, y / grid_height + j); + hlist.append_array(tmp); } } if (hlist.size() == 0) return Vector2(); - for (e = hlist.front(); e; e = e->next()) { - struct half_edge *he = e->get(); + for (i = 0; i < hlist.size(); i++) { + struct half_edge *he = hlist[i]; Vector2 a = diagram_vertices[he->a]; Vector2 b = diagram_vertices[he->b]; Vector2 p(x, y); @@ -338,7 +339,8 @@ Vector2 RoadGrid::get_influence(int x, int y, float radius) const float l = he->length; assert(l > 0.0f); float m1 = pt.distance_to(a) / l; - float m2 = CLAMP(1.0f - m1, 0.0f, 1.0f); + float m2 = 1.0f - m1; + m2 = CLAMP(m2, 0.0f, 1.0f); float h = h1 * (1.0f - m1) + h2 * (1.0f - m2); ret.y = h - 2.5f; return ret; @@ -354,3 +356,132 @@ void RoadGrid::_bind_methods() ClassDB::bind_method(D_METHOD("build", "curve", "noise"), &RoadGrid::build); } +int RoadGrid::find_edge(int a, int b) +{ + int i; + for (i = 0; i < map_hedges.size(); i++) { + if (map_hedges[i]->a == a && + map_hedges[i]->b == b) + return i; + } + return -1; +} +void RoadGrid::setup_vshapes() +{ + int i, j; + 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; + } + List vdata_list; + for (i = 0; i < map_hedges.size(); i++) { + for (j = 0; j < map_hedges.size(); j++) { + if (i == j) + continue; + if (map_hedges[i]->b != + map_hedges[j]->a) + continue; + if (map_hedges[i]->site != + map_hedges[j]->site) + continue; + int a, b1, b2; + struct vshape v; + /* star topology */ + a = map_hedges[i]->b; + b1 = map_hedges[i]->a; + b2 = map_hedges[j]->b; + v.e1 = i; + v.e2 = j; + v.site = map_hedges[i]->site; + v.area.position = vertices[a]; + v.area.expand_to(vertices[b1] + Vector3(0, 1, 0)); + v.area.expand_to(vertices[b2] + Vector3(0, -1, 0)); + v.instance = -1; + Vector3 p1 = vertices[map_hedges[v.e1]->a]; + Vector3 p2 = vertices[map_hedges[v.e1]->b]; + Vector3 p3 = vertices[map_hedges[v.e2]->b]; + p1 = (p2 + (p1 - p2) * 0.5f).snapped(Vector3(4.0f, 0.1f, 4.0f)); + p3 = (p2 + (p3 - p2) * 0.5f).snapped(Vector3(4.0f, 0.1f, 4.0f)); + p2 = p2.snapped(Vector3(4.0f, 0.1f, 4.0f)); + v.p1 = p1; + v.p2 = p2; + v.p3 = p3; + /* add v-shape only if we can actually generate it */ + if (v.p1.distance_squared_to(v.p2) > 2.0f && + v.p2.distance_squared_to(v.p3) > 2.0f && + v.p1.distance_squared_to(v.p3) > 2.0f) + vdata_list.push_back(v); + } + } + vshapes.resize(vdata_list.size()); + for (i = 0; i < vdata_list.size(); i++) + vshapes.write()[i] = vdata_list[i]; + for (i = 0; i < vshapes.size(); i++) { + for (j = 0; j < vshapes.size(); j++) { + if (i == j) + continue; + if (vshapes[i].e1 == vshapes[j].e1) + vshapes.write()[j].p1 = vshapes[i].p1; + if (vshapes[i].e2 == vshapes[j].e1) + vshapes.write()[j].p1 = vshapes[i].p3; + if (vshapes[i].e1 == vshapes[j].e2) + vshapes.write()[j].p3 = vshapes[i].p1; + if (vshapes[i].e2 == vshapes[j].e2) + vshapes.write()[j].p3 = vshapes[i].p3; + } + } + + for (i = 0; i < vshapes.size(); i++) { + const struct vshape &v = vshapes[i]; + assert(map_hedges[v.e1]->site == map_hedges[v.e2]->site); + assert(v.e1 >= 0 && v.e2 >= 0 && v.e1 != v.e2); + int e1a = map_hedges[vshapes[i].e1]->a; + int e1b = map_hedges[vshapes[i].e1]->b; + int e2a = map_hedges[vshapes[i].e2]->a; + int e2b = map_hedges[vshapes[i].e2]->b; + printf("vshape %d: %d: %d: %f %f %f -> %d: %f %f %f -> %d: %d: %f %f %f -> %d: %f %f %f\n", + i, + vshapes[i].e1, + e1a, + vertices[e1a].x, + vertices[e1a].y, + vertices[e1a].z, + e1b, + vertices[e1b].x, + vertices[e1b].y, + vertices[e1b].z, + vshapes[i].e2, + e2a, + vertices[e2a].x, + vertices[e2a].y, + vertices[e2a].z, + e2b, + vertices[e2b].x, + vertices[e2b].y, + vertices[e2b].z + ); + } +} + +void RoadGrid::sort_angle(Vector &sort_data) +{ + struct comparator { + Vector3 *vertices; + bool operator()(int a, int b) const { + Vector3 p1 = vertices[a]; + Vector3 p2 = vertices[b]; + Vector2 rp1(p1.x, p1.z); + Vector2 rp2(p2.x, p2.z); + return rp1.angle() < rp2.angle(); + } + }; + SortArray sorter; + sorter.compare.vertices = vertices.write().ptr(); + sorter.sort(sort_data.ptrw(), sort_data.size()); +} + +void RoadGrid::build_building_positions() +{ +} diff --git a/modules/world/road_grid.h b/modules/world/road_grid.h index 3204f99..5b7030a 100644 --- a/modules/world/road_grid.h +++ b/modules/world/road_grid.h @@ -1,10 +1,11 @@ #ifndef ROAD_GRID_H #define ROAD_GRID_H +#include #include #include #include #include -#include +#include class CanvasItem; @@ -44,7 +45,6 @@ protected: int spread, int dim); HashMap class_sizes; struct half_edge; - HashMap > > hedge_grid; Rect2 bounds; void set_class_size(int cl, int sz) { @@ -141,15 +141,38 @@ protected: rect.size.x = grid_height; return rect; } - inline void insert_hedge_to_grid_cell(int x, int y, struct half_edge *hedge) - { - if (hedge_grid.has(x) && hedge_grid[x].has(y)) - hedge_grid[x][y].push_back(hedge); - else { - List items; - items.push_back(hedge); + class hg { + typedef Vector tvalue; + std::unordered_map > > hedge_grid; + public: + inline const tvalue get(int x, int y) const + { + return hedge_grid.at(x).at(y); + } + inline bool has(int x, int y) const + { + if (hedge_grid.find(x) != hedge_grid.end() && + hedge_grid.at(x).find(y) != hedge_grid.at(x).end()) + return true; + return false; + } + inline void set(int x, int y, struct half_edge *hedge) + { + Vector items; + if (has(x, y)) + items = get(x, y); + items.resize(items.size() + 1); + items.write[items.size() - 1] = hedge; hedge_grid[x][y] = items; } + }; + class hg hedge_grid; + inline void insert_hedge_to_grid_cell(int x, int y, struct half_edge *hedge) + { + static int count = 0; + count++; + hedge_grid.set(x, y, hedge); + printf("count: %d\n", count); } inline void add_hedge_to_grid(struct half_edge *hedge) { @@ -186,12 +209,44 @@ protected: return (int)(y / grid_height); } float grid_width, grid_height; - friend class Roads; + PoolVector vertices; public: - void build(Ref curve, Ref noise); + struct vshape { + AABB area; + int instance; + int e1, e2; + int site; + Vector3 p1, p2, p3; + }; +protected: + PoolVector vshapes; + void sort_angle(Vector &sort_data); +public: + void build(Ref curve, Ref noise); void draw_debug(Node *drawable, int size_x, int size_y) const; + int find_edge(int a, int b); + void setup_vshapes(); + inline const PoolVector &get_vshapes() const + { + const PoolVector &ret = vshapes; + return ret; + } + inline PoolVector &get_vshapes() + { + PoolVector &ret = vshapes; + return ret; + } Vector2 get_influence(int x, int y, float radius) const; RoadGrid(); ~RoadGrid(); + inline int get_diagram_vertex_count() const + { + return diagram_vertices.size(); + } + inline int get_map_hedges_count() const + { + return map_hedges.size(); + } + void build_building_positions(); }; #endif diff --git a/modules/world/roads.cpp b/modules/world/roads.cpp index f23c5e7..c07b62a 100644 --- a/modules/world/roads.cpp +++ b/modules/world/roads.cpp @@ -54,121 +54,6 @@ bool Roads::_set(const StringName &p_name, const Variant &p_value) return update; } -void Roads::sort_angle(Vector &sort_data) -{ - struct comparator { - Vector3 *vertices; - bool operator()(int a, int b) const { - Vector3 p1 = vertices[a]; - Vector3 p2 = vertices[b]; - Vector2 rp1(p1.x, p1.z); - Vector2 rp2(p2.x, p2.z); - return rp1.angle() < rp2.angle(); - } - }; - SortArray sorter; - sorter.compare.vertices = vertices.write().ptr(); - sorter.sort(sort_data.ptrw(), sort_data.size()); -} -void Roads::setup_vshapes() -{ - int i, j; - RoadGrid *rg = RoadsData::get_singleton()->get_road_grid(); - vertices.resize(rg->diagram_vertices.size()); - for (i = 0; i < vertices.size(); i++) { - vertices.write()[i].x = rg->diagram_vertices[i].x; - vertices.write()[i].y = rg->diagram_vertex_heights[i]; - vertices.write()[i].z = rg->diagram_vertices[i].y; - } - List vdata_list; - for (i = 0; i < rg->map_hedges.size(); i++) { - for (j = 0; j < rg->map_hedges.size(); j++) { - if (i == j) - continue; - if (rg->map_hedges[i]->b != - rg->map_hedges[j]->a) - continue; - if (rg->map_hedges[i]->site != - rg->map_hedges[j]->site) - continue; - int a, b1, b2; - struct vshape v; - /* star topology */ - a = rg->map_hedges[i]->b; - b1 = rg->map_hedges[i]->a; - b2 = rg->map_hedges[j]->b; - v.e1 = i; - v.e2 = j; - v.site = rg->map_hedges[i]->site; - v.area.position = vertices[a]; - v.area.expand_to(vertices[b1] + Vector3(0, 1, 0)); - v.area.expand_to(vertices[b2] + Vector3(0, -1, 0)); - v.instance = -1; - Vector3 p1 = vertices[rg->map_hedges[v.e1]->a]; - Vector3 p2 = vertices[rg->map_hedges[v.e1]->b]; - Vector3 p3 = vertices[rg->map_hedges[v.e2]->b]; - p1 = (p2 + (p1 - p2) * 0.5f).snapped(Vector3(4.0f, 0.1f, 4.0f)); - p3 = (p2 + (p3 - p2) * 0.5f).snapped(Vector3(4.0f, 0.1f, 4.0f)); - p2 = p2.snapped(Vector3(4.0f, 0.1f, 4.0f)); - v.p1 = p1; - v.p2 = p2; - v.p3 = p3; - /* add v-shape only if we can actually generate it */ - if (v.p1.distance_squared_to(v.p2) > 2.0f && - v.p2.distance_squared_to(v.p3) > 2.0f && - v.p1.distance_squared_to(v.p3) > 2.0f) - vdata_list.push_back(v); - } - } - vshapes.resize(vdata_list.size()); - for (i = 0; i < vdata_list.size(); i++) - vshapes.write()[i] = vdata_list[i]; - for (i = 0; i < vshapes.size(); i++) { - for (j = 0; j < vshapes.size(); j++) { - if (i == j) - continue; - if (vshapes[i].e1 == vshapes[j].e1) - vshapes.write()[j].p1 = vshapes[i].p1; - if (vshapes[i].e2 == vshapes[j].e1) - vshapes.write()[j].p1 = vshapes[i].p3; - if (vshapes[i].e1 == vshapes[j].e2) - vshapes.write()[j].p3 = vshapes[i].p1; - if (vshapes[i].e2 == vshapes[j].e2) - vshapes.write()[j].p3 = vshapes[i].p3; - } - } - - for (i = 0; i < vshapes.size(); i++) { - const struct vshape &v = vshapes[i]; - assert(rg->map_hedges[v.e1]->site == rg->map_hedges[v.e2]->site); - assert(v.e1 >= 0 && v.e2 >= 0 && v.e1 != v.e2); - int e1a = rg->map_hedges[vshapes[i].e1]->a; - int e1b = rg->map_hedges[vshapes[i].e1]->b; - int e2a = rg->map_hedges[vshapes[i].e2]->a; - int e2b = rg->map_hedges[vshapes[i].e2]->b; - printf("vshape %d: %d: %d: %f %f %f -> %d: %f %f %f -> %d: %d: %f %f %f -> %d: %f %f %f\n", - i, - vshapes[i].e1, - e1a, - vertices[e1a].x, - vertices[e1a].y, - vertices[e1a].z, - e1b, - vertices[e1b].x, - vertices[e1b].y, - vertices[e1b].z, - vshapes[i].e2, - e2a, - vertices[e2a].x, - vertices[e2a].y, - vertices[e2a].z, - e2b, - vertices[e2b].x, - vertices[e2b].y, - vertices[e2b].z - ); - } -} void Roads::update_all() { int i; @@ -195,7 +80,7 @@ void Roads::update_all() } printf("vertices: %d\n", rg->get_diagram_vertex_count()); printf("edges: %d\n", rg->get_map_hedges_count()); - setup_vshapes(); + rg->setup_vshapes(); } } @@ -476,11 +361,13 @@ void Roads::process_vshapes() { if (get_viewport() && get_viewport()->get_camera()) cam_xform = get_viewport()->get_camera()->get_global_transform(); + RoadGrid *rg = RoadsData::get_singleton()->get_road_grid(); AABB camarea; camarea.position = cam_xform.origin; camarea.grow_by(550.0f); int i; List active_vshapes; + const PoolVector &vshapes = rg->get_vshapes(); printf("camera %f %f %f\n", cam_xform.origin.x, cam_xform.origin.y, cam_xform.origin.z); for (i = 0; i < vshapes.size(); i++) { if (active_vshapes.size() > 32) @@ -504,7 +391,7 @@ void Roads::process_vshapes() List::Element *e; for (e = active_vshapes.front(); e; e = e->next()) { i = e->get(); - const struct vshape &v = vshapes[i]; + const struct RoadGrid::vshape &v = vshapes[i]; assert(v.p1.distance_squared_to(v.p2) > 2.0f); assert(v.p2.distance_squared_to(v.p3) > 2.0f); assert(v.p1.distance_squared_to(v.p3) > 2.0f); @@ -546,14 +433,16 @@ void Roads::generate_threaded(void *p_userdata) struct thread_data *data = (struct thread_data *)p_userdata; Roads *obj = Object::cast_to(data->root); obj->mutex.lock(); - Vector3 p1 = obj->vshapes[data->vshape].p1; - Vector3 p2 = obj->vshapes[data->vshape].p2; - Vector3 p3 = obj->vshapes[data->vshape].p3; + RoadGrid *rg = RoadsData::get_singleton()->get_road_grid(); + const PoolVector &vshapes = rg->get_vshapes(); + Vector3 p1 = vshapes[data->vshape].p1; + Vector3 p2 = vshapes[data->vshape].p2; + Vector3 p3 = vshapes[data->vshape].p3; obj->mutex.unlock(); int instance = obj->make_vmesh(obj, data->mat, data->mesh, data->xmi, p1, p2, p3, data->width, data->flags, data->sidewalk_width); assert(instance >= 0); obj->mutex.lock(); - obj->vshapes.write()[data->vshape].instance = instance; + rg->get_vshapes().write()[data->vshape].instance = instance; obj->mutex.unlock(); } diff --git a/modules/world/roads.h b/modules/world/roads.h index f4f88ec..041ade7 100644 --- a/modules/world/roads.h +++ b/modules/world/roads.h @@ -22,7 +22,6 @@ protected: void _get_property_list(List *p_list) const; static void _bind_methods(); void update_all(); - PoolVector vertices; struct thread_data { Thread thread; Ref mat; @@ -49,19 +48,9 @@ protected: {} }; #endif - struct vshape { - AABB area; - int instance; - int e1, e2; - int site; - Vector3 p1, p2, p3; - }; #if 0 PoolVector edges; #endif - PoolVector vshapes; - void setup_vshapes(); - void sort_angle(Vector &sort_data); #if 0 void extrude_direct(Array &out, const Array &arrays, const struct edge_data *data) const; void extrude_vshape(Array &out, const Array &arrays, const struct vshape *data) const;