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 "edict.h"
|
||||||
#include "mathlib.h"
|
#include "mathlib.h"
|
||||||
|
|
||||||
int CM_RecursiveLightPoint( vec3_t color, mnode_t *node, const vec3_t start, const vec3_t end )
|
static vec3_t cm_pointColor;
|
||||||
{
|
static float cm_modulate;
|
||||||
float front, back, frac;
|
|
||||||
vec3_t mid;
|
|
||||||
|
|
||||||
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
|
// calculate mid point
|
||||||
if( node->plane->type < 3 )
|
plane = node->plane;
|
||||||
|
if( plane->type < 3 )
|
||||||
{
|
{
|
||||||
front = start[node->plane->type] - node->plane->dist;
|
front = start[plane->type] - plane->dist;
|
||||||
back = end[node->plane->type] - node->plane->dist;
|
back = end[plane->type] - plane->dist;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
front = DotProduct( start, node->plane->normal ) - node->plane->dist;
|
front = DotProduct( start, plane->normal ) - plane->dist;
|
||||||
back = DotProduct( end, node->plane->normal ) - node->plane->dist;
|
back = DotProduct( end, plane->normal ) - plane->dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized recursion
|
side = front < 0;
|
||||||
if(( back < 0 ) == ( front < 0 ))
|
if(( back < 0 ) == side )
|
||||||
{
|
return CM_RecursiveLightPoint( node->children[side], start, end );
|
||||||
node = node->children[front < 0];
|
|
||||||
goto loc0;
|
|
||||||
}
|
|
||||||
|
|
||||||
frac = front / ( front - back );
|
frac = front / ( front - back );
|
||||||
|
|
||||||
VectorLerp( start, frac, end, mid );
|
VectorLerp( start, frac, end, mid );
|
||||||
|
|
||||||
// go down front side
|
// co down front side
|
||||||
if( CM_RecursiveLightPoint( color, node->children[front < 0], start, mid ))
|
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
|
||||||
|
surf = node->firstface;
|
||||||
|
|
||||||
|
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||||
{
|
{
|
||||||
// hit something
|
tex = surf->texinfo;
|
||||||
|
|
||||||
|
if( surf->flags & SURF_DRAWTILED )
|
||||||
|
continue; // no lightmaps
|
||||||
|
|
||||||
|
s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0];
|
||||||
|
t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1];
|
||||||
|
|
||||||
|
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s >>= 4;
|
||||||
|
t >>= 4;
|
||||||
|
|
||||||
|
if( !surf->samples )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
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++ )
|
||||||
|
{
|
||||||
|
VectorScale( cm.lightstyle[surf->styles[map]].rgb, cm_modulate, scale );
|
||||||
|
|
||||||
|
cm_pointColor[0] += lm[0] * scale[0];
|
||||||
|
cm_pointColor[1] += lm[1] * scale[1];
|
||||||
|
cm_pointColor[2] += lm[2] * scale[2];
|
||||||
|
|
||||||
|
lm += size; // skip to next lightmap
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int i, ds, dt;
|
|
||||||
msurface_t *surf;
|
|
||||||
|
|
||||||
// check for impact on this node
|
// go down back side
|
||||||
for( i = 0, surf = node->firstface; i < node->numfaces; i++, surf++ )
|
return CM_RecursiveLightPoint( node->children[!side], mid, end );
|
||||||
{
|
|
||||||
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] );
|
|
||||||
|
|
||||||
if( ds < surf->texturemins[0] || dt < surf->texturemins[1] )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ds -= surf->texturemins[0];
|
|
||||||
dt -= surf->texturemins[1];
|
|
||||||
|
|
||||||
if( ds > surf->extents[0] || dt > surf->extents[1] )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( surf->samples )
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
line3 = ((surf->extents[0] >> 4) + 1) * 3;
|
|
||||||
lightmap = surf->samples + ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// go down back side
|
|
||||||
return CM_RecursiveLightPoint( color, node->children[front >= 0], mid, end );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CM_RunLightStyles( float time )
|
void CM_RunLightStyles( float time )
|
||||||
{
|
{
|
||||||
int i, ofs;
|
int i, ofs;
|
||||||
clightstyle_t *ls;
|
clightstyle_t *ls;
|
||||||
|
float l;
|
||||||
|
|
||||||
if( !sv_models[1] )
|
if( !worldmodel ) return;
|
||||||
return; // no world
|
|
||||||
|
|
||||||
// run lightstyles animation
|
// run lightstyles animation
|
||||||
ofs = (time * 10);
|
ofs = (time * 10);
|
||||||
|
@ -134,9 +117,11 @@ void CM_RunLightStyles( float time )
|
||||||
|
|
||||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||||
{
|
{
|
||||||
if( ls->length == 0 ) ls->value = 0.0f;
|
if( ls->length == 0 ) l = 0.0f;
|
||||||
else if( ls->length == 1 ) ls->value = ls->map[0];
|
else if( ls->length == 1 ) l = ls->map[0];
|
||||||
else ls->value = ls->map[ofs%ls->length];
|
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 ));
|
Mem_Set( cm.lightstyle, 0, sizeof( cm.lightstyle ));
|
||||||
|
|
||||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
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;
|
cm.lastofs = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +164,7 @@ grab the ambient lighting color for current point
|
||||||
*/
|
*/
|
||||||
int CM_LightEntity( edict_t *pEdict )
|
int CM_LightEntity( edict_t *pEdict )
|
||||||
{
|
{
|
||||||
vec3_t start, end, color;
|
vec3_t start, end;
|
||||||
|
|
||||||
if( !pEdict ) return 0;
|
if( !pEdict ) return 0;
|
||||||
if( pEdict->v.effects & EF_FULLBRIGHT || !worldmodel->lightdata )
|
if( pEdict->v.effects & EF_FULLBRIGHT || !worldmodel->lightdata )
|
||||||
|
@ -198,11 +183,12 @@ int CM_LightEntity( edict_t *pEdict )
|
||||||
VectorCopy( pEdict->v.origin, end );
|
VectorCopy( pEdict->v.origin, end );
|
||||||
|
|
||||||
if( pEdict->v.effects & EF_INVLIGHT )
|
if( pEdict->v.effects & EF_INVLIGHT )
|
||||||
end[2] = start[2] + 4096;
|
end[2] = start[2] + 8192;
|
||||||
else end[2] = start[2] - 4096;
|
else end[2] = start[2] - 8192;
|
||||||
|
VectorSet( cm_pointColor, 1.0f, 1.0f, 1.0f );
|
||||||
|
|
||||||
VectorClear( color );
|
cm_modulate = cm_lighting_modulate->value * (1.0 / 255);
|
||||||
CM_RecursiveLightPoint( color, worldmodel->nodes, start, end );
|
CM_RecursiveLightPoint( worldmodel->nodes, start, end );
|
||||||
|
|
||||||
return VectorAvg( color );
|
return VectorAvg( cm_pointColor );
|
||||||
}
|
}
|
|
@ -22,12 +22,13 @@
|
||||||
#define DVIS_PHS 1
|
#define DVIS_PHS 1
|
||||||
|
|
||||||
extern cvar_t *cm_novis;
|
extern cvar_t *cm_novis;
|
||||||
|
extern cvar_t *cm_lighting_modulate;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
float map[MAX_STRING];
|
float map[MAX_STRING];
|
||||||
float value; // current lightvalue
|
vec3_t rgb; // 0.0 - 2.0
|
||||||
} clightstyle_t;
|
} clightstyle_t;
|
||||||
|
|
||||||
typedef struct leaflist_s
|
typedef struct leaflist_s
|
||||||
|
@ -61,15 +62,9 @@ typedef struct clipmap_s
|
||||||
} clipmap_t;
|
} clipmap_t;
|
||||||
|
|
||||||
extern clipmap_t cm;
|
extern clipmap_t cm;
|
||||||
extern model_t *sv_models[MAX_MODELS]; // replacement client-server table
|
|
||||||
extern model_t *loadmodel;
|
extern model_t *loadmodel;
|
||||||
extern model_t *worldmodel;
|
extern model_t *worldmodel;
|
||||||
|
|
||||||
//
|
|
||||||
// cm_debug.c
|
|
||||||
//
|
|
||||||
void CM_DrawCollision( cmdraw_t callback );
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// cm_light.c
|
// cm_light.c
|
||||||
//
|
//
|
||||||
|
@ -78,13 +73,6 @@ void CM_SetLightStyle( int style, const char* val );
|
||||||
int CM_LightEntity( edict_t *pEdict );
|
int CM_LightEntity( edict_t *pEdict );
|
||||||
void CM_ClearLightStyles( void );
|
void CM_ClearLightStyles( void );
|
||||||
|
|
||||||
//
|
|
||||||
// cm_main.c
|
|
||||||
//
|
|
||||||
bool CM_InitPhysics( void );
|
|
||||||
void CM_Frame( float time );
|
|
||||||
void CM_FreePhysics( void );
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// cm_test.c
|
// cm_test.c
|
||||||
//
|
//
|
||||||
|
@ -93,7 +81,6 @@ byte *CM_LeafPHS( int leafnum );
|
||||||
int CM_PointLeafnum( const vec3_t p );
|
int CM_PointLeafnum( const vec3_t p );
|
||||||
mleaf_t *CM_PointInLeaf( const vec3_t p, mnode_t *node );
|
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_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 );
|
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_HullPointContents( hull_t *hull, int num, const vec3_t p );
|
||||||
int CM_PointContents( 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
|
// cm_model.c
|
||||||
//
|
//
|
||||||
void CM_FreeModels( void );
|
bool CM_InitPhysics( void );
|
||||||
int CM_NumBmodels( void );
|
void CM_FreePhysics( void );
|
||||||
script_t *CM_GetEntityScript( void );
|
script_t *CM_GetEntityScript( void );
|
||||||
void Mod_GetBounds( int handle, vec3_t mins, vec3_t maxs );
|
void Mod_GetBounds( int handle, vec3_t mins, vec3_t maxs );
|
||||||
void Mod_GetFrames( int handle, int *numFrames );
|
void Mod_GetFrames( int handle, int *numFrames );
|
||||||
modtype_t CM_GetModelType( int handle );
|
modtype_t CM_GetModelType( int handle );
|
||||||
model_t *CM_ClipHandleToModel( 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 );
|
void CM_BeginRegistration ( const char *name, bool clientload, uint *checksum );
|
||||||
bool CM_RegisterModel( const char *name, int sv_index );
|
bool CM_RegisterModel( const char *name, int sv_index );
|
||||||
void *Mod_Extradata( int handle );
|
void *Mod_Extradata( int handle );
|
||||||
model_t *CM_ModForName( const char *name, bool world );
|
|
||||||
void CM_EndRegistration( void );
|
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
|
#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;
|
clipmap_t cm;
|
||||||
|
|
||||||
byte *mod_base;
|
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_inline[MAX_MAP_MODELS]; // inline bsp models
|
||||||
static model_t cm_models[MAX_MODELS];
|
static model_t cm_models[MAX_MODELS];
|
||||||
static int cm_nummodels;
|
static int cm_nummodels;
|
||||||
|
|
||||||
mplane_t box_planes[6];
|
|
||||||
dclipnode_t box_clipnodes[6];
|
|
||||||
hull_t box_hull[1];
|
|
||||||
model_t *loadmodel;
|
model_t *loadmodel;
|
||||||
model_t *worldmodel;
|
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 )
|
script_t *CM_GetEntityScript( void )
|
||||||
{
|
{
|
||||||
string entfilename;
|
string entfilename;
|
||||||
|
@ -136,6 +55,71 @@ script_t *CM_GetEntityScript( void )
|
||||||
return cm.entityscript;
|
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
|
BSP_LoadVisibility
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void BSP_LoadVisibility( dlump_t *l )
|
static void BSP_LoadVisibility( dlump_t *l )
|
||||||
{
|
{
|
||||||
if( !l->filelen )
|
if( !l->filelen )
|
||||||
{
|
{
|
||||||
|
@ -653,7 +637,7 @@ void BSP_LoadVisibility( dlump_t *l )
|
||||||
BSP_LoadEntityString
|
BSP_LoadEntityString
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void BSP_LoadEntityString( dlump_t *l )
|
static void BSP_LoadEntityString( dlump_t *l )
|
||||||
{
|
{
|
||||||
byte *in;
|
byte *in;
|
||||||
|
|
||||||
|
@ -724,7 +708,7 @@ CM_MakeHull0
|
||||||
Duplicate the drawing hull structure as a clipping hull
|
Duplicate the drawing hull structure as a clipping hull
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void CM_MakeHull0( void )
|
static void CM_MakeHull0( void )
|
||||||
{
|
{
|
||||||
mnode_t *in, *child;
|
mnode_t *in, *child;
|
||||||
dclipnode_t *out;
|
dclipnode_t *out;
|
||||||
|
@ -757,7 +741,6 @@ void CM_MakeHull0( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CM_BrushModel
|
CM_BrushModel
|
||||||
|
@ -910,7 +893,100 @@ static void CM_SpriteModel( model_t *mod, byte *buffer )
|
||||||
loadmodel->maxs[2] = phdr->bounds[1] / 2;
|
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 )
|
if( worldmodel )
|
||||||
CM_FreeModel( &cm_models[0] );
|
CM_FreeModel( &cm_models[0] );
|
||||||
|
@ -923,14 +999,6 @@ void CM_FreeWorld( void )
|
||||||
worldmodel = NULL;
|
worldmodel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CM_FreeModels( void )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < cm_nummodels; i++ )
|
|
||||||
CM_FreeModel( &cm_models[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
CM_BeginRegistration
|
CM_BeginRegistration
|
||||||
|
@ -980,9 +1048,6 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
|
||||||
|
|
||||||
if( checksum ) *checksum = cm.checksum;
|
if( checksum ) *checksum = cm.checksum;
|
||||||
|
|
||||||
CM_BmodelInitBoxHull ();
|
|
||||||
CM_StudioInitBoxHull (); // hitbox tracing
|
|
||||||
|
|
||||||
CM_ClearLightStyles();
|
CM_ClearLightStyles();
|
||||||
CM_CalcPHS ();
|
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 )
|
bool CM_RegisterModel( const char *name, int index )
|
||||||
{
|
{
|
||||||
model_t *mod;
|
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 "matrix_lib.h"
|
||||||
#include "pm_local.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 t1, t2, frac;
|
||||||
float numerator = DotProduct( normal, org ) + d;
|
int side, ds, dt;
|
||||||
float denominator = DotProduct( normal, dir );
|
mplane_t *plane;
|
||||||
|
msurface_t *surf;
|
||||||
|
vec3_t mid;
|
||||||
|
int i;
|
||||||
|
|
||||||
if( fabs( denominator ) < EQUAL_EPSILON )
|
if( node->contents < 0 )
|
||||||
return -1.0f; // normal is orthogonal to vector, no intersection
|
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
|
PM_TraceTexture
|
||||||
|
|
||||||
find the face where the traceline hit
|
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 *surf;
|
||||||
msurface_t **mark, *surf, *hitface = NULL;
|
matrix4x4 matrix;
|
||||||
float d1, d2, min_diff = 9999.9f;
|
|
||||||
vec3_t forward, vecPos1, vecPos2;
|
|
||||||
model_t *bmodel;
|
model_t *bmodel;
|
||||||
mleaf_t *endleaf;
|
hull_t *hull;
|
||||||
mplane_t *plane;
|
vec3_t start_l, end_l;
|
||||||
pmtrace_t trace;
|
vec3_t temp, offset;
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !PM_TraceModel( pe, v1, vec3_origin, vec3_origin, v2, &trace, PM_STUDIO_IGNORE ))
|
|
||||||
return NULL; // not intersect
|
|
||||||
|
|
||||||
bmodel = pe->model;
|
bmodel = pe->model;
|
||||||
if( !bmodel || bmodel->type != mod_brush && bmodel->type != mod_world )
|
if( !bmodel || bmodel->type != mod_brush && bmodel->type != mod_world )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// making trace adjustments
|
hull = PM_HullForBsp( pe, vec3_origin, vec3_origin, offset );
|
||||||
VectorSubtract( v1, pe->origin, vecStartPos );
|
|
||||||
VectorSubtract( trace.endpos, pe->origin, trace.endpos );
|
VectorSubtract( start, offset, start_l );
|
||||||
|
VectorSubtract( end, offset, end_l );
|
||||||
|
|
||||||
// rotate start and end into the models frame of reference
|
// 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 );
|
Matrix4x4_Invert_Simple( imatrix, matrix );
|
||||||
|
|
||||||
VectorCopy( vecStartPos, temp );
|
Matrix4x4_VectorTransform( imatrix, start, start_l );
|
||||||
Matrix4x4_VectorTransform( imatrix, temp, vecStartPos );
|
Matrix4x4_VectorTransform( imatrix, end, end_l );
|
||||||
VectorCopy( trace.endpos, temp );
|
#if 1
|
||||||
Matrix4x4_VectorTransform( imatrix, temp, trace.endpos );
|
// 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 );
|
surf = PM_RecursiveSurfCheck( &bmodel->nodes[hull->firstclipnode], start_l, end_l );
|
||||||
VectorNormalize( forward );
|
if( !surf ) return NULL;
|
||||||
|
|
||||||
// nudge endpos back to can be trace face between two points
|
return surf->texinfo->texture->name;
|
||||||
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;
|
|
||||||
}
|
}
|
|
@ -183,30 +183,27 @@ hull_t *PM_HullForBsp( physent_t *pe, const vec3_t mins, const vec3_t maxs, floa
|
||||||
|
|
||||||
VectorSubtract( maxs, mins, size );
|
VectorSubtract( maxs, mins, size );
|
||||||
|
|
||||||
if( size[0] < 3 )
|
if( size[0] <= 8.0f )
|
||||||
{
|
{
|
||||||
// point hull
|
hull = &pe->model->hulls[0];
|
||||||
hull = &model->hulls[0];
|
VectorCopy( hull->clip_mins, offset );
|
||||||
}
|
|
||||||
else if( size[0] <= 36 )
|
|
||||||
{
|
|
||||||
if( size[2] <= 36 )
|
|
||||||
{
|
|
||||||
// head hull (ducked)
|
|
||||||
hull = &model->hulls[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// human hull
|
|
||||||
hull = &model->hulls[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// large hull
|
if( size[0] <= 36.0f )
|
||||||
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
|
// calculate an offset value to center the origin
|
||||||
VectorSubtract( hull->clip_mins, mins, offset );
|
VectorSubtract( hull->clip_mins, mins, offset );
|
||||||
VectorAdd( offset, pe->origin, offset );
|
VectorAdd( offset, pe->origin, 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
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\common\cm_debug.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\common\cm_light.c
|
SOURCE=.\common\cm_light.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\common\cm_main.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\common\cm_model.c
|
SOURCE=.\common\cm_model.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -198,18 +190,10 @@ SOURCE=.\common\cm_portals.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\common\cm_studio.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\common\cm_test.c
|
SOURCE=.\common\cm_test.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\common\cm_trace.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\common\con_utils.c
|
SOURCE=.\common\con_utils.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -270,10 +254,6 @@ SOURCE=.\common\pm_trace.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\common\pm_utils.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\server\sv_client.c
|
SOURCE=.\server\sv_client.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
|
@ -93,6 +93,13 @@ void Host_EndGame( const char *message, ... )
|
||||||
Host_AbortCurrentFrame ();
|
Host_AbortCurrentFrame ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Host_DrawDebugCollision( cmdraw_t drawPoly )
|
||||||
|
{
|
||||||
|
if( !drawPoly ) return;
|
||||||
|
|
||||||
|
// FIXME: get collision polys here
|
||||||
|
}
|
||||||
|
|
||||||
void Host_FreeRender( void )
|
void Host_FreeRender( void )
|
||||||
{
|
{
|
||||||
if( render_dll.link )
|
if( render_dll.link )
|
||||||
|
@ -116,7 +123,7 @@ bool Host_InitRender( void )
|
||||||
ri.UpdateScreen = SCR_UpdateScreen;
|
ri.UpdateScreen = SCR_UpdateScreen;
|
||||||
ri.StudioEvent = CL_StudioEvent;
|
ri.StudioEvent = CL_StudioEvent;
|
||||||
ri.StudioFxTransform = CL_StudioFxTransform;
|
ri.StudioFxTransform = CL_StudioFxTransform;
|
||||||
ri.ShowCollision = CM_DrawCollision;
|
ri.ShowCollision = Host_DrawDebugCollision;
|
||||||
ri.GetClientEdict = CL_GetEntityByIndex;
|
ri.GetClientEdict = CL_GetEntityByIndex;
|
||||||
ri.GetPlayerInfo = CL_GetPlayerInfo;
|
ri.GetPlayerInfo = CL_GetPlayerInfo;
|
||||||
ri.GetLocalPlayer = CL_GetLocalPlayer;
|
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 );
|
edict_t* pfnPEntityOfEntIndex( int iEntIndex );
|
||||||
int pfnIndexOfEdict( const edict_t *pEdict );
|
int pfnIndexOfEdict( const edict_t *pEdict );
|
||||||
void SV_UpdateBaseVelocity( edict_t *ent );
|
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 )
|
_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_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_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 );
|
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 );
|
trace_t SV_MoveToss( edict_t *tossent, edict_t *ignore );
|
||||||
void SV_LinkEdict( edict_t *ent, bool touch_triggers );
|
void SV_LinkEdict( edict_t *ent, bool touch_triggers );
|
||||||
void SV_TouchLinks( edict_t *ent, areanode_t *node );
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( VectorIsNAN( v1 ) || VectorIsNAN( v2 ))
|
return SV_TraceTexture( pTextureEntity, v1, 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -322,7 +322,7 @@ bool SV_SpawnServer( const char *mapname, const char *startspot )
|
||||||
com.sprintf( sv.configstrings[CS_MAPCHECKSUM], "%i", checksum );
|
com.sprintf( sv.configstrings[CS_MAPCHECKSUM], "%i", checksum );
|
||||||
sv.worldmodel = CM_ClipHandleToModel( 1 ); // get world pointer
|
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 );
|
com.sprintf( sv.configstrings[CS_MODELS+1+i], "*%i", i );
|
||||||
CM_RegisterModel( sv.configstrings[CS_MODELS+1+i], i+1 );
|
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
|
// animate lightstyles (used for GetEntityIllum)
|
||||||
CM_Frame( sv_time( ));
|
CM_RunLightStyles( sv.time );
|
||||||
|
|
||||||
// at end of frame kill all entities which supposed to it
|
// at end of frame kill all entities which supposed to it
|
||||||
SV_FreeOldEntities();
|
SV_FreeOldEntities();
|
||||||
|
|
|
@ -9,6 +9,12 @@
|
||||||
#include "pm_local.h"
|
#include "pm_local.h"
|
||||||
#include "matrix_lib.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
|
typedef struct moveclip_s
|
||||||
{
|
{
|
||||||
vec3_t boxmins, boxmaxs; // enclose the test object along entire move
|
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( hullNumber == -1 )
|
||||||
{
|
{
|
||||||
#if 0 // more precision but doesn't matched with HL gameplay
|
#ifdef HULL_AUTOSELECT
|
||||||
float curdiff;
|
float curdiff;
|
||||||
float lastdiff = 999;
|
float lastdiff = 999;
|
||||||
int i;
|
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;
|
hull_t *hull;
|
||||||
model_t *model;
|
model_t *model;
|
||||||
vec3_t size;
|
vec3_t size;
|
||||||
float curdiff, lastdiff = 999;
|
float curdiff = 0, lastdiff = 999;
|
||||||
int i, hullNumber = 0;
|
int i = 0, hullNumber = 0;
|
||||||
|
|
||||||
// decide which clipping hull to use, based on the size
|
// decide which clipping hull to use, based on the size
|
||||||
model = CM_ClipHandleToModel( ent->v.modelindex );
|
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 );
|
VectorSubtract( maxs, mins, size );
|
||||||
|
|
||||||
|
#ifdef HULL_AUTOSELECT // more precision but doesn't matched with HL gameplay
|
||||||
|
|
||||||
// select the hull automatically
|
// select the hull automatically
|
||||||
for( i = 0; i < 4; i++ )
|
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];
|
hull = &model->hulls[hullNumber];
|
||||||
|
|
||||||
// calculate an offset value to center the origin
|
// calculate an offset value to center the origin
|
||||||
VectorSubtract( hull->clip_mins, mins, offset );
|
// 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 );
|
VectorAdd( offset, ent->v.origin, offset );
|
||||||
|
|
||||||
return hull;
|
return hull;
|
||||||
|
@ -935,81 +965,131 @@ trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DESCRIPTION: SurfaceAtPoint
|
/*
|
||||||
// LOCATION:
|
==================
|
||||||
// PATH: TraceTexture, recursive
|
SV_RecursiveSurfCheck
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
*/
|
*/
|
||||||
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;
|
float t1, t2, frac;
|
||||||
int var_10, var_10_2;
|
int side, ds, dt;
|
||||||
mplane_t * var_14_plane;
|
mplane_t *plane;
|
||||||
vec3_t var_20;
|
msurface_t *surf;
|
||||||
msurface_t * var_24_surface;
|
vec3_t mid;
|
||||||
int var_28, var_2c;
|
int i;
|
||||||
int var_30, var_34;
|
|
||||||
int var_38;
|
|
||||||
mtexinfo_t * var_3C_texinfo;
|
|
||||||
|
|
||||||
|
if( node->contents < 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if(node->contents < 0) { return(NULL); }
|
plane = node->plane;
|
||||||
|
|
||||||
var_14_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;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
if( t1 >= 0 && t2 >= 0 )
|
||||||
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;
|
return SV_RecursiveSurfCheck( node->children[0], p1, p2 );
|
||||||
|
if( t1 < 0 && t2 < 0 )
|
||||||
|
return SV_RecursiveSurfCheck( node->children[1], p1, p2 );
|
||||||
|
|
||||||
if(var_4 < 0) { var_10 = 1; }
|
frac = t1 / ( t1 - t2 );
|
||||||
else { var_10 = 0; }
|
|
||||||
|
|
||||||
if(var_8 < 0) { var_10_2 = 1; }
|
if( frac < 0.0f ) frac = 0.0f;
|
||||||
else { var_10_2 = 0; }
|
if( frac > 1.0f ) frac = 1.0f;
|
||||||
|
|
||||||
if(var_10 == var_10_2) {
|
VectorLerp( p1, frac, p2, mid );
|
||||||
|
|
||||||
return(SV_RecursiveSurfCheck(model, node->children[var_10], v1, v2));
|
side = (t1 < 0);
|
||||||
}
|
|
||||||
|
|
||||||
var_c = var_4 / (var_4 - var_8);
|
// now this is weird.
|
||||||
|
surf = SV_RecursiveSurfCheck( node->children[side], p1, mid );
|
||||||
|
|
||||||
var_20[0] = ((v2[0] - v1[0]) * var_c) + v1[0];
|
if( surf != NULL || ( t1 >= 0 && t2 >= 0 ) || ( t1 < 0 && t2 < 0 ))
|
||||||
var_20[1] = ((v2[1] - v1[1]) * var_c) + v1[1];
|
{
|
||||||
var_20[2] = ((v2[2] - v1[2]) * var_c) + v1[2];
|
return surf;
|
||||||
|
}
|
||||||
|
|
||||||
//Now THIS is weird.
|
surf = node->firstface;
|
||||||
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.
|
|
||||||
|
|
||||||
|
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] );
|
||||||
|
|
||||||
var_24_surface = node->firstface;
|
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] )
|
||||||
|
{
|
||||||
|
int s = ds - surf->texturemins[0];
|
||||||
|
int t = dt - surf->texturemins[1];
|
||||||
|
|
||||||
for(var_38 = 0; var_38 < node->numfaces; var_38++, var_24_surface++) {
|
if( s <= surf->extents[0] && t <= surf->extents[1] )
|
||||||
|
return surf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var_3C_texinfo = var_24_surface->texinfo;
|
return SV_RecursiveSurfCheck( node->children[side^1], mid, p2 );
|
||||||
|
}
|
||||||
|
|
||||||
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];
|
==================
|
||||||
|
SV_TraceTexture
|
||||||
|
|
||||||
if(var_28 >= var_24_surface->texturemins[0] && var_2c >= var_24_surface->texturemins[1]) {
|
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;
|
||||||
|
|
||||||
var_30 = var_28 - var_24_surface->texturemins[0];
|
bmodel = CM_ClipHandleToModel( ent->v.modelindex );
|
||||||
var_34 = var_2c - var_24_surface->texturemins[1];
|
if( !bmodel || bmodel->type != mod_brush && bmodel->type != mod_world )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if(var_30 <= var_24_surface->extents[0] && var_34 <= var_24_surface->extents[1]) {
|
hull = SV_HullForBsp( ent, vec3_origin, vec3_origin, offset );
|
||||||
|
|
||||||
return(var_24_surface);
|
VectorSubtract( start, offset, start_l );
|
||||||
}
|
VectorSubtract( end, offset, end_l );
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(var_10 == 1) { var_10 = 0; }
|
// rotate start and end into the models frame of reference
|
||||||
else { var_10 = 1; }
|
if( !VectorIsNull( ent->v.angles ))
|
||||||
return(SV_RecursiveSurfCheck( model, node->children[var_10], var_20, v2 ));
|
{
|
||||||
|
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" );
|
Host_Error( "trigger in clipping list\n" );
|
||||||
|
|
||||||
// completely ignore all edicts but brushes
|
// 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;
|
continue;
|
||||||
|
|
||||||
if( clip->type == MOVE_WORLDONLY )
|
if( clip->type == MOVE_WORLDONLY )
|
||||||
|
|
Reference in New Issue