Updated world module (now voronoi roads work

This commit is contained in:
Segey Lapin
2021-10-13 16:33:36 +03:00
parent d0b1daa6e9
commit e35d566eb8
14 changed files with 1533 additions and 246 deletions

View File

@@ -4,37 +4,26 @@
void DensityMap::_get_property_list(List<PropertyInfo> *p_list) const
{
p_list->push_back(PropertyInfo(Variant::INT, "world/grid_size"));
p_list->push_back(PropertyInfo(Variant::INT, "world/clusters/count"));
if (grid_size == 0 || num_clusters == 0)
return;
p_list->push_back(PropertyInfo(Variant::INT, "world/size/x"));
p_list->push_back(PropertyInfo(Variant::INT, "world/size/y"));
p_list->push_back(PropertyInfo(Variant::INT, "world/size/z"));
if (world_x_size * world_y_size * world_z_size == 0U)
return;
p_list->push_back(PropertyInfo(Variant::INT, "world/clusters/seed"));
// p_list->push_back(PropertyInfo(Variant::INT, "world/grid_size"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"));
p_list->push_back(PropertyInfo(Variant::INT, "rnd_seed"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
p_list->push_back(PropertyInfo(Variant::OBJECT, "height_map", PROPERTY_HINT_RESOURCE_TYPE, "WorldHeightMap"));
}
bool DensityMap::_get(const StringName &p_name, Variant &r_ret) const
{
if (p_name == "world/clusters/count") {
r_ret = num_clusters;
if (p_name == "noise") {
r_ret = noise;
return true;
} else if (p_name == "world/clusters/seed") {
} else if (p_name == "rnd_seed") {
r_ret = seed;
return true;
} else if (p_name == "world/grid_size") {
r_ret = grid_size;
} else if (p_name == "curve") {
r_ret = curve;
return true;
} else if (p_name == "world/size/x") {
r_ret = world_x_size;
return true;
} else if (p_name == "world/size/y") {
r_ret = world_y_size;
return true;
} else if (p_name == "world/size/z") {
r_ret = world_z_size;
} else if (p_name == "height_map") {
r_ret = height_map;
return true;
}
@@ -44,189 +33,66 @@ bool DensityMap::_get(const StringName &p_name, Variant &r_ret) const
bool DensityMap::_set(const StringName &p_name, const Variant &p_value)
{
bool update = false;
if (p_name == "world/clusters/count") {
num_clusters = p_value;
if (p_name == "noise") {
noise = p_value;
update = true;
} else if (p_name == "world/clusters/seed") {
} else if (p_name == "rnd_seed") {
seed = p_value;
update = true;
} else if (p_name == "world/grid_size") {
grid_size = p_value;
} else if (p_name == "curve") {
curve = p_value;
update = true;
} else if (p_name == "world/size/x") {
world_x_size = p_value;
update = true;
} else if (p_name == "world/size/y") {
world_y_size = p_value;
update = true;
} else if (p_name == "world/size/z") {
world_z_size = p_value;
} else if (p_name == "height_map") {
curve = p_value;
update = true;
}
if (update) {
update_clusters();
update_all();
_change_notify();
}
return update;
}
void DensityMap::populate_grid(List<struct area> &list)
void DensityMap::update_all()
{
}
void DensityMap::update_clusters()
{
int i;
clusters.clear();
regions.clear();
counties.clear();
cities.clear();
districts.clear();
circle_grid.clear();
if (num_clusters < 1)
if (!curve.ptr() || !rnd.ptr() || !noise.ptr() || !height_map.ptr())
return;
rnd->set_seed(seed);
world_center.x = world_x_size / 2;
world_center.y = world_y_size / 2;
world_center.z = world_z_size / 2;
if (world_x_size * world_y_size * world_z_size == 0)
return;
split_area(NULL, num_clusters, clusters);
for (i = 0; i < clusters.size(); i++) {
split_area(&clusters[i], num_regions, regions);
}
for (i = 0; i < regions.size(); i++) {
split_area(&regions[i], num_counties, counties);
}
for (i = 0; i < counties.size(); i++) {
split_area(&counties[i], num_cities, cities);
}
for (i = 0; i < cities.size(); i++) {
split_area(&cities[i], num_districts, districts);
}
WorldMapData *wmd = WorldMapData::get_singleton();
wmd->clear();
wmd->set_world_size(world_x_size, world_z_size);
#if 0
for (i = 0; i < clusters.size(); i++) {
wmd->add_circle(clusters[i].pos.x, clusters[i].pos.y, clusters[i].radius);
printf("cluster: %d x: %d y: %d radius: %f\n", i, clusters[i].pos.x, clusters[i].pos.y, clusters[i].radius);
}
#endif
for (i = 0; i < districts.size(); i++) {
wmd->add_circle(districts[i].pos.x, districts[i].pos.y, districts[i].radius);
printf("districts: %d x: %d y: %d radius: %f\n", i, districts[i].pos.x, districts[i].pos.y, districts[i].radius);
}
wmd->save_debug_image();
printf("num_clusters: %d - %d\n", (int)num_clusters, (int)clusters.size());
printf("num_regions: %d - %d\n", (int)num_regions, (int)regions.size());
printf("num_counties: %d - %d\n", (int)num_counties, (int)counties.size());
printf("num_cities: %d - %d\n", (int)num_cities, (int)cities.size());
printf("num_districts: %d - %d\n", (int)num_districts, (int)districts.size());
}
void DensityMap::split_area(struct area *area, int num_split, List<struct area> &list)
void DensityMap::_bind_methods()
{
ClassDB::bind_method(D_METHOD("get_population_density", "x", "y"), &DensityMap::get_population_density);
}
float DensityMap::get_population_density(float x, float y)
{
Vector2i pstart;
struct area astart;
float mrad;
int count = 500 * num_split;
int orig_size = (int)list.size();
if (area) {
pstart.x = area->pos.x;
pstart.y = area->pos.y;
#if 0
while (true) {
float angle = rnd->randf() * M_PI * 2.0f;
float off = rnd->randf() * area->radius;
float tx = cosf(angle) * off;
float ty = cosf(angle) * off;
int px = area->pos.x + (int)tx;
int py = area->pos.y + (int)ty;
if (px < 0 || px >= (int)world_x_size)
continue;
if (px < 0 || px >= (int)world_x_size)
continue;
pstart.x = px;
pstart.y = py;
break;
}
float n = (noise->get_noise_2d(x, y) + 1.0f) * 0.5f;
float d = curve->interpolate_baked(n);
#endif
mrad = area->radius / (float)num_split;
} else {
pstart.x = rnd->randi() % world_x_size;
pstart.y = rnd->randi() % world_z_size;
mrad = sqrtf((float)world_x_size * (float)world_z_size) / (float)num_split;
mrad *= 0.9f;
pstart.x -= (int)mrad + 1;
pstart.y -= (int)mrad + 1;
}
astart.pos = pstart;
astart.radius = mrad;
astart.parent = area;
list.push_back(astart);
Vector2i cur(pstart.x, pstart.y);
while ((int)list.size() - orig_size < num_split && count-- > 0) {
float angle = rnd->randf() * M_PI * 2.0f;
float offt_x = cosf(angle) * mrad;
float offt_y = sinf(angle) * mrad;
int ox = (int)(cur.x + offt_x);
int oy = (int)(cur.y + offt_y);
if (ox < 0 || ox >= (int)world_x_size)
ox = (int)(cur.x - offt_x);
if (oy < 0 || ox >= (int)world_y_size)
oy = (int)(cur.y - offt_y);
if (area && !area->has_point(Vector2i(ox, oy)))
continue;
if (ox < 0 || ox >= (int)world_x_size)
continue;
if (oy < 0 || oy >= (int)world_z_size)
continue;
// printf("sample: %d %d %f\n", ox, oy, mrad);
const List<struct area>::Element *e = list.front();
bool good = true;
while (e) {
struct area a = e->get();
int oxd = ox - a.pos.x;
int oyd = oy - a.pos.y;
int r = oxd * oxd + oyd * oyd;
if (r < mrad * mrad) {
good = false;
break;
}
e = e->next();
}
if (good) {
struct area anext;
anext.pos.x = ox;
anext.pos.y = oy;
anext.radius = mrad;
anext.parent = area;
list.push_back(anext);
printf("result: %d %d %f\n", anext.pos.x, anext.pos.y, anext.radius);
}
}
if (count <= 0)
printf("list count %d\n", (int)list.size());
float h = height_map->get_surface_height(x, y);
if (h < 0.0f || h > max_height)
return 0.0f;
float s = height_map->get_base_steepness(x, y);
if (s > 0.3f)
return 0.0f;
float d = 0.0f;
/* Still use curve for it? */
if (h < max_height * 0.3f)
d = 1.0f;
else
d = max_height * 0.3f / h;
return d * s;
}
DensityMap::DensityMap()
{
rnd.instance();
rnd->randomize();
seed = rnd->get_seed();
world_x_size = 400000;
world_y_size = 1000;
world_z_size = 400000;
grid_size = 100;
num_clusters = 5;
num_regions = 15;
num_counties = 30;
num_cities = 5;
num_districts = 5;
max_height = 300.0f;
}
DensityMap::~DensityMap()
{
}