/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see .
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../../renderer/tr_local.h"
typedef struct primitive_s {
struct primitive_s *next;
// only one of these will be non-NULL
struct bspbrush_s * brush;
struct mapTri_s * tris;
} primitive_t;
typedef struct {
struct optimizeGroup_s *groups;
// we might want to add other fields later
} uArea_t;
typedef struct {
idMapEntity * mapEntity; // points into mapFile_t data
idVec3 origin;
primitive_t * primitives;
struct tree_s * tree;
int numAreas;
uArea_t * areas;
} uEntity_t;
// chains of mapTri_t are the general unit of processing
typedef struct mapTri_s {
struct mapTri_s * next;
const idMaterial * material;
void * mergeGroup; // we want to avoid merging triangles
// from different fixed groups, like guiSurfs and mirrors
int planeNum; // not set universally, just in some areas
idDrawVert v[3];
const struct hashVert_s *hashVert[3];
struct optVertex_s *optVert[3];
} mapTri_t;
typedef struct {
int width, height;
idDrawVert * verts;
} mesh_t;
#define MAX_PATCH_SIZE 32
#define PLANENUM_LEAF -1
typedef struct parseMesh_s {
struct parseMesh_s *next;
mesh_t mesh;
const idMaterial * material;
} parseMesh_t;
typedef struct bspface_s {
struct bspface_s * next;
int planenum;
bool portal; // all portals will be selected before
// any non-portals
bool checked; // used by SelectSplitPlaneNum()
idWinding * w;
} bspface_t;
typedef struct {
idVec4 v[2]; // the offset value will always be in the 0.0 to 1.0 range
} textureVectors_t;
typedef struct side_s {
int planenum;
const idMaterial * material;
textureVectors_t texVec;
idWinding * winding; // only clipped to the other sides of the brush
idWinding * visibleHull; // also clipped to the solid parts of the world
} side_t;
typedef struct bspbrush_s {
struct bspbrush_s * next;
struct bspbrush_s * original; // chopped up brushes will reference the originals
int entitynum; // editor numbering for messages
int brushnum; // editor numbering for messages
const idMaterial * contentShader; // one face's shader will determine the volume attributes
int contents;
bool opaque;
int outputNumber; // set when the brush is written to the file list
idBounds bounds;
int numsides;
side_t sides[6]; // variably sized
} uBrush_t;
typedef struct drawSurfRef_s {
struct drawSurfRef_s * nextRef;
int outputNumber;
} drawSurfRef_t;
typedef struct node_s {
// both leafs and nodes
int planenum; // -1 = leaf node
struct node_s * parent;
idBounds bounds; // valid after portalization
// nodes only
side_t * side; // the side that created the node
struct node_s * children[2];
int nodeNumber; // set after pruning
// leafs only
bool opaque; // view can never be inside
uBrush_t * brushlist; // fragments of all brushes in this leaf
// needed for FindSideForPortal
int area; // determined by flood filling up to areaportals
int occupied; // 1 or greater can reach entity
uEntity_t * occupant; // for leak file testing
struct uPortal_s * portals; // also on nodes during construction
} node_t;
typedef struct uPortal_s {
idPlane plane;
node_t *onnode; // NULL = outside box
node_t *nodes[2]; // [0] = front side of plane
struct uPortal_s *next[2];
idWinding *winding;
} uPortal_t;
// a tree_t is created by FaceBSP()
typedef struct tree_s {
node_t *headnode;
node_t outside_node;
idBounds bounds;
} tree_t;
#define MAX_QPATH 256 // max length of a game pathname
typedef struct {
idRenderLightLocal def;
char name[MAX_QPATH]; // for naming the shadow volume surface and interactions
srfTriangles_t *shadowTris;
} mapLight_t;
#define MAX_GROUP_LIGHTS 16
typedef struct optimizeGroup_s {
struct optimizeGroup_s *nextGroup;
idBounds bounds; // set in CarveGroupsByLight
// all of these must match to add a triangle to the triList
bool smoothed; // curves will never merge with brushes
int planeNum;
int areaNum;
const idMaterial * material;
int numGroupLights;
mapLight_t * groupLights[MAX_GROUP_LIGHTS]; // lights effecting this list
void * mergeGroup; // if this differs (guiSurfs, mirrors, etc), the
// groups will not be combined into model surfaces
// after optimization
textureVectors_t texVec;
bool surfaceEmited;
mapTri_t * triList;
mapTri_t * regeneratedTris; // after each island optimization
idVec3 axis[2]; // orthogonal to the plane, so optimization can be 2D
} optimizeGroup_t;
// all primitives from the map are added to optimzeGroups, creating new ones as needed
// each optimizeGroup is then split into the map areas, creating groups in each area
// each optimizeGroup is then divided by each light, creating more groups
// the final list of groups is then tjunction fixed against all groups, then optimized internally
// multiple optimizeGroups will be merged together into .proc surfaces, but no further optimization
// is done on them
//=============================================================================
// dmap.cpp
typedef enum {
SO_NONE, // 0
SO_MERGE_SURFACES, // 1
SO_CULL_OCCLUDED, // 2
SO_CLIP_OCCLUDERS, // 3
SO_CLIP_SILS, // 4
SO_SIL_OPTIMIZE // 5
} shadowOptLevel_t;
typedef struct {
// mapFileBase will contain the qpath without any extension: "maps/test_box"
char mapFileBase[1024];
idMapFile *dmapFile;
idPlaneSet mapPlanes;
int num_entities;
uEntity_t *uEntities;
int entityNum;
idList mapLights;
bool verbose;
bool glview;
bool noOptimize;
bool verboseentities;
bool noCurves;
bool fullCarve;
bool noModelBrushes;
bool noTJunc;
bool nomerge;
bool noFlood;
bool noClipSides; // don't cut sides by solid leafs, use the entire thing
bool noLightCarve; // extra triangle subdivision by light frustums
shadowOptLevel_t shadowOptLevel;
bool noShadow; // don't create optimized shadow volumes
idBounds drawBounds;
bool drawflag;
int totalShadowTriangles;
int totalShadowVerts;
} dmapGlobals_t;
extern dmapGlobals_t dmapGlobals;
int FindFloatPlane( const idPlane &plane, bool *fixedDegeneracies = NULL );
//=============================================================================
// brush.cpp
#ifndef CLIP_EPSILON
#define CLIP_EPSILON 0.1f
#endif
#define PSIDE_FRONT 1
#define PSIDE_BACK 2
#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK)
#define PSIDE_FACING 4
int CountBrushList (uBrush_t *brushes);
uBrush_t *AllocBrush (int numsides);
void FreeBrush (uBrush_t *brushes);
void FreeBrushList (uBrush_t *brushes);
uBrush_t *CopyBrush (uBrush_t *brush);
void DrawBrushList (uBrush_t *brush);
void PrintBrush (uBrush_t *brush);
bool BoundBrush (uBrush_t *brush);
bool CreateBrushWindings (uBrush_t *brush);
uBrush_t *BrushFromBounds( const idBounds &bounds );
float BrushVolume (uBrush_t *brush);
void WriteBspBrushMap( const char *name, uBrush_t *list );
void FilterBrushesIntoTree( uEntity_t *e );
void SplitBrush( uBrush_t *brush, int planenum, uBrush_t **front, uBrush_t **back);
node_t *AllocNode( void );
//=============================================================================
// map.cpp
bool LoadDMapFile( const char *filename );
void FreeOptimizeGroupList( optimizeGroup_t *groups );
void FreeDMapFile( void );
//=============================================================================
// draw.cpp -- draw debug views either directly, or through glserv.exe
void Draw_ClearWindow( void );
void DrawWinding( const idWinding *w );
void DrawAuxWinding( const idWinding *w );
void DrawLine( idVec3 v1, idVec3 v2, int color );
void GLS_BeginScene( void );
void GLS_Winding( const idWinding *w, int code );
void GLS_Triangle( const mapTri_t *tri, int code );
void GLS_EndScene( void );
//=============================================================================
// portals.cpp
#define MAX_INTER_AREA_PORTALS 1024
typedef struct {
int area0, area1;
side_t *side;
} interAreaPortal_t;
extern interAreaPortal_t interAreaPortals[MAX_INTER_AREA_PORTALS];
extern int numInterAreaPortals;
bool FloodEntities( tree_t *tree );
void FillOutside( uEntity_t *e );
void FloodAreas( uEntity_t *e );
void MakeTreePortals( tree_t *tree );
void FreePortal( uPortal_t *p );
//=============================================================================
// glfile.cpp -- write a debug file to be viewd with glview.exe
void OutputWinding( idWinding *w, idFile *glview );
void WriteGLView( tree_t *tree, char *source );
//=============================================================================
// leakfile.cpp
void LeakFile( tree_t *tree );
//=============================================================================
// facebsp.cpp
tree_t *AllocTree( void );
void FreeTree( tree_t *tree );
void FreeTree_r( node_t *node );
void FreeTreePortals_r( node_t *node );
bspface_t *MakeStructuralBspFaceList( primitive_t *list );
bspface_t *MakeVisibleBspFaceList( primitive_t *list );
tree_t *FaceBSP( bspface_t *list );
//=============================================================================
// surface.cpp
mapTri_t *CullTrisInOpaqueLeafs( mapTri_t *triList, tree_t *tree );
void ClipSidesByTree( uEntity_t *e );
void SplitTrisToSurfaces( mapTri_t *triList, tree_t *tree );
void PutPrimitivesInAreas( uEntity_t *e );
void Prelight( uEntity_t *e );
//=============================================================================
// tritjunction.cpp
struct hashVert_s *GetHashVert( idVec3 &v );
void HashTriangles( optimizeGroup_t *groupList );
void FreeTJunctionHash( void );
int CountGroupListTris( const optimizeGroup_t *groupList );
void FixEntityTjunctions( uEntity_t *e );
void FixAreaGroupsTjunctions( optimizeGroup_t *groupList );
void FixGlobalTjunctions( uEntity_t *e );
//=============================================================================
// optimize.cpp -- trianlge mesh reoptimization
// the shadow volume optimizer call internal optimizer routines, normal triangles
// will just be done by OptimizeEntity()
typedef struct optVertex_s {
idDrawVert v;
idVec3 pv; // projected against planar axis, third value is 0
struct optEdge_s *edges;
struct optVertex_s *islandLink;
bool addedToIsland;
bool emited; // when regenerating triangles
} optVertex_t;
typedef struct optEdge_s {
optVertex_t *v1, *v2;
struct optEdge_s *islandLink;
bool addedToIsland;
bool created; // not one of the original edges
bool combined; // combined from two or more colinear edges
struct optTri_s *frontTri, *backTri;
struct optEdge_s *v1link, *v2link;
} optEdge_t;
typedef struct optTri_s {
struct optTri_s *next;
idVec3 midpoint;
optVertex_t *v[3];
bool filled;
} optTri_t;
typedef struct {
optimizeGroup_t *group;
optVertex_t *verts;
optEdge_t *edges;
optTri_t *tris;
} optIsland_t;
void OptimizeEntity( uEntity_t *e );
void OptimizeGroupList( optimizeGroup_t *groupList );
//=============================================================================
// tritools.cpp
mapTri_t *AllocTri( void );
void FreeTri( mapTri_t *tri );
int CountTriList( const mapTri_t *list );
mapTri_t *MergeTriLists( mapTri_t *a, mapTri_t *b );
mapTri_t *CopyTriList( const mapTri_t *a );
void FreeTriList( mapTri_t *a );
mapTri_t *CopyMapTri( const mapTri_t *tri );
float MapTriArea( const mapTri_t *tri );
mapTri_t *RemoveBadTris( const mapTri_t *tri );
void BoundTriList( const mapTri_t *list, idBounds &b );
void DrawTri( const mapTri_t *tri );
void FlipTriList( mapTri_t *tris );
void TriVertsFromOriginal( mapTri_t *tri, const mapTri_t *original );
void PlaneForTri( const mapTri_t *tri, idPlane &plane );
idWinding *WindingForTri( const mapTri_t *tri );
mapTri_t *WindingToTriList( const idWinding *w, const mapTri_t *originalTri );
void ClipTriList( const mapTri_t *list, const idPlane &plane, float epsilon, mapTri_t **front, mapTri_t **back );
//=============================================================================
// output.cpp
srfTriangles_t *ShareMapTriVerts( const mapTri_t *tris );
void WriteOutputFile( void );
//=============================================================================
// shadowopt.cpp
srfTriangles_t *CreateLightShadow( optimizeGroup_t *shadowerGroups, const mapLight_t *light );
void FreeBeamTree( struct beamTree_s *beamTree );
void CarveTriByBeamTree( const struct beamTree_s *beamTree, const mapTri_t *tri, mapTri_t **lit, mapTri_t **unLit );