06 Jan 2019
This commit is contained in:
parent
073fa79bd4
commit
f838d648a7
|
@ -134,6 +134,8 @@ BRUSH MODELS
|
|||
#define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel
|
||||
#define TEX_SCROLL BIT( 6 ) // Doom special FX
|
||||
|
||||
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
|
||||
|
||||
// ambient sound types
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -109,6 +109,15 @@ typedef struct
|
|||
int reserved[32]; // just for future expansions or mod-makers
|
||||
} mfaceinfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mplane_t *edges;
|
||||
int numedges;
|
||||
vec3_t origin;
|
||||
vec_t radius; // for culling tests
|
||||
int contents; // sky or solid
|
||||
} mfacebevel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float vecs[2][4]; // [s/t] unit vectors in world space.
|
||||
|
@ -208,7 +217,7 @@ typedef struct mextrasurf_s
|
|||
// begin userdata
|
||||
struct msurface_s *lightmapchain; // lightmapped polys
|
||||
struct mextrasurf_s *detailchain; // for detail textures drawing
|
||||
struct mextrasurf_s *mirrorchain; // for gl_texsort drawing
|
||||
mfacebevel_t *bevel; // for exact face traceline
|
||||
struct mextrasurf_s *lumachain; // draw fullbrights
|
||||
struct cl_entity_s *parent; // upcast to owner entity
|
||||
|
||||
|
|
|
@ -112,6 +112,9 @@ void GL_ApplyTextureParams( gl_texture_t *tex )
|
|||
{
|
||||
vec4_t border = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
if( !glw_state.initialized )
|
||||
return;
|
||||
|
||||
Assert( tex != NULL );
|
||||
|
||||
// set texture filter
|
||||
|
@ -1085,6 +1088,10 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
|
|||
qboolean normalMap;
|
||||
const byte *bufend;
|
||||
|
||||
// dedicated server
|
||||
if( !glw_state.initialized )
|
||||
return true;
|
||||
|
||||
Assert( pic != NULL );
|
||||
Assert( tex != NULL );
|
||||
|
||||
|
@ -1210,6 +1217,7 @@ do specified actions on pixels
|
|||
*/
|
||||
static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
|
||||
{
|
||||
float emboss_scale = 0.0f;
|
||||
uint img_flags = 0;
|
||||
|
||||
// force upload texture as RGB or RGBA (detail textures requires this)
|
||||
|
@ -1255,8 +1263,12 @@ static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
|
|||
if( pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32 )
|
||||
img_flags |= IMAGE_FORCE_RGBA;
|
||||
|
||||
// dedicated server doesn't register this variable
|
||||
if( gl_emboss_scale != NULL )
|
||||
emboss_scale = gl_emboss_scale->value;
|
||||
|
||||
// processing image before uploading (force to rgba, make luma etc)
|
||||
if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags, gl_emboss_scale->value );
|
||||
if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags, emboss_scale );
|
||||
|
||||
if( FBitSet( tex->flags, TF_LUMINANCE ))
|
||||
ClearBits( pic->flags, IMAGE_HAS_COLOR );
|
||||
|
@ -1270,7 +1282,7 @@ GL_CheckTexName
|
|||
*/
|
||||
qboolean GL_CheckTexName( const char *name )
|
||||
{
|
||||
if( !COM_CheckString( name ) || !glw_state.initialized )
|
||||
if( !COM_CheckString( name ))
|
||||
return false;
|
||||
|
||||
// because multi-layered textures can exceed name string
|
||||
|
@ -1385,7 +1397,8 @@ static void GL_DeleteTexture( gl_texture_t *tex )
|
|||
if( tex->original )
|
||||
FS_FreeImage( tex->original );
|
||||
|
||||
pglDeleteTextures( 1, &tex->texnum );
|
||||
if( glw_state.initialized )
|
||||
pglDeleteTextures( 1, &tex->texnum );
|
||||
memset( tex, 0, sizeof( *tex ));
|
||||
}
|
||||
|
||||
|
@ -1643,6 +1656,7 @@ int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags
|
|||
}
|
||||
|
||||
GL_ProcessImage( tex, pic );
|
||||
|
||||
if( !GL_UploadTexture( tex, pic ))
|
||||
{
|
||||
memset( tex, 0, sizeof( gl_texture_t ));
|
||||
|
@ -1784,8 +1798,7 @@ GL_FreeTexture
|
|||
void GL_FreeTexture( GLenum texnum )
|
||||
{
|
||||
// number 0 it's already freed
|
||||
if( texnum <= 0 || !glw_state.initialized )
|
||||
return;
|
||||
if( texnum <= 0 ) return;
|
||||
|
||||
GL_DeleteTexture( &gl_textures[texnum] );
|
||||
}
|
||||
|
|
|
@ -151,11 +151,16 @@ void Image_Init( void )
|
|||
image.loadformats = load_game;
|
||||
image.saveformats = save_game;
|
||||
break;
|
||||
default: // all other instances not using imagelib
|
||||
image.cmd_flags = 0;
|
||||
case HOST_DEDICATED:
|
||||
image.cmd_flags = 0;
|
||||
image.loadformats = load_game;
|
||||
image.saveformats = save_null;
|
||||
break;
|
||||
default: // all other instances not using imagelib
|
||||
image.cmd_flags = 0;
|
||||
image.loadformats = load_null;
|
||||
image.saveformats = save_null;
|
||||
break;
|
||||
}
|
||||
|
||||
image.tempbuffer = NULL;
|
||||
|
|
|
@ -885,6 +885,59 @@ int Mod_SampleSizeForFace( msurface_t *surf )
|
|||
return LM_SAMPLE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Mod_GetFaceContents
|
||||
|
||||
determine face contents by name
|
||||
==================
|
||||
*/
|
||||
static int Mod_GetFaceContents( const char *name )
|
||||
{
|
||||
if( !Q_strnicmp( name, "SKY", 3 ))
|
||||
return CONTENTS_SKY;
|
||||
|
||||
if( name[0] == '!' || name[0] == '*' )
|
||||
{
|
||||
if( !Q_strnicmp( name + 1, "lava", 4 ))
|
||||
return CONTENTS_LAVA;
|
||||
else if( !Q_strnicmp( name + 1, "slime", 5 ))
|
||||
return CONTENTS_SLIME;
|
||||
return CONTENTS_WATER; // otherwise it's water
|
||||
}
|
||||
|
||||
if( !Q_strnicmp( name, "water", 5 ))
|
||||
return CONTENTS_WATER;
|
||||
|
||||
return CONTENTS_SOLID;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Mod_GetFaceContents
|
||||
|
||||
determine face contents by name
|
||||
==================
|
||||
*/
|
||||
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge )
|
||||
{
|
||||
int lindex;
|
||||
medge_t *edge;
|
||||
|
||||
lindex = mod->surfedges[surfedge];
|
||||
|
||||
if( lindex > 0 )
|
||||
{
|
||||
edge = &mod->edges[lindex];
|
||||
return &mod->vertexes[edge->v[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
edge = &mod->edges[-lindex];
|
||||
return &mod->vertexes[edge->v[1]];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Mod_MakeNormalAxial
|
||||
|
@ -1067,6 +1120,66 @@ static void Mod_CalcSurfaceBounds( msurface_t *surf )
|
|||
VectorAverage( surf->info->mins, surf->info->maxs, surf->info->origin );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_CreateFaceBevels
|
||||
=================
|
||||
*/
|
||||
static void Mod_CreateFaceBevels( msurface_t *surf )
|
||||
{
|
||||
vec3_t delta, edgevec;
|
||||
byte *facebevel;
|
||||
vec3_t faceNormal;
|
||||
mvertex_t *v0, *v1;
|
||||
int contents;
|
||||
int i, size;
|
||||
vec_t radius;
|
||||
mfacebevel_t *fb;
|
||||
|
||||
if( surf->texinfo && surf->texinfo->texture )
|
||||
contents = Mod_GetFaceContents( surf->texinfo->texture->name );
|
||||
else contents = CONTENTS_SOLID;
|
||||
|
||||
size = sizeof( mfacebevel_t ) + surf->numedges * sizeof( mplane_t );
|
||||
facebevel = (byte *)Mem_Calloc( loadmodel->mempool, size );
|
||||
fb = (mfacebevel_t *)facebevel;
|
||||
facebevel += sizeof( mfacebevel_t );
|
||||
fb->edges = (mplane_t *)facebevel;
|
||||
fb->numedges = surf->numedges;
|
||||
fb->contents = contents;
|
||||
surf->info->bevel = fb;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
VectorNegate( surf->plane->normal, faceNormal );
|
||||
else VectorCopy( surf->plane->normal, faceNormal );
|
||||
|
||||
// compute face origin and plane edges
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
mplane_t *dest = &fb->edges[i];
|
||||
|
||||
v0 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + i );
|
||||
v1 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + (i + 1) % surf->numedges );
|
||||
VectorSubtract( v1->position, v0->position, edgevec );
|
||||
CrossProduct( faceNormal, edgevec, dest->normal );
|
||||
VectorNormalize( dest->normal );
|
||||
dest->dist = DotProduct( dest->normal, v0->position );
|
||||
dest->type = PlaneTypeForNormal( dest->normal );
|
||||
VectorAdd( fb->origin, v0->position, fb->origin );
|
||||
}
|
||||
|
||||
VectorScale( fb->origin, 1.0f / surf->numedges, fb->origin );
|
||||
|
||||
// compute face radius
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
v0 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + i );
|
||||
VectorSubtract( v0->position, fb->origin, delta );
|
||||
radius = DotProduct( delta, delta );
|
||||
fb->radius = Q_max( radius, fb->radius );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_SetParent
|
||||
|
@ -1818,6 +1931,8 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
|||
|
||||
for( i = 0; i < loadmodel->numtextures; i++ )
|
||||
{
|
||||
int txFlags = 0;
|
||||
|
||||
if( in->dataofs[i] == -1 )
|
||||
{
|
||||
// create default texture (some mods requires this)
|
||||
|
@ -1845,6 +1960,9 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
|||
tx->width = mt->width;
|
||||
tx->height = mt->height;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ) && mt->name[0] == '{' )
|
||||
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
|
||||
|
||||
if( mt->offsets[0] > 0 )
|
||||
{
|
||||
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
|
||||
|
@ -1892,7 +2010,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
|||
|
||||
if( FS_FileExists( texpath, false ))
|
||||
{
|
||||
tx->gl_texturenum = GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS );
|
||||
tx->gl_texturenum = GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS|txFlags );
|
||||
bmod->wadlist.wadusage[j]++; // this wad are really used
|
||||
break;
|
||||
}
|
||||
|
@ -1908,14 +2026,13 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
|
|||
|
||||
if( custom_palette ) size += sizeof( short ) + 768;
|
||||
Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name );
|
||||
tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS );
|
||||
tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS|txFlags );
|
||||
}
|
||||
|
||||
// if texture is completely missed
|
||||
if( !tx->gl_texturenum )
|
||||
{
|
||||
if( host.type != HOST_DEDICATED )
|
||||
Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name );
|
||||
Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name );
|
||||
tx->gl_texturenum = tr.defaultTexture;
|
||||
}
|
||||
|
||||
|
@ -2210,6 +2327,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod )
|
|||
|
||||
Mod_CalcSurfaceBounds( out );
|
||||
Mod_CalcSurfaceExtents( out );
|
||||
Mod_CreateFaceBevels( out );
|
||||
|
||||
// grab the second sample to detect colored lighting
|
||||
if( test_lightsize > 0 && lightofs != -1 )
|
||||
|
|
|
@ -16,84 +16,153 @@ GNU General Public License for more details.
|
|||
#include "common.h"
|
||||
#include "mathlib.h"
|
||||
#include "pm_local.h"
|
||||
#include "gl_local.h"
|
||||
|
||||
#define FRAC_EPSILON (1.0f / 32.0f)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float fraction;
|
||||
int contents;
|
||||
float fraction;
|
||||
int contents;
|
||||
msurface_t *surface;
|
||||
} linetrace_t;
|
||||
|
||||
/*
|
||||
==============
|
||||
fix_coord
|
||||
|
||||
converts the reletive tex coords to absolute
|
||||
==============
|
||||
*/
|
||||
static uint fix_coord( vec_t in, uint width )
|
||||
{
|
||||
if( in > 0 ) return (uint)in % width;
|
||||
return width - ((uint)fabs( in ) % width);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SampleMiptex
|
||||
|
||||
fence texture testing
|
||||
=============
|
||||
*/
|
||||
int PM_SampleMiptex( const msurface_t *surf, const vec3_t point )
|
||||
{
|
||||
mextrasurf_t *info = surf->info;
|
||||
mfacebevel_t *fb = info->bevel;
|
||||
int contents;
|
||||
vec_t ds, dt;
|
||||
byte *data;
|
||||
int x, y;
|
||||
mtexinfo_t *tx;
|
||||
texture_t *mt;
|
||||
rgbdata_t *src;
|
||||
|
||||
// fill the default contents
|
||||
if( fb ) contents = fb->contents;
|
||||
else contents = CONTENTS_SOLID;
|
||||
|
||||
if( !surf->texinfo || !surf->texinfo->texture )
|
||||
return contents;
|
||||
|
||||
tx = surf->texinfo;
|
||||
mt = tx->texture;
|
||||
|
||||
if( mt->name[0] != '{' )
|
||||
return contents;
|
||||
|
||||
src = R_GetTexture( mt->gl_texturenum )->original;
|
||||
if( !src ) return contents; // original doesn't kept
|
||||
|
||||
ds = DotProduct( point, tx->vecs[0] ) + tx->vecs[0][3];
|
||||
dt = DotProduct( point, tx->vecs[1] ) + tx->vecs[1][3];
|
||||
|
||||
// convert ST to real pixels position
|
||||
x = fix_coord( ds, mt->width - 1 );
|
||||
y = fix_coord( dt, mt->height - 1 );
|
||||
|
||||
ASSERT( x >= 0 && y >= 0 );
|
||||
|
||||
data = src->buffer;
|
||||
if( data[(mt->width * y) + x] == 255 )
|
||||
return CONTENTS_EMPTY;
|
||||
return CONTENTS_SOLID;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
PM_RecursiveSurfCheck
|
||||
|
||||
==================
|
||||
*/
|
||||
msurface_t *PM_RecursiveSurfCheck( model_t *model, mnode_t *node, vec3_t p1, vec3_t p2 )
|
||||
msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_t p2 )
|
||||
{
|
||||
float t1, t2, frac;
|
||||
int side, ds, dt;
|
||||
mplane_t *plane;
|
||||
int i, side;
|
||||
msurface_t *surf;
|
||||
vec3_t mid;
|
||||
int i;
|
||||
|
||||
loc0:
|
||||
if( node->contents < 0 )
|
||||
return NULL;
|
||||
|
||||
plane = node->plane;
|
||||
t1 = PlaneDiff( p1, node->plane );
|
||||
t2 = PlaneDiff( p2, node->plane );
|
||||
|
||||
if( plane->type < 3 )
|
||||
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
|
||||
{
|
||||
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;
|
||||
node = node->children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( t1 >= 0.0f && t2 >= 0.0f )
|
||||
return PM_RecursiveSurfCheck( model, node->children[0], p1, p2 );
|
||||
if( t1 < 0.0f && t2 < 0.0f )
|
||||
return PM_RecursiveSurfCheck( model, node->children[1], p1, p2 );
|
||||
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
side = (t1 < 0.0f);
|
||||
frac = t1 / ( t1 - t2 );
|
||||
|
||||
if( frac < 0.0f ) frac = 0.0f;
|
||||
if( frac > 1.0f ) frac = 1.0f;
|
||||
frac = bound( 0.0f, frac, 1.0f );
|
||||
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
side = (t1 < 0.0f);
|
||||
|
||||
// now this is weird.
|
||||
surf = PM_RecursiveSurfCheck( model, node->children[side], p1, mid );
|
||||
|
||||
if( surf != NULL || ( t1 >= 0.0f && t2 >= 0.0f ) || ( t1 < 0.0f && t2 < 0.0f ))
|
||||
{
|
||||
if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
|
||||
return surf;
|
||||
}
|
||||
|
||||
surf = model->surfaces + node->firstsurface;
|
||||
|
||||
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
// walk through real faces
|
||||
for( i = 0; i < node->numsurfaces; i++ )
|
||||
{
|
||||
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] );
|
||||
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
|
||||
mextrasurf_t *info = surf->info;
|
||||
mfacebevel_t *fb = info->bevel;
|
||||
int j, contents;
|
||||
vec3_t delta;
|
||||
|
||||
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] )
|
||||
if( !fb ) continue; // ???
|
||||
|
||||
VectorSubtract( mid, fb->origin, delta );
|
||||
if( DotProduct( delta, delta ) >= fb->radius )
|
||||
continue; // no intersection
|
||||
|
||||
for( j = 0; j < fb->numedges; j++ )
|
||||
{
|
||||
int s = ds - surf->texturemins[0];
|
||||
int t = dt - surf->texturemins[1];
|
||||
|
||||
if( s <= surf->extents[0] && t <= surf->extents[1] )
|
||||
return surf;
|
||||
if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
|
||||
break; // outside the bounds
|
||||
}
|
||||
|
||||
if( j != fb->numedges )
|
||||
continue; // we are outside the bounds of the facet
|
||||
|
||||
// hit the surface
|
||||
contents = PM_SampleMiptex( surf, mid );
|
||||
|
||||
if( contents != CONTENTS_EMPTY )
|
||||
return surf;
|
||||
return NULL; // through the fence
|
||||
}
|
||||
|
||||
return PM_RecursiveSurfCheck( model, node->children[side^1], mid, p2 );
|
||||
return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -160,32 +229,34 @@ PM_TestLine_r
|
|||
optimized trace for light gathering
|
||||
==================
|
||||
*/
|
||||
int PM_TestLine_r( mnode_t *node, vec_t p1f, vec_t p2f, const vec3_t start, const vec3_t stop, linetrace_t *trace )
|
||||
int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, const vec3_t start, const vec3_t stop, linetrace_t *trace )
|
||||
{
|
||||
float front, back;
|
||||
float frac, midf;
|
||||
int r, side;
|
||||
int i, r, side;
|
||||
vec3_t mid;
|
||||
loc0:
|
||||
if( node->contents < 0 )
|
||||
trace->contents = node->contents;
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
return CONTENTS_SOLID;
|
||||
if( node->contents == CONTENTS_SKY )
|
||||
return CONTENTS_SKY;
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
// water, slime or lava interpret as empty
|
||||
if( node->contents == CONTENTS_SOLID )
|
||||
return CONTENTS_SOLID;
|
||||
if( node->contents == CONTENTS_SKY )
|
||||
return CONTENTS_SKY;
|
||||
trace->fraction = 1.0f;
|
||||
return CONTENTS_EMPTY;
|
||||
}
|
||||
|
||||
front = PlaneDiff( start, node->plane );
|
||||
back = PlaneDiff( stop, node->plane );
|
||||
|
||||
if( front >= -ON_EPSILON && back >= -ON_EPSILON )
|
||||
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( front < ON_EPSILON && back < ON_EPSILON )
|
||||
if( front < FRAC_EPSILON && back < FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[1];
|
||||
goto loc0;
|
||||
|
@ -198,15 +269,54 @@ loc0:
|
|||
VectorLerp( start, frac, stop, mid );
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
|
||||
r = PM_TestLine_r( node->children[side], p1f, midf, start, mid, trace );
|
||||
r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace );
|
||||
|
||||
if( r != CONTENTS_EMPTY )
|
||||
{
|
||||
trace->fraction = midf;
|
||||
if( trace->surface == NULL )
|
||||
trace->fraction = midf;
|
||||
trace->contents = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
return PM_TestLine_r( node->children[!side], midf, p2f, mid, stop, trace );
|
||||
// walk through real faces
|
||||
for( i = 0; i < node->numsurfaces; i++ )
|
||||
{
|
||||
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
|
||||
mextrasurf_t *info = surf->info;
|
||||
mfacebevel_t *fb = info->bevel;
|
||||
int j, contents;
|
||||
vec3_t delta;
|
||||
|
||||
if( !fb ) continue;
|
||||
|
||||
VectorSubtract( mid, fb->origin, delta );
|
||||
if( DotProduct( delta, delta ) >= fb->radius )
|
||||
continue; // no intersection
|
||||
|
||||
for( j = 0; j < fb->numedges; j++ )
|
||||
{
|
||||
if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
|
||||
break; // outside the bounds
|
||||
}
|
||||
|
||||
if( j != fb->numedges )
|
||||
continue; // we are outside the bounds of the facet
|
||||
|
||||
// hit the surface
|
||||
contents = PM_SampleMiptex( surf, mid );
|
||||
|
||||
// fill the trace and out
|
||||
trace->contents = contents;
|
||||
trace->fraction = midf;
|
||||
|
||||
if( contents != CONTENTS_EMPTY )
|
||||
trace->surface = surf;
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace );
|
||||
}
|
||||
|
||||
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )
|
||||
|
@ -221,18 +331,19 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
|
|||
|
||||
trace.contents = CONTENTS_EMPTY;
|
||||
trace.fraction = 1.0f;
|
||||
trace.surface = NULL;
|
||||
|
||||
for( i = 0; i < numents; i++ )
|
||||
{
|
||||
pe = &ents[i];
|
||||
|
||||
if( i != 0 && ( flags & PM_WORLD_ONLY ))
|
||||
if( i != 0 && FBitSet( flags, PM_WORLD_ONLY ))
|
||||
break;
|
||||
|
||||
if( !pe->model || pe->model->type != mod_brush || pe->solid != SOLID_BSP )
|
||||
continue;
|
||||
|
||||
if( pe->rendermode != kRenderNormal )
|
||||
if( FBitSet( flags, PM_GLASS_IGNORE ) && pe->rendermode != kRenderNormal )
|
||||
continue;
|
||||
|
||||
hull = &pe->model->hulls[0];
|
||||
|
@ -257,8 +368,9 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
|
|||
|
||||
trace_bbox.contents = CONTENTS_EMPTY;
|
||||
trace_bbox.fraction = 1.0f;
|
||||
trace_bbox.surface = NULL;
|
||||
|
||||
PM_TestLine_r( &pe->model->nodes[hull->firstclipnode], 0.0f, 1.0f, start_l, end_l, &trace_bbox );
|
||||
PM_TestLine_r( pe->model, &pe->model->nodes[hull->firstclipnode], 0.0f, 1.0f, start_l, end_l, &trace_bbox );
|
||||
|
||||
if( trace_bbox.contents != CONTENTS_EMPTY || trace_bbox.fraction < trace.fraction )
|
||||
{
|
||||
|
|
|
@ -339,6 +339,11 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3
|
|||
SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs );
|
||||
}
|
||||
|
||||
int SV_TestLine( const vec3_t start, const vec3_t end, int flags )
|
||||
{
|
||||
return PM_TestLineExt( svgame.pmove, svgame.pmove->physents, svgame.pmove->numphysent, start, end, flags );
|
||||
}
|
||||
|
||||
static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
|
||||
{
|
||||
return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL );
|
||||
|
|
Reference in New Issue