233 lines
6.3 KiB
C++
233 lines
6.3 KiB
C++
#include <cstdio>
|
|
#include "world_map_data.h"
|
|
#include "density_map.h"
|
|
|
|
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"));
|
|
}
|
|
|
|
bool DensityMap::_get(const StringName &p_name, Variant &r_ret) const
|
|
{
|
|
if (p_name == "world/clusters/count") {
|
|
r_ret = num_clusters;
|
|
return true;
|
|
} else if (p_name == "world/clusters/seed") {
|
|
r_ret = seed;
|
|
return true;
|
|
} else if (p_name == "world/grid_size") {
|
|
r_ret = grid_size;
|
|
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;
|
|
return true;
|
|
}
|
|
|
|
const String pv = p_name.operator String();
|
|
return false;
|
|
}
|
|
bool DensityMap::_set(const StringName &p_name, const Variant &p_value)
|
|
{
|
|
bool update = false;
|
|
if (p_name == "world/clusters/count") {
|
|
num_clusters = p_value;
|
|
update = true;
|
|
} else if (p_name == "world/clusters/seed") {
|
|
seed = p_value;
|
|
update = true;
|
|
} else if (p_name == "world/grid_size") {
|
|
grid_size = 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;
|
|
update = true;
|
|
}
|
|
if (update) {
|
|
update_clusters();
|
|
_change_notify();
|
|
}
|
|
|
|
return update;
|
|
}
|
|
|
|
void DensityMap::populate_grid(List<struct area> &list)
|
|
{
|
|
}
|
|
|
|
void DensityMap::update_clusters()
|
|
{
|
|
int i;
|
|
clusters.clear();
|
|
regions.clear();
|
|
counties.clear();
|
|
cities.clear();
|
|
districts.clear();
|
|
circle_grid.clear();
|
|
if (num_clusters < 1)
|
|
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(®ions[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)
|
|
{
|
|
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;
|
|
}
|
|
#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());
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
DensityMap::~DensityMap()
|
|
{
|
|
}
|