Propagated side to wedge

This commit is contained in:
2025-02-15 01:30:31 +03:00
parent 2eed8ef509
commit 66838892d5
27 changed files with 4444 additions and 589 deletions

View File

@@ -20,6 +20,9 @@
struct CLine {
struct RoadLinesData::road_line line;
};
struct CLineIndex {
struct RoadLinesData::road_line_index index;
};
class LinesAccessor {
public:
@@ -121,17 +124,6 @@ public:
struct CLine *cl = e.get_mut<CLine>();
cl->line.points[index].origin = position;
}
inline void clear_all_line_indices()
{
BaseData::get_singleton()->get_singleton()->get().each(
[](CLine &cl) { cl.line.indices.clear(); });
}
inline void clear_line_indices(const String &key)
{
flecs::entity e = lookup(key);
struct CLine *cl = e.get_mut<CLine>();
cl->line.indices.clear();
}
inline int get_line_points_count(const String &key) const
{
flecs::entity e = lookup(key);
@@ -145,18 +137,6 @@ public:
const struct CLine *cl = e.get<CLine>();
return cl->line.points[index].origin;
}
inline void add_line_index(const String &key, int id)
{
flecs::entity e = lookup(key);
struct CLine *cl = e.get_mut<CLine>();
cl->line.indices.push_back(id);
}
inline void insert_line_index(const String &key, int index, int id)
{
flecs::entity e = lookup(key);
struct CLine *cl = e.get_mut<CLine>();
cl->line.indices.insert(cl->line.indices.begin() + index, id);
}
inline void clear_line_segments(const String &key)
{
flecs::entity e = lookup(key);
@@ -224,7 +204,82 @@ public:
}
};
class IndexAccessor {
public:
IndexAccessor()
{
BaseData::get_singleton()->get().component<CLineIndex>();
}
inline const struct RoadLinesData::road_line_index &
operator[](const String &key) const
{
flecs::entity e = lookup(key);
const struct CLineIndex *cl = e.get<CLineIndex>();
return cl->index;
}
const flecs::world &get() const
{
return BaseData::get_singleton()->get();
}
flecs::world &get()
{
return BaseData::get_singleton()->get();
}
template <typename F> void each(F &&func) const
{
get().each<F>(func);
}
inline flecs::entity lookup(const String &key) const
{
String ename = "line:" + key;
flecs::entity e = get().lookup(ename.ascii().ptr());
if (!e.is_valid())
print_line("can't find: " + key);
assert(e.is_valid());
return e;
}
inline void clear_all_line_indices()
{
BaseData::get_singleton()->get_singleton()->get().each(
[](CLineIndex &cl) { cl.index.indices.clear(); });
}
inline void clear_line_indices(const String &key)
{
flecs::entity e = lookup(key);
struct CLineIndex *cl = e.get_mut<CLineIndex>();
assert(cl);
cl->index.indices.clear();
}
inline void add_line_index(const String &key, int id)
{
flecs::entity e = lookup(key);
struct CLineIndex *cl = e.get_mut<CLineIndex>();
cl->index.indices.push_back(id);
}
inline void insert_line_index(const String &key, int index, int id)
{
flecs::entity e = lookup(key);
struct CLineIndex *cl = e.get_mut<CLineIndex>();
cl->index.indices.insert(cl->index.indices.begin() + index, id);
}
inline void
set_index(const String &key,
const struct RoadLinesData::road_line_index &index)
{
flecs::entity e = lookup_create(key);
e.set<CLineIndex>({ index });
}
inline flecs::entity lookup_create(const String &key) const
{
String ename = "line:" + key;
flecs::entity e = get().entity(ename.ascii().ptr());
assert(e.is_valid());
return e;
}
};
static LinesAccessor lines;
static IndexAccessor indices;
ImmediateGeometry *RoadLinesData::debug_im = nullptr;
static Ref<Material> debug_material;
@@ -243,6 +298,11 @@ const RoadLinesData::road_line &RoadLinesData::lines(const String &key) const
{
return ::lines[key];
}
const RoadLinesData::road_line_index &
RoadLinesData::indices(const String &key) const
{
return ::indices[key];
}
void RoadLinesData::set_line(const String &key, const road_line &line)
{
::lines.set_line(key, line);
@@ -267,11 +327,11 @@ void RoadLinesData::set_line_point_position(const String &key, int index,
}
void RoadLinesData::clear_all_line_indices()
{
::lines.clear_all_line_indices();
::indices.clear_all_line_indices();
}
void RoadLinesData::clear_line_indices(const String &key)
{
::lines.clear_line_indices(key);
::indices.clear_line_indices(key);
}
void RoadLinesData::set_line_metadata(const String &key,
const Dictionary &metadata)
@@ -366,7 +426,6 @@ void RoadLinesData::load_data()
rline.pattern = pattern;
rline.points.resize(points.size());
rline.edges.resize(edges.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);
@@ -375,13 +434,11 @@ void RoadLinesData::load_data()
const Dictionary &d = edges[i];
rline.edges[i].from_dict(rline.edges[i], d);
}
for (i = 0; i < (int)indices.size(); i++) {
int index = indices[i];
rline.indices[i] = index;
}
// TODO: wtf is flags?
rline.lanes = lanes;
set_line(key, rline);
RoadLinesData::road_line_index index;
::indices.set_index(key, index);
e = e->next();
}
{
@@ -414,9 +471,10 @@ void RoadLinesData::save_data()
points[i] = to_string(lines(e->get()).points[i]);
for (i = 0; i < (int)lines(e->get()).edges.size(); i++)
edges[i] = lines(e->get()).edges[i].to_dict();
indices.resize(lines(e->get()).indices.size());
for (i = 0; i < (int)lines(e->get()).indices.size(); i++)
indices[i] = lines(e->get()).indices[i];
indices.resize(this->indices(e->get()).indices.size());
for (i = 0; i < (int)this->indices(e->get()).indices.size();
i++)
indices[i] = this->indices(e->get()).indices[i];
pvalues["points"] = points;
pvalues["edges"] = edges;
// pvalues["indices"] = indices;
@@ -488,7 +546,7 @@ void RoadLinesData::road_lines_curve_index(
std::vector<Vector3> &road_lines_nodes)
{
int i, j;
::lines.clear_line_indices(key);
::indices.clear_line_indices(key);
for (i = 0; i < (int)::lines.get_line_points_count(key); i++) {
Vector3 pt = ::lines.get_line_point_position(key, i);
int pt_hash = road_lines_hash(pt);
@@ -518,7 +576,7 @@ void RoadLinesData::road_lines_curve_index(
road_lines_nodes.begin(), road_lines_nodes.end(), pt);
assert(it != road_lines_nodes.end());
int index = it - road_lines_nodes.begin();
::lines.add_line_index(key, index);
::indices.add_line_index(key, index);
}
}
void RoadLinesData::index_lines(
@@ -545,19 +603,20 @@ void RoadLinesData::index_lines(
static inline int get_segment_index(const String &road, int pos)
{
RoadLinesData *rld = RoadLinesData::get_singleton();
int idx = rld->get_line(road).indices[pos];
int idx = rld->indices(road).indices[pos];
return idx;
}
void RoadLinesData::create_segments(const String &road,
std::vector<int> &segments)
{
int i;
for (i = 0; i < (int)::lines[road].indices.size() - 1; i++) {
for (i = 0; i < (int)::indices[road].indices.size() - 1; i++) {
segments.push_back(i);
segments.push_back(i + 1);
}
}
/* add close points on each line to the line */
// FIXME: used?
void RoadLinesData::insert_close_points(std::vector<Vector3> &road_lines_nodes,
float distance_squared)
{
@@ -602,8 +661,8 @@ void RoadLinesData::insert_close_points(std::vector<Vector3> &road_lines_nodes,
distance_squared) {
/* split segment and replace road
point with a point on segment */
::lines.insert_line_index(rkey, idx,
idx3);
::indices.insert_line_index(rkey, idx,
idx3);
road_lines_nodes[idx3] = closest;
}
}
@@ -648,12 +707,12 @@ 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 (::lines[k].indices.size() < 2)
if (::indices[k].indices.size() < 2)
continue;
if (::lines[r].indices.size() < 2)
if (::indices[r].indices.size() < 2)
continue;
for (i = 0; i < (int)::lines[k].indices.size() - 1; i++) {
for (j = 0; j < (int)::lines[k].indices.size() - 1;
for (i = 0; i < (int)::indices[k].indices.size() - 1; i++) {
for (j = 0; j < (int)::indices[k].indices.size() - 1;
j++) {
uint32_t key = k.hash() ^ i ^ r.hash() ^ j ^
2147483137;
@@ -661,10 +720,12 @@ void RoadLinesData::update_road_lines_nodes(
2147463167;
if (checks.find(key) == checks.end() &&
checks.find(key2) == checks.end()) {
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];
int idx_a1 = ::indices[k].indices[i];
int idx_a2 =
::indices[k].indices[i + 1];
int idx_b1 = ::indices[k].indices[j];
int idx_b2 =
::indices[k].indices[j + 1];
std::vector<int> cmp1 = { idx_a1,
idx_a2 };
if (std::find(cmp1.begin(), cmp1.end(),
@@ -730,14 +791,14 @@ 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(::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.insert_line_index(k, i + 1, nidx);
::lines.insert_line_index(r, j + 1, nidx);
assert(std::find(::indices[k].indices.begin(),
::indices[k].indices.end(),
nidx) == ::indices[k].indices.end());
assert(std::find(::indices[r].indices.begin(),
::indices[r].indices.end(),
nidx) == ::indices[r].indices.end());
::indices.insert_line_index(k, i + 1, nidx);
::indices.insert_line_index(r, j + 1, nidx);
}
}
}

View File

@@ -192,7 +192,6 @@ public:
struct road_line {
std::vector<Transform> points;
std::vector<struct road_edge> edges;
std::vector<int> indices;
std::vector<struct line_segment> segments;
int lanes;
int pattern;
@@ -200,6 +199,9 @@ public:
Dictionary metadata;
_Signal<void> line_updated;
};
struct road_line_index {
std::vector<int> indices;
};
public:
static ImmediateGeometry *get_debug_node();
@@ -210,6 +212,7 @@ private:
public:
const struct road_line &get_line(const String &key) const;
const struct road_line &lines(const String &key) const;
const struct road_line_index &indices(const String &key) const;
void set_line(const String &key, const struct road_line &line);
bool has_line(const String &key);
void insert_line_point(const String &key, int index,

View File

@@ -578,7 +578,6 @@ void RoadLinesEditor::create_new_line_at_cursor(const String &line_name)
RoadLinesData *rld = RoadLinesData::get_singleton();
struct RoadLinesData::road_line rline;
rline.flags = 0;
rline.indices.resize(0);
rline.lanes = -1;
if (line_name.ends_with("_road"))
rline.lanes = 4;
@@ -1197,6 +1196,38 @@ class EdgeEditorHandler {
}
return true;
}
void set_lot(RoadLinesData::road_edge_side &side, const String &pname,
float dir_offt)
{
side.lot_type = pname.replace("lot-", "");
if (side.lot == 0) {
side.lot = 1;
side.lot_offset = get_edge_conf<float>(pname, "left",
"lot_offset");
side.lot_y_rotation = get_edge_conf<float>(
pname, "left", "lot_y_rotation");
side.lot_offset = get_edge_conf<float>(pname, "left",
"lot_offset");
side.lot_dir_offset = dir_offt;
}
}
String get_pname(PopupMenu *menu, int id)
{
String pname;
switch (id) {
case 200:
pname = "clear";
break;
case 201:
pname = "clear-buildings";
break;
default: {
int item_index = menu->get_item_index(id);
pname = menu->get_item_metadata(item_index);
} break;
}
return pname;
}
void event_handler(const String &event, const Vector<Variant> &args)
{
if (event == "road_lines_edge_editor::edit") {
@@ -1234,44 +1265,13 @@ class EdgeEditorHandler {
RoadLinesData *rld = RoadLinesData::get_singleton();
RoadLinesData::road_line rl =
rld->get_line(current_line);
String pname;
switch (id) {
case 200:
pname = "clear";
break;
case 201:
pname = "clear-buildings";
break;
default:
pname = menu->get_item_metadata(item_index);
break;
}
String pname = get_pname(menu, id);
if (pname.begins_with("lot-")) {
rl.edges[index].left.lot_type =
pname.replace("lot-", "");
if (rl.edges[index].left.lot == 0) {
rl.edges[index].left.lot = 1;
rl.edges[index].left.lot_offset =
get_edge_conf<float>(
pname, "left",
"lot_offset");
rl.edges[index].left.lot_y_rotation =
get_edge_conf<float>(
pname, "left",
"lot_y_rotation");
rl.edges[index].left.lot_offset =
get_edge_conf<float>(
pname, "left",
"lot_offset");
float dir_offt =
rl.points[index + 1]
.origin.distance_to(
rl.points[index]
.origin) /
2.0f;
rl.edges[index].left.lot_dir_offset =
dir_offt;
}
float dir_offt =
rl.points[index + 1].origin.distance_to(
rl.points[index].origin) /
2.0f;
set_lot(rl.edges[index].left, pname, dir_offt);
} else if (pname.begins_with("residental-")) {
struct RoadLinesData::road_edge_side::buildings
b;
@@ -1291,17 +1291,20 @@ class EdgeEditorHandler {
->building_aabbs
["lot-" +
lot_id];
pack_buildings(
bool pack_result = pack_buildings(
aabb_lot,
rl.edges[index]
.left.buildings,
2.0f);
assert(pack_result);
}
}
} else if (pname == "clear") {
rl.edges[index].left.lot_type = "";
rl.edges[index].left.lot = 0;
rl.edges[index].left.buildings.clear();
} else if (pname == "clear-buildings") {
rl.edges[index].right.buildings.clear();
}
rld->set_line(current_line, rl);
editor->rebuild_roads();
@@ -1309,47 +1312,16 @@ class EdgeEditorHandler {
PopupMenu *menu = Object::cast_to<PopupMenu>(args[0]);
int id = args[1];
int item_index = menu->get_item_index(id);
String pname;
switch (id) {
case 200:
pname = "clear";
break;
case 201:
pname = "clear-buildings";
break;
default:
pname = menu->get_item_metadata(item_index);
break;
}
String pname = get_pname(menu, id);
RoadLinesData *rld = RoadLinesData::get_singleton();
RoadLinesData::road_line rl =
rld->get_line(current_line);
if (pname.begins_with("lot-")) {
rl.edges[index].right.lot_type =
pname.replace("lot-", "");
if (rl.edges[index].right.lot == 0) {
rl.edges[index].right.lot = 1;
rl.edges[index].right.lot_offset =
get_edge_conf<float>(
pname, "right",
"lot_offset");
rl.edges[index].right.lot_y_rotation =
get_edge_conf<float>(
pname, "right",
"lot_y_rotation");
rl.edges[index].right.lot_offset =
get_edge_conf<float>(
pname, "right",
"lot_offset");
float dir_offt =
rl.points[index + 1]
.origin.distance_to(
rl.points[index]
.origin) /
2.0f;
rl.edges[index].right.lot_dir_offset =
dir_offt;
}
float dir_offt =
rl.points[index + 1].origin.distance_to(
rl.points[index].origin) /
2.0f;
set_lot(rl.edges[index].right, pname, dir_offt);
} else if (pname.begins_with("residental-") ||
pname.begins_with("business-")) {
struct RoadLinesData::road_edge_side::buildings
@@ -1370,17 +1342,20 @@ class EdgeEditorHandler {
->building_aabbs
["lot-" +
lot_id];
pack_buildings(
bool pack_result = pack_buildings(
aabb_lot,
rl.edges[index]
.right.buildings,
2.0f);
assert(pack_result);
}
}
} else if (pname == "clear") {
rl.edges[index].right.lot_type = "";
rl.edges[index].right.lot = 0;
rl.edges[index].right.buildings.clear();
} else if (pname == "clear-buildings") {
rl.edges[index].right.buildings.clear();
}
rld->set_line(current_line, rl);
editor->rebuild_roads();

View File

@@ -24,14 +24,26 @@ struct wedge {
Vector3 p[3];
Vector3 y[3];
int width1, width2;
const RoadLinesData::road_edge_side *side1, *side2;
};
struct RoadLinesProcessing {
std::vector<Vector3> nodes;
struct edgedata {
std::vector<int> neighbors;
RoadLinesData::road_edge_side *side;
};
std::unordered_map<int, struct edgedata> edges;
struct side_hash {
std::size_t operator()(const std::pair<int, int> &key) const
{
return std::hash<int>()(key.first) ^
(std::hash<int>()(key.second) << 8);
}
};
std::unordered_map<std::pair<int, int>,
const RoadLinesData::road_edge_side *, side_hash>
sides;
std::unordered_map<uint32_t, std::vector<struct wedge> > wedges;
String road_center_mesh_path, road_mid_mesh_path,
road_sidewalk_mesh_path;
@@ -386,14 +398,16 @@ out2:;
List<String>::Element *e = keys.front();
while (e) {
const String &key = e->get();
if (rld->lines(key).indices.size() < 2) {
if (rld->indices(key).indices.size() < 2) {
e = e->next();
continue;
}
for (i = 0; i < (int)rld->lines(key).indices.size() - 1;
/* creating neighbor data */
for (i = 0;
i < (int)rld->indices(key).indices.size() - 1;
i++) {
int idx1 = rld->lines(key).indices[i];
int idx2 = rld->lines(key).indices[i + 1];
int idx1 = rld->indices(key).indices[i];
int idx2 = rld->indices(key).indices[i + 1];
if (edges.find(idx1) == edges.end()) {
struct edgedata ed;
ed.neighbors.clear();
@@ -407,13 +421,19 @@ out2:;
if (std::find(edges[idx1].neighbors.begin(),
edges[idx1].neighbors.end(),
idx2) ==
edges[idx1].neighbors.end())
edges[idx1].neighbors.end()) {
edges[idx1].neighbors.push_back(idx2);
sides[{ idx1, idx2 }] =
&rld->lines(key).edges[i].right;
}
if (std::find(edges[idx2].neighbors.begin(),
edges[idx2].neighbors.end(),
idx1) ==
edges[idx2].neighbors.end())
edges[idx2].neighbors.end()) {
edges[idx2].neighbors.push_back(idx1);
sides[{ idx2, idx1 }] =
&rld->lines(key).edges[i].left;
}
}
e = e->next();
}
@@ -476,6 +496,10 @@ out2:;
}
}
if (dst <= maxdst * maxdst) {
/* split edge too close to other node
replace node's position with point on the edge
we don't create any new nodes here, only new edges.
*/
nodes[k] = np;
edges[n2].neighbors.erase(std::remove(
edges[n2].neighbors.begin(),
@@ -485,20 +509,30 @@ out2:;
edges[n1].neighbors.end(), n2));
if (std::find(edges[k].neighbors.begin(),
edges[k].neighbors.end(),
n1) == edges[k].neighbors.end())
n1) == edges[k].neighbors.end()) {
edges[k].neighbors.push_back(n1);
assert(sides.find({ n2, n1 }) !=
sides.end());
sides[{ k, n1 }] = sides[{ n2, n1 }];
}
if (std::find(edges[k].neighbors.begin(),
edges[k].neighbors.end(),
n2) == edges[k].neighbors.end())
n2) == edges[k].neighbors.end()) {
edges[k].neighbors.push_back(n2);
sides[{ k, n2 }] = sides[{ n1, n2 }];
}
if (std::find(edges[n1].neighbors.begin(),
edges[n1].neighbors.end(),
k) == edges[n1].neighbors.end())
k) == edges[n1].neighbors.end()) {
edges[n1].neighbors.push_back(k);
sides[{ n1, k }] = sides[{ n1, n2 }];
}
if (std::find(edges[n2].neighbors.begin(),
edges[n2].neighbors.end(),
k) == edges[n2].neighbors.end())
k) == edges[n2].neighbors.end()) {
edges[n2].neighbors.push_back(k);
sides[{ n2, k }] = sides[{ n2, n1 }];
}
print_verbose("FIXED: " + itos(k) + ": " +
String::num(dst));
}
@@ -536,7 +570,20 @@ out2:;
for (j = 0; j < (int)edges[i].neighbors.size(); j++) {
if (edges[i].neighbors.size() == 0)
continue;
/* 1 = side to center, 2 - center to other side */
int idx1 = i;
int idx2 = edges[i].neighbors[j];
int onext = (j + 1) % edges[i].neighbors.size();
int idx3 = edges[i].neighbors[onext];
const RoadLinesData::road_edge_side *side1 =
sides[{ idx2, idx1 }];
const RoadLinesData::road_edge_side *side2 =
sides[{ idx1, idx3 }];
print_line(itos(sides.size()));
print_line(itos(idx2) + " " + itos(idx1));
print_line(itos(idx1) + " " + itos(idx3));
assert(side1);
assert(side2);
Vector3 n1 = normal(node - neighbors[j]);
Vector3 n2 = normal(neighbors[onext] - node);
float angle = n1.signed_angle_to(
@@ -604,6 +651,8 @@ out2:;
w.y[2] = o3;
w.width1 = 2.0f * 5.0f;
w.width2 = 2.0f * 5.0f;
w.side1 = side1;
w.side2 = side2;
wedges[i].push_back(w);
}
}