02 Jul 2010

This commit is contained in:
g-cont 2010-07-02 00:00:00 +04:00 committed by Alibek Omarov
parent 99ecb9fcbe
commit 303191f982
47 changed files with 857 additions and 124 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2018,7 +2018,7 @@ pfnDecalIndexFromName
=================
*/
static int pfnDecalIndexFromName( const char *szDecalName )
int pfnDecalIndexFromName( const char *szDecalName )
{
int i;

View File

@ -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();

View File

@ -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 ));

View File

@ -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 )

View File

@ -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 );

View File

@ -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 );

View File

@ -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
//

View File

@ -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 )

View File

@ -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 )
{

View File

@ -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 );

View File

@ -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 );
}

View File

@ -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 );

View File

@ -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 );
}
/*

View File

@ -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();

View File

@ -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 );
}
}

View File

@ -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" );

200
physic/cm_light.c Normal file
View File

@ -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 );
}

View File

@ -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
//

View File

@ -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;

View File

@ -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 ();
}

View File

@ -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 );

View File

@ -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

View 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 );

View File

@ -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 );

View File

@ -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;

View File

@ -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

View File

@ -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( ));

View File

@ -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 );

View File

@ -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 )

View File

@ -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 )

View File

@ -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 );

View File

@ -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 );

View File

@ -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

View File

@ -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

View File

@ -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 )

View File

@ -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;

View File

@ -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"
/*
=============================================================================

View File

@ -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 );

View File

@ -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;

View File

@ -73,6 +73,7 @@ typedef struct
int lastPoly;
uint dlightbits;
uint modhandle;
float placeTime; // decal createtime
};
uint shadowbits;
} meshbuffer_t;

View File

@ -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++ )
{

View File

@ -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];

View File

@ -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;

View File

@ -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