Worked on buildings in lines

This commit is contained in:
2024-09-22 02:19:40 +03:00
parent 6fa644c57d
commit 2f3187257d
13 changed files with 5452 additions and 3527 deletions

View File

@@ -11,6 +11,7 @@
#include <scene/3d/immediate_geometry.h>
#include <scene/main/viewport.h>
#include "from_string.h"
#include "buildings_data.h"
#include "road_lines_data.h"
ImmediateGeometry *RoadLinesData::debug_im = nullptr;
@@ -62,7 +63,6 @@ RoadLinesData::RoadLinesData()
e = e->next();
}
}
RoadLinesData *RoadLinesData::singleton = nullptr;
RoadLinesData *RoadLinesData::get_singleton()
{
@@ -70,7 +70,6 @@ RoadLinesData *RoadLinesData::get_singleton()
singleton = memnew(RoadLinesData);
return singleton;
}
RoadLinesData::~RoadLinesData()
{
#if 0
@@ -80,18 +79,15 @@ RoadLinesData::~RoadLinesData()
}
#endif
}
void RoadLinesData::cleanup()
{
memdelete(singleton);
singleton = nullptr;
}
String RoadLinesData::get_road_lines_path()
{
return road_lines_path;
}
void RoadLinesData::get_road_lines_key_list(List<String> *keys)
{
List<String> line_keys;
@@ -234,8 +230,7 @@ void RoadLinesData::create_segments(const String &road,
std::vector<int> &segments)
{
int i;
RoadLinesData *rld = RoadLinesData::get_singleton();
for (i = 0; i < (int)rld->lines[road].indices.size() - 1; i++) {
for (i = 0; i < (int)lines[road].indices.size() - 1; i++) {
segments.push_back(i);
segments.push_back(i + 1);
}
@@ -296,14 +291,12 @@ void RoadLinesData::insert_close_points(std::vector<Vector3> &road_lines_nodes,
}
}
}
void RoadLinesData::update_road_lines_nodes(
std::vector<Vector3> &road_lines_nodes)
{
List<String> keys;
RoadLinesData *rld = RoadLinesData::get_singleton();
rld->get_road_lines_key_list(&keys);
get_road_lines_key_list(&keys);
std::unordered_map<uint32_t, std::tuple<String, String> > kcmp;
{
List<String>::Element *k = keys.front();
@@ -335,25 +328,22 @@ void RoadLinesData::update_road_lines_nodes(
std::tuple<String, String> data = kcmp[it->first];
const String &k = std::get<0>(data);
const String &r = std::get<1>(data);
if (rld->lines[k].indices.size() < 2)
if (lines[k].indices.size() < 2)
continue;
if (rld->lines[r].indices.size() < 2)
if (lines[r].indices.size() < 2)
continue;
for (i = 0; i < (int)rld->lines[k].indices.size() - 1; i++) {
for (j = 0; j < (int)rld->lines[k].indices.size() - 1;
j++) {
for (i = 0; i < (int)lines[k].indices.size() - 1; i++) {
for (j = 0; j < (int)lines[k].indices.size() - 1; j++) {
uint32_t key = k.hash() ^ i ^ r.hash() ^ j ^
2147483137;
uint32_t key2 = r.hash() ^ j ^ k.hash() ^ i ^
2147463167;
if (checks.find(key) == checks.end() &&
checks.find(key2) == checks.end()) {
int idx_a1 = rld->lines[k].indices[i];
int idx_a2 =
rld->lines[k].indices[i + 1];
int idx_b1 = rld->lines[k].indices[j];
int idx_b2 =
rld->lines[k].indices[j + 1];
int idx_a1 = lines[k].indices[i];
int idx_a2 = lines[k].indices[i + 1];
int idx_b1 = lines[k].indices[j];
int idx_b2 = lines[k].indices[j + 1];
std::vector<int> cmp1 = { idx_a1,
idx_a2 };
if (std::find(cmp1.begin(), cmp1.end(),
@@ -419,16 +409,16 @@ void RoadLinesData::update_road_lines_nodes(
int nidx = road_lines_nodes.size();
road_lines_nodes.push_back(pxt);
// int il = (int)road_lines[k].indices.size();
assert(std::find(rld->lines[k].indices.begin(),
rld->lines[k].indices.end(),
nidx) == rld->lines[k].indices.end());
assert(std::find(rld->lines[r].indices.begin(),
rld->lines[r].indices.end(),
nidx) == rld->lines[r].indices.end());
rld->lines[k].indices.insert(
rld->lines[k].indices.begin() + i + 1, nidx);
rld->lines[r].indices.insert(
rld->lines[k].indices.begin() + j + 1, nidx);
assert(std::find(lines[k].indices.begin(),
lines[k].indices.end(),
nidx) == lines[k].indices.end());
assert(std::find(lines[r].indices.begin(),
lines[r].indices.end(),
nidx) == lines[r].indices.end());
lines[k].indices.insert(
lines[k].indices.begin() + i + 1, nidx);
lines[r].indices.insert(
lines[k].indices.begin() + j + 1, nidx);
}
}
}
@@ -436,12 +426,11 @@ void RoadLinesData::dump_road_lines(const std::vector<Vector3> &road_lines_nodes
{
int i;
List<String> keys;
RoadLinesData *rld = RoadLinesData::get_singleton();
rld->get_road_lines_key_list(&keys);
get_road_lines_key_list(&keys);
List<String>::Element *e = keys.front();
while (e) {
String rkey = e->get();
struct RoadLinesData::road_line &pt = rld->lines[rkey];
struct RoadLinesData::road_line &pt = lines[rkey];
String outline = rkey + ": ";
for (i = 0; i < (int)pt.indices.size(); i++) {
outline += " " + itos(pt.indices[i]);
@@ -453,7 +442,6 @@ void RoadLinesData::dump_road_lines(const std::vector<Vector3> &road_lines_nodes
e = e->next();
}
}
ImmediateGeometry *RoadLinesData::get_debug_node()
{
if (!debug_im) {
@@ -474,7 +462,6 @@ ImmediateGeometry *RoadLinesData::get_debug_node()
}
return debug_im;
}
void RoadLinesData::process_lines(
std::unordered_map<uint32_t, std::vector<Vector3> >
&road_lines_nodes_hash,
@@ -485,13 +472,181 @@ void RoadLinesData::process_lines(
update_road_lines_nodes(road_lines_nodes);
dump_road_lines(road_lines_nodes);
}
void RoadLinesData::set_debug_flags(int debug_flags)
{
this->debug_flags = debug_flags;
}
int RoadLinesData::get_debug_flags() const
{
return debug_flags;
}
void RoadLinesData::update_line_segments(const String &line)
{
int i;
lines[line].segments.clear();
lines[line].segments.resize(lines[line].points.size() - 1);
float offset = 0.0f;
for (i = 0; i < (int)lines[line].points.size() - 1; i++) {
struct line_segment segment;
segment.p1 = lines[line].points[i].origin;
segment.p2 = lines[line].points[i + 1].origin;
segment.length = segment.p1.distance_to(segment.p2);
segment.dir = (segment.p2 - segment.p1).normalized();
Vector3 side = segment.dir.cross(Vector3(0, 1, 0));
side.y = 0;
segment.tangent = side.normalized();
segment.offset = offset;
lines[line].segments[i] = segment;
offset += segment.length;
}
}
void RoadLinesData::line_add_building(const String &line, const String &key,
float curve_offset, float normal_offset)
{
int index = BuildingsData::get_singleton()->get_building_by_key(key);
if (index < 0)
return;
struct line_building_data lb;
lb.building_key = key;
lb.building_key_hash = key.hash64();
lb.line_offset = curve_offset;
lb.normal_offset = normal_offset;
lines[line].buildings.push_back(lb);
// TODO: save/load
BuildingsData::get_singleton()->buildings[index].line_name = line;
}
void RoadLinesData::assign_close_buildings(const String &line)
{
int i, j;
print_line("assign_close_buildings: " + line);
if (!lines.has(line))
return;
if (!line.ends_with("_buildings"))
return;
if (lines[line].points.size() < 2)
return;
update_line_segments(line);
if (lines[line].segments.size() == 0)
return;
print_line("assign_close_buildings: processing: " +
itos(BuildingsData::get_singleton()->buildings.size()) +
" buildings");
for (i = 0; i < (int)BuildingsData::get_singleton()->buildings.size();
i++) {
float dst = Math_INF;
float result_offset = 0.0f;
float side = 0.0f;
String building_key;
struct BuildingsData::building &data =
BuildingsData::get_singleton()->buildings[i];
// manually placed
if (!data.generated)
continue;
// already assigned to another line
const String &building_line =
BuildingsData::get_singleton()->buildings[i].line_name;
if (building_line != line && building_line != "")
continue;
if (line_has_building(line, data.key))
continue;
Vector3 p = data.xform.origin;
Vector3 segment_point;
int segment_index = -1;
for (j = 0; j < (int)lines[line].segments.size(); j++) {
Vector3 seg[] = { lines[line].segments[j].p1,
lines[line].segments[j].p2 };
Vector3 closest =
Geometry::get_closest_point_to_segment(p, seg);
Vector3 xp = p;
xp.y = p.y;
float tmpdst = xp.distance_squared_to(closest);
if (closest.is_equal_approx(
lines[line].segments[j].p1) ||
closest.is_equal_approx(
lines[line].segments[j].p2)) {
float w = closest.dot(
lines[line].segments[j].dir);
float wt = xp.dot(lines[line].segments[j].dir);
if (wt - w > 0.1f || wt - w < -0.1f)
continue;
}
if (dst > tmpdst) {
dst = tmpdst;
building_key = data.key;
segment_index = j;
segment_point = closest;
}
}
if (segment_index < 0)
continue;
const Vector3 &p1 = lines[line].segments[segment_index].p1;
const Vector3 &p2 = lines[line].segments[segment_index].p2;
const Vector3 &dir = lines[line].segments[segment_index].dir;
assert(segment_index >= 0);
// assert(!segment_point.is_equal_approx(p1));
// assert(!segment_point.is_equal_approx(p2));
assert((segment_point - p1).dot(dir) >= 0);
float wdst = (p - p1).dot(dir);
print_line("wdst=" + String::num(wdst));
assert(wdst >= 0);
result_offset =
lines[line].segments[segment_index].offset + wdst;
side = (p - p1).dot(lines[line].segments[j].tangent);
assert(result_offset >= 0);
print_line("key: " + building_key +
" dst: " + String::num(dst));
if (dst < 16 * 16) {
print_line("adding: key: " + building_key +
" dst: " + String::num(dst));
assert(result_offset >= 0);
line_add_building(line, building_key, result_offset,
side);
}
}
}
bool RoadLinesData::line_has_building(const String &line,
const String &building_key)
{
uint64_t key_hash = building_key.hash64();
bool ret = false;
int i;
for (i = 0; i < (int)lines[line].buildings.size(); i++)
if (lines[line].buildings[i].building_key_hash == key_hash) {
ret = true;
break;
}
return ret;
}
Vector3 RoadLinesData::get_point_by_offsets(const String &line,
float dir_offset,
float normal_offset)
{
Vector3 ret;
int i;
print_verbose("line: " + line +
" line_offset: " + String::num(dir_offset) +
" normal_offset: " + String::num(normal_offset));
float n_offset = dir_offset;
int selected_segment = 0;
for (i = 0; i < (int)lines[line].segments.size(); i++) {
struct line_segment *segment = &lines[line].segments[i];
if (n_offset < segment->length) {
selected_segment = i;
break;
}
n_offset -= segment->length;
}
ret = lines[line].segments[selected_segment].p1 +
lines[line].segments[selected_segment].dir * n_offset +
lines[line].segments[selected_segment].tangent * normal_offset;
return ret;
}