ericw-tools/include/qbsp/qbsp.hh

375 lines
11 KiB
C++

/*
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 1997 Greg Lewis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See file, 'COPYING', for details.
*/
// qbsp.h
#ifndef QBSP_H
#define QBSP_H
#include <vector>
#include <map>
#include <unordered_map>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <common/bspfile.hh>
#include "file.hh"
#include "warnerr.hh"
#ifndef offsetof
#define offsetof(type, member) __builtin_offsetof(type, member)
#endif
#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif
#ifndef __GNUC__
#define __attribute__(x)
#endif
/*
* 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
* the negative range was unused apart from a few values reserved for flags,
* this has been extended to allow up to 65520 (0xfff0) clipnodes (with a
* suitably modified engine).
*/
#define MAX_BSP_CLIPNODES 0xfff0
// key / value pair sizes
#define MAX_KEY 32
#define MAX_VALUE 1024
// Various other geometry maximums
#define MAX_POINTS_ON_WINDING 96
#define MAXEDGES 64
#define MAXPOINTS 60 // don't let a base face get past this
// because it can be split more later
// For brush.c, normal and +16 (?)
#define NUM_HULLS 2
// 0-2 are axial planes
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
// planenum for a leaf (?)
#define PLANENUM_LEAF -1
// Which side of polygon a point is on
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
#define SIDE_CROSS -2
// Pi
#define Q_PI 3.14159265358979323846
// Special contents flags for the compiler only
#define CFLAGS_STRUCTURAL_COVERED_BY_DETAIL (1U << 0)
#define CFLAGS_WAS_ILLUSIONARY (1U << 1) /* was illusionary, got changed to something else */
#define CFLAGS_DETAIL_WALL (1U << 2) /* don't clip world for func_detail_wall entities */
#define CFLAGS_BMODEL_MIRROR_INSIDE (1U << 3) /* set "_mirrorinside" "1" on a bmodel to mirror faces for when the player is inside. */
#define CFLAGS_NO_CLIPPING_SAME_TYPE (1U << 4) /* Don't clip the same content type. mostly intended for CONTENTS_DETAIL_ILLUSIONARY */
/*
* The quality of the bsp output is highly sensitive to these epsilon values.
* Notes:
* - T-junction calculations are sensitive to errors and need the various
* epsilons to be such that EQUAL_EPSILON < T_EPSILON < CONTINUOUS_EPSILON.
* ( TODO: re-check if CONTINUOUS_EPSILON is still directly related )
*/
#define ANGLEEPSILON 0.000001
#define DIST_EPSILON 0.0001
#define ZERO_EPSILON 0.0001
#define DISTEPSILON 0.0001
#define POINT_EPSILON 0.0001
#define ON_EPSILON options.on_epsilon
#define EQUAL_EPSILON 0.0001
#define T_EPSILON 0.0002
#define CONTINUOUS_EPSILON 0.0005
// from q3map
#define MAX_WORLD_COORD ( 128*1024 )
#define MIN_WORLD_COORD ( -128*1024 )
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
// the exact bounding box of the brushes is expanded some for the headnode
// volume. is this still needed?
#define SIDESPACE 24
// AllocMem types
enum {
WINDING,
OTHER
};
#include <common/cmdlib.hh>
#include <common/mathlib.hh>
#include <qbsp/winding.hh>
typedef struct mtexinfo_s {
float vecs[2][4]; /* [s/t][xyz offset] */
int32_t miptex;
uint64_t flags;
int outputnum; // -1 until added to bsp
bool operator<(const mtexinfo_s &other) const {
if (this->miptex < other.miptex)
return true;
if (this->miptex > other.miptex)
return false;
if (this->flags < other.flags)
return true;
if (this->flags > other.flags)
return false;
for (int i=0; i<2; i++) {
for (int j=0; j<4; j++) {
if (this->vecs[i][j] < other.vecs[i][j])
return true;
if (this->vecs[i][j] > other.vecs[i][j])
return false;
}
}
return false;
}
} mtexinfo_t;
typedef struct visfacet_s {
struct visfacet_s *next;
int planenum;
int planeside; // which side is the front of the face
int texinfo;
short contents[2]; // 0 = front side
short cflags[2]; // contents flags
short lmshift[2]; //lightmap scale.
struct visfacet_s *original; // face on node
int outputnumber; // only valid for original faces after
// write surfaces
bool touchesOccupiedLeaf; // internal use in outside.cc
vec3_t origin;
vec_t radius;
int *edges;
winding_t w;
} face_t;
typedef struct surface_s {
struct surface_s *next;
struct surface_s *original; // before BSP cuts it up
int planenum;
int outputplanenum; // only valid after WriteSurfacePlanes
vec3_t mins, maxs;
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
short lmshift;
} surface_t;
// there is a node_t structure for every node and leaf in the bsp tree
class mapentity_t;
typedef struct brush_s brush_t;
typedef struct node_s {
vec3_t mins, maxs; // bounding volume, not just points inside
// information for decision nodes
int planenum; // -1 = leaf node
//outputplanenum moved to qbsp_plane_t
int firstface; // decision node only
int numfaces; // decision node only
struct node_s *children[2]; // children[0] = front side, children[1] = back side of plane. only valid for decision nodes
face_t *faces; // decision nodes only, list for both sides
// information for leafs
int contents; // leaf nodes (0 for decision nodes)
face_t **markfaces; // leaf nodes only, point to node faces
struct portal_s *portals;
int visleafnum; // -1 = solid
int viscluster; // detail cluster for faster vis
int occupied; // 0=can't reach entity, 1 = has entity, >1 = distance from leaf with entity
mapentity_t *occupant; // example occupant, for leak hunting
bool detail_separator; // for vis portal generation. true if ALL faces on node, and on all descendant nodes/leafs, are detail.
bool opaque() const {
return contents == CONTENTS_SOLID
|| contents == CONTENTS_SKY;
}
} node_t;
#include <qbsp/brush.hh>
#include <qbsp/csg4.hh>
#include <qbsp/solidbsp.hh>
#include <qbsp/merge.hh>
#include <qbsp/surfaces.hh>
#include <qbsp/portals.hh>
#include <qbsp/region.hh>
#include <qbsp/tjunc.hh>
#include <qbsp/writebsp.hh>
#include <qbsp/outside.hh>
typedef enum {
TX_QUAKED = 0,
TX_QUARK_TYPE1 = 1,
TX_QUARK_TYPE2 = 2,
TX_VALVE_220 = 3,
TX_BRUSHPRIM = 4
} texcoord_style_t;
enum class conversion_t {
quake, quake2, valve, bp
};
class options_t {
public:
bool fNofill;
bool fNoclip;
bool fNoskip;
bool fNodetail;
bool fOnlyents;
bool fConvertMapFormat;
conversion_t convertMapFormat;
bool fVerbose;
bool fAllverbose;
bool fSplitspecial;
bool fSplitturb;
bool fSplitsky;
bool fTranswater;
bool fTranssky;
bool fOldaxis;
bool fNoverbose;
bool fNopercent;
bool forceGoodTree;
bool fixRotateObjTexture;
bool fbspx_brushes;
bool fNoTextures;
const bspversion_t *target_version = &bspver_q1;
int dxSubdivide;
int dxLeakDist;
int maxNodeSize;
/**
* 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;
char szMapName[512];
char szBSPName[512];
struct wadpath {
std::string 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<wadpath> wadPathsVec;
vec_t on_epsilon;
bool fObjExport;
bool fOmitDetail;
bool fOmitDetailWall;
bool fOmitDetailIllusionary;
bool fOmitDetailFence;
bool fForcePRT1;
bool fTestExpand;
bool fLeakTest;
bool fContentHack;
vec_t worldExtent;
bool fNoThreads;
options_t() :
fNofill(false),
fNoclip(false),
fNoskip(false),
fNodetail(false),
fOnlyents(false),
fConvertMapFormat(false),
convertMapFormat(conversion_t::quake),
fVerbose(true),
fAllverbose(false),
fSplitspecial(false),
fSplitturb(false),
fSplitsky(false),
fTranswater(true),
fTranssky(false),
fOldaxis(true),
fNoverbose(false),
fNopercent(false),
forceGoodTree(false),
fixRotateObjTexture(true),
fbspx_brushes(false),
fNoTextures(false),
dxSubdivide(240),
dxLeakDist(2),
maxNodeSize(1024),
midsplitSurfFraction(0.0f),
szMapName{},
szBSPName{},
on_epsilon(0.0001),
fObjExport(false),
fOmitDetail(false),
fOmitDetailWall(false),
fOmitDetailIllusionary(false),
fOmitDetailFence(false),
fForcePRT1(false),
fTestExpand(false),
fLeakTest(false),
fContentHack(false),
worldExtent(65536.0f),
fNoThreads(false) {}
};
extern options_t options;
#include <qbsp/map.hh>
#include <qbsp/util.hh>
int qbsp_main(int argc, const char **argv);
void ProcessEntity(mapentity_t *entity, const int hullnum);
void CreateSingleHull(const int hullnum);
void CreateHulls(void);
#endif