use an optional<uint8_t> to store hull number, which gets rid of special -1 collision hull number.
fixed no-hull always chopping even with chop off
This commit is contained in:
parent
20f5d73a3c
commit
f7b8f85ece
|
|
@ -464,12 +464,12 @@ static int BSP_FindClipnodeAtPoint_r(const mbsp_t *bsp, const int clipnodenum, c
|
|||
}
|
||||
}
|
||||
|
||||
int BSP_FindContentsAtPoint(const mbsp_t *bsp, int hull, const dmodelh2_t *model, const qvec3d &point)
|
||||
int BSP_FindContentsAtPoint(const mbsp_t *bsp, hull_index_t hullnum, const dmodelh2_t *model, const qvec3d &point)
|
||||
{
|
||||
if (hull == 0) {
|
||||
if (!hullnum.value_or(0)) {
|
||||
return BSP_FindLeafAtPoint_r(bsp, model->headnode[0], point)->contents;
|
||||
}
|
||||
return BSP_FindClipnodeAtPoint_r(bsp, model->headnode.at(hull), point);
|
||||
return BSP_FindClipnodeAtPoint_r(bsp, model->headnode.at(hullnum.value()), point);
|
||||
}
|
||||
|
||||
std::vector<const mface_t *> Leaf_Markfaces(const mbsp_t *bsp, const mleaf_t *leaf)
|
||||
|
|
|
|||
|
|
@ -421,6 +421,9 @@ struct fmt::formatter<texvec<T>> : formatter<qmat<T, 2, 4>>
|
|||
|
||||
using texvecf = texvec<float>;
|
||||
|
||||
// type to store a hull index; max 256 hulls, zero is valid.
|
||||
using hull_index_t = std::optional<uint8_t>;
|
||||
|
||||
#include "bspfile_generic.hh"
|
||||
#include "bspfile_q1.hh"
|
||||
#include "bspfile_q2.hh"
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ const bsp2_dnode_t *BSP_FindNodeAtPoint(
|
|||
const mbsp_t *bsp, const dmodelh2_t *model, const qvec3d &point, const qvec3d &wanted_normal);
|
||||
|
||||
const mleaf_t *BSP_FindLeafAtPoint(const mbsp_t *bsp, const dmodelh2_t *model, const qvec3d &point);
|
||||
int BSP_FindContentsAtPoint(const mbsp_t *bsp, int hull, const dmodelh2_t *model, const qvec3d &point);
|
||||
int BSP_FindContentsAtPoint(const mbsp_t *bsp, hull_index_t hullnum, const dmodelh2_t *model, const qvec3d &point);
|
||||
|
||||
std::vector<const mface_t *> Leaf_Markfaces(const mbsp_t *bsp, const mleaf_t *leaf);
|
||||
std::vector<const dbrush_t *> Leaf_Brushes(const mbsp_t *bsp, const mleaf_t *leaf);
|
||||
|
|
|
|||
|
|
@ -595,12 +595,14 @@ std::tuple<qvec<T, 3>, qvec<T, 3>> MakeTangentAndBitangentUnnormalized(const qve
|
|||
}
|
||||
|
||||
// debug test
|
||||
#ifdef PARANOID
|
||||
if (0) {
|
||||
auto n = qv::normalize(qv::cross(tangent, bitangent));
|
||||
double d = qv::distance(n, normal);
|
||||
|
||||
assert(d < 0.0001);
|
||||
}
|
||||
#endif
|
||||
|
||||
return {tangent, bitangent};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,5 +93,5 @@ struct bspbrush_t
|
|||
bspbrush_t clone() const;
|
||||
};
|
||||
|
||||
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum, std::optional<std::reference_wrapper<size_t>> num_clipped);
|
||||
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, hull_index_t hullnum, std::optional<std::reference_wrapper<size_t>> num_clipped);
|
||||
bool CreateBrushWindings(bspbrush_t *brush);
|
||||
|
|
@ -139,7 +139,7 @@ struct maptexdata_t
|
|||
surfflags_t flags;
|
||||
int32_t value;
|
||||
std::string animation;
|
||||
int32_t animation_miptex = -1;
|
||||
std::optional<int32_t> animation_miptex = std::nullopt;
|
||||
};
|
||||
|
||||
#include <common/imglib.hh>
|
||||
|
|
@ -342,18 +342,15 @@ void WriteEntitiesToString();
|
|||
|
||||
qvec3d FixRotateOrigin(mapentity_t *entity);
|
||||
|
||||
/** Special ID for the collision-only hull; used for wrbrushes/Q2 */
|
||||
constexpr int HULL_COLLISION = -1;
|
||||
|
||||
/* Create BSP brushes from map brushes */
|
||||
void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes, size_t &num_clipped);
|
||||
void Brush_LoadEntity(mapentity_t *entity, hull_index_t hullnum, bspbrush_t::container &brushes, size_t &num_clipped);
|
||||
|
||||
std::list<face_t *> CSGFace(
|
||||
face_t *srcface, const mapentity_t *srcentity, const bspbrush_t *srcbrush, const node_t *srcnode);
|
||||
void TJunc(node_t *headnode);
|
||||
int MakeFaceEdges(node_t *headnode);
|
||||
void EmitVertices(node_t *headnode);
|
||||
void ExportClipNodes(mapentity_t *entity, node_t *headnode, const int hullnum);
|
||||
void ExportClipNodes(mapentity_t *entity, node_t *headnode, hull_index_t::value_type hullnum);
|
||||
void ExportDrawNodes(mapentity_t *entity, node_t *headnode, int firstface);
|
||||
|
||||
struct bspxbrushes_s
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class mapentity_t;
|
|||
struct node_t;
|
||||
struct tree_t;
|
||||
|
||||
bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes);
|
||||
bool FillOutside(mapentity_t *entity, tree_t *tree, hull_index_t hullnum, bspbrush_t::container &brushes);
|
||||
std::vector<node_t *> FindOccupiedClusters(node_t *headnode);
|
||||
|
||||
void FillBrushEntity(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes);
|
||||
void FillBrushEntity(mapentity_t *entity, tree_t *tree, hull_index_t hullnum, bspbrush_t::container &brushes);
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ struct maptexinfo_t
|
|||
int32_t miptex = 0;
|
||||
surfflags_t flags = {};
|
||||
int32_t value = 0; // Q2-specific
|
||||
int32_t next = -1; // Q2-specific
|
||||
std::optional<int32_t> next = std::nullopt; // Q2-specific
|
||||
std::optional<size_t> outputnum = std::nullopt; // nullopt until added to bsp
|
||||
|
||||
constexpr auto as_tuple() const { return std::tie(vecs, miptex, flags, value, next); }
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ Converts a mapbrush to a bsp brush
|
|||
===============
|
||||
*/
|
||||
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents,
|
||||
const int hullnum, std::optional<std::reference_wrapper<size_t>> num_clipped)
|
||||
hull_index_t hullnum, std::optional<std::reference_wrapper<size_t>> num_clipped)
|
||||
{
|
||||
// create the brush
|
||||
bspbrush_t brush{};
|
||||
|
|
@ -295,7 +295,7 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush
|
|||
for (size_t i = 0; i < mapbrush->faces.size(); i++) {
|
||||
auto &src = mapbrush->faces[i];
|
||||
|
||||
if (hullnum <= 0 && mapbrush->is_hint) {
|
||||
if (!hullnum.value_or(0) && mapbrush->is_hint) {
|
||||
/* Don't generate hintskip faces */
|
||||
const maptexinfo_t &texinfo = map.mtexinfos.at(src.texinfo);
|
||||
|
||||
|
|
@ -306,23 +306,22 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush
|
|||
}
|
||||
|
||||
// don't add bevels for the point hull
|
||||
if (hullnum <= 0 && src.bevel) {
|
||||
if (!hullnum.value_or(0) && src.bevel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &dst = brush.sides.emplace_back();
|
||||
|
||||
dst.texinfo = hullnum > 0 ? 0 : src.texinfo;
|
||||
dst.texinfo = hullnum.value_or(0) ? 0 : src.texinfo;
|
||||
dst.planenum = src.planenum;
|
||||
dst.bevel = src.bevel;
|
||||
dst.source = &src;
|
||||
}
|
||||
|
||||
// expand the brushes for the hull
|
||||
if (hullnum > 0) {
|
||||
if (hullnum.value_or(0)) {
|
||||
auto &hulls = qbsp_options.target_game->get_hull_sizes();
|
||||
Q_assert(hullnum < hulls.size());
|
||||
auto &hull = *(hulls.begin() + hullnum);
|
||||
auto &hull = *(hulls.begin() + hullnum.value());
|
||||
|
||||
for (auto &mapface : brush.sides) {
|
||||
if (mapface.get_texinfo().flags.no_expand) {
|
||||
|
|
@ -365,8 +364,8 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush
|
|||
// The idea behind the bounds expansion was to avoid incorrect vis culling (AFAIK).
|
||||
const bool shouldExpand = (src->origin[0] != 0.0 || src->origin[1] != 0.0 || src->origin[2] != 0.0) &&
|
||||
src->rotation == rotation_t::hipnotic &&
|
||||
(hullnum >= 0) // hullnum < 0 corresponds to -wrbrushes clipping hulls
|
||||
&& qbsp_options.target_game->id != GAME_HEXEN_II; // never do this in Hexen 2
|
||||
hullnum.has_value() &&
|
||||
qbsp_options.target_game->id != GAME_HEXEN_II; // never do this in Hexen 2
|
||||
|
||||
if (shouldExpand) {
|
||||
vec_t max = -std::numeric_limits<vec_t>::infinity(), min = std::numeric_limits<vec_t>::infinity();
|
||||
|
|
@ -389,7 +388,7 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush
|
|||
|
||||
//=============================================================================
|
||||
|
||||
static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hullnum, content_stats_base_t &stats, bspbrush_t::container &brushes, logging::percent_clock &clock, size_t &num_clipped)
|
||||
static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, hull_index_t hullnum, content_stats_base_t &stats, bspbrush_t::container &brushes, logging::percent_clock &clock, size_t &num_clipped)
|
||||
{
|
||||
// _omitbrushes 1 just discards all brushes in the entity.
|
||||
// could be useful for geometry guides, selective compilation, etc.
|
||||
|
|
@ -477,7 +476,7 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
|
|||
|
||||
/* func_detail_illusionary don't exist in the collision hull
|
||||
* (or bspx export) except for Q2, who needs them in there */
|
||||
if (hullnum > 0 && detail_illusionary) {
|
||||
if (hullnum.value_or(0) && detail_illusionary) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -486,8 +485,8 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
|
|||
* include them in the model bounds so collision detection works
|
||||
* correctly.
|
||||
*/
|
||||
if (hullnum != HULL_COLLISION && contents.is_clip(qbsp_options.target_game)) {
|
||||
if (hullnum == 0) {
|
||||
if (hullnum.has_value() && contents.is_clip(qbsp_options.target_game)) {
|
||||
if (hullnum.value() == 0) {
|
||||
if (auto brush = LoadBrush(src, &mapbrush, contents, hullnum, num_clipped)) {
|
||||
dst->bounds += brush->bounds;
|
||||
}
|
||||
|
|
@ -500,8 +499,9 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
|
|||
|
||||
/* "hint" brushes don't affect the collision hulls */
|
||||
if (mapbrush.is_hint) {
|
||||
if (hullnum > 0)
|
||||
if (hullnum.value_or(0)) {
|
||||
continue;
|
||||
}
|
||||
contents = qbsp_options.target_game->create_empty_contents();
|
||||
}
|
||||
|
||||
|
|
@ -517,18 +517,20 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
|
|||
before writing the bsp, and bmodels normally have CONTENTS_SOLID as their
|
||||
contents type.
|
||||
*/
|
||||
if (hullnum <= 0 && mirrorinside.value_or(false)) {
|
||||
if (!hullnum.value_or(0) && mirrorinside.value_or(false)) {
|
||||
contents = qbsp_options.target_game->create_detail_fence_contents(contents);
|
||||
}
|
||||
}
|
||||
|
||||
/* nonsolid brushes don't show up in clipping hulls */
|
||||
if (hullnum > 0 && !contents.is_any_solid(qbsp_options.target_game) && !contents.is_sky(qbsp_options.target_game))
|
||||
continue;
|
||||
if (hullnum.value_or(0)) {
|
||||
/* nonsolid brushes don't show up in clipping hulls */
|
||||
if (!contents.is_any_solid(qbsp_options.target_game) && !contents.is_sky(qbsp_options.target_game))
|
||||
continue;
|
||||
|
||||
/* sky brushes are solid in the collision hulls */
|
||||
if (hullnum > 0 && contents.is_sky(qbsp_options.target_game))
|
||||
contents = qbsp_options.target_game->create_solid_contents();
|
||||
/* sky brushes are solid in the collision hulls */
|
||||
if (contents.is_sky(qbsp_options.target_game))
|
||||
contents = qbsp_options.target_game->create_solid_contents();
|
||||
}
|
||||
|
||||
// apply extended flags
|
||||
contents.set_mirrored(mirrorinside);
|
||||
|
|
@ -552,11 +554,11 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
|
|||
============
|
||||
Brush_LoadEntity
|
||||
|
||||
hullnum HULL_COLLISION should contain ALL brushes. (used by BSPX_CreateBrushList())
|
||||
hullnum nullopt should contain ALL brushes; BSPX and Quake II, etc.
|
||||
hullnum 0 does not contain clip brushes.
|
||||
============
|
||||
*/
|
||||
void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes, size_t &num_clipped)
|
||||
void Brush_LoadEntity(mapentity_t *entity, hull_index_t hullnum, bspbrush_t::container &brushes, size_t &num_clipped)
|
||||
{
|
||||
logging::funcheader();
|
||||
|
||||
|
|
|
|||
|
|
@ -395,10 +395,10 @@ int FindTexinfo(const maptexinfo_t &texinfo)
|
|||
assert(map.mtexinfo_lookup.find(texinfo) != map.mtexinfo_lookup.end());
|
||||
|
||||
// create a copy of the miptex for animation chains
|
||||
if (map.miptex[texinfo.miptex].animation_miptex != -1) {
|
||||
if (map.miptex[texinfo.miptex].animation_miptex.has_value()) {
|
||||
maptexinfo_t anim_next = texinfo;
|
||||
|
||||
anim_next.miptex = map.miptex[texinfo.miptex].animation_miptex;
|
||||
anim_next.miptex = map.miptex[texinfo.miptex].animation_miptex.value();
|
||||
|
||||
map.mtexinfos[num_texinfo].next = FindTexinfo(anim_next);
|
||||
}
|
||||
|
|
@ -2869,7 +2869,7 @@ static void TestExpandBrushes(mapentity_t *src)
|
|||
|
||||
for (auto &mapbrush : src->mapbrushes) {
|
||||
auto hull1brush = LoadBrush(src, &mapbrush, {CONTENTS_SOLID},
|
||||
qbsp_options.target_game->id == GAME_QUAKE_II ? HULL_COLLISION : 1, std::nullopt);
|
||||
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)));
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@ get incorrectly marked as "invisible").
|
|||
Special cases: structural fully covered by detail still needs to be marked "visible".
|
||||
===========
|
||||
*/
|
||||
bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes)
|
||||
bool FillOutside(mapentity_t *entity, tree_t *tree, hull_index_t hullnum, bspbrush_t::container &brushes)
|
||||
{
|
||||
node_t *node = tree->headnode;
|
||||
|
||||
|
|
@ -604,7 +604,7 @@ bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_
|
|||
}
|
||||
|
||||
if (occupied_clusters.empty()) {
|
||||
logging::print("WARNING: No entities in empty space -- no filling performed (hull {})\n", hullnum);
|
||||
logging::print("WARNING: No entities in empty space -- no filling performed (hull {})\n", hullnum.value_or(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -705,7 +705,7 @@ bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_
|
|||
return true;
|
||||
}
|
||||
|
||||
void FillBrushEntity(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes)
|
||||
void FillBrushEntity(mapentity_t *entity, tree_t *tree, hull_index_t hullnum, bspbrush_t::container &brushes)
|
||||
{
|
||||
logging::funcheader();
|
||||
|
||||
|
|
|
|||
181
qbsp/qbsp.cc
181
qbsp/qbsp.cc
|
|
@ -393,7 +393,7 @@ static void CountLeafs(node_t *headnode)
|
|||
ProcessEntity
|
||||
===============
|
||||
*/
|
||||
static void ProcessEntity(mapentity_t *entity, const int hullnum)
|
||||
static void ProcessEntity(mapentity_t *entity, hull_index_t hullnum)
|
||||
{
|
||||
/* No map brushes means non-bmodel entity.
|
||||
We need to handle worldspawn containing no brushes, though. */
|
||||
|
|
@ -426,8 +426,9 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
|
|||
if (qbsp_options.verbose.value())
|
||||
PrintEntity(entity);
|
||||
|
||||
if (hullnum <= 0)
|
||||
if (!hullnum.value_or(0) || qbsp_options.loghulls.value()) {
|
||||
logging::print(logging::flag::STAT, " MODEL: {}\n", mod);
|
||||
}
|
||||
entity->epairs.set("model", mod);
|
||||
}
|
||||
}
|
||||
|
|
@ -461,8 +462,8 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
|
|||
|
||||
logging::print(logging::flag::STAT, "INFO: calculating BSP for {} brushes with {} sides\n", brushes.size(), num_sides);
|
||||
|
||||
// always chop the other hulls
|
||||
if (qbsp_options.chop.value() || hullnum != 0) {
|
||||
// always chop the other hulls to reduce brush tests
|
||||
if (qbsp_options.chop.value() || hullnum.value_or(0)) {
|
||||
ChopBrushes(brushes);
|
||||
}
|
||||
|
||||
|
|
@ -474,7 +475,9 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
|
|||
}
|
||||
|
||||
std::unique_ptr<tree_t> tree = nullptr;
|
||||
if (hullnum > 0) {
|
||||
|
||||
// simpler operation for hulls
|
||||
if (hullnum.value_or(0)) {
|
||||
tree = BrushBSP(entity, brushes, true);
|
||||
if (entity == map.world_entity() && !qbsp_options.nofill.value()) {
|
||||
// assume non-world bmodels are simple
|
||||
|
|
@ -490,88 +493,89 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
|
|||
PruneNodes(tree->headnode);
|
||||
}
|
||||
}
|
||||
ExportClipNodes(entity, tree->headnode, hullnum);
|
||||
ExportClipNodes(entity, tree->headnode, hullnum.value());
|
||||
return;
|
||||
}
|
||||
|
||||
// fixme-brushbsp: return here?
|
||||
// full operation for collision (or main hull)
|
||||
|
||||
if (qbsp_options.forcegoodtree.value()) {
|
||||
tree = BrushBSP(entity, brushes, false);
|
||||
} else {
|
||||
tree = BrushBSP(entity, brushes, entity == map.world_entity() ? std::nullopt : std::optional<bool>(false));
|
||||
}
|
||||
|
||||
if (qbsp_options.forcegoodtree.value()) {
|
||||
tree = BrushBSP(entity, brushes, false);
|
||||
} else {
|
||||
tree = BrushBSP(entity, brushes, entity == map.world_entity() ? std::nullopt : std::optional<bool>(false));
|
||||
}
|
||||
// build all the portals in the bsp tree
|
||||
// some portals are solid polygons, and some are paths to other leafs
|
||||
MakeTreePortals(tree.get());
|
||||
|
||||
// build all the portals in the bsp tree
|
||||
// some portals are solid polygons, and some are paths to other leafs
|
||||
MakeTreePortals(tree.get());
|
||||
|
||||
if (entity == map.world_entity()) {
|
||||
// flood fills from the void.
|
||||
// marks brush sides which are *only* touching void;
|
||||
// we can skip using them as BSP splitters on the "really good tree"
|
||||
// (effectively expanding those brush sides outwards).
|
||||
if (!qbsp_options.nofill.value() && FillOutside(entity, tree.get(), hullnum, brushes)) {
|
||||
// make a really good tree
|
||||
tree.reset();
|
||||
tree = BrushBSP(entity, brushes, false);
|
||||
|
||||
// make the real portals for vis tracing
|
||||
MakeTreePortals(tree.get());
|
||||
|
||||
// fill again so PruneNodes works
|
||||
FillOutside(entity, tree.get(), hullnum, brushes);
|
||||
}
|
||||
|
||||
// Area portals
|
||||
if (qbsp_options.target_game->id == GAME_QUAKE_II) {
|
||||
FloodAreas(entity, tree->headnode);
|
||||
EmitAreaPortals(tree->headnode);
|
||||
}
|
||||
} else {
|
||||
FillBrushEntity(entity, tree.get(), hullnum, brushes);
|
||||
|
||||
// rebuild BSP now that we've marked invisible brush sides
|
||||
if (entity == map.world_entity()) {
|
||||
// flood fills from the void.
|
||||
// marks brush sides which are *only* touching void;
|
||||
// we can skip using them as BSP splitters on the "really good tree"
|
||||
// (effectively expanding those brush sides outwards).
|
||||
if (!qbsp_options.nofill.value() && FillOutside(entity, tree.get(), hullnum, brushes)) {
|
||||
// make a really good tree
|
||||
tree.reset();
|
||||
tree = BrushBSP(entity, brushes, false);
|
||||
|
||||
// make the real portals for vis tracing
|
||||
MakeTreePortals(tree.get());
|
||||
|
||||
// fill again so PruneNodes works
|
||||
FillOutside(entity, tree.get(), hullnum, brushes);
|
||||
}
|
||||
|
||||
MakeTreePortals(tree.get());
|
||||
|
||||
MarkVisibleSides(tree.get(), entity, brushes);
|
||||
MakeFaces(tree->headnode);
|
||||
|
||||
FreeTreePortals(tree.get());
|
||||
PruneNodes(tree->headnode);
|
||||
|
||||
if (hullnum <= 0 && entity == map.world_entity() && (!map.leakfile || qbsp_options.keepprt.value())) {
|
||||
WritePortalFile(tree.get());
|
||||
}
|
||||
|
||||
// needs to come after any face creation
|
||||
MakeMarkFaces(tree->headnode);
|
||||
|
||||
CountLeafs(tree->headnode);
|
||||
|
||||
// output vertices first, since TJunc needs it
|
||||
EmitVertices(tree->headnode);
|
||||
|
||||
TJunc(tree->headnode);
|
||||
|
||||
if (qbsp_options.objexport.value() && entity == map.world_entity()) {
|
||||
ExportObj_Nodes("pre_makefaceedges_plane_faces", tree->headnode);
|
||||
ExportObj_Marksurfaces("pre_makefaceedges_marksurfaces", tree->headnode);
|
||||
}
|
||||
|
||||
Q_assert(!entity->firstoutputfacenumber.has_value());
|
||||
|
||||
entity->firstoutputfacenumber = MakeFaceEdges(tree->headnode);
|
||||
|
||||
// Area portals
|
||||
if (qbsp_options.target_game->id == GAME_QUAKE_II) {
|
||||
ExportBrushList(entity, tree->headnode);
|
||||
FloodAreas(entity, tree->headnode);
|
||||
EmitAreaPortals(tree->headnode);
|
||||
}
|
||||
} else {
|
||||
FillBrushEntity(entity, tree.get(), hullnum, brushes);
|
||||
|
||||
ExportDrawNodes(entity, tree->headnode, entity->firstoutputfacenumber.value());
|
||||
// rebuild BSP now that we've marked invisible brush sides
|
||||
tree.reset();
|
||||
tree = BrushBSP(entity, brushes, false);
|
||||
}
|
||||
|
||||
MakeTreePortals(tree.get());
|
||||
|
||||
MarkVisibleSides(tree.get(), entity, brushes);
|
||||
MakeFaces(tree->headnode);
|
||||
|
||||
FreeTreePortals(tree.get());
|
||||
PruneNodes(tree->headnode);
|
||||
|
||||
// write out .prt for main hull
|
||||
if (!hullnum.value_or(0) && entity == map.world_entity() && (!map.leakfile || qbsp_options.keepprt.value())) {
|
||||
WritePortalFile(tree.get());
|
||||
}
|
||||
|
||||
// needs to come after any face creation
|
||||
MakeMarkFaces(tree->headnode);
|
||||
|
||||
CountLeafs(tree->headnode);
|
||||
|
||||
// output vertices first, since TJunc needs it
|
||||
EmitVertices(tree->headnode);
|
||||
|
||||
TJunc(tree->headnode);
|
||||
|
||||
if (qbsp_options.objexport.value() && entity == map.world_entity()) {
|
||||
ExportObj_Nodes("pre_makefaceedges_plane_faces", tree->headnode);
|
||||
ExportObj_Marksurfaces("pre_makefaceedges_marksurfaces", tree->headnode);
|
||||
}
|
||||
|
||||
Q_assert(!entity->firstoutputfacenumber.has_value());
|
||||
|
||||
entity->firstoutputfacenumber = MakeFaceEdges(tree->headnode);
|
||||
|
||||
if (qbsp_options.target_game->id == GAME_QUAKE_II) {
|
||||
ExportBrushList(entity, tree->headnode);
|
||||
}
|
||||
|
||||
ExportDrawNodes(entity, tree->headnode, entity->firstoutputfacenumber.value());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -767,10 +771,12 @@ static void BSPX_CreateBrushList(void)
|
|||
CreateSingleHull
|
||||
=================
|
||||
*/
|
||||
static void CreateSingleHull(const int hullnum)
|
||||
static void CreateSingleHull(hull_index_t hullnum)
|
||||
{
|
||||
if (hullnum >= 0) {
|
||||
logging::print("Processing hull {}...\n", hullnum);
|
||||
if (hullnum.has_value()) {
|
||||
logging::print("Processing hull {}...\n", hullnum.value());
|
||||
} else {
|
||||
logging::print("Processing map...\n");
|
||||
}
|
||||
|
||||
// for each entity in the map file that has geometry
|
||||
|
|
@ -781,7 +787,7 @@ static void CreateSingleHull(const int hullnum)
|
|||
if (&entity != map.world_entity()) {
|
||||
wants_logging = wants_logging && qbsp_options.logbmodels.value();
|
||||
}
|
||||
if (hullnum > 0) {
|
||||
if (hullnum.value_or(0)) {
|
||||
wants_logging = wants_logging && qbsp_options.loghulls.value();
|
||||
}
|
||||
|
||||
|
|
@ -818,14 +824,17 @@ static void CreateHulls(void)
|
|||
|
||||
// game has no hulls, so we have to export brush lists and stuff.
|
||||
if (!hulls.size()) {
|
||||
CreateSingleHull(HULL_COLLISION);
|
||||
CreateSingleHull(std::nullopt);
|
||||
return;
|
||||
}
|
||||
|
||||
// all the hulls
|
||||
for (size_t i = 0; i < hulls.size(); i++) {
|
||||
CreateSingleHull(i);
|
||||
|
||||
// only create hull 0 if fNoclip is set
|
||||
} else if (qbsp_options.noclip.value()) {
|
||||
CreateSingleHull(0);
|
||||
// do all the hulls
|
||||
} else {
|
||||
for (size_t i = 0; i < hulls.size(); i++) {
|
||||
CreateSingleHull(i);
|
||||
if (qbsp_options.noclip.value()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ size_t ExportMapTexinfo(size_t texinfonum)
|
|||
|
||||
src.outputnum = i;
|
||||
|
||||
if (src.next != -1) {
|
||||
map.bsp.texinfo[i].nexttexinfo = ExportMapTexinfo(src.next);
|
||||
if (src.next.has_value()) {
|
||||
map.bsp.texinfo[i].nexttexinfo = ExportMapTexinfo(src.next.value());
|
||||
}
|
||||
|
||||
return i;
|
||||
|
|
@ -127,7 +127,7 @@ First time just store away data, second time fix up reference points to
|
|||
accomodate new data interleaved with old.
|
||||
==================
|
||||
*/
|
||||
void ExportClipNodes(mapentity_t *entity, node_t *nodes, const int hullnum)
|
||||
void ExportClipNodes(mapentity_t *entity, node_t *nodes, hull_index_t::value_type hullnum)
|
||||
{
|
||||
auto &model = map.bsp.dmodels.at(entity->outputmodelnumber.value());
|
||||
model.headnode[hullnum] = ExportClipNodes(nodes);
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ static std::tuple<mbsp_t, bspxentries_t, std::optional<prtfile_t>> LoadTestmapQ1
|
|||
#endif
|
||||
}
|
||||
|
||||
static void CheckFilled(const mbsp_t &bsp, int hullnum)
|
||||
static void CheckFilled(const mbsp_t &bsp, hull_index_t hullnum)
|
||||
{
|
||||
int32_t contents = BSP_FindContentsAtPoint(&bsp, hullnum, &bsp.dmodels[0], qvec3d{8192, 8192, 8192});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue