fix legacy bevel bug

pushing up changes for Q1 hulls just in case we ever want these back
This commit is contained in:
Jonathan 2022-08-16 13:52:30 -04:00
parent 0c90a33f28
commit 95c728a5b6
5 changed files with 523 additions and 151 deletions

View File

@ -367,5 +367,4 @@ void ExportObj_Marksurfaces(const std::string &filesuffix, const node_t *nodes);
void WriteBspBrushMap(const fs::path &name, const bspbrush_t::container &list);
bool IsValidTextureProjection(const qvec3f &faceNormal, const qvec3f &s_vec, const qvec3f &t_vec);
void TestExpandBrushes(mapentity_t *src);
bool IsValidTextureProjection(const qvec3f &faceNormal, const qvec3f &s_vec, const qvec3f &t_vec);

View File

@ -30,6 +30,7 @@
#include <array>
#include <optional>
#include <string>
#include <variant>
#include <cassert>
#include <cctype>
@ -245,6 +246,65 @@ public:
std::string format() const override { return "[x [y [z]]]"; }
};
class setting_debugexpand : public setting_value<std::variant<uint8_t, aabb3d>>
{
public:
inline setting_debugexpand(setting_container *dictionary, const nameset &names,
const setting_group *group = nullptr, const char *description = "")
: setting_value(dictionary, names, {}, group, description)
{
}
bool parse(const std::string &settingName, parser_base_t &parser, source source) override
{
std::array<vec_t, 6> values;
size_t i = 0;
try {
for (; i < 6; i++) {
if (!parser.parse_token(PARSE_PEEK)) {
throw std::exception();
}
values[i] = std::stod(parser.token);
parser.parse_token();
}
this->setValue(aabb3d { { values[0], values[1], values[2] }, { values[3], values[4], values[5] } }, source);
return true;
} catch (std::exception &) {
// single hull value
if (i == 1) {
setValue(static_cast<uint8_t>(values[0]), source);
return true;
}
return false;
}
}
std::string stringValue() const override { return is_hull() ? std::to_string(hull_index_value()) : fmt::format("{}", hull_bounds_value()); }
std::string format() const override { return "[single hull index] or [mins_x mins_y mins_z maxs_x maxs_y maxs_z]"; }
inline bool is_hull() const
{
return std::holds_alternative<uint8_t>(_value);
}
inline const uint8_t &hull_index_value() const
{
return std::get<uint8_t>(_value);
}
inline const aabb3d &hull_bounds_value() const
{
return std::get<aabb3d>(_value);
}
};
class qbsp_settings : public common_settings
{
public:
@ -302,6 +362,7 @@ public:
setting_bool outsidedebug{this, "outsidedebug", false, &debugging_group,
"write a .map after outside filling showing non-visible brush sides"};
setting_bool debugchop{this, "debugchop", false, &debugging_group, "write a .map after ChopBrushes"};
setting_debugexpand debugexpand{this, "debugexpand", &debugging_group, "write expanded hull .map for debugging/inspecting hulls/brush bevelling"};
setting_bool keepprt{this, "keepprt", false, &debugging_group, "avoid deleting the .prt file on leaking maps"};
setting_bool includeskip{this, "includeskip", false, &common_format_group,
"don't cull skip faces from the list of renderable surfaces (Q2RTX)"};
@ -328,8 +389,6 @@ public:
"func_detail_illusionary brushes are omitted from the compile"};
setting_bool omitdetailfence{this, "omitdetailfence", false, &map_development_group,
"func_detail_fence brushes are omitted from the compile"};
setting_bool expand{
this, "expand", false, &common_format_group, "write hull 1 expanded brushes to expanded.map for debugging"};
setting_wadpathset wadpaths{this, {"wadpath", "xwadpath"}, &map_development_group,
"add a path to the wad search paths; wads found in xwadpath's will not be embedded, otherwise they will be embedded (if not -notex)"};
setting_bool notriggermodels{this, "notriggermodels", false, &common_format_group,

View File

@ -276,15 +276,9 @@ bool CreateBrushWindings(bspbrush_t *brush)
return brush->update_bounds(true);
}
#define QBSP3
#ifndef QBSP3
struct hullbrush_t {
bspbrush_t &brush;
std::vector<qvec3d> points;
std::vector<qvec3d> corners;
std::vector<std::array<size_t, 2>> edges;
};
/*
==============================================================================
@ -294,30 +288,35 @@ This is done by brute force, and could easily get a lot faster if anyone cares.
==============================================================================
*/
struct hullbrush_t {
bspbrush_t &brush;
std::vector<qvec3d> points;
std::vector<qvec3d> corners;
std::vector<std::array<size_t, 2>> edges;
};
/*
============
AddBrushPlane
=============
*/
static void
AddBrushPlane(hullbrush_t &hullbrush, const qbsp_plane_t &plane)
static bool AddBrushPlane(hullbrush_t &hullbrush, const qbsp_plane_t &plane)
{
vec_t len = qv::length(plane.get_normal());
if (len < 1.0 - NORMAL_EPSILON || len > 1.0 + NORMAL_EPSILON)
Error("%s: invalid normal (vector length %.4f)", __func__, len);
for (auto &s : hullbrush.brush.sides) {
if (qv::epsilonEqual(s.get_plane(), plane)) {
return;
return false;
}
}
auto &s = hullbrush.brush.sides.emplace_back();
s.planenum = map.add_or_find_plane(plane);
s.texinfo = 0;
return true;
}
/*
============
TestAddPlane
@ -326,48 +325,41 @@ Adds the given plane to the brush description if all of the original brush
vertexes can be put on the front side
=============
*/
static void
TestAddPlane(hullbrush_t &hullbrush, qbsp_plane_t plane)
static bool TestAddPlane(hullbrush_t &hullbrush, const qbsp_plane_t &plane)
{
int i, c;
vec_t d;
qvec3d *corner;
qbsp_plane_t flip;
bool points_front, points_back;
/* see if the plane has already been added */
for (auto &s : hullbrush.brush.sides) {
if (qv::epsilonEqual(plane, s.get_plane()))
return;
if (qv::epsilonEqual(-plane, s.get_plane()))
return;
if (qv::epsilonEqual(plane, s.get_plane()) ||
qv::epsilonEqual(plane, s.get_positive_plane())) {
return false;
}
}
/* check all the corner points */
points_front = false;
points_back = false;
bool points_front = false;
bool points_back = false;
corner = &hullbrush.corners.front();
c = hullbrush.points.size() * 8;
for (size_t i = 0; i < hullbrush.corners.size(); i++) {
vec_t d = qv::dot(hullbrush.corners[i], plane.get_normal()) - plane.get_dist();
for (i = 0; i < c; i++, corner++) {
d = qv::dot(*corner, plane.get_normal()) - plane.get_dist();
if (d < -qbsp_options.epsilon.value()) {
if (points_front)
return;
if (points_front) {
return false;
}
points_back = true;
} else if (d > qbsp_options.epsilon.value()) {
if (points_back)
return;
if (points_back) {
return false;
}
points_front = true;
}
}
// the plane is a seperator
if (points_front) {
AddBrushPlane(hullbrush, -plane);
return AddBrushPlane(hullbrush, -plane);
} else {
AddBrushPlane(hullbrush, plane);
return AddBrushPlane(hullbrush, plane);
}
}
@ -378,29 +370,25 @@ AddHullPoint
Doesn't add if duplicated
=============
*/
static size_t
AddHullPoint(hullbrush_t &hullbrush, const qvec3d &p, const aabb3d &hull_size)
static size_t AddHullPoint(hullbrush_t &hullbrush, const qvec3d &p, const aabb3d &hull_size)
{
size_t i;
int x, y, z;
for (i = 0; i < hullbrush.points.size(); i++)
if (qv::epsilonEqual(p, hullbrush.points[i], EQUAL_EPSILON))
return i;
for (auto &pt : hullbrush.points) {
if (qv::epsilonEqual(p, pt, EQUAL_EPSILON)) {
return &pt - hullbrush.points.data();
}
}
hullbrush.points.emplace_back(p);
for (x = 0; x < 2; x++)
for (y = 0; y < 2; y++)
for (z = 0; z < 2; z++) {
qvec3d c;
c[0] = p[0] + hull_size[x][0];
c[1] = p[1] + hull_size[y][1];
c[2] = p[2] + hull_size[z][2];
hullbrush.corners.emplace_back(c);
for (size_t x = 0; x < 2; x++) {
for (size_t y = 0; y < 2; y++) {
for (size_t z = 0; z < 2; z++) {
hullbrush.corners.emplace_back(p + qvec3d { hull_size[x][0], hull_size[y][1], hull_size[z][2] });
}
}
}
return i;
return hullbrush.points.size() - 1;
}
@ -408,121 +396,120 @@ AddHullPoint(hullbrush_t &hullbrush, const qvec3d &p, const aabb3d &hull_size)
============
AddHullEdge
Creates all of the hull planes around the given edge, if not done allready
Creates all of the hull planes around the given edge, if not done already
=============
*/
static void
AddHullEdge(hullbrush_t &hullbrush, const qvec3d &p1, const qvec3d &p2, const aabb3d &hull_size)
static bool AddHullEdge(hullbrush_t &hullbrush, const qvec3d &p1, const qvec3d &p2, const aabb3d &hull_size)
{
size_t pt1, pt2;
int i;
int a, b, c, d, e;
qvec3d edgevec, planeorg, planevec;
qplane3d plane;
vec_t length;
std::array<size_t, 2> edge = {
AddHullPoint(hullbrush, p1, hull_size),
AddHullPoint(hullbrush, p2, hull_size)
};
pt1 = AddHullPoint(hullbrush, p1, hull_size);
pt2 = AddHullPoint(hullbrush, p2, hull_size);
for (auto &e : hullbrush.edges) {
if (e == edge || e == decltype(edge) { edge[1], edge[0] }) {
return false;
}
}
for (i = 0; i < hullbrush.edges.size(); i++)
if ((hullbrush.edges[i][0] == pt1 && hullbrush.edges[i][1] == pt2)
|| (hullbrush.edges[i][0] == pt2 && hullbrush.edges[i][1] == pt1))
return;
hullbrush.edges.emplace_back(edge);
hullbrush.edges.push_back({ pt1, pt2 });
edgevec = p1 - p2;
qv::normalizeInPlace(edgevec);
for (a = 0; a < 3; a++) {
b = (a + 1) % 3;
c = (a + 2) % 3;
qvec3d edgevec = qv::normalize(p1 - p2);
bool added = false;
for (size_t a = 0; a < 3; a++) {
qvec3d planevec{};
planevec[a] = 1;
planevec[b] = 0;
planevec[c] = 0;
qplane3d plane;
plane.normal = qv::cross(planevec, edgevec);
length = qv::normalizeInPlace(plane.normal);
vec_t length = qv::normalizeInPlace(plane.normal);
/* If this edge is almost parallel to the hull edge, skip it. */
if (length < ANGLEEPSILON)
if (length < ANGLEEPSILON) {
continue;
}
for (d = 0; d <= 1; d++) {
for (e = 0; e <= 1; e++) {
planeorg = p1;
size_t b = (a + 1) % 3;
size_t c = (a + 2) % 3;
for (size_t d = 0; d < 2; d++) {
for (size_t e = 0; e < 2; e++) {
qvec3d planeorg = p1;
planeorg[b] += hull_size[d][b];
planeorg[c] += hull_size[e][c];
plane.dist = qv::dot(planeorg, plane.normal);
TestAddPlane(hullbrush, plane);
added = TestAddPlane(hullbrush, plane) || added;
}
}
}
}
return added;
}
/*
============
ExpandBrush
=============
*/
static void
ExpandBrush(hullbrush_t &hullbrush, const aabb3d &hull_size)
static void ExpandBrush(hullbrush_t &hullbrush, const aabb3d &hull_size)
{
int i, x, s;
qvec3d corner;
qplane3d plane;
int cBevEdge = 0;
size_t total_original_sides = hullbrush.brush.sides.size();
// create all the hull points
for (auto &f : hullbrush.brush.sides) {
if (!f.w) {
FError("bad input winding");
}
for (i = 0; i < f.w.size(); i++) {
AddHullPoint(hullbrush, f.w[i], hull_size);
cBevEdge++;
for (auto &pt : f.w) {
AddHullPoint(hullbrush, pt, hull_size);
}
}
// expand all of the planes
for (auto &f : hullbrush.brush.sides) {
if (f.get_texinfo().flags.no_expand)
if (f.get_texinfo().flags.no_expand) {
continue;
corner = {};
plane = f.get_plane();
for (x = 0; x < 3; x++) {
if (plane.normal[x] > 0)
}
qvec3d corner = {};
qplane3d plane = f.get_plane();
for (size_t x = 0; x < 3; x++) {
if (plane.normal[x] > 0) {
corner[x] = hull_size[1][x];
else if (plane.normal[x] < 0)
} else if (plane.normal[x] < 0) {
corner[x] = hull_size[0][x];
}
}
plane.dist += qv::dot(corner, plane.normal);
f.planenum = map.add_or_find_plane(plane);
}
// add any axis planes not contained in the brush to bevel off corners
for (x = 0; x < 3; x++)
for (s = -1; s <= 1; s += 2) {
for (size_t x = 0; x < 3; x++) {
for (int32_t s = -1; s <= 1; s += 2) {
// add the plane
qplane3d plane;
plane.normal = {};
plane.normal[x] = (vec_t)s;
if (s == -1)
plane.normal[x] = (vec_t) s;
if (s == -1) {
plane.dist = -hullbrush.brush.bounds.mins()[x] + -hull_size[0][x];
else
} else {
plane.dist = hullbrush.brush.bounds.maxs()[x] + hull_size[1][x];
}
AddBrushPlane(hullbrush, plane);
}
}
// add all of the edge bevels
for (size_t f = 0; f < total_original_sides; f++) {
auto &side = hullbrush.brush.sides[f];
for (size_t f = 0; f < hullbrush.brush.sides.size(); f++) {
auto *side = &hullbrush.brush.sides[f];
auto *w = &side->w;
for (i = 0; i < side.w.size(); i++)
AddHullEdge(hullbrush, side.w[i],
side.w[(i + 1) % side.w.size()], hull_size);
for (size_t i = 0; i < w->size(); i++) {
if (AddHullEdge(hullbrush, (*w)[i], (*w)[(i + 1) % w->size()], hull_size)) {
// re-fetch ptrs
side = &hullbrush.brush.sides[f];
w = &side->w;
}
}
}
}
#endif

View File

@ -1638,6 +1638,9 @@ static std::optional<mapface_t> ParseBrushFace(parser_t &parser, const mapbrush_
return face;
}
#define QBSP3
#ifdef QBSP3
/*
=================
AddBrushBevels
@ -1738,11 +1741,22 @@ inline void AddBrushBevels(mapentity_t &e, mapbrush_t &b)
qplane3d plane {};
plane.normal[axis] = dir;
plane.normal = qv::cross(vec, plane.normal);
if (qv::normalizeInPlace(plane.normal) < 0.5) {
// If this edge is almost parallel to the hull edge, skip it
if (qv::normalizeInPlace(plane.normal) < ANGLEEPSILON) {
continue;
}
plane.dist = qv::dot(b.faces[i].winding[j], plane.normal);
auto w = BaseWindingForPlane<winding_t>(plane);
if (fabs(trunc(w[0][0])) == 693 ||
fabs(trunc(w[1][0])) == 693 ||
fabs(trunc(w[2][0])) == 693) {
__debugbreak();
}
// if all the points on all the sides are
// behind this plane, it is a proper edge bevel
for (k = 0; k < b.faces.size(); k++) {
@ -1792,6 +1806,267 @@ inline void AddBrushBevels(mapentity_t &e, mapbrush_t &b)
}
}
}
#else
/*
==============================================================================
BEVELED CLIPPING HULL GENERATION
This is done by brute force, and could easily get a lot faster if anyone cares.
==============================================================================
*/
struct map_hullbrush_t {
mapentity_t &entity;
mapbrush_t &brush;
std::vector<qvec3d> points;
std::vector<qvec3d> corners;
std::vector<std::array<size_t, 2>> edges;
};
/*
============
AddBrushPlane
=============
*/
static bool AddBrushPlane(map_hullbrush_t &hullbrush, const qbsp_plane_t &plane, size_t &index)
{
for (auto &s : hullbrush.brush.faces) {
if (qv::epsilonEqual(s.get_plane(), plane)) {
index = &s - hullbrush.brush.faces.data();
return false;
}
}
index = hullbrush.brush.faces.size();
auto &s = hullbrush.brush.faces.emplace_back();
s.planenum = map.add_or_find_plane(plane);
// add this plane
s.texinfo = hullbrush.brush.faces[0].texinfo;
s.contents = hullbrush.brush.faces[0].contents;
// fixme: why did we need to store all this stuff again, isn't
// it in texinfo?
s.raw_info = hullbrush.brush.faces[0].raw_info;
s.flags = hullbrush.brush.faces[0].flags;
s.texname = hullbrush.brush.faces[0].texname;
s.value = hullbrush.brush.faces[0].value;
s.bevel = true;
return true;
}
/*
============
TestAddPlane
Adds the given plane to the brush description if all of the original brush
vertexes can be put on the front side
=============
*/
static bool TestAddPlane(map_hullbrush_t &hullbrush, const qbsp_plane_t &plane)
{
/* see if the plane has already been added */
for (auto &s : hullbrush.brush.faces) {
if (qv::epsilonEqual(plane, s.get_plane()) ||
qv::epsilonEqual(plane, s.get_positive_plane())) {
return false;
}
}
/* check all the corner points */
bool points_front = false;
bool points_back = false;
for (size_t i = 0; i < hullbrush.corners.size(); i++) {
vec_t d = qv::dot(hullbrush.corners[i], plane.get_normal()) - plane.get_dist();
if (d < -qbsp_options.epsilon.value()) {
if (points_front) {
return false;
}
points_back = true;
} else if (d > qbsp_options.epsilon.value()) {
if (points_back) {
return false;
}
points_front = true;
}
}
bool added;
size_t index;
// the plane is a seperator
if (points_front) {
added = AddBrushPlane(hullbrush, -plane, index);
} else {
added = AddBrushPlane(hullbrush, plane, index);
}
if (added) {
hullbrush.entity.numedgebevels++;
}
return added;
}
/*
============
AddHullPoint
Doesn't add if duplicated
=============
*/
static size_t AddHullPoint(map_hullbrush_t &hullbrush, const qvec3d &p, const aabb3d &hull_size)
{
for (auto &pt : hullbrush.points) {
if (qv::epsilonEqual(p, pt, EQUAL_EPSILON)) {
return &pt - hullbrush.points.data();
}
}
hullbrush.points.emplace_back(p);
for (size_t x = 0; x < 2; x++) {
for (size_t y = 0; y < 2; y++) {
for (size_t z = 0; z < 2; z++) {
hullbrush.corners.emplace_back(p + qvec3d { hull_size[x][0], hull_size[y][1], hull_size[z][2] });
}
}
}
return hullbrush.points.size() - 1;
}
/*
============
AddHullEdge
Creates all of the hull planes around the given edge, if not done already
=============
*/
static bool AddHullEdge(map_hullbrush_t &hullbrush, const qvec3d &p1, const qvec3d &p2, const aabb3d &hull_size)
{
std::array<size_t, 2> edge = {
AddHullPoint(hullbrush, p1, hull_size),
AddHullPoint(hullbrush, p2, hull_size)
};
for (auto &e : hullbrush.edges) {
if (e == edge || e == decltype(edge) { edge[1], edge[0] }) {
return false;
}
}
hullbrush.edges.emplace_back(edge);
qvec3d edgevec = qv::normalize(p1 - p2);
bool added = false;
for (size_t a = 0; a < 3; a++) {
qvec3d planevec{};
planevec[a] = 1;
qplane3d plane;
plane.normal = qv::cross(planevec, edgevec);
vec_t length = qv::normalizeInPlace(plane.normal);
/* If this edge is almost parallel to the hull edge, skip it. */
if (length < ANGLEEPSILON) {
continue;
}
size_t b = (a + 1) % 3;
size_t c = (a + 2) % 3;
for (size_t d = 0; d < 2; d++) {
for (size_t e = 0; e < 2; e++) {
qvec3d planeorg = p1;
planeorg[b] += hull_size[d][b];
planeorg[c] += hull_size[e][c];
plane.dist = qv::dot(planeorg, plane.normal);
added = TestAddPlane(hullbrush, plane) || added;
}
}
}
return added;
}
/*
============
ExpandBrush
=============
*/
static void ExpandBrush(map_hullbrush_t &hullbrush, const aabb3d &hull_size)
{
size_t total_original_sides = hullbrush.brush.faces.size();
// create all the hull points
for (auto &f : hullbrush.brush.faces) {
for (auto &pt : f.winding) {
AddHullPoint(hullbrush, pt, hull_size);
}
}
// expand all of the planes
for (auto &f : hullbrush.brush.faces) {
/*if (f.get_texinfo().flags.no_expand) {
continue;
}*/
qvec3d corner = {};
qplane3d plane = f.get_plane();
for (size_t x = 0; x < 3; x++) {
if (plane.normal[x] > 0) {
corner[x] = hull_size[1][x];
} else if (plane.normal[x] < 0) {
corner[x] = hull_size[0][x];
}
}
plane.dist += qv::dot(corner, plane.normal);
f.planenum = map.add_or_find_plane(plane);
}
// add any axis planes not contained in the brush to bevel off corners
for (size_t x = 0, o = 0; x < 3; x++) {
for (int32_t s = -1; s <= 1; s += 2, o++) {
// add the plane
qplane3d plane;
plane.normal = {};
plane.normal[x] = (vec_t) s;
if (s == -1) {
plane.dist = -hullbrush.brush.bounds.mins()[x] + -hull_size[0][x];
} else {
plane.dist = hullbrush.brush.bounds.maxs()[x] + hull_size[1][x];
}
size_t index;
AddBrushPlane(hullbrush, plane, index);
// if the plane is not in it canonical order, swap it
if (index != o) {
std::swap(hullbrush.brush.faces[o], hullbrush.brush.faces[index]);
}
}
}
// add all of the edge bevels
for (size_t f = 0; f < hullbrush.brush.faces.size(); f++) {
auto *side = &hullbrush.brush.faces[f];
auto *w = &side->winding;
for (size_t i = 0; i < w->size(); i++) {
if (AddHullEdge(hullbrush, (*w)[i], (*w)[(i + 1) % w->size()], hull_size)) {
// re-fetch ptrs
side = &hullbrush.brush.faces[f];
w = &side->winding;
}
}
}
}
#endif
static contentflags_t Brush_GetContents(const mapbrush_t &mapbrush)
{
@ -2260,6 +2535,63 @@ inline bool MapBrush_IsHint(const mapbrush_t &brush)
return false;
}
/*
==================
WriteBspBrushMap
from q3map
==================
*/
inline void WriteMapBrushMap(const fs::path &name, const std::vector<mapbrush_t> &list, const aabb3d &hull)
{
logging::print("writing {}\n", name);
std::ofstream f(name);
if (!f)
FError("Can't write {}", name);
fmt::print(f, "{{\n\"classname\" \"worldspawn\"\n");
for (auto &brush : list) {
fmt::print(f, "{{\n");
for (auto &face : brush.faces) {
qvec3d corner = {};
qplane3d plane = face.get_plane();
for (size_t x = 0; x < 3; x++) {
if (plane.normal[x] > 0) {
corner[x] = hull[1][x];
} else if (plane.normal[x] < 0) {
corner[x] = hull[0][x];
}
}
plane.dist += qv::dot(corner, plane.normal);
winding_t w = BaseWindingForPlane<winding_t>(plane);
fmt::print(f, "( {} ) ", w[0]);
fmt::print(f, "( {} ) ", w[1]);
fmt::print(f, "( {} ) ", w[2]);
#if 0
if (face.visible) {
fmt::print(f, "skip 0 0 0 1 1\n");
} else {
fmt::print(f, "nonvisible 0 0 0 1 1\n");
}
#endif
fmt::print(f, "{} 0 0 0 1 1\n", face.texname);
}
fmt::print(f, "}}\n");
}
fmt::print(f, "}}\n");
f.close();
}
void ProcessMapBrushes()
{
logging::funcheader();
@ -2334,7 +2666,14 @@ void ProcessMapBrushes()
num_faces += old_num_faces;
// add the brush bevels
#ifdef QBSP3
AddBrushBevels(entity, brush);
#else
{
map_hullbrush_t hullbrush { entity, brush };
ExpandBrush(hullbrush, { { 0, 0, 0 }, { 0, 0, 0 } });
}
#endif
for (auto &f : brush.faces) {
f.lmshift = brush.lmshift;
@ -2418,6 +2757,24 @@ void ProcessMapBrushes()
logging::print(logging::flag::STAT, " {:8} brushes translated from origins\n", num_offset);
}
logging::print(logging::flag::STAT, "\n");
if (qbsp_options.debugexpand.isChanged()) {
aabb3d hull;
if (qbsp_options.debugexpand.is_hull()) {
const auto &hulls = qbsp_options.target_game->get_hull_sizes();
if (hulls.size() <= qbsp_options.debugexpand.hull_index_value()) {
FError("invalid hull index passed to debugexpand\n");
}
hull = *(hulls.begin() + qbsp_options.debugexpand.hull_index_value());
} else {
hull = qbsp_options.debugexpand.hull_bounds_value();
}
WriteMapBrushMap("expanded.map", map.world_entity()->mapbrushes, hull);
}
}
void LoadMapFile(void)
@ -2847,29 +3204,3 @@ void WriteBspBrushMap(const fs::path &name, const bspbrush_t::container &list)
f.close();
}
/*
================
TestExpandBrushes
Expands all the brush planes and saves a new map out to
allow visual inspection of the clipping bevels
from q3map
================
*/
static void TestExpandBrushes(mapentity_t *src)
{
bspbrush_t::container hull1brushes;
for (auto &mapbrush : src->mapbrushes) {
auto hull1brush = LoadBrush(src, &mapbrush, {CONTENTS_SOLID},
qbsp_options.target_game->id == GAME_QUAKE_II ? std::nullopt : std::optional<int32_t>(1), std::nullopt);
if (hull1brush) {
hull1brushes.emplace_back(bspbrush_t::make_ptr(std::move(*hull1brush)));
}
}
WriteBspBrushMap("expanded.map", hull1brushes);
}

View File

@ -953,10 +953,6 @@ void ProcessFile()
// handle load time operation on the .map
ProcessMapBrushes();
if (qbsp_options.expand.value()) {
TestExpandBrushes(map.world_entity());
}
// initialize secondary textures
LoadSecondaryTextures();