📄 sv_world.c
字号:
break; // crosses the node
}
// link it in
ent->worldSector = node;
ent->nextEntityInWorldSector = node->entities;
node->entities = ent;
gEnt->r.linked = qtrue;
}
/*
============================================================================
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.
============================================================================
*/
typedef struct {
const float *mins;
const float *maxs;
int *list;
int count, maxcount;
} areaParms_t;
/*
====================
SV_AreaEntities_r
====================
*/
void SV_AreaEntities_r( worldSector_t *node, areaParms_t *ap ) {
svEntity_t *check, *next;
sharedEntity_t *gcheck;
int count;
count = 0;
for ( check = node->entities ; check ; check = next ) {
next = check->nextEntityInWorldSector;
gcheck = SV_GEntityForSvEntity( check );
if ( gcheck->r.absmin[0] > ap->maxs[0]
|| gcheck->r.absmin[1] > ap->maxs[1]
|| gcheck->r.absmin[2] > ap->maxs[2]
|| gcheck->r.absmax[0] < ap->mins[0]
|| gcheck->r.absmax[1] < ap->mins[1]
|| gcheck->r.absmax[2] < ap->mins[2]) {
continue;
}
if ( ap->count == ap->maxcount ) {
Com_Printf ("SV_AreaEntities: MAXCOUNT\n");
return;
}
ap->list[ap->count] = check - sv.svEntities;
ap->count++;
}
if (node->axis == -1) {
return; // terminal node
}
// recurse down both sides
if ( ap->maxs[node->axis] > node->dist ) {
SV_AreaEntities_r ( node->children[0], ap );
}
if ( ap->mins[node->axis] < node->dist ) {
SV_AreaEntities_r ( node->children[1], ap );
}
}
/*
================
SV_AreaEntities
================
*/
int SV_AreaEntities( const vec3_t mins, const vec3_t maxs, int *entityList, int maxcount ) {
areaParms_t ap;
ap.mins = mins;
ap.maxs = maxs;
ap.list = entityList;
ap.count = 0;
ap.maxcount = maxcount;
SV_AreaEntities_r( sv_worldSectors, &ap );
return ap.count;
}
//===========================================================================
typedef struct {
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
const float *mins;
const float *maxs; // size of the moving object
const float *start;
vec3_t end;
trace_t trace;
int passEntityNum;
int contentmask;
int capsule;
} moveclip_t;
/*
====================
SV_ClipToEntity
====================
*/
void SV_ClipToEntity( trace_t *trace, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int entityNum, int contentmask, int capsule ) {
sharedEntity_t *touch;
clipHandle_t clipHandle;
float *origin, *angles;
touch = SV_GentityNum( entityNum );
Com_Memset(trace, 0, sizeof(trace_t));
// if it doesn't have any brushes of a type we
// are looking for, ignore it
if ( ! ( contentmask & touch->r.contents ) ) {
trace->fraction = 1.0;
return;
}
// might intersect, so do an exact clip
clipHandle = SV_ClipHandleForEntity (touch);
origin = touch->r.currentOrigin;
angles = touch->r.currentAngles;
if ( !touch->r.bmodel ) {
angles = vec3_origin; // boxes don't rotate
}
CM_TransformedBoxTrace ( trace, (float *)start, (float *)end,
(float *)mins, (float *)maxs, clipHandle, contentmask,
origin, angles, capsule);
if ( trace->fraction < 1 ) {
trace->entityNum = touch->s.number;
}
}
/*
====================
SV_ClipMoveToEntities
====================
*/
void SV_ClipMoveToEntities( moveclip_t *clip ) {
int i, num;
int touchlist[MAX_GENTITIES];
sharedEntity_t *touch;
int passOwnerNum;
trace_t trace;
clipHandle_t clipHandle;
float *origin, *angles;
num = SV_AreaEntities( clip->boxmins, clip->boxmaxs, touchlist, MAX_GENTITIES);
if ( clip->passEntityNum != ENTITYNUM_NONE ) {
passOwnerNum = ( SV_GentityNum( clip->passEntityNum ) )->r.ownerNum;
if ( passOwnerNum == ENTITYNUM_NONE ) {
passOwnerNum = -1;
}
} else {
passOwnerNum = -1;
}
for ( i=0 ; i<num ; i++ ) {
if ( clip->trace.allsolid ) {
return;
}
touch = SV_GentityNum( touchlist[i] );
// see if we should ignore this entity
if ( clip->passEntityNum != ENTITYNUM_NONE ) {
if ( touchlist[i] == clip->passEntityNum ) {
continue; // don't clip against the pass entity
}
if ( touch->r.ownerNum == clip->passEntityNum ) {
continue; // don't clip against own missiles
}
if ( touch->r.ownerNum == passOwnerNum ) {
continue; // don't clip against other missiles from our owner
}
}
// if it doesn't have any brushes of a type we
// are looking for, ignore it
if ( ! ( clip->contentmask & touch->r.contents ) ) {
continue;
}
// might intersect, so do an exact clip
clipHandle = SV_ClipHandleForEntity (touch);
origin = touch->r.currentOrigin;
angles = touch->r.currentAngles;
if ( !touch->r.bmodel ) {
angles = vec3_origin; // boxes don't rotate
}
CM_TransformedBoxTrace ( &trace, (float *)clip->start, (float *)clip->end,
(float *)clip->mins, (float *)clip->maxs, clipHandle, clip->contentmask,
origin, angles, clip->capsule);
if ( trace.allsolid ) {
clip->trace.allsolid = qtrue;
trace.entityNum = touch->s.number;
} else if ( trace.startsolid ) {
clip->trace.startsolid = qtrue;
trace.entityNum = touch->s.number;
}
if ( trace.fraction < clip->trace.fraction ) {
qboolean oldStart;
// make sure we keep a startsolid from a previous trace
oldStart = clip->trace.startsolid;
trace.entityNum = touch->s.number;
clip->trace = trace;
clip->trace.startsolid |= oldStart;
}
}
}
/*
==================
SV_Trace
Moves the given mins/maxs volume through the world from start to end.
passEntityNum and entities owned by passEntityNum are explicitly not checked.
==================
*/
void SV_Trace( trace_t *results, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int passEntityNum, int contentmask, int capsule ) {
moveclip_t clip;
int i;
if ( !mins ) {
mins = vec3_origin;
}
if ( !maxs ) {
maxs = vec3_origin;
}
Com_Memset ( &clip, 0, sizeof ( moveclip_t ) );
// clip to world
CM_BoxTrace( &clip.trace, start, end, mins, maxs, 0, contentmask, capsule );
clip.trace.entityNum = clip.trace.fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE;
if ( clip.trace.fraction == 0 ) {
*results = clip.trace;
return; // blocked immediately by the world
}
clip.contentmask = contentmask;
clip.start = start;
// VectorCopy( clip.trace.endpos, clip.end );
VectorCopy( end, clip.end );
clip.mins = mins;
clip.maxs = maxs;
clip.passEntityNum = passEntityNum;
clip.capsule = capsule;
// create the bounding box of the entire move
// 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 );
*results = clip.trace;
}
/*
=============
SV_PointContents
=============
*/
int SV_PointContents( const vec3_t p, int passEntityNum ) {
int touch[MAX_GENTITIES];
sharedEntity_t *hit;
int i, num;
int contents, c2;
clipHandle_t clipHandle;
float *angles;
// get base contents from world
contents = CM_PointContents( p, 0 );
// or in contents from all the other entities
num = SV_AreaEntities( p, p, touch, MAX_GENTITIES );
for ( i=0 ; i<num ; i++ ) {
if ( touch[i] == passEntityNum ) {
continue;
}
hit = SV_GentityNum( touch[i] );
// might intersect, so do an exact clip
clipHandle = SV_ClipHandleForEntity( hit );
angles = hit->s.angles;
if ( !hit->r.bmodel ) {
angles = vec3_origin; // boxes don't rotate
}
c2 = CM_TransformedPointContents (p, clipHandle, hit->s.origin, hit->s.angles);
contents |= c2;
}
return contents;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -