10 Sep 2008

This commit is contained in:
g-cont 2008-09-10 00:00:00 +04:00 committed by Alibek Omarov
parent 38c5b71df1
commit 6cc2444932
40 changed files with 4195 additions and 4154 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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++;

View File

@ -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];

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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++ )
{

View File

@ -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

View File

@ -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;
}

View File

@ -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 );
}
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
/*
==============================================================

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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" );

View File

@ -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 );
}
/*

View File

@ -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;
}
/*

View File

@ -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 );

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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 );

View File

@ -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

View File

@ -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 );

View File

@ -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;

View File

@ -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 );

View File

@ -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();

View File

@ -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 ));

View File

@ -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 );
}
/*

View File

@ -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 );

View File

@ -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();
}

View File

@ -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

View File

@ -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;