Lot separation and splitting works
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
#undef NDEBUG
|
||||
#include <cassert>
|
||||
#include <core/object.h>
|
||||
#include <scene/3d/immediate_geometry.h>
|
||||
#include "wedge.h"
|
||||
#include "contours.h"
|
||||
|
||||
Contours *Contours::singleton = nullptr;
|
||||
@@ -11,6 +15,7 @@ Contours *Contours::get_singleton()
|
||||
}
|
||||
|
||||
Contours::Contours()
|
||||
: dbg(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,3 +33,246 @@ bool Contours::is_in_closed_contour(const struct wedge *w)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static Vector3 tangent(const Vector3 &v)
|
||||
{
|
||||
Vector2 rv = Vector2(v.x, v.z).tangent();
|
||||
return Vector3(rv.x, v.y, rv.y);
|
||||
}
|
||||
static Vector3 normal(const Vector3 &v)
|
||||
{
|
||||
Vector3 rv = tangent(v);
|
||||
rv.y = 0.0f;
|
||||
return rv.normalized();
|
||||
}
|
||||
|
||||
void Contours::build()
|
||||
{
|
||||
int i, j;
|
||||
contours.clear();
|
||||
for (i = 0; i < (int)wedge_contours.size(); i++) {
|
||||
struct main_contour mc;
|
||||
for (j = 0; j < (int)wedge_contours[i].size(); j++) {
|
||||
struct wedge *w = wedge_contours[i][j];
|
||||
struct contour_wedge cw;
|
||||
Vector3 d1 = (w->p[1] - w->p[0]).normalized();
|
||||
Vector3 n1 = normal(d1);
|
||||
Vector3 d2 = (w->p[2] - w->p[1]).normalized();
|
||||
Vector3 n2 = normal(d2);
|
||||
Vector3 m1 = n1 * (w->width1);
|
||||
Vector3 m2 = n2 * (w->width2);
|
||||
Vector3 dx = (d1 + d2).normalized();
|
||||
Vector3 f1 = w->p[1] + m1;
|
||||
Vector3 f2 = w->p[1] + m2;
|
||||
Vector3 q, r;
|
||||
Geometry::get_closest_points_between_segments(
|
||||
w->p[0] + m1, f1, f2, w->p[2] + m2, q, r);
|
||||
r = q.linear_interpolate(r, 0.5f);
|
||||
cw.p[0] = w->p[0] + m1;
|
||||
cw.p[1] = r;
|
||||
cw.p[2] = w->p[2] + m2;
|
||||
if (mc.aabb.size.is_equal_approx(Vector3()))
|
||||
mc.aabb.position = cw.p[0];
|
||||
else
|
||||
mc.aabb.expand_to(cw.p[0]);
|
||||
mc.aabb.expand_to(cw.p[1]);
|
||||
mc.aabb.expand_to(cw.p[2]);
|
||||
mc.points.push_back(cw.p[0]);
|
||||
mc.points.push_back(cw.p[1]);
|
||||
cw.wedge = w;
|
||||
mc.contour_wedges.push_back(cw);
|
||||
}
|
||||
contours.push_back(mc);
|
||||
}
|
||||
polygons.clear();
|
||||
for (i = 0; i < (int)contours.size(); i++)
|
||||
polygons.push_back({ contours[i].points, contours[i].aabb });
|
||||
List<struct polygon> polygon_queue;
|
||||
List<struct polygon> polygon_output;
|
||||
for (i = 0; i < (int)polygons.size(); i++)
|
||||
polygon_queue.push_back(polygons[i]);
|
||||
polygons.clear();
|
||||
List<struct polygon>::Element *e = polygon_queue.front();
|
||||
while (e) {
|
||||
struct polygon item = e->get();
|
||||
print_line("queue: " + itos(polygon_queue.size()));
|
||||
polygon_queue.pop_front();
|
||||
float area = item.area();
|
||||
if (area > 120.0f * 120.0f && item.aabb.size.x > 10.0f &&
|
||||
item.aabb.size.z > 10.0f) {
|
||||
std::pair<struct polygon, struct polygon> polys =
|
||||
item.split();
|
||||
if (polys.first.area() < 10.0f ||
|
||||
polys.second.area() < 10.0f) {
|
||||
polygon_output.push_back(item);
|
||||
} else {
|
||||
polygon_queue.push_back(polys.first);
|
||||
polygon_queue.push_back(polys.second);
|
||||
}
|
||||
} else
|
||||
polygon_output.push_back(item);
|
||||
e = polygon_queue.front();
|
||||
}
|
||||
polygons.reserve(polygon_output.size());
|
||||
e = polygon_output.front();
|
||||
while (e) {
|
||||
polygons.push_back(e->get());
|
||||
e = e->next();
|
||||
}
|
||||
}
|
||||
|
||||
void Contours::debug()
|
||||
{
|
||||
int i, j;
|
||||
if (!dbg) {
|
||||
dbg = memnew(ImmediateGeometry);
|
||||
SceneTree::get_singleton()->get_current_scene()->call_deferred(
|
||||
"add_child", dbg);
|
||||
if (!imm_mat.is_valid()) {
|
||||
imm_mat.instance();
|
||||
imm_mat->set_flag(
|
||||
SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,
|
||||
true);
|
||||
imm_mat->set_flag(
|
||||
SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, true);
|
||||
imm_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
|
||||
}
|
||||
dbg->set_material_override(imm_mat);
|
||||
}
|
||||
dbg->clear();
|
||||
dbg->begin(Mesh::PRIMITIVE_LINES);
|
||||
dbg->set_color(Color(1, 1, 0, 1));
|
||||
for (i = 0; i < (int)wedge_contours.size(); i++) {
|
||||
for (j = 0; j < (int)wedge_contours[i].size(); j++) {
|
||||
dbg->add_vertex(wedge_contours[i][j]->p[0] +
|
||||
Vector3(0, 1, 0));
|
||||
dbg->add_vertex(wedge_contours[i][j]->p[1] +
|
||||
Vector3(0, 1, 0));
|
||||
dbg->add_vertex(wedge_contours[i][j]->p[1] +
|
||||
Vector3(0, 1, 0));
|
||||
dbg->add_vertex(wedge_contours[i][j]->p[2] +
|
||||
Vector3(0, 1, 0));
|
||||
}
|
||||
}
|
||||
dbg->end();
|
||||
dbg->begin(Mesh::PRIMITIVE_LINES);
|
||||
dbg->set_color(Color(1, 1, 0.4f, 1));
|
||||
for (i = 0; i < (int)polygons.size(); i++) {
|
||||
for (j = 0; j < (int)polygons[i].points.size(); j++) {
|
||||
dbg->add_vertex(polygons[i].points[j] +
|
||||
Vector3(0, 2, 0));
|
||||
dbg->add_vertex(
|
||||
polygons[i].points[(j + 1) %
|
||||
polygons[i].points.size()] +
|
||||
Vector3(0, 2, 0));
|
||||
}
|
||||
}
|
||||
dbg->end();
|
||||
}
|
||||
|
||||
std::pair<struct Contours::polygon, struct Contours::polygon>
|
||||
Contours::polygon::split() const
|
||||
{
|
||||
int i, j;
|
||||
float split_polygons_area = 0.0f;
|
||||
float split_polygons_area_min = 0.0f;
|
||||
std::pair<struct Contours::polygon, struct Contours::polygon>
|
||||
split_polygons;
|
||||
std::vector<int> edges;
|
||||
for (i = 0; i < (int)points.size(); i++) {
|
||||
Vector3 p0 = points[i];
|
||||
Vector3 p1 = points[(i + 1) % points.size()];
|
||||
if (p0.distance_squared_to(p1) > 100 * 100)
|
||||
edges.push_back(i);
|
||||
}
|
||||
if (edges.size() == 0) {
|
||||
for (i = 0; i < (int)points.size(); i++) {
|
||||
Vector3 p0 = points[i];
|
||||
Vector3 p1 = points[(i + 1) % points.size()];
|
||||
edges.push_back(i);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (int)edges.size(); i++) {
|
||||
Vector3 p0 = points[edges[i]];
|
||||
Vector3 p1 = points[(edges[i] + 1) % points.size()];
|
||||
Transform xf =
|
||||
Transform(Basis(), p0).looking_at(p1, Vector3(0, 1, 0));
|
||||
AABB base;
|
||||
base.position = xf.xform_inv(p0);
|
||||
base.expand_to(xf.xform_inv(p1));
|
||||
for (j = 0; j < (int)points.size(); j++)
|
||||
base.expand_to(xf.xform_inv(points[j]));
|
||||
Vector3 mpos0, mpos1;
|
||||
if (base.size.x > base.size.z) {
|
||||
mpos0 = base.position +
|
||||
Vector3(base.size.x, 0, 0) * 0.5f;
|
||||
mpos1 = mpos0 + Vector3(0, 0, base.size.z);
|
||||
mpos0 = xf.xform(mpos0);
|
||||
mpos1 = xf.xform(mpos1);
|
||||
} else {
|
||||
mpos0 = base.position +
|
||||
Vector3(0, 0, base.size.z) * 0.5f;
|
||||
mpos1 = mpos0 + Vector3(base.size.x, 0, 0);
|
||||
mpos0 = xf.xform(mpos0);
|
||||
mpos1 = xf.xform(mpos1);
|
||||
}
|
||||
mpos0.y = 0;
|
||||
mpos1.y == 0;
|
||||
/* mpos0 is at start of cut */
|
||||
|
||||
Vector3 n =
|
||||
(mpos1 - mpos0).cross(Vector3(0, 1, 0)).normalized();
|
||||
Plane pl1(mpos0 - n * 1.5f, n);
|
||||
Plane pl2(mpos0 + n * 1.5f, -n);
|
||||
Vector<Vector3> pdata;
|
||||
pdata.resize(points.size());
|
||||
memcpy(pdata.ptrw(), points.data(),
|
||||
points.size() * sizeof(Vector3));
|
||||
struct polygon poly1, poly2;
|
||||
Vector<Vector3> rpdata = Geometry::clip_polygon(pdata, pl1);
|
||||
poly1.points.resize(rpdata.size());
|
||||
memcpy(poly1.points.data(), rpdata.ptr(),
|
||||
rpdata.size() * sizeof(Vector3));
|
||||
poly1.update_aabb();
|
||||
rpdata = Geometry::clip_polygon(pdata, pl2);
|
||||
poly2.points.resize(rpdata.size());
|
||||
memcpy(poly2.points.data(), rpdata.ptr(),
|
||||
rpdata.size() * sizeof(Vector3));
|
||||
poly2.update_aabb();
|
||||
float area1 = poly1.area();
|
||||
float area2 = poly2.area();
|
||||
if (area1 <= 4.0f || area2 <= 4.0f)
|
||||
continue;
|
||||
float area_min = MIN(area1, area2);
|
||||
float area = area1 + area2;
|
||||
if (split_polygons_area_min < area_min &&
|
||||
split_polygons_area < area) {
|
||||
split_polygons = { poly1, poly2 };
|
||||
split_polygons_area_min = area_min;
|
||||
split_polygons_area = area;
|
||||
}
|
||||
}
|
||||
return split_polygons;
|
||||
}
|
||||
|
||||
int Contours::polygon::longest_edge() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Contours::polygon::update_aabb()
|
||||
{
|
||||
aabb = AABB();
|
||||
int i;
|
||||
for (i = 0; i < (int)points.size(); i++) {
|
||||
if (aabb.is_equal_approx(AABB()))
|
||||
aabb.position = points[i];
|
||||
else
|
||||
aabb.expand_to(points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
float Contours::polygon::area() const
|
||||
{
|
||||
return Geometry::find_polygon_area(points.data(), points.size());
|
||||
}
|
||||
|
||||
@@ -3,13 +3,37 @@
|
||||
#define CONTOURS_H_
|
||||
#include <vector>
|
||||
|
||||
class ImmediateGeometry;
|
||||
struct Contours {
|
||||
struct contour_wedge {
|
||||
Vector3 p[3];
|
||||
struct wedge *wedge;
|
||||
};
|
||||
struct main_contour {
|
||||
std::vector<struct contour_wedge> contour_wedges;
|
||||
std::vector<Vector3> points;
|
||||
AABB aabb;
|
||||
};
|
||||
struct polygon {
|
||||
std::vector<Vector3> points;
|
||||
AABB aabb;
|
||||
std::pair<struct polygon, struct polygon> split() const;
|
||||
float area() const;
|
||||
int longest_edge() const;
|
||||
void update_aabb();
|
||||
};
|
||||
void build();
|
||||
ImmediateGeometry *dbg;
|
||||
Ref<SpatialMaterial> imm_mat;
|
||||
std::vector<std::vector<struct wedge *> > wedge_contours;
|
||||
std::vector<struct main_contour> contours;
|
||||
std::vector<struct polygon> polygons;
|
||||
static Contours *singleton;
|
||||
static Contours *get_singleton();
|
||||
Contours();
|
||||
virtual ~Contours();
|
||||
bool is_in_closed_contour(const struct wedge *w);
|
||||
void debug();
|
||||
};
|
||||
|
||||
#endif // CONTOURS_H_
|
||||
@@ -22,21 +22,9 @@
|
||||
#include "road_lines_data.h"
|
||||
#include "buildings_data.h"
|
||||
#include "contours.h"
|
||||
#include "wedge.h"
|
||||
#include "road_processing.h"
|
||||
|
||||
struct side_ref {
|
||||
String line_key;
|
||||
int edge;
|
||||
int side; // left = 0, right = 1
|
||||
};
|
||||
struct wedge {
|
||||
Vector3 p[3];
|
||||
Vector3 y[3];
|
||||
int width1, width2;
|
||||
struct side_ref side1_ref, side2_ref;
|
||||
bool acute;
|
||||
};
|
||||
|
||||
class DebugGeo : public ImmediateGeometry {
|
||||
Ref<SpatialMaterial> imm_mat;
|
||||
int vertex_count;
|
||||
@@ -1245,6 +1233,8 @@ out_skip_end:;
|
||||
if (base >= (int)wedges_ref.size())
|
||||
break;
|
||||
}
|
||||
contours->build();
|
||||
contours->debug();
|
||||
}
|
||||
~RoadLinesProcessing()
|
||||
{
|
||||
|
||||
20
src/modules/stream/wedge.h
Normal file
20
src/modules/stream/wedge.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* ~/godot-projects/streaming_world/src/modules/stream/wedge.h */
|
||||
#ifndef WEDGE_H_
|
||||
#define WEDGE_H_
|
||||
#include <core/math/vector3.h>
|
||||
#include <core/ustring.h>
|
||||
|
||||
struct side_ref {
|
||||
String line_key;
|
||||
int edge;
|
||||
int side; // left = 0, right = 1
|
||||
};
|
||||
struct wedge {
|
||||
Vector3 p[3];
|
||||
Vector3 y[3];
|
||||
int width1, width2;
|
||||
struct side_ref side1_ref, side2_ref;
|
||||
bool acute;
|
||||
};
|
||||
|
||||
#endif // WEDGE_H_
|
||||
Reference in New Issue
Block a user