#include #include "world_map_data.h" #include "density_map.h" void DensityMap::_get_property_list(List *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 &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 &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::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() { }