07 Mar 2017

This commit is contained in:
g-cont 2017-03-07 00:00:00 +03:00 committed by Alibek Omarov
parent 17d224208a
commit 14b954bb63
28 changed files with 1463 additions and 1300 deletions

View File

@ -221,7 +221,7 @@ public:
void Spawn( void );
void Think( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() | FCAP_DONT_SAVE | FCAP_IMPULSE_USE); }
virtual int ObjectCaps( void ) { return (CBaseEntity :: ObjectCaps() | FCAP_IMPULSE_USE); }
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
void Animate( float frames );

View File

@ -1059,6 +1059,7 @@ void CL_LinkPacketEntities( frame_t *frame )
#ifdef STUDIO_INTERPOLATION_FIX
if( ent->lastmove >= cl.time )
VectorCopy( ent->curstate.origin, ent->latched.prevorigin );
ent->curstate.movetype = MOVETYPE_STEP;
#else
if( ent->lastmove >= cl.time )
{
@ -1108,6 +1109,12 @@ void CL_LinkPacketEntities( frame_t *frame )
VectorCopy( ent->curstate.origin, ent->origin );
VectorCopy( ent->curstate.angles, ent->angles );
}
if( ent->model->type == mod_studio )
{
if( ent->curstate.movetype == MOVETYPE_STEP && FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ))
R_StudioLerpStepMovement( ent, cl.time, ent->origin, ent->angles );
}
}
if( !FBitSet( state->entityType, ENTITY_NORMAL ))

View File

@ -633,7 +633,7 @@ void CL_DrawScreenFade( void )
if( sf->fadeFlags & FFADE_MODULATE )
GL_SetRenderMode( kRenderTransAdd );
else GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( 0, 0, glState.width, glState.height, 0, 0, 1, 1, cls.fillImage );
R_DrawStretchPic( 0, 0, glState.width, glState.height, 0, 0, 1, 1, tr.whiteTexture );
pglColor4ub( 255, 255, 255, 255 );
}
@ -1189,7 +1189,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
}
// load new map sprite
if( CL_LoadHudSprite( name, &clgame.sprites[i], true, 0 ))
if( CL_LoadHudSprite( name, &clgame.sprites[i], type, 0 ))
{
if( i < ( MAX_IMAGES - 1 ))
clgame.sprites[i].needload = clgame.load_sequence;
@ -1451,7 +1451,7 @@ void CL_FillRGBA( int x, int y, int width, int height, int r, int g, int b, int
SPR_AdjustSize( (float *)&x, (float *)&y, (float *)&width, (float *)&height );
GL_SetRenderMode( kRenderTransAdd );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, cls.fillImage );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, tr.whiteTexture );
pglColor4ub( 255, 255, 255, 255 );
}
@ -2835,7 +2835,7 @@ void CL_FillRGBABlend( int x, int y, int width, int height, int r, int g, int b,
pglBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_ONE );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, cls.fillImage );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, tr.whiteTexture );
pglColor4ub( 255, 255, 255, 255 );
}
@ -4048,5 +4048,8 @@ qboolean CL_LoadProgs( const char *name )
CL_InitStudioAPI( );
// grab them from client.dll
cl_righthand = Cvar_Get( "cl_righthand", "0", FCVAR_ARCHIVE, "flip viewmodel (left to right)" );
return true;
}

View File

@ -522,7 +522,7 @@ static void pfnFillRGBA( int x, int y, int width, int height, int r, int g, int
a = bound( 0, a, 255 );
pglColor4ub( r, g, b, a );
GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, cls.fillImage );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, tr.whiteTexture );
pglColor4ub( 255, 255, 255, 255 );
}

View File

@ -600,12 +600,12 @@ void CL_WeaponAnim( int iAnim, int body )
view->curstate.rendermode = kRenderNormal;
view->curstate.renderamt = 255;
#if 1 // g-cont. for GlowShell testing
#if 0 // g-cont. for GlowShell testing
view->curstate.renderfx = kRenderFxGlowShell;
view->curstate.rendercolor.r = 255;
view->curstate.rendercolor.g = 128;
view->curstate.rendercolor.b = 0;
view->curstate.renderamt = 100;
view->curstate.renderamt = 150;
#endif
}

View File

@ -339,7 +339,7 @@ void CL_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_
}
}
static void CL_CopyEntityToPhysEnt( physent_t *pe, entity_state_t *state )
static void CL_CopyEntityToPhysEnt( physent_t *pe, entity_state_t *state, qboolean visent )
{
model_t *mod = Mod_Handle( state->modelindex );
@ -361,31 +361,26 @@ static void CL_CopyEntityToPhysEnt( physent_t *pe, entity_state_t *state )
pe->model = pe->studiomodel = NULL;
switch( state->solid )
VectorCopy( state->mins, pe->mins );
VectorCopy( state->maxs, pe->maxs );
if( state->solid == SOLID_BBOX )
{
case SOLID_NOT:
case SOLID_BSP:
pe->model = mod;
VectorClear( pe->mins );
VectorClear( pe->maxs );
break;
case SOLID_BBOX:
if( mod && mod->type == mod_studio && mod->flags & STUDIO_TRACE_HITBOX )
if( FBitSet( mod->flags, STUDIO_TRACE_HITBOX ))
pe->studiomodel = mod;
VectorCopy( state->mins, pe->mins );
VectorCopy( state->maxs, pe->maxs );
break;
case SOLID_CUSTOM:
pe->model = (mod->type == mod_brush) ? mod : NULL;
pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
VectorCopy( state->mins, pe->mins );
VectorCopy( state->maxs, pe->maxs );
break;
default:
pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
VectorCopy( state->mins, pe->mins );
VectorCopy( state->maxs, pe->maxs );
break;
}
else
{
if( pe->solid != SOLID_BSP && mod->type == mod_studio )
pe->studiomodel = mod;
else pe->model = mod;
}
// rare case: not solid entities in vistrace
if( visent && VectorIsNull( pe->mins ))
{
VectorCopy( mod->mins, pe->mins );
VectorCopy( mod->maxs, pe->maxs );
}
pe->info = state->number;
@ -458,7 +453,7 @@ void CL_AddLinksToPmove( frame_t *frame )
if(( model->hulls[1].firstclipnode || model->type == mod_studio ) && clgame.pmove->numvisent < MAX_PHYSENTS )
{
pe = &clgame.pmove->visents[clgame.pmove->numvisent];
CL_CopyEntityToPhysEnt( pe, state );
CL_CopyEntityToPhysEnt( pe, state, true );
clgame.pmove->numvisent++;
}
@ -482,7 +477,7 @@ void CL_AddLinksToPmove( frame_t *frame )
continue;
pe = &clgame.pmove->moveents[clgame.pmove->nummoveent];
CL_CopyEntityToPhysEnt( pe, state );
CL_CopyEntityToPhysEnt( pe, state, false );
clgame.pmove->nummoveent++;
}
else
@ -492,7 +487,7 @@ void CL_AddLinksToPmove( frame_t *frame )
continue;
pe = &clgame.pmove->physents[clgame.pmove->numphysent];
CL_CopyEntityToPhysEnt( pe, state );
CL_CopyEntityToPhysEnt( pe, state, false );
clgame.pmove->numphysent++;
}
}
@ -576,7 +571,7 @@ void CL_SetSolidPlayers( int playernum )
break;
pe = &clgame.pmove->physents[clgame.pmove->numphysent];
CL_CopyEntityToPhysEnt( pe, state );
CL_CopyEntityToPhysEnt( pe, state, false );
clgame.pmove->numphysent++;
// some fields needs to be override from cls.predicted_players
@ -715,15 +710,35 @@ pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags )
{
int old_usehull;
pmtrace_t tr;
old_usehull = clgame.pmove->usehull;
clgame.pmove->usehull = 2;
clgame.pmove->usehull = 2;
tr = PM_PlayerTraceExt( clgame.pmove, start, end, flags, clgame.pmove->numphysent, clgame.pmove->physents, -1, NULL );
clgame.pmove->usehull = old_usehull;
return tr;
}
/*
=============
CL_VisTraceLine
trace by visible objects (thats can be non-solid)
=============
*/
pmtrace_t CL_VisTraceLine( vec3_t start, vec3_t end, int flags )
{
int old_usehull;
pmtrace_t tr;
old_usehull = clgame.pmove->usehull;
clgame.pmove->usehull = 2;
tr = PM_PlayerTraceExt( clgame.pmove, start, end, flags, clgame.pmove->numvisent, clgame.pmove->visents, -1, NULL );
clgame.pmove->usehull = old_usehull;
return tr;
}
/*
=============
CL_GetWaterEntity

View File

@ -544,15 +544,12 @@ void SCR_InstallParticlePalette( void )
void SCR_RegisterTextures( void )
{
cls.fillImage = GL_LoadTexture( "*white", NULL, 0, TF_IMAGE, NULL ); // used for FillRGBA
cls.particleImage = GL_LoadTexture( "*particle", NULL, 0, TF_IMAGE, NULL );
// register gfx.wad images
cls.pauseIcon = GL_LoadTexture( "gfx.wad/paused.lmp", NULL, 0, TF_IMAGE, NULL );
if( cl_allow_levelshots->value )
cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE, NULL );
else cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE, NULL );
cls.tileImage = GL_LoadTexture( "gfx.wad/backtile.lmp", NULL, 0, TF_UNCOMPRESSED|TF_NOPICMIP|TF_NOMIPMAP, NULL );
cls.tileImage = GL_LoadTexture( "gfx.wad/backtile.lmp", NULL, 0, TF_IMAGE, NULL );
}
/*

View File

@ -94,27 +94,39 @@ int CL_FxBlend( cl_entity_t *e )
break;
// JAY: HACK for now -- not time based
case kRenderFxFadeSlow:
if( e->curstate.renderamt > 0 )
e->curstate.renderamt -= 1;
else e->curstate.renderamt = 0;
if( tr.frametime )
{
if( e->curstate.renderamt > 0 )
e->curstate.renderamt -= 1;
else e->curstate.renderamt = 0;
}
blend = e->curstate.renderamt;
break;
case kRenderFxFadeFast:
if( e->curstate.renderamt > 3 )
e->curstate.renderamt -= 4;
else e->curstate.renderamt = 0;
if( tr.frametime )
{
if( e->curstate.renderamt > 3 )
e->curstate.renderamt -= 4;
else e->curstate.renderamt = 0;
}
blend = e->curstate.renderamt;
break;
case kRenderFxSolidSlow:
if( e->curstate.renderamt < 255 )
e->curstate.renderamt += 1;
else e->curstate.renderamt = 255;
if( tr.frametime )
{
if( e->curstate.renderamt < 255 )
e->curstate.renderamt += 1;
else e->curstate.renderamt = 255;
}
blend = e->curstate.renderamt;
break;
case kRenderFxSolidFast:
if( e->curstate.renderamt < 252 )
e->curstate.renderamt += 4;
else e->curstate.renderamt = 255;
if( tr.frametime )
{
if( e->curstate.renderamt < 252 )
e->curstate.renderamt += 4;
else e->curstate.renderamt = 255;
}
blend = e->curstate.renderamt;
break;
case kRenderFxStrobeSlow:
@ -184,6 +196,9 @@ void CL_InitTempEnts( void )
{
cl_tempents = Mem_Alloc( cls.mempool, sizeof( TEMPENTITY ) * GI->max_tents );
CL_ClearTempEnts();
// load tempent sprites (glowshell, muzzleflashes etc)
CL_LoadClientSprites ();
}
/*
@ -2636,15 +2651,18 @@ void CL_UpdateFlashlight( cl_entity_t *ent )
VectorAdd( ent->origin, view_ofs, vecSrc );
VectorMA( vecSrc, FLASHLIGHT_DISTANCE, forward, vecEnd );
trace = CL_TraceLine( vecSrc, vecEnd, PM_STUDIO_BOX );
trace = CL_VisTraceLine( vecSrc, vecEnd, PM_STUDIO_BOX );
// update flashlight endpos
dl = CL_AllocDlight( ent->index );
if( trace.ent > 0 && clgame.pmove->physents[trace.ent].studiomodel )
VectorCopy( clgame.pmove->physents[trace.ent].origin, dl->origin );
#if 0
// g-cont. disabled until studio lighting will be finished
if( trace.ent > 0 && clgame.pmove->visents[trace.ent].studiomodel )
VectorCopy( clgame.pmove->visents[trace.ent].origin, dl->origin );
else VectorCopy( trace.endpos, dl->origin );
#else
VectorCopy( trace.endpos, dl->origin );
#endif
// compute falloff
falloff = trace.fraction * FLASHLIGHT_DISTANCE;
if( falloff < 500.0f ) falloff = 1.0f;

View File

@ -528,13 +528,10 @@ typedef struct
int lastoutgoingcommand; // sequence number of last outgoing command
int lastupdate_sequence; // prediction stuff
// internal images
int fillImage; // used for emulate FillRGBA to avoid wrong draw-sort
int particleImage; // built-in particle and sparks image
// game images
int pauseIcon; // draw 'paused' when game in-pause
int loadingBar; // 'loading' progress bar
int glowShell; // for renderFxGlowShell
int tileImage; // for draw any areas not covered by the refresh
int loadingBar; // 'loading' progress bar
cl_font_t creditsFont; // shared creditsfont
float latency; // rolling average of frame latencey (receivedtime - senttime) values.
@ -620,6 +617,7 @@ extern convar_t *cl_clockreset;
extern convar_t *cl_fixtimerate;
extern convar_t *gl_showtextures;
extern convar_t *cl_bmodelinterp;
extern convar_t *cl_righthand;
extern convar_t *cl_lw; // local weapons
extern convar_t *cl_showevents;
extern convar_t *scr_centertime;
@ -803,6 +801,7 @@ int CL_PointContents( const vec3_t p );
int CL_WaterEntity( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time );
pmtrace_t CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags );
void CL_MoveSpectatorCamera( void );
void CL_SetLastUpdate( void );

View File

@ -41,43 +41,43 @@ qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, uint clipflags )
if( r_nocull->value )
return false;
for( i = sizeof( RI.frustum ) / sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit<<=1, p++ )
for( i = sizeof( RI.frustum ) / sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit++, p++ )
{
if( !( clipflags & bit ))
if( !FBitSet( clipflags, BIT( bit )))
continue;
switch( p->signbits )
{
case 0:
if( p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist )
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 1:
if( p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist )
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 2:
if( p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist )
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 3:
if( p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist )
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
return true;
break;
case 4:
if( p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist )
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
case 5:
if( p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist )
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
case 6:
if( p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist )
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
case 7:
if( p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist )
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
return true;
break;
default:
@ -96,19 +96,22 @@ Returns true if the sphere is completely outside the frustum
*/
qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags )
{
uint i, bit;
const mplane_t *p;
uint i, bit;
const mplane_t *p;
// client.dll may use additional passes for render custom mirrors etc
if( r_nocull->value )
return false;
for( i = sizeof( RI.frustum ) / sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit<<=1, p++ )
for( i = sizeof( RI.frustum ) / sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit++, p++ )
{
if(!( clipflags & bit )) continue;
if( !FBitSet( clipflags, BIT( bit )))
continue;
if( DotProduct( centre, p->normal ) - p->dist <= -radius )
return true;
}
return false;
}
@ -117,30 +120,35 @@ qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipf
R_CullModel
=============
*/
int R_CullModel( cl_entity_t *e, vec3_t origin, vec3_t mins, vec3_t maxs, float radius )
int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax )
{
if( e == &clgame.viewent )
{
if( RI.params & RP_NONVIEWERREF )
if( CL_IsDevOverviewMode( ))
return 1;
return 0;
if( RP_NORMALPASS() && !RI.thirdPerson && cl.viewentity == ( cl.playernum + 1 ))
return 0;
return 1;
}
// don't reflect this entity in mirrors
if( e->curstate.effects & EF_NOREFLECT && RI.params & RP_MIRRORVIEW )
if( FBitSet( e->curstate.effects, EF_NOREFLECT ) && FBitSet( RI.params, RP_MIRRORVIEW ))
return 1;
// draw only in mirrors
if( e->curstate.effects & EF_REFLECTONLY && !( RI.params & RP_MIRRORVIEW ))
if( FBitSet( e->curstate.effects, EF_REFLECTONLY ) && !FBitSet( RI.params, RP_MIRRORVIEW ))
return 1;
// local client can't view himself if camera or thirdperson is not active
if( RP_LOCALCLIENT( e ) && !RI.thirdPerson && cl.viewentity == ( cl.playernum + 1 ))
{
if(!( RI.params & RP_MIRRORVIEW ))
if( !FBitSet( RI.params, RP_MIRRORVIEW ))
return 1;
}
if( R_CullSphere( origin, radius, RI.clipFlags ))
if( R_CullBox( absmin, absmax, RI.clipFlags ))
return 1;
return 0;

View File

@ -18,27 +18,16 @@ GNU General Public License for more details.
#include "gl_local.h"
#include "studio.h"
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2)
static gltexture_t r_textures[MAX_TEXTURES];
static gltexture_t *r_texturesHashTable[TEXTURES_HASH_SIZE];
static int r_numTextures;
static byte data2D[BLOCK_SIZE_MAX*BLOCK_SIZE_MAX*4]; // intermediate texbuffer
static int r_numTextures;
static rgbdata_t r_image; // generic pixelbuffer used for internal textures
// internal tables
static vec3_t r_luminanceTable[256]; // RGB to luminance
static byte r_particleTexture[8][8] =
{
{0,0,0,0,0,0,0,0},
{0,0,0,1,1,0,0,0},
{0,0,0,1,1,0,0,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,0,0,1,1,0,0,0},
{0,0,0,1,1,0,0,0},
{0,0,0,0,0,0,0,0},
};
static vec3_t r_luminanceTable[256]; // RGB to luminance
/*
=================
@ -1896,71 +1885,6 @@ static rgbdata_t *R_InitDefaultTexture( texFlags_t *flags )
return &r_image;
}
/*
==================
R_InitParticleTexture
==================
*/
static rgbdata_t *R_InitParticleTexture( texFlags_t *flags )
{
int x, y;
int dx2, dy, d;
// particle texture
r_image.width = r_image.height = 16;
r_image.buffer = data2D;
r_image.flags = (IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA);
r_image.type = PF_RGBA_32;
r_image.size = r_image.width * r_image.height * 4;
*flags = TF_NOPICMIP|TF_NOMIPMAP;
for( x = 0; x < 16; x++ )
{
dx2 = x - 8;
dx2 = dx2 * dx2;
for( y = 0; y < 16; y++ )
{
dy = y - 8;
d = 255 - 35 * sqrt( dx2 + dy * dy );
data2D[( y*16 + x ) * 4 + 3] = bound( 0, d, 255 );
}
}
return &r_image;
}
/*
==================
R_InitParticleTexture2
==================
*/
static rgbdata_t *R_InitParticleTexture2( texFlags_t *flags )
{
int x, y;
// particle texture
r_image.width = r_image.height = 8;
r_image.buffer = data2D;
r_image.flags = (IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA);
r_image.type = PF_RGBA_32;
r_image.size = r_image.width * r_image.height * 4;
*flags = TF_NOPICMIP|TF_NOMIPMAP;
for( x = 0; x < 8; x++ )
{
for( y = 0; y < 8; y++ )
{
data2D[(y * 8 + x) * 4 + 0] = 255;
data2D[(y * 8 + x) * 4 + 1] = 255;
data2D[(y * 8 + x) * 4 + 2] = 255;
data2D[(y * 8 + x) * 4 + 3] = r_particleTexture[x][y] * 255;
}
}
return &r_image;
}
/*
==================
R_InitSkyTexture
@ -2477,8 +2401,6 @@ static void R_InitBuiltinTextures( void )
{ "*white", &tr.whiteTexture, R_InitWhiteTexture },
{ "*gray", &tr.grayTexture, R_InitGrayTexture },
{ "*black", &tr.blackTexture, R_InitBlackTexture },
{ "*particle", &tr.particleTexture, R_InitParticleTexture },
{ "*particle2", &tr.particleTexture2, R_InitParticleTexture2 },
{ "*cintexture", &tr.cinTexture, R_InitCinematicTexture }, // force linear filter
{ "*dlight", &tr.dlightTexture, R_InitDlightTexture },
{ "*dlight2", &tr.dlightTexture2, R_InitDlightTexture2 },

View File

@ -162,8 +162,6 @@ typedef struct
int grayTexture;
int blackTexture;
int defaultTexture; // use for bad textures
int particleTexture; // particle texture
int particleTexture2; // unsmoothed particle texture
int solidskyTexture; // quake1 solid-sky layer
int alphaskyTexture; // quake1 alpha-sky layer
int lightmapTextures[MAX_LIGHTMAPS];
@ -213,6 +211,7 @@ typedef struct
float lightcache[MAX_LIGHTSTYLES];
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
float blend; // global blend value
// cull info
vec3_t modelorg; // relative to viewpoint
@ -279,7 +278,7 @@ void R_ShowTextures( void );
//
// gl_cull.c
//
int R_CullModel( cl_entity_t *e, vec3_t origin, vec3_t mins, vec3_t maxs, float radius );
int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax );
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, uint clipflags );
qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags );
qboolean R_CullSurface( msurface_t *surf, uint clipflags );
@ -342,8 +341,8 @@ void R_PushDlights( void );
void R_AnimateLight( void );
void R_GetLightSpot( vec3_t lightspot );
void R_MarkLights( dlight_t *light, int bit, mnode_t *node );
void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius );
void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, qboolean useAmbient, float radius );
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot );
int R_CountSurfaceDlights( msurface_t *surf );
int R_CountDlights( void );
@ -417,6 +416,7 @@ void R_DrawSpriteModel( cl_entity_t *e );
//
void R_StudioInit( void );
void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded );
void R_StudioLerpStepMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles );
struct mstudiotex_s *R_StudioGetTexture( cl_entity_t *e );
float CL_GetStudioEstimatedFrame( cl_entity_t *ent );
void R_DrawStudioModel( cl_entity_t *e );
@ -666,13 +666,12 @@ extern convar_t *r_detailtextures;
extern convar_t *r_faceplanecull;
extern convar_t *r_drawentities;
extern convar_t *r_adjust_fov;
extern convar_t *r_lefthand;
extern convar_t *r_flaresize;
extern convar_t *r_decals;
extern convar_t *r_novis;
extern convar_t *r_nocull;
extern convar_t *r_lockpvs;
extern convar_t *r_lockcull;
extern convar_t *r_lockfrustum;
extern convar_t *r_dynamic;
extern convar_t *r_lightmap;
extern convar_t *r_fastsky;

View File

@ -226,17 +226,17 @@ int R_CountSurfaceDlights( msurface_t *surf )
=======================================================================
*/
static uint r_pointColor[3];
static vec3_t r_lightSpot;
static float g_trace_fraction;
static vec3_t g_trace_lightspot;
/*
=================
R_RecursiveLightPoint
=================
*/
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3_t start, const vec3_t end )
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, colorVec *cv, const vec3_t start, const vec3_t end )
{
float front, back, frac;
float front, back, frac, midf;
int i, map, side, size, s, t;
int sample_size;
msurface_t *surf;
@ -246,7 +246,10 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3
// didn't hit anything
if( !node || node->contents < 0 )
{
cv->r = cv->g = cv->b = cv->a = 0;
return false;
}
// calculate mid point
front = PlaneDiff( start, node->plane );
@ -254,24 +257,27 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3
side = front < 0;
if(( back < 0 ) == side )
return R_RecursiveLightPoint( model, node->children[side], start, end );
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end );
frac = front / ( front - back );
VectorLerp( start, frac, end, mid );
midf = p1f + ( p2f - p1f ) * frac;
// co down front side
if( R_RecursiveLightPoint( model, node->children[side], start, mid ))
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid ))
return true; // hit something
if(( back < 0 ) == side )
return false;// didn't hit anything
VectorCopy( mid, r_lightSpot );
{
cv->r = cv->g = cv->b = cv->a = 0;
return false; // didn't hit anything
}
// check for impact on this node
surf = model->surfaces + node->firstsurface;
sample_size = Mod_SampleSizeForFace( surf );
VectorCopy( mid, g_trace_lightspot );
for( i = 0; i < node->numsurfaces; i++, surf++ )
{
@ -289,29 +295,31 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3
s /= sample_size;
t /= sample_size;
cv->r = cv->g = cv->b = cv->a = 0;
if( !surf->samples )
return true;
VectorClear( r_pointColor );
lm = surf->samples + (t * ((surf->extents[0] / sample_size) + 1) + s);
size = ((surf->extents[0] / sample_size) + 1) * ((surf->extents[1] / sample_size) + 1);
size = ((surf->extents[0] / sample_size) + 1) * ((surf->extents[1] / sample_size) + 1);
g_trace_fraction = midf;
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
{
uint scale = tr.lightstylevalue[surf->styles[map]];
r_pointColor[0] += TextureToTexGamma( lm->r ) * scale;
r_pointColor[1] += TextureToTexGamma( lm->g ) * scale;
r_pointColor[2] += TextureToTexGamma( lm->b ) * scale;
cv->r += TextureToTexGamma( lm->r ) * scale;
cv->g += TextureToTexGamma( lm->g ) * scale;
cv->b += TextureToTexGamma( lm->b ) * scale;
lm += size; // skip to next lightmap
}
return true;
}
// go down back side
return R_RecursiveLightPoint( model, node->children[!side], mid, end );
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end );
}
int R_LightTraceFilter( physent_t *pe )
@ -331,6 +339,7 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
{
dlight_t *dl;
pmtrace_t trace;
colorVec light;
cl_entity_t *m_pGround;
vec3_t start, end, dir;
qboolean secondpass = false;
@ -405,13 +414,11 @@ get_light:
VectorCopy( end_l, end );
}
VectorClear( r_pointColor );
if( R_RecursiveLightPoint( pmodel, pnodes, start, end ))
if( R_RecursiveLightPoint( pmodel, pnodes, 0.0f, 1.0f, &light, start, end ))
{
ambientLight->r = min((r_pointColor[0] >> 7), 255 );
ambientLight->g = min((r_pointColor[1] >> 7), 255 );
ambientLight->b = min((r_pointColor[2] >> 7), 255 );
ambientLight->r = Q_min(( light.r >> 7 ), 255 );
ambientLight->g = Q_min(( light.g >> 7 ), 255 );
ambientLight->b = Q_min(( light.b >> 7 ), 255 );
}
else
{
@ -439,7 +446,7 @@ get_light:
int lnum, total;
float f;
VectorClear( r_pointColor );
light.r = light.g = light.b = light.a = 0;
for( total = lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ )
{
@ -453,87 +460,101 @@ get_light:
continue;
add = 1.0f - (dist / ( dl->radius + radius ));
r_pointColor[0] += TextureToTexGamma( dl->color.r ) * add;
r_pointColor[1] += TextureToTexGamma( dl->color.g ) * add;
r_pointColor[2] += TextureToTexGamma( dl->color.b ) * add;
light.r += TextureToTexGamma( dl->color.r ) * add;
light.g += TextureToTexGamma( dl->color.g ) * add;
light.b += TextureToTexGamma( dl->color.b ) * add;
total++;
}
if( total != 0 )
{
r_pointColor[0] += ambientLight->r;
r_pointColor[1] += ambientLight->g;
r_pointColor[2] += ambientLight->b;
light.r += ambientLight->r;
light.g += ambientLight->g;
light.b += ambientLight->b;
f = max( max( r_pointColor[0], r_pointColor[1] ), r_pointColor[2] );
if( f > 1.0f ) VectorScale( r_pointColor, ( 255.0f / f ), r_pointColor );
f = max( max( light.r, light.g ), light.b );
if( f > 1.0f )
{
light.r *= (255.0f / f);
light.r *= (255.0f / f);
light.r *= ( 255.0f / f);
}
ambientLight->r = r_pointColor[0];
ambientLight->g = r_pointColor[1];
ambientLight->b = r_pointColor[2];
ambientLight->r = light.r;
ambientLight->g = light.g;
ambientLight->b = light.b;
}
}
}
/*
=================
R_GetLightSpot
R_LightVec
NOTE: must call R_LightForPoint first
check bspmodels to get light from
=================
*/
void R_GetLightSpot( vec3_t lightspot )
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot )
{
if( lightspot ) VectorCopy( r_lightSpot, lightspot );
}
float last_fraction;
int i, maxEnts = 1;
colorVec light, cv;
/*
=================
R_LightDir
=================
*/
void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius )
{
dlight_t *dl;
vec3_t dir, local;
float dist;
int lnum;
VectorClear( local );
// add dynamic lights
if( radius > 0.0f && r_dynamic->value )
if( cl.worldmodel->lightdata )
{
for( lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ )
light.r = light.b = light.b = light.a = 0;
last_fraction = 1.0f;
// get light from bmodels too
if( r_lighting_extended->value )
maxEnts = clgame.pmove->numphysent;
// check al the bsp-models
for( i = 0; i < maxEnts; i++ )
{
if( dl->die < cl.time || !dl->radius )
continue;
physent_t *pe = &clgame.pmove->physents[i];
vec3_t offset, start_l, end_l;
mnode_t *pnodes;
matrix4x4 matrix;
VectorSubtract( dl->origin, origin, dir );
dist = VectorLength( dir );
if( !pe->model || pe->model->type != mod_brush )
continue; // skip non-bsp models
if( !dist || dist > dl->radius + radius )
continue;
VectorAdd( local, dir, local );
}
pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset );
VectorAdd( offset, pe->origin, offset );
VectorSubtract( start, offset, start_l );
VectorSubtract( end, offset, end_l );
for( lnum = 0, dl = cl_elights; lnum < MAX_ELIGHTS; lnum++, dl++ )
{
if( dl->die < cl.time || !dl->radius )
continue;
// rotate start and end into the models frame of reference
if( !VectorIsNull( pe->angles ))
{
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
Matrix4x4_VectorITransform( matrix, start, start_l );
Matrix4x4_VectorITransform( matrix, end, end_l );
}
VectorSubtract( dl->origin, origin, dir );
dist = VectorLength( dir );
VectorClear( g_trace_lightspot );
g_trace_fraction = 1.0f;
if( !dist || dist > dl->radius + radius )
continue;
VectorAdd( local, dir, local );
}
if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l ))
continue; // didn't hit anything
if( !VectorIsNull( local ))
{
VectorNormalize( local );
VectorCopy( local, lightDir );
if( g_trace_fraction < last_fraction )
{
if( lspot ) VectorCopy( g_trace_lightspot, lspot );
light.r = Q_min(( cv.r >> 7 ), 255 );
light.g = Q_min(( cv.g >> 7 ), 255 );
light.b = Q_min(( cv.b >> 7 ), 255 );
last_fraction = g_trace_fraction;
}
}
}
else
{
light.r = light.g = light.b = 255;
light.a = 0;
}
return light;
}

View File

@ -283,8 +283,6 @@ qboolean R_AddEntity( struct cl_entity_s *clent, int type )
if( clent->curstate.effects & EF_NODRAW )
return false; // done
clent->curstate.renderamt = CL_FxBlend( clent );
if( clent->curstate.rendermode != kRenderNormal && clent->curstate.renderamt <= 0.0f )
return true; // invisible
@ -451,7 +449,7 @@ void R_SetupFrustum( void )
// build the transformation matrix for the given view angles
AngleVectors( RI.viewangles, RI.vforward, RI.vright, RI.vup );
if( !r_lockcull->value )
if( !r_lockfrustum->value )
{
VectorCopy( RI.vieworg, RI.cullorigin );
VectorCopy( RI.vforward, RI.cull_vforward );
@ -914,6 +912,7 @@ void R_DrawEntitiesOnList( void )
int i;
glState.drawTrans = false;
tr.blend = 1.0f;
// draw the solid submodels fog
R_DrawFog ();
@ -966,6 +965,8 @@ void R_DrawEntitiesOnList( void )
{
RI.currententity = tr.trans_entities[i];
RI.currentmodel = RI.currententity->model;
tr.blend = CL_FxBlend( RI.currententity ) / 255.0f;
if( tr.blend <= 0.0f ) continue;
ASSERT( RI.currententity != NULL );
ASSERT( RI.currententity->model != NULL );

View File

@ -1485,7 +1485,7 @@ void R_DrawBrushModel( cl_entity_t *e )
case kRenderTransTexture:
need_sort = true;
case kRenderGlow:
pglColor4ub( 255, 255, 255, e->curstate.renderamt );
pglColor4f( 1.0f, 1.0f, 1.0f, tr.blend );
break;
case kRenderTransColor:
pglDisable( GL_TEXTURE_2D );
@ -1929,6 +1929,7 @@ void R_DrawWorld( void )
GL_SetRenderMode( kRenderNormal );
gl_lms.dynamic_surfaces = NULL;
tr.blend = 1.0f;
R_ClearSkyBox ();

View File

@ -29,9 +29,8 @@ GNU General Public License for more details.
convar_t *r_sprite_lerping;
convar_t *r_sprite_lighting;
char group_suffix[8];
static vec3_t sprite_mins, sprite_maxs;
static float sprite_radius;
static uint r_texFlags = 0;
float sprite_radius;
/*
====================
@ -710,41 +709,6 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe,
return lerpFrac;
}
/*
================
R_StudioComputeBBox
Compute a full bounding box for current sequence
================
*/
qboolean R_SpriteComputeBBox( cl_entity_t *e, vec3_t bbox[8] )
{
float scale = 1.0f;
vec3_t p1;
int i;
// copy original bbox (no rotation for sprites)
VectorCopy( e->model->mins, sprite_mins );
VectorCopy( e->model->maxs, sprite_maxs );
// compute a full bounding box
for( i = 0; bbox && i < 8; i++ )
{
p1[0] = ( i & 1 ) ? sprite_mins[0] : sprite_maxs[0];
p1[1] = ( i & 2 ) ? sprite_mins[1] : sprite_maxs[1];
p1[2] = ( i & 4 ) ? sprite_mins[2] : sprite_maxs[2];
VectorCopy( p1, bbox[i] );
}
if( e->curstate.scale > 0.0f )
scale = e->curstate.scale;
sprite_radius = RadiusFromBounds( sprite_mins, sprite_maxs ) * scale;
return true;
}
/*
================
R_CullSpriteModel
@ -754,16 +718,25 @@ Cull sprite model by bbox
*/
qboolean R_CullSpriteModel( cl_entity_t *e, vec3_t origin )
{
vec3_t sprite_mins, sprite_maxs;
float scale = 1.0f;
if( !e->model->cache.data )
return true;
if( e == &clgame.viewent && r_lefthand->value >= 2 )
return true;
if( e->curstate.scale > 0.0f )
scale = e->curstate.scale;
if( !R_SpriteComputeBBox( e, NULL ))
return true; // invalid frame
// scale original bbox (no rotation for sprites)
VectorScale( e->model->mins, scale, sprite_mins );
VectorScale( e->model->maxs, scale, sprite_maxs );
return R_CullModel( e, origin, sprite_mins, sprite_maxs, sprite_radius );
sprite_radius = RadiusFromBounds( sprite_mins, sprite_maxs );
VectorAdd( sprite_mins, origin, sprite_mins );
VectorAdd( sprite_maxs, origin, sprite_maxs );
return R_CullModel( e, sprite_mins, sprite_maxs );
}
/*

File diff suppressed because it is too large Load Diff

View File

@ -66,12 +66,11 @@ convar_t *r_faceplanecull;
convar_t *r_drawentities;
convar_t *r_adjust_fov;
convar_t *r_flaresize;
convar_t *r_lefthand;
convar_t *r_decals;
convar_t *r_novis;
convar_t *r_nocull;
convar_t *r_lockpvs;
convar_t *r_lockcull;
convar_t *r_lockfrustum;
convar_t *r_dynamic;
convar_t *r_lightmap;
convar_t *r_fastsky;
@ -1749,13 +1748,12 @@ void GL_InitCommands( void )
r_faceplanecull = Cvar_Get( "r_faceplanecull", "1", 0, "ignore face plane culling (perfomance test)" );
r_detailtextures = Cvar_Get( "r_detailtextures", "1", FCVAR_ARCHIVE, "enable detail textures support, use '2' for autogenerate detail.txt" );
r_lockpvs = Cvar_Get( "r_lockpvs", "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" );
r_lockcull = Cvar_Get( "r_lockcull", "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
r_lockfrustum = Cvar_Get( "r_lockfrustum", "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
r_dynamic = Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
r_lightmap = Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" );
r_fastsky = Cvar_Get( "r_fastsky", "0", FCVAR_ARCHIVE, "enable algorhytm fo fast sky rendering (for old machines)" );
r_drawentities = Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT|FCVAR_ARCHIVE, "render entities" );
r_flaresize = Cvar_Get( "r_flaresize", "200", FCVAR_ARCHIVE, "set flares size" );
r_lefthand = Cvar_Get( "hand", "0", FCVAR_ARCHIVE, "viewmodel handedness" );
r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
r_xpos = Cvar_Get( "r_xpos", "130", FCVAR_RENDERINFO, "window position by horizontal" );
r_ypos = Cvar_Get( "r_ypos", "48", FCVAR_RENDERINFO, "window position by vertical" );

View File

@ -135,7 +135,7 @@ void VGUI_CreateTexture( int id, int width, int height )
void VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
{
if( id <= 0 || id >= VGUI_MAX_TEXTURES || g_textures[id] == 0 || g_textures[id] == cls.fillImage )
if( id <= 0 || id >= VGUI_MAX_TEXTURES || g_textures[id] == 0 || g_textures[id] == tr.whiteTexture )
{
MsgDev( D_ERROR, "VGUI_UploadTextureBlock: bad texture %i. Ignored\n", id );
return;

View File

@ -15,8 +15,24 @@ GNU General Public License for more details.
#include "common.h"
#include "mathlib.h"
#include "eiface.h"
vec3_t vec3_origin = { 0, 0, 0 };
#define NUM_HULL_ROUNDS ARRAYSIZE( hull_table )
#define HULL_PRECISION 4
vec3_t vec3_origin = { 0, 0, 0 };
static word hull_table[] = { 2, 4, 6, 8, 12, 16, 18, 24, 28, 32, 36, 40, 48, 54, 56, 60, 64, 72, 80, 112, 120, 128, 140, 176 };
int boxpnt[6][4] =
{
{ 0, 4, 6, 2 }, // +X
{ 0, 1, 5, 4 }, // +Y
{ 0, 2, 3, 1 }, // +Z
{ 7, 5, 1, 3 }, // -X
{ 7, 3, 2, 6 }, // -Y
{ 7, 6, 4, 5 }, // -Z
};
/*
=================
@ -75,6 +91,56 @@ float HalfToFloat( word h )
return *((float *)&f);
}
/*
=================
RoundUpHullSize
round the hullsize to nearest 'right' value
=================
*/
void RoundUpHullSize( vec3_t size )
{
int i, j;
for( i = 0; i < 3; i++)
{
qboolean negative = false;
float result, value;
value = size[i];
if( value < 0.0f ) negative = true;
value = Q_ceil( fabs( value ));
// lookup hull table to find nearest supposed value
for( j = 0; j < NUM_HULL_ROUNDS; j++ )
{
if( value > hull_table[j] )
continue; // ceil only
if( negative )
{
result = ( value - hull_table[j] );
if( result <= HULL_PRECISION )
{
result = -hull_table[j];
break;
}
}
else
{
result = ( value - hull_table[j] );
if( result <= HULL_PRECISION )
{
result = hull_table[j];
break;
}
}
}
size[i] = result;
}
}
/*
=================
SignbitsForPlane
@ -370,6 +436,29 @@ qboolean BoundsAndSphereIntersect( const vec3_t mins, const vec3_t maxs, const v
return true;
}
/*
=================
SphereIntersect
=================
*/
qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir )
{
float a, b, c, insideSqr;
vec3_t p;
// translate sphere to origin.
VectorSubtract( vLinePt, vSphereCenter, p );
a = DotProduct( vLineDir, vLineDir );
b = 2.0f * DotProduct( p, vLineDir );
c = DotProduct( p, p ) - fSphereRadiusSquared;
insideSqr = b * b - 4.0f * a * c;
if( insideSqr <= 0.000001f )
return false;
return true;
}
/*
=================
RadiusFromBounds
@ -469,52 +558,70 @@ void QuaternionAngle( const vec4_t q, vec3_t angles )
/*
====================
QuaternionSlerp
QuaternionAlign
make sure quaternions are within 180 degrees of one another,
if not, reverse q
====================
*/
void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt )
void QuaternionAlign( const vec4_t p, const vec4_t q, vec4_t qt )
{
float omega, sclp, sclq;
float cosom, sinom;
// decide if one of the quaternions is backwards
float a = 0.0f;
float b = 0.0f;
int i;
// decide if one of the quaternions is backwards
for( i = 0; i < 4; i++ )
for( i = 0; i < 4; i++ )
{
a += (p[i] - q[i]) * (p[i] - q[i]);
b += (p[i] + q[i]) * (p[i] + q[i]);
}
if( a > b )
if( a > b )
{
for( i = 0; i < 4; i++ )
{
q[i] = -q[i];
}
for( i = 0; i < 4; i++ )
qt[i] = -q[i];
}
else
{
for( i = 0; i < 4; i++ )
qt[i] = q[i];
}
}
/*
====================
QuaternionSlerpNoAlign
====================
*/
void QuaternionSlerpNoAlign( const vec4_t p, const vec4_t q, float t, vec4_t qt )
{
float omega, cosom, sinom, sclp, sclq;
int i;
// 0.0 returns p, 1.0 return q.
cosom = p[0] * q[0] + p[1] * q[1] + p[2] * q[2] + p[3] * q[3];
if(( 1.0 + cosom ) > 0.000001f )
if(( 1.0f + cosom ) > 0.000001f )
{
if(( 1.0f - cosom ) > 0.000001f )
{
omega = acos( cosom );
sinom = sin( omega );
sclp = sin(( 1.0f - t ) * omega ) / sinom;
sclp = sin( (1.0f - t) * omega) / sinom;
sclq = sin( t * omega ) / sinom;
}
else
{
// TODO: add short circuit for cosom == 1.0f?
sclp = 1.0f - t;
sclq = t;
}
for( i = 0; i < 4; i++ )
{
qt[i] = sclp * p[i] + sclq * q[i];
}
}
else
{
@ -526,6 +633,26 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt )
sclq = sin( t * ( 0.5f * M_PI ));
for( i = 0; i < 3; i++ )
{
qt[i] = sclp * p[i] + sclq * qt[i];
}
}
}
/*
====================
QuaternionSlerp
Quaternion sphereical linear interpolation
====================
*/
void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt )
{
vec4_t q2;
// 0.0 returns p, 1.0 return q.
// decide if one of the quaternions is backwards
QuaternionAlign( p, q, q2 );
QuaternionSlerpNoAlign( p, q2, t, qt );
}

View File

@ -119,6 +119,7 @@ float rsqrt( float number );
float anglemod( const float a );
word FloatToHalf( float v );
float HalfToFloat( word h );
void RoundUpHullSize( vec3_t size );
int SignbitsForPlane( const vec3_t normal );
int NearestPOW( int value, qboolean roundDown );
void SinCos( float radians, float *sine, float *cosine );
@ -133,11 +134,12 @@ void ClearBounds( vec3_t mins, vec3_t maxs );
void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
qboolean BoundsIntersect( const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2 );
qboolean BoundsAndSphereIntersect( const vec3_t mins, const vec3_t maxs, const vec3_t origin, float radius );
qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir );
float RadiusFromBounds( const vec3_t mins, const vec3_t maxs );
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio );
void QuaternionAngle( const vec4_t q, vec3_t angles );
void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt );
void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
float RemapVal( float val, float A, float B, float C, float D );
float ApproachVal( float target, float value, float speed );
@ -180,6 +182,7 @@ void Matrix4x4_Transpose( matrix4x4 out, const matrix4x4 in1 );
qboolean Matrix4x4_Invert_Full( matrix4x4 out, const matrix4x4 in1 );
extern vec3_t vec3_origin;
extern int boxpnt[6][4];
extern const matrix3x4 matrix3x4_identity;
extern const matrix4x4 matrix4x4_identity;

View File

@ -166,6 +166,9 @@ qboolean Mod_GetStudioBounds( const char *name, vec3_t mins, vec3_t maxs );
void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *org, float *ang );
void Mod_GetBonePosition( const edict_t *e, int iBone, float *org, float *ang );
hull_t *Mod_HullForStudio( model_t *m, float frame, int seq, vec3_t ang, vec3_t org, vec3_t size, byte *pcnt, byte *pbl, int *hitboxes, edict_t *ed );
void R_StudioCalcBoneQuaternion( int frame, float s, void *pbone, void *panim, float *adj, vec4_t q );
void R_StudioCalcBonePosition( int frame, float s, void *pbone, void *panim, vec3_t adj, vec3_t pos );
void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs );
int Mod_HitgroupForStudioHull( int index );
#endif//MOD_LOCAL_H

View File

@ -330,162 +330,6 @@ static void Mod_StudioCalcBoneAdj( float *adj, const byte *pcontroller )
}
}
/*
====================
StudioCalcBoneQuaterion
====================
*/
static void Mod_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, true );
AngleQuaternion( angle2, q2, true );
QuaternionSlerp( q1, q2, s, q );
}
else
{
AngleQuaternion( angle1, q, true );
}
}
/*
====================
StudioCalcBonePosition
====================
*/
static void Mod_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.0f - 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.0f - 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]];
}
}
}
/*
====================
StudioCalcRotations
@ -515,8 +359,8 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
for( j = numbones - 1; j >= 0; j-- )
{
i = boneused[j];
Mod_StudioCalcBoneQuaterion( frame, s, &pbone[i], &panim[i], adj, q[i] );
Mod_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] );
R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
}
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
@ -869,8 +713,10 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs )
studiohdr_t *pstudiohdr;
mstudiobodyparts_t *pbodypart;
mstudiomodel_t *m_pSubModel;
mstudioseqgroup_t *pseqgroup;
mstudioseqdesc_t *pseqdesc;
mstudiobone_t *pbones;
mstudioanim_t *panim;
vec3_t vecmins1, vecmaxs1;
vec3_t vecmins2, vecmaxs2;
int counter1, counter2;
@ -905,17 +751,21 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs )
}
pbones = (mstudiobone_t *)((byte *)pstudiohdr + pstudiohdr->boneindex);
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
for( i = 0; i < pstudiohdr->numseq; i++ )
{
mstudioanim_t *panim = (mstudioanim_t *) (((byte *)buffer) + pseqdesc[i].animindex);
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + i;
pseqgroup = (mstudioseqgroup_t *)((byte *)pstudiohdr + pstudiohdr->seqgroupindex) + pseqdesc->seqgroup;
if( pseqdesc->seqgroup == 0 )
panim = (mstudioanim_t *)((byte *)pstudiohdr + pseqgroup->data + pseqdesc->animindex);
else continue;
for( j = 0; j < pstudiohdr->numbones; j++ )
{
for( k = 0; k < pseqdesc[i].numframes; k++ )
for( k = 0; k < pseqdesc->numframes; k++ )
{
Mod_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos );
R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos );
Mod_StudioBoundVertex( vecmins2, vecmaxs2, &counter2, pos );
}
}

View File

@ -20,16 +20,6 @@ GNU General Public License for more details.
// expand debugging BBOX particle hulls by this many units.
#define BOX_GAP 0.0f
static int boxpnt[6][4] =
{
{ 0, 4, 6, 2 }, // +X
{ 0, 1, 5, 4 }, // +Y
{ 0, 2, 3, 1 }, // +Z
{ 7, 5, 1, 3 }, // -X
{ 7, 3, 2, 6 }, // -Y
{ 7, 6, 4, 5 }, // -Z
};
/*
===============
PM_ParticleLine

View File

@ -22,6 +22,8 @@ GNU General Public License for more details.
#include "studio.h"
#include "world.h"
#define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 ))
static mplane_t pm_boxplanes[6];
static dclipnode_t pm_boxclipnodes[6];
static hull_t pm_boxhull;
@ -341,22 +343,23 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
VectorClear( offset );
}
else if( !pe->model )
else if( pe->model )
{
if( !pe->studiomodel )
hull = PM_HullForBsp( pe, pmove, offset );
}
else
{
if( pe->studiomodel )
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
}
else
{
if( flags & PM_STUDIO_IGNORE )
if( FBitSet( flags, PM_STUDIO_IGNORE ))
continue;
if( pe->studiomodel->type != mod_studio || (!( pe->studiomodel->flags & STUDIO_TRACE_HITBOX ) && ( pmove->usehull != 2 || flags & PM_STUDIO_BOX )))
if( PM_AllowHitBoxTrace( pe->studiomodel, pmove->usehull ) && !FBitSet( flags, PM_STUDIO_BOX ))
{
hull = PM_HullForStudio( pe, pmove, &hullcount );
VectorClear( offset );
}
else
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
@ -364,16 +367,16 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
}
else
{
hull = PM_HullForStudio( pe, pmove, &hullcount );
VectorClear( offset );
}
}
else
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
}
}
else
{
hull = PM_HullForBsp( pe, pmove, offset );
}
if( pe->solid == SOLID_BSP && !VectorIsNull( pe->angles ))
@ -538,7 +541,12 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
{
hull = PM_HullForBsp( pe, pmove, offset );
}
else if( !pe->studiomodel || pe->studiomodel->type != mod_studio || (!( pe->studiomodel->flags & STUDIO_TRACE_HITBOX ) && pmove->usehull != 2 ))
else if( PM_AllowHitBoxTrace( pe->studiomodel, pmove->usehull ))
{
hull = PM_HullForStudio( pe, pmove, &hullcount );
VectorClear( offset );
}
else
{
VectorSubtract( pe->mins, pmove->player_maxs[pmove->usehull], mins );
VectorSubtract( pe->maxs, pmove->player_mins[pmove->usehull], maxs );
@ -546,11 +554,6 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
hull = PM_HullForBox( mins, maxs );
VectorCopy( pe->origin, offset );
}
else
{
hull = PM_HullForStudio( pe, pmove, &hullcount );
VectorClear( offset );
}
// CM_TransformedPointContents :-)
if( pe->solid == SOLID_BSP && !VectorIsNull( pe->angles ))

View File

@ -125,6 +125,7 @@ SV_CheckVelocity
void SV_CheckVelocity( edict_t *ent )
{
float wishspd;
float maxspd;
int i;
// bound velocity
@ -144,10 +145,11 @@ void SV_CheckVelocity( edict_t *ent )
}
wishspd = DotProduct( ent->v.velocity, ent->v.velocity );
maxspd = sv_maxvelocity.value * sv_maxvelocity.value * 1.73f; // half-diagonal
if( wishspd > ( sv_maxvelocity.value * sv_maxvelocity.value ))
if( wishspd > maxspd )
{
MsgDev( D_INFO, "Got a velocity too high on %s\n", STRING( ent->v.classname ));
MsgDev( D_INFO, "Got a velocity too high on %s ( %.2f > %.2f )\n", STRING( ent->v.classname ), sqrt( wishspd ), sqrt( maxspd ));
wishspd = sv_maxvelocity.value / sqrt( wishspd );
VectorScale( ent->v.velocity, wishspd, ent->v.velocity );
}

View File

@ -107,6 +107,48 @@ void SV_StudioPlayerBlend( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitc
}
}
/*
====================
SV_CheckSphereIntersection
check clients only
====================
*/
qboolean SV_CheckSphereIntersection( edict_t *ent, const vec3_t start, const vec3_t end )
{
int i, sequence;
float radiusSquared;
vec3_t traceOrg, traceDir;
studiohdr_t *pstudiohdr;
mstudioseqdesc_t *pseqdesc;
model_t *mod;
if( !FBitSet( ent->v.flags, FL_CLIENT|FL_FAKECLIENT ))
return true;
if(( mod = Mod_Handle( ent->v.modelindex )) == NULL )
return true;
if(( pstudiohdr = (studiohdr_t *)Mod_Extradata( mod )) == NULL )
return true;
sequence = ent->v.sequence;
if( sequence < 0 || sequence >= pstudiohdr->numseq )
sequence = 0;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
VectorCopy( start, traceOrg );
VectorSubtract( end, start, traceDir );
radiusSquared = 0.0f;
for ( i = 0; i < 3; i++ )
radiusSquared += Q_max( fabs( pseqdesc->bbmin[i] ), fabs( pseqdesc->bbmax[i] ));
return SphereIntersect( ent->v.origin, radiusSquared, traceOrg, traceDir );
}
/*
===================
SV_HullForBox
@ -1141,6 +1183,10 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
if( !BoundsIntersect( clip->boxmins, clip->boxmaxs, touch->v.absmin, touch->v.absmax ))
continue;
// aditional check to intersects clients with sphere
if( touch->v.solid != SOLID_SLIDEBOX && !SV_CheckSphereIntersection( touch, clip->start, clip->end ))
continue;
// Xash3D extension
if( SV_IsValidEdict( clip->passedict ) && clip->passedict->v.solid == SOLID_TRIGGER )
{

View File

@ -57,8 +57,9 @@ Studio models are position independent, so the cache manager can move them.
#define STUDIO_ZOMGIB 0x0020 // small blood trail
#define STUDIO_TRACER2 0x0040 // orange split trail + rotate
#define STUDIO_TRACER3 0x0080 // purple trail
#define STUDIO_DYNAMIC_LIGHT 0x0100 // dynamically get lighting from floor or ceil (flying monsters)
#define STUDIO_AMBIENT_LIGHT 0x0100 // force to use ambient shading
#define STUDIO_TRACE_HITBOX 0x0200 // always use hitbox trace instead of bbox
#define STUDIO_FORCE_SKYLIGHT 0x0400 // always grab lightvalues from the sky settings (even if sky is invisible)
// lighting & rendermode options
#define STUDIO_NF_FLATSHADE 0x0001
@ -97,7 +98,6 @@ Studio models are position independent, so the cache manager can move them.
// sequence flags
#define STUDIO_LOOPING 0x0001
#define STUDIO_STATIC 0x8000 // studiomodel is static
// bone flags
#define STUDIO_HAS_NORMALS 0x0001