10 Sep 2008
This commit is contained in:
parent
38c5b71df1
commit
6cc2444932
4332
baserc/server.h
4332
baserc/server.h
File diff suppressed because it is too large
Load Diff
2494
baserc/uimenu.h
2494
baserc/uimenu.h
File diff suppressed because it is too large
Load Diff
@ -39,10 +39,8 @@ int lightdatasize;
|
||||
dlightgrid_t dlightgrid[MAX_MAP_LIGHTGRID];
|
||||
int numlightgrids;
|
||||
byte dpvsdata[MAX_MAP_VISIBILITY];
|
||||
dvis_t *dpvs = (dvis_t *)dpvsdata;
|
||||
int pvsdatasize;
|
||||
byte dphsdata[MAX_MAP_VISIBILITY];
|
||||
dvis_t *dphs = (dvis_t *)dphsdata;
|
||||
int phsdatasize;
|
||||
|
||||
//=============================================================================
|
||||
@ -100,12 +98,12 @@ void SwapBSPFile( void )
|
||||
SwapBlock( (int *)dsurfaces, numsurfaces * sizeof(dsurfaces[0]));
|
||||
|
||||
// visibility
|
||||
dpvs->numclusters = LittleLong( dpvs->numclusters );
|
||||
dpvs->rowsize = LittleLong( dpvs->rowsize );
|
||||
((int *)&dpvsdata)[0] = LittleLong( ((int *)&dpvsdata)[0] );
|
||||
((int *)&dpvsdata)[1] = LittleLong( ((int *)&dpvsdata)[1] );
|
||||
|
||||
// hearability
|
||||
dphs->numclusters = LittleLong( dphs->numclusters );
|
||||
dphs->rowsize = LittleLong( dphs->rowsize );
|
||||
((int *)&dphsdata)[0] = LittleLong( ((int *)&dphsdata)[0] );
|
||||
((int *)&dphsdata)[1] = LittleLong( ((int *)&dphsdata)[1] );
|
||||
}
|
||||
|
||||
size_t BSP_LoadLump( const char *lumpname, void *dest, size_t block_size )
|
||||
@ -183,7 +181,7 @@ bool LoadBSPFile( void )
|
||||
numvertexes = CopyLump (LUMP_VERTICES, dvertexes, sizeof(dvertex_t));
|
||||
numindexes = CopyLump (LUMP_INDICES, dindexes, sizeof(dindexes[0]));
|
||||
dcollisiondatasize = CopyLump(LUMP_COLLISION, dcollision, 1);
|
||||
numsurfaces = CopyLump (LUMP_SURFACES, dsurfaces, sizeof(dsurface_t));
|
||||
numsurfaces = CopyLump (LUMP_SURFACES, dsurfaces, sizeof(dsurfaces[0]));
|
||||
lightdatasize = CopyLump (LUMP_LIGHTMAPS, dlightdata, 1);
|
||||
pvsdatasize = CopyLump (LUMP_VISIBILITY, dpvsdata, 1);
|
||||
phsdatasize = CopyLump (LUMP_HEARABILITY, dphsdata, 1);
|
||||
@ -250,7 +248,7 @@ void WriteBSPFile( void )
|
||||
AddLump (LUMP_VERTICES, dvertexes, numvertexes*sizeof(dvertexes[0]));
|
||||
AddLump (LUMP_INDICES, dindexes, numindexes*sizeof(dindexes[0]));
|
||||
AddLump (LUMP_COLLISION, dcollision, dcollisiondatasize );
|
||||
AddLump (LUMP_SURFACES, dsurfaces, numsurfaces*sizeof(dsurface_t));
|
||||
AddLump (LUMP_SURFACES, dsurfaces, numsurfaces*sizeof(dsurfaces[0]));
|
||||
AddLump (LUMP_LIGHTMAPS, dlightdata, lightdatasize);
|
||||
AddLump (LUMP_VISIBILITY, dpvsdata, pvsdatasize);
|
||||
AddLump (LUMP_HEARABILITY, dphsdata, phsdatasize);
|
||||
@ -314,8 +312,8 @@ bool ParseEntity (void)
|
||||
|
||||
if (!Com_GetToken (true)) return false;
|
||||
|
||||
if (!Com_MatchToken( "{")) Sys_Error ("ParseEntity: { not found");
|
||||
if (num_entities == MAX_MAP_ENTITIES) Sys_Error ("num_entities == MAX_MAP_ENTITIES");
|
||||
if( !Com_MatchToken( "{" )) Sys_Break( "ParseEntity: '{' not found\n" );
|
||||
if( num_entities == MAX_MAP_ENTITIES ) Sys_Break( "MAX_MAP_ENTITIES limit excceded\n" );
|
||||
|
||||
mapent = &entities[num_entities];
|
||||
num_entities++;
|
||||
|
@ -17,6 +17,7 @@ enum
|
||||
BRUSH_WORLDCRAFT_22, // half-life worldcraft >= 2.2
|
||||
BRUSH_RADIANT,
|
||||
BRUSH_QUARK,
|
||||
BRUSH_COUNT
|
||||
};
|
||||
|
||||
#define MAX_BRUSH_SIDES 128
|
||||
@ -383,10 +384,8 @@ extern byte dcollision[MAX_MAP_COLLISION];
|
||||
extern int dcollisiondatasize;
|
||||
extern int pvsdatasize;
|
||||
extern byte dpvsdata[MAX_MAP_VISIBILITY];
|
||||
extern dvis_t *dpvs;
|
||||
extern int phsdatasize;
|
||||
extern byte dphsdata[MAX_MAP_VISIBILITY];
|
||||
extern dvis_t *dphs;
|
||||
extern int lightdatasize;
|
||||
extern byte dlightdata[MAX_MAP_LIGHTDATA];
|
||||
|
||||
|
@ -844,9 +844,11 @@ void GatherSampleLight (vec3_t pos, vec3_t normal,
|
||||
float dist;
|
||||
float scale;
|
||||
float *dest;
|
||||
dvis_t *dpvs;
|
||||
|
||||
// get the PVS for the pos to limit the number of checks
|
||||
pvs = PvsForOrigin( pos );
|
||||
dpvs = (dvis_t *)dpvsdata;
|
||||
|
||||
if( !pvs ) return;
|
||||
|
||||
|
@ -27,6 +27,15 @@ int c_areaportals;
|
||||
int c_structural;
|
||||
int c_detail;
|
||||
|
||||
const char *g_sMapType[BRUSH_COUNT] =
|
||||
{
|
||||
"unknown",
|
||||
"Worldcraft 2.1",
|
||||
"Valve Hammer 3.4",
|
||||
"Radiant",
|
||||
"QuArK"
|
||||
};
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
@ -828,17 +837,18 @@ bspbrush_t *FinishBrush( void )
|
||||
{
|
||||
VectorSet( movedir, 0, 0, 1 ); // z-rotate
|
||||
}
|
||||
else VectorClear( movedir ); // custom movedir
|
||||
|
||||
if(!VectorIsNull( movedir ))
|
||||
{
|
||||
com.sprintf( string, "%i %i %i", (int)movedir[0], (int)movedir[1], (int)movedir[2]);
|
||||
SetKeyValue( &entities[buildBrush->entitynum], "movedir", string );
|
||||
SetKeyValue( &entities[num_entities - 1], "movedir", string );
|
||||
}
|
||||
if(!VectorIsNull( origin ))
|
||||
{
|
||||
com.sprintf( string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
|
||||
SetKeyValue( &entities[buildBrush->entitynum], "origin", string );
|
||||
VectorCopy( origin, entities[buildBrush->entitynum].origin );
|
||||
SetKeyValue( &entities[num_entities - 1], "origin", string );
|
||||
VectorCopy( origin, entities[num_entities - 1].origin );
|
||||
}
|
||||
|
||||
// don't keep this brush
|
||||
@ -980,15 +990,16 @@ bool ParseMapEntity( void )
|
||||
else if( Com_MatchToken( "brushDef" ))
|
||||
{
|
||||
g_brushtype = BRUSH_RADIANT;
|
||||
ParseBrush( mapent ); // parse brush primitive
|
||||
if(ParseBrush( mapent )) // parse brush primitive
|
||||
entity_numbrushes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// QuArK or Worldcraft map
|
||||
Com_FreeToken();
|
||||
ParseBrush( mapent );
|
||||
if(ParseBrush( mapent ))
|
||||
entity_numbrushes++;
|
||||
}
|
||||
entity_numbrushes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1000,6 +1011,7 @@ bool ParseMapEntity( void )
|
||||
g_brushtype = BRUSH_WORLDCRAFT_22;
|
||||
else g_brushtype = BRUSH_WORLDCRAFT_21;
|
||||
}
|
||||
else g_brushtype = BRUSH_WORLDCRAFT_21;
|
||||
e->next = mapent->epairs;
|
||||
mapent->epairs = e;
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ dleaf_t *RadPointInLeaf( vec3_t point )
|
||||
const byte *PvsForOrigin( vec3_t org )
|
||||
{
|
||||
dleaf_t *leaf;
|
||||
dvis_t *dpvs;
|
||||
|
||||
if( !pvsdatasize )
|
||||
{
|
||||
@ -137,6 +138,7 @@ const byte *PvsForOrigin( vec3_t org )
|
||||
return novis;
|
||||
}
|
||||
|
||||
dpvs = (dvis_t *)dpvsdata;
|
||||
leaf = RadPointInLeaf( org );
|
||||
if( leaf->cluster == -1 ) return NULL; // in solid leaf
|
||||
return dpvs->data + leaf->cluster * dpvs->rowsize;
|
||||
|
@ -19,6 +19,7 @@ int leafbytes; // (portalclusters+63)>>3
|
||||
int leaflongs;
|
||||
int portalbytes;
|
||||
int portallongs;
|
||||
int numvisfaces;
|
||||
|
||||
bool fastvis; // fast calc visibility
|
||||
bool noPassageVis; // ignore passages
|
||||
@ -181,7 +182,6 @@ void ClusterMerge( int leafnum )
|
||||
}
|
||||
|
||||
memset( uncompressed, 0, leafbytes );
|
||||
|
||||
uncompressed[mergedleafnum>>3] |= (1<<( mergedleafnum & 7 ));
|
||||
|
||||
// convert portal bits to leaf bits
|
||||
@ -189,8 +189,8 @@ void ClusterMerge( int leafnum )
|
||||
numvis++; // count the leaf itself
|
||||
totalpvs += numvis;
|
||||
|
||||
Msg( "cluster %4i : %4i visible\n", leafnum, numvis );
|
||||
Mem_Copy( dpvs->data + leafnum * leafbytes, uncompressed, leafbytes );
|
||||
MsgDev( D_NOTE, "cluster %4i : %4i visible\n", leafnum, numvis );
|
||||
Mem_Copy( dpvsdata + VIS_HEADER_SIZE + leafnum * leafbytes, uncompressed, leafbytes );
|
||||
}
|
||||
|
||||
|
||||
@ -664,14 +664,14 @@ void LoadPortals( void )
|
||||
com.strcpy( magic, Com_GetToken( true ));
|
||||
portalclusters = com.atoi(Com_GetToken( true ));
|
||||
numportals = com.atoi(Com_GetToken( true ));
|
||||
numsurfaces = com.atoi(Com_GetToken( true ));
|
||||
numvisfaces = com.atoi(Com_GetToken( true ));
|
||||
|
||||
if( !portalclusters && !numportals ) Sys_Break( "LoadPortals: failed to read header\n" );
|
||||
if( com.strcmp( magic, PORTALFILE )) Sys_Break( "LoadPortals: not a portal file\n" );
|
||||
|
||||
Msg( "%4i portalclusters\n", portalclusters );
|
||||
Msg( "%4i numportals\n", numportals );
|
||||
Msg( "%6i numfaces\n", numsurfaces );
|
||||
Msg( "%6i numfaces\n", numvisfaces );
|
||||
|
||||
// these counts should take advantage of 64 bit systems automatically
|
||||
leafbytes = ((portalclusters+63)&~63)>>3;
|
||||
@ -688,11 +688,13 @@ void LoadPortals( void )
|
||||
for( i = 0; i < portalclusters; i++ )
|
||||
leafs[i].merged = -1;
|
||||
|
||||
pvsdatasize = (sizeof(dvis_t) - 1) + portalclusters * leafbytes;
|
||||
pvsdatasize = VIS_HEADER_SIZE + portalclusters * leafbytes;
|
||||
|
||||
// vis header
|
||||
dpvs->numclusters = portalclusters;
|
||||
dpvs->rowsize = leafbytes;
|
||||
((int *)dpvsdata)[0] = portalclusters;
|
||||
((int *)dpvsdata)[1] = leafbytes;
|
||||
((int *)dphsdata)[0] = portalclusters;
|
||||
((int *)dphsdata)[1] = leafbytes;
|
||||
|
||||
for( i = 0, p = portals; i < numportals; i++ )
|
||||
{
|
||||
@ -767,10 +769,10 @@ void LoadPortals( void )
|
||||
p++;
|
||||
}
|
||||
|
||||
faces = BSP_Malloc( 2 * numsurfaces * sizeof( vportal_t ));
|
||||
faces = BSP_Malloc( 2 * numvisfaces * sizeof( vportal_t ));
|
||||
faceleafs = BSP_Malloc( portalclusters * sizeof( leaf_t ));
|
||||
|
||||
for( i = 0, p = faces; i < numsurfaces; i++ )
|
||||
for( i = 0, p = faces; i < numvisfaces; i++ )
|
||||
{
|
||||
numpoints = com.atoi(Com_GetToken( true )); // newline
|
||||
leafnums[0] = com.atoi(Com_GetToken( false ));
|
||||
@ -830,7 +832,7 @@ void ClusterPHS( int clusternum )
|
||||
byte *scan;
|
||||
byte uncompressed[MAX_MAP_LEAFS/8];
|
||||
|
||||
scan = dpvs->data + clusternum * leafbytes;
|
||||
scan = dpvsdata + VIS_HEADER_SIZE + clusternum * leafbytes;
|
||||
Mem_Copy( uncompressed, scan, leafbytes );
|
||||
for( j = 0; j < leafbytes; j++ )
|
||||
{
|
||||
@ -843,7 +845,7 @@ void ClusterPHS( int clusternum )
|
||||
index = ((j<<3)+k);
|
||||
if( index >= portalclusters )
|
||||
Sys_Error( "Bad bit in PVS\n" ); // pad bits should be 0
|
||||
src = (long *)(dpvs->data + index * leafbytes);
|
||||
src = (long *)(dpvsdata + VIS_HEADER_SIZE + index * leafbytes);
|
||||
dest = (long *)uncompressed;
|
||||
for (l = 0; l < leaflongs; l++) ((long *)uncompressed)[l] |= src[l];
|
||||
}
|
||||
@ -853,7 +855,7 @@ void ClusterPHS( int clusternum )
|
||||
totalphs++;
|
||||
|
||||
// FIXME: copy it off
|
||||
Mem_Copy( dphs->data + clusternum * leafbytes, uncompressed, leafbytes );
|
||||
Mem_Copy( dphsdata + VIS_HEADER_SIZE + clusternum * leafbytes, uncompressed, leafbytes );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -864,7 +866,7 @@ Calculate the PHS (Potentially Hearable Set)
|
||||
by ORing together all the PVS visible from a leaf
|
||||
================
|
||||
*/
|
||||
void CalcPHS (void)
|
||||
void CalcPHS( void )
|
||||
{
|
||||
Msg ("Building PHS...\n");
|
||||
RunThreadsOnIndividual (portalclusters, true, ClusterPHS);
|
||||
@ -894,8 +896,8 @@ void WvisMain ( bool option )
|
||||
CountActivePortals ();
|
||||
|
||||
CalcPVS ();
|
||||
// CalcPHS ();
|
||||
|
||||
CalcPHS ();
|
||||
|
||||
WriteBSPFile();
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ shader_t shaderInfo[MAX_SURFACE_INFO];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
bool clearSolid;
|
||||
const char *name;
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
bool clearSolid;
|
||||
} infoParm_t;
|
||||
|
||||
infoParm_t infoParms[] =
|
||||
@ -83,6 +83,8 @@ static void LoadShaderImage( shader_t *si )
|
||||
rgbdata_t *pic;
|
||||
|
||||
if( !si ) return;
|
||||
if( !com.stricmp( si->name, "default" ))
|
||||
return;
|
||||
pic = FS_LoadImage( si->name, NULL, 0 );
|
||||
if( !pic ) return;
|
||||
|
||||
@ -255,21 +257,24 @@ static void ParseShaderFile( char *filename )
|
||||
FindShader
|
||||
===============
|
||||
*/
|
||||
shader_t *FindShader( const char *texture )
|
||||
shader_t *FindShader( const char *textureName )
|
||||
{
|
||||
string shader;
|
||||
shader_t *si;
|
||||
int i;
|
||||
|
||||
com.sprintf( shader, "textures/%s", texture );
|
||||
|
||||
// strip off extension
|
||||
com.strncpy( shader, textureName, MAX_STRING );
|
||||
FS_StripExtension( shader ); // cut off extension
|
||||
com.strlwr( shader, shader ); // convert to lower case
|
||||
|
||||
// look for it
|
||||
for( i = 0, si = shaderInfo; i < numShaderInfo; i++, si++ )
|
||||
{
|
||||
if( !com.stricmp( shader, si->name ))
|
||||
if( !com.stricmp( va("textures/%s", shader ), si->name ) || !com.stricmp( shader, si->name ))
|
||||
{
|
||||
LoadShaderImage( si );
|
||||
if( !si->width || !si->height )
|
||||
LoadShaderImage( si );
|
||||
return si;
|
||||
}
|
||||
}
|
||||
|
@ -227,8 +227,9 @@ void EmitPlanarSurf( drawsurf_t *ds )
|
||||
out = &dsurfaces[numsurfaces];
|
||||
numsurfaces++;
|
||||
|
||||
out->planenum = ds->planenum & (~1);
|
||||
out->lm_side = ds->planenum & 1;
|
||||
out->shadernum = EmitShader( ds->shader->name );
|
||||
out->planenum = ds->planenum;
|
||||
out->lightmapnum = ds->lightmapNum;
|
||||
out->firstvertex = numvertexes;
|
||||
out->numvertices = ds->numverts;
|
||||
@ -237,7 +238,7 @@ void EmitPlanarSurf( drawsurf_t *ds )
|
||||
out->lm_base[1] = ds->lightmapY;
|
||||
out->lm_size[0] = ds->lightmapWidth;
|
||||
out->lm_size[1] = ds->lightmapHeight;
|
||||
out->lm_side = ds->planenum & 1;
|
||||
out->styles[0] = 255; // no lightstyles
|
||||
|
||||
VectorCopy( ds->lightmapOrigin, out->origin );
|
||||
VectorCopy( ds->lightmapVecs[0], out->vecs[0] );
|
||||
@ -614,7 +615,6 @@ int FilterSideIntoTree_r( winding_t *w, side_t *side, drawsurf_t *ds, node_t *no
|
||||
plane = &mapplanes[node->planenum];
|
||||
ClipWindingEpsilon( w, plane->normal, plane->dist, ON_EPSILON, &front, &back );
|
||||
|
||||
// g-cont. it's expression valid ?
|
||||
total = FilterSideIntoTree_r( front, side, ds, node->children[0] );
|
||||
total += FilterSideIntoTree_r( back, side, ds, node->children[1] );
|
||||
|
||||
@ -668,6 +668,7 @@ void FilterDrawsurfsIntoTree( bsp_entity_t *e, tree_t *tree )
|
||||
int c_surfs = 0, c_refs = 0;
|
||||
|
||||
MsgDev( D_INFO, "----- FilterDrawsurfsIntoTree -----\n" );
|
||||
c_stripSurfaces = c_fanSurfaces = 0;
|
||||
|
||||
for( i = e->firstsurf; i < numdrawsurfs; i++ )
|
||||
{
|
||||
|
@ -400,8 +400,11 @@ void FixTJunctions( bsp_entity_t *ent )
|
||||
|
||||
MsgDev( D_INFO, "----- FixTJuncs -----\n" );
|
||||
|
||||
c_addedVerts = 0;
|
||||
numEdgeLines = 0;
|
||||
numOriginalEdges = 0;
|
||||
c_degenerateEdges = 0;
|
||||
c_natural = c_rotate = c_cant = 0;
|
||||
|
||||
// add all the edges
|
||||
// this actually creates axial edges, but it
|
||||
|
@ -28,7 +28,6 @@ winding_t *AllocWinding (int points)
|
||||
}
|
||||
s = sizeof(vec_t) * 3 * points + sizeof( int );
|
||||
w = BSP_Malloc( s );
|
||||
memset (w, 0, s);
|
||||
return w;
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ void Com_CheckToken( const char *match )
|
||||
|
||||
if(!Com_MatchToken( match ))
|
||||
{
|
||||
Sys_Break( "\"%s\" not found\n" );
|
||||
Sys_Break( "Com_CheckToken: \"%s\" not found\n", match );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,5 +71,5 @@ if exist vsound\vsound.plg del /f /q vsound\vsound.plg
|
||||
echo Build succeeded!
|
||||
echo Please wait. Xash is now loading
|
||||
cd D:\Xash3D\
|
||||
quake.exe -game tmpQuArK -log -debug -dev 3 +map skytest
|
||||
quake.exe -game tmpQuArK -log -debug -dev 3 +map e1m1
|
||||
:done
|
@ -194,7 +194,8 @@ CL_ParseFrame
|
||||
*/
|
||||
void CL_ParseFrame( sizebuf_t *msg )
|
||||
{
|
||||
int cmd, len;
|
||||
int cmd, len, idx;
|
||||
edict_t *clent;
|
||||
frame_t *old;
|
||||
|
||||
memset( &cl.frame, 0, sizeof(cl.frame));
|
||||
@ -243,30 +244,37 @@ void CL_ParseFrame( sizebuf_t *msg )
|
||||
len = MSG_ReadByte( msg );
|
||||
MSG_ReadData( msg, &cl.frame.areabits, len );
|
||||
|
||||
#if 0
|
||||
// read clientindex
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_playerinfo ) Host_Error( "CL_ParseFrame: not clientindex\n" );
|
||||
idx = MSG_ReadByte( msg );
|
||||
clent = PRVM_EDICT_NUM( idx ); // get client
|
||||
if((idx-1) != cl.playernum ) Host_Error("CL_ParseFrame: invalid playernum (%d should be %d)\n", idx-1, cl.playernum );
|
||||
#else
|
||||
// read playerinfo
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_playerinfo ) Host_Error( "CL_ParseFrame: not playerinfo\n" );
|
||||
if( old ) MSG_ReadDeltaPlayerstate( msg, &old->ps, &cl.frame.ps );
|
||||
else MSG_ReadDeltaPlayerstate( msg, NULL, &cl.frame.ps );
|
||||
#endif
|
||||
if( sv_newprotocol->integer )
|
||||
{
|
||||
// read clientindex
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_playerinfo ) Host_Error( "CL_ParseFrame: not clientindex\n" );
|
||||
idx = MSG_ReadByte( msg );
|
||||
clent = PRVM_EDICT_NUM( idx ); // get client
|
||||
if((idx-1) != cl.playernum ) Host_Error("CL_ParseFrame: invalid playernum (%d should be %d)\n", idx-1, cl.playernum );
|
||||
}
|
||||
else
|
||||
{
|
||||
// read playerinfo
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_playerinfo ) Host_Error( "CL_ParseFrame: not playerinfo\n" );
|
||||
if( old ) MSG_ReadDeltaPlayerstate( msg, &old->ps, &cl.frame.ps );
|
||||
else MSG_ReadDeltaPlayerstate( msg, NULL, &cl.frame.ps );
|
||||
}
|
||||
|
||||
// read packet entities
|
||||
cmd = MSG_ReadByte( msg );
|
||||
if( cmd != svc_packetentities ) Host_Error("CL_ParseFrame: not packetentities[%d]\n", cmd );
|
||||
CL_ParsePacketEntities( msg, old, &cl.frame );
|
||||
#if 0
|
||||
// now we can reading delta player state
|
||||
if( old ) cl.frame.ps = MSG_ParseDeltaPlayer( &old->ps, &clent->priv.cl->current );
|
||||
else cl.frame.ps = MSG_ParseDeltaPlayer( NULL, &clent->priv.cl->current );
|
||||
#endif
|
||||
// HACKHACK
|
||||
|
||||
if( sv_newprotocol->integer )
|
||||
{
|
||||
// now we can reading delta player state
|
||||
if( old ) cl.frame.ps = MSG_ParseDeltaPlayer( &old->ps, &clent->priv.cl->current );
|
||||
else cl.frame.ps = MSG_ParseDeltaPlayer( NULL, &clent->priv.cl->current );
|
||||
}
|
||||
|
||||
// FIXME
|
||||
if( cls.state == ca_cinematic || cls.demoplayback )
|
||||
cl.frame.ps.pm_type = PM_FREEZE; // demo or movie playback
|
||||
|
||||
|
@ -37,7 +37,7 @@ typedef struct frame_s
|
||||
int serverframe;
|
||||
int servertime; // server time the message is valid for (in msec)
|
||||
int deltaframe;
|
||||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
byte areabits[MAX_MAP_AREA_BYTES]; // portalarea visibility bits
|
||||
int num_entities;
|
||||
int parse_entities; // non-masked index into cl_parse_entities array
|
||||
entity_state_t ps;
|
||||
|
@ -29,6 +29,7 @@ extern cvar_t *scr_loading;
|
||||
extern cvar_t *scr_download;
|
||||
extern cvar_t *scr_width;
|
||||
extern cvar_t *scr_height;
|
||||
extern cvar_t *sv_newprotocol;
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
@ -24,9 +24,9 @@ static net_field_t ent_fields[] =
|
||||
{ ES_FIELD(old_origin[0]), NET_FLOAT, true }, // send always
|
||||
{ ES_FIELD(old_origin[1]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_origin[2]), NET_FLOAT, true },
|
||||
{ ES_FIELD(old_velocity[0]), NET_FLOAT, false }, // client velocity
|
||||
{ ES_FIELD(old_velocity[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(old_velocity[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(infotarget[0]), NET_FLOAT, false }, // beam endpoint, portal camera pos, etc
|
||||
{ ES_FIELD(infotarget[1]), NET_FLOAT, false },
|
||||
{ ES_FIELD(infotarget[2]), NET_FLOAT, false },
|
||||
{ ES_FIELD(model.index), NET_WORD, false }, // 4096 models
|
||||
{ ES_FIELD(model.colormap), NET_WORD, false }, // encoded as two shorts for top and bottom color
|
||||
{ ES_FIELD(model.scale), NET_COLOR, false }, // 0-255 values
|
||||
|
@ -72,7 +72,7 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
cs_free, // can be reused for a new connection
|
||||
cs_free = 0, // can be reused for a new connection
|
||||
cs_zombie, // client has been disconnected, but don't reuse connection for a couple seconds
|
||||
cs_connected, // has been assigned to a sv_client_t, but not in game yet
|
||||
cs_spawned // client is fully in game
|
||||
@ -88,6 +88,7 @@ typedef struct server_s
|
||||
float time; // always sv.framenum * 50 msec
|
||||
float frametime;
|
||||
int framenum;
|
||||
int net_framenum;
|
||||
|
||||
string name; // map name, or cinematic name
|
||||
cmodel_t *models[MAX_MODELS];
|
||||
@ -109,7 +110,7 @@ typedef struct server_s
|
||||
typedef struct
|
||||
{
|
||||
entity_state_t ps;
|
||||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
byte areabits[MAX_MAP_AREA_BYTES]; // portalarea visibility bits
|
||||
int areabits_size;
|
||||
int num_entities;
|
||||
int first_entity; // into the circular sv_packet_entities[]
|
||||
@ -184,9 +185,11 @@ struct sv_edict_s
|
||||
int linkcount;
|
||||
int num_clusters; // if -1, use headnode instead
|
||||
int clusternums[MAX_ENT_CLUSTERS];
|
||||
int framenum; // update framenumber
|
||||
int areanum, areanum2;
|
||||
bool forceupdate; // physic_push force update
|
||||
bool suspended; // suspended in air toss object
|
||||
bool linked; // passed through SV_LinkEdict
|
||||
|
||||
vec3_t water_origin; // step old origin
|
||||
vec3_t moved_origin; // push old origin
|
||||
|
@ -945,7 +945,7 @@ void _MSG_Send( msgtype_t msg_type, vec3_t origin, edict_t *ent, const char *fil
|
||||
if( origin == NULL ) return;
|
||||
leafnum = pe->PointLeafnum( origin );
|
||||
cluster = pe->LeafCluster( leafnum );
|
||||
mask = pe->ClusterPHS( cluster );
|
||||
mask = pe->ClusterPVS( cluster ); //FIXME: use PHS
|
||||
area1 = pe->LeafArea( leafnum );
|
||||
break;
|
||||
case MSG_PVS_R:
|
||||
|
@ -82,6 +82,7 @@ struct sv_entvars_s
|
||||
vec3_t size;
|
||||
float mass;
|
||||
float solid;
|
||||
float contents;
|
||||
float movetype;
|
||||
float waterlevel;
|
||||
float watertype;
|
||||
@ -99,7 +100,6 @@ struct sv_entvars_s
|
||||
float renderfx;
|
||||
float renderamt;
|
||||
float colormap;
|
||||
float areaportal;
|
||||
float flags;
|
||||
float aiflags;
|
||||
float spawnflags;
|
||||
@ -142,6 +142,6 @@ struct sv_entvars_s
|
||||
float team;
|
||||
};
|
||||
|
||||
#define PROG_CRC_SERVER 12094
|
||||
#define PROG_CRC_SERVER 9289
|
||||
|
||||
#endif//SV_EDICT_H
|
@ -6,57 +6,33 @@
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
static byte fatpvs[MAX_MAP_LEAFS/8];
|
||||
static byte *clientpvs;
|
||||
static byte *clientphs;
|
||||
static byte *bitvector;
|
||||
#define MAX_VISIBLE_PACKET 1024
|
||||
typedef struct
|
||||
{
|
||||
int num_entities;
|
||||
int entities[MAX_VISIBLE_PACKET];
|
||||
} sv_ents_t;
|
||||
|
||||
int c_fullsend;
|
||||
|
||||
/*
|
||||
============
|
||||
SV_FatPVS
|
||||
|
||||
The client will interpolate the view position,
|
||||
so we can't use a single PVS point
|
||||
===========
|
||||
*/
|
||||
void SV_FatPVS( vec3_t org )
|
||||
=======================
|
||||
SV_EntityNumbers
|
||||
=======================
|
||||
*/
|
||||
static int SV_EntityNumbers( const void *a, const void *b )
|
||||
{
|
||||
int leafs[64];
|
||||
int i, j, count;
|
||||
int longs;
|
||||
byte *src;
|
||||
vec3_t mins, maxs;
|
||||
int *ea, *eb;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
mins[i] = org[i] - 1;
|
||||
maxs[i] = org[i] + 1;
|
||||
}
|
||||
ea = (int *)a;
|
||||
eb = (int *)b;
|
||||
|
||||
count = pe->BoxLeafnums( mins, maxs, leafs, 64, NULL );
|
||||
if( count < 1 ) Host_Error( "SV_FatPVS: invalid leafcount\n" );
|
||||
longs = (pe->NumClusters() + 31)>>5;
|
||||
|
||||
// convert leafs to clusters
|
||||
for( i = 0; i < count; i++) leafs[i] = pe->LeafCluster( leafs[i] );
|
||||
|
||||
Mem_Copy( fatpvs, pe->ClusterPVS( leafs[0] ), longs<<2 );
|
||||
|
||||
// or in all the other leaf bits
|
||||
for( i = 1; i < count; i++ )
|
||||
{
|
||||
for( j = 0; j < i; j++ )
|
||||
{
|
||||
if( leafs[i] == leafs[j] )
|
||||
break;
|
||||
}
|
||||
if( j != i ) continue; // already have the cluster we want
|
||||
src = pe->ClusterPVS( leafs[i] );
|
||||
for( j = 0; j < longs; j++ ) ((long *)fatpvs)[j] |= ((long *)src)[j];
|
||||
}
|
||||
if( *ea == *eb )
|
||||
Host_Error( "SV_EntityNumbers: duplicated entity\n" );
|
||||
if( *ea < *eb ) return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
@ -105,89 +81,24 @@ void SV_UpdateEntityState( edict_t *ent )
|
||||
}
|
||||
}
|
||||
|
||||
bool SV_EdictNeedsUpdate( edict_t *ent, edict_t *clent, int clientarea )
|
||||
/*
|
||||
===============
|
||||
SV_AddEntToSnapshot
|
||||
===============
|
||||
*/
|
||||
static void SV_AddEntToSnapshot( sv_edict_t *svent, edict_t *ent, sv_ents_t *ents )
|
||||
{
|
||||
int i, l;
|
||||
// if we have already added this entity to this snapshot, don't add again
|
||||
if( svent->framenum == sv.net_framenum ) return;
|
||||
svent->framenum = sv.net_framenum;
|
||||
|
||||
//NOTE: client index on client expected that entity will be valid
|
||||
if( ent->priv.sv->s.ed_type == ED_CLIENT )
|
||||
return true;
|
||||
// if we are full, silently discard entities
|
||||
if( ents->num_entities == MAX_VISIBLE_PACKET ) return;
|
||||
|
||||
// send viewmodel entity always
|
||||
// NOTE: never apply LinkEdict to viewmodel entity, because
|
||||
// we wan't see it in list of entities returned with SV_AreaEdicts
|
||||
if( ent->priv.sv->s.ed_type == ED_VIEWMODEL )
|
||||
return true;
|
||||
|
||||
// ignore if not touching a PV leaf
|
||||
if( ent != clent )
|
||||
{
|
||||
// check area
|
||||
if( !pe->AreasConnected( clientarea, ent->priv.sv->areanum ))
|
||||
{
|
||||
// doors can legally straddle two areas, so
|
||||
// we may need to check another one
|
||||
int areanum2 = ent->priv.sv->areanum2;
|
||||
if( !areanum2 || !pe->AreasConnected( clientarea, areanum2 ))
|
||||
return false; // blocked by a door
|
||||
}
|
||||
|
||||
// FIXME: if an ent has a model and a sound, but isn't
|
||||
// in the PVS, only the PHS, clear the model
|
||||
if( ent->priv.sv->s.soundindex ) bitvector = clientphs;
|
||||
else if( sv_fatpvs->integer ) bitvector = fatpvs;
|
||||
else bitvector = clientpvs;
|
||||
|
||||
// check individual leafs
|
||||
if( !ent->priv.sv->num_clusters ) return false;
|
||||
for( i = 0, l = 0; i < ent->priv.sv->num_clusters; i++ )
|
||||
{
|
||||
l = ent->priv.sv->clusternums[i];
|
||||
if( bitvector[l>>3] & (1<<(l&7)))
|
||||
break;
|
||||
}
|
||||
|
||||
// if we haven't found it to be visible,
|
||||
// check overflow clusters that coudln't be stored
|
||||
if( i == ent->priv.sv->num_clusters )
|
||||
{
|
||||
if( ent->priv.sv->lastcluster )
|
||||
{
|
||||
for( ; l <= ent->priv.sv->lastcluster; l++ )
|
||||
{
|
||||
if( bitvector[l>>3] & (1<<(l&7)))
|
||||
break;
|
||||
}
|
||||
if( l == ent->priv.sv->lastcluster )
|
||||
return false; // not visible
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
if( !ent->progs.sv->modelindex )
|
||||
{
|
||||
// don't send sounds if they will be attenuated away
|
||||
vec3_t org, delta, entorigin;
|
||||
float len;
|
||||
|
||||
if(VectorIsNull( ent->progs.sv->origin ))
|
||||
{
|
||||
VectorAdd( ent->progs.sv->mins, ent->progs.sv->maxs, entorigin );
|
||||
VectorScale( entorigin, 0.5, entorigin );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( ent->progs.sv->origin, entorigin );
|
||||
}
|
||||
|
||||
VectorCopy( clent->priv.sv->s.origin, org );
|
||||
VectorAdd( org, clent->priv.sv->s.viewoffset, org );
|
||||
VectorSubtract( org, entorigin, delta );
|
||||
len = VectorLength( delta );
|
||||
if( len > 400 ) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
SV_UpdateEntityState( ent ); // copy entity state from progs
|
||||
ents->entities[ents->num_entities] = svent->serialnumber;
|
||||
ents->num_entities++;
|
||||
c_fullsend++; // debug counter
|
||||
}
|
||||
|
||||
/*
|
||||
@ -216,6 +127,8 @@ void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t
|
||||
if( !from ) from_num_entities = 0;
|
||||
else from_num_entities = from->num_entities;
|
||||
|
||||
newent = NULL;
|
||||
oldent = NULL;
|
||||
newindex = 0;
|
||||
oldindex = 0;
|
||||
while( newindex < to->num_entities || oldindex < from_num_entities )
|
||||
@ -263,6 +176,124 @@ void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t
|
||||
MSG_WriteBits( msg, 0, NET_WORD ); // end of packetentities
|
||||
}
|
||||
|
||||
static void SV_AddEntitiesToPacket( vec3_t origin, client_frame_t *frame, sv_ents_t *ents, bool portal )
|
||||
{
|
||||
int l, e, i;
|
||||
edict_t *ent;
|
||||
sv_edict_t *svent;
|
||||
int leafnum;
|
||||
byte *clientpvs;
|
||||
byte *bitvector;
|
||||
int clientarea, clientcluster;
|
||||
bool force = false;
|
||||
|
||||
// during an error shutdown message we may need to transmit
|
||||
// the shutdown message after the server has shutdown, so
|
||||
// specfically check for it
|
||||
if( !sv.state ) return;
|
||||
|
||||
leafnum = pe->PointLeafnum( origin );
|
||||
clientarea = pe->LeafArea( leafnum );
|
||||
clientcluster = pe->LeafCluster( leafnum );
|
||||
|
||||
// calculate the visible areas
|
||||
frame->areabits_size = pe->WriteAreaBits( frame->areabits, clientarea );
|
||||
clientpvs = pe->ClusterPVS( clientcluster );
|
||||
|
||||
for( e = 0; e < prog->num_edicts; e++ )
|
||||
{
|
||||
ent = PRVM_EDICT_NUM( e );
|
||||
force = false; // clear forceflag
|
||||
|
||||
// send viewmodel entity always
|
||||
// NOTE: never apply LinkEdict to viewmodel entity, because
|
||||
// we wan't see it in list of entities returned with SV_AreaEdicts
|
||||
if( ent->priv.sv->s.ed_type == ED_VIEWMODEL )
|
||||
force = true;
|
||||
|
||||
// NOTE: client index on client expected that entity will be valid
|
||||
if( sv_newprotocol->integer && ent->priv.sv->s.ed_type == ED_CLIENT )
|
||||
force = true;
|
||||
|
||||
// never send entities that aren't linked in
|
||||
if( !ent->priv.sv->linked && !force ) continue;
|
||||
|
||||
if( ent->priv.sv->serialnumber != e )
|
||||
{
|
||||
MsgDev( D_WARN, "fixing ent->priv.sv->serialnumber\n");
|
||||
ent->priv.sv->serialnumber = e;
|
||||
}
|
||||
|
||||
svent = ent->priv.sv;
|
||||
|
||||
// don't double add an entity through portals
|
||||
if( svent->framenum == sv.net_framenum ) continue;
|
||||
|
||||
// ignore if not touching a PV leaf check area
|
||||
if( !pe->AreasConnected( clientarea, ent->priv.sv->areanum ))
|
||||
{
|
||||
// doors can legally straddle two areas, so
|
||||
// we may need to check another one
|
||||
if( !pe->AreasConnected( clientarea, ent->priv.sv->areanum2 ))
|
||||
continue; // blocked by a door
|
||||
}
|
||||
bitvector = clientpvs;
|
||||
|
||||
// check individual leafs
|
||||
if( !svent->num_clusters && !force ) continue;
|
||||
for( i = l = 0; i < svent->num_clusters && !force; i++ )
|
||||
{
|
||||
l = svent->clusternums[i];
|
||||
if( bitvector[l>>3] & (1<<(l & 7)))
|
||||
break;
|
||||
}
|
||||
|
||||
// if we haven't found it to be visible,
|
||||
// check overflow clusters that coudln't be stored
|
||||
if( !force && i == svent->num_clusters )
|
||||
{
|
||||
if( svent->lastcluster )
|
||||
{
|
||||
for( ; l <= svent->lastcluster; l++ )
|
||||
{
|
||||
if( bitvector[l>>3] & (1<<(l & 7)))
|
||||
break;
|
||||
}
|
||||
if( l == svent->lastcluster )
|
||||
continue; // not visible
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
|
||||
if( ent->priv.sv->s.ed_type == ED_AMBIENT )
|
||||
{
|
||||
// don't send sounds if they will be attenuated away
|
||||
vec3_t delta, entorigin;
|
||||
float len;
|
||||
|
||||
if(VectorIsNull( ent->progs.sv->origin ))
|
||||
{
|
||||
VectorAverage( ent->progs.sv->mins, ent->progs.sv->maxs, entorigin );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( ent->progs.sv->origin, entorigin );
|
||||
}
|
||||
|
||||
VectorSubtract( origin, entorigin, delta );
|
||||
len = VectorLength( delta );
|
||||
if( len > 400 ) continue;
|
||||
}
|
||||
|
||||
// add it
|
||||
SV_AddEntToSnapshot( svent, ent, ents );
|
||||
|
||||
// if its a portal entity, add everything visible from its camera position
|
||||
if( svent->s.ed_type == ED_PORTAL )
|
||||
SV_AddEntitiesToPacket( svent->s.infotarget, frame, ents, true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_WriteFrameToClient
|
||||
@ -292,6 +323,14 @@ void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
|
||||
{ // we have a valid message to delta from
|
||||
oldframe = &cl->frames[cl->lastframe & UPDATE_MASK];
|
||||
lastframe = cl->lastframe;
|
||||
|
||||
// the snapshot's entities may still have rolled off the buffer, though
|
||||
if( oldframe->first_entity <= svs.next_client_entities - svs.num_client_entities )
|
||||
{
|
||||
MsgDev( D_WARN, "%s: delta request from out of date entities.\n", cl->name );
|
||||
oldframe = NULL;
|
||||
lastframe = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MSG_WriteByte( msg, svc_frame );
|
||||
@ -307,13 +346,17 @@ void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
|
||||
// just send an client index
|
||||
// it's safe, because PRVM_NUM_FOR_EDICT always equal ed->serialnumber,
|
||||
// thats shared across network
|
||||
#if 0
|
||||
MSG_WriteByte( msg, svc_playerinfo );
|
||||
MSG_WriteByte( msg, frame->index );
|
||||
#else
|
||||
// delta encode the playerstate
|
||||
MSG_WriteDeltaPlayerstate( &oldframe->ps, &frame->ps, msg );
|
||||
#endif
|
||||
if( sv_newprotocol->integer )
|
||||
{
|
||||
MSG_WriteByte( msg, svc_playerinfo );
|
||||
MSG_WriteByte( msg, frame->index );
|
||||
}
|
||||
else
|
||||
{
|
||||
// delta encode the playerstate
|
||||
MSG_WriteDeltaPlayerstate( &oldframe->ps, &frame->ps, msg );
|
||||
}
|
||||
|
||||
// delta encode the entities
|
||||
SV_EmitPacketEntities( oldframe, frame, msg );
|
||||
}
|
||||
@ -341,74 +384,68 @@ void SV_BuildClientFrame( sv_client_t *cl )
|
||||
edict_t *clent;
|
||||
client_frame_t *frame;
|
||||
entity_state_t *state;
|
||||
int e, clientarea;
|
||||
int clientcluster;
|
||||
int leafnum;
|
||||
sv_ents_t frame_ents;
|
||||
int i;
|
||||
|
||||
clent = cl->edict;
|
||||
if( !clent->priv.sv->client )
|
||||
return; // not in game yet
|
||||
sv.net_framenum++;
|
||||
|
||||
// this is the frame we are creating
|
||||
frame = &cl->frames[sv.framenum & UPDATE_MASK];
|
||||
|
||||
frame->msg_sent = svs.realtime; // save it for ping calc later
|
||||
|
||||
// clear everything in this snapshot
|
||||
frame_ents.num_entities = c_fullsend = 0;
|
||||
memset( frame->areabits, 0, sizeof( frame->areabits ));
|
||||
if( !clent->priv.sv->client ) return; // not in game yet
|
||||
|
||||
// find the client's PVS
|
||||
VectorCopy( clent->priv.sv->s.origin, org );
|
||||
VectorAdd( org, clent->priv.sv->s.viewoffset, org );
|
||||
|
||||
// calculate fat pvs
|
||||
if( sv_fatpvs->integer == 1 ) SV_FatPVS( org );
|
||||
if( sv_fatpvs->integer == 2 ) pe->FatPVS( org, 64, fatpvs, sizeof(fatpvs), false );
|
||||
if( sv_newprotocol->integer )
|
||||
{
|
||||
// grab the current player index
|
||||
frame->index = PRVM_NUM_FOR_EDICT( clent );
|
||||
}
|
||||
else
|
||||
{
|
||||
// grab the current player state
|
||||
cl->edict->priv.sv->framenum = sv.net_framenum;
|
||||
frame->ps = clent->priv.sv->s;
|
||||
}
|
||||
|
||||
leafnum = pe->PointLeafnum( org );
|
||||
clientarea = pe->LeafArea( leafnum );
|
||||
clientcluster = pe->LeafCluster( leafnum );
|
||||
// add all the entities directly visible to the eye, which
|
||||
// may include portal entities that merge other viewpoints
|
||||
SV_AddEntitiesToPacket( org, frame, &frame_ents, false );
|
||||
|
||||
// calculate the visible areas
|
||||
frame->areabits_size = pe->WriteAreaBits( frame->areabits, clientarea );
|
||||
#if 0
|
||||
// grab the current player index
|
||||
frame->index = PRVM_NUM_FOR_EDICT( clent );
|
||||
#else
|
||||
// grab the current player state
|
||||
frame->ps = clent->priv.sv->s;
|
||||
#endif
|
||||
clientpvs = pe->ClusterPVS( clientcluster );
|
||||
clientphs = pe->ClusterPHS( clientcluster );
|
||||
// if there were portals visible, there may be out of order entities
|
||||
// in the list which will need to be resorted for the delta compression
|
||||
// to work correctly. This also catches the error condition
|
||||
// of an entity being included twice.
|
||||
qsort( frame_ents.entities, frame_ents.num_entities, sizeof( frame_ents.entities[0] ), SV_EntityNumbers );
|
||||
|
||||
// build up the list of visible entities
|
||||
// now that all viewpoint's areabits have been OR'd together, invert
|
||||
// all of them to make it a mask vector, which is what the renderer wants
|
||||
for( i = 0; i < MAX_MAP_AREA_BYTES / 4; i++ )
|
||||
((int *)frame->areabits)[i] = ((int *)frame->areabits)[i] ^ -1;
|
||||
|
||||
// copy the entity states out
|
||||
frame->num_entities = 0;
|
||||
frame->first_entity = svs.next_client_entities;
|
||||
|
||||
for( e = 1; e < prog->num_edicts; e++ )
|
||||
for( i = 0; i < frame_ents.num_entities; i++ )
|
||||
{
|
||||
ent = PRVM_EDICT_NUM(e);
|
||||
|
||||
// ignore ents without visible models unless they have an effect
|
||||
if( !ent->progs.sv->modelindex && !ent->progs.sv->effects && !ent->priv.sv->s.soundindex )
|
||||
continue;
|
||||
|
||||
if(!SV_EdictNeedsUpdate( ent, clent, clientarea ))
|
||||
continue;
|
||||
ent = PRVM_EDICT_NUM( frame_ents.entities[i] );
|
||||
|
||||
// add it to the circular client_entities array
|
||||
state = &svs.client_entities[svs.next_client_entities % svs.num_client_entities];
|
||||
if( ent->priv.sv->serialnumber != e )
|
||||
{
|
||||
MsgDev( D_WARN, "SV_BuildClientFrame: invalid number %d\n", ent->priv.sv->serialnumber );
|
||||
ent->priv.sv->serialnumber = e; // ptr to current entity such as entnumber
|
||||
}
|
||||
|
||||
SV_UpdateEntityState( ent );
|
||||
*state = ent->priv.sv->s;
|
||||
|
||||
// don't mark players missiles as solid
|
||||
if( PRVM_PROG_TO_EDICT( ent->progs.sv->owner) == cl->edict )
|
||||
state->solid = 0;
|
||||
|
||||
svs.next_client_entities++;
|
||||
|
||||
// this should never hit, map should always be restarted first in SV_Frame
|
||||
if( svs.next_client_entities >= 0x7FFFFFFE )
|
||||
Host_Error( "svs.next_client_entities wrapped (sv.time integer limit is out)\n" );
|
||||
frame->num_entities++;
|
||||
}
|
||||
}
|
||||
@ -432,7 +469,7 @@ bool SV_SendClientDatagram( sv_client_t *cl )
|
||||
|
||||
SV_BuildClientFrame( cl );
|
||||
|
||||
MSG_Init( &msg, msg_buf, sizeof(msg_buf));
|
||||
MSG_Init( &msg, msg_buf, sizeof( msg_buf ));
|
||||
|
||||
// send over all the relevant entity_state_t
|
||||
// and the player state
|
||||
|
@ -29,6 +29,7 @@ cvar_t *sv_rollspeed;
|
||||
cvar_t *sv_maxspeed;
|
||||
cvar_t *sv_accelerate;
|
||||
cvar_t *sv_friction;
|
||||
cvar_t *sv_newprotocol;
|
||||
cvar_t *hostname;
|
||||
cvar_t *public_server; // should heartbeats be sent
|
||||
|
||||
@ -372,6 +373,7 @@ void SV_Init( void )
|
||||
sv_maxspeed = Cvar_Get("sv_maxspeed", "320", 0, "maximum speed a player can accelerate to when on ground (can be exceeded by tricks)");
|
||||
sv_accelerate = Cvar_Get( "sv_accelerate", "10", 0, "rate at which a player accelerates to sv_maxspeed" );
|
||||
sv_friction = Cvar_Get( "sv_friction", "4", 0, "how fast you slow down" );
|
||||
sv_newprotocol = Cvar_Get( "sv_protocol", "0", CVAR_LATCH|CVAR_ARCHIVE, "using protocol version 0 or 1" );
|
||||
|
||||
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
|
||||
|
||||
|
@ -2118,7 +2118,7 @@ void PF_AreaPortalState( void )
|
||||
ent = PRVM_G_EDICT( OFS_PARM0 );
|
||||
if( ent->priv.sv->areanum2 == -1 ) return;
|
||||
open = (bool)PRVM_G_FLOAT( OFS_PARM1 );
|
||||
pe->SetAreaPortalState( ent->priv.sv->s.number, ent->priv.sv->areanum, ent->priv.sv->areanum2, open );
|
||||
pe->SetAreaPortalState( ent->priv.sv->areanum, ent->priv.sv->areanum2, open );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
#include "const.h"
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
@ -115,7 +116,7 @@ SV_ClearWorld
|
||||
|
||||
===============
|
||||
*/
|
||||
void SV_ClearWorld (void)
|
||||
void SV_ClearWorld( void )
|
||||
{
|
||||
cmodel_t *world = sv.models[1];
|
||||
memset( sv_worldsectors, 0, sizeof(sv_worldsectors));
|
||||
@ -134,6 +135,7 @@ void SV_UnlinkEdict( edict_t *ent )
|
||||
worldsector_t *ws;
|
||||
|
||||
sv_ent = ent->priv.sv;
|
||||
sv_ent->linked = false;
|
||||
ws = sv_ent->worldsector;
|
||||
if( !ws ) return; // not linked in anywhere
|
||||
sv_ent->worldsector = NULL;
|
||||
@ -181,18 +183,18 @@ void SV_LinkEdict( edict_t *ent )
|
||||
VectorSubtract( ent->progs.sv->maxs, ent->progs.sv->mins, ent->progs.sv->size );
|
||||
|
||||
// encode the size into the entity_state for client prediction
|
||||
if (ent->progs.sv->solid == SOLID_BBOX && !((int)ent->progs.sv->flags & FL_DEADMONSTER))
|
||||
if((int)ent->progs.sv->contents & ( CONTENTS_SOLID | CONTENTS_BODY ))
|
||||
{
|
||||
// assume that x/y are equal and symetric
|
||||
i = ent->progs.sv->maxs[0]/8;
|
||||
i = ent->progs.sv->maxs[0];
|
||||
i = bound( 1, i, 255 );
|
||||
|
||||
// z is not symetric
|
||||
j = (-ent->progs.sv->mins[2])/8;
|
||||
j = (-ent->progs.sv->mins[2]);
|
||||
j = bound( 1, j, 255 );
|
||||
|
||||
// and z maxs can be negative...
|
||||
k = (ent->progs.sv->maxs[2] + 32)/8;
|
||||
k = (ent->progs.sv->maxs[2] + 32);
|
||||
k = bound( 1, k, 255 );
|
||||
sv_ent->solid = (k<<16)|(j<<8)|i;
|
||||
}
|
||||
@ -233,8 +235,8 @@ void SV_LinkEdict( edict_t *ent )
|
||||
// link to PVS leafs
|
||||
sv_ent->num_clusters = 0;
|
||||
sv_ent->lastcluster = 0;
|
||||
sv_ent->areanum = 0;
|
||||
sv_ent->areanum2 = 0;
|
||||
sv_ent->areanum = -1;
|
||||
sv_ent->areanum2 = -1;
|
||||
|
||||
// get all leafs, including solids
|
||||
num_leafs = pe->BoxLeafnums( ent->progs.sv->absmin, ent->progs.sv->absmax, leafs, MAX_TOTAL_ENT_LEAFS, &lastleaf );
|
||||
@ -247,13 +249,13 @@ void SV_LinkEdict( edict_t *ent )
|
||||
for( i = 0; i < num_leafs; i++ )
|
||||
{
|
||||
area = pe->LeafArea( leafs[i] );
|
||||
if( area )
|
||||
if( area != -1 )
|
||||
{
|
||||
// doors may legally straggle two areas,
|
||||
// but nothing should evern need more than that
|
||||
if (ent->priv.sv->areanum && ent->priv.sv->areanum != area)
|
||||
{
|
||||
if (ent->priv.sv->areanum2 && ent->priv.sv->areanum2 != area && sv.state == ss_loading )
|
||||
if( ent->priv.sv->areanum != -1 && ent->priv.sv->areanum != area && sv.state == ss_loading )
|
||||
{
|
||||
float *v = ent->progs.sv->absmin;
|
||||
MsgDev( D_WARN, "SV_LinkEdict: object touching 3 areas at %f %f %f\n", v[0], v[1], v[2]);
|
||||
@ -264,12 +266,11 @@ void SV_LinkEdict( edict_t *ent )
|
||||
}
|
||||
}
|
||||
|
||||
// store as many explicit clusters as we can
|
||||
sv_ent->num_clusters = 0;
|
||||
for( i = 0; i < num_leafs; i++ )
|
||||
{
|
||||
cluster = pe->LeafCluster( leafs[i] );
|
||||
if( cluster )
|
||||
if( cluster != -1 )
|
||||
{
|
||||
sv_ent->clusternums[sv_ent->num_clusters++] = cluster;
|
||||
if( sv_ent->num_clusters == MAX_ENT_CLUSTERS )
|
||||
@ -289,7 +290,10 @@ void SV_LinkEdict( edict_t *ent )
|
||||
|
||||
// don't link not solid or rigid bodies
|
||||
if( ent->progs.sv->solid == SOLID_NOT || ent->progs.sv->solid >= SOLID_BOX )
|
||||
{
|
||||
sv_ent->linked = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// find the first world sector node that the ent's box crosses
|
||||
node = sv_worldsectors;
|
||||
@ -307,6 +311,7 @@ void SV_LinkEdict( edict_t *ent )
|
||||
sv_ent->worldsector = node;
|
||||
sv_ent->nextedict = node->entities;
|
||||
node->entities = sv_ent;
|
||||
sv_ent->linked = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -13,13 +13,6 @@
|
||||
#define CAPSULE_MODEL_HANDLE MAX_MODELS - 2
|
||||
#define BOX_MODEL_HANDLE MAX_MODELS - 1
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AP_UNREGISTERED = 0,
|
||||
AP_CLOSED,
|
||||
AP_OPENED
|
||||
} portalstate_t;
|
||||
|
||||
typedef struct cpointf_s
|
||||
{
|
||||
float v[3];
|
||||
@ -113,18 +106,17 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int area;
|
||||
int otherarea;
|
||||
} careaportal_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numareaportals;
|
||||
careaportal_t *areaportals[MAX_MAP_AREAPORTALS];
|
||||
int floodnum; // if two areas have equal floodnums, they are connected
|
||||
int floodvalid;
|
||||
} carea_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numClusters;
|
||||
int clusterBytes;
|
||||
byte *data; // vis data
|
||||
} cvis_t;
|
||||
|
||||
typedef struct material_info_s
|
||||
{
|
||||
string name;
|
||||
@ -147,10 +139,7 @@ typedef struct collide_info_s
|
||||
typedef struct clipmap_s
|
||||
{
|
||||
string name;
|
||||
|
||||
uint checksum; // map checksum
|
||||
byte nullvis[MAX_MAP_LEAFS/8];
|
||||
byte portalstate[MAX_MAP_AREAPORTALS];
|
||||
|
||||
// brush, studio and sprite models
|
||||
cmodel_t cmodels[MAX_MODELS];
|
||||
@ -172,11 +161,12 @@ typedef struct clipmap_s
|
||||
int *indices;
|
||||
cbrush_t *brushes;
|
||||
cbrushside_t *brushsides;
|
||||
dvis_t *pvs;
|
||||
dvis_t *phs;
|
||||
cvis_t pvs;
|
||||
cvis_t phs;
|
||||
NewtonCollision *collision;
|
||||
carea_t *areas;
|
||||
careaportal_t *areaportals;
|
||||
int *areaportals; // [ cm.numareas * cm.numareas ] reference counts
|
||||
size_t areaportals_size;
|
||||
|
||||
int numbrushsides;
|
||||
int numplanes;
|
||||
@ -189,7 +179,6 @@ typedef struct clipmap_s
|
||||
int numsurfaces;
|
||||
int numbrushes;
|
||||
int numareas;
|
||||
int numclusters;
|
||||
int floodvalid;
|
||||
|
||||
// misc stuff
|
||||
@ -204,6 +193,7 @@ typedef struct clipmap_s
|
||||
vfile_t *world_tree; // pre-calcualated collision tree (worldmodel only)
|
||||
trace_t trace; // contains result of last trace
|
||||
int checkcount;
|
||||
bool vised; // additional vis info
|
||||
} clipmap_t;
|
||||
|
||||
typedef struct physic_s
|
||||
@ -268,9 +258,7 @@ extern float *m_upVector;
|
||||
//
|
||||
int CM_PointLeafnum_r( const vec3_t p, cnode_t *node );
|
||||
int CM_PointLeafnum( const vec3_t p );
|
||||
void CM_StoreLeafs( leaflist_t *ll, cnode_t *node );
|
||||
void CM_StoreBrushes( leaflist_t *ll, cnode_t *node );
|
||||
void CM_BoxLeafnums_r( leaflist_t *ll, cnode_t *node );
|
||||
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastleaf );
|
||||
int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize );
|
||||
cmodel_t *CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, bool capsule );
|
||||
|
@ -23,14 +23,12 @@ int registration_sequence = 0;
|
||||
*/
|
||||
void CM_GetPoint( int index, vec3_t out )
|
||||
{
|
||||
int vert_index = cm.indices[index];
|
||||
CM_ConvertPositionToMeters( out, cm.vertices[vert_index].point );
|
||||
CM_ConvertPositionToMeters( out, cm.vertices[index].point );
|
||||
}
|
||||
|
||||
void CM_GetPoint2( int index, vec3_t out )
|
||||
{
|
||||
int vert_index = cm.indices[index];
|
||||
CM_ConvertDimensionToMeters( out, cm.vertices[vert_index].point );
|
||||
CM_ConvertDimensionToMeters( out, cm.vertices[index].point );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -66,7 +64,7 @@ void CM_FreeModel( cmodel_t *mod )
|
||||
}
|
||||
|
||||
int CM_NumTextures( void ) { return cm.numshaders; }
|
||||
int CM_NumClusters( void ) { return cm.numclusters; }
|
||||
int CM_NumClusters( void ) { return cm.pvs.numClusters; }
|
||||
int CM_NumInlineModels( void ) { return cm.numbmodels; }
|
||||
const char *CM_EntityString( void ) { return cm.entitystring; }
|
||||
const char *CM_TexName( int index ) { return cm.shaders[index].name; }
|
||||
@ -145,8 +143,7 @@ void BSP_LoadModels( lump_t *l )
|
||||
cm.numbmodels = count;
|
||||
out = &cm.bmodels[0];
|
||||
|
||||
Msg("BSP_LoadModels: %i\n", cm.numbmodels );
|
||||
for ( i = 0; i < count; i++, in++, out++ )
|
||||
for( i = 0; i < count; i++, in++, out++ )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
@ -197,8 +194,7 @@ void BSP_LoadShaders( lump_t *l )
|
||||
cm.numshaders = l->filelen / sizeof(*in);
|
||||
cm.shaders = out = (csurface_t *)Mem_Alloc( cmappool, cm.numshaders * sizeof(*out));
|
||||
|
||||
Msg("BSP_LoadShaders: %i\n", cm.numshaders );
|
||||
for ( i = 0; i < cm.numshaders; i++, in++, out++)
|
||||
for( i = 0; i < cm.numshaders; i++, in++, out++)
|
||||
{
|
||||
com.strncpy( out->name, in->name, MAX_QPATH );
|
||||
out->contentflags = LittleLong( in->contents );
|
||||
@ -225,8 +221,7 @@ void BSP_LoadNodes( lump_t *l )
|
||||
out = cm.nodes = (cnode_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numnodes = count;
|
||||
|
||||
Msg("BSP_LoadNodes: %i\n", cm.numnodes );
|
||||
for (i = 0; i < count; i++, out++, in++)
|
||||
for( i = 0; i < count; i++, out++, in++ )
|
||||
{
|
||||
out->parent = NULL;
|
||||
n = LittleLong( in->planenum );
|
||||
@ -279,8 +274,7 @@ void BSP_LoadBrushes( lump_t *l )
|
||||
out = cm.brushes = (cbrush_t *)Mem_Alloc( cmappool, (count + 1) * sizeof(*out));
|
||||
cm.numbrushes = count;
|
||||
|
||||
Msg("BSP_LoadBrushes: %i\n", cm.numbrushes );
|
||||
for (i = 0; i < count; i++, out++, in++)
|
||||
for( i = 0; i < count; i++, out++, in++ )
|
||||
{
|
||||
out->firstbrushside = LittleLong(in->firstside);
|
||||
out->numsides = LittleLong(in->numsides);
|
||||
@ -322,7 +316,6 @@ void BSP_LoadLeafFaces( lump_t *l )
|
||||
out = cm.leafsurfaces = (dword *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numleafsurfaces = count;
|
||||
|
||||
Msg("BSP_LoadLeafFaces: %i\n", cm.numleafsurfaces );
|
||||
for( i = 0; i < count; i++, in++, out++ )
|
||||
{
|
||||
n = LittleLong( *in );
|
||||
@ -349,8 +342,7 @@ void BSP_LoadLeafBrushes( lump_t *l )
|
||||
if( count < 1 ) Host_Error("Map %s with no leaf brushes\n", cm.name );
|
||||
out = cm.leafbrushes = (dword *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numleafbrushes = count;
|
||||
Msg("BSP_LoadLeafBrushes: %i\n", cm.numleafbrushes );
|
||||
for ( i = 0; i < count; i++, in++, out++) *out = LittleShort(*in);
|
||||
for( i = 0; i < count; i++, in++, out++) *out = LittleLong( *in );
|
||||
}
|
||||
|
||||
|
||||
@ -371,19 +363,19 @@ void BSP_LoadLeafs( lump_t *l )
|
||||
count = l->filelen / sizeof(*in);
|
||||
if( count < 1 ) Host_Error("Map %s with no leafs\n", cm.name );
|
||||
out = cm.leafs = (cleaf_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.pvs.numClusters = cm.pvs.clusterBytes = cm.numareas = 0;
|
||||
cm.numleafs = count;
|
||||
cm.numclusters = 0;
|
||||
|
||||
Msg("BSP_LoadLeafs: %i\n", cm.numleafs );
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
for( i = 0; i < count; i++, in++, out++)
|
||||
{
|
||||
out->parent = NULL;
|
||||
out->plane = NULL;
|
||||
out->contents = LittleLong( in->contents );
|
||||
out->cluster = LittleLong( in->cluster );
|
||||
out->area = LittleLong( in->area );
|
||||
if( out->cluster >= cm.numclusters )
|
||||
cm.numclusters = out->cluster + 1;
|
||||
|
||||
if( out->cluster >= cm.pvs.numClusters )
|
||||
cm.pvs.numClusters = out->cluster + 1;
|
||||
if( out->area >= cm.numareas )
|
||||
cm.numareas = out->area + 1;
|
||||
for( j = 0; j < 3; j++ )
|
||||
@ -406,9 +398,9 @@ void BSP_LoadLeafs( lump_t *l )
|
||||
out->numleafbrushes = c;
|
||||
}
|
||||
|
||||
Msg("BSP_LoadLeafs: areas %i\n", cm.numareas );
|
||||
cm.areaportals_size = cm.numareas * cm.numareas * sizeof( *cm.areaportals );
|
||||
cm.areas = Mem_Alloc( cmappool, cm.numareas * sizeof( *cm.areas ));
|
||||
cm.areaportals = Mem_Alloc( cmappool, cm.numareas * cm.numareas * sizeof( *cm.areaportals ));
|
||||
cm.areaportals = Mem_Alloc( cmappool, cm.areaportals_size );
|
||||
|
||||
// probably any wall it's liquid ?
|
||||
if( cm.leafs[0].contents != CONTENTS_SOLID )
|
||||
@ -445,8 +437,7 @@ void BSP_LoadPlanes( lump_t *l )
|
||||
out = cm.planes = (cplane_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numplanes = count;
|
||||
|
||||
Msg("BSP_LoadPlanes: %i\n", cm.numplanes );
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
for( i = 0; i < count; i++, in++, out++ )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
out->normal[j] = LittleFloat(in->normal[j]);
|
||||
@ -472,8 +463,7 @@ void BSP_LoadBrushSides( lump_t *l )
|
||||
out = cm.brushsides = (cbrushside_t *)Mem_Alloc( cmappool, count * sizeof(*out));
|
||||
cm.numbrushsides = count;
|
||||
|
||||
Msg("BSP_LoadBrushsides: %i\n", cm.numbrushsides );
|
||||
for ( i = 0; i < count; i++, in++, out++)
|
||||
for( i = 0; i < count; i++, in++, out++)
|
||||
{
|
||||
num = LittleLong(in->planenum);
|
||||
out->plane = cm.planes + num;
|
||||
@ -491,25 +481,26 @@ BSP_LoadVisibility
|
||||
*/
|
||||
void BSP_LoadVisibility( lump_t *l )
|
||||
{
|
||||
dvis_t *pvs;
|
||||
byte *buffer;
|
||||
|
||||
if( !l->filelen )
|
||||
{
|
||||
size_t pvs_size, row_size;
|
||||
|
||||
// create novis lump
|
||||
row_size = (cm.numclusters + 7) / 8;
|
||||
pvs_size = row_size * cm.numclusters;
|
||||
cm.pvs = (dvis_t *)Mem_Alloc( cmappool, pvs_size + sizeof(dvis_t) - 1 );
|
||||
cm.pvs->numclusters = cm.numclusters;
|
||||
cm.pvs->rowsize = row_size;
|
||||
memset( cm.pvs->data, 0xFF, pvs_size );
|
||||
cm.pvs.clusterBytes = ( cm.pvs.numClusters + 31 ) & ~31;
|
||||
cm.pvs.data = (byte *)Mem_Alloc( cmappool, cm.pvs.clusterBytes );
|
||||
memset( cm.pvs.data, 0xFF, cm.pvs.clusterBytes );
|
||||
cm.vised = false;
|
||||
return;
|
||||
}
|
||||
|
||||
cm.pvs = (dvis_t *)Mem_Alloc( cmappool, l->filelen );
|
||||
Mem_Copy( cm.pvs, cm.mod_base + l->fileofs, l->filelen );
|
||||
|
||||
cm.pvs->numclusters = LittleLong ( cm.pvs->numclusters );
|
||||
cm.pvs->rowsize = LittleLong ( cm.pvs->rowsize );
|
||||
buffer = (byte *)cm.mod_base + l->fileofs;
|
||||
pvs = (dvis_t *)buffer;
|
||||
cm.pvs.numClusters = LittleLong ( pvs->numclusters );
|
||||
cm.pvs.clusterBytes = LittleLong ( pvs->rowsize );
|
||||
cm.pvs.data = (byte *)Mem_Alloc( cmappool, l->filelen - VIS_HEADER_SIZE );
|
||||
Mem_Copy( cm.pvs.data, pvs->data, l->filelen - VIS_HEADER_SIZE );
|
||||
cm.vised = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -519,25 +510,28 @@ BSP_LoadHearability
|
||||
*/
|
||||
void BSP_LoadHearability( lump_t *l )
|
||||
{
|
||||
if( !l->filelen )
|
||||
{
|
||||
size_t phs_size, row_size;
|
||||
dvis_t *phs;
|
||||
byte *buffer;
|
||||
|
||||
// FIXME: calculate PHS on fly from PVS, probably it's very fast
|
||||
// FIXME: kill lump phs
|
||||
|
||||
// create novis lump
|
||||
row_size = (cm.numclusters + 7) / 8;
|
||||
phs_size = row_size * cm.numclusters;
|
||||
cm.phs = (dvis_t *)Mem_Alloc( cmappool, phs_size + sizeof(dvis_t) - 1 );
|
||||
cm.phs->numclusters = cm.numclusters;
|
||||
cm.phs->rowsize = row_size;
|
||||
memset( cm.phs->data, 0xFF, phs_size );
|
||||
if( !cm.vised || !l->filelen )
|
||||
{
|
||||
// create totalphs lump
|
||||
cm.phs.numClusters = cm.pvs.numClusters;
|
||||
cm.phs.clusterBytes = ( cm.phs.numClusters + 31 ) & ~31;
|
||||
cm.phs.data = (byte *)Mem_Alloc( cmappool, cm.phs.clusterBytes );
|
||||
memset( cm.phs.data, 0xFF, cm.phs.clusterBytes );
|
||||
return;
|
||||
}
|
||||
|
||||
cm.phs = (dvis_t *)Mem_Alloc( cmappool, l->filelen );
|
||||
Mem_Copy( cm.phs, cm.mod_base + l->fileofs, l->filelen );
|
||||
|
||||
cm.phs->numclusters = LittleLong ( cm.phs->numclusters );
|
||||
cm.phs->rowsize = LittleLong ( cm.phs->rowsize );
|
||||
buffer = (byte *)cm.mod_base + l->fileofs;
|
||||
phs = (dvis_t *)buffer;
|
||||
cm.phs.numClusters = LittleLong ( phs->numclusters );
|
||||
cm.phs.clusterBytes = LittleLong ( phs->rowsize );
|
||||
cm.phs.data = (byte *)Mem_Alloc( cmappool, l->filelen - VIS_HEADER_SIZE );
|
||||
Mem_Copy( cm.phs.data, phs->data, l->filelen - VIS_HEADER_SIZE );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -602,8 +596,7 @@ void BSP_LoadSurfaces( lump_t *l )
|
||||
cm.numsurfaces = l->filelen / sizeof(*in);
|
||||
cm.surfaces = Mem_Alloc( cmappool, cm.numsurfaces * sizeof(*in));
|
||||
|
||||
Msg("BSP_LoadSurfaces: %i\n", cm.numsurfaces );
|
||||
Mem_Copy( cm.surfaces, in, cm.numsurfaces * sizeof(*in));
|
||||
Mem_Copy( cm.surfaces, in, cm.numsurfaces * sizeof( *in ));
|
||||
SwapBlock((int *)cm.surfaces, cm.numsurfaces * sizeof(*in));
|
||||
}
|
||||
|
||||
@ -703,7 +696,7 @@ void BSP_BeginBuildTree( void )
|
||||
void BSP_AddCollisionFace( int facenum )
|
||||
{
|
||||
dsurface_t *m_surface;
|
||||
int i, j, k;
|
||||
int j, k;
|
||||
int flags;
|
||||
|
||||
if( facenum < 0 || facenum >= cm.numsurfaces )
|
||||
@ -715,7 +708,6 @@ void BSP_AddCollisionFace( int facenum )
|
||||
m_surface = cm.surfaces + facenum;
|
||||
flags = cm.shaders[m_surface->shadernum].surfaceflags;
|
||||
k = m_surface->firstvertex;
|
||||
Msg("add collision face %i [%i verts, inds %i]\n", facenum, m_surface->numvertices, m_surface->numindices );
|
||||
|
||||
// sky is noclip for all physobjects
|
||||
if( flags & SURF_SKY ) return;
|
||||
@ -726,13 +718,9 @@ void BSP_AddCollisionFace( int facenum )
|
||||
for( j = 0; j < m_surface->numvertices - 2; j++ )
|
||||
{
|
||||
vec3_t face[3]; // triangle
|
||||
Msg("triangle: %i ", j );
|
||||
CM_GetPoint( k, face[0] );
|
||||
CM_GetPoint( k+j+2, face[1] );
|
||||
CM_GetPoint( k+j+1, face[2] );
|
||||
for( i = 0; i < 3; i++ )
|
||||
Msg("( %.f %.f %.f ) ", face[i][0], face[i][1], face[i][2] );
|
||||
Msg("\n" );
|
||||
CM_GetPoint( k+j+1, face[1] );
|
||||
CM_GetPoint( k+j+2, face[2] );
|
||||
NewtonTreeCollisionAddFace( cm.collision, 3, (float *)face[0], sizeof(vec3_t), 1 );
|
||||
}
|
||||
}
|
||||
@ -845,15 +833,14 @@ void CM_FreeWorld( void )
|
||||
|
||||
// free old stuff
|
||||
if( cm.loaded ) Mem_EmptyPool( cmappool );
|
||||
cm.numclusters = cm.floodvalid = 0;
|
||||
cm.numplanes = cm.numnodes = cm.numleafs = 0;
|
||||
cm.floodvalid = cm.numbrushsides = cm.numshaders = 0;
|
||||
cm.numbrushes = cm.numleafsurfaces = cm.numareas = 0;
|
||||
cm.numleafbrushes = cm.numsurfaces = cm.numbmodels = 0;
|
||||
|
||||
cm.vised = cm.floodvalid = cm.areaportals_size = 0;
|
||||
|
||||
cm.name[0] = 0;
|
||||
memset( cm.matrix, 0, sizeof(matrix4x4));
|
||||
memset( cm.nullvis, 0xFF, MAX_MAP_LEAFS / 8 );
|
||||
|
||||
// free bmodels too
|
||||
for (i = 0, mod = &cm.bmodels[0]; i < cm.numbmodels; i++, mod++)
|
||||
@ -887,11 +874,11 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
|
||||
dheader_t *hdr;
|
||||
size_t length;
|
||||
|
||||
if(!com.strlen(name))
|
||||
if(!com.strlen( name ))
|
||||
{
|
||||
CM_FreeWorld(); // release old map
|
||||
// cinematic servers won't have anything at all
|
||||
cm.numleafs = cm.numclusters = cm.numareas = 1;
|
||||
cm.numleafs = cm.pvs.numClusters = cm.numareas = 1;
|
||||
*checksum = 0;
|
||||
return &cm.bmodels[0];
|
||||
}
|
||||
@ -902,7 +889,7 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
|
||||
if( !clientload )
|
||||
{
|
||||
// rebuild portals for server
|
||||
memset( cm.portalstate, 0, sizeof(cm.portalstate));
|
||||
memset( cm.areaportals, 0, cm.areaportals_size );
|
||||
CM_FloodAreaConnections();
|
||||
}
|
||||
// still have the right version
|
||||
@ -948,7 +935,6 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
|
||||
Mem_Free( buf ); // release map buffer
|
||||
|
||||
com.strncpy( cm.name, name, MAX_STRING );
|
||||
memset( cm.portalstate, 0, sizeof(cm.portalstate));
|
||||
CM_FloodAreaConnections();
|
||||
cm.loaded = true;
|
||||
|
||||
@ -984,8 +970,8 @@ int CM_LeafCluster( int leafnum )
|
||||
|
||||
int CM_LeafArea( int leafnum )
|
||||
{
|
||||
if (leafnum < 0 || leafnum >= cm.numleafs)
|
||||
Host_Error("CM_LeafArea: bad number %d\n", leafnum );
|
||||
if( leafnum < 0 || leafnum >= cm.numleafs )
|
||||
Host_Error("CM_LeafArea: bad number %i >= %i\n", leafnum, cm.numleafs );
|
||||
return cm.leafs[leafnum].area;
|
||||
}
|
||||
|
||||
|
@ -14,14 +14,16 @@ PVS / PHS
|
||||
*/
|
||||
byte *CM_ClusterPVS( int cluster )
|
||||
{
|
||||
if( cluster == -1 || !cm.pvs ) return cm.nullvis;
|
||||
return (byte *)cm.pvs->data + cluster * cm.pvs->rowsize;
|
||||
if( cluster < 0 || cluster >= cm.pvs.numClusters || !cm.vised )
|
||||
return cm.pvs.data;
|
||||
return (byte *)cm.pvs.data + cluster * cm.pvs.clusterBytes;
|
||||
}
|
||||
|
||||
byte *CM_ClusterPHS( int cluster )
|
||||
{
|
||||
if( cluster == -1 || !cm.phs ) return cm.nullvis;
|
||||
return (byte *)cm.phs->data + cluster * cm.phs->rowsize;
|
||||
if( cluster < 0 || cluster >= cm.phs.numClusters || !cm.vised )
|
||||
return cm.phs.data;
|
||||
return (byte *)cm.phs.data + cluster * cm.phs.clusterBytes;
|
||||
}
|
||||
|
||||
static byte *CM_GetPVS( const vec3_t p )
|
||||
@ -55,17 +57,16 @@ static void CM_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *fa
|
||||
{
|
||||
int i;
|
||||
byte *pvs = CM_ClusterPVS(((cleaf_t *)node)->cluster );
|
||||
for (i = 0;i < fatpvs_size;i++)
|
||||
fatpvs[i] |= pvs[i];
|
||||
for( i = 0; i < fatpvs_size; i++ ) fatpvs[i] |= pvs[i];
|
||||
}
|
||||
}
|
||||
|
||||
int CM_FatPVS( const vec3_t org, vec_t radius, byte *fatpvs, size_t fatpvs_size, bool merge )
|
||||
{
|
||||
int bytes = cm.pvs->numclusters;
|
||||
int bytes = cm.pvs.numClusters;
|
||||
|
||||
bytes = min( bytes, fatpvs_size );
|
||||
if( cm_novis->integer || !cm.pvs->numclusters || !CM_GetPVS( org ))
|
||||
if( cm_novis->integer || !cm.vised || !CM_GetPVS( org ))
|
||||
{
|
||||
memset( fatpvs, 0xFF, bytes );
|
||||
return bytes;
|
||||
@ -82,34 +83,10 @@ AREAPORTALS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
====================
|
||||
CM_RegisterAreaPortal
|
||||
====================
|
||||
*/
|
||||
static void CM_RegisterAreaPortal( int portalnum, int areanum, int otherarea )
|
||||
{
|
||||
carea_t *area;
|
||||
careaportal_t *portal;
|
||||
|
||||
portal = &cm.areaportals[portalnum];
|
||||
cm.portalstate[portalnum] = AP_CLOSED;
|
||||
portal->area = areanum;
|
||||
portal->otherarea = otherarea;
|
||||
|
||||
area = &cm.areas[areanum];
|
||||
area->areaportals[area->numareaportals++] = portal;
|
||||
|
||||
area = &cm.areas[otherarea];
|
||||
area->areaportals[area->numareaportals++] = portal;
|
||||
|
||||
}
|
||||
|
||||
void CM_FloodArea_r( int areanum, int floodnum )
|
||||
{
|
||||
careaportal_t *portal;
|
||||
carea_t *area;
|
||||
int i;
|
||||
int i, *con;
|
||||
|
||||
area = &cm.areas[areanum];
|
||||
|
||||
@ -121,18 +98,10 @@ void CM_FloodArea_r( int areanum, int floodnum )
|
||||
|
||||
area->floodnum = floodnum;
|
||||
area->floodvalid = cm.floodvalid;
|
||||
con = cm.areaportals + areanum * cm.numareas;
|
||||
|
||||
for( i = 0; i < area->numareaportals; i++ )
|
||||
{
|
||||
if( cm.portalstate[i] != AP_OPENED );
|
||||
continue;
|
||||
|
||||
portal = area->areaportals[i];
|
||||
if( portal->area == areanum )
|
||||
CM_FloodArea_r( portal->otherarea, floodnum );
|
||||
else if( portal->otherarea == areanum )
|
||||
CM_FloodArea_r( portal->area, floodnum );
|
||||
}
|
||||
for( i = 0; i < cm.numareas; i++ )
|
||||
if( con[i] > 0 ) CM_FloodArea_r( i, floodnum );
|
||||
}
|
||||
|
||||
/*
|
||||
@ -153,39 +122,48 @@ void CM_FloodAreaConnections( void )
|
||||
{
|
||||
if( area->floodvalid == cm.floodvalid )
|
||||
continue; // already flooded into
|
||||
CM_FloodArea_r( i, floodnum++ );
|
||||
floodnum++;
|
||||
CM_FloodArea_r( i, floodnum );
|
||||
}
|
||||
}
|
||||
|
||||
void CM_SetAreaPortals ( byte *portals, size_t size )
|
||||
{
|
||||
if( size == sizeof( cm.portalstate ))
|
||||
if( size == cm.areaportals_size )
|
||||
{
|
||||
Mem_Copy( cm.portalstate, portals, size );
|
||||
Mem_Copy( cm.areaportals, portals, cm.areaportals_size );
|
||||
CM_FloodAreaConnections();
|
||||
return;
|
||||
}
|
||||
MsgDev( D_ERROR, "CM_SetAreaPortals: portals mismatch size (%i should be %i)\n", size, sizeof( cm.portalstate ));
|
||||
MsgDev( D_ERROR, "CM_SetAreaPortals: portals mismatch size (%i should be %i)\n", size, cm.areaportals_size );
|
||||
}
|
||||
|
||||
void CM_GetAreaPortals ( byte **portals, size_t *size )
|
||||
{
|
||||
byte *prt = *portals;
|
||||
|
||||
if( prt ) Mem_Copy( prt, cm.portalstate, sizeof( cm.portalstate ));
|
||||
if( size) *size = sizeof( cm.portalstate );
|
||||
if( prt ) Mem_Copy( prt, cm.areaportals, cm.areaportals_size );
|
||||
if( size) *size = cm.areaportals_size;
|
||||
}
|
||||
|
||||
void CM_SetAreaPortalState( int portalnum, int area, int otherarea, bool open )
|
||||
void CM_SetAreaPortalState( int area1, int area2, bool open )
|
||||
{
|
||||
if( area < 0 || otherarea < 0 ) return;
|
||||
if( portalnum < 0 || portalnum >= MAX_MAP_AREAPORTALS || area > cm.numareas || otherarea > cm.numareas )
|
||||
Host_Error( "CM_SetAreaPortalState: for portal %i bad parms\n", portalnum, area, otherarea, open );
|
||||
if( area1 < 0 || area2 < 0 ) return;
|
||||
if( area1 >= cm.numareas || area2 >= cm.numareas )
|
||||
Host_Error( "CM_SetAreaPortalState: bad area numbers %i or %i\n", area1, area2 );
|
||||
|
||||
if( cm.portalstate[portalnum] == AP_UNREGISTERED )
|
||||
CM_RegisterAreaPortal( portalnum, area, otherarea );
|
||||
|
||||
cm.portalstate[portalnum] = open ? AP_OPENED : AP_CLOSED;
|
||||
if( open )
|
||||
{
|
||||
cm.areaportals[area1*cm.numareas+area2]++;
|
||||
cm.areaportals[area2*cm.numareas+area1]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cm.areaportals[area1*cm.numareas+area2]--;
|
||||
cm.areaportals[area2*cm.numareas+area1]--;
|
||||
if(cm.areaportals[area2*cm.numareas+area1] < 0 )
|
||||
Host_Error( "CM_SetAreaPortalState: negative reference count\n" );
|
||||
}
|
||||
CM_FloodAreaConnections();
|
||||
}
|
||||
|
||||
@ -193,7 +171,7 @@ bool CM_AreasConnected( int area, int otherarea )
|
||||
{
|
||||
if( cm_noareas->integer ) return true;
|
||||
if( area > cm.numareas || otherarea > cm.numareas )
|
||||
Host_Error("CM_AreasConnected: area > numareas\n");
|
||||
Host_Error("CM_AreasConnected: area >= cm.numareas\n" );
|
||||
|
||||
if( area < 0 || otherarea < 0 ) return false;
|
||||
if( area == otherarea ) return true; // quick test
|
||||
@ -214,16 +192,20 @@ This is used by the client refreshes to cull visibility
|
||||
*/
|
||||
int CM_WriteAreaBits( byte *buffer, int area )
|
||||
{
|
||||
int i, size;
|
||||
int i, size, floodnum;
|
||||
|
||||
size = (cm.numareas + 7)>>3;
|
||||
memset( buffer, 0, size );
|
||||
|
||||
if( !cm_noareas->integer )
|
||||
|
||||
if( cm_noareas->integer || area == -1 )
|
||||
{
|
||||
memset( buffer, 0xFF, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
floodnum = cm.areas[area].floodnum;
|
||||
for( i = 0; i < cm.numareas; i++ )
|
||||
{
|
||||
if(!CM_AreasConnected( i, area ))
|
||||
if( cm.areas[i].floodnum == floodnum || area == -1 )
|
||||
buffer[i>>3] |= 1 << (i & 7);
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ void CM_EndRegistration ( void );
|
||||
|
||||
void CM_SetAreaPortals ( byte *portals, size_t size );
|
||||
void CM_GetAreaPortals ( byte **portals, size_t *size );
|
||||
void CM_SetAreaPortalState ( int portalnum, int area, int otherarea, bool open );
|
||||
void CM_SetAreaPortalState ( int area, int otherarea, bool open );
|
||||
|
||||
int CM_NumClusters( void );
|
||||
int CM_NumTextures( void );
|
||||
|
@ -131,6 +131,7 @@ BRUSH MODELS
|
||||
#define IDBSPMODHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I') // little-endian "IBSP"
|
||||
|
||||
// 32 bit limits
|
||||
#define MAX_MAP_AREA_BYTES 32 // bit vector of area visibility
|
||||
#define MAX_MAP_MODELS 0x2000 // mesh models and sprites too
|
||||
#define MAX_MAP_BRUSHES 0x8000
|
||||
#define MAX_MAP_ENTITIES 0x2000 // same as models
|
||||
@ -160,6 +161,7 @@ BRUSH MODELS
|
||||
#define MIN_WORLD_COORD (-128 * 1024 )
|
||||
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
|
||||
#define MAX_BUILD_SIDES 512 // per one brush. (don't change)
|
||||
#define VIS_HEADER_SIZE 8 // sizeof(int) + sizeof(int)
|
||||
#define LIGHTMAP_WIDTH 128
|
||||
#define LIGHTMAP_HEIGHT 128
|
||||
#define LIGHTMAP_BITS 3 // RGB
|
||||
@ -292,7 +294,7 @@ typedef struct
|
||||
{
|
||||
int numclusters;
|
||||
int rowsize;
|
||||
byte data[1]; // variable sized
|
||||
byte data[1]; // unbounded, variable sized
|
||||
} dvis_t;
|
||||
|
||||
typedef struct dlightmap_s
|
||||
|
@ -167,7 +167,7 @@ typedef struct entity_state_s
|
||||
vec3_t angles; // entity angles, not viewangles
|
||||
vec3_t velocity; // player velocity
|
||||
vec3_t old_origin; // for lerping animation
|
||||
vec3_t old_velocity; // for movement predicting
|
||||
vec3_t infotarget; // portal camera, etc
|
||||
model_state_t model; // general entity model
|
||||
solid_t solidtype; // entity solidtype
|
||||
movetype_t movetype; // entity movetype
|
||||
@ -1270,7 +1270,7 @@ typedef struct physic_exp_s
|
||||
|
||||
void (*SetAreaPortals)( byte *portals, size_t size );
|
||||
void (*GetAreaPortals)( byte **portals, size_t *size );
|
||||
void (*SetAreaPortalState)( int portalnum, int area, int otherarea, bool open );
|
||||
void (*SetAreaPortalState)( int area, int otherarea, bool open );
|
||||
|
||||
int (*NumClusters)( void );
|
||||
int (*NumTextures)( void );
|
||||
|
@ -15,88 +15,6 @@
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveLightNode
|
||||
=================
|
||||
*/
|
||||
static void R_RecursiveLightNode( node_t *node, dlight_t *dl, int bit )
|
||||
{
|
||||
#if 0
|
||||
surface_t *surf;
|
||||
cplane_t *plane;
|
||||
float dist;
|
||||
int i;
|
||||
|
||||
if( node->contents != -1 )
|
||||
return;
|
||||
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
return;
|
||||
|
||||
// Find which side of the node we are on
|
||||
plane = node->plane;
|
||||
if( plane->type < 3 )dist = dl->origin[plane->type] - plane->dist;
|
||||
else dist = DotProduct( dl->origin, plane->normal ) - plane->dist;
|
||||
|
||||
// Go down the appropriate sides
|
||||
if( dist > dl->intensity )
|
||||
{
|
||||
R_RecursiveLightNode( node->children[0], dl, bit );
|
||||
return;
|
||||
}
|
||||
if( dist < -dl->intensity )
|
||||
{
|
||||
R_RecursiveLightNode( node->children[1], dl, bit );
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the surfaces
|
||||
surf = r_worldModel->surfaces + node->firstSurface;
|
||||
for( i = 0; i < node->numSurfaces; i++, surf++ )
|
||||
{
|
||||
if( !BoundsAndSphereIntersect( surf->mins, surf->maxs, dl->origin, dl->intensity ))
|
||||
continue; // No intersection
|
||||
|
||||
if( surf->dlightFrame != r_frameCount )
|
||||
{
|
||||
surf->dlightFrame = r_frameCount;
|
||||
surf->dlightBits = bit;
|
||||
}
|
||||
else surf->dlightBits |= bit;
|
||||
}
|
||||
|
||||
// recurse down the children
|
||||
R_RecursiveLightNode( node->children[0], dl, bit );
|
||||
R_RecursiveLightNode( node->children[1], dl, bit );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_MarkLights
|
||||
=================
|
||||
*/
|
||||
void R_MarkLights( void )
|
||||
{
|
||||
dlight_t *dl;
|
||||
int l;
|
||||
|
||||
if( !r_dynamiclights->integer || !r_numDLights )
|
||||
return;
|
||||
|
||||
r_stats.numDLights += r_numDLights;
|
||||
|
||||
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
|
||||
{
|
||||
if( R_CullSphere( dl->origin, dl->intensity, MAX_CLIPFLAGS ))
|
||||
continue;
|
||||
R_RecursiveLightNode( r_worldModel->nodes, dl, 1<<l );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
@ -165,8 +83,8 @@ static bool R_RecursiveLightPoint( node_t *node, const vec3_t start, const vec3_
|
||||
if( tex->flags & (SURF_SKY|SURF_WARP|SURF_NODRAW|SURF_NOLIGHTMAP))
|
||||
continue; // no lightmaps
|
||||
|
||||
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3] - surf->textureMins[0];
|
||||
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3] - surf->textureMins[1];
|
||||
s = DotProduct(mid, surf->lmVecs[0]) + surf->lmVecs[0][3] - surf->textureMins[0];
|
||||
t = DotProduct(mid, surf->lmVecs[1]) + surf->lmVecs[1][3] - surf->textureMins[1];
|
||||
|
||||
if((s < 0 || s > surf->extents[0]) || (t < 0 || t > surf->extents[1]))
|
||||
continue;
|
||||
|
@ -460,6 +460,8 @@ BRUSH MODELS
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
#define SURF_PLANEBACK 1 // fast surface culling
|
||||
#define CONTENTS_NODE -1
|
||||
#define SKY_SIZE 8
|
||||
#define SKY_INDICES (SKY_SIZE * SKY_SIZE * 6)
|
||||
#define SKY_VERTICES ((SKY_SIZE+1) * (SKY_SIZE+1))
|
||||
@ -568,6 +570,7 @@ typedef struct
|
||||
int lmS;
|
||||
int lmT;
|
||||
int lmNum;
|
||||
float lmVecs[2][3]; // lightmap vecs
|
||||
byte *lmSamples;
|
||||
int numStyles;
|
||||
byte styles[MAX_LIGHTSTYLES];
|
||||
@ -576,33 +579,23 @@ typedef struct
|
||||
|
||||
typedef struct node_s
|
||||
{
|
||||
// common with leaf
|
||||
int contents; // -1, to differentiate from leafs
|
||||
int visFrame; // Node needs to be traversed if current
|
||||
vec3_t mins; // For bounding box culling
|
||||
vec3_t maxs; // For bounding box culling
|
||||
// common with leaf and node
|
||||
int contents; // -1, to differentiate from leafs
|
||||
int visFrame; // Node needs to be traversed if current
|
||||
vec3_t mins, maxs; // for bounding box culling
|
||||
struct node_s *parent;
|
||||
|
||||
// node specific
|
||||
cplane_t *plane;
|
||||
struct node_s *children[2];
|
||||
} node_t;
|
||||
|
||||
typedef struct leaf_s
|
||||
{
|
||||
// common with node
|
||||
int contents;
|
||||
int visFrame; // node needs to be traversed if current
|
||||
vec3_t mins; // for bounding box culling
|
||||
vec3_t maxs; // for bounding box culling
|
||||
struct node_s *parent;
|
||||
|
||||
struct node_s *children[2];
|
||||
|
||||
// common with leaf
|
||||
// leaf specific
|
||||
int cluster;
|
||||
int area;
|
||||
surface_t **firstMarkSurface;
|
||||
int numMarkSurfaces;
|
||||
} leaf_t;
|
||||
} node_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -620,8 +613,6 @@ typedef struct
|
||||
vec3_t maxs;
|
||||
vec3_t origin; // for sounds or lights
|
||||
float radius;
|
||||
int headNode;
|
||||
int visLeafs; // not including the solid leaf 0
|
||||
int firstFace;
|
||||
int numFaces;
|
||||
} submodel_t;
|
||||
@ -782,14 +773,14 @@ typedef struct rmodel_s
|
||||
cplane_t *planes;
|
||||
|
||||
int numNodes;
|
||||
node_t *nodes;
|
||||
node_t *nodes; // also included leafs
|
||||
|
||||
int numClusters;
|
||||
int numLeafs;
|
||||
leaf_t *leafs;
|
||||
int clusterBytes;
|
||||
byte *vis; // may be passed in by CM_LoadMap to save space
|
||||
byte *novis; // clusterBytes of 0xff
|
||||
|
||||
sky_t *sky;
|
||||
dvis_t *vis;
|
||||
byte *lightMaps;
|
||||
int numLightmaps;
|
||||
|
||||
@ -887,7 +878,7 @@ typedef struct ref_entity_s
|
||||
} ref_entity_t;
|
||||
|
||||
const char *R_GetStringFromTable( int index );
|
||||
leaf_t *R_PointInLeaf( const vec3_t p );
|
||||
node_t *R_PointInLeaf( const vec3_t p );
|
||||
byte *R_ClusterPVS( int cluster );
|
||||
|
||||
void R_ModelList_f( void );
|
||||
@ -1175,8 +1166,8 @@ extern vec3_t r_worldMins, r_worldMaxs;
|
||||
|
||||
extern int r_frameCount;
|
||||
extern int r_visFrameCount;
|
||||
extern int r_viewCluster, r_viewCluster2;
|
||||
extern int r_oldViewCluster, r_oldViewCluster2;
|
||||
extern int r_viewCluster;
|
||||
extern int r_areabitsChanged;
|
||||
extern vec3_t r_origin; // same as r_refdef.vieworg
|
||||
extern vec3_t r_forward;
|
||||
extern vec3_t r_right;
|
||||
@ -1223,7 +1214,6 @@ void R_AddSpriteModelToList( ref_entity_t *entity );
|
||||
void R_SpriteLoadModel( rmodel_t *mod, const void *buffer );
|
||||
mspriteframe_t *R_GetSpriteFrame( ref_entity_t *ent );
|
||||
|
||||
void R_MarkLights( void );
|
||||
void R_LightDir( const vec3_t origin, vec3_t lightDir );
|
||||
void R_LightForPoint( const vec3_t point, vec3_t ambientLight );
|
||||
void R_LightingAmbient( void );
|
||||
|
@ -810,10 +810,28 @@ void R_RenderView( const refdef_t *fd )
|
||||
if( r_skipfrontend->integer )
|
||||
return;
|
||||
|
||||
r_refdef = *fd;
|
||||
r_numSolidMeshes = 0;
|
||||
r_numTransMeshes = 0;
|
||||
|
||||
// copy the areamask data over and note if it has changed, which
|
||||
// will force a reset of the visible leafs even if the view hasn't moved
|
||||
r_areabitsChanged = false;
|
||||
if(!(r_refdef.rdflags & RDF_NOWORLDMODEL ))
|
||||
{
|
||||
int i, areaDiff = 0;
|
||||
|
||||
// compare the area bits
|
||||
for( i = 0; i < MAX_MAP_AREA_BYTES / 4; i++ )
|
||||
{
|
||||
areaDiff |= ((int *)r_refdef.areabits)[i] ^ ((int *)fd->areabits)[i];
|
||||
((int *)r_refdef.areabits)[i] = ((int *)fd->areabits)[i];
|
||||
}
|
||||
|
||||
// a door just opened or something
|
||||
if( areaDiff ) r_areabitsChanged = true;
|
||||
}
|
||||
|
||||
r_refdef = *fd;
|
||||
// set up frustum
|
||||
R_SetFrustum();
|
||||
|
||||
|
198
render/r_model.c
198
render/r_model.c
@ -22,26 +22,26 @@ static int r_nummodels;
|
||||
R_PointInLeaf
|
||||
===============
|
||||
*/
|
||||
leaf_t *R_PointInLeaf( const vec3_t p )
|
||||
node_t *R_PointInLeaf( const vec3_t p )
|
||||
{
|
||||
node_t *node;
|
||||
cplane_t *plane;
|
||||
float d;
|
||||
|
||||
if( !r_worldModel || !r_worldModel->nodes )
|
||||
Host_Error( "Mod_PointInLeaf: bad model\n" );
|
||||
Host_Error( "R_PointInLeaf: bad model\n" );
|
||||
|
||||
node = r_worldModel->nodes;
|
||||
while( 1 )
|
||||
{
|
||||
if( node->contents != -1 )
|
||||
return (leaf_t *)node;
|
||||
if( node->contents != CONTENTS_NODE )
|
||||
break;
|
||||
plane = node->plane;
|
||||
d = DotProduct( p, plane->normal ) - plane->dist;
|
||||
if( d > 0 ) node = node->children[0];
|
||||
else node = node->children[1];
|
||||
}
|
||||
return NULL; // never reached
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -51,9 +51,9 @@ R_ClusterPVS
|
||||
*/
|
||||
byte *R_ClusterPVS( int cluster )
|
||||
{
|
||||
if( cluster == -1 || !r_worldModel || !r_worldModel->vis )
|
||||
return r_fullvis;
|
||||
return (byte *)r_worldModel->vis->data + cluster * r_worldModel->vis->rowsize;
|
||||
if (!r_worldModel || !r_worldModel->vis || cluster < 0 || cluster >= r_worldModel->numClusters )
|
||||
return r_worldModel->novis;
|
||||
return (byte *)r_worldModel->vis + cluster * r_worldModel->clusterBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -278,6 +278,7 @@ static void R_LoadFaces( const byte *base, const lump_t *l )
|
||||
|
||||
for( i = 0; i < m_pLoadModel->numSurfaces; i++, in++, out++ )
|
||||
{
|
||||
if( LittleLong( in->lm_side )) out->flags |= SURF_PLANEBACK;
|
||||
out->firstIndex = LittleLong( in->firstindex );
|
||||
out->numIndexes = LittleLong( in->numindices );
|
||||
out->firstVertex = LittleLong( in->firstvertex );
|
||||
@ -290,7 +291,9 @@ static void R_LoadFaces( const byte *base, const lump_t *l )
|
||||
// FIXME: tangent vectors
|
||||
// VectorCopy( out->texInfo->vecs[0], out->tangent );
|
||||
// VectorNegate( out->texInfo->vecs[1], out->binormal );
|
||||
VectorCopy( out->plane->normal, out->normal );
|
||||
if(!(out->flags & SURF_PLANEBACK))
|
||||
VectorCopy( out->plane->normal, out->normal );
|
||||
else VectorNegate( out->plane->normal, out->normal );
|
||||
|
||||
// FIXME: tangent vectors
|
||||
// VectorNormalize( out->tangent );
|
||||
@ -357,60 +360,101 @@ R_LoadVisibility
|
||||
*/
|
||||
static void R_LoadVisibility( const byte *base, const lump_t *l )
|
||||
{
|
||||
if( !l->filelen )
|
||||
{
|
||||
size_t pvs_size, row_size;
|
||||
|
||||
// create novis lump
|
||||
row_size = (m_pLoadModel->numClusters + 7) / 8;
|
||||
pvs_size = row_size * m_pLoadModel->numClusters;
|
||||
m_pLoadModel->vis = (dvis_t *)Mem_Alloc( m_pLoadModel->mempool, pvs_size + sizeof(dvis_t) - 1 );
|
||||
m_pLoadModel->vis->numclusters = m_pLoadModel->numClusters;
|
||||
m_pLoadModel->vis->rowsize = row_size;
|
||||
memset( m_pLoadModel->vis->data, 0xFF, pvs_size );
|
||||
return;
|
||||
}
|
||||
size_t vis_length;
|
||||
const byte *buffer;
|
||||
|
||||
m_pLoadModel->vis = Mem_Alloc( m_pLoadModel->mempool, l->filelen + sizeof(dvis_t) - 1 );
|
||||
Mem_Copy( m_pLoadModel->vis, base + l->fileofs, l->filelen );
|
||||
vis_length = ( m_pLoadModel->numClusters + 63 ) & ~63;
|
||||
m_pLoadModel->novis = Mem_Alloc( m_pLoadModel->mempool, vis_length );
|
||||
memset( m_pLoadModel->novis, 0xff, vis_length );
|
||||
|
||||
m_pLoadModel->vis->numclusters = LittleLong ( m_pLoadModel->vis->numclusters );
|
||||
m_pLoadModel->vis->rowsize = LittleLong ( m_pLoadModel->vis->rowsize );
|
||||
if( !l->filelen ) return;
|
||||
buffer = base + l->fileofs;
|
||||
m_pLoadModel->numClusters = LittleLong(((int *)buffer)[0] );
|
||||
m_pLoadModel->clusterBytes = LittleLong(((int *)buffer)[1] );
|
||||
m_pLoadModel->vis = Mem_Alloc( m_pLoadModel->mempool, l->filelen - VIS_HEADER_SIZE );
|
||||
Mem_Copy(m_pLoadModel->vis, buffer + VIS_HEADER_SIZE, l->filelen - VIS_HEADER_SIZE );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LoadLeafs
|
||||
R_SetParent
|
||||
=================
|
||||
*/
|
||||
static void R_LoadLeafs( const byte *base, const lump_t *l )
|
||||
static void R_NodeSetParent( node_t *node, node_t *parent )
|
||||
{
|
||||
dleaf_t *in;
|
||||
leaf_t *out;
|
||||
int i, j;
|
||||
node->parent = parent;
|
||||
if( node->contents != CONTENTS_NODE ) return;
|
||||
|
||||
in = (dleaf_t *)(base + l->fileofs);
|
||||
if (l->filelen % sizeof(dleaf_t))
|
||||
Host_Error( "R_LoadLeafs: funny lump size in '%s'\n", m_pLoadModel->name );
|
||||
R_NodeSetParent( node->children[0], node );
|
||||
R_NodeSetParent( node->children[1], node );
|
||||
}
|
||||
|
||||
m_pLoadModel->numLeafs = l->filelen / sizeof(dleaf_t);
|
||||
m_pLoadModel->leafs = out = Mem_Alloc( m_pLoadModel->mempool, m_pLoadModel->numLeafs * sizeof(leaf_t));
|
||||
/*
|
||||
=================
|
||||
R_LoadLeafNodes
|
||||
=================
|
||||
*/
|
||||
static void R_LoadLeafNodes( const byte *base, const lump_t *nodes, const lump_t *leafs )
|
||||
{
|
||||
int i, j, p;
|
||||
node_t *out;
|
||||
dnode_t *inNode;
|
||||
dleaf_t *inLeaf;
|
||||
int numNodes, numLeafs;
|
||||
|
||||
for( i = 0; i < m_pLoadModel->numLeafs; i++, in++, out++ )
|
||||
inNode = (void *)(base + nodes->fileofs);
|
||||
if( nodes->filelen % sizeof(dnode_t) || leafs->filelen % sizeof(dleaf_t))
|
||||
Host_Error( "R_LoadLeafNodes: funny lump size in '%s'\n", m_pLoadModel->name );
|
||||
numNodes = nodes->filelen / sizeof(dnode_t);
|
||||
numLeafs = leafs->filelen / sizeof(dleaf_t);
|
||||
|
||||
out = Mem_Alloc( m_pLoadModel->mempool, (numNodes + numLeafs) * sizeof( *out ));
|
||||
|
||||
m_pLoadModel->nodes = out;
|
||||
m_pLoadModel->numNodes = numNodes + numLeafs;
|
||||
|
||||
// load nodes
|
||||
for( i = 0; i < numNodes; i++, inNode++, out++ )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
out->mins[j] = LittleLong( in->mins[j] );
|
||||
out->maxs[j] = LittleLong( in->maxs[j] );
|
||||
out->mins[j] = LittleLong( inNode->mins[j] );
|
||||
out->maxs[j] = LittleLong( inNode->maxs[j] );
|
||||
}
|
||||
|
||||
p = LittleLong( inNode->planenum );
|
||||
if( p < 0 || p >= m_pLoadModel->numPlanes )
|
||||
Host_Error( "R_LoadLeafNodes: bad planenum %i\n", p );
|
||||
out->plane = m_pLoadModel->planes + p;
|
||||
out->contents = CONTENTS_NODE; // differentiate from leafs
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
p = LittleLong( inNode->children[j] );
|
||||
if( p >= 0 ) out->children[j] = m_pLoadModel->nodes + p;
|
||||
else out->children[j] = m_pLoadModel->nodes + numNodes + (-1 - p);
|
||||
}
|
||||
}
|
||||
|
||||
// load leafs
|
||||
inLeaf = (void *)(base + leafs->fileofs);
|
||||
for( i = 0; i < numLeafs; i++, inLeaf++, out++ )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
out->mins[j] = LittleLong( inLeaf->mins[j] );
|
||||
out->maxs[j] = LittleLong( inLeaf->maxs[j] );
|
||||
}
|
||||
|
||||
out->contents = LittleLong( in->contents );
|
||||
out->cluster = LittleLong( in->cluster );
|
||||
out->contents = LittleLong( inLeaf->contents ); // FIXME
|
||||
out->cluster = LittleLong( inLeaf->cluster );
|
||||
out->area = LittleLong( inLeaf->area );
|
||||
|
||||
if( out->cluster >= m_pLoadModel->numClusters )
|
||||
m_pLoadModel->numClusters = out->cluster + 1;
|
||||
out->area = LittleLong( in->area );
|
||||
out->firstMarkSurface = m_pLoadModel->markSurfaces + LittleLong( in->firstleafface );
|
||||
out->numMarkSurfaces = LittleLong( in->numleaffaces );
|
||||
|
||||
out->firstMarkSurface = m_pLoadModel->markSurfaces + LittleLong( inLeaf->firstleafface );
|
||||
out->numMarkSurfaces = LittleLong( inLeaf->numleaffaces );
|
||||
|
||||
// mark the surfaces for caustics
|
||||
if( out->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA))
|
||||
@ -428,61 +472,9 @@ static void R_LoadLeafs( const byte *base, const lump_t *l )
|
||||
out->firstMarkSurface[j]->flags |= SURF_LAVACAUSTICS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SetParent
|
||||
=================
|
||||
*/
|
||||
static void R_NodeSetParent( node_t *node, node_t *parent )
|
||||
{
|
||||
node->parent = parent;
|
||||
if( node->contents != -1 ) return;
|
||||
|
||||
R_NodeSetParent( node->children[0], node );
|
||||
R_NodeSetParent( node->children[1], node );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LoadNodes
|
||||
=================
|
||||
*/
|
||||
static void R_LoadNodes( const byte *base, const lump_t *l )
|
||||
{
|
||||
dnode_t *in;
|
||||
node_t *out;
|
||||
int i, j, p;
|
||||
|
||||
in = (dnode_t *)(base + l->fileofs);
|
||||
if (l->filelen % sizeof(dnode_t))
|
||||
Host_Error( "R_LoadNodes: funny lump size in '%s'\n", m_pLoadModel->name );
|
||||
|
||||
m_pLoadModel->numNodes = l->filelen / sizeof(dnode_t);
|
||||
m_pLoadModel->nodes = out = Mem_Alloc( m_pLoadModel->mempool, m_pLoadModel->numNodes * sizeof(node_t));
|
||||
|
||||
for( i = 0; i < m_pLoadModel->numNodes; i++, in++, out++ )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
out->mins[j] = LittleLong(in->mins[j]);
|
||||
out->maxs[j] = LittleLong(in->maxs[j]);
|
||||
}
|
||||
|
||||
out->plane = m_pLoadModel->planes + LittleLong( in->planenum );
|
||||
out->contents = -1;
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
p = LittleLong( in->children[j] );
|
||||
if( p >= 0 ) out->children[j] = m_pLoadModel->nodes + p;
|
||||
else out->children[j] = (node_t *)(m_pLoadModel->leafs + (-1 - p));
|
||||
}
|
||||
}
|
||||
|
||||
// set nodes and leafs
|
||||
// chain decendants
|
||||
R_NodeSetParent( m_pLoadModel->nodes, NULL );
|
||||
}
|
||||
|
||||
@ -512,7 +504,6 @@ static void R_SetupSubmodels( void )
|
||||
|
||||
if( i == 0 ) *m_pLoadModel = *model;
|
||||
else com.snprintf( model->name, sizeof(model->name), "*%i", i );
|
||||
model->numLeafs = bm->visLeafs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -574,6 +565,8 @@ void Mod_LoadBrushModel( rmodel_t *mod, const void *buffer )
|
||||
byte *mod_base;
|
||||
|
||||
m_pLoadModel->type = mod_world;
|
||||
m_pLoadModel->numClusters = 0;
|
||||
|
||||
if( m_pLoadModel != r_models )
|
||||
{
|
||||
MsgDev( D_ERROR, "loaded a brush model after the world\n");
|
||||
@ -598,9 +591,8 @@ void Mod_LoadBrushModel( rmodel_t *mod, const void *buffer )
|
||||
R_LoadShaders( mod_base, &header->lumps[LUMP_SHADERS]);
|
||||
R_LoadFaces( mod_base, &header->lumps[LUMP_SURFACES]);
|
||||
R_LoadMarkSurfaces( mod_base, &header->lumps[LUMP_LEAFFACES]);
|
||||
R_LoadLeafNodes( mod_base, &header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS] );
|
||||
R_LoadVisibility( mod_base, &header->lumps[LUMP_VISIBILITY]);
|
||||
R_LoadLeafs( mod_base, &header->lumps[LUMP_LEAFS]);
|
||||
R_LoadNodes( mod_base, &header->lumps[LUMP_NODES]);
|
||||
R_LoadSubmodels( mod_base, &header->lumps[LUMP_MODELS]);
|
||||
|
||||
mod->registration_sequence = registration_sequence; // register model
|
||||
@ -734,8 +726,6 @@ void R_BeginRegistration( const char *mapname )
|
||||
string fullname;
|
||||
|
||||
registration_sequence++;
|
||||
r_oldViewCluster = -1; // force markleafs
|
||||
|
||||
com.sprintf( fullname, "maps/%s.bsp", mapname );
|
||||
|
||||
// explicitly free the old map if different
|
||||
@ -851,7 +841,7 @@ void R_InitModels( void )
|
||||
r_worldModel = NULL;
|
||||
r_frameCount = 1; // no dlight cache
|
||||
r_nummodels = 0;
|
||||
r_viewCluster = r_oldViewCluster = -1; // force markleafs
|
||||
r_viewCluster = -1; // force markleafs
|
||||
|
||||
r_worldEntity = &r_entities[0]; // First entity is the world
|
||||
memset( r_worldEntity, 0, sizeof( ref_entity_t ));
|
||||
|
@ -54,8 +54,9 @@ shaderParm_t infoParms[] =
|
||||
{"additive", SURFACEPARM_ADDITIVE, CONTENTS_TRANSLUCENT}, // don't eat contained surfaces
|
||||
{"blend", SURFACEPARM_BLEND, CONTENTS_WINDOW }, // normal window
|
||||
{"chrome", SURF_CHROME, 0 }, // don't eat contained surfaces
|
||||
// enbale after implementation mirrors
|
||||
// {"mirror", SURFACEPARM_MIRROR, CONTENTS_SOLID },
|
||||
{"nodraw", 0, 0, }, // stub
|
||||
{"null", 0, 0, }, // stub
|
||||
{"mirror", SURFACEPARM_MIRROR, 0 },
|
||||
// {"portal", SURFACEPARM_PORTAL, CONTENTS_TRIGGER },
|
||||
{"light", SURFACEPARM_LIGHTMAP, 0 },
|
||||
{"lightmap", SURFACEPARM_LIGHTMAP, 0 },
|
||||
@ -3824,7 +3825,6 @@ void R_ShaderRegisterImages( rmodel_t *mod )
|
||||
}
|
||||
}
|
||||
}
|
||||
Msg("R_ShaderRegisterImages: %s (%i textures updated)\n", mod->name, c_total );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -770,6 +770,11 @@ void R_StudioSetUpTransform( void )
|
||||
// don't rotate player model, only aim
|
||||
angles[PITCH] = 0;
|
||||
}
|
||||
else if( m_pCurrentEntity->ent_type == ED_VIEWMODEL )
|
||||
{
|
||||
// stupid quake bug
|
||||
angles[PITCH] = -angles[PITCH];
|
||||
}
|
||||
else if( m_pCurrentEntity->movetype != MOVETYPE_NONE )
|
||||
{
|
||||
VectorCopy( m_pCurrentEntity->angles, angles );
|
||||
|
@ -15,8 +15,8 @@ ref_entity_t *r_worldEntity;
|
||||
vec3_t r_worldMins, r_worldMaxs;
|
||||
int r_frameCount;
|
||||
int r_visFrameCount;
|
||||
int r_viewCluster, r_viewCluster2;
|
||||
int r_oldViewCluster, r_oldViewCluster2;
|
||||
int r_areabitsChanged;
|
||||
int r_viewCluster;
|
||||
int numRadarEnts = 0;
|
||||
radar_ent_t RadarEnts[MAX_RADAR_ENTS];
|
||||
|
||||
@ -83,7 +83,17 @@ static bool R_CullSurface( surface_t *surf, const vec3_t origin, int clipFlags )
|
||||
plane = surf->plane;
|
||||
if( plane->type < 3 ) dist = origin[plane->type] - plane->dist;
|
||||
else dist = DotProduct( origin, plane->normal ) - plane->dist;
|
||||
if( dist <= BACKFACE_EPSILON ) return true; // wrong side
|
||||
|
||||
if(!(surf->flags & SURF_PLANEBACK))
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return true; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return true; // wrong side
|
||||
}
|
||||
|
||||
// cull
|
||||
if( clipFlags )
|
||||
@ -247,91 +257,68 @@ Mark the leaves and nodes that are in the PVS for the current cluster
|
||||
*/
|
||||
static void R_MarkLeaves( void )
|
||||
{
|
||||
byte *vis, fatVis[MAX_MAP_LEAFS/8];
|
||||
node_t *node;
|
||||
leaf_t *leaf;
|
||||
vec3_t tmp;
|
||||
int i, c;
|
||||
byte *vis;
|
||||
int i, cluster;
|
||||
node_t *leaf, *parent;
|
||||
|
||||
// lockpvs lets designers walk around to determine the
|
||||
// extent of the current pvs
|
||||
if( r_lockpvs->integer ) return;
|
||||
|
||||
// Current view cluster
|
||||
r_oldViewCluster = r_viewCluster;
|
||||
r_oldViewCluster2 = r_viewCluster2;
|
||||
|
||||
leaf = R_PointInLeaf( r_refdef.vieworg );
|
||||
cluster = leaf->cluster;
|
||||
|
||||
if( r_showcluster->integer )
|
||||
Msg( "Cluster: %i, Area: %i\n", leaf->cluster, leaf->area );
|
||||
// if the cluster is the same and the area visibility matrix
|
||||
// hasn't changed, we don't need to mark everything again
|
||||
|
||||
r_viewCluster = r_viewCluster2 = leaf->cluster;
|
||||
|
||||
// check above and below so crossing solid water doesn't draw wrong
|
||||
if( !leaf->contents )
|
||||
{
|
||||
// look down a bit
|
||||
VectorCopy( r_refdef.vieworg, tmp );
|
||||
tmp[2] -= 16;
|
||||
leaf = R_PointInLeaf( tmp );
|
||||
if(!(leaf->contents & CONTENTS_SOLID) && (leaf->cluster != r_viewCluster2))
|
||||
r_viewCluster2 = leaf->cluster;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look up a bit
|
||||
VectorCopy( r_refdef.vieworg, tmp );
|
||||
tmp[2] += 16;
|
||||
leaf = R_PointInLeaf( tmp );
|
||||
if(!(leaf->contents & CONTENTS_SOLID) && (leaf->cluster != r_viewCluster2))
|
||||
r_viewCluster2 = leaf->cluster;
|
||||
}
|
||||
|
||||
if( r_viewCluster == r_oldViewCluster && r_viewCluster2 == r_oldViewCluster2 && !r_novis->integer && r_viewCluster != -1 )
|
||||
// if r_showcluster was just turned on, remark everything
|
||||
if( r_viewCluster == cluster && !r_areabitsChanged && !r_showcluster->modified )
|
||||
return;
|
||||
|
||||
// development aid to let you run around and see exactly where the PVS ends
|
||||
if( r_lockpvs->integer )
|
||||
return;
|
||||
if( r_showcluster->modified || r_showcluster->integer )
|
||||
{
|
||||
r_showcluster->modified = false;
|
||||
if( r_showcluster->integer )
|
||||
Msg( "cluster:%i area:%i\n", cluster, leaf->area );
|
||||
}
|
||||
|
||||
r_visFrameCount++;
|
||||
r_oldViewCluster = r_viewCluster;
|
||||
r_oldViewCluster2 = r_viewCluster2;
|
||||
|
||||
if( r_novis->integer || r_viewCluster == -1 || !r_worldModel->vis )
|
||||
r_viewCluster = cluster;
|
||||
|
||||
if( r_novis->integer || r_viewCluster == -1 )
|
||||
{
|
||||
// mark everything
|
||||
for( i = 0, leaf = r_worldModel->leafs; i < r_worldModel->numLeafs; i++, leaf++ )
|
||||
leaf->visFrame = r_visFrameCount;
|
||||
for( i = 0, node = r_worldModel->nodes; i < r_worldModel->numNodes; i++, node++ )
|
||||
node->visFrame = r_visFrameCount;
|
||||
for( i = 0; i < r_worldModel->numNodes; i++ )
|
||||
{
|
||||
if( r_worldModel->nodes[i].contents != CONTENTS_SOLID )
|
||||
r_worldModel->nodes[i].visFrame = r_visFrameCount;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// may have to combine two clusters because of solid water boundaries
|
||||
vis = R_ClusterPVS(r_viewCluster);
|
||||
if( r_viewCluster != r_viewCluster2 )
|
||||
vis = R_ClusterPVS( r_viewCluster );
|
||||
|
||||
for( i = 0, leaf = r_worldModel->nodes; i < r_worldModel->numNodes; i++, leaf++ )
|
||||
{
|
||||
Mem_Copy( fatVis, vis, (r_worldModel->numLeafs+7)/8);
|
||||
vis = R_ClusterPVS( r_viewCluster2 );
|
||||
c = (r_worldModel->numLeafs+31)/32;
|
||||
for( i = 0; i < c; i++ )
|
||||
((int *)fatVis)[i] |= ((int *)vis)[i];
|
||||
vis = fatVis;
|
||||
}
|
||||
|
||||
for( i = 0, leaf = r_worldModel->leafs; i < r_worldModel->numLeafs; i++, leaf++ )
|
||||
{
|
||||
if( leaf->cluster == -1 )
|
||||
continue;
|
||||
if(!(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))))
|
||||
cluster = leaf->cluster;
|
||||
if( cluster < 0 || cluster >= r_worldModel->numClusters )
|
||||
continue;
|
||||
|
||||
node = (node_t *)leaf;
|
||||
do
|
||||
{
|
||||
if( node->visFrame == r_visFrameCount )
|
||||
// check general pvs
|
||||
if(!(vis[cluster>>3] & (1<<(cluster&7))))
|
||||
continue;
|
||||
|
||||
// check for door connection
|
||||
if((r_refdef.areabits[leaf->area>>3] & (1<<(leaf->area & 7 ))))
|
||||
continue; // not visible
|
||||
|
||||
parent = (node_t *)leaf;
|
||||
do {
|
||||
if( parent->visFrame == r_visFrameCount )
|
||||
break;
|
||||
node->visFrame = r_visFrameCount;
|
||||
node = node->parent;
|
||||
} while( node );
|
||||
parent->visFrame = r_visFrameCount;
|
||||
parent = parent->parent;
|
||||
} while( parent );
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,70 +327,94 @@ static void R_MarkLeaves( void )
|
||||
R_RecursiveWorldNode
|
||||
=================
|
||||
*/
|
||||
static void R_RecursiveWorldNode( node_t *node, int clipFlags )
|
||||
static void R_RecursiveWorldNode( node_t *node, int planeBits, int dlightBits )
|
||||
{
|
||||
leaf_t *leaf;
|
||||
surface_t *surf, **mark;
|
||||
cplane_t *plane;
|
||||
surface_t *surf, **mark;
|
||||
int i, clipped;
|
||||
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
return; // solid
|
||||
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
return;
|
||||
|
||||
// cull
|
||||
if( clipFlags )
|
||||
while( 1 )
|
||||
{
|
||||
for( i = 0, plane = r_frustum; i < 4; i++, plane++ )
|
||||
int newDlights[2];
|
||||
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
return; // solid
|
||||
|
||||
if( node->visFrame != r_visFrameCount )
|
||||
return;
|
||||
|
||||
// if the bounding volume is outside the frustum, nothing
|
||||
// inside can be visible OPTIMIZE: don't do this all the way to leafs?
|
||||
// g-cont. because we throw node->firstface and node->numfaces !!!!
|
||||
if( planeBits )
|
||||
{
|
||||
if(!(clipFlags & (1<<i)))
|
||||
continue;
|
||||
for( i = 0, plane = r_frustum; i < 4; i++, plane++ )
|
||||
{
|
||||
if(!(planeBits & (1<<i))) continue;
|
||||
|
||||
clipped = BoxOnPlaneSide( node->mins, node->maxs, plane );
|
||||
if( clipped == 2 ) return;
|
||||
if( clipped == 1 ) clipFlags &= ~(1<<i);
|
||||
clipped = BoxOnPlaneSide( node->mins, node->maxs, plane );
|
||||
if( clipped == 2 ) return;
|
||||
if( clipped == 1 ) planeBits &= ~(1<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recurse down the children
|
||||
if( node->contents == -1 )
|
||||
{
|
||||
R_RecursiveWorldNode( node->children[0], clipFlags );
|
||||
R_RecursiveWorldNode( node->children[1], clipFlags );
|
||||
return;
|
||||
}
|
||||
if( node->contents != CONTENTS_NODE ) break;
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
leaf = (leaf_t *)node;
|
||||
// node is just a decision point, so go down both sides
|
||||
// since we don't care about sort orders, just go positive to negative
|
||||
|
||||
if( !leaf->numMarkSurfaces ) return;
|
||||
// determine which dlights are needed
|
||||
newDlights[0] = 0;
|
||||
newDlights[1] = 0;
|
||||
if( dlightBits )
|
||||
{
|
||||
for( i = 0; i < r_numDLights; i++ )
|
||||
{
|
||||
dlight_t *dl;
|
||||
float dist;
|
||||
|
||||
// check for door connected areas
|
||||
if( r_refdef.areabits )
|
||||
{
|
||||
if(!(r_refdef.areabits[leaf->area>>3] & (1<<(leaf->area&7))))
|
||||
return; // not visible
|
||||
if( dlightBits & (1<<i ))
|
||||
{
|
||||
dl = &r_dlights[i];
|
||||
dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist;
|
||||
|
||||
if( dist > -dl->intensity ) newDlights[0] |= (1<<i);
|
||||
if( dist < dl->intensity ) newDlights[1] |= (1<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recurse down the children, front side first
|
||||
R_RecursiveWorldNode( node->children[0], planeBits, newDlights[0] );
|
||||
|
||||
// tail recurse
|
||||
node = node->children[1];
|
||||
dlightBits = newDlights[1];
|
||||
}
|
||||
|
||||
// add to world mins/maxs
|
||||
AddPointToBounds( leaf->mins, r_worldMins, r_worldMaxs );
|
||||
AddPointToBounds( leaf->maxs, r_worldMins, r_worldMaxs );
|
||||
AddPointToBounds( node->mins, r_worldMins, r_worldMaxs );
|
||||
AddPointToBounds( node->maxs, r_worldMins, r_worldMaxs );
|
||||
|
||||
r_stats.numLeafs++;
|
||||
|
||||
// add all the surfaces
|
||||
for( i = 0, mark = leaf->firstMarkSurface; i < leaf->numMarkSurfaces; i++, mark++ )
|
||||
// add the individual surfaces
|
||||
for( i = 0, mark = node->firstMarkSurface; i < node->numMarkSurfaces; i++, mark++ )
|
||||
{
|
||||
surf = *mark;
|
||||
|
||||
if( surf->visFrame == r_frameCount )
|
||||
continue; // already added this surface from another leaf
|
||||
surf->visFrame = r_frameCount;
|
||||
if( surf->dlightFrame != r_frameCount )
|
||||
{
|
||||
surf->dlightFrame = r_frameCount;
|
||||
surf->dlightBits = dlightBits;
|
||||
}
|
||||
else surf->dlightBits |= dlightBits;
|
||||
|
||||
// cull
|
||||
if( R_CullSurface( surf, r_refdef.vieworg, clipFlags ))
|
||||
if( R_CullSurface( surf, r_refdef.vieworg, planeBits ))
|
||||
continue;
|
||||
|
||||
// clip sky surfaces
|
||||
@ -425,27 +436,34 @@ R_AddWorldToList
|
||||
*/
|
||||
void R_AddWorldToList( void )
|
||||
{
|
||||
int planeBits;
|
||||
int dlightBits;
|
||||
|
||||
if( r_refdef.rdflags & RDF_NOWORLDMODEL )
|
||||
return;
|
||||
|
||||
if( !r_drawworld->integer )
|
||||
return;
|
||||
|
||||
if( r_nocull->integer ) planeBits = 0;
|
||||
else planeBits = MAX_CLIPFLAGS;
|
||||
|
||||
if( !r_dynamiclights->integer ) dlightBits = 0;
|
||||
else dlightBits = (1<<r_numDLights ) - 1;
|
||||
|
||||
// bump frame count
|
||||
r_frameCount++;
|
||||
|
||||
// auto cycle the world frame for texture animation
|
||||
r_worldEntity->frame = (int)(r_refdef.time * 2);
|
||||
r_stats.numDLights += r_numDLights;
|
||||
|
||||
// clear world mins/maxs
|
||||
ClearBounds( r_worldMins, r_worldMaxs );
|
||||
|
||||
R_MarkLeaves();
|
||||
R_MarkLights();
|
||||
R_ClearSky(); // S.T.A.L.K.E.R ClearSky
|
||||
|
||||
R_ClearSky();
|
||||
|
||||
if( r_nocull->integer ) R_RecursiveWorldNode( r_worldModel->nodes, 0 );
|
||||
else R_RecursiveWorldNode( r_worldModel->nodes, 15 );
|
||||
R_RecursiveWorldNode( r_worldModel->nodes, planeBits, dlightBits );
|
||||
R_AddSkyToList();
|
||||
}
|
||||
|
9
todo.log
9
todo.log
@ -18,7 +18,11 @@ fopen
|
||||
|
||||
GLOBAL: Äîñòèãíóòü óðîâíÿ xash 0.45 ê î÷åðåäíîìó ðåëèçó
|
||||
|
||||
операция "Напильник: render.dll"
|
||||
îïåðàöèÿ "Íàïèëüíèê: bsp 40
|
||||
1. collision triangles OK
|
||||
2. cm.novis Ok
|
||||
3. èìïëåìåíòàöèÿ PHS
|
||||
4. óáðàòü contents èç dleaf_t
|
||||
|
||||
1. r_backend.c:1335
|
||||
2. r_backend.c:1338
|
||||
@ -30,7 +34,8 @@ GLOBAL:
|
||||
|
||||
9. r_texture.c:1724
|
||||
|
||||
возвращаемся к смене формата карты
|
||||
1. îòëàäèòü vis
|
||||
2. îòëàäèòü r_culling
|
||||
|
||||
|
||||
TODO LIST
|
||||
|
@ -503,7 +503,7 @@ word PR_WriteProgdefs( void )
|
||||
|
||||
switch( crc )
|
||||
{
|
||||
case 12094:
|
||||
case 9289:
|
||||
PR_Message("Xash3D unmodified server.dat\n");
|
||||
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "server.dat");
|
||||
break;
|
||||
|
Reference in New Issue
Block a user