allow update_bounds to tell the caller that a brush may have been destroyed
This commit is contained in:
parent
712dd24cff
commit
b3fbf8841d
|
|
@ -73,12 +73,12 @@ struct bspbrush_t
|
||||||
qvec3d sphere_origin;
|
qvec3d sphere_origin;
|
||||||
double sphere_radius;
|
double sphere_radius;
|
||||||
|
|
||||||
void update_bounds();
|
bool update_bounds();
|
||||||
|
|
||||||
std::unique_ptr<bspbrush_t> copy_unique() const;
|
std::unique_ptr<bspbrush_t> copy_unique() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using bspbrush_vector_t = std::vector<std::unique_ptr<bspbrush_t>>;
|
using bspbrush_vector_t = std::vector<std::unique_ptr<bspbrush_t>>;
|
||||||
|
|
||||||
bspbrush_t LoadBrush(const mapentity_t *src, const mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum);
|
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, const mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum);
|
||||||
void CreateBrushWindings(bspbrush_t *brush);
|
bool CreateBrushWindings(bspbrush_t *brush);
|
||||||
|
|
@ -214,7 +214,7 @@ Create all of the windings for the specified brush, and
|
||||||
calculate its bounds.
|
calculate its bounds.
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void CreateBrushWindings(bspbrush_t *brush)
|
bool CreateBrushWindings(bspbrush_t *brush)
|
||||||
{
|
{
|
||||||
std::optional<winding_t> w;
|
std::optional<winding_t> w;
|
||||||
|
|
||||||
|
|
@ -231,13 +231,22 @@ void CreateBrushWindings(bspbrush_t *brush)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w) {
|
if (w) {
|
||||||
|
for (auto &p : *w) {
|
||||||
|
for (auto &v : p) {
|
||||||
|
if (fabs(v) > qbsp_options.worldextent.value()) {
|
||||||
|
logging::print("WARNING: {}: invalid winding point\n", brush->mapbrush ? brush->mapbrush->line : parser_source_location{});
|
||||||
|
w = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
side->w = *w;
|
side->w = *w;
|
||||||
} else {
|
} else {
|
||||||
side->w.clear();
|
side->w.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
brush->update_bounds();
|
return brush->update_bounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -247,7 +256,7 @@ LoadBrush
|
||||||
Converts a mapbrush to a bsp brush
|
Converts a mapbrush to a bsp brush
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
bspbrush_t LoadBrush(const mapentity_t *src, const mapbrush_t *mapbrush, const contentflags_t &contents,
|
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, const mapbrush_t *mapbrush, const contentflags_t &contents,
|
||||||
const int hullnum)
|
const int hullnum)
|
||||||
{
|
{
|
||||||
// create the brush
|
// create the brush
|
||||||
|
|
@ -297,7 +306,9 @@ bspbrush_t LoadBrush(const mapentity_t *src, const mapbrush_t *mapbrush, const c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBrushWindings(&brush);
|
if (!CreateBrushWindings(&brush)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &face : brush.sides) {
|
for (auto &face : brush.sides) {
|
||||||
CheckFace(&face, *face.source);
|
CheckFace(&face, *face.source);
|
||||||
|
|
@ -451,8 +462,9 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
||||||
*/
|
*/
|
||||||
if (hullnum != HULL_COLLISION && contents.is_clip(qbsp_options.target_game)) {
|
if (hullnum != HULL_COLLISION && contents.is_clip(qbsp_options.target_game)) {
|
||||||
if (hullnum == 0) {
|
if (hullnum == 0) {
|
||||||
bspbrush_t brush = LoadBrush(src, &mapbrush, contents, hullnum);
|
if (auto brush = LoadBrush(src, &mapbrush, contents, hullnum)) {
|
||||||
dst->bounds += brush.bounds;
|
dst->bounds += brush->bounds;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
// for hull1, 2, etc., convert clip to CONTENTS_SOLID
|
// for hull1, 2, etc., convert clip to CONTENTS_SOLID
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -497,22 +509,26 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
||||||
contents.set_clips_same_type(clipsametype);
|
contents.set_clips_same_type(clipsametype);
|
||||||
contents.illusionary_visblocker = func_illusionary_visblocker;
|
contents.illusionary_visblocker = func_illusionary_visblocker;
|
||||||
|
|
||||||
bspbrush_t brush = LoadBrush(src, &mapbrush, contents, hullnum);
|
auto brush = LoadBrush(src, &mapbrush, contents, hullnum);
|
||||||
|
|
||||||
brush.lmshift = lmshift;
|
if (!brush) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &face : brush.sides) {
|
brush->lmshift = lmshift;
|
||||||
|
|
||||||
|
for (auto &face : brush->sides) {
|
||||||
face.lmshift = lmshift;
|
face.lmshift = lmshift;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classname == std::string_view("func_areaportal")) {
|
if (classname == std::string_view("func_areaportal")) {
|
||||||
brush.func_areaportal = const_cast<mapentity_t *>(src); // FIXME: get rid of consts on src in the callers?
|
brush->func_areaportal = const_cast<mapentity_t *>(src); // FIXME: get rid of consts on src in the callers?
|
||||||
}
|
}
|
||||||
|
|
||||||
qbsp_options.target_game->count_contents_in_stats(brush.contents, stats);
|
qbsp_options.target_game->count_contents_in_stats(brush->contents, stats);
|
||||||
|
|
||||||
dst->bounds += brush.bounds;
|
dst->bounds += brush->bounds;
|
||||||
brushes.push_back(std::make_unique<bspbrush_t>(std::move(brush)));
|
brushes.push_back(std::make_unique<bspbrush_t>(std::move(*brush)));
|
||||||
}
|
}
|
||||||
|
|
||||||
logging::percent(src->mapbrushes.size(), src->mapbrushes.size(), src == map.world_entity());
|
logging::percent(src->mapbrushes.size(), src->mapbrushes.size(), src == map.world_entity());
|
||||||
|
|
@ -562,9 +578,10 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_vector_t
|
||||||
qbsp_options.target_game->print_content_stats(*stats, "brushes");
|
qbsp_options.target_game->print_content_stats(*stats, "brushes");
|
||||||
}
|
}
|
||||||
|
|
||||||
void bspbrush_t::update_bounds()
|
bool bspbrush_t::update_bounds()
|
||||||
{
|
{
|
||||||
this->bounds = {};
|
this->bounds = {};
|
||||||
|
|
||||||
for (const auto &face : sides) {
|
for (const auto &face : sides) {
|
||||||
if (face.w) {
|
if (face.w) {
|
||||||
this->bounds = this->bounds.unionWith(face.w.bounds());
|
this->bounds = this->bounds.unionWith(face.w.bounds());
|
||||||
|
|
@ -575,12 +592,16 @@ void bspbrush_t::update_bounds()
|
||||||
// todo: map_source_location in bspbrush_t
|
// todo: map_source_location in bspbrush_t
|
||||||
if (this->bounds.mins()[0] <= -qbsp_options.worldextent.value() || this->bounds.maxs()[0] >= qbsp_options.worldextent.value()) {
|
if (this->bounds.mins()[0] <= -qbsp_options.worldextent.value() || this->bounds.maxs()[0] >= qbsp_options.worldextent.value()) {
|
||||||
logging::print("WARNING: {}: brush bounds out of range\n", mapbrush ? mapbrush->line : parser_source_location());
|
logging::print("WARNING: {}: brush bounds out of range\n", mapbrush ? mapbrush->line : parser_source_location());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (this->bounds.mins()[0] >= qbsp_options.worldextent.value() || this->bounds.maxs()[0] <= -qbsp_options.worldextent.value()) {
|
if (this->bounds.mins()[0] >= qbsp_options.worldextent.value() || this->bounds.maxs()[0] <= -qbsp_options.worldextent.value()) {
|
||||||
logging::print("WARNING: {}: no visible sides on brush\n", mapbrush ? mapbrush->line : parser_source_location());
|
logging::print("WARNING: {}: no visible sides on brush\n", mapbrush ? mapbrush->line : parser_source_location());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->sphere_origin = (bounds.mins() + bounds.maxs()) / 2.0;
|
this->sphere_origin = (bounds.mins() + bounds.maxs()) / 2.0;
|
||||||
this->sphere_radius = qv::length((bounds.maxs() - bounds.mins()) / 2.0);
|
this->sphere_radius = qv::length((bounds.maxs() - bounds.mins()) / 2.0);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1040,6 +1040,7 @@ static std::unique_ptr<tree_t> BrushBSP_internal(mapentity_t *entity, std::vecto
|
||||||
size_t c_faces = 0;
|
size_t c_faces = 0;
|
||||||
size_t c_nonvisfaces = 0;
|
size_t c_nonvisfaces = 0;
|
||||||
size_t c_brushes = 0;
|
size_t c_brushes = 0;
|
||||||
|
|
||||||
for (const auto &b : brushlist) {
|
for (const auto &b : brushlist) {
|
||||||
c_brushes++;
|
c_brushes++;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2824,10 +2824,12 @@ static void TestExpandBrushes(const mapentity_t *src)
|
||||||
std::vector<std::unique_ptr<bspbrush_t>> hull1brushes;
|
std::vector<std::unique_ptr<bspbrush_t>> hull1brushes;
|
||||||
|
|
||||||
for (auto &mapbrush : src->mapbrushes) {
|
for (auto &mapbrush : src->mapbrushes) {
|
||||||
bspbrush_t hull1brush = LoadBrush(src, &mapbrush, {CONTENTS_SOLID},
|
auto hull1brush = LoadBrush(src, &mapbrush, {CONTENTS_SOLID},
|
||||||
qbsp_options.target_game->id == GAME_QUAKE_II ? HULL_COLLISION : 1);
|
qbsp_options.target_game->id == GAME_QUAKE_II ? HULL_COLLISION : 1);
|
||||||
|
|
||||||
hull1brushes.emplace_back(std::make_unique<bspbrush_t>(std::move(hull1brush)));
|
if (hull1brush) {
|
||||||
|
hull1brushes.emplace_back(std::make_unique<bspbrush_t>(std::move(*hull1brush)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteBspBrushMap("expanded.map", hull1brushes);
|
WriteBspBrushMap("expanded.map", hull1brushes);
|
||||||
|
|
|
||||||
|
|
@ -401,8 +401,8 @@ TEST_CASE("duplicatePlanes", "[qbsp]")
|
||||||
REQUIRE(1 == worldspawn.mapbrushes.size());
|
REQUIRE(1 == worldspawn.mapbrushes.size());
|
||||||
CHECK(6 == worldspawn.mapbrushes.front().faces.size());
|
CHECK(6 == worldspawn.mapbrushes.front().faces.size());
|
||||||
|
|
||||||
bspbrush_t brush = LoadBrush(&worldspawn, &worldspawn.mapbrushes.front(), {CONTENTS_SOLID}, 0);
|
auto brush = LoadBrush(&worldspawn, &worldspawn.mapbrushes.front(), {CONTENTS_SOLID}, 0);
|
||||||
CHECK(6 == brush.sides.size());
|
CHECK(6 == brush->sides.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue