07 Oct 2011

This commit is contained in:
g-cont 2011-10-07 00:00:00 +04:00 committed by Alibek Omarov
parent 378412a8f5
commit 95af1226ef
46 changed files with 1411 additions and 656 deletions

View File

@ -12,14 +12,34 @@ Render: allow 16-bit color mode when decktop has same
Render: rename "vid_gamma" to "gamma", make backward compatibility with GoldSource config
Sound: get support for automatic ambient sounds like in Quake
Sound: add cvar "s_combine" that trying to combine mutilpe channels with same sounds into one
Engine: add "secure" option for both liblist.gam and gameinfo.txt
Engine: add "secure" option support for both liblist.gam and gameinfo.txt
Engine: fix bug determine current directory
Server: fix bug when some sound messages can't be sended to client (e.g. not vised map)
Render: allow to load hi-res quake sky (two layers called as sky_solid and sky_alpha)
Physic: fix trace bug when bbox mins are 0 0 0 and bbox maxs are positive values (like quake boxes)
GameUI: add checkbox "allow materials" in menu Video Options.
Client: implement "viewsize" cvar
GameUI: add new function to inteface called as pfnProcessImage
Client: add support for default studiomodel flags like quake effects (light, smoke, blood etc)
Render: add engine mirrors (can be set on map with texture "decals.wad\reflect1")
Client: rewrite client font system to allow support for "hud_scale" feature
Client: re-enable client static entities (see engine function MAKE_STATIC for details)
Sound: clear "loop" flags for client engine functions PlaySoundByName and PlaySoundByIndex
Client: fix potentially crash in StudioRemap code
Client: finalize 'GlowShell' effect on StudioModels
Render: implement software gamma control that based on lightmap adjusting (gl_ignorehwgamma 1)
Render: restore projection and modelview matrices before call V_CalcRefdef to avoid errors on custom rendering (e.g. HLFX 0.5, Trinity Renderers)
Render: remove all stuff for 3dfx gamma control
Render: add missing function R_ScreenToWorld
Engine: add "icon" option support for both liblist.gam and gameinfo.txt
Render: get support for rotational skybox that can be saved and restored with current angle
Engine: fix bug with incorrect detecting Blue-Shift maps in some rare cases
Engine: add autocomplete for 'entpatch' command
Engine: fix Host_Error issues
Network: add IPX and IPX_BROADCAST for backward compatibility with GoldSrc
Engine: do revision for 'allow_studio_scale' cvar in trace code
GameUI: added support for Steam backgrounds
GameUI: hide input symbols for "password" field in "create server" menu page
build 1662

View File

@ -3,244 +3,23 @@
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: hl - Win32 Debug--------------------
--------------------Configuration: hl - Win32 Release--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP3740.tmp" with contents
[
/nologo /G5 /MTd /W3 /Gm /ZI /Od /I "..\dlls" /I "..\engine" /I "..\common" /I "..\game_shared" /I "..\pm_shared" /I "..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "QUIVER" /D "VOXEL" /D "QUAKE2" /D "VALVE_DLL" /D "CLIENT_WEAPONS" /FR"..\temp\dlls\!debug/" /Fp"..\temp\dlls\!debug/hl.pch" /YX /Fo"..\temp\dlls\!debug/" /Fd"..\temp\dlls\!debug/" /FD /c
"D:\Xash3D\src_main\dlls\aflock.cpp"
"D:\Xash3D\src_main\dlls\agrunt.cpp"
"D:\Xash3D\src_main\dlls\airtank.cpp"
"D:\Xash3D\src_main\dlls\animating.cpp"
"D:\Xash3D\src_main\dlls\animation.cpp"
"D:\Xash3D\src_main\dlls\apache.cpp"
"D:\Xash3D\src_main\dlls\barnacle.cpp"
"D:\Xash3D\src_main\dlls\barney.cpp"
"D:\Xash3D\src_main\dlls\bigmomma.cpp"
"D:\Xash3D\src_main\dlls\bloater.cpp"
"D:\Xash3D\src_main\dlls\bmodels.cpp"
"D:\Xash3D\src_main\dlls\bullsquid.cpp"
"D:\Xash3D\src_main\dlls\buttons.cpp"
"D:\Xash3D\src_main\dlls\cbase.cpp"
"D:\Xash3D\src_main\dlls\client.cpp"
"D:\Xash3D\src_main\dlls\combat.cpp"
"D:\Xash3D\src_main\dlls\controller.cpp"
"D:\Xash3D\src_main\dlls\crossbow.cpp"
"D:\Xash3D\src_main\dlls\crowbar.cpp"
"D:\Xash3D\src_main\dlls\defaultai.cpp"
"D:\Xash3D\src_main\dlls\doors.cpp"
"D:\Xash3D\src_main\dlls\effects.cpp"
"D:\Xash3D\src_main\dlls\egon.cpp"
"D:\Xash3D\src_main\dlls\explode.cpp"
"D:\Xash3D\src_main\dlls\flyingmonster.cpp"
"D:\Xash3D\src_main\dlls\func_break.cpp"
"D:\Xash3D\src_main\dlls\func_tank.cpp"
"D:\Xash3D\src_main\dlls\game.cpp"
"D:\Xash3D\src_main\dlls\gamerules.cpp"
"D:\Xash3D\src_main\dlls\gargantua.cpp"
"D:\Xash3D\src_main\dlls\gauss.cpp"
"D:\Xash3D\src_main\dlls\genericmonster.cpp"
"D:\Xash3D\src_main\dlls\ggrenade.cpp"
"D:\Xash3D\src_main\dlls\globals.cpp"
"D:\Xash3D\src_main\dlls\gman.cpp"
"D:\Xash3D\src_main\dlls\h_ai.cpp"
"D:\Xash3D\src_main\dlls\h_battery.cpp"
"D:\Xash3D\src_main\dlls\h_cine.cpp"
"D:\Xash3D\src_main\dlls\h_cycler.cpp"
"D:\Xash3D\src_main\dlls\h_export.cpp"
"D:\Xash3D\src_main\dlls\handgrenade.cpp"
"D:\Xash3D\src_main\dlls\hassassin.cpp"
"D:\Xash3D\src_main\dlls\headcrab.cpp"
"D:\Xash3D\src_main\dlls\healthkit.cpp"
"D:\Xash3D\src_main\dlls\hgrunt.cpp"
"D:\Xash3D\src_main\dlls\wpn_shared\hl_wpn_glock.cpp"
"D:\Xash3D\src_main\dlls\hornet.cpp"
"D:\Xash3D\src_main\dlls\hornetgun.cpp"
"D:\Xash3D\src_main\dlls\houndeye.cpp"
"D:\Xash3D\src_main\dlls\ichthyosaur.cpp"
"D:\Xash3D\src_main\dlls\islave.cpp"
"D:\Xash3D\src_main\dlls\items.cpp"
"D:\Xash3D\src_main\dlls\leech.cpp"
"D:\Xash3D\src_main\dlls\lights.cpp"
"D:\Xash3D\src_main\dlls\maprules.cpp"
"D:\Xash3D\src_main\dlls\monstermaker.cpp"
"D:\Xash3D\src_main\dlls\monsters.cpp"
"D:\Xash3D\src_main\dlls\monsterstate.cpp"
"D:\Xash3D\src_main\dlls\mortar.cpp"
"D:\Xash3D\src_main\dlls\mp5.cpp"
"D:\Xash3D\src_main\dlls\multiplay_gamerules.cpp"
"D:\Xash3D\src_main\dlls\nihilanth.cpp"
"D:\Xash3D\src_main\dlls\nodes.cpp"
"D:\Xash3D\src_main\dlls\osprey.cpp"
"D:\Xash3D\src_main\dlls\pathcorner.cpp"
"D:\Xash3D\src_main\dlls\plane.cpp"
"D:\Xash3D\src_main\dlls\plats.cpp"
"D:\Xash3D\src_main\dlls\player.cpp"
"D:\Xash3D\src_main\pm_shared\pm_debug.c"
"D:\Xash3D\src_main\pm_shared\pm_math.c"
"D:\Xash3D\src_main\pm_shared\pm_shared.c"
"D:\Xash3D\src_main\dlls\python.cpp"
"D:\Xash3D\src_main\dlls\rat.cpp"
"D:\Xash3D\src_main\dlls\roach.cpp"
"D:\Xash3D\src_main\dlls\rpg.cpp"
"D:\Xash3D\src_main\dlls\satchel.cpp"
"D:\Xash3D\src_main\dlls\schedule.cpp"
"D:\Xash3D\src_main\dlls\scientist.cpp"
"D:\Xash3D\src_main\dlls\scripted.cpp"
"D:\Xash3D\src_main\dlls\shotgun.cpp"
"D:\Xash3D\src_main\dlls\singleplay_gamerules.cpp"
"D:\Xash3D\src_main\dlls\skill.cpp"
"D:\Xash3D\src_main\dlls\sound.cpp"
"D:\Xash3D\src_main\dlls\soundent.cpp"
"D:\Xash3D\src_main\dlls\spectator.cpp"
"D:\Xash3D\src_main\dlls\squadmonster.cpp"
"D:\Xash3D\src_main\dlls\squeakgrenade.cpp"
"D:\Xash3D\src_main\dlls\subs.cpp"
"D:\Xash3D\src_main\dlls\talkmonster.cpp"
"D:\Xash3D\src_main\dlls\teamplay_gamerules.cpp"
"D:\Xash3D\src_main\dlls\tempmonster.cpp"
"D:\Xash3D\src_main\dlls\tentacle.cpp"
"D:\Xash3D\src_main\dlls\triggers.cpp"
"D:\Xash3D\src_main\dlls\tripmine.cpp"
"D:\Xash3D\src_main\dlls\turret.cpp"
"D:\Xash3D\src_main\dlls\util.cpp"
"D:\Xash3D\src_main\game_shared\voice_gamemgr.cpp"
"D:\Xash3D\src_main\dlls\weapons.cpp"
"D:\Xash3D\src_main\dlls\world.cpp"
"D:\Xash3D\src_main\dlls\xen.cpp"
"D:\Xash3D\src_main\dlls\zombie.cpp"
]
Creating command line "cl.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP3740.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP3741.tmp" with contents
[
user32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\dlls\!debug/hl.pdb" /debug /machine:I386 /def:".\hl.def" /out:"..\temp\dlls\!debug/hl.dll" /implib:"..\temp\dlls\!debug/hl.lib"
"\Xash3D\src_main\temp\dlls\!debug\aflock.obj"
"\Xash3D\src_main\temp\dlls\!debug\agrunt.obj"
"\Xash3D\src_main\temp\dlls\!debug\airtank.obj"
"\Xash3D\src_main\temp\dlls\!debug\animating.obj"
"\Xash3D\src_main\temp\dlls\!debug\animation.obj"
"\Xash3D\src_main\temp\dlls\!debug\apache.obj"
"\Xash3D\src_main\temp\dlls\!debug\barnacle.obj"
"\Xash3D\src_main\temp\dlls\!debug\barney.obj"
"\Xash3D\src_main\temp\dlls\!debug\bigmomma.obj"
"\Xash3D\src_main\temp\dlls\!debug\bloater.obj"
"\Xash3D\src_main\temp\dlls\!debug\bmodels.obj"
"\Xash3D\src_main\temp\dlls\!debug\bullsquid.obj"
"\Xash3D\src_main\temp\dlls\!debug\buttons.obj"
"\Xash3D\src_main\temp\dlls\!debug\cbase.obj"
"\Xash3D\src_main\temp\dlls\!debug\client.obj"
"\Xash3D\src_main\temp\dlls\!debug\combat.obj"
"\Xash3D\src_main\temp\dlls\!debug\controller.obj"
"\Xash3D\src_main\temp\dlls\!debug\crossbow.obj"
"\Xash3D\src_main\temp\dlls\!debug\crowbar.obj"
"\Xash3D\src_main\temp\dlls\!debug\defaultai.obj"
"\Xash3D\src_main\temp\dlls\!debug\doors.obj"
"\Xash3D\src_main\temp\dlls\!debug\effects.obj"
"\Xash3D\src_main\temp\dlls\!debug\egon.obj"
"\Xash3D\src_main\temp\dlls\!debug\explode.obj"
"\Xash3D\src_main\temp\dlls\!debug\flyingmonster.obj"
"\Xash3D\src_main\temp\dlls\!debug\func_break.obj"
"\Xash3D\src_main\temp\dlls\!debug\func_tank.obj"
"\Xash3D\src_main\temp\dlls\!debug\game.obj"
"\Xash3D\src_main\temp\dlls\!debug\gamerules.obj"
"\Xash3D\src_main\temp\dlls\!debug\gargantua.obj"
"\Xash3D\src_main\temp\dlls\!debug\gauss.obj"
"\Xash3D\src_main\temp\dlls\!debug\genericmonster.obj"
"\Xash3D\src_main\temp\dlls\!debug\ggrenade.obj"
"\Xash3D\src_main\temp\dlls\!debug\globals.obj"
"\Xash3D\src_main\temp\dlls\!debug\gman.obj"
"\Xash3D\src_main\temp\dlls\!debug\h_ai.obj"
"\Xash3D\src_main\temp\dlls\!debug\h_battery.obj"
"\Xash3D\src_main\temp\dlls\!debug\h_cine.obj"
"\Xash3D\src_main\temp\dlls\!debug\h_cycler.obj"
"\Xash3D\src_main\temp\dlls\!debug\h_export.obj"
"\Xash3D\src_main\temp\dlls\!debug\handgrenade.obj"
"\Xash3D\src_main\temp\dlls\!debug\hassassin.obj"
"\Xash3D\src_main\temp\dlls\!debug\headcrab.obj"
"\Xash3D\src_main\temp\dlls\!debug\healthkit.obj"
"\Xash3D\src_main\temp\dlls\!debug\hgrunt.obj"
"\Xash3D\src_main\temp\dlls\!debug\hl_wpn_glock.obj"
"\Xash3D\src_main\temp\dlls\!debug\hornet.obj"
"\Xash3D\src_main\temp\dlls\!debug\hornetgun.obj"
"\Xash3D\src_main\temp\dlls\!debug\houndeye.obj"
"\Xash3D\src_main\temp\dlls\!debug\ichthyosaur.obj"
"\Xash3D\src_main\temp\dlls\!debug\islave.obj"
"\Xash3D\src_main\temp\dlls\!debug\items.obj"
"\Xash3D\src_main\temp\dlls\!debug\leech.obj"
"\Xash3D\src_main\temp\dlls\!debug\lights.obj"
"\Xash3D\src_main\temp\dlls\!debug\maprules.obj"
"\Xash3D\src_main\temp\dlls\!debug\monstermaker.obj"
"\Xash3D\src_main\temp\dlls\!debug\monsters.obj"
"\Xash3D\src_main\temp\dlls\!debug\monsterstate.obj"
"\Xash3D\src_main\temp\dlls\!debug\mortar.obj"
"\Xash3D\src_main\temp\dlls\!debug\mp5.obj"
"\Xash3D\src_main\temp\dlls\!debug\multiplay_gamerules.obj"
"\Xash3D\src_main\temp\dlls\!debug\nihilanth.obj"
"\Xash3D\src_main\temp\dlls\!debug\nodes.obj"
"\Xash3D\src_main\temp\dlls\!debug\osprey.obj"
"\Xash3D\src_main\temp\dlls\!debug\pathcorner.obj"
"\Xash3D\src_main\temp\dlls\!debug\plane.obj"
"\Xash3D\src_main\temp\dlls\!debug\plats.obj"
"\Xash3D\src_main\temp\dlls\!debug\player.obj"
"\Xash3D\src_main\temp\dlls\!debug\pm_debug.obj"
"\Xash3D\src_main\temp\dlls\!debug\pm_math.obj"
"\Xash3D\src_main\temp\dlls\!debug\pm_shared.obj"
"\Xash3D\src_main\temp\dlls\!debug\python.obj"
"\Xash3D\src_main\temp\dlls\!debug\rat.obj"
"\Xash3D\src_main\temp\dlls\!debug\roach.obj"
"\Xash3D\src_main\temp\dlls\!debug\rpg.obj"
"\Xash3D\src_main\temp\dlls\!debug\satchel.obj"
"\Xash3D\src_main\temp\dlls\!debug\schedule.obj"
"\Xash3D\src_main\temp\dlls\!debug\scientist.obj"
"\Xash3D\src_main\temp\dlls\!debug\scripted.obj"
"\Xash3D\src_main\temp\dlls\!debug\shotgun.obj"
"\Xash3D\src_main\temp\dlls\!debug\singleplay_gamerules.obj"
"\Xash3D\src_main\temp\dlls\!debug\skill.obj"
"\Xash3D\src_main\temp\dlls\!debug\sound.obj"
"\Xash3D\src_main\temp\dlls\!debug\soundent.obj"
"\Xash3D\src_main\temp\dlls\!debug\spectator.obj"
"\Xash3D\src_main\temp\dlls\!debug\squadmonster.obj"
"\Xash3D\src_main\temp\dlls\!debug\squeakgrenade.obj"
"\Xash3D\src_main\temp\dlls\!debug\subs.obj"
"\Xash3D\src_main\temp\dlls\!debug\talkmonster.obj"
"\Xash3D\src_main\temp\dlls\!debug\teamplay_gamerules.obj"
"\Xash3D\src_main\temp\dlls\!debug\tempmonster.obj"
"\Xash3D\src_main\temp\dlls\!debug\tentacle.obj"
"\Xash3D\src_main\temp\dlls\!debug\triggers.obj"
"\Xash3D\src_main\temp\dlls\!debug\tripmine.obj"
"\Xash3D\src_main\temp\dlls\!debug\turret.obj"
"\Xash3D\src_main\temp\dlls\!debug\util.obj"
"\Xash3D\src_main\temp\dlls\!debug\voice_gamemgr.obj"
"\Xash3D\src_main\temp\dlls\!debug\weapons.obj"
"\Xash3D\src_main\temp\dlls\!debug\world.obj"
"\Xash3D\src_main\temp\dlls\!debug\xen.obj"
"\Xash3D\src_main\temp\dlls\!debug\zombie.obj"
]
Creating command line "link.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP3741.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP3742.bat" with contents
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP614.bat" with contents
[
@echo off
copy \Xash3D\src_main\temp\dlls\!debug\hl.dll "D:\Xash3D\valve\dlls\hl.dll"
copy \Xash3D\src_main\temp\dlls\!release\hl.dll "D:\Xash3D\valve\dlls\hl.dll"
]
Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP3742.bat""
Compiling...
aflock.cpp
agrunt.cpp
airtank.cpp
animating.cpp
animation.cpp
apache.cpp
barnacle.cpp
barney.cpp
bigmomma.cpp
bloater.cpp
bmodels.cpp
bullsquid.cpp
buttons.cpp
cbase.cpp
cl.exe terminated at user request.
Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP614.bat""
<h3>Output Window</h3>
Performing Custom Build Step on \Xash3D\src_main\temp\dlls\!release\hl.dll
‘ª®¯¨à®¢ ­® ä ©«®¢: 1.
<h3>Results</h3>
hl.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -168,10 +168,8 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
if(( ent->index - 1 ) == cl.playernum && ent != &clgame.viewent &&
cl.thirdperson == false && cls.key_dest != key_menu && cl.refdef.viewentity == ( cl.playernum + 1 ))
{
#ifdef MIRROR_TEST
// will be drawn in mirror
R_AddEntity( ent, entityType );
#endif
if( gl_allow_mirrors->integer && world.has_mirrors )
R_AddEntity( ent, entityType ); // will be drawn in mirror
}
else
{

View File

@ -1357,6 +1357,7 @@ void CL_ClearWorld( void )
cl.world->index = 0;
clgame.ds.cullMode = GL_FRONT;
clgame.numStatics = 0;
}
void CL_InitEdicts( void )
@ -1367,6 +1368,8 @@ void CL_InitEdicts( void )
cls.num_client_entities = CL_UPDATE_BACKUP * 64;
cls.packet_entities = Z_Realloc( cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities );
clgame.entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities );
clgame.static_entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
clgame.numStatics = 0;
if(( clgame.maxRemapInfos - 1 ) != clgame.maxEntities )
{
@ -1382,11 +1385,17 @@ void CL_FreeEdicts( void )
Mem_Free( clgame.entities );
clgame.entities = NULL;
if( clgame.static_entities )
Mem_Free( clgame.static_entities );
clgame.static_entities = NULL;
if( cls.packet_entities )
Z_Free( cls.packet_entities );
cls.packet_entities = NULL;
cls.num_client_entities = 0;
cls.next_client_entities = 0;
clgame.numStatics = 0;
}
/*
@ -3460,7 +3469,7 @@ Voice_StartVoiceTweakMode
*/
int Voice_StartVoiceTweakMode( void )
{
// UNDONE: wait for voice implementation
// TODO: implement
return 0;
}

View File

@ -348,6 +348,7 @@ pfnPIC_Load
static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long image_size )
{
HIMAGE tx;
int flags = TF_IMAGE;
if( !szPicName || !*szPicName )
{
@ -355,8 +356,12 @@ static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long im
return 0;
}
// HACKHACK: keep source for gfx\shell\gamma
if( !glConfig.deviceSupportsGamma && Q_stristr( szPicName, "gamma" ))
flags |= TF_KEEP_RGBDATA;
host.decal_loading = true;
tx = GL_LoadTexture( szPicName, image_buf, image_size, TF_IMAGE );
tx = GL_LoadTexture( szPicName, image_buf, image_size, flags );
host.decal_loading = false;
return tx;
@ -920,6 +925,7 @@ static ui_enginefuncs_t gEngfuncs =
Com_RandomLong,
IN_SetCursor,
pfnIsMapValid,
GL_ProcessTexture,
};
void UI_UnloadProgs( void )

View File

@ -346,42 +346,70 @@ void CL_ParseParticles( sizebuf_t *msg )
==================
CL_ParseStaticEntity
UDNONE: we need a client implementation of save\restore for use it not in multiplayer only
wait for XashXT when it should be done
==================
*/
void CL_ParseStaticEntity( sizebuf_t *msg )
{
entity_state_t ent;
entity_state_t state;
cl_entity_t *ent;
int i;
Q_memset( &ent, 0, sizeof( ent ));
Q_memset( &state, 0, sizeof( state ));
ent.modelindex = BF_ReadShort( msg );
ent.sequence = BF_ReadByte( msg );
ent.frame = BF_ReadByte( msg );
ent.colormap = BF_ReadWord( msg );
ent.skin = BF_ReadByte( msg );
state.modelindex = BF_ReadShort( msg );
state.sequence = BF_ReadByte( msg );
state.frame = BF_ReadByte( msg );
state.colormap = BF_ReadWord( msg );
state.skin = BF_ReadByte( msg );
for( i = 0; i < 3; i++ )
{
ent.origin[i] = BF_ReadBitCoord( msg );
ent.angles[i] = BF_ReadBitAngle( msg, 16 );
state.origin[i] = BF_ReadBitCoord( msg );
state.angles[i] = BF_ReadBitAngle( msg, 16 );
}
ent.rendermode = BF_ReadByte( msg );
state.rendermode = BF_ReadByte( msg );
if( ent.rendermode != kRenderNormal )
if( state.rendermode != kRenderNormal )
{
ent.renderamt = BF_ReadByte( msg );
ent.rendercolor.r = BF_ReadByte( msg );
ent.rendercolor.g = BF_ReadByte( msg );
ent.rendercolor.b = BF_ReadByte( msg );
ent.renderfx = BF_ReadByte( msg );
state.renderamt = BF_ReadByte( msg );
state.rendercolor.r = BF_ReadByte( msg );
state.rendercolor.g = BF_ReadByte( msg );
state.rendercolor.b = BF_ReadByte( msg );
state.renderfx = BF_ReadByte( msg );
}
// R_AddEfrags( ent );
i = clgame.numStatics;
if( i >= MAX_STATIC_ENTITIES )
{
MsgDev( D_ERROR, "CL_ParseStaticEntity: static entities limit exceeded!\n" );
return;
}
// TODO: allocate client entity, add new static...
MsgDev( D_ERROR, "Static entities are not implemented\n" );
ent = &clgame.static_entities[i];
clgame.numStatics++;
ent->index = 0; // ???
ent->baseline = state;
ent->curstate = state;
ent->prevstate = state;
// setup the new static entity
CL_UpdateEntityFields( ent );
if( Mod_GetType( state.modelindex ) == mod_studio )
{
CL_UpdateStudioVars( ent, &state, true );
// animate studio model
ent->curstate.animtime = cl.time;
ent->curstate.framerate = 1.0f;
ent->latched.prevframe = 0.0f;
}
R_AddEfrags( ent ); // add link
}
/*
@ -430,7 +458,7 @@ void CL_ParseReliableEvent( sizebuf_t *msg, int flags )
Q_memset( &nullargs, 0, sizeof( nullargs ));
event_index = BF_ReadWord( msg ); // read event index
delay = (float)BF_ReadWord( msg ) / 100.0f; // read event delay
MSG_ReadDeltaEvent( msg, &nullargs, &args ); // TODO: delta-compressing
MSG_ReadDeltaEvent( msg, &nullargs, &args ); // reliable events not use delta
CL_QueueEvent( flags, event_index, delay, &args );
}

View File

@ -2622,10 +2622,10 @@ void CL_ClearEfrags( void )
Q_memset( cl_efrags, 0, sizeof( cl_efrags ));
// allocate the efrags and chain together into a free list
cl.free_efrags = cl_efrags;
clgame.free_efrags = cl_efrags;
for( i = 0; i < MAX_EFRAGS - 1; i++ )
cl.free_efrags[i].entnext = &cl.free_efrags[i+1];
cl.free_efrags[i].entnext = NULL;
clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1];
clgame.free_efrags[i].entnext = NULL;
}
/*

View File

@ -34,8 +34,9 @@ GNU General Public License for more details.
#define MAX_MOVIES 8
#define MAX_CDTRACKS 32
#define MAX_IMAGES 256 // SpriteTextures
#define MAX_EFRAGS 640
#define MAX_EFRAGS 256 // g-cont. just no need more
#define MAX_REQUESTS 32
#define MAX_STATIC_ENTITIES 128 // same as in quake1
// screenshot types
#define VID_SCREENSHOT 0
@ -141,7 +142,6 @@ typedef struct
cl_entity_t *world;
model_t *worldmodel; // pointer to world
efrag_t *free_efrags;
} client_t;
/*
@ -362,10 +362,12 @@ typedef struct
string itemspath; // path to items description for auto-complete func
cl_entity_t *entities; // dynamically allocated entity array
cl_entity_t *static_entities; // dynamically allocated static entity array
remap_info_t **remap_info; // store local copy of all remap textures for each entity
int maxEntities;
int maxRemapInfos; // maxEntities + cl.viewEnt; also used for catch entcount
int numStatics; // actual static entity count
// movement values from server
movevars_t movevars;
@ -399,6 +401,7 @@ typedef struct
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
efrag_t *free_efrags; // efrags
cl_entity_t viewent; // viewmodel
} clgame_static_t;
@ -695,6 +698,8 @@ qboolean CL_InitStudioAPI( void );
void CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta );
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType );
qboolean CL_GetEntitySpatialization( int ent, vec3_t origin, vec3_t velocity );
void CL_UpdateStudioVars( cl_entity_t *ent, entity_state_t *newstate, qboolean noInterp );
void CL_UpdateEntityFields( cl_entity_t *ent );
qboolean CL_IsPlayerIndex( int idx );
//

View File

@ -393,7 +393,7 @@ VID_ImageAdjustGamma
void VID_ImageAdjustGamma( byte *in, uint width, uint height )
{
int i, c = width * height;
float g = 1.0f / bound( 0.5f, vid_gamma->value, 3.0f );
float g = 1.0f / bound( 0.5f, vid_gamma->value, 2.3f );
byte r_gammaTable[256]; // adjust screenshot gamma
byte *p = in;
@ -459,7 +459,7 @@ qboolean VID_ScreenShot( const char *filename, int shot_type )
break;
}
Image_Process( &r_shot, width, height, flags );
Image_Process( &r_shot, width, height, 0.0f, flags );
// write image
result = FS_SaveImage( filename, r_shot );
@ -524,7 +524,7 @@ qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qbo
r_side->size = r_side->width * r_side->height * 3;
r_side->buffer = temp;
if( flags ) Image_Process( &r_side, 0, 0, flags );
if( flags ) Image_Process( &r_side, 0, 0, 0.0f, flags );
Q_memcpy( buffer + (size * size * 3 * i), r_side->buffer, size * size * 3 );
}

View File

@ -142,7 +142,7 @@ static void ComputeBeamPerpendicular( const vec3_t vecBeamDelta, vec3_t pPerp )
vec3_t vecBeamCenter;
VectorNormalize2( vecBeamDelta, vecBeamCenter );
CrossProduct( cl.refdef.forward, vecBeamCenter, pPerp );
CrossProduct( RI.vforward, vecBeamCenter, pPerp );
VectorNormalize( pPerp );
}
@ -154,7 +154,7 @@ static void ComputeNormal( const vec3_t vStartPos, const vec3_t vNextPos, vec3_t
VectorSubtract( vStartPos, vNextPos, vTangentY );
// vDirToBeam = vector from viewer origin to beam
VectorSubtract( vStartPos, cl.refdef.vieworg, vDirToBeam );
VectorSubtract( vStartPos, RI.vieworg, vDirToBeam );
// Get a vector that is perpendicular to us and perpendicular to the beam.
// This is used to fatten the beam.
@ -212,18 +212,13 @@ static void CL_DrawSegs( int modelIndex, float frame, int rendermode, const vec3
if( segments < 2 ) segments = 2;
}
if( segments > NOISE_DIVISIONS ) // UNDONE: Allow more segments?
{
if( segments > NOISE_DIVISIONS )
segments = NOISE_DIVISIONS;
}
div = 1.0f / (segments - 1);
length *= 0.01f;
// UNDONE: Expose texture length scale factor to control "fuzziness"
vStep = length * div; // Texture length texels per space pixel
// UNDONE: Expose this paramter as well(3.5)? Texture scroll rate along beam
// Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture)
vLast = fmod( freq * speed, 1 );
@ -314,11 +309,11 @@ static void CL_DrawSegs( int modelIndex, float frame, int rendermode, const vec3
float s, c;
SinCos( fraction * M_PI * length + freq, &s, &c );
VectorMA( nextSeg.pos, (factor * s), cl.refdef.up, nextSeg.pos );
VectorMA( nextSeg.pos, (factor * s), RI.vup, nextSeg.pos );
// rotate the noise along the perpendicluar axis a bit to keep the bolt
// from looking diagonal
VectorMA( nextSeg.pos, (factor * c), cl.refdef.right, nextSeg.pos );
VectorMA( nextSeg.pos, (factor * c), RI.vright, nextSeg.pos );
}
else
{
@ -416,18 +411,15 @@ static void CL_DrawDisk( int modelIndex, float frame, int rendermode, const vec3
if( !m_hSprite || segments < 2 )
return;
if( segments > NOISE_DIVISIONS ) // UNDONE: Allow more segments?
if( segments > NOISE_DIVISIONS )
segments = NOISE_DIVISIONS;
length = VectorLength( delta ) * 0.01f;
if( length < 0.5f ) length = 0.5f; // don't lose all of the noise/texture on short beams
div = 1.0f / (segments - 1);
// UNDONE: Expose texture length scale factor to control "fuzziness"
vStep = length * div; // Texture length texels per space pixel
// UNDONE: Expose this paramter as well(3.5)? Texture scroll rate along beam
// Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture)
vLast = fmod( freq * speed, 1 );
scale = scale * length;
@ -487,18 +479,15 @@ static void CL_DrawCylinder( int modelIndex, float frame, int rendermode, const
if( !m_hSprite || segments < 2 )
return;
if( segments > NOISE_DIVISIONS ) // UNDONE: Allow more segments?
if( segments > NOISE_DIVISIONS )
segments = NOISE_DIVISIONS;
length = VectorLength( delta ) * 0.01f;
if( length < 0.5f ) length = 0.5f; // Don't lose all of the noise/texture on short beams
div = 1.0f / (segments - 1);
// UNDONE: Expose texture length scale factor to control "fuzziness"
vStep = length * div; // Texture length texels per space pixel
// UNDONE: Expose this paramter as well(3.5)? Texture scroll rate along beam
// Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture)
vLast = fmod( freq * speed, 1.0f );
scale = scale * length;
@ -567,7 +556,7 @@ void CL_DrawRing( int modelIndex, float frame, int rendermode, const vec3_t sour
VectorClear( screenLast );
segments = segments * M_PI;
if( segments > NOISE_DIVISIONS * 8 ) // UNDONE: Allow more segments?
if( segments > NOISE_DIVISIONS * 8 )
segments = NOISE_DIVISIONS * 8;
length = VectorLength( d ) * 0.01f * M_PI;
@ -575,10 +564,8 @@ void CL_DrawRing( int modelIndex, float frame, int rendermode, const vec3_t sour
div = 1.0 / ( segments - 1 );
// UNDONE: Expose texture length scale factor to control "fuzziness"
vStep = length * div / 8.0f; // Texture length texels per space pixel
// UNDONE: Expose this paramter as well(3.5)? Texture scroll rate along beam
// Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture)
vLast = fmod( freq * speed, 1.0f );
scale = amplitude * length / 8.0f;
@ -633,12 +620,12 @@ void CL_DrawRing( int modelIndex, float frame, int rendermode, const vec3_t sour
// Distort using noise
factor = rgNoise[(noiseIndex >> 16) & (NOISE_DIVISIONS - 1)] * scale;
VectorMA( point, factor, cl.refdef.up, point );
VectorMA( point, factor, RI.vup, point );
// Rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal
factor = rgNoise[(noiseIndex>>16) & (NOISE_DIVISIONS - 1)] * scale;
factor *= cos( fraction * M_PI * 24 + freq );
VectorMA( point, factor, cl.refdef.right, point );
VectorMA( point, factor, RI.vright, point );
// Transform point into screen space
TriWorldToScreen( point, screen );
@ -653,8 +640,8 @@ void CL_DrawRing( int modelIndex, float frame, int rendermode, const vec3_t sour
VectorNormalize( tmp );
// Build point along normal line (normal is -y, x)
VectorScale( cl.refdef.up, tmp[0], normal );
VectorMA( normal, tmp[1], cl.refdef.right, normal );
VectorScale( RI.vup, tmp[0], normal );
VectorMA( normal, tmp[1], RI.vright, normal );
// make a wide line
VectorMA( point, width, normal, last1 );
@ -694,7 +681,6 @@ Helper to drawing laser
void CL_DrawLaser( BEAM *pbeam, int frame, int rendermode, float *color, int spriteIndex )
{
float color2[3];
vec3_t vecForward;
vec3_t beamDir;
float flDot;
@ -703,8 +689,7 @@ void CL_DrawLaser( BEAM *pbeam, int frame, int rendermode, float *color, int spr
VectorSubtract( pbeam->target, pbeam->source, beamDir );
VectorNormalize( beamDir );
AngleVectors( cl.refdef.viewangles, vecForward, NULL, NULL );
flDot = DotProduct( beamDir, vecForward );
flDot = DotProduct( beamDir, RI.vforward );
// abort if the player's looking along it away from the source
if( flDot > 0 )
@ -719,7 +704,7 @@ void CL_DrawLaser( BEAM *pbeam, int frame, int rendermode, float *color, int spr
float flDistance;
// Fade the beam based on the player's proximity to the beam
VectorSubtract( cl.refdef.vieworg, pbeam->source, localDir );
VectorSubtract( RI.vieworg, pbeam->source, localDir );
flDot = DotProduct( beamDir, localDir );
VectorScale( beamDir, flDot, vecProjection );
VectorSubtract( localDir, vecProjection, tmp );
@ -764,9 +749,7 @@ static void DrawBeamFollow( int modelIndex, particle_t *pHead, int frame, int re
rgb_t nColor;
m_hSprite = R_GetSpriteTexture( Mod_Handle( modelIndex ), frame );
if( !m_hSprite )
return;
if( !m_hSprite ) return;
// UNDONE: This won't work, screen and screenLast must be extrapolated here to fix the
// first beam segment for this trail
@ -778,8 +761,8 @@ static void DrawBeamFollow( int modelIndex, particle_t *pHead, int frame, int re
VectorNormalize( tmp );
// Build point along noraml line (normal is -y, x)
VectorScale( cl.refdef.up, tmp[0], normal ); // Build point along normal line (normal is -y, x)
VectorMA( normal, tmp[1], cl.refdef.right, normal );
VectorScale( RI.vup, tmp[0], normal ); // Build point along normal line (normal is -y, x)
VectorMA( normal, tmp[1], RI.vright, normal );
// make a wide line
VectorMA( delta, width, normal, last1 );
@ -818,8 +801,8 @@ static void DrawBeamFollow( int modelIndex, particle_t *pHead, int frame, int re
VectorNormalize( tmp );
// build point along normal line (normal is -y, x)
VectorScale( cl.refdef.up, tmp[0], normal );
VectorMA( normal, tmp[1], cl.refdef.right, normal );
VectorScale( RI.vup, tmp[0], normal );
VectorMA( normal, tmp[1], RI.vright, normal );
// Make a wide line
VectorMA( pHead->org, width, normal, last1 );

View File

@ -143,4 +143,77 @@ int R_CullModel( cl_entity_t *e, vec3_t origin, vec3_t mins, vec3_t maxs, float
return 1;
return 0;
}
/*
=================
R_CullSurface
cull invisible surfaces
=================
*/
qboolean R_CullSurface( msurface_t *surf, uint clipflags )
{
mextrasurf_t *info;
if( !surf || !surf->texinfo || !surf->texinfo->texture )
return true;
if( surf->flags & SURF_WATERCSG && !( RI.currententity->curstate.effects & EF_NOWATERCSG ))
return true;
if( surf->flags & SURF_NOCULL )
return false;
if( r_nocull->integer )
return false;
// world surfaces can be culled by vis frame too
if( RI.currententity == clgame.entities && surf->visframe != tr.framecount )
return true;
if( r_faceplanecull->integer && glState.faceCull != 0 )
{
if(!(surf->flags & SURF_DRAWTURB) || !RI.currentWaveHeight )
{
if( !VectorIsNull( surf->plane->normal ))
{
float dist;
if( RI.drawOrtho ) dist = surf->plane->normal[2];
else dist = PlaneDiff( tr.modelorg, surf->plane );
if( glState.faceCull == GL_FRONT || ( RI.params & RP_MIRRORVIEW ))
{
if( surf->flags & SURF_PLANEBACK )
{
if( dist >= -BACKFACE_EPSILON )
return true; // wrong side
}
else
{
if( dist <= BACKFACE_EPSILON )
return true; // wrong side
}
}
else if( glState.faceCull == GL_BACK )
{
if( surf->flags & SURF_PLANEBACK )
{
if( dist <= BACKFACE_EPSILON )
return true; // wrong side
}
else
{
if( dist >= -BACKFACE_EPSILON )
return true; // wrong side
}
}
}
}
}
info = SURF_INFO( surf, RI.currentmodel );
return ( clipflags && R_CullBox( info->mins, info->maxs, clipflags ));
}

View File

@ -963,11 +963,9 @@ static int DecalListAdd( decallist_t *pList, int count )
if( !Q_strcmp( pdecal->name, pList[i].name ) && pdecal->entityIndex == pList[i].entityIndex )
{
VectorSubtract( pdecal->position, pList[i].position, tmp ); // Merge
if( VectorLength( tmp ) < 2 )
{
// UNDONE: Tune this '2' constant
if( VectorLength( tmp ) < 2 ) // UNDONE: Tune this '2' constant
return count;
}
}
}

View File

@ -676,6 +676,34 @@ byte *GL_ResampleTexture( const byte *source, int inWidth, int inHeight, int out
return scaledImage;
}
/*
=================
GL_ResampleTexture
Assume input buffer is RGBA
=================
*/
byte *GL_ApplyGamma( const byte *source, int pixels, qboolean isNormalMap )
{
byte *in = (byte *)source;
byte *out = (byte *)source;
int i;
if( isNormalMap )
{
}
else
{
for( i = 0; i < pixels; i++, in += 4 )
{
in[0] = TextureToGamma( in[0] );
in[1] = TextureToGamma( in[1] );
in[2] = TextureToGamma( in[2] );
}
}
return out;
}
/*
=================
GL_BuildMipMap
@ -851,7 +879,7 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag
img_flags |= IMAGE_FORCE_RGBA;
// processing image before uploading (force to rgba, make luma etc)
if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags );
if( pic->buffer ) Image_Process( &pic, 0, 0, 0.0f, img_flags );
if( tex->flags & TF_LUMINANCE )
{
@ -930,7 +958,13 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag
{
data = GL_ResampleTexture( buf, tex->srcWidth, tex->srcHeight, tex->width, tex->height, ( tex->flags & TF_NORMALMAP ));
}
if( !glConfig.deviceSupportsGamma )
{
if(!( tex->flags & TF_NOMIPMAP ) && !( tex->flags & TF_SKYSIDE ))
data = GL_ApplyGamma( data, tex->width * tex->height, ( tex->flags & TF_NORMALMAP ));
}
if( GL_Support( GL_SGIS_MIPMAPS_EXT )) GL_GenerateMipmaps( data, pic, tex, glTarget, inFormat, i, subImage );
if( subImage ) pglTexSubImage2D( tex->target + i, 0, 0, 0, tex->width, tex->height, inFormat, GL_UNSIGNED_BYTE, data );
else pglTexImage2D( tex->target + i, 0, outFormat, tex->width, tex->height, 0, inFormat, GL_UNSIGNED_BYTE, data );
@ -1012,7 +1046,10 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags )
GL_UploadTexture( pic, tex, false );
GL_TexFilter( tex, false ); // update texture filter, wrap etc
FS_FreeImage( pic ); // release source texture
if( flags & TF_KEEP_RGBDATA )
tex->original = pic;
else FS_FreeImage( pic ); // release source texture
// add to hash table
hash = Com_HashKey( tex->name, TEXTURES_HASH_SIZE );
@ -1108,6 +1145,41 @@ int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags,
return tex->texnum;
}
/*
================
GL_ProcessTexture
================
*/
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
{
gltexture_t *image;
rgbdata_t *pic;
byte *buf;
ASSERT( texnum > 0 && texnum < MAX_TEXTURES );
image = &r_textures[texnum];
if(!( image->flags & TF_KEEP_RGBDATA ) || !image->original )
{
MsgDev( D_ERROR, "GL_ProcessTexture: no input data for %s\n", image->name );
return;
}
pic = image->original;
buf = Mem_Alloc( r_temppool, pic->size );
Q_memcpy( buf, pic->buffer, pic->size );
// UNDONE: topColor and bottomColor just for future expansions
Image_Process( &pic, topColor, bottomColor, gamma, IMAGE_LIGHTGAMMA );
GL_UploadTexture( pic, image, true );
GL_TexFilter( image, true ); // update texture filter, wrap etc
// restore original image
Q_memcpy( pic->buffer, buf, pic->size );
Mem_Free( buf );
}
/*
================
GL_LoadTexture
@ -1221,6 +1293,10 @@ void GL_FreeTexture( GLenum texnum )
prev = &cur->nextHash;
}
// release source
if( image->flags & TF_KEEP_RGBDATA && image->original )
FS_FreeImage( image->original );
pglDeleteTextures( 1, &image->texnum );
Q_memset( image, 0, sizeof( *image ));
}

View File

@ -32,12 +32,11 @@ extern byte *r_temppool;
#define MAX_DETAIL_TEXTURES 256
#define MAX_LIGHTMAPS 128
#define SUBDIVIDE_SIZE 64
#define MAX_MIRRORS 32 // per one frame!
#define NUMVERTEXNORMALS 162
#define SHADEDOT_QUANT 16 // precalculated dot products for quantized angles
//#define MIRROR_TEST
// refparams
#define RP_NONE 0
#define RP_MIRRORVIEW BIT( 0 ) // lock pvs at vieworg
@ -68,7 +67,8 @@ typedef enum
TEX_VGUI, // vgui fonts or images
TEX_CUBEMAP, // cubemap textures (sky)
TEX_DETAIL, // detail textures
TEX_REMAP // local copy of remap texture
TEX_REMAP, // local copy of remap texture
TEX_SCREENCOPY // keep screen copy e.g. for mirror
} texType_t;
typedef enum
@ -89,6 +89,7 @@ typedef enum
TF_NORMALMAP = BIT(13), // is a normalmap
TF_LIGHTMAP = BIT(14), // is a lightmap
TF_FORCE_COLOR = BIT(15), // force upload monochrome textures as RGB (detail textures)
TF_KEEP_RGBDATA = BIT(16), // some images keep source
} texFlags_t;
typedef struct gltexture_s
@ -106,6 +107,8 @@ typedef struct gltexture_s
rgba_t fogParams; // some water textures
// contain info about underwater fog
rgbdata_t *original; // keep original image
// debug info
byte texType; // used for gl_showtextures
size_t size; // upload size for debug targets
@ -125,13 +128,17 @@ typedef struct mextrasurf_s
int checkcount; // for multi-check avoidance
int dlight_s, dlight_t; // gl lightmap coordinates for dynamic lightmaps
int mirrortexturenum; // gl texnum
matrix4x4 mirrormatrix;
struct mextrasurf_s *mirrorchain; // for gl_texsort drawing
} mextrasurf_t;
// mirror entity
typedef struct gl_entity_s
{
cl_entity_t *ent;
msurface_t *chain;
mextrasurf_t *chain;
} gl_entity_t;
typedef struct
@ -202,6 +209,8 @@ typedef struct
int lightmapTextures[MAX_LIGHTMAPS];
int dlightTexture; // custom dlight texture
int skyboxTextures[6]; // skybox sides
int mirrorTextures[MAX_MIRRORS];
int num_mirrors_used; // used mirror textures
int skytexturenum; // this not a gl_texturenum!
@ -225,6 +234,9 @@ typedef struct
int visframecount; // PVS frame
int dlightframecount; // dynamic light frame
int framecount;
// cull info
vec3_t modelorg; // relative to viewpoint
} ref_globals_t;
typedef struct
@ -270,6 +282,7 @@ void GL_SelectTexture( GLenum texture );
void GL_DisableMultitexture( void );
void GL_EnableMultitexture( void );
void GL_LoadIdentityTexMatrix( void );
void GL_DisableAllTexGens( void );
void GL_SetRenderMode( int mode );
void GL_FrontFace( GLenum front );
void GL_MBind( GLenum texnum );
@ -282,6 +295,7 @@ void R_ShowTextures( void );
int R_CullModel( cl_entity_t *e, vec3_t origin, vec3_t mins, vec3_t maxs, float radius );
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, uint clipflags );
qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags );
qboolean R_CullSurface( msurface_t *surf, uint clipflags );
//
// gl_decals.c
@ -306,6 +320,7 @@ void GL_SetTextureType( GLenum texnum, GLenum type );
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap );
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
int GL_FindTexture( const char *name );
void GL_FreeTexture( GLenum texnum );
void GL_FreeImage( const char *name );
@ -313,6 +328,14 @@ void R_TextureList_f( void );
void R_InitImages( void );
void R_ShutdownImages( void );
//
// gl_mirror.c
//
void R_BeginDrawMirror( msurface_t *fa );
void R_EndDrawMirror( void );
void R_DrawMirrors( void );
void R_FindMirrors( const ref_params_t *fd );
//
// gl_refrag.c
//
@ -339,6 +362,8 @@ qboolean R_WorldToScreen2( const vec3_t in, vec3_t out );
void R_TranslateForEntity( cl_entity_t *e );
void R_RotateForEntity( cl_entity_t *e );
int R_ComputeFxBlend( cl_entity_t *e );
void R_SetupFrustum( void );
void R_FindViewLeaf( void );
void R_DrawFog( void );
//
@ -372,6 +397,7 @@ void R_DrawWaterSurfaces( void );
void R_DrawBrushModel( cl_entity_t *e );
void GL_SubdivideSurface( msurface_t *fa );
void GL_BuildPolygonFromSurface( msurface_t *fa );
void GL_RebuildLightmaps( void );
void GL_BuildLightmaps( void );
//
@ -600,6 +626,7 @@ extern convar_t *gl_luminance_textures;
extern convar_t *gl_overview; // draw map in overview mode
extern convar_t *gl_wireframe;
extern convar_t *gl_allow_static;
extern convar_t *gl_allow_mirrors;
extern convar_t *gl_picmip;
extern convar_t *gl_skymip;
extern convar_t *gl_finish;
@ -632,6 +659,7 @@ extern convar_t *r_fastsky;
extern convar_t *vid_displayfrequency;
extern convar_t *vid_fullscreen;
extern convar_t *vid_gamma;
extern convar_t *vid_texgamma;
extern convar_t *vid_mode;
#endif//GL_LOCAL_H

579
engine/client/gl_mirror.c Normal file
View File

@ -0,0 +1,579 @@
/*
gl_mirror.c - draw reflected surfaces
Copyright (C) 2010 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "client.h"
#include "gl_local.h"
#include "mod_local.h"
#include "mathlib.h"
/*
================
R_BeginDrawMirror
Setup texture matrix for mirror texture
================
*/
void R_BeginDrawMirror( msurface_t *fa )
{
matrix4x4 m1, m2, matrix;
GLfloat genVector[4][4];
mextrasurf_t *es;
int i;
es = SURF_INFO( fa, RI.currentmodel );
Matrix4x4_Copy( matrix, es->mirrormatrix );
Matrix4x4_LoadIdentity( m1 );
Matrix4x4_ConcatScale( m1, 0.5 );
Matrix4x4_Concat( m2, m1, matrix );
Matrix4x4_LoadIdentity( m1 );
Matrix4x4_ConcatTranslate( m1, 0.5f, 0.5f, 0.5f );
Matrix4x4_Concat( matrix, m1, m2 );
for( i = 0; i < 4; i++ )
{
genVector[0][i] = i == 0 ? 1 : 0;
genVector[1][i] = i == 1 ? 1 : 0;
genVector[2][i] = i == 2 ? 1 : 0;
genVector[3][i] = i == 3 ? 1 : 0;
}
GL_TexGen( GL_S, GL_OBJECT_LINEAR );
GL_TexGen( GL_T, GL_OBJECT_LINEAR );
GL_TexGen( GL_R, GL_OBJECT_LINEAR );
GL_TexGen( GL_Q, GL_OBJECT_LINEAR );
pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] );
pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] );
pglTexGenfv( GL_R, GL_OBJECT_PLANE, genVector[2] );
pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] );
GL_LoadTexMatrix( matrix );
}
/*
================
R_EndDrawMirror
Restore identity texmatrix
================
*/
void R_EndDrawMirror( void )
{
GL_DisableAllTexGens();
GL_LoadIdentityTexMatrix();
pglMatrixMode( GL_MODELVIEW );
}
/*
=============================================================
MIRROR RENDERING
=============================================================
*/
/*
================
R_PlaneForMirror
Get transformed mirrorplane and entity matrix
================
*/
void R_PlaneForMirror( msurface_t *surf, mplane_t *out, matrix4x4 m )
{
cl_entity_t *ent;
ASSERT( out != NULL );
ent = RI.currententity;
// setup mirror plane
*out = *surf->plane;
if( surf->flags & SURF_PLANEBACK )
{
VectorNegate( out->normal, out->normal );
out->dist = -out->dist;
}
if( !VectorIsNull( ent->origin ) || !VectorIsNull( ent->angles ))
{
mplane_t tmp;
if( !VectorIsNull( ent->angles )) Matrix4x4_CreateFromEntity( m, ent->angles, ent->origin, 1.0f );
else Matrix4x4_CreateFromEntity( m, vec3_origin, ent->origin, 1.0f );
tmp = *out;
// transform mirror plane by entity matrix
Matrix4x4_TransformPositivePlane( m, tmp.normal, tmp.dist, out->normal, &out->dist );
}
else Matrix4x4_LoadIdentity( m );
}
/*
================
R_AllocateMirrorTexture
Allocate the screen texture and make copy
================
*/
int R_AllocateMirrorTexture( void )
{
rgbdata_t r_screen;
int i, texture;
char txName[16];
i = tr.num_mirrors_used;
if( i >= MAX_MIRRORS )
{
MsgDev( D_ERROR, "R_AllocateMirrorTexture: mirror textures limit exceeded!\n" );
return 0; // disable
}
texture = tr.mirrorTextures[i];
tr.num_mirrors_used++;
if( !texture )
{
// not iniatlized ?
Q_memset( &r_screen, 0, sizeof( r_screen ));
Q_snprintf( txName, sizeof( txName ), "*screen%i", i );
r_screen.width = RI.viewport[2];
r_screen.height = RI.viewport[3];
r_screen.type = PF_RGBA_32;
r_screen.size = r_screen.width * r_screen.height * 4;
r_screen.flags = IMAGE_HAS_COLOR;
r_screen.buffer = NULL; // create empty texture for now
tr.mirrorTextures[i] = GL_LoadTextureInternal( txName, &r_screen, TF_IMAGE, false );
GL_SetTextureType( tr.mirrorTextures[i], TEX_SCREENCOPY );
texture = tr.mirrorTextures[i];
}
GL_Bind( GL_TEXTURE0, texture );
pglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3], 0 );
return texture;
}
/*
================
R_DrawMirrors
Draw all viewpasess from mirror position
Mirror textures will be drawn in normal pass
================
*/
void R_DrawMirrors( void )
{
ref_instance_t oldRI;
mplane_t plane;
msurface_t *surf;
int i, oldframecount;
mextrasurf_t *es, *tmp, *mirrorchain;
vec3_t forward, right, up;
vec3_t origin, angles;
matrix4x4 mirrormatrix;
cl_entity_t *e;
model_t *m;
float d;
if( !tr.num_mirror_entities ) return; // mo mirrors for this frame
oldRI = RI; // make refinst backup
oldframecount = tr.framecount;
for( i = 0; i < tr.num_mirror_entities; i++ )
{
mirrorchain = tr.mirror_entities[i].chain;
for( es = mirrorchain; es != NULL; )
{
RI.currententity = e = tr.mirror_entities[i].ent;
RI.currentmodel = m = RI.currententity->model;
surf = INFO_SURF( es, m );
ASSERT( RI.currententity != NULL );
ASSERT( RI.currentmodel != NULL );
R_PlaneForMirror( surf, &plane, mirrormatrix );
d = -2.0f * ( DotProduct( RI.vieworg, plane.normal ) - plane.dist );
VectorMA( RI.vieworg, d, plane.normal, origin );
d = -2.0f * DotProduct( RI.vforward, plane.normal );
VectorMA( RI.vforward, d, plane.normal, forward );
VectorNormalize( forward );
d = -2.0f * DotProduct( RI.vright, plane.normal );
VectorMA( RI.vright, d, plane.normal, right );
VectorNormalize( right );
d = -2.0f * DotProduct( RI.vup, plane.normal );
VectorMA( RI.vup, d, plane.normal, up );
VectorNormalize( up );
VectorsAngles( forward, right, up, angles );
angles[ROLL] = -angles[ROLL];
RI.params = RP_MIRRORVIEW|RP_FLIPFRONTFACE|RP_CLIPPLANE|RP_OLDVIEWLEAF;
RI.clipPlane = plane;
RI.clipFlags |= ( 1<<5 );
RI.frustum[5] = plane;
RI.frustum[5].signbits = SignbitsForPlane( RI.frustum[5].normal );
RI.frustum[5].type = PLANE_NONAXIAL;
RI.refdef.viewangles[0] = anglemod( angles[0] );
RI.refdef.viewangles[1] = anglemod( angles[1] );
RI.refdef.viewangles[2] = anglemod( angles[2] );
VectorCopy( origin, RI.refdef.vieworg );
#if 0
// put pvsorigin before the mirror plane to avoid get full visibility on world mirrors
if( RI.currententity == clgame.entities ) VectorMA( es->origin, 5.0f, plane.normal, origin );
#endif
VectorCopy( origin, RI.pvsorigin );
VectorCopy( origin, RI.cullorigin );
// combine two leafs from client and mirror views
r_viewleaf = Mod_PointInLeaf( oldRI.pvsorigin, cl.worldmodel->nodes );
r_viewleaf2 = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );
// FIXME: how to combine two cull origins ?
if( GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
{
// allow screen size
RI.viewport[2] = bound( 96, RI.viewport[2], 1024 );
RI.viewport[3] = bound( 72, RI.viewport[3], 768 );
}
else
{
RI.viewport[2] = NearestPOW( RI.viewport[2], true );
RI.viewport[3] = NearestPOW( RI.viewport[3], true );
RI.viewport[2] = bound( 128, RI.viewport[2], 1024 );
RI.viewport[3] = bound( 64, RI.viewport[3], 512 );
}
tr.framecount++;
R_RenderScene( &RI.refdef );
es->mirrortexturenum = R_AllocateMirrorTexture();
// create personal projection matrix for mirror
if( VectorIsNull( e->origin ) && VectorIsNull( e->angles ))
{
Matrix4x4_Copy( es->mirrormatrix, RI.worldviewProjectionMatrix );
}
else
{
Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, mirrormatrix );
Matrix4x4_Concat( es->mirrormatrix, RI.projectionMatrix, RI.modelviewMatrix );
}
tmp = es->mirrorchain;
es->mirrorchain = NULL;
es = tmp;
RI = oldRI; // restore ref instance
}
tr.mirror_entities[i].chain = NULL; // done
tr.mirror_entities[i].ent = NULL;
}
r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame
tr.framecount = oldframecount; // restore real framecount
tr.num_mirror_entities = 0;
tr.num_mirrors_used = 0;
}
/*
================
R_RecursiveMirrorNode
================
*/
void R_RecursiveMirrorNode( mnode_t *node, uint clipflags )
{
mextrasurf_t *extrasurf;
const mplane_t *clipplane;
int i, clipped;
msurface_t *surf, **mark;
mleaf_t *pleaf;
int c, side;
float dot;
if( node->contents == CONTENTS_SOLID )
return; // hit a solid leaf
if( node->visframe != tr.visframecount )
return;
if( clipflags )
{
for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ )
{
if(!( clipflags & ( 1<<i )))
continue;
clipped = BoxOnPlaneSide( node->minmaxs, node->minmaxs + 3, clipplane );
if( clipped == 2 ) return;
if( clipped == 1 ) clipflags &= ~(1<<i);
}
}
// if a leaf node, draw stuff
if( node->contents < 0 )
{
pleaf = (mleaf_t *)node;
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
if( c )
{
do
{
(*mark)->visframe = tr.framecount;
mark++;
} while( --c );
}
return;
}
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
dot = PlaneDiff( tr.modelorg, node->plane );
side = (dot >= 0) ? 0 : 1;
// recurse down the children, front side first
R_RecursiveMirrorNode( node->children[side], clipflags );
// draw stuff
for( c = node->numsurfaces, surf = cl.worldmodel->surfaces + node->firstsurface; c; c--, surf++ )
{
if(!( surf->flags & SURF_MIRROR ))
continue;
if( R_CullSurface( surf, clipflags ))
continue;
extrasurf = SURF_INFO( surf, RI.currentmodel );
extrasurf->mirrorchain = tr.mirror_entities[0].chain;
tr.mirror_entities[0].chain = extrasurf;
}
// recurse down the back side
R_RecursiveMirrorNode( node->children[!side], clipflags );
}
/*
=================
R_FindBmodelMirrors
Check all bmodel surfaces and make personal mirror chain
=================
*/
void R_FindBmodelMirrors( cl_entity_t *e, qboolean static_entity )
{
mextrasurf_t *extrasurf;
vec3_t mins, maxs;
msurface_t *psurf;
model_t *clmodel;
qboolean rotated;
int i, clipFlags;
clmodel = e->model;
if( static_entity )
{
Matrix4x4_LoadIdentity( RI.objectMatrix );
if( R_CullBox( clmodel->mins, clmodel->maxs, RI.clipFlags ))
return;
VectorCopy( RI.cullorigin, tr.modelorg );
clipFlags = RI.clipFlags;
}
else
{
if( !VectorIsNull( e->angles ))
{
for( i = 0; i < 3; i++ )
{
mins[i] = e->origin[i] - clmodel->radius;
maxs[i] = e->origin[i] + clmodel->radius;
}
rotated = true;
}
else
{
VectorAdd( e->origin, clmodel->mins, mins );
VectorAdd( e->origin, clmodel->maxs, maxs );
rotated = false;
}
if( R_CullBox( mins, maxs, RI.clipFlags ))
return;
if( !VectorIsNull( e->origin ) || !VectorIsNull( e->angles ))
{
if( rotated ) Matrix4x4_CreateFromEntity( RI.objectMatrix, e->angles, e->origin, 1.0f );
else Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, 1.0f );
}
else Matrix4x4_LoadIdentity( RI.objectMatrix );
VectorSubtract( RI.cullorigin, e->origin, tr.modelorg );
e->visframe = tr.framecount; // visible
if( rotated )
{
vec3_t temp;
VectorCopy( tr.modelorg, temp );
Matrix4x4_VectorITransform( RI.objectMatrix, temp, tr.modelorg );
}
clipFlags = 0;
}
psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
{
if(!( psurf->flags & SURF_MIRROR ))
continue;
if( R_CullSurface( psurf, clipFlags ))
continue;
extrasurf = SURF_INFO( psurf, RI.currentmodel );
extrasurf->mirrorchain = tr.mirror_entities[tr.num_mirror_entities].chain;
tr.mirror_entities[tr.num_mirror_entities].chain = extrasurf;
}
// store new mirror entity
if( !static_entity && tr.mirror_entities[tr.num_mirror_entities].chain != NULL )
{
tr.mirror_entities[tr.num_mirror_entities].ent = RI.currententity;
tr.num_mirror_entities++;
}
}
/*
=================
R_CheckEntitiesOnList
Check all bmodels for mirror surfaces
=================
*/
void R_CheckEntitiesOnList( void )
{
int i;
// check static entities
for( i = 0; i < tr.num_static_entities; i++ )
{
RI.currententity = tr.static_entities[i];
RI.currentmodel = RI.currententity->model;
ASSERT( RI.currententity != NULL );
ASSERT( RI.currententity->model != NULL );
switch( RI.currentmodel->type )
{
case mod_brush:
R_FindBmodelMirrors( RI.currententity, true );
break;
}
}
// world or static entities has mirror surfaces
if( tr.mirror_entities[0].chain != NULL )
{
tr.mirror_entities[0].ent = clgame.entities;
tr.num_mirror_entities++;
}
// check solid entities
for( i = 0; i < tr.num_solid_entities; i++ )
{
RI.currententity = tr.solid_entities[i];
RI.currentmodel = RI.currententity->model;
ASSERT( RI.currententity != NULL );
ASSERT( RI.currententity->model != NULL );
switch( RI.currentmodel->type )
{
case mod_brush:
R_FindBmodelMirrors( RI.currententity, false );
break;
}
}
// check translucent entities
for( i = 0; i < tr.num_trans_entities; i++ )
{
RI.currententity = tr.trans_entities[i];
RI.currentmodel = RI.currententity->model;
ASSERT( RI.currententity != NULL );
ASSERT( RI.currententity->model != NULL );
switch( RI.currentmodel->type )
{
case mod_brush:
R_FindBmodelMirrors( RI.currententity, false );
break;
}
}
}
/*
================
R_FindMirrors
Build mirror chains for this frame
================
*/
void R_FindMirrors( const ref_params_t *fd )
{
if( !world.has_mirrors || RI.drawOrtho || !RI.drawWorld || RI.refdef.onlyClientDraw || !cl.worldmodel )
return;
RI.refdef = *fd;
// build the transformation matrix for the given view angles
VectorCopy( RI.refdef.vieworg, RI.vieworg );
AngleVectors( RI.refdef.viewangles, RI.vforward, RI.vright, RI.vup );
R_FindViewLeaf();
R_SetupFrustum();
R_MarkLeaves ();
VectorCopy( RI.cullorigin, tr.modelorg );
RI.currententity = clgame.entities;
RI.currentmodel = RI.currententity->model;
R_RecursiveMirrorNode( cl.worldmodel->nodes, RI.clipFlags );
R_CheckEntitiesOnList();
}

View File

@ -66,8 +66,8 @@ void R_RemoveEfrags( cl_entity_t *ent )
ef = ef->entnext;
// put it on the free list
old->entnext = cl.free_efrags;
cl.free_efrags = old;
old->entnext = clgame.free_efrags;
clgame.free_efrags = old;
}
ent->efrag = NULL;
}
@ -96,14 +96,14 @@ static void R_SplitEntityOnNode( mnode_t *node )
leaf = (mleaf_t *)node;
// grab an efrag off the free list
ef = cl.free_efrags;
ef = clgame.free_efrags;
if( !ef )
{
MsgDev( D_ERROR, "too many efrags!\n" );
return; // no free fragments...
}
cl.free_efrags = cl.free_efrags->entnext;
clgame.free_efrags = clgame.free_efrags->entnext;
ef->entity = r_addent;
// add the entity link
@ -134,8 +134,6 @@ static void R_SplitEntityOnNode( mnode_t *node )
if( sides & 2 ) R_SplitEntityOnNode( node->children[1] );
}
/*
===========
R_AddEfrags
@ -162,7 +160,6 @@ void R_AddEfrags( cl_entity_t *ent )
ent->topnode = r_pefragtopnode;
}
/*
================
R_StoreEfrags

View File

@ -254,9 +254,9 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3
{
uint scale = RI.lightstylevalue[surf->styles[map]];
r_pointColor[0] += lm->r * scale;
r_pointColor[1] += lm->g * scale;
r_pointColor[2] += lm->b * scale;
r_pointColor[0] += TextureToTexGamma( lm->r ) * scale;
r_pointColor[1] += TextureToTexGamma( lm->g ) * scale;
r_pointColor[2] += TextureToTexGamma( lm->b ) * scale;
lm += size; // skip to next lightmap
}
@ -293,9 +293,9 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
// set to full bright if no light data
if( !cl.worldmodel || !cl.worldmodel->lightdata )
{
ambientLight->r = RI.refdef.movevars->skycolor_r;
ambientLight->g = RI.refdef.movevars->skycolor_g;
ambientLight->b = RI.refdef.movevars->skycolor_b;
ambientLight->r = TextureToTexGamma( RI.refdef.movevars->skycolor_r );
ambientLight->g = TextureToTexGamma( RI.refdef.movevars->skycolor_g );
ambientLight->b = TextureToTexGamma( RI.refdef.movevars->skycolor_b );
return;
}
@ -398,9 +398,9 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
continue;
add = 1.0f - (dist / ( dl->radius + radius ));
r_pointColor[0] += dl->color.r * add;
r_pointColor[1] += dl->color.g * add;
r_pointColor[2] += dl->color.b * add;
r_pointColor[0] += TextureToTexGamma( dl->color.r ) * add;
r_pointColor[1] += TextureToTexGamma( dl->color.g ) * add;
r_pointColor[2] += TextureToTexGamma( dl->color.b ) * add;
total++;
}

View File

@ -202,9 +202,7 @@ qboolean R_WorldToScreen( const vec3_t point, vec3_t screen )
screen[1] = worldToScreen[1][0] * point[0] + worldToScreen[1][1] * point[1] + worldToScreen[1][2] * point[2] + worldToScreen[1][3];
// z = worldToScreen[2][0] * point[0] + worldToScreen[2][1] * point[1] + worldToScreen[2][2] * point[2] + worldToScreen[2][3];
w = worldToScreen[3][0] * point[0] + worldToScreen[3][1] * point[1] + worldToScreen[3][2] * point[2] + worldToScreen[3][3];
// Just so we have something valid here
screen[2] = 0.0f;
screen[2] = 0.0f; // just so we have something valid here
if( w < 0.001f )
{
@ -224,7 +222,24 @@ qboolean R_WorldToScreen( const vec3_t point, vec3_t screen )
void R_ScreenToWorld( const vec3_t screen, vec3_t point )
{
// TODO: implement
matrix4x4 screenToWorld;
vec3_t temp;
float w;
if( !point || !screen )
return;
// FIXME: does we need a full invert here?
Matrix4x4_Invert_Simple( screenToWorld, RI.worldviewProjectionMatrix );
temp[0] = 2.0f * (screen[0] - RI.viewport[0]) / RI.viewport[2] - 1;
temp[1] = -2.0f * (screen[1] - RI.viewport[1]) / RI.viewport[3] + 1;
temp[2] = 0.0f; // just so we have something valid here
point[0] = temp[0] * screenToWorld[0][0] + temp[1] * screenToWorld[0][1] + temp[2] * screenToWorld[0][2] + screenToWorld[0][3];
point[1] = temp[0] * screenToWorld[1][0] + temp[1] * screenToWorld[1][1] + temp[2] * screenToWorld[1][2] + screenToWorld[1][3];
point[2] = temp[0] * screenToWorld[2][0] + temp[1] * screenToWorld[2][1] + temp[2] * screenToWorld[2][2] + screenToWorld[2][3];
w = temp[0] * screenToWorld[3][0] + temp[1] * screenToWorld[3][1] + temp[2] * screenToWorld[3][2] + screenToWorld[3][3];
if( w ) VectorScale( point, ( 1.0f / w ), point );
}
/*
@ -541,7 +556,7 @@ static void R_SetupFrustumOrtho( void )
R_SetupFrustum
===============
*/
static void R_SetupFrustum( void )
void R_SetupFrustum( void )
{
vec3_t farPoint;
int i;
@ -644,6 +659,8 @@ void R_LoadIdentity( void )
Matrix4x4_LoadIdentity( RI.objectMatrix );
Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix );
pglMatrixMode( GL_MODELVIEW );
GL_LoadMatrix( RI.modelviewMatrix );
tr.modelviewIdentity = true;
}
@ -669,6 +686,7 @@ void R_RotateForEntity( cl_entity_t *e )
Matrix4x4_CreateFromEntity( RI.objectMatrix, e->angles, e->origin, scale );
Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix );
pglMatrixMode( GL_MODELVIEW );
GL_LoadMatrix( RI.modelviewMatrix );
tr.modelviewIdentity = false;
}
@ -694,10 +712,49 @@ void R_TranslateForEntity( cl_entity_t *e )
Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, scale );
Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix );
pglMatrixMode( GL_MODELVIEW );
GL_LoadMatrix( RI.modelviewMatrix );
tr.modelviewIdentity = false;
}
/*
===============
R_FindViewLeaf
===============
*/
void R_FindViewLeaf( void )
{
float height;
mleaf_t *leaf;
vec3_t tmp;
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
leaf = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );
r_viewleaf2 = r_viewleaf = leaf;
height = RI.waveHeight ? RI.waveHeight : 16;
// check above and below so crossing solid water doesn't draw wrong
if( leaf->contents == CONTENTS_EMPTY )
{
// look down a bit
VectorCopy( RI.pvsorigin, tmp );
tmp[2] -= height;
leaf = Mod_PointInLeaf( tmp, cl.worldmodel->nodes );
if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 ))
r_viewleaf2 = leaf;
}
else
{
// look up a bit
VectorCopy( RI.pvsorigin, tmp );
tmp[2] += height;
leaf = Mod_PointInLeaf( tmp, cl.worldmodel->nodes );
if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 ))
r_viewleaf2 = leaf;
}
}
/*
===============
R_SetupFrame
@ -721,41 +778,11 @@ static void R_SetupFrame( void )
// current viewleaf
if( RI.drawWorld )
{
float height;
mleaf_t *leaf;
vec3_t tmp;
RI.waveHeight = RI.refdef.movevars->waveHeight * 2.0f; // set global waveheight
RI.isSkyVisible = false; // unknown at this moment
if(!( RI.params & RP_OLDVIEWLEAF ))
{
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
leaf = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );
r_viewleaf2 = r_viewleaf = leaf;
height = RI.waveHeight ? RI.waveHeight : 16;
// check above and below so crossing solid water doesn't draw wrong
if( leaf->contents == CONTENTS_EMPTY )
{
// look down a bit
VectorCopy( RI.pvsorigin, tmp );
tmp[2] -= height;
leaf = Mod_PointInLeaf( tmp, cl.worldmodel->nodes );
if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 ))
r_viewleaf2 = leaf;
}
else
{
// look up a bit
VectorCopy( RI.pvsorigin, tmp );
tmp[2] += height;
leaf = Mod_PointInLeaf( tmp, cl.worldmodel->nodes );
if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 ))
r_viewleaf2 = leaf;
}
}
R_FindViewLeaf();
}
}
@ -847,7 +874,7 @@ static void R_CheckFog( void )
if( RI.refdef.waterlevel < 2 || !RI.drawWorld || !r_viewleaf )
return;
ent = CL_GetWaterEntity( cl.refdef.vieworg );
ent = CL_GetWaterEntity( RI.vieworg );
if( ent && ent->model && ent->model->type == mod_brush && ent->curstate.skin < 0 )
cnt = ent->curstate.skin;
else cnt = r_viewleaf->contents;
@ -1092,8 +1119,16 @@ void R_BeginFrame( qboolean clearScene )
// update gamma
if( vid_gamma->modified )
{
vid_gamma->modified = false;
GL_UpdateGammaRamp();
if( glConfig.deviceSupportsGamma )
{
GL_UpdateGammaRamp();
vid_gamma->modified = false;
}
else
{
BuildGammaTable( vid_gamma->value, vid_texgamma->value );
GL_RebuildLightmaps();
}
}
R_Set2DMode( true );
@ -1123,6 +1158,7 @@ void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld )
return;
if( drawWorld ) r_lastRefdef = *fd;
GL_BackendStartFrame();
RI.params = RP_NONE;
RI.farClip = 0;
@ -1131,8 +1167,6 @@ void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld )
RI.thirdPerson = cl.thirdperson;
RI.drawOrtho = gl_overview->integer;
GL_BackendStartFrame();
// adjust field of view for widescreen
if( glState.wideScreen && r_adjust_fov->integer )
V_AdjustFov( &RI.refdef.fov_x, &RI.refdef.fov_y, glState.width, glState.height, false );
@ -1156,10 +1190,15 @@ void R_RenderFrame( const ref_params_t *fd, qboolean drawWorld )
if( gl_finish->integer && drawWorld )
pglFinish();
if( gl_allow_mirrors->integer )
{
// render mirrors
R_FindMirrors( fd );
R_DrawMirrors ();
}
R_RenderScene( fd );
#ifdef MIRROR_TEST
R_DrawMirrors ();
#endif
GL_BackendEndFrame();
}

View File

@ -50,6 +50,7 @@ static const dmaterial_t detail_table[] =
{ "car", "dt_metal%i", 'M', 1, 2 },
{ "circuit", "dt_metal%i", 'M', 1, 2 },
{ "steel", "dt_ssteel1", 'M', 0, 0 },
{ "reflect", "dt_ssteel1", 'G', 0, 0 },
{ "dirt", "dt_ground%i", 'D', 1, 5 }, // dirt
{ "drt", "dt_ground%i", 'D', 1, 5 },
{ "out", "dt_ground%i", 'D', 1, 5 },

View File

@ -356,7 +356,7 @@ static void CL_BulletTracerDraw( particle_t *p, float frametime )
// setup our info for drawing the line
VectorSubtract( vecEnd, vecStart, lineDir );
VectorSubtract( vecEnd, cl.refdef.vieworg, viewDir );
VectorSubtract( vecEnd, RI.vieworg, viewDir );
CrossProduct( lineDir, viewDir, cross );
VectorNormalize( cross );
@ -490,16 +490,16 @@ void CL_UpdateParticle( particle_t *p, float ft )
#if 0
// HACKHACK a scale up to keep particles from disappearing
size += (p->org[0] - cl.refdef.vieworg[0]) * cl.refdef.forward[0];
size += (p->org[1] - cl.refdef.vieworg[1]) * cl.refdef.forward[1];
size += (p->org[2] - cl.refdef.vieworg[2]) * cl.refdef.forward[2];
size += (p->org[0] - RI.vieworg[0]) * RI.vforward[0];
size += (p->org[1] - RI.vieworg[1]) * RI.vforward[1];
size += (p->org[2] - RI.vieworg[2]) * RI.vforward[2];
if( size < 20.0f ) size = 1.0f;
else size = 1.0f + size * 0.004f;
#endif
// scale the axes by radius
VectorScale( cl.refdef.right, size, right );
VectorScale( cl.refdef.up, size, up );
VectorScale( RI.vright, size, right );
VectorScale( RI.vup, size, up );
p->color = bound( 0, p->color, 255 );
VectorSet( color, clgame.palette[p->color][0], clgame.palette[p->color][1], clgame.palette[p->color][2] );
@ -1328,8 +1328,8 @@ qboolean CL_TracerComputeVerts( const vec3_t start, const vec3_t delta, float wi
VectorNormalize( tmp );
// build point along noraml line (normal is -y, x)
VectorScale( cl.refdef.up, tmp[0], normal );
VectorScale( cl.refdef.right, -tmp[1], tmp2 );
VectorScale( RI.vup, tmp[0], normal );
VectorScale( RI.vright, -tmp[1], tmp2 );
VectorSubtract( normal, tmp2, normal );
// compute four vertexes

View File

@ -28,9 +28,6 @@ typedef struct
byte lightmap_buffer[BLOCK_WIDTH*BLOCK_HEIGHT*4];
} gllightmapstate_t;
static vec3_t modelorg; // relative to viewpoint
static vec3_t modelmins;
static vec3_t modelmaxs;
static vec2_t world_orthocenter;
static vec2_t world_orthohalf;
static byte visbytes[MAX_MAP_LEAFS/8];
@ -446,9 +443,9 @@ void R_AddDynamicLights( msurface_t *surf )
if( dist < minlight )
{
bl[0] += ( rad - dist ) * dl->color.r;
bl[1] += ( rad - dist ) * dl->color.g;
bl[2] += ( rad - dist ) * dl->color.b;
bl[0] += ( rad - dist ) * TextureToTexGamma( dl->color.r );
bl[1] += ( rad - dist ) * TextureToTexGamma( dl->color.g );
bl[2] += ( rad - dist ) * TextureToTexGamma( dl->color.b );
}
}
}
@ -592,9 +589,9 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride )
for( i = 0, bl = r_blocklights; i < size; i++, bl += 3, lm++ )
{
bl[0] += lm->r * scale;
bl[1] += lm->g * scale;
bl[2] += lm->b * scale;
bl[0] += TextureToTexGamma( lm->r ) * scale;
bl[1] += TextureToTexGamma( lm->g ) * scale;
bl[2] += TextureToTexGamma( lm->b ) * scale;
}
}
@ -974,6 +971,7 @@ void R_RenderBrushPoly( msurface_t *fa )
texture_t *t;
int maps;
qboolean is_dynamic = false;
qboolean is_mirror = false;
if( RI.currententity == clgame.entities )
r_stats.c_world_polys++;
@ -990,7 +988,20 @@ void R_RenderBrushPoly( msurface_t *fa )
}
t = R_TextureAnimation( fa->texinfo->texture, fa - RI.currententity->model->surfaces );
GL_MBind( t->gl_texturenum );
if( RP_NORMALPASS() && fa->flags & SURF_MIRROR )
{
if( SURF_INFO( fa, RI.currentmodel )->mirrortexturenum )
{
GL_MBind( SURF_INFO( fa, RI.currentmodel )->mirrortexturenum );
is_mirror = true;
}
else GL_MBind( t->gl_texturenum ); // dummy
// DEBUG: reset the mirror texture after drawing
SURF_INFO( fa, RI.currentmodel )->mirrortexturenum = 0;
}
else GL_MBind( t->gl_texturenum );
if( fa->flags & SURF_DRAWTURB )
{
@ -1015,9 +1026,15 @@ void R_RenderBrushPoly( msurface_t *fa )
draw_details = true;
}
if( is_mirror ) R_BeginDrawMirror( fa );
DrawGLPoly( fa->polys, 0.0f, 0.0f );
if( is_mirror ) R_EndDrawMirror();
DrawSurfaceDecals( fa );
// NOTE: draw mirror through in mirror show dummy lightmapped texture
if( fa->flags & SURF_MIRROR && RP_NORMALPASS() && r_lighting_extended->integer < 2 )
return; // no lightmaps for mirror
// check for lightmap modification
for( maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++ )
{
@ -1086,13 +1103,6 @@ void R_DrawTextureChains( void )
RI.currententity = clgame.entities;
RI.currentmodel = RI.currententity->model;
// world has mirrors!
if( RP_NORMALPASS() && tr.mirror_entities[0].chain != NULL )
{
tr.mirror_entities[0].ent = clgame.entities;
tr.num_mirror_entities++;
}
// clip skybox surfaces
for( s = skychain; s != NULL; s = s->texturechain )
R_AddSkyBoxSurface( s );
@ -1141,8 +1151,7 @@ void R_DrawWaterSurfaces( void )
return;
// go back to the world matrix
pglMatrixMode( GL_MODELVIEW );
GL_LoadMatrix( RI.worldviewMatrix );
R_LoadIdentity();
pglEnable( GL_BLEND );
pglDepthMask( GL_FALSE );
@ -1214,79 +1223,6 @@ static int R_SurfaceCompare( const msurface_t **a, const msurface_t **b )
return 0;
}
/*
=================
R_CullSurface
cull invisible surfaces
=================
*/
static _inline qboolean R_CullSurface( msurface_t *surf, uint clipflags )
{
mextrasurf_t *info;
if( !surf || !surf->texinfo || !surf->texinfo->texture )
return true;
if( surf->flags & SURF_WATERCSG && !( RI.currententity->curstate.effects & EF_NOWATERCSG ))
return true;
if( surf->flags & SURF_NOCULL )
return false;
if( r_nocull->integer )
return false;
// world surfaces can be culled by vis frame too
if( RI.currententity == clgame.entities && surf->visframe != tr.framecount )
return true;
if( r_faceplanecull->integer && glState.faceCull != 0 )
{
if(!(surf->flags & SURF_DRAWTURB) || !RI.currentWaveHeight )
{
if( !VectorIsNull( surf->plane->normal ))
{
float dist;
if( RI.drawOrtho ) dist = surf->plane->normal[2];
else dist = PlaneDiff( modelorg, surf->plane );
if( glState.faceCull == GL_FRONT || ( RI.params & RP_MIRRORVIEW ))
{
if( surf->flags & SURF_PLANEBACK )
{
if( dist >= -BACKFACE_EPSILON )
return true; // wrong side
}
else
{
if( dist <= BACKFACE_EPSILON )
return true; // wrong side
}
}
else if( glState.faceCull == GL_BACK )
{
if( surf->flags & SURF_PLANEBACK )
{
if( dist <= BACKFACE_EPSILON )
return true; // wrong side
}
else
{
if( dist >= -BACKFACE_EPSILON )
return true; // wrong side
}
}
}
}
}
info = SURF_INFO( surf, RI.currentmodel );
return ( clipflags && R_CullBox( info->mins, info->maxs, clipflags ));
}
/*
=================
R_DrawBrushModel
@ -1332,14 +1268,14 @@ void R_DrawBrushModel( cl_entity_t *e )
if( rotated ) R_RotateForEntity( e );
else R_TranslateForEntity( e );
VectorSubtract( RI.cullorigin, e->origin, modelorg );
VectorSubtract( RI.cullorigin, e->origin, tr.modelorg );
e->visframe = tr.framecount; // visible
if( rotated )
{
vec3_t temp;
VectorCopy( modelorg, temp );
Matrix4x4_VectorITransform( RI.objectMatrix, temp, modelorg );
VectorCopy( tr.modelorg, temp );
Matrix4x4_VectorITransform( RI.objectMatrix, temp, tr.modelorg );
}
// calculate dynamic lighting for bmodel
@ -1389,12 +1325,7 @@ void R_DrawBrushModel( cl_entity_t *e )
if( R_CullSurface( psurf, 0 ))
continue;
if( RP_NORMALPASS() && psurf->flags & SURF_MIRROR )
{
psurf->texturechain = tr.mirror_entities[tr.num_mirror_entities].chain;
tr.mirror_entities[tr.num_mirror_entities].chain = psurf;
}
else if( need_sort )
if( need_sort )
{
world.draw_surfaces[num_sorted] = psurf;
num_sorted++;
@ -1407,13 +1338,6 @@ void R_DrawBrushModel( cl_entity_t *e )
}
}
// store new mirror entity
if( RP_NORMALPASS() && tr.mirror_entities[tr.num_mirror_entities].chain != NULL )
{
tr.mirror_entities[tr.num_mirror_entities].ent = RI.currententity;
tr.num_mirror_entities++;
}
if( need_sort )
qsort( world.draw_surfaces, num_sorted, sizeof( msurface_t* ), R_SurfaceCompare );
@ -1460,16 +1384,17 @@ void R_DrawStaticModel( cl_entity_t *e )
psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
{
if( R_CullSurface( psurf, 0 ))
if( R_CullSurface( psurf, RI.clipFlags ))
continue;
if( RP_NORMALPASS() && psurf->flags & SURF_MIRROR )
if( psurf->flags & SURF_DRAWSKY && !world.sky_sphere )
{
psurf->texturechain = tr.mirror_entities[0].chain;
tr.mirror_entities[0].chain = psurf;
// make sky chain to right clip the skybox
psurf->texturechain = skychain;
skychain = psurf;
}
else
{
{
psurf->texturechain = psurf->texinfo->texture->texturechain;
psurf->texinfo->texture->texturechain = psurf;
}
@ -1490,9 +1415,6 @@ void R_DrawStaticBrushes( void )
// draw static entities
for( i = 0; i < tr.num_static_entities; i++ )
{
if( RI.refdef.onlyClientDraw )
break;
RI.currententity = tr.static_entities[i];
RI.currentmodel = RI.currententity->model;
@ -1511,123 +1433,6 @@ void R_DrawStaticBrushes( void )
}
}
/*
=============================================================
MIRROR RENDERING
=============================================================
*/
void R_PlaneForMirror( msurface_t *surf, mplane_t *out )
{
cl_entity_t *ent;
ASSERT( out != NULL );
ent = RI.currententity;
// setup mirror plane
*out = *surf->plane;
if( surf->flags & SURF_PLANEBACK )
{
VectorNegate( out->normal, out->normal );
}
if( !VectorIsNull( ent->angles ))
R_RotateForEntity( ent );
else R_TranslateForEntity( ent );
// transform mirror plane by entity matrix
if( !tr.modelviewIdentity )
{
mplane_t tmp;
tmp = *out;
Matrix4x4_TransformPositivePlane( RI.objectMatrix, tmp.normal, tmp.dist, out->normal, &out->dist );
}
}
void R_DrawMirrors( void )
{
ref_instance_t oldRI;
mplane_t plane;
msurface_t *surf, *mirrorchain;
vec3_t forward, right, up;
vec3_t origin, angles;
int i;
float d;
if( !tr.num_mirror_entities ) return; // mo mirrors for this frame
oldRI = RI; // make refinst backup
for( i = 0; i < tr.num_mirror_entities; i++ )
{
mirrorchain = tr.mirror_entities[i].chain;
for( surf = mirrorchain; surf != NULL; surf = surf->texturechain )
{
RI.currententity = tr.mirror_entities[i].ent;
RI.currentmodel = RI.currententity->model;
ASSERT( RI.currententity != NULL );
ASSERT( RI.currentmodel != NULL );
R_PlaneForMirror( surf, &plane );
d = -2.0f * ( DotProduct( RI.vieworg, plane.normal ) - plane.dist );
VectorMA( RI.vieworg, d, plane.normal, origin );
d = -2.0f * DotProduct( RI.vforward, plane.normal );
VectorMA( RI.vforward, d, plane.normal, forward );
VectorNormalize( forward );
d = -2.0f * DotProduct( RI.vright, plane.normal );
VectorMA( RI.vright, d, plane.normal, right );
VectorNormalize( right );
d = -2.0f * DotProduct( RI.vup, plane.normal );
VectorMA( RI.vup, d, plane.normal, up );
VectorNormalize( up );
VectorsAngles( forward, right, up, angles );
angles[ROLL] = -angles[ROLL];
RI.params = RP_MIRRORVIEW|RP_FLIPFRONTFACE|RP_CLIPPLANE;
if( r_viewleaf ) RI.params |= RP_OLDVIEWLEAF;
RI.clipPlane = plane;
RI.clipFlags |= ( 1<<5 );
RI.frustum[5] = plane;
RI.frustum[5].signbits = SignbitsForPlane( RI.frustum[5].normal );
RI.frustum[5].type = PLANE_NONAXIAL;
RI.refdef.viewangles[0] = anglemod( angles[0] );
RI.refdef.viewangles[1] = anglemod( angles[1] );
RI.refdef.viewangles[2] = anglemod( angles[2] );
VectorCopy( origin, RI.refdef.vieworg );
VectorCopy( origin, RI.pvsorigin );
VectorCopy( origin, RI.cullorigin );
R_RenderScene( &RI.refdef );
if( !( RI.params & RP_OLDVIEWLEAF ))
r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame
RI = oldRI; // restore ref instance
// TODO: draw mirror surface here
}
tr.mirror_entities[i].chain = NULL; // done
tr.mirror_entities[i].ent = NULL;
}
tr.num_mirror_entities = 0;
}
/*
=============================================================
@ -1696,7 +1501,7 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
dot = PlaneDiff( modelorg, node->plane );
dot = PlaneDiff( tr.modelorg, node->plane );
side = (dot >= 0) ? 0 : 1;
// recurse down the children, front side first
@ -1714,11 +1519,6 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
surf->texturechain = skychain;
skychain = surf;
}
else if( RP_NORMALPASS() && surf->flags & SURF_MIRROR )
{
surf->texturechain = tr.mirror_entities[0].chain;
tr.mirror_entities[0].chain = surf;
}
else
{
surf->texturechain = surf->texinfo->texture->texturechain;
@ -1931,7 +1731,7 @@ void R_DrawWorld( void )
if( !RI.drawWorld || RI.refdef.onlyClientDraw )
return;
VectorCopy( RI.cullorigin, modelorg );
VectorCopy( RI.cullorigin, tr.modelorg );
Q_memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces ));
Q_memset( fullbright_polys, 0, sizeof( fullbright_polys ));
Q_memset( detail_polys, 0, sizeof( detail_polys ));
@ -2079,6 +1879,51 @@ void GL_CreateSurfaceLightmap( msurface_t *surf )
R_BuildLightMap( surf, base, BLOCK_WIDTH * 4 );
}
/*
==================
GL_RebuildLightmaps
Rebuilds the lightmap texture
when gamma is changed
==================
*/
void GL_RebuildLightmaps( void )
{
int i, j;
model_t *m;
if( !cl.worldmodel ) return; // wait for worldmodel
vid_gamma->modified = false;
// release old lightmaps
for( i = 0; i < MAX_LIGHTMAPS; i++ )
{
if( !tr.lightmapTextures[i] ) break;
GL_FreeTexture( tr.lightmapTextures[i] );
}
Q_memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
gl_lms.current_lightmap_texture = 0;
// setup all the lightstyles
R_AnimateLight();
LM_InitBlock();
for( i = 1; i < MAX_MODELS; i++ )
{
if(( m = Mod_Handle( i )) == NULL )
continue;
if( m->name[0] == '*' || m->type != mod_brush )
continue;
for( j = 0; j < m->numsurfaces; j++ )
GL_CreateSurfaceLightmap( m->surfaces + j );
}
LM_UploadBlock( false );
}
/*
==================
GL_BuildLightmaps
@ -2099,14 +1944,24 @@ void GL_BuildLightmaps( void )
GL_FreeTexture( tr.lightmapTextures[i] );
}
// release old mirror textures
for( i = 0; i < MAX_MIRRORS; i++ )
{
if( !tr.mirrorTextures[i] ) break;
GL_FreeTexture( tr.mirrorTextures[i] );
}
Q_memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
Q_memset( tr.mirror_entities, 0, sizeof( tr.mirror_entities ));
Q_memset( tr.mirrorTextures, 0, sizeof( tr.mirrorTextures ));
Q_memset( visbytes, 0x00, sizeof( visbytes ));
skychain = NULL;
tr.framecount = tr.visframecount = 1; // no dlight cache
gl_lms.current_lightmap_texture = 0;
tr.num_mirror_entities = 0;
tr.num_mirrors_used = 0;
// setup all the lightstyles
R_AnimateLight();

View File

@ -287,7 +287,7 @@ void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean
if( h < MAPSPRITE_SIZE ) h = MAPSPRITE_SIZE;
// resample image if needed
Image_Process( &pix, w, h, IMAGE_FORCE_RGBA|IMAGE_RESAMPLE );
Image_Process( &pix, w, h, 0.0f, IMAGE_FORCE_RGBA|IMAGE_RESAMPLE );
w = h = MAPSPRITE_SIZE;

View File

@ -252,6 +252,7 @@ static qboolean R_StudioComputeBBox( cl_entity_t *e, vec3_t bbox[8] )
p1[1] = ( i & 2 ) ? tmp_mins[1] : tmp_maxs[1];
p1[2] = ( i & 4 ) ? tmp_mins[2] : tmp_maxs[2];
// rotate by YAW
p2[0] = DotProduct( p1, vectors[0] );
p2[1] = DotProduct( p1, vectors[1] );
p2[2] = DotProduct( p1, vectors[2] );
@ -2412,7 +2413,7 @@ R_StudioSetChromeOrigin
*/
void R_StudioSetChromeOrigin( void )
{
VectorNegate( cl.refdef.vieworg, g_chrome_origin );
VectorNegate( RI.vieworg, g_chrome_origin );
}
/*
@ -2998,6 +2999,7 @@ R_DrawStudioModel
void R_DrawStudioModelInternal( cl_entity_t *e, qboolean follow_entity )
{
int i, flags, result;
float prevFrame;
if( RI.params & RP_ENVVIEW )
return;
@ -3017,6 +3019,8 @@ void R_DrawStudioModelInternal( cl_entity_t *e, qboolean follow_entity )
m_fDoInterp = (e->curstate.effects & EF_NOINTERP) ? false : true;
else m_fDoInterp = false;
prevFrame = e->latched.prevframe;
// prevent to crash some mods like HLFX in menu Customize
if( !RI.drawWorld && !r_customdraw_playermodel->integer )
{
@ -3032,6 +3036,9 @@ void R_DrawStudioModelInternal( cl_entity_t *e, qboolean follow_entity )
else result = pStudioDraw->StudioDrawModel( flags );
}
// old frame must be restored
if( !RP_NORMALPASS( )) e->latched.prevframe = prevFrame;
if( !result || follow_entity ) return;
// NOTE: we must draw all followed entities
@ -3067,7 +3074,7 @@ R_RunViewmodelEvents
*/
void R_RunViewmodelEvents( void )
{
if( cl.refdef.nextView || cl.thirdperson || RI.params & RP_ENVVIEW )
if( cl.refdef.nextView || cl.thirdperson || RI.params & RP_NONVIEWERREF )
return;
if( !Mod_Extradata( clgame.viewent.model ))
@ -3097,7 +3104,7 @@ void R_DrawViewModel( void )
if( cl.thirdperson || cl.refdef.health <= 0 || cl.refdef.viewentity != ( cl.playernum + 1 ))
return;
if( RI.params & RP_ENVVIEW )
if( RI.params & RP_NONVIEWERREF )
return;
if( !Mod_Extradata( clgame.viewent.model ))

View File

@ -39,6 +39,7 @@ convar_t *gl_showtextures;
convar_t *gl_swapInterval;
convar_t *gl_check_errors;
convar_t *gl_allow_static;
convar_t *gl_allow_mirrors;
convar_t *gl_texturemode;
convar_t *gl_wireframe;
convar_t *gl_round_down;
@ -78,6 +79,7 @@ convar_t *r_fastsky;
convar_t *vid_displayfrequency;
convar_t *vid_fullscreen;
convar_t *vid_gamma;
convar_t *vid_texgamma;
convar_t *vid_mode;
byte *r_temppool;
@ -549,7 +551,7 @@ void GL_BuildGammaTable( void )
int i, v;
double invGamma, div;
invGamma = 1.0 / bound( 0.5, vid_gamma->value, 3.0 );
invGamma = 1.0 / bound( 0.5, vid_gamma->value, 2.3 );
div = (double) 1.0 / 255.5;
Q_memcpy( glState.gammaRamp, glState.stateRamp, sizeof( glState.gammaRamp ));
@ -570,7 +572,6 @@ GL_UpdateGammaRamp
*/
void GL_UpdateGammaRamp( void )
{
if( gl_ignorehwgamma->integer ) return;
if( !glConfig.deviceSupportsGamma ) return;
GL_BuildGammaTable();
@ -737,11 +738,25 @@ void VID_StartupGamma( void )
size_t gamma_size;
byte *savedGamma;
glConfig.deviceSupportsGamma = GetDeviceGammaRamp( glw_state.hDC, glState.stateRamp );
if( !glConfig.deviceSupportsGamma )
{
// force to set cvar
Cvar_FullSet( "gl_ignorehwgamma", "1", CVAR_GLCONFIG );
}
if( gl_ignorehwgamma->integer )
{
glConfig.deviceSupportsGamma = false; // even if supported!
BuildGammaTable( vid_gamma->value, vid_texgamma->value );
MsgDev( D_NOTE, "VID_StartupGamma: software gamma initialized\n" );
return;
}
// init gamma ramp
Q_memset( glState.stateRamp, 0, sizeof( glState.stateRamp ));
glConfig.deviceSupportsGamma = GetDeviceGammaRamp( glw_state.hDC, glState.stateRamp );
// share this extension so engine can grab them
GL_SetExtension( GL_HARDWARE_GAMMA_CONTROL, glConfig.deviceSupportsGamma );
@ -811,7 +826,7 @@ void VID_StartupGamma( void )
void VID_RestoreGamma( void )
{
if( !glw_state.hDC ) return;
if( !glw_state.hDC || !glConfig.deviceSupportsGamma ) return;
SetDeviceGammaRamp( glw_state.hDC, glState.stateRamp );
}
@ -1414,7 +1429,7 @@ void GL_InitCommands( void )
gl_picmip = Cvar_Get( "gl_picmip", "0", CVAR_GLCONFIG, "reduces resolution of textures by powers of 2" );
gl_skymip = Cvar_Get( "gl_skymip", "0", CVAR_GLCONFIG, "reduces resolution of skybox textures by powers of 2" );
gl_ignorehwgamma = Cvar_Get( "gl_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" );
gl_ignorehwgamma = Cvar_Get( "gl_ignorehwgamma", "0", CVAR_GLCONFIG, "ignore hardware gamma" );
gl_allow_software = Cvar_Get( "gl_allow_software", "0", CVAR_ARCHIVE, "allow OpenGL software emulation" );
gl_alphabits = Cvar_Get( "gl_alphabits", "8", CVAR_GLCONFIG, "pixelformat alpha bits (0 - auto)" );
gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, "texture filter" );
@ -1429,6 +1444,7 @@ void GL_InitCommands( void )
gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_GLCONFIG, "compress textures to safe video memory" );
gl_luminance_textures = Cvar_Get( "gl_luminance_textures", "0", CVAR_GLCONFIG, "force all textures to luminance" );
gl_allow_static = Cvar_Get( "gl_allow_static", "1", CVAR_ARCHIVE, "force to drawing non-moveable brushes as part of world (save FPS)" );
gl_allow_mirrors = Cvar_Get( "gl_allow_mirrors", "1", CVAR_ARCHIVE, "allow to draw mirror surfaces" );
gl_showtextures = Cvar_Get( "r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures (type values from 1 to 9)" );
gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE, "use glFinish instead of glFlush" );
gl_clear = Cvar_Get( "gl_clear", "0", CVAR_ARCHIVE, "clearing screen after each frame" );
@ -1443,6 +1459,7 @@ void GL_InitCommands( void )
gl_swapInterval->modified = true;
vid_gamma = Cvar_Get( "gamma", "1.0", CVAR_ARCHIVE, "gamma amount" );
vid_texgamma = Cvar_Get( "texgamma", "2.2", CVAR_GLCONFIG, "texgamma amount (default Half-Life artwork gamma)" );
vid_mode = Cvar_Get( "vid_mode", VID_DEFAULTMODE, CVAR_RENDERINFO, "display resolution mode" );
vid_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO, "set in 1 to enable fullscreen mode" );
vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO, "fullscreen refresh rate" );

View File

@ -307,6 +307,16 @@ void R_AddSkyBoxSurface( msurface_t *fa )
if( r_fastsky->integer )
return;
if( clgame.movevars.skyangle )
{
// HACK: force full sky to draw when it has angle
for( i = 0; i < 6; i++ )
{
RI.skyMins[0][i] = RI.skyMins[1][i] = -1;
RI.skyMaxs[0][i] = RI.skyMaxs[1][i] = 1;
}
}
// calculate vertex values for sky box
for( p = fa->polys; p; p = p->next )
{
@ -348,6 +358,18 @@ void R_DrawSkyBox( void )
{
int i;
if( clgame.movevars.skyangle )
{
// check for no sky at all
for( i = 0; i < 6; i++ )
{
if( RI.skyMins[0][i] < RI.skyMaxs[0][i] && RI.skyMins[1][i] < RI.skyMaxs[1][i] )
break;
}
if( i == 6 ) return; // nothing visible
}
RI.isSkyVisible = true;
// don't fogging skybox (this fix old Half-Life bug)
@ -357,6 +379,16 @@ void R_DrawSkyBox( void )
pglDisable( GL_ALPHA_TEST );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
if( clgame.movevars.skyangle && !VectorIsNull( (float *)&clgame.movevars.skydir_x ))
{
matrix4x4 m;
Matrix4x4_CreateRotate( m, clgame.movevars.skyangle, clgame.movevars.skydir_x, clgame.movevars.skydir_y, clgame.movevars.skydir_z );
Matrix4x4_ConcatTranslate( m, -RI.vieworg[0], -RI.vieworg[1], -RI.vieworg[2] );
Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, m );
GL_LoadMatrix( RI.modelviewMatrix );
tr.modelviewIdentity = false;
}
for( i = 0; i < 6; i++ )
{
if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
@ -371,6 +403,8 @@ void R_DrawSkyBox( void )
MakeSkyVec( RI.skyMaxs[0][i], RI.skyMins[1][i], i );
pglEnd();
}
R_LoadIdentity();
}
/*

View File

@ -198,6 +198,7 @@ sfx_t *S_FindName( const char *name, int *pfInCache )
{
if( !sfx->name[0] ) break; // free spot
}
if( i == s_numSfx )
{
if( s_numSfx == MAX_SFX )

View File

@ -15,6 +15,7 @@ GNU General Public License for more details.
#include "common.h"
#include "client.h"
#include "gl_local.h"
#include <vfw.h> // video for windows
// msvfw32.dll exports
@ -294,7 +295,8 @@ byte *AVI_GetVideoFrame( movie_state_t *Avi, long frame )
frame_raw = (char *)frame_info + frame_info->biSize + frame_info->biClrUsed * sizeof( RGBQUAD );
pDrawDibDraw( Avi->hDD, Avi->hDC, 0, 0, Avi->video_xres, Avi->video_yres, frame_info, frame_raw, 0, 0, Avi->video_xres, Avi->video_yres, 0 );
if( Avi->ignore_hwgamma )
// adjust gamma only if hardware gamma is enabled
if( Avi->ignore_hwgamma && glConfig.deviceSupportsGamma )
{
tmp = Avi->pframe_data;

View File

@ -468,6 +468,7 @@ typedef enum
IMAGE_FORCE_RGBA = BIT(23), // force image to RGBA buffer
IMAGE_MAKE_LUMA = BIT(24), // create luma texture from indexed
IMAGE_QUANTIZE = BIT(25), // make indexed image from 24 or 32- bit image
IMAGE_LIGHTGAMMA = BIT(26), // apply gamma for image
} imgFlags_t;
typedef struct rgbdata_s
@ -491,7 +492,7 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size )
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
void FS_FreeImage( rgbdata_t *pack );
extern const bpc_desc_t PFDesc[]; // image get pixelformat
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags );
qboolean Image_Process( rgbdata_t **pix, int width, int height, float gamma, uint flags );
/*
========================================================================
@ -778,6 +779,11 @@ void S_StopSound( int entnum, int channel, const char *soundname );
int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
void S_StopAllSounds( void );
// gamma routines
void BuildGammaTable( float gamma, float texGamma );
byte TextureToTexGamma( byte b );
byte TextureToGamma( byte b );
#ifdef __cplusplus
}
#endif

68
engine/common/gamma.c Normal file
View File

@ -0,0 +1,68 @@
/*
gamma.c - gamma routines
Copyright (C) 2011 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include <mathlib.h>
#include "gl_local.h"
//-----------------------------------------------------------------------------
// Gamma conversion support
//-----------------------------------------------------------------------------
static byte gammatable[256];
static byte texgammatable[256]; // palette is sent through this to convert to screen gamma
void BuildGammaTable( float gamma, float texGamma )
{
int i, inf;
float g1, g = gamma;
double f;
g = bound( 1.8f, g, 3.0f );
texGamma = bound( 1.8f, texGamma, 3.0f );
g = 1.0f / g;
g1 = texGamma * g;
for( i = 0; i < 256; i++ )
{
inf = 255 * pow( i / 255.f, g1 );
texgammatable[i] = bound( 0, inf, 255 );
}
for( i = 0; i < 256; i++ )
{
f = 255.0 * pow(( float )i / 255.0f, 2.2f / texGamma );
inf = (int)(f + 0.5f);
gammatable[i] = bound( 0, inf, 255 );
}
}
byte TextureToTexGamma( byte b )
{
if( glConfig.deviceSupportsGamma )
return b; // passthrough
b = bound( 0, b, 255 );
return texgammatable[b];
}
byte TextureToGamma( byte b )
{
if( glConfig.deviceSupportsGamma )
return b; // passthrough
b = bound( 0, b, 255 );
return gammatable[b];
}

View File

@ -1203,7 +1203,37 @@ rgbdata_t *Image_DecompressInternal( rgbdata_t *pic )
return pic;
}
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags )
rgbdata_t *Image_LightGamma( rgbdata_t *pic, float texGamma )
{
byte *in = (byte *)pic->buffer;
byte gammatable[256];
int i, inf;
double f;
if( pic->type != PF_RGBA_32 )
return pic;
texGamma = bound( 1.8f, texGamma, 3.0f );
// build the gamma table
for( i = 0; i < 256; i++ )
{
f = 255.0 * pow(( float )i / 255.0f, 2.2f / texGamma );
inf = (int)(f + 0.5f);
gammatable[i] = bound( 0, inf, 255 );
}
for( i = 0; i < pic->width * pic->height; i++, in += 4 )
{
in[0] = gammatable[in[0]];
in[1] = gammatable[in[1]];
in[2] = gammatable[in[2]];
}
return pic;
}
qboolean Image_Process( rgbdata_t **pix, int width, int height, float gamma, uint flags )
{
rgbdata_t *pic = *pix;
qboolean result = true;
@ -1227,6 +1257,7 @@ qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags )
// update format to RGBA if any
if( flags & IMAGE_FORCE_RGBA ) pic = Image_DecompressInternal( pic );
if( flags & IMAGE_LIGHTGAMMA ) pic = Image_LightGamma( pic, gamma );
// quantize image
if( flags & IMAGE_QUANTIZE ) pic = Image_Quantize( pic );

View File

@ -149,6 +149,7 @@ void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matri
void Matrix4x4_FromOriginQuat( matrix4x4 out, const vec4_t quaternion, const vec3_t origin );
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale );
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist );
void Matrix4x4_TransformStandardPlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist );
void Matrix4x4_SetOrigin( matrix4x4 out, float x, float y, float z );
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 );
void Matrix4x4_OriginFromMatrix( const matrix4x4 in, float *out );

View File

@ -432,6 +432,17 @@ void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal,
*dist = d * scale + ( out[0] * in[0][3] + out[1] * in[1][3] + out[2] * in[2][3] );
}
void Matrix4x4_TransformStandardPlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist )
{
float scale = sqrt( in[0][0] * in[0][0] + in[0][1] * in[0][1] + in[0][2] * in[0][2] );
float iscale = 1.0f / scale;
out[0] = (normal[0] * in[0][0] + normal[1] * in[0][1] + normal[2] * in[0][2]) * iscale;
out[1] = (normal[0] * in[1][0] + normal[1] * in[1][1] + normal[2] * in[1][2]) * iscale;
out[2] = (normal[0] * in[2][0] + normal[1] * in[2][1] + normal[2] * in[2][2]) * iscale;
*dist = d * scale - ( out[0] * in[0][3] + out[1] * in[1][3] + out[2] * in[2][3] );
}
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 )
{
// we only support uniform scaling, so assume the first row is enough

View File

@ -38,6 +38,7 @@ GNU General Public License for more details.
#define PLATE_HUE_END 191
#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))
// model flags (stored in model_t->flags)
#define MODEL_CONVEYOR BIT( 0 )
@ -64,6 +65,7 @@ typedef struct
size_t visdatasize; // actual size of the visdata
qboolean loading; // true if worldmodel is loading
qboolean sky_sphere; // true when quake sky-sphere is used
qboolean has_mirrors; // one or more brush models contain reflective textures
vec3_t mins; // real accuracy world bounds
vec3_t maxs;

View File

@ -492,6 +492,7 @@ static void Mod_LoadTextures( const dlump_t *l )
GL_FreeTexture( tr.solidskyTexture );
GL_FreeTexture( tr.alphaskyTexture );
tr.solidskyTexture = tr.alphaskyTexture = 0;
world.has_mirrors = false;
world.sky_sphere = false;
}
@ -1062,10 +1063,14 @@ static void Mod_LoadSurfaces( const dlump_t *l )
if( !Q_strncmp( tex->name, "scroll", 6 ))
out->flags |= SURF_CONVEYOR;
#ifdef MIRROR_TEST
if( !Q_strncmp( tex->name, "glassblue1", 10 ))
// g-cont this texture from decals.wad he-he
if( !Q_strncmp( tex->name, "reflect", 7 ))
{
out->flags |= SURF_MIRROR;
#endif
world.has_mirrors = true;
}
if( tex->name[0] == '{' )
out->flags |= SURF_TRANSPARENT;

View File

@ -81,6 +81,10 @@ static const delta_field_t pm_fields[] =
{ PHYS_DEF( studio_scale ) },
{ PHYS_DEF( clienttrace ) },
{ PHYS_DEF( wateralpha ) },
{ PHYS_DEF( skydir_x ) },
{ PHYS_DEF( skydir_y ) },
{ PHYS_DEF( skydir_z ) },
{ PHYS_DEF( skyangle ) },
{ NULL },
};
@ -817,6 +821,10 @@ void Delta_Init( void )
Delta_AddField( "movevars_t", "skyvec_x", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f ); // 0 - 1
Delta_AddField( "movevars_t", "skyvec_y", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "skyvec_z", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "skydir_x", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f ); // 0 - 1
Delta_AddField( "movevars_t", "skydir_y", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "skydir_z", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "skyangle", DT_ANGLE, 16, 1.0f, 1.0f ); // 0 - 360
Delta_AddField( "movevars_t", "studio_scale", DT_INTEGER, 1, 1.0f, 1.0f );
Delta_AddField( "movevars_t", "clienttrace", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "wateralpha", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );

View File

@ -206,6 +206,10 @@ SOURCE=.\common\filesystem.c
# End Source File
# Begin Source File
SOURCE=.\common\gamma.c
# End Source File
# Begin Source File
SOURCE=.\client\gl_backend.c
# End Source File
# Begin Source File
@ -230,6 +234,10 @@ SOURCE=.\client\gl_image.c
# End Source File
# Begin Source File
SOURCE=.\client\gl_mirror.c
# End Source File
# Begin Source File
SOURCE=.\client\gl_refrag.c
# End Source File
# Begin Source File

View File

@ -153,6 +153,7 @@ typedef struct ui_enginefuncs_s
void (*pfnSetCursor)( void *hCursor ); // change cursor
int (*pfnIsMapValid)( char *filename );
void (*pfnProcessImage)( int texnum, float gamma, int topColor, int bottomColor );
} ui_enginefuncs_t;
typedef struct

View File

@ -401,6 +401,8 @@ extern convar_t *sv_clienttrace;
extern convar_t *sv_send_resources;
extern convar_t *sv_send_logos;
extern convar_t *sv_sendvelocity;
extern convar_t *sv_skyspeed;
extern convar_t *sv_skyangle;
extern convar_t *mp_consistency;
extern convar_t *public_server;
extern convar_t *physinfo;

View File

@ -806,7 +806,7 @@ void SV_PlaybackEvent( sizebuf_t *msg, event_info_t *info )
BF_WriteWord( msg, info->index ); // send event index
BF_WriteWord( msg, (int)( info->fire_time * 100.0f )); // send event delay
MSG_WriteDeltaEvent( msg, &nullargs, &info->args ); // TODO: use delta-compressing
MSG_WriteDeltaEvent( msg, &nullargs, &info->args ); // reliable events not use delta
}
const char *SV_ClassName( const edict_t *e )
@ -3533,18 +3533,17 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
}
}
flags |= FEV_SERVER; // it's a server event
flags |= FEV_SERVER; // it's a server event!
if( delay < 0.0f )
delay = 0.0f; // fixup negative delays
if( delay < 0.0f ) delay = 0.0f; // fixup negative delays
if( SV_IsValidEdict( pInvoker ))
invokerIndex = NUM_FOR_EDICT( pInvoker );
if( flags & FEV_RELIABLE )
{
args.ducking = 0;
VectorClear( args.velocity );
args.ducking = 0;
}
else if( invokerIndex )
{
@ -4520,6 +4519,11 @@ void SV_SpawnEntities( const char *mapname, char *entities )
Cvar_Reset( "sv_skyvec_y" );
Cvar_Reset( "sv_skyvec_z" );
Cvar_Reset( "sv_skyname" );
Cvar_Reset( "sv_skydir_x" );
Cvar_Reset( "sv_skydir_y" );
Cvar_Reset( "sv_skydir_z" );
Cvar_Reset( "sv_skyangle" );
Cvar_Reset( "sv_skyspeed" );
ent = EDICT_NUM( 0 );
if( ent->free ) SV_InitEdict( ent );

View File

@ -80,6 +80,11 @@ convar_t *sv_skyvec_y;
convar_t *sv_skyvec_z;
convar_t *sv_skyname;
convar_t *sv_wateralpha;
convar_t *sv_skydir_x;
convar_t *sv_skydir_y;
convar_t *sv_skydir_z;
convar_t *sv_skyangle;
convar_t *sv_skyspeed;
void Master_Shutdown( void );
@ -225,6 +230,10 @@ void SV_UpdateMovevars( void )
svgame.movevars.skyvec_x = sv_skyvec_x->value;
svgame.movevars.skyvec_y = sv_skyvec_y->value;
svgame.movevars.skyvec_z = sv_skyvec_z->value;
svgame.movevars.skydir_x = sv_skydir_x->value;
svgame.movevars.skydir_y = sv_skydir_y->value;
svgame.movevars.skydir_z = sv_skydir_z->value;
svgame.movevars.skyangle = sv_skyangle->value;
svgame.movevars.studio_scale = sv_allow_studio_scaling->integer;
svgame.movevars.clienttrace = sv_clienttrace->value;
svgame.movevars.wateralpha = sv_wateralpha->value;
@ -645,13 +654,18 @@ void SV_Init( void )
// half-life shared variables
sv_zmax = Cvar_Get ("sv_zmax", "4096", CVAR_PHYSICINFO, "zfar server value" );
sv_wateramp = Cvar_Get ("sv_wateramp", "0", CVAR_PHYSICINFO, "global water wave height" );
sv_skycolor_r = Cvar_Get ("sv_skycolor_r", "255", CVAR_PHYSICINFO, "skycolor red (hl1 compatibility)" );
sv_skycolor_g = Cvar_Get ("sv_skycolor_g", "255", CVAR_PHYSICINFO, "skycolor green (hl1 compatibility)" );
sv_skycolor_b = Cvar_Get ("sv_skycolor_b", "255", CVAR_PHYSICINFO, "skycolor blue (hl1 compatibility)" );
sv_skyvec_x = Cvar_Get ("sv_skyvec_x", "0", CVAR_PHYSICINFO, "sky direction x (hl1 compatibility)" );
sv_skyvec_y = Cvar_Get ("sv_skyvec_y", "0", CVAR_PHYSICINFO, "sky direction y (hl1 compatibility)" );
sv_skyvec_z = Cvar_Get ("sv_skyvec_z", "0", CVAR_PHYSICINFO, "sky direction z (hl1 compatibility)" );
sv_skycolor_r = Cvar_Get ("sv_skycolor_r", "255", CVAR_PHYSICINFO, "skycolor red" );
sv_skycolor_g = Cvar_Get ("sv_skycolor_g", "255", CVAR_PHYSICINFO, "skycolor green" );
sv_skycolor_b = Cvar_Get ("sv_skycolor_b", "255", CVAR_PHYSICINFO, "skycolor blue" );
sv_skyvec_x = Cvar_Get ("sv_skyvec_x", "0", CVAR_PHYSICINFO, "skylight direction x" );
sv_skyvec_y = Cvar_Get ("sv_skyvec_y", "0", CVAR_PHYSICINFO, "skylight direction y" );
sv_skyvec_z = Cvar_Get ("sv_skyvec_z", "0", CVAR_PHYSICINFO, "skylight direction z" );
sv_skyname = Cvar_Get ("sv_skyname", "desert", CVAR_PHYSICINFO, "skybox name (can be dynamically changed in-game)" );
sv_skydir_x = Cvar_Get ("sv_skydir_x", "0", CVAR_PHYSICINFO, "sky rotation direction x" );
sv_skydir_y = Cvar_Get ("sv_skydir_y", "0", CVAR_PHYSICINFO, "sky rotation direction y" );
sv_skydir_z = Cvar_Get ("sv_skydir_z", "1", CVAR_PHYSICINFO, "sky rotation direction z" ); // g-cont. add default sky rotate direction
sv_skyangle = Cvar_Get ("sv_skyangle", "0", CVAR_PHYSICINFO, "skybox rotational angle (in degrees)" );
sv_skyspeed = Cvar_Get ("sv_skyspeed", "0", 0, "skybox rotational speed" );
sv_footsteps = Cvar_Get ("mp_footsteps", "1", CVAR_PHYSICINFO, "can hear footsteps from other players" );
sv_wateralpha = Cvar_Get ("sv_wateralpha", "1", CVAR_PHYSICINFO, "world surfaces water transparency factor. 1.0 - solid, 0.0 - fully transparent" );

View File

@ -1707,6 +1707,14 @@ void SV_Physics( void )
// animate lightstyles (used for GetEntityIllum)
SV_RunLightStyles ();
if( sv_skyspeed->value )
{
// evaluate sky rotation.
// FIXME: ignore this feature in multiplayer to save traffic?
float skyAngle = sv_skyangle->value + sv_skyspeed->value * host.frametime;
Cvar_SetFloat( "sv_skyangle", anglemod( skyAngle ));
}
// decrement svgame.numEntities if the highest number entities died
for( ; EDICT_NUM( svgame.numEntities - 1 )->free; svgame.numEntities-- );
}

View File

@ -75,6 +75,11 @@ typedef struct
int viewentity; // Xash3D added
int serverflags; // converted to float and back
float wateralpha;
float skyDir_x;
float skyDir_y;
float skyDir_z;
float skyAngle;
float skySpeed;
} SAVE_HEADER;
typedef struct
@ -108,6 +113,11 @@ static TYPEDESCRIPTION gSaveHeader[] =
DEFINE_FIELD( SAVE_HEADER, viewentity, FIELD_SHORT ),
DEFINE_FIELD( SAVE_HEADER, serverflags, FIELD_INTEGER ),
DEFINE_FIELD( SAVE_HEADER, wateralpha, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, skyDir_x, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, skyDir_y, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, skyDir_z, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, skyAngle, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, skySpeed, FIELD_FLOAT ),
};
static TYPEDESCRIPTION gAdjacency[] =
@ -697,6 +707,11 @@ void SV_SaveGameStateGlobals( SAVERESTOREDATA *pSaveData )
header.skyVec_x = Cvar_VariableValue( "sv_skyvec_x" );
header.skyVec_y = Cvar_VariableValue( "sv_skyvec_y" );
header.skyVec_z = Cvar_VariableValue( "sv_skyvec_z" );
header.skyDir_x = Cvar_VariableValue( "sv_skydir_x" );
header.skyDir_y = Cvar_VariableValue( "sv_skydir_y" );
header.skyDir_z = Cvar_VariableValue( "sv_skydir_z" );
header.skyAngle = Cvar_VariableValue( "sv_skyangle" );
header.skySpeed = Cvar_VariableValue( "sv_skyspeed" );
// save viewentity to allow camera works after save\restore
if(( cl = SV_ClientFromEdict( EDICT_NUM( 1 ), true )) != NULL )
@ -1181,10 +1196,16 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
Cvar_SetFloat( "sv_skyvec_x", header.skyVec_x );
Cvar_SetFloat( "sv_skyvec_y", header.skyVec_y );
Cvar_SetFloat( "sv_skyvec_z", header.skyVec_z );
Cvar_SetFloat( "sv_skydir_x", header.skyDir_x );
Cvar_SetFloat( "sv_skydir_y", header.skyDir_y );
Cvar_SetFloat( "sv_skydir_z", header.skyDir_z );
Cvar_SetFloat( "sv_skyangle", header.skyAngle );
Cvar_SetFloat( "sv_skyspeed", header.skySpeed );
// restore serverflags
svgame.globals->serverflags = header.serverflags;
if( header.wateralpha <= 0.0f ) header.wateralpha = 1.0f; // make compatibility with old saves
Cvar_SetFloat( "sv_wateralpha", header.wateralpha );
// re-base the savedata since we re-ordered the entity/table / restore fields

View File

@ -1016,11 +1016,11 @@ void SV_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang
void SV_GetBonePosition( edict_t *e, int iBone, float *org, float *ang )
{
iBone = bound( 0, iBone, sv_studiohdr->numbones );
if( !SV_StudioSetupModel( e, iBone, false ) || sv_studiohdr->numbones <= 0 )
return;
iBone = bound( 0, iBone, sv_studiohdr->numbones );
if( org ) Matrix3x4_OriginFromMatrix( sv_studiobones[iBone], org );
if( ang ) VectorAngles( sv_studiobones[iBone][0], ang ); // bone forward to angles

View File

@ -31,6 +31,8 @@ GNU General Public License for more details.
#define GetGameInfo (*g_engfuncs.pfnGetGameInfo)
#define CheckGameDll (*g_engfuncs.pfnCheckGameDll)
#define PIC_SetGamma( x, y ) (*g_engfuncs.pfnProcessImage)( x, y, 0, 0 )
#define DRAW_LOGO (*g_engfuncs.pfnDrawLogo)
#define PRECACHE_LOGO( x ) (*g_engfuncs.pfnDrawLogo)( x, 0, 0, 0, 0 )
#define GetLogoWidth (*g_engfuncs.pfnGetLogoWidth)

View File

@ -51,6 +51,8 @@ typedef struct
menuSlider_s glareReduction;
menuCheckBox_s fastSky;
menuCheckBox_s hiTextures;
HIMAGE hTestImage;
} uiVidOptions_t;
static uiVidOptions_t uiVidOptions;
@ -64,9 +66,15 @@ UI_VidOptions_GetConfig
static void UI_VidOptions_GetConfig( void )
{
uiVidOptions.screenSize.curValue = RemapVal( CVAR_GET_FLOAT( "viewsize" ), 30.0f, 120.0f, 0.0f, 1.0f );
uiVidOptions.gammaIntensity.curValue = RemapVal( CVAR_GET_FLOAT( "gamma" ), 0.5f, 2.3f, 0.0f, 1.0f );
uiVidOptions.glareReduction.curValue = (CVAR_GET_FLOAT( "r_flaresize" ) - 100.0f ) / 200.0f;
if( CVAR_GET_FLOAT( "gl_ignorehwgamma" ))
{
uiVidOptions.gammaIntensity.curValue = RemapVal( CVAR_GET_FLOAT( "gamma" ), 1.8f, 3.0f, 0.0f, 1.0f );
PIC_SetGamma( uiVidOptions.hTestImage, CVAR_GET_FLOAT( "gamma" ));
}
else uiVidOptions.gammaIntensity.curValue = RemapVal( CVAR_GET_FLOAT( "gamma" ), 0.5f, 3.0f, 0.0f, 1.0f );
if( CVAR_GET_FLOAT( "r_fastsky" ))
uiVidOptions.fastSky.enabled = 1;
@ -85,10 +93,25 @@ UI_VidOptions_UpdateConfig
static void UI_VidOptions_UpdateConfig( void )
{
CVAR_SET_FLOAT( "viewsize", RemapVal( uiVidOptions.screenSize.curValue, 0.0f, 1.0f, 30.0f, 120.0f ));
CVAR_SET_FLOAT( "gamma", RemapVal( uiVidOptions.gammaIntensity.curValue, 0.0f, 1.0f, 0.5f, 2.3f ));
CVAR_SET_FLOAT( "r_flaresize", (uiVidOptions.glareReduction.curValue * 200.0f ) + 100.0f );
CVAR_SET_FLOAT( "r_fastsky", uiVidOptions.fastSky.enabled );
CVAR_SET_FLOAT( "host_allow_materials", uiVidOptions.hiTextures.enabled );
if( CVAR_GET_FLOAT( "gl_ignorehwgamma" ))
PIC_SetGamma( uiVidOptions.hTestImage, RemapVal( uiVidOptions.gammaIntensity.curValue, 0.0f, 1.0f, 1.8f, 3.0f ));
else CVAR_SET_FLOAT( "gamma", RemapVal( uiVidOptions.gammaIntensity.curValue, 0.0f, 1.0f, 0.5f, 2.3f ));
}
static void UI_VidOptions_SetConfig( void )
{
CVAR_SET_FLOAT( "viewsize", RemapVal( uiVidOptions.screenSize.curValue, 0.0f, 1.0f, 30.0f, 120.0f ));
CVAR_SET_FLOAT( "r_flaresize", (uiVidOptions.glareReduction.curValue * 200.0f ) + 100.0f );
CVAR_SET_FLOAT( "r_fastsky", uiVidOptions.fastSky.enabled );
CVAR_SET_FLOAT( "host_allow_materials", uiVidOptions.hiTextures.enabled );
if( CVAR_GET_FLOAT( "gl_ignorehwgamma" ))
CVAR_SET_FLOAT( "gamma", RemapVal( uiVidOptions.gammaIntensity.curValue, 0.0f, 1.0f, 1.8f, 3.0f ));
else CVAR_SET_FLOAT( "gamma", RemapVal( uiVidOptions.gammaIntensity.curValue, 0.0f, 1.0f, 0.5f, 2.3f ));
}
/*
@ -162,6 +185,7 @@ static void UI_VidOptions_Callback( void *self, int event )
switch( item->id )
{
case ID_DONE:
UI_VidOptions_SetConfig();
UI_PopMenu();
break;
}
@ -176,6 +200,8 @@ static void UI_VidOptions_Init( void )
{
memset( &uiVidOptions, 0, sizeof( uiVidOptions_t ));
uiVidOptions.hTestImage = PIC_Load( ART_GAMMA );
uiVidOptions.menu.vidInitFunc = UI_VidOptions_Init;
uiVidOptions.background.generic.id = ID_BACKGROUND;
@ -293,7 +319,6 @@ void UI_VidOptions_Precache( void )
{
PIC_Load( ART_BACKGROUND );
PIC_Load( ART_BANNER );
PIC_Load( ART_GAMMA );
}
/*
@ -306,6 +331,5 @@ void UI_VidOptions_Menu( void )
UI_VidOptions_Precache();
UI_VidOptions_Init();
UI_VidOptions_UpdateConfig();
UI_PushMenu( &uiVidOptions.menu );
}

View File

@ -43,6 +43,10 @@ struct movevars_s
qboolean studio_scale; // Allow engine to scale visible and physic hull of studiomodels
float clienttrace; // Studiomodels scale that applied for the clients (visual effect only)
float wateralpha; // World water alpha 1.0 - solid 0.0 - transparent
float skydir_x; // skybox rotate direction
float skydir_y; //
float skydir_z; //
float skyangle; // skybox rotate angle
};
extern movevars_t movevars;