18 Jan 2008

This commit is contained in:
g-cont 2008-01-18 00:00:00 +03:00 committed by Alibek Omarov
parent a5ca5ac292
commit b3fa6d6dbd
25 changed files with 585 additions and 458 deletions

View File

@ -12,7 +12,6 @@ fopen
// замеченные баги
1. viewer ничего не пишет в лог (сцуко)
2. Модели не рисуются для неотвизеных карт (даже самых мелких)
// из неоконченного
0. Приделать бы всем утилитам разные иконки
@ -35,7 +34,8 @@ physic.dll
12.Подключить его к серверу и клиенту OK
13.Билдер коллижн мешей для бсп-моделей OK
14.Переписать трасинг OK
15.Доделать трасинг
15.Доделать трасинг OK
16.Переписать pmove
}
Создание sdk_main

View File

@ -106,7 +106,7 @@ void CL_ClipMoveToEntities ( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end,
}
if( tr->allsolid ) return;
trace = pe->TransformedBoxTrace( start, end, mins, maxs, MASK_PLAYERSOLID, ent->origin, angles );
trace = pe->TransformedBoxTrace( start, end, mins, maxs, cmodel, MASK_PLAYERSOLID, ent->origin, angles );
if( trace.allsolid || trace.startsolid || trace.fraction < tr->fraction )
{
@ -133,7 +133,7 @@ trace_t CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
trace_t t;
// check against world
t = pe->BoxTrace( start, end, mins, maxs, MASK_PLAYERSOLID );
t = pe->BoxTrace( start, end, mins, maxs, NULL, MASK_PLAYERSOLID );
if (t.fraction < 1.0) t.ent = (edict_t *)1;
// check all other solid models
@ -142,15 +142,15 @@ trace_t CL_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
return t;
}
int CL_PMpointcontents (vec3_t point)
int CL_PMpointcontents( vec3_t point )
{
int i;
int i;
entity_state_t *ent;
int num;
int num;
cmodel_t *cmodel;
int contents;
int contents;
contents = pe->PointContents( point );
contents = pe->PointContents( point, NULL );
for( i = 0; i < cl.frame.num_entities; i++ )
{
@ -163,7 +163,7 @@ int CL_PMpointcontents (vec3_t point)
cmodel = cl.model_clip[ent->modelindex];
if (!cmodel) continue;
contents |= pe->TransformedPointContents( point, ent->origin, ent->angles );
contents |= pe->TransformedPointContents( point, cmodel, ent->origin, ent->angles );
}
return contents;
}

View File

@ -30,19 +30,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct
{
vec3_t origin; // full float precision
vec3_t velocity; // full float precision
vec3_t origin;
vec3_t velocity;
vec3_t previous_origin;
vec3_t previous_velocity;
int previous_waterlevel;
vec3_t forward, right, up;
float frametime;
int msec;
bool walking;
bool onladder;
trace_t groundtrace;
float impact_speed;
csurface_t *groundsurface;
cplane_t groundplane;
int groundcontents;
vec3_t previous_origin;
bool ladder;
} pml_t;
pmove_t *pm;
@ -81,14 +88,15 @@ void PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
float change;
int i;
backoff = DotProduct (in, normal) * overbounce;
backoff = DotProduct (in, normal);
for (i=0 ; i<3 ; i++)
if( backoff < 0 ) backoff *= overbounce;
else backoff /= overbounce;
for( i = 0; i < 3; i++ )
{
change = normal[i]*backoff;
out[i] = in[i] - change;
if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
out[i] = 0;
}
}
@ -286,48 +294,47 @@ Handles both ground friction and water friction
==================
*/
void PM_Friction (void)
void PM_Friction( void )
{
vec3_t vec;
float *vel;
float speed, newspeed, control;
float friction;
float drop;
vel = pml.velocity;
speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1] + vel[2]*vel[2]);
if (speed < 1)
VectorCopy( vel, vec );
if( pml.walking ) vec[2] = 0; // ignore slope movement
speed = VectorLength( vec );
Msg("speed %g\n", speed );
if( speed < 1 )
{
vel[0] = 0;
vel[1] = 0;
vel[0] = vel[1] = 0; // allow sinking underwater
// FIXME: still have z friction underwater?
return;
}
drop = 0;
// apply ground friction
if ((pm->groundentity && pml.groundsurface && !(pml.groundsurface->flags & SURF_SLICK) ) || (pml.ladder) )
if( pm->waterlevel <= 1 )
{
friction = pm_friction;
control = speed < pm_stopspeed ? pm_stopspeed : speed;
drop += control*friction*pml.frametime;
if( pml.walking && !(pml.groundtrace.flags & SURF_SLICK) || (pml.onladder))
{
control = speed < pm_stopspeed ? pm_stopspeed : speed;
drop += control * pm_friction * pml.frametime;
}
}
// apply water friction
if (pm->waterlevel && !pml.ladder)
drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime;
if( pm->waterlevel && !pml.onladder ) drop += speed * pm_waterfriction * pm->waterlevel * pml.frametime;
// scale the velocity
newspeed = speed - drop;
if (newspeed < 0)
{
newspeed = 0;
}
if (newspeed < 0) newspeed = 0;
newspeed /= speed;
vel[0] = vel[0] * newspeed;
vel[1] = vel[1] * newspeed;
vel[2] = vel[2] * newspeed;
VectorScale( vel, newspeed, vel );
}
@ -340,19 +347,17 @@ Handles user intended acceleration
*/
void PM_Accelerate (vec3_t wishdir, float wishspeed, float accel)
{
int i;
float addspeed, accelspeed, currentspeed;
int i;
float addspeed, accelspeed, currentspeed;
currentspeed = DotProduct (pml.velocity, wishdir);
addspeed = wishspeed - currentspeed;
if (addspeed <= 0)
return;
accelspeed = accel*pml.frametime*wishspeed;
if (accelspeed > addspeed)
accelspeed = addspeed;
if( addspeed <= 0 ) return;
accelspeed = accel * pml.frametime * wishspeed;
if( accelspeed > addspeed ) accelspeed = addspeed;
for (i=0 ; i<3 ; i++)
pml.velocity[i] += accelspeed*wishdir[i];
for( i = 0; i < 3; i++ )
pml.velocity[i] += accelspeed * wishdir[i];
}
void PM_AirAccelerate (vec3_t wishdir, float wishspeed, float accel)
@ -384,8 +389,8 @@ void PM_AddCurrents (vec3_t wishvel)
vec3_t v;
float s;
// account for ladders
if (pml.ladder && fabs(pml.velocity[2]) <= 200)
// account for onladders
if (pml.onladder && fabs(pml.velocity[2]) <= 200)
{
if ((pm->viewangles[PITCH] <= -15) && (pm->cmd.forwardmove > 0))
wishvel[2] = 200;
@ -397,7 +402,7 @@ void PM_AddCurrents (vec3_t wishvel)
wishvel[2] = -200;
else wishvel[2] = 0;
// limit horizontal speed when on a ladder
// limit horizontal speed when on a onladder
if (wishvel[0] < -25)
wishvel[0] = -25;
else if (wishvel[0] > 25)
@ -539,7 +544,7 @@ void PM_AirMove (void)
wishspeed = maxspeed;
}
if ( pml.ladder )
if ( pml.onladder )
{
PM_Accelerate (wishdir, wishspeed, pm_accelerate);
if (!wishvel[2])
@ -612,6 +617,7 @@ void PM_CatagorizePosition (void)
else
{
trace = pm->trace (pml.origin, pm->mins, pm->maxs, point);
groundtrace = trace;
pml.groundplane = trace.plane;
pml.groundsurface = trace.surface;
pml.groundcontents = trace.contents;
@ -747,9 +753,9 @@ void PM_CheckSpecialMovement (void)
if (pm->s.pm_time) return;
pml.ladder = false;
pml.onladder = false;
// check for ladder
// check for onladder
flatforward[0] = pml.forward[0];
flatforward[1] = pml.forward[1];
flatforward[2] = 0;
@ -758,7 +764,7 @@ void PM_CheckSpecialMovement (void)
VectorMA (pml.origin, 1, flatforward, spot);
trace = pm->trace (pml.origin, pm->mins, pm->maxs, spot);
if ((trace.fraction < 1) && (trace.contents & CONTENTS_LADDER))
pml.ladder = true;
pml.onladder = true;
// check for water jump
if (pm->waterlevel != 2) return;
@ -964,6 +970,7 @@ bool PM_GoodPosition (void)
for (i = 0; i < 3; i++) origin[i] = end[i] = pm->s.origin[i] * CL_COORD_FRAC;
trace = pm->trace (origin, pm->mins, pm->maxs, end);
pml.groundtrace = trace;
return !trace.allsolid;
}

View File

@ -50,7 +50,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define FL_WORLDBRUSH (1<<3) // Not moveable/removeable brush entity
#define FL_DORMANT (1<<4) // Entity is dormant, no updates to client
#define FL_FRAMETHINK (1<<5) // entity will be thinking every frame
#define FL_GRAPHED (1<<6) // worldgraph has this ent listed as something that blocks a connection
#define FL_GRAPHED (1<<6) // worldgraph has this ent listed as something that blocks a conection
#define FL_FLOAT (1<<7) // this entity can be floating. FIXME: remove this ?
#define FL_TRACKTRAIN (1<<8) // old stuff...
@ -299,7 +299,8 @@ void SV_ExecuteClientMessage (client_state_t *cl);
//
// sv_ccmds.c
//
void SV_Status_f (void);
void SV_Status_f( void );
void SV_SectorList_f( void );
//
// sv_ents.c
@ -375,7 +376,7 @@ void SV_LinkEdict (edict_t *ent);
// sets ent->leafnums[] for pvs determination even if the entity
// is not solid
int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype);
int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount );
// fills in a table of edict pointers with edicts that have bounding boxes
// that intersect the given area. It is possible for a non-axial bmodel
// to be returned that doesn't actually intersect the area on an exact
@ -388,13 +389,13 @@ int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int a
//
// functions that interact with everything apropriate
//
int SV_PointContents (vec3_t p);
int SV_PointContents( const vec3_t p, edict_t *passedict );
// returns the CONTENTS_* value from the world at the given point.
// Quake 2 extends this to also check entities, to allow moving liquids
trace_t SV_ClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int contentsmask );
trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask);
trace_t SV_Trace( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, edict_t *passedict, int contentmask );
trace_t SV_TraceToss (edict_t *tossent, edict_t *ignore);
// mins and maxs are relative

View File

@ -515,6 +515,7 @@ void SV_InitOperatorCommands( void )
Cmd_AddCommand("movie", SV_Movie_f, "playing video file" );
Cmd_AddCommand("changelevel", SV_ChangeLevel_f, "changing level" );
Cmd_AddCommand("restart", SV_Restart_f, "restarting current level" );
Cmd_AddCommand("sectorlist", SV_SectorList_f, "display pvs sectors" );
if( dedicated->value )
{
@ -540,6 +541,7 @@ void SV_KillOperatorCommands( void )
Cmd_RemoveCommand("movie");
Cmd_RemoveCommand("changelevel");
Cmd_RemoveCommand("restart");
Cmd_RemoveCommand("sectorlist");
if( dedicated->value )
{

View File

@ -30,6 +30,14 @@ typedef struct link_s
int entnum; // get edict by number
} link_t;
typedef struct worldsector_s
{
int axis; // -1 = leaf node
float dist;
struct worldsector_s *children[2];
sv_edict_t *entities;
} worldsector_t;
struct gclient_s
{
player_state_t ps; // communicated by server to clients
@ -51,13 +59,16 @@ struct sv_edict_s
float freetime; // sv.time when the object was freed
// sv_private_edict_t
worldsector_t *worldsector; // member of current wolrdsector
struct sv_edict_s *nextedict; // next edict in world sector
link_t area; // linked to a division node or leaf
int clipmask; // trace info
int headnode; // unused if num_clusters != -1
int lastcluster; // unused if num_clusters != -1
int linkcount;
int num_clusters; // if -1, use headnode instead
int clusternums[MAX_ENT_CLUSTERS];
int areanum, areanum2;
int serialnumber; // unical entity #id
int solid; // see entity_state_t for details
int event; // apply sv.events too

View File

@ -92,8 +92,7 @@ void SV_EmitPacketEntities (client_frame_t *from, client_frame_t *to, sizebuf_t
newnum = newent->number;
}
if (oldindex >= from_num_entities)
oldnum = 9999;
if (oldindex >= from_num_entities) oldnum = 9999;
else
{
oldent = &svs.client_entities[(from->first_entity+oldindex)%svs.num_client_entities];
@ -409,6 +408,7 @@ void SV_BuildClientFrame (client_state_t *client)
int clientarea, clientcluster;
int leafnum;
int c_fullsend;
byte *clientpvs;
byte *clientphs;
byte *bitvector;
@ -434,8 +434,8 @@ void SV_BuildClientFrame (client_state_t *client)
// grab the current player_state_t
frame->ps = clent->priv.sv->client->ps;
SV_FatPVS (org);
clientphs = pe->ClusterPHS (clientcluster);
clientpvs = pe->ClusterPVS( clientcluster );
clientphs = pe->ClusterPHS( clientcluster );
// build up the list of visible entities
frame->num_entities = 0;
@ -474,14 +474,11 @@ void SV_BuildClientFrame (client_state_t *client)
{
// FIXME: if an ent has a model and a sound, but isn't
// in the PVS, only the PHS, clear the model
if (ent->progs.sv->noise3)
{
bitvector = fatpvs; //clientphs;
}
else bitvector = fatpvs;
if (ent->progs.sv->noise3) bitvector = clientphs;
else bitvector = clientpvs;
// check individual leafs
/*if( !ent->priv.sv->num_clusters )
if( !ent->priv.sv->num_clusters )
{
continue;
}
@ -495,38 +492,18 @@ void SV_BuildClientFrame (client_state_t *client)
// check overflow clusters that coudln't be stored
if( i == ent->priv.sv->num_clusters )
{
if( svEnt->lastCluster )
if( ent->priv.sv->lastcluster )
{
for( ; l <= svEnt->lastCluster; l++ )
for( ; l <= ent->priv.sv->lastcluster; l++ )
{
if( bitvector[l>>3] & (1<<(l&7)))
break;
}
if ( l == svEnt->lastCluster )
if( l == ent->priv.sv->lastcluster )
continue; // not visible
}
else continue;
}*/
if (ent->priv.sv->num_clusters == -1)
{
// too many leafs for individual check, go by headnode
//if(!pe->HeadnodeVisible (ent->priv.sv->headnode, bitvector))
// continue;
c_fullsend++;
}
else
{ // check individual leafs
for (i=0 ; i < ent->priv.sv->num_clusters ; i++)
{
l = ent->priv.sv->clusternums[i];
if (bitvector[l >> 3] & (1 << (l&7) ))
break;
}
if (i == ent->priv.sv->num_clusters)
continue; // not visible
}
if (!ent->progs.sv->modelindex)
{
// don't send sounds if they will be attenuated away

View File

@ -194,7 +194,7 @@ void SV_SpawnServer (char *server, char *savename, sv_state_t serverstate )
if (serverstate != ss_game)
{
sv.models[1] = pe->BeginRegistration("", false, &checksum); // no real map
sv.models[1] = pe->BeginRegistration( "", false, &checksum); // no real map
}
else
{

View File

@ -85,7 +85,7 @@ bool SV_CheckBottom (edict_t *ent)
{
start[0] = x ? maxs[0] : mins[0];
start[1] = y ? maxs[1] : mins[1];
if (SV_PointContents(start) != CONTENTS_SOLID)
if (SV_PointContents(start, ent ) != CONTENTS_SOLID)
goto realcheck;
}
}
@ -224,7 +224,7 @@ void SV_Impact (edict_t *e1, trace_t *trace)
prog->globals.sv->trace_plane_dist = trace->plane.dist;
if (trace->ent) prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(trace->ent);
else prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing");
PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing\n");
}
if (!e1->priv.sv->free && !e2->priv.sv->free && e2->progs.sv->touch && e2->progs.sv->solid != SOLID_NOT)
{
@ -239,7 +239,7 @@ void SV_Impact (edict_t *e1, trace_t *trace)
VectorSet (prog->globals.sv->trace_plane_normal, 0, 0, 1);
prog->globals.sv->trace_plane_dist = 0;
prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(e1);
PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing");
PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing\n");
}
PRVM_POP_GLOBALS;
@ -381,17 +381,17 @@ bool SV_CheckWater (edict_t *ent)
ent->progs.sv->waterlevel = 0;
ent->progs.sv->watertype = CONTENTS_NONE;
cont = SV_PointContents(point);
cont = SV_PointContents( point, ent );
if (cont & (MASK_WATER))
{
ent->progs.sv->watertype = cont;
ent->progs.sv->waterlevel = 1;
point[2] = ent->progs.sv->origin[2] + (ent->progs.sv->mins[2] + ent->progs.sv->maxs[2])*0.5;
if (SV_PointContents(point) & (MASK_WATER))
if (SV_PointContents(point, ent ) & (MASK_WATER))
{
ent->progs.sv->waterlevel = 2;
point[2] = ent->progs.sv->origin[2] + ent->progs.sv->view_ofs[2];
if (SV_PointContents(point) & (MASK_WATER))
if (SV_PointContents(point, ent ) & (MASK_WATER))
ent->progs.sv->waterlevel = 3;
}
}
@ -640,7 +640,7 @@ bool SV_MoveStep (edict_t *ent, vec3_t move, bool relink)
if (trace.fraction == 1)
{
VectorCopy(trace.endpos, traceendpos);
if (((int)ent->progs.sv->aiflags & AI_SWIM) && !(SV_PointContents(traceendpos) & MASK_WATER))
if (((int)ent->progs.sv->aiflags & AI_SWIM) && !(SV_PointContents(traceendpos, ent ) & MASK_WATER))
return false; // swim monster left water
VectorCopy (traceendpos, ent->progs.sv->origin);
@ -1022,7 +1022,7 @@ SV_CheckWaterTransition
*/
void SV_CheckWaterTransition (edict_t *ent)
{
int cont = SV_PointContents(ent->progs.sv->origin);
int cont = SV_PointContents(ent->progs.sv->origin, ent );
if (!ent->progs.sv->watertype)
{

View File

@ -173,7 +173,7 @@ void SV_TouchTriggers (edict_t *ent)
if ((ent->priv.sv->client || ((int)ent->progs.sv->flags & FL_MONSTER)) && (ent->progs.sv->health <= 0))
return;
num = SV_AreaEdicts(ent->progs.sv->absmin, ent->progs.sv->absmax, touch, MAX_EDICTS, AREA_TRIGGERS);
num = SV_AreaEdicts(ent->progs.sv->absmin, ent->progs.sv->absmax, touch, MAX_EDICTS );
PRVM_PUSH_GLOBALS;

View File

@ -83,14 +83,14 @@ void SV_SetMinMaxSize (edict_t *e, float *min, float *max, bool rotate)
PRVM_ERROR("SV_SetMinMaxSize: backwards mins/maxs");
// set derived values
if( rotate && e->progs.sv->solid == SOLID_BBOX)
if( rotate && e->progs.sv->solid == SOLID_BBOX )
{
SV_CalcBBox( e, min, max );
}
else
{
VectorCopy (min, e->progs.sv->mins);
VectorCopy (max, e->progs.sv->maxs);
VectorCopy( min, e->progs.sv->mins);
VectorCopy( max, e->progs.sv->maxs);
}
VectorSubtract (max, min, e->progs.sv->size );
@ -684,7 +684,7 @@ PF_pointcontents
*/
void PF_pointcontents (void)
{
PRVM_G_FLOAT(OFS_RETURN) = SV_PointContents(PRVM_G_VECTOR(OFS_PARM0));
PRVM_G_FLOAT(OFS_RETURN) = SV_PointContents(PRVM_G_VECTOR(OFS_PARM0), NULL );
}
/*

View File

@ -25,94 +25,86 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/*
===============================================================================
ENTITY AREA CHECKING
ENTITY CHECKING
FIXME: this use of "area" is different from the bsp file use
To avoid linearly searching through lists of entities during environment testing,
the world is carved up with an evenly spaced, axially aligned bsp tree. Entities
are kept in chains either at the final leafs, or at the first node that splits
them, which prevents having to deal with multiple fragments of a single entity.
===============================================================================
*/
#define EDICT_FROM_AREA(l) PRVM_EDICT_NUM(l->entnum)
typedef struct areanode_s
{
int axis; // -1 = leaf node
float dist;
struct areanode_s *children[2];
link_t trigger_edicts;
link_t solid_edicts;
} areanode_t;
#define AREA_DEPTH 4
#define AREA_NODES 32
#define AREA_NODES 64
#define MAX_TOTAL_ENT_LEAFS 128
areanode_t sv_areanodes[AREA_NODES];
int sv_numareanodes;
float *area_mins, *area_maxs;
edict_t **area_list;
int area_count, area_maxcount;
int area_type;
// ClearLink is used for new headnodes
void ClearLink (link_t *l)
typedef struct area_s
{
l->prev = l->next = l;
}
const float *mins;
const float *maxs;
edict_t **list;
int count;
int maxcount;
int type;
} area_t;
void RemoveLink (link_t *l)
{
l->next->prev = l->prev;
l->prev->next = l->next;
}
worldsector_t sv_worldsectors[AREA_NODES];
int sv_numworldsectors;
void InsertLinkBefore (link_t *l, link_t *before, edict_t *ent)
/*
===============
SV_SectorList_f
===============
*/
void SV_SectorList_f( void )
{
l->next = before;
l->prev = before->prev;
l->prev->next = l;
l->next->prev = l;
l->entnum = PRVM_NUM_FOR_EDICT(ent);
int i, c;
worldsector_t *sec;
sv_edict_t *ent;
for ( i = 0; i < sv_numworldsectors; i++ )
{
sec = &sv_worldsectors[i], c = 0;
for( ent = sec->entities; ent; ent = ent->nextedict ) c++;
if(c) Msg( "sector %i: %i entities\n", i, c );
}
}
/*
===============
SV_CreateAreaNode
SV_CreateworldSector
Builds a uniformly subdivided tree for the given world size
===============
*/
areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
worldsector_t *SV_CreateWorldSector( int depth, vec3_t mins, vec3_t maxs )
{
areanode_t *anode;
worldsector_t *anode;
vec3_t size;
vec3_t mins1, maxs1, mins2, maxs2;
anode = &sv_areanodes[sv_numareanodes];
sv_numareanodes++;
anode = &sv_worldsectors[sv_numworldsectors];
sv_numworldsectors++;
ClearLink (&anode->trigger_edicts);
ClearLink (&anode->solid_edicts);
if (depth == AREA_DEPTH)
if( depth == AREA_DEPTH )
{
anode->axis = -1;
anode->children[0] = anode->children[1] = NULL;
return anode;
}
VectorSubtract (maxs, mins, size);
if (size[0] > size[1]) anode->axis = 0;
VectorSubtract( maxs, mins, size );
if( size[0] > size[1] ) anode->axis = 0;
else anode->axis = 1;
anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
VectorCopy (mins, mins1);
VectorCopy (mins, mins2);
VectorCopy (maxs, maxs1);
VectorCopy (maxs, maxs2);
anode->dist = 0.5f * (maxs[anode->axis] + mins[anode->axis]);
VectorCopy(mins, mins1);
VectorCopy(mins, mins2);
VectorCopy(maxs, maxs1);
VectorCopy(maxs, maxs2);
maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
anode->children[0] = SV_CreateWorldSector( depth+1, mins2, maxs2);
anode->children[1] = SV_CreateWorldSector( depth+1, mins1, maxs1);
return anode;
}
@ -125,90 +117,103 @@ SV_ClearWorld
*/
void SV_ClearWorld (void)
{
memset (sv_areanodes, 0, sizeof(sv_areanodes));
sv_numareanodes = 0;
SV_CreateAreaNode (0, sv.models[1]->mins, sv.models[1]->maxs);
cmodel_t *world = sv.models[1];
memset( sv_worldsectors, 0, sizeof(sv_worldsectors));
sv_numworldsectors = 0;
SV_CreateWorldSector( 0, world->mins, world->maxs );
}
/*
===============
SV_UnlinkEdict
===============
*/
void SV_UnlinkEdict (edict_t *ent)
void SV_UnlinkEdict( edict_t *ent )
{
if (!ent->priv.sv->area.prev) return; // not linked in anywhere
RemoveLink (&ent->priv.sv->area);
ent->priv.sv->area.prev = ent->priv.sv->area.next = NULL;
}
sv_edict_t *sv_ent, *scan;
worldsector_t *ws;
sv_ent = ent->priv.sv;
ws = sv_ent->worldsector;
if( !ws ) return; // not linked in anywhere
sv_ent->worldsector = NULL;
//sv_ent->linked = false;
if( ws->entities == sv_ent )
{
ws->entities = sv_ent->nextedict;
return;
}
for( scan = ws->entities; scan; scan = scan->nextedict )
{
if( scan->nextedict == sv_ent )
{
scan->nextedict = sv_ent->nextedict;
return;
}
}
MsgWarn("SV_UnlinkEdict: not found in worldSector\n" );
}
/*
===============
SV_LinkEdict
SV_LinkEntity
===============
*/
#define MAX_TOTAL_ENT_LEAFS 128
void SV_LinkEdict (edict_t *ent)
void SV_LinkEdict( edict_t *ent )
{
areanode_t *node;
worldsector_t *node;
int leafs[MAX_TOTAL_ENT_LEAFS];
int clusters[MAX_TOTAL_ENT_LEAFS];
int cluster;
int num_leafs;
int i, j, k;
int area;
int topnode;
int lastleaf;
sv_edict_t *sv_ent;
if (ent->priv.sv->area.prev) SV_UnlinkEdict (ent); // unlink from old position
sv_ent = ent->priv.sv;
if( sv_ent->worldsector ) SV_UnlinkEdict( ent ); // unlink from old position
if (ent == prog->edicts) return; // don't add the world
if (ent->priv.sv->free) return;
// set the size
VectorSubtract (ent->progs.sv->maxs, ent->progs.sv->mins, ent->progs.sv->size);
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))
{
// assume that x/y are equal and symetric
i = ent->progs.sv->maxs[0]/SV_COORD_FRAC;
if (i<1) i = 1;
if (i>31) i = 31;
if( i < 1 ) i = 1;
if( i > 31) i = 31;
// z is not symetric
j = (-ent->progs.sv->mins[2])/SV_COORD_FRAC;
if (j < 1) j = 1;
if (j > 31) j = 31;
if( j < 1 ) j = 1;
if( j > 31) j = 31;
// and z maxs can be negative...
k = (ent->progs.sv->maxs[2]+32)/SV_COORD_FRAC;
if (k<1) k = 1;
if (k>63) k = 63;
ent->priv.sv->solid = (k<<10) | (j<<5) | i;
if( k < 1 ) k = 1;
if( k > 63) k = 63;
sv_ent->solid = (k<<10) | (j<<5) | i;
}
else if (ent->progs.sv->solid == SOLID_BSP)
{
ent->priv.sv->solid = 31; // a solid_bbox will never create this value
sv_ent->solid = 31; // a solid_bbox will never create this value
}
else ent->priv.sv->solid = 0;
else sv_ent->solid = 0;
// set the abs box
if (ent->progs.sv->solid == SOLID_BSP && !VectorIsNull(ent->progs.sv->angles))
{
// expand for rotation
float max = 0, v;
int i;
float max = RadiusFromBounds( ent->progs.sv->mins, ent->progs.sv->maxs );
for (i = 0; i<3 ; i++)
{
v =fabs( ent->progs.sv->mins[i]);
if (v > max) max = v;
v =fabs( ent->progs.sv->maxs[i]);
if (v > max) max = v;
}
for (i=0 ; i<3 ; i++)
for (i = 0; i < 3; i++)
{
ent->progs.sv->absmin[i] = ent->progs.sv->origin[i] - max;
ent->progs.sv->absmax[i] = ent->progs.sv->origin[i] + max;
@ -230,74 +235,69 @@ void SV_LinkEdict (edict_t *ent)
ent->progs.sv->absmax[2] += 1;
// link to PVS leafs
ent->priv.sv->num_clusters = 0;
ent->priv.sv->areanum = 0;
ent->priv.sv->areanum2 = 0;
sv_ent->num_clusters = 0;
sv_ent->lastcluster = 0;
sv_ent->areanum = 0;
sv_ent->areanum2 = 0;
//get all leafs, including solids
num_leafs = pe->BoxLeafnums (ent->progs.sv->absmin, ent->progs.sv->absmax, leafs, MAX_TOTAL_ENT_LEAFS, &topnode);
// get all leafs, including solids
num_leafs = pe->BoxLeafnums( ent->progs.sv->absmin, ent->progs.sv->absmax, leafs, MAX_TOTAL_ENT_LEAFS, &lastleaf );
// set areas
for (i = 0; i < num_leafs; i++)
// if none of the leafs were inside the map, the
// entity is outside the world and can be considered unlinked
if( !num_leafs ) return;
// set areas, even from clusters that don't fit in the entity array
for( i = 0; i < num_leafs; i++ )
{
clusters[i] = pe->LeafCluster (leafs[i]);
area = pe->LeafArea (leafs[i]);
if (area)
{ // doors may legally straggle two areas,
area = pe->LeafArea( leafs[i] );
if( area )
{
// 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)
MsgWarn("SV_LinkEdict: object touching 3 areas at %f %f %f\n", ent->progs.sv->absmin[0], ent->progs.sv->absmin[1], ent->progs.sv->absmin[2]);
if (ent->priv.sv->areanum2 && ent->priv.sv->areanum2 != area && sv.state == ss_loading )
{
float *v = ent->progs.sv->absmin;
MsgWarn("SV_LinkEdict: object touching 3 areas at %f %f %f\n", v[0], v[1], v[2]);
}
ent->priv.sv->areanum2 = area;
}
else ent->priv.sv->areanum = area;
}
}
if (num_leafs >= MAX_TOTAL_ENT_LEAFS)
// store as many explicit clusters as we can
sv_ent->num_clusters = 0;
for (i = 0; i < num_leafs; i++)
{
// assume we missed some leafs, and mark by headnode
ent->priv.sv->num_clusters = -1;
ent->priv.sv->headnode = topnode;
}
else
{
ent->priv.sv->num_clusters = 0;
for (i = 0; i < num_leafs; i++)
cluster = pe->LeafCluster( leafs[i] );
if( cluster )
{
if (clusters[i] == -1) continue; // not a visible leaf
for (j = 0; j < i; j++)
{
if (clusters[j] == clusters[i]) break;
}
if (j == i)
{
if (ent->priv.sv->num_clusters == MAX_ENT_CLUSTERS)
{
// assume we missed some leafs, and mark by headnode
ent->priv.sv->num_clusters = -1;
ent->priv.sv->headnode = topnode;
break;
}
ent->priv.sv->clusternums[ent->priv.sv->num_clusters++] = clusters[i];
}
sv_ent->clusternums[sv_ent->num_clusters++] = cluster;
if( sv_ent->num_clusters == MAX_ENT_CLUSTERS )
break; // list is full
}
}
// store off a last cluster if we need to
if( i != num_leafs ) sv_ent->lastcluster = pe->LeafCluster( lastleaf );
// if first time, make sure old_origin is valid
if (!ent->priv.sv->linkcount)
if(!ent->priv.sv->linkcount)
{
VectorCopy (ent->progs.sv->origin, ent->progs.sv->old_origin);
}
ent->priv.sv->linkcount++;
// don't link not solid or rigid bodies
if (ent->progs.sv->solid == SOLID_NOT || ent->progs.sv->solid >= SOLID_BOX)
return;
// find the first node that the ent's box crosses
node = sv_areanodes;
while (1)
// find the first world sector node that the ent's box crosses
node = sv_worldsectors;
while( 1 )
{
if (node->axis == -1) break;
if (ent->progs.sv->absmin[node->axis] > node->dist)
@ -307,57 +307,57 @@ void SV_LinkEdict (edict_t *ent)
else break; // crosses the node
}
// link it in
if (ent->progs.sv->solid == SOLID_TRIGGER) InsertLinkBefore (&ent->priv.sv->area, &node->trigger_edicts, ent );
else InsertLinkBefore (&ent->priv.sv->area, &node->solid_edicts, ent );
// link it in
sv_ent->worldsector = node;
sv_ent->nextedict = node->entities;
node->entities = sv_ent;
//sv_ent->linked = true;
}
/*
============================================================================
AREA QUERY
Fills in a list of all entities who's absmin / absmax intersects the given
bounds. This does NOT mean that they actually touch in the case of bmodels.
============================================================================
*/
/*
====================
SV_AreaEdicts_r
====================
*/
void SV_AreaEdicts_r (areanode_t *node)
void SV_AreaEdicts_r( worldsector_t *node, area_t *ap )
{
link_t *l, *next, *start;
edict_t *check;
sv_edict_t *check, *next;
edict_t *gcheck;
int count = 0;
// touch linked edicts
if (area_type == AREA_SOLID)
start = &node->solid_edicts;
else start = &node->trigger_edicts;
for (l = start->next; l != start; l = next)
for( check = node->entities; check; check = next )
{
next = l->next;
check = EDICT_FROM_AREA(l);
next = check->nextedict;
gcheck = PRVM_EDICT_NUM( check->serialnumber );
if (check->progs.sv->solid == SOLID_NOT) continue; // deactivated
if (check->progs.sv->absmin[0] > area_maxs[0] || check->progs.sv->absmin[1] > area_maxs[1] || check->progs.sv->absmin[2] > area_maxs[2]
|| check->progs.sv->absmax[0] < area_mins[0] || check->progs.sv->absmax[1] < area_mins[1] || check->progs.sv->absmax[2] < area_mins[2])
if (gcheck->progs.sv->absmin[0] > ap->maxs[0] || gcheck->progs.sv->absmin[1] > ap->maxs[1] || gcheck->progs.sv->absmin[2] > ap->maxs[2]
|| gcheck->progs.sv->absmax[0] < ap->mins[0] || gcheck->progs.sv->absmax[1] < ap->mins[1] || gcheck->progs.sv->absmax[2] < ap->mins[2])
continue; // not touching
if (area_count == area_maxcount)
if( ap->count == ap->maxcount )
{
MsgWarn("SV_AreaEdicts: maxcount\n");
MsgDev(D_NOTE, "SV_AreaEdicts_r: maxcount!\n");
return;
}
area_list[area_count] = check;
area_count++;
ap->list[ap->count] = PRVM_EDICT_NUM( check->serialnumber );
ap->count++;
}
if (node->axis == -1) return; // terminal node
if( node->axis == -1 ) return; // terminal node
// recurse down both sides
if ( area_maxs[node->axis] > node->dist )
SV_AreaEdicts_r ( node->children[0] );
if ( area_mins[node->axis] < node->dist )
SV_AreaEdicts_r ( node->children[1] );
if( ap->maxs[node->axis] > node->dist ) SV_AreaEdicts_r ( node->children[0], ap );
if( ap->mins[node->axis] < node->dist ) SV_AreaEdicts_r ( node->children[1], ap );
}
/*
@ -365,92 +365,56 @@ void SV_AreaEdicts_r (areanode_t *node)
SV_AreaEdicts
================
*/
int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype)
int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount )
{
area_mins = mins;
area_maxs = maxs;
area_list = list;
area_count = 0;
area_maxcount = maxcount;
area_type = areatype;
area_t ap;
SV_AreaEdicts_r (sv_areanodes);
ap.mins = mins;
ap.maxs = maxs;
ap.list = list;
ap.count = 0;
ap.maxcount = maxcount;
return area_count;
SV_AreaEdicts_r( sv_worldsectors, &ap );
return ap.count;
}
//===========================================================================
/*
=============
SV_PointContents
=============
*/
int SV_PointContents( vec3_t p )
{
edict_t *touch[MAX_EDICTS], *hit;
int i, num;
int contents, c2;
float *angles;
// get base contents from world
contents = pe->PointContents( p );
// or in contents from all the other entities
num = SV_AreaEdicts (p, p, touch, MAX_EDICTS, AREA_SOLID);
for (i = 0; i < num; i++)
{
hit = touch[i];
// might intersect, so do an exact clip
angles = hit->progs.sv->angles;
if (hit->progs.sv->solid != SOLID_BSP) angles = vec3_origin; // boxes don't rotate
c2 = pe->TransformedPointContents( p, hit->progs.sv->origin, hit->progs.sv->angles );
contents |= c2;
}
return contents;
}
typedef struct
{
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
float *mins, *maxs; // size of the moving object
vec3_t mins2, maxs2; // size when clipping against mosnters
float *start, *end;
const float *mins, *maxs;
const float *start;
vec3_t end;
trace_t trace;
edict_t *passedict;
int contentmask;
} moveclip_t;
/*
====================
SV_ClipMoveToEntities
====================
*/
void SV_ClipMoveToEntities ( moveclip_t *clip )
void SV_ClipMoveToEntities( moveclip_t *clip )
{
int i, num;
edict_t *touchlist[MAX_EDICTS], *touch;
trace_t trace;
float *angles;
cmodel_t *cmodel;
float *origin, *angles;
num = SV_AreaEdicts (clip->boxmins, clip->boxmaxs, touchlist, MAX_EDICTS, AREA_SOLID);
num = SV_AreaEdicts( clip->boxmins, clip->boxmaxs, touchlist, MAX_EDICTS );
// be careful, it is possible to have an entity in this
// list removed before we get to it (killtriggered)
for (i = 0; i < num; i++)
for( i = 0; i < num; i++ )
{
if( clip->trace.allsolid ) return;
touch = touchlist[i];
if (touch->progs.sv->solid == SOLID_NOT) continue;
if (touch == clip->passedict) continue;
if (clip->trace.allsolid) return;
if (clip->passedict)
if( touch == clip->passedict ) continue;
if( touch->progs.sv->solid == SOLID_NOT ) continue;
if( clip->passedict )
{
if (PRVM_PROG_TO_EDICT(touch->progs.sv->owner) == clip->passedict)
continue; // don't clip against own missiles
@ -458,56 +422,37 @@ void SV_ClipMoveToEntities ( moveclip_t *clip )
continue; // don't clip against owner
}
if ( !(clip->contentmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
if(!(clip->contentmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
continue;
// might intersect, so do an exact clip
cmodel = SV_GetModelPtr( touch );
origin = touch->progs.sv->origin;
angles = touch->progs.sv->angles;
if (touch->progs.sv->solid != SOLID_BSP) angles = vec3_origin; // boxes don't rotate
if ((int)touch->progs.sv->flags & FL_MONSTER)
{
trace = pe->TransformedBoxTrace (clip->start, clip->end, clip->mins2, clip->maxs2, clip->contentmask, touch->progs.sv->origin, angles);
}
else
{
trace = pe->TransformedBoxTrace (clip->start, clip->end, clip->mins, clip->maxs, clip->contentmask, touch->progs.sv->origin, angles);
}
if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction)
if( !touch->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
trace = pe->TransformedBoxTrace((float *)clip->start, (float *)clip->end, (float *)clip->mins, (float *)clip->maxs, cmodel, clip->contentmask, origin, angles );
if( trace.allsolid )
{
clip->trace.allsolid = true;
trace.ent = touch;
if (clip->trace.startsolid)
{
clip->trace = trace;
clip->trace.startsolid = true;
}
else clip->trace = trace;
}
else if (trace.startsolid) clip->trace.startsolid = true;
}
}
/*
==================
SV_TraceBounds
==================
*/
void SV_TraceBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
{
int i;
for (i = 0; i < 3; i++)
{
if (end[i] > start[i])
}
else if( trace.startsolid )
{
boxmins[i] = start[i] + mins[i] - 1;
boxmaxs[i] = end[i] + maxs[i] + 1;
clip->trace.startsolid = true;
trace.ent = touch;
}
else
if( trace.fraction < clip->trace.fraction )
{
boxmins[i] = end[i] + mins[i] - 1;
boxmaxs[i] = start[i] + maxs[i] + 1;
bool oldStart;
// make sure we keep a startsolid from a previous trace
oldStart = clip->trace.startsolid;
trace.ent = touch;
clip->trace = trace;
clip->trace.startsolid |= oldStart;
}
}
}
@ -517,40 +462,50 @@ void SV_TraceBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t
SV_Trace
Moves the given mins/maxs volume through the world from start to end.
Passedict and edicts owned by passedict are explicitly not checked.
passEntityNum and entities owned by passEntityNum are explicitly not checked.
==================
*/
trace_t SV_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask)
trace_t SV_Trace( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, edict_t *passedict, int contentmask )
{
moveclip_t clip;
int i;
if (!mins) mins = vec3_origin;
if (!maxs) maxs = vec3_origin;
memset ( &clip, 0, sizeof ( moveclip_t ) );
if( !mins ) mins = vec3_origin;
if( !maxs ) maxs = vec3_origin;
memset( &clip, 0, sizeof( moveclip_t ));
// clip to world
clip.trace = pe->BoxTrace( start, end, mins, maxs, contentmask );
clip.trace.ent = prog->edicts;
if (clip.trace.fraction == 0) return clip.trace; // blocked by the world
clip.trace = pe->BoxTrace( start, end, mins, maxs, NULL, contentmask );
clip.trace.ent = clip.trace.fraction != 1.0 ? prog->edicts : NULL;
if( clip.trace.fraction == 0 ) return clip.trace; // blocked immediately by the world
clip.contentmask = contentmask;
clip.start = start;
clip.end = end;
VectorCopy( end, clip.end );
clip.mins = mins;
clip.maxs = maxs;
clip.passedict = passedict;
VectorCopy (mins, clip.mins2);
VectorCopy (maxs, clip.maxs2);
// create the bounding box of the entire move
SV_TraceBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
// we can limit it to the part of the move not
// already clipped off by the world, which can be
// a significant savings for line of sight and shot traces
for( i = 0; i < 3; i++ )
{
if( end[i] > start[i] )
{
clip.boxmins[i] = clip.start[i] + clip.mins[i] - 1;
clip.boxmaxs[i] = clip.end[i] + clip.maxs[i] + 1;
}
else
{
clip.boxmins[i] = clip.end[i] + clip.mins[i] - 1;
clip.boxmaxs[i] = clip.start[i] + clip.maxs[i] + 1;
}
}
// clip to other solid entities
SV_ClipMoveToEntities ( &clip );
SV_ClipMoveToEntities( &clip );
return clip.trace;
}
@ -595,5 +550,63 @@ trace_t SV_TraceToss (edict_t *tossent, edict_t *ignore)
trace_t SV_ClipMoveToEntity(edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int contentsmask)
{
return pe->BoxTrace(start, end, mins, maxs, contentsmask);
edict_t *touch;
cmodel_t *cmodel;
float *origin, *angles;
trace_t trace;
touch = ent;
memset( &trace, 0, sizeof(trace_t));
// if it doesn't have any brushes of a type we
// are looking for, ignore it
if(!(contentsmask & CONTENTS_DEADMONSTER) && ((int)touch->progs.sv->flags & FL_DEADMONSTER))
{
trace.fraction = 1.0;
return trace;
}
// might intersect, so do an exact clip
cmodel = SV_GetModelPtr( touch );
origin = touch->progs.sv->origin;
angles = touch->progs.sv->angles;
if( !touch->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
trace = pe->TransformedBoxTrace( start, end, mins, maxs, cmodel, contentsmask, origin, angles );
if( trace.fraction < 1 ) trace.ent = touch;
return trace;
}
/*
=============
SV_PointContents
=============
*/
int SV_PointContents( const vec3_t p, edict_t *passedict )
{
edict_t *touch[MAX_EDICTS], *hit;
int i, num;
int contents, c2;
cmodel_t *cmodel;
float *angles;
// get base contents from world
contents = pe->PointContents( p, NULL );
// or in contents from all the other entities
num = SV_AreaEdicts( p, p, touch, MAX_EDICTS );
for( i = 0; i < num; i++ )
{
if ( touch[i] == passedict ) continue;
hit = touch[i];
// might intersect, so do an exact clip
cmodel = SV_GetModelPtr( hit );
angles = hit->progs.sv->angles;
if( !hit->progs.sv->solid == SOLID_BSP ) angles = vec3_origin; // boxes don't rotate
c2 = pe->TransformedPointContents( p, cmodel, hit->progs.sv->origin, angles );
contents |= c2;
}
return contents;
}

View File

@ -7,6 +7,8 @@
#include "physic.h"
#define BOX_MODEL_HANDLE MAX_MODELS - 1
typedef struct
{
cplane_t *plane;
@ -19,15 +21,6 @@ typedef struct
csurface_t *surface;
} cbrushside_t;
typedef struct
{
int contents;
int cluster;
int area;
int firstleafbrush;
int numleafbrushes;
} cleaf_t;
typedef struct
{
int contents;
@ -138,6 +131,7 @@ typedef struct box_s
{
cplane_t *planes;
cbrush_t *brush;
cmodel_t model;
} box_t;
typedef struct mapleaf_s
@ -171,6 +165,7 @@ typedef struct tracework_s
float maxOffset; // longest corner length from origin
vec3_t bounds[2]; // enclosing box of start and end surrounding by size
vec3_t extents; // greatest of abs(size[0]) and abs(size[1])
vec3_t origin;
int contents;
bool ispoint; // optimized case
trace_t result; // returned from trace call

View File

@ -59,6 +59,25 @@ void CM_GetPoint2( int index, vec3_t out )
CM_ConvertDimensionToMeters( out, cm.vertices[vert_index].point );
}
/*
=================
CM_BoundBrush
=================
*/
void CM_BoundBrush( cbrush_t *b )
{
cbrushside_t *sides;
sides = &cm.brushsides[b->firstbrushside];
b->bounds[0][0] = -sides[0].plane->dist;
b->bounds[1][0] = sides[1].plane->dist;
b->bounds[0][1] = -sides[2].plane->dist;
b->bounds[1][1] = sides[3].plane->dist;
b->bounds[0][2] = -sides[4].plane->dist;
b->bounds[1][2] = sides[5].plane->dist;
}
int CM_NumTexinfo( void ) { return cm.numtexinfo; }
int CM_NumClusters( void ) { return cm.numclusters; }
@ -231,6 +250,7 @@ void BSP_LoadBrushes( lump_t *l )
out->firstbrushside = LittleLong(in->firstside);
out->numsides = LittleLong(in->numsides);
out->contents = LittleLong(in->contents);
CM_BoundBrush( out );
}
}
@ -563,6 +583,19 @@ void BSP_LoadStringData( lump_t *l )
Mem_Copy( cm.stringdata, cm.mod_base + l->fileofs, l->filelen );
}
/*
=================
BSP_LoadStringData
=================
*/
void BSP_LoadBuiltinProgs( lump_t *l )
{
if(!l->filelen)
{
return;
}
}
/*
=================
BSP_LoadStringTable
@ -660,8 +693,8 @@ void CM_LoadBSP( const void *buffer )
BSP_LoadSurfedges(&header.lumps[LUMP_SURFEDGES]);
BSP_LoadFaces(&header.lumps[LUMP_FACES]);
BSP_LoadSurfDesc(&header.lumps[LUMP_SURFDESC]);
BSP_LoadCollision(&header.lumps[LUMP_COLLISION]);
BSP_LoadModels(&header.lumps[LUMP_MODELS]);
BSP_LoadCollision(&header.lumps[LUMP_COLLISION]);
cm.loaded = true;
cm.use_thread = true;
@ -802,8 +835,8 @@ cmodel_t *CM_BeginRegistration( const char *name, bool clientload, uint *checksu
BSP_LoadLeafs(&hdr->lumps[LUMP_LEAFS]);
BSP_LoadLeafBrushes(&hdr->lumps[LUMP_LEAFBRUSHES]);
BSP_LoadPlanes(&hdr->lumps[LUMP_PLANES]);
BSP_LoadBrushes(&hdr->lumps[LUMP_BRUSHES]);
BSP_LoadBrushSides(&hdr->lumps[LUMP_BRUSHSIDES]);
BSP_LoadBrushes(&hdr->lumps[LUMP_BRUSHES]);
BSP_LoadNodes(&hdr->lumps[LUMP_NODES]);
BSP_LoadAreas(&hdr->lumps[LUMP_AREAS]);
BSP_LoadAreaPortals(&hdr->lumps[LUMP_AREAPORTALS]);
@ -893,7 +926,7 @@ Set up the planes and nodes so that the six floats of a bounding box
can just be stored out and get a proper clipping hull structure.
===================
*/
void CM_InitBoxHull (void)
void CM_InitBoxHull( void )
{
cplane_t *p;
cbrushside_t *s;
@ -903,7 +936,9 @@ void CM_InitBoxHull (void)
box.brush = &cm.brushes[cm.numbrushes];
box.brush->numsides = 6;
box.brush->firstbrushside = cm.numbrushsides;
box.brush->contents = CONTENTS_MONSTER;
box.brush->contents = CONTENTS_MONSTER;//FIXME
box.model.leaf.numleafbrushes = 1;
box.model.leaf.firstleafbrush = cm.numleafbrushes;
cm.leafbrushes[cm.numleafbrushes] = cm.numbrushes;
for (i = 0; i < 6; i++)
@ -931,6 +966,60 @@ void CM_InitBoxHull (void)
}
}
/*
===================
CM_TempBoxModel
To keep everything totally uniform, bounding boxes are turned into small
BSP trees instead of being compared directly.
Capsules are handled differently though.
===================
*/
int CM_TempBoxModel( const vec3_t mins, const vec3_t maxs )
{
VectorCopy( mins, box.model.mins );
VectorCopy( maxs, box.model.maxs );
box.planes[0].dist = maxs[0];
box.planes[1].dist = -maxs[0];
box.planes[2].dist = mins[0];
box.planes[3].dist = -mins[0];
box.planes[4].dist = maxs[1];
box.planes[5].dist = -maxs[1];
box.planes[6].dist = mins[1];
box.planes[7].dist = -mins[1];
box.planes[8].dist = maxs[2];
box.planes[9].dist = -maxs[2];
box.planes[10].dist = mins[2];
box.planes[11].dist = -mins[2];
VectorCopy( mins, box.brush->bounds[0] );
VectorCopy( maxs, box.brush->bounds[1] );
return BOX_MODEL_HANDLE;
}
/*
===================
CM_ModelBounds
===================
*/
void CM_ModelBounds( cmodel_t *cmod, vec3_t mins, vec3_t maxs )
{
if( cmod )
{
VectorCopy( cmod->mins, mins );
VectorCopy( cmod->maxs, maxs );
}
else
{
VectorSet( mins, -32, -32, -32 );
VectorSet( maxs, 32, 32, 32 );
MsgWarn("can't compute bounding box, use default size\n");
}
}
/*
===============================================================================

View File

@ -160,7 +160,7 @@ int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsiz
CM_BoxLeafnums_r( &ll, 0 );
//if( lastleaf ) *lastleaf = ll.lastleaf;//FIXME
if( lastleaf ) *lastleaf = ll.lastleaf;
return ll.count;
}
@ -170,7 +170,7 @@ CM_PointContents
==================
*/
int CM_PointContents( const vec3_t p )
int CM_PointContents( const vec3_t p, cmodel_t *model )
{
int leafnum;
int i, k;
@ -182,9 +182,16 @@ int CM_PointContents( const vec3_t p )
float d;
if(!cm.numnodes) return 0; // map not loaded
leafnum = CM_PointLeafnum_r (p, 0);
leaf = &cm.leafs[leafnum];
if( model && model->type == mod_brush )
{
// ignore studio models
leaf = &model->leaf;
}
else
{
leafnum = CM_PointLeafnum_r (p, 0);
leaf = &cm.leafs[leafnum];
}
contents = 0;
for( k = 0; k < leaf->numleafbrushes; k++)
@ -212,7 +219,7 @@ Handles offseting and rotation of the end points for moving and
rotating entities
==================
*/
int CM_TransformedPointContents( const vec3_t p, const vec3_t origin, const vec3_t angles )
int CM_TransformedPointContents( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles )
{
vec3_t p_l;
vec3_t temp;
@ -230,5 +237,5 @@ int CM_TransformedPointContents( const vec3_t p, const vec3_t origin, const vec3
p_l[1] = -DotProduct( temp, right );
p_l[2] = DotProduct( temp, up );
}
return CM_PointContents( p_l );
return CM_PointContents( p_l, model );
}

View File

@ -4,7 +4,7 @@
//=======================================================================
#include "cm_local.h"
#include "basefiles.h"
#include "cm_utils.h"
#define DIST_EPSILON (0.03125) // 1/32 epsilon to keep floating point happy
#define MAX_POSITION_LEAFS 1024
@ -111,16 +111,13 @@ void CM_TestBoxInBrush( tracework_t *tw, cbrush_t *brush )
CM_TestInLeaf
================
*/
void CM_TestInLeaf( tracework_t *tw, int leafnum )
void CM_TestInLeaf( tracework_t *tw, cleaf_t *leaf )
{
int k;
int brushnum;
cleaf_t *leaf;
cbrush_t *b;
leaf = &cm.leafs[leafnum];
if(!(leaf->contents & maptrace.contents)) return;
// test box position against all brushes in the leaf
for (k = 0; k < leaf->numleafbrushes; k++)
{
@ -300,7 +297,7 @@ void CM_PositionTest( tracework_t *tw )
// test the contents of the leafs
for( i = 0; i < ll.count; i++)
{
CM_TestInLeaf( tw, leafs[i] );
CM_TestInLeaf( tw, &cm.leafs[leafs[i]] );
if( tw->result.allsolid )
break;
}
@ -420,22 +417,23 @@ void CM_TraceThroughTree( tracework_t *tw, int num, float p1f, float p2f, vec3_t
CM_Trace
==================
*/
void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask )
void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *mod, const vec3_t origin, int brushmask )
{
int i;
tracework_t tw;
vec3_t offset;
cm.checkcount++; // for multi-check avoidance
// fill in a default trace
memset( &tw, 0, sizeof(tw) );
tw.result.fraction = 1; // assume it goes the entire distance until shown otherwise
tw.result.fraction = 1; // assume it goes the entire distance until shown otherwise
VectorCopy( origin, tw.origin );
if(!cm.numnodes)
{
*results = tw.result;
return; // map not loaded, shouldn't happen
return; // map not loaded, shouldn't happen
}
// allow NULL to be passed in for 0,0,0
@ -510,7 +508,8 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
// check for position test special case
if( VectorCompare( start, end ))
{
CM_PositionTest( &tw );
if( mod && mod->type == mod_brush ) CM_TestInLeaf( &tw, &mod->leaf );
else CM_PositionTest( &tw );
}
else
{
@ -527,8 +526,10 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
tw.extents[1] = tw.maxs[1];
tw.extents[2] = tw.maxs[2];
}
// general sweeping through world
CM_TraceThroughTree( &tw, 0, 0, 1, tw.start, tw.end );
if ( mod && mod->type == mod_brush ) CM_TraceThroughLeaf( &tw, &mod->leaf );
else CM_TraceThroughTree( &tw, 0, 0, 1, tw.start, tw.end );
}
// generate endpos from the original, unmodified start/end
@ -557,15 +558,14 @@ void CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, vec3_t mi
===============================================================================
*/
/*
==================
CM_BoxTrace
==================
*/
trace_t CM_BoxTrace( vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask )
trace_t CM_BoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask )
{
CM_Trace( &cm.trace, start, end, mins, maxs, brushmask );
CM_Trace( &cm.trace, start, end, mins, maxs, model, vec3_origin, brushmask );
return cm.trace;
}
@ -577,7 +577,7 @@ Handles offseting and rotation of the end points for moving and
rotating entities
==================
*/
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles )
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles )
{
trace_t trace;
vec3_t start_l, end_l;
@ -608,7 +608,7 @@ trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t min
VectorSubtract( end_l, origin, end_l );
// rotate start and end into the models frame of reference
if (!VectorIsNull( angles )) rotated = true;
if(!VectorIsNull( angles )) rotated = true;
else rotated = false;
if( rotated )
@ -625,7 +625,7 @@ trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t min
}
// sweep the box through the model
CM_Trace( &trace, start_l, end_l, symetricSize[0], symetricSize[1], brushmask );
CM_Trace( &trace, start_l, end_l, symetricSize[0], symetricSize[1], model, origin, brushmask );
// if the bmodel was rotated and there was a collision
if( rotated && trace.fraction != 1.0 )

View File

@ -44,10 +44,10 @@ int CM_NumTexinfo( void );
int CM_NumInlineModels( void );
const char *CM_EntityString( void );
const char *CM_TexName( int index );
int CM_PointContents( const vec3_t p );
int CM_TransformedPointContents( const vec3_t p, const vec3_t origin, const vec3_t angles );
trace_t CM_BoxTrace( vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask );
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles );
int CM_PointContents( const vec3_t p, cmodel_t *model );
int CM_TransformedPointContents( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles );
trace_t CM_BoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask );
trace_t CM_TransformedBoxTrace( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles );
byte *CM_ClusterPVS( int cluster );
byte *CM_ClusterPHS( int cluster );
int CM_PointLeafnum( const vec3_t p );
@ -56,5 +56,6 @@ int CM_LeafCluster( int leafnum );
int CM_LeafArea( int leafnum );
bool CM_AreasConnected( int area1, int area2 );
int CM_WriteAreaBits( byte *buffer, int area );
void CM_ModelBounds( cmodel_t *model, vec3_t mins, vec3_t maxs );
#endif//CM_UTILS_H

View File

@ -289,6 +289,7 @@ void() PutClientInServer =
pev->mass = 90;
pev->th_pain = PlayerPain;
pev->th_die = PlayerDie;
pev->touch = PlayerTouch;
setstats( pev, STAT_HEALTH_ICON, "hud/i_health");
setstats( pev, STAT_HEALTH, ftoa(pev->health));

View File

@ -186,6 +186,11 @@ void() func_mover_touch =
}
};
void func_mover_null ( void )
{
// null touching function
}
void() func_mover_use =
{
if(pev->message)
@ -221,6 +226,7 @@ void() func_mover =
pev->th_die = func_mover_die;
if(!pev->targetname) pev->touch = func_mover_touch;
else pev->touch = func_mover_null;
//func_mover; DEFAULTS;
if (!pev->speed)

View File

@ -51,6 +51,11 @@ void() func_illusionary =
pev->solid = SOLID_TRIGGER;
};
void func_wall_touch ( void )
{
// null touching function
}
void animate_wall( void )
{
pev->frame++;
@ -66,6 +71,7 @@ void() func_wall =
pev->nextthink = time + 1.0;
pev->think = animate_wall;
pev->touch = func_wall_touch;
};
/*

View File

@ -204,6 +204,10 @@ void() DeathSound =
sound (pev, CHAN_VOICE, pev->noise, 1, ATTN_NONE);
};
void PlayerTouch( void )
{
}
void () PlayerDie =
{
pev->view_ofs = '0 0 -8';

View File

@ -245,10 +245,10 @@ typedef struct physic_exp_s
int (*NumBmodels )( void );
const char *(*GetEntityString)( void );
const char *(*GetTextureName)( int index );
int (*PointContents)( const vec3_t p );
int (*TransformedPointContents)( const vec3_t p, const vec3_t origin, const vec3_t angles );
trace_t (*BoxTrace)( vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int brushmask);
trace_t (*TransformedBoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, int brushmask, vec3_t origin, vec3_t angles );
int (*PointContents)( const vec3_t p, cmodel_t *model );
int (*TransformedPointContents)( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles );
trace_t (*BoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask);
trace_t (*TransformedBoxTrace)( const vec3_t start, const vec3_t end, vec3_t mins, vec3_t maxs, cmodel_t *model, int brushmask, vec3_t origin, vec3_t angles );
byte *(*ClusterPVS)( int cluster );
byte *(*ClusterPHS)( int cluster );
int (*PointLeafnum)( vec3_t p );

View File

@ -960,6 +960,23 @@ _inline void CM_RoundUpHullSize( vec3_t size )
}
}
/*
=================
RadiusFromBounds
=================
*/
_inline float RadiusFromBounds( vec3_t mins, vec3_t maxs )
{
int i;
vec3_t corner;
for (i = 0; i < 3; i++)
{
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
}
return VectorLength( corner );
}
static vec3_t vec3_origin = { 0, 0, 0 };
static vec3_t vec3_angles = { 0, 0, 0 };

View File

@ -1364,6 +1364,15 @@ typedef struct cplane_s
byte pad[2];
} cplane_t;
typedef struct
{
int contents;
int cluster;
int area;
int firstleafbrush;
int numleafbrushes;
} cleaf_t;
typedef struct cmesh_s
{
vec3_t *verts;
@ -1376,8 +1385,8 @@ typedef struct cmodel_s
byte *mempool; // personal mempool
int registration_sequence;
vec3_t mins, maxs; // boundbox
int headnode; // bsp info
vec3_t mins, maxs; // model boundbox
cleaf_t leaf;
int type; // model type
int firstface; // used to create collision tree
int numfaces;

View File

@ -372,25 +372,6 @@ void Mod_LoadVertexes (lump_t *l)
}
}
/*
=================
RadiusFromBounds
=================
*/
float RadiusFromBounds (vec3_t mins, vec3_t maxs)
{
int i;
vec3_t corner;
for (i=0 ; i<3 ; i++)
{
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
}
return VectorLength (corner);
}
/*
=================
Mod_LoadSubmodels