From 5f81657621fd8a1c99f470762b48aff56f9e6b3d Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 23 Jan 2022 00:46:11 -0500 Subject: [PATCH] move calculatesurfaceinfo into a member func --- include/qbsp/qbsp.hh | 196 ++++++++++++++++++++++----------------- include/qbsp/solidbsp.hh | 1 - qbsp/csg4.cc | 2 +- qbsp/solidbsp.cc | 40 +------- qbsp/surfaces.cc | 2 +- 5 files changed, 116 insertions(+), 125 deletions(-) diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index f3034332..06bc82a4 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -42,6 +42,88 @@ #include #include +enum texcoord_style_t +{ + TX_QUAKED = 0, + TX_QUARK_TYPE1 = 1, + TX_QUARK_TYPE2 = 2, + TX_VALVE_220 = 3, + TX_BRUSHPRIM = 4 +}; + +enum class conversion_t +{ + quake, + quake2, + valve, + bp +}; + +class options_t +{ +public: + bool fNofill = false; + bool fNoclip = false; + bool fNoskip = false; + bool fNodetail = false; + bool fOnlyents = false; + bool fConvertMapFormat = false; + conversion_t convertMapFormat = conversion_t::quake; + bool fVerbose = true; + bool fAllverbose = false; + bool fSplitspecial = false; + bool fSplitturb = false; + bool fSplitsky = false; + bool fTranswater = true; + bool fTranssky = false; + bool fOldaxis = true; + bool fNoverbose = false; + bool fNopercent = false; + bool forceGoodTree = false; + bool fixRotateObjTexture = true; + bool fbspx_brushes = false; + bool fNoTextures = false; + const bspversion_t *target_version = &bspver_q1; + const gamedef_t *target_game = target_version->game; + int dxSubdivide = 240; + int dxLeakDist = 2; + int maxNodeSize = 1024; + /** + * if 0 (default), use maxNodeSize for deciding when to switch to midsplit bsp heuristic. + * + * if 0 < midsplitSurfFraction <=1, switch to midsplit if the node contains more than this fraction of the model's + * total surfaces. Try 0.15 to 0.5. Works better than maxNodeSize for maps with a 3D skybox (e.g. +-128K unit maps) + */ + float midsplitSurfFraction = 0.f; + std::filesystem::path szMapName; + std::filesystem::path szBSPName; + + struct wadpath + { + std::filesystem::path path; + bool external; // wads from this path are not to be embedded into the bsp, but will instead require the engine + // to load them from elsewhere. strongly recommended for eg halflife.wad + }; + + std::vector wadPathsVec; + vec_t on_epsilon = 0.0001; + bool fObjExport = false; + bool fOmitDetail = false; + bool fOmitDetailWall = false; + bool fOmitDetailIllusionary = false; + bool fOmitDetailFence = false; + bool fForcePRT1 = false; + bool fTestExpand = false; + bool fLeakTest = false; + bool fContentHack = false; + vec_t worldExtent = 65536.0f; + bool fNoThreads = false; + bool includeSkip = false; + bool fNoTJunc = false; +}; + +extern options_t options; + /* * Clipnodes need to be stored as a 16-bit offset. Originally, this was a * signed value and only the positive values up to 32767 were available. Since @@ -149,14 +231,39 @@ struct surface_t surface_t *next; int planenum; std::optional outputplanenum; // only valid after WriteSurfacePlanes - aabb3d bounds; bool onnode; // true if surface has already been used // as a splitting node bool detail_separator; // true if ALL faces are detail face_t *faces; // links to all faces on either side of the surf - bool has_detail; // 1 if the surface has detail brushes - bool has_struct; // 1 if the surface has non-detail brushes + + // bounds of all the face windings; calculated via calculateInfo + aabb3d bounds; + // 1 if the surface has non-detail brushes; calculated via calculateInfo + bool has_struct; + // smallest lmshift of all faces; calculated via calculateInfo short lmshift; + + // calculate bounds & info + inline void calculateInfo() + { + bounds = {}; + lmshift = std::numeric_limits::max(); + + for (const face_t *f = faces; f; f = f->next) { + for (auto &contents : f->contents) + if (!contents.is_valid(options.target_game, false)) + FError("Bad contents in face: {}", contents.to_string(options.target_game)); + + lmshift = min(f->lmshift.front, f->lmshift.back); + + has_struct = !((f->contents[0].extended | f->contents[1].extended) & + (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE | CFLAGS_WAS_ILLUSIONARY)); + + bounds += f->w.bounds(); + + Q_assert(!qv::emptyExact(bounds.size())); + } + } }; // there is a node_t structure for every node and leaf in the bsp tree @@ -202,89 +309,6 @@ struct node_t #include #include #include - -enum texcoord_style_t -{ - TX_QUAKED = 0, - TX_QUARK_TYPE1 = 1, - TX_QUARK_TYPE2 = 2, - TX_VALVE_220 = 3, - TX_BRUSHPRIM = 4 -}; - -enum class conversion_t -{ - quake, - quake2, - valve, - bp -}; - -class options_t -{ -public: - bool fNofill = false; - bool fNoclip = false; - bool fNoskip = false; - bool fNodetail = false; - bool fOnlyents = false; - bool fConvertMapFormat = false; - conversion_t convertMapFormat = conversion_t::quake; - bool fVerbose = true; - bool fAllverbose = false; - bool fSplitspecial = false; - bool fSplitturb = false; - bool fSplitsky = false; - bool fTranswater = true; - bool fTranssky = false; - bool fOldaxis = true; - bool fNoverbose = false; - bool fNopercent = false; - bool forceGoodTree = false; - bool fixRotateObjTexture = true; - bool fbspx_brushes = false; - bool fNoTextures = false; - const bspversion_t *target_version = &bspver_q1; - const gamedef_t *target_game = target_version->game; - int dxSubdivide = 240; - int dxLeakDist = 2; - int maxNodeSize = 1024; - /** - * if 0 (default), use maxNodeSize for deciding when to switch to midsplit bsp heuristic. - * - * if 0 < midsplitSurfFraction <=1, switch to midsplit if the node contains more than this fraction of the model's - * total surfaces. Try 0.15 to 0.5. Works better than maxNodeSize for maps with a 3D skybox (e.g. +-128K unit maps) - */ - float midsplitSurfFraction = 0.f; - std::filesystem::path szMapName; - std::filesystem::path szBSPName; - - struct wadpath - { - std::filesystem::path path; - bool external; // wads from this path are not to be embedded into the bsp, but will instead require the engine - // to load them from elsewhere. strongly recommended for eg halflife.wad - }; - - std::vector wadPathsVec; - vec_t on_epsilon = 0.0001; - bool fObjExport = false; - bool fOmitDetail = false; - bool fOmitDetailWall = false; - bool fOmitDetailIllusionary = false; - bool fOmitDetailFence = false; - bool fForcePRT1 = false; - bool fTestExpand = false; - bool fLeakTest = false; - bool fContentHack = false; - vec_t worldExtent = 65536.0f; - bool fNoThreads = false; - bool includeSkip = false; - bool fNoTJunc = false; -}; - -extern options_t options; - #include int qbsp_main(int argc, const char **argv); diff --git a/include/qbsp/solidbsp.hh b/include/qbsp/solidbsp.hh index 1c9c5f37..aea7cfaa 100644 --- a/include/qbsp/solidbsp.hh +++ b/include/qbsp/solidbsp.hh @@ -26,5 +26,4 @@ extern std::atomic splitnodes; void DetailToSolid(node_t *node); -void CalcSurfaceInfo(surface_t *surf); void SubdivideFace(face_t *f, face_t **prevptr); diff --git a/qbsp/csg4.cc b/qbsp/csg4.cc index b9957594..4c299f42 100644 --- a/qbsp/csg4.cc +++ b/qbsp/csg4.cc @@ -478,7 +478,7 @@ surface_t *BuildSurfaces(const std::map &planefaces) csgmergefaces++; /* Calculate bounding box and flags */ - CalcSurfaceInfo(surf); + surf->calculateInfo(); } return surfaces; diff --git a/qbsp/solidbsp.cc b/qbsp/solidbsp.cc index 194cffe5..fd8e3334 100644 --- a/qbsp/solidbsp.cc +++ b/qbsp/solidbsp.cc @@ -491,38 +491,6 @@ static surface_t *SelectPartition(surface_t *surfaces) //============================================================================ -/* -================= -CalcSurfaceInfo - -Calculates the bounding box -================= -*/ -void CalcSurfaceInfo(surface_t *surf) -{ - // calculate a bounding box - surf->bounds = {}; - - surf->has_struct = false; - - for (const face_t *f = surf->faces; f; f = f->next) { - for (auto &contents : f->contents) - if (!contents.is_valid(options.target_game, false)) - FError("Bad contents in face: {}", contents.to_string(options.target_game)); - - surf->lmshift = min(f->lmshift.front, f->lmshift.back); - - surf->has_struct = !((f->contents[0].extended | f->contents[1].extended) & - (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE | CFLAGS_WAS_ILLUSIONARY)); - - for (int i = 0; i < f->w.size(); i++) { - surf->bounds += f->w[i]; - } - - Q_assert(!qv::emptyExact(surf->bounds.size())); - } -} - /* ================== DividePlane @@ -560,8 +528,8 @@ static void DividePlane(surface_t *in, const qplane3d &split, surface_t **front, // ericw -- added these CalcSurfaceInfo to recalculate the surf bbox. // pretty sure their omission here was a bug. - CalcSurfaceInfo(newsurf); - CalcSurfaceInfo(in); + newsurf->calculateInfo(); + in->calculateInfo(); if (in->faces) *front = in; @@ -626,8 +594,8 @@ static void DividePlane(surface_t *in, const qplane3d &split, surface_t **front, *front = in; // recalc bboxes and flags - CalcSurfaceInfo(newsurf); - CalcSurfaceInfo(in); + newsurf->calculateInfo(); + in->calculateInfo(); } /* diff --git a/qbsp/surfaces.cc b/qbsp/surfaces.cc index 14eb2ac3..2dd40e9f 100644 --- a/qbsp/surfaces.cc +++ b/qbsp/surfaces.cc @@ -109,7 +109,7 @@ void SubdivideFace(face_t *f, face_t **prevptr) next = f->next; SplitFace(f, plane, &front, &back); if (!front || !back) { - printf("didn't split\n"); + LogPrintLocked("didn't split\n"); break; // FError("Didn't split the polygon"); }