19 Oct 2010
This commit is contained in:
parent
a2a61486e2
commit
6b87c02012
|
@ -1,12 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// cm_debug.c - draw collision hulls outlines
|
||||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
void CM_DrawCollision( cmdraw_t drawPoly )
|
||||
{
|
||||
if( !drawPoly ) return;
|
||||
}
|
|
@ -7,124 +7,107 @@
|
|||
#include "edict.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
int CM_RecursiveLightPoint( vec3_t color, mnode_t *node, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
float front, back, frac;
|
||||
vec3_t mid;
|
||||
static vec3_t cm_pointColor;
|
||||
static float cm_modulate;
|
||||
|
||||
loc0:
|
||||
if( node->contents < 0 )
|
||||
return false; // didn't hit anything
|
||||
/*
|
||||
=================
|
||||
CM_RecursiveLightPoint
|
||||
=================
|
||||
*/
|
||||
static bool CM_RecursiveLightPoint( mnode_t *node, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
int side;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
vec3_t mid, scale;
|
||||
float front, back, frac;
|
||||
int i, map, size, s, t;
|
||||
byte *lm;
|
||||
|
||||
// didn't hit anything
|
||||
if( !node->plane ) return false;
|
||||
|
||||
// calculate mid point
|
||||
if( node->plane->type < 3 )
|
||||
plane = node->plane;
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
front = start[node->plane->type] - node->plane->dist;
|
||||
back = end[node->plane->type] - node->plane->dist;
|
||||
front = start[plane->type] - plane->dist;
|
||||
back = end[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = DotProduct( start, node->plane->normal ) - node->plane->dist;
|
||||
back = DotProduct( end, node->plane->normal ) - node->plane->dist;
|
||||
front = DotProduct( start, plane->normal ) - plane->dist;
|
||||
back = DotProduct( end, plane->normal ) - plane->dist;
|
||||
}
|
||||
|
||||
// optimized recursion
|
||||
if(( back < 0 ) == ( front < 0 ))
|
||||
{
|
||||
node = node->children[front < 0];
|
||||
goto loc0;
|
||||
}
|
||||
side = front < 0;
|
||||
if(( back < 0 ) == side )
|
||||
return CM_RecursiveLightPoint( node->children[side], start, end );
|
||||
|
||||
frac = front / ( front - back );
|
||||
|
||||
VectorLerp( start, frac, end, mid );
|
||||
|
||||
// go down front side
|
||||
if( CM_RecursiveLightPoint( color, node->children[front < 0], start, mid ))
|
||||
{
|
||||
// hit something
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, ds, dt;
|
||||
msurface_t *surf;
|
||||
// co down front side
|
||||
if( CM_RecursiveLightPoint( node->children[side], start, mid ))
|
||||
return true; // hit something
|
||||
|
||||
if(( back < 0 ) == side )
|
||||
return false;// didn't hit anything
|
||||
|
||||
// check for impact on this node
|
||||
for( i = 0, surf = node->firstface; i < node->numfaces; i++, surf++ )
|
||||
surf = node->firstface;
|
||||
|
||||
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
tex = surf->texinfo;
|
||||
|
||||
if( surf->flags & SURF_DRAWTILED )
|
||||
continue; // no lightmaps
|
||||
|
||||
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] );
|
||||
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
|
||||
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];
|
||||
|
||||
if( ds < surf->texturemins[0] || dt < surf->texturemins[1] )
|
||||
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
|
||||
continue;
|
||||
|
||||
ds -= surf->texturemins[0];
|
||||
dt -= surf->texturemins[1];
|
||||
s >>= 4;
|
||||
t >>= 4;
|
||||
|
||||
if( ds > surf->extents[0] || dt > surf->extents[1] )
|
||||
continue;
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
if( surf->samples )
|
||||
VectorClear( cm_pointColor );
|
||||
|
||||
lm = surf->samples + 3 * (t * ((surf->extents[0] >> 4) + 1) + s);
|
||||
size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
|
||||
|
||||
for( map = 0; map < surf->numstyles; map++ )
|
||||
{
|
||||
// enhanced to interpolate lighting
|
||||
byte *lightmap;
|
||||
int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15;
|
||||
int r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0;
|
||||
int r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
|
||||
float scale;
|
||||
VectorScale( cm.lightstyle[surf->styles[map]].rgb, cm_modulate, scale );
|
||||
|
||||
line3 = ((surf->extents[0] >> 4) + 1) * 3;
|
||||
lightmap = surf->samples + ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
|
||||
cm_pointColor[0] += lm[0] * scale[0];
|
||||
cm_pointColor[1] += lm[1] * scale[1];
|
||||
cm_pointColor[2] += lm[2] * scale[2];
|
||||
|
||||
for( maps = 0; maps < LM_STYLES && surf->styles[maps] != 255; maps++ )
|
||||
{
|
||||
scale = (float)cm.lightstyle[surf->styles[maps]].value;
|
||||
r00 += (float)lightmap[0] * scale;
|
||||
g00 += (float)lightmap[1] * scale;
|
||||
b00 += (float)lightmap[2] * scale;
|
||||
|
||||
r01 += (float)lightmap[3] * scale;
|
||||
g01 += (float)lightmap[4] * scale;
|
||||
b01 += (float)lightmap[5] * scale;
|
||||
|
||||
r10 += (float)lightmap[line3+0] * scale;
|
||||
g10 += (float)lightmap[line3+1] * scale;
|
||||
b10 += (float)lightmap[line3+2] * scale;
|
||||
|
||||
r11 += (float)lightmap[line3+3] * scale;
|
||||
g11 += (float)lightmap[line3+4] * scale;
|
||||
b11 += (float)lightmap[line3+5] * scale;
|
||||
|
||||
lightmap += ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
|
||||
lm += size; // skip to next lightmap
|
||||
}
|
||||
color[0] += (float)((int)((((((((r11 - r10) * dsfrac) >> 4) + r10)
|
||||
- ((((r01 - r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4)
|
||||
+ ((((r01 - r00) * dsfrac) >> 4) + r00)));
|
||||
color[1] += (float)((int)((((((((g11 - g10) * dsfrac) >> 4) + g10)
|
||||
- ((((g01 - g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4)
|
||||
+ ((((g01 - g00) * dsfrac) >> 4) + g00)));
|
||||
color[2] += (float)((int)((((((((b11 - b10) * dsfrac) >> 4) + b10)
|
||||
- ((((b01 - b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4)
|
||||
+ ((((b01 - b00) * dsfrac) >> 4) + b00)));
|
||||
}
|
||||
return true; // success
|
||||
return true;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return CM_RecursiveLightPoint( color, node->children[front >= 0], mid, end );
|
||||
}
|
||||
return CM_RecursiveLightPoint( node->children[!side], mid, end );
|
||||
}
|
||||
|
||||
void CM_RunLightStyles( float time )
|
||||
{
|
||||
int i, ofs;
|
||||
clightstyle_t *ls;
|
||||
float l;
|
||||
|
||||
if( !sv_models[1] )
|
||||
return; // no world
|
||||
if( !worldmodel ) return;
|
||||
|
||||
// run lightstyles animation
|
||||
ofs = (time * 10);
|
||||
|
@ -134,9 +117,11 @@ void CM_RunLightStyles( float time )
|
|||
|
||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
{
|
||||
if( ls->length == 0 ) ls->value = 0.0f;
|
||||
else if( ls->length == 1 ) ls->value = ls->map[0];
|
||||
else ls->value = ls->map[ofs%ls->length];
|
||||
if( ls->length == 0 ) l = 0.0f;
|
||||
else if( ls->length == 1 ) l = ls->map[0];
|
||||
else l = ls->map[ofs%ls->length];
|
||||
|
||||
VectorSet( ls->rgb, l, l, l );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +151,7 @@ void CM_ClearLightStyles( void )
|
|||
Mem_Set( cm.lightstyle, 0, sizeof( cm.lightstyle ));
|
||||
|
||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
cm.lightstyle[i].value = 1.0f;
|
||||
VectorSet( cm.lightstyle[i].rgb, 1.0f, 1.0f, 1.0f );
|
||||
cm.lastofs = -1;
|
||||
}
|
||||
|
||||
|
@ -179,7 +164,7 @@ grab the ambient lighting color for current point
|
|||
*/
|
||||
int CM_LightEntity( edict_t *pEdict )
|
||||
{
|
||||
vec3_t start, end, color;
|
||||
vec3_t start, end;
|
||||
|
||||
if( !pEdict ) return 0;
|
||||
if( pEdict->v.effects & EF_FULLBRIGHT || !worldmodel->lightdata )
|
||||
|
@ -198,11 +183,12 @@ int CM_LightEntity( edict_t *pEdict )
|
|||
VectorCopy( pEdict->v.origin, end );
|
||||
|
||||
if( pEdict->v.effects & EF_INVLIGHT )
|
||||
end[2] = start[2] + 4096;
|
||||
else end[2] = start[2] - 4096;
|
||||
end[2] = start[2] + 8192;
|
||||
else end[2] = start[2] - 8192;
|
||||
VectorSet( cm_pointColor, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
VectorClear( color );
|
||||
CM_RecursiveLightPoint( color, worldmodel->nodes, start, end );
|
||||
cm_modulate = cm_lighting_modulate->value * (1.0 / 255);
|
||||
CM_RecursiveLightPoint( worldmodel->nodes, start, end );
|
||||
|
||||
return VectorAvg( color );
|
||||
return VectorAvg( cm_pointColor );
|
||||
}
|
|
@ -22,12 +22,13 @@
|
|||
#define DVIS_PHS 1
|
||||
|
||||
extern cvar_t *cm_novis;
|
||||
extern cvar_t *cm_lighting_modulate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int length;
|
||||
float map[MAX_STRING];
|
||||
float value; // current lightvalue
|
||||
vec3_t rgb; // 0.0 - 2.0
|
||||
} clightstyle_t;
|
||||
|
||||
typedef struct leaflist_s
|
||||
|
@ -61,15 +62,9 @@ typedef struct clipmap_s
|
|||
} clipmap_t;
|
||||
|
||||
extern clipmap_t cm;
|
||||
extern model_t *sv_models[MAX_MODELS]; // replacement client-server table
|
||||
extern model_t *loadmodel;
|
||||
extern model_t *worldmodel;
|
||||
|
||||
//
|
||||
// cm_debug.c
|
||||
//
|
||||
void CM_DrawCollision( cmdraw_t callback );
|
||||
|
||||
//
|
||||
// cm_light.c
|
||||
//
|
||||
|
@ -78,13 +73,6 @@ void CM_SetLightStyle( int style, const char* val );
|
|||
int CM_LightEntity( edict_t *pEdict );
|
||||
void CM_ClearLightStyles( void );
|
||||
|
||||
//
|
||||
// cm_main.c
|
||||
//
|
||||
bool CM_InitPhysics( void );
|
||||
void CM_Frame( float time );
|
||||
void CM_FreePhysics( void );
|
||||
|
||||
//
|
||||
// cm_test.c
|
||||
//
|
||||
|
@ -93,7 +81,6 @@ byte *CM_LeafPHS( int leafnum );
|
|||
int CM_PointLeafnum( const vec3_t p );
|
||||
mleaf_t *CM_PointInLeaf( const vec3_t p, mnode_t *node );
|
||||
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int listsize, int *lastleaf );
|
||||
int CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, bool capsule );
|
||||
bool CM_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
|
||||
int CM_HullPointContents( hull_t *hull, int num, const vec3_t p );
|
||||
int CM_PointContents( const vec3_t p );
|
||||
|
@ -109,35 +96,16 @@ byte *CM_FatPHS( const vec3_t org, bool portal );
|
|||
//
|
||||
// cm_model.c
|
||||
//
|
||||
void CM_FreeModels( void );
|
||||
int CM_NumBmodels( void );
|
||||
bool CM_InitPhysics( void );
|
||||
void CM_FreePhysics( void );
|
||||
script_t *CM_GetEntityScript( void );
|
||||
void Mod_GetBounds( int handle, vec3_t mins, vec3_t maxs );
|
||||
void Mod_GetFrames( int handle, int *numFrames );
|
||||
modtype_t CM_GetModelType( int handle );
|
||||
model_t *CM_ClipHandleToModel( int handle );
|
||||
hull_t *CM_HullForBox( const vec3_t mins, const vec3_t maxs );
|
||||
int CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, bool capsule );
|
||||
void CM_BeginRegistration ( const char *name, bool clientload, uint *checksum );
|
||||
bool CM_RegisterModel( const char *name, int sv_index );
|
||||
void *Mod_Extradata( int handle );
|
||||
model_t *CM_ModForName( const char *name, bool world );
|
||||
void CM_EndRegistration( void );
|
||||
|
||||
//
|
||||
// cm_studio.c
|
||||
//
|
||||
void CM_StudioInitBoxHull( void );
|
||||
int CM_StudioBodyVariations( int handle );
|
||||
void CM_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang );
|
||||
bool CM_StudioTrace( edict_t *e, const vec3_t start, const vec3_t end, trace_t *tr );
|
||||
void CM_GetBonePosition( edict_t* e, int iBone, float *rgflOrigin, float *rgflAngles );
|
||||
|
||||
//
|
||||
// cm_trace.c
|
||||
//
|
||||
trace_t CM_ClipMove( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int flags );
|
||||
const char *CM_TraceTexture( edict_t *pTextureEntity, const vec3_t v1, const vec3_t v2 );
|
||||
hull_t *CM_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, float *offset );
|
||||
|
||||
#endif//CM_LOCAL_H
|
|
@ -1,27 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// cm_main.c - collision interface
|
||||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
|
||||
// cvars
|
||||
cvar_t *cm_novis;
|
||||
|
||||
bool CM_InitPhysics( void )
|
||||
{
|
||||
cm_novis = Cvar_Get( "cm_novis", "0", 0, "force to ignore server visibility" );
|
||||
|
||||
Mem_Set( cm.nullrow, 0xFF, MAX_MAP_LEAFS / 8 );
|
||||
return true;
|
||||
}
|
||||
|
||||
void CM_Frame( float time )
|
||||
{
|
||||
CM_RunLightStyles( time );
|
||||
}
|
||||
|
||||
void CM_FreePhysics( void )
|
||||
{
|
||||
CM_FreeModels();
|
||||
}
|
|
@ -15,17 +15,18 @@
|
|||
clipmap_t cm;
|
||||
|
||||
byte *mod_base;
|
||||
model_t *sv_models[MAX_MODELS]; // server replacement modeltable
|
||||
static model_t *sv_models[MAX_MODELS]; // server replacement modeltable
|
||||
static model_t cm_inline[MAX_MAP_MODELS]; // inline bsp models
|
||||
static model_t cm_models[MAX_MODELS];
|
||||
static int cm_nummodels;
|
||||
|
||||
mplane_t box_planes[6];
|
||||
dclipnode_t box_clipnodes[6];
|
||||
hull_t box_hull[1];
|
||||
model_t *loadmodel;
|
||||
model_t *worldmodel;
|
||||
|
||||
// cvars
|
||||
cvar_t *cm_novis;
|
||||
cvar_t *cm_lighting_modulate;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
@ -33,88 +34,6 @@ model_t *worldmodel;
|
|||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
===================
|
||||
CM_BmodelInitBoxHull
|
||||
|
||||
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_BmodelInitBoxHull( void )
|
||||
{
|
||||
mplane_t *p;
|
||||
dclipnode_t *c;
|
||||
int i, side;
|
||||
|
||||
box_hull->clipnodes = box_clipnodes;
|
||||
box_hull->planes = box_planes;
|
||||
box_hull->firstclipnode = 0;
|
||||
box_hull->lastclipnode = 5;
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
side = i & 1;
|
||||
|
||||
// setup clipnodes
|
||||
c = &box_clipnodes[i];
|
||||
c->planenum = i;
|
||||
|
||||
c->children[side] = CONTENTS_EMPTY;
|
||||
if( i != 5 ) c->children[side^1] = i + 1;
|
||||
else c->children[side^1] = CONTENTS_SOLID;
|
||||
|
||||
// setup planes
|
||||
p = &box_planes[i];
|
||||
VectorClear( p->normal );
|
||||
|
||||
p->type = i>>1;
|
||||
p->normal[i>>1] = 1.0f;
|
||||
p->signbits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CM_HullForBox
|
||||
|
||||
To keep everything totally uniform, bounding boxes are turned into small
|
||||
BSP trees instead of being compared directly.
|
||||
===================
|
||||
*/
|
||||
hull_t *CM_HullForBox( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
box_planes[0].dist = maxs[0];
|
||||
box_planes[1].dist = mins[0];
|
||||
box_planes[2].dist = maxs[1];
|
||||
box_planes[3].dist = mins[1];
|
||||
box_planes[4].dist = maxs[2];
|
||||
box_planes[5].dist = mins[2];
|
||||
|
||||
return box_hull;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CM_FreeModel
|
||||
================
|
||||
*/
|
||||
void CM_FreeModel( model_t *mod )
|
||||
{
|
||||
if( !mod || !mod->mempool )
|
||||
return;
|
||||
|
||||
Mem_FreePool( &mod->mempool );
|
||||
Mem_Set( mod, 0, sizeof( *mod ));
|
||||
}
|
||||
|
||||
int CM_NumBmodels( void )
|
||||
{
|
||||
if( worldmodel )
|
||||
return worldmodel->numsubmodels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
script_t *CM_GetEntityScript( void )
|
||||
{
|
||||
string entfilename;
|
||||
|
@ -136,6 +55,71 @@ script_t *CM_GetEntityScript( void )
|
|||
return cm.entityscript;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CM_StudioBodyVariations
|
||||
================
|
||||
*/
|
||||
static int CM_StudioBodyVariations( int handle )
|
||||
{
|
||||
studiohdr_t *pstudiohdr;
|
||||
mstudiobodyparts_t *pbodypart;
|
||||
int i, count;
|
||||
|
||||
pstudiohdr = (studiohdr_t *)Mod_Extradata( handle );
|
||||
if( !pstudiohdr ) return 0;
|
||||
|
||||
count = 1;
|
||||
pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex);
|
||||
|
||||
// each body part has nummodels variations so there are as many total variations as there
|
||||
// are in a matrix of each part by each other part
|
||||
for( i = 0; i < pstudiohdr->numbodyparts; i++ )
|
||||
{
|
||||
count = count * pbodypart[i].nummodels;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CM_FreeModel
|
||||
================
|
||||
*/
|
||||
static void CM_FreeModel( model_t *mod )
|
||||
{
|
||||
if( !mod || !mod->mempool )
|
||||
return;
|
||||
|
||||
Mem_FreePool( &mod->mempool );
|
||||
Mem_Set( mod, 0, sizeof( *mod ));
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
CM INITALIZE\SHUTDOWN
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
bool CM_InitPhysics( void )
|
||||
{
|
||||
cm_novis = Cvar_Get( "cm_novis", "0", 0, "force to ignore server visibility" );
|
||||
cm_lighting_modulate = Cvar_Get( "r_lighting_modulate", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lightstyles modulate scale" );
|
||||
|
||||
Mem_Set( cm.nullrow, 0xFF, MAX_MAP_LEAFS / 8 );
|
||||
return true;
|
||||
}
|
||||
|
||||
void CM_FreePhysics( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < cm_nummodels; i++ )
|
||||
CM_FreeModel( &cm_models[i] );
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
@ -635,7 +619,7 @@ static void BSP_LoadPlanes( dlump_t *l )
|
|||
BSP_LoadVisibility
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadVisibility( dlump_t *l )
|
||||
static void BSP_LoadVisibility( dlump_t *l )
|
||||
{
|
||||
if( !l->filelen )
|
||||
{
|
||||
|
@ -653,7 +637,7 @@ void BSP_LoadVisibility( dlump_t *l )
|
|||
BSP_LoadEntityString
|
||||
=================
|
||||
*/
|
||||
void BSP_LoadEntityString( dlump_t *l )
|
||||
static void BSP_LoadEntityString( dlump_t *l )
|
||||
{
|
||||
byte *in;
|
||||
|
||||
|
@ -724,7 +708,7 @@ CM_MakeHull0
|
|||
Duplicate the drawing hull structure as a clipping hull
|
||||
=================
|
||||
*/
|
||||
void CM_MakeHull0( void )
|
||||
static void CM_MakeHull0( void )
|
||||
{
|
||||
mnode_t *in, *child;
|
||||
dclipnode_t *out;
|
||||
|
@ -757,7 +741,6 @@ void CM_MakeHull0( void )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CM_BrushModel
|
||||
|
@ -910,7 +893,100 @@ static void CM_SpriteModel( model_t *mod, byte *buffer )
|
|||
loadmodel->maxs[2] = phdr->bounds[1] / 2;
|
||||
}
|
||||
|
||||
void CM_FreeWorld( void )
|
||||
static model_t *CM_ModForName( const char *name, bool world )
|
||||
{
|
||||
byte *buf;
|
||||
model_t *mod;
|
||||
int i, size;
|
||||
|
||||
if( !name || !name[0] )
|
||||
return NULL;
|
||||
|
||||
// fast check for worldmodel
|
||||
if( !com.strcmp( name, cm_models[0].name ))
|
||||
return &cm_models[0];
|
||||
|
||||
// check for submodel
|
||||
if( name[0] == '*' )
|
||||
{
|
||||
i = com.atoi( name + 1 );
|
||||
if( i < 1 || !worldmodel || i >= worldmodel->numsubmodels )
|
||||
{
|
||||
MsgDev( D_ERROR, "CM_InlineModel: bad submodel number %d\n", i );
|
||||
return NULL;
|
||||
}
|
||||
return &cm_inline[i];
|
||||
}
|
||||
|
||||
// search the currently loaded models
|
||||
for( i = 0, mod = cm_models; i < cm_nummodels; i++, mod++ )
|
||||
{
|
||||
if( !mod->name[0] ) continue;
|
||||
if( !com.strcmp( name, mod->name ))
|
||||
{
|
||||
// prolonge registration
|
||||
mod->registration_sequence = cm.registration_sequence;
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
// find a free model slot spot
|
||||
for( i = 0, mod = cm_models; i < cm_nummodels; i++, mod++ )
|
||||
if( !mod->name[0] ) break; // free spot
|
||||
|
||||
if( i == cm_nummodels )
|
||||
{
|
||||
if( cm_nummodels == MAX_MODELS )
|
||||
Host_Error( "Mod_ForName: MAX_MODELS limit exceeded\n" );
|
||||
cm_nummodels++;
|
||||
}
|
||||
|
||||
buf = FS_LoadFile( name, &size );
|
||||
if( !buf )
|
||||
{
|
||||
MsgDev( D_ERROR, "CM_LoadModel: %s couldn't load\n", name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if it's world - calc the map checksum
|
||||
if( world ) cm.checksum = LittleLong( Com_BlockChecksum( buf, size ));
|
||||
|
||||
MsgDev( D_NOTE, "CM_LoadModel: %s\n", name );
|
||||
com.strncpy( mod->name, name, sizeof( mod->name ));
|
||||
mod->registration_sequence = cm.registration_sequence; // register mod
|
||||
mod->type = mod_bad;
|
||||
loadmodel = mod;
|
||||
|
||||
// call the apropriate loader
|
||||
switch( LittleLong( *(uint *)buf ))
|
||||
{
|
||||
case IDSTUDIOHEADER:
|
||||
CM_StudioModel( mod, buf );
|
||||
break;
|
||||
case IDSPRITEHEADER:
|
||||
CM_SpriteModel( mod, buf );
|
||||
break;
|
||||
default:
|
||||
CM_BrushModel( mod, buf );
|
||||
break;
|
||||
}
|
||||
|
||||
Mem_Free( buf );
|
||||
|
||||
if( mod->type == mod_bad )
|
||||
{
|
||||
CM_FreeModel( mod );
|
||||
|
||||
// check for loading problems
|
||||
if( world ) Host_Error( "Mod_ForName: %s unknown format\n", name );
|
||||
else MsgDev( D_ERROR, "Mod_ForName: %s unknown format\n", name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
static void CM_FreeWorld( void )
|
||||
{
|
||||
if( worldmodel )
|
||||
CM_FreeModel( &cm_models[0] );
|
||||
|
@ -923,14 +999,6 @@ void CM_FreeWorld( void )
|
|||
worldmodel = NULL;
|
||||
}
|
||||
|
||||
void CM_FreeModels( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < cm_nummodels; i++ )
|
||||
CM_FreeModel( &cm_models[i] );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_BeginRegistration
|
||||
|
@ -980,9 +1048,6 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
|
|||
|
||||
if( checksum ) *checksum = cm.checksum;
|
||||
|
||||
CM_BmodelInitBoxHull ();
|
||||
CM_StudioInitBoxHull (); // hitbox tracing
|
||||
|
||||
CM_ClearLightStyles();
|
||||
CM_CalcPHS ();
|
||||
}
|
||||
|
@ -1086,98 +1151,6 @@ void Mod_GetBounds( int handle, vec3_t mins, vec3_t maxs )
|
|||
}
|
||||
}
|
||||
|
||||
model_t *CM_ModForName( const char *name, bool world )
|
||||
{
|
||||
byte *buf;
|
||||
model_t *mod;
|
||||
int i, size;
|
||||
|
||||
if( !name || !name[0] )
|
||||
return NULL;
|
||||
|
||||
// fast check for worldmodel
|
||||
if( !com.strcmp( name, cm_models[0].name ))
|
||||
return &cm_models[0];
|
||||
|
||||
// check for submodel
|
||||
if( name[0] == '*' )
|
||||
{
|
||||
i = com.atoi( name + 1 );
|
||||
if( i < 1 || !worldmodel || i >= worldmodel->numsubmodels )
|
||||
{
|
||||
MsgDev( D_ERROR, "CM_InlineModel: bad submodel number %d\n", i );
|
||||
return NULL;
|
||||
}
|
||||
return &cm_inline[i];
|
||||
}
|
||||
|
||||
// search the currently loaded models
|
||||
for( i = 0, mod = cm_models; i < cm_nummodels; i++, mod++ )
|
||||
{
|
||||
if( !mod->name[0] ) continue;
|
||||
if( !com.strcmp( name, mod->name ))
|
||||
{
|
||||
// prolonge registration
|
||||
mod->registration_sequence = cm.registration_sequence;
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
|
||||
// find a free model slot spot
|
||||
for( i = 0, mod = cm_models; i < cm_nummodels; i++, mod++ )
|
||||
if( !mod->name[0] ) break; // free spot
|
||||
|
||||
if( i == cm_nummodels )
|
||||
{
|
||||
if( cm_nummodels == MAX_MODELS )
|
||||
Host_Error( "Mod_ForName: MAX_MODELS limit exceeded\n" );
|
||||
cm_nummodels++;
|
||||
}
|
||||
|
||||
buf = FS_LoadFile( name, &size );
|
||||
if( !buf )
|
||||
{
|
||||
MsgDev( D_ERROR, "CM_LoadModel: %s couldn't load\n", name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if it's world - calc the map checksum
|
||||
if( world ) cm.checksum = LittleLong( Com_BlockChecksum( buf, size ));
|
||||
|
||||
MsgDev( D_NOTE, "CM_LoadModel: %s\n", name );
|
||||
com.strncpy( mod->name, name, sizeof( mod->name ));
|
||||
mod->registration_sequence = cm.registration_sequence; // register mod
|
||||
mod->type = mod_bad;
|
||||
loadmodel = mod;
|
||||
|
||||
// call the apropriate loader
|
||||
switch( LittleLong( *(uint *)buf ))
|
||||
{
|
||||
case IDSTUDIOHEADER:
|
||||
CM_StudioModel( mod, buf );
|
||||
break;
|
||||
case IDSPRITEHEADER:
|
||||
CM_SpriteModel( mod, buf );
|
||||
break;
|
||||
default:
|
||||
CM_BrushModel( mod, buf );
|
||||
break;
|
||||
}
|
||||
|
||||
Mem_Free( buf );
|
||||
|
||||
if( mod->type == mod_bad )
|
||||
{
|
||||
// check for loading problems
|
||||
if( world ) Host_Error( "CMod_ForName: %s unknown format\n", name );
|
||||
else MsgDev( D_ERROR, "CMod_ForName: %s unknown format\n", name );
|
||||
CM_FreeModel( mod );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
bool CM_RegisterModel( const char *name, int index )
|
||||
{
|
||||
model_t *mod;
|
||||
|
|
|
@ -1,804 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2009 ©
|
||||
// cm_studio.c - stduio models tracing
|
||||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "studio.h"
|
||||
#include "mathlib.h"
|
||||
#include "matrix_lib.h"
|
||||
#include "edict.h"
|
||||
#include "byteorder.h"
|
||||
#include "const.h"
|
||||
|
||||
struct
|
||||
{
|
||||
studiohdr_t *hdr;
|
||||
mstudiomodel_t *submodel;
|
||||
mstudiobodyparts_t *bodypart;
|
||||
matrix4x4 rotmatrix;
|
||||
matrix4x4 bones[MAXSTUDIOBONES];
|
||||
mplane_t planes[12];
|
||||
trace_t trace;
|
||||
} studio;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
STUDIO MODELS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
int CM_StudioExtractBbox( studiohdr_t *phdr, int sequence, float *mins, float *maxs )
|
||||
{
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
|
||||
|
||||
if( sequence == -1 ) return 0;
|
||||
VectorCopy( pseqdesc[sequence].bbmin, mins );
|
||||
VectorCopy( pseqdesc[sequence].bbmax, maxs );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CM_StudioBodyVariations( int handle )
|
||||
{
|
||||
studiohdr_t *pstudiohdr;
|
||||
mstudiobodyparts_t *pbodypart;
|
||||
int i, count;
|
||||
|
||||
pstudiohdr = (studiohdr_t *)Mod_Extradata( handle );
|
||||
if( !pstudiohdr ) return 0;
|
||||
|
||||
count = 1;
|
||||
pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex);
|
||||
|
||||
// each body part has nummodels variations so there are as many total variations as there
|
||||
// are in a matrix of each part by each other part
|
||||
for( i = 0; i < pstudiohdr->numbodyparts; i++ )
|
||||
{
|
||||
count = count * pbodypart[i].nummodels;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioSetUpTransform
|
||||
====================
|
||||
*/
|
||||
void CM_StudioSetUpTransform( edict_t *e )
|
||||
{
|
||||
float *ang, *org, scale = 1.0f;
|
||||
|
||||
org = e->v.origin;
|
||||
ang = e->v.angles;
|
||||
if( e->v.scale != 0.0f )
|
||||
scale = e->v.scale;
|
||||
|
||||
Matrix4x4_CreateFromEntity( studio.rotmatrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], scale );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBoneAdj
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2 )
|
||||
{
|
||||
int i, j;
|
||||
float value;
|
||||
mstudiobonecontroller_t *pbonecontroller;
|
||||
|
||||
pbonecontroller = (mstudiobonecontroller_t *)((byte *)studio.hdr + studio.hdr->bonecontrollerindex);
|
||||
|
||||
for( j = 0; j < studio.hdr->numbonecontrollers; j++ )
|
||||
{
|
||||
i = pbonecontroller[j].index;
|
||||
|
||||
if( i == 4 ) continue; // ignore mouth
|
||||
if( i <= MAXSTUDIOCONTROLLERS )
|
||||
{
|
||||
// check for 360% wrapping
|
||||
if( pbonecontroller[j].type & STUDIO_RLOOP )
|
||||
{
|
||||
if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 )
|
||||
{
|
||||
int a, b;
|
||||
|
||||
a = (pcontroller1[j] + 128) % 256;
|
||||
b = (pcontroller2[j] + 128) % 256;
|
||||
value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0/256.0) + pbonecontroller[j].start;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0/256.0) + pbonecontroller[j].start;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0;
|
||||
if( value < 0 ) value = 0;
|
||||
if( value > 1.0 ) value = 1.0;
|
||||
value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
|
||||
}
|
||||
}
|
||||
|
||||
switch( pbonecontroller[j].type & STUDIO_TYPES )
|
||||
{
|
||||
case STUDIO_XR:
|
||||
case STUDIO_YR:
|
||||
case STUDIO_ZR:
|
||||
adj[j] = value * (M_PI / 180.0);
|
||||
break;
|
||||
case STUDIO_X:
|
||||
case STUDIO_Y:
|
||||
case STUDIO_Z:
|
||||
adj[j] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioCalcBoneQuaterion
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_StudioCalcBoneQuaterion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q )
|
||||
{
|
||||
int j, k;
|
||||
vec4_t q1, q2;
|
||||
vec3_t angle1, angle2;
|
||||
mstudioanimvalue_t *panimvalue;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( panim->offset[j+3] == 0 )
|
||||
{
|
||||
angle2[j] = angle1[j] = pbone->value[j+3]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
// DEBUG
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
// Bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
angle1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
angle2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angle2[j] = angle1[j];
|
||||
else angle2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
{
|
||||
angle2[j] = angle1[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
angle2[j] = panimvalue[panimvalue->num.valid + 2].value;
|
||||
}
|
||||
}
|
||||
angle1[j] = pbone->value[j+3] + angle1[j] * pbone->scale[j+3];
|
||||
angle2[j] = pbone->value[j+3] + angle2[j] * pbone->scale[j+3];
|
||||
}
|
||||
|
||||
if( pbone->bonecontroller[j+3] != -1 )
|
||||
{
|
||||
angle1[j] += adj[pbone->bonecontroller[j+3]];
|
||||
angle2[j] += adj[pbone->bonecontroller[j+3]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( angle1, angle2 ))
|
||||
{
|
||||
AngleQuaternion( angle1, q1 );
|
||||
AngleQuaternion( angle2, q2 );
|
||||
QuaternionSlerp( q1, q2, s, q );
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleQuaternion( angle1, q );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioCalcBonePosition
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos )
|
||||
{
|
||||
int j, k;
|
||||
mstudioanimvalue_t *panimvalue;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
pos[j] = pbone->value[j]; // default;
|
||||
if( panim->offset[j] != 0.0f )
|
||||
{
|
||||
panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
|
||||
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// DEBUG
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
// if we're inside the span
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
// and there's more data in the span
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
pos[j] += (panimvalue[k+1].value * (1.0 - s) + s * panimvalue[k+2].value) * pbone->scale[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
pos[j] += panimvalue[k+1].value * pbone->scale[j];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// are we at the end of the repeating values section and there's another section with data?
|
||||
if( panimvalue->num.total <= k + 1 )
|
||||
{
|
||||
pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pbone->bonecontroller[j] != -1 && adj )
|
||||
{
|
||||
pos[j] += adj[pbone->bonecontroller[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioCalcRotations
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_StudioCalcRotations( edict_t *e, float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f )
|
||||
{
|
||||
int i;
|
||||
int frame;
|
||||
mstudiobone_t *pbone;
|
||||
float adj[MAXSTUDIOCONTROLLERS];
|
||||
float s, dadt = 1.0f; // noInterp
|
||||
|
||||
if( f > pseqdesc->numframes - 1 )
|
||||
f = 0;
|
||||
else if( f < -0.01 )
|
||||
f = -0.01;
|
||||
|
||||
frame = (int)f;
|
||||
s = (f - frame);
|
||||
|
||||
// add in programtic controllers
|
||||
pbone = (mstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
|
||||
|
||||
CM_StudioCalcBoneAdj( dadt, adj, e->v.controller, e->v.controller );
|
||||
|
||||
for (i = 0; i < studio.hdr->numbones; i++, pbone++, panim++)
|
||||
{
|
||||
CM_StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] );
|
||||
CM_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f;
|
||||
if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f;
|
||||
|
||||
s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * e->v.framerate;
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_LX ) pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0];
|
||||
if( pseqdesc->motiontype & STUDIO_LY ) pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1];
|
||||
if( pseqdesc->motiontype & STUDIO_LZ ) pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2];
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioEstimateFrame
|
||||
|
||||
====================
|
||||
*/
|
||||
float CM_StudioEstimateFrame( edict_t *e, mstudioseqdesc_t *pseqdesc )
|
||||
{
|
||||
double f;
|
||||
|
||||
if( pseqdesc->numframes <= 1 )
|
||||
f = 0;
|
||||
else f = (e->v.frame * (pseqdesc->numframes - 1)) / 256.0;
|
||||
|
||||
if( pseqdesc->flags & STUDIO_LOOPING )
|
||||
{
|
||||
if( pseqdesc->numframes > 1 )
|
||||
f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1);
|
||||
if( f < 0 ) f += (pseqdesc->numframes - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( f >= pseqdesc->numframes - 1.001 )
|
||||
f = pseqdesc->numframes - 1.001;
|
||||
if( f < 0.0 ) f = 0.0;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioSlerpBones
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
|
||||
{
|
||||
int i;
|
||||
vec4_t q3;
|
||||
float s1;
|
||||
|
||||
s = bound( 0.0f, s, 1.0f );
|
||||
s1 = 1.0f - s;
|
||||
|
||||
for( i = 0; i < studio.hdr->numbones; i++ )
|
||||
{
|
||||
QuaternionSlerp( q1[i], q2[i], s, q3 );
|
||||
q1[i][0] = q3[0];
|
||||
q1[i][1] = q3[1];
|
||||
q1[i][2] = q3[2];
|
||||
q1[i][3] = q3[3];
|
||||
pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s;
|
||||
pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s;
|
||||
pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioGetAnim
|
||||
|
||||
====================
|
||||
*/
|
||||
mstudioanim_t *CM_StudioGetAnim( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
|
||||
{
|
||||
mstudioseqgroup_t *pseqgroup;
|
||||
cache_user_t *paSequences;
|
||||
size_t filesize;
|
||||
byte *buf;
|
||||
|
||||
pseqgroup = (mstudioseqgroup_t *)((byte *)studio.hdr + studio.hdr->seqgroupindex) + pseqdesc->seqgroup;
|
||||
if( pseqdesc->seqgroup == 0 )
|
||||
return (mstudioanim_t *)((byte *)studio.hdr + pseqgroup->data + pseqdesc->animindex);
|
||||
|
||||
paSequences = (cache_user_t *)m_pSubModel->submodels;
|
||||
|
||||
if( paSequences == NULL )
|
||||
{
|
||||
paSequences = (cache_user_t *)Mem_Alloc( m_pSubModel->mempool, MAXSTUDIOGROUPS * sizeof( cache_user_t ));
|
||||
m_pSubModel->submodels = (void *)paSequences;
|
||||
}
|
||||
|
||||
if( !Cache_Check( m_pSubModel->mempool, ( cache_user_t *)&( paSequences[pseqdesc->seqgroup] )))
|
||||
{
|
||||
string filepath, modelname, modelpath;
|
||||
|
||||
FS_FileBase( m_pSubModel->name, modelname );
|
||||
FS_ExtractFilePath( m_pSubModel->name, modelpath );
|
||||
com.snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 );
|
||||
|
||||
buf = FS_LoadFile( filepath, &filesize );
|
||||
if( !buf || !filesize ) Host_Error( "CM_StudioGetAnim: can't load %s\n", modelpath );
|
||||
if( IDSEQGRPHEADER != LittleLong(*(uint *)buf ))
|
||||
Host_Error( "CM_StudioGetAnim: %s is corrpted\n", modelpath );
|
||||
|
||||
MsgDev( D_INFO, "loading %s\n", filepath );
|
||||
|
||||
paSequences[pseqdesc->seqgroup].data = Mem_Alloc( m_pSubModel->mempool, filesize );
|
||||
Mem_Copy( paSequences[pseqdesc->seqgroup].data, buf, filesize );
|
||||
Mem_Free( buf );
|
||||
}
|
||||
return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_StudioSetupBones
|
||||
====================
|
||||
*/
|
||||
void CM_StudioSetupBones( edict_t *e )
|
||||
{
|
||||
int i, oldseq;
|
||||
double f;
|
||||
|
||||
mstudiobone_t *pbones;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
mstudioanim_t *panim;
|
||||
|
||||
static float pos[MAXSTUDIOBONES][3];
|
||||
static vec4_t q[MAXSTUDIOBONES];
|
||||
matrix4x4 bonematrix;
|
||||
|
||||
static float pos2[MAXSTUDIOBONES][3];
|
||||
static vec4_t q2[MAXSTUDIOBONES];
|
||||
static float pos3[MAXSTUDIOBONES][3];
|
||||
static vec4_t q3[MAXSTUDIOBONES];
|
||||
static float pos4[MAXSTUDIOBONES][3];
|
||||
static vec4_t q4[MAXSTUDIOBONES];
|
||||
|
||||
oldseq = e->v.sequence; // TraceCode can't change sequence
|
||||
|
||||
if( e->v.sequence >= studio.hdr->numseq ) e->v.sequence = 0;
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)studio.hdr + studio.hdr->seqindex) + e->v.sequence;
|
||||
|
||||
f = CM_StudioEstimateFrame( e, pseqdesc );
|
||||
|
||||
panim = CM_StudioGetAnim( CM_ClipHandleToModel( e->v.modelindex ), pseqdesc );
|
||||
CM_StudioCalcRotations( e, pos, q, pseqdesc, panim, f );
|
||||
|
||||
if( pseqdesc->numblends > 1 )
|
||||
{
|
||||
float s;
|
||||
float dadt = 1.0f;
|
||||
|
||||
panim += studio.hdr->numbones;
|
||||
CM_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, f );
|
||||
|
||||
s = (e->v.blending[0] * dadt + e->v.blending[0] * (1.0 - dadt)) / 255.0;
|
||||
|
||||
CM_StudioSlerpBones( q, pos, q2, pos2, s );
|
||||
|
||||
if( pseqdesc->numblends == 4 )
|
||||
{
|
||||
panim += studio.hdr->numbones;
|
||||
CM_StudioCalcRotations( e, pos3, q3, pseqdesc, panim, f );
|
||||
|
||||
panim += studio.hdr->numbones;
|
||||
CM_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, f );
|
||||
|
||||
s = (e->v.blending[0] * dadt + e->v.blending[0] * (1.0 - dadt)) / 255.0;
|
||||
CM_StudioSlerpBones( q3, pos3, q4, pos4, s );
|
||||
|
||||
s = (e->v.blending[1] * dadt + e->v.blending[1] * (1.0 - dadt)) / 255.0;
|
||||
CM_StudioSlerpBones( q, pos, q3, pos3, s );
|
||||
}
|
||||
}
|
||||
|
||||
pbones = (mstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
|
||||
|
||||
for( i = 0; i < studio.hdr->numbones; i++ )
|
||||
{
|
||||
Matrix4x4_FromOriginQuat( bonematrix, pos[i][0], pos[i][1], pos[i][2], q[i][0], q[i][1], q[i][2], q[i][3] );
|
||||
if( pbones[i].parent == -1 )
|
||||
Matrix4x4_ConcatTransforms( studio.bones[i], studio.rotmatrix, bonematrix );
|
||||
else Matrix4x4_ConcatTransforms( studio.bones[i], studio.bones[pbones[i].parent], bonematrix );
|
||||
}
|
||||
|
||||
e->v.sequence = oldseq; // restore original value
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcAttachments
|
||||
|
||||
====================
|
||||
*/
|
||||
static void CM_StudioCalcAttachments( edict_t *e, int iAttachment, float *org, float *ang )
|
||||
{
|
||||
int i;
|
||||
mstudioattachment_t *pAtt;
|
||||
vec3_t axis[3];
|
||||
vec3_t localOrg, localAng;
|
||||
|
||||
if( studio.hdr->numattachments > MAXSTUDIOATTACHMENTS )
|
||||
{
|
||||
studio.hdr->numattachments = MAXSTUDIOATTACHMENTS; // reduce it
|
||||
MsgDev( D_WARN, "CM_StudioCalcAttahments: too many attachments on %s\n", studio.hdr->name );
|
||||
}
|
||||
|
||||
iAttachment = bound( 0, iAttachment, studio.hdr->numattachments );
|
||||
|
||||
// calculate attachment points
|
||||
pAtt = (mstudioattachment_t *)((byte *)studio.hdr + studio.hdr->attachmentindex);
|
||||
|
||||
for( i = 0; i < studio.hdr->numattachments; i++ )
|
||||
{
|
||||
if( i == iAttachment )
|
||||
{
|
||||
// compute pos and angles
|
||||
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].org, localOrg );
|
||||
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[0], axis[0] );
|
||||
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[1], axis[1] );
|
||||
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[2], axis[2] );
|
||||
Matrix3x3_ToAngles( axis, localAng, true ); // FIXME: dll's uses FLU ?
|
||||
if( org ) VectorCopy( localOrg, org );
|
||||
if( ang ) VectorCopy( localAng, ang );
|
||||
break; // done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CM_StudioInitBoxHull( void )
|
||||
{
|
||||
int i, side;
|
||||
mplane_t *p;
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
side = i & 1;
|
||||
|
||||
// planes
|
||||
p = &studio.planes[i*2];
|
||||
p->type = i>>1;
|
||||
p->signbits = 0;
|
||||
VectorClear( p->normal );
|
||||
p->normal[i>>1] = 1.0f;
|
||||
|
||||
p = &studio.planes[i*2+1];
|
||||
p->type = 3 + (i>>1);
|
||||
p->signbits = 0;
|
||||
VectorClear( p->normal );
|
||||
p->normal[i>>1] = -1;
|
||||
|
||||
p->signbits = SignbitsForPlane( p->normal );
|
||||
}
|
||||
}
|
||||
|
||||
void CM_StudioBoxHullFromBounds( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
studio.planes[0].dist = maxs[0];
|
||||
studio.planes[1].dist = -maxs[0];
|
||||
studio.planes[2].dist = mins[0];
|
||||
studio.planes[3].dist = -mins[0];
|
||||
studio.planes[4].dist = maxs[1];
|
||||
studio.planes[5].dist = -maxs[1];
|
||||
studio.planes[6].dist = mins[1];
|
||||
studio.planes[7].dist = -mins[1];
|
||||
studio.planes[8].dist = maxs[2];
|
||||
studio.planes[9].dist = -maxs[2];
|
||||
studio.planes[10].dist = mins[2];
|
||||
studio.planes[11].dist = -mins[2];
|
||||
}
|
||||
|
||||
bool CM_StudioSetup( edict_t *e )
|
||||
{
|
||||
model_t *mod = CM_ClipHandleToModel( e->v.modelindex );
|
||||
|
||||
if( mod && mod->type == mod_studio && mod->extradata )
|
||||
{
|
||||
studio.hdr = (studiohdr_t *)mod->extradata;
|
||||
CM_StudioSetUpTransform( e );
|
||||
CM_StudioSetupBones( e );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CM_StudioTraceBox( vec3_t start, vec3_t end )
|
||||
{
|
||||
int i;
|
||||
mplane_t *plane, *clipplane;
|
||||
float enterFrac, leaveFrac;
|
||||
bool getout, startout;
|
||||
float d1, d2;
|
||||
float f;
|
||||
|
||||
enterFrac = -1.0;
|
||||
leaveFrac = 1.0;
|
||||
clipplane = NULL;
|
||||
|
||||
getout = false;
|
||||
startout = false;
|
||||
|
||||
// compare the trace against all planes of the brush
|
||||
// find the latest time the trace crosses a plane towards the interior
|
||||
// and the earliest time the trace crosses a plane towards the exterior
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
plane = studio.planes + i * 2 + (i & 1);
|
||||
|
||||
d1 = DotProduct( start, plane->normal ) - plane->dist;
|
||||
d2 = DotProduct( end, plane->normal ) - plane->dist;
|
||||
|
||||
if( d2 > 0.0f ) getout = TRUE; // endpoint is not in solid
|
||||
if( d1 > 0.0f ) startout = TRUE;
|
||||
|
||||
// if completely in front of face, no intersection with the entire brush
|
||||
if( d1 > 0 && ( d2 >= DIST_EPSILON || d2 >= d1 ))
|
||||
return false;
|
||||
|
||||
// if it doesn't cross the plane, the plane isn't relevent
|
||||
if( d1 <= 0 && d2 <= 0 )
|
||||
continue;
|
||||
|
||||
// crosses face
|
||||
if( d1 > d2 )
|
||||
{
|
||||
// enter
|
||||
f = (d1 - DIST_EPSILON) / (d1 - d2);
|
||||
if( f < 0.0f ) f = 0.0f;
|
||||
|
||||
if( f > enterFrac )
|
||||
{
|
||||
enterFrac = f;
|
||||
clipplane = plane;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// leave
|
||||
f = (d1 + DIST_EPSILON) / (d1 - d2);
|
||||
if( f > 1.0f ) f = 1.0f;
|
||||
|
||||
if( f < leaveFrac )
|
||||
{
|
||||
leaveFrac = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// all planes have been checked, and the trace was not
|
||||
// completely outside the brush
|
||||
if( !startout )
|
||||
{
|
||||
// original point was inside brush
|
||||
if( !getout ) studio.trace.flFraction = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( enterFrac < leaveFrac )
|
||||
{
|
||||
if( enterFrac > -1 && enterFrac < studio.trace.flFraction )
|
||||
{
|
||||
if( enterFrac < 0.0f )
|
||||
enterFrac = 0.0f;
|
||||
|
||||
studio.trace.flFraction = enterFrac;
|
||||
VectorCopy( clipplane->normal, studio.trace.vecPlaneNormal );
|
||||
studio.trace.flPlaneDist = clipplane->dist;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CM_StudioTrace( edict_t *e, const vec3_t start, const vec3_t end, trace_t *tr )
|
||||
{
|
||||
matrix4x4 m;
|
||||
vec3_t start_l, end_l;
|
||||
int i, outBone;
|
||||
|
||||
if( !CM_StudioSetup( e ) || !studio.hdr->numhitboxes )
|
||||
{
|
||||
tr->iHitgroup = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
Mem_Set( &studio.trace, 0, sizeof( trace_t ));
|
||||
VectorCopy( end, studio.trace.vecEndPos );
|
||||
studio.trace.fAllSolid = true;
|
||||
studio.trace.flFraction = 1.0f;
|
||||
studio.trace.iHitgroup = -1;
|
||||
outBone = -1;
|
||||
|
||||
for( i = 0; i < studio.hdr->numhitboxes; i++ )
|
||||
{
|
||||
mstudiobbox_t *phitbox = (mstudiobbox_t *)((byte*)studio.hdr + studio.hdr->hitboxindex) + i;
|
||||
|
||||
Matrix4x4_Invert_Simple( m, studio.bones[phitbox->bone] );
|
||||
Matrix4x4_VectorTransform( m, start, start_l );
|
||||
Matrix4x4_VectorTransform( m, end, end_l );
|
||||
|
||||
CM_StudioBoxHullFromBounds( phitbox->bbmin, phitbox->bbmax );
|
||||
|
||||
if( CM_StudioTraceBox( start_l, end_l ))
|
||||
{
|
||||
outBone = phitbox->bone;
|
||||
studio.trace.iHitgroup = phitbox->group;
|
||||
}
|
||||
|
||||
if( studio.trace.flFraction == 0.0f )
|
||||
break;
|
||||
}
|
||||
|
||||
if( studio.trace.flFraction > 0.0f )
|
||||
studio.trace.fAllSolid = false;
|
||||
|
||||
// all hitboxes were swept, get trace result
|
||||
if( outBone >= 0 )
|
||||
{
|
||||
tr->flFraction = studio.trace.flFraction;
|
||||
tr->iHitgroup = studio.trace.iHitgroup;
|
||||
tr->fAllSolid = studio.trace.fAllSolid;
|
||||
tr->pHit = e;
|
||||
|
||||
Matrix4x4_VectorRotate( studio.bones[outBone], studio.trace.vecPlaneNormal, tr->vecPlaneNormal );
|
||||
if( tr->flFraction == 1.0f )
|
||||
{
|
||||
VectorCopy( end, tr->vecEndPos );
|
||||
}
|
||||
else
|
||||
{
|
||||
mstudiobone_t *pbone = (mstudiobone_t *)((byte*)studio.hdr + studio.hdr->boneindex) + outBone;
|
||||
|
||||
// MsgDev( D_INFO, "Bone name %s\n", pbone->name ); // debug
|
||||
VectorLerp( start, tr->flFraction, end, tr->vecEndPos );
|
||||
}
|
||||
tr->flPlaneDist = DotProduct( tr->vecEndPos, tr->vecPlaneNormal );
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CM_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang )
|
||||
{
|
||||
if( !CM_StudioSetup( e ) || studio.hdr->numattachments <= 0 )
|
||||
{
|
||||
// reset attachments
|
||||
if( org ) VectorCopy( e->v.origin, org );
|
||||
if( ang ) VectorCopy( e->v.angles, ang );
|
||||
return;
|
||||
}
|
||||
CM_StudioCalcAttachments( e, iAttachment, org, ang );
|
||||
}
|
||||
|
||||
void CM_GetBonePosition( edict_t* e, int iBone, float *org, float *ang )
|
||||
{
|
||||
matrix3x3 axis;
|
||||
|
||||
if( !CM_StudioSetup( e ) || studio.hdr->numbones <= 0 )
|
||||
{
|
||||
// reset bones
|
||||
if( org ) VectorCopy( e->v.origin, org );
|
||||
if( ang ) VectorCopy( e->v.angles, ang );
|
||||
return;
|
||||
}
|
||||
|
||||
iBone = bound( 0, iBone, studio.hdr->numbones );
|
||||
Matrix3x3_FromMatrix4x4( axis, studio.bones[iBone] );
|
||||
if( org ) Matrix4x4_OriginFromMatrix( studio.bones[iBone], org );
|
||||
if( ang ) Matrix3x3_ToAngles( axis, ang, true );
|
||||
|
||||
}
|
|
@ -1,510 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2009 ©
|
||||
// cm_trace.c - geometry tracing
|
||||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "edict.h"
|
||||
#include "mathlib.h"
|
||||
#include "matrix_lib.h"
|
||||
|
||||
float CM_DistanceToIntersect( const vec3_t org, const vec3_t dir, const vec3_t plane_origin, const vec3_t plane_normal )
|
||||
{
|
||||
float d = -(DotProduct( plane_normal, plane_origin ));
|
||||
float numerator = DotProduct( plane_normal, org ) + d;
|
||||
float denominator = DotProduct( plane_normal, dir );
|
||||
|
||||
if( fabs( denominator ) < EQUAL_EPSILON )
|
||||
return -1.0f; // normal is orthogonal to vector, no intersection
|
||||
|
||||
return -( numerator / denominator );
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
BOX TRACING
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
================
|
||||
SV_HullForEntity
|
||||
|
||||
Returns a hull that can be used for testing or clipping an object of mins/maxs size.
|
||||
Offset is filled in to contain the adjustment that must be added to the
|
||||
testing object's origin to get a point to use with the returned hull.
|
||||
================
|
||||
*/
|
||||
hull_t *CM_HullForEntity( edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset )
|
||||
{
|
||||
hull_t *hull;
|
||||
model_t *model;
|
||||
vec3_t size, hullmins, hullmaxs;
|
||||
|
||||
// decide which clipping hull to use, based on the size
|
||||
if( ent->v.solid == SOLID_BSP )
|
||||
{
|
||||
// explicit hulls in the BSP model
|
||||
if( ent->v.movetype != MOVETYPE_PUSH )
|
||||
Host_Error( "Entity %i SOLID_BSP without MOVETYPE_PUSH\n", ent->serialnumber );
|
||||
|
||||
model = CM_ClipHandleToModel( ent->v.modelindex );
|
||||
|
||||
if( !model || model->type != mod_brush && model->type != mod_world )
|
||||
Host_Error( "Entity %i SOLID_BSP with a non bsp model\n", ent->serialnumber );
|
||||
|
||||
VectorSubtract( maxs, mins, size );
|
||||
|
||||
if( size[0] < 3 )
|
||||
{
|
||||
// point hull
|
||||
hull = &model->hulls[0];
|
||||
}
|
||||
else if( size[0] <= 36 )
|
||||
{
|
||||
if( size[2] <= 36 )
|
||||
{
|
||||
// head hull (ducked)
|
||||
hull = &model->hulls[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
// human hull
|
||||
hull = &model->hulls[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// large hull
|
||||
hull = &model->hulls[2];
|
||||
}
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorSubtract( hull->clip_mins, mins, offset );
|
||||
VectorAdd( offset, ent->v.origin, offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a temp hull from bounding box sizes
|
||||
VectorSubtract( ent->v.mins, maxs, hullmins );
|
||||
VectorSubtract( ent->v.maxs, mins, hullmaxs );
|
||||
hull = CM_HullForBox( hullmins, hullmaxs );
|
||||
VectorCopy( ent->v.origin, offset );
|
||||
}
|
||||
return hull;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_HullForBsp
|
||||
|
||||
assume edict is valid
|
||||
==================
|
||||
*/
|
||||
hull_t *CM_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, float *offset )
|
||||
{
|
||||
hull_t *hull;
|
||||
model_t *model;
|
||||
vec3_t size;
|
||||
|
||||
// decide which clipping hull to use, based on the size
|
||||
model = CM_ClipHandleToModel( ent->v.modelindex );
|
||||
|
||||
if( !model || ( model->type != mod_brush && model->type != mod_world ))
|
||||
Host_Error( "Entity %i SOLID_BSP with a non bsp model %i\n", ent->serialnumber, model->type );
|
||||
|
||||
VectorSubtract( maxs, mins, size );
|
||||
|
||||
if( size[0] < 3 )
|
||||
{
|
||||
// point hull
|
||||
hull = &model->hulls[0];
|
||||
}
|
||||
else if( size[0] <= 36 )
|
||||
{
|
||||
if( size[2] <= 36 )
|
||||
{
|
||||
// head hull (ducked)
|
||||
hull = &model->hulls[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
// human hull
|
||||
hull = &model->hulls[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// large hull
|
||||
hull = &model->hulls[2];
|
||||
}
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorSubtract( hull->clip_mins, mins, offset );
|
||||
VectorAdd( offset, ent->v.origin, offset );
|
||||
|
||||
return hull;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_RecursiveHullCheck
|
||||
==================
|
||||
*/
|
||||
bool CM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace )
|
||||
{
|
||||
dclipnode_t *node;
|
||||
mplane_t *plane;
|
||||
float t1, t2;
|
||||
float frac, midf;
|
||||
int side;
|
||||
vec3_t mid;
|
||||
loc0:
|
||||
// check for empty
|
||||
if( num < 0 )
|
||||
{
|
||||
if( num != CONTENTS_SOLID )
|
||||
{
|
||||
trace->fAllSolid = false;
|
||||
if( num == CONTENTS_EMPTY )
|
||||
trace->fInOpen = true;
|
||||
else trace->fInWater = true;
|
||||
}
|
||||
else trace->fStartSolid = true;
|
||||
return true; // empty
|
||||
}
|
||||
|
||||
if( num < hull->firstclipnode || num > hull->lastclipnode )
|
||||
Host_Error( "CM_RecursiveHullCheck: bad node number\n" );
|
||||
|
||||
// find the point distances
|
||||
node = hull->clipnodes + num;
|
||||
plane = hull->planes + node->planenum;
|
||||
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
t1 = p1[plane->type] - plane->dist;
|
||||
t2 = p2[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
|
||||
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
|
||||
}
|
||||
|
||||
if( t1 >= 0 && t2 >= 0 )
|
||||
{
|
||||
num = node->children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( t1 < 0 && t2 < 0 )
|
||||
{
|
||||
num = node->children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
// put the crosspoint DIST_EPSILON pixels on the near side
|
||||
side = (t1 < 0);
|
||||
|
||||
if( side ) frac = ( t1 + DIST_EPSILON ) / ( t1 - t2 );
|
||||
else frac = ( t1 - DIST_EPSILON ) / ( t1 - t2 );
|
||||
|
||||
if( frac < 0 ) frac = 0;
|
||||
if( frac > 1 ) frac = 1;
|
||||
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
// move up to the node
|
||||
if( !CM_RecursiveHullCheck( hull, node->children[side], p1f, midf, p1, mid, trace ))
|
||||
return false;
|
||||
|
||||
// this recursion can not be optimized because mid would need to be duplicated on a stack
|
||||
if( CM_HullPointContents( hull, node->children[side^1], mid ) != CONTENTS_SOLID )
|
||||
{
|
||||
// go past the node
|
||||
return CM_RecursiveHullCheck( hull, node->children[side^1], midf, p2f, mid, p2, trace );
|
||||
}
|
||||
|
||||
// never got out of the solid area
|
||||
if( trace->fAllSolid )
|
||||
return false;
|
||||
|
||||
// the other side of the node is solid, this is the impact point
|
||||
if( !side )
|
||||
{
|
||||
VectorCopy( plane->normal, trace->vecPlaneNormal );
|
||||
trace->flPlaneDist = plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorNegate( plane->normal, trace->vecPlaneNormal );
|
||||
trace->flPlaneDist = -plane->dist;
|
||||
}
|
||||
|
||||
while( CM_HullPointContents( hull, hull->firstclipnode, mid ) == CONTENTS_SOLID )
|
||||
{
|
||||
// shouldn't really happen, but does occasionally
|
||||
frac -= 0.1f;
|
||||
|
||||
if( frac < 0 )
|
||||
{
|
||||
trace->flFraction = midf;
|
||||
VectorCopy( mid, trace->vecEndPos );
|
||||
MsgDev( D_INFO, "backup past 0\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
}
|
||||
|
||||
trace->flFraction = midf;
|
||||
VectorCopy( mid, trace->vecEndPos );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_ClipMove
|
||||
|
||||
Handles selection or creation of a clipping hull, and offseting (and
|
||||
eventually rotation) of the end points
|
||||
==================
|
||||
*/
|
||||
trace_t CM_ClipMove( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int flags )
|
||||
{
|
||||
vec3_t offset, temp;
|
||||
vec3_t start_l, end_l;
|
||||
trace_t trace;
|
||||
matrix4x4 matrix;
|
||||
hull_t *hull;
|
||||
|
||||
// fill in a default trace
|
||||
Mem_Set( &trace, 0, sizeof( trace_t ));
|
||||
VectorCopy( end, trace.vecEndPos );
|
||||
trace.flFraction = 1.0f;
|
||||
trace.fAllSolid = true;
|
||||
trace.iHitgroup = -1;
|
||||
|
||||
// get the clipping hull
|
||||
hull = CM_HullForEntity( ent, mins, maxs, offset );
|
||||
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( ent->v.solid == SOLID_BSP && !VectorIsNull( ent->v.angles ))
|
||||
{
|
||||
matrix4x4 imatrix;
|
||||
|
||||
Matrix4x4_CreateFromEntity( matrix, ent->v.origin[0], ent->v.origin[1], ent->v.origin[2], ent->v.angles[PITCH], ent->v.angles[YAW], ent->v.angles[ROLL], 1.0f );
|
||||
Matrix4x4_Invert_Simple( imatrix, matrix );
|
||||
|
||||
Matrix4x4_VectorTransform( imatrix, start, start_l );
|
||||
Matrix4x4_VectorTransform( imatrix, end, end_l );
|
||||
#if 1
|
||||
// calc hull offsets (monsters use this)
|
||||
VectorCopy( start_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, mins, -1, hull->clip_mins, start_l );
|
||||
|
||||
VectorCopy( end_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, mins, -1, hull->clip_mins, end_l );
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!( flags & FMOVE_SIMPLEBOX ) && CM_GetModelType( ent->v.modelindex ) == mod_studio )
|
||||
{
|
||||
if( CM_StudioTrace( ent, start, end, &trace )); // continue tracing bbox if hitbox missing
|
||||
else CM_RecursiveHullCheck( hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace );
|
||||
}
|
||||
else
|
||||
{
|
||||
// trace a line through the apropriate clipping hull
|
||||
CM_RecursiveHullCheck( hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace );
|
||||
}
|
||||
|
||||
// rotate endpos back to world frame of reference
|
||||
if( ent->v.solid == SOLID_BSP && !VectorIsNull( ent->v.angles ))
|
||||
{
|
||||
if( trace.flFraction != 1.0f )
|
||||
{
|
||||
vec3_t temp;
|
||||
|
||||
// compute endpos
|
||||
trace.vecEndPos[0] = start[0] + trace.flFraction * ( end[0] - start[0] );
|
||||
trace.vecEndPos[1] = start[1] + trace.flFraction * ( end[1] - start[1] );
|
||||
trace.vecEndPos[2] = start[2] + trace.flFraction * ( end[2] - start[2] );
|
||||
|
||||
VectorCopy( trace.vecPlaneNormal, temp );
|
||||
Matrix4x4_TransformPositivePlane( matrix, temp, trace.flPlaneDist, trace.vecPlaneNormal, &trace.flPlaneDist );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// special case for non-rotated bmodels
|
||||
// fix trace up by the offset when we hit bmodel
|
||||
if( trace.flFraction != 1.0f && trace.iHitgroup == -1 )
|
||||
VectorAdd( trace.vecEndPos, offset, trace.vecEndPos );
|
||||
|
||||
trace.flPlaneDist = DotProduct( trace.vecEndPos, trace.vecPlaneNormal );
|
||||
}
|
||||
|
||||
// did we clip the move?
|
||||
if( trace.flFraction < 1.0f || trace.fStartSolid )
|
||||
trace.pHit = ent;
|
||||
|
||||
if(!( flags & FMOVE_SIMPLEBOX ) && CM_GetModelType( ent->v.modelindex ) == mod_studio )
|
||||
{
|
||||
if( VectorIsNull( mins ) && VectorIsNull( maxs ) && trace.iHitgroup == -1 )
|
||||
{
|
||||
// NOTE: studio traceline doesn't check studio bbox hitboxes only
|
||||
trace.flFraction = 1.0f;
|
||||
trace.pHit = NULL; // clear entity when any hitbox not intersected
|
||||
}
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_TraceTexture
|
||||
|
||||
find the face where the traceline hit
|
||||
==================
|
||||
*/
|
||||
const char *CM_TraceTexture( edict_t *pTextureEntity, const vec3_t v1, const vec3_t v2 )
|
||||
{
|
||||
vec3_t intersect, temp, vecStartPos;
|
||||
msurface_t **mark, *surf, *hitface = NULL;
|
||||
float d1, d2, min_diff = 9999.9f;
|
||||
vec3_t forward, right, up;
|
||||
vec3_t vecPos1, vecPos2;
|
||||
model_t *bmodel;
|
||||
mleaf_t *endleaf;
|
||||
mplane_t *plane;
|
||||
trace_t trace;
|
||||
int i;
|
||||
|
||||
trace = CM_ClipMove( pTextureEntity, v1, vec3_origin, vec3_origin, v2, FMOVE_SIMPLEBOX );
|
||||
|
||||
if( !trace.pHit ) return NULL; // trace entity must be valid
|
||||
|
||||
bmodel = CM_ClipHandleToModel( trace.pHit->v.modelindex );
|
||||
if( !bmodel || bmodel->type != mod_brush && bmodel->type != mod_world )
|
||||
return NULL;
|
||||
|
||||
// making trace adjustments
|
||||
VectorSubtract( v1, trace.pHit->v.origin, vecStartPos );
|
||||
VectorSubtract( trace.vecEndPos, trace.pHit->v.origin, trace.vecEndPos );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( trace.pHit->v.solid == SOLID_BSP && !VectorIsNull( trace.pHit->v.angles ))
|
||||
{
|
||||
VectorCopy( trace.pHit->v.angles, temp );
|
||||
AngleVectors( temp, forward, right, up );
|
||||
|
||||
VectorCopy( vecStartPos, temp );
|
||||
vecStartPos[0] = DotProduct( temp, forward );
|
||||
vecStartPos[1] = -DotProduct( temp, right );
|
||||
vecStartPos[2] = DotProduct( temp, up );
|
||||
|
||||
VectorCopy( trace.vecEndPos, temp );
|
||||
trace.vecEndPos[0] = DotProduct( temp, forward );
|
||||
trace.vecEndPos[1] = -DotProduct( temp, right );
|
||||
trace.vecEndPos[2] = DotProduct( temp, up );
|
||||
}
|
||||
|
||||
VectorSubtract( trace.vecEndPos, vecStartPos, forward );
|
||||
VectorNormalize( forward );
|
||||
|
||||
// nudge endpos back to can be trace face between two points
|
||||
VectorMA( trace.vecEndPos, 5.0f, trace.vecPlaneNormal, vecPos1 );
|
||||
VectorMA( trace.vecEndPos, -5.0f, trace.vecPlaneNormal, vecPos2 );
|
||||
|
||||
endleaf = CM_PointInLeaf( trace.vecEndPos, bmodel->nodes + bmodel->hulls[0].firstclipnode );
|
||||
mark = endleaf->firstmarksurface;
|
||||
|
||||
// find a plane with endpos on one side and hitpos on the other side...
|
||||
for( i = 0; i < endleaf->nummarksurfaces; i++ )
|
||||
{
|
||||
surf = *mark++;
|
||||
plane = surf->plane;
|
||||
|
||||
d1 = DotProduct( vecPos1, plane->normal ) - plane->dist;
|
||||
d2 = DotProduct( vecPos2, plane->normal ) - plane->dist;
|
||||
|
||||
if(( d1 > 0.0f && d2 <= 0.0f ) || ( d1 <= 0.0f && d2 > 0.0f ))
|
||||
{
|
||||
// found a plane, find the intersection point in the plane...
|
||||
vec3_t plane_origin, angle1, angle2;
|
||||
float dist, anglef, angle_sum = 0.0f;
|
||||
int i, e;
|
||||
|
||||
VectorScale( plane->normal, plane->dist, plane_origin );
|
||||
dist = CM_DistanceToIntersect( vecStartPos, forward, plane_origin, plane->normal );
|
||||
|
||||
if( dist < 0.0f ) return NULL; // can't find intersection
|
||||
|
||||
VectorScale( forward, dist, temp );
|
||||
VectorAdd( vecStartPos, temp, intersect );
|
||||
|
||||
// loop through all of the vertexes of all the edges of this face and
|
||||
// find the angle between vertex-n, v_intersect and vertex-n+1, then add
|
||||
// all these angles together. if the sum of these angles is 360 degrees
|
||||
// (or 2 PI radians), then the intersect point lies within that polygon.
|
||||
// loop though all of the edges, getting the vertexes...
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
vec3_t vertex1, vertex2;
|
||||
|
||||
// get the coordinates of the vertex of this edge...
|
||||
e = worldmodel->surfedges[surf->firstedge + i];
|
||||
|
||||
if( e < 0 )
|
||||
{
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[-e].v[1]], vertex1);
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[-e].v[0]], vertex2);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[e].v[0]], vertex1);
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[e].v[1]], vertex2);
|
||||
}
|
||||
|
||||
// now create vectors from the vertexes to the plane intersect point...
|
||||
VectorSubtract( vertex1, intersect, angle1 );
|
||||
VectorSubtract( vertex2, intersect, angle2 );
|
||||
|
||||
VectorNormalize( angle1 );
|
||||
VectorNormalize( angle2 );
|
||||
|
||||
// find the angle between these vectors...
|
||||
anglef = DotProduct( angle1, angle2 );
|
||||
|
||||
anglef = acos( anglef );
|
||||
angle_sum += anglef;
|
||||
}
|
||||
|
||||
// is the sum of the angles 360 degrees (2 PI)?...
|
||||
if(( angle_sum >= ( M_PI2 - EQUAL_EPSILON )) && ( angle_sum <= ( M_PI2 + EQUAL_EPSILON )))
|
||||
{
|
||||
// find the difference between the sum and 2 PI...
|
||||
float diff = fabs( angle_sum - M_PI2 );
|
||||
|
||||
if( diff < min_diff ) // is this the BEST so far?...
|
||||
{
|
||||
min_diff = diff;
|
||||
hitface = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( hitface && hitface->texinfo && hitface->texinfo->texture )
|
||||
return hitface->texinfo->texture->name;
|
||||
return NULL;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2009 ©
|
||||
// net_sound.h - sound message options
|
||||
//=======================================================================
|
||||
#ifndef NET_SOUND_H
|
||||
#define NET_SOUND_H
|
||||
|
||||
#endif//NET_SOUND_H
|
|
@ -8,16 +8,77 @@
|
|||
#include "matrix_lib.h"
|
||||
#include "pm_local.h"
|
||||
|
||||
static float PM_DistanceToIntersect( const vec3_t org, const vec3_t dir, const vec3_t origin, const vec3_t normal )
|
||||
/*
|
||||
==================
|
||||
PM_RecursiveSurfCheck
|
||||
|
||||
==================
|
||||
*/
|
||||
msurface_t *PM_RecursiveSurfCheck( mnode_t *node, vec3_t p1, vec3_t p2 )
|
||||
{
|
||||
float d = -(DotProduct( normal, origin ));
|
||||
float numerator = DotProduct( normal, org ) + d;
|
||||
float denominator = DotProduct( normal, dir );
|
||||
float t1, t2, frac;
|
||||
int side, ds, dt;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf;
|
||||
vec3_t mid;
|
||||
int i;
|
||||
|
||||
if( fabs( denominator ) < EQUAL_EPSILON )
|
||||
return -1.0f; // normal is orthogonal to vector, no intersection
|
||||
if( node->contents < 0 )
|
||||
return NULL;
|
||||
|
||||
return -( numerator / denominator );
|
||||
plane = node->plane;
|
||||
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
t1 = p1[plane->type] - plane->dist;
|
||||
t2 = p2[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
|
||||
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
|
||||
}
|
||||
|
||||
if( t1 >= 0 && t2 >= 0 )
|
||||
return PM_RecursiveSurfCheck( node->children[0], p1, p2 );
|
||||
if( t1 < 0 && t2 < 0 )
|
||||
return PM_RecursiveSurfCheck( node->children[1], p1, p2 );
|
||||
|
||||
frac = t1 / ( t1 - t2 );
|
||||
|
||||
if( frac < 0.0f ) frac = 0.0f;
|
||||
if( frac > 1.0f ) frac = 1.0f;
|
||||
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
side = (t1 < 0);
|
||||
|
||||
// now this is weird.
|
||||
surf = PM_RecursiveSurfCheck( node->children[side], p1, mid );
|
||||
|
||||
if( surf != NULL || ( t1 >= 0 && t2 >= 0 ) || ( t1 < 0 && t2 < 0 ))
|
||||
{
|
||||
return surf;
|
||||
}
|
||||
|
||||
surf = node->firstface;
|
||||
|
||||
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] );
|
||||
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
|
||||
|
||||
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] )
|
||||
{
|
||||
int s = ds - surf->texturemins[0];
|
||||
int t = dt - surf->texturemins[1];
|
||||
|
||||
if( s <= surf->extents[0] && t <= surf->extents[1] )
|
||||
return surf;
|
||||
}
|
||||
}
|
||||
|
||||
return PM_RecursiveSurfCheck( node->children[side^1], mid, p2 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -25,132 +86,51 @@ static float PM_DistanceToIntersect( const vec3_t org, const vec3_t dir, const v
|
|||
PM_TraceTexture
|
||||
|
||||
find the face where the traceline hit
|
||||
assume physentity is valid
|
||||
==================
|
||||
*/
|
||||
const char *PM_TraceTexture( physent_t *pe, vec3_t v1, vec3_t v2 )
|
||||
const char *PM_TraceTexture( physent_t *pe, vec3_t start, vec3_t end )
|
||||
{
|
||||
vec3_t intersect, temp, vecStartPos;
|
||||
msurface_t **mark, *surf, *hitface = NULL;
|
||||
float d1, d2, min_diff = 9999.9f;
|
||||
vec3_t forward, vecPos1, vecPos2;
|
||||
msurface_t *surf;
|
||||
matrix4x4 matrix;
|
||||
model_t *bmodel;
|
||||
mleaf_t *endleaf;
|
||||
mplane_t *plane;
|
||||
pmtrace_t trace;
|
||||
int i;
|
||||
|
||||
if( !PM_TraceModel( pe, v1, vec3_origin, vec3_origin, v2, &trace, PM_STUDIO_IGNORE ))
|
||||
return NULL; // not intersect
|
||||
hull_t *hull;
|
||||
vec3_t start_l, end_l;
|
||||
vec3_t temp, offset;
|
||||
|
||||
bmodel = pe->model;
|
||||
if( !bmodel || bmodel->type != mod_brush && bmodel->type != mod_world )
|
||||
return NULL;
|
||||
|
||||
// making trace adjustments
|
||||
VectorSubtract( v1, pe->origin, vecStartPos );
|
||||
VectorSubtract( trace.endpos, pe->origin, trace.endpos );
|
||||
hull = PM_HullForBsp( pe, vec3_origin, vec3_origin, offset );
|
||||
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( pe->solid == SOLID_BSP && !VectorIsNull( pe->angles ))
|
||||
if( !VectorIsNull( pe->angles ))
|
||||
{
|
||||
matrix4x4 matrix, imatrix;
|
||||
matrix4x4 imatrix;
|
||||
float *org = pe->origin;
|
||||
float *ang = pe->angles;
|
||||
|
||||
Matrix4x4_CreateFromEntity( matrix, pe->origin[0], pe->origin[1], pe->origin[2], pe->angles[PITCH], pe->angles[YAW], pe->angles[ROLL], 1.0f );
|
||||
Matrix4x4_CreateFromEntity( matrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], 1.0f );
|
||||
Matrix4x4_Invert_Simple( imatrix, matrix );
|
||||
|
||||
VectorCopy( vecStartPos, temp );
|
||||
Matrix4x4_VectorTransform( imatrix, temp, vecStartPos );
|
||||
VectorCopy( trace.endpos, temp );
|
||||
Matrix4x4_VectorTransform( imatrix, temp, trace.endpos );
|
||||
Matrix4x4_VectorTransform( imatrix, start, start_l );
|
||||
Matrix4x4_VectorTransform( imatrix, end, end_l );
|
||||
#if 1
|
||||
// calc hull offsets (monsters use this)
|
||||
VectorCopy( start_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, vec3_origin, -1, hull->clip_mins, start_l );
|
||||
|
||||
VectorCopy( end_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, vec3_origin, -1, hull->clip_mins, end_l );
|
||||
#endif
|
||||
}
|
||||
|
||||
VectorSubtract( trace.endpos, vecStartPos, forward );
|
||||
VectorNormalize( forward );
|
||||
surf = PM_RecursiveSurfCheck( &bmodel->nodes[hull->firstclipnode], start_l, end_l );
|
||||
if( !surf ) return NULL;
|
||||
|
||||
// nudge endpos back to can be trace face between two points
|
||||
VectorMA( trace.endpos, 5.0f, trace.plane.normal, vecPos1 );
|
||||
VectorMA( trace.endpos, -5.0f, trace.plane.normal, vecPos2 );
|
||||
|
||||
endleaf = CM_PointInLeaf( trace.endpos, bmodel->nodes + bmodel->hulls[0].firstclipnode );
|
||||
mark = endleaf->firstmarksurface;
|
||||
|
||||
// find a plane with endpos on one side and hitpos on the other side...
|
||||
for( i = 0; i < endleaf->nummarksurfaces; i++ )
|
||||
{
|
||||
surf = *mark++;
|
||||
plane = surf->plane;
|
||||
|
||||
d1 = DotProduct( vecPos1, plane->normal ) - plane->dist;
|
||||
d2 = DotProduct( vecPos2, plane->normal ) - plane->dist;
|
||||
|
||||
if(( d1 > 0.0f && d2 <= 0.0f ) || ( d1 <= 0.0f && d2 > 0.0f ))
|
||||
{
|
||||
// found a plane, find the intersection point in the plane...
|
||||
vec3_t plane_origin, angle1, angle2;
|
||||
float dist, anglef, angle_sum = 0.0f;
|
||||
int i, e;
|
||||
|
||||
VectorScale( plane->normal, plane->dist, plane_origin );
|
||||
dist = PM_DistanceToIntersect( vecStartPos, forward, plane_origin, plane->normal );
|
||||
|
||||
if( dist < 0.0f ) return NULL; // can't find intersection
|
||||
|
||||
VectorScale( forward, dist, temp );
|
||||
VectorAdd( vecStartPos, temp, intersect );
|
||||
|
||||
// loop through all of the vertexes of all the edges of this face and
|
||||
// find the angle between vertex-n, v_intersect and vertex-n+1, then add
|
||||
// all these angles together. if the sum of these angles is 360 degrees
|
||||
// (or 2 PI radians), then the intersect point lies within that polygon.
|
||||
// loop though all of the edges, getting the vertexes...
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
vec3_t vertex1, vertex2;
|
||||
|
||||
// get the coordinates of the vertex of this edge...
|
||||
e = worldmodel->surfedges[surf->firstedge + i];
|
||||
|
||||
if( e < 0 )
|
||||
{
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[-e].v[1]], vertex1);
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[-e].v[0]], vertex2);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[e].v[0]], vertex1);
|
||||
VectorCopy(worldmodel->vertexes[worldmodel->edges[e].v[1]], vertex2);
|
||||
}
|
||||
|
||||
// now create vectors from the vertexes to the plane intersect point...
|
||||
VectorSubtract( vertex1, intersect, angle1 );
|
||||
VectorSubtract( vertex2, intersect, angle2 );
|
||||
|
||||
VectorNormalize( angle1 );
|
||||
VectorNormalize( angle2 );
|
||||
|
||||
// find the angle between these vectors...
|
||||
anglef = DotProduct( angle1, angle2 );
|
||||
|
||||
anglef = acos( anglef );
|
||||
angle_sum += anglef;
|
||||
}
|
||||
|
||||
// is the sum of the angles 360 degrees (2 PI)?...
|
||||
if(( angle_sum >= ( M_PI2 - EQUAL_EPSILON )) && ( angle_sum <= ( M_PI2 + EQUAL_EPSILON )))
|
||||
{
|
||||
// find the difference between the sum and 2 PI...
|
||||
float diff = fabs( angle_sum - M_PI2 );
|
||||
|
||||
if( diff < min_diff ) // is this the BEST so far?...
|
||||
{
|
||||
min_diff = diff;
|
||||
hitface = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( hitface && hitface->texinfo && hitface->texinfo->texture )
|
||||
return hitface->texinfo->texture->name;
|
||||
return NULL;
|
||||
return surf->texinfo->texture->name;
|
||||
}
|
|
@ -183,29 +183,26 @@ hull_t *PM_HullForBsp( physent_t *pe, const vec3_t mins, const vec3_t maxs, floa
|
|||
|
||||
VectorSubtract( maxs, mins, size );
|
||||
|
||||
if( size[0] < 3 )
|
||||
if( size[0] <= 8.0f )
|
||||
{
|
||||
// point hull
|
||||
hull = &model->hulls[0];
|
||||
}
|
||||
else if( size[0] <= 36 )
|
||||
{
|
||||
if( size[2] <= 36 )
|
||||
{
|
||||
// head hull (ducked)
|
||||
hull = &model->hulls[3];
|
||||
hull = &pe->model->hulls[0];
|
||||
VectorCopy( hull->clip_mins, offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
// human hull
|
||||
hull = &model->hulls[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
if( size[0] <= 36.0f )
|
||||
{
|
||||
// large hull
|
||||
hull = &model->hulls[2];
|
||||
if( size[2] <= 36.0f )
|
||||
hull = &pe->model->hulls[3];
|
||||
else hull = &pe->model->hulls[1];
|
||||
}
|
||||
else hull = &pe->model->hulls[2];
|
||||
|
||||
VectorSubtract( hull->clip_mins, mins, offset );
|
||||
}
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorAdd( offset, pe->origin, offset );
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorSubtract( hull->clip_mins, mins, offset );
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2010 ©
|
||||
// pm_utils.c - misc movement utilities
|
||||
//=======================================================================
|
||||
|
||||
#include "common.h"
|
||||
#include "pm_local.h"
|
||||
|
|
@ -178,18 +178,10 @@ SOURCE=.\client\cl_world.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_debug.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_light.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_main.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_model.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -198,18 +190,10 @@ SOURCE=.\common\cm_portals.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_studio.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_test.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_trace.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\con_utils.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -270,10 +254,6 @@ SOURCE=.\common\pm_trace.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\pm_utils.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_client.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -93,6 +93,13 @@ void Host_EndGame( const char *message, ... )
|
|||
Host_AbortCurrentFrame ();
|
||||
}
|
||||
|
||||
static void Host_DrawDebugCollision( cmdraw_t drawPoly )
|
||||
{
|
||||
if( !drawPoly ) return;
|
||||
|
||||
// FIXME: get collision polys here
|
||||
}
|
||||
|
||||
void Host_FreeRender( void )
|
||||
{
|
||||
if( render_dll.link )
|
||||
|
@ -116,7 +123,7 @@ bool Host_InitRender( void )
|
|||
ri.UpdateScreen = SCR_UpdateScreen;
|
||||
ri.StudioEvent = CL_StudioEvent;
|
||||
ri.StudioFxTransform = CL_StudioFxTransform;
|
||||
ri.ShowCollision = CM_DrawCollision;
|
||||
ri.ShowCollision = Host_DrawDebugCollision;
|
||||
ri.GetClientEdict = CL_GetEntityByIndex;
|
||||
ri.GetPlayerInfo = CL_GetPlayerInfo;
|
||||
ri.GetLocalPlayer = CL_GetLocalPlayer;
|
||||
|
|
|
@ -470,7 +470,6 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
edict_t* pfnPEntityOfEntIndex( int iEntIndex );
|
||||
int pfnIndexOfEdict( const edict_t *pEdict );
|
||||
void SV_UpdateBaseVelocity( edict_t *ent );
|
||||
script_t *CM_GetEntityScript( void );
|
||||
|
||||
_inline edict_t *SV_EDICT_NUM( int n, const char * file, const int line )
|
||||
{
|
||||
|
@ -518,6 +517,7 @@ int SV_HullPointContents( hull_t *hull, int num, const vec3_t p );
|
|||
trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end );
|
||||
trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int type, edict_t *e );
|
||||
trace_t SV_MoveHull( const vec3_t start, int hullNumber, const vec3_t end, int type, edict_t *e );
|
||||
const char *SV_TraceTexture( edict_t *ent, const vec3_t start, const vec3_t end );
|
||||
trace_t SV_MoveToss( edict_t *tossent, edict_t *ignore );
|
||||
void SV_LinkEdict( edict_t *ent, bool touch_triggers );
|
||||
void SV_TouchLinks( edict_t *ent, areanode_t *node );
|
||||
|
|
|
@ -1819,10 +1819,7 @@ static const char *pfnTraceTexture( edict_t *pTextureEntity, const float *v1, co
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if( VectorIsNAN( v1 ) || VectorIsNAN( v2 ))
|
||||
Host_Error( "TraceTexture: NAN errors detected '%f %f %f', '%f %f %f'\n", v1[0], v1[1], v1[2], v2[0], v2[1], v2[2] );
|
||||
|
||||
return CM_TraceTexture( pTextureEntity, v1, v2 );
|
||||
return SV_TraceTexture( pTextureEntity, v1, v2 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -322,7 +322,7 @@ bool SV_SpawnServer( const char *mapname, const char *startspot )
|
|||
com.sprintf( sv.configstrings[CS_MAPCHECKSUM], "%i", checksum );
|
||||
sv.worldmodel = CM_ClipHandleToModel( 1 ); // get world pointer
|
||||
|
||||
for( i = 1; i < CM_NumBmodels(); i++ )
|
||||
for( i = 1; i < sv.worldmodel->numsubmodels; i++ )
|
||||
{
|
||||
com.sprintf( sv.configstrings[CS_MODELS+1+i], "*%i", i );
|
||||
CM_RegisterModel( sv.configstrings[CS_MODELS+1+i], i+1 );
|
||||
|
|
|
@ -1576,8 +1576,8 @@ void SV_Physics( void )
|
|||
}
|
||||
}
|
||||
|
||||
// let everything in the world think and move
|
||||
CM_Frame( sv_time( ));
|
||||
// animate lightstyles (used for GetEntityIllum)
|
||||
CM_RunLightStyles( sv.time );
|
||||
|
||||
// at end of frame kill all entities which supposed to it
|
||||
SV_FreeOldEntities();
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#include "pm_local.h"
|
||||
#include "matrix_lib.h"
|
||||
|
||||
// more precision but doesn't matched with HL gameplay
|
||||
// g-cont. this is pretty generic solution for maps with different hull sizes
|
||||
// but in HL this got 'wrong' sizes for pushables :(
|
||||
|
||||
//#define HULL_AUTOSELECT
|
||||
|
||||
typedef struct moveclip_s
|
||||
{
|
||||
vec3_t boxmins, boxmaxs; // enclose the test object along entire move
|
||||
|
@ -120,7 +126,7 @@ hull_t *SV_HullForEntity( edict_t *ent, int hullNumber, vec3_t mins, vec3_t maxs
|
|||
|
||||
if( hullNumber == -1 )
|
||||
{
|
||||
#if 0 // more precision but doesn't matched with HL gameplay
|
||||
#ifdef HULL_AUTOSELECT
|
||||
float curdiff;
|
||||
float lastdiff = 999;
|
||||
int i;
|
||||
|
@ -209,8 +215,8 @@ hull_t *SV_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, float
|
|||
hull_t *hull;
|
||||
model_t *model;
|
||||
vec3_t size;
|
||||
float curdiff, lastdiff = 999;
|
||||
int i, hullNumber = 0;
|
||||
float curdiff = 0, lastdiff = 999;
|
||||
int i = 0, hullNumber = 0;
|
||||
|
||||
// decide which clipping hull to use, based on the size
|
||||
model = CM_ClipHandleToModel( ent->v.modelindex );
|
||||
|
@ -220,6 +226,8 @@ hull_t *SV_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, float
|
|||
|
||||
VectorSubtract( maxs, mins, size );
|
||||
|
||||
#ifdef HULL_AUTOSELECT // more precision but doesn't matched with HL gameplay
|
||||
|
||||
// select the hull automatically
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
|
@ -233,10 +241,32 @@ hull_t *SV_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, float
|
|||
}
|
||||
}
|
||||
|
||||
// TraceHull stuff
|
||||
hull = &model->hulls[hullNumber];
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
// NOTE: never get offset of drawing hull
|
||||
if( !hullNumber ) VectorCopy( hull->clip_mins, offset );
|
||||
else VectorSubtract( hull->clip_mins, mins, offset );
|
||||
#else
|
||||
if( size[0] <= 8.0f )
|
||||
{
|
||||
hull = &model->hulls[0];
|
||||
VectorCopy( hull->clip_mins, offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( size[0] <= 36.0f )
|
||||
{
|
||||
if( size[2] <= 36.0f )
|
||||
hull = &model->hulls[3];
|
||||
else hull = &model->hulls[1];
|
||||
}
|
||||
else hull = &model->hulls[2];
|
||||
|
||||
VectorSubtract( hull->clip_mins, mins, offset );
|
||||
}
|
||||
#endif
|
||||
VectorAdd( offset, ent->v.origin, offset );
|
||||
|
||||
return hull;
|
||||
|
@ -935,81 +965,131 @@ trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins
|
|||
return trace;
|
||||
}
|
||||
|
||||
/* DESCRIPTION: SurfaceAtPoint
|
||||
// LOCATION:
|
||||
// PATH: TraceTexture, recursive
|
||||
//
|
||||
// A weird one. First, it seems to recursively call itself to dig deep into
|
||||
// the node tree, treating its own failure as a sign that it's dug deep
|
||||
// enough. Then, it loops through some odd texture stuff, looking for
|
||||
// a match. A match of what? Don't know yet.
|
||||
/*
|
||||
==================
|
||||
SV_RecursiveSurfCheck
|
||||
|
||||
==================
|
||||
*/
|
||||
msurface_t *SV_RecursiveSurfCheck( model_t *model, mnode_t *node, vec3_t v1, vec3_t v2 )
|
||||
msurface_t *SV_RecursiveSurfCheck( mnode_t *node, vec3_t p1, vec3_t p2 )
|
||||
{
|
||||
double var_4, var_8, var_c;
|
||||
int var_10, var_10_2;
|
||||
mplane_t * var_14_plane;
|
||||
vec3_t var_20;
|
||||
msurface_t * var_24_surface;
|
||||
int var_28, var_2c;
|
||||
int var_30, var_34;
|
||||
int var_38;
|
||||
mtexinfo_t * var_3C_texinfo;
|
||||
float t1, t2, frac;
|
||||
int side, ds, dt;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf;
|
||||
vec3_t mid;
|
||||
int i;
|
||||
|
||||
if( node->contents < 0 )
|
||||
return NULL;
|
||||
|
||||
if(node->contents < 0) { return(NULL); }
|
||||
plane = node->plane;
|
||||
|
||||
var_14_plane = node->plane;
|
||||
|
||||
var_4 = ((v1[0] * var_14_plane->normal[0]) + (v1[1] * var_14_plane->normal[1]) + (v1[2] * var_14_plane->normal[2])) - var_14_plane->dist;
|
||||
var_8 = ((v2[0] * var_14_plane->normal[0]) + (v2[1] * var_14_plane->normal[1]) + (v2[2] * var_14_plane->normal[2])) - var_14_plane->dist;
|
||||
|
||||
if(var_4 < 0) { var_10 = 1; }
|
||||
else { var_10 = 0; }
|
||||
|
||||
if(var_8 < 0) { var_10_2 = 1; }
|
||||
else { var_10_2 = 0; }
|
||||
|
||||
if(var_10 == var_10_2) {
|
||||
|
||||
return(SV_RecursiveSurfCheck(model, node->children[var_10], v1, v2));
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
t1 = p1[plane->type] - plane->dist;
|
||||
t2 = p2[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
|
||||
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
|
||||
}
|
||||
|
||||
var_c = var_4 / (var_4 - var_8);
|
||||
if( t1 >= 0 && t2 >= 0 )
|
||||
return SV_RecursiveSurfCheck( node->children[0], p1, p2 );
|
||||
if( t1 < 0 && t2 < 0 )
|
||||
return SV_RecursiveSurfCheck( node->children[1], p1, p2 );
|
||||
|
||||
var_20[0] = ((v2[0] - v1[0]) * var_c) + v1[0];
|
||||
var_20[1] = ((v2[1] - v1[1]) * var_c) + v1[1];
|
||||
var_20[2] = ((v2[2] - v1[2]) * var_c) + v1[2];
|
||||
frac = t1 / ( t1 - t2 );
|
||||
|
||||
//Now THIS is weird.
|
||||
var_24_surface = SV_RecursiveSurfCheck(model, node->children[var_10], v1, var_20);
|
||||
if(var_24_surface != NULL || var_10 == var_10_2) { return(var_24_surface); } //Second check not possible as in asm... I think.
|
||||
if( frac < 0.0f ) frac = 0.0f;
|
||||
if( frac > 1.0f ) frac = 1.0f;
|
||||
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
var_24_surface = node->firstface;
|
||||
side = (t1 < 0);
|
||||
|
||||
for(var_38 = 0; var_38 < node->numfaces; var_38++, var_24_surface++) {
|
||||
// now this is weird.
|
||||
surf = SV_RecursiveSurfCheck( node->children[side], p1, mid );
|
||||
|
||||
var_3C_texinfo = var_24_surface->texinfo;
|
||||
|
||||
var_28 = (var_20[0] * var_3C_texinfo->vecs[0][0]) + (var_20[1] * var_3C_texinfo->vecs[0][1]) + (var_20[2] * var_3C_texinfo->vecs[0][2]) + var_3C_texinfo->vecs[0][3];
|
||||
var_2c = (var_20[0] * var_3C_texinfo->vecs[1][0]) + (var_20[1] * var_3C_texinfo->vecs[1][1]) + (var_20[2] * var_3C_texinfo->vecs[1][2]) + var_3C_texinfo->vecs[1][3];
|
||||
|
||||
if(var_28 >= var_24_surface->texturemins[0] && var_2c >= var_24_surface->texturemins[1]) {
|
||||
|
||||
var_30 = var_28 - var_24_surface->texturemins[0];
|
||||
var_34 = var_2c - var_24_surface->texturemins[1];
|
||||
|
||||
if(var_30 <= var_24_surface->extents[0] && var_34 <= var_24_surface->extents[1]) {
|
||||
|
||||
return(var_24_surface);
|
||||
}
|
||||
}
|
||||
if( surf != NULL || ( t1 >= 0 && t2 >= 0 ) || ( t1 < 0 && t2 < 0 ))
|
||||
{
|
||||
return surf;
|
||||
}
|
||||
|
||||
if(var_10 == 1) { var_10 = 0; }
|
||||
else { var_10 = 1; }
|
||||
return(SV_RecursiveSurfCheck( model, node->children[var_10], var_20, v2 ));
|
||||
surf = node->firstface;
|
||||
|
||||
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] );
|
||||
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
|
||||
|
||||
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] )
|
||||
{
|
||||
int s = ds - surf->texturemins[0];
|
||||
int t = dt - surf->texturemins[1];
|
||||
|
||||
if( s <= surf->extents[0] && t <= surf->extents[1] )
|
||||
return surf;
|
||||
}
|
||||
}
|
||||
|
||||
return SV_RecursiveSurfCheck( node->children[side^1], mid, p2 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_TraceTexture
|
||||
|
||||
find the face where the traceline hit
|
||||
assume pTextureEntity is valid
|
||||
==================
|
||||
*/
|
||||
const char *SV_TraceTexture( edict_t *ent, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
msurface_t *surf;
|
||||
matrix4x4 matrix;
|
||||
model_t *bmodel;
|
||||
hull_t *hull;
|
||||
vec3_t start_l, end_l;
|
||||
vec3_t temp, offset;
|
||||
|
||||
bmodel = CM_ClipHandleToModel( ent->v.modelindex );
|
||||
if( !bmodel || bmodel->type != mod_brush && bmodel->type != mod_world )
|
||||
return NULL;
|
||||
|
||||
hull = SV_HullForBsp( ent, vec3_origin, vec3_origin, offset );
|
||||
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( !VectorIsNull( ent->v.angles ))
|
||||
{
|
||||
matrix4x4 imatrix;
|
||||
float *org = ent->v.origin;
|
||||
float *ang = ent->v.angles;
|
||||
|
||||
Matrix4x4_CreateFromEntity( matrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], 1.0f );
|
||||
Matrix4x4_Invert_Simple( imatrix, matrix );
|
||||
|
||||
Matrix4x4_VectorTransform( imatrix, start, start_l );
|
||||
Matrix4x4_VectorTransform( imatrix, end, end_l );
|
||||
#if 1
|
||||
// calc hull offsets (monsters use this)
|
||||
VectorCopy( start_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, vec3_origin, -1, hull->clip_mins, start_l );
|
||||
|
||||
VectorCopy( end_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, vec3_origin, -1, hull->clip_mins, end_l );
|
||||
#endif
|
||||
}
|
||||
|
||||
surf = SV_RecursiveSurfCheck( &bmodel->nodes[hull->firstclipnode], start_l, end_l );
|
||||
if( !surf ) return NULL;
|
||||
|
||||
return surf->texinfo->texture->name;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1044,7 +1124,7 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
Host_Error( "trigger in clipping list\n" );
|
||||
|
||||
// completely ignore all edicts but brushes
|
||||
if( clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP )
|
||||
if( clip->type == MOVE_NOMONSTERS && modType != mod_brush )
|
||||
continue;
|
||||
|
||||
if( clip->type == MOVE_WORLDONLY )
|
||||
|
|
Reference in New Issue