Paranoia2/utils/p2bsp/tree.cpp
2020-08-31 19:50:41 +03:00

263 lines
5.6 KiB
C++

/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
****/
#include "bsp5.h"
//===========================================================================
/*
===========
AllocTree
===========
*/
tree_t *AllocTree( void )
{
tree_t *t;
t = (tree_t *)Mem_Alloc( sizeof( tree_t ), C_BSPTREE );
ClearBounds( t->mins, t->maxs );
return t;
}
/*
===========
FreeTree
===========
*/
void FreeTree( tree_t *t )
{
Mem_Free( t, C_BSPTREE );
}
// =====================================================================================
// CheckFaceForHint
// Returns true if the passed face is facetype hint
// =====================================================================================
bool CheckFaceForHint( const face_t *f )
{
const char *name = GetTextureByTexinfo( f->texturenum );
if( !Q_strnicmp( name, "HINT", 4 ))
return true;
return false;
}
// =====================================================================================
// CheckFaceForHint
// Returns true if the passed face is facetype solidhint
// =====================================================================================
bool CheckFaceForDiscardable( const face_t *f )
{
const char *name = GetTextureByTexinfo( f->texturenum );
if( !Q_strnicmp( name, "SOLIDHINT", 9 ))
return true;
return false;
}
static facestyle_e SetFaceType( face_t *f )
{
if( CheckFaceForHint( f ))
f->facestyle = face_hint;
else if( CheckFaceForDiscardable( f ))
f->facestyle = face_discardable;
return f->facestyle;
}
/*
===============
SurflistFromValidFaces
===============
*/
void MakeSurflistFromValidFaces( tree_t *tree )
{
face_t *f, *next;
surface_t *n;
tree->surfaces = NULL;
ClearBounds( tree->mins, tree->maxs );
tree->numfaces = 0;
// grab planes from both sides
for( int i = 0; i < g_nummapplanes; i += 2 )
{
if( !tree->validfaces[i+0] && !tree->validfaces[i+1] )
continue;
n = AllocSurface();
n->next = tree->surfaces;
n->detaillevel = -1;
tree->surfaces = n;
tree->numsurfaces++;
n->planenum = i;
n->faces = NULL;
for( f = tree->validfaces[i+0]; f != NULL; f = next )
{
AddFaceToBounds( f, n->mins, n->maxs );
if( n->detaillevel == -1 || f->detaillevel < n->detaillevel )
n->detaillevel = f->detaillevel;
next = f->next;
f->next = n->faces;
n->faces = f;
tree->numfaces++;
}
for( f = tree->validfaces[i+1]; f != NULL; f = next )
{
AddFaceToBounds( f, n->mins, n->maxs );
if( n->detaillevel == -1 || f->detaillevel < n->detaillevel )
n->detaillevel = f->detaillevel;
next = f->next;
f->next = n->faces;
n->faces = f;
tree->numfaces++;
}
// update tree size
AddPointToBounds( n->mins, tree->mins, tree->maxs );
AddPointToBounds( n->maxs, tree->mins, tree->maxs );
tree->validfaces[i+0] = NULL;
tree->validfaces[i+1] = NULL;
}
// merge polygons
MergeTreeFaces( tree );
}
/*
===============
MakeTreeFromHullFaces
===============
*/
tree_t *MakeTreeFromHullFaces( FILE *polyfile, FILE *brushfile )
{
int texinfo, contents, numpoints;
int r, planenum, detaillevel;
tree_t *tree = NULL;
bool skipface;
int line = 0;
double v[3];
face_t *f;
// read in the polygons
while( 1 )
{
r = fscanf( polyfile, "%i %i %i %i %i\n", &detaillevel, &planenum, &texinfo, &contents, &numpoints );
skipface = false;
line++;
if( r == 0 || r == -1 )
return NULL;
// alloc a new tree for model
if( !tree ) tree = AllocTree();
if( planenum == -1 ) // end of model
break;
if( r != 5 )
COM_FatalError( "ReadSurfs (line %i): scanf failure %d != 5\n", line, r );
if( planenum > g_nummapplanes )
COM_FatalError( "ReadSurfs (line %i): %i > numplanes\n", line, planenum );
if( texinfo > g_numtexinfo )
COM_FatalError( "ReadSurfs (line %i): %i > numtexinfo\n", line, texinfo );
if( detaillevel < 0 )
COM_FatalError( "ReadSurfs (line %i): detaillevel %i < 0", line, detaillevel);
if( !Q_stricmp( GetTextureByTexinfo( texinfo ), "SKIP" ))
skipface = true;
if( !skipface )
{
f = AllocFace ();
f->planenum = planenum;
f->texturenum = texinfo;
f->contents = contents;
f->detaillevel = detaillevel;
f->w = AllocWinding( numpoints );
f->w->numpoints = numpoints;
f->next = tree->validfaces[planenum];
tree->validfaces[planenum] = f;
SetFaceType( f );
}
// restore winding
for( int i = 0; i < numpoints; i++ )
{
r = fscanf( polyfile, "%lf %lf %lf\n", &v[0], &v[1], &v[2] );
if( !skipface ) VectorCopy( v, f->w->p[i] );
line++;
}
fscanf( polyfile, "\n" );
line++;
}
MakeSurflistFromValidFaces( tree );
// time to read detailbrushes
tree->detailbrushes = ReadBrushes( brushfile );
return tree;
}
/*
===============
TreeProcessModel
===============
*/
tree_t *TreeProcessModel( tree_t *tree, int modnum, int hullnum )
{
bool worldmodel = (modnum == 0);
if( hullnum == 0 )
{
// if not the world, make a good tree first
// the world is just going to make a bad tree
// because the outside filling will force a regeneration later
SolidBSP( tree, modnum, hullnum ); // SolidBSP generates a node tree
if( worldmodel && !g_nofill )
{
FillInside( tree->headnode );
FillOutside( tree, hullnum, true );
}
FreeTreePortals( tree );
// fix tjunctions
tjunc( tree->headnode, worldmodel );
MakeFaceEdges();
}
else
{
// clipping tree are simply
SolidBSP( tree, modnum, hullnum );
// assume non-world bmodels are simple
if( worldmodel && !g_nofill && !g_noclip )
FillOutside( tree, hullnum, false );
FreeTreePortals( tree );
}
return tree;
}