01 Jul 2010
This commit is contained in:
parent
9eb4e5cde1
commit
99ecb9fcbe
|
@ -180,11 +180,6 @@ void TE_ParseExplosion( void )
|
|||
if(!( flags & TE_EXPLFLAG_NOPARTICLES ))
|
||||
g_engfuncs.pEfxAPI->R_RunParticleEffect( pos, g_vecZero, 224, 200 );
|
||||
|
||||
char szDecal[32];
|
||||
|
||||
sprintf( szDecal, "{scorch%i", RANDOM_LONG( 1, 3 ));
|
||||
g_pTempEnts->PlaceDecal( pos2, 0, szDecal );
|
||||
|
||||
if( !( flags & TE_EXPLFLAG_NOSOUND ))
|
||||
{
|
||||
CL_PlaySound( "weapons/explode3.wav", 1.0f, pos2 );
|
||||
|
@ -425,6 +420,7 @@ void TE_ParseBSPDecal( void )
|
|||
entityIndex = READ_SHORT();
|
||||
if( entityIndex != NULLENT_INDEX )
|
||||
modelIndex = READ_SHORT();
|
||||
else modelIndex = 0;
|
||||
|
||||
g_pTempEnts->PlaceDecal( pos, entityIndex, decalIndex );
|
||||
}
|
||||
|
@ -793,9 +789,8 @@ void TE_ParseDecal( int type )
|
|||
decalIndex = READ_BYTE();
|
||||
|
||||
if( type == TE_DECAL || type == TE_DECALHIGH )
|
||||
{
|
||||
entityIndex = READ_SHORT();
|
||||
}
|
||||
else entityIndex = 0;
|
||||
|
||||
if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH )
|
||||
decalIndex += 256;
|
||||
|
@ -984,6 +979,7 @@ Create a colored decal, get settings from client
|
|||
void TE_ParsePlayerDecal( void )
|
||||
{
|
||||
int clientIndex, decalIndex, entityIndex;
|
||||
byte color[4];
|
||||
Vector pos;
|
||||
|
||||
clientIndex = READ_BYTE();
|
||||
|
@ -993,9 +989,14 @@ void TE_ParsePlayerDecal( void )
|
|||
entityIndex = READ_SHORT();
|
||||
decalIndex = READ_BYTE();
|
||||
|
||||
// FIXME: get logo color from user variable
|
||||
color[0] = 255;
|
||||
color[1] = 255;
|
||||
color[2] = 255;
|
||||
color[3] = 255; // alpha
|
||||
|
||||
HSPRITE hDecal = g_engfuncs.pEfxAPI->CL_DecalIndex( decalIndex );
|
||||
edict_t *pEnt = GetEntityByIndex( entityIndex );
|
||||
g_engfuncs.pEfxAPI->R_DecalShoot( hDecal, pEnt, pEnt->v.modelindex, pos, 0 );
|
||||
g_engfuncs.pEfxAPI->R_PlayerDecal( hDecal, entityIndex, pos, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1506,7 +1506,7 @@ void CTempEnts::PlaceDecal( Vector pos, int entityIndex, int decalIndex )
|
|||
pEnt = GetEntityByIndex( entityIndex );
|
||||
if( pEnt && !pEnt->free ) modelIndex = pEnt->v.modelindex;
|
||||
hDecal = g_engfuncs.pEfxAPI->CL_DecalIndex( decalIndex );
|
||||
g_engfuncs.pEfxAPI->R_DecalShoot( hDecal, pEnt, modelIndex, pos, 0 );
|
||||
g_engfuncs.pEfxAPI->R_DecalShoot( hDecal, entityIndex, modelIndex, pos, 0 );
|
||||
}
|
||||
|
||||
void CTempEnts::PlaceDecal( Vector pos, int entityIndex, const char *decalname )
|
||||
|
@ -1518,7 +1518,7 @@ void CTempEnts::PlaceDecal( Vector pos, int entityIndex, const char *decalname )
|
|||
pEnt = GetEntityByIndex( entityIndex );
|
||||
if( pEnt && !pEnt->free ) modelIndex = pEnt->v.modelindex;
|
||||
hDecal = g_engfuncs.pEfxAPI->CL_DecalIndexFromName( decalname );
|
||||
g_engfuncs.pEfxAPI->R_DecalShoot( hDecal, pEnt, modelIndex, pos, 0 );
|
||||
g_engfuncs.pEfxAPI->R_DecalShoot( hDecal, entityIndex, modelIndex, pos, 0 );
|
||||
}
|
||||
|
||||
void CTempEnts::AllocDLight( Vector pos, byte r, byte g, byte b, float radius, float time, float decay )
|
||||
|
|
|
@ -264,11 +264,6 @@ typedef enum
|
|||
#define IN_ALT1 (1<<14)
|
||||
#define IN_SCORE (1<<15) // Used by client.dll for when scoreboard is held down
|
||||
|
||||
// temp entity bounce sound types
|
||||
#define TE_BOUNCE_NULL 0
|
||||
#define TE_BOUNCE_SHELL 1
|
||||
#define TE_BOUNCE_SHOTSHELL 2
|
||||
|
||||
// rendering constants
|
||||
typedef enum
|
||||
{
|
||||
|
@ -360,6 +355,16 @@ typedef enum
|
|||
#define RDF_NOFOVADJUSTMENT (1<<3) // do not adjust fov for widescreen
|
||||
#define RDF_THIRDPERSON (1<<4) // enable chase cam instead firstperson
|
||||
|
||||
// decal flags
|
||||
#define FDECAL_PERMANENT 0x01 // This decal should not be removed in favor of any new decals
|
||||
#define FDECAL_REFERENCE 0x02 // This is a decal that's been moved from another level
|
||||
#define FDECAL_CUSTOM 0x04 // This is a custom clan logo and should not be saved/restored
|
||||
#define FDECAL_DYNAMIC 0x08 // Indicates the decal is dynamic
|
||||
#define FDECAL_DONTSAVE 0x10 // Decal was loaded from adjacent level, don't save it for this level
|
||||
#define FDECAL_CLIPTEST 0x20 // Decal needs to be clip-tested
|
||||
#define FDECAL_NOCLIP 0x40 // Decal is not clipped by containing polygon
|
||||
#define FDECAL_USESAXIS 0x80 // Uses the s axis field to determine orientation (footprints)
|
||||
|
||||
// client modelindexes
|
||||
#define NULLENT_INDEX -1 // engine always return NULL, only for internal use
|
||||
#define VIEWENT_INDEX -2 // can get viewmodel for local client
|
||||
|
|
|
@ -27,20 +27,6 @@ struct dlight_s
|
|||
bool dark; // subtracts light instead of adding
|
||||
};
|
||||
|
||||
// decal flags
|
||||
#define FDECAL_PERMANENT 0x01 // This decal should not be removed in favor of any new decals
|
||||
#define FDECAL_REFERENCE 0x02 // This is a decal that's been moved from another level
|
||||
#define FDECAL_CUSTOM 0x04 // This is a custom clan logo and should not be saved/restored
|
||||
#define FDECAL_HFLIP 0x08 // Flip horizontal (U/S) axis
|
||||
#define FDECAL_VFLIP 0x10 // Flip vertical (V/T) axis
|
||||
#define FDECAL_CLIPTEST 0x20 // Decal needs to be clip-tested
|
||||
#define FDECAL_NOCLIP 0x40 // Decal is not clipped by containing polygon
|
||||
#define FDECAL_USESAXIS 0x80 // Uses the s axis field to determine orientation
|
||||
#define FDECAL_DYNAMIC 0x100 // Indicates the decal is dynamic
|
||||
#define FDECAL_SECONDPASS 0x200 // Decals that have to be drawn after everything else
|
||||
#define FDECAL_WATER 0x400 // Decal should only be applied to water
|
||||
#define FDECAL_DONTSAVE 0x800 // Decal was loaded from adjacent level, don't save it for this level
|
||||
|
||||
typedef struct efxapi_s
|
||||
{
|
||||
particle_t* (*R_AllocParticle)( void );
|
||||
|
@ -55,7 +41,8 @@ typedef struct efxapi_s
|
|||
void (*R_GetPaletteColor)( int colorIndex, float *outColor );
|
||||
int (*CL_DecalIndex)( int id );
|
||||
int (*CL_DecalIndexFromName)( const char *szDecalName );
|
||||
void (*R_DecalShoot)( HSPRITE hDecal, edict_t *pEnt, int modelIndex, float *pos, int flags );
|
||||
void (*R_DecalShoot)( HSPRITE hDecal, int entityIndex, int modelIndex, float *pos, int flags );
|
||||
void (*R_PlayerDecal)( HSPRITE hDecal, int entityIndex, float *pos, byte *color );
|
||||
dlight_t* (*CL_AllocDLight)( int key );
|
||||
dlight_t* (*CL_AllocELight)( int key );
|
||||
void (*R_LightForPoint)( const float *rgflOrigin, float *lightValue );
|
||||
|
|
|
@ -954,270 +954,45 @@ void CL_RocketTrail( const vec3_t org, const vec3_t end, int type )
|
|||
}
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
===============
|
||||
CL_DecalShoot
|
||||
|
||||
DECALS MANAGEMENT
|
||||
|
||||
==============================================================
|
||||
normal temporary decal
|
||||
===============
|
||||
*/
|
||||
#define MAX_DRAWDECALS 1024
|
||||
#define MAX_DECAL_VERTS 128 // per one decal
|
||||
#define MAX_DECAL_FRAGMENTS 64
|
||||
|
||||
typedef struct cdecal_s
|
||||
void CL_DecalShoot( HSPRITE hDecal, int entityIndex, int modelIndex, float *pos, int flags )
|
||||
{
|
||||
struct cdecal_s *prev;
|
||||
struct cdecal_s *next;
|
||||
|
||||
edict_t *pent; // parent entity
|
||||
poly_t *poly;
|
||||
} cdecal_t;
|
||||
|
||||
static cdecal_t cl_decals[MAX_DRAWDECALS];
|
||||
static cdecal_t cl_decals_headnode, *cl_free_decals;
|
||||
static poly_t cl_decal_polys[MAX_DRAWDECALS];
|
||||
static vec3_t cl_decal_verts[MAX_DRAWDECALS][MAX_DECAL_VERTS];
|
||||
static vec2_t cl_decal_stcoords[MAX_DRAWDECALS][MAX_DECAL_VERTS];
|
||||
static rgba_t cl_decal_colors[MAX_DRAWDECALS][MAX_DECAL_VERTS];
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ClearDecals
|
||||
=================
|
||||
*/
|
||||
void CL_ClearDecals( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
Mem_Set( cl_decals, 0, sizeof( cl_decals ));
|
||||
Mem_Set( cl_decal_polys, 0, sizeof( cl_decal_polys ));
|
||||
|
||||
// link decals
|
||||
cl_free_decals = cl_decals;
|
||||
cl_decals_headnode.prev = &cl_decals_headnode;
|
||||
cl_decals_headnode.next = &cl_decals_headnode;
|
||||
|
||||
for( i = 0; i < MAX_DRAWDECALS; i++ )
|
||||
{
|
||||
if( i < MAX_DRAWDECALS - 1 )
|
||||
cl_decals[i].next = &cl_decals[i+1];
|
||||
|
||||
cl_decals[i].poly = &cl_decal_polys[i];
|
||||
cl_decals[i].poly->verts = cl_decal_verts[i];
|
||||
cl_decals[i].poly->stcoords = cl_decal_stcoords[i];
|
||||
cl_decals[i].poly->colors = cl_decal_colors[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_AllocDecal
|
||||
|
||||
Returns either a free decal or the oldest one
|
||||
=================
|
||||
*/
|
||||
cdecal_t *CL_AllocDecal( void )
|
||||
{
|
||||
cdecal_t *dl;
|
||||
|
||||
if( cl_free_decals )
|
||||
{
|
||||
// take a free decal if possible
|
||||
dl = cl_free_decals;
|
||||
cl_free_decals = dl->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// grab the oldest one otherwise
|
||||
dl = cl_decals_headnode.prev;
|
||||
dl->prev->next = dl->next;
|
||||
dl->next->prev = dl->prev;
|
||||
}
|
||||
|
||||
// put the decal at the start of the list
|
||||
dl->prev = &cl_decals_headnode;
|
||||
dl->next = cl_decals_headnode.next;
|
||||
dl->next->prev = dl;
|
||||
dl->prev->next = dl;
|
||||
|
||||
return dl;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FreeDecal
|
||||
=================
|
||||
*/
|
||||
void CL_FreeDecal( cdecal_t *dl )
|
||||
{
|
||||
// remove from linked active list
|
||||
dl->prev->next = dl->next;
|
||||
dl->next->prev = dl->prev;
|
||||
|
||||
// insert into linked free list
|
||||
dl->next = cl_free_decals;
|
||||
cl_free_decals = dl;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_SpawnDecal
|
||||
=================
|
||||
*/
|
||||
int CL_SpawnDecal( HSPRITE m_hDecal, edict_t *pEnt, const vec3_t pos, int colorIndex, float roll, float scale )
|
||||
{
|
||||
cdecal_t *dl;
|
||||
poly_t *poly;
|
||||
vec3_t axis[3];
|
||||
int i, j, numfragments;
|
||||
vec3_t dir, verts[MAX_DECAL_VERTS];
|
||||
fragment_t *fr, fragments[MAX_DECAL_FRAGMENTS];
|
||||
rgba_t color;
|
||||
|
||||
// invalid decal
|
||||
if( scale <= 0.0f || !m_hDecal )
|
||||
return false;
|
||||
|
||||
CL_FindExplosionPlane( pos, scale, dir );
|
||||
|
||||
// calculate orientation matrix
|
||||
VectorNormalize2( dir, axis[0] );
|
||||
PerpendicularVector( axis[1], axis[0] );
|
||||
RotatePointAroundVector( axis[2], axis[0], axis[1], roll );
|
||||
CrossProduct( axis[0], axis[2], axis[1] );
|
||||
|
||||
numfragments = re->GetFragments( pos, scale, axis, MAX_DECAL_VERTS, verts, MAX_DECAL_FRAGMENTS, fragments );
|
||||
|
||||
// no valid fragments
|
||||
if( !numfragments ) return false;
|
||||
|
||||
// setup decal color
|
||||
if( colorIndex )
|
||||
{
|
||||
colorIndex = bound( 0, colorIndex, 255 );
|
||||
color[0] = cl_particlePalette[colorIndex][0];
|
||||
color[1] = cl_particlePalette[colorIndex][1];
|
||||
color[2] = cl_particlePalette[colorIndex][2];
|
||||
color[3] = 0xFF;
|
||||
}
|
||||
else Vector4Set( color, 255, 255, 255, 255 );
|
||||
|
||||
scale = 0.5f / scale;
|
||||
VectorScale( axis[1], scale, axis[1] );
|
||||
VectorScale( axis[2], scale, axis[2] );
|
||||
|
||||
for( i = 0, fr = fragments; i < numfragments; i++, fr++ )
|
||||
{
|
||||
if( fr->numverts >= MAX_DECAL_VERTS )
|
||||
return -1; // in case we partially failed
|
||||
else if( fr->numverts <= 0 )
|
||||
continue;
|
||||
|
||||
// allocate decal
|
||||
dl = CL_AllocDecal();
|
||||
dl->pent = pEnt;
|
||||
|
||||
// setup polygon for drawing
|
||||
poly = dl->poly;
|
||||
poly->shadernum = m_hDecal;
|
||||
poly->numverts = fr->numverts;
|
||||
poly->fognum = fr->fognum;
|
||||
|
||||
for( j = 0; j < fr->numverts; j++ )
|
||||
{
|
||||
vec3_t v;
|
||||
|
||||
VectorCopy( verts[fr->firstvert+j], poly->verts[j] );
|
||||
VectorSubtract( poly->verts[j], pos, v );
|
||||
poly->stcoords[j][0] = DotProduct( v, axis[1] ) + 0.5f;
|
||||
poly->stcoords[j][1] = DotProduct( v, axis[2] ) + 0.5f;
|
||||
*(int *)poly->colors[j] = *(int *)color;
|
||||
}
|
||||
}
|
||||
return true; // all done
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_AddDecals
|
||||
=================
|
||||
*/
|
||||
void CL_AddDecals( void )
|
||||
{
|
||||
cdecal_t *dl, *next, *hnode;
|
||||
|
||||
// add decals in first-spawned - first-drawn order
|
||||
hnode = &cl_decals_headnode;
|
||||
for( dl = hnode->prev; dl != hnode; dl = next )
|
||||
{
|
||||
next = dl->prev;
|
||||
|
||||
if( dl->pent && dl->pent->free )
|
||||
{
|
||||
// remove attached decals
|
||||
CL_FreeDecal( dl );
|
||||
continue;
|
||||
}
|
||||
re->AddPolygon( dl->poly );
|
||||
}
|
||||
}
|
||||
|
||||
void CL_DecalShoot( HSPRITE hDecal, edict_t *pEnt, int modelIndex, float *pos, int flags )
|
||||
{
|
||||
int entityIndex = 0;
|
||||
rgba_t color;
|
||||
|
||||
if( CL_IsValidEdict( pEnt ))
|
||||
entityIndex = pEnt->serialnumber;
|
||||
Vector4Set( color, 255, 255, 255, 255 );
|
||||
|
||||
if( re ) re->DecalShoot( hDecal, entityIndex, modelIndex, pos, NULL, 0, color );
|
||||
Vector4Set( color, 255, 255, 255, 255 ); // don't use custom colors
|
||||
if( re ) re->DecalShoot( hDecal, entityIndex, modelIndex, pos, NULL, flags, color, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_SpawnStaticDecal
|
||||
CL_PlayerDecal
|
||||
|
||||
spray custom colored decal (clan logo etc)
|
||||
===============
|
||||
*/
|
||||
void CL_SpawnStaticDecal( vec3_t origin, int decalIndex, int entityIndex, int modelIndex )
|
||||
void CL_PlayerDecal( HSPRITE hDecal, int entityIndex, float *pos, byte *color )
|
||||
{
|
||||
rgba_t color;
|
||||
edict_t *pEnt;
|
||||
int modelIndex = 0;
|
||||
|
||||
decalIndex = bound( 0, decalIndex, MAX_DECALNAMES - 1 );
|
||||
Vector4Set( color, 255, 255, 255, 255 );
|
||||
pEnt = CL_GetEdictByIndex( entityIndex );
|
||||
if( CL_IsValidEdict( pEnt )) modelIndex = pEnt->v.modelindex;
|
||||
|
||||
if( re ) re->DecalShoot( cl.decal_shaders[decalIndex], entityIndex, modelIndex, origin, NULL, 0, color );
|
||||
if( re ) re->DecalShoot( hDecal, entityIndex, modelIndex, pos, NULL, FDECAL_CUSTOM, color, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result )
|
||||
{
|
||||
static vec3_t planes[6] = {{0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, -1, 0}, {-1, 0, 0}};
|
||||
float best = 1.0f;
|
||||
vec3_t point, dir;
|
||||
trace_t trace;
|
||||
int i;
|
||||
|
||||
if( !result ) return;
|
||||
VectorClear( dir );
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
VectorMA( origin, radius, planes[i], point );
|
||||
|
||||
trace = CL_Move( origin, vec3_origin, vec3_origin, point, MOVE_NOMONSTERS, NULL );
|
||||
if( trace.fAllSolid || trace.flFraction == 1.0f )
|
||||
continue;
|
||||
|
||||
if( trace.flFraction < best )
|
||||
{
|
||||
best = trace.flFraction;
|
||||
VectorCopy( trace.vecPlaneNormal, dir );
|
||||
}
|
||||
}
|
||||
VectorCopy( dir, result );
|
||||
}
|
||||
/*
|
||||
===============
|
||||
CL_LightForPoint
|
||||
|
||||
get lighting color for specified point
|
||||
===============
|
||||
*/
|
||||
void CL_LightForPoint( const vec3_t point, vec3_t ambientLight )
|
||||
{
|
||||
if( re ) re->LightForPoint( point, ambientLight );
|
||||
|
@ -1392,5 +1167,4 @@ void CL_ClearEffects( void )
|
|||
CL_ClearParticles ();
|
||||
CL_ClearDlights ();
|
||||
CL_ClearLightStyles ();
|
||||
CL_ClearDecals ();
|
||||
}
|
||||
}
|
|
@ -334,7 +334,6 @@ void CL_AddEntities( void )
|
|||
CL_AddParticles();
|
||||
CL_AddDLights();
|
||||
CL_AddLightStyles();
|
||||
CL_AddDecals();
|
||||
|
||||
// perfomance test
|
||||
CL_TestEntities();
|
||||
|
|
|
@ -2028,7 +2028,7 @@ static int pfnDecalIndexFromName( const char *szDecalName )
|
|||
if( !com.stricmp( szDecalName, cl.configstrings[CS_DECALS+i+1] ))
|
||||
return cl.decal_shaders[i+1];
|
||||
}
|
||||
return 0; // invalid sprite
|
||||
return 0; // invalid decal
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2399,6 +2399,7 @@ static efxapi_t gEfxApi =
|
|||
pfnDecalIndex,
|
||||
pfnDecalIndexFromName,
|
||||
CL_DecalShoot,
|
||||
CL_PlayerDecal,
|
||||
CL_AllocDlight,
|
||||
CL_AllocElight,
|
||||
CL_LightForPoint,
|
||||
|
|
|
@ -431,10 +431,11 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
|
|||
decalIndex = MSG_ReadWord( msg );
|
||||
entityIndex = MSG_ReadShort( msg );
|
||||
|
||||
if( entityIndex > 0 )
|
||||
if( entityIndex != NULLENT_INDEX )
|
||||
modelIndex = MSG_ReadWord( msg );
|
||||
else modelIndex = 0;
|
||||
|
||||
CL_SpawnStaticDecal( origin, decalIndex, entityIndex, modelIndex );
|
||||
CL_DecalShoot( cl.decal_shaders[decalIndex], entityIndex, modelIndex, origin, FDECAL_PERMANENT );
|
||||
}
|
||||
|
||||
void CL_ParseSoundFade( sizebuf_t *msg )
|
||||
|
|
|
@ -547,7 +547,6 @@ void CL_GetEntitySpatialization( int ent, vec3_t origin, vec3_t velocity );
|
|||
// cl_effects.c
|
||||
//
|
||||
void CL_AddParticles( void );
|
||||
void CL_AddDecals( void );
|
||||
void CL_ClearEffects( void );
|
||||
void CL_TestLights( void );
|
||||
void CL_TestEntities( void );
|
||||
|
@ -562,11 +561,10 @@ void CL_ParticleExplosion( const vec3_t org );
|
|||
void CL_RocketTrail( const vec3_t start, const vec3_t end, int type );
|
||||
void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength );
|
||||
void CL_GetPaletteColor( int colorIndex, vec3_t outColor );
|
||||
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result );
|
||||
void CL_LightForPoint( const vec3_t point, vec3_t ambientLight );
|
||||
void CL_DecalShoot( HSPRITE hDecal, edict_t *pEnt, int modelIndex, float *pos, int flags );
|
||||
void CL_DecalShoot( HSPRITE hDecal, int entityIndex, int modelIndex, float *pos, int flags );
|
||||
void CL_PlayerDecal( HSPRITE hDecal, int entityIndex, float *pos, byte *color );
|
||||
void CL_ParticleEffect( const vec3_t org, const vec3_t dir, int color, int count ); // q1 legacy
|
||||
void CL_SpawnStaticDecal( vec3_t origin, int decalIndex, int entityIndex, int modelIndex );
|
||||
void CL_QueueEvent( int flags, int index, float delay, event_args_t *args );
|
||||
word CL_PrecacheEvent( const char *name );
|
||||
void CL_ResetEvent( event_info_t *ei );
|
||||
|
|
|
@ -850,7 +850,7 @@ void Host_Main( void )
|
|||
oldtime = Sys_DoubleTime();
|
||||
|
||||
// main window message loop
|
||||
while( host.state != HOST_OFFLINE )
|
||||
while( host.type != HOST_OFFLINE )
|
||||
{
|
||||
IN_Frame();
|
||||
|
||||
|
|
|
@ -2593,7 +2593,7 @@ void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int m
|
|||
MSG_WritePos( &sv.multicast, origin );
|
||||
MSG_WriteWord( &sv.multicast, decalIndex );
|
||||
MSG_WriteShort( &sv.multicast, entityIndex );
|
||||
if( entityIndex > 0 )
|
||||
if( entityIndex != NULLENT_INDEX )
|
||||
MSG_WriteWord( &sv.multicast, modelIndex );
|
||||
MSG_Send( MSG_INIT, NULL, NULL );
|
||||
}
|
||||
|
|
|
@ -362,6 +362,11 @@ int EntityInSolid( edict_t *ent )
|
|||
if( pParent->v.flags & FL_CLIENT )
|
||||
return 0;
|
||||
}
|
||||
|
||||
// never suppressing logical entities
|
||||
if( !ent->v.modelindex )
|
||||
return 0;
|
||||
|
||||
return SV_TestEntityPosition( ent );
|
||||
}
|
||||
|
||||
|
|
|
@ -1339,8 +1339,8 @@ void UI_Shutdown( void )
|
|||
Cmd_RemoveCommand( "menu_loadgame" );
|
||||
Cmd_RemoveCommand( "menu_savegame" );
|
||||
Cmd_RemoveCommand( "menu_saveload" );
|
||||
Cmd_RemoveCommand( "menu_recdemo" );
|
||||
Cmd_RemoveCommand( "menu_playdemo" );
|
||||
Cmd_RemoveCommand( "menu_record" );
|
||||
Cmd_RemoveCommand( "menu_playpack" );
|
||||
Cmd_RemoveCommand( "menu_playrec" );
|
||||
Cmd_RemoveCommand( "menu_multiplayer" );
|
||||
Cmd_RemoveCommand( "menu_options" );
|
||||
|
|
|
@ -560,7 +560,6 @@ bool Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rendermode = LUMP_NORMAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,13 +57,17 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int firstvert;
|
||||
int numverts; // can't exceed MAX_POLY_VERTS
|
||||
int fognum; // -1 - do not bother adding fog later at rendering stage
|
||||
// 0 - determine fog later
|
||||
// >0 - valid fog volume number returned by R_GetClippedFragments
|
||||
vec3_t normal;
|
||||
} fragment_t;
|
||||
vec3_t position;
|
||||
char name[64]; // same as CS_SIZE
|
||||
short entityIndex;
|
||||
byte depth;
|
||||
byte flags;
|
||||
|
||||
// this is the surface plane that we hit so that
|
||||
// we can move certain decals across
|
||||
// transitions if they hit similar geometry
|
||||
vec3_t impactPlaneNormal;
|
||||
} decallist_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -165,7 +169,7 @@ typedef struct render_exp_s
|
|||
// prepare frame to rendering
|
||||
bool (*AddRefEntity)( edict_t *pRefEntity, int ed_type, shader_t customShader );
|
||||
bool (*AddTmpEntity)( struct tempent_s *TempEnt, int ed_type, shader_t customShader );
|
||||
bool (*DecalShoot)( shader_t decal, int ent, model_t mod, vec3_t pos, vec3_t saxis, int flags, rgba_t color );
|
||||
bool (*DecalShoot)( shader_t decal, int ent, int model, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration );
|
||||
bool (*AddDLight)( vec3_t pos, rgb_t color, float radius, int flags );
|
||||
bool (*AddPolygon)( const poly_t *poly );
|
||||
bool (*AddLightStyle)( int stylenum, vec3_t color );
|
||||
|
@ -195,15 +199,15 @@ typedef struct render_exp_s
|
|||
void (*SetParms)( shader_t handle, kRenderMode_t rendermode, int frame );
|
||||
void (*GetParms)( int *w, int *h, int *frames, int frame, shader_t shader );
|
||||
bool (*ScrShot)( const char *filename, int shot_type ); // write screenshot with same name
|
||||
bool (*EnvShot)( const char *filename, uint size, const float *vieworg, bool skyshot ); // write envshot with same name
|
||||
bool (*EnvShot)( const char *filename, uint size, const float *vieworg, bool skyshot );
|
||||
void (*LightForPoint)( const vec3_t point, vec3_t ambientLight );
|
||||
void (*DrawStretchRaw)( int x, int y, int w, int h, int cols, int rows, byte *data, bool redraw );
|
||||
void (*DrawStretchPic)( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader );
|
||||
int (*GetFragments)( const vec3_t org, float rad, vec3_t axis[3], int maxverts, vec3_t *verts, int maxfrags, fragment_t *frags );
|
||||
int (*WorldToScreen)( const float *world, float *screen );
|
||||
void (*ScreenToWorld)( const float *screen, float *world );
|
||||
bool (*CullBox)( const vec3_t mins, const vec3_t maxs );
|
||||
bool (*RSpeedsMessage)( char *out, size_t size );
|
||||
int (*CreateDecalList)( decallist_t *pList ); // helper to serialize decals
|
||||
bool (*Support)( int extension );
|
||||
byte *(*GetCurrentVis)( void );
|
||||
void (*RestoreGamma)( void );
|
||||
|
|
|
@ -191,7 +191,7 @@ void S_MixAllChannels( int endtime, int end )
|
|||
for( i = 0, ch = channels; i < total_channels; i++, ch++ )
|
||||
{
|
||||
if( !ch->sfx ) continue;
|
||||
if( !ch->leftvol && !ch->rightvol )
|
||||
if( !ch->leftvol && !ch->rightvol && !ch->isSentence )
|
||||
continue;
|
||||
|
||||
// only local sounds can be playing in menus or on pause
|
||||
|
|
6
todo.log
6
todo.log
|
@ -26,4 +26,8 @@ Xash 0.72 Beta 5.07.10
|
|||
2.clgame interface - new revision OK
|
||||
3.entity_state - new revision OK
|
||||
4.rework dlights OK
|
||||
5.rework decals
|
||||
5.rework decals OK
|
||||
6.batch drawing decals OK
|
||||
7.draw lightmapped decals OK
|
||||
8.draw decals on bmodels OK
|
||||
9.implement save\restore for decals
|
||||
|
|
|
@ -1281,6 +1281,7 @@ static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit )
|
|||
if( !RI.currententity ) return pass->textures[0]; // assume error
|
||||
return pass->textures[angleframe];
|
||||
}
|
||||
|
||||
if( pass->flags & SHADERSTAGE_FRAMES && !(pass->flags & SHADERSTAGE_ANIMFREQUENCY))
|
||||
{
|
||||
if( glState.in2DMode || triState.fActive )
|
||||
|
@ -2666,7 +2667,7 @@ void R_RenderMeshBuffer( const meshbuffer_t *mb )
|
|||
msurface_t *surf;
|
||||
ref_stage_t *pass;
|
||||
mfog_t *fog;
|
||||
int i;
|
||||
int i, j, type;
|
||||
|
||||
if( !r_backacc.numVerts || !r_backacc.numElems )
|
||||
{
|
||||
|
@ -2676,10 +2677,33 @@ void R_RenderMeshBuffer( const meshbuffer_t *mb )
|
|||
|
||||
Com_Assert( mb == NULL );
|
||||
|
||||
surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL;
|
||||
if( surf ) r_currentLightStyle = &tr.superLightStyles[surf->superLightStyle];
|
||||
else r_currentLightStyle = NULL;
|
||||
type = mb->sortkey & 3;
|
||||
r_currentLightStyle = NULL;
|
||||
r_currentMeshBuffer = mb;
|
||||
surf = NULL;
|
||||
|
||||
// trying to extract lightstyle for mesh
|
||||
switch( type )
|
||||
{
|
||||
case MB_MODEL:
|
||||
if( RI.currentmodel )
|
||||
{
|
||||
switch( RI.currentmodel->type )
|
||||
{
|
||||
case mod_world:
|
||||
case mod_brush:
|
||||
surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL;
|
||||
if( surf ) r_currentLightStyle = &tr.superLightStyles[surf->superLightStyle];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MB_DECAL:
|
||||
j = ((mb->sortkey>>10) & (MAX_SUPER_STYLES - 1));
|
||||
r_currentLightStyle = &tr.superLightStyles[j - 1];
|
||||
surf = R_DecalFromMeshbuf( mb )->psurf;
|
||||
break;
|
||||
}
|
||||
|
||||
MB_NUM2SHADER( mb->shaderkey, r_currentShader );
|
||||
|
||||
|
@ -2960,9 +2984,6 @@ static _inline void R_SetColorForOutlines( void )
|
|||
}
|
||||
}
|
||||
break;
|
||||
case MB_SPRITE:
|
||||
pglColor4fv( colorBlue );
|
||||
break;
|
||||
case MB_POLY:
|
||||
case MB_DECAL:
|
||||
pglColor4fv( colorGreen );
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "bspfile.h"
|
||||
#include "const.h"
|
||||
|
||||
#define DECAL_DISTANCE 4 // FIXME: revert to 10 ?
|
||||
#define DECAL_DISTANCE 4 // too big values produce more clipped polygons
|
||||
#define MAX_DECALCLIPVERT 32 // produced vertexes of fragmented decal
|
||||
#define DECAL_CACHEENTRY 256 // MUST BE POWER OF 2 or code below needs to change!
|
||||
|
||||
|
@ -19,6 +19,13 @@
|
|||
#define MAX_OVERLAP_DECALS 4
|
||||
#define DECAL_OVERLAP_DIST 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t m_vPos;
|
||||
vec2_t m_tCoords; // these are the texcoords for the decal itself
|
||||
vec2_t m_LMCoords; // lightmap texcoords for the decal.
|
||||
} decalvert_t;
|
||||
|
||||
// FIXME: move this out to the r_math.c ?
|
||||
typedef struct
|
||||
{
|
||||
|
@ -61,62 +68,38 @@ typedef struct
|
|||
int m_Flags;
|
||||
int m_Entity; // Entity the decal is applied to.
|
||||
float m_scale;
|
||||
float m_flFadeTime;
|
||||
float m_flFadeDuration;
|
||||
int m_decalWidth;
|
||||
int m_decalHeight;
|
||||
rgba_t m_Color;
|
||||
vec3_t m_Basis[3];
|
||||
} decalinfo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int decalIndex;
|
||||
decalvert_t decalVert[4];
|
||||
} decalcache_t;
|
||||
|
||||
decalcache_t gDecalCache[DECAL_CACHEENTRY];
|
||||
|
||||
// list of actual decals, that we needs to rendering
|
||||
uint r_numDecals;
|
||||
decal_t *r_drawdecals[MAX_DECALS];
|
||||
|
||||
static decalvert_t g_DecalClipVerts[MAX_DECALCLIPVERT];
|
||||
static decalvert_t g_DecalClipVerts2[MAX_DECALCLIPVERT];
|
||||
static mesh_t decal_mesh;
|
||||
static byte *r_decalPool; // pool of decal meshes
|
||||
|
||||
static decal_t gDecalPool[MAX_DECALS];
|
||||
static int gDecalCount;
|
||||
|
||||
static int R_DecalIndex( decal_t *pdecal )
|
||||
void R_ClearDecals( void )
|
||||
{
|
||||
return ( pdecal - gDecalPool );
|
||||
Mem_EmptyPool( r_decalPool );
|
||||
Mem_Set( gDecalPool, 0, sizeof( gDecalPool ));
|
||||
gDecalCount = 0;
|
||||
}
|
||||
|
||||
static int R_DecalCacheIndex( int index )
|
||||
// Init the decal pool
|
||||
void R_InitDecals( void )
|
||||
{
|
||||
return index & (DECAL_CACHEENTRY-1);
|
||||
r_decalPool = Mem_AllocPool( "Decals Mesh Pool" );
|
||||
R_ClearDecals ();
|
||||
}
|
||||
|
||||
static decalcache_t *R_DecalCacheSlot( int decalIndex )
|
||||
void R_ShutdownDecals( void )
|
||||
{
|
||||
int cacheIndex;
|
||||
|
||||
cacheIndex = R_DecalCacheIndex( decalIndex ); // find the cache slot
|
||||
|
||||
return gDecalCache + cacheIndex;
|
||||
}
|
||||
|
||||
|
||||
// release the cache entry for this decal
|
||||
static void R_DecalCacheClear( decal_t *pdecal )
|
||||
{
|
||||
int index;
|
||||
decalcache_t *pCache;
|
||||
|
||||
index = R_DecalIndex( pdecal );
|
||||
pCache = R_DecalCacheSlot( index ); // Find the cache slot
|
||||
|
||||
if( pCache->decalIndex == index ) // If this is the decal that's cached here, clear it.
|
||||
pCache->decalIndex = -1;
|
||||
Mem_FreePool( &r_decalPool );
|
||||
}
|
||||
|
||||
// unlink pdecal from any surface it's attached to
|
||||
|
@ -124,7 +107,6 @@ static void R_DecalUnlink( decal_t *pdecal )
|
|||
{
|
||||
decal_t *tmp;
|
||||
|
||||
R_DecalCacheClear( pdecal );
|
||||
if( pdecal->psurf )
|
||||
{
|
||||
if( pdecal->psurf->pdecals == pdecal )
|
||||
|
@ -147,7 +129,12 @@ static void R_DecalUnlink( decal_t *pdecal )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pdecal->mesh )
|
||||
Mem_Free( pdecal->mesh );
|
||||
|
||||
pdecal->psurf = NULL;
|
||||
pdecal->mesh = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,10 +174,14 @@ static decal_t *R_DecalAlloc( decal_t *pdecal )
|
|||
//-----------------------------------------------------------------------------
|
||||
// compute the decal basis based on surface normal, and preferred saxis
|
||||
//-----------------------------------------------------------------------------
|
||||
void R_DecalComputeBasis( vec3_t surfaceNormal, vec3_t pSAxis, vec3_t textureSpaceBasis[3] )
|
||||
void R_DecalComputeBasis( msurface_t *surf, vec3_t pSAxis, vec3_t textureSpaceBasis[3] )
|
||||
{
|
||||
// get the surface normal.
|
||||
VectorCopy( surfaceNormal, textureSpaceBasis[2] );
|
||||
vec3_t surfaceNormal;
|
||||
|
||||
// setup normal
|
||||
if( surf->flags & SURF_PLANEBACK )
|
||||
VectorNegate( surf->plane->normal, surfaceNormal );
|
||||
else VectorCopy( surf->plane->normal, surfaceNormal );
|
||||
|
||||
if( pSAxis )
|
||||
{
|
||||
|
@ -211,36 +202,16 @@ void R_DecalComputeBasis( vec3_t surfaceNormal, vec3_t pSAxis, vec3_t textureSpa
|
|||
// Fall through to the standard algorithm for parallel or antiparallel
|
||||
}
|
||||
|
||||
// floor/ceiling?
|
||||
if( fabs( surfaceNormal[2] ) > 0.70710678118654752440084436210485f ) // sin( 45 ) degrees
|
||||
{
|
||||
textureSpaceBasis[0][0] = 1.0f;
|
||||
textureSpaceBasis[0][1] = 0.0f;
|
||||
textureSpaceBasis[0][2] = 0.0f;
|
||||
|
||||
// T = S cross N
|
||||
CrossProduct( textureSpaceBasis[0], textureSpaceBasis[2], textureSpaceBasis[1] );
|
||||
|
||||
// S = N cross T
|
||||
CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
|
||||
}
|
||||
else // wall
|
||||
{
|
||||
textureSpaceBasis[1][0] = 0.0f;
|
||||
textureSpaceBasis[1][1] = 0.0f;
|
||||
textureSpaceBasis[1][2] = -1.0f;
|
||||
|
||||
// S = N cross T
|
||||
CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
|
||||
// T = S cross N
|
||||
CrossProduct( textureSpaceBasis[0], textureSpaceBasis[2], textureSpaceBasis[1] );
|
||||
}
|
||||
// original Half-Life algorithm: get textureBasis from linked surface
|
||||
VectorCopy( surf->texinfo->vecs[0], textureSpaceBasis[0] );
|
||||
VectorCopy( surf->texinfo->vecs[1], textureSpaceBasis[1] );
|
||||
VectorCopy( surfaceNormal, textureSpaceBasis[2] );
|
||||
|
||||
VectorNormalizeFast( textureSpaceBasis[0] );
|
||||
VectorNormalizeFast( textureSpaceBasis[1] );
|
||||
}
|
||||
|
||||
void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, vec3_t vSurfNormal, ref_shader_t *pShader, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
|
||||
void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
|
||||
{
|
||||
float *sAxis = NULL;
|
||||
|
||||
|
@ -248,7 +219,7 @@ void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, vec3_t vSurfNormal, ref_sha
|
|||
sAxis = pDecal->saxis;
|
||||
|
||||
// Compute the non-scaled decal basis
|
||||
R_DecalComputeBasis( vSurfNormal, sAxis, textureSpaceBasis );
|
||||
R_DecalComputeBasis( surf, sAxis, textureSpaceBasis );
|
||||
|
||||
// world width of decal = ptexture->width / pDecal->scale
|
||||
// world height of decal = ptexture->height / pDecal->scale
|
||||
|
@ -268,21 +239,20 @@ void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t tex
|
|||
|
||||
for( j = 0; j < surf->mesh->numVerts; j++ )
|
||||
{
|
||||
Vector4Copy( surf->mesh->vertexArray[j], pVerts[j].m_vPos ); // copy model space coordinates
|
||||
VectorCopy( surf->mesh->vertexArray[j], pVerts[j].m_vPos ); // copy model space coordinates
|
||||
pVerts[j].m_tCoords[0] = DotProduct( pVerts[j].m_vPos, textureSpaceBasis[0] ) - pDecal->dx + 0.5f;
|
||||
pVerts[j].m_tCoords[1] = DotProduct( pVerts[j].m_vPos, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||
pVerts[j].m_LMCoords[0] = pVerts[j].m_LMCoords[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Figure out where the decal maps onto the surface.
|
||||
void R_SetupDecalClip( decalvert_t *pOutVerts, decal_t *pDecal, vec3_t vSurfNormal, ref_shader_t *pMaterial, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
|
||||
void R_SetupDecalClip( decalvert_t *pOutVerts, decal_t *pDecal, msurface_t *surf, ref_shader_t *pMaterial, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
|
||||
{
|
||||
// if ( pOutVerts == NULL )
|
||||
// pOutVerts = &g_DecalClipVerts[0];
|
||||
|
||||
R_SetupDecalTextureSpaceBasis( pDecal, vSurfNormal, pMaterial, textureSpaceBasis, decalWorldScale );
|
||||
R_SetupDecalTextureSpaceBasis( pDecal, surf, pMaterial, textureSpaceBasis, decalWorldScale );
|
||||
|
||||
// Generate texture coordinates for each vertex in decal s,t space
|
||||
// probably should pre-generate this, store it and use it for decal-decal collisions
|
||||
|
@ -370,7 +340,7 @@ decalvert_t *R_DoDecalSHClip( decalvert_t *pInVerts, decalvert_t *pOutVerts, dec
|
|||
s = v->m_tCoords[0];
|
||||
t = v->m_tCoords[1];
|
||||
|
||||
if ( (s != 0.0 && s != 1.0) || (t != 0.0 && t != 1.0) )
|
||||
if (( s != 0.0f && s != 1.0f ) || ( t != 0.0f && t != 1.0f ))
|
||||
clipped = 1;
|
||||
}
|
||||
|
||||
|
@ -394,7 +364,7 @@ decalvert_t *R_DecalVertsClip( decalvert_t *pOutVerts, decal_t *pDecal, msurface
|
|||
vec3_t textureSpaceBasis[3];
|
||||
|
||||
// figure out where the decal maps onto the surface.
|
||||
R_SetupDecalClip( pOutVerts, pDecal, surf->plane->normal, pShader, textureSpaceBasis, decalWorldScale );
|
||||
R_SetupDecalClip( pOutVerts, pDecal, surf, pShader, textureSpaceBasis, decalWorldScale );
|
||||
|
||||
// build the initial list of vertices from the surface verts.
|
||||
R_SetupDecalVertsForMSurface( pDecal, surf, textureSpaceBasis, g_DecalClipVerts );
|
||||
|
@ -431,25 +401,11 @@ static void R_DecalVertsLight( decalvert_t *v, msurface_t *surf, int vertCount )
|
|||
|
||||
static decalvert_t* R_DecalVertsNoclip( decal_t *pdecal, msurface_t *surf, ref_shader_t *pShader )
|
||||
{
|
||||
decalcache_t *pCache;
|
||||
decalvert_t *vlist;
|
||||
int decalIndex;
|
||||
int outCount;
|
||||
|
||||
decalIndex = R_DecalIndex( pdecal );
|
||||
pCache = R_DecalCacheSlot( decalIndex );
|
||||
|
||||
// Is the decal cached?
|
||||
if ( pCache->decalIndex == decalIndex )
|
||||
{
|
||||
return &pCache->decalVert[0];
|
||||
}
|
||||
|
||||
pCache->decalIndex = decalIndex;
|
||||
vlist = &pCache->decalVert[0];
|
||||
|
||||
// use the old code for now, and just cache them
|
||||
vlist = R_DecalVertsClip( vlist, pdecal, surf, pShader, &outCount );
|
||||
vlist = R_DecalVertsClip( NULL, pdecal, surf, pShader, &outCount );
|
||||
|
||||
R_DecalVertsLight( vlist, surf, 4 );
|
||||
|
||||
|
@ -505,7 +461,7 @@ static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int
|
|||
vec2_t vDecalMin, vDecalMax;
|
||||
vec2_t vUnionMin, vUnionMax;
|
||||
|
||||
R_SetupDecalTextureSpaceBasis( pDecal, surf->plane->normal, pShader, testBasis, testWorldScale );
|
||||
R_SetupDecalTextureSpaceBasis( pDecal, surf, pShader, testBasis, testWorldScale );
|
||||
|
||||
VectorSubtract( decalinfo->m_Position, decalExtents[0], testPosition[0] );
|
||||
VectorSubtract( decalinfo->m_Position, decalExtents[1], testPosition[1] );
|
||||
|
@ -551,7 +507,6 @@ static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int
|
|||
}
|
||||
|
||||
// Add the decal to the surface's list of decals.
|
||||
// If the surface is a displacement, let the displacement precalculate data for the decal.
|
||||
static void R_AddDecalToSurface( decal_t *pdecal, msurface_t *surf, decalinfo_t *decalinfo )
|
||||
{
|
||||
decal_t *pold;
|
||||
|
@ -570,9 +525,12 @@ static void R_AddDecalToSurface( decal_t *pdecal, msurface_t *surf, decalinfo_t
|
|||
surf->pdecals = pdecal;
|
||||
}
|
||||
|
||||
// Tag surface
|
||||
// tag surface
|
||||
pdecal->psurf = surf;
|
||||
pdecal->m_Size = decalinfo->m_Size;
|
||||
|
||||
// at this point decal are linked with surface
|
||||
// and will be culled, drawing and sorting
|
||||
// together with surface
|
||||
}
|
||||
|
||||
static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, float y )
|
||||
|
@ -608,16 +566,13 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl
|
|||
pdecal->entityIndex = decalinfo->m_Entity;
|
||||
|
||||
// Get dynamic information from the material (fade start, fade time)
|
||||
/*
|
||||
// pseudo-code for future expansions
|
||||
if( shader->decalFadeTime )
|
||||
if( decalinfo->m_flFadeDuration != 0.0f )
|
||||
{
|
||||
pdecal->flags |= FDECAL_DYNAMIC;
|
||||
pdecal->fadeStartTime = RI.refdef.time + RANDOM_LONG( shader->decalTime / 2, shader->decalTime );
|
||||
pdecal->fadeDuration = decalinfo->m_flFadeDuration;
|
||||
pdecal->fadeStartTime = decalinfo->m_flFadeTime;
|
||||
pdecal->fadeStartTime += RI.refdef.time;
|
||||
}
|
||||
*/
|
||||
// Is this a second-pass decal?
|
||||
// if( shader->decalSecondPass ) pdecal->flags |= FDECAL_SECONDPASS;
|
||||
|
||||
// check to see if the decal actually intersects the surface
|
||||
// if not, then remove the decal
|
||||
|
@ -629,8 +584,6 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl
|
|||
return;
|
||||
}
|
||||
|
||||
Msg( "R_AddDecalToSurface( %i verts )\n", vertCount );
|
||||
|
||||
// add to the surface's list
|
||||
R_AddDecalToSurface( pdecal, surf, decalinfo );
|
||||
}
|
||||
|
@ -657,7 +610,7 @@ void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo )
|
|||
if( decalinfo->m_Flags & FDECAL_USESAXIS )
|
||||
sAxis = decalinfo->m_SAxis;
|
||||
|
||||
R_DecalComputeBasis( surf->plane->normal, sAxis, decalinfo->m_Basis );
|
||||
R_DecalComputeBasis( surf, sAxis, decalinfo->m_Basis );
|
||||
|
||||
// Compute an effective width and height (axis aligned) in the parent texture space
|
||||
// How does this work? decalBasis[0] represents the u-direction (width)
|
||||
|
@ -703,43 +656,14 @@ static void R_DecalNodeSurfaces( mnode_t* node, decalinfo_t *decalinfo )
|
|||
|
||||
for( i = 0, surf = node->firstface; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
// If this is a water decal, ONLY decal water, reject other surfaces
|
||||
if( decalinfo->m_Flags & FDECAL_WATER )
|
||||
{
|
||||
if(!( surf->flags & SURF_DRAWTURB ))
|
||||
continue;
|
||||
}
|
||||
// never apply decals on the water or sky surfaces
|
||||
if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY))
|
||||
continue;
|
||||
|
||||
R_DecalSurface( surf, decalinfo );
|
||||
}
|
||||
}
|
||||
|
||||
void R_DecalLeaf( mleaf_t *pleaf, decalinfo_t *decalinfo )
|
||||
{
|
||||
msurface_t **mark, *surf;
|
||||
int i;
|
||||
|
||||
for( i = 0, mark = pleaf->firstMarkSurface; i < pleaf->numMarkSurfaces; i++, mark++ )
|
||||
{
|
||||
float dist;
|
||||
|
||||
surf = *mark;
|
||||
|
||||
// If this is a water decal, ONLY decal water, reject other surfaces
|
||||
if( decalinfo->m_Flags & FDECAL_WATER )
|
||||
{
|
||||
if(!( surf->flags & SURF_DRAWTURB ))
|
||||
continue;
|
||||
}
|
||||
|
||||
dist = fabs( DotProduct( decalinfo->m_Position, surf->plane->normal ) - surf->plane->dist );
|
||||
|
||||
if( dist < DECAL_DISTANCE )
|
||||
{
|
||||
R_DecalSurface( surf, decalinfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Recursive routine to find surface to apply a decal to. World coordinates of
|
||||
// the decal are passed in r_recalpos like the rest of the engine. This should
|
||||
|
@ -750,12 +674,11 @@ static void R_DecalNode( mnode_t *node, decalinfo_t *decalinfo )
|
|||
cplane_t *splitplane;
|
||||
float dist;
|
||||
|
||||
if( !node ) return;
|
||||
Com_Assert( node == NULL );
|
||||
|
||||
if( !node->plane )
|
||||
{
|
||||
// hit a leaf
|
||||
R_DecalLeaf(( mleaf_t *)node, decalinfo );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -789,7 +712,7 @@ static void R_DecalNode( mnode_t *node, decalinfo_t *decalinfo )
|
|||
}
|
||||
|
||||
// Shoots a decal onto the surface of the BSP. position is the center of the decal in world coords
|
||||
static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model, vec3_t pos, vec3_t saxis, int flags, rgba_t color )
|
||||
static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration )
|
||||
{
|
||||
decalinfo_t decalInfo;
|
||||
mbrushmodel_t *bmodel;
|
||||
|
@ -807,10 +730,43 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
return;
|
||||
}
|
||||
|
||||
VectorCopy( pos, decalInfo.m_Position ); // pass position in global
|
||||
decalInfo.m_pModel = model;
|
||||
|
||||
if( model ) decalInfo.m_pModel = model;
|
||||
else decalInfo.m_pModel = NULL;
|
||||
if( model->type == mod_brush )
|
||||
{
|
||||
edict_t *ent = ri.GetClientEdict( entity );
|
||||
vec3_t pos_l;
|
||||
|
||||
if( ent && !ent->free )
|
||||
{
|
||||
// transform decal position in local bmodel space
|
||||
VectorSubtract( pos, ent->v.origin, pos_l );
|
||||
|
||||
if( !VectorIsNull( ent->v.angles ))
|
||||
{
|
||||
vec3_t temp, forward, right, up;
|
||||
|
||||
VectorCopy( ent->v.angles, temp );
|
||||
AngleVectors( temp, forward, right, up );
|
||||
|
||||
VectorCopy( pos_l, temp );
|
||||
pos_l[0] = DotProduct( temp, forward );
|
||||
pos_l[1] = -DotProduct( temp, right );
|
||||
pos_l[2] = DotProduct( temp, up );
|
||||
}
|
||||
VectorCopy( pos_l, decalInfo.m_Position );
|
||||
}
|
||||
else
|
||||
{
|
||||
// give untransformed pos
|
||||
VectorCopy( pos, decalInfo.m_Position );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pass position in global
|
||||
VectorCopy( pos, decalInfo.m_Position );
|
||||
}
|
||||
|
||||
// deal with the s axis if one was passed in
|
||||
if( saxis )
|
||||
|
@ -822,6 +778,9 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
// more state used by R_DecalNode()
|
||||
decalInfo.m_pShader = shader;
|
||||
|
||||
decalInfo.m_flFadeTime = fadeTime;
|
||||
decalInfo.m_flFadeDuration = fadeDuration;
|
||||
|
||||
// don't optimize custom decals
|
||||
if(!( flags & FDECAL_CUSTOM ))
|
||||
flags |= FDECAL_CLIPTEST;
|
||||
|
@ -838,7 +797,7 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
// compute the decal dimensions in world space
|
||||
decalInfo.m_decalWidth = shader->stages[0].textures[0]->srcWidth / decalInfo.m_scale;
|
||||
decalInfo.m_decalHeight = shader->stages[0].textures[0]->srcHeight / decalInfo.m_scale;
|
||||
Vector4Copy( color, decalInfo.m_Color );
|
||||
if( color ) Vector4Copy( color, decalInfo.m_Color );
|
||||
|
||||
bmodel = (mbrushmodel_t *)decalInfo.m_pModel->extradata;
|
||||
pnodes = bmodel->firstmodelnode;
|
||||
|
@ -846,7 +805,7 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
R_DecalNode( pnodes, &decalInfo );
|
||||
}
|
||||
|
||||
bool R_DecalShoot( shader_t texture, int entity, model_t modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color )
|
||||
bool R_DecalShoot( shader_t texture, int entityIndex, model_t modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration )
|
||||
{
|
||||
ref_shader_t *shader;
|
||||
ref_model_t *model;
|
||||
|
@ -860,15 +819,16 @@ bool R_DecalShoot( shader_t texture, int entity, model_t modelIndex, vec3_t pos,
|
|||
model = r_worldmodel;
|
||||
else model = cl_models[modelIndex];
|
||||
|
||||
R_DecalShoot_( shader, entity, model, pos, saxis, flags, color );
|
||||
R_DecalShoot_( shader, entityIndex, model, pos, saxis, flags, color, fadeTime, fadeDuration );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_AddSurfaceDecals( msurface_t *surf )
|
||||
{
|
||||
decal_t *plist;
|
||||
|
||||
decal_t *plist;
|
||||
meshbuffer_t *mb;
|
||||
|
||||
Com_Assert( surf == NULL );
|
||||
|
||||
plist = surf->pdecals;
|
||||
|
@ -877,15 +837,11 @@ void R_AddSurfaceDecals( msurface_t *surf )
|
|||
{
|
||||
// Store off the next pointer, DecalUpdateAndDrawSingle could unlink
|
||||
decal_t *pnext = plist->pnext;
|
||||
|
||||
if( r_numDecals >= MAX_DECALS )
|
||||
{
|
||||
MsgDev( D_ERROR, "R_AddSurfaceDecals: too many decals\n" );
|
||||
break;
|
||||
}
|
||||
int decalNum = -((signed int)(plist - gDecalPool) + 1);
|
||||
|
||||
// add decals into list
|
||||
r_drawdecals[r_numDecals++] = plist;
|
||||
mb = R_AddMeshToList( MB_DECAL, surf->fog, plist->shader, decalNum );
|
||||
if( mb ) mb->sortkey |= (( surf->superLightStyle+1 ) << 10 );
|
||||
plist = pnext;
|
||||
}
|
||||
}
|
||||
|
@ -906,7 +862,7 @@ bool DecalUpdate( decal_t *pDecal )
|
|||
// Build the vertex list for a decal on a surface and clip it to the surface.
|
||||
// This is a template so it can work on world surfaces and dynamic displacement
|
||||
// triangles the same way.
|
||||
decalvert_t* R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, int *outCount )
|
||||
decalvert_t *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, int *outCount )
|
||||
{
|
||||
decalvert_t *v;
|
||||
|
||||
|
@ -923,6 +879,113 @@ decalvert_t* R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, ref_shader_t
|
|||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_BuildMeshForDecal
|
||||
|
||||
creates mesh for decal on first rendering
|
||||
====================
|
||||
*/
|
||||
mesh_t *R_BuildMeshForDecal( decal_t *pDecal )
|
||||
{
|
||||
decalvert_t *v;
|
||||
uint index, bufSize;
|
||||
bool createSTverts = false;
|
||||
int i, numVerts, numElems;
|
||||
byte *buffer;
|
||||
vec3_t normal;
|
||||
mesh_t *mesh;
|
||||
|
||||
if( pDecal->mesh )
|
||||
{
|
||||
// already have mesh
|
||||
return pDecal->mesh;
|
||||
}
|
||||
|
||||
// first rendering? create mesh for it
|
||||
v = R_DecalSetupVerts( pDecal, pDecal->psurf, pDecal->shader, &numVerts );
|
||||
|
||||
// degenerate polygon
|
||||
if( !numVerts ) return NULL;
|
||||
|
||||
// allocate mesh
|
||||
numElems = (numVerts - 2) * 3;
|
||||
|
||||
if( mapConfig.deluxeMappingEnabled || ( pDecal->shader->flags & SHADER_PORTAL_CAPTURE2 ))
|
||||
createSTverts = true;
|
||||
|
||||
// mesh + ( align vertex, align normal, (st + lmst) + elem * numElems) * numVerts;
|
||||
bufSize = sizeof( mesh_t ) + numVerts * ( sizeof( vec4_t ) + sizeof( vec4_t ) + sizeof( vec4_t )) + numElems * sizeof( elem_t );
|
||||
if( createSTverts ) bufSize += numVerts * sizeof( vec4_t );
|
||||
|
||||
buffer = Mem_Alloc( r_decalPool, bufSize );
|
||||
|
||||
mesh = (mesh_t *)buffer;
|
||||
buffer += sizeof( mesh_t );
|
||||
mesh->numVerts = numVerts;
|
||||
mesh->numElems = numElems;
|
||||
|
||||
// setup pointers
|
||||
mesh->vertexArray = (vec4_t *)buffer;
|
||||
buffer += numVerts * sizeof( vec4_t );
|
||||
mesh->normalsArray = (vec4_t *)buffer;
|
||||
buffer += numVerts * sizeof( vec4_t );
|
||||
mesh->stCoordArray = (vec2_t *)buffer;
|
||||
buffer += numVerts * sizeof( vec2_t );
|
||||
mesh->lmCoordArray = (vec2_t *)buffer;
|
||||
buffer += numVerts * sizeof( vec2_t );
|
||||
mesh->elems = (elem_t *)buffer;
|
||||
buffer += numElems * sizeof( elem_t );
|
||||
|
||||
// create indices
|
||||
for( i = 0, index = 2; i < mesh->numElems; i += 3, index++ )
|
||||
{
|
||||
mesh->elems[i+0] = 0;
|
||||
mesh->elems[i+1] = index - 1;
|
||||
mesh->elems[i+2] = index;
|
||||
}
|
||||
|
||||
// setup normal
|
||||
if( pDecal->psurf->flags & SURF_PLANEBACK )
|
||||
VectorNegate( pDecal->psurf->plane->normal, normal );
|
||||
else VectorCopy( pDecal->psurf->plane->normal, normal );
|
||||
|
||||
VectorNormalize( normal );
|
||||
|
||||
// create vertices
|
||||
mesh->numVerts = numVerts;
|
||||
|
||||
for( i = 0; i < numVerts; i++, v++ )
|
||||
{
|
||||
VectorCopy( v->m_vPos, mesh->vertexArray[i] );
|
||||
VectorCopy( normal, mesh->normalsArray[i] );
|
||||
Vector2Copy( v->m_tCoords, mesh->stCoordArray[i] );
|
||||
Vector2Copy( v->m_LMCoords, mesh->lmCoordArray[i] );
|
||||
}
|
||||
|
||||
if( createSTverts )
|
||||
{
|
||||
mesh->sVectorsArray = (vec4_t *)buffer;
|
||||
buffer += numVerts * sizeof( vec4_t );
|
||||
R_BuildTangentVectors( mesh->numVerts, mesh->vertexArray, mesh->normalsArray, mesh->stCoordArray, mesh->numElems / 3, mesh->elems, mesh->sVectorsArray );
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
decal_t *R_DecalFromMeshbuf( const meshbuffer_t *mb )
|
||||
{
|
||||
decal_t *pDecal;
|
||||
|
||||
pDecal = &gDecalPool[-mb->infokey-1];
|
||||
|
||||
// in case we compare two meshes for batching
|
||||
if( !pDecal->mesh )
|
||||
pDecal->mesh = R_BuildMeshForDecal( pDecal );
|
||||
|
||||
return pDecal;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PushDecal
|
||||
|
@ -933,83 +996,169 @@ void R_PushDecal( const meshbuffer_t *mb )
|
|||
decal_t *pDecal;
|
||||
ref_shader_t *shader;
|
||||
bool retire = false;
|
||||
int i, outCount, features;
|
||||
decalvert_t *v;
|
||||
int features;
|
||||
|
||||
MB_NUM2SHADER( mb->shaderkey, shader );
|
||||
pDecal = r_drawdecals[-mb->infokey-1];
|
||||
|
||||
Com_Assert( pDecal == NULL );
|
||||
|
||||
if( !pDecal->shader )
|
||||
return;
|
||||
pDecal = &gDecalPool[-mb->infokey-1];
|
||||
|
||||
// update dynamic decals
|
||||
if( pDecal->flags & FDECAL_DYNAMIC )
|
||||
retire = DecalUpdate( pDecal );
|
||||
|
||||
v = R_DecalSetupVerts( pDecal, pDecal->psurf, pDecal->shader, &outCount );
|
||||
|
||||
if( !outCount ) return; // nothing to draw
|
||||
if( retire ) R_DecalUnlink( pDecal );
|
||||
|
||||
features = ( shader->features|MF_TRIFAN );
|
||||
|
||||
|
||||
decal_mesh.numVerts = outCount;
|
||||
decal_mesh.vertexArray = inVertsArray;
|
||||
decal_mesh.normalsArray = inNormalsArray;
|
||||
decal_mesh.stCoordArray = inCoordsArray;
|
||||
decal_mesh.colorsArray = inColorsArray;
|
||||
decal_mesh.lmCoordArray = inLightmapCoordsArray;
|
||||
|
||||
for( i = 0; i < outCount; i++, v++ )
|
||||
if( !pDecal->mesh )
|
||||
{
|
||||
Vector4Copy( v->m_vPos, inVertsArray[r_backacc.numVerts+i] );
|
||||
Vector4Copy( pDecal->color, inColorsArray[r_backacc.numVerts+i] );
|
||||
Vector2Copy( v->m_tCoords, inCoordsArray[r_backacc.numVerts+i] );
|
||||
Vector2Copy( v->m_LMCoords, inLightmapCoordsArray[r_backacc.numVerts+i] );
|
||||
Vector4Set( inNormalsArray[r_backacc.numVerts+i], 0.0f, 0.0f, 1.0f, 1.0f );
|
||||
// first draw? create mesh for it
|
||||
pDecal->mesh = R_BuildMeshForDecal( pDecal );
|
||||
}
|
||||
|
||||
R_PushMesh( &decal_mesh, features );
|
||||
if( !pDecal->mesh || retire )
|
||||
{
|
||||
// invalid or expired decal, unlink it
|
||||
R_DecalUnlink( pDecal );
|
||||
return;
|
||||
}
|
||||
|
||||
features = shader->features;
|
||||
|
||||
// Deal with fading out... (should this be done in the shader?)
|
||||
// Note that we do it with per-vertex color even though the translucency
|
||||
// is constant so as to not change any rendering state (like the constant
|
||||
// alpha value)
|
||||
if( pDecal->flags & FDECAL_DYNAMIC )
|
||||
{
|
||||
float fadeval;
|
||||
rgba_t color;
|
||||
|
||||
Vector4Copy( pDecal->color, color );
|
||||
|
||||
// negative fadeDuration value means to fade in
|
||||
if( pDecal->fadeDuration < 0 )
|
||||
{
|
||||
fadeval = -( RI.refdef.time - pDecal->fadeStartTime ) / pDecal->fadeDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
fadeval = 1.0f - ( RI.refdef.time - pDecal->fadeStartTime ) / pDecal->fadeDuration;
|
||||
}
|
||||
color[3] = bound( 0, (byte)(fadeval * 255), 255 );
|
||||
|
||||
// FIXME: apply custom color to decal
|
||||
}
|
||||
|
||||
R_PushMesh( pDecal->mesh, features );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_AddDecalsToList
|
||||
=============================================================
|
||||
|
||||
list contain only decals that passed culling
|
||||
================
|
||||
DECALS SERIALIZATION
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
void R_AddDecalsToList( void )
|
||||
static bool R_DecalUnProject( decal_t *pdecal, decallist_t *entry )
|
||||
{
|
||||
decal_t *decal;
|
||||
meshbuffer_t *mb;
|
||||
int i;
|
||||
if( !pdecal || !( pdecal->psurf ))
|
||||
return false;
|
||||
|
||||
RI.currententity = r_worldent;
|
||||
RI.currentmodel = r_worldmodel;
|
||||
|
||||
for( i = 0; i < r_numDecals; i++ )
|
||||
{
|
||||
decal = r_drawdecals[i];
|
||||
Com_Assert( decal == NULL );
|
||||
Com_Assert( decal->shader == NULL );
|
||||
mb = R_AddMeshToList( MB_DECAL, NULL, decal->shader, -((signed int)i + 1 ));
|
||||
// if( mb ) mb->lastPoly = i;
|
||||
}
|
||||
VectorCopy( pdecal->position, entry->position );
|
||||
entry->entityIndex = pdecal->entityIndex;
|
||||
|
||||
// Grab surface plane equation
|
||||
VectorCopy( pdecal->psurf->plane->normal, entry->impactPlaneNormal );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_DrawSingleDecal( const meshbuffer_t *mb )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pList -
|
||||
// count -
|
||||
// Output : static int
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DecalListAdd( decallist_t *pList, int count )
|
||||
{
|
||||
RI.currententity = r_worldent;
|
||||
RI.currentmodel = r_worldmodel;
|
||||
vec3_t tmp;
|
||||
decallist_t *pdecal;
|
||||
int i;
|
||||
|
||||
// decals are already batched at this point
|
||||
R_PushDecal( mb );
|
||||
pdecal = pList + count;
|
||||
|
||||
if( RI.previousentity != RI.currententity )
|
||||
R_LoadIdentity();
|
||||
R_RenderMeshBuffer( mb );
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( !com.strcmp( pdecal->name, pList[i].name ) && pdecal->entityIndex == pList[i].entityIndex )
|
||||
{
|
||||
VectorSubtract( pdecal->position, pList[i].position, tmp ); // Merge
|
||||
if( VectorLength( tmp ) < 2 )
|
||||
{
|
||||
// UNDONE: Tune this '2' constant
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is a new decal
|
||||
return count + 1;
|
||||
}
|
||||
|
||||
static int DecalDepthCompare( const void *a, const void *b )
|
||||
{
|
||||
const decallist_t *elem1, *elem2;
|
||||
|
||||
elem1 = (const decallist_t *)a;
|
||||
elem2 = (const decallist_t *)b;
|
||||
|
||||
if ( elem1->depth > elem2->depth )
|
||||
return -1;
|
||||
if ( elem1->depth < elem2->depth )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called by CSaveRestore::SaveClientState
|
||||
// Input : *pList -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int R_CreateDecalList( decallist_t *pList )
|
||||
{
|
||||
int total = 0;
|
||||
int i, depth;
|
||||
|
||||
if( r_worldmodel && !( RI.refdef.flags & RDF_NOWORLDMODEL ))
|
||||
{
|
||||
for( i = 0; i < MAX_DECALS; i++ )
|
||||
{
|
||||
decal_t *decal = &gDecalPool[i];
|
||||
decal_t *pdecals;
|
||||
|
||||
// decal is in use and is not a custom decal
|
||||
if( decal->psurf == NULL || (decal->flags & ( FDECAL_CUSTOM|FDECAL_DONTSAVE )))
|
||||
continue;
|
||||
|
||||
// compute depth
|
||||
depth = 0;
|
||||
pdecals = decal->psurf->pdecals;
|
||||
|
||||
while( pdecals && pdecals != decal )
|
||||
{
|
||||
depth++;
|
||||
pdecals = pdecals->pnext;
|
||||
}
|
||||
|
||||
pList[total].depth = depth;
|
||||
pList[total].flags = decal->flags;
|
||||
|
||||
R_DecalUnProject( decal, &pList[total] );
|
||||
com.strncpy( pList[total].name, decal->shader->name, sizeof( pList[total].name ));
|
||||
|
||||
// check to see if the decal should be added
|
||||
total = DecalListAdd( pList, total );
|
||||
}
|
||||
}
|
||||
|
||||
// sort the decals lowest depth first, so they can be re-applied in order
|
||||
qsort( pList, total, sizeof( decallist_t ), DecalDepthCompare );
|
||||
|
||||
return total;
|
||||
}
|
|
@ -44,7 +44,7 @@ extern byte *r_temppool;
|
|||
#define Host_Error com.error
|
||||
|
||||
typedef unsigned int elem_t;
|
||||
typedef enum { RT_NONE, RT_MODEL, RT_SPRITE, RT_PORTALSURFACE, NUM_RTYPES } refEntityType_t;
|
||||
typedef enum { RT_NONE, RT_MODEL, RT_PORTALSURFACE, NUM_RTYPES } refEntityType_t;
|
||||
|
||||
/*
|
||||
skins will be outline flood filled and mip mapped
|
||||
|
@ -321,9 +321,6 @@ extern ref_entity_t r_entities[MAX_ENTITIES];
|
|||
extern uint r_numDlights;
|
||||
extern ref_dlight_t r_dlights[MAX_DLIGHTS];
|
||||
|
||||
extern uint r_numDecals;
|
||||
extern decal_t *r_drawdecals[MAX_DECALS];
|
||||
|
||||
extern uint r_numPolys;
|
||||
extern poly_t r_polys[MAX_POLYS];
|
||||
|
||||
|
@ -708,17 +705,20 @@ void R_ProgramDump_f( void );
|
|||
// r_decals.c
|
||||
//
|
||||
|
||||
bool R_DecalShoot( shader_t texture, int entity, model_t modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color );
|
||||
void R_InitDecals( void );
|
||||
void R_ClearDecals( void );
|
||||
void R_ShutdownDecals( void );
|
||||
bool R_DecalShoot( shader_t texture, int entity, model_t modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration );
|
||||
decal_t *R_DecalFromMeshbuf( const meshbuffer_t *mb );
|
||||
int R_CreateDecalList( decallist_t *pList );
|
||||
void R_AddSurfaceDecals( msurface_t *surf );
|
||||
void R_DrawSingleDecal( const meshbuffer_t *mb );
|
||||
void R_AddDecalsToList( void );
|
||||
void R_PushDecal( const meshbuffer_t *mb );
|
||||
|
||||
//
|
||||
// r_poly.c
|
||||
//
|
||||
void R_PushPoly( const meshbuffer_t *mb );
|
||||
void R_AddPolysToList( void );
|
||||
int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts, int maxfragments, fragment_t *fragments );
|
||||
msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test );
|
||||
|
||||
//
|
||||
|
|
|
@ -728,29 +728,6 @@ static void R_AddSpriteModelToList( ref_entity_t *e )
|
|||
if( mb ) mb->shaderkey |= ( bound( 1, 0x4000 - (uint)dist, 0x4000 - 1 )<<12 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AddSpritePolyToList
|
||||
=================
|
||||
*/
|
||||
static void R_AddSpritePolyToList( ref_entity_t *e )
|
||||
{
|
||||
float dist;
|
||||
meshbuffer_t *mb;
|
||||
|
||||
dist = (e->origin[0] - RI.refdef.vieworg[0]) * RI.vpn[0] + (e->origin[1] - RI.refdef.vieworg[1]) * RI.vpn[1] + (e->origin[2] - RI.refdef.vieworg[2]) * RI.vpn[2];
|
||||
if( dist < 0 ) return; // cull it because we don't want to sort unneeded things
|
||||
|
||||
if( RI.refdef.flags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( RI.params & RP_SKYPORTALVIEW ) )
|
||||
{
|
||||
if( R_VisCullSphere( e->origin, e->radius ) )
|
||||
return;
|
||||
}
|
||||
|
||||
mb = R_AddMeshToList( MB_SPRITE, R_FogForSphere( e->origin, e->radius ), e->customShader, -1 );
|
||||
if( mb ) mb->shaderkey |= ( bound( 1, 0x4000 - (unsigned int)dist, 0x4000 - 1 ) << 12 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_SpriteOverflow
|
||||
|
@ -1337,9 +1314,6 @@ static void R_CullEntities( void )
|
|||
default: break;
|
||||
}
|
||||
break;
|
||||
case RT_SPRITE:
|
||||
culled = ( e->radius <= 0 ) || ( e->customShader == NULL );
|
||||
break;
|
||||
case RT_NONE:
|
||||
default: break;
|
||||
}
|
||||
|
@ -1438,10 +1412,6 @@ add:
|
|||
default: break;
|
||||
}
|
||||
break;
|
||||
case RT_SPRITE:
|
||||
if( !shadowmap )
|
||||
R_AddSpritePolyToList( e );
|
||||
break;
|
||||
case RT_NONE:
|
||||
default: break;
|
||||
}
|
||||
|
@ -1621,8 +1591,6 @@ void R_RenderView( const ref_params_t *fd )
|
|||
|
||||
R_AddPolysToList();
|
||||
|
||||
R_AddDecalsToList();
|
||||
|
||||
if( r_speeds->integer )
|
||||
r_add_polys += ( Sys_DoubleTime() - starttime );
|
||||
}
|
||||
|
@ -1791,7 +1759,6 @@ void R_ClearScene( void )
|
|||
{
|
||||
r_numEntities = 1; // worldmodel
|
||||
r_numDlights = 0;
|
||||
r_numDecals = 0;
|
||||
r_numPolys = 0;
|
||||
RI.previousentity = NULL;
|
||||
RI.currententity = r_worldent;
|
||||
|
@ -2740,10 +2707,10 @@ render_exp_t DLLEXPORT *CreateAPI(stdlib_api_t *input, render_imp_t *engfuncs )
|
|||
re.DrawStretchRaw = R_DrawStretchRaw;
|
||||
re.DrawStretchPic = R_DrawStretchPic;
|
||||
re.GetSpriteTexture = R_GetSpriteTexture;
|
||||
re.GetFragments = R_GetClippedFragments;
|
||||
re.ScreenToWorld = R_ScreenToWorld;
|
||||
re.WorldToScreen = R_WorldToScreen;
|
||||
re.RSpeedsMessage = R_SpeedsMessage;
|
||||
re.CreateDecalList = R_CreateDecalList;
|
||||
re.CullBox = Mod_CullBox;
|
||||
re.Support = GL_Support;
|
||||
re.GetCurrentVis = Mod_GetCurrentVis;
|
||||
|
|
|
@ -406,6 +406,7 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm
|
|||
int type, features;
|
||||
bool nonMergable;
|
||||
msurface_t *surf, *nextSurf;
|
||||
decal_t *decal, *nextDecal;
|
||||
ref_shader_t *shader;
|
||||
ref_entity_t *ent;
|
||||
|
||||
|
@ -491,7 +492,6 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case MB_SPRITE:
|
||||
case MB_CORONA:
|
||||
nonMergable = R_PushSpritePoly( mb );
|
||||
if( nonMergable || !nextmb || (( nextmb->shaderkey & 0xFC000FFF ) != ( mb->shaderkey & 0xFC000FFF ))
|
||||
|
@ -518,7 +518,44 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm
|
|||
R_RenderMeshBuffer( mb );
|
||||
break;
|
||||
case MB_DECAL:
|
||||
R_DrawSingleDecal( mb );
|
||||
MB_NUM2SHADER( mb->shaderkey, shader );
|
||||
|
||||
features = shader->features;
|
||||
if( r_shownormals->integer )
|
||||
features |= MF_NORMALS;
|
||||
|
||||
nextDecal = NULL;
|
||||
decal = R_DecalFromMeshbuf( mb );
|
||||
|
||||
if( features & MF_NONBATCHED )
|
||||
{
|
||||
nonMergable = true;
|
||||
}
|
||||
else
|
||||
{ // check if we need to render batched geometry this frame
|
||||
if( nextmb
|
||||
&& ( nextmb->shaderkey == mb->shaderkey )
|
||||
&& ( nextmb->sortkey == mb->sortkey )
|
||||
&& ( nextmb->dlightbits == mb->dlightbits )
|
||||
&& ( nextmb->shadowbits == mb->shadowbits ))
|
||||
{
|
||||
if(( nextmb->sortkey & 3 ) == MB_DECAL )
|
||||
nextDecal = R_DecalFromMeshbuf( nextmb );
|
||||
}
|
||||
|
||||
nonMergable = nextDecal ? R_MeshOverflow2( decal->mesh, nextDecal->mesh ) : true;
|
||||
if( nonMergable && !r_backacc.numVerts )
|
||||
features |= MF_NONBATCHED;
|
||||
}
|
||||
|
||||
R_PushDecal( mb );
|
||||
|
||||
if( nonMergable )
|
||||
{
|
||||
if( RI.previousentity != RI.currententity )
|
||||
R_RotateForEntity( RI.currententity );
|
||||
R_RenderMeshBuffer( mb );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,10 @@ enum
|
|||
enum
|
||||
{
|
||||
MB_MODEL,
|
||||
MB_SPRITE,
|
||||
MB_POLY,
|
||||
MB_DECAL,
|
||||
MB_CORONA,
|
||||
MB_MAXTYPES = 5
|
||||
MB_MAXTYPES = 4
|
||||
};
|
||||
|
||||
typedef struct mesh_s
|
||||
|
|
|
@ -377,6 +377,16 @@ static void Mod_UpdateShaders( ref_model_t *mod )
|
|||
if( !mod || !mod->name )
|
||||
return;
|
||||
|
||||
if( mod->type == mod_world || mod->type == mod_brush )
|
||||
{
|
||||
mbrushmodel_t *bmodel;
|
||||
|
||||
// clearing all linked decals here
|
||||
bmodel = (mbrushmodel_t *)mod->extradata;
|
||||
for( i = 0; i < bmodel->numsurfaces; i++ )
|
||||
bmodel->surfaces[i].pdecals = NULL;
|
||||
}
|
||||
|
||||
for( i = 0; i < mod->numshaders; i++ )
|
||||
{
|
||||
shader = mod->shaders[i];
|
||||
|
|
|
@ -58,14 +58,6 @@ typedef struct
|
|||
cplane_t *planes;
|
||||
} mfog_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec4_t m_vPos;
|
||||
vec2_t m_tCoords; // these are the texcoords for the decal itself
|
||||
vec2_t m_LMCoords; // lightmap texcoords for the decal.
|
||||
// FIXME: adds the lightmapnum here ?
|
||||
} decalvert_t;
|
||||
|
||||
typedef struct decal_s
|
||||
{
|
||||
struct decal_s *pnext; // linked list for each surface
|
||||
|
@ -74,16 +66,13 @@ typedef struct decal_s
|
|||
|
||||
vec3_t position; // location of the decal center in world space.
|
||||
vec3_t saxis; // direction of the s axis in world space
|
||||
float dx; // Offsets into surface texture
|
||||
float dy;
|
||||
float dx, dy; // Offsets into surface texture
|
||||
float scale; // pixel scale
|
||||
short flags; // decal flags FDECAL_*
|
||||
short entityIndex; // entity this is attached to
|
||||
int m_Size; // size of decal, used for rejecting on dispinfo planes
|
||||
mesh_t *mesh; // cached mesh, created on first decal rendering
|
||||
|
||||
// NOTE: The following variables are dynamic variables.
|
||||
// We could put these into a separate array and reference them
|
||||
// by index to reduce memory costs of this...
|
||||
// dynamic decals stuff
|
||||
float fadeDuration; // Negative value means to fade in
|
||||
float fadeStartTime;
|
||||
rgba_t color;
|
||||
|
|
367
vid_gl/r_poly.c
367
vid_gl/r_poly.c
|
@ -104,346 +104,7 @@ void R_AddPolysToList( void )
|
|||
|
||||
//==================================================================================
|
||||
|
||||
static int numFragmentVerts;
|
||||
static int maxFragmentVerts;
|
||||
static vec3_t *fragmentVerts;
|
||||
|
||||
static int numClippedFragments;
|
||||
static int maxClippedFragments;
|
||||
static fragment_t *clippedFragments;
|
||||
|
||||
static cplane_t fragmentPlanes[6];
|
||||
static vec3_t fragmentNormal;
|
||||
static float fragmentDiameterSquared;
|
||||
|
||||
static int r_fragmentframecount;
|
||||
|
||||
#define MAX_FRAGMENT_VERTS 64
|
||||
|
||||
/*
|
||||
=================
|
||||
R_WindingClipFragment
|
||||
|
||||
This function operates on windings (convex polygons without
|
||||
any points inside) like triangles, quads, etc. The output is
|
||||
a convex fragment (polygon, trifan) which the result of clipping
|
||||
the input winding by six fragment planes.
|
||||
=================
|
||||
*/
|
||||
static bool R_WindingClipFragment( vec3_t *wVerts, int numVerts, msurface_t *surf, vec3_t snorm )
|
||||
{
|
||||
int i, j;
|
||||
int stage, newc, numv;
|
||||
cplane_t *plane;
|
||||
bool front;
|
||||
float *v, *nextv, d;
|
||||
float dists[MAX_FRAGMENT_VERTS+1];
|
||||
int sides[MAX_FRAGMENT_VERTS+1];
|
||||
vec3_t *verts, *newverts, newv[2][MAX_FRAGMENT_VERTS], t;
|
||||
fragment_t *fr;
|
||||
|
||||
numv = numVerts;
|
||||
verts = wVerts;
|
||||
|
||||
for( stage = 0, plane = fragmentPlanes; stage < 6; stage++, plane++ )
|
||||
{
|
||||
for( i = 0, v = verts[0], front = false; i < numv; i++, v += 3 )
|
||||
{
|
||||
d = PlaneDiff( v, plane );
|
||||
|
||||
if( d > ON_EPSILON )
|
||||
{
|
||||
front = true;
|
||||
sides[i] = SIDE_FRONT;
|
||||
}
|
||||
else if( d < -ON_EPSILON )
|
||||
{
|
||||
sides[i] = SIDE_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = true;
|
||||
sides[i] = SIDE_ON;
|
||||
}
|
||||
dists[i] = d;
|
||||
}
|
||||
|
||||
if( !front )
|
||||
return false;
|
||||
|
||||
// clip it
|
||||
sides[i] = sides[0];
|
||||
dists[i] = dists[0];
|
||||
|
||||
newc = 0;
|
||||
newverts = newv[stage & 1];
|
||||
for( i = 0, v = verts[0]; i < numv; i++, v += 3 )
|
||||
{
|
||||
switch( sides[i] )
|
||||
{
|
||||
case SIDE_FRONT:
|
||||
if( newc == MAX_FRAGMENT_VERTS )
|
||||
return false;
|
||||
VectorCopy( v, newverts[newc] );
|
||||
newc++;
|
||||
break;
|
||||
case SIDE_BACK:
|
||||
break;
|
||||
case SIDE_ON:
|
||||
if( newc == MAX_FRAGMENT_VERTS )
|
||||
return false;
|
||||
VectorCopy( v, newverts[newc] );
|
||||
newc++;
|
||||
break;
|
||||
}
|
||||
|
||||
if( sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i] )
|
||||
continue;
|
||||
if( newc == MAX_FRAGMENT_VERTS )
|
||||
return false;
|
||||
|
||||
d = dists[i] / ( dists[i] - dists[i+1] );
|
||||
nextv = ( i == numv - 1 ) ? verts[0] : v + 3;
|
||||
for( j = 0; j < 3; j++ )
|
||||
newverts[newc][j] = v[j] + d * ( nextv[j] - v[j] );
|
||||
newc++;
|
||||
}
|
||||
|
||||
if( newc <= 2 )
|
||||
return false;
|
||||
|
||||
// continue with new verts
|
||||
numv = newc;
|
||||
verts = newverts;
|
||||
}
|
||||
|
||||
// fully clipped
|
||||
if( numFragmentVerts + numv > maxFragmentVerts )
|
||||
return false;
|
||||
|
||||
fr = &clippedFragments[numClippedFragments++];
|
||||
fr->numverts = numv;
|
||||
fr->firstvert = numFragmentVerts;
|
||||
fr->fognum = surf->fog ? surf->fog - r_worldbrushmodel->fogs + 1 : -1;
|
||||
VectorCopy( snorm, fr->normal );
|
||||
for( i = 0, v = verts[0], nextv = fragmentVerts[numFragmentVerts]; i < numv; i++, v += 3, nextv += 3 )
|
||||
VectorCopy( v, nextv );
|
||||
|
||||
numFragmentVerts += numv;
|
||||
if( numFragmentVerts == maxFragmentVerts && numClippedFragments == maxClippedFragments )
|
||||
return true;
|
||||
|
||||
// if all of the following is true:
|
||||
// a) all clipping planes are perpendicular
|
||||
// b) there are 4 in a clipped fragment
|
||||
// c) all sides of the fragment are equal (it is a quad)
|
||||
// d) all sides are radius*2 +- epsilon (0.001)
|
||||
// then it is safe to assume there's only one fragment possible
|
||||
// not sure if it's 100% correct, but sounds convincing
|
||||
if( numv == 4 )
|
||||
{
|
||||
for( i = 0, v = verts[0]; i < numv; i++, v += 3 )
|
||||
{
|
||||
nextv = ( i == 3 ) ? verts[0] : v + 3;
|
||||
VectorSubtract( v, nextv, t );
|
||||
|
||||
d = fragmentDiameterSquared - DotProduct( t, t );
|
||||
if( d > 0.01 || d < -0.01 )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PlanarSurfClipFragment
|
||||
|
||||
NOTE: one might want to combine this function with
|
||||
R_WindingClipFragment for special cases like trifans (q1 and
|
||||
q2 polys) or tristrips for ultra-fast clipping, providing there's
|
||||
enough stack space (depending on MAX_FRAGMENT_VERTS value).
|
||||
=================
|
||||
*/
|
||||
static bool R_PlanarSurfClipFragment( msurface_t *surf, const vec3_t normal )
|
||||
{
|
||||
int i;
|
||||
mesh_t *mesh;
|
||||
elem_t *elem;
|
||||
vec4_t *verts;
|
||||
vec3_t poly[4];
|
||||
vec3_t dir1, dir2, snorm;
|
||||
bool planar;
|
||||
|
||||
planar = surf->plane && !VectorCompare( surf->plane->normal, vec3_origin );
|
||||
if( planar )
|
||||
{
|
||||
VectorCopy( surf->plane->normal, snorm );
|
||||
if( DotProduct( normal, snorm ) < 0.5 )
|
||||
return false; // greater than 60 degrees
|
||||
}
|
||||
|
||||
mesh = surf->mesh;
|
||||
elem = mesh->elems;
|
||||
verts = mesh->vertexArray;
|
||||
|
||||
// clip each triangle individually
|
||||
for( i = 0; i < mesh->numElems; i += 3, elem += 3 )
|
||||
{
|
||||
VectorCopy( verts[elem[0]], poly[0] );
|
||||
VectorCopy( verts[elem[1]], poly[1] );
|
||||
VectorCopy( verts[elem[2]], poly[2] );
|
||||
|
||||
if( !planar )
|
||||
{
|
||||
// calculate two mostly perpendicular edge directions
|
||||
VectorSubtract( poly[0], poly[1], dir1 );
|
||||
VectorSubtract( poly[2], poly[1], dir2 );
|
||||
|
||||
// we have two edge directions, we can calculate a third vector from
|
||||
// them, which is the direction of the triangle normal
|
||||
CrossProduct( dir1, dir2, snorm );
|
||||
VectorNormalize( snorm );
|
||||
|
||||
// we multiply 0.5 by length of snorm to avoid normalizing
|
||||
if( DotProduct( normal, snorm ) < 0.5 )
|
||||
continue; // greater than 60 degrees
|
||||
}
|
||||
|
||||
if( R_WindingClipFragment( poly, 3, surf, snorm ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveFragmentNode
|
||||
=================
|
||||
*/
|
||||
static void R_RecursiveFragmentNode( mnode_t *node, const vec3_t origin, const vec3_t normal, float radius )
|
||||
{
|
||||
float dist;
|
||||
cplane_t *plane;
|
||||
msurface_t *surf;
|
||||
int i, inside;
|
||||
|
||||
if( !node->plane ) return; // hit a leaf
|
||||
|
||||
if( numFragmentVerts == maxFragmentVerts || numClippedFragments == maxClippedFragments )
|
||||
return; // already reached the limit somewhere else
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = node->plane;
|
||||
if( plane->type < 3 )
|
||||
dist = origin[plane->type] - plane->dist;
|
||||
else dist = DotProduct( origin, plane->normal ) - plane->dist;
|
||||
|
||||
// go down the appropriate sides
|
||||
if( dist > radius )
|
||||
{
|
||||
R_RecursiveFragmentNode( node->children[0], origin, normal, radius );
|
||||
return;
|
||||
}
|
||||
|
||||
if( dist < -radius )
|
||||
{
|
||||
R_RecursiveFragmentNode( node->children[1], origin, normal, radius );
|
||||
return;
|
||||
}
|
||||
|
||||
// clip to each surface
|
||||
surf = node->firstface;
|
||||
|
||||
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
if( numFragmentVerts == maxFragmentVerts || numClippedFragments == maxClippedFragments )
|
||||
break; // already reached the limit
|
||||
|
||||
if( surf->fragmentframe == r_fragmentframecount )
|
||||
continue; // already checked this surface in another node
|
||||
surf->fragmentframe = r_fragmentframecount;
|
||||
|
||||
if( surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
|
||||
continue; // don't bother clipping
|
||||
|
||||
if( surf->shader->flags & SHADER_NOFRAGMENTS )
|
||||
continue; // don't bother clipping
|
||||
|
||||
if( !BoundsAndSphereIntersect( surf->mins, surf->maxs, origin, radius ))
|
||||
continue; // no intersection
|
||||
|
||||
if(!( surf->flags & SURF_PLANEBACK ))
|
||||
{
|
||||
if( DotProduct( normal, surf->plane->normal ) < 0.5f )
|
||||
continue; // greater than 60 degrees
|
||||
}
|
||||
else
|
||||
{
|
||||
if( DotProduct( normal, surf->plane->normal ) > -0.5f )
|
||||
continue; // greater than 60 degrees
|
||||
}
|
||||
|
||||
// clip to the surface
|
||||
inside = R_PlanarSurfClipFragment( surf, normal );
|
||||
if( inside ) return;
|
||||
}
|
||||
|
||||
// recurse down the children
|
||||
R_RecursiveFragmentNode( node->children[0], origin, normal, radius );
|
||||
R_RecursiveFragmentNode( node->children[1], origin, normal, radius );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_GetClippedFragments
|
||||
=================
|
||||
*/
|
||||
int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts, int maxfragments, fragment_t *fragments )
|
||||
{
|
||||
int i;
|
||||
float d;
|
||||
|
||||
if( maxfverts <= 0 || fverts == NULL || maxfragments <= 0 || fragments == NULL )
|
||||
return 0; // invalid arguments
|
||||
|
||||
r_fragmentframecount++;
|
||||
|
||||
// initialize fragments
|
||||
numFragmentVerts = 0;
|
||||
maxFragmentVerts = maxfverts;
|
||||
fragmentVerts = fverts;
|
||||
|
||||
numClippedFragments = 0;
|
||||
maxClippedFragments = maxfragments;
|
||||
clippedFragments = fragments;
|
||||
fragmentDiameterSquared = radius * radius * 4;
|
||||
|
||||
// calculate clipping planes
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
d = DotProduct( origin, axis[i] );
|
||||
|
||||
VectorCopy( axis[i], fragmentPlanes[i*2].normal );
|
||||
fragmentPlanes[i*2].dist = d - radius;
|
||||
fragmentPlanes[i*2].type = PlaneTypeForNormal( fragmentPlanes[i*2].normal );
|
||||
|
||||
VectorNegate( axis[i], fragmentPlanes[i*2+1].normal );
|
||||
fragmentPlanes[i*2+1].dist = -d - radius;
|
||||
fragmentPlanes[i*2+1].type = PlaneTypeForNormal( fragmentPlanes[i*2+1].normal );
|
||||
}
|
||||
|
||||
// clip against world geometry
|
||||
R_RecursiveFragmentNode( r_worldbrushmodel->nodes, origin, axis[0], radius );
|
||||
|
||||
return numClippedFragments;
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
|
||||
static vec3_t trace_start, trace_end;
|
||||
static vec3_t trace_absmins, trace_absmaxs;
|
||||
static float trace_fraction;
|
||||
|
@ -689,9 +350,12 @@ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_
|
|||
{
|
||||
if( model->type == mod_world || model->type == mod_brush )
|
||||
{
|
||||
mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;
|
||||
mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata;
|
||||
vec3_t temp, start_l, end_l, axis[3];
|
||||
bool rotated = !Matrix3x3_Compare( test->axis, matrix3x3_identity );
|
||||
vec3_t model_mins, model_maxs;
|
||||
float v, max = 0.0f;
|
||||
int i;
|
||||
|
||||
// transform
|
||||
VectorSubtract( start, test->origin, start_l );
|
||||
|
@ -702,6 +366,27 @@ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_
|
|||
Matrix3x3_Transform( test->axis, temp, start_l );
|
||||
VectorCopy( end_l, temp );
|
||||
Matrix3x3_Transform( test->axis, temp, end_l );
|
||||
|
||||
// expand mins/maxs for rotation
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
v = fabs( model->mins[i] );
|
||||
if( v > max ) max = v;
|
||||
v = fabs( model->maxs[i] );
|
||||
if( v > max ) max = v;
|
||||
}
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
model_mins[i] = test->origin[i] - max;
|
||||
model_maxs[i] = test->origin[i] + max;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd( test->origin, model->mins, model_mins );
|
||||
VectorAdd( test->origin, model->maxs, model_maxs );
|
||||
}
|
||||
|
||||
VectorCopy( start_l, trace_start );
|
||||
|
@ -711,7 +396,7 @@ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_
|
|||
// just walk the list of surfaces linearly
|
||||
if( test->model->type == mod_world )
|
||||
R_RecursiveHullCheck( bmodel->nodes, start_l, end_l );
|
||||
else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) )
|
||||
else if( BoundsIntersect( model_mins, model_maxs, trace_absmins, trace_absmaxs ) )
|
||||
R_TraceAgainstBmodel( bmodel );
|
||||
|
||||
// transform back
|
||||
|
|
|
@ -1016,6 +1016,7 @@ static void R_InitMedia( void )
|
|||
R_InitCinematics ();
|
||||
R_InitShaders();
|
||||
R_InitModels();
|
||||
R_InitDecals();
|
||||
R_InitCoronas();
|
||||
R_InitShadows();
|
||||
R_InitOcclusionQueries();
|
||||
|
@ -1039,6 +1040,7 @@ static void R_FreeMedia( void )
|
|||
return;
|
||||
|
||||
R_ShutdownOcclusionQueries();
|
||||
R_ShutdownDecals();
|
||||
R_ShutdownShadows();
|
||||
R_ShutdownModels();
|
||||
R_ShutdownShaders();
|
||||
|
@ -1115,7 +1117,9 @@ void R_NewMap( void )
|
|||
|
||||
R_InitCustomColors(); // clear custom colors
|
||||
R_InitCoronas(); // update corona shader (because we can't make it static)
|
||||
|
||||
R_StudioFreeAllExtradata(); // free boneposes
|
||||
R_ClearDecals(); // purge all decals
|
||||
|
||||
GL_SetDefaultTexState ();
|
||||
Mem_Set( &RI, 0, sizeof( refinst_t ));
|
||||
|
|
|
@ -3413,21 +3413,27 @@ static ref_shader_t *Shader_CreateDefault( ref_shader_t *shader, int type, int a
|
|||
{
|
||||
case SHADER_DECAL:
|
||||
shader->type = SHADER_DECAL;
|
||||
shader->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT|SHADER_POLYGONOFFSET;
|
||||
shader->features = MF_STCOORDS|MF_COLORS;
|
||||
shader->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT|SHADER_POLYGONOFFSET|SHADER_HASLIGHTMAP;
|
||||
shader->features = MF_STCOORDS|MF_LMCOORDS;
|
||||
shader->sort = SORT_DECAL;
|
||||
shader->num_stages = 1;
|
||||
shader->num_stages = 2;
|
||||
shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages );
|
||||
strcpy( shader->name, shortname );
|
||||
shader->stages = ( ref_stage_t * )(( byte * )shader->name + length + 1 );
|
||||
shader->stages = (ref_stage_t *)((byte *)shader->name + length + 1 );
|
||||
pass = &shader->stages[0];
|
||||
pass->flags = SHADERSTAGE_BLEND_DECAL;
|
||||
pass->flags = SHADERSTAGE_BLEND_REPLACE;
|
||||
pass->glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA;
|
||||
pass->tcgen = TCGEN_BASE;
|
||||
pass->textures[0] = Shader_FindImage( shader, shortname, addFlags );
|
||||
pass->textures[0] = Shader_FindImage( shader, shortname, TF_CLAMP|addFlags );
|
||||
pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING;
|
||||
pass->alphaGen.type = ALPHAGEN_VERTEX;
|
||||
pass->alphaGen.type = ALPHAGEN_VERTEX; // for fading decals
|
||||
pass->num_textures++;
|
||||
pass = &shader->stages[1];
|
||||
pass->flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_REPLACE;
|
||||
pass->glState = GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO;
|
||||
pass->tcgen = TCGEN_LIGHTMAP;
|
||||
pass->rgbGen.type = RGBGEN_IDENTITY;
|
||||
pass->alphaGen.type = ALPHAGEN_IDENTITY;
|
||||
break;
|
||||
case SHADER_FLARE:
|
||||
shader->type = SHADER_FLARE;
|
||||
|
|
Reference in New Issue