25 Dec 2011

This commit is contained in:
g-cont 2011-12-25 00:00:00 +04:00 committed by Alibek Omarov
parent 4e6fddad7d
commit 358b11ed3d
16 changed files with 223 additions and 60 deletions

View File

@ -1,3 +1,7 @@
build ????
Physic: add check for liquid brushes that has only hull0
build 1770
Client: add command "on"-"off" for virtual CD-player

View File

@ -19,7 +19,8 @@ GNU General Public License for more details.
#include "lightstyle.h"
#include "dlight.h"
#define CL_RENDER_INTERFACE_VERSION 12
#define CL_RENDER_INTERFACE_VERSION 13
#define MAX_STUDIO_DECALS 4096 // + unused space of BSP decals
#define SURF_INFO( surf, mod ) ((mextrasurf_t *)mod->cache.data + (surf - mod->surfaces))
#define INFO_SURF( surf, mod ) (mod->surfaces + (surf - (mextrasurf_t *)mod->cache.data))
@ -78,6 +79,31 @@ typedef enum
typedef struct beam_s BEAM;
typedef struct particle_s particle_t;
// 10 bytes here
typedef struct modelstate_s
{
short sequence;
short frame; // 10 bits multiple by 4, should be enough
byte blending[2];
byte controller[4];
} modelstate_t;
typedef struct decallist_s
{
vec3_t position;
char name[16];
short entityIndex;
byte depth;
byte flags;
// this is the surface plane that we hit so that
// we can move certain decals across
// transitions if they hit similar geometry
vec3_t impactPlaneNormal;
modelstate_t studio_state; // studio decals only
} decallist_t;
typedef struct render_api_s
{
void (*DrawSingleDecal)( struct decal_s *pDecal, struct msurface_s *fa );
@ -113,6 +139,8 @@ typedef struct render_api_s
void (*AVI_UploadRawFrame)( int texture, int cols, int rows, int width, int height, const byte *data );
void (*AVI_FreeVideo)( void *Avi );
int (*AVI_IsActive)( void *Avi );
const char* (*GL_TextureName)( unsigned int texnum );
} render_api_t;
// render callbacks
@ -126,9 +154,9 @@ typedef struct render_interface_s
// setup map bounds for ortho-projection when we in dev_overview mode
void (*GL_OrthoBounds)( const float *mins, const float *maxs );
// handle decals which hit mod_studio or mod_sprite
void (*R_DecalShoot)( int decalTexture, struct cl_entity_s *ent, struct model_s *mod, const float *pos, int flags );
// detach all entity effects on remove
void (*CL_EntityRemoved)( struct cl_entity_s *ent, qboolean removedFromServer );
void (*R_StudioDecalShoot)( int decalTexture, struct cl_entity_s *ent, const float *start, const float *pos, int flags, modelstate_t *state );
// prepare studio decals for save
int (*R_CreateStudioDecalList)( decallist_t *pList, int count, qboolean changelevel );
} render_interface_t;
#endif//RENDER_API_H

View File

@ -483,13 +483,6 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
// R_RemoveEfrags( ent );
}
// tell the client about removed entity
if( clgame.drawFuncs.CL_EntityRemoved )
{
// build lightmaps on the client-side
clgame.drawFuncs.CL_EntityRemoved( ent, ( state->number == - 1));
}
// entity was delta removed
return;
}

View File

@ -80,6 +80,7 @@ const char *svc_strings[256] =
"svc_unused49",
"svc_unused50",
"svc_director",
"svc_studiodecal",
};
typedef struct
@ -1005,6 +1006,61 @@ void CL_ParseDirector( sizebuf_t *msg )
clgame.dllFuncs.pfnDirectorMessage( iSize, pbuf );
}
/*
==============
CL_ParseStudioDecal
Studio Decal message. Used by engine in case
we need save\restore decals
==============
*/
void CL_ParseStudioDecal( sizebuf_t *msg )
{
modelstate_t state;
vec3_t start, pos;
int decalIndex, entityIndex;
int modelIndex = 0;
int flags;
pos[0] = BF_ReadCoord( msg );
pos[1] = BF_ReadCoord( msg );
pos[2] = BF_ReadCoord( msg );
start[0] = BF_ReadCoord( msg );
start[1] = BF_ReadCoord( msg );
start[2] = BF_ReadCoord( msg );
decalIndex = BF_ReadShort( msg );
entityIndex = BF_ReadShort( msg );
flags = BF_ReadByte( msg );
state.sequence = BF_ReadShort( msg );
state.frame = BF_ReadShort( msg );
state.blending[0] = BF_ReadByte( msg );
state.blending[1] = BF_ReadByte( msg );
state.controller[0] = BF_ReadByte( msg );
state.controller[1] = BF_ReadByte( msg );
state.controller[2] = BF_ReadByte( msg );
state.controller[3] = BF_ReadByte( msg );
if( cls.state == ca_connected )
{
// this message came on restore.
// read modelindex in case client models are not linked with entities
// because first client frame has not yet received
modelIndex = BF_ReadShort( msg );
}
if( clgame.drawFuncs.R_StudioDecalShoot )
{
int decalTexture = CL_DecalIndex( decalIndex );
cl_entity_t *ent = CL_GetEntityByIndex( entityIndex );
if( ent && !ent->model && modelIndex != 0 )
ent->model = Mod_Handle( modelIndex );
clgame.drawFuncs.R_StudioDecalShoot( decalTexture, ent, start, pos, flags, &state );
}
}
/*
==============
CL_ParseScreenShake
@ -1398,6 +1454,9 @@ void CL_ParseServerMessage( sizebuf_t *msg )
case svc_director:
CL_ParseDirector( msg );
break;
case svc_studiodecal:
CL_ParseStudioDecal( msg );
break;
default:
CL_ParseUserMessage( msg, cmd );
break;

View File

@ -2051,7 +2051,8 @@ void CL_ParseTempEntity( sizebuf_t *msg )
if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH )
decalIndex += 256;
pEnt = CL_GetEntityByIndex( entityIndex );
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
if( pEnt ) modelIndex = pEnt->curstate.modelindex;
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, pos, 0 );
break;
case TE_FIZZ:
entityIndex = BF_ReadShort( &buf );

View File

@ -782,15 +782,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos
if( model->type != mod_brush )
{
if( clgame.drawFuncs.R_DecalShoot )
{
// fallback to client - e.g. for R_StudiodecalShoot
clgame.drawFuncs.R_DecalShoot( textureIndex, ent, model, pos, flags );
}
else
{
MsgDev( D_ERROR, "Decals must hit mod_brush!\n" );
}
MsgDev( D_ERROR, "Decals must hit mod_brush!\n" );
return;
}
@ -1040,7 +1032,7 @@ int R_CreateDecalList( decallist_t *pList, qboolean changelevel )
int total = 0;
int i, depth;
if( cl.worldmodel && RI.drawWorld )
if( cl.worldmodel )
{
for( i = 0; i < MAX_RENDER_DECALS; i++ )
{
@ -1070,6 +1062,11 @@ int R_CreateDecalList( decallist_t *pList, qboolean changelevel )
// check to see if the decal should be added
total = DecalListAdd( pList, total );
}
if( clgame.drawFuncs.R_CreateStudioDecalList )
{
total += clgame.drawFuncs.R_CreateStudioDecalList( pList, total, changelevel );
}
}
// sort the decals lowest depth first, so they can be re-applied in order

View File

@ -1427,7 +1427,12 @@ static void GL_SetWorldviewProjectionMatrix( const float *glmatrix )
Matrix4x4_FromArrayFloatGL( RI.worldviewProjectionMatrix, glmatrix );
}
static const char *GL_TextureName( unsigned int texnum )
{
return R_GetTexture( texnum )->name;
}
static render_api_t gRenderAPI =
{
DrawSingleDecal,
@ -1461,6 +1466,7 @@ static render_api_t gRenderAPI =
R_UploadStretchRaw,
AVI_FreeVideo,
AVI_IsActive,
GL_TextureName,
};
/*

View File

@ -258,20 +258,6 @@ typedef struct host_redirect_s
void (*flush)( netadr_t adr, rdtype_t target, char *buffer );
} host_redirect_t;
typedef struct
{
vec3_t position;
char name[64];
short entityIndex;
byte depth;
byte flags;
// this is the surface plane that we hit so that
// we can move certain decals across
// transitions if they hit similar geometry
vec3_t impactPlaneNormal;
} decallist_t;
typedef struct
{
string name;
@ -332,7 +318,7 @@ typedef struct host_parm_s
int window_center_x;
int window_center_y;
decallist_t *decalList; // used for keep decals, when renderer is restarted or changed
struct decallist_s *decalList; // used for keep decals, when renderer is restarted or changed
int numdecals;
soundlist_t *soundList; // used for keep ambient sounds, when renderer or sound is restarted
@ -720,7 +706,7 @@ void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appNam
int COM_ExpandFilename( const char *fileName, char *nameOutBuffer, int nameOutBufferSize );
struct pmtrace_s *PM_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe );
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
int R_CreateDecalList( decallist_t *pList, qboolean changelevel );
int R_CreateDecalList( struct decallist_s *pList, qboolean changelevel );
struct cl_entity_s *CL_GetEntityByIndex( int index );
struct cl_entity_s *CL_GetLocalPlayer( void );
struct player_info_s *CL_GetPlayerInfo( int playerIndex );

View File

@ -43,6 +43,7 @@ GNU General Public License for more details.
// model flags (stored in model_t->flags)
#define MODEL_CONVEYOR BIT( 0 )
#define MODEL_HAS_ORIGIN BIT( 1 )
#define MODEL_LIQUID BIT( 2 ) // model has only point hull
typedef struct leaflist_s
{

View File

@ -1828,6 +1828,8 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
// kill water backplanes for submodels (half-life rules)
if( surf->flags & SURF_DRAWTURB )
{
mod->flags |= MODEL_LIQUID;
if( surf->plane->type == PLANE_Z )
{
// kill bottom plane too

View File

@ -127,7 +127,7 @@ hull_t *PM_HullForEntity( physent_t *pe, vec3_t mins, vec3_t maxs, vec3_t offset
VectorSubtract( maxs, mins, size );
if( size[0] <= 8.0f )
if( size[0] <= 8.0f || pe->model->flags & MODEL_LIQUID )
{
hull = &pe->model->hulls[0];
VectorCopy( hull->clip_mins, offset );
@ -191,6 +191,10 @@ hull_t *PM_HullForBsp( physent_t *pe, playermove_t *pmove, float *offset )
ASSERT( hull != NULL );
// force to use hull0 because other hulls doesn't exist for water
if( pe->model->flags & MODEL_LIQUID )
hull = &pe->model->hulls[0];
// calculate an offset value to center the origin
VectorSubtract( hull->clip_mins, pmove->player_mins[pmove->usehull], offset );
VectorAdd( offset, pe->origin, offset );

View File

@ -16,7 +16,7 @@ GNU General Public License for more details.
#ifndef PROTOCOL_H
#define PROTOCOL_H
#define PROTOCOL_VERSION 43
#define PROTOCOL_VERSION 44
// server to client
#define svc_bad 0 // immediately crash client when received
@ -69,6 +69,7 @@ GNU General Public License for more details.
#define svc_soundfade 48 // [float*4] sound fade parms
#define svc_director 51 // <variable sized>
#define svc_studiodecal 52 // [float*3][float*3][short][short][byte]
#define svc_lastmsg 64 // start user messages at this point
// client to server
@ -130,6 +131,7 @@ GNU General Public License for more details.
#define FDECAL_CLIPTEST 0x08 // Decal needs to be clip-tested
#define FDECAL_NOCLIP 0x10 // Decal is not clipped by containing polygon
#define FDECAL_USESAXIS 0x20 // Uses the s axis field to determine orientation (footprints)
#define FDECAL_STUDIO 0x40 // Indicates a studio decal
// Max number of history commands to send ( 2 by default ) in case of dropped packets
#define NUM_BACKUP_COMMAND_BITS 4

View File

@ -525,6 +525,8 @@ 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_CreateStudioDecal( const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex,
int flags, struct modelstate_s *state );
void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
void SV_PlaybackReliableEvent( sizebuf_t *msg, word eventindex, float delay, event_args_t *args );

View File

@ -21,6 +21,7 @@ GNU General Public License for more details.
#include "pm_defs.h"
#include "studio.h"
#include "const.h"
#include "render_api.h" // modelstate_t
// fatpvs stuff
static byte fatpvs[MAX_MAP_LEAFS/8];
@ -362,6 +363,54 @@ void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int m
BF_WriteByte( &sv.signon, flags );
}
/*
=======================
SV_CreateStudioDecal
NOTE: static decals only accepted when game is loading
=======================
*/
void SV_CreateStudioDecal( const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex, int flags, modelstate_t *state )
{
if( sv.state != ss_loading ) return;
// bad model or bad entity (e.g. changelevel)
if( !entityIndex || !modelIndex )
return;
ASSERT( origin );
ASSERT( start );
// this can happens if serialized map contain 4096 static decals...
if(( BF_GetNumBytesWritten( &sv.signon ) + 28 ) >= BF_GetMaxBytes( &sv.signon ))
return;
// static decals are posters, it's always reliable
BF_WriteByte( &sv.signon, svc_studiodecal );
BF_WriteShort( &sv.signon, (int)( origin[0] * 8.0f ));
BF_WriteShort( &sv.signon, (int)( origin[1] * 8.0f ));
BF_WriteShort( &sv.signon, (int)( origin[2] * 8.0f ));
BF_WriteShort( &sv.signon, (int)( start[0] * 8.0f ));
BF_WriteShort( &sv.signon, (int)( start[1] * 8.0f ));
BF_WriteShort( &sv.signon, (int)( start[2] * 8.0f ));
BF_WriteWord( &sv.signon, decalIndex );
BF_WriteShort( &sv.signon, entityIndex );
BF_WriteByte( &sv.signon, flags );
// write model state
BF_WriteShort( &sv.signon, state->sequence );
BF_WriteShort( &sv.signon, state->frame );
BF_WriteByte( &sv.signon, state->blending[0] );
BF_WriteByte( &sv.signon, state->blending[1] );
BF_WriteByte( &sv.signon, state->controller[0] );
BF_WriteByte( &sv.signon, state->controller[1] );
BF_WriteByte( &sv.signon, state->controller[2] );
BF_WriteByte( &sv.signon, state->controller[3] );
// write additional data (excluded from the game message)
BF_WriteShort( &sv.signon, modelIndex );
}
static qboolean SV_OriginIn( int mode, const vec3_t v1, const vec3_t v2 )
{
int leafnum;

View File

@ -17,6 +17,7 @@ GNU General Public License for more details.
#include "server.h"
#include "library.h"
#include "const.h"
#include "render_api.h" // decallist_t
/*
==============================================================================
@ -25,10 +26,10 @@ SAVE FILE
half-life implementation of saverestore system
==============================================================================
*/
#define SAVEFILE_HEADER (('V'<<24)+('L'<<16)+('A'<<8)+'V') // little-endian "VALV"
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
#define SAVEGAME_VERSION 0x0065 // Version 0.65
#define SAVEFILE_HEADER (('V'<<24)+('L'<<16)+('A'<<8)+'V') // little-endian "VALV"
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
#define SAVEGAME_VERSION 0x0065 // Version 0.65
#define CLIENT_SAVEGAME_VERSION 0x0066 // Version 0.66
#define SAVE_AGED_COUNT 1
#define SAVENAME_LENGTH 128 // matches with MAX_OSPATH
@ -422,10 +423,22 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja
int decalIndex, entityIndex = 0;
int modelIndex = 0;
if( adjacent ) flags |= FDECAL_DONTSAVE;
// NOTE: at this point all decal indexes is valid
decalIndex = pfnDecalIndex( entry->name );
if( flags & FDECAL_STUDIO )
{
edict_t *pEdict = pSaveData->pTable[entry->entityIndex].pent;
if( SV_IsValidEdict( pEdict )) modelIndex = pEdict->v.modelindex;
if( SV_IsValidEdict( pEdict )) entityIndex = NUM_FOR_EDICT( pEdict );
// NOTE: studio decals is always applies in local space and doesn't need to landmark transformation
SV_CreateStudioDecal( entry->position, entry->impactPlaneNormal, decalIndex, entityIndex, modelIndex, flags, &entry->studio_state );
return;
}
// NOTE: not needs for studio decals
if( adjacent ) flags |= FDECAL_DONTSAVE;
if( adjacent )
{
@ -967,13 +980,14 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
if( !pFile ) return;
id = SAVEFILE_HEADER;
version = SAVEGAME_VERSION;
version = CLIENT_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_RENDER_DECALS );
// g-cont. add space for studiodecals if present
decalList = (decallist_t *)Z_Malloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
decalCount = R_CreateDecalList( decalList, svgame.globals->changelevel );
FS_Write( pFile, &decalCount, sizeof( int ));
@ -987,7 +1001,8 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
entry = &decalList[i];
if( pSaveData->fUseLandmark )
// NOTE: all the studio decals save transform into local space
if( pSaveData->fUseLandmark && !( entry->flags & FDECAL_STUDIO ))
VectorSubtract( entry->position, pSaveData->vecLandmarkOffset, localPos );
else VectorCopy( entry->position, localPos );
@ -999,6 +1014,12 @@ void SV_SaveClientState( SAVERESTOREDATA *pSaveData, const char *level )
FS_Write( pFile, &entry->entityIndex, sizeof( entry->entityIndex ));
FS_Write( pFile, &entry->flags, sizeof( entry->flags ));
FS_Write( pFile, entry->impactPlaneNormal, sizeof( entry->impactPlaneNormal ));
if( entry->flags & FDECAL_STUDIO )
{
// write additional data for studio decals
FS_Write( pFile, &entry->studio_state, sizeof( entry->studio_state ));
}
}
Z_Free( decalList );
@ -1033,7 +1054,7 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean
}
FS_Read( pFile, &tag, sizeof( int ));
if( tag != SAVEGAME_VERSION )
if( tag != CLIENT_SAVEGAME_VERSION )
{
FS_Close( pFile );
return;
@ -1055,17 +1076,23 @@ void SV_LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboolean
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 ));
// NOTE: studiodecals are reached in local space so we don't need use landmark offset
if( pSaveData->fUseLandmark && !( entry->flags & FDECAL_STUDIO ))
VectorAdd( localPos, pSaveData->vecLandmarkOffset, entry->position );
else VectorCopy( localPos, entry->position );
if( entry->flags & FDECAL_STUDIO )
{
// read additional data for studio decals
FS_Read( pFile, &entry->studio_state, sizeof( entry->studio_state ));
}
ReapplyDecal( pSaveData, entry, adjacent );
}
@ -1977,7 +2004,7 @@ qboolean SV_GetComment( const char *savename, char *comment )
if( pSaveData ) Mem_Free( pSaveData );
FS_Close( f );
return 0;
};
}
// int (fieldcount)
pData += sizeof( short );
@ -2035,9 +2062,11 @@ qboolean SV_GetComment( const char *savename, char *comment )
strftime( timestring, sizeof( timestring ), "%H:%M", file_tm );
Q_strncpy( comment + CS_SIZE + CS_TIME, timestring, CS_TIME );
Q_strncpy( comment + CS_SIZE + (CS_TIME * 2), description + CS_SIZE, CS_SIZE );
return 1;
}
Q_strncpy( comment, "<unknown version>", MAX_STRING );
return 0;
}

View File

@ -168,9 +168,9 @@ hull_t *SV_HullForEntity( edict_t *ent, int hullNumber, vec3_t mins, vec3_t maxs
// calculate an offset value to center the origin
// NOTE: never get offset of drawing hull
if( !hullNumber ) VectorCopy( hull->clip_mins, offset );
else VectorSubtract( hull->clip_mins, mins, offset );
else VectorSubtract( hull->clip_mins, mins, offset );
#else
if( size[0] <= 8.0f )
if( size[0] <= 8.0f || model->flags & MODEL_LIQUID )
{
hull = &model->hulls[0];
VectorCopy( hull->clip_mins, offset );
@ -273,7 +273,7 @@ hull_t *SV_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, float
if( !hullNumber ) VectorCopy( hull->clip_mins, offset );
else VectorSubtract( hull->clip_mins, mins, offset );
#else
if( size[0] <= 8.0f )
if( size[0] <= 8.0f || model->flags & MODEL_LIQUID )
{
hull = &model->hulls[0];
VectorCopy( hull->clip_mins, offset );