Optimized, updated

This commit is contained in:
Segey Lapin
2021-10-15 18:22:02 +03:00
parent ea4c8a5731
commit ccee4fb686
5 changed files with 230 additions and 166 deletions

View File

@@ -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<CanvasItem>(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<struct half_edge *> items = hedge_grid[j][i];
List<struct half_edge *>::Element *e;
for (e = items.front(); e; e = e->next()) {
struct half_edge *he = e->get();
if (hedge_grid.has(j, i)) {
const Vector<struct half_edge *> &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> curve, Ref<OpenSimplexNoise> noise)
void RoadGrid::build(Ref<Curve> curve, Ref<FastNoiseLite> noise)
{
rnd.instance();
rnd->randomize();
@@ -274,7 +278,8 @@ void RoadGrid::build(Ref<Curve> curve, Ref<OpenSimplexNoise> 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> curve, Ref<OpenSimplexNoise> noise)
Vector2 RoadGrid::get_influence(int x, int y, float radius) const
{
int rd = (int)(radius / grid_width) + 1;
List<struct half_edge *> hlist;
List<struct half_edge *>::Element *e;
Vector<struct half_edge *> hlist;
const List<struct half_edge *>::Element *e;
int i = 0, j = 0;
for (i = -rd; i < rd + 1; i++)
for (j = -rd; j < rd + 1; j++) {
List<struct half_edge *> 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<struct half_edge *> &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<struct vshape> 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<int> &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<int, struct comparator> sorter;
sorter.compare.vertices = vertices.write().ptr();
sorter.sort(sort_data.ptrw(), sort_data.size());
}
void RoadGrid::build_building_positions()
{
}