Refactoring of lines handling
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
#undef NDEBUG
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <core/reference.h>
|
||||
#include <core/io/config_file.h>
|
||||
#include <core/os/file_access.h>
|
||||
#include <core/io/json.h>
|
||||
#include <scene/resources/mesh.h>
|
||||
#include <scene/3d/mesh_instance.h>
|
||||
#include <core/math/transform.h>
|
||||
@@ -16,6 +15,7 @@
|
||||
#include <core/hash_map.h>
|
||||
#include "from_string.h"
|
||||
#include "road_debug.h"
|
||||
#include "road_lines_data.h"
|
||||
#include "road_processing.h"
|
||||
|
||||
struct wedge {
|
||||
@@ -25,13 +25,6 @@ struct wedge {
|
||||
};
|
||||
|
||||
struct RoadLinesProcessing {
|
||||
struct road_line {
|
||||
std::vector<Transform> points;
|
||||
std::vector<int> indices;
|
||||
int lanes;
|
||||
int flags;
|
||||
};
|
||||
HashMap<String, struct road_line> road_lines;
|
||||
std::vector<Vector3> nodes;
|
||||
struct edgedata {
|
||||
std::vector<int> neighbors;
|
||||
@@ -52,284 +45,6 @@ struct RoadLinesProcessing {
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
uint32_t road_lines_hash(const Vector3 &v)
|
||||
{
|
||||
int x = (int)(v.x / 100);
|
||||
int y = (int)(v.y / 100);
|
||||
int z = (int)(v.z / 100);
|
||||
return x ^ (y * 100) ^ (z * 10000);
|
||||
}
|
||||
void create_segments(const String &road, std::vector<int> &segments)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int)road_lines[road].indices.size() - 1; i++) {
|
||||
int idx1 = road_lines[road].indices[i];
|
||||
int idx2 = road_lines[road].indices[i + 1];
|
||||
segments.push_back(idx1);
|
||||
segments.push_back(idx2);
|
||||
segments.push_back(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void road_lines_curve_index(
|
||||
struct road_line &rline,
|
||||
std::unordered_map<uint32_t, std::vector<Vector3> >
|
||||
&road_lines_nodes_hash,
|
||||
std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
int i, j;
|
||||
rline.indices.clear();
|
||||
for (i = 0; i < (int)rline.points.size(); i++) {
|
||||
Vector3 pt = rline.points[i].origin;
|
||||
int pt_hash = road_lines_hash(pt);
|
||||
if (road_lines_nodes_hash.find(pt_hash) !=
|
||||
road_lines_nodes_hash.end()) {
|
||||
bool ok = true;
|
||||
for (j = 0;
|
||||
j <
|
||||
(int)road_lines_nodes_hash[pt_hash].size();
|
||||
j++) {
|
||||
const Vector3 &xpt =
|
||||
road_lines_nodes_hash[pt_hash]
|
||||
[j];
|
||||
if (xpt.distance_squared_to(pt) < 160) {
|
||||
ok = false;
|
||||
pt = xpt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
road_lines_nodes_hash[pt_hash].push_back(
|
||||
pt);
|
||||
road_lines_nodes.push_back(pt);
|
||||
}
|
||||
} else {
|
||||
road_lines_nodes.push_back(pt);
|
||||
road_lines_nodes_hash[pt_hash] = { pt };
|
||||
}
|
||||
std::vector<Vector3>::iterator it =
|
||||
std::find(road_lines_nodes.begin(),
|
||||
road_lines_nodes.end(), pt);
|
||||
assert(it != road_lines_nodes.end());
|
||||
int index = it - road_lines_nodes.begin();
|
||||
rline.indices.push_back(index);
|
||||
}
|
||||
}
|
||||
void index_lines(std::unordered_map<uint32_t, std::vector<Vector3> >
|
||||
&road_lines_nodes_hash,
|
||||
std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
List<String> keys;
|
||||
road_lines.get_key_list(&keys);
|
||||
List<String>::Element *e = keys.front();
|
||||
while (e) {
|
||||
String rkey = e->get();
|
||||
struct road_line &pt = road_lines[rkey];
|
||||
pt.indices.clear();
|
||||
e = e->next();
|
||||
}
|
||||
e = keys.front();
|
||||
while (e) {
|
||||
String rkey = e->get();
|
||||
struct road_line &pt = road_lines[rkey];
|
||||
road_lines_curve_index(pt, road_lines_nodes_hash,
|
||||
road_lines_nodes);
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
/* add close points on each line to the line */
|
||||
void insert_close_points(std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
int i;
|
||||
List<String> keys;
|
||||
road_lines.get_key_list(&keys);
|
||||
List<String>::Element *e = keys.front();
|
||||
for (i = 0; i < (int)road_lines_nodes.size(); i++) {
|
||||
int idx3 = i;
|
||||
while (e) {
|
||||
int j;
|
||||
std::vector<int> segments;
|
||||
String rkey = e->get();
|
||||
create_segments(rkey, segments);
|
||||
for (j = 0; j < (int)segments.size(); j += 3) {
|
||||
int idx1 = segments[j];
|
||||
int idx2 = segments[j + 1];
|
||||
int idx = segments[j + 2];
|
||||
/* Skip segment point */
|
||||
if (idx3 == idx1 || idx3 == idx2)
|
||||
continue;
|
||||
Vector3 p1 = road_lines_nodes[idx1];
|
||||
Vector3 p2 = road_lines_nodes[idx2];
|
||||
Vector3 p3 = road_lines_nodes[idx3];
|
||||
std::vector<Vector3> seg = { p1, p2 };
|
||||
Vector3 closest = Geometry::
|
||||
get_closest_point_to_segment(
|
||||
p3, seg.data());
|
||||
if (p3.distance_squared_to(closest) <
|
||||
160) {
|
||||
road_lines_nodes[idx3] =
|
||||
closest;
|
||||
road_lines[rkey].indices.insert(
|
||||
road_lines[rkey].indices
|
||||
.begin() +
|
||||
idx,
|
||||
idx3);
|
||||
}
|
||||
}
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
void update_road_lines_nodes(std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
List<String> keys;
|
||||
|
||||
road_lines.get_key_list(&keys);
|
||||
std::unordered_map<uint32_t, std::tuple<String, String> > kcmp;
|
||||
{
|
||||
List<String>::Element *k = keys.front();
|
||||
List<String>::Element *r = keys.front();
|
||||
while (k) {
|
||||
String kkey = k->get();
|
||||
uint32_t kkey_hash = kkey.hash();
|
||||
while (r) {
|
||||
String rkey = r->get();
|
||||
uint32_t rkey_hash = rkey.hash();
|
||||
uint32_t key = kkey_hash ^ rkey_hash;
|
||||
uint32_t key2 = rkey_hash ^ kkey_hash;
|
||||
if (kcmp.find(key) == kcmp.end() &&
|
||||
kcmp.find(key2) == kcmp.end())
|
||||
kcmp[key] = std::make_tuple(
|
||||
k->get(), r->get());
|
||||
r = r->next();
|
||||
}
|
||||
k = k->next();
|
||||
}
|
||||
}
|
||||
using checks_tuple =
|
||||
std::tuple<String, int, int, int, String, int, int, int>;
|
||||
std::unordered_map<uint32_t, checks_tuple> checks;
|
||||
std::unordered_map<uint32_t, checks_tuple>::iterator checks_it;
|
||||
std::unordered_map<uint32_t,
|
||||
std::tuple<String, String> >::iterator it;
|
||||
for (it = kcmp.begin(); it != kcmp.end(); it++) {
|
||||
int i, j;
|
||||
std::tuple<String, String> data = kcmp[it->first];
|
||||
const String &k = std::get<0>(data);
|
||||
const String &r = std::get<1>(data);
|
||||
if (road_lines[k].indices.size() < 2)
|
||||
continue;
|
||||
if (road_lines[r].indices.size() < 2)
|
||||
continue;
|
||||
for (i = 0; i < (int)road_lines[k].indices.size() - 1;
|
||||
i++) {
|
||||
for (j = 0;
|
||||
j < (int)road_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 =
|
||||
road_lines[k].indices[i];
|
||||
int idx_a2 =
|
||||
road_lines[k]
|
||||
.indices[i + 1];
|
||||
int idx_b1 =
|
||||
road_lines[k].indices[j];
|
||||
int idx_b2 =
|
||||
road_lines[k]
|
||||
.indices[j + 1];
|
||||
std::vector<int> cmp1 = {
|
||||
idx_a1, idx_a2
|
||||
};
|
||||
if (std::find(cmp1.begin(),
|
||||
cmp1.end(),
|
||||
idx_b1) !=
|
||||
cmp1.end())
|
||||
continue;
|
||||
if (std::find(cmp1.begin(),
|
||||
cmp1.end(),
|
||||
idx_b2) !=
|
||||
cmp1.end())
|
||||
continue;
|
||||
checks[key] = std::make_tuple(
|
||||
k, i, idx_a1, idx_a2, r,
|
||||
j, idx_b1, idx_b2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
for ch in checks.values():
|
||||
var k = ch[0]
|
||||
var i1 = ch[1]
|
||||
var idx_a1 = ch[2]
|
||||
var idx_a2 = ch[3]
|
||||
var r = ch[4]
|
||||
var j1 = ch[5]
|
||||
var idx_b1 = ch[6]
|
||||
var idx_b2 = ch[7]
|
||||
var p_a1 = road_lines_nodes[idx_a1]
|
||||
var p_a2 = road_lines_nodes[idx_a2]
|
||||
var p_b1 = road_lines_nodes[idx_b1]
|
||||
var p_b2 = road_lines_nodes[idx_b2]
|
||||
var px = Geometry.get_closest_points_between_segments(p_a1, p_a2, p_b1, p_b2)
|
||||
var d = px[0].distance_squared_to(px[1])
|
||||
if d < 160:
|
||||
var pxt = px[0].linear_interpolate(px[1], 0.5)
|
||||
var nidx = road_lines_nodes.size()
|
||||
road_lines_nodes.push_back(pxt)
|
||||
var il = road_lines[k].indices.size()
|
||||
assert(!nidx in road_lines[k].indices)
|
||||
assert(!nidx in road_lines[r].indices)
|
||||
road_lines[k].indices.insert(i1 + 1, nidx)
|
||||
road_lines[r].indices.insert(j1 + 1, nidx)
|
||||
##end
|
||||
*/
|
||||
for (checks_it = checks.begin(); checks_it != checks.end();
|
||||
checks_it++) {
|
||||
String k = std::get<0>(checks_it->second);
|
||||
int i = std::get<1>(checks_it->second);
|
||||
int idx_a1 = std::get<2>(checks_it->second);
|
||||
int idx_a2 = std::get<3>(checks_it->second);
|
||||
String r = std::get<4>(checks_it->second);
|
||||
int j = std::get<5>(checks_it->second);
|
||||
int idx_b1 = std::get<6>(checks_it->second);
|
||||
int idx_b2 = std::get<7>(checks_it->second);
|
||||
Vector3 p_a1 = road_lines_nodes[idx_a1];
|
||||
Vector3 p_a2 = road_lines_nodes[idx_a2];
|
||||
Vector3 p_b1 = road_lines_nodes[idx_b1];
|
||||
Vector3 p_b2 = road_lines_nodes[idx_b2];
|
||||
Vector3 px, px2;
|
||||
Geometry::get_closest_points_between_segments(
|
||||
p_a1, p_a2, p_b1, p_b2, px, px2);
|
||||
float d = px.distance_squared_to(px2);
|
||||
if (d < 160) {
|
||||
Vector3 pxt = px.linear_interpolate(px2, 0.5f);
|
||||
int nidx = road_lines_nodes.size();
|
||||
road_lines_nodes.push_back(pxt);
|
||||
// int il = (int)road_lines[k].indices.size();
|
||||
assert(std::find(road_lines[k].indices.begin(),
|
||||
road_lines[k].indices.end(),
|
||||
nidx) ==
|
||||
road_lines[k].indices.end());
|
||||
assert(std::find(road_lines[r].indices.begin(),
|
||||
road_lines[r].indices.end(),
|
||||
nidx) ==
|
||||
road_lines[r].indices.end());
|
||||
road_lines[k].indices.insert(
|
||||
road_lines[k].indices.begin() + i + 1,
|
||||
nidx);
|
||||
road_lines[r].indices.insert(
|
||||
road_lines[k].indices.begin() + j + 1,
|
||||
nidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
void create_nodes(const std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
nodes.resize(road_lines_nodes.size());
|
||||
@@ -340,18 +55,19 @@ struct RoadLinesProcessing {
|
||||
{
|
||||
int i;
|
||||
List<String> keys;
|
||||
road_lines.get_key_list(&keys);
|
||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||
rld->get_road_lines_key_list(&keys);
|
||||
List<String>::Element *e = keys.front();
|
||||
while (e) {
|
||||
const String &key = e->get();
|
||||
if (road_lines[key].indices.size() < 2) {
|
||||
if (rld->lines[key].indices.size() < 2) {
|
||||
e = e->next();
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < (int)road_lines[key].indices.size() - 1;
|
||||
for (i = 0; i < (int)rld->lines[key].indices.size() - 1;
|
||||
i++) {
|
||||
int idx1 = road_lines[key].indices[i];
|
||||
int idx2 = road_lines[key].indices[i + 1];
|
||||
int idx1 = rld->lines[key].indices[i];
|
||||
int idx2 = rld->lines[key].indices[i + 1];
|
||||
if (edges.find(idx1) == edges.end()) {
|
||||
struct edgedata ed;
|
||||
ed.neighbors.clear();
|
||||
@@ -458,27 +174,6 @@ struct RoadLinesProcessing {
|
||||
}
|
||||
}
|
||||
}
|
||||
void dump_lines(const std::vector<Vector3> &road_lines_nodes)
|
||||
{
|
||||
int i;
|
||||
List<String> keys;
|
||||
road_lines.get_key_list(&keys);
|
||||
List<String>::Element *e = keys.front();
|
||||
while (e) {
|
||||
String rkey = e->get();
|
||||
struct road_line &pt = road_lines[rkey];
|
||||
String outline = rkey + ": ";
|
||||
for (i = 0; i < (int)pt.indices.size(); i++) {
|
||||
outline += " " + itos(pt.indices[i]);
|
||||
}
|
||||
for (i = 0; i < (int)pt.indices.size(); i++) {
|
||||
outline +=
|
||||
" " + (road_lines_nodes[pt.indices[i]]
|
||||
.operator String());
|
||||
}
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
~RoadLinesProcessing()
|
||||
{
|
||||
}
|
||||
@@ -489,68 +184,21 @@ struct RoadLinesProcessing {
|
||||
singleton = nullptr;
|
||||
}
|
||||
}
|
||||
void road_setup(Node *base);
|
||||
void read_road_lines_json(const String &road_lines_path);
|
||||
};
|
||||
void RoadLinesProcessing::road_setup(Node *base)
|
||||
{
|
||||
std::vector<Vector3> road_lines_nodes;
|
||||
std::unordered_map<uint32_t, std::vector<Vector3> >
|
||||
road_lines_nodes_hash;
|
||||
road_lines_nodes.clear();
|
||||
road_lines_nodes_hash.clear();
|
||||
index_lines(road_lines_nodes_hash, road_lines_nodes);
|
||||
insert_close_points(road_lines_nodes);
|
||||
update_road_lines_nodes(road_lines_nodes);
|
||||
dump_lines(road_lines_nodes);
|
||||
create_nodes(road_lines_nodes);
|
||||
create_edges();
|
||||
build_wedges(wedges);
|
||||
print_line("ROAD SETUP DONE");
|
||||
}
|
||||
void RoadLinesProcessing::read_road_lines_json(const String &road_lines_path)
|
||||
{
|
||||
int i;
|
||||
String road_lines_json =
|
||||
FileAccess::get_file_as_string(road_lines_path);
|
||||
Variant json_v;
|
||||
String es;
|
||||
int eline;
|
||||
Error status = JSON::parse(road_lines_json, json_v, es, eline);
|
||||
ERR_FAIL_COND_MSG(status != OK, "Can't parse json: " + es +
|
||||
" at line: " + itos(eline));
|
||||
|
||||
Dictionary json = json_v;
|
||||
List<Variant> keys;
|
||||
json.get_key_list(&keys);
|
||||
List<Variant>::Element *e = keys.front();
|
||||
while (e) {
|
||||
String key = e->get();
|
||||
if (!key.ends_with("_road")) {
|
||||
e = e->next();
|
||||
continue;
|
||||
}
|
||||
struct road_line rline;
|
||||
Array points = json[key].get("points");
|
||||
Array indices = json[key].get("indices");
|
||||
int lanes = json[key].get("lanes");
|
||||
rline.points.resize(points.size());
|
||||
rline.indices.resize(indices.size());
|
||||
for (i = 0; i < (int)points.size(); i++) {
|
||||
String point_s = points[i];
|
||||
rline.points[i] = from_string<Transform>(point_s);
|
||||
}
|
||||
for (i = 0; i < (int)indices.size(); i++) {
|
||||
int index = indices[i];
|
||||
rline.indices[i] = index;
|
||||
}
|
||||
// TODO: wtf is flags?
|
||||
rline.lanes = lanes;
|
||||
road_lines[key] = rline;
|
||||
e = e->next();
|
||||
void road_setup(Node *base)
|
||||
{
|
||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||
std::vector<Vector3> road_lines_nodes;
|
||||
std::unordered_map<uint32_t, std::vector<Vector3> >
|
||||
road_lines_nodes_hash;
|
||||
road_lines_nodes.clear();
|
||||
road_lines_nodes_hash.clear();
|
||||
rld->process_lines(road_lines_nodes_hash, road_lines_nodes);
|
||||
create_nodes(road_lines_nodes);
|
||||
create_edges();
|
||||
build_wedges(wedges);
|
||||
print_line("ROAD SETUP DONE");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
RoadLinesProcessing *RoadLinesProcessing::singleton;
|
||||
|
||||
class RoadMeshProcessing {
|
||||
@@ -571,6 +219,7 @@ class RoadMeshProcessing {
|
||||
}
|
||||
};
|
||||
HashMap<String, struct mesh_data> road_meshes;
|
||||
std::vector<MeshInstance *> nodes_mi;
|
||||
|
||||
public:
|
||||
void load_road_mesh(const String &category, const String &name,
|
||||
@@ -936,6 +585,9 @@ public:
|
||||
{
|
||||
int i;
|
||||
RoadLinesProcessing *r = RoadLinesProcessing::get_singleton();
|
||||
for (i = 0; i < (int)nodes_mi.size(); i++)
|
||||
nodes_mi[i]->queue_delete();
|
||||
nodes_mi.clear();
|
||||
for (i = 0; i < (int)r->nodes.size(); i++) {
|
||||
Ref<ArrayMesh> mesh =
|
||||
build_road(r->wedges[i], "common/center",
|
||||
@@ -947,6 +599,7 @@ public:
|
||||
base->call_deferred("add_child", mi);
|
||||
mi->set_transform(xform);
|
||||
mi->call_deferred("show");
|
||||
nodes_mi.push_back(mi);
|
||||
}
|
||||
}
|
||||
static RoadMeshProcessing *singleton;
|
||||
@@ -978,12 +631,11 @@ void RoadProcessing::road_setup(Node *target)
|
||||
|
||||
void RoadProcessing::load_data()
|
||||
{
|
||||
/* Not needed but still */
|
||||
RoadLinesData::get_singleton();
|
||||
ConfigFile config;
|
||||
Error result = config.load("res://config/stream.conf");
|
||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||
String road_lines_path = config.get_value("lines", "road_lines_path");
|
||||
RoadLinesProcessing::get_singleton()->read_road_lines_json(
|
||||
road_lines_path);
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
"common", "center", config.get_value("road", "center_mesh"));
|
||||
RoadMeshProcessing::get_singleton()->load_road_mesh(
|
||||
@@ -1096,4 +748,4 @@ void RoadProcessing::cleanup()
|
||||
{
|
||||
RoadLinesProcessing::cleanup();
|
||||
RoadMeshProcessing::cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user