winding_t: make non-copyable

This commit is contained in:
Eric Wasylishen 2022-08-12 01:23:10 -06:00
parent 8b9c1bd784
commit 06a116670b
14 changed files with 102 additions and 48 deletions

View File

@ -413,8 +413,14 @@ std::pair<std::vector<qvec3f>, std::vector<qvec3f>> GLM_ClipPoly(const std::vect
auto clipped = w.clip({plane.xyz(), plane[3]});
return make_pair(
clipped[0].value_or(winding_t{}).glm_winding_points(), clipped[1].value_or(winding_t{}).glm_winding_points());
std::pair<std::vector<qvec3f>, std::vector<qvec3f>> result;
if (clipped[0]) {
result.first = clipped[0]->glm_winding_points();
}
if (clipped[1]) {
result.second = clipped[1]->glm_winding_points();
}
return result;
}
std::vector<qvec3f> GLM_ShrinkPoly(const std::vector<qvec3f> &poly, const float amount)

View File

@ -648,19 +648,14 @@ public:
// initializer list constructor
inline winding_base_t(std::initializer_list<qvec3d> l) : storage(l.begin(), l.end()) { }
// copy constructor; uses optimized method of copying
// data over.
inline winding_base_t(const winding_base_t &copy) : storage(copy.storage) { }
// copy constructor; we require copying to be done with clone() to avoid performance bugs
inline winding_base_t(const winding_base_t &copy) = delete;
// move constructor
inline winding_base_t(winding_base_t &&move) noexcept : storage(std::move(move.storage)) { }
// assignment copy
inline winding_base_t &operator=(const winding_base_t &copy)
{
storage = copy.storage;
return *this;
}
inline winding_base_t &operator=(const winding_base_t &copy) = delete;
// assignment move
inline winding_base_t &operator=(winding_base_t &&move) noexcept
@ -745,6 +740,14 @@ public:
// non-storage functions
// explicit copying function
winding_base_t clone() const
{
winding_base_t result;
result.storage = storage;
return result;
}
vec_t area() const
{
vec_t total = 0;
@ -996,12 +999,12 @@ public:
std::array<size_t, SIDE_TOTAL> counts = calc_sides(plane, dists, sides, on_epsilon);
if (keepon && !counts[SIDE_FRONT] && !counts[SIDE_BACK])
return {*this, std::nullopt};
return {this->clone(), std::nullopt};
if (!counts[SIDE_FRONT])
return {std::nullopt, *this};
return {std::nullopt, this->clone()};
else if (!counts[SIDE_BACK])
return {*this, std::nullopt};
return {this->clone(), std::nullopt};
twosided<winding_base_t> results{};
@ -1108,7 +1111,7 @@ public:
result.push_back(mid);
}
return std::move(result);
return result;
}
@ -1250,7 +1253,7 @@ public:
winding_base_t translate(const qvec3d &offset) const
{
winding_base_t result(*this);
winding_base_t result = this->clone();
for (qvec3d &p : result) {
p += offset;

View File

@ -45,6 +45,9 @@ struct side_t
bool tested;
side_t clone_non_winding_data() const;
side_t clone() const;
bool is_visible() const;
const maptexinfo_t &get_texinfo() const;
const qbsp_plane_t &get_plane() const;
@ -86,6 +89,8 @@ struct bspbrush_t
bool update_bounds(bool warn_on_failures);
ptr copy_unique() const;
bspbrush_t clone() const;
};
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum);

View File

@ -37,7 +37,7 @@ struct portal_t
node_t *onnode; // nullptr = portal to the outside of the world (one of six sides of a box)
node_t *nodes[2]; // [0] = front side of planenum
portal_t *next[2]; // [0] = next portal in nodes[0]'s list of portals
std::unique_ptr<winding_t> winding;
winding_t winding;
bool sidefound; // false if ->side hasn't been checked
side_t *sides[2]; // [0] = the brush side visible on nodes[0] - it could come from a brush in nodes[1]. NULL =
@ -51,7 +51,7 @@ struct buildportal_t
qbsp_plane_t plane;
node_t *onnode = nullptr; // nullptr = portal to the outside of the world (one of six sides of a box)
node_t *nodes[2] = {nullptr, nullptr}; // [0] = front side of planenum
std::unique_ptr<winding_t> winding;
winding_t winding;
inline void set_nodes(node_t *front, node_t *back) {
nodes[0] = front;

View File

@ -61,10 +61,10 @@ struct winding_t : polylib::winding_base_t<polylib::winding_storage_hybrid_t<MAX
}
// copy constructor
inline winding_t(const winding_t &copy) : winding_base_t(copy), origin(copy.origin), radius(copy.radius) { }
inline winding_t(const winding_t &copy) = delete;
// move constructor
inline winding_t(winding_t &&move) noexcept : winding_base_t(move), origin(move.origin), radius(move.radius) { }
inline winding_t(winding_t &&move) noexcept : winding_base_t(std::move(move)), origin(move.origin), radius(move.radius) { }
// sets origin & radius
inline void set_winding_sphere()
@ -84,15 +84,7 @@ struct winding_t : polylib::winding_base_t<polylib::winding_storage_hybrid_t<MAX
}
// assignment copy
inline winding_t &operator=(const winding_t &copy)
{
origin = copy.origin;
radius = copy.radius;
winding_base_t::operator=(copy);
return *this;
}
inline winding_t &operator=(const winding_t &copy) = delete;
// assignment move
inline winding_t &operator=(winding_t &&move) noexcept
@ -100,7 +92,7 @@ struct winding_t : polylib::winding_base_t<polylib::winding_storage_hybrid_t<MAX
origin = move.origin;
radius = move.radius;
winding_base_t::operator=(move);
winding_base_t::operator=(std::move(move));
return *this;
}

View File

@ -28,6 +28,25 @@
#include <qbsp/map.hh>
#include <qbsp/qbsp.hh>
side_t side_t::clone_non_winding_data() const
{
side_t result;
result.planenum = this->planenum;
result.texinfo = this->texinfo;
result.onnode = this->onnode;
result.bevel = this->bevel;
result.source = this->source;
result.tested = this->tested;
return result;
}
side_t side_t::clone() const
{
side_t result = clone_non_winding_data();
result.w = this->w.clone();
return result;
}
bool side_t::is_visible() const
{
return source && source->visible;
@ -50,7 +69,31 @@ const qbsp_plane_t &side_t::get_positive_plane() const
bspbrush_t::ptr bspbrush_t::copy_unique() const
{
return bspbrush_t::make_ptr(*this);
return bspbrush_t::make_ptr(this->clone());
}
bspbrush_t bspbrush_t::clone() const
{
bspbrush_t result;
result.original_ptr = this->original_ptr;
result.mapbrush = this->mapbrush;
result.bounds = this->bounds;
result.side = this->side;
result.testside = this->testside;
result.sides.reserve(this->sides.size());
for (auto &side : this->sides) {
result.sides.push_back(side.clone());
}
result.contents = this->contents;
result.sphere_origin = this->sphere_origin;
result.sphere_radius = this->sphere_radius;
return result;
}
/*
@ -238,7 +281,7 @@ bool CreateBrushWindings(bspbrush_t *brush)
}
}
side->w = *w;
side->w = std::move(*w);
} else {
side->w.clear();
}

View File

@ -481,7 +481,7 @@ static twosided<bspbrush_t::ptr> SplitBrush(bspbrush_t::ptr brush, size_t planen
logging::print("WARNING: huge winding\n");
}
winding_t midwinding = *w;
winding_t &midwinding = *w;
// split it for real
@ -512,7 +512,7 @@ static twosided<bspbrush_t::ptr> SplitBrush(bspbrush_t::ptr brush, size_t planen
#endif
// add the clipped face to result[j]
side_t faceCopy = face;
side_t faceCopy = face.clone_non_winding_data();
faceCopy.w = std::move(*cw[j]);
// fixme-brushbsp: configure any settings on the faceCopy?
@ -583,7 +583,11 @@ static twosided<bspbrush_t::ptr> SplitBrush(bspbrush_t::ptr brush, size_t planen
cs.onnode = true;
// fixme-brushbsp: configure any other settings on the face?
cs.w = brushOnFront ? midwinding.flip() : midwinding;
if (brushOnFront) {
cs.w = midwinding.flip();
} else {
cs.w = std::move(midwinding);
}
result[i]->sides.push_back(std::move(cs));
}

View File

@ -65,7 +65,7 @@ std::unique_ptr<face_t> NewFaceFromFace(const face_t *in)
std::unique_ptr<face_t> CopyFace(const face_t *in)
{
auto temp = NewFaceFromFace(in);
temp->w = in->w;
temp->w = in->w.clone();
return temp;
}

View File

@ -504,9 +504,9 @@ static std::unique_ptr<face_t> FaceFromPortal(portal_t *p, bool pside)
#endif
if (pside) {
f->w = p->winding->flip();
f->w = p->winding.flip();
} else {
f->w = *p->winding;
f->w = p->winding.clone();
}
f->contents = p->nodes[pside]->contents;

View File

@ -2233,10 +2233,11 @@ inline void CalculateBrushBounds(mapbrush_t &ob)
}
if (w) {
ob.faces[i].winding = w.value();
// calc bounds before moving from w
for (auto &p : w.value()) {
ob.bounds += p;
}
ob.faces[i].winding = std::move(w.value());
}
}

View File

@ -272,7 +272,7 @@ static void WriteLeakLine(const mapentity_t *leakentity, const std::vector<porta
qvec3d prevpt = leakentity->origin;
for (portal_t *portal : leakline) {
qvec3d currpt = portal->winding->center();
qvec3d currpt = portal->winding.center();
// draw dots from prevpt to currpt
WriteLeakTrail(ptsfile, prevpt, currpt);

View File

@ -158,7 +158,7 @@ std::list<std::unique_ptr<buildportal_t>> MakeHeadnodePortals(tree_t *tree)
}
bool side = p->plane.set_plane(pl, true);
p->winding = std::make_unique<winding_t>(BaseWindingForPlane(pl));
p->winding = BaseWindingForPlane(pl);
if (side) {
p->set_nodes(&tree->outside_node, tree->headnode);
} else {
@ -168,7 +168,7 @@ std::list<std::unique_ptr<buildportal_t>> MakeHeadnodePortals(tree_t *tree)
// clip the basewindings by all the other planes
for (i = 0; i < 6; i++) {
winding_t &w = *portals[i]->winding.get();
winding_t &w = portals[i]->winding;
for (j = 0; j < 6; j++) {
if (j == i)
@ -266,7 +266,7 @@ std::unique_ptr<buildportal_t> MakeNodePortal(node_t *node, const std::list<std:
auto new_portal = std::make_unique<buildportal_t>();
new_portal->plane = node->get_plane();
new_portal->onnode = node;
new_portal->winding = std::make_unique<winding_t>(*w);
new_portal->winding = std::move(*w);
new_portal->set_nodes(node->children[0], node->children[1]);
return new_portal;
@ -304,7 +304,7 @@ twosided<std::list<std::unique_ptr<buildportal_t>>> SplitNodePortals(const node_
//
// cut the portal into two portals, one on each side of the cut plane
//
auto [frontwinding, backwinding] = p->winding->clip(plane, SPLIT_WINDING_EPSILON, true);
auto [frontwinding, backwinding] = p->winding.clip(plane, SPLIT_WINDING_EPSILON, true);
if (frontwinding && WindingIsTiny(*frontwinding)) {
frontwinding = {};
@ -345,8 +345,8 @@ twosided<std::list<std::unique_ptr<buildportal_t>>> SplitNodePortals(const node_
new_portal->onnode = p->onnode;
new_portal->nodes[0] = p->nodes[0];
new_portal->nodes[1] = p->nodes[1];
new_portal->winding = std::make_unique<winding_t>(*backwinding);
p->winding = std::make_unique<winding_t>(*frontwinding);
new_portal->winding = std::move(*backwinding);
p->winding = std::move(*frontwinding);
if (side == SIDE_FRONT) {
p->set_nodes(f, other_node);
@ -392,7 +392,7 @@ void CalcNodeBounds(node_t *node)
for (portal_t *p = node->portals; p;) {
int s = (p->nodes[1] == node);
for (auto &point : *p->winding) {
for (auto &point : p->winding) {
node->bounds += point;
}
p = p->next[s];

View File

@ -69,7 +69,7 @@ static void WritePortals_r(node_t *node, std::ofstream &portalFile, bool cluster
if (!Portal_VisFlood(p))
continue;
w = p->winding.get();
w = &p->winding;
front = clusters ? p->nodes[0]->viscluster : p->nodes[0]->visleafnum;
back = clusters ? p->nodes[1]->viscluster : p->nodes[1]->visleafnum;

View File

@ -410,7 +410,7 @@ TEST_CASE("winding iterators", "[winding_base_t]")
// check that constructors work
{
polylib::winding_base_t<polylib::winding_storage_hybrid_t<4>> winding_other(winding);
polylib::winding_base_t<polylib::winding_storage_hybrid_t<4>> winding_other(winding.begin(), winding.end());
{
auto it = winding_other.begin();