Merge branch 'brushbsp' of https://github.com/ericwa/ericw-tools into brushbsp
This commit is contained in:
commit
8b1472dfd1
|
|
@ -53,7 +53,7 @@ constexpr vec_t DIST_EPSILON = 0.0001;
|
|||
constexpr vec_t DEGREES_EPSILON = 0.001;
|
||||
constexpr vec_t DEFAULT_ON_EPSILON = 0.1;
|
||||
|
||||
enum side_t : int8_t
|
||||
enum planeside_t : int8_t
|
||||
{
|
||||
SIDE_FRONT,
|
||||
SIDE_BACK,
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@ public:
|
|||
|
||||
// dists/sides can be null, or must have (size() + 1) reserved
|
||||
inline std::array<size_t, SIDE_TOTAL> calc_sides(
|
||||
const qplane3d &plane, vec_t *dists, side_t *sides, const vec_t &on_epsilon = DEFAULT_ON_EPSILON) const
|
||||
const qplane3d &plane, vec_t *dists, planeside_t *sides, const vec_t &on_epsilon = DEFAULT_ON_EPSILON) const
|
||||
{
|
||||
std::array<size_t, SIDE_TOTAL> counts{};
|
||||
|
||||
|
|
@ -554,7 +554,7 @@ public:
|
|||
dists[i] = dot;
|
||||
}
|
||||
|
||||
side_t side;
|
||||
planeside_t side;
|
||||
|
||||
if (dot > on_epsilon)
|
||||
side = SIDE_FRONT;
|
||||
|
|
@ -593,7 +593,7 @@ public:
|
|||
const qplane3d &plane, const vec_t &on_epsilon = DEFAULT_ON_EPSILON, const bool &keepon = false) const
|
||||
{
|
||||
vec_t *dists = (vec_t *)alloca(sizeof(vec_t) * (count + 1));
|
||||
side_t *sides = (side_t *)alloca(sizeof(side_t) * (count + 1));
|
||||
planeside_t *sides = (planeside_t *)alloca(sizeof(planeside_t) * (count + 1));
|
||||
|
||||
std::array<size_t, SIDE_TOTAL> counts = calc_sides(plane, dists, sides, on_epsilon);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,16 +28,33 @@
|
|||
|
||||
class mapentity_t;
|
||||
|
||||
struct brush_t
|
||||
struct side_t
|
||||
{
|
||||
winding_t w;
|
||||
int planenum;
|
||||
planeside_t planeside; // which side is the front of the face
|
||||
int texinfo;
|
||||
|
||||
int16_t lmshift;
|
||||
|
||||
qvec3d origin;
|
||||
vec_t radius;
|
||||
|
||||
bool onnode; // has this face been used as a BSP node plane yet?
|
||||
bool visible = true; // can any part of this side be seen from non-void parts of the level?
|
||||
// non-visible means we can discard the brush side
|
||||
// (avoiding generating a BSP spit, so expanding it outwards)
|
||||
};
|
||||
|
||||
struct bspbrush_t {
|
||||
/**
|
||||
* The brushes in the mapentity_t::brushes vector are considered originals. Brush fragments created during
|
||||
* the BrushBSP will have this pointing back to the original brush in mapentity_t::brushes.
|
||||
*/
|
||||
brush_t *original;
|
||||
bspbrush_t *original;
|
||||
uint32_t file_order;
|
||||
aabb3d bounds;
|
||||
std::vector<face_t> faces;
|
||||
std::vector<side_t> sides;
|
||||
contentflags_t contents; /* BSP contents */
|
||||
short lmshift; /* lightmap scaling (qu/lightmap pixel), passed to the light util */
|
||||
std::optional<uint32_t> outputnumber; /* only set for original brushes */
|
||||
|
|
@ -49,6 +66,7 @@ struct brush_t
|
|||
class mapbrush_t;
|
||||
|
||||
qplane3d Face_Plane(const face_t *face);
|
||||
qplane3d Face_Plane(const side_t *face);
|
||||
|
||||
enum class rotation_t
|
||||
{
|
||||
|
|
@ -57,10 +75,10 @@ enum class rotation_t
|
|||
origin_brush
|
||||
};
|
||||
|
||||
std::optional<brush_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 qvec3d &rotate_offset, const rotation_t rottype, const int hullnum);
|
||||
void FreeBrushes(mapentity_t *ent);
|
||||
|
||||
int FindPlane(const qplane3d &plane, side_t *side);
|
||||
int FindPlane(const qplane3d &plane, planeside_t *side);
|
||||
int FindPositivePlane(int planenum);
|
||||
int FindPositivePlane(const qplane3d &plane, side_t *side);
|
||||
int FindPositivePlane(const qplane3d &plane, planeside_t *side);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
extern std::atomic<int> splitnodes;
|
||||
|
||||
struct brush_t;
|
||||
struct bspbrush_t;
|
||||
struct node_t;
|
||||
struct face_t;
|
||||
class mapentity_t;
|
||||
|
|
@ -40,5 +40,5 @@ struct tree_t;
|
|||
void DetailToSolid(node_t *node);
|
||||
void PruneNodes(node_t *node);
|
||||
bool WindingIsTiny(const winding_t &w, double size = 0.2);
|
||||
twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, const qplane3d &split);
|
||||
twosided<std::unique_ptr<bspbrush_t>> SplitBrush(std::unique_ptr<bspbrush_t> brush, const qplane3d &split);
|
||||
tree_t *BrushBSP(mapentity_t *entity, bool midsplit);
|
||||
|
|
@ -27,13 +27,15 @@
|
|||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
struct brush_t;
|
||||
struct bspbrush_t;
|
||||
struct face_t;
|
||||
struct side_t;
|
||||
|
||||
face_t *NewFaceFromFace(const face_t *in);
|
||||
face_t *CopyFace(const face_t *in);
|
||||
face_t *MirrorFace(const face_t *face);
|
||||
std::tuple<face_t *, face_t *> SplitFace(face_t *in, const qplane3d &split);
|
||||
void UpdateFaceSphere(face_t *in);
|
||||
bool BrushGE(const brush_t &a, const brush_t &b);
|
||||
std::vector<std::unique_ptr<brush_t>> ChopBrushes(const std::vector<std::unique_ptr<brush_t>> &input);
|
||||
void UpdateFaceSphere(side_t *in);
|
||||
bool BrushGE(const bspbrush_t &a, const bspbrush_t &b);
|
||||
std::vector<std::unique_ptr<bspbrush_t>> ChopBrushes(const std::vector<std::unique_ptr<bspbrush_t>> &input);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
struct brush_t;
|
||||
struct bspbrush_t;
|
||||
|
||||
struct qbsp_plane_t : qplane3d
|
||||
{
|
||||
|
|
@ -102,7 +102,7 @@ public:
|
|||
entdict_t epairs;
|
||||
|
||||
aabb3d bounds;
|
||||
std::vector<std::unique_ptr<brush_t>> brushes;
|
||||
std::vector<std::unique_ptr<bspbrush_t>> brushes;
|
||||
|
||||
int firstoutputfacenumber = -1;
|
||||
std::optional<size_t> outputmodelnumber = std::nullopt;
|
||||
|
|
@ -218,7 +218,7 @@ constexpr int HULL_COLLISION = -1;
|
|||
/* Create BSP brushes from map brushes */
|
||||
void Brush_LoadEntity(mapentity_t *entity, const int hullnum);
|
||||
|
||||
std::list<face_t *> CSGFace(face_t *srcface, const mapentity_t* srcentity, const brush_t *srcbrush, const node_t *srcnode);
|
||||
std::list<face_t *> CSGFace(face_t *srcface, const mapentity_t* srcentity, const bspbrush_t *srcbrush, const node_t *srcnode);
|
||||
void TJunc(const mapentity_t *entity, node_t *headnode);
|
||||
int MakeFaceEdges(mapentity_t *entity, node_t *headnode);
|
||||
void ExportClipNodes(mapentity_t *entity, node_t *headnode, const int hullnum);
|
||||
|
|
@ -232,10 +232,10 @@ void BSPX_Brushes_Finalize(struct bspxbrushes_s *ctx);
|
|||
void BSPX_Brushes_Init(struct bspxbrushes_s *ctx);
|
||||
|
||||
void ExportObj_Faces(const std::string &filesuffix, const std::vector<const face_t *> &faces);
|
||||
void ExportObj_Brushes(const std::string &filesuffix, const std::vector<const brush_t *> &brushes);
|
||||
void ExportObj_Brushes(const std::string &filesuffix, const std::vector<const bspbrush_t *> &brushes);
|
||||
void ExportObj_Nodes(const std::string &filesuffix, const node_t *nodes);
|
||||
void ExportObj_Marksurfaces(const std::string &filesuffix, const node_t *nodes);
|
||||
|
||||
void WriteBspBrushMap(const fs::path &name, const std::vector<std::unique_ptr<brush_t>> &list);
|
||||
void WriteBspBrushMap(const fs::path &name, const std::vector<std::unique_ptr<bspbrush_t>> &list);
|
||||
|
||||
bool IsValidTextureProjection(const qvec3f &faceNormal, const qvec3f &s_vec, const qvec3f &t_vec);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <atomic>
|
||||
|
||||
struct side_t;
|
||||
|
||||
struct portal_t
|
||||
{
|
||||
int planenum;
|
||||
|
|
@ -35,7 +37,7 @@ struct portal_t
|
|||
std::optional<winding_t> winding;
|
||||
|
||||
bool sidefound; // false if ->side hasn't been checked
|
||||
face_t *side; // NULL = non-visible // fixme-brushbsp: change to side_t
|
||||
side_t *side; // NULL = non-visible
|
||||
face_t *face[2]; // output face in bsp file
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -332,10 +332,10 @@ struct portal_t;
|
|||
struct face_t : face_fragment_t
|
||||
{
|
||||
int planenum;
|
||||
side_t planeside; // which side is the front of the face
|
||||
planeside_t planeside; // which side is the front of the face
|
||||
int texinfo;
|
||||
twosided<contentflags_t> contents;
|
||||
twosided<int16_t> lmshift;
|
||||
contentflags_t contents; // contents on the front of the face
|
||||
int16_t lmshift;
|
||||
|
||||
qvec3d origin;
|
||||
vec_t radius;
|
||||
|
|
@ -343,17 +343,12 @@ struct face_t : face_fragment_t
|
|||
// filled by TJunc
|
||||
std::vector<face_fragment_t> fragments;
|
||||
|
||||
// fixme-brushbsp: move to a brush_side_t struct
|
||||
bool onnode; // has this face been used as a BSP node plane yet?
|
||||
bool visible = true; // can any part of this side be seen from non-void parts of the level?
|
||||
// non-visible means we can discard the brush side
|
||||
// (avoiding generating a BSP spit, so expanding it outwards)
|
||||
portal_t *portal;
|
||||
};
|
||||
|
||||
// there is a node_t structure for every node and leaf in the bsp tree
|
||||
|
||||
struct brush_t;
|
||||
struct bspbrush_t;
|
||||
|
||||
struct node_t
|
||||
{
|
||||
|
|
@ -369,7 +364,7 @@ struct node_t
|
|||
|
||||
// information for leafs
|
||||
contentflags_t contents; // leaf nodes (0 for decision nodes)
|
||||
std::vector<brush_t *> original_brushes;
|
||||
std::vector<bspbrush_t *> original_brushes;
|
||||
std::vector<face_t *> markfaces; // leaf nodes only, point to node faces
|
||||
portal_t *portals;
|
||||
int visleafnum; // -1 = solid
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ set(QBSP_INCLUDES
|
|||
${CMAKE_SOURCE_DIR}/include/qbsp/outside.hh
|
||||
${CMAKE_SOURCE_DIR}/include/qbsp/portals.hh
|
||||
${CMAKE_SOURCE_DIR}/include/qbsp/prtfile.hh
|
||||
${CMAKE_SOURCE_DIR}/include/qbsp/solidbsp.hh
|
||||
${CMAKE_SOURCE_DIR}/include/qbsp/brushbsp.hh
|
||||
${CMAKE_SOURCE_DIR}/include/qbsp/surfaces.hh
|
||||
${CMAKE_SOURCE_DIR}/include/qbsp/writebsp.hh)
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ set(QBSP_SOURCES
|
|||
${CMAKE_SOURCE_DIR}/qbsp/portals.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/prtfile.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/qbsp.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/solidbsp.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/brushbsp.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/surfaces.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/tjunc.cc
|
||||
${CMAKE_SOURCE_DIR}/qbsp/wad.cc
|
||||
|
|
|
|||
|
|
@ -65,6 +65,17 @@ qplane3d Face_Plane(const face_t *face)
|
|||
return result;
|
||||
}
|
||||
|
||||
qplane3d Face_Plane(const side_t *face)
|
||||
{
|
||||
const qplane3d &result = map.planes.at(face->planenum);
|
||||
|
||||
if (face->planeside) {
|
||||
return -result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CheckFace
|
||||
|
|
@ -72,7 +83,7 @@ CheckFace
|
|||
Note: this will not catch 0 area polygons
|
||||
=================
|
||||
*/
|
||||
static void CheckFace(face_t *face, const mapface_t &sourceface)
|
||||
static void CheckFace(side_t *face, const mapface_t &sourceface)
|
||||
{
|
||||
const qbsp_plane_t &plane = map.planes.at(face->planenum);
|
||||
|
||||
|
|
@ -206,7 +217,7 @@ static void PlaneHash_Add(const qplane3d &p, int index)
|
|||
* NewPlane
|
||||
* - Returns a global plane number and the side that will be the front
|
||||
*/
|
||||
static int NewPlane(const qplane3d &plane, side_t *side)
|
||||
static int NewPlane(const qplane3d &plane, planeside_t *side)
|
||||
{
|
||||
vec_t len = qv::length(plane.normal);
|
||||
|
||||
|
|
@ -235,7 +246,7 @@ static int NewPlane(const qplane3d &plane, side_t *side)
|
|||
* - Returns a global plane number and the side that will be the front
|
||||
* - if `side` is null, only an exact match will be fetched.
|
||||
*/
|
||||
int FindPlane(const qplane3d &plane, side_t *side)
|
||||
int FindPlane(const qplane3d &plane, planeside_t *side)
|
||||
{
|
||||
for (int i : map.planehash[plane_hash_fn(plane)]) {
|
||||
const qbsp_plane_t &p = map.planes.at(i);
|
||||
|
|
@ -268,7 +279,7 @@ int FindPositivePlane(int planenum)
|
|||
return FindPlane(-plane, nullptr);
|
||||
}
|
||||
|
||||
int FindPositivePlane(const qplane3d &plane, side_t *side)
|
||||
int FindPositivePlane(const qplane3d &plane, planeside_t *side)
|
||||
{
|
||||
int planenum = FindPlane(plane, side);
|
||||
int positive_plane = FindPositivePlane(planenum);
|
||||
|
|
@ -358,13 +369,13 @@ static bool MapBrush_IsHint(const mapbrush_t &brush)
|
|||
CreateBrushFaces
|
||||
=================
|
||||
*/
|
||||
static std::vector<face_t> CreateBrushFaces(const mapentity_t *src, hullbrush_t *hullbrush, const int hullnum,
|
||||
static std::vector<side_t> CreateBrushFaces(const mapentity_t *src, hullbrush_t *hullbrush, const int hullnum,
|
||||
const rotation_t rottype = rotation_t::none, const qvec3d &rotate_offset = {})
|
||||
{
|
||||
vec_t r;
|
||||
std::optional<winding_t> w;
|
||||
qbsp_plane_t plane;
|
||||
std::vector<face_t> facelist;
|
||||
std::vector<side_t> facelist;
|
||||
qvec3d point;
|
||||
vec_t max, min;
|
||||
|
||||
|
|
@ -405,7 +416,7 @@ static std::vector<face_t> CreateBrushFaces(const mapentity_t *src, hullbrush_t
|
|||
}
|
||||
|
||||
// this face is a keeper
|
||||
face_t &f = facelist.emplace_back();
|
||||
side_t &f = facelist.emplace_back();
|
||||
f.planenum = PLANENUM_LEAF;
|
||||
|
||||
f.w.resize(w->size());
|
||||
|
|
@ -660,7 +671,7 @@ static void AddHullEdge(hullbrush_t *hullbrush, const qvec3d &p1, const qvec3d &
|
|||
ExpandBrush
|
||||
=============
|
||||
*/
|
||||
static void ExpandBrush(hullbrush_t *hullbrush, const aabb3d &hull_size, std::vector<face_t> &facelist)
|
||||
static void ExpandBrush(hullbrush_t *hullbrush, const aabb3d &hull_size, std::vector<side_t> &facelist)
|
||||
{
|
||||
int x, s;
|
||||
qbsp_plane_t plane;
|
||||
|
|
@ -755,11 +766,11 @@ LoadBrush
|
|||
Converts a mapbrush to a bsp brush
|
||||
===============
|
||||
*/
|
||||
std::optional<brush_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 qvec3d &rotate_offset, const rotation_t rottype, const int hullnum)
|
||||
{
|
||||
hullbrush_t hullbrush;
|
||||
std::vector<face_t> facelist;
|
||||
std::vector<side_t> facelist;
|
||||
|
||||
// create the faces
|
||||
|
||||
|
|
@ -796,9 +807,9 @@ std::optional<brush_t> LoadBrush(const mapentity_t *src, const mapbrush_t *mapbr
|
|||
}
|
||||
|
||||
// create the brush
|
||||
brush_t brush{};
|
||||
bspbrush_t brush{};
|
||||
brush.contents = contents;
|
||||
brush.faces = std::move(facelist);
|
||||
brush.sides = std::move(facelist);
|
||||
brush.bounds = hullbrush.bounds;
|
||||
return brush;
|
||||
}
|
||||
|
|
@ -826,7 +837,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
continue;
|
||||
}
|
||||
|
||||
std::optional<brush_t> brush = LoadBrush(src, mapbrush, contents, {}, rotation_t::none, 0);
|
||||
std::optional<bspbrush_t> brush = LoadBrush(src, mapbrush, contents, {}, rotation_t::none, 0);
|
||||
|
||||
if (brush) {
|
||||
rotate_offset = brush->bounds.centroid();
|
||||
|
|
@ -946,7 +957,7 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
*/
|
||||
if (hullnum != HULL_COLLISION && contents.is_clip(options.target_game)) {
|
||||
if (hullnum == 0) {
|
||||
std::optional<brush_t> brush = LoadBrush(src, mapbrush, contents, rotate_offset, rottype, hullnum);
|
||||
std::optional<bspbrush_t> brush = LoadBrush(src, mapbrush, contents, rotate_offset, rottype, hullnum);
|
||||
|
||||
if (brush) {
|
||||
dst->bounds += brush->bounds;
|
||||
|
|
@ -996,21 +1007,21 @@ static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int
|
|||
contents.set_clips_same_type(clipsametype);
|
||||
contents.illusionary_visblocker = func_illusionary_visblocker;
|
||||
|
||||
std::optional<brush_t> brush = LoadBrush(src, mapbrush, contents, rotate_offset, rottype, hullnum);
|
||||
std::optional<bspbrush_t> brush = LoadBrush(src, mapbrush, contents, rotate_offset, rottype, hullnum);
|
||||
if (!brush)
|
||||
continue;
|
||||
|
||||
brush->lmshift = lmshift;
|
||||
|
||||
for (auto &face : brush->faces)
|
||||
face.lmshift = { (short) lmshift, (short) lmshift };
|
||||
for (auto &face : brush->sides)
|
||||
face.lmshift = lmshift;
|
||||
|
||||
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?
|
||||
}
|
||||
|
||||
options.target_game->count_contents_in_stats(brush->contents, stats);
|
||||
dst->brushes.push_back(std::make_unique<brush_t>(brush.value()));
|
||||
dst->brushes.push_back(std::make_unique<bspbrush_t>(brush.value()));
|
||||
dst->bounds += brush->bounds;
|
||||
}
|
||||
|
||||
|
|
@ -1057,10 +1068,10 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum)
|
|||
options.target_game->print_content_stats(stats, "brushes");
|
||||
}
|
||||
|
||||
void brush_t::update_bounds()
|
||||
void bspbrush_t::update_bounds()
|
||||
{
|
||||
this->bounds = {};
|
||||
for (const face_t &face : faces) {
|
||||
for (const auto &face : sides) {
|
||||
this->bounds = this->bounds.unionWith(face.w.bounds());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
See file, 'COPYING', for details.
|
||||
*/
|
||||
|
||||
#include <qbsp/solidbsp.hh>
|
||||
#include <qbsp/brushbsp.hh>
|
||||
|
||||
#include <climits>
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ FaceSide
|
|||
For BSP hueristic
|
||||
==================
|
||||
*/
|
||||
static int FaceSide__(const face_t *in, const qbsp_plane_t &split)
|
||||
static int FaceSide__(const winding_t &w, const qbsp_plane_t &split)
|
||||
{
|
||||
bool have_front, have_back;
|
||||
int i;
|
||||
|
|
@ -151,8 +151,8 @@ static int FaceSide__(const face_t *in, const qbsp_plane_t &split)
|
|||
|
||||
if (split.type < plane_type_t::PLANE_ANYX) {
|
||||
/* shortcut for axial planes */
|
||||
const vec_t *p = &in->w[0][static_cast<size_t>(split.type)];
|
||||
for (i = 0; i < in->w.size(); i++, p += 3) {
|
||||
const vec_t *p = &w[0][static_cast<size_t>(split.type)];
|
||||
for (i = 0; i < w.size(); i++, p += 3) {
|
||||
if (*p > split.dist + options.epsilon.value()) {
|
||||
if (have_back)
|
||||
return SIDE_ON;
|
||||
|
|
@ -165,8 +165,8 @@ static int FaceSide__(const face_t *in, const qbsp_plane_t &split)
|
|||
}
|
||||
} else {
|
||||
/* sloping planes take longer */
|
||||
for (i = 0; i < in->w.size(); i++) {
|
||||
const vec_t dot = split.distance_to(in->w[i]);
|
||||
for (i = 0; i < w.size(); i++) {
|
||||
const vec_t dot = split.distance_to(w[i]);
|
||||
if (dot > options.epsilon.value()) {
|
||||
if (have_back)
|
||||
return SIDE_ON;
|
||||
|
|
@ -196,7 +196,19 @@ inline int FaceSide(const face_t *in, const qbsp_plane_t &split)
|
|||
else if (dist < -in->radius)
|
||||
return SIDE_BACK;
|
||||
else
|
||||
return FaceSide__(in, split);
|
||||
return FaceSide__(in->w, split);
|
||||
}
|
||||
|
||||
inline int FaceSide(const side_t *in, const qbsp_plane_t &split)
|
||||
{
|
||||
vec_t dist = split.distance_to(in->origin);
|
||||
|
||||
if (dist > in->radius)
|
||||
return SIDE_FRONT;
|
||||
else if (dist < -in->radius)
|
||||
return SIDE_BACK;
|
||||
else
|
||||
return FaceSide__(in->w, split);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -309,13 +321,13 @@ ChooseMidPlaneFromList
|
|||
The clipping hull BSP doesn't worry about avoiding splits
|
||||
==================
|
||||
*/
|
||||
static const face_t *ChooseMidPlaneFromList(const std::vector<std::unique_ptr<brush_t>> &brushes, const aabb3d &bounds)
|
||||
static const side_t *ChooseMidPlaneFromList(const std::vector<std::unique_ptr<bspbrush_t>> &brushes, const aabb3d &bounds)
|
||||
{
|
||||
/* pick the plane that splits the least */
|
||||
vec_t bestaxialmetric = VECT_MAX;
|
||||
face_t *bestaxialsurface = nullptr;
|
||||
side_t *bestaxialsurface = nullptr;
|
||||
vec_t bestanymetric = VECT_MAX;
|
||||
face_t *bestanysurface = nullptr;
|
||||
side_t *bestanysurface = nullptr;
|
||||
|
||||
for (int pass = 0; pass < 2; pass++) {
|
||||
for (auto &brush : brushes) {
|
||||
|
|
@ -323,7 +335,7 @@ static const face_t *ChooseMidPlaneFromList(const std::vector<std::unique_ptr<br
|
|||
continue;
|
||||
}
|
||||
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
if (face.onnode)
|
||||
continue;
|
||||
if (!face.visible) {
|
||||
|
|
@ -375,12 +387,12 @@ The real BSP heuristic
|
|||
fixme-brushbsp: prefer splits that include a lot of brush sides?
|
||||
==================
|
||||
*/
|
||||
static const face_t *ChoosePlaneFromList(const std::vector<std::unique_ptr<brush_t>> &brushes, const aabb3d &bounds)
|
||||
static const side_t *ChoosePlaneFromList(const std::vector<std::unique_ptr<bspbrush_t>> &brushes, const aabb3d &bounds)
|
||||
{
|
||||
/* pick the plane that splits the least */
|
||||
int minsplits = INT_MAX - 1;
|
||||
vec_t bestdistribution = VECT_MAX;
|
||||
face_t *bestsurface = nullptr;
|
||||
side_t *bestsurface = nullptr;
|
||||
|
||||
/* passes:
|
||||
* 0: structural visible
|
||||
|
|
@ -397,7 +409,7 @@ static const face_t *ChoosePlaneFromList(const std::vector<std::unique_ptr<brush
|
|||
continue;
|
||||
}
|
||||
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
if (face.onnode) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -413,7 +425,7 @@ static const face_t *ChoosePlaneFromList(const std::vector<std::unique_ptr<brush
|
|||
// now check all of the other faces in `brushes` and count how many
|
||||
// would get split if we used `face` as the splitting plane
|
||||
for (auto &brush2 : brushes) {
|
||||
for (auto &face2 : brush2->faces) {
|
||||
for (auto &face2 : brush2->sides) {
|
||||
if (face2.planenum == face.planenum || face2.onnode)
|
||||
continue;
|
||||
if (!face2.visible)
|
||||
|
|
@ -477,7 +489,7 @@ returns NULL if the surface list can not be divided any more (a leaf)
|
|||
Called in parallel.
|
||||
==================
|
||||
*/
|
||||
static const face_t *SelectPartition(const std::vector<std::unique_ptr<brush_t>> &brushes)
|
||||
static const side_t *SelectPartition(const std::vector<std::unique_ptr<bspbrush_t>> &brushes)
|
||||
{
|
||||
// calculate a bounding box of the entire surfaceset
|
||||
aabb3d bounds;
|
||||
|
|
@ -569,11 +581,11 @@ BrushMostlyOnSide
|
|||
|
||||
==================
|
||||
*/
|
||||
side_t BrushMostlyOnSide(const brush_t &brush, const qplane3d &plane)
|
||||
planeside_t BrushMostlyOnSide(const bspbrush_t &brush, const qplane3d &plane)
|
||||
{
|
||||
vec_t max = 0;
|
||||
side_t side = SIDE_FRONT;
|
||||
for (auto &face : brush.faces) {
|
||||
planeside_t side = SIDE_FRONT;
|
||||
for (auto &face : brush.sides) {
|
||||
for (size_t j = 0; j < face.w.size(); j++) {
|
||||
vec_t d = qv::dot(face.w[j], plane.normal) - plane.dist;
|
||||
if (d > max) {
|
||||
|
|
@ -595,13 +607,13 @@ BrushVolume
|
|||
|
||||
==================
|
||||
*/
|
||||
vec_t BrushVolume(const brush_t &brush)
|
||||
vec_t BrushVolume(const bspbrush_t &brush)
|
||||
{
|
||||
// grab the first valid point as the corner
|
||||
|
||||
bool found = false;
|
||||
qvec3d corner;
|
||||
for (auto &face : brush.faces) {
|
||||
for (auto &face : brush.sides) {
|
||||
if (face.w.size() > 0) {
|
||||
corner = face.w[0];
|
||||
found = true;
|
||||
|
|
@ -614,7 +626,7 @@ vec_t BrushVolume(const brush_t &brush)
|
|||
// make tetrahedrons to all other faces
|
||||
|
||||
vec_t volume = 0;
|
||||
for (auto &face : brush.faces) {
|
||||
for (auto &face : brush.sides) {
|
||||
auto plane = Face_Plane(&face);
|
||||
vec_t d = -(qv::dot(corner, plane.normal) - plane.dist);
|
||||
vec_t area = face.w.area();
|
||||
|
|
@ -635,14 +647,14 @@ input.
|
|||
https://github.com/id-Software/Quake-2-Tools/blob/master/bsp/qbsp3/brushbsp.c#L935
|
||||
================
|
||||
*/
|
||||
twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, const qplane3d &split)
|
||||
twosided<std::unique_ptr<bspbrush_t>> SplitBrush(std::unique_ptr<bspbrush_t> brush, const qplane3d &split)
|
||||
{
|
||||
twosided<std::unique_ptr<brush_t>> result;
|
||||
twosided<std::unique_ptr<bspbrush_t>> result;
|
||||
|
||||
// check all points
|
||||
vec_t d_front = 0;
|
||||
vec_t d_back = 0;
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
for (int j = 0; j < face.w.size(); j++) {
|
||||
vec_t d = qv::dot(face.w[j], split.normal) - split.dist;
|
||||
if (d > 0 && d > d_front)
|
||||
|
|
@ -664,7 +676,7 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
|
||||
// create a new winding from the split plane
|
||||
auto w = std::optional<winding_t>{BaseWindingForPlane(split)};
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
if (!w) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -673,7 +685,7 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
}
|
||||
|
||||
if (!w || WindingIsTiny(*w)) { // the brush isn't really split
|
||||
side_t side = BrushMostlyOnSide(*brush, split);
|
||||
planeside_t side = BrushMostlyOnSide(*brush, split);
|
||||
if (side == SIDE_FRONT)
|
||||
result.front = std::move(brush);
|
||||
else
|
||||
|
|
@ -692,9 +704,9 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
// start with 2 empty brushes
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
result[i] = std::make_unique<brush_t>();
|
||||
result[i] = std::make_unique<bspbrush_t>();
|
||||
result[i]->original = brush->original;
|
||||
// fixme-brushbsp: add a brush_t copy constructor to make sure we get all fields
|
||||
// fixme-brushbsp: add a bspbrush_t copy constructor to make sure we get all fields
|
||||
result[i]->contents = brush->contents;
|
||||
result[i]->lmshift = brush->lmshift;
|
||||
result[i]->func_areaportal = brush->func_areaportal;
|
||||
|
|
@ -702,7 +714,7 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
|
||||
// split all the current windings
|
||||
|
||||
for (const auto &face : brush->faces) {
|
||||
for (const auto &face : brush->sides) {
|
||||
auto cw = face.w.clip(split, 0 /*PLANESIDE_EPSILON*/);
|
||||
for (size_t j = 0; j < 2; j++) {
|
||||
if (!cw[j])
|
||||
|
|
@ -716,13 +728,13 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
#endif
|
||||
|
||||
// add the clipped face to result[j]
|
||||
face_t faceCopy = face;
|
||||
side_t faceCopy = face;
|
||||
faceCopy.w = *cw[j];
|
||||
|
||||
// fixme-brushbsp: configure any settings on the faceCopy?
|
||||
// Q2 does `cs->tested = false;`, why?
|
||||
|
||||
result[j]->faces.push_back(std::move(faceCopy));
|
||||
result[j]->sides.push_back(std::move(faceCopy));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -740,7 +752,7 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
}
|
||||
}
|
||||
|
||||
if (result[i]->faces.size() < 3 || bogus) {
|
||||
if (result[i]->sides.size() < 3 || bogus) {
|
||||
result[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -762,7 +774,7 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
|
||||
// add the midwinding to both sides
|
||||
for (int i = 0; i < 2; i++) {
|
||||
face_t cs{};
|
||||
side_t cs{};
|
||||
|
||||
const bool brushOnFront = (i == 0);
|
||||
|
||||
|
|
@ -775,7 +787,7 @@ twosided<std::unique_ptr<brush_t>> SplitBrush(std::unique_ptr<brush_t> brush, co
|
|||
|
||||
cs.w = brushOnFront ? midwinding.flip() : midwinding;
|
||||
|
||||
result[i]->faces.push_back(std::move(cs));
|
||||
result[i]->sides.push_back(std::move(cs));
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -806,7 +818,7 @@ inline void DivideNodeBounds(node_t *node, const qbsp_plane_t &split)
|
|||
DivideBounds(node->bounds, split, node->children[0]->bounds, node->children[1]->bounds);
|
||||
}
|
||||
|
||||
static bool AllDetail(const std::vector<std::unique_ptr<brush_t>> &brushes)
|
||||
static bool AllDetail(const std::vector<std::unique_ptr<bspbrush_t>> &brushes)
|
||||
{
|
||||
for (auto &brush : brushes) {
|
||||
if (!brush->contents.is_any_detail(options.target_game)) {
|
||||
|
|
@ -826,7 +838,7 @@ original faces that have some fragment inside this leaf.
|
|||
Called in parallel.
|
||||
==================
|
||||
*/
|
||||
static void CreateLeaf(std::vector<std::unique_ptr<brush_t>> brushes, node_t *leafnode)
|
||||
static void CreateLeaf(std::vector<std::unique_ptr<bspbrush_t>> brushes, node_t *leafnode)
|
||||
{
|
||||
leafnode->facelist.clear();
|
||||
leafnode->planenum = PLANENUM_LEAF;
|
||||
|
|
@ -850,9 +862,9 @@ PartitionBrushes
|
|||
Called in parallel.
|
||||
==================
|
||||
*/
|
||||
static void PartitionBrushes(std::vector<std::unique_ptr<brush_t>> brushes, node_t *node)
|
||||
static void PartitionBrushes(std::vector<std::unique_ptr<bspbrush_t>> brushes, node_t *node)
|
||||
{
|
||||
face_t *split = const_cast<face_t *>(SelectPartition(brushes));
|
||||
auto *split = const_cast<side_t *>(SelectPartition(brushes));
|
||||
|
||||
if (split == nullptr) { // this is a leaf node
|
||||
node->planenum = PLANENUM_LEAF;
|
||||
|
|
@ -876,7 +888,7 @@ static void PartitionBrushes(std::vector<std::unique_ptr<brush_t>> brushes, node
|
|||
DivideNodeBounds(node, splitplane);
|
||||
|
||||
// multiple surfaces, so split all the polysurfaces into front and back lists
|
||||
std::vector<std::unique_ptr<brush_t>> frontlist, backlist;
|
||||
std::vector<std::unique_ptr<bspbrush_t>> frontlist, backlist;
|
||||
|
||||
for (auto &brush : brushes) {
|
||||
// NOTE: we're destroying `brushes` here with the std::move()
|
||||
|
|
@ -885,7 +897,7 @@ static void PartitionBrushes(std::vector<std::unique_ptr<brush_t>> brushes, node
|
|||
// mark faces which were used as a splitter
|
||||
for (auto &brushMaybe : frags) {
|
||||
if (brushMaybe) {
|
||||
for (auto &face : brushMaybe->faces) {
|
||||
for (auto &face : brushMaybe->sides) {
|
||||
if (face.planenum == split->planenum) {
|
||||
face.onnode = true;
|
||||
}
|
||||
|
|
@ -894,13 +906,13 @@ static void PartitionBrushes(std::vector<std::unique_ptr<brush_t>> brushes, node
|
|||
}
|
||||
|
||||
if (frags.front) {
|
||||
if (frags.front->faces.empty()) {
|
||||
if (frags.front->sides.empty()) {
|
||||
FError("Surface with no faces");
|
||||
}
|
||||
frontlist.emplace_back(std::move(frags.front));
|
||||
}
|
||||
if (frags.back) {
|
||||
if (frags.back->faces.empty()) {
|
||||
if (frags.back->sides.empty()) {
|
||||
FError("Surface with no faces");
|
||||
}
|
||||
backlist.emplace_back(std::move(frags.back));
|
||||
|
|
@ -952,7 +964,7 @@ tree_t *BrushBSP(mapentity_t *entity, bool midsplit)
|
|||
int visible_brush_sides = 0;
|
||||
int invisible_brush_sides = 0;
|
||||
for (const auto &brush : entity->brushes) {
|
||||
for (auto &side : brush->faces) {
|
||||
for (auto &side : brush->sides) {
|
||||
if (side.visible) {
|
||||
++visible_brush_sides;
|
||||
} else {
|
||||
|
|
@ -977,9 +989,9 @@ tree_t *BrushBSP(mapentity_t *entity, bool midsplit)
|
|||
mapbrushes = entity->brushes.size();
|
||||
|
||||
// set the original pointers
|
||||
std::vector<std::unique_ptr<brush_t>> brushcopies;
|
||||
std::vector<std::unique_ptr<bspbrush_t>> brushcopies;
|
||||
for (const auto &original : entity->brushes) {
|
||||
auto copy = std::make_unique<brush_t>(*original);
|
||||
auto copy = std::make_unique<bspbrush_t>(*original);
|
||||
copy->original = original.get();
|
||||
brushcopies.push_back(std::move(copy));
|
||||
}
|
||||
16
qbsp/csg4.cc
16
qbsp/csg4.cc
|
|
@ -23,7 +23,7 @@
|
|||
#include <qbsp/brush.hh>
|
||||
#include <qbsp/csg4.hh>
|
||||
#include <qbsp/map.hh>
|
||||
#include <qbsp/solidbsp.hh>
|
||||
#include <qbsp/brushbsp.hh>
|
||||
#include <qbsp/qbsp.hh>
|
||||
|
||||
#include <atomic>
|
||||
|
|
@ -80,6 +80,16 @@ void UpdateFaceSphere(face_t *in)
|
|||
in->radius = sqrt(in->radius);
|
||||
}
|
||||
|
||||
void UpdateFaceSphere(side_t *in)
|
||||
{
|
||||
in->origin = in->w.center();
|
||||
in->radius = 0;
|
||||
for (size_t i = 0; i < in->w.size(); i++) {
|
||||
in->radius = max(in->radius, qv::distance2(in->w[i], in->origin));
|
||||
}
|
||||
in->radius = sqrt(in->radius);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SplitFace
|
||||
|
|
@ -131,9 +141,7 @@ face_t *MirrorFace(const face_t *face)
|
|||
{
|
||||
face_t *newface = NewFaceFromFace(face);
|
||||
newface->w = face->w.flip();
|
||||
newface->planeside = static_cast<side_t>(face->planeside ^ 1);
|
||||
newface->contents.swap();
|
||||
newface->lmshift.swap();
|
||||
newface->planeside = static_cast<planeside_t>(face->planeside ^ 1);
|
||||
|
||||
return newface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ static void ExportObjFace(std::ofstream &f, const face_t *face, int *vertcount)
|
|||
}
|
||||
|
||||
// fixme-brushbsp
|
||||
fmt::print(f, "usemtl contents{}\n", face->contents[0].native);
|
||||
fmt::print(f, "usemtl contents{}\n", face->contents.native);
|
||||
f << 'f';
|
||||
for (int i = 0; i < face->w.size(); i++) {
|
||||
// .obj vertexes start from 1
|
||||
|
|
@ -122,15 +122,8 @@ void ExportObj_Faces(const std::string &filesuffix, const std::vector<const face
|
|||
}
|
||||
}
|
||||
|
||||
void ExportObj_Brushes(const std::string &filesuffix, const std::vector<const brush_t *> &brushes)
|
||||
void ExportObj_Brushes(const std::string &filesuffix, const std::vector<const bspbrush_t *> &brushes)
|
||||
{
|
||||
std::vector<const face_t *> faces;
|
||||
|
||||
for (const brush_t *brush : brushes)
|
||||
for (auto &face : brush->faces)
|
||||
faces.push_back(&face);
|
||||
|
||||
ExportObj_Faces(filesuffix, faces);
|
||||
}
|
||||
|
||||
static void ExportObj_Nodes_r(const node_t *node, std::vector<const face_t *> *dest)
|
||||
|
|
|
|||
10
qbsp/map.cc
10
qbsp/map.cc
|
|
@ -2284,7 +2284,7 @@ WriteBspBrushMap
|
|||
from q3map
|
||||
==================
|
||||
*/
|
||||
void WriteBspBrushMap(const fs::path &name, const std::vector<std::unique_ptr<brush_t>> &list)
|
||||
void WriteBspBrushMap(const fs::path &name, const std::vector<std::unique_ptr<bspbrush_t>> &list)
|
||||
{
|
||||
logging::print("writing {}\n", name);
|
||||
std::ofstream f(name);
|
||||
|
|
@ -2296,7 +2296,7 @@ void WriteBspBrushMap(const fs::path &name, const std::vector<std::unique_ptr<br
|
|||
|
||||
for (auto &brush : list) {
|
||||
fmt::print(f, "{{\n");
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
// FIXME: Factor out this mess
|
||||
const qbsp_plane_t &plane = map.planes.at(face.planenum);
|
||||
winding_t w = BaseWindingForPlane(face.planeside ? -plane : plane);
|
||||
|
|
@ -2330,16 +2330,16 @@ from q3map
|
|||
*/
|
||||
static void TestExpandBrushes(const mapentity_t *src)
|
||||
{
|
||||
std::vector<std::unique_ptr<brush_t>> hull1brushes;
|
||||
std::vector<std::unique_ptr<bspbrush_t>> hull1brushes;
|
||||
|
||||
for (int i = 0; i < src->nummapbrushes; i++) {
|
||||
const mapbrush_t *mapbrush = &src->mapbrush(i);
|
||||
std::optional<brush_t> hull1brush = LoadBrush(
|
||||
std::optional<bspbrush_t> hull1brush = LoadBrush(
|
||||
src, mapbrush, {CONTENTS_SOLID}, {}, rotation_t::none, options.target_game->id == GAME_QUAKE_II ? HULL_COLLISION : 1);
|
||||
|
||||
if (hull1brush) {
|
||||
hull1brushes.emplace_back(
|
||||
std::make_unique<brush_t>(std::move(*hull1brush)));
|
||||
std::make_unique<bspbrush_t>(std::move(*hull1brush)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ static face_t *TryMerge(face_t *f1, face_t *f2)
|
|||
|
||||
if (!f1->w.size() || !f2->w.size() || f1->planeside != f2->planeside || f1->texinfo != f2->texinfo ||
|
||||
/*!f1->contents[0].equals(options.target_game, f2->contents[0]) || !f1->contents[1].equals(options.target_game, f2->contents[1]) || */
|
||||
f1->lmshift[0] != f2->lmshift[0] || f1->lmshift[1] != f2->lmshift[1])
|
||||
f1->lmshift != f2->lmshift)
|
||||
return NULL;
|
||||
|
||||
// find a common edge
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ std::vector<node_t *> FindOccupiedClusters(node_t *headnode)
|
|||
static void MarkBrushSidesInvisible(mapentity_t *entity)
|
||||
{
|
||||
for (auto &brush : entity->brushes) {
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
face.visible = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -368,7 +368,7 @@ static void MarkAllBrushSidesVisible_R(node_t *node)
|
|||
}
|
||||
|
||||
for (auto *brush : node->original_brushes) {
|
||||
for (auto &side : brush->faces) {
|
||||
for (auto &side : brush->sides) {
|
||||
side.visible = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -410,7 +410,7 @@ static void MarkVisibleBrushSides_R(node_t *node)
|
|||
// optimized case: just mark the brush sides in the neighbouring
|
||||
// leaf that are coplanar
|
||||
for (auto *brush : neighbour_leaf->original_brushes) {
|
||||
for (auto &side : brush->faces) {
|
||||
for (auto &side : brush->sides) {
|
||||
if (side.planenum == portal->planenum) {
|
||||
// we've found a brush side in an original brush in the neighbouring
|
||||
// leaf, on a portal to this (non-opaque) leaf, so mark it as visible.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <qbsp/portals.hh>
|
||||
|
||||
#include <qbsp/map.hh>
|
||||
#include <qbsp/solidbsp.hh>
|
||||
#include <qbsp/brushbsp.hh>
|
||||
#include <qbsp/qbsp.hh>
|
||||
|
||||
#include <atomic>
|
||||
|
|
@ -98,7 +98,7 @@ void MakeHeadnodePortals(tree_t *tree)
|
|||
int i, j, n;
|
||||
portal_t *p, *portals[6];
|
||||
qbsp_plane_t bplanes[6];
|
||||
side_t side;
|
||||
planeside_t side;
|
||||
|
||||
// pad with some space so there will never be null volume leafs
|
||||
aabb3d bounds = tree->bounds.grow(SIDESPACE);
|
||||
|
|
@ -167,7 +167,7 @@ std::optional<winding_t> BaseWindingForNode(node_t *node)
|
|||
{
|
||||
plane = map.planes.at(np->planenum);
|
||||
|
||||
const side_t keep = (np->children[0] == node) ?
|
||||
const planeside_t keep = (np->children[0] == node) ?
|
||||
SIDE_FRONT : SIDE_BACK;
|
||||
|
||||
w = w->clip(plane, BASE_WINDING_EPSILON, false)[keep];
|
||||
|
|
@ -247,7 +247,7 @@ void SplitNodePortals(node_t *node, portalstats_t &stats)
|
|||
portal_t *next_portal = nullptr;
|
||||
for (portal_t *p = node->portals; p ; p = next_portal)
|
||||
{
|
||||
side_t side;
|
||||
planeside_t side;
|
||||
if (p->nodes[SIDE_FRONT] == node)
|
||||
side = SIDE_FRONT;
|
||||
else if (p->nodes[SIDE_BACK] == node)
|
||||
|
|
@ -445,7 +445,7 @@ static void FindPortalSide(portal_t *p)
|
|||
return;
|
||||
|
||||
int planenum = p->onnode->planenum;
|
||||
face_t *bestside = nullptr;
|
||||
side_t *bestside = nullptr;
|
||||
float bestdot = 0;
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
|
|
@ -460,7 +460,7 @@ static void FindPortalSide(portal_t *p)
|
|||
auto *brush = *it;
|
||||
if (!options.target_game->contents_contains(brush->contents, viscontents))
|
||||
continue;
|
||||
for (face_t &side : brush->faces)
|
||||
for (auto &side : brush->sides)
|
||||
{
|
||||
// fixme-brushbsp: port these
|
||||
// if (side.bevel)
|
||||
|
|
@ -537,7 +537,7 @@ void MarkVisibleSides(tree_t *tree, mapentity_t* entity)
|
|||
|
||||
// clear all the visible flags
|
||||
for (auto &brush : entity->brushes) {
|
||||
for (auto &face : brush->faces) {
|
||||
for (auto &face : brush->sides) {
|
||||
face.visible = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
qbsp/qbsp.cc
26
qbsp/qbsp.cc
|
|
@ -35,7 +35,7 @@
|
|||
#include <qbsp/merge.hh>
|
||||
#include <qbsp/portals.hh>
|
||||
#include <qbsp/prtfile.hh>
|
||||
#include <qbsp/solidbsp.hh>
|
||||
#include <qbsp/brushbsp.hh>
|
||||
#include <qbsp/surfaces.hh>
|
||||
#include <qbsp/qbsp.hh>
|
||||
#include <qbsp/wad.hh>
|
||||
|
|
@ -296,12 +296,12 @@ Adds any additional planes necessary to allow the brush to be expanded
|
|||
against axial bounding boxes
|
||||
=================
|
||||
*/
|
||||
static std::vector<std::tuple<size_t, const face_t *>> AddBrushBevels(const brush_t &b)
|
||||
static std::vector<std::tuple<size_t, const side_t *>> AddBrushBevels(const bspbrush_t &b)
|
||||
{
|
||||
// add already-present planes
|
||||
std::vector<std::tuple<size_t, const face_t *>> planes;
|
||||
std::vector<std::tuple<size_t, const side_t *>> planes;
|
||||
|
||||
for (auto &f : b.faces) {
|
||||
for (auto &f : b.sides) {
|
||||
int32_t planenum = f.planenum;
|
||||
|
||||
if (f.planeside) {
|
||||
|
|
@ -336,7 +336,7 @@ static std::vector<std::tuple<size_t, const face_t *>> AddBrushBevels(const brus
|
|||
|
||||
int32_t planenum = FindPlane(new_plane, nullptr);
|
||||
int32_t outputplanenum = ExportMapPlane(planenum);
|
||||
planes.emplace_back(outputplanenum, &b.faces.front());
|
||||
planes.emplace_back(outputplanenum, &b.sides.front());
|
||||
}
|
||||
|
||||
// if the plane is not in it canonical order, swap it
|
||||
|
|
@ -384,11 +384,11 @@ static std::vector<std::tuple<size_t, const face_t *>> AddBrushBevels(const brus
|
|||
continue;
|
||||
current.dist = qv::dot(w[j], current.normal);
|
||||
|
||||
auto it = b.faces.begin();
|
||||
auto it = b.sides.begin();
|
||||
|
||||
// if all the points on all the sides are
|
||||
// behind this plane, it is a proper edge bevel
|
||||
for (; it != b.faces.end(); it++) {
|
||||
for (; it != b.sides.end(); it++) {
|
||||
auto &f = *it;
|
||||
const auto &plane = map.planes.at(f.planenum);
|
||||
qplane3d temp = f.planeside ? -plane : plane;
|
||||
|
|
@ -410,13 +410,13 @@ static std::vector<std::tuple<size_t, const face_t *>> AddBrushBevels(const brus
|
|||
break;
|
||||
}
|
||||
|
||||
if (it != b.faces.end())
|
||||
if (it != b.sides.end())
|
||||
continue; // wasn't part of the outer hull
|
||||
|
||||
// add this plane
|
||||
int32_t planenum = FindPlane(current, nullptr);
|
||||
int32_t outputplanenum = ExportMapPlane(planenum);
|
||||
planes.emplace_back(outputplanenum, &b.faces.front());
|
||||
planes.emplace_back(outputplanenum, &b.sides.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1019,13 +1019,13 @@ hull sizes
|
|||
*/
|
||||
|
||||
static void BSPX_Brushes_AddModel(
|
||||
struct bspxbrushes_s *ctx, int modelnum, std::vector<std::unique_ptr<brush_t>> &brushes)
|
||||
struct bspxbrushes_s *ctx, int modelnum, std::vector<std::unique_ptr<bspbrush_t>> &brushes)
|
||||
{
|
||||
bspxbrushes_permodel permodel{1, modelnum};
|
||||
|
||||
for (auto &b : brushes) {
|
||||
permodel.numbrushes++;
|
||||
for (auto &f : b->faces) {
|
||||
for (auto &f : b->sides) {
|
||||
/*skip axial*/
|
||||
const auto &plane = map.planes.at(f.planenum);
|
||||
if (fabs(plane.normal[0]) == 1 || fabs(plane.normal[1]) == 1 ||
|
||||
|
|
@ -1044,7 +1044,7 @@ static void BSPX_Brushes_AddModel(
|
|||
for (auto &b : brushes) {
|
||||
bspxbrushes_perbrush perbrush{};
|
||||
|
||||
for (auto &f : b->faces) {
|
||||
for (auto &f : b->sides) {
|
||||
/*skip axial*/
|
||||
const auto &plane = map.planes.at(f.planenum);
|
||||
if (fabs(plane.normal[0]) == 1 || fabs(plane.normal[1]) == 1 ||
|
||||
|
|
@ -1086,7 +1086,7 @@ static void BSPX_Brushes_AddModel(
|
|||
|
||||
str <= perbrush;
|
||||
|
||||
for (auto &f : b->faces) {
|
||||
for (auto &f : b->sides) {
|
||||
/*skip axial*/
|
||||
const auto &plane = map.planes.at(f.planenum);
|
||||
if (fabs(plane.normal[0]) == 1 || fabs(plane.normal[1]) == 1 ||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include <qbsp/csg4.hh>
|
||||
#include <qbsp/map.hh>
|
||||
#include <qbsp/merge.hh>
|
||||
#include <qbsp/solidbsp.hh>
|
||||
#include <qbsp/brushbsp.hh>
|
||||
#include <qbsp/qbsp.hh>
|
||||
#include <qbsp/writebsp.hh>
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ static bool ShouldOmitFace(face_t *f)
|
|||
return true;
|
||||
|
||||
// HACK: to save a few faces, don't output the interior faces of sky brushes
|
||||
if (f->contents[0].is_sky(options.target_game)) {
|
||||
if (f->contents.is_sky(options.target_game)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ std::list<face_t *> SubdivideFace(face_t *f)
|
|||
// one lightmap block will always be added at the end, for smooth interpolation
|
||||
|
||||
// engines that do support scaling will support 256*256 blocks (at whatever scale).
|
||||
lmshift = f->lmshift[0];
|
||||
lmshift = f->lmshift;
|
||||
if (lmshift > 4)
|
||||
lmshift = 4; // no bugging out with legacy lighting
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ Returns a global edge number, possibly negative to indicate a backwards edge.
|
|||
*/
|
||||
inline size_t GetEdge(mapentity_t *entity, const qvec3d &p1, const qvec3d &p2, const face_t *face)
|
||||
{
|
||||
if (!face->contents[0].is_valid(options.target_game, false))
|
||||
if (!face->contents.is_valid(options.target_game, false))
|
||||
FError("Face with invalid contents");
|
||||
|
||||
size_t v1 = GetVertex(p1);
|
||||
|
|
@ -304,7 +304,7 @@ inline size_t GetEdge(mapentity_t *entity, const qvec3d &p1, const qvec3d &p2, c
|
|||
auto it = hashedges.find(edge_hash_key);
|
||||
if (it != hashedges.end()) {
|
||||
for (const int i : it->second) {
|
||||
if (pEdgeFaces1[i] == NULL && pEdgeFaces0[i]->contents[0].native == face->contents[0].native) {
|
||||
if (pEdgeFaces1[i] == NULL && pEdgeFaces0[i]->contents.native == face->contents.native) {
|
||||
pEdgeFaces1[i] = face;
|
||||
return -i;
|
||||
}
|
||||
|
|
@ -392,7 +392,7 @@ static void EmitFaceFragment(mapentity_t *entity, face_t *face, face_fragment_t
|
|||
mface_t &out = map.bsp.dfaces.emplace_back();
|
||||
|
||||
// emit lmshift
|
||||
map.exported_lmshifts.push_back(face->lmshift[1]);
|
||||
map.exported_lmshifts.push_back(face->lmshift);
|
||||
Q_assert(map.bsp.dfaces.size() == map.exported_lmshifts.size());
|
||||
|
||||
out.planenum = ExportMapPlane(face->planenum);
|
||||
|
|
@ -458,7 +458,7 @@ static void CountFace(mapentity_t *entity, face_t *f, size_t &facesCount, size_t
|
|||
if (ShouldOmitFace(f))
|
||||
return;
|
||||
|
||||
if (f->lmshift[1] != 4)
|
||||
if (f->lmshift != 4)
|
||||
map.needslmshifts = true;
|
||||
|
||||
facesCount++;
|
||||
|
|
@ -597,7 +597,7 @@ see also FindPortalSide which populates p->side
|
|||
*/
|
||||
static face_t *FaceFromPortal(portal_t *p, int pside)
|
||||
{
|
||||
face_t *side = p->side;
|
||||
side_t *side = p->side;
|
||||
if (!side)
|
||||
return nullptr; // portal does not bridge different visible contents
|
||||
|
||||
|
|
@ -605,7 +605,7 @@ static face_t *FaceFromPortal(portal_t *p, int pside)
|
|||
|
||||
f->texinfo = side->texinfo;
|
||||
f->planenum = side->planenum;
|
||||
f->planeside = static_cast<side_t>(pside);
|
||||
f->planeside = static_cast<planeside_t>(pside);
|
||||
f->portal = p;
|
||||
f->lmshift = side->lmshift;
|
||||
|
||||
|
|
@ -632,15 +632,12 @@ static face_t *FaceFromPortal(portal_t *p, int pside)
|
|||
if (pside)
|
||||
{
|
||||
f->w = p->winding->flip();
|
||||
// fixme-brushbsp: was just `f->contents` on qbsp3
|
||||
f->contents[0] = p->nodes[1]->contents;
|
||||
f->contents[1] = p->nodes[0]->contents;
|
||||
f->contents = p->nodes[1]->contents;
|
||||
}
|
||||
else
|
||||
{
|
||||
f->w = *p->winding;
|
||||
f->contents[0] = p->nodes[0]->contents;
|
||||
f->contents[1] = p->nodes[1]->contents;
|
||||
f->contents = p->nodes[0]->contents;
|
||||
}
|
||||
|
||||
UpdateFaceSphere(f);
|
||||
|
|
|
|||
|
|
@ -351,10 +351,10 @@ TEST_CASE("duplicatePlanes", "[qbsp]")
|
|||
CHECK(0 == worldspawn.brushes.size());
|
||||
CHECK(6 == worldspawn.mapbrush(0).numfaces);
|
||||
|
||||
std::optional<brush_t> brush =
|
||||
std::optional<bspbrush_t> brush =
|
||||
LoadBrush(&worldspawn, &worldspawn.mapbrush(0), {CONTENTS_SOLID}, {}, rotation_t::none, 0);
|
||||
REQUIRE(std::nullopt != brush);
|
||||
CHECK(6 == brush->faces.size());
|
||||
CHECK(6 == brush->sides.size());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue