2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition 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 BFG Edition 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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
# include "../idlib/precompiled.h"
# include "tr_local.h"
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : FreeWorld
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : FreeWorld ( )
{
2012-11-26 18:58:24 +00:00
// this will free all the lightDefs and entityDefs
FreeDefs ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free all the portals and check light/model references
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numPortalAreas ; i + + )
{
portalArea_t * area ;
portal_t * portal , * nextPortal ;
2012-11-26 18:58:24 +00:00
area = & portalAreas [ i ] ;
2012-11-28 15:47:07 +00:00
for ( portal = area - > portals ; portal ; portal = nextPortal )
{
2012-11-26 18:58:24 +00:00
nextPortal = portal - > next ;
delete portal - > w ;
R_StaticFree ( portal ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// there shouldn't be any remaining lightRefs or entityRefs
2012-11-28 15:47:07 +00:00
if ( area - > lightRefs . areaNext ! = & area - > lightRefs )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " FreeWorld: unexpected remaining lightRefs " ) ;
}
2012-11-28 15:47:07 +00:00
if ( area - > entityRefs . areaNext ! = & area - > entityRefs )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " FreeWorld: unexpected remaining entityRefs " ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( portalAreas )
{
2012-11-26 18:58:24 +00:00
R_StaticFree ( portalAreas ) ;
portalAreas = NULL ;
numPortalAreas = 0 ;
R_StaticFree ( areaScreenRect ) ;
areaScreenRect = NULL ;
}
2012-11-28 15:47:07 +00:00
if ( doublePortals )
{
2012-11-26 18:58:24 +00:00
R_StaticFree ( doublePortals ) ;
doublePortals = NULL ;
numInterAreaPortals = 0 ;
}
2012-11-28 15:47:07 +00:00
if ( areaNodes )
{
2012-11-26 18:58:24 +00:00
R_StaticFree ( areaNodes ) ;
areaNodes = NULL ;
}
2012-11-28 15:47:07 +00:00
// free all the inline idRenderModels
for ( int i = 0 ; i < localModels . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
renderModelManager - > RemoveModel ( localModels [ i ] ) ;
delete localModels [ i ] ;
}
localModels . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
areaReferenceAllocator . Shutdown ( ) ;
interactionAllocator . Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapName = " <FREED> " ;
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : TouchWorldModels
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : TouchWorldModels ( )
{
for ( int i = 0 ; i < localModels . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
renderModelManager - > CheckModel ( localModels [ i ] - > Name ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ReadBinaryShadowModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idRenderModel * idRenderWorldLocal : : ReadBinaryModel ( idFile * fileIn )
{
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > name ;
fileIn - > ReadString ( name ) ;
2012-11-28 15:47:07 +00:00
idRenderModel * model = renderModelManager - > AllocModel ( ) ;
2012-11-26 18:58:24 +00:00
model - > InitEmpty ( name ) ;
2012-11-28 15:47:07 +00:00
if ( model - > LoadBinaryModel ( fileIn , mapTimeStamp ) )
{
2012-11-26 18:58:24 +00:00
return model ;
}
return NULL ;
}
extern idCVar r_binaryLoadRenderModels ;
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ParseModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idRenderModel * idRenderWorldLocal : : ParseModel ( idLexer * src , const char * mapName , ID_TIME_T mapTimeStamp , idFile * fileOut )
{
2012-11-26 18:58:24 +00:00
idToken token ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " { " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse the name
src - > ExpectAnyToken ( & token ) ;
2012-11-28 15:47:07 +00:00
idRenderModel * model = renderModelManager - > AllocModel ( ) ;
2012-11-26 18:58:24 +00:00
model - > InitEmpty ( token ) ;
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
// write out the type so the binary reader knows what to instantiate
fileOut - > WriteString ( " shadowmodel " ) ;
fileOut - > WriteString ( token ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numSurfaces = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( numSurfaces < 0 )
{
2012-11-26 18:58:24 +00:00
src - > Error ( " R_ParseModel: bad numSurfaces " ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numSurfaces ; i + + )
{
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " { " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectAnyToken ( & token ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
modelSurface_t surf ;
surf . shader = declManager - > FindMaterial ( token ) ;
2012-11-28 15:47:07 +00:00
( ( idMaterial * ) surf . shader ) - > AddReference ( ) ;
srfTriangles_t * tri = R_AllocStaticTriSurf ( ) ;
2012-11-26 18:58:24 +00:00
surf . geometry = tri ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
tri - > numVerts = src - > ParseInt ( ) ;
tri - > numIndexes = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse the vertices
idTempArray < float > verts ( tri - > numVerts * 8 ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numVerts ; j + + )
{
2012-11-26 18:58:24 +00:00
src - > Parse1DMatrix ( 8 , & verts [ j * 8 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse the indices
idTempArray < triIndex_t > indexes ( tri - > numIndexes ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numIndexes ; j + + )
{
2012-11-26 18:58:24 +00:00
indexes [ j ] = src - > ParseInt ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# if 1
// find the island that each vertex belongs to
idTempArray < int > vertIslands ( tri - > numVerts ) ;
idTempArray < bool > trisVisited ( tri - > numIndexes ) ;
vertIslands . Zero ( ) ;
trisVisited . Zero ( ) ;
int numIslands = 0 ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numIndexes ; j + = 3 )
{
if ( trisVisited [ j ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int islandNum = + + numIslands ;
vertIslands [ indexes [ j + 0 ] ] = islandNum ;
vertIslands [ indexes [ j + 1 ] ] = islandNum ;
vertIslands [ indexes [ j + 2 ] ] = islandNum ;
trisVisited [ j ] = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idList < int > queue ;
queue . Append ( j ) ;
2012-11-28 15:47:07 +00:00
for ( int n = 0 ; n < queue . Num ( ) ; n + + )
{
2012-11-26 18:58:24 +00:00
int t = queue [ n ] ;
2012-11-28 15:47:07 +00:00
for ( int k = 0 ; k < tri - > numIndexes ; k + = 3 )
{
if ( trisVisited [ k ] )
{
2012-11-26 18:58:24 +00:00
continue ;
}
bool connected = indexes [ t + 0 ] = = indexes [ k + 0 ] | | indexes [ t + 0 ] = = indexes [ k + 1 ] | | indexes [ t + 0 ] = = indexes [ k + 2 ] | |
indexes [ t + 1 ] = = indexes [ k + 0 ] | | indexes [ t + 1 ] = = indexes [ k + 1 ] | | indexes [ t + 1 ] = = indexes [ k + 2 ] | |
indexes [ t + 2 ] = = indexes [ k + 0 ] | | indexes [ t + 2 ] = = indexes [ k + 1 ] | | indexes [ t + 2 ] = = indexes [ k + 2 ] ;
2012-11-28 15:47:07 +00:00
if ( connected )
{
2012-11-26 18:58:24 +00:00
vertIslands [ indexes [ k + 0 ] ] = islandNum ;
vertIslands [ indexes [ k + 1 ] ] = islandNum ;
vertIslands [ indexes [ k + 2 ] ] = islandNum ;
trisVisited [ k ] = true ;
queue . Append ( k ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// center the texture coordinates for each island for maximum 16-bit precision
2012-11-28 15:47:07 +00:00
for ( int j = 1 ; j < = numIslands ; j + + )
{
2012-11-26 18:58:24 +00:00
float minS = idMath : : INFINITY ;
float minT = idMath : : INFINITY ;
float maxS = - idMath : : INFINITY ;
float maxT = - idMath : : INFINITY ;
2012-11-28 15:47:07 +00:00
for ( int k = 0 ; k < tri - > numVerts ; k + + )
{
if ( vertIslands [ k ] = = j )
{
2012-11-26 18:58:24 +00:00
minS = Min ( minS , verts [ k * 8 + 3 ] ) ;
maxS = Max ( maxS , verts [ k * 8 + 3 ] ) ;
minT = Min ( minT , verts [ k * 8 + 4 ] ) ;
maxT = Max ( maxT , verts [ k * 8 + 4 ] ) ;
}
}
const float averageS = idMath : : Ftoi ( ( minS + maxS ) * 0.5f ) ;
const float averageT = idMath : : Ftoi ( ( minT + maxT ) * 0.5f ) ;
2012-11-28 15:47:07 +00:00
for ( int k = 0 ; k < tri - > numVerts ; k + + )
{
if ( vertIslands [ k ] = = j )
{
2012-11-26 18:58:24 +00:00
verts [ k * 8 + 3 ] - = averageS ;
verts [ k * 8 + 4 ] - = averageT ;
}
}
}
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
R_AllocStaticTriSurfVerts ( tri , tri - > numVerts ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numVerts ; j + + )
{
2012-11-26 18:58:24 +00:00
tri - > verts [ j ] . xyz [ 0 ] = verts [ j * 8 + 0 ] ;
tri - > verts [ j ] . xyz [ 1 ] = verts [ j * 8 + 1 ] ;
tri - > verts [ j ] . xyz [ 2 ] = verts [ j * 8 + 2 ] ;
tri - > verts [ j ] . SetTexCoord ( verts [ j * 8 + 3 ] , verts [ j * 8 + 4 ] ) ;
tri - > verts [ j ] . SetNormal ( verts [ j * 8 + 5 ] , verts [ j * 8 + 6 ] , verts [ j * 8 + 7 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
R_AllocStaticTriSurfIndexes ( tri , tri - > numIndexes ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numIndexes ; j + + )
{
2012-11-26 18:58:24 +00:00
tri - > indexes [ j ] = indexes [ j ] ;
}
src - > ExpectTokenString ( " } " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add the completed surface to the model
model - > AddSurface ( surf ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " } " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
model - > FinishSurfaces ( ) ;
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL & & model - > SupportsBinaryModel ( ) & & r_binaryLoadRenderModels . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
model - > WriteBinaryModel ( fileOut , & mapTimeStamp ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return model ;
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ReadBinaryShadowModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idRenderModel * idRenderWorldLocal : : ReadBinaryShadowModel ( idFile * fileIn )
{
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > name ;
fileIn - > ReadString ( name ) ;
2012-11-28 15:47:07 +00:00
idRenderModel * model = renderModelManager - > AllocModel ( ) ;
2012-11-26 18:58:24 +00:00
model - > InitEmpty ( name ) ;
2012-11-28 15:47:07 +00:00
if ( model - > LoadBinaryModel ( fileIn , mapTimeStamp ) )
{
2012-11-26 18:58:24 +00:00
return model ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ParseShadowModel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idRenderModel * idRenderWorldLocal : : ParseShadowModel ( idLexer * src , idFile * fileOut )
{
2012-11-26 18:58:24 +00:00
idToken token ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " { " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse the name
src - > ExpectAnyToken ( & token ) ;
2012-11-28 15:47:07 +00:00
idRenderModel * model = renderModelManager - > AllocModel ( ) ;
2012-11-26 18:58:24 +00:00
model - > InitEmpty ( token ) ;
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
// write out the type so the binary reader knows what to instantiate
fileOut - > WriteString ( " shadowmodel " ) ;
fileOut - > WriteString ( token ) ;
}
2012-11-28 15:47:07 +00:00
srfTriangles_t * tri = R_AllocStaticTriSurf ( ) ;
2012-11-26 18:58:24 +00:00
tri - > numVerts = src - > ParseInt ( ) ;
tri - > numShadowIndexesNoCaps = src - > ParseInt ( ) ;
tri - > numShadowIndexesNoFrontCaps = src - > ParseInt ( ) ;
tri - > numIndexes = src - > ParseInt ( ) ;
tri - > shadowCapPlaneBits = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( ( tri - > numVerts & 1 ) = = 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
R_AllocStaticTriSurfPreLightShadowVerts ( tri , ALIGN ( tri - > numVerts , 2 ) ) ;
tri - > bounds . Clear ( ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numVerts ; j + + )
{
2012-11-26 18:58:24 +00:00
float vec [ 8 ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > Parse1DMatrix ( 3 , vec ) ;
tri - > preLightShadowVertexes [ j ] . xyzw [ 0 ] = vec [ 0 ] ;
tri - > preLightShadowVertexes [ j ] . xyzw [ 1 ] = vec [ 1 ] ;
tri - > preLightShadowVertexes [ j ] . xyzw [ 2 ] = vec [ 2 ] ;
tri - > preLightShadowVertexes [ j ] . xyzw [ 3 ] = 1.0f ; // no homogenous value
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
tri - > bounds . AddPoint ( tri - > preLightShadowVertexes [ j ] . xyzw . ToVec3 ( ) ) ;
}
// clear the last vertex if it wasn't stored
2012-11-28 15:47:07 +00:00
if ( ( tri - > numVerts & 1 ) ! = 0 )
{
2012-11-26 18:58:24 +00:00
tri - > preLightShadowVertexes [ ALIGN ( tri - > numVerts , 2 ) - 1 ] . xyzw . Zero ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// to be consistent set the number of vertices to half the number of shadow vertices
tri - > numVerts = ALIGN ( tri - > numVerts , 2 ) / 2 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
R_AllocStaticTriSurfIndexes ( tri , tri - > numIndexes ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < tri - > numIndexes ; j + + )
{
2012-11-26 18:58:24 +00:00
tri - > indexes [ j ] = src - > ParseInt ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add the completed surface to the model
modelSurface_t surf ;
surf . id = 0 ;
surf . shader = tr . defaultMaterial ;
surf . geometry = tri ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
model - > AddSurface ( surf ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " } " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// NOTE: we do NOT do a model->FinishSurfaceces, because we don't need sil edges, planes, tangents, etc.
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL & & model - > SupportsBinaryModel ( ) & & r_binaryLoadRenderModels . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
model - > WriteBinaryModel ( fileOut , & mapTimeStamp ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return model ;
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : SetupAreaRefs
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : SetupAreaRefs ( )
{
2012-11-26 18:58:24 +00:00
connectedAreaNum = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numPortalAreas ; i + + )
{
2012-11-26 18:58:24 +00:00
portalAreas [ i ] . areaNum = i ;
portalAreas [ i ] . lightRefs . areaNext =
2012-11-28 15:47:07 +00:00
portalAreas [ i ] . lightRefs . areaPrev = & portalAreas [ i ] . lightRefs ;
2012-11-26 18:58:24 +00:00
portalAreas [ i ] . entityRefs . areaNext =
2012-11-28 15:47:07 +00:00
portalAreas [ i ] . entityRefs . areaPrev = & portalAreas [ i ] . entityRefs ;
2012-11-26 18:58:24 +00:00
}
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ParseInterAreaPortals
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ParseInterAreaPortals ( idLexer * src , idFile * fileOut )
{
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " { " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numPortalAreas = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( numPortalAreas < 0 )
{
2012-11-26 18:58:24 +00:00
src - > Error ( " R_ParseInterAreaPortals: bad numPortalAreas " ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
// write out the type so the binary reader knows what to instantiate
fileOut - > WriteString ( " interAreaPortals " ) ;
}
2012-11-28 15:47:07 +00:00
portalAreas = ( portalArea_t * ) R_ClearedStaticAlloc ( numPortalAreas * sizeof ( portalAreas [ 0 ] ) ) ;
areaScreenRect = ( idScreenRect * ) R_ClearedStaticAlloc ( numPortalAreas * sizeof ( idScreenRect ) ) ;
2012-11-26 18:58:24 +00:00
// set the doubly linked lists
SetupAreaRefs ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numInterAreaPortals = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( numInterAreaPortals < 0 )
{
src - > Error ( " R_ParseInterAreaPortals: bad numInterAreaPortals " ) ;
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
fileOut - > WriteBig ( numPortalAreas ) ;
fileOut - > WriteBig ( numInterAreaPortals ) ;
}
2012-11-28 15:47:07 +00:00
doublePortals = ( doublePortal_t * ) R_ClearedStaticAlloc ( numInterAreaPortals *
sizeof ( doublePortals [ 0 ] ) ) ;
for ( int i = 0 ; i < numInterAreaPortals ; i + + )
{
2012-11-26 18:58:24 +00:00
int numPoints , a1 , a2 ;
2012-11-28 15:47:07 +00:00
idWinding * w ;
portal_t * p ;
2012-11-26 18:58:24 +00:00
numPoints = src - > ParseInt ( ) ;
a1 = src - > ParseInt ( ) ;
a2 = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
fileOut - > WriteBig ( numPoints ) ;
fileOut - > WriteBig ( a1 ) ;
fileOut - > WriteBig ( a2 ) ;
}
2012-11-28 15:47:07 +00:00
w = new ( TAG_RENDER_WINDING ) idWinding ( numPoints ) ;
2012-11-26 18:58:24 +00:00
w - > SetNumPoints ( numPoints ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < numPoints ; j + + )
{
src - > Parse1DMatrix ( 3 , ( * w ) [ j ] . ToFloatPtr ( ) ) ;
if ( fileOut ! = NULL )
{
fileOut - > WriteBig ( ( * w ) [ j ] . x ) ;
fileOut - > WriteBig ( ( * w ) [ j ] . y ) ;
fileOut - > WriteBig ( ( * w ) [ j ] . z ) ;
2012-11-26 18:58:24 +00:00
}
// no texture coordinates
2012-11-28 15:47:07 +00:00
( * w ) [ j ] [ 3 ] = 0 ;
( * w ) [ j ] [ 4 ] = 0 ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add the portal to a1
2012-11-28 15:47:07 +00:00
p = ( portal_t * ) R_ClearedStaticAlloc ( sizeof ( * p ) ) ;
2012-11-26 18:58:24 +00:00
p - > intoArea = a2 ;
p - > doublePortal = & doublePortals [ i ] ;
p - > w = w ;
p - > w - > GetPlane ( p - > plane ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
p - > next = portalAreas [ a1 ] . portals ;
portalAreas [ a1 ] . portals = p ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
doublePortals [ i ] . portals [ 0 ] = p ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reverse it for a2
2012-11-28 15:47:07 +00:00
p = ( portal_t * ) R_ClearedStaticAlloc ( sizeof ( * p ) ) ;
2012-11-26 18:58:24 +00:00
p - > intoArea = a1 ;
p - > doublePortal = & doublePortals [ i ] ;
p - > w = w - > Reverse ( ) ;
p - > w - > GetPlane ( p - > plane ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
p - > next = portalAreas [ a2 ] . portals ;
portalAreas [ a2 ] . portals = p ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
doublePortals [ i ] . portals [ 1 ] = p ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " } " ) ;
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ParseInterAreaPortals
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ReadBinaryAreaPortals ( idFile * file )
{
2012-11-26 18:58:24 +00:00
file - > ReadBig ( numPortalAreas ) ;
file - > ReadBig ( numInterAreaPortals ) ;
2012-11-28 15:47:07 +00:00
portalAreas = ( portalArea_t * ) R_ClearedStaticAlloc ( numPortalAreas * sizeof ( portalAreas [ 0 ] ) ) ;
areaScreenRect = ( idScreenRect * ) R_ClearedStaticAlloc ( numPortalAreas * sizeof ( idScreenRect ) ) ;
2012-11-26 18:58:24 +00:00
// set the doubly linked lists
SetupAreaRefs ( ) ;
2012-11-28 15:47:07 +00:00
doublePortals = ( doublePortal_t * ) R_ClearedStaticAlloc ( numInterAreaPortals * sizeof ( doublePortals [ 0 ] ) ) ;
for ( int i = 0 ; i < numInterAreaPortals ; i + + )
{
2012-11-26 18:58:24 +00:00
int numPoints , a1 , a2 ;
2012-11-28 15:47:07 +00:00
idWinding * w ;
portal_t * p ;
2012-11-26 18:58:24 +00:00
file - > ReadBig ( numPoints ) ;
file - > ReadBig ( a1 ) ;
file - > ReadBig ( a2 ) ;
2012-11-28 15:47:07 +00:00
w = new ( TAG_RENDER_WINDING ) idWinding ( numPoints ) ;
2012-11-26 18:58:24 +00:00
w - > SetNumPoints ( numPoints ) ;
2012-11-28 15:47:07 +00:00
for ( int j = 0 ; j < numPoints ; j + + )
{
file - > ReadBig ( ( * w ) [ j ] [ 0 ] ) ;
file - > ReadBig ( ( * w ) [ j ] [ 1 ] ) ;
file - > ReadBig ( ( * w ) [ j ] [ 2 ] ) ;
2012-11-26 18:58:24 +00:00
// no texture coordinates
2012-11-28 15:47:07 +00:00
( * w ) [ j ] [ 3 ] = 0 ;
( * w ) [ j ] [ 4 ] = 0 ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add the portal to a1
2012-11-28 15:47:07 +00:00
p = ( portal_t * ) R_ClearedStaticAlloc ( sizeof ( * p ) ) ;
2012-11-26 18:58:24 +00:00
p - > intoArea = a2 ;
p - > doublePortal = & doublePortals [ i ] ;
p - > w = w ;
p - > w - > GetPlane ( p - > plane ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
p - > next = portalAreas [ a1 ] . portals ;
portalAreas [ a1 ] . portals = p ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
doublePortals [ i ] . portals [ 0 ] = p ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// reverse it for a2
2012-11-28 15:47:07 +00:00
p = ( portal_t * ) R_ClearedStaticAlloc ( sizeof ( * p ) ) ;
2012-11-26 18:58:24 +00:00
p - > intoArea = a1 ;
p - > doublePortal = & doublePortals [ i ] ;
p - > w = w - > Reverse ( ) ;
p - > w - > GetPlane ( p - > plane ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
p - > next = portalAreas [ a2 ] . portals ;
portalAreas [ a2 ] . portals = p ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
doublePortals [ i ] . portals [ 1 ] = p ;
}
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ParseNodes
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ParseNodes ( idLexer * src , idFile * fileOut )
{
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " { " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numAreaNodes = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( numAreaNodes < 0 )
{
2012-11-26 18:58:24 +00:00
src - > Error ( " R_ParseNodes: bad numAreaNodes " ) ;
}
2012-11-28 15:47:07 +00:00
areaNodes = ( areaNode_t * ) R_ClearedStaticAlloc ( numAreaNodes * sizeof ( areaNodes [ 0 ] ) ) ;
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
// write out the type so the binary reader knows what to instantiate
fileOut - > WriteString ( " nodes " ) ;
}
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
fileOut - > WriteBig ( numAreaNodes ) ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numAreaNodes ; i + + )
{
areaNode_t * node ;
2012-11-26 18:58:24 +00:00
node = & areaNodes [ i ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > Parse1DMatrix ( 4 , node - > plane . ToFloatPtr ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
node - > children [ 0 ] = src - > ParseInt ( ) ;
node - > children [ 1 ] = src - > ParseInt ( ) ;
2012-11-28 15:47:07 +00:00
if ( fileOut ! = NULL )
{
2012-11-26 18:58:24 +00:00
fileOut - > WriteBig ( node - > plane [ 0 ] ) ;
fileOut - > WriteBig ( node - > plane [ 1 ] ) ;
fileOut - > WriteBig ( node - > plane [ 2 ] ) ;
fileOut - > WriteBig ( node - > plane [ 3 ] ) ;
fileOut - > WriteBig ( node - > children [ 0 ] ) ;
fileOut - > WriteBig ( node - > children [ 1 ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > ExpectTokenString ( " } " ) ;
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : ReadBinaryNodes
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ReadBinaryNodes ( idFile * file )
{
2012-11-26 18:58:24 +00:00
file - > ReadBig ( numAreaNodes ) ;
2012-11-28 15:47:07 +00:00
areaNodes = ( areaNode_t * ) R_ClearedStaticAlloc ( numAreaNodes * sizeof ( areaNodes [ 0 ] ) ) ;
for ( int i = 0 ; i < numAreaNodes ; i + + )
{
areaNode_t * node = & areaNodes [ i ] ;
2012-11-26 18:58:24 +00:00
file - > ReadBig ( node - > plane [ 0 ] ) ;
file - > ReadBig ( node - > plane [ 1 ] ) ;
file - > ReadBig ( node - > plane [ 2 ] ) ;
file - > ReadBig ( node - > plane [ 3 ] ) ;
file - > ReadBig ( node - > children [ 0 ] ) ;
file - > ReadBig ( node - > children [ 1 ] ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idRenderWorldLocal : : CommonChildrenArea_r
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idRenderWorldLocal : : CommonChildrenArea_r ( areaNode_t * node )
{
2012-11-26 18:58:24 +00:00
int nums [ 2 ] ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
if ( node - > children [ i ] < = 0 )
{
2012-11-26 18:58:24 +00:00
nums [ i ] = - 1 - node - > children [ i ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
nums [ i ] = CommonChildrenArea_r ( & areaNodes [ node - > children [ i ] ] ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// solid nodes will match any area
2012-11-28 15:47:07 +00:00
if ( nums [ 0 ] = = AREANUM_SOLID )
{
2012-11-26 18:58:24 +00:00
nums [ 0 ] = nums [ 1 ] ;
}
2012-11-28 15:47:07 +00:00
if ( nums [ 1 ] = = AREANUM_SOLID )
{
2012-11-26 18:58:24 +00:00
nums [ 1 ] = nums [ 0 ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int common ;
2012-11-28 15:47:07 +00:00
if ( nums [ 0 ] = = nums [ 1 ] )
{
2012-11-26 18:58:24 +00:00
common = nums [ 0 ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
common = CHILDREN_HAVE_MULTIPLE_AREAS ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
node - > commonChildrenArea = common ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return common ;
}
/*
= = = = = = = = = = = = = = = = =
idRenderWorldLocal : : ClearWorld
Sets up for a single area world
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ClearWorld ( )
{
2012-11-26 18:58:24 +00:00
numPortalAreas = 1 ;
2012-11-28 15:47:07 +00:00
portalAreas = ( portalArea_t * ) R_ClearedStaticAlloc ( sizeof ( portalAreas [ 0 ] ) ) ;
areaScreenRect = ( idScreenRect * ) R_ClearedStaticAlloc ( sizeof ( idScreenRect ) ) ;
2012-11-26 18:58:24 +00:00
SetupAreaRefs ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// even though we only have a single area, create a node
// that has both children pointing at it so we don't need to
//
2012-11-28 15:47:07 +00:00
areaNodes = ( areaNode_t * ) R_ClearedStaticAlloc ( sizeof ( areaNodes [ 0 ] ) ) ;
2012-11-26 18:58:24 +00:00
areaNodes [ 0 ] . plane [ 3 ] = 1 ;
areaNodes [ 0 ] . children [ 0 ] = - 1 ;
areaNodes [ 0 ] . children [ 1 ] = - 1 ;
}
/*
= = = = = = = = = = = = = = = = =
idRenderWorldLocal : : FreeDefs
dump all the interactions
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : FreeDefs ( )
{
2012-11-26 18:58:24 +00:00
generateAllInteractionsCalled = false ;
2012-11-28 15:47:07 +00:00
if ( interactionTable )
{
2012-11-26 18:58:24 +00:00
R_StaticFree ( interactionTable ) ;
interactionTable = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free all lightDefs
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < lightDefs . Num ( ) ; i + + )
{
idRenderLightLocal * light = lightDefs [ i ] ;
if ( light ! = NULL & & light - > world = = this )
{
2012-11-26 18:58:24 +00:00
FreeLightDef ( i ) ;
lightDefs [ i ] = NULL ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free all entityDefs
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < entityDefs . Num ( ) ; i + + )
{
idRenderEntityLocal * mod = entityDefs [ i ] ;
if ( mod ! = NULL & & mod - > world = = this )
{
2012-11-26 18:58:24 +00:00
FreeEntityDef ( i ) ;
entityDefs [ i ] = NULL ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Reset decals and overlays
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < decals . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
decals [ i ] . entityHandle = - 1 ;
decals [ i ] . lastStartTime = 0 ;
}
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < overlays . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
overlays [ i ] . entityHandle = - 1 ;
overlays [ i ] . lastStartTime = 0 ;
}
}
/*
= = = = = = = = = = = = = = = = =
idRenderWorldLocal : : InitFromMap
A NULL or empty name will make a world without a map model , which
is still useful for displaying a bare model
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idRenderWorldLocal : : InitFromMap ( const char * name )
{
idLexer * src ;
2012-11-26 18:58:24 +00:00
idToken token ;
2012-11-28 15:47:07 +00:00
idRenderModel * lastModel ;
2012-11-26 18:58:24 +00:00
// if this is an empty world, initialize manually
2012-11-28 15:47:07 +00:00
if ( ! name | | ! name [ 0 ] )
{
2012-11-26 18:58:24 +00:00
FreeWorld ( ) ;
mapName . Clear ( ) ;
ClearWorld ( ) ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load it
idStrStatic < MAX_OSPATH > filename = name ;
filename . SetFileExtension ( PROC_FILE_EXT ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for generated file
idStrStatic < MAX_OSPATH > generatedFileName = filename ;
generatedFileName . Insert ( " generated/ " , 0 ) ;
generatedFileName . SetFileExtension ( " bproc " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we are reloading the same map, check the timestamp
// and try to skip all the work
ID_TIME_T currentTimeStamp = fileSystem - > GetTimestamp ( filename ) ;
2012-11-28 15:47:07 +00:00
if ( name = = mapName )
{
if ( fileSystem - > InProductionMode ( ) | | ( currentTimeStamp ! = FILE_NOT_FOUND_TIMESTAMP & & currentTimeStamp = = mapTimeStamp ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " idRenderWorldLocal::InitFromMap: retaining existing map \n " ) ;
FreeDefs ( ) ;
TouchWorldModels ( ) ;
AddWorldModelEntities ( ) ;
ClearPortalStates ( ) ;
return true ;
}
common - > Printf ( " idRenderWorldLocal::InitFromMap: timestamp has changed, reloading. \n " ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FreeWorld ( ) ;
2012-11-28 15:47:07 +00:00
// see if we have a generated version of this
2012-11-26 18:58:24 +00:00
static const byte BPROC_VERSION = 1 ;
static const unsigned int BPROC_MAGIC = ( ' P ' < < 24 ) | ( ' R ' < < 16 ) | ( ' O ' < < 8 ) | BPROC_VERSION ;
bool loaded = false ;
idFileLocal file ( fileSystem - > OpenFileReadMemory ( generatedFileName ) ) ;
2012-11-28 15:47:07 +00:00
if ( file ! = NULL )
{
2012-11-26 18:58:24 +00:00
int numEntries = 0 ;
int magic = 0 ;
file - > ReadBig ( magic ) ;
2012-11-28 15:47:07 +00:00
if ( magic = = BPROC_MAGIC )
{
2012-11-26 18:58:24 +00:00
file - > ReadBig ( numEntries ) ;
file - > ReadString ( mapName ) ;
file - > ReadBig ( mapTimeStamp ) ;
loaded = true ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numEntries ; i + + )
{
2012-11-26 18:58:24 +00:00
idStrStatic < MAX_OSPATH > type ;
file - > ReadString ( type ) ;
type . ToLower ( ) ;
2012-11-28 15:47:07 +00:00
if ( type = = " model " )
{
idRenderModel * lastModel = ReadBinaryModel ( file ) ;
if ( lastModel = = NULL )
{
2012-11-26 18:58:24 +00:00
loaded = false ;
break ;
}
renderModelManager - > AddModel ( lastModel ) ;
localModels . Append ( lastModel ) ;
2012-11-28 15:47:07 +00:00
}
else if ( type = = " shadowmodel " )
{
idRenderModel * lastModel = ReadBinaryModel ( file ) ;
if ( lastModel = = NULL )
{
2012-11-26 18:58:24 +00:00
loaded = false ;
break ;
}
renderModelManager - > AddModel ( lastModel ) ;
localModels . Append ( lastModel ) ;
2012-11-28 15:47:07 +00:00
}
else if ( type = = " interareaportals " )
{
2012-11-26 18:58:24 +00:00
ReadBinaryAreaPortals ( file ) ;
2012-11-28 15:47:07 +00:00
}
else if ( type = = " nodes " )
{
2012-11-26 18:58:24 +00:00
ReadBinaryNodes ( file ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Error ( " Binary proc file failed, unexpected type %s \n " , type . c_str ( ) ) ;
}
}
}
}
2012-11-28 15:47:07 +00:00
if ( ! loaded )
{
src = new ( TAG_RENDER ) idLexer ( filename , LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE ) ;
if ( ! src - > IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " idRenderWorldLocal::InitFromMap: %s not found \n " , filename . c_str ( ) ) ;
ClearWorld ( ) ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
mapName = name ;
mapTimeStamp = currentTimeStamp ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we are writing a demo, archive the load command
2012-11-28 15:47:07 +00:00
if ( common - > WriteDemo ( ) )
{
2012-11-26 18:58:24 +00:00
WriteLoadMap ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! src - > ReadToken ( & token ) | | token . Icmp ( PROC_FILE_ID ) )
{
2012-11-26 18:58:24 +00:00
common - > Printf ( " idRenderWorldLocal::InitFromMap: bad id '%s' instead of '%s' \n " , token . c_str ( ) , PROC_FILE_ID ) ;
delete src ;
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numEntries = 0 ;
idFileLocal outputFile ( fileSystem - > OpenFileWrite ( generatedFileName , " fs_basepath " ) ) ;
2012-11-28 15:47:07 +00:00
if ( outputFile ! = NULL )
{
2012-11-26 18:58:24 +00:00
int magic = BPROC_MAGIC ;
outputFile - > WriteBig ( magic ) ;
outputFile - > WriteBig ( numEntries ) ;
outputFile - > WriteString ( mapName ) ;
outputFile - > WriteBig ( mapTimeStamp ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse the file
2012-11-28 15:47:07 +00:00
while ( 1 )
{
if ( ! src - > ReadToken ( & token ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
if ( token = = " model " )
{
2012-11-26 18:58:24 +00:00
lastModel = ParseModel ( src , name , currentTimeStamp , outputFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add it to the model manager list
renderModelManager - > AddModel ( lastModel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save it in the list to free when clearing this map
localModels . Append ( lastModel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numEntries + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token = = " shadowModel " )
{
2012-11-26 18:58:24 +00:00
lastModel = ParseShadowModel ( src , outputFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add it to the model manager list
renderModelManager - > AddModel ( lastModel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save it in the list to free when clearing this map
localModels . Append ( lastModel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numEntries + + ;
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token = = " interAreaPortals " )
{
2012-11-26 18:58:24 +00:00
ParseInterAreaPortals ( src , outputFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numEntries + + ;
continue ;
}
2012-11-28 15:47:07 +00:00
if ( token = = " nodes " )
{
2012-11-26 18:58:24 +00:00
ParseNodes ( src , outputFile ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numEntries + + ;
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
src - > Error ( " idRenderWorldLocal::InitFromMap: bad token \" %s \" " , token . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delete src ;
2012-11-28 15:47:07 +00:00
if ( outputFile ! = NULL )
{
2012-11-26 18:58:24 +00:00
outputFile - > Seek ( 0 , FS_SEEK_SET ) ;
int magic = BPROC_MAGIC ;
outputFile - > WriteBig ( magic ) ;
outputFile - > WriteBig ( numEntries ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if it was a trivial map without any areas, create a single area
2012-11-28 15:47:07 +00:00
if ( ! numPortalAreas )
{
2012-11-26 18:58:24 +00:00
ClearWorld ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the points where we can early-our of reference pushing into the BSP tree
CommonChildrenArea_r ( & areaNodes [ 0 ] ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AddWorldModelEntities ( ) ;
ClearPortalStates ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// done!
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderWorldLocal : : ClearPortalStates
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ClearPortalStates ( )
{
2012-11-26 18:58:24 +00:00
// all portals start off open
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numInterAreaPortals ; i + + )
{
2012-11-26 18:58:24 +00:00
doublePortals [ i ] . blockingBits = PS_BLOCK_NONE ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// flood fill all area connections
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numPortalAreas ; i + + )
{
for ( int j = 0 ; j < NUM_PORTAL_ATTRIBUTES ; j + + )
{
2012-11-26 18:58:24 +00:00
connectedAreaNum + + ;
FloodConnectedAreas ( & portalAreas [ i ] , j ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idRenderWorldLocal : : AddWorldModelEntities
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : AddWorldModelEntities ( )
{
2012-11-26 18:58:24 +00:00
// add the world model for each portal area
// we can't just call AddEntityDef, because that would place the references
// based on the bounding box, rather than explicitly into the correct area
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < numPortalAreas ; i + + )
{
2012-11-26 18:58:24 +00:00
common - > UpdateLevelLoadPacifier ( ) ;
2012-11-28 15:47:07 +00:00
idRenderEntityLocal * def = new ( TAG_RENDER_ENTITY ) idRenderEntityLocal ;
2012-11-26 18:58:24 +00:00
// try and reuse a free spot
int index = entityDefs . FindNull ( ) ;
2012-11-28 15:47:07 +00:00
if ( index = = - 1 )
{
index = entityDefs . Append ( def ) ;
}
else
{
2012-11-26 18:58:24 +00:00
entityDefs [ index ] = def ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
def - > index = index ;
def - > world = this ;
2012-11-28 15:47:07 +00:00
def - > parms . hModel = renderModelManager - > FindModel ( va ( " _area%i " , i ) ) ;
if ( def - > parms . hModel - > IsDefaultModel ( ) | | ! def - > parms . hModel - > IsStaticWorldModel ( ) )
{
2012-11-26 18:58:24 +00:00
common - > Error ( " idRenderWorldLocal::InitFromMap: bad area model lookup " ) ;
}
2012-11-28 15:47:07 +00:00
idRenderModel * hModel = def - > parms . hModel ;
for ( int j = 0 ; j < hModel - > NumSurfaces ( ) ; j + + )
{
const modelSurface_t * surf = hModel - > Surface ( j ) ;
if ( surf - > shader - > GetName ( ) = = idStr ( " textures/smf/portal_sky " ) )
{
2012-11-26 18:58:24 +00:00
def - > needsPortalSky = true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the local and global reference bounds are the same for area models
def - > localReferenceBounds = def - > parms . hModel - > Bounds ( ) ;
def - > globalReferenceBounds = def - > parms . hModel - > Bounds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
def - > parms . axis [ 0 ] [ 0 ] = 1.0f ;
def - > parms . axis [ 1 ] [ 1 ] = 1.0f ;
def - > parms . axis [ 2 ] [ 2 ] = 1.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// in case an explicit shader is used on the world, we don't
// want it to have a 0 alpha or color
def - > parms . shaderParms [ 0 ] = 1.0f ;
def - > parms . shaderParms [ 1 ] = 1.0f ;
def - > parms . shaderParms [ 2 ] = 1.0f ;
def - > parms . shaderParms [ 3 ] = 1.0f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
R_DeriveEntityData ( def ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
AddEntityRefToArea ( def , & portalAreas [ i ] ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
CheckAreaForPortalSky
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idRenderWorldLocal : : CheckAreaForPortalSky ( int areaNum )
{
2012-11-26 18:58:24 +00:00
assert ( areaNum > = 0 & & areaNum < numPortalAreas ) ;
2012-11-28 15:47:07 +00:00
for ( areaReference_t * ref = portalAreas [ areaNum ] . entityRefs . areaNext ; ref - > entity ; ref = ref - > areaNext )
{
2012-11-26 18:58:24 +00:00
assert ( ref - > area = = & portalAreas [ areaNum ] ) ;
2012-11-28 15:47:07 +00:00
if ( ref - > entity & & ref - > entity - > needsPortalSky )
{
2012-11-26 18:58:24 +00:00
return true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
ResetLocalRenderModels
= = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idRenderWorldLocal : : ResetLocalRenderModels ( )
{
2012-11-26 18:58:24 +00:00
localModels . Clear ( ) ; // Clear out the list when switching between expansion packs, so InitFromMap doesn't try to delete the list whose content has already been deleted by the model manager being re-started
}