02 Jul 2010
This commit is contained in:
parent
99ecb9fcbe
commit
303191f982
|
@ -1202,9 +1202,9 @@ addEntity:
|
|||
// copy progs values to state
|
||||
state->solid = (solid_t)pEntity->pev->solid;
|
||||
|
||||
state->modelindex = pEntity->pev->modelindex;
|
||||
state->origin = pEntity->pev->origin;
|
||||
state->angles = pEntity->pev->angles;
|
||||
state->modelindex = pEntity->pev->modelindex;
|
||||
state->health = pEntity->pev->health;
|
||||
state->skin = pEntity->pev->skin; // studio model skin
|
||||
state->body = pEntity->pev->body; // studio model submodel
|
||||
|
|
|
@ -21,6 +21,13 @@ BRUSH MODELS
|
|||
// bmodel limits
|
||||
#define MAX_MAP_HULLS 4 // MAX_HULLS
|
||||
|
||||
// in-game helper surface flags
|
||||
#define SURF_PLANEBACK BIT( 0 )
|
||||
#define SURF_DRAWSKY BIT( 1 ) // sky surface
|
||||
#define SURF_DRAWTURB BIT( 2 ) // warp surface
|
||||
#define SURF_DRAWTILED BIT( 3 ) // face without lighmap
|
||||
#define SURF_UNDERWATER BIT( 4 ) // caustics
|
||||
|
||||
// lightstyle management
|
||||
#define LM_STYLES 4 // MAXLIGHTMAPS
|
||||
#define LM_SAMPLE_SIZE 16 // lightmap resoultion
|
||||
|
|
|
@ -357,13 +357,13 @@ typedef enum
|
|||
|
||||
// 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)
|
||||
#define FDECAL_CUSTOM 0x02 // This is a custom clan logo and should not be saved/restored
|
||||
#define FDECAL_DYNAMIC 0x04 // Indicates the decal is dynamic
|
||||
#define FDECAL_DONTSAVE 0x08 // Decal was loaded from adjacent level, don't save it for this level
|
||||
#define FDECAL_CLIPTEST 0x10 // Decal needs to be clip-tested
|
||||
#define FDECAL_NOCLIP 0x20 // Decal is not clipped by containing polygon
|
||||
#define FDECAL_USESAXIS 0x40 // Uses the s axis field to determine orientation (footprints)
|
||||
#define FDECAL_ANIMATED 0x80 // this is decal has multiple frames
|
||||
|
||||
// client modelindexes
|
||||
#define NULLENT_INDEX -1 // engine always return NULL, only for internal use
|
||||
|
|
|
@ -2018,7 +2018,7 @@ pfnDecalIndexFromName
|
|||
|
||||
=================
|
||||
*/
|
||||
static int pfnDecalIndexFromName( const char *szDecalName )
|
||||
int pfnDecalIndexFromName( const char *szDecalName )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
|
@ -51,6 +51,11 @@ bool CL_IsInGame( void )
|
|||
return ( cls.key_dest == key_game ); // active if not menu or console
|
||||
}
|
||||
|
||||
bool CL_IsInMenu( void )
|
||||
{
|
||||
return ( cls.key_dest == key_menu );
|
||||
}
|
||||
|
||||
bool CL_IsPlaybackDemo( void )
|
||||
{
|
||||
return cls.demoplayback;
|
||||
|
@ -694,6 +699,25 @@ void CL_PrepVideo( void )
|
|||
re->EndRegistration( cl.configstrings[CS_SKYNAME] );
|
||||
CM_EndRegistration (); // free unused models
|
||||
Cvar_SetValue( "scr_loading", 100.0f ); // all done
|
||||
|
||||
if( host.decalList )
|
||||
{
|
||||
// need to reapply all decals after restarting
|
||||
for( i = 0; i < host.numdecals; i++ )
|
||||
{
|
||||
decallist_t *entry = &host.decalList[i];
|
||||
edict_t *pEdict = CL_GetEdictByIndex( entry->entityIndex );
|
||||
shader_t decalIndex = pfnDecalIndexFromName( entry->name );
|
||||
int modelIndex = 0;
|
||||
|
||||
if( CL_IsValidEdict( pEdict )) modelIndex = pEdict->v.modelindex;
|
||||
CL_DecalShoot( decalIndex, entry->entityIndex, modelIndex, entry->position, entry->flags );
|
||||
}
|
||||
Z_Free( host.decalList );
|
||||
}
|
||||
|
||||
host.decalList = NULL;
|
||||
host.numdecals = 0;
|
||||
|
||||
if( host.developer <= 2 ) Con_ClearNotify(); // clear any lines of console text
|
||||
SCR_UpdateScreen();
|
||||
|
|
|
@ -56,7 +56,7 @@ usercmd_t CL_CreateCmd( void )
|
|||
}
|
||||
|
||||
// send milliseconds of time to apply the move
|
||||
ms = ( cl.time - cl.oldtime ) * 1000;
|
||||
ms = host.frametime * 1000;
|
||||
if( ms > 250 ) ms = 100; // time was unreasonable
|
||||
|
||||
Mem_Set( &cmd, 0, sizeof( cmd ));
|
||||
|
|
|
@ -426,6 +426,7 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
|
|||
{
|
||||
vec3_t origin;
|
||||
int decalIndex, entityIndex, modelIndex;
|
||||
int flags;
|
||||
|
||||
MSG_ReadPos( msg, origin );
|
||||
decalIndex = MSG_ReadWord( msg );
|
||||
|
@ -434,8 +435,9 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
|
|||
if( entityIndex != NULLENT_INDEX )
|
||||
modelIndex = MSG_ReadWord( msg );
|
||||
else modelIndex = 0;
|
||||
flags = MSG_ReadByte( msg );
|
||||
|
||||
CL_DecalShoot( cl.decal_shaders[decalIndex], entityIndex, modelIndex, origin, FDECAL_PERMANENT );
|
||||
CL_DecalShoot( cl.decal_shaders[decalIndex], entityIndex, modelIndex, origin, flags );
|
||||
}
|
||||
|
||||
void CL_ParseSoundFade( sizebuf_t *msg )
|
||||
|
|
|
@ -454,6 +454,7 @@ const char *CL_ClassName( const edict_t *e );
|
|||
void CL_SetEventIndex( const char *szEvName, int ev_index );
|
||||
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||
mouth_t *CL_GetEntityMouth( edict_t *ent );
|
||||
int pfnDecalIndexFromName( const char *szDecalName );
|
||||
|
||||
// TriAPI implementation
|
||||
void TriRenderMode( kRenderMode_t mode );
|
||||
|
|
|
@ -99,6 +99,9 @@ typedef struct host_parm_s
|
|||
HWND hWnd; // main window
|
||||
int developer; // show all developer's message
|
||||
bool key_overstrike; // key overstrike mode
|
||||
|
||||
decallist_t *decalList; // used for keep decals, when renderer is restarted or changed
|
||||
int numdecals;
|
||||
} host_parm_t;
|
||||
|
||||
extern host_parm_t host;
|
||||
|
@ -212,6 +215,7 @@ byte *CIN_ReadNextFrame( cinematics_t *cin, bool silent );
|
|||
|
||||
// shared calls
|
||||
bool CL_IsInGame( void );
|
||||
bool CL_IsInMenu( void );
|
||||
float CL_GetServerTime( void );
|
||||
float CL_GetLerpFrac( void );
|
||||
void CL_CharEvent( int key );
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
#define COM_EXPORT_H
|
||||
|
||||
// linked interfaces
|
||||
extern stdlib_api_t com;
|
||||
extern physic_exp_t *pe;
|
||||
extern vsound_exp_t *se;
|
||||
extern stdlib_api_t com;
|
||||
extern physic_exp_t *pe;
|
||||
extern vsound_exp_t *se;
|
||||
extern render_exp_t *re;
|
||||
|
||||
//
|
||||
|
@ -18,6 +18,7 @@ extern render_exp_t *re;
|
|||
#define CM_GetAttachment if( pe ) pe->Mod_GetAttachment
|
||||
#define CM_GetBonePosition if( pe ) pe->Mod_GetBonePos
|
||||
#define CM_GetAmbientLevels if( pe ) pe->AmbientLevels
|
||||
#define CM_SetLightStyle if( pe ) pe->AddLightstyle
|
||||
#define CM_EndRegistration if( pe ) pe->EndRegistration
|
||||
#define CM_Frame if( pe ) pe->Frame
|
||||
|
||||
|
@ -61,6 +62,12 @@ _inline int CM_PointLeafnum( const vec3_t origin )
|
|||
return pe->PointLeafnum( origin );
|
||||
}
|
||||
|
||||
_inline int CM_LightEntity( edict_t *pEnt )
|
||||
{
|
||||
if( !pe ) return 255;
|
||||
return pe->LightPoint( pEnt );
|
||||
}
|
||||
|
||||
_inline byte *CM_LeafPVS( int cluster )
|
||||
{
|
||||
if( !pe ) return NULL;
|
||||
|
@ -156,6 +163,13 @@ _inline bool CM_BoxVisible( const vec3_t mins, const vec3_t maxs )
|
|||
return pe->BoxVisible( mins, maxs, re->GetCurrentVis());
|
||||
}
|
||||
|
||||
_inline int CL_CreateDecalList( decallist_t *pList, bool changelevel )
|
||||
{
|
||||
if( !re ) return 0;
|
||||
|
||||
return re->CreateDecalList( pList, changelevel );
|
||||
}
|
||||
|
||||
//
|
||||
// vsound.dll exports
|
||||
//
|
||||
|
|
|
@ -417,7 +417,7 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
|
|||
else host.state = HOST_FRAME;
|
||||
|
||||
wnd_caption = GetSystemMetrics( SM_CYCAPTION );
|
||||
S_Activate(( host.state == HOST_FRAME ) ? true : false );
|
||||
S_Activate(( host.state == HOST_FRAME ) ? true : false, host.hWnd );
|
||||
Key_ClearStates(); // FIXME!!!
|
||||
|
||||
if( host.state == HOST_FRAME )
|
||||
|
|
|
@ -222,7 +222,7 @@ bool Host_InitSound( void )
|
|||
si.GetClientEdict = CL_GetEdictByIndex;
|
||||
si.GetEntityMouth = CL_GetEntityMouth;
|
||||
si.GetServerTime = CL_GetServerTime;
|
||||
si.IsInGame = pfnIsInGame;
|
||||
si.IsInMenu = CL_IsInMenu;
|
||||
si.IsActive = CL_Active;
|
||||
|
||||
Sys_LoadLibrary( host_audio->string, &vsound_dll );
|
||||
|
@ -264,6 +264,13 @@ void Host_CheckChanges( void )
|
|||
|
||||
num_changes = 0;
|
||||
|
||||
if( host_video->modified && CL_Active( ))
|
||||
{
|
||||
// we're in game and want keep decals when renderer is changed
|
||||
host.decalList = (decallist_t *)Z_Malloc(sizeof( decallist_t ) * MAX_DECALS );
|
||||
host.numdecals = CL_CreateDecalList( host.decalList, false );
|
||||
}
|
||||
|
||||
// restart or change renderer
|
||||
while( host_video->modified )
|
||||
{
|
||||
|
|
|
@ -390,6 +390,7 @@ void SV_ConfigString( int index, const char *val );
|
|||
void SV_SetModel( edict_t *ent, const char *name );
|
||||
void SV_CopyTraceToGlobal( trace_t *trace );
|
||||
void SV_SetMinMaxSize( edict_t *e, const float *min, const float *max );
|
||||
void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags );
|
||||
void SV_PlaybackEvent( sizebuf_t *msg, event_info_t *info );
|
||||
void SV_BaselineForEntity( edict_t *pEdict );
|
||||
void SV_WriteEntityPatch( const char *filename );
|
||||
|
@ -403,6 +404,8 @@ const char *SV_GetString( string_t iString );
|
|||
void SV_SetClientMaxspeed( sv_client_t *cl, float fNewMaxspeed );
|
||||
int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name );
|
||||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
||||
edict_t* pfnPEntityOfEntIndex( int iEntIndex );
|
||||
int pfnIndexOfEdict( const edict_t *pEdict );
|
||||
void SV_UpdateBaseVelocity( edict_t *ent );
|
||||
bool SV_IsValidEdict( const edict_t *e );
|
||||
script_t *CM_GetEntityScript( void );
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
//=======================================================================
|
||||
// Copyright XashXT Group 2008 ©
|
||||
// sv_client.c - client interactions
|
||||
|
@ -1105,21 +1106,19 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
|
|||
// apply custom playermodel
|
||||
if( com.strlen( model ) && com.stricmp( model, "player" ))
|
||||
{
|
||||
const char *path = va( "models/player/%s/%s.mdl", model, model );
|
||||
string path;
|
||||
|
||||
com.snprintf( path, sizeof( path ), "models/player/%s/%s.mdl", model, model );
|
||||
cl->modelindex = SV_ModelIndex( path );
|
||||
CM_RegisterModel( path, cl->modelindex ); // upload model
|
||||
}
|
||||
else cl->modelindex = 0; // reset to default
|
||||
|
||||
ent->v.netname = MAKE_STRING( Info_ValueForKey( cl->userinfo, "name" ));
|
||||
}
|
||||
|
||||
// call prog code to allow overrides
|
||||
svgame.dllFuncs.pfnClientUserInfoChanged( cl->edict, cl->userinfo );
|
||||
|
||||
if( SV_IsValidEdict( ent ))
|
||||
{
|
||||
if( sv_maxclients->integer > 1 )
|
||||
ent->v.netname = MAKE_STRING(Info_ValueForKey( cl->userinfo, "name" ));
|
||||
else ent->v.netname = 0;
|
||||
}
|
||||
if( cl->state >= cs_connected ) cl->sendinfo = true; // needs for update client info
|
||||
}
|
||||
|
||||
|
@ -1469,6 +1468,7 @@ static void SV_ReadClientMove( sv_client_t *cl, sizebuf_t *msg )
|
|||
if( net_drop > 0 ) SV_RunCmd( cl, &oldcmd );
|
||||
|
||||
}
|
||||
cl->netchan.dropped = 0;
|
||||
SV_RunCmd( cl, &newcmd );
|
||||
SV_PostRunCmd( cl );
|
||||
}
|
||||
|
|
|
@ -357,6 +357,7 @@ void SV_BuildClientFrame( sv_client_t *cl )
|
|||
cl->addangle = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
clent->v.fixangle = 0; // reset fixangle
|
||||
|
||||
// this is the frame we are creating
|
||||
|
@ -380,6 +381,9 @@ void SV_BuildClientFrame( sv_client_t *cl )
|
|||
// of an entity being included twice.
|
||||
qsort( frame_ents.entities, frame_ents.num_entities, sizeof( frame_ents.entities[0] ), SV_EntityNumbers );
|
||||
|
||||
if( cl->modelindex ) // apply custom model if present
|
||||
clent->pvServerData->s.modelindex = cl->modelindex;
|
||||
|
||||
// copy the entity states out
|
||||
frame->num_entities = 0;
|
||||
frame->first_entity = svs.next_client_entities;
|
||||
|
@ -520,12 +524,13 @@ void SV_SendClientMessages( void )
|
|||
// only send messages if the client has sent one
|
||||
if( !cl->send_message ) continue;
|
||||
|
||||
/*
|
||||
if( !sv.paused && !Netchan_CanPacket( &cl->netchan ))
|
||||
{
|
||||
cl->surpressCount++;
|
||||
continue; // bandwidth choke
|
||||
}
|
||||
|
||||
*/
|
||||
if( cl->state == cs_spawned )
|
||||
{
|
||||
SV_SendClientDatagram( cl );
|
||||
|
|
|
@ -161,6 +161,21 @@ void SV_ConfigString( int index, const char *val )
|
|||
}
|
||||
}
|
||||
|
||||
void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags )
|
||||
{
|
||||
Com_Assert( origin == NULL );
|
||||
|
||||
// static decals are posters, it's always reliable
|
||||
MSG_WriteByte( &sv.multicast, svc_bspdecal );
|
||||
MSG_WritePos( &sv.multicast, origin );
|
||||
MSG_WriteWord( &sv.multicast, decalIndex );
|
||||
MSG_WriteShort( &sv.multicast, entityIndex );
|
||||
if( entityIndex != NULLENT_INDEX )
|
||||
MSG_WriteWord( &sv.multicast, modelIndex );
|
||||
MSG_WriteByte( &sv.multicast, flags );
|
||||
MSG_Send( MSG_INIT, NULL, NULL );
|
||||
}
|
||||
|
||||
static bool SV_OriginIn( int mode, const vec3_t v1, const vec3_t v2 )
|
||||
{
|
||||
int leafnum;
|
||||
|
@ -969,7 +984,7 @@ edict_t* pfnFindEntityByString( edict_t *pStartEdict, const char *pszField, cons
|
|||
==============
|
||||
pfnGetEntityIllum
|
||||
|
||||
FIXME: implement
|
||||
returns weighted lightvalue for entity position
|
||||
==============
|
||||
*/
|
||||
int pfnGetEntityIllum( edict_t* pEnt )
|
||||
|
@ -977,9 +992,9 @@ int pfnGetEntityIllum( edict_t* pEnt )
|
|||
if( !SV_IsValidEdict( pEnt ))
|
||||
{
|
||||
MsgDev( D_WARN, "SV_GetEntityIllum: invalid entity %s\n", SV_ClassName( pEnt ));
|
||||
return 255;
|
||||
return 0;
|
||||
}
|
||||
return 255;
|
||||
return CM_LightEntity( pEnt );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1342,6 +1357,7 @@ SV_StartSound
|
|||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch )
|
||||
{
|
||||
int sound_idx;
|
||||
int entityIndex;
|
||||
int msg_dest;
|
||||
vec3_t origin;
|
||||
|
||||
|
@ -1367,6 +1383,10 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
if( attn != ATTN_NONE ) flags |= SND_ATTENUATION;
|
||||
if( pitch != PITCH_NORM ) flags |= SND_PITCH;
|
||||
|
||||
// can't track this entity on the client.
|
||||
// write static sound
|
||||
if( !ent->pvServerData->linked ) flags |= SND_FIXED_ORIGIN;
|
||||
|
||||
// ultimate method for detect bsp models with invalid solidity (e.g. func_pushable)
|
||||
if( CM_GetModelType( ent->v.modelindex ) == mod_brush )
|
||||
{
|
||||
|
@ -1408,6 +1428,12 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
sound_idx = SV_SoundIndex( sample );
|
||||
}
|
||||
|
||||
if( !ent->pvServerData->linked )
|
||||
entityIndex = 0;
|
||||
else if( SV_IsValidEdict( ent->v.aiment ))
|
||||
entityIndex = ent->v.aiment->serialnumber;
|
||||
else entityIndex = ent->serialnumber;
|
||||
|
||||
MSG_Begin( svc_sound );
|
||||
MSG_WriteWord( &sv.multicast, flags );
|
||||
MSG_WriteWord( &sv.multicast, sound_idx );
|
||||
|
@ -1417,10 +1443,8 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
|
||||
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
|
||||
|
||||
// plays from aiment
|
||||
if( ent->v.aiment && !ent->v.aiment->free )
|
||||
MSG_WriteWord( &sv.multicast, ent->v.aiment->serialnumber );
|
||||
else MSG_WriteWord( &sv.multicast, ent->serialnumber );
|
||||
MSG_WriteWord( &sv.multicast, entityIndex );
|
||||
if( flags & SND_FIXED_ORIGIN ) MSG_WritePos( &sv.multicast, origin );
|
||||
|
||||
MSG_Send( msg_dest, origin, NULL );
|
||||
}
|
||||
|
@ -1852,6 +1876,8 @@ void pfnLightStyle( int style, const char* val )
|
|||
if( style < 0 ) style = 0;
|
||||
if( style >= MAX_LIGHTSTYLES )
|
||||
Host_Error( "SV_LightStyle: style: %i >= %d", style, MAX_LIGHTSTYLES );
|
||||
|
||||
CM_SetLightStyle( style, val ); // update info for SV_LightPoint
|
||||
SV_ConfigString( CS_LIGHTSTYLES + style, val );
|
||||
}
|
||||
|
||||
|
@ -2588,14 +2614,7 @@ void pfnStaticDecal( const float *origin, int decalIndex, int entityIndex, int m
|
|||
return;
|
||||
}
|
||||
|
||||
// static decals are posters, it's always reliable
|
||||
MSG_WriteByte( &sv.multicast, svc_bspdecal );
|
||||
MSG_WritePos( &sv.multicast, origin );
|
||||
MSG_WriteWord( &sv.multicast, decalIndex );
|
||||
MSG_WriteShort( &sv.multicast, entityIndex );
|
||||
if( entityIndex != NULLENT_INDEX )
|
||||
MSG_WriteWord( &sv.multicast, modelIndex );
|
||||
MSG_Send( MSG_INIT, NULL, NULL );
|
||||
SV_CreateDecal( origin, decalIndex, entityIndex, modelIndex, FDECAL_PERMANENT );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1840,7 +1840,7 @@ void SV_Physics( void )
|
|||
}
|
||||
|
||||
// let everything in the world think and move
|
||||
CM_Frame( sv.frametime );
|
||||
CM_Frame( sv.time );
|
||||
|
||||
// at end of frame kill all entities which supposed to it
|
||||
SV_FreeOldEntities();
|
||||
|
|
|
@ -118,6 +118,15 @@ static TYPEDESCRIPTION gEntityTable[] =
|
|||
DEFINE_FIELD( ENTITYTABLE, classname, FIELD_STRING ),
|
||||
};
|
||||
|
||||
static TYPEDESCRIPTION gDecalList[] =
|
||||
{
|
||||
DEFINE_FIELD( decallist_t, position, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_ARRAY( decallist_t, name, FIELD_CHARACTER, 64 ),
|
||||
DEFINE_FIELD( decallist_t, entityIndex, FIELD_SHORT ),
|
||||
DEFINE_FIELD( decallist_t, flags, FIELD_CHARACTER ),
|
||||
DEFINE_FIELD( decallist_t, impactPlaneNormal, FIELD_VECTOR ),
|
||||
};
|
||||
|
||||
int SumBytes( SaveFileSectionsInfo_t *section )
|
||||
{
|
||||
return ( section->nBytesSymbols + section->nBytesDataHeaders + section->nBytesData );
|
||||
|
@ -370,6 +379,58 @@ int EntityInSolid( edict_t *ent )
|
|||
return SV_TestEntityPosition( ent );
|
||||
}
|
||||
|
||||
void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, bool adjacent )
|
||||
{
|
||||
int flags = entry->flags;
|
||||
int decalIndex, entityIndex;
|
||||
int modelIndex = 0;
|
||||
|
||||
if( adjacent ) flags |= FDECAL_DONTSAVE;
|
||||
|
||||
// NOTE: at this point all decal indexes is valid
|
||||
decalIndex = SV_DecalIndex( entry->name );
|
||||
|
||||
if( adjacent )
|
||||
{
|
||||
// these entities might not exist over transitions,
|
||||
// so we'll use the saved plane and do a traceline instead
|
||||
vec3_t testspot, testend;
|
||||
trace_t tr;
|
||||
|
||||
VectorCopy( entry->position, testspot );
|
||||
VectorMA( testspot, 5.0f, entry->impactPlaneNormal, testspot );
|
||||
|
||||
VectorCopy( entry->position, testend );
|
||||
VectorMA( testend, -5.0f, entry->impactPlaneNormal, testend );
|
||||
|
||||
tr = SV_Move( testspot, vec3_origin, vec3_origin, testend, MOVE_NOMONSTERS, NULL );
|
||||
|
||||
if( tr.flFraction != 1.0f && !tr.fAllSolid )
|
||||
{
|
||||
// check impact plane normal
|
||||
float dot = DotProduct( entry->impactPlaneNormal, tr.vecPlaneNormal );
|
||||
|
||||
if( dot >= 0.95f )
|
||||
{
|
||||
entityIndex = pfnIndexOfEdict( tr.pHit );
|
||||
if( entityIndex != NULLENT_INDEX )
|
||||
modelIndex = tr.pHit->v.modelindex;
|
||||
|
||||
// FIXME: probably some rotating or moving objects can't receive decal properly
|
||||
SV_CreateDecal( tr.vecEndPos, decalIndex, entityIndex, modelIndex, flags );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edict_t *pEdict = pfnPEntityOfEntIndex( entry->entityIndex );
|
||||
if( pEdict != NULL )
|
||||
modelIndex = pEdict->v.modelindex;
|
||||
|
||||
SV_CreateDecal( entry->position, decalIndex, entry->entityIndex, modelIndex, flags );
|
||||
}
|
||||
}
|
||||
|
||||
void SV_ClearSaveDir( void )
|
||||
{
|
||||
search_t *t;
|
||||
|
@ -827,6 +888,133 @@ void SV_EntityPatchRead( SAVERESTOREDATA *pSaveData, const char *level )
|
|||
FS_Close( pFile );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_SaveClientState
|
||||
|
||||
write out the list of premanent decals for this level
|
||||
=============
|
||||
*/
|
||||
void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
|
||||
{
|
||||
string name;
|
||||
file_t *pFile;
|
||||
decallist_t *decalList;
|
||||
int i, decalCount;
|
||||
int id, version;
|
||||
|
||||
com.snprintf( name, sizeof( name ), "save/%s.HL2", level );
|
||||
|
||||
pFile = FS_Open( name, "wb" );
|
||||
if( !pFile ) return;
|
||||
|
||||
id = SAVEFILE_HEADER;
|
||||
version = SAVEGAME_VERSION;
|
||||
|
||||
// write the header
|
||||
FS_Write( pFile, &id, sizeof( int ));
|
||||
FS_Write( pFile, &version, sizeof( int ));
|
||||
|
||||
decalList = (decallist_t *)Z_Malloc(sizeof( decallist_t ) * MAX_DECALS );
|
||||
decalCount = CL_CreateDecalList( decalList, svgame.globals->changelevel );
|
||||
|
||||
FS_Write( pFile, &decalCount, sizeof( int ));
|
||||
|
||||
// we can't use SaveRestore system here...
|
||||
for( i = 0; i < decalCount; i++ )
|
||||
{
|
||||
vec3_t localPos;
|
||||
decallist_t *entry;
|
||||
byte nameSize;
|
||||
|
||||
entry = &decalList[i];
|
||||
|
||||
if( pSaveData->fUseLandmark )
|
||||
VectorSubtract( entry->position, pSaveData->vecLandmarkOffset, localPos );
|
||||
else VectorCopy( entry->position, localPos );
|
||||
|
||||
nameSize = com.strlen( entry->name ) + 1;
|
||||
|
||||
FS_Write( pFile, localPos, sizeof( localPos ));
|
||||
FS_Write( pFile, &nameSize, sizeof( nameSize ));
|
||||
FS_Write( pFile, entry->name, nameSize );
|
||||
FS_Write( pFile, &entry->entityIndex, sizeof( entry->entityIndex ));
|
||||
FS_Write( pFile, &entry->flags, sizeof( entry->flags ));
|
||||
FS_Write( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal ));
|
||||
}
|
||||
|
||||
Z_Free( decalList );
|
||||
FS_Close( pFile );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_LoadClientState
|
||||
|
||||
read the list of decals and reapply them again
|
||||
=============
|
||||
*/
|
||||
void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, bool adjacent )
|
||||
{
|
||||
string name;
|
||||
file_t *pFile;
|
||||
int i, tag;
|
||||
decallist_t *decalList;
|
||||
int decalCount;
|
||||
|
||||
com.snprintf( name, sizeof( name ), "†save/%s.HL2", level );
|
||||
|
||||
pFile = FS_Open( name, "rb" );
|
||||
if( !pFile ) return;
|
||||
|
||||
FS_Read( pFile, &tag, sizeof( int ));
|
||||
if( tag != SAVEFILE_HEADER )
|
||||
{
|
||||
FS_Close( pFile );
|
||||
return;
|
||||
}
|
||||
|
||||
FS_Read( pFile, &tag, sizeof( int ));
|
||||
if( tag != SAVEGAME_VERSION )
|
||||
{
|
||||
FS_Close( pFile );
|
||||
return;
|
||||
}
|
||||
|
||||
if( adjacent ) MsgDev( D_INFO, "Loading decals from %s\n", level );
|
||||
|
||||
// read the decalCount
|
||||
FS_Read( pFile, &decalCount, sizeof( int ));
|
||||
decalList = (decallist_t *)Z_Malloc( sizeof( decallist_t ) * decalCount );
|
||||
|
||||
// we can't use SaveRestore system here...
|
||||
for( i = 0; i < decalCount; i++ )
|
||||
{
|
||||
vec3_t localPos;
|
||||
decallist_t *entry;
|
||||
byte nameSize;
|
||||
|
||||
entry = &decalList[i];
|
||||
|
||||
FS_Read( pFile, localPos, sizeof( localPos ));
|
||||
|
||||
if( pSaveData->fUseLandmark )
|
||||
VectorAdd( localPos, pSaveData->vecLandmarkOffset, entry->position );
|
||||
else VectorCopy( localPos, entry->position );
|
||||
|
||||
FS_Read( pFile, &nameSize, sizeof( nameSize ));
|
||||
FS_Read( pFile, entry->name, nameSize );
|
||||
FS_Read( pFile, &entry->entityIndex, sizeof( entry->entityIndex ));
|
||||
FS_Read( pFile, &entry->flags, sizeof( entry->flags ));
|
||||
FS_Read( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal ));
|
||||
|
||||
ReapplyDecal( pSaveData, entry, adjacent );
|
||||
}
|
||||
|
||||
Z_Free( decalList );
|
||||
FS_Close( pFile );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SV_SaveGameState
|
||||
|
@ -917,7 +1105,7 @@ SAVERESTOREDATA *SV_SaveGameState( void )
|
|||
|
||||
SV_EntityPatchWrite( pSaveData, sv.name );
|
||||
|
||||
// FIXME: here a point to save client state e.g. decals
|
||||
SV_SaveClientState( pSaveData, sv.name );
|
||||
|
||||
return pSaveData;
|
||||
}
|
||||
|
@ -1030,6 +1218,8 @@ int SV_LoadGameState( char const *level, bool createPlayers )
|
|||
}
|
||||
}
|
||||
|
||||
SV_LoadClientState( pSaveData, level, false );
|
||||
|
||||
SV_SaveFinish( pSaveData );
|
||||
|
||||
// restore server time
|
||||
|
@ -1214,6 +1404,9 @@ void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName )
|
|||
// if ents were moved, rewrite entity table to save file
|
||||
if( movedCount ) SV_EntityPatchWrite( pSaveData, currentLevelData.levelList[i].mapName );
|
||||
|
||||
// move the decals from another level
|
||||
SV_LoadClientState( pSaveData, currentLevelData.levelList[i].mapName, true );
|
||||
|
||||
SV_SaveFinish( pSaveData );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1340,7 +1340,7 @@ void UI_Shutdown( void )
|
|||
Cmd_RemoveCommand( "menu_savegame" );
|
||||
Cmd_RemoveCommand( "menu_saveload" );
|
||||
Cmd_RemoveCommand( "menu_record" );
|
||||
Cmd_RemoveCommand( "menu_playpack" );
|
||||
Cmd_RemoveCommand( "menu_playback" );
|
||||
Cmd_RemoveCommand( "menu_playrec" );
|
||||
Cmd_RemoveCommand( "menu_multiplayer" );
|
||||
Cmd_RemoveCommand( "menu_options" );
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2010 ©
|
||||
// cm_light.c - lighting info for GETENTITYILLUM
|
||||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
int CM_RecursiveLightPoint( vec3_t color, cnode_t *node, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
float front, back, frac;
|
||||
vec3_t mid;
|
||||
|
||||
loc0:
|
||||
if( node->contents < 0 )
|
||||
return false; // didn't hit anything
|
||||
|
||||
// calculate mid point
|
||||
if( node->plane->type < 3 )
|
||||
{
|
||||
front = start[node->plane->type] - node->plane->dist;
|
||||
back = end[node->plane->type] - node->plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = DotProduct( start, node->plane->normal ) - node->plane->dist;
|
||||
back = DotProduct( end, node->plane->normal ) - node->plane->dist;
|
||||
}
|
||||
|
||||
// optimized recursion
|
||||
if(( back < 0 ) == ( front < 0 ))
|
||||
{
|
||||
node = node->children[front < 0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
frac = front / ( front - back );
|
||||
VectorLerp( start, frac, end, mid );
|
||||
|
||||
// go down front side
|
||||
if( CM_RecursiveLightPoint( color, node->children[front < 0], start, mid ))
|
||||
{
|
||||
// hit something
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, ds, dt;
|
||||
csurface_t *surf;
|
||||
|
||||
// check for impact on this node
|
||||
for( i = 0, surf = node->firstface; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
if( surf->flags & SURF_DRAWTILED )
|
||||
continue; // no lightmaps
|
||||
|
||||
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] );
|
||||
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
|
||||
|
||||
if( ds < surf->textureMins[0] || dt < surf->textureMins[1] )
|
||||
continue;
|
||||
|
||||
ds -= surf->textureMins[0];
|
||||
dt -= surf->textureMins[1];
|
||||
|
||||
if( ds > surf->extents[0] || dt > surf->extents[1] )
|
||||
continue;
|
||||
|
||||
if( surf->samples )
|
||||
{
|
||||
// enhanced to interpolate lighting
|
||||
byte *lightmap;
|
||||
int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15;
|
||||
int r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0;
|
||||
int r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
|
||||
float scale;
|
||||
|
||||
line3 = ((surf->extents[0] >> 4) + 1) * 3;
|
||||
lightmap = surf->samples + ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
|
||||
|
||||
for( maps = 0; maps < LM_STYLES && surf->styles[maps] != 255; maps++ )
|
||||
{
|
||||
scale = (float)cm.lightstyle[surf->styles[maps]].value;
|
||||
r00 += (float)lightmap[0] * scale;
|
||||
g00 += (float)lightmap[1] * scale;
|
||||
b00 += (float)lightmap[2] * scale;
|
||||
|
||||
r01 += (float)lightmap[3] * scale;
|
||||
g01 += (float)lightmap[4] * scale;
|
||||
b01 += (float)lightmap[5] * scale;
|
||||
|
||||
r10 += (float)lightmap[line3+0] * scale;
|
||||
g10 += (float)lightmap[line3+1] * scale;
|
||||
b10 += (float)lightmap[line3+2] * scale;
|
||||
|
||||
r11 += (float)lightmap[line3+3] * scale;
|
||||
g11 += (float)lightmap[line3+4] * scale;
|
||||
b11 += (float)lightmap[line3+5] * scale;
|
||||
|
||||
lightmap += ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
|
||||
}
|
||||
color[0] += (float)((int)((((((((r11 - r10) * dsfrac) >> 4) + r10)
|
||||
- ((((r01 - r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4)
|
||||
+ ((((r01 - r00) * dsfrac) >> 4) + r00)));
|
||||
color[1] += (float)((int)((((((((g11 - g10) * dsfrac) >> 4) + g10)
|
||||
- ((((g01 - g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4)
|
||||
+ ((((g01 - g00) * dsfrac) >> 4) + g00)));
|
||||
color[2] += (float)((int)((((((((b11 - b10) * dsfrac) >> 4) + b10)
|
||||
- ((((b01 - b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4)
|
||||
+ ((((b01 - b00) * dsfrac) >> 4) + b00)));
|
||||
}
|
||||
return true; // success
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return CM_RecursiveLightPoint( color, node->children[front >= 0], mid, end );
|
||||
}
|
||||
}
|
||||
|
||||
void CM_RunLightStyles( float time )
|
||||
{
|
||||
int i, ofs;
|
||||
clightstyle_t *ls;
|
||||
|
||||
if( !sv_models[1] )
|
||||
return; // no world
|
||||
|
||||
// run lightstyles animation
|
||||
ofs = (time * 10);
|
||||
|
||||
if( ofs == cm.lastofs ) return;
|
||||
cm.lastofs = ofs;
|
||||
|
||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
{
|
||||
if( ls->length == 0 ) ls->value = 0.0f;
|
||||
else if( ls->length == 1 ) ls->value = ls->map[0];
|
||||
else ls->value = ls->map[ofs%ls->length];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_AddLightstyle
|
||||
|
||||
needs to get correct working SV_LightPoint
|
||||
==================
|
||||
*/
|
||||
void CM_AddLightstyle( int style, const char* s )
|
||||
{
|
||||
int j, k;
|
||||
|
||||
j = com.strlen( s );
|
||||
cm.lightstyle[style].length = j;
|
||||
|
||||
for( k = 0; k < j; k++ )
|
||||
cm.lightstyle[style].map[k] = (float)( s[k]-'a' ) / (float)( 'm'-'a' );
|
||||
}
|
||||
|
||||
void CM_ClearLightStyles( void )
|
||||
{
|
||||
clightstyle_t *ls;
|
||||
int i;
|
||||
|
||||
Mem_Set( cm.lightstyle, 0, sizeof( cm.lightstyle ));
|
||||
|
||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
cm.lightstyle[i].value = 1.0f;
|
||||
cm.lastofs = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_LightPoint
|
||||
|
||||
grab the ambient lighting color for current point
|
||||
==================
|
||||
*/
|
||||
int CM_LightPoint( edict_t *pEdict )
|
||||
{
|
||||
vec3_t start, end, color;
|
||||
|
||||
if( !pEdict ) return 0;
|
||||
if( pEdict->v.effects & EF_FULLBRIGHT || !worldmodel->lightdata )
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
|
||||
VectorCopy( pEdict->v.origin, start );
|
||||
VectorCopy( pEdict->v.origin, end );
|
||||
|
||||
if( pEdict->v.effects & EF_INVLIGHT )
|
||||
end[2] = start[2] + 4096;
|
||||
else end[2] = start[2] - 4096;
|
||||
|
||||
VectorClear( color );
|
||||
CM_RecursiveLightPoint( color, worldmodel->nodes, start, end );
|
||||
|
||||
return VectorAvg( color );
|
||||
}
|
|
@ -53,12 +53,16 @@ typedef struct csurface_s
|
|||
int numedges; // are backwards edges
|
||||
|
||||
ctexinfo_t *texinfo;
|
||||
|
||||
short textureMins[2];
|
||||
short extents[2];
|
||||
|
||||
// lighting info
|
||||
byte *samples; // [numstyles*surfsize]
|
||||
int numstyles;
|
||||
byte styles[LM_STYLES]; // index into d_lightstylevalue[] for animated lights
|
||||
// no one surface can be effected by more than 4
|
||||
// animated lights.
|
||||
byte *samples; // [numstyles*surfsize]
|
||||
} csurface_t;
|
||||
|
||||
typedef struct cleaf_s
|
||||
|
@ -88,8 +92,18 @@ typedef struct cnode_s
|
|||
|
||||
// node specific
|
||||
struct cnode_s *children[2];
|
||||
|
||||
csurface_t *firstface; // used for grab lighting info, decals etc
|
||||
uint numfaces;
|
||||
} cnode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int length;
|
||||
float map[MAX_STRING];
|
||||
float value; // current lightvalue
|
||||
} clightstyle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string name; // model name
|
||||
|
@ -164,10 +178,15 @@ typedef struct clipmap_s
|
|||
uint checksum; // map checksum
|
||||
int registration_sequence;
|
||||
int checkcount;
|
||||
int version; // current map version
|
||||
|
||||
byte *pvs; // fully uncompressed visdata alloced in cm.mempool;
|
||||
byte *phs;
|
||||
byte nullrow[MAX_MAP_LEAFS/8];
|
||||
|
||||
// run local lightstyles to get SV_LightPoint grab the actual information
|
||||
clightstyle_t lightstyle[MAX_LIGHTSTYLES];
|
||||
int lastofs;
|
||||
} clipmap_t;
|
||||
|
||||
extern clipmap_t cm;
|
||||
|
@ -180,6 +199,14 @@ extern cmodel_t *worldmodel;
|
|||
//
|
||||
void CM_DrawCollision( cmdraw_t callback );
|
||||
|
||||
//
|
||||
// cm_light.c
|
||||
//
|
||||
void CM_RunLightStyles( float time );
|
||||
void CM_AddLightstyle( int style, const char* val );
|
||||
int CM_LightPoint( edict_t *pEdict );
|
||||
void CM_ClearLightStyles( void );
|
||||
|
||||
//
|
||||
// cm_test.c
|
||||
//
|
||||
|
@ -194,7 +221,7 @@ bool CM_BoxVisible( const vec3_t mins, const vec3_t maxs, byte *visbits );
|
|||
int CM_HullPointContents( chull_t *hull, int num, const vec3_t p );
|
||||
int CM_PointContents( const vec3_t p );
|
||||
void CM_AmbientLevels( const vec3_t p, byte *pvolumes );
|
||||
|
||||
|
||||
//
|
||||
// cm_portals.c
|
||||
//
|
||||
|
|
|
@ -25,8 +25,9 @@ bool CM_InitPhysics( void )
|
|||
return true;
|
||||
}
|
||||
|
||||
void CM_PhysFrame( float frametime )
|
||||
void CM_PhysFrame( float time )
|
||||
{
|
||||
CM_RunLightStyles( time );
|
||||
}
|
||||
|
||||
void CM_FreePhysics( void )
|
||||
|
@ -79,6 +80,9 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
|
|||
Phys.Mod_GetAttachment = CM_StudioGetAttachment;
|
||||
Phys.Mod_GetBonePos = CM_GetBonePosition;
|
||||
|
||||
Phys.AddLightstyle = CM_AddLightstyle;
|
||||
Phys.LightPoint = CM_LightPoint;
|
||||
|
||||
Phys.PointContents = CM_PointContents;
|
||||
Phys.HullPointContents = CM_HullPointContents;
|
||||
Phys.Trace = CM_ClipMoveToEntity;
|
||||
|
|
|
@ -262,6 +262,90 @@ static void BSP_LoadTexInfo( const dlump_t *l )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadLighting
|
||||
=================
|
||||
*/
|
||||
static void BSP_LoadLighting( const dlump_t *l )
|
||||
{
|
||||
byte d, *in, *out;
|
||||
int i;
|
||||
|
||||
if( !l->filelen ) return;
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
|
||||
switch( cm.version )
|
||||
{
|
||||
case Q1BSP_VERSION:
|
||||
// expand the white lighting data
|
||||
loadmodel->lightdata = Mem_Alloc( loadmodel->mempool, l->filelen * 3 );
|
||||
out = loadmodel->lightdata;
|
||||
|
||||
for( i = 0; i < l->filelen; i++ )
|
||||
{
|
||||
d = *in++;
|
||||
*out++ = d;
|
||||
*out++ = d;
|
||||
*out++ = d;
|
||||
}
|
||||
break;
|
||||
case HLBSP_VERSION:
|
||||
// load colored lighting
|
||||
loadmodel->lightdata = Mem_Alloc( loadmodel->mempool, l->filelen );
|
||||
Mem_Copy( loadmodel->lightdata, in, l->filelen );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_CalcSurfaceExtents
|
||||
|
||||
Fills in surf->textureMins and surf->extents
|
||||
=================
|
||||
*/
|
||||
static void BSP_CalcSurfaceExtents( csurface_t *surf )
|
||||
{
|
||||
float mins[2], maxs[2], val;
|
||||
int bmins[2], bmaxs[2];
|
||||
int i, j, e;
|
||||
float *v;
|
||||
|
||||
if( surf->flags & SURF_DRAWTURB )
|
||||
{
|
||||
surf->extents[0] = surf->extents[1] = 16384;
|
||||
surf->textureMins[0] = surf->textureMins[1] = -8192;
|
||||
return;
|
||||
}
|
||||
|
||||
mins[0] = mins[1] = 999999;
|
||||
maxs[0] = maxs[1] = -999999;
|
||||
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
e = loadmodel->surfedges[surf->firstedge + i];
|
||||
if( e >= 0 ) v = (float *)&loadmodel->vertexes[loadmodel->edges[e].v[0]];
|
||||
else v = (float *)&loadmodel->vertexes[loadmodel->edges[-e].v[1]];
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
val = DotProduct( v, surf->texinfo->vecs[j] ) + surf->texinfo->vecs[j][3];
|
||||
if( val < mins[j] ) mins[j] = val;
|
||||
if( val > maxs[j] ) maxs[j] = val;
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
bmins[i] = floor( mins[i] / LM_SAMPLE_SIZE );
|
||||
bmaxs[i] = ceil( maxs[i] / LM_SAMPLE_SIZE );
|
||||
|
||||
surf->textureMins[i] = bmins[i] * LM_SAMPLE_SIZE;
|
||||
surf->extents[i] = (bmaxs[i] - bmins[i]) * LM_SAMPLE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
BSP_LoadSurfaces
|
||||
|
@ -272,6 +356,7 @@ static void BSP_LoadSurfaces( const dlump_t *l )
|
|||
dface_t *in;
|
||||
csurface_t *out;
|
||||
int i, count;
|
||||
int lightofs;
|
||||
|
||||
in = (void *)(mod_base + l->fileofs);
|
||||
if( l->filelen % sizeof( dface_t ))
|
||||
|
@ -290,6 +375,30 @@ static void BSP_LoadSurfaces( const dlump_t *l )
|
|||
if( LittleShort( in->side )) out->flags |= SURF_PLANEBACK;
|
||||
out->plane = loadmodel->planes + LittleLong( in->planenum );
|
||||
out->texinfo = loadmodel->texinfo + LittleLong( in->texinfo );
|
||||
|
||||
if( !com.strncmp( out->texinfo->texture->name, "sky", 3 ))
|
||||
out->flags |= (SURF_DRAWSKY|SURF_DRAWTILED);
|
||||
|
||||
if( out->texinfo->texture->name[0] == '*' || out->texinfo->texture->name[0] == '!' )
|
||||
out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED);
|
||||
|
||||
BSP_CalcSurfaceExtents( out );
|
||||
|
||||
if( out->flags & SURF_DRAWTILED ) lightofs = -1;
|
||||
else lightofs = LittleLong( in->lightofs );
|
||||
|
||||
if( loadmodel->lightdata && lightofs != -1 )
|
||||
{
|
||||
if( cm.version == HLBSP_VERSION )
|
||||
out->samples = loadmodel->lightdata + lightofs;
|
||||
else out->samples = loadmodel->lightdata + (lightofs * 3);
|
||||
}
|
||||
|
||||
while( out->numstyles < LM_STYLES && in->styles[out->numstyles] != 255 )
|
||||
{
|
||||
out->styles[out->numstyles] = in->styles[out->numstyles];
|
||||
out->numstyles++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,6 +538,8 @@ static void BSP_LoadNodes( dlump_t *l )
|
|||
p = LittleLong( in->planenum );
|
||||
out->plane = loadmodel->planes + p;
|
||||
out->contents = CONTENTS_NODE;
|
||||
out->firstface = loadmodel->surfaces + LittleLong( in->firstface );
|
||||
out->numfaces = LittleLong( in->numfaces );
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
|
@ -673,6 +784,7 @@ static void CM_BrushModel( cmodel_t *mod, byte *buffer )
|
|||
|
||||
// will be merged later
|
||||
loadmodel->type = mod_brush;
|
||||
cm.version = i;
|
||||
|
||||
// swap all the lumps
|
||||
mod_base = (byte *)header;
|
||||
|
@ -697,12 +809,13 @@ static void CM_BrushModel( cmodel_t *mod, byte *buffer )
|
|||
}
|
||||
|
||||
BSP_LoadVertexes( &header->lumps[LUMP_VERTEXES] );
|
||||
BSP_LoadTextures( &header->lumps[LUMP_TEXTURES] );
|
||||
BSP_LoadTexInfo( &header->lumps[LUMP_TEXINFO] );
|
||||
BSP_LoadEdges( &header->lumps[LUMP_EDGES] );
|
||||
BSP_LoadSurfEdges( &header->lumps[LUMP_SURFEDGES] );
|
||||
BSP_LoadSurfaces( &header->lumps[LUMP_FACES] );
|
||||
BSP_LoadTextures( &header->lumps[LUMP_TEXTURES] );
|
||||
BSP_LoadLighting( &header->lumps[LUMP_LIGHTING] );
|
||||
BSP_LoadVisibility( &header->lumps[LUMP_VISIBILITY] );
|
||||
BSP_LoadTexInfo( &header->lumps[LUMP_TEXINFO] );
|
||||
BSP_LoadSurfaces( &header->lumps[LUMP_FACES] );
|
||||
BSP_LoadMarkFaces( &header->lumps[LUMP_MARKSURFACES] );
|
||||
BSP_LoadLeafs( &header->lumps[LUMP_LEAFS] );
|
||||
BSP_LoadNodes( &header->lumps[LUMP_NODES] );
|
||||
|
@ -712,6 +825,7 @@ static void CM_BrushModel( cmodel_t *mod, byte *buffer )
|
|||
CM_MakeHull0 ();
|
||||
|
||||
loadmodel->numframes = 2; // regular and alternate animation
|
||||
cm.version = 0;
|
||||
|
||||
// set up the submodels (FIXME: this is confusing)
|
||||
for( i = 0; i < mod->numsubmodels; i++ )
|
||||
|
@ -788,8 +902,11 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
|
|||
if( checksum ) *checksum = cm.checksum;
|
||||
if( !clientload )
|
||||
{
|
||||
// reset entity script
|
||||
// reset entity script...
|
||||
Com_ResetScript( worldmodel->entityscript );
|
||||
|
||||
// ..and lightstyles
|
||||
CM_ClearLightStyles();
|
||||
}
|
||||
sv_models[1] = cm_models; // make link to world
|
||||
|
||||
|
@ -811,6 +928,7 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
|
|||
CM_BmodelInitBoxHull ();
|
||||
CM_StudioInitBoxHull (); // hitbox tracing
|
||||
|
||||
CM_ClearLightStyles();
|
||||
CM_CalcPHS ();
|
||||
}
|
||||
|
||||
|
|
|
@ -374,9 +374,10 @@ find the face where the traceline hit
|
|||
*/
|
||||
const char *CM_TraceTexture( const vec3_t start, trace_t trace )
|
||||
{
|
||||
vec3_t intersect, forward, temp, vecStartPos;
|
||||
vec3_t intersect, temp, vecStartPos;
|
||||
csurface_t **mark, *surf, *hitface = NULL;
|
||||
float d1, d2, min_diff = 9999.9f;
|
||||
vec3_t forward, right, up;
|
||||
vec3_t vecPos1, vecPos2;
|
||||
cmodel_t *bmodel;
|
||||
cleaf_t *endleaf;
|
||||
|
@ -393,6 +394,23 @@ const char *CM_TraceTexture( const vec3_t start, trace_t trace )
|
|||
VectorSubtract( start, trace.pHit->v.origin, vecStartPos );
|
||||
VectorSubtract( trace.vecEndPos, trace.pHit->v.origin, trace.vecEndPos );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( trace.pHit->v.solid == SOLID_BSP && !VectorIsNull( trace.pHit->v.angles ))
|
||||
{
|
||||
VectorCopy( trace.pHit->v.angles, temp );
|
||||
AngleVectors( temp, forward, right, up );
|
||||
|
||||
VectorCopy( vecStartPos, temp );
|
||||
vecStartPos[0] = DotProduct( temp, forward );
|
||||
vecStartPos[1] = -DotProduct( temp, right );
|
||||
vecStartPos[2] = DotProduct( temp, up );
|
||||
|
||||
VectorCopy( trace.vecEndPos, temp );
|
||||
trace.vecEndPos[0] = DotProduct( temp, forward );
|
||||
trace.vecEndPos[1] = -DotProduct( temp, right );
|
||||
trace.vecEndPos[2] = DotProduct( temp, up );
|
||||
}
|
||||
|
||||
VectorSubtract( trace.vecEndPos, vecStartPos, forward );
|
||||
VectorNormalize( forward );
|
||||
|
||||
|
|
|
@ -117,6 +117,10 @@ SOURCE=.\cm_debug.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cm_light.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cm_main.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -57,6 +57,10 @@ typedef struct physic_exp_s
|
|||
void (*Mod_GetAttachment)( edict_t *ent, int iAttachment, float *rgflOrigin, float *rgflAngles );
|
||||
void (*Mod_GetBonePos)( edict_t *ent, int iBone, float *rgflOrigin, float *rgflAngles );
|
||||
|
||||
// lighting info
|
||||
void (*AddLightstyle)( int style, const char* val );
|
||||
int (*LightPoint)( edict_t *pEdict ); // for GETENTITYILLUM
|
||||
|
||||
// tracing
|
||||
int (*PointContents)( const vec3_t p );
|
||||
int (*HullPointContents)( chull_t *hull, int num, const vec3_t p );
|
||||
|
|
|
@ -207,7 +207,7 @@ typedef struct render_exp_s
|
|||
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
|
||||
int (*CreateDecalList)( decallist_t *pList, bool changelevel ); // helper to serialize decals
|
||||
bool (*Support)( int extension );
|
||||
byte *(*GetCurrentVis)( void );
|
||||
void (*RestoreGamma)( void );
|
||||
|
|
|
@ -53,7 +53,7 @@ typedef struct vsound_exp_s
|
|||
void (*StopSound)( int entnum, int channel, const char *soundname );
|
||||
void (*StopAllSounds)( void );
|
||||
|
||||
void (*Activate)( bool active );
|
||||
void (*Activate)( bool active, void *hInst );
|
||||
|
||||
} vsound_exp_t;
|
||||
|
||||
|
@ -68,7 +68,7 @@ typedef struct vsound_imp_s
|
|||
edict_t *(*GetClientEdict)( int index );
|
||||
mouth_t *(*GetEntityMouth)( edict_t *ent );
|
||||
float (*GetServerTime)( void );
|
||||
bool (*IsInGame)( void ); // returns false for menu, console, etc
|
||||
bool (*IsInMenu)( void ); // returns true when client is in-menu
|
||||
bool (*IsActive)( void ); // returns true when client is completely in-game
|
||||
} vsound_imp_t;
|
||||
|
||||
|
|
|
@ -1527,9 +1527,9 @@ addEntity:
|
|||
// copy progs values to state
|
||||
state->solid = (solid_t)pEntity->pev->solid;
|
||||
|
||||
state->modelindex = pEntity->pev->modelindex;
|
||||
state->origin = pEntity->pev->origin;
|
||||
state->angles = pEntity->pev->angles;
|
||||
state->modelindex = pEntity->pev->modelindex;
|
||||
state->health = pEntity->pev->health;
|
||||
state->skin = pEntity->pev->skin; // studio model skin
|
||||
state->body = pEntity->pev->body; // studio model submodel
|
||||
|
|
|
@ -125,7 +125,7 @@ float S_GetMasterVolume( void )
|
|||
{
|
||||
float scale = 1.0f;
|
||||
|
||||
if( si.IsInGame() && soundfade.percent != 0 )
|
||||
if( !si.IsInMenu() && soundfade.percent != 0 )
|
||||
{
|
||||
scale = bound( 0.0f, soundfade.percent / 100.0f, 1.0f );
|
||||
scale = 1.0f - scale;
|
||||
|
@ -790,7 +790,7 @@ void S_Update( ref_params_t *fd )
|
|||
al_state.refdef = fd; // for using everthing else
|
||||
|
||||
// update any client side sound fade
|
||||
if( !fd->paused && si.IsInGame( ))
|
||||
if( !fd->paused && !si.IsInMenu( ))
|
||||
S_UpdateSoundFade();
|
||||
|
||||
// set up listener
|
||||
|
@ -877,7 +877,7 @@ The window may have been destroyed and recreated between a deactivate
|
|||
and an activate.
|
||||
=================
|
||||
*/
|
||||
void S_Activate( bool active )
|
||||
void S_Activate( bool active, void *hInst )
|
||||
{
|
||||
al_state.active = active;
|
||||
if( active ) palListenerf( AL_GAIN, S_GetMasterVolume( ));
|
||||
|
|
|
@ -150,7 +150,7 @@ uint S_GetFormat( int width, int channels );
|
|||
|
||||
bool S_Init( void *hInst );
|
||||
void S_Shutdown( void );
|
||||
void S_Activate( bool active );
|
||||
void S_Activate( bool active, void *hInst );
|
||||
void S_SoundList_f( void );
|
||||
bool S_CheckForErrors( void );
|
||||
void S_BeginFrame( void );
|
||||
|
|
|
@ -779,8 +779,10 @@ The window have been destroyed and recreated
|
|||
between a deactivate and an activate.
|
||||
===========
|
||||
*/
|
||||
void S_Activate( bool active )
|
||||
void S_Activate( bool active, void *hInst )
|
||||
{
|
||||
snd_hwnd = (HWND)hInst;
|
||||
|
||||
if( active )
|
||||
{
|
||||
if( pDS && snd_hwnd && snd_isdirect )
|
||||
|
|
|
@ -1233,7 +1233,7 @@ void SX_RoomFX( int endtime, int fFilter, int fTimefx )
|
|||
int sampleCount;
|
||||
int roomType;
|
||||
|
||||
if( !si.IsInGame()) return;
|
||||
if( !s_listener.ingame ) return;
|
||||
|
||||
// return right away if fx processing is turned off
|
||||
if( sxroom_off->value != 0.0f )
|
||||
|
|
|
@ -322,30 +322,6 @@ int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int
|
|||
return false;
|
||||
}
|
||||
|
||||
void S_SpatializeChannel( int *left_vol, int *right_vol, int master_vol, float gain, float dotRight )
|
||||
{
|
||||
float lscale, rscale, scale;
|
||||
|
||||
rscale = 1.0f + dotRight;
|
||||
lscale = 1.0f - dotRight;
|
||||
|
||||
// add in distance effect
|
||||
scale = gain * rscale / 2;
|
||||
*right_vol = (int)( master_vol * scale );
|
||||
|
||||
scale = gain * lscale / 2;
|
||||
*left_vol = (int)( master_vol * scale );
|
||||
|
||||
*right_vol = bound( 0, *right_vol, 255 );
|
||||
*left_vol = bound( 0, *left_vol, 255 );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SND_Spatialize
|
||||
=================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
SND_Spatialize
|
||||
|
@ -772,7 +748,7 @@ void S_RenderFrame( ref_params_t *fd )
|
|||
s_listener.entnum = fd->viewentity; // can be camera entity too
|
||||
s_listener.frametime = fd->frametime;
|
||||
s_listener.waterlevel = fd->waterlevel;
|
||||
s_listener.ingame = si.IsInGame();
|
||||
s_listener.ingame = !si.IsInMenu();
|
||||
s_listener.paused = fd->paused;
|
||||
|
||||
VectorCopy( fd->simorg, s_listener.origin );
|
||||
|
|
|
@ -195,7 +195,7 @@ void SX_RoomFX( int endtime, int fFilter, int fTimefx );
|
|||
|
||||
bool S_Init( void *hInst );
|
||||
void S_Shutdown( void );
|
||||
void S_Activate( bool active );
|
||||
void S_Activate( bool active, void *hInst );
|
||||
void S_SoundList_f( void );
|
||||
void S_SoundInfo_f( void );
|
||||
|
||||
|
|
|
@ -1328,9 +1328,9 @@ addEntity:
|
|||
// copy progs values to state
|
||||
state->solid = (solid_t)pEntity->pev->solid;
|
||||
|
||||
state->modelindex = pEntity->pev->modelindex;
|
||||
state->origin = pEntity->pev->origin;
|
||||
state->angles = pEntity->pev->angles;
|
||||
state->modelindex = pEntity->pev->modelindex;
|
||||
state->health = pEntity->pev->health;
|
||||
state->skin = pEntity->pev->skin; // studio model skin
|
||||
state->body = pEntity->pev->body; // studio model submodel
|
||||
|
|
6
todo.log
6
todo.log
|
@ -30,4 +30,8 @@ Xash 0.72 Beta 5.07.10
|
|||
6.batch drawing decals OK
|
||||
7.draw lightmapped decals OK
|
||||
8.draw decals on bmodels OK
|
||||
9.implement save\restore for decals
|
||||
9.implement save\restore for decals OK
|
||||
10.create animated decals OK
|
||||
11.fix external shader lighting bug OK
|
||||
12.revision resources
|
||||
13.implement the sv_lightpoint
|
||||
|
|
|
@ -1303,6 +1303,31 @@ static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit )
|
|||
{
|
||||
int frame, numframes;
|
||||
|
||||
if(( r_currentMeshBuffer->sortkey & 3 ) == MB_DECAL )
|
||||
{
|
||||
decal_t *pDecal = R_DecalFromMeshbuf( r_currentMeshBuffer );
|
||||
|
||||
// play animation once and freeze at last frame
|
||||
if( pDecal->flags & FDECAL_ANIMATED )
|
||||
{
|
||||
numframes = pass->num_textures - 1;
|
||||
|
||||
pDecal->currentFrame += pass->animFrequency[0] * ( r_currentShaderTime - pDecal->fadeStartTime );
|
||||
|
||||
// animation is finished ?
|
||||
if( pDecal->currentFrame > numframes )
|
||||
{
|
||||
// in case we compare current frame for right batching
|
||||
pDecal->currentFrame = numframes;
|
||||
pDecal->flags &= ~FDECAL_ANIMATED;
|
||||
}
|
||||
return pass->textures[bound( 0, (int)pDecal->currentFrame, pass->num_textures - 1 )];
|
||||
}
|
||||
else if( pDecal->currentFrame != 0.0f )
|
||||
return pass->textures[bound( 0, (int)pDecal->currentFrame, pass->num_textures - 1 )];
|
||||
// fallback to default methods
|
||||
}
|
||||
|
||||
if( RI.currententity )
|
||||
{
|
||||
if( RI.currententity->frame && pass->animFrequency[1] != 0.0f )
|
||||
|
|
|
@ -61,6 +61,7 @@ static void Intersect( decal_clip_t clipFunc, decalvert_t *one, decalvert_t *two
|
|||
typedef struct
|
||||
{
|
||||
vec3_t m_Position; // world coordinates of the decal center
|
||||
vec3_t m_BasePosition; // untransformed world pos for right serialize
|
||||
vec3_t m_SAxis; // the s axis for the decal in world coordinates
|
||||
ref_model_t* m_pModel; // the model the decal is going to be applied in
|
||||
ref_shader_t *m_pShader; // The decal material
|
||||
|
@ -171,6 +172,34 @@ static decal_t *R_DecalAlloc( decal_t *pdecal )
|
|||
return pdecal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// find decal image and grab size from it
|
||||
//-----------------------------------------------------------------------------
|
||||
static void R_GetDecalDimensions( ref_shader_t *shader, int *width, int *height )
|
||||
{
|
||||
ref_stage_t *pass;
|
||||
int i;
|
||||
|
||||
if( !shader ) return;
|
||||
|
||||
for( i = 0; i < shader->num_stages; i++ )
|
||||
{
|
||||
pass = &shader->stages[i];
|
||||
if( pass->flags & SHADERSTAGE_LIGHTMAP )
|
||||
continue; // skip lightmap
|
||||
if( pass->num_textures )
|
||||
{
|
||||
if( width ) *width = pass->textures[0]->srcWidth;
|
||||
if( height ) *height = pass->textures[0]->srcHeight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found ?
|
||||
if( width ) *width = 1; // to avoid divide by zero
|
||||
if( height ) *height = 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// compute the decal basis based on surface normal, and preferred saxis
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -214,19 +243,21 @@ void R_DecalComputeBasis( msurface_t *surf, vec3_t pSAxis, vec3_t textureSpaceBa
|
|||
void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
|
||||
{
|
||||
float *sAxis = NULL;
|
||||
int width, height;
|
||||
|
||||
if( pDecal->flags & FDECAL_USESAXIS )
|
||||
sAxis = pDecal->saxis;
|
||||
|
||||
// Compute the non-scaled decal basis
|
||||
R_DecalComputeBasis( surf, sAxis, textureSpaceBasis );
|
||||
R_GetDecalDimensions( pShader, &width, &height );
|
||||
|
||||
// world width of decal = ptexture->width / pDecal->scale
|
||||
// world height of decal = ptexture->height / pDecal->scale
|
||||
// scale is inverse, scales world space to decal u/v space [0,1]
|
||||
// OPTIMIZE: Get rid of these divides
|
||||
decalWorldScale[0] = pDecal->scale / pShader->stages[0].textures[0]->srcWidth;
|
||||
decalWorldScale[1] = pDecal->scale / pShader->stages[0].textures[0]->srcHeight;
|
||||
decalWorldScale[0] = pDecal->scale / width;
|
||||
decalWorldScale[1] = pDecal->scale / height;
|
||||
|
||||
VectorScale( textureSpaceBasis[0], decalWorldScale[0], textureSpaceBasis[0] );
|
||||
VectorScale( textureSpaceBasis[1], decalWorldScale[1], textureSpaceBasis[1] );
|
||||
|
@ -440,8 +471,7 @@ static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int
|
|||
pShader = decalinfo->m_pShader;
|
||||
|
||||
// precalculate the extents of decalinfo's decal in world space.
|
||||
mapSize[0] = pShader->stages[0].textures[0]->srcWidth;
|
||||
mapSize[1] = pShader->stages[0].textures[0]->srcHeight;
|
||||
R_GetDecalDimensions( pShader, &mapSize[0], &mapSize[1] );
|
||||
VectorScale( decalinfo->m_Basis[0], ((mapSize[0] / decalinfo->m_scale) * 0.5f), decalExtents[0] );
|
||||
VectorScale( decalinfo->m_Basis[1], ((mapSize[1] / decalinfo->m_scale) * 0.5f), decalExtents[1] );
|
||||
|
||||
|
@ -552,6 +582,7 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl
|
|||
|
||||
Vector4Copy( decalinfo->m_Color, pdecal->color );
|
||||
VectorCopy( decalinfo->m_Position, pdecal->position );
|
||||
VectorCopy( decalinfo->m_BasePosition, pdecal->worldPos );
|
||||
|
||||
if( pdecal->flags & FDECAL_USESAXIS )
|
||||
VectorCopy( decalinfo->m_SAxis, pdecal->saxis );
|
||||
|
@ -564,14 +595,18 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl
|
|||
// set scaling
|
||||
pdecal->scale = decalinfo->m_scale;
|
||||
pdecal->entityIndex = decalinfo->m_Entity;
|
||||
|
||||
pdecal->fadeStartTime = RI.refdef.time;
|
||||
|
||||
// Get dynamic information from the material (fade start, fade time)
|
||||
if( decalinfo->m_flFadeDuration != 0.0f )
|
||||
{
|
||||
pdecal->flags |= FDECAL_DYNAMIC;
|
||||
pdecal->fadeDuration = decalinfo->m_flFadeDuration;
|
||||
pdecal->fadeStartTime = decalinfo->m_flFadeTime;
|
||||
pdecal->fadeStartTime += RI.refdef.time;
|
||||
pdecal->fadeStartTime += decalinfo->m_flFadeTime;
|
||||
}
|
||||
else if( decalinfo->m_Flags & FDECAL_ANIMATED )
|
||||
{
|
||||
pdecal->currentFrame = 0.0f;
|
||||
}
|
||||
|
||||
// check to see if the decal actually intersects the surface
|
||||
|
@ -717,6 +752,7 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
decalinfo_t decalInfo;
|
||||
mbrushmodel_t *bmodel;
|
||||
mnode_t *pnodes;
|
||||
int i, width, height;
|
||||
|
||||
if( !shader || shader->type != SHADER_DECAL )
|
||||
{
|
||||
|
@ -732,6 +768,8 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
|
||||
decalInfo.m_pModel = model;
|
||||
|
||||
VectorCopy( pos, decalInfo.m_BasePosition );
|
||||
|
||||
if( model->type == mod_brush )
|
||||
{
|
||||
edict_t *ent = ri.GetClientEdict( entity );
|
||||
|
@ -775,6 +813,16 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
VectorCopy( saxis, decalInfo.m_SAxis );
|
||||
}
|
||||
|
||||
// check for animated decal
|
||||
for( i = 0; i < shader->num_stages; i++ )
|
||||
{
|
||||
if( shader->stages[i].flags & ( SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES ))
|
||||
{
|
||||
flags |= FDECAL_ANIMATED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// more state used by R_DecalNode()
|
||||
decalInfo.m_pShader = shader;
|
||||
|
||||
|
@ -787,16 +835,18 @@ static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model,
|
|||
|
||||
decalInfo.m_Flags = flags;
|
||||
decalInfo.m_Entity = entity;
|
||||
decalInfo.m_Size = shader->stages[0].textures[0]->srcWidth >> 1;
|
||||
if((shader->stages[0].textures[0]->srcHeight >> 1) > decalInfo.m_Size )
|
||||
decalInfo.m_Size = shader->stages[0].textures[0]->srcHeight >> 1;
|
||||
|
||||
R_GetDecalDimensions( shader, &width, &height );
|
||||
decalInfo.m_Size = width >> 1;
|
||||
if(( height >> 1 ) > decalInfo.m_Size )
|
||||
decalInfo.m_Size = height >> 1;
|
||||
|
||||
// FIXME: grab scale from shader ?
|
||||
decalInfo.m_scale = 1.0f;
|
||||
|
||||
// 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;
|
||||
decalInfo.m_decalWidth = width / decalInfo.m_scale;
|
||||
decalInfo.m_decalHeight = height / decalInfo.m_scale;
|
||||
if( color ) Vector4Copy( color, decalInfo.m_Color );
|
||||
|
||||
bmodel = (mbrushmodel_t *)decalInfo.m_pModel->extradata;
|
||||
|
@ -841,7 +891,11 @@ void R_AddSurfaceDecals( msurface_t *surf )
|
|||
|
||||
// add decals into list
|
||||
mb = R_AddMeshToList( MB_DECAL, surf->fog, plist->shader, decalNum );
|
||||
if( mb ) mb->sortkey |= (( surf->superLightStyle+1 ) << 10 );
|
||||
if( mb )
|
||||
{
|
||||
mb->sortkey |= (( surf->superLightStyle+1 ) << 10 );
|
||||
mb->placeTime = plist->fadeStartTime; // FIXME: doesn't work
|
||||
}
|
||||
plist = pnext;
|
||||
}
|
||||
}
|
||||
|
@ -1060,11 +1114,14 @@ static bool R_DecalUnProject( decal_t *pdecal, decallist_t *entry )
|
|||
if( !pdecal || !( pdecal->psurf ))
|
||||
return false;
|
||||
|
||||
VectorCopy( pdecal->position, entry->position );
|
||||
// NOTE: return original decal position for world or bmodel
|
||||
VectorCopy( pdecal->worldPos, entry->position );
|
||||
entry->entityIndex = pdecal->entityIndex;
|
||||
|
||||
// Grab surface plane equation
|
||||
VectorCopy( pdecal->psurf->plane->normal, entry->impactPlaneNormal );
|
||||
if( pdecal->psurf->flags & SURF_PLANEBACK )
|
||||
VectorNegate( pdecal->psurf->plane->normal, entry->impactPlaneNormal );
|
||||
else VectorCopy( pdecal->psurf->plane->normal, entry->impactPlaneNormal );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1120,7 +1177,7 @@ static int DecalDepthCompare( const void *a, const void *b )
|
|||
// Input : *pList -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int R_CreateDecalList( decallist_t *pList )
|
||||
int R_CreateDecalList( decallist_t *pList, bool changelevel )
|
||||
{
|
||||
int total = 0;
|
||||
int i, depth;
|
||||
|
@ -1133,9 +1190,13 @@ int R_CreateDecalList( decallist_t *pList )
|
|||
decal_t *pdecals;
|
||||
|
||||
// decal is in use and is not a custom decal
|
||||
if( decal->psurf == NULL || (decal->flags & ( FDECAL_CUSTOM|FDECAL_DONTSAVE )))
|
||||
if( decal->psurf == NULL || ( decal->flags & FDECAL_CUSTOM ))
|
||||
continue;
|
||||
|
||||
// another transition - ignore moved decals
|
||||
if( changelevel && decal->flags & FDECAL_DONTSAVE )
|
||||
continue;
|
||||
|
||||
// compute depth
|
||||
depth = 0;
|
||||
pdecals = decal->psurf->pdecals;
|
||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "r_local.h"
|
||||
#include "mathlib.h"
|
||||
#include "matrix_lib.h"
|
||||
#include "bspfile.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
|
|
@ -710,7 +710,7 @@ 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 );
|
||||
int R_CreateDecalList( decallist_t *pList, bool changelevel );
|
||||
void R_AddSurfaceDecals( msurface_t *surf );
|
||||
void R_PushDecal( const meshbuffer_t *mb );
|
||||
|
||||
|
|
|
@ -541,6 +541,9 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm
|
|||
{
|
||||
if(( nextmb->sortkey & 3 ) == MB_DECAL )
|
||||
nextDecal = R_DecalFromMeshbuf( nextmb );
|
||||
|
||||
if( decal->currentFrame != nextDecal->currentFrame )
|
||||
nextDecal = NULL; // force to flush
|
||||
}
|
||||
|
||||
nonMergable = nextDecal ? R_MeshOverflow2( decal->mesh, nextDecal->mesh ) : true;
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef struct
|
|||
int lastPoly;
|
||||
uint dlightbits;
|
||||
uint modhandle;
|
||||
float placeTime; // decal createtime
|
||||
};
|
||||
uint shadowbits;
|
||||
} meshbuffer_t;
|
||||
|
|
|
@ -2733,11 +2733,8 @@ void R_EndRegistration( const char *skyname )
|
|||
int i;
|
||||
ref_model_t *mod;
|
||||
|
||||
if( skyname && com.strncmp( skyname, "<skybox>", 8 ))
|
||||
{
|
||||
// half-life or quake2 skybox-style
|
||||
R_SetupSky( skyname );
|
||||
}
|
||||
// half-life or quake2 skybox-style
|
||||
R_SetupSky( skyname );
|
||||
|
||||
for( i = 0, mod = r_models; i < r_nummodels; i++, mod++ )
|
||||
{
|
||||
|
|
|
@ -65,6 +65,7 @@ typedef struct decal_s
|
|||
ref_shader_t *shader; // decal image
|
||||
|
||||
vec3_t position; // location of the decal center in world space.
|
||||
vec3_t worldPos; // untransformed position, keep for serialization
|
||||
vec3_t saxis; // direction of the s axis in world space
|
||||
float dx, dy; // Offsets into surface texture
|
||||
float scale; // pixel scale
|
||||
|
@ -75,6 +76,7 @@ typedef struct decal_s
|
|||
// dynamic decals stuff
|
||||
float fadeDuration; // Negative value means to fade in
|
||||
float fadeStartTime;
|
||||
float currentFrame; // for animated decals
|
||||
rgba_t color;
|
||||
} decal_t;
|
||||
|
||||
|
@ -86,12 +88,6 @@ typedef struct decal_s
|
|||
#define MIPTEX_NOLIGHTMAP BIT( 4 ) // this surface if fullbright
|
||||
#define MIPTEX_WARPSURFACE BIT( 5 ) // this surface is warped
|
||||
|
||||
#define SURF_PLANEBACK BIT( 0 )
|
||||
#define SURF_DRAWSKY BIT( 1 ) // sky surface
|
||||
#define SURF_DRAWTURB BIT( 2 ) // warp surface
|
||||
#define SURF_DRAWTILED BIT( 3 ) // face without lighmap
|
||||
#define SURF_UNDERWATER BIT( 4 ) // caustics
|
||||
|
||||
typedef struct mtexinfo_s
|
||||
{
|
||||
float vecs[2][4];
|
||||
|
|
|
@ -1115,6 +1115,12 @@ static bool Shader_SkyRotate( ref_shader_t *shader, ref_stage_t *pass, script_t
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool Shader_CustomDecal( ref_shader_t *shader, ref_stage_t *pass, script_t *script )
|
||||
{
|
||||
shader->flags |= SHADER_DECALPARMS;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Shader_Sort( ref_shader_t *shader, ref_stage_t *pass, script_t *script )
|
||||
{
|
||||
token_t tok;
|
||||
|
@ -1231,6 +1237,7 @@ static const ref_parsekey_t shaderkeys[] =
|
|||
{ "endif", Shader_Endif },
|
||||
{ "portal", Shader_Portal },
|
||||
{ "fogvars", Shader_FogParms }, // RTCW fog params
|
||||
{ "decal", Shader_CustomDecal },
|
||||
{ "skyParms", Shader_SkyParms },
|
||||
{ "skyRotate", Shader_SkyRotate },
|
||||
{ "fogparms", Shader_FogParms },
|
||||
|
@ -3155,6 +3162,9 @@ void Shader_Finish( ref_shader_t *s )
|
|||
else s->sort = SORT_ADDITIVE;
|
||||
}
|
||||
|
||||
if( s->flags & SHADER_DECALPARMS )
|
||||
s->flags |= SHADER_POLYGONOFFSET;
|
||||
|
||||
if( ( s->flags & SHADER_POLYGONOFFSET ) && !s->sort )
|
||||
s->sort = SORT_DECAL;
|
||||
|
||||
|
@ -3278,7 +3288,11 @@ void Shader_Finish( ref_shader_t *s )
|
|||
if( r_shaderHasDlightPass )
|
||||
pass->textures[5] = ( (texture_t *)1); // HACKHACK no dlights
|
||||
}
|
||||
Shader_SetBlendmode( pass );
|
||||
|
||||
// custom lightmapped decals are handled seperately
|
||||
if( s->flags & SHADER_DECALPARMS )
|
||||
pass->flags |= SHADERSTAGE_BLEND_REPLACE;
|
||||
else Shader_SetBlendmode( pass );
|
||||
}
|
||||
|
||||
for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ )
|
||||
|
@ -3413,7 +3427,7 @@ 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_HASLIGHTMAP;
|
||||
shader->flags = SHADER_CULL_FRONT|SHADER_POLYGONOFFSET|SHADER_HASLIGHTMAP;
|
||||
shader->features = MF_STCOORDS|MF_LMCOORDS;
|
||||
shader->sort = SORT_DECAL;
|
||||
shader->num_stages = 2;
|
||||
|
@ -4099,7 +4113,7 @@ ref_shader_t *R_SetupSky( const char *name )
|
|||
ref_shader_t *shader;
|
||||
uint hashKey;
|
||||
|
||||
com.strncpy( loadname, name, sizeof( loadname ));
|
||||
com.snprintf( loadname, sizeof( loadname ), "%s/%s", SI->envpath, name );
|
||||
|
||||
// make sure what new shader it's a skyShader and existing
|
||||
hashKey = Com_HashKey( loadname, SHADERS_HASH_SIZE );
|
||||
|
@ -4167,7 +4181,6 @@ ref_shader_t *R_SetupSky( const char *name )
|
|||
{
|
||||
if( !Shader_CheckSkybox( loadname ))
|
||||
{
|
||||
com.strncpy( loadname, va( "%s/%s", SI->envpath, name ), sizeof( loadname ));
|
||||
if( Shader_CheckSkybox( loadname ))
|
||||
shader_valid = true;
|
||||
else shader_valid = true;
|
||||
|
|
|
@ -53,7 +53,7 @@ typedef enum
|
|||
SHADER_STATIC = BIT(0), // never freed by R_ShaderFreeUnused
|
||||
SHADER_DEPTHWRITE = BIT(1),
|
||||
SHADER_SKYPARMS = BIT(2),
|
||||
SHADER_SURFACEPARM = BIT(3), // shader has surface and contents parms
|
||||
SHADER_DECALPARMS = BIT(3), // it's a lightmapped decal
|
||||
SHADER_POLYGONOFFSET = BIT(4),
|
||||
SHADER_CULL_FRONT = BIT(5),
|
||||
SHADER_CULL_BACK = BIT(6),
|
||||
|
@ -71,7 +71,7 @@ typedef enum
|
|||
SHADER_DEFAULTED = BIT(18),
|
||||
SHADER_PORTAL_CAPTURE = (SHADER_PORTAL_CAPTURE1|SHADER_PORTAL_CAPTURE1),
|
||||
SHADER_CULL = (SHADER_CULL_FRONT|SHADER_CULL_BACK),
|
||||
SHADER_NOFRAGMENTS = BIT(19),
|
||||
|
||||
} shaderFlags_t;
|
||||
|
||||
// shaderstage flags
|
||||
|
|
Reference in New Issue