Update; refactor of initial code
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <core/os/file_access.h>
|
||||
#include <core/io/json.h>
|
||||
#include <core/math/geometry.h>
|
||||
#include <core/resource.h>
|
||||
#include <core/variant_parser.h>
|
||||
#include <scene/2d/canvas_item.h>
|
||||
#include <modules/voronoi/voronoi.h>
|
||||
#include <modules/opensimplex/open_simplex_noise.h>
|
||||
@@ -11,11 +14,6 @@ RoadGrid::RoadGrid()
|
||||
{
|
||||
grid_width = 16;
|
||||
grid_height = 16;
|
||||
class_sizes[SITE_EMPTY] = 10000;
|
||||
class_sizes[SITE_TOWN] = 100000;
|
||||
class_sizes[SITE_FARM] = 500000;
|
||||
class_sizes[SITE_FOREST] = 1000000;
|
||||
class_sizes[SITE_UNASSIGNED] = 2000000;
|
||||
}
|
||||
|
||||
RoadGrid::~RoadGrid()
|
||||
@@ -23,7 +21,7 @@ RoadGrid::~RoadGrid()
|
||||
}
|
||||
|
||||
/* TODO: constants, configuration */
|
||||
Dictionary RoadGrid::build_diagram(int npatches, int center_count, int center_step, int spread, int dim)
|
||||
Dictionary RoadDiagram::build_diagram(Ref<RandomNumberGenerator> rnd, int npatches, int center_count, int center_step, int spread, int dim)
|
||||
{
|
||||
printf("build_diagram %d %d %d %d %d\n", npatches, center_count, center_step, spread, dim);
|
||||
Vector<Vector2i> centers;
|
||||
@@ -72,6 +70,22 @@ Dictionary RoadGrid::build_diagram(int npatches, int center_count, int center_st
|
||||
Dictionary diagram = Voronoi::get_singleton()->generate_diagram(cpoints, 11);
|
||||
return diagram;
|
||||
}
|
||||
const List<struct cluster> &RoadDiagram::get_clusters() const
|
||||
{
|
||||
return clusters;
|
||||
}
|
||||
const Vector<struct map_site> &RoadDiagram::get_map_sites() const
|
||||
{
|
||||
return map_sites;
|
||||
}
|
||||
const Vector<Vector2> &RoadDiagram::get_diagram_vertices() const
|
||||
{
|
||||
return diagram_vertices;
|
||||
}
|
||||
const Vector<struct half_edge *> &RoadDiagram::get_map_hedges() const
|
||||
{
|
||||
return map_hedges;
|
||||
}
|
||||
bool RoadGrid::segment_intersects_rect(const Vector2 &a, const Vector2 &b, const Rect2 &rect)
|
||||
{
|
||||
real_t min = 0, max = 1;
|
||||
@@ -165,7 +179,7 @@ void RoadGrid::draw_debug(Node *drawable, int size_x, int size_y) const
|
||||
}
|
||||
}
|
||||
|
||||
void RoadGrid::index_site(struct map_site *site)
|
||||
void RoadDiagram::index_site(struct map_site *site)
|
||||
{
|
||||
int i;
|
||||
site->vertices_ind.resize(site->vertices.size());
|
||||
@@ -203,14 +217,21 @@ void RoadGrid::index_site(struct map_site *site)
|
||||
he.b = idx2;
|
||||
he.site = site->index;
|
||||
/* use length to decide */
|
||||
he.depth = 6.0f;
|
||||
he.length = diagram_vertices[idx1].distance_to(diagram_vertices[idx2]);
|
||||
if (he.length < 50.0f)
|
||||
he.depth = 3.0f;
|
||||
else if (he.length < 100.0f)
|
||||
he.depth = 6.0f;
|
||||
else if (he.length < 200.0f)
|
||||
he.depth = 12.0f;
|
||||
else
|
||||
he.depth = 24.0f;
|
||||
site->hedges.write[count++] = he;
|
||||
}
|
||||
site->hedges.resize(count);
|
||||
}
|
||||
|
||||
void RoadGrid::process_diagram(const Dictionary &diagram)
|
||||
void RoadDiagram::process_diagram(const Dictionary &diagram)
|
||||
{
|
||||
const Array &sites = diagram["sites"];
|
||||
int i, j;
|
||||
@@ -237,7 +258,7 @@ void RoadGrid::process_diagram(const Dictionary &diagram)
|
||||
site.pos = site_data["pos"];
|
||||
site.polygon = site_data["polygon"];
|
||||
site.vertices = site_data["vertices"];
|
||||
site.site_type = SITE_UNASSIGNED;
|
||||
site.site_type = map_site::SITE_UNASSIGNED;
|
||||
site.cluster = -1;
|
||||
index_site(&site);
|
||||
hedge_count += site.hedges.size();
|
||||
@@ -253,7 +274,6 @@ void RoadGrid::process_diagram(const Dictionary &diagram)
|
||||
/* bad bad constness */
|
||||
struct half_edge *hedge = &map_sites.write[i].hedges.write[j];
|
||||
map_hedges.write[hedge_idx] = hedge;
|
||||
add_hedge_to_grid(hedge);
|
||||
hedge_idx++;
|
||||
}
|
||||
}
|
||||
@@ -261,49 +281,48 @@ void RoadGrid::process_diagram(const Dictionary &diagram)
|
||||
classify_sites();
|
||||
printf("processing done, sites count: %d\n", map_sites.size());
|
||||
}
|
||||
RoadDiagram::RoadDiagram()
|
||||
{
|
||||
class_sizes[map_site::SITE_EMPTY] = 10000;
|
||||
class_sizes[map_site::SITE_TOWN] = 100000;
|
||||
class_sizes[map_site::SITE_FARM] = 500000;
|
||||
class_sizes[map_site::SITE_FOREST] = 1000000;
|
||||
class_sizes[map_site::SITE_UNASSIGNED] = 2000000;
|
||||
}
|
||||
|
||||
void RoadDiagram::build(Ref<RandomNumberGenerator> rnd,
|
||||
int npatches, int center_count, int center_step,
|
||||
int spread, int dim)
|
||||
{
|
||||
Dictionary diagram = build_diagram(rnd, npatches, center_count, center_step,
|
||||
spread, dim);
|
||||
process_diagram(diagram);
|
||||
}
|
||||
void RoadGrid::build(Ref<Curve> curve, Ref<FastNoiseLite> noise)
|
||||
{
|
||||
int i, j;
|
||||
RoadDiagram rd;
|
||||
rnd.instance();
|
||||
rnd->randomize();
|
||||
printf("build_diagram\n");
|
||||
// Dictionary diagram = build_diagram(8, 2 + (rnd->randi() % 2), 100, 100, 50);
|
||||
Dictionary diagram = build_diagram(8, 2, 100, 100, 500);
|
||||
rd.build(rnd, 8, 2, 100, 100, 500);
|
||||
printf("build_diagram done\n");
|
||||
printf("process_diagram\n");
|
||||
process_diagram(diagram);
|
||||
printf("process_diagram done\n");
|
||||
const List<struct cluster> &cl = rd.get_clusters();
|
||||
const List<struct cluster>::Element *e = cl.front();
|
||||
for (e = cl.front(); e; e = e->next())
|
||||
clusters.push_back(e->get());
|
||||
map_sites.append_array(rd.get_map_sites());
|
||||
diagram_vertices.append_array(rd.get_diagram_vertices());
|
||||
map_hedges.append_array(rd.get_map_hedges());
|
||||
for (i = 0; i < map_hedges.size(); i++) {
|
||||
struct half_edge *hedge = map_hedges.write[i];
|
||||
add_hedge_to_grid(hedge);
|
||||
}
|
||||
printf("%d %d\n", curve.is_valid(), noise.is_valid());
|
||||
assert(curve.is_valid() && noise.is_valid());
|
||||
int i, j;
|
||||
if (curve.is_valid() && noise.is_valid()) {
|
||||
printf("building 3rd dimention\n");
|
||||
diagram_vertex_heights.resize(diagram_vertices.size());
|
||||
for (i = 0; i < diagram_vertices.size(); 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);
|
||||
diagram_vertex_heights.write[i] = d;
|
||||
}
|
||||
for (j = 0; j < 3; j++) {
|
||||
for (i = 0; i < map_hedges.size(); i++) {
|
||||
int x1 = map_hedges[i]->a;
|
||||
int x2 = map_hedges[i]->b;
|
||||
float xd = map_hedges[i]->length;
|
||||
float dh = fabsf(diagram_vertex_heights[x2] - diagram_vertex_heights[x1]);
|
||||
if (fabsf(dh / xd) > 0.01f)
|
||||
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd;
|
||||
}
|
||||
#if 0
|
||||
for (i = 0; i < diagram_vertices.size(); i++)
|
||||
diagram_vertex_heights.write[i] = Math::stepify(diagram_vertex_heights.write[i], 4.0f);
|
||||
for (i = 0; i < diagram_vertices.size(); i++)
|
||||
diagram_vertex_heights.write[i] = 2.0;
|
||||
#endif
|
||||
}
|
||||
generate_3d_vertices();
|
||||
generate_3d_vertices(curve, noise);
|
||||
for (i = 0; i < map_sites.size(); i++) {
|
||||
float max_height = -10000.0f;
|
||||
float min_height = 10000.0f;
|
||||
@@ -319,6 +338,7 @@ void RoadGrid::build(Ref<Curve> curve, Ref<FastNoiseLite> noise)
|
||||
generate_building_positions();
|
||||
printf("building 3rd dimention done\n");
|
||||
}
|
||||
keep_seed = rnd->get_state();
|
||||
}
|
||||
|
||||
Vector2 RoadGrid::get_influence(int x, int y, float radius) const
|
||||
@@ -345,13 +365,13 @@ Vector2 RoadGrid::get_influence(int x, int y, float radius) const
|
||||
Vector2 seg[] = {a, b};
|
||||
Vector2 pt = Geometry::get_closest_point_to_segment_2d(p, seg);
|
||||
float d = pt.distance_squared_to(p);
|
||||
if (d < radius * radius) {
|
||||
if (d < radius * radius + he->depth * he->depth) {
|
||||
Vector2 ret;
|
||||
ret.x = 1.0f;
|
||||
assert(diagram_vertex_heights.size() > he->a);
|
||||
assert(diagram_vertex_heights.size() > he->b);
|
||||
float h1 = diagram_vertex_heights[he->a];
|
||||
float h2 = diagram_vertex_heights[he->b];
|
||||
assert(vertices.size() > he->a);
|
||||
assert(vertices.size() > he->b);
|
||||
float h1 = vertices[he->a].y;
|
||||
float h2 = vertices[he->b].y;
|
||||
float l = he->length;
|
||||
assert(l > 0.0f);
|
||||
float m1 = pt.distance_to(a) / l;
|
||||
@@ -409,6 +429,8 @@ void RoadGrid::setup_vshapes()
|
||||
v.area.expand_to(vertices[b1] + Vector3(0, 1, 0));
|
||||
v.area.expand_to(vertices[b2] + Vector3(0, -1, 0));
|
||||
v.instance = -1;
|
||||
v.depth1 = map_hedges[v.e1]->depth;
|
||||
v.depth2 = map_hedges[v.e2]->depth;
|
||||
Vector3 p1 = vertices[map_hedges[v.e1]->a];
|
||||
Vector3 p2 = vertices[map_hedges[v.e1]->b];
|
||||
Vector3 p3 = vertices[map_hedges[v.e2]->b];
|
||||
@@ -492,9 +514,29 @@ void RoadGrid::sort_angle(Vector<int> &sort_data)
|
||||
sorter.sort(sort_data.ptrw(), sort_data.size());
|
||||
}
|
||||
|
||||
void RoadGrid::generate_3d_vertices()
|
||||
void RoadGrid::generate_3d_vertices(Ref<Curve> curve, Ref<FastNoiseLite> noise)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
Vector<float> diagram_vertex_heights;
|
||||
diagram_vertex_heights.resize(diagram_vertices.size());
|
||||
for (i = 0; i < diagram_vertices.size(); 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);
|
||||
diagram_vertex_heights.write[i] = d;
|
||||
}
|
||||
for (j = 0; j < 3; j++) {
|
||||
for (i = 0; i < map_hedges.size(); i++) {
|
||||
int x1 = map_hedges[i]->a;
|
||||
int x2 = map_hedges[i]->b;
|
||||
float xd = map_hedges[i]->length;
|
||||
float dh = fabsf(diagram_vertex_heights[x2] - diagram_vertex_heights[x1]);
|
||||
if (fabsf(dh / xd) > 0.01f)
|
||||
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd;
|
||||
}
|
||||
}
|
||||
vertices.resize(get_diagram_vertex_count());
|
||||
for (i = 0; i < vertices.size(); i++) {
|
||||
vertices.write()[i].x = diagram_vertices[i].x;
|
||||
@@ -525,3 +567,117 @@ int RoadGrid::get_site_from_point(int x, int z)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static String var2str(const Variant &data)
|
||||
{
|
||||
String s;
|
||||
VariantWriter::write_to_string(data, s);
|
||||
return s;
|
||||
}
|
||||
template <class T>
|
||||
static Array avar2str(const Vector<T> &data)
|
||||
{
|
||||
Array pdata;
|
||||
int i;
|
||||
pdata.resize(data.size());
|
||||
for (i = 0; i < data.size(); i++)
|
||||
pdata[i] = var2str(data[i]);
|
||||
return pdata;
|
||||
}
|
||||
static Dictionary half_edge2dict(const struct half_edge *he)
|
||||
{
|
||||
Dictionary ret;
|
||||
ret["a"] = he->a;
|
||||
ret["b"] = he->b;
|
||||
ret["site"] = he->site;
|
||||
ret["depth"] = he->depth;
|
||||
ret["length"] = he->length;
|
||||
return ret;
|
||||
}
|
||||
static Array rect2i_array(const Rect2i &rect)
|
||||
{
|
||||
Array tmp;
|
||||
tmp.resize(4);
|
||||
tmp[0] = rect.position[0];
|
||||
tmp[1] = rect.position[1];
|
||||
tmp[2] = rect.size[0];
|
||||
tmp[3] = rect.size[1];
|
||||
return tmp;
|
||||
}
|
||||
static Dictionary map_site2dict(const struct map_site *ms)
|
||||
{
|
||||
int i;
|
||||
Dictionary ret;
|
||||
Array hedges;
|
||||
ret["index"] = ms->index;
|
||||
ret["pos"] = var2str(ms->pos);
|
||||
ret["vertices"] = avar2str(ms->vertices);
|
||||
ret["polygon"] = avar2str(ms->polygon);
|
||||
ret["vertices_ind"] = avar2str(ms->vertices_ind);
|
||||
ret["polygon_ind"] = avar2str(ms->polygon_ind);
|
||||
ret["site_type"] = ms->site_type;
|
||||
ret["cluster"] = ms->cluster;
|
||||
hedges.resize(ms->hedges.size());
|
||||
for (i = 0; i < ms->hedges.size(); i++)
|
||||
hedges[i] = half_edge2dict(&ms->hedges[i]);
|
||||
ret["hedges"] = hedges;
|
||||
ret["rect"] = rect2i_array(ms->rect);
|
||||
ret["avg_height"] = ms->avg_height;
|
||||
return ret;
|
||||
}
|
||||
static Dictionary vshape2dict(const struct RoadGrid::vshape *v)
|
||||
{
|
||||
Dictionary ret;
|
||||
ret["area"] = var2str(v->area);
|
||||
ret["instance"] = v->instance;
|
||||
ret["e1"] = v->e1;
|
||||
ret["e2"] = v->e2;
|
||||
ret["site"] = v->site;
|
||||
ret["p1"] = var2str(v->p1);
|
||||
ret["p2"] = var2str(v->p2);
|
||||
ret["p3"] = var2str(v->p3);
|
||||
ret["depth1"] = v->depth1;
|
||||
ret["depth2"] = v->depth2;
|
||||
return ret;
|
||||
}
|
||||
void RoadGrid::save_json(const String &path)
|
||||
{
|
||||
int i;
|
||||
String vars;
|
||||
FileAccess *f;
|
||||
Dictionary to_json;
|
||||
/* Clusters */
|
||||
Array save_clusters;
|
||||
/* save clusters */
|
||||
save_clusters.resize(clusters.size());
|
||||
for (i = 0; i < clusters.size(); i++) {
|
||||
Dictionary cluster;
|
||||
cluster["pos_x"] = clusters[i].c.x;
|
||||
cluster["pos_y"] = clusters[i].c.y;
|
||||
cluster["radius"] = clusters[i].r;
|
||||
save_clusters[i] = cluster;
|
||||
}
|
||||
to_json["clusters"] = save_clusters;
|
||||
to_json["bounds"] = var2str(bounds);
|
||||
to_json["diagram_vertices"] = avar2str(diagram_vertices);
|
||||
Array msites, mvshapes;
|
||||
msites.resize(map_sites.size());
|
||||
for (i = 0; i < map_sites.size(); i++)
|
||||
msites[i] = map_site2dict(&map_sites[i]);
|
||||
to_json["map_sites"] = msites;
|
||||
to_json["vertices"] = var2str(vertices);
|
||||
mvshapes.resize(vshapes.size());
|
||||
for (i = 0; i < vshapes.size(); i++) {
|
||||
const struct vshape *v = &(vshapes.read()[i]);
|
||||
mvshapes[i] = vshape2dict(v);
|
||||
}
|
||||
to_json["vshapes"] = mvshapes;
|
||||
|
||||
String json = JSON::print(to_json, "\t");
|
||||
f = FileAccess::open(path, FileAccess::WRITE);
|
||||
if (f) {
|
||||
f->store_string(json);
|
||||
f->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user