mirror of
https://github.com/id-Software/DOOM-3.git
synced 2026-03-20 00:49:31 +01:00
hello world
This commit is contained in:
499
neo/tools/compilers/dmap/facebsp.cpp
Normal file
499
neo/tools/compilers/dmap/facebsp.cpp
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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 "../../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "dmap.h"
|
||||
|
||||
int c_faceLeafs;
|
||||
|
||||
|
||||
extern int c_nodes;
|
||||
|
||||
void RemovePortalFromNode( uPortal_t *portal, node_t *l );
|
||||
|
||||
node_t *NodeForPoint( node_t *node, idVec3 origin ) {
|
||||
float d;
|
||||
|
||||
while( node->planenum != PLANENUM_LEAF ) {
|
||||
idPlane &plane = dmapGlobals.mapPlanes[node->planenum];
|
||||
d = plane.Distance( origin );
|
||||
if ( d >= 0 ) {
|
||||
node = node->children[0];
|
||||
} else {
|
||||
node = node->children[1];
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTreePortals_r
|
||||
=============
|
||||
*/
|
||||
void FreeTreePortals_r (node_t *node)
|
||||
{
|
||||
uPortal_t *p, *nextp;
|
||||
int s;
|
||||
|
||||
// free children
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
FreeTreePortals_r (node->children[0]);
|
||||
FreeTreePortals_r (node->children[1]);
|
||||
}
|
||||
|
||||
// free portals
|
||||
for (p=node->portals ; p ; p=nextp)
|
||||
{
|
||||
s = (p->nodes[1] == node);
|
||||
nextp = p->next[s];
|
||||
|
||||
RemovePortalFromNode (p, p->nodes[!s]);
|
||||
FreePortal (p);
|
||||
}
|
||||
node->portals = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTree_r
|
||||
=============
|
||||
*/
|
||||
void FreeTree_r (node_t *node)
|
||||
{
|
||||
// free children
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
FreeTree_r (node->children[0]);
|
||||
FreeTree_r (node->children[1]);
|
||||
}
|
||||
|
||||
// free brushes
|
||||
FreeBrushList (node->brushlist);
|
||||
|
||||
// free the node
|
||||
c_nodes--;
|
||||
Mem_Free (node);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
FreeTree
|
||||
=============
|
||||
*/
|
||||
void FreeTree( tree_t *tree ) {
|
||||
if ( !tree ) {
|
||||
return;
|
||||
}
|
||||
FreeTreePortals_r (tree->headnode);
|
||||
FreeTree_r (tree->headnode);
|
||||
Mem_Free (tree);
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
void PrintTree_r (node_t *node, int depth)
|
||||
{
|
||||
int i;
|
||||
uBrush_t *bb;
|
||||
|
||||
for (i=0 ; i<depth ; i++)
|
||||
common->Printf(" ");
|
||||
if (node->planenum == PLANENUM_LEAF)
|
||||
{
|
||||
if (!node->brushlist)
|
||||
common->Printf("NULL\n");
|
||||
else
|
||||
{
|
||||
for (bb=node->brushlist ; bb ; bb=bb->next)
|
||||
common->Printf("%i ", bb->original->brushnum);
|
||||
common->Printf("\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
idPlane &plane = dmapGlobals.mapPlanes[node->planenum];
|
||||
common->Printf( "#%i (%5.2f %5.2f %5.2f %5.2f)\n", node->planenum,
|
||||
plane[0], plane[1], plane[2], plane[3] );
|
||||
PrintTree_r( node->children[0], depth+1 );
|
||||
PrintTree_r( node->children[1], depth+1 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
AllocBspFace
|
||||
================
|
||||
*/
|
||||
bspface_t *AllocBspFace( void ) {
|
||||
bspface_t *f;
|
||||
|
||||
f = (bspface_t *)Mem_Alloc(sizeof(*f));
|
||||
memset( f, 0, sizeof(*f) );
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FreeBspFace
|
||||
================
|
||||
*/
|
||||
void FreeBspFace( bspface_t *f ) {
|
||||
if ( f->w ) {
|
||||
delete f->w;
|
||||
}
|
||||
Mem_Free( f );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SelectSplitPlaneNum
|
||||
================
|
||||
*/
|
||||
#define BLOCK_SIZE 1024
|
||||
int SelectSplitPlaneNum( node_t *node, bspface_t *list ) {
|
||||
bspface_t *split;
|
||||
bspface_t *check;
|
||||
bspface_t *bestSplit;
|
||||
int splits, facing, front, back;
|
||||
int side;
|
||||
idPlane *mapPlane;
|
||||
int value, bestValue;
|
||||
idPlane plane;
|
||||
int planenum;
|
||||
bool havePortals;
|
||||
float dist;
|
||||
idVec3 halfSize;
|
||||
|
||||
// if it is crossing a 1k block boundary, force a split
|
||||
// this prevents epsilon problems from extending an
|
||||
// arbitrary distance across the map
|
||||
|
||||
halfSize = ( node->bounds[1] - node->bounds[0] ) * 0.5f;
|
||||
for ( int axis = 0; axis < 3; axis++ ) {
|
||||
if ( halfSize[axis] > BLOCK_SIZE ) {
|
||||
dist = BLOCK_SIZE * ( floor( ( node->bounds[0][axis] + halfSize[axis] ) / BLOCK_SIZE ) + 1.0f );
|
||||
} else {
|
||||
dist = BLOCK_SIZE * ( floor( node->bounds[0][axis] / BLOCK_SIZE ) + 1.0f );
|
||||
}
|
||||
if ( dist > node->bounds[0][axis] + 1.0f && dist < node->bounds[1][axis] - 1.0f ) {
|
||||
plane[0] = plane[1] = plane[2] = 0.0f;
|
||||
plane[axis] = 1.0f;
|
||||
plane[3] = -dist;
|
||||
planenum = FindFloatPlane( plane );
|
||||
return planenum;
|
||||
}
|
||||
}
|
||||
|
||||
// pick one of the face planes
|
||||
// if we have any portal faces at all, only
|
||||
// select from them, otherwise select from
|
||||
// all faces
|
||||
bestValue = -999999;
|
||||
bestSplit = list;
|
||||
|
||||
havePortals = false;
|
||||
for ( split = list ; split ; split = split->next ) {
|
||||
split->checked = false;
|
||||
if ( split->portal ) {
|
||||
havePortals = true;
|
||||
}
|
||||
}
|
||||
|
||||
for ( split = list ; split ; split = split->next ) {
|
||||
if ( split->checked ) {
|
||||
continue;
|
||||
}
|
||||
if ( havePortals != split->portal ) {
|
||||
continue;
|
||||
}
|
||||
mapPlane = &dmapGlobals.mapPlanes[ split->planenum ];
|
||||
splits = 0;
|
||||
facing = 0;
|
||||
front = 0;
|
||||
back = 0;
|
||||
for ( check = list ; check ; check = check->next ) {
|
||||
if ( check->planenum == split->planenum ) {
|
||||
facing++;
|
||||
check->checked = true; // won't need to test this plane again
|
||||
continue;
|
||||
}
|
||||
side = check->w->PlaneSide( *mapPlane );
|
||||
if ( side == SIDE_CROSS ) {
|
||||
splits++;
|
||||
} else if ( side == SIDE_FRONT ) {
|
||||
front++;
|
||||
} else if ( side == SIDE_BACK ) {
|
||||
back++;
|
||||
}
|
||||
}
|
||||
value = 5*facing - 5*splits; // - abs(front-back);
|
||||
if ( mapPlane->Type() < PLANETYPE_TRUEAXIAL ) {
|
||||
value+=5; // axial is better
|
||||
}
|
||||
|
||||
if ( value > bestValue ) {
|
||||
bestValue = value;
|
||||
bestSplit = split;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bestValue == -999999 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bestSplit->planenum;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
BuildFaceTree_r
|
||||
================
|
||||
*/
|
||||
void BuildFaceTree_r( node_t *node, bspface_t *list ) {
|
||||
bspface_t *split;
|
||||
bspface_t *next;
|
||||
int side;
|
||||
bspface_t *newFace;
|
||||
bspface_t *childLists[2];
|
||||
idWinding *frontWinding, *backWinding;
|
||||
int i;
|
||||
int splitPlaneNum;
|
||||
|
||||
splitPlaneNum = SelectSplitPlaneNum( node, list );
|
||||
// if we don't have any more faces, this is a node
|
||||
if ( splitPlaneNum == -1 ) {
|
||||
node->planenum = PLANENUM_LEAF;
|
||||
c_faceLeafs++;
|
||||
return;
|
||||
}
|
||||
|
||||
// partition the list
|
||||
node->planenum = splitPlaneNum;
|
||||
idPlane &plane = dmapGlobals.mapPlanes[ splitPlaneNum ];
|
||||
childLists[0] = NULL;
|
||||
childLists[1] = NULL;
|
||||
for ( split = list ; split ; split = next ) {
|
||||
next = split->next;
|
||||
|
||||
if ( split->planenum == node->planenum ) {
|
||||
FreeBspFace( split );
|
||||
continue;
|
||||
}
|
||||
|
||||
side = split->w->PlaneSide( plane );
|
||||
|
||||
if ( side == SIDE_CROSS ) {
|
||||
split->w->Split( plane, CLIP_EPSILON * 2, &frontWinding, &backWinding );
|
||||
if ( frontWinding ) {
|
||||
newFace = AllocBspFace();
|
||||
newFace->w = frontWinding;
|
||||
newFace->next = childLists[0];
|
||||
newFace->planenum = split->planenum;
|
||||
childLists[0] = newFace;
|
||||
}
|
||||
if ( backWinding ) {
|
||||
newFace = AllocBspFace();
|
||||
newFace->w = backWinding;
|
||||
newFace->next = childLists[1];
|
||||
newFace->planenum = split->planenum;
|
||||
childLists[1] = newFace;
|
||||
}
|
||||
FreeBspFace( split );
|
||||
} else if ( side == SIDE_FRONT ) {
|
||||
split->next = childLists[0];
|
||||
childLists[0] = split;
|
||||
} else if ( side == SIDE_BACK ) {
|
||||
split->next = childLists[1];
|
||||
childLists[1] = split;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// recursively process children
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
node->children[i] = AllocNode();
|
||||
node->children[i]->parent = node;
|
||||
node->children[i]->bounds = node->bounds;
|
||||
}
|
||||
|
||||
// split the bounds if we have a nice axial plane
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( idMath::Fabs( plane[i] - 1.0 ) < 0.001 ) {
|
||||
node->children[0]->bounds[0][i] = plane.Dist();
|
||||
node->children[1]->bounds[1][i] = plane.Dist();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 2 ; i++ ) {
|
||||
BuildFaceTree_r ( node->children[i], childLists[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
FaceBSP
|
||||
|
||||
List will be freed before returning
|
||||
================
|
||||
*/
|
||||
tree_t *FaceBSP( bspface_t *list ) {
|
||||
tree_t *tree;
|
||||
bspface_t *face;
|
||||
int i;
|
||||
int count;
|
||||
int start, end;
|
||||
|
||||
start = Sys_Milliseconds();
|
||||
|
||||
common->Printf( "--- FaceBSP ---\n" );
|
||||
|
||||
tree = AllocTree ();
|
||||
|
||||
count = 0;
|
||||
tree->bounds.Clear();
|
||||
for ( face = list ; face ; face = face->next ) {
|
||||
count++;
|
||||
for ( i = 0 ; i < face->w->GetNumPoints() ; i++ ) {
|
||||
tree->bounds.AddPoint( (*face->w)[i].ToVec3() );
|
||||
}
|
||||
}
|
||||
common->Printf( "%5i faces\n", count );
|
||||
|
||||
tree->headnode = AllocNode();
|
||||
tree->headnode->bounds = tree->bounds;
|
||||
c_faceLeafs = 0;
|
||||
|
||||
BuildFaceTree_r ( tree->headnode, list );
|
||||
|
||||
common->Printf( "%5i leafs\n", c_faceLeafs );
|
||||
|
||||
end = Sys_Milliseconds();
|
||||
|
||||
common->Printf( "%5.1f seconds faceBsp\n", ( end - start ) / 1000.0 );
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeStructuralBspFaceList
|
||||
=================
|
||||
*/
|
||||
bspface_t *MakeStructuralBspFaceList( primitive_t *list ) {
|
||||
uBrush_t *b;
|
||||
int i;
|
||||
side_t *s;
|
||||
idWinding *w;
|
||||
bspface_t *f, *flist;
|
||||
|
||||
flist = NULL;
|
||||
for ( ; list ; list = list->next ) {
|
||||
b = list->brush;
|
||||
if ( !b ) {
|
||||
continue;
|
||||
}
|
||||
if ( !b->opaque && !( b->contents & CONTENTS_AREAPORTAL ) ) {
|
||||
continue;
|
||||
}
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
s = &b->sides[i];
|
||||
w = s->winding;
|
||||
if ( !w ) {
|
||||
continue;
|
||||
}
|
||||
if ( ( b->contents & CONTENTS_AREAPORTAL ) && ! ( s->material->GetContentFlags() & CONTENTS_AREAPORTAL ) ) {
|
||||
continue;
|
||||
}
|
||||
f = AllocBspFace();
|
||||
if ( s->material->GetContentFlags() & CONTENTS_AREAPORTAL ) {
|
||||
f->portal = true;
|
||||
}
|
||||
f->w = w->Copy();
|
||||
f->planenum = s->planenum & ~1;
|
||||
f->next = flist;
|
||||
flist = f;
|
||||
}
|
||||
}
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
MakeVisibleBspFaceList
|
||||
=================
|
||||
*/
|
||||
bspface_t *MakeVisibleBspFaceList( primitive_t *list ) {
|
||||
uBrush_t *b;
|
||||
int i;
|
||||
side_t *s;
|
||||
idWinding *w;
|
||||
bspface_t *f, *flist;
|
||||
|
||||
flist = NULL;
|
||||
for ( ; list ; list = list->next ) {
|
||||
b = list->brush;
|
||||
if ( !b ) {
|
||||
continue;
|
||||
}
|
||||
if ( !b->opaque && !( b->contents & CONTENTS_AREAPORTAL ) ) {
|
||||
continue;
|
||||
}
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
s = &b->sides[i];
|
||||
w = s->visibleHull;
|
||||
if ( !w ) {
|
||||
continue;
|
||||
}
|
||||
f = AllocBspFace();
|
||||
if ( s->material->GetContentFlags() & CONTENTS_AREAPORTAL ) {
|
||||
f->portal = true;
|
||||
}
|
||||
f->w = w->Copy();
|
||||
f->planenum = s->planenum & ~1;
|
||||
f->next = flist;
|
||||
flist = f;
|
||||
}
|
||||
}
|
||||
|
||||
return flist;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user