forked from FWGS/Paranoia2
1.51 Aug30 2020 https://hlfx.ru/forum/showthread.php?s=&postid=196728#post196728
This commit is contained in:
commit
0455f5d6e2
31
backup.bat
Normal file
31
backup.bat
Normal file
@ -0,0 +1,31 @@
|
||||
@echo off
|
||||
color 4F
|
||||
echo XashXT Group 2006 (C)
|
||||
echo Prepare source for backup
|
||||
echo.
|
||||
|
||||
if exist backup.log del /f /q backup.log
|
||||
if not exist D:\Paranoia2\!backup/ mkdir D:\Paranoia2\!backup\
|
||||
echo Prepare OK!
|
||||
echo Please wait: backup in progress
|
||||
C:\Progra~1\WinRar\rar a -agMMMYYYY-DD D:\Paranoia2\!backup\.rar -dh -m5 @backup.lst >>backup.log
|
||||
if errorlevel 1 goto error
|
||||
if errorlevel 0 goto ok
|
||||
:ok
|
||||
cls
|
||||
echo Source was sucessfully backuped
|
||||
echo and stored in folder "backup"
|
||||
echo Press any key for exit. :-)
|
||||
if exist backup.log del /f /q backup.log
|
||||
exit
|
||||
:error
|
||||
echo ******************************
|
||||
echo ***********Error!*************
|
||||
echo ******************************
|
||||
echo **See backup.log for details**
|
||||
echo ******************************
|
||||
echo ******************************
|
||||
echo.
|
||||
echo press any key for exit :-(
|
||||
pause>nul
|
||||
exit
|
45
backup.lst
Normal file
45
backup.lst
Normal file
@ -0,0 +1,45 @@
|
||||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// list with backup directories
|
||||
//=======================================================================
|
||||
|
||||
// global stuff
|
||||
paranoia_sdk.dsw
|
||||
debug.bat
|
||||
backup.lst
|
||||
backup.bat
|
||||
release.bat
|
||||
|
||||
cl_dll\
|
||||
cl_dll\hl\
|
||||
cl_dll\render\
|
||||
common\
|
||||
dlls\
|
||||
engine\
|
||||
game_shared\
|
||||
mainui\
|
||||
mainui\legacy
|
||||
p2_launch\
|
||||
pm_shared\
|
||||
utils\
|
||||
utils\bsp31migrate\
|
||||
utils\common\
|
||||
utils\decal2tga\
|
||||
utils\hlmv\
|
||||
utils\hlsv\
|
||||
utils\mxtk\
|
||||
utils\makefont\
|
||||
utils\maketex\
|
||||
utils\makewad\
|
||||
utils\p2bsp\
|
||||
utils\p2csg\
|
||||
utils\p2rad\
|
||||
utils\p2vis\
|
||||
utils\reqtest\
|
||||
utils\squish\
|
||||
utils\stalker2tga\
|
||||
utils\spritegen\
|
||||
utils\studiomdl\
|
||||
utils\vgui\
|
||||
utils\vgui\include\
|
||||
utils\vgui\lib\win32_vc6\
|
124
bspextra.h
Normal file
124
bspextra.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
bspfile.h - BSP format included q1, hl1 support
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef BSPEXTRAFILE_H
|
||||
#define BSPEXTRAFILE_H
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
EXTRA BSP INFO
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define IDEXTRAHEADER (('H'<<24)+('S'<<16)+('A'<<8)+'X') // little-endian "XASH"
|
||||
#define EXTRA_VERSION 3 // ver. 1 was occupied by old versions of XashXT, ver. 2 was occupied by old vesrions of P2:savior
|
||||
|
||||
#define MAX_MAP_CUBEMAPS 1024
|
||||
#define MAX_MAP_LANDSCAPES 8192 // can be increased but not needs
|
||||
#define MAX_MAP_LEAFLIGHTS 0x40000 // can be increased but not needs
|
||||
#define MAX_MAP_WORLDLIGHTS 65535 // including a light surfaces too
|
||||
|
||||
#define LUMP_VERTNORMALS 0 // phong shaded vertex normals
|
||||
#define LUMP_LIGHTVECS 1 // deluxemap data
|
||||
#define LUMP_CUBEMAPS 2 // cubemap description
|
||||
#define LUMP_LANDSCAPES 3 // landscape and lightmap resolution info
|
||||
#define LUMP_LEAF_LIGHTING 4 // contain compressed light cubes per empty leafs
|
||||
#define LUMP_WORLDLIGHTS 5 // list of all the virtual and real lights (used to relight models in-game)
|
||||
#define LUMP_COLLISION 6 // physics engine collision hull dump
|
||||
#define LUMP_AINODEGRAPH 7 // node graph that stored into the bsp
|
||||
#define EXTRA_LUMPS 8 // count of the extra lumps
|
||||
|
||||
#define LM_ENVIRONMENT_STYLE 20 // light_environment always handle into separate style, so we can ignore it
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int id; // must be little endian XASH
|
||||
int version;
|
||||
dlump_t lumps[EXTRA_LUMPS];
|
||||
} dextrahdr_t;
|
||||
|
||||
// MODIFIED: int flags -> short flags, short landscape (total struct size not changed!)
|
||||
typedef struct
|
||||
{
|
||||
float vecs[2][4]; // texmatrix [s/t][xyz offset]
|
||||
int miptex;
|
||||
short flags;
|
||||
short landscape;
|
||||
} dtexinfo_t;
|
||||
|
||||
//============================================================================
|
||||
typedef struct
|
||||
{
|
||||
float normal[3];
|
||||
} dnormal_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short origin[3]; // position of light snapped to the nearest integer
|
||||
short size; // cubemap side size
|
||||
} dcubemap_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte color[6][3]; // 6 sides 1x1 (single pixel per side)
|
||||
} dsample_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dsample_t cube;
|
||||
short origin[3];
|
||||
short leafnum; // leaf that contain this sample
|
||||
} dleafambient_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char landname[16]; // name of decsription in mapname_land.txt
|
||||
word texture_step; // default is 16, pixels\luxels ratio
|
||||
word max_extent; // default is 16, subdivision step ((texture_step * max_extent) - texture_step)
|
||||
short groupid; // to determine equal landscapes from various groups
|
||||
} dlandscape_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
emit_surface,
|
||||
emit_point,
|
||||
emit_spotlight,
|
||||
emit_skylight
|
||||
} emittype_t;
|
||||
|
||||
#define VERTEXNORMAL_CONE_INNER_ANGLE DEG2RAD( 7.275 )
|
||||
#define DWL_FLAGS_INAMBIENTCUBE 0x0001 // This says that the light was put into the per-leaf ambient cubes.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte emittype;
|
||||
byte style;
|
||||
byte flags; // will be set in ComputeLeafAmbientLighting
|
||||
short origin[3]; // light abs origin
|
||||
float intensity[3]; // RGB
|
||||
float normal[3]; // for surfaces and spotlights
|
||||
float stopdot; // for spotlights
|
||||
float stopdot2; // for spotlights
|
||||
float fade; // falloff scaling for linear and inverse square falloff 1.0 = normal, 0.5 = farther, 2.0 = shorter etc
|
||||
float radius; // light radius
|
||||
short leafnum; // light linked into this leaf
|
||||
byte falloff; // falloff style 0 = default (inverse square), 1 = inverse falloff, 2 = inverse square (arghrad compat)
|
||||
word facenum; // face number for emit_surface
|
||||
short modelnumber; // g-cont. we can't link lights with entities by entity number so we link it by bmodel number
|
||||
} dworldlight_t;
|
||||
|
||||
#endif//BSPFILE_H
|
1247
cl_dll/ammo.cpp
Normal file
1247
cl_dll/ammo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
64
cl_dll/ammo.h
Normal file
64
cl_dll/ammo.h
Normal file
@ -0,0 +1,64 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
#ifndef __AMMO_H__
|
||||
#define __AMMO_H__
|
||||
|
||||
#define MAX_WEAPON_NAME 128
|
||||
|
||||
|
||||
#define WEAPON_FLAGS_SELECTONEMPTY 1
|
||||
|
||||
#define WEAPON_IS_ONTARGET 0x40
|
||||
|
||||
struct WEAPON
|
||||
{
|
||||
char szName[MAX_WEAPON_NAME];
|
||||
int iAmmoType;
|
||||
int iAmmo2Type;
|
||||
int iMax1;
|
||||
int iMax2;
|
||||
int iSlot;
|
||||
int iSlotPos;
|
||||
int iFlags;
|
||||
int iId;
|
||||
int iClip;
|
||||
|
||||
int iCount; // # of itesm in plist
|
||||
|
||||
HSPRITE hActive;
|
||||
wrect_t rcActive;
|
||||
HSPRITE hInactive;
|
||||
wrect_t rcInactive;
|
||||
HSPRITE hNoAmmo; // buz
|
||||
wrect_t rcNoAmmo; // buz
|
||||
HSPRITE hAmmo;
|
||||
wrect_t rcAmmo;
|
||||
HSPRITE hAmmo2;
|
||||
wrect_t rcAmmo2;
|
||||
HSPRITE hCrosshair;
|
||||
wrect_t rcCrosshair;
|
||||
HSPRITE hAutoaim;
|
||||
wrect_t rcAutoaim;
|
||||
HSPRITE hZoomedCrosshair;
|
||||
wrect_t rcZoomedCrosshair;
|
||||
HSPRITE hZoomedAutoaim;
|
||||
wrect_t rcZoomedAutoaim;
|
||||
};
|
||||
|
||||
typedef int AMMO;
|
||||
|
||||
|
||||
#endif
|
159
cl_dll/ammo_secondary.cpp
Normal file
159
cl_dll/ammo_secondary.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// ammo_secondary.cpp
|
||||
//
|
||||
// implementation of CHudAmmoSecondary class
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "parsemsg.h"
|
||||
|
||||
DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoVal );
|
||||
DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoIcon );
|
||||
|
||||
int CHudAmmoSecondary :: Init( void )
|
||||
{
|
||||
HOOK_MESSAGE( SecAmmoVal );
|
||||
HOOK_MESSAGE( SecAmmoIcon );
|
||||
|
||||
gHUD.AddHudElem(this);
|
||||
m_HUD_ammoicon = 0;
|
||||
|
||||
for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ )
|
||||
m_iAmmoAmounts[i] = -1; // -1 means don't draw this value
|
||||
|
||||
Reset();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CHudAmmoSecondary :: Reset( void )
|
||||
{
|
||||
m_fFade = 0;
|
||||
}
|
||||
|
||||
int CHudAmmoSecondary :: VidInit( void )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudAmmoSecondary :: Draw(float flTime)
|
||||
{
|
||||
if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
|
||||
return 1;
|
||||
|
||||
// draw secondary ammo icons above normal ammo readout
|
||||
int a, x, y, r, g, b, AmmoWidth;
|
||||
UnpackRGB( r, g, b, gHUD.m_iHUDColor ); //LRC
|
||||
a = (int) max( MIN_ALPHA, m_fFade );
|
||||
if (m_fFade > 0)
|
||||
m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons
|
||||
ScaleColors( r, g, b, a );
|
||||
|
||||
AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
|
||||
|
||||
y = ScreenHeight - (gHUD.m_iFontHeight*4); // this is one font height higher than the weapon ammo values
|
||||
x = ScreenWidth - AmmoWidth;
|
||||
|
||||
if ( m_HUD_ammoicon )
|
||||
{
|
||||
// Draw the ammo icon
|
||||
x -= (gHUD.GetSpriteRect(m_HUD_ammoicon).right - gHUD.GetSpriteRect(m_HUD_ammoicon).left);
|
||||
y -= (gHUD.GetSpriteRect(m_HUD_ammoicon).top - gHUD.GetSpriteRect(m_HUD_ammoicon).bottom);
|
||||
|
||||
SPR_Set( gHUD.GetSprite(m_HUD_ammoicon), r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_ammoicon) );
|
||||
}
|
||||
else
|
||||
{ // move the cursor by the '0' char instead, since we don't have an icon to work with
|
||||
x -= AmmoWidth;
|
||||
y -= (gHUD.GetSpriteRect(gHUD.m_HUD_number_0).top - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).bottom);
|
||||
}
|
||||
|
||||
// draw the ammo counts, in reverse order, from right to left
|
||||
for ( int i = MAX_SEC_AMMO_VALUES-1; i >= 0; i-- )
|
||||
{
|
||||
if ( m_iAmmoAmounts[i] < 0 )
|
||||
continue; // negative ammo amounts imply that they shouldn't be drawn
|
||||
|
||||
// half a char gap between the ammo number and the previous pic
|
||||
x -= (AmmoWidth / 2);
|
||||
|
||||
// draw the number, right-aligned
|
||||
x -= (gHUD.GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth);
|
||||
gHUD.DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b );
|
||||
|
||||
if ( i != 0 )
|
||||
{
|
||||
// draw the divider bar
|
||||
x -= (AmmoWidth / 2);
|
||||
FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Message handler for Secondary Ammo Value
|
||||
// accepts one value:
|
||||
// string: sprite name
|
||||
int CHudAmmoSecondary :: MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
m_HUD_ammoicon = gHUD.GetSpriteIndex( READ_STRING() );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Message handler for Secondary Ammo Icon
|
||||
// Sets an ammo value
|
||||
// takes two values:
|
||||
// byte: ammo index
|
||||
// byte: ammo value
|
||||
int CHudAmmoSecondary :: MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
int index = READ_BYTE();
|
||||
if ( index < 0 || index >= MAX_SEC_AMMO_VALUES )
|
||||
return 1;
|
||||
|
||||
m_iAmmoAmounts[index] = READ_BYTE();
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
// check to see if there is anything left to draw
|
||||
int count = 0;
|
||||
for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ )
|
||||
{
|
||||
count += max( 0, m_iAmmoAmounts[i] );
|
||||
}
|
||||
|
||||
if ( count == 0 )
|
||||
{ // the ammo fields are all empty, so turn off this hud area
|
||||
m_iFlags &= ~HUD_ACTIVE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// make the icons light up
|
||||
m_fFade = 200.0f;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
190
cl_dll/ammohistory.cpp
Normal file
190
cl_dll/ammohistory.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// ammohistory.cpp
|
||||
//
|
||||
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ammohistory.h"
|
||||
|
||||
HistoryResource gHR;
|
||||
|
||||
#define AMMO_PICKUP_GAP (gHR.iHistoryGap+5)
|
||||
#define AMMO_PICKUP_PICK_HEIGHT (32 + (gHR.iHistoryGap * 2))
|
||||
#define AMMO_PICKUP_HEIGHT_MAX (ScreenHeight - 100)
|
||||
|
||||
#define MAX_ITEM_NAME 32
|
||||
int HISTORY_DRAW_TIME = 5;
|
||||
|
||||
// keep a list of items
|
||||
struct ITEM_INFO
|
||||
{
|
||||
char szName[MAX_ITEM_NAME];
|
||||
HSPRITE spr;
|
||||
wrect_t rect;
|
||||
};
|
||||
|
||||
void HistoryResource :: AddToHistory( int iType, int iId, int iCount )
|
||||
{
|
||||
if ( iType == HISTSLOT_AMMO && !iCount )
|
||||
return; // no amount, so don't add
|
||||
|
||||
if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) )
|
||||
{ // the pic would have to be drawn too high
|
||||
// so start from the bottom
|
||||
iCurrentHistorySlot = 0;
|
||||
}
|
||||
|
||||
HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot
|
||||
HISTORY_DRAW_TIME = CVAR_GET_FLOAT( "hud_drawhistory_time" );
|
||||
|
||||
freeslot->type = iType;
|
||||
freeslot->iId = iId;
|
||||
freeslot->iCount = iCount;
|
||||
freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME;
|
||||
}
|
||||
|
||||
void HistoryResource :: AddToHistory( int iType, const char *szName, int iCount )
|
||||
{
|
||||
if ( iType != HISTSLOT_ITEM )
|
||||
return;
|
||||
|
||||
if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) )
|
||||
{ // the pic would have to be drawn too high
|
||||
// so start from the bottom
|
||||
iCurrentHistorySlot = 0;
|
||||
}
|
||||
|
||||
HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot
|
||||
|
||||
// I am really unhappy with all the code in this file
|
||||
|
||||
int i = gHUD.GetSpriteIndex( szName );
|
||||
if ( i == -1 )
|
||||
return; // unknown sprite name, don't add it to history
|
||||
|
||||
freeslot->iId = i;
|
||||
freeslot->type = iType;
|
||||
freeslot->iCount = iCount;
|
||||
|
||||
HISTORY_DRAW_TIME = CVAR_GET_FLOAT( "hud_drawhistory_time" );
|
||||
freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME;
|
||||
}
|
||||
|
||||
|
||||
void HistoryResource :: CheckClearHistory( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_HISTORY; i++ )
|
||||
{
|
||||
if ( rgAmmoHistory[i].type )
|
||||
return;
|
||||
}
|
||||
|
||||
iCurrentHistorySlot = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Draw Ammo pickup history
|
||||
//
|
||||
int HistoryResource :: DrawAmmoHistory( float flTime )
|
||||
{
|
||||
for ( int i = 0; i < MAX_HISTORY; i++ )
|
||||
{
|
||||
if ( rgAmmoHistory[i].type )
|
||||
{
|
||||
rgAmmoHistory[i].DisplayTime = min( rgAmmoHistory[i].DisplayTime, gHUD.m_flTime + HISTORY_DRAW_TIME );
|
||||
|
||||
if ( rgAmmoHistory[i].DisplayTime <= flTime )
|
||||
{ // pic drawing time has expired
|
||||
memset( &rgAmmoHistory[i], 0, sizeof(HIST_ITEM) );
|
||||
CheckClearHistory();
|
||||
}
|
||||
else if ( rgAmmoHistory[i].type == HISTSLOT_AMMO )
|
||||
{
|
||||
wrect_t rcPic;
|
||||
HSPRITE *spr = gWR.GetAmmoPicFromWeapon( rgAmmoHistory[i].iId, rcPic );
|
||||
|
||||
int r, g, b;
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
|
||||
ScaleColors(r, g, b, min(scale, 255) );
|
||||
|
||||
// Draw the pic
|
||||
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
|
||||
int xpos = ScreenWidth - 24;
|
||||
if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic
|
||||
{ // the dll has to make sure it has sent info the weapons you need
|
||||
SPR_Set( *spr, r, g, b );
|
||||
SPR_DrawAdditive( 0, xpos, ypos, &rcPic );
|
||||
}
|
||||
|
||||
// Draw the number
|
||||
gHUD.DrawHudNumberString( xpos - 10, ypos, xpos - 100, rgAmmoHistory[i].iCount, r, g, b );
|
||||
}
|
||||
else if ( rgAmmoHistory[i].type == HISTSLOT_WEAP )
|
||||
{
|
||||
WEAPON *weap = gWR.GetWeapon( rgAmmoHistory[i].iId );
|
||||
|
||||
if ( !weap )
|
||||
return 1; // we don't know about the weapon yet, so don't draw anything
|
||||
|
||||
int r, g, b;
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
|
||||
if ( !gWR.HasAmmo( weap ) )
|
||||
UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red
|
||||
|
||||
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
|
||||
ScaleColors(r, g, b, min(scale, 255) );
|
||||
|
||||
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
|
||||
int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left);
|
||||
SPR_Set( weap->hInactive, r, g, b );
|
||||
SPR_DrawAdditive( 0, xpos, ypos, &weap->rcInactive );
|
||||
}
|
||||
else if ( rgAmmoHistory[i].type == HISTSLOT_ITEM )
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
if ( !rgAmmoHistory[i].iId )
|
||||
continue; // sprite not loaded
|
||||
|
||||
wrect_t rect = gHUD.GetSpriteRect( rgAmmoHistory[i].iId );
|
||||
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
|
||||
ScaleColors(r, g, b, min(scale, 255) );
|
||||
|
||||
int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i));
|
||||
int xpos = ScreenWidth - (rect.right - rect.left) - 10;
|
||||
|
||||
SPR_Set( gHUD.GetSprite( rgAmmoHistory[i].iId ), r, g, b );
|
||||
SPR_DrawAdditive( 0, xpos, ypos, &rect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
154
cl_dll/ammohistory.h
Normal file
154
cl_dll/ammohistory.h
Normal file
@ -0,0 +1,154 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// ammohistory.h
|
||||
//
|
||||
|
||||
// this is the max number of items in each bucket
|
||||
#define MAX_WEAPON_POSITIONS MAX_WEAPON_SLOTS
|
||||
extern WEAPON *gpActiveSel;
|
||||
|
||||
class WeaponsResource
|
||||
{
|
||||
public: // buz: made public to access from drawing code (valves idea about WR is suxx)
|
||||
// Information about weapons & ammo
|
||||
WEAPON rgWeapons[MAX_WEAPONS]; // Weapons Array
|
||||
|
||||
// counts of weapons * ammo
|
||||
WEAPON* rgSlots[MAX_WEAPON_SLOTS+1][MAX_WEAPON_POSITIONS+1]; // The slots currently in use by weapons. The value is a pointer to the weapon; if it's NULL, no weapon is there
|
||||
int riAmmo[MAX_AMMO_SLOTS]; // count of each ammo type
|
||||
|
||||
public:
|
||||
void Init( void )
|
||||
{
|
||||
memset( rgWeapons, 0, sizeof rgWeapons );
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
iOldWeaponBits = 0;
|
||||
m_iSelectedColumn = -1;
|
||||
memset( rgSlots, 0, sizeof rgSlots );
|
||||
memset( riAmmo, 0, sizeof riAmmo );
|
||||
}
|
||||
|
||||
///// WEAPON /////
|
||||
int iOldWeaponBits;
|
||||
|
||||
WEAPON *GetWeapon( int iId ) { return &rgWeapons[iId]; }
|
||||
void AddWeapon( WEAPON *wp )
|
||||
{
|
||||
rgWeapons[ wp->iId ] = *wp;
|
||||
LoadWeaponSprites( &rgWeapons[ wp->iId ] );
|
||||
}
|
||||
|
||||
void PickupWeapon( WEAPON *wp )
|
||||
{
|
||||
rgSlots[ wp->iSlot ][ wp->iSlotPos ] = wp;
|
||||
if ((m_iSelectedColumn == wp->iSlot) && !gpActiveSel) // buz: menu active, but no weapons in this category
|
||||
gpActiveSel = wp;
|
||||
}
|
||||
|
||||
void DropWeapon( WEAPON *wp )
|
||||
{
|
||||
rgSlots[ wp->iSlot ][ wp->iSlotPos ] = NULL;
|
||||
if (wp == gpActiveSel) // buz: removed current weapon
|
||||
gpActiveSel = GetFirstPos( wp->iSlot );
|
||||
}
|
||||
|
||||
void DropAllWeapons( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_WEAPONS; i++ )
|
||||
{
|
||||
if ( rgWeapons[i].iId )
|
||||
DropWeapon( &rgWeapons[i] );
|
||||
}
|
||||
}
|
||||
|
||||
WEAPON* GetWeaponSlot( int slot, int pos ) { return rgSlots[slot][pos]; }
|
||||
|
||||
void LoadWeaponSprites( WEAPON* wp );
|
||||
void LoadAllWeaponSprites( void );
|
||||
WEAPON* GetFirstPos( int iSlot );
|
||||
WEAPON* GetLastPos( int iSlot ); // buz
|
||||
void SelectSlot( int iSlot, int fAdvance, int iDirection );
|
||||
WEAPON* GetNextActivePos( int iSlot, int iSlotPos );
|
||||
WEAPON* GetPrevActivePos( int iSlot, int iSlotPos ); // buz
|
||||
|
||||
int HasAmmo( WEAPON *p );
|
||||
|
||||
///// AMMO /////
|
||||
AMMO GetAmmo( int iId ) { return iId; }
|
||||
|
||||
void SetAmmo( int iId, int iCount ) { riAmmo[ iId ] = iCount; }
|
||||
|
||||
int CountAmmo( int iId );
|
||||
|
||||
HSPRITE* GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect );
|
||||
|
||||
int m_iSelectedColumn; // buz: -1 means menu inactive
|
||||
float m_rgColumnSizes[MAX_WEAPON_SLOTS]; // buz
|
||||
};
|
||||
|
||||
extern WeaponsResource gWR;
|
||||
|
||||
|
||||
#define MAX_HISTORY 12
|
||||
enum {
|
||||
HISTSLOT_EMPTY,
|
||||
HISTSLOT_AMMO,
|
||||
HISTSLOT_WEAP,
|
||||
HISTSLOT_ITEM,
|
||||
};
|
||||
|
||||
class HistoryResource
|
||||
{
|
||||
private:
|
||||
struct HIST_ITEM {
|
||||
int type;
|
||||
float DisplayTime; // the time at which this item should be removed from the history
|
||||
int iCount;
|
||||
int iId;
|
||||
};
|
||||
|
||||
HIST_ITEM rgAmmoHistory[MAX_HISTORY];
|
||||
|
||||
public:
|
||||
|
||||
void Init( void )
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
memset( rgAmmoHistory, 0, sizeof rgAmmoHistory );
|
||||
}
|
||||
|
||||
int iHistoryGap;
|
||||
int iCurrentHistorySlot;
|
||||
|
||||
void AddToHistory( int iType, int iId, int iCount = 0 );
|
||||
void AddToHistory( int iType, const char *szName, int iCount = 0 );
|
||||
|
||||
void CheckClearHistory( void );
|
||||
int DrawAmmoHistory( float flTime );
|
||||
};
|
||||
|
||||
extern HistoryResource gHR;
|
||||
|
||||
|
||||
|
145
cl_dll/battery.cpp
Normal file
145
cl_dll/battery.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// battery.cpp
|
||||
//
|
||||
// implementation of CHudBattery class
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vgui_TeamFortressViewport.h" // buz
|
||||
#include "vgui_hud.h" // buz
|
||||
|
||||
DECLARE_MESSAGE(m_Battery, Battery)
|
||||
|
||||
int CHudBattery::Init(void)
|
||||
{
|
||||
m_iBat = 0;
|
||||
m_fFade = 0;
|
||||
m_iFlags = 0;
|
||||
|
||||
HOOK_MESSAGE(Battery);
|
||||
|
||||
gHUD.AddHudElem(this);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
int CHudBattery::VidInit(void)
|
||||
{
|
||||
int HUD_suit_empty = gHUD.GetSpriteIndex( "suit_empty" );
|
||||
int HUD_suit_full = gHUD.GetSpriteIndex( "suit_full" );
|
||||
|
||||
m_hSprite1 = m_hSprite2 = 0; // delaying get sprite handles until we know the sprites are loaded
|
||||
m_prc1 = &gHUD.GetSpriteRect( HUD_suit_empty );
|
||||
m_prc2 = &gHUD.GetSpriteRect( HUD_suit_full );
|
||||
m_iHeight = m_prc2->bottom - m_prc1->top;
|
||||
m_fFade = 0;
|
||||
return 1;
|
||||
};
|
||||
|
||||
int CHudBattery:: MsgFunc_Battery(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
int x = READ_SHORT();
|
||||
|
||||
if( x != m_iBat )
|
||||
{
|
||||
m_fFade = FADE_TIME;
|
||||
m_iBat = x;
|
||||
}
|
||||
|
||||
gViewPort->m_pHud2->UpdateArmor(x); // buz
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int CHudBattery::Draw(float flTime)
|
||||
{
|
||||
return 1; // buz: dont draw battery..
|
||||
|
||||
if ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH )
|
||||
return 1;
|
||||
|
||||
int r, g, b, x, y, a;
|
||||
wrect_t rc;
|
||||
|
||||
rc = *m_prc2;
|
||||
rc.top += m_iHeight * ((float)(100-(min(100,m_iBat))) * 0.01); // battery can go from 0 to 100 so * 0.01 goes from 0 to 1
|
||||
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
|
||||
if (!FBitSet( gHUD.m_iHideHUDDisplay, ITEM_SUIT ))
|
||||
return 1;
|
||||
|
||||
// Has health changed? Flash the health #
|
||||
if (m_fFade)
|
||||
{
|
||||
if (m_fFade > FADE_TIME)
|
||||
m_fFade = FADE_TIME;
|
||||
|
||||
m_fFade -= (gHUD.m_flTimeDelta * 20);
|
||||
if (m_fFade <= 0)
|
||||
{
|
||||
a = 128;
|
||||
m_fFade = 0;
|
||||
}
|
||||
|
||||
// Fade the health number back to dim
|
||||
|
||||
a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128;
|
||||
|
||||
}
|
||||
else
|
||||
a = MIN_ALPHA;
|
||||
|
||||
ScaleColors(r, g, b, a );
|
||||
|
||||
int iOffset = (m_prc1->bottom - m_prc1->top)/6;
|
||||
|
||||
y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
|
||||
x = ScreenWidth/5;
|
||||
|
||||
// make sure we have the right sprite handles
|
||||
if ( !m_hSprite1 )
|
||||
m_hSprite1 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_empty" ) );
|
||||
if ( !m_hSprite2 )
|
||||
m_hSprite2 = gHUD.GetSprite( gHUD.GetSpriteIndex( "suit_full" ) );
|
||||
|
||||
SPR_Set(m_hSprite1, r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y - iOffset, m_prc1);
|
||||
|
||||
if (rc.bottom > rc.top)
|
||||
{
|
||||
SPR_Set(m_hSprite2, r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y - iOffset + (rc.top - m_prc2->top), &rc);
|
||||
}
|
||||
|
||||
x += (m_prc1->right - m_prc1->left);
|
||||
x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iBat, r, g, b);
|
||||
|
||||
return 1;
|
||||
}
|
24
cl_dll/camera.h
Normal file
24
cl_dll/camera.h
Normal file
@ -0,0 +1,24 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
// Camera.h -- defines and such for a 3rd person camera
|
||||
// NOTE: must include quakedef.h first
|
||||
|
||||
#ifndef _CAMERA_H_
|
||||
#define _CAMEA_H_
|
||||
|
||||
// pitch, yaw, dist
|
||||
extern vec3_t cam_ofs;
|
||||
// Using third person camera
|
||||
extern int cam_thirdperson;
|
||||
|
||||
void CAM_Init( void );
|
||||
void CAM_ClearStates( void );
|
||||
void CAM_StartMouseMove(void);
|
||||
void CAM_EndMouseMove(void);
|
||||
|
||||
#endif // _CAMERA_H_
|
344
cl_dll/cdll_int.cpp
Normal file
344
cl_dll/cdll_int.cpp
Normal file
@ -0,0 +1,344 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// cdll_int.c
|
||||
//
|
||||
// this implementation handles the linking of the engine to the DLL
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "netadr.h"
|
||||
#include "vgui_schememanager.h"
|
||||
|
||||
#include "pm_shared.h"
|
||||
#include "pm_defs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "hud_servers.h"
|
||||
#include "vgui_int.h"
|
||||
|
||||
int developer_level;
|
||||
int g_iXashEngineBuildNumber;
|
||||
BOOL g_fRenderInitialized = FALSE;
|
||||
BOOL g_fRenderInterfaceValid = FALSE;
|
||||
BOOL g_fXashEngine = FALSE;
|
||||
cl_enginefunc_t gEngfuncs;
|
||||
render_api_t gRenderfuncs;
|
||||
CHud gHUD;
|
||||
TeamFortressViewport *gViewPort = NULL;
|
||||
|
||||
void InitInput( void );
|
||||
void ShutdownInput( void );
|
||||
void EV_HookEvents( void );
|
||||
void IN_Commands( void );
|
||||
|
||||
/*
|
||||
==========================
|
||||
Initialize
|
||||
|
||||
Called when the DLL is first loaded.
|
||||
==========================
|
||||
*/
|
||||
extern "C"
|
||||
{
|
||||
int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion );
|
||||
int DLLEXPORT HUD_VidInit( void );
|
||||
void DLLEXPORT HUD_Init( void );
|
||||
void DLLEXPORT HUD_Shutdown( void );
|
||||
int DLLEXPORT HUD_Redraw( float flTime, int intermission );
|
||||
int DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime );
|
||||
void DLLEXPORT HUD_Reset ( void );
|
||||
void DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server );
|
||||
void DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove );
|
||||
char DLLEXPORT HUD_PlayerMoveTexture( char *name );
|
||||
int DLLEXPORT HUD_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
|
||||
void DLLEXPORT HUD_PostRunCmd( local_state_t *from, local_state_t *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int seed );
|
||||
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs );
|
||||
void DLLEXPORT HUD_Frame( double time );
|
||||
void DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking);
|
||||
void DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf );
|
||||
void DLLEXPORT HUD_ClipMoveToEntity( physent_t *pe, const float *start, float *mins, float *maxs, const float *end, pmtrace_t *tr );
|
||||
}
|
||||
|
||||
/*
|
||||
================================
|
||||
HUD_GetHullBounds
|
||||
|
||||
Engine calls this to enumerate player collision hulls, for prediction. Return 0 if the hullnumber doesn't exist.
|
||||
================================
|
||||
*/
|
||||
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs )
|
||||
{
|
||||
int iret = 0;
|
||||
|
||||
switch ( hullnumber )
|
||||
{
|
||||
case 0: // Normal player
|
||||
mins = Vector(-16, -16, -36);
|
||||
maxs = Vector(16, 16, 36);
|
||||
iret = 1;
|
||||
break;
|
||||
case 1: // Crouched player
|
||||
mins = Vector(-16, -16, -18 );
|
||||
maxs = Vector(16, 16, 18 );
|
||||
iret = 1;
|
||||
break;
|
||||
case 2: // Point based hull
|
||||
mins = Vector( 0, 0, 0 );
|
||||
maxs = Vector( 0, 0, 0 );
|
||||
iret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return iret;
|
||||
}
|
||||
|
||||
/*
|
||||
================================
|
||||
HUD_ConnectionlessPacket
|
||||
|
||||
Return 1 if the packet is valid. Set response_buffer_size if you want to send a response packet. Incoming, it holds the max
|
||||
size of the response_buffer, so you must zero it out if you choose not to respond.
|
||||
================================
|
||||
*/
|
||||
int DLLEXPORT HUD_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
|
||||
{
|
||||
// Parse stuff from args
|
||||
int max_buffer_size = *response_buffer_size;
|
||||
|
||||
// Zero it out since we aren't going to respond.
|
||||
// If we wanted to response, we'd write data into response_buffer
|
||||
*response_buffer_size = 0;
|
||||
|
||||
// Since we don't listen for anything here, just respond that it's a bogus message
|
||||
// If we didn't reject the message, we'd return 1 for success instead.
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove )
|
||||
{
|
||||
PM_Init( ppmove );
|
||||
}
|
||||
|
||||
char DLLEXPORT HUD_PlayerMoveTexture( char *name )
|
||||
{
|
||||
return (char)0;
|
||||
}
|
||||
|
||||
void DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server )
|
||||
{
|
||||
PM_Move( ppmove, server );
|
||||
}
|
||||
|
||||
int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion )
|
||||
{
|
||||
gEngfuncs = *pEnginefuncs;
|
||||
|
||||
if( iVersion != CLDLL_INTERFACE_VERSION )
|
||||
return 0;
|
||||
|
||||
memcpy( &gEngfuncs, pEnginefuncs, sizeof( cl_enginefunc_t ));
|
||||
|
||||
// get developer level
|
||||
developer_level = (int)CVAR_GET_FLOAT( "developer" );
|
||||
|
||||
if( CVAR_GET_POINTER( "host_clientloaded" ) != NULL )
|
||||
g_fXashEngine = TRUE;
|
||||
|
||||
g_iXashEngineBuildNumber = (int)CVAR_GET_FLOAT( "build" ); // 0 for old builds or GoldSrc
|
||||
if( g_iXashEngineBuildNumber <= 0 )
|
||||
g_iXashEngineBuildNumber = (int)CVAR_GET_FLOAT( "buildnum" );
|
||||
|
||||
EV_HookEvents();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_VidInit
|
||||
|
||||
Called when the game initializes
|
||||
and whenever the vid_mode is changed
|
||||
so the HUD can reinitialize itself.
|
||||
==========================
|
||||
*/
|
||||
int DLLEXPORT HUD_VidInit( void )
|
||||
{
|
||||
gHUD.VidInit();
|
||||
|
||||
VGui_Startup();
|
||||
|
||||
if( g_fXashEngine && g_fRenderInitialized )
|
||||
R_VidInit();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_Init
|
||||
|
||||
Called whenever the client connects
|
||||
to a server. Reinitializes all
|
||||
the hud variables.
|
||||
==========================
|
||||
*/
|
||||
void DLLEXPORT HUD_Init( void )
|
||||
{
|
||||
InitInput();
|
||||
|
||||
if( g_fXashEngine && g_fRenderInitialized )
|
||||
GL_Init();
|
||||
|
||||
gHUD.Init();
|
||||
Scheme_Init();
|
||||
}
|
||||
|
||||
void DLLEXPORT HUD_Shutdown( void )
|
||||
{
|
||||
ShutdownInput();
|
||||
|
||||
if( g_fXashEngine && g_fRenderInitialized )
|
||||
GL_Shutdown();
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_Redraw
|
||||
|
||||
called every screen frame to
|
||||
redraw the HUD.
|
||||
===========================
|
||||
*/
|
||||
int DLLEXPORT HUD_Redraw( float time, int intermission )
|
||||
{
|
||||
return gHUD.Redraw( time, intermission );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_UpdateClientData
|
||||
|
||||
called every time shared client
|
||||
dll/engine data gets changed,
|
||||
and gives the cdll a chance
|
||||
to modify the data.
|
||||
|
||||
returns 1 if anything has been changed, 0 otherwise.
|
||||
==========================
|
||||
*/
|
||||
int DLLEXPORT HUD_UpdateClientData(client_data_t *pcldata, float flTime )
|
||||
{
|
||||
IN_Commands();
|
||||
|
||||
return gHUD.UpdateClientData(pcldata, flTime );
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_Reset
|
||||
|
||||
Called at start and end of demos to restore to "non"HUD state.
|
||||
==========================
|
||||
*/
|
||||
void DLLEXPORT HUD_Reset( void )
|
||||
{
|
||||
gHUD.VidInit();
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_Frame
|
||||
|
||||
Called by engine every frame that client .dll is loaded
|
||||
==========================
|
||||
*/
|
||||
void DLLEXPORT HUD_Frame( double time )
|
||||
{
|
||||
ServersThink( time );
|
||||
|
||||
GetClientVoiceMgr()->Frame(time);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_VoiceStatus
|
||||
|
||||
Called when a player starts or stops talking.
|
||||
==========================
|
||||
*/
|
||||
void DLLEXPORT HUD_VoiceStatus( int entindex, qboolean bTalking )
|
||||
{
|
||||
GetClientVoiceMgr()->UpdateSpeakerStatus( entindex, bTalking );
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_DirectorEvent
|
||||
|
||||
Called when a director event message was received
|
||||
==========================
|
||||
*/
|
||||
void DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf )
|
||||
{
|
||||
gHUD.m_Spectator.DirectorMessage( iSize, pbuf );
|
||||
}
|
||||
|
||||
void DLLEXPORT HUD_PostRunCmd( local_state_t *from, local_state_t *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int seed )
|
||||
{
|
||||
to->client.fov = 0;//g_lastFOV; buz
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
HUD_ClipMoveToEntity
|
||||
|
||||
This called only for non-local clients (multiplayer)
|
||||
==========================
|
||||
*/
|
||||
void DLLEXPORT HUD_ClipMoveToEntity( physent_t *pe, const float *start, float *mins, float *maxs, const float *end, pmtrace_t *tr )
|
||||
{
|
||||
// convert physent_t to cl_entity_t
|
||||
cl_entity_t *pTouch = gEngfuncs.GetEntityByIndex( pe->info );
|
||||
trace_t trace;
|
||||
|
||||
if( !pTouch )
|
||||
{
|
||||
// removed entity?
|
||||
tr->allsolid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// make trace default
|
||||
memset( &trace, 0, sizeof( trace ));
|
||||
trace.allsolid = true;
|
||||
trace.fraction = 1.0f;
|
||||
trace.endpos = end;
|
||||
|
||||
Physic_SweepTest( pTouch, start, mins, maxs, end, &trace );
|
||||
|
||||
// convert trace_t into pmtrace_t
|
||||
memcpy( tr, &trace, 48 );
|
||||
tr->surf = trace.surf;
|
||||
|
||||
if( trace.ent != NULL && PM_GetPlayerMove( ))
|
||||
tr->ent = pe - PM_GetPlayerMove()->physents;
|
||||
else tr->ent = -1;
|
||||
}
|
929
cl_dll/cl_dll.dsp
Normal file
929
cl_dll/cl_dll.dsp
Normal file
@ -0,0 +1,929 @@
|
||||
# Microsoft Developer Studio Project File - Name="cl_dll" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=cl_dll - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "cl_dll.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "cl_dll.mak" CFG="cl_dll - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "cl_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "cl_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/GoldSrc/cl_dll", HGEBAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "cl_dll - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "..\temp\client\!release"
|
||||
# PROP Intermediate_Dir "..\temp\client\!release"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\utils\vgui\include" /I "..\engine" /I "..\common" /I "..\pm_shared" /I ".\render" /I ".\\" /I "..\game_shared" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 msvcrt.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib glu32.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /out:"..\temp\client\!release\client.dll"
|
||||
# SUBTRACT LINK32 /map /debug
|
||||
# Begin Custom Build
|
||||
TargetDir=\Paranoia2\src_main\temp\client\!release
|
||||
InputPath=\Paranoia2\src_main\temp\client\!release\client.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"D:\Paranoia2\base\bin\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\client.dll "D:\Paranoia2\base\bin\client.dll"
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "cl_dll - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "cl_dll___Win32_Debug"
|
||||
# PROP BASE Intermediate_Dir "cl_dll___Win32_Debug"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "..\temp\client\!debug"
|
||||
# PROP Intermediate_Dir "..\temp\client\!debug"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\utils\vgui\include" /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\dlls" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /Fr /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gi /GX /ZI /Od /I "..\utils\vgui\include" /I "..\engine" /I "..\common" /I "..\pm_shared" /I ".\render" /I ".\\" /I "..\game_shared" /D "WIN32" /D "DEBUG" /D "_DEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /FAs /FR /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /D "DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG" /d "DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib opengl32.lib cg.lib cgGL.lib /nologo /subsystem:windows /dll /map /debug /machine:I386 /out:".\Release\client.dll"
|
||||
# ADD LINK32 msvcrtd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:yes /debug /machine:I386 /nodefaultlib:"libcd.lib" /out:"..\temp\client\!debug\client.dll"
|
||||
# SUBTRACT LINK32 /map
|
||||
# Begin Custom Build
|
||||
TargetDir=\Paranoia2\src_main\temp\client\!debug
|
||||
InputPath=\Paranoia2\src_main\temp\client\!debug\client.dll
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"D:\Paranoia2\base\bin\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
copy $(TargetDir)\client.dll "D:\Paranoia2\base\bin\client.dll"
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "cl_dll - Win32 Release"
|
||||
# Name "cl_dll - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
# Begin Group "hl"
|
||||
|
||||
# PROP Default_Filter "*.CPP"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\bone_setup.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\common.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_cubemaps.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_deferred.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_dlight.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_framebuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_frustum.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_grass.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_lightmap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_occlusion.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_primitive.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_scene.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_shader.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_shadowmap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_slight.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_studio_draw.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_studio_init.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_studiodecal_new.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_studiovbo.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_subview.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_world_new.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\ikcontext.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\jigglebones.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\material.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\mathlib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\matrix.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\meshdesc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\pm_shared.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\procbones.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\stamina.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\stringlib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\trace.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_checkbutton2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_grid.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_helpers.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_listbox.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_loadtga.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_scrollbar2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_slider2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_banmgr.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_status.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_vgui_tweakdlg.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "render"
|
||||
|
||||
# PROP Default_Filter "*.CPP"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_aurora.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_backend.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_cull.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_debug.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_decals.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_export.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_movie.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_postprocess.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_rmain.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_rmisc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_rpart.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_rsurf.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_shadows.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_sky.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_sprite.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\rain.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\tri.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\view.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ammo.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ammo_secondary.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ammohistory.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\battery.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cdll_int.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\death.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\demo.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\entity.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ev_common.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ev_files.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ev_hldm.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\events.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\flashlight.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\geiger.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\health.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_msg.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_redraw.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_servers.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_spectator.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_update.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\in_camera.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\input.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\inputw32.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lensflare.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\menu.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\message.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\parsemsg.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\saytext.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\status_icons.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\statusbar.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\text_message.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\train.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ClassMenu.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ConsolePanel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ControlConfigPanel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_CustomObjects.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_gamma.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_hud.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_int.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_MOTDWindow.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_paranoiatext.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_radio.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_SchemeManager.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ScorePanel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ServerBrowser.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_SpectatorPanel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_subtitles.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_tabpanel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_TeamFortressViewport.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_teammenu.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_tips.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ammo.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ammohistory.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\bitvec.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\camera.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\cdll_dll.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cl_dll.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cl_util.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\clipfile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\com_weapons.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\cubemap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\custom_alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\demo.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\enginecallback.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ev_hldm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\eventscripts.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fmod_errors.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getfont.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_aurora.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_decals.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_export.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_framebuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_frustum.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_grass.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_local.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_occlusion.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_rpart.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_shader.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_sprite.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\gl_studio.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\health.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_iface.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_servers.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_servers_priv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hud_spectator.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\in_defs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\kbutton.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\material.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\matrix.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\meshdesc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\overview.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\parsemsg.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\pm_debug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\rain.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\stringlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\texture.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tf_defs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\pm_shared\trace.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\tri_stripper.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\utlarray.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\utlblockmemory.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\utllinkedlist.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\utlmemory.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vector.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\render\vertex_fmt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_checkbutton2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ConsolePanel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ControlConfigPanel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_defaultinputsignal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_gamma.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_grid.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_helpers.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_hud.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_int.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_listbox.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_loadtga.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_paranoiatext.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_pickup.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_radio.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_SchemeManager.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ScorePanel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_screenmsg.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_scrollbar2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_ServerBrowser.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_shadowtext.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\vgui_slider2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_SpectatorPanel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_subtitles.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_tabpanel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_TeamFortressViewport.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\vgui_tips.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_banmgr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_common.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_gamemgr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_status.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game_shared\voice_vgui_tweakdlg.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
49
cl_dll/cl_dll.h
Normal file
49
cl_dll/cl_dll.h
Normal file
@ -0,0 +1,49 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// cl_dll.h
|
||||
//
|
||||
|
||||
// 4-23-98 JOHN
|
||||
|
||||
//
|
||||
// This DLL is linked by the client when they first initialize.
|
||||
// This DLL is responsible for the following tasks:
|
||||
// - Loading the HUD graphics upon initialization
|
||||
// - Drawing the HUD graphics every frame
|
||||
// - Handling the custum HUD-update packets
|
||||
//
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
#include <vector.h>
|
||||
#define EXPORT _declspec( dllexport )
|
||||
|
||||
#include "../engine/cdll_int.h"
|
||||
#include "cdll_dll.h"
|
||||
|
||||
extern cl_enginefunc_t gEngfuncs;
|
||||
|
||||
#define CONPRINT (gEngfuncs.Con_Printf) //LRC - I can't live without printf!
|
||||
|
||||
//
|
||||
// gl_export.cpp
|
||||
//
|
||||
bool GL_Init( void );
|
||||
void GL_MapChanged( void );
|
||||
void GL_Shutdown( void );
|
||||
bool GL_Support( int r_ext );
|
||||
void R_VidInit( void );
|
319
cl_dll/cl_util.h
Normal file
319
cl_dll/cl_util.h
Normal file
@ -0,0 +1,319 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// cl_util.h
|
||||
//
|
||||
|
||||
#include "cvardef.h"
|
||||
|
||||
#define EXPORT _declspec( dllexport )
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
extern int developer_level;
|
||||
extern int r_currentMessageNum;
|
||||
|
||||
extern int g_iXashEngineBuildNumber;
|
||||
extern BOOL g_fRenderInitialized;
|
||||
extern BOOL g_fRenderInterfaceValid;
|
||||
extern BOOL g_fXashEngine;
|
||||
|
||||
enum
|
||||
{
|
||||
DEV_NONE = 0,
|
||||
DEV_NORMAL,
|
||||
DEV_EXTENDED
|
||||
};
|
||||
|
||||
typedef HMODULE dllhandle_t;
|
||||
|
||||
typedef struct dllfunc_s
|
||||
{
|
||||
const char *name;
|
||||
void **func;
|
||||
} dllfunc_t;
|
||||
|
||||
// misc cvars
|
||||
extern cvar_t *r_test; // just cvar for testify new effects
|
||||
extern cvar_t *r_stencilbits;
|
||||
extern cvar_t *r_drawentities;
|
||||
extern cvar_t *gl_extensions;
|
||||
extern cvar_t *cv_dynamiclight;
|
||||
extern cvar_t *r_detailtextures;
|
||||
extern cvar_t *r_lighting_ambient;
|
||||
extern cvar_t *r_lighting_modulate;
|
||||
extern cvar_t *r_lightstyle_lerping;
|
||||
extern cvar_t *r_lighting_extended;
|
||||
extern cvar_t *r_occlusion_culling;
|
||||
extern cvar_t *r_show_lightprobes;
|
||||
extern cvar_t *r_show_cubemaps;
|
||||
extern cvar_t *r_show_viewleaf;
|
||||
extern cvar_t *cv_crosshair;
|
||||
extern cvar_t *r_shadows;
|
||||
extern cvar_t *r_fullbright;
|
||||
extern cvar_t *r_draw_beams;
|
||||
extern cvar_t *r_overview;
|
||||
extern cvar_t *r_novis;
|
||||
extern cvar_t *r_nocull;
|
||||
extern cvar_t *r_lockpvs;
|
||||
extern cvar_t *r_dof;
|
||||
extern cvar_t *r_dof_hold_time;
|
||||
extern cvar_t *r_dof_change_time;
|
||||
extern cvar_t *r_dof_focal_length;
|
||||
extern cvar_t *r_dof_fstop;
|
||||
extern cvar_t *r_dof_debug;
|
||||
extern cvar_t *r_allow_mirrors;
|
||||
extern cvar_t *cv_renderer;
|
||||
extern cvar_t *cv_brdf;
|
||||
extern cvar_t *cv_bump;
|
||||
extern cvar_t *cv_specular;
|
||||
extern cvar_t *cv_parallax;
|
||||
extern cvar_t *cv_decals;
|
||||
extern cvar_t *cv_realtime_puddles;
|
||||
extern cvar_t *cv_shadow_offset;
|
||||
extern cvar_t *cv_cubemaps;
|
||||
extern cvar_t *cv_deferred;
|
||||
extern cvar_t *cv_deferred_full;
|
||||
extern cvar_t *cv_deferred_maxlights;
|
||||
extern cvar_t *cv_deferred_tracebmodels;
|
||||
extern cvar_t *cv_cube_lod_bias;
|
||||
extern cvar_t *cv_gamma;
|
||||
extern cvar_t *cv_brightness;
|
||||
extern cvar_t *cv_water;
|
||||
extern cvar_t *cv_decalsdebug;
|
||||
extern cvar_t *cv_show_tbn;
|
||||
extern cvar_t *cv_nosort;
|
||||
extern cvar_t *r_lightmap;
|
||||
extern cvar_t *r_speeds;
|
||||
extern cvar_t *r_decals;
|
||||
extern cvar_t *r_studio_decals;
|
||||
extern cvar_t *r_hand;
|
||||
extern cvar_t *r_sunshadows;
|
||||
extern cvar_t *r_sun_allowed;
|
||||
extern cvar_t *r_shadow_split_weight;
|
||||
extern cvar_t *r_wireframe;
|
||||
extern cvar_t *r_lightstyles;
|
||||
extern cvar_t *r_polyoffset;
|
||||
extern cvar_t *r_dynamic;
|
||||
extern cvar_t *r_finish;
|
||||
extern cvar_t *r_clear;
|
||||
extern cvar_t *r_grass;
|
||||
extern cvar_t *r_grass_alpha;
|
||||
extern cvar_t *r_grass_lighting;
|
||||
extern cvar_t *r_grass_shadows;
|
||||
extern cvar_t *r_grass_fade_start;
|
||||
extern cvar_t *r_grass_fade_dist;
|
||||
extern cvar_t *r_scissor_glass_debug;
|
||||
extern cvar_t *r_scissor_light_debug;
|
||||
extern cvar_t *r_showlightmaps;
|
||||
extern cvar_t *r_recursion_depth;
|
||||
extern cvar_t *r_shadowmap_size;
|
||||
extern cvar_t *r_pssm_show_split;
|
||||
extern cvar_t *v_sunshafts;
|
||||
extern cvar_t *v_glows;
|
||||
|
||||
extern "C" void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
|
||||
|
||||
// Macros to hook function calls into the HUD object
|
||||
#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x );
|
||||
|
||||
#define DECLARE_MESSAGE(y, x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \
|
||||
{ \
|
||||
return gHUD.##y.MsgFunc_##x(pszName, iSize, pbuf ); \
|
||||
}
|
||||
|
||||
|
||||
#define HOOK_COMMAND(x, y) gEngfuncs.pfnAddCommand( x, __CmdFunc_##y );
|
||||
#define DECLARE_COMMAND(y, x) void __CmdFunc_##x( void ) \
|
||||
{ \
|
||||
gHUD.##y.UserCmd_##x( ); \
|
||||
}
|
||||
|
||||
#define SPR_Set (*gEngfuncs.pfnSPR_Set)
|
||||
#define SPR_Frames (*gEngfuncs.pfnSPR_Frames)
|
||||
client_sprite_t *SPR2_GetList( char *psz, int *piCount ); // new version
|
||||
|
||||
// SPR_Draw draws a the current sprite as solid
|
||||
#define SPR_Draw (*gEngfuncs.pfnSPR_Draw)
|
||||
// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent)
|
||||
#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles)
|
||||
// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency)
|
||||
#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive)
|
||||
|
||||
// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen.
|
||||
#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor)
|
||||
// SPR_DisableScissor disables the clipping rect
|
||||
#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor)
|
||||
//
|
||||
#define FillRGBA (*gEngfuncs.pfnFillRGBA)
|
||||
|
||||
|
||||
// ScreenHeight returns the height of the screen, in pixels
|
||||
#define ScreenHeight (gHUD.m_scrinfo.iHeight)
|
||||
// ScreenWidth returns the width of the screen, in pixels
|
||||
#define ScreenWidth (gHUD.m_scrinfo.iWidth)
|
||||
|
||||
// Use this to set any co-ords in 640x480 space
|
||||
#define XRES(x) ((int)(float(x) * ((float)ScreenWidth / 640.0f) + 0.5f))
|
||||
#define YRES(y) ((int)(float(y) * ((float)ScreenHeight / 480.0f) + 0.5f))
|
||||
|
||||
// use this to project world coordinates to screen coordinates
|
||||
#define XPROJECT(x) ( (1.0f+(x))*ScreenWidth*0.5f )
|
||||
#define YPROJECT(y) ( (1.0f-(y))*ScreenHeight*0.5f )
|
||||
|
||||
#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
|
||||
#define ServerCmd (*gEngfuncs.pfnServerCmd)
|
||||
#define ClientCmd (*gEngfuncs.pfnClientCmd)
|
||||
#define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
|
||||
#define AngleVectors (*gEngfuncs.pfnAngleVectors)
|
||||
|
||||
inline int ConsoleStringLen( const char *string )
|
||||
{
|
||||
int _width, _height;
|
||||
GetConsoleStringSize( string, &_width, &_height );
|
||||
return _width;
|
||||
}
|
||||
|
||||
// returns the players name of entity no.
|
||||
#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo)
|
||||
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define fabs(x) ((x) > 0 ? (x) : 0 - (x))
|
||||
|
||||
void ScaleColors( int &r, int &g, int &b, int a );
|
||||
|
||||
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
|
||||
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
|
||||
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
|
||||
#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
|
||||
inline void VectorClear(float *a) { a[0]=0.0;a[1]=0.0;a[2]=0.0;}
|
||||
float Length(const float *v);
|
||||
void VectorMA (const float *veca, float scale, const float *vecb, float *vecc);
|
||||
void VectorScale (const float *in, float scale, float *out);
|
||||
float VectorNormalize (float *v);
|
||||
|
||||
extern vec3_t vec3_origin;
|
||||
extern struct ref_params_s *g_pViewParams;
|
||||
|
||||
// disable 'possible loss of data converting float to int' warning message
|
||||
#pragma warning( disable: 4244 )
|
||||
// disable 'truncation from 'const double' to 'float' warning message
|
||||
#pragma warning( disable: 4305 )
|
||||
|
||||
inline void UnpackRGB(int &r, int &g, int &b, unsigned long ulRGB)\
|
||||
{\
|
||||
r = (ulRGB & 0xFF0000) >>16;\
|
||||
g = (ulRGB & 0xFF00) >> 8;\
|
||||
b = ulRGB & 0xFF;\
|
||||
}
|
||||
|
||||
inline unsigned int PackRGBA( int r, int g, int b, int a )
|
||||
{
|
||||
r = bound( 0, r, 255 );
|
||||
g = bound( 0, g, 255 );
|
||||
b = bound( 0, b, 255 );
|
||||
a = bound( 0, a, 255 );
|
||||
|
||||
return ((a)<<24|(r)<<16|(g)<<8|(b));
|
||||
}
|
||||
|
||||
inline void UnpackRGBA( int &r, int &g, int &b, int &a, unsigned int ulRGBA )
|
||||
{
|
||||
a = (ulRGBA & 0xFF000000) >> 24;
|
||||
r = (ulRGBA & 0xFF0000) >> 16;
|
||||
g = (ulRGBA & 0xFF00) >> 8;
|
||||
b = (ulRGBA & 0xFF) >> 0;
|
||||
}
|
||||
|
||||
float PackColor( const color24 &color );
|
||||
color24 UnpackColor( float pack );
|
||||
|
||||
HSPRITE LoadSprite(const char *pszName);
|
||||
|
||||
#define CHECKVISBIT( vis, b ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] & (1 << ((b) & 7))) : (byte)false )
|
||||
#define SETVISBIT( vis, b )( void ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] |= (1 << ((b) & 7))) : (byte)false )
|
||||
#define CLEARVISBIT( vis, b )( void ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] &= ~(1 << ((b) & 7))) : (byte)false )
|
||||
|
||||
typedef struct leaflist_s
|
||||
{
|
||||
int count;
|
||||
int maxcount;
|
||||
bool overflowed;
|
||||
short *list;
|
||||
Vector mins, maxs;
|
||||
struct mnode_s *headnode; // for overflows where each leaf can't be stored individually
|
||||
} leaflist_t;
|
||||
|
||||
struct mleaf_s *Mod_PointInLeaf( const Vector &p, struct mnode_s *node );
|
||||
byte *Mod_LeafPVS( struct mleaf_s *leaf, struct model_s *model );
|
||||
byte *Mod_GetCurrentVis( void );
|
||||
bool Mod_BoxVisible( const Vector &mins, const Vector &maxs, const byte *visbits );
|
||||
bool Mod_CheckEntityPVS( cl_entity_t *ent );
|
||||
bool Mod_CheckTempEntityPVS( struct tempent_s *pTemp );
|
||||
bool Mod_CheckEntityLeafPVS( const Vector &absmin, const Vector &absmax, struct mleaf_s *leaf );
|
||||
bool Mod_CheckBoxVisible( const Vector &absmin, const Vector &absmax );
|
||||
void Mod_GetFrames( int modelIndex, int &numFrames );
|
||||
struct model_s *Mod_Handle( int modelIndex );
|
||||
bool Mod_PointInSolid( const Vector &p );
|
||||
int Mod_GetType( int modelIndex );
|
||||
extern void ParseRain( void );
|
||||
extern int CL_IsDead( void );
|
||||
void SetDLightVis( struct mworldlight_s *wl, int leafnum );
|
||||
void MergeDLightVis( struct mworldlight_s *wl, int leafnum );
|
||||
|
||||
bool UTIL_IsPlayer( int idx );
|
||||
bool UTIL_IsLocal( int idx );
|
||||
void UTIL_WeaponAnimation( int iAnim, float framerate );
|
||||
void UTIL_StudioDecal( const char *pDecalName, struct pmtrace_s *pTrace, const Vector &vecSrc );
|
||||
bool R_ScissorForAABB( const Vector &absmin, const Vector &absmax, float *x, float *y, float *w, float *h );
|
||||
bool R_AABBToScreen( const Vector &absmin, const Vector &absmax, Vector2D &scrmin, Vector2D &scrmax, wrect_t *rect = NULL );
|
||||
bool R_ScissorForFrustum( class CFrustum *frustum, float *x, float *y, float *w, float *h );
|
||||
void R_DrawScissorRectangle( float x, float y, float w, float h );
|
||||
int WorldToScreen( const Vector &world, Vector &screen );
|
||||
void R_TransformWorldToDevice( const Vector &world, Vector &ndc );
|
||||
void R_TransformDeviceToScreen( const Vector &ndc, Vector &screen );
|
||||
float ComputePixelWidthOfSphere( const Vector& vecOrigin, float flRadius );
|
||||
|
||||
bool R_SkyIsVisible( void );
|
||||
|
||||
bool R_ClipPolygon( int numPoints, Vector *points, const struct mplane_s *plane, int *numClipped, Vector *clipped );
|
||||
void R_SplitPolygon( int numPoints, Vector *points, const struct mplane_s *plane, int *numFront, Vector *front, int *numBack, Vector *back );
|
||||
|
||||
// dll managment
|
||||
bool Sys_LoadLibrary( const char *dllname, dllhandle_t *handle, const dllfunc_t *fcts = NULL );
|
||||
void *Sys_GetProcAddress( dllhandle_t handle, const char *name );
|
||||
void Sys_FreeLibrary( dllhandle_t *handle );
|
||||
bool Sys_RemoveFile( const char *path );
|
||||
|
||||
void UTIL_CreateAurora( cl_entity_t *ent, const char *file, int attachment, float lifetime = 0.0f );
|
||||
void UTIL_RemoveAurora( cl_entity_t *ent );
|
||||
|
||||
extern void AngleMatrix (const float *angles, float (*matrix)[4] );
|
||||
extern void VectorTransform (const float *in1, float in2[3][4], float *out);
|
||||
extern void SetPoint( float x, float y, float z, float (*matrix)[4]);
|
||||
extern void CreateDecal( const Vector &p, const Vector &n, float ang, const char *sz, int flags = 0, int eIdx = 0, int mIdx = 0, bool source = true );
|
||||
extern void CreateDecal( struct pmtrace_s *tr, const char *name, float angle, bool visent = false );
|
||||
|
||||
extern void Physic_SweepTest( struct cl_entity_s *pTouch, const Vector &start, const Vector &mins, const Vector &maxs, const Vector &end, trace_t *tr );
|
||||
|
||||
extern void BuildGammaTable( void );
|
||||
extern float TextureToLinear( int c );
|
||||
extern int LinearToTexture( float f );
|
||||
extern void GL_GpuMemUsage_f( void );
|
108
cl_dll/custom_alloc.h
Normal file
108
cl_dll/custom_alloc.h
Normal file
@ -0,0 +1,108 @@
|
||||
/************************************
|
||||
simple memory allocator
|
||||
by BUzer
|
||||
************************************/
|
||||
|
||||
template <class T>
|
||||
class MemBlock
|
||||
{
|
||||
typedef struct chunk_s {
|
||||
int next;
|
||||
T data;
|
||||
} chunk_t;
|
||||
|
||||
public:
|
||||
MemBlock(int numElements)
|
||||
{
|
||||
// ýëåìåíò 0 èñïîëüçóåòñÿ â êà÷åñòâå íà÷àëà ñïèñêà çàíÿòûõ ÿ÷ååê
|
||||
m_iArraySize = numElements + 1;
|
||||
m_pArray = new chunk_t[m_iArraySize];
|
||||
|
||||
if (!m_pArray)
|
||||
{
|
||||
m_iArraySize = 1;
|
||||
m_iFirstFree = m_iArraySize;
|
||||
return;
|
||||
}
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
~MemBlock()
|
||||
{
|
||||
delete[] m_pArray;
|
||||
m_pArray = NULL;
|
||||
}
|
||||
|
||||
void Clear( void )
|
||||
{
|
||||
if (m_iArraySize > 1)
|
||||
{
|
||||
m_pArray[0].next = 0; // åñëè îí ññûëàåòñÿ ñàì íà ñåáÿ, çíà÷èò ñïèñîê çàíÿòûõ ïóñò
|
||||
m_iFirstFree = 1;
|
||||
|
||||
for (int i = 1; i < m_iArraySize; ++i)
|
||||
m_pArray[i].next = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
T* Allocate( void )
|
||||
{
|
||||
if (m_iFirstFree != m_iArraySize)
|
||||
{
|
||||
int savedFirstFree = m_pArray[m_iFirstFree].next;
|
||||
m_pArray[m_iFirstFree].next = m_pArray[0].next; // äîáàâëÿåì ñâîáîäíóþ ÿ÷åéêó â
|
||||
m_pArray[0].next = m_iFirstFree; // ñïèñîê çàíÿòûõ
|
||||
m_iFirstFree = savedFirstFree; // èñêëþ÷àåì ÿ÷åéêó èç ñïèñêà ñâîáîäíûõ
|
||||
return &(m_pArray[m_pArray[0].next].data);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool IsClear( void )
|
||||
{
|
||||
return m_pArray[0].next ? false : true;
|
||||
}
|
||||
|
||||
bool StartPass( void )
|
||||
{
|
||||
m_iCurrent = 0; // íà÷èíàåì îáõîä ñ íóëåâîãî ýëåìåíòà
|
||||
|
||||
if (m_iArraySize > 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
T* GetCurrent( void )
|
||||
{
|
||||
int retindex = m_pArray[m_iCurrent].next;
|
||||
if (!retindex)
|
||||
return NULL;
|
||||
|
||||
return &(m_pArray[retindex].data);
|
||||
}
|
||||
|
||||
void MoveNext( void )
|
||||
{
|
||||
m_iCurrent = m_pArray[m_iCurrent].next;
|
||||
}
|
||||
|
||||
void DeleteCurrent( void )
|
||||
{
|
||||
int delindex = m_pArray[m_iCurrent].next;
|
||||
m_pArray[m_iCurrent].next = m_pArray[delindex].next; // âûáðàñûâàåì ýëåìåíò èç öåïè çàíÿòûõ
|
||||
m_pArray[delindex].next = m_iFirstFree;
|
||||
m_iFirstFree = delindex; // âêëþ÷àåì ýëåìåíò â íà÷àëî öåïè ñâîáîäíûõ
|
||||
}
|
||||
|
||||
private:
|
||||
chunk_t *m_pArray;
|
||||
int m_iArraySize;
|
||||
int m_iCurrent; // äëÿ ïðîõîæäåíèÿ ÷åðåç ìàññèâ
|
||||
|
||||
int m_iFirstFree; // íà÷àëî ñïèñêà ñâîáîäíûõ ýëåìåíòîâ
|
||||
};
|
||||
|
||||
|
297
cl_dll/death.cpp
Normal file
297
cl_dll/death.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// death notice
|
||||
//
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vgui_TeamFortressViewport.h"
|
||||
|
||||
DECLARE_MESSAGE( m_DeathNotice, DeathMsg );
|
||||
|
||||
struct DeathNoticeItem {
|
||||
char szKiller[MAX_PLAYER_NAME_LENGTH*2];
|
||||
char szVictim[MAX_PLAYER_NAME_LENGTH*2];
|
||||
int iId; // the index number of the associated sprite
|
||||
int iSuicide;
|
||||
int iTeamKill;
|
||||
int iNonPlayerKill;
|
||||
float flDisplayTime;
|
||||
float *KillerColor;
|
||||
float *VictimColor;
|
||||
};
|
||||
|
||||
#define MAX_DEATHNOTICES 4
|
||||
static int DEATHNOTICE_DISPLAY_TIME = 6;
|
||||
|
||||
#define DEATHNOTICE_TOP 32
|
||||
|
||||
DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ];
|
||||
|
||||
float g_ColorBlue[3] = { 0.6, 0.8, 1.0 };
|
||||
float g_ColorRed[3] = { 1.0, 0.25, 0.25 };
|
||||
float g_ColorGreen[3] = { 0.6, 1.0, 0.6 };
|
||||
float g_ColorYellow[3] = { 1.0, 0.7, 0.0 };
|
||||
float g_ColorGrey[3] = { 0.8, 0.8, 0.8 };
|
||||
|
||||
float *GetClientColor( int clientIndex )
|
||||
{
|
||||
switch ( g_PlayerExtraInfo[clientIndex].teamnumber )
|
||||
{
|
||||
case 1: return g_ColorBlue;
|
||||
case 2: return g_ColorRed;
|
||||
case 3: return g_ColorYellow;
|
||||
case 4: return g_ColorGreen;
|
||||
case 0: return g_ColorYellow;
|
||||
|
||||
default : return g_ColorGrey;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CHudDeathNotice :: Init( void )
|
||||
{
|
||||
gHUD.AddHudElem( this );
|
||||
|
||||
HOOK_MESSAGE( DeathMsg );
|
||||
|
||||
CVAR_REGISTER( "hud_deathnotice_time", "6", 0 );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CHudDeathNotice :: InitHUDData( void )
|
||||
{
|
||||
memset( rgDeathNoticeList, 0, sizeof(rgDeathNoticeList) );
|
||||
}
|
||||
|
||||
|
||||
int CHudDeathNotice :: VidInit( void )
|
||||
{
|
||||
m_HUD_d_skull = gHUD.GetSpriteIndex( "d_skull" );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudDeathNotice :: Draw( float flTime )
|
||||
{
|
||||
int x, y, r, g, b;
|
||||
|
||||
for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
|
||||
{
|
||||
if ( rgDeathNoticeList[i].iId == 0 )
|
||||
break; // we've gone through them all
|
||||
|
||||
if ( rgDeathNoticeList[i].flDisplayTime < flTime )
|
||||
{ // display time has expired
|
||||
// remove the current item from the list
|
||||
memmove( &rgDeathNoticeList[i], &rgDeathNoticeList[i+1], sizeof(DeathNoticeItem) * (MAX_DEATHNOTICES - i) );
|
||||
i--; // continue on the next item; stop the counter getting incremented
|
||||
continue;
|
||||
}
|
||||
|
||||
rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME );
|
||||
|
||||
// Only draw if the viewport will let me
|
||||
if ( gViewPort && gViewPort->AllowedToPrintText() )
|
||||
{
|
||||
// Draw the death notice
|
||||
y = YRES(DEATHNOTICE_TOP) + 2 + (20 * i); //!!!
|
||||
|
||||
int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
|
||||
x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
|
||||
|
||||
if ( !rgDeathNoticeList[i].iSuicide )
|
||||
{
|
||||
x -= (5 + ConsoleStringLen( rgDeathNoticeList[i].szKiller ) );
|
||||
|
||||
// Draw killers name
|
||||
if ( rgDeathNoticeList[i].KillerColor )
|
||||
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
|
||||
x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
|
||||
}
|
||||
|
||||
r = 255; g = 80; b = 0;
|
||||
if ( rgDeathNoticeList[i].iTeamKill )
|
||||
{
|
||||
r = 10; g = 240; b = 10; // display it in sickly green
|
||||
}
|
||||
|
||||
// Draw death weapon
|
||||
SPR_Set( gHUD.GetSprite(id), r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(id) );
|
||||
|
||||
x += (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
|
||||
|
||||
// Draw victims name (if it was a player that was killed)
|
||||
if (rgDeathNoticeList[i].iNonPlayerKill == FALSE)
|
||||
{
|
||||
if ( rgDeathNoticeList[i].VictimColor )
|
||||
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
|
||||
x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This message handler may be better off elsewhere
|
||||
int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
int killer = READ_BYTE();
|
||||
int victim = READ_BYTE();
|
||||
|
||||
char killedwith[32];
|
||||
strcpy( killedwith, "d_" );
|
||||
strncat( killedwith, READ_STRING(), 32 );
|
||||
|
||||
if (gViewPort)
|
||||
gViewPort->DeathMsg( killer, victim );
|
||||
|
||||
gHUD.m_Spectator.DeathMessage(victim);
|
||||
|
||||
for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
|
||||
{
|
||||
if ( rgDeathNoticeList[i].iId == 0 )
|
||||
break;
|
||||
}
|
||||
if ( i == MAX_DEATHNOTICES )
|
||||
{ // move the rest of the list forward to make room for this item
|
||||
memmove( rgDeathNoticeList, rgDeathNoticeList+1, sizeof(DeathNoticeItem) * MAX_DEATHNOTICES );
|
||||
i = MAX_DEATHNOTICES - 1;
|
||||
}
|
||||
|
||||
if (gViewPort)
|
||||
gViewPort->GetAllPlayersInfo();
|
||||
|
||||
// Get the Killer's name
|
||||
char *killer_name = g_PlayerInfoList[ killer ].name;
|
||||
if ( !killer_name )
|
||||
{
|
||||
killer_name = "";
|
||||
rgDeathNoticeList[i].szKiller[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rgDeathNoticeList[i].KillerColor = GetClientColor( killer );
|
||||
strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
|
||||
rgDeathNoticeList[i].szKiller[MAX_PLAYER_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
// Get the Victim's name
|
||||
char *victim_name = NULL;
|
||||
// If victim is -1, the killer killed a specific, non-player object (like a sentrygun)
|
||||
if ( ((char)victim) != -1 )
|
||||
victim_name = g_PlayerInfoList[ victim ].name;
|
||||
if ( !victim_name )
|
||||
{
|
||||
victim_name = "";
|
||||
rgDeathNoticeList[i].szVictim[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rgDeathNoticeList[i].VictimColor = GetClientColor( victim );
|
||||
strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
|
||||
rgDeathNoticeList[i].szVictim[MAX_PLAYER_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
// Is it a non-player object kill?
|
||||
if ( ((char)victim) == -1 )
|
||||
{
|
||||
rgDeathNoticeList[i].iNonPlayerKill = TRUE;
|
||||
|
||||
// Store the object's name in the Victim slot (skip the d_ bit)
|
||||
strcpy( rgDeathNoticeList[i].szVictim, killedwith+2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( killer == victim || killer == 0 )
|
||||
rgDeathNoticeList[i].iSuicide = TRUE;
|
||||
|
||||
if ( !strcmp( killedwith, "d_teammate" ) )
|
||||
rgDeathNoticeList[i].iTeamKill = TRUE;
|
||||
}
|
||||
|
||||
// Find the sprite in the list
|
||||
int spr = gHUD.GetSpriteIndex( killedwith );
|
||||
|
||||
rgDeathNoticeList[i].iId = spr;
|
||||
|
||||
DEATHNOTICE_DISPLAY_TIME = CVAR_GET_FLOAT( "hud_deathnotice_time" );
|
||||
rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME;
|
||||
|
||||
if (rgDeathNoticeList[i].iNonPlayerKill)
|
||||
{
|
||||
ConsolePrint( rgDeathNoticeList[i].szKiller );
|
||||
ConsolePrint( " killed a " );
|
||||
ConsolePrint( rgDeathNoticeList[i].szVictim );
|
||||
ConsolePrint( "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// record the death notice in the console
|
||||
if ( rgDeathNoticeList[i].iSuicide )
|
||||
{
|
||||
ConsolePrint( rgDeathNoticeList[i].szVictim );
|
||||
|
||||
if ( !strcmp( killedwith, "d_world" ) )
|
||||
{
|
||||
ConsolePrint( " died" );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsolePrint( " killed self" );
|
||||
}
|
||||
}
|
||||
else if ( rgDeathNoticeList[i].iTeamKill )
|
||||
{
|
||||
ConsolePrint( rgDeathNoticeList[i].szKiller );
|
||||
ConsolePrint( " killed his teammate " );
|
||||
ConsolePrint( rgDeathNoticeList[i].szVictim );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsolePrint( rgDeathNoticeList[i].szKiller );
|
||||
ConsolePrint( " killed " );
|
||||
ConsolePrint( rgDeathNoticeList[i].szVictim );
|
||||
}
|
||||
|
||||
if ( killedwith && *killedwith && (*killedwith > 13 ) && strcmp( killedwith, "d_world" ) && !rgDeathNoticeList[i].iTeamKill )
|
||||
{
|
||||
ConsolePrint( " with " );
|
||||
ConsolePrint( killedwith+2 ); // skip over the "d_" part
|
||||
}
|
||||
|
||||
ConsolePrint( "\n" );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
103
cl_dll/demo.cpp
Normal file
103
cl_dll/demo.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "demo.h"
|
||||
#include "demo_api.h"
|
||||
#include <memory.h>
|
||||
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
int g_demosniper = 0;
|
||||
int g_demosniperdamage = 0;
|
||||
float g_demosniperorg[3];
|
||||
float g_demosniperangles[3];
|
||||
float g_demozoom;
|
||||
|
||||
// FIXME: There should be buffer helper functions to avoid all of the *(int *)& crap.
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
Demo_WriteBuffer
|
||||
|
||||
Write some data to the demo stream
|
||||
=====================
|
||||
*/
|
||||
void Demo_WriteBuffer( int type, int size, unsigned char *buffer )
|
||||
{
|
||||
int pos = 0;
|
||||
unsigned char buf[ 32 * 1024 ];
|
||||
*( int * )&buf[pos] = type;
|
||||
pos+=sizeof( int );
|
||||
|
||||
memcpy( &buf[pos], buffer, size );
|
||||
|
||||
// Write full buffer out
|
||||
gEngfuncs.pDemoAPI->WriteBuffer( size + sizeof( int ), buf );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
Demo_ReadBuffer
|
||||
|
||||
Engine wants us to parse some data from the demo stream
|
||||
=====================
|
||||
*/
|
||||
void DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer )
|
||||
{
|
||||
int type;
|
||||
int i = 0;
|
||||
|
||||
type = *( int * )buffer;
|
||||
i += sizeof( int );
|
||||
switch ( type )
|
||||
{
|
||||
case TYPE_SNIPERDOT:
|
||||
g_demosniper = *(int * )&buffer[ i ];
|
||||
i += sizeof( int );
|
||||
|
||||
if ( g_demosniper )
|
||||
{
|
||||
g_demosniperdamage = *( int * )&buffer[ i ];
|
||||
i += sizeof( int );
|
||||
|
||||
g_demosniperangles[ 0 ] = *(float *)&buffer[i];
|
||||
i += sizeof( float );
|
||||
g_demosniperangles[ 1 ] = *(float *)&buffer[i];
|
||||
i += sizeof( float );
|
||||
g_demosniperangles[ 2 ] = *(float *)&buffer[i];
|
||||
i += sizeof( float );
|
||||
g_demosniperorg[ 0 ] = *(float *)&buffer[i];
|
||||
i += sizeof( float );
|
||||
g_demosniperorg[ 1 ] = *(float *)&buffer[i];
|
||||
i += sizeof( float );
|
||||
g_demosniperorg[ 2 ] = *(float *)&buffer[i];
|
||||
i += sizeof( float );
|
||||
}
|
||||
break;
|
||||
case TYPE_ZOOM:
|
||||
g_demozoom = *(float * )&buffer[ i ];
|
||||
i += sizeof( float );
|
||||
break;
|
||||
default:
|
||||
gEngfuncs.Con_DPrintf( "Unknown demo buffer type, skipping.\n" );
|
||||
break;
|
||||
}
|
||||
}
|
27
cl_dll/demo.h
Normal file
27
cl_dll/demo.h
Normal file
@ -0,0 +1,27 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined( DEMOH )
|
||||
#define DEMOH
|
||||
#pragma once
|
||||
|
||||
// Types of demo messages we can write/parse
|
||||
enum
|
||||
{
|
||||
TYPE_SNIPERDOT = 0,
|
||||
TYPE_ZOOM
|
||||
};
|
||||
|
||||
void Demo_WriteBuffer( int type, int size, unsigned char *buffer );
|
||||
|
||||
extern int g_demosniper;
|
||||
extern int g_demosniperdamage;
|
||||
extern float g_demosniperorg[3];
|
||||
extern float g_demosniperangles[3];
|
||||
extern float g_demozoom;
|
||||
|
||||
#endif
|
173
cl_dll/enginecallback.h
Normal file
173
cl_dll/enginecallback.h
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
enginecallback.h - actual engine callbacks
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef ENGINECALLBACK_H
|
||||
#define ENGINECALLBACK_H
|
||||
|
||||
extern cl_enginefunc_t gEngfuncs;
|
||||
extern render_api_t gRenderfuncs;
|
||||
|
||||
#define GET_CLIENT_TIME (*gEngfuncs.GetClientTime)
|
||||
#define GET_CLIENT_OLDTIME (*gEngfuncs.GetClientOldTime)
|
||||
#define CVAR_REGISTER (*gEngfuncs.pfnRegisterVariable)
|
||||
#define CVAR_GET_FLOAT (*gEngfuncs.pfnGetCvarFloat)
|
||||
#define CVAR_GET_STRING (*gEngfuncs.pfnGetCvarString)
|
||||
#define CVAR_SET_FLOAT (*gEngfuncs.Cvar_SetValue)
|
||||
//#define CVAR_SET_STRING (*gEngfuncs.pfnCVarSetString) // not implemented
|
||||
#define CVAR_GET_POINTER (*gEngfuncs.pfnGetCvarPointer)
|
||||
#define ADD_COMMAND (*gEngfuncs.pfnAddCommand)
|
||||
#define CMD_ARGC (*gEngfuncs.Cmd_Argc)
|
||||
#define CMD_ARGV (*gEngfuncs.Cmd_Argv)
|
||||
#define Msg (*gEngfuncs.Con_Printf)
|
||||
|
||||
#define GET_LOCAL_PLAYER (*gEngfuncs.GetLocalPlayer)
|
||||
#define GET_VIEWMODEL (*gEngfuncs.GetViewModel)
|
||||
#define GET_ENTITY (*gEngfuncs.GetEntityByIndex)
|
||||
|
||||
#define POINT_CONTENTS( p ) (*gEngfuncs.PM_PointContents)( p, NULL )
|
||||
#define WATER_ENTITY (*gEngfuncs.PM_WaterEntity)
|
||||
#define RANDOM_LONG (*gEngfuncs.pfnRandomLong)
|
||||
#define RANDOM_FLOAT (*gEngfuncs.pfnRandomFloat)
|
||||
|
||||
#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo)
|
||||
#define ServerCmd (*gEngfuncs.pfnServerCmd)
|
||||
#define ClientCmd (*gEngfuncs.pfnClientCmd)
|
||||
#define SetCrosshair (*gEngfuncs.pfnSetCrosshair)
|
||||
#define AngleVectors (*gEngfuncs.pfnAngleVectors)
|
||||
#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo)
|
||||
|
||||
#define SPR_Load (*gEngfuncs.pfnSPR_Load)
|
||||
#define SPR_Set (*gEngfuncs.pfnSPR_Set)
|
||||
#define SPR_Frames (*gEngfuncs.pfnSPR_Frames)
|
||||
#define SPR_Draw (*gEngfuncs.pfnSPR_Draw)
|
||||
#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles)
|
||||
#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive)
|
||||
#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor)
|
||||
#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor)
|
||||
#define FillRGBA (*gEngfuncs.pfnFillRGBA)
|
||||
#define SPR_Height (*gEngfuncs.pfnSPR_Height)
|
||||
#define SPR_Width (*gEngfuncs.pfnSPR_Width)
|
||||
#define SPR_GetList (*gEngfuncs.pfnSPR_GetList)
|
||||
#define SPR_LoadEx (*gRenderfuncs.SPR_LoadExt)
|
||||
|
||||
#define ConsolePrint (*gEngfuncs.pfnConsolePrint)
|
||||
#define CenterPrint (*gEngfuncs.pfnCenterPrint)
|
||||
#define TextMessageGet (*gEngfuncs.pfnTextMessageGet)
|
||||
#define TextMessageDrawChar (*gEngfuncs.pfnDrawCharacter)
|
||||
#define DrawConsoleString (*gEngfuncs.pfnDrawConsoleString)
|
||||
#define GetConsoleStringSize (*gEngfuncs.pfnDrawConsoleStringLen)
|
||||
#define DrawSetTextColor (*gEngfuncs.pfnDrawSetTextColor)
|
||||
|
||||
#define LOAD_FILE( x, y ) (*gEngfuncs.COM_LoadFile)( x, 5, y )
|
||||
#define FREE_FILE (*gEngfuncs.COM_FreeFile)
|
||||
#define SAVE_FILE (*gRenderfuncs.pfnSaveFile)
|
||||
|
||||
#define Sys_DoubleTime (*gRenderfuncs.pfnTime)
|
||||
|
||||
// sound functions (we can't use macroses - this names is collide with standard windows methods)
|
||||
inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); }
|
||||
inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); }
|
||||
|
||||
// render api callbacks
|
||||
#define RENDER_GET_PARM (*gRenderfuncs.RenderGetParm)
|
||||
#define SET_CURRENT_ENTITY (*gRenderfuncs.R_SetCurrentEntity)
|
||||
#define SET_CURRENT_MODEL (*gRenderfuncs.R_SetCurrentModel)
|
||||
#define ENGINE_SET_PVS (*gRenderfuncs.R_FatPVS)
|
||||
#define HOST_ERROR (*gRenderfuncs.Host_Error)
|
||||
#define GET_LIGHTSTYLE (*gRenderfuncs.GetLightStyle)
|
||||
#define GET_DYNAMIC_LIGHT (*gRenderfuncs.GetDynamicLight)
|
||||
#define GET_ENTITY_LIGHT (*gRenderfuncs.GetEntityLight)
|
||||
#define TEXTURE_TO_TEXGAMMA (*gRenderfuncs.LightToTexGamma)
|
||||
#define GET_FRAMETIME (*gRenderfuncs.GetFrameTime)
|
||||
#define DRAW_SINGLE_DECAL (*gRenderfuncs.DrawSingleDecal)
|
||||
#define DECAL_SETUP_VERTS (*gRenderfuncs.R_DecalSetupVerts)
|
||||
#define GET_DETAIL_SCALE (*gRenderfuncs.GetDetailScaleForTexture)
|
||||
#define GET_EXTRA_PARAMS (*gRenderfuncs.GetExtraParmsForTexture)
|
||||
#define CREATE_TEXTURE (*gRenderfuncs.GL_CreateTexture)
|
||||
#define FIND_TEXTURE (*gRenderfuncs.GL_FindTexture)
|
||||
#define FREE_TEXTURE (*gRenderfuncs.GL_FreeTexture)
|
||||
#define CREATE_TEXTURE_ARRAY (*gRenderfuncs.GL_CreateTextureArray)
|
||||
#define STORE_EFRAGS (*gRenderfuncs.R_StoreEfrags)
|
||||
#define INIT_BEAMCHAINS (*gRenderfuncs.GetBeamChains)
|
||||
#define DRAW_PARTICLES (*gRenderfuncs.GL_DrawParticles)
|
||||
#define SET_ENGINE_WORLDVIEW_MATRIX (*gRenderfuncs.GL_SetWorldviewProjectionMatrix)
|
||||
#define GET_FOG_PARAMS (*gRenderfuncs.GetExtraParmsForTexture)
|
||||
#define GET_TEXTURE_NAME (*gRenderfuncs.GL_TextureName)
|
||||
#define GET_TEXTURE_DATA (*gRenderfuncs.GL_TextureData)
|
||||
#define COMPARE_FILE_TIME (*gRenderfuncs.COM_CompareFileTime)
|
||||
#define REMOVE_BSP_DECALS (*gRenderfuncs.R_EntityRemoveDecals)
|
||||
#define STUDIO_GET_TEXTURE (*gRenderfuncs.StudioGetTexture)
|
||||
#define GET_OVERVIEW_PARMS (*gRenderfuncs.GetOverviewParms)
|
||||
#define FS_SEARCH (*gRenderfuncs.pfnGetFilesList)
|
||||
#define ENV_SHOT (*gRenderfuncs.EnvShot)
|
||||
|
||||
#define LOAD_TEXTURE (*gRenderfuncs.GL_LoadTexture)
|
||||
#define LOAD_TEXTURE_ARRAY (*gRenderfuncs.GL_LoadTextureArray)
|
||||
|
||||
// AVIKit interface
|
||||
#define OPEN_CINEMATIC (*gRenderfuncs.AVI_LoadVideo)
|
||||
#define FREE_CINEMATIC (*gRenderfuncs.AVI_FreeVideo)
|
||||
#define CIN_IS_ACTIVE (*gRenderfuncs.AVI_IsActive)
|
||||
#define CIN_GET_VIDEO_INFO (*gRenderfuncs.AVI_GetVideoInfo)
|
||||
#define CIN_GET_FRAME_NUMBER (*gRenderfuncs.AVI_GetVideoFrameNumber)
|
||||
#define CIN_GET_FRAMEDATA (*gRenderfuncs.AVI_GetVideoFrame)
|
||||
#define CIN_UPLOAD_FRAME (*gRenderfuncs.AVI_UploadRawFrame)
|
||||
#define CIN_UPDATE_SOUND (*gRenderfuncs.AVI_StreamSound)
|
||||
|
||||
// glcommands
|
||||
#define GL_BindTexture (*gRenderfuncs.GL_Bind)
|
||||
#define GL_SelectTexture (*gRenderfuncs.GL_SelectTexture)
|
||||
#define GL_TexGen (*gRenderfuncs.GL_TexGen)
|
||||
#define GL_LoadTextureMatrix (*gRenderfuncs.GL_LoadTextureMatrix)
|
||||
#define GL_LoadIdentityTexMatrix (*gRenderfuncs.GL_TexMatrixIdentity)
|
||||
#define GL_CleanUpTextureUnits (*gRenderfuncs.GL_CleanUpTextureUnits)
|
||||
#define GL_TexCoordArrayMode (*gRenderfuncs.GL_TexCoordArrayMode)
|
||||
#define GL_TextureTarget (*gRenderfuncs.GL_TextureTarget)
|
||||
#define GL_UpdateTexSize (*gRenderfuncs.GL_UpdateTexSize)
|
||||
|
||||
#define RANDOM_SEED (*gRenderfuncs.SetRandomSeed)
|
||||
#define MUSIC_FADE_VOLUME (*gRenderfuncs.S_FadeMusicVolume)
|
||||
|
||||
#define GL_GetProcAddress (*gRenderfuncs.GL_GetProcAddress)
|
||||
|
||||
#define MODEL_HANDLE (*gRenderfuncs.pfnGetModel)
|
||||
|
||||
// built-in memory manager
|
||||
#define Mem_Alloc( x ) (*gRenderfuncs.pfnMemAlloc)( x, __FILE__, __LINE__ )
|
||||
#define Mem_Free( x ) (*gRenderfuncs.pfnMemFree)( x, __FILE__, __LINE__ )
|
||||
#define _Mem_Alloc (*gRenderfuncs.pfnMemAlloc)
|
||||
#define _Mem_Free (*gRenderfuncs.pfnMemFree)
|
||||
|
||||
#define ASSERT( exp ) if(!( exp )) HOST_ERROR( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
|
||||
#define IMAGE_EXISTS( path ) ( FILE_EXISTS( va( "%s.tga", path )) || FILE_EXISTS( va( "%s.dds", path )))
|
||||
|
||||
extern void ALERT( ALERT_TYPE level, char *szFmt, ... );
|
||||
|
||||
inline bool FILE_EXISTS( const char *filename )
|
||||
{
|
||||
int iCompare;
|
||||
|
||||
// verify file exists
|
||||
// g-cont. idea! use COMPARE_FILE_TIME instead of COM_LoadFile
|
||||
if( COMPARE_FILE_TIME( filename, filename, &iCompare ))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#define FILE_CRC32 (*gRenderfuncs.pfnFileBufferCRC32)
|
||||
#define GET_MAX_CLIENTS (*gEngfuncs.GetMaxClients)
|
||||
|
||||
#endif//ENGINECALLBACK_H
|
937
cl_dll/entity.cpp
Normal file
937
cl_dll/entity.cpp
Normal file
@ -0,0 +1,937 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
// Client side entity management functions
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "entity_types.h"
|
||||
#include "r_efx.h"
|
||||
#include "event_api.h"
|
||||
#include "pm_defs.h"
|
||||
#include "pmtrace.h"
|
||||
#include "pm_shared.h"
|
||||
#include "eventscripts.h" // buz
|
||||
#include "gl_local.h"
|
||||
#include "gl_studio.h"
|
||||
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
void Game_AddObjects( void );
|
||||
|
||||
extern vec3_t v_origin;
|
||||
extern vec3_t g_vSpread;
|
||||
extern int g_iGunMode;
|
||||
|
||||
int g_iAlive = 1;
|
||||
int g_flashlight; // buz
|
||||
int r_currentMessageNum = 0;
|
||||
int GlowFilterEntities ( int type, struct cl_entity_s *ent, const char *modelname ); // buz
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname );
|
||||
void DLLEXPORT HUD_CreateEntities( void );
|
||||
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
|
||||
void DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client );
|
||||
void DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src );
|
||||
void DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd );
|
||||
void DLLEXPORT HUD_TempEntUpdate( double frametime, double client_time, double cl_gravity, struct tempent_s **ppTempEntFree, struct tempent_s **ppTempEntActive, int ( *Callback_AddVisibleEntity )( struct cl_entity_s *pEntity ), void ( *Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp ) );
|
||||
struct cl_entity_s DLLEXPORT *HUD_GetUserEntity( int index );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
HUD_AddEntity
|
||||
Return 0 to filter entity from visible list for rendering
|
||||
========================
|
||||
*/
|
||||
int DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname )
|
||||
{
|
||||
if( ent->curstate.rendermode == kRenderTransAlpha && ent->model && ent->model->type == mod_brush )
|
||||
{
|
||||
// fix invisible grates on fallback renderer
|
||||
ent->curstate.renderamt = 255;
|
||||
}
|
||||
|
||||
if( g_fXashEngine && g_fRenderInitialized )
|
||||
{
|
||||
// use engine renderer
|
||||
if( cv_renderer->value == 0 )
|
||||
return 1;
|
||||
|
||||
if( type == ET_BEAM )
|
||||
return 1; // let the engine draw beams
|
||||
|
||||
R_AddEntity( ent, type );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// each frame every entity passes this function, so the overview hooks it to filter the overview entities
|
||||
// in spectator mode:
|
||||
// each frame every entity passes this function, so the overview hooks
|
||||
// it to filter the overview entities
|
||||
|
||||
if ( g_iUser1 )
|
||||
{
|
||||
gHUD.m_Spectator.AddOverviewEntity( type, ent, modelname );
|
||||
|
||||
if ( ( g_iUser1 == OBS_IN_EYE || gHUD.m_Spectator.m_pip->value == INSET_IN_EYE ) &&
|
||||
ent->index == g_iUser2 )
|
||||
return 0; // don't draw the player we are following in eye
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
HUD_TxferLocalOverrides
|
||||
|
||||
The server sends us our origin with extra precision as part of the clientdata structure, not during the normal
|
||||
playerstate update in entity_state_t. In order for these overrides to eventually get to the appropriate playerstate
|
||||
structure, we need to copy them into the state structure at this point.
|
||||
=========================
|
||||
*/
|
||||
void DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client )
|
||||
{
|
||||
state->origin = client->origin;
|
||||
state->velocity = client->velocity;
|
||||
|
||||
gHUD.m_iViewModelIndex = client->viewmodel;
|
||||
|
||||
// Spectator
|
||||
state->iuser1 = client->iuser1;
|
||||
state->iuser2 = client->iuser2;
|
||||
|
||||
// Duck prevention
|
||||
state->iuser3 = client->iuser3;
|
||||
|
||||
// Fire prevention
|
||||
state->iuser4 = client->iuser4;
|
||||
|
||||
// always have valid PVS message
|
||||
r_currentMessageNum = state->messagenum;
|
||||
|
||||
// IMPORTANT: this data doesn't present in entity_state_t
|
||||
// but only in clientdata_t for local player (gun params, spectator mode etc)
|
||||
g_iUser1 = client->iuser1;
|
||||
g_iUser2 = client->iuser2;
|
||||
g_iUser3 = client->iuser3;
|
||||
|
||||
// buz
|
||||
g_vSpread = client->vuser1;
|
||||
g_iGunMode = client->iuser4;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
HUD_ProcessPlayerState
|
||||
|
||||
We have received entity_state_t for this player over the network. We need to copy appropriate fields to the
|
||||
playerstate structure
|
||||
=========================
|
||||
*/
|
||||
void DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src )
|
||||
{
|
||||
// Copy in network data
|
||||
dst->origin = src->origin;
|
||||
dst->angles = src->angles;
|
||||
|
||||
dst->velocity = src->velocity;
|
||||
dst->basevelocity = src->basevelocity;
|
||||
|
||||
dst->frame = src->frame;
|
||||
dst->modelindex = src->modelindex;
|
||||
dst->skin = src->skin;
|
||||
dst->effects = src->effects;
|
||||
dst->weaponmodel = src->weaponmodel;
|
||||
dst->movetype = src->movetype;
|
||||
dst->sequence = src->sequence;
|
||||
dst->animtime = src->animtime;
|
||||
|
||||
dst->solid = src->solid;
|
||||
|
||||
dst->rendermode = src->rendermode;
|
||||
dst->renderamt = src->renderamt;
|
||||
dst->rendercolor.r = src->rendercolor.r;
|
||||
dst->rendercolor.g = src->rendercolor.g;
|
||||
dst->rendercolor.b = src->rendercolor.b;
|
||||
dst->renderfx = src->renderfx;
|
||||
|
||||
dst->framerate = src->framerate;
|
||||
dst->body = src->body;
|
||||
|
||||
dst->friction = src->friction;
|
||||
dst->gravity = src->gravity;
|
||||
dst->gaitsequence = src->gaitsequence;
|
||||
dst->usehull = src->usehull;
|
||||
dst->playerclass = src->playerclass;
|
||||
dst->team = src->team;
|
||||
dst->colormap = src->colormap;
|
||||
|
||||
dst->fuser1 = src->fuser1;
|
||||
dst->fuser2 = src->fuser2;
|
||||
dst->fuser3 = src->fuser3;
|
||||
dst->fuser4 = src->fuser4;
|
||||
|
||||
dst->vuser1 = src->vuser1;
|
||||
dst->vuser2 = src->vuser2;
|
||||
dst->vuser3 = src->vuser3;
|
||||
dst->vuser4 = src->vuser4;
|
||||
|
||||
memcpy( &dst->controller[0], &src->controller[0], 4 * sizeof( byte ));
|
||||
memcpy( &dst->blending[0], &src->blending[0], 2 * sizeof( byte ));
|
||||
|
||||
// Save off some data so other areas of the Client DLL can get to it
|
||||
cl_entity_t *player = gEngfuncs.GetLocalPlayer(); // Get the local player's index
|
||||
if ( dst->number == player->index )
|
||||
{
|
||||
g_iPlayerClass = dst->playerclass;
|
||||
g_iTeamNumber = dst->team;
|
||||
}
|
||||
|
||||
// buz: get flashlight status
|
||||
if (dst->effects & EF_DIMLIGHT)
|
||||
g_flashlight = 1;
|
||||
else g_flashlight = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
HUD_TxferPredictionData
|
||||
|
||||
Because we can predict an arbitrary number of frames before the server responds with an update, we need to be able to copy client side prediction data in
|
||||
from the state that the server ack'd receiving, which can be anywhere along the predicted frame path ( i.e., we could predict 20 frames into the future and the server ack's
|
||||
up through 10 of those frames, so we need to copy persistent client-side only state from the 10th predicted frame to the slot the server
|
||||
update is occupying.
|
||||
=========================
|
||||
*/
|
||||
void DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd )
|
||||
{
|
||||
ps->oldbuttons = pps->oldbuttons;
|
||||
ps->flFallVelocity = pps->flFallVelocity;
|
||||
ps->iStepLeft = pps->iStepLeft;
|
||||
ps->playerclass = pps->playerclass;
|
||||
|
||||
pcd->viewmodel = ppcd->viewmodel;
|
||||
pcd->m_iId = ppcd->m_iId;
|
||||
pcd->ammo_shells = ppcd->ammo_shells;
|
||||
pcd->ammo_nails = ppcd->ammo_nails;
|
||||
pcd->ammo_cells = ppcd->ammo_cells;
|
||||
pcd->ammo_rockets = ppcd->ammo_rockets;
|
||||
pcd->m_flNextAttack = ppcd->m_flNextAttack;
|
||||
pcd->fov = ppcd->fov;
|
||||
pcd->weaponanim = ppcd->weaponanim;
|
||||
pcd->tfstate = ppcd->tfstate;
|
||||
pcd->maxspeed = ppcd->maxspeed;
|
||||
|
||||
pcd->deadflag = ppcd->deadflag;
|
||||
|
||||
// Spectating or not dead == get control over view angles.
|
||||
g_iAlive = ( ppcd->iuser1 || ( pcd->deadflag == DEAD_NO ) ) ? 1 : 0;
|
||||
|
||||
// Spectator
|
||||
pcd->iuser1 = ppcd->iuser1;
|
||||
pcd->iuser2 = ppcd->iuser2;
|
||||
|
||||
// Duck prevention
|
||||
pcd->iuser3 = ppcd->iuser3;
|
||||
|
||||
if ( gEngfuncs.IsSpectateOnly() )
|
||||
{
|
||||
// in specator mode we tell the engine who we want to spectate and how
|
||||
// iuser3 is not used for duck prevention (since the spectator can't duck at all)
|
||||
pcd->iuser1 = g_iUser1; // observer mode
|
||||
pcd->iuser2 = g_iUser2; // first target
|
||||
pcd->iuser3 = g_iUser3; // second target
|
||||
|
||||
}
|
||||
|
||||
// Fire prevention
|
||||
pcd->iuser4 = ppcd->iuser4;
|
||||
|
||||
pcd->fuser1 = ppcd->fuser1;
|
||||
pcd->fuser2 = ppcd->fuser2;
|
||||
pcd->fuser3 = ppcd->fuser3;
|
||||
pcd->fuser4 = ppcd->fuser4;
|
||||
|
||||
pcd->vuser1 = ppcd->vuser1;
|
||||
pcd->vuser2 = ppcd->vuser2;
|
||||
pcd->vuser3 = ppcd->vuser3;
|
||||
pcd->vuser4 = ppcd->vuser4;
|
||||
|
||||
memcpy( wd, pwd, 32 * sizeof( weapon_data_t ) );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
HUD_CreateEntities
|
||||
|
||||
Gives us a chance to add additional entities to the render this frame
|
||||
=========================
|
||||
*/
|
||||
void DLLEXPORT HUD_CreateEntities( void )
|
||||
{
|
||||
// e.g., create a persistent cl_entity_t somewhere.
|
||||
// Load an appropriate model into it ( gEngfuncs.CL_LoadModel )
|
||||
// Call gEngfuncs.CL_CreateVisibleEntity to add it to the visedicts list
|
||||
|
||||
GetClientVoiceMgr()->CreateEntities();
|
||||
|
||||
// used to draw legs
|
||||
HUD_AddEntity( ET_PLAYER, GET_LOCAL_PLAYER(), GET_LOCAL_PLAYER()->model->name );
|
||||
}
|
||||
|
||||
void DlightFlash( const Vector &origin, int index )
|
||||
{
|
||||
dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight( index );
|
||||
dl->origin = origin;
|
||||
dl->radius = 128;
|
||||
dl->color.r = 180;
|
||||
dl->color.g = 160;
|
||||
dl->color.b = 120;
|
||||
dl->die = GET_CLIENT_TIME() + 0.06f;
|
||||
|
||||
CDynLight *pl = CL_AllocDlight( index );
|
||||
|
||||
R_SetupLightParams( pl, origin, g_vecZero, 128.0f, 0.0f, LIGHT_OMNI, DLF_NOSHADOWS );
|
||||
pl->color = Vector( 0.7f, 0.6f, 0.5f );
|
||||
pl->die = GET_CLIENT_TIME() + 0.06f;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_MuzzleFlash
|
||||
|
||||
Do muzzleflash
|
||||
==============
|
||||
*/
|
||||
void HUD_MuzzleFlash( const cl_entity_t *e, const Vector &pos, const Vector &fwd, int type, float mul )
|
||||
{
|
||||
TEMPENTITY *pTemp;
|
||||
int body, modelIndex, frameCount;
|
||||
Vector flash_angles;
|
||||
int flags = 0;
|
||||
float scale;
|
||||
|
||||
if( RP_NORMALPASS( ))
|
||||
{
|
||||
if( e == gEngfuncs.GetViewModel( ))
|
||||
flags |= EF_NOREFLECT|EF_NODEPTHTEST;
|
||||
else if( e->player && RP_LOCALCLIENT( e ))
|
||||
flags |= EF_REFLECTONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( e->player && RP_LOCALCLIENT( e ))
|
||||
flags |= EF_REFLECTONLY;
|
||||
}
|
||||
|
||||
body = bound( 0, type % 5, 4 );
|
||||
scale = (type / 5) * 0.2f;
|
||||
if( scale == 0.0f ) scale = 0.5f;
|
||||
|
||||
modelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/m_flash1.mdl");
|
||||
if( !modelIndex ) return;
|
||||
|
||||
Mod_GetFrames( modelIndex, frameCount );
|
||||
|
||||
if( body > ( frameCount - 1 ))
|
||||
body = frameCount - 1;
|
||||
|
||||
// must set position for right culling on render
|
||||
if( !( pTemp = gEngfuncs.pEfxAPI->CL_TempEntAllocHigh((float *)&pos, Mod_Handle( modelIndex ))))
|
||||
return;
|
||||
|
||||
VectorAngles( -fwd, flash_angles );
|
||||
scale *= mul;
|
||||
|
||||
pTemp->entity.curstate.rendermode = kRenderGlow;
|
||||
pTemp->entity.curstate.renderamt = 255;
|
||||
pTemp->entity.curstate.framerate = 10;
|
||||
pTemp->entity.curstate.renderfx = 0;
|
||||
pTemp->entity.angles = flash_angles;
|
||||
pTemp->die = tr.time + 0.015f; // die at next frame
|
||||
pTemp->entity.curstate.body = body;
|
||||
// pTemp->flags |= FTENT_MDLANIMATE|FTENT_MDLANIMATELOOP;
|
||||
pTemp->entity.angles[2] = RANDOM_LONG( 0, 359 );
|
||||
pTemp->entity.curstate.scale = scale;
|
||||
pTemp->frameMax = frameCount - 1;
|
||||
|
||||
gEngfuncs.CL_CreateVisibleEntity( ET_TEMPENTITY, &pTemp->entity );
|
||||
pTemp->entity.curstate.effects |= EF_FULLBRIGHT|flags; // CL_CreateVisibleEntity clears 'effect' field, so we need add it here
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
HUD_StudioEvent
|
||||
|
||||
The entity's studio model description indicated an event was
|
||||
fired during this frame, handle the event by it's tag ( e.g., muzzleflash, sound )
|
||||
=========================
|
||||
*/
|
||||
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity )
|
||||
{
|
||||
float rnd2 = gEngfuncs.pfnRandomFloat( -0.03, 0.03 );
|
||||
Vector pos, dir;
|
||||
float mul = 2.0f;
|
||||
int shell;
|
||||
|
||||
// ALERT( at_console, "Play event: %i, options %s, framecount %i\n", event->event, event->options, tr.realframecount );
|
||||
|
||||
if( entity == GET_VIEWMODEL( ))
|
||||
mul = 8.0f;
|
||||
|
||||
switch( event->event )
|
||||
{
|
||||
case 5001:
|
||||
R_StudioAttachmentPosDir( entity, 0, &pos, &dir );
|
||||
HUD_MuzzleFlash( entity, pos, dir, atoi( event->options), mul );
|
||||
DlightFlash((float *)&entity->attachment[0], entity->index );
|
||||
EV_GunSmoke( entity->attachment[0] );
|
||||
break;
|
||||
case 5007:
|
||||
EV_GunSmoke( entity->attachment[0] );
|
||||
break;
|
||||
case 5008:
|
||||
EV_GunSmoke( entity->attachment[1] );
|
||||
break;
|
||||
case 5009: // custom shell ejection
|
||||
shell = gEngfuncs.pEventAPI->EV_FindModelIndex( event->options );
|
||||
R_StudioAttachmentPosDir( entity, 2, &pos, &dir );
|
||||
EV_EjectBrass( pos, dir, 0, shell, TE_BOUNCE_SHELL );
|
||||
break;
|
||||
case 5010: // custom shell ejection, no velocity
|
||||
shell = gEngfuncs.pEventAPI->EV_FindModelIndex( event->options );
|
||||
R_StudioAttachmentPosDir( entity, 2, &pos, &dir );
|
||||
EV_EjectBrass( pos, (float *)&g_vecZero, 0, shell, TE_BOUNCE_SHELL );
|
||||
break;
|
||||
case 5011:
|
||||
R_StudioAttachmentPosDir( entity, 1, &pos, &dir );
|
||||
HUD_MuzzleFlash( entity, pos, dir, atoi( event->options), mul );
|
||||
DlightFlash((float *)&entity->attachment[1], entity->index );
|
||||
EV_GunSmoke( entity->attachment[1] );
|
||||
break;
|
||||
case 5021:
|
||||
R_StudioAttachmentPosDir( entity, 2, &pos, &dir );
|
||||
HUD_MuzzleFlash( entity, pos, dir, atoi( event->options), mul );
|
||||
DlightFlash((float *)&entity->attachment[2], entity->index );
|
||||
EV_GunSmoke( entity->attachment[2] );
|
||||
break;
|
||||
case 5031:
|
||||
R_StudioAttachmentPosDir( entity, 3, &pos, &dir );
|
||||
HUD_MuzzleFlash( entity, pos, dir, atoi( event->options), mul );
|
||||
DlightFlash((float *)&entity->attachment[3], entity->index );
|
||||
EV_GunSmoke( entity->attachment[3] );
|
||||
break;
|
||||
case 5002:
|
||||
gEngfuncs.pEfxAPI->R_SparkEffect( (float *)&entity->attachment[0], atoi( event->options), -100, 100 );
|
||||
break;
|
||||
// Client side sound
|
||||
case 5004:
|
||||
gEngfuncs.pfnPlaySoundByNameAtLocation( (char *)event->options, 1.0, (float *)&entity->attachment[0] );
|
||||
break;
|
||||
case 5005: // buz: left foot step (attach 3)
|
||||
{
|
||||
int contents = gEngfuncs.PM_PointContents( (float *)&entity->attachment[3], NULL );
|
||||
if (contents == CONTENTS_WATER) // leg is in the water
|
||||
{
|
||||
int waterEntity = gEngfuncs.PM_WaterEntity( (float *)&entity->attachment[3] );
|
||||
if ( waterEntity > 0 ) // water should be func_water entity
|
||||
{
|
||||
cl_entity_t *pwater = gEngfuncs.GetEntityByIndex( waterEntity );
|
||||
if ( pwater && ( pwater->model != NULL ) )
|
||||
{
|
||||
if ((pwater->curstate.maxs[2] - entity->attachment[3][2]) < 16)
|
||||
{
|
||||
vec3_t vecNull(0, 0, 0);
|
||||
vec3_t vecSrc((float *)&entity->attachment[3]);
|
||||
vecSrc.z += 25;
|
||||
int iPuff = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wsplash_x.spr");
|
||||
TEMPENTITY *wp = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc, vecNull, 0.5, iPuff, kRenderTransAdd, kRenderFxNone, 1, 5, FTENT_SPRANIMATE);
|
||||
wp->entity.curstate.framerate = 20;
|
||||
//wp->entity.curstate.rendercolor.r = entity->cvFloorColor.r;
|
||||
//wp->entity.curstate.rendercolor.g = entity->cvFloorColor.g;
|
||||
//wp->entity.curstate.rendercolor.b = entity->cvFloorColor.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5015: // buz: right foot step (attach 2)
|
||||
{
|
||||
int contents = gEngfuncs.PM_PointContents( (float *)&entity->attachment[2], NULL );
|
||||
if (contents == CONTENTS_WATER) // leg is in the water
|
||||
{
|
||||
int waterEntity = gEngfuncs.PM_WaterEntity( (float *)&entity->attachment[2] );
|
||||
if ( waterEntity > 0 ) // water should be func_water entity
|
||||
{
|
||||
cl_entity_t *pwater = gEngfuncs.GetEntityByIndex( waterEntity );
|
||||
if ( pwater && ( pwater->model != NULL ) )
|
||||
{
|
||||
if ((pwater->curstate.maxs[2] - entity->attachment[2][2]) < 16)
|
||||
{
|
||||
vec3_t vecNull(0, 0, 0);
|
||||
vec3_t vecSrc((float *)&entity->attachment[2]);
|
||||
vecSrc.z += 25;
|
||||
int iPuff = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wsplash_x.spr");
|
||||
TEMPENTITY *wp = gEngfuncs.pEfxAPI->R_TempSprite(vecSrc, vecNull, 0.5, iPuff, kRenderTransAdd, kRenderFxNone, 1, 5, FTENT_SPRANIMATE);
|
||||
wp->entity.curstate.framerate = 20;
|
||||
//wp->entity.curstate.rendercolor.r = entity->cvFloorColor.r;
|
||||
//wp->entity.curstate.rendercolor.g = entity->cvFloorColor.g;
|
||||
//wp->entity.curstate.rendercolor.b = entity->cvFloorColor.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5006: // buz: shell at 2nd attachment flying to 3rd
|
||||
{
|
||||
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");
|
||||
vec3_t VecDir = entity->attachment[2] - entity->attachment[1];
|
||||
VecDir = VecDir * 10;
|
||||
EV_EjectBrass ( (float *)&entity->attachment[1], VecDir, 0, shell, TE_BOUNCE_SHELL );
|
||||
break;
|
||||
}
|
||||
case 5040:
|
||||
// make aurora for origin
|
||||
UTIL_CreateAurora((cl_entity_t *)entity, event->options, 0, 0.0f );
|
||||
break;
|
||||
case 5041:
|
||||
// make aurora for attachment #1
|
||||
UTIL_CreateAurora((cl_entity_t *)entity, event->options, 1, 0.0f );
|
||||
break;
|
||||
case 5042:
|
||||
// make aurora for attachment #2
|
||||
UTIL_CreateAurora((cl_entity_t *)entity, event->options, 2, 0.0f );
|
||||
break;
|
||||
case 5043:
|
||||
// make aurora for attachment #3
|
||||
UTIL_CreateAurora((cl_entity_t *)entity, event->options, 3, 0.0f );
|
||||
break;
|
||||
case 5044:
|
||||
// make aurora for attachment #4
|
||||
UTIL_CreateAurora((cl_entity_t *)entity, event->options, 4, 0.0f );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_UpdateTEnts
|
||||
|
||||
Simulation and cleanup of temporary entities
|
||||
=================
|
||||
*/
|
||||
void DLLEXPORT HUD_TempEntUpdate (
|
||||
double frametime, // Simulation time
|
||||
double client_time, // Absolute time on client
|
||||
double cl_gravity, // True gravity on client
|
||||
TEMPENTITY **ppTempEntFree, // List of freed temporary ents
|
||||
TEMPENTITY **ppTempEntActive, // List
|
||||
int (*Callback_AddVisibleEntity)( cl_entity_t *pEntity ),
|
||||
void (*Callback_TempEntPlaySound)( TEMPENTITY *pTemp, float damp ) )
|
||||
{
|
||||
static int gTempEntFrame = 0;
|
||||
TEMPENTITY *pTemp, *pnext, *pprev;
|
||||
float freq, gravity, gravitySlow, life, fastFreq;
|
||||
|
||||
// Nothing to simulate
|
||||
if( !*ppTempEntActive ) return;
|
||||
|
||||
// in order to have tents collide with players, we have to run the player prediction code so
|
||||
// that the client has the player list. We run this code once when we detect any COLLIDEALL
|
||||
// tent, then set this BOOL to true so the code doesn't get run again if there's more than
|
||||
// one COLLIDEALL ent for this update. (often are).
|
||||
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
|
||||
|
||||
// Store off the old count
|
||||
gEngfuncs.pEventAPI->EV_PushPMStates();
|
||||
|
||||
// Now add in all of the players.
|
||||
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( -1 );
|
||||
|
||||
// !!!BUGBUG -- This needs to be time based
|
||||
gTempEntFrame = (gTempEntFrame+1) & 31;
|
||||
|
||||
pTemp = *ppTempEntActive;
|
||||
|
||||
// !!! Don't simulate while paused.... This is sort of a hack, revisit.
|
||||
if( frametime <= 0 )
|
||||
{
|
||||
while( pTemp )
|
||||
{
|
||||
if( !(pTemp->flags & FTENT_NOMODEL ))
|
||||
{
|
||||
Callback_AddVisibleEntity( &pTemp->entity );
|
||||
}
|
||||
pTemp = pTemp->next;
|
||||
}
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pprev = NULL;
|
||||
freq = client_time * 0.01;
|
||||
fastFreq = client_time * 5.5;
|
||||
gravity = -frametime * cl_gravity;
|
||||
gravitySlow = gravity * 0.5;
|
||||
|
||||
while ( pTemp )
|
||||
{
|
||||
int active = 1;
|
||||
|
||||
life = pTemp->die - client_time;
|
||||
pnext = pTemp->next;
|
||||
|
||||
if( life < 0 )
|
||||
{
|
||||
if ( pTemp->flags & FTENT_FADEOUT )
|
||||
{
|
||||
if (pTemp->entity.curstate.rendermode == kRenderNormal)
|
||||
pTemp->entity.curstate.rendermode = kRenderTransTexture;
|
||||
pTemp->entity.curstate.renderamt = pTemp->entity.baseline.renderamt * ( 1 + life * pTemp->fadeSpeed );
|
||||
|
||||
if ( pTemp->entity.curstate.renderamt <= 0 )
|
||||
active = 0;
|
||||
|
||||
}
|
||||
else active = 0;
|
||||
}
|
||||
|
||||
if( !active ) // Kill it
|
||||
{
|
||||
pTemp->next = *ppTempEntFree;
|
||||
*ppTempEntFree = pTemp;
|
||||
|
||||
if( !pprev ) // deleting at head of list
|
||||
*ppTempEntActive = pnext;
|
||||
else
|
||||
pprev->next = pnext;
|
||||
}
|
||||
else
|
||||
{
|
||||
pprev = pTemp;
|
||||
|
||||
VectorCopy( pTemp->entity.origin, pTemp->entity.prevstate.origin );
|
||||
|
||||
if ( pTemp->flags & FTENT_SPARKSHOWER )
|
||||
{
|
||||
// Adjust speed if it's time
|
||||
// Scale is next think time
|
||||
if ( client_time > pTemp->entity.baseline.scale )
|
||||
{
|
||||
// Show Sparks
|
||||
gEngfuncs.pEfxAPI->R_SparkEffect( pTemp->entity.origin, 8, -200, 200 );
|
||||
|
||||
// Reduce life
|
||||
pTemp->entity.baseline.framerate -= 0.1;
|
||||
|
||||
if ( pTemp->entity.baseline.framerate <= 0.0 )
|
||||
{
|
||||
pTemp->die = client_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
// So it will die no matter what
|
||||
pTemp->die = client_time + 0.5;
|
||||
|
||||
// Next think
|
||||
pTemp->entity.baseline.scale = client_time + 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( pTemp->flags & FTENT_PLYRATTACHMENT )
|
||||
{
|
||||
cl_entity_t *pClient;
|
||||
|
||||
pClient = gEngfuncs.GetEntityByIndex( pTemp->clientIndex );
|
||||
|
||||
VectorAdd( pClient->origin, pTemp->tentOffset, pTemp->entity.origin );
|
||||
}
|
||||
else if ( pTemp->flags & FTENT_SINEWAVE )
|
||||
{
|
||||
pTemp->x += pTemp->entity.baseline.origin[0] * frametime;
|
||||
pTemp->y += pTemp->entity.baseline.origin[1] * frametime;
|
||||
|
||||
pTemp->entity.origin[0] = pTemp->x + sin( pTemp->entity.baseline.origin[2] + client_time * pTemp->entity.prevstate.frame ) * (10*pTemp->entity.curstate.framerate);
|
||||
pTemp->entity.origin[1] = pTemp->y + sin( pTemp->entity.baseline.origin[2] + fastFreq + 0.7 ) * (8*pTemp->entity.curstate.framerate);
|
||||
pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
|
||||
}
|
||||
else if ( pTemp->flags & FTENT_SPIRAL )
|
||||
{
|
||||
float s, c;
|
||||
s = sin( pTemp->entity.baseline.origin[2] + fastFreq );
|
||||
c = cos( pTemp->entity.baseline.origin[2] + fastFreq );
|
||||
|
||||
pTemp->entity.origin[0] += pTemp->entity.baseline.origin[0] * frametime + 8 * sin( client_time * 20 + (int)pTemp );
|
||||
pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (int)pTemp );
|
||||
pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
pTemp->entity.origin[i] += pTemp->entity.baseline.origin[i] * frametime;
|
||||
}
|
||||
|
||||
if ( pTemp->flags & FTENT_SPRANIMATE )
|
||||
{
|
||||
pTemp->entity.curstate.frame += frametime * pTemp->entity.curstate.framerate;
|
||||
if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
|
||||
{
|
||||
pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
|
||||
|
||||
if ( !(pTemp->flags & FTENT_SPRANIMATELOOP) )
|
||||
{
|
||||
// this animating sprite isn't set to loop, so destroy it.
|
||||
pTemp->die = client_time;
|
||||
pTemp = pnext;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( pTemp->flags & FTENT_MDLANIMATE )
|
||||
{
|
||||
pTemp->entity.curstate.body += frametime * pTemp->entity.curstate.framerate;
|
||||
if ( pTemp->entity.curstate.body >= pTemp->frameMax )
|
||||
{
|
||||
pTemp->entity.curstate.body = pTemp->frameMax;
|
||||
|
||||
if( !( pTemp->flags & FTENT_MDLANIMATELOOP ))
|
||||
{
|
||||
// this animating sprite isn't set to loop, so destroy it.
|
||||
pTemp->die = client_time;
|
||||
pTemp = pnext;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( pTemp->flags & FTENT_SPRCYCLE )
|
||||
{
|
||||
pTemp->entity.curstate.frame += frametime * 10;
|
||||
if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
|
||||
{
|
||||
pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
|
||||
}
|
||||
}
|
||||
// Experiment
|
||||
#if 0
|
||||
if ( pTemp->flags & FTENT_SCALE )
|
||||
pTemp->entity.curstate.framerate += 20.0 * (frametime / pTemp->entity.curstate.framerate);
|
||||
#endif
|
||||
|
||||
if ( pTemp->flags & FTENT_ROTATE )
|
||||
{
|
||||
pTemp->entity.angles[0] += pTemp->entity.baseline.angles[0] * frametime;
|
||||
pTemp->entity.angles[1] += pTemp->entity.baseline.angles[1] * frametime;
|
||||
pTemp->entity.angles[2] += pTemp->entity.baseline.angles[2] * frametime;
|
||||
|
||||
VectorCopy( pTemp->entity.angles, pTemp->entity.latched.prevangles );
|
||||
}
|
||||
|
||||
if ( pTemp->flags & (FTENT_COLLIDEALL | FTENT_COLLIDEWORLD) )
|
||||
{
|
||||
vec3_t traceNormal;
|
||||
float traceFraction = 1;
|
||||
|
||||
if ( pTemp->flags & FTENT_COLLIDEALL )
|
||||
{
|
||||
pmtrace_t pmtrace;
|
||||
physent_t *pe;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX, -1, &pmtrace );
|
||||
|
||||
|
||||
if ( pmtrace.fraction != 1 )
|
||||
{
|
||||
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pmtrace.ent );
|
||||
|
||||
if ( !pmtrace.ent || ( pe->info != pTemp->clientIndex ) )
|
||||
{
|
||||
traceFraction = pmtrace.fraction;
|
||||
VectorCopy( pmtrace.plane.normal, traceNormal );
|
||||
|
||||
if ( pTemp->hitcallback )
|
||||
{
|
||||
(*pTemp->hitcallback)( pTemp, &pmtrace );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( pTemp->flags & FTENT_COLLIDEWORLD )
|
||||
{
|
||||
pmtrace_t pmtrace;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX | PM_WORLD_ONLY, -1, &pmtrace );
|
||||
|
||||
if ( pmtrace.fraction != 1 )
|
||||
{
|
||||
traceFraction = pmtrace.fraction;
|
||||
VectorCopy( pmtrace.plane.normal, traceNormal );
|
||||
|
||||
if ( pTemp->flags & FTENT_SPARKSHOWER )
|
||||
{
|
||||
// Chop spark speeds a bit more
|
||||
//
|
||||
VectorScale( pTemp->entity.baseline.origin, 0.6, pTemp->entity.baseline.origin );
|
||||
|
||||
if ( Length( pTemp->entity.baseline.origin ) < 10 )
|
||||
{
|
||||
pTemp->entity.baseline.framerate = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pTemp->hitcallback )
|
||||
{
|
||||
(*pTemp->hitcallback)( pTemp, &pmtrace );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( traceFraction != 1 ) // Decent collision now, and damping works
|
||||
{
|
||||
float proj, damp;
|
||||
|
||||
// Place at contact point
|
||||
VectorMA( pTemp->entity.prevstate.origin, traceFraction*frametime, pTemp->entity.baseline.origin, pTemp->entity.origin );
|
||||
// Damp velocity
|
||||
damp = pTemp->bounceFactor;
|
||||
if ( pTemp->flags & (FTENT_GRAVITY|FTENT_SLOWGRAVITY) )
|
||||
{
|
||||
damp *= 0.5;
|
||||
if ( traceNormal[2] > 0.9 ) // Hit floor?
|
||||
{
|
||||
if ( pTemp->entity.baseline.origin[2] <= 0 && pTemp->entity.baseline.origin[2] >= gravity*3 )
|
||||
{
|
||||
damp = 0; // Stop
|
||||
pTemp->flags &= ~(FTENT_ROTATE|FTENT_GRAVITY|FTENT_SLOWGRAVITY|FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL);
|
||||
pTemp->entity.angles[0] = 0;
|
||||
pTemp->entity.angles[2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pTemp->hitSound)
|
||||
{
|
||||
Callback_TempEntPlaySound(pTemp, damp);
|
||||
}
|
||||
|
||||
if (pTemp->flags & FTENT_COLLIDEKILL)
|
||||
{
|
||||
// die on impact
|
||||
pTemp->flags &= ~FTENT_FADEOUT;
|
||||
pTemp->die = client_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reflect velocity
|
||||
if ( damp != 0 )
|
||||
{
|
||||
proj = DotProduct( pTemp->entity.baseline.origin, traceNormal );
|
||||
VectorMA( pTemp->entity.baseline.origin, -proj*2, traceNormal, pTemp->entity.baseline.origin );
|
||||
// Reflect rotation (fake)
|
||||
|
||||
pTemp->entity.angles[1] = -pTemp->entity.angles[1];
|
||||
}
|
||||
|
||||
if ( damp != 1 )
|
||||
{
|
||||
|
||||
VectorScale( pTemp->entity.baseline.origin, damp, pTemp->entity.baseline.origin );
|
||||
VectorScale( pTemp->entity.angles, 0.9, pTemp->entity.angles );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (pTemp->flags & FTENT_FLICKER) && gTempEntFrame == pTemp->entity.curstate.effects )
|
||||
{
|
||||
dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight (0);
|
||||
VectorCopy (pTemp->entity.origin, dl->origin);
|
||||
dl->radius = 60;
|
||||
dl->color.r = 255;
|
||||
dl->color.g = 120;
|
||||
dl->color.b = 0;
|
||||
dl->die = client_time + 0.01;
|
||||
}
|
||||
|
||||
if ( pTemp->flags & FTENT_SMOKETRAIL )
|
||||
{
|
||||
gEngfuncs.pEfxAPI->R_RocketTrail (pTemp->entity.prevstate.origin, pTemp->entity.origin, 1);
|
||||
}
|
||||
|
||||
if ( pTemp->flags & FTENT_GRAVITY )
|
||||
pTemp->entity.baseline.origin[2] += gravity;
|
||||
else if ( pTemp->flags & FTENT_SLOWGRAVITY )
|
||||
pTemp->entity.baseline.origin[2] += gravitySlow;
|
||||
|
||||
if ( pTemp->flags & FTENT_CLIENTCUSTOM )
|
||||
{
|
||||
if ( pTemp->callback )
|
||||
{
|
||||
( *pTemp->callback )( pTemp, frametime, client_time );
|
||||
}
|
||||
}
|
||||
|
||||
// Cull to PVS (not frustum cull, just PVS)
|
||||
if ( !(pTemp->flags & FTENT_NOMODEL ) )
|
||||
{
|
||||
if( g_fRenderInitialized )
|
||||
{
|
||||
Callback_AddVisibleEntity( &pTemp->entity );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !Callback_AddVisibleEntity( &pTemp->entity ) )
|
||||
{
|
||||
if ( !(pTemp->flags & FTENT_PERSIST) )
|
||||
{
|
||||
pTemp->die = client_time; // If we can't draw it this frame, just dump it.
|
||||
pTemp->flags &= ~FTENT_FADEOUT; // Don't fade out, just die
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pTemp = pnext;
|
||||
}
|
||||
|
||||
finish:
|
||||
// Restore state info
|
||||
gEngfuncs.pEventAPI->EV_PopPMStates();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
HUD_GetUserEntity
|
||||
|
||||
If you specify negative numbers for beam start and end point entities, then
|
||||
the engine will call back into this function requesting a pointer to a cl_entity_t
|
||||
object that describes the entity to attach the beam onto.
|
||||
|
||||
Indices must start at 1, not zero.
|
||||
=================
|
||||
*/
|
||||
cl_entity_t DLLEXPORT *HUD_GetUserEntity( int index )
|
||||
{
|
||||
return NULL;
|
||||
}
|
205
cl_dll/ev_common.cpp
Normal file
205
cl_dll/ev_common.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
// shared event functions
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "entity_state.h"
|
||||
#include "cl_entity.h"
|
||||
|
||||
#include "r_efx.h"
|
||||
|
||||
#include "eventscripts.h"
|
||||
#include "event_api.h"
|
||||
#include "pm_shared.h"
|
||||
|
||||
#define IS_FIRSTPERSON_SPEC ( g_iUser1 == OBS_IN_EYE || (g_iUser1 && (gHUD.m_Spectator.m_pip->value == INSET_IN_EYE)) )
|
||||
/*
|
||||
=================
|
||||
GetEntity
|
||||
|
||||
Return's the requested cl_entity_t
|
||||
=================
|
||||
*/
|
||||
struct cl_entity_s *GetEntity( int idx )
|
||||
{
|
||||
return gEngfuncs.GetEntityByIndex( idx );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GetViewEntity
|
||||
|
||||
Return's the current weapon/view model
|
||||
=================
|
||||
*/
|
||||
struct cl_entity_s *GetViewEntity( void )
|
||||
{
|
||||
return gEngfuncs.GetViewModel();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_CreateTracer
|
||||
|
||||
Creates a tracer effect
|
||||
=================
|
||||
*/
|
||||
void EV_CreateTracer( float *start, float *end )
|
||||
{
|
||||
gEngfuncs.pEfxAPI->R_TracerEffect( start, end );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_IsPlayer
|
||||
|
||||
Is the entity's index in the player range?
|
||||
=================
|
||||
*/
|
||||
qboolean EV_IsPlayer( int idx )
|
||||
{
|
||||
if ( idx >= 1 && idx <= gEngfuncs.GetMaxClients() )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_IsLocal
|
||||
|
||||
Is the entity == the local player
|
||||
=================
|
||||
*/
|
||||
qboolean EV_IsLocal( int idx )
|
||||
{
|
||||
// check if we are in some way in first person spec mode
|
||||
if ( IS_FIRSTPERSON_SPEC )
|
||||
return (g_iUser2 == idx);
|
||||
else
|
||||
return gEngfuncs.pEventAPI->EV_IsLocal( idx - 1 ) ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_GetGunPosition
|
||||
|
||||
Figure out the height of the gun
|
||||
=================
|
||||
*/
|
||||
void EV_GetGunPosition( event_args_t *args, float *pos, float *origin )
|
||||
{
|
||||
int idx;
|
||||
vec3_t view_ofs;
|
||||
|
||||
idx = args->entindex;
|
||||
|
||||
VectorClear( view_ofs );
|
||||
view_ofs[2] = DEFAULT_VIEWHEIGHT;
|
||||
|
||||
if ( EV_IsPlayer( idx ) )
|
||||
{
|
||||
// in spec mode use entity viewheigh, not own
|
||||
if ( EV_IsLocal( idx ) && !IS_FIRSTPERSON_SPEC )
|
||||
{
|
||||
// Grab predicted result for local player
|
||||
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
|
||||
}
|
||||
else if ( args->ducking == 1 )
|
||||
{
|
||||
view_ofs[2] = VEC_DUCK_VIEW;
|
||||
}
|
||||
}
|
||||
|
||||
VectorAdd( origin, view_ofs, pos );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_EjectBrass
|
||||
|
||||
Bullet shell casings
|
||||
=================
|
||||
*/
|
||||
void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype )
|
||||
{
|
||||
Vector endpos = Vector( 0.0f, rotation, 0.0f );
|
||||
gEngfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, RANDOM_FLOAT( 1.5f, 3.0f ), model, soundtype );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_GetDefaultShellInfo
|
||||
|
||||
Determine where to eject shells from
|
||||
=================
|
||||
*/
|
||||
void EV_GetDefaultShellInfo( event_args_t *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale )
|
||||
{
|
||||
int i;
|
||||
vec3_t view_ofs;
|
||||
float fR, fU;
|
||||
|
||||
int idx;
|
||||
|
||||
idx = args->entindex;
|
||||
|
||||
VectorClear( view_ofs );
|
||||
view_ofs[2] = DEFAULT_VIEWHEIGHT;
|
||||
|
||||
if ( EV_IsPlayer( idx ) )
|
||||
{
|
||||
if ( EV_IsLocal( idx ) )
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
|
||||
}
|
||||
else if ( args->ducking == 1 )
|
||||
{
|
||||
view_ofs[2] = VEC_DUCK_VIEW;
|
||||
}
|
||||
}
|
||||
|
||||
// fR = gEngfuncs.pfnRandomFloat( 50, 70 );
|
||||
// fU = gEngfuncs.pfnRandomFloat( 100, 150 );
|
||||
fR = gEngfuncs.pfnRandomFloat( 80, 120 );
|
||||
fU = gEngfuncs.pfnRandomFloat( 10, 30 ); // buz
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
{
|
||||
ShellVelocity[i] = velocity[i] + right[i] * fR + up[i] * fU + forward[i] * 25;
|
||||
ShellOrigin[i] = origin[i] + view_ofs[i] + up[i] * upScale + forward[i] * forwardScale + right[i] * rightScale;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
EV_MuzzleFlash
|
||||
|
||||
Flag weapon/view model for muzzle flash
|
||||
=================
|
||||
*/
|
||||
void EV_MuzzleFlash( void )
|
||||
{
|
||||
// Add muzzle flash to current weapon model
|
||||
cl_entity_t *ent = GetViewEntity();
|
||||
if ( !ent )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Or in the muzzle flash
|
||||
ent->curstate.effects |= EF_MUZZLEFLASH;
|
||||
}
|
44
cl_dll/ev_files.cpp
Normal file
44
cl_dll/ev_files.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#include "../hud.h"
|
||||
#include "../cl_util.h"
|
||||
#include "event_api.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void EV_FireGeneric( struct event_args_s *args );
|
||||
void EV_TrainPitchAdjust( struct event_args_s *args );
|
||||
void EV_SmokePuff( struct event_args_s *args );
|
||||
}
|
||||
|
||||
/*
|
||||
======================
|
||||
Game_HookEvents
|
||||
|
||||
Associate script file name with callback functions. Callback's must be extern "C" so
|
||||
the engine doesn't get confused about name mangling stuff. Note that the format is
|
||||
always the same. Of course, a clever mod team could actually embed parameters, behavior
|
||||
into the actual .sc files and create a .sc file parser and hook their functionality through
|
||||
that.. i.e., a scripting system.
|
||||
|
||||
That was what we were going to do, but we ran out of time...oh well.
|
||||
======================
|
||||
*/
|
||||
void Game_HookEvents( void )
|
||||
{
|
||||
gEngfuncs.pfnHookEvent( "evTrainSound", EV_TrainPitchAdjust );
|
||||
gEngfuncs.pfnHookEvent( "evSmokePuff", EV_SmokePuff );
|
||||
gEngfuncs.pfnHookEvent( "evFireGeneric", EV_FireGeneric );
|
||||
}
|
418
cl_dll/ev_hldm.cpp
Normal file
418
cl_dll/ev_hldm.cpp
Normal file
@ -0,0 +1,418 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "entity_state.h"
|
||||
#include "cl_entity.h"
|
||||
#include "entity_types.h"
|
||||
#include "usercmd.h"
|
||||
#include "pm_defs.h"
|
||||
|
||||
#include "eventscripts.h"
|
||||
#include "ev_hldm.h"
|
||||
|
||||
#include "r_efx.h"
|
||||
#include "event_api.h"
|
||||
#include "event_args.h"
|
||||
#include "in_defs.h"
|
||||
#include "gl_rpart.h"
|
||||
#include <string.h>
|
||||
#include "material.h"
|
||||
#include "r_studioint.h"
|
||||
#include "com_model.h"
|
||||
#include "studio.h"
|
||||
|
||||
extern engine_studio_api_t IEngineStudio;
|
||||
|
||||
static int tracerCount[ 32 ];
|
||||
|
||||
void V_PunchAxis( int axis, float punch );
|
||||
void VectorAngles( const float *forward, float *angles );
|
||||
|
||||
extern cvar_t *cl_lw;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void EV_FireGeneric( struct event_args_s *args );
|
||||
void EV_TrainPitchAdjust( struct event_args_s *args );
|
||||
void EV_SmokePuff( struct event_args_s *args );
|
||||
}
|
||||
|
||||
// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the
|
||||
// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture.
|
||||
// returns volume of strike instrument (crowbar) to play
|
||||
void EV_HLDM_PlayTextureSound( pmtrace_t *ptr, const Vector &vecSrc, const Vector &vecEnd )
|
||||
{
|
||||
// hit the world, try to play sound based on texture material type
|
||||
char *rgsz[MAX_MAT_SOUNDS];
|
||||
float fattn = ATTN_NORM;
|
||||
int cnt = 0;
|
||||
|
||||
physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( ptr->ent );
|
||||
|
||||
matdef_t *pMat = NULL;
|
||||
|
||||
if( pe )
|
||||
{
|
||||
if( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP )
|
||||
pMat = COM_MatDefFromSurface( gEngfuncs.pEventAPI->EV_TraceSurface( ptr->ent, (float *)&vecSrc, (float *)&vecEnd ), ptr->endpos );
|
||||
else if( pe->solid == SOLID_CUSTOM && ptr->surf )
|
||||
pMat = ptr->surf->effects;
|
||||
|
||||
if( !pMat ) return;
|
||||
|
||||
// fire effects
|
||||
for( cnt = 0; pMat->impact_parts[cnt] != NULL; cnt++ )
|
||||
g_pParticles.CreateEffect( pMat->impact_parts[cnt], ptr->endpos, ptr->plane.normal );
|
||||
|
||||
// count sounds
|
||||
for( cnt = 0; pMat->impact_sounds[cnt] != NULL; cnt++ )
|
||||
rgsz[cnt] = (char *)pMat->impact_sounds[cnt];
|
||||
}
|
||||
|
||||
if( !cnt ) return;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[RANDOM_LONG( 0, cnt - 1 )], 0.9, fattn, 0, 96 + RANDOM_LONG( 0, 0xf ));
|
||||
}
|
||||
|
||||
void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, const Vector &vecSrc, const Vector &vecEnd )
|
||||
{
|
||||
if( pTrace->inwater ) return;
|
||||
|
||||
int iRand = RANDOM_LONG( 0, 0x7FFF );
|
||||
|
||||
if( iRand < ( 0x7fff / 2 )) // not every bullet makes a sound.
|
||||
{
|
||||
switch( iRand % 5)
|
||||
{
|
||||
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
||||
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
||||
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
||||
case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
||||
case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
||||
}
|
||||
}
|
||||
|
||||
physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
|
||||
|
||||
matdef_t *pMat = NULL;
|
||||
|
||||
if( pe )
|
||||
{
|
||||
if( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP )
|
||||
{
|
||||
pMat = COM_MatDefFromSurface( gEngfuncs.pEventAPI->EV_TraceSurface( pTrace->ent, (float *)&vecSrc, (float *)&vecEnd ), pTrace->endpos );
|
||||
if ( pMat ) CreateDecal( pTrace, pMat->impact_decal, RANDOM_FLOAT( 0.0f, 360.0f ));
|
||||
}
|
||||
else if( pe->solid == SOLID_CUSTOM && pTrace->surf )
|
||||
{
|
||||
pMat = pTrace->surf->effects;
|
||||
if ( pMat ) UTIL_StudioDecal( pMat->impact_decal, pTrace, vecSrc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FireBullets
|
||||
|
||||
Go to the trouble of combining multiple pellets into a single damage call.
|
||||
================
|
||||
*/
|
||||
void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY )
|
||||
{
|
||||
int i;
|
||||
pmtrace_t tr;
|
||||
int iShot;
|
||||
|
||||
for ( iShot = 1; iShot <= cShots; iShot++ )
|
||||
{
|
||||
Vector vecDir, vecEnd;
|
||||
|
||||
float x, y, z;
|
||||
|
||||
// We randomize for the Shotgun.
|
||||
if ( iBulletType == BULLET_BUCKSHOT )
|
||||
{
|
||||
do {
|
||||
x = RANDOM_FLOAT( -0.5f, 0.5f ) + RANDOM_FLOAT( -0.5f, 0.5f );
|
||||
y = RANDOM_FLOAT( -0.5f, 0.5f ) + RANDOM_FLOAT( -0.5f, 0.5f );
|
||||
z = x * x + y * y;
|
||||
} while( z > 1.0f );
|
||||
|
||||
for ( i = 0 ; i < 3; i++ )
|
||||
{
|
||||
vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[i] + y * flSpreadY * up[i];
|
||||
vecEnd[i] = vecSrc[i] + flDistance * vecDir[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// but other guns already have their spread randomized in the synched spread.
|
||||
for ( i = 0 ; i < 3; i++ )
|
||||
{
|
||||
vecDir[i] = vecDirShooting[i] + flSpreadX * right[i] + flSpreadY * up[i];
|
||||
vecEnd[i] = vecSrc[i] + flDistance * vecDir[i];
|
||||
}
|
||||
}
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
|
||||
|
||||
// Store off the old count
|
||||
gEngfuncs.pEventAPI->EV_PushPMStates();
|
||||
|
||||
// Now add in all of the players.
|
||||
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, 0, -1, &tr );
|
||||
|
||||
// do damage, paint decals
|
||||
if ( tr.fraction != 1.0 && !tr.inwater ) // buz: dont smoke and particle if shoot in sky
|
||||
{
|
||||
EV_HLDM_PlayTextureSound( &tr, vecSrc, vecEnd );
|
||||
EV_HLDM_GunshotDecalTrace( &tr, vecSrc, vecEnd );
|
||||
}
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PopPMStates();
|
||||
}
|
||||
}
|
||||
|
||||
//======================
|
||||
// WEAPON GENERIC START
|
||||
//======================
|
||||
void EV_FireGeneric( struct event_args_s *args )
|
||||
{
|
||||
int idx;
|
||||
Vector origin;
|
||||
Vector angles;
|
||||
Vector velocity;
|
||||
|
||||
Vector ShellVelocity;
|
||||
Vector ShellOrigin;
|
||||
Vector vecSrc, vecAiming;
|
||||
Vector up, right, forward;
|
||||
float flSpread = 0.01;
|
||||
|
||||
idx = args->entindex;
|
||||
VectorCopy( args->origin, origin );
|
||||
VectorCopy( args->angles, angles );
|
||||
VectorCopy( args->velocity, velocity );
|
||||
|
||||
AngleVectors( angles, forward, right, up );
|
||||
|
||||
int shell = args->bparam1; // brass shell
|
||||
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
|
||||
|
||||
if( EV_IsLocal( idx ))
|
||||
{
|
||||
// add muzzle flash to current weapon model
|
||||
EV_MuzzleFlash();
|
||||
|
||||
UTIL_WeaponAnimation(( args->iparam1 & 0xFFF ), 1.0f ); // FIXME: how to send framerate?
|
||||
|
||||
V_PunchAxis( 0, RANDOM_FLOAT( ((float)args->iparam2 / 255.0f ) * -3.0f, 0.0f ));
|
||||
|
||||
cl_entity_t *ent = GetViewEntity();
|
||||
if( ent ) ShellOrigin = ent->attachment[1];
|
||||
}
|
||||
|
||||
int numShots = ((args->iparam1 >> 12) & 0xF);
|
||||
int soundType = TE_BOUNCE_SHELL;
|
||||
int bulletType = BULLET_NORMAL;
|
||||
float flDist = 8192.0f;
|
||||
|
||||
// shotgun case
|
||||
if( numShots > 1 )
|
||||
{
|
||||
bulletType = BULLET_BUCKSHOT;
|
||||
soundType = TE_BOUNCE_SHOTSHELL;
|
||||
flDist = 2048.0f;
|
||||
}
|
||||
|
||||
EV_EjectBrass( ShellOrigin, ShellVelocity , RANDOM_FLOAT( -angles[YAW], angles[YAW] ), shell, soundType );
|
||||
|
||||
if( args->bparam2 )
|
||||
{
|
||||
const char *fireSound = gEngfuncs.pEventAPI->EV_SoundForIndex( args->bparam2 );
|
||||
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, fireSound, 1, ATTN_NORM, 0, 94 + RANDOM_LONG( 0, 0xf ));
|
||||
}
|
||||
|
||||
EV_GetGunPosition( args, vecSrc, origin );
|
||||
|
||||
VectorCopy( forward, vecAiming );
|
||||
|
||||
EV_HLDM_FireBullets( idx, forward, right, up, numShots, vecSrc, vecAiming, flDist, bulletType, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 );
|
||||
}
|
||||
//======================
|
||||
// WEAPON GENERIC END
|
||||
//======================
|
||||
#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch
|
||||
|
||||
void EV_TrainPitchAdjust( event_args_t *args )
|
||||
{
|
||||
int idx;
|
||||
Vector origin;
|
||||
|
||||
unsigned short us_params;
|
||||
int noise;
|
||||
float m_flVolume;
|
||||
int pitch;
|
||||
int stop;
|
||||
|
||||
char sz[ 256 ];
|
||||
|
||||
idx = args->entindex;
|
||||
|
||||
VectorCopy( args->origin, origin );
|
||||
|
||||
us_params = (unsigned short)args->iparam1;
|
||||
stop = args->bparam1;
|
||||
|
||||
m_flVolume = (float)(us_params & 0x003f)/40.0;
|
||||
noise = (int)(((us_params) >> 12 ) & 0x0007);
|
||||
pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) );
|
||||
|
||||
switch ( noise )
|
||||
{
|
||||
case 1: strcpy( sz, "plats/ttrain1.wav"); break;
|
||||
case 2: strcpy( sz, "plats/ttrain2.wav"); break;
|
||||
case 3: strcpy( sz, "plats/ttrain3.wav"); break;
|
||||
case 4: strcpy( sz, "plats/ttrain4.wav"); break;
|
||||
case 5: strcpy( sz, "plats/ttrain6.wav"); break;
|
||||
case 6: strcpy( sz, "plats/ttrain7.wav"); break;
|
||||
default:
|
||||
// no sound
|
||||
strcpy( sz, "" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( stop )
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz );
|
||||
}
|
||||
else
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch );
|
||||
}
|
||||
}
|
||||
|
||||
int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// buz: smokepuff event - for invoke puffs from server, when monsters firing, etc..
|
||||
void EV_SmokePuff( struct event_args_s *args )
|
||||
{
|
||||
VectorNormalize(args->angles); // there is surface normal actually
|
||||
g_pParticles.BulletParticles( args->origin, args->angles );
|
||||
}
|
||||
|
||||
void EV_GunSmoke( const Vector &pos )
|
||||
{
|
||||
g_pParticles.GunSmoke( pos, 2 );
|
||||
}
|
||||
|
||||
void EV_ExplodeSmoke( const Vector &pos )
|
||||
{
|
||||
g_pParticles.SmokeParticles( pos, 10 );
|
||||
}
|
||||
|
||||
void EV_HLDM_WaterSplash( float x, float y, float z, float ScaleSplash1, float ScaleSplash2 )
|
||||
{
|
||||
int iWaterSplash = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/splash1.spr");
|
||||
TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 15 ),
|
||||
Vector( 0, 0, 0 ),
|
||||
/*ScaleSplash1*/0.2, iWaterSplash, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL );
|
||||
|
||||
if(pTemp)
|
||||
{
|
||||
pTemp->fadeSpeed = 90.0;
|
||||
pTemp->entity.curstate.framerate = 70.0;
|
||||
pTemp->entity.curstate.renderamt = 155;
|
||||
pTemp->entity.curstate.rendercolor.r = 255;
|
||||
pTemp->entity.curstate.rendercolor.g = 255;
|
||||
pTemp->entity.curstate.rendercolor.b = 255;
|
||||
}
|
||||
|
||||
iWaterSplash = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/splash2.spr");
|
||||
pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z ),
|
||||
Vector( 0, 0, 0 ),
|
||||
/*ScaleSplash2*/0.08, iWaterSplash, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL );
|
||||
|
||||
if(pTemp)
|
||||
{
|
||||
pTemp->fadeSpeed = 60.0;
|
||||
pTemp->entity.curstate.framerate = 60.0;
|
||||
pTemp->entity.curstate.renderamt = 150;
|
||||
pTemp->entity.curstate.rendercolor.r = 255;
|
||||
pTemp->entity.curstate.rendercolor.g = 255;
|
||||
pTemp->entity.curstate.rendercolor.b = 255;
|
||||
pTemp->entity.angles = Vector( 90, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void EV_HLDM_NewExplode( float x, float y, float z, float ScaleExplode1 )
|
||||
{
|
||||
float rnd = gEngfuncs.pfnRandomFloat( -0.03, 0.03 );
|
||||
int iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/dexplo.spr");
|
||||
TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 15 ), Vector( 0, 0, 0 ),
|
||||
ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT );
|
||||
|
||||
if( pTemp )
|
||||
{
|
||||
pTemp->fadeSpeed = 90.0;
|
||||
pTemp->entity.curstate.framerate = 37.0;
|
||||
pTemp->entity.curstate.renderamt = 155;
|
||||
pTemp->entity.curstate.rendercolor.r = 255;
|
||||
pTemp->entity.curstate.rendercolor.g = 255;
|
||||
pTemp->entity.curstate.rendercolor.b = 255;
|
||||
}
|
||||
|
||||
iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/fexplo.spr");
|
||||
pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 15), Vector( 0, 0, 0 ),
|
||||
ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT );
|
||||
|
||||
if( pTemp )
|
||||
{
|
||||
pTemp->fadeSpeed = 100.0;
|
||||
pTemp->entity.curstate.framerate = 35.0;
|
||||
pTemp->entity.curstate.renderamt = 150;
|
||||
pTemp->entity.curstate.rendercolor.r = 255;
|
||||
pTemp->entity.curstate.rendercolor.g = 255;
|
||||
pTemp->entity.curstate.rendercolor.b = 255;
|
||||
pTemp->entity.angles = Vector( 90, 0, 0 );
|
||||
}
|
||||
|
||||
iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/smokeball.spr");
|
||||
pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 16), Vector( 0, 0, 0 ),
|
||||
ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT );
|
||||
|
||||
if( pTemp )
|
||||
{
|
||||
pTemp->fadeSpeed = 50.0;
|
||||
pTemp->entity.curstate.framerate = 22.0;
|
||||
pTemp->entity.curstate.renderamt = 120;
|
||||
pTemp->entity.curstate.rendercolor.r = 255;
|
||||
pTemp->entity.curstate.rendercolor.g = 255;
|
||||
pTemp->entity.curstate.rendercolor.b = 255;
|
||||
pTemp->entity.angles = Vector( 90, 0, 0 );
|
||||
}
|
||||
|
||||
EV_ExplodeSmoke( Vector( x, y, z + 4.0f ));
|
||||
}
|
17
cl_dll/ev_hldm.h
Normal file
17
cl_dll/ev_hldm.h
Normal file
@ -0,0 +1,17 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined ( EV_HLDMH )
|
||||
#define EV_HLDMH
|
||||
|
||||
#include <bullets.h>
|
||||
|
||||
void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, const Vector &vecSrc, const Vector &vecEnd );
|
||||
int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount );
|
||||
void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY );
|
||||
|
||||
#endif // EV_HLDMH
|
23
cl_dll/events.cpp
Normal file
23
cl_dll/events.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
|
||||
void Game_HookEvents( void );
|
||||
|
||||
/*
|
||||
===================
|
||||
EV_HookEvents
|
||||
|
||||
See if game specific code wants to hook any events.
|
||||
===================
|
||||
*/
|
||||
void EV_HookEvents( void )
|
||||
{
|
||||
Game_HookEvents();
|
||||
}
|
74
cl_dll/eventscripts.h
Normal file
74
cl_dll/eventscripts.h
Normal file
@ -0,0 +1,74 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
// eventscripts.h
|
||||
#if !defined ( EVENTSCRIPTSH )
|
||||
#define EVENTSCRIPTSH
|
||||
|
||||
// defaults for clientinfo messages
|
||||
#define DEFAULT_VIEWHEIGHT 28
|
||||
#define VEC_DUCK_VIEW 12
|
||||
|
||||
#define FTENT_FADEOUT 0x00000080
|
||||
|
||||
#define DMG_GENERIC 0 // generic damage was done
|
||||
#define DMG_CRUSH (1 << 0) // crushed by falling or moving object
|
||||
#define DMG_BULLET (1 << 1) // shot
|
||||
#define DMG_SLASH (1 << 2) // cut, clawed, stabbed
|
||||
#define DMG_BURN (1 << 3) // heat burned
|
||||
#define DMG_FREEZE (1 << 4) // frozen
|
||||
#define DMG_FALL (1 << 5) // fell too far
|
||||
#define DMG_BLAST (1 << 6) // explosive blast damage
|
||||
#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt
|
||||
#define DMG_SHOCK (1 << 8) // electric shock
|
||||
#define DMG_SONIC (1 << 9) // sound pulse shockwave
|
||||
#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam
|
||||
#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death
|
||||
#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death.
|
||||
|
||||
// time-based damage
|
||||
//mask off TF-specific stuff too
|
||||
#define DMG_TIMEBASED (~(0xff003fff)) // mask for time-based damage
|
||||
|
||||
#define DMG_DROWN (1 << 14) // Drowning
|
||||
#define DMG_FIRSTTIMEBASED DMG_DROWN
|
||||
|
||||
#define DMG_PARALYZE (1 << 15) // slows affected creature down
|
||||
#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
|
||||
#define DMG_POISON (1 << 17) // blood poisioning
|
||||
#define DMG_RADIATION (1 << 18) // radiation exposure
|
||||
#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
|
||||
#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
|
||||
#define DMG_SLOWBURN (1 << 21) // in an oven
|
||||
#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer
|
||||
#define DMG_MORTAR (1 << 23) // Hit by air raid (done to distinguish grenade from mortar)
|
||||
|
||||
//TF ADDITIONS
|
||||
#define DMG_IGNITE (1 << 24) // Players hit by this begin to burn
|
||||
#define DMG_RADIUS_MAX (1 << 25) // Radius damage with this flag doesn't decrease over distance
|
||||
#define DMG_RADIUS_QUAKE (1 << 26) // Radius damage is done like Quake. 1/2 damage at 1/2 radius.
|
||||
#define DMG_IGNOREARMOR (1 << 27) // Damage ignores target's armor
|
||||
#define DMG_AIMED (1 << 28) // Does Hit location damage
|
||||
#define DMG_WALLPIERCING (1 << 29) // Blast Damages ents through walls
|
||||
|
||||
#define DMG_CALTROP (1<<30)
|
||||
#define DMG_HALLUC (1<<31)
|
||||
|
||||
// Some of these are HL/TFC specific?
|
||||
void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype );
|
||||
void EV_GetGunPosition( struct event_args_s *args, float *pos, float *origin );
|
||||
void EV_GetDefaultShellInfo( struct event_args_s *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale );
|
||||
qboolean EV_IsLocal( int idx );
|
||||
qboolean EV_IsPlayer( int idx );
|
||||
void EV_CreateTracer( float *start, float *end );
|
||||
|
||||
struct cl_entity_s *GetEntity( int idx );
|
||||
struct cl_entity_s *GetViewEntity( void );
|
||||
void EV_GunSmoke( const Vector &pos );
|
||||
void EV_MuzzleFlash( void );
|
||||
|
||||
#endif // EVENTSCRIPTSH
|
151
cl_dll/flashlight.cpp
Normal file
151
cl_dll/flashlight.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// flashlight.cpp
|
||||
//
|
||||
// implementation of CHudFlashlight class
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
DECLARE_MESSAGE(m_Flash, FlashBat)
|
||||
DECLARE_MESSAGE(m_Flash, Flashlight)
|
||||
|
||||
#define BAT_NAME "sprites/%d_Flashlight.spr"
|
||||
|
||||
int CHudFlashlight::Init(void)
|
||||
{
|
||||
m_fFade = 0;
|
||||
m_fOn = 0;
|
||||
|
||||
HOOK_MESSAGE(Flashlight);
|
||||
HOOK_MESSAGE(FlashBat);
|
||||
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
gHUD.AddHudElem(this);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
void CHudFlashlight::Reset(void)
|
||||
{
|
||||
m_fFade = 0;
|
||||
m_fOn = 0;
|
||||
}
|
||||
|
||||
int CHudFlashlight::VidInit(void)
|
||||
{
|
||||
int HUD_flash_empty = gHUD.GetSpriteIndex( "flash_empty" );
|
||||
int HUD_flash_full = gHUD.GetSpriteIndex( "flash_full" );
|
||||
int HUD_flash_beam = gHUD.GetSpriteIndex( "flash_beam" );
|
||||
|
||||
m_hSprite1 = gHUD.GetSprite(HUD_flash_empty);
|
||||
m_hSprite2 = gHUD.GetSprite(HUD_flash_full);
|
||||
m_hBeam = gHUD.GetSprite(HUD_flash_beam);
|
||||
m_prc1 = &gHUD.GetSpriteRect(HUD_flash_empty);
|
||||
m_prc2 = &gHUD.GetSpriteRect(HUD_flash_full);
|
||||
m_prcBeam = &gHUD.GetSpriteRect(HUD_flash_beam);
|
||||
m_iWidth = m_prc2->right - m_prc2->left;
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
int CHudFlashlight:: MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
int x = READ_BYTE();
|
||||
m_iBat = x;
|
||||
m_flBat = ((float)x)/100.0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudFlashlight:: MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
m_fOn = READ_BYTE();
|
||||
int x = READ_BYTE();
|
||||
m_iBat = x;
|
||||
m_flBat = ((float)x)/100.0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudFlashlight::Draw(float flTime)
|
||||
{
|
||||
return 1; // buz: no flashlight
|
||||
|
||||
if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) )
|
||||
return 1;
|
||||
|
||||
int r, g, b, x, y, a;
|
||||
wrect_t rc;
|
||||
|
||||
if (!FBitSet( gHUD.m_iHideHUDDisplay, ITEM_SUIT ))
|
||||
return 1;
|
||||
|
||||
if (m_fOn)
|
||||
a = 225;
|
||||
else
|
||||
a = MIN_ALPHA;
|
||||
|
||||
if (m_flBat < 0.20)
|
||||
UnpackRGB(r,g,b, RGB_REDISH);
|
||||
else
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
|
||||
ScaleColors(r, g, b, a);
|
||||
|
||||
y = (m_prc1->bottom - m_prc2->top)/2;
|
||||
x = ScreenWidth - m_iWidth - m_iWidth/2 ;
|
||||
|
||||
// Draw the flashlight casing
|
||||
SPR_Set(m_hSprite1, r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y, m_prc1);
|
||||
|
||||
if ( m_fOn )
|
||||
{ // draw the flashlight beam
|
||||
x = ScreenWidth - m_iWidth/2;
|
||||
|
||||
SPR_Set( m_hBeam, r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y, m_prcBeam );
|
||||
}
|
||||
|
||||
// draw the flashlight energy level
|
||||
x = ScreenWidth - m_iWidth - m_iWidth/2 ;
|
||||
int iOffset = m_iWidth * (1.0 - m_flBat);
|
||||
if (iOffset < m_iWidth)
|
||||
{
|
||||
rc = *m_prc2;
|
||||
rc.left += iOffset;
|
||||
|
||||
SPR_Set(m_hSprite2, r, g, b );
|
||||
SPR_DrawAdditive( 0, x + iOffset, y, &rc);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
184
cl_dll/geiger.cpp
Normal file
184
cl_dll/geiger.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// Geiger.cpp
|
||||
//
|
||||
// implementation of CHudAmmo class
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "parsemsg.h"
|
||||
|
||||
DECLARE_MESSAGE(m_Geiger, Geiger )
|
||||
|
||||
int CHudGeiger::Init(void)
|
||||
{
|
||||
HOOK_MESSAGE( Geiger );
|
||||
|
||||
m_iGeigerRange = 0;
|
||||
m_iFlags = 0;
|
||||
|
||||
gHUD.AddHudElem(this);
|
||||
|
||||
srand( (unsigned)time( NULL ) );
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
int CHudGeiger::VidInit(void)
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
int CHudGeiger::MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
// update geiger data
|
||||
m_iGeigerRange = READ_BYTE();
|
||||
m_iGeigerRange = m_iGeigerRange << 2;
|
||||
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudGeiger::Draw (float flTime)
|
||||
{
|
||||
int pct;
|
||||
float flvol;
|
||||
int rg[3];
|
||||
int i;
|
||||
|
||||
if (m_iGeigerRange < 1000 && m_iGeigerRange > 0)
|
||||
{
|
||||
// peicewise linear is better than continuous formula for this
|
||||
if (m_iGeigerRange > 800)
|
||||
{
|
||||
pct = 0; //Con_Printf ( "range > 800\n");
|
||||
}
|
||||
else if (m_iGeigerRange > 600)
|
||||
{
|
||||
pct = 2;
|
||||
flvol = 0.4; //Con_Printf ( "range > 600\n");
|
||||
rg[0] = 1;
|
||||
rg[1] = 1;
|
||||
i = 2;
|
||||
}
|
||||
else if (m_iGeigerRange > 500)
|
||||
{
|
||||
pct = 4;
|
||||
flvol = 0.5; //Con_Printf ( "range > 500\n");
|
||||
rg[0] = 1;
|
||||
rg[1] = 2;
|
||||
i = 2;
|
||||
}
|
||||
else if (m_iGeigerRange > 400)
|
||||
{
|
||||
pct = 8;
|
||||
flvol = 0.6; //Con_Printf ( "range > 400\n");
|
||||
rg[0] = 1;
|
||||
rg[1] = 2;
|
||||
rg[2] = 3;
|
||||
i = 3;
|
||||
}
|
||||
else if (m_iGeigerRange > 300)
|
||||
{
|
||||
pct = 8;
|
||||
flvol = 0.7; //Con_Printf ( "range > 300\n");
|
||||
rg[0] = 2;
|
||||
rg[1] = 3;
|
||||
rg[2] = 4;
|
||||
i = 3;
|
||||
}
|
||||
else if (m_iGeigerRange > 200)
|
||||
{
|
||||
pct = 28;
|
||||
flvol = 0.78; //Con_Printf ( "range > 200\n");
|
||||
rg[0] = 2;
|
||||
rg[1] = 3;
|
||||
rg[2] = 4;
|
||||
i = 3;
|
||||
}
|
||||
else if (m_iGeigerRange > 150)
|
||||
{
|
||||
pct = 40;
|
||||
flvol = 0.80; //Con_Printf ( "range > 150\n");
|
||||
rg[0] = 3;
|
||||
rg[1] = 4;
|
||||
rg[2] = 5;
|
||||
i = 3;
|
||||
}
|
||||
else if (m_iGeigerRange > 100)
|
||||
{
|
||||
pct = 60;
|
||||
flvol = 0.85; //Con_Printf ( "range > 100\n");
|
||||
rg[0] = 3;
|
||||
rg[1] = 4;
|
||||
rg[2] = 5;
|
||||
i = 3;
|
||||
}
|
||||
else if (m_iGeigerRange > 75)
|
||||
{
|
||||
pct = 80;
|
||||
flvol = 0.9; //Con_Printf ( "range > 75\n");
|
||||
//gflGeigerDelay = cl.time + GEIGERDELAY * 0.75;
|
||||
rg[0] = 4;
|
||||
rg[1] = 5;
|
||||
rg[2] = 6;
|
||||
i = 3;
|
||||
}
|
||||
else if (m_iGeigerRange > 50)
|
||||
{
|
||||
pct = 90;
|
||||
flvol = 0.95; //Con_Printf ( "range > 50\n");
|
||||
rg[0] = 5;
|
||||
rg[1] = 6;
|
||||
i = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pct = 95;
|
||||
flvol = 1.0; //Con_Printf ( "range < 50\n");
|
||||
rg[0] = 5;
|
||||
rg[1] = 6;
|
||||
i = 2;
|
||||
}
|
||||
|
||||
flvol = (flvol * ((rand() & 127)) / 255) + 0.25; // UTIL_RandomFloat(0.25, 0.5);
|
||||
|
||||
if ((rand() & 127) < pct || (rand() & 127) < pct)
|
||||
{
|
||||
//S_StartDynamicSound (-1, 0, rgsfx[rand() % i], r_origin, flvol, 1.0, 0, 100);
|
||||
char sz[256];
|
||||
|
||||
int j = rand() & 1;
|
||||
if (i > 2)
|
||||
j += rand() & 1;
|
||||
|
||||
sprintf(sz, "player/geiger%d.wav", j + 1);
|
||||
PlaySound(sz, flvol);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
11
cl_dll/getfont.h
Normal file
11
cl_dll/getfont.h
Normal file
@ -0,0 +1,11 @@
|
||||
// ============================
|
||||
// getfont - function, returning font pointer from text message
|
||||
// written by BUzer
|
||||
// ============================
|
||||
|
||||
#ifndef _GETFONT_H
|
||||
#define _GETFONT_H
|
||||
|
||||
Font* FontFromMessage(const char* &ptext);
|
||||
|
||||
#endif // _GETFONT_H
|
508
cl_dll/health.cpp
Normal file
508
cl_dll/health.cpp
Normal file
@ -0,0 +1,508 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// Health.cpp
|
||||
//
|
||||
// implementation of CHudHealth class
|
||||
//
|
||||
|
||||
#include "STDIO.H"
|
||||
#include "STDLIB.H"
|
||||
#include "MATH.H"
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "vgui_TeamFortressViewport.h" // buz
|
||||
#include "vgui_hud.h" // buz
|
||||
|
||||
|
||||
DECLARE_MESSAGE(m_Health, Health )
|
||||
DECLARE_MESSAGE(m_Health, Damage )
|
||||
|
||||
#define PAIN_NAME "sprites/%d_pain.spr"
|
||||
#define DAMAGE_NAME "sprites/%d_dmg.spr"
|
||||
|
||||
int giDmgHeight, giDmgWidth;
|
||||
|
||||
int giDmgFlags[NUM_DMG_TYPES] =
|
||||
{
|
||||
DMG_POISON,
|
||||
DMG_ACID,
|
||||
DMG_FREEZE|DMG_SLOWFREEZE,
|
||||
DMG_DROWN,
|
||||
DMG_BURN|DMG_SLOWBURN,
|
||||
DMG_NERVEGAS,
|
||||
DMG_RADIATION,
|
||||
DMG_SHOCK,
|
||||
DMG_CALTROP,
|
||||
DMG_TRANQ,
|
||||
DMG_CONCUSS,
|
||||
DMG_HALLUC
|
||||
};
|
||||
|
||||
int CHudHealth::Init(void)
|
||||
{
|
||||
HOOK_MESSAGE(Health);
|
||||
HOOK_MESSAGE(Damage);
|
||||
m_iHealth = 100;
|
||||
m_fFade = 0;
|
||||
m_iFlags = 0;
|
||||
m_bitsDamage = 0;
|
||||
m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
|
||||
giDmgHeight = 0;
|
||||
giDmgWidth = 0;
|
||||
|
||||
memset(m_dmg, 0, sizeof(DAMAGE_IMAGE) * NUM_DMG_TYPES);
|
||||
|
||||
|
||||
gHUD.AddHudElem(this);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CHudHealth::Reset( void )
|
||||
{
|
||||
// make sure the pain compass is cleared when the player respawns
|
||||
m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
|
||||
|
||||
|
||||
// force all the flashing damage icons to expire
|
||||
m_bitsDamage = 0;
|
||||
for ( int i = 0; i < NUM_DMG_TYPES; i++ )
|
||||
{
|
||||
m_dmg[i].fExpire = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CHudHealth::VidInit(void)
|
||||
{
|
||||
m_hSprite = 0;
|
||||
// m_hDecoration = gHUD.GetSpriteIndex( "health_decoration" ); // buz
|
||||
|
||||
m_HUD_dmg_bio = gHUD.GetSpriteIndex( "dmg_bio" ) + 1;
|
||||
m_HUD_cross = gHUD.GetSpriteIndex( "cross" );
|
||||
|
||||
giDmgHeight = gHUD.GetSpriteRect(m_HUD_dmg_bio).right - gHUD.GetSpriteRect(m_HUD_dmg_bio).left;
|
||||
giDmgWidth = gHUD.GetSpriteRect(m_HUD_dmg_bio).bottom - gHUD.GetSpriteRect(m_HUD_dmg_bio).top;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudHealth:: MsgFunc_Health(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
// TODO: update local health data
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
int x = READ_BYTE();
|
||||
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
// Only update the fade if we've changed health
|
||||
if (x != m_iHealth)
|
||||
{
|
||||
m_fFade = FADE_TIME;
|
||||
m_iHealth = x;
|
||||
}
|
||||
|
||||
gViewPort->m_pHud2->UpdateHealth(x); // buz
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudHealth:: MsgFunc_Damage(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
int armor = READ_BYTE(); // armor
|
||||
int damageTaken = READ_BYTE(); // health
|
||||
long bitsDamage = READ_LONG(); // damage bits
|
||||
|
||||
Vector vecFrom;
|
||||
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
vecFrom[i] = READ_COORD();
|
||||
|
||||
UpdateTiles(gHUD.m_flTime, bitsDamage);
|
||||
|
||||
// Actually took damage?
|
||||
if( damageTaken > 0 || armor > 0)
|
||||
{
|
||||
CalcDamageDirection( vecFrom );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Returns back a color from the
|
||||
// Green <-> Yellow <-> Red ramp
|
||||
void CHudHealth::GetPainColor( int &r, int &g, int &b )
|
||||
{
|
||||
int iHealth = m_iHealth;
|
||||
|
||||
if (iHealth > 25)
|
||||
iHealth -= 25;
|
||||
else if ( iHealth < 0 )
|
||||
iHealth = 0;
|
||||
#if 0
|
||||
g = iHealth * 255 / 100;
|
||||
r = 255 - g;
|
||||
b = 0;
|
||||
#else
|
||||
if (m_iHealth > 25)
|
||||
{
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 250;
|
||||
g = 0;
|
||||
b = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int CHudHealth::Draw(float flTime)
|
||||
{
|
||||
// gEngfuncs.Con_Printf("drawing health. decindex is %d\n", m_hDecoration);
|
||||
|
||||
if ( (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || gEngfuncs.IsSpectateOnly() )
|
||||
return 1;
|
||||
|
||||
if ( !m_hSprite )
|
||||
m_hSprite = LoadSprite(PAIN_NAME);
|
||||
|
||||
#if (0) // buz: dont draw health!
|
||||
int r, g, b;
|
||||
int a = 0, x, y;
|
||||
int HealthWidth;
|
||||
|
||||
// Has health changed? Flash the health # // buz - comment from here
|
||||
if (m_fFade)
|
||||
{
|
||||
m_fFade -= (gHUD.m_flTimeDelta * 20);
|
||||
if (m_fFade <= 0)
|
||||
{
|
||||
a = MIN_ALPHA;
|
||||
m_fFade = 0;
|
||||
}
|
||||
|
||||
// Fade the health number back to dim
|
||||
|
||||
a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128;
|
||||
|
||||
}
|
||||
else
|
||||
a = MIN_ALPHA;
|
||||
|
||||
// If health is getting low, make it bright red
|
||||
if (m_iHealth <= 15)
|
||||
a = 255;
|
||||
|
||||
GetPainColor( r, g, b );
|
||||
ScaleColors(r, g, b, a ); // buz - to here
|
||||
|
||||
// r = 255; g = 255; b = 255; //buz
|
||||
|
||||
// Only draw health if we have the suit.
|
||||
if (FBitSet( gHUD.m_iHideHUDDisplay, ITEM_SUIT ))
|
||||
{
|
||||
// buz: draw decoration
|
||||
// SPR_Set(gHUD.GetSprite(m_hDecoration), 255, 255, 255 );
|
||||
// SPR_DrawHoles(0, 0, ScreenHeight - (gHUD.GetSpriteRect(m_hDecoration).bottom - gHUD.GetSpriteRect(m_hDecoration).top), &gHUD.GetSpriteRect(m_hDecoration));
|
||||
|
||||
// buz- comment from here
|
||||
HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
|
||||
int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left;
|
||||
|
||||
y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
|
||||
x = CrossWidth /2;
|
||||
|
||||
SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b);
|
||||
SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross));
|
||||
|
||||
x = CrossWidth + HealthWidth / 2;
|
||||
|
||||
x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b);
|
||||
|
||||
x += HealthWidth/2;
|
||||
|
||||
int iHeight = gHUD.m_iFontHeight;
|
||||
int iWidth = HealthWidth/10;
|
||||
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor); //LRC
|
||||
//LRC FillRGBA(x, y, iWidth, iHeight, 255, 160, 0, a);
|
||||
FillRGBA(x, y, iWidth, iHeight, r, g, b, a); //LRC buz - to here
|
||||
/* if (ScreenWidth < 640)
|
||||
{
|
||||
x = 57;
|
||||
y = ScreenHeight - 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 112;
|
||||
y = ScreenHeight - 29;
|
||||
}*/ // buz
|
||||
|
||||
// gEngfuncs.Con_Printf("Health amount: %d\n", m_iHealth);
|
||||
// x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b);
|
||||
}
|
||||
#endif // buz
|
||||
|
||||
DrawDamage(flTime);
|
||||
return DrawPain(flTime);
|
||||
}
|
||||
|
||||
void CHudHealth::CalcDamageDirection(Vector vecFrom)
|
||||
{
|
||||
Vector forward, right, up;
|
||||
float side, front;
|
||||
Vector vecOrigin, vecAngles;
|
||||
|
||||
if (!vecFrom[0] && !vecFrom[1] && !vecFrom[2])
|
||||
{
|
||||
m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
memcpy(vecOrigin, gHUD.m_vecOrigin, sizeof(Vector));
|
||||
memcpy(vecAngles, gHUD.m_vecAngles, sizeof(Vector));
|
||||
|
||||
|
||||
VectorSubtract (vecFrom, vecOrigin, vecFrom);
|
||||
|
||||
float flDistToTarget = vecFrom.Length();
|
||||
|
||||
vecFrom = vecFrom.Normalize();
|
||||
AngleVectors (vecAngles, forward, right, up);
|
||||
|
||||
front = DotProduct (vecFrom, right);
|
||||
side = DotProduct (vecFrom, forward);
|
||||
|
||||
if (flDistToTarget <= 50)
|
||||
{
|
||||
m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (side > 0)
|
||||
{
|
||||
if (side > 0.3)
|
||||
m_fAttackFront = max(m_fAttackFront, side);
|
||||
}
|
||||
else
|
||||
{
|
||||
float f = fabs(side);
|
||||
if (f > 0.3)
|
||||
m_fAttackRear = max(m_fAttackRear, f);
|
||||
}
|
||||
|
||||
if (front > 0)
|
||||
{
|
||||
if (front > 0.3)
|
||||
m_fAttackRight = max(m_fAttackRight, front);
|
||||
}
|
||||
else
|
||||
{
|
||||
float f = fabs(front);
|
||||
if (f > 0.3)
|
||||
m_fAttackLeft = max(m_fAttackLeft, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CHudHealth::DrawPain(float flTime)
|
||||
{
|
||||
if (!(m_fAttackFront || m_fAttackRear || m_fAttackLeft || m_fAttackRight))
|
||||
return 1;
|
||||
|
||||
int r, g, b;
|
||||
int x, y, a, shade;
|
||||
|
||||
// TODO: get the shift value of the health
|
||||
a = 255; // max brightness until then
|
||||
|
||||
float fFade = gHUD.m_flTimeDelta * 2;
|
||||
|
||||
// SPR_Draw top
|
||||
if (m_fAttackFront > 0.4)
|
||||
{
|
||||
GetPainColor(r,g,b);
|
||||
shade = a * max( m_fAttackFront, 0.5 );
|
||||
ScaleColors(r, g, b, shade);
|
||||
SPR_Set(m_hSprite, r, g, b );
|
||||
|
||||
x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2;
|
||||
y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3;
|
||||
SPR_DrawAdditive(0, x, y, NULL);
|
||||
m_fAttackFront = max( 0, m_fAttackFront - fFade );
|
||||
} else
|
||||
m_fAttackFront = 0;
|
||||
|
||||
if (m_fAttackRight > 0.4)
|
||||
{
|
||||
GetPainColor(r,g,b);
|
||||
shade = a * max( m_fAttackRight, 0.5 );
|
||||
ScaleColors(r, g, b, shade);
|
||||
SPR_Set(m_hSprite, r, g, b );
|
||||
|
||||
x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2;
|
||||
y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2;
|
||||
SPR_DrawAdditive(1, x, y, NULL);
|
||||
m_fAttackRight = max( 0, m_fAttackRight - fFade );
|
||||
} else
|
||||
m_fAttackRight = 0;
|
||||
|
||||
if (m_fAttackRear > 0.4)
|
||||
{
|
||||
GetPainColor(r,g,b);
|
||||
shade = a * max( m_fAttackRear, 0.5 );
|
||||
ScaleColors(r, g, b, shade);
|
||||
SPR_Set(m_hSprite, r, g, b );
|
||||
|
||||
x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2;
|
||||
y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2;
|
||||
SPR_DrawAdditive(2, x, y, NULL);
|
||||
m_fAttackRear = max( 0, m_fAttackRear - fFade );
|
||||
} else
|
||||
m_fAttackRear = 0;
|
||||
|
||||
if (m_fAttackLeft > 0.4)
|
||||
{
|
||||
GetPainColor(r,g,b);
|
||||
shade = a * max( m_fAttackLeft, 0.5 );
|
||||
ScaleColors(r, g, b, shade);
|
||||
SPR_Set(m_hSprite, r, g, b );
|
||||
|
||||
x = ScreenWidth/2 - SPR_Width(m_hSprite, 3) * 3;
|
||||
y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2;
|
||||
SPR_DrawAdditive(3, x, y, NULL);
|
||||
|
||||
m_fAttackLeft = max( 0, m_fAttackLeft - fFade );
|
||||
} else
|
||||
m_fAttackLeft = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudHealth::DrawDamage(float flTime)
|
||||
{
|
||||
int r, g, b, a;
|
||||
DAMAGE_IMAGE *pdmg;
|
||||
|
||||
if (!m_bitsDamage)
|
||||
return 1;
|
||||
|
||||
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
||||
|
||||
a = (int)( fabs(sin(flTime*2)) * 256.0);
|
||||
|
||||
ScaleColors(r, g, b, a);
|
||||
|
||||
// Draw all the items
|
||||
for (int i = 0; i < NUM_DMG_TYPES; i++)
|
||||
{
|
||||
if (m_bitsDamage & giDmgFlags[i])
|
||||
{
|
||||
pdmg = &m_dmg[i];
|
||||
HSPRITE hCurrent = gHUD.GetSprite( m_HUD_dmg_bio + i );
|
||||
if( !hCurrent ) continue; // sprite was missed
|
||||
SPR_Set( hCurrent, r, g, b );
|
||||
SPR_DrawAdditive(0, pdmg->x, pdmg->y, &gHUD.GetSpriteRect(m_HUD_dmg_bio + i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for bits that should be expired
|
||||
for ( i = 0; i < NUM_DMG_TYPES; i++ )
|
||||
{
|
||||
DAMAGE_IMAGE *pdmg = &m_dmg[i];
|
||||
|
||||
if ( m_bitsDamage & giDmgFlags[i] )
|
||||
{
|
||||
pdmg->fExpire = min( flTime + DMG_IMAGE_LIFE, pdmg->fExpire );
|
||||
|
||||
if ( pdmg->fExpire <= flTime // when the time has expired
|
||||
&& a < 40 ) // and the flash is at the low point of the cycle
|
||||
{
|
||||
pdmg->fExpire = 0;
|
||||
|
||||
int y = pdmg->y;
|
||||
pdmg->x = pdmg->y = 0;
|
||||
|
||||
// move everyone above down
|
||||
for (int j = 0; j < NUM_DMG_TYPES; j++)
|
||||
{
|
||||
pdmg = &m_dmg[j];
|
||||
if ((pdmg->y) && (pdmg->y < y))
|
||||
pdmg->y += giDmgHeight;
|
||||
|
||||
}
|
||||
|
||||
m_bitsDamage &= ~giDmgFlags[i]; // clear the bits
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CHudHealth::UpdateTiles(float flTime, long bitsDamage)
|
||||
{
|
||||
DAMAGE_IMAGE *pdmg;
|
||||
|
||||
// Which types are new?
|
||||
long bitsOn = ~m_bitsDamage & bitsDamage;
|
||||
|
||||
for (int i = 0; i < NUM_DMG_TYPES; i++)
|
||||
{
|
||||
pdmg = &m_dmg[i];
|
||||
|
||||
// Is this one already on?
|
||||
if (m_bitsDamage & giDmgFlags[i])
|
||||
{
|
||||
pdmg->fExpire = flTime + DMG_IMAGE_LIFE; // extend the duration
|
||||
if (!pdmg->fBaseline)
|
||||
pdmg->fBaseline = flTime;
|
||||
}
|
||||
|
||||
// Are we just turning it on?
|
||||
if (bitsOn & giDmgFlags[i])
|
||||
{
|
||||
// put this one at the bottom
|
||||
pdmg->x = giDmgWidth/8;
|
||||
pdmg->y = ScreenHeight - giDmgHeight * 2;
|
||||
pdmg->fExpire=flTime + DMG_IMAGE_LIFE;
|
||||
|
||||
// move everyone else up
|
||||
for (int j = 0; j < NUM_DMG_TYPES; j++)
|
||||
{
|
||||
if (j == i)
|
||||
continue;
|
||||
|
||||
pdmg = &m_dmg[j];
|
||||
if (pdmg->y)
|
||||
pdmg->y -= giDmgHeight;
|
||||
|
||||
}
|
||||
pdmg = &m_dmg[i];
|
||||
}
|
||||
}
|
||||
|
||||
// damage bits are only turned on here; they are turned off when the draw time has expired (in DrawDamage())
|
||||
m_bitsDamage |= bitsDamage;
|
||||
}
|
128
cl_dll/health.h
Normal file
128
cl_dll/health.h
Normal file
@ -0,0 +1,128 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
#define DMG_IMAGE_LIFE 2 // seconds that image is up
|
||||
|
||||
#define DMG_IMAGE_POISON 0
|
||||
#define DMG_IMAGE_ACID 1
|
||||
#define DMG_IMAGE_COLD 2
|
||||
#define DMG_IMAGE_DROWN 3
|
||||
#define DMG_IMAGE_BURN 4
|
||||
#define DMG_IMAGE_NERVE 5
|
||||
#define DMG_IMAGE_RAD 6
|
||||
#define DMG_IMAGE_SHOCK 7
|
||||
//tf defines
|
||||
#define DMG_IMAGE_CALTROP 8
|
||||
#define DMG_IMAGE_TRANQ 9
|
||||
#define DMG_IMAGE_CONCUSS 10
|
||||
#define DMG_IMAGE_HALLUC 11
|
||||
#define NUM_DMG_TYPES 12
|
||||
// instant damage
|
||||
|
||||
#define DMG_GENERIC 0 // generic damage was done
|
||||
#define DMG_CRUSH (1 << 0) // crushed by falling or moving object
|
||||
#define DMG_BULLET (1 << 1) // shot
|
||||
#define DMG_SLASH (1 << 2) // cut, clawed, stabbed
|
||||
#define DMG_BURN (1 << 3) // heat burned
|
||||
#define DMG_FREEZE (1 << 4) // frozen
|
||||
#define DMG_FALL (1 << 5) // fell too far
|
||||
#define DMG_BLAST (1 << 6) // explosive blast damage
|
||||
#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt
|
||||
#define DMG_SHOCK (1 << 8) // electric shock
|
||||
#define DMG_SONIC (1 << 9) // sound pulse shockwave
|
||||
#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam
|
||||
#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death
|
||||
#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death.
|
||||
|
||||
|
||||
// time-based damage
|
||||
//mask off TF-specific stuff too
|
||||
#define DMG_TIMEBASED (~(0xff003fff)) // mask for time-based damage
|
||||
|
||||
|
||||
#define DMG_DROWN (1 << 14) // Drowning
|
||||
#define DMG_FIRSTTIMEBASED DMG_DROWN
|
||||
|
||||
#define DMG_PARALYZE (1 << 15) // slows affected creature down
|
||||
#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
|
||||
#define DMG_POISON (1 << 17) // blood poisioning
|
||||
#define DMG_RADIATION (1 << 18) // radiation exposure
|
||||
#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
|
||||
#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
|
||||
#define DMG_SLOWBURN (1 << 21) // in an oven
|
||||
#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer
|
||||
#define DMG_MORTAR (1 << 23) // Hit by air raid (done to distinguish grenade from mortar)
|
||||
|
||||
//TF ADDITIONS
|
||||
#define DMG_IGNITE (1 << 24) // Players hit by this begin to burn
|
||||
#define DMG_RADIUS_MAX (1 << 25) // Radius damage with this flag doesn't decrease over distance
|
||||
#define DMG_RADIUS_QUAKE (1 << 26) // Radius damage is done like Quake. 1/2 damage at 1/2 radius.
|
||||
#define DMG_IGNOREARMOR (1 << 27) // Damage ignores target's armor
|
||||
#define DMG_AIMED (1 << 28) // Does Hit location damage
|
||||
#define DMG_WALLPIERCING (1 << 29) // Blast Damages ents through walls
|
||||
|
||||
#define DMG_CALTROP (1<<30)
|
||||
#define DMG_HALLUC (1<<31)
|
||||
|
||||
// TF Healing Additions for TakeHealth
|
||||
#define DMG_IGNORE_MAXHEALTH DMG_IGNITE
|
||||
// TF Redefines since we never use the originals
|
||||
#define DMG_NAIL DMG_SLASH
|
||||
#define DMG_NOT_SELF DMG_FREEZE
|
||||
|
||||
|
||||
#define DMG_TRANQ DMG_MORTAR
|
||||
#define DMG_CONCUSS DMG_SONIC
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float fExpire;
|
||||
float fBaseline;
|
||||
int x, y;
|
||||
} DAMAGE_IMAGE;
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudHealth: public CHudBase
|
||||
{
|
||||
public:
|
||||
virtual int Init( void );
|
||||
virtual int VidInit( void );
|
||||
virtual int Draw(float fTime);
|
||||
virtual void Reset( void );
|
||||
int MsgFunc_Health(const char *pszName, int iSize, void *pbuf);
|
||||
int MsgFunc_Damage(const char *pszName, int iSize, void *pbuf);
|
||||
int m_iHealth;
|
||||
int m_HUD_dmg_bio;
|
||||
int m_HUD_cross;
|
||||
float m_fAttackFront, m_fAttackRear, m_fAttackLeft, m_fAttackRight;
|
||||
void GetPainColor( int &r, int &g, int &b );
|
||||
float m_fFade;
|
||||
|
||||
private:
|
||||
HSPRITE m_hSprite;
|
||||
HSPRITE m_hDamage;
|
||||
int m_hDecoration; // buz
|
||||
|
||||
DAMAGE_IMAGE m_dmg[NUM_DMG_TYPES];
|
||||
int m_bitsDamage;
|
||||
int DrawPain(float fTime);
|
||||
int DrawDamage(float fTime);
|
||||
void CalcDamageDirection(vec3_t vecFrom);
|
||||
void UpdateTiles(float fTime, long bits);
|
||||
};
|
889
cl_dll/hud.cpp
Normal file
889
cl_dll/hud.cpp
Normal file
@ -0,0 +1,889 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// hud.cpp
|
||||
//
|
||||
// implementation of CHud class
|
||||
//
|
||||
|
||||
//LRC - define to help track what calls are made on changelevel, save/restore, etc
|
||||
#define ENGINE_DEBUG
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include <stringlib.h>
|
||||
#include <stdio.h>
|
||||
#include "parsemsg.h"
|
||||
#include "hud_servers.h"
|
||||
#include "vgui_int.h"
|
||||
#include "vgui_TeamFortressViewport.h"
|
||||
#include "vgui_subtitles.h" // buz
|
||||
#include "vgui_radio.h" // buz
|
||||
#include "vgui_hud.h" // buz
|
||||
#include "vgui_tabpanel.h" // buz
|
||||
#include "studio.h"
|
||||
#include "demo.h"
|
||||
#include "demo_api.h"
|
||||
#include "vgui_scorepanel.h"
|
||||
#include "gl_local.h" // buz
|
||||
#include "r_studioint.h"
|
||||
|
||||
cvar_t *cl_rollspeed;
|
||||
cvar_t *cl_rollangle;
|
||||
|
||||
class CHLVoiceStatusHelper : public IVoiceStatusHelper
|
||||
{
|
||||
public:
|
||||
virtual void GetPlayerTextColor(int entindex, int color[3])
|
||||
{
|
||||
color[0] = color[1] = color[2] = 255;
|
||||
|
||||
if( entindex >= 0 && entindex < sizeof(g_PlayerExtraInfo)/sizeof(g_PlayerExtraInfo[0]) )
|
||||
{
|
||||
int iTeam = g_PlayerExtraInfo[entindex].teamnumber;
|
||||
|
||||
if ( iTeam < 0 )
|
||||
{
|
||||
iTeam = 0;
|
||||
}
|
||||
|
||||
iTeam = iTeam % iNumberOfTeamColors;
|
||||
|
||||
color[0] = iTeamColors[iTeam][0];
|
||||
color[1] = iTeamColors[iTeam][1];
|
||||
color[2] = iTeamColors[iTeam][2];
|
||||
}
|
||||
}
|
||||
|
||||
virtual void UpdateCursorState()
|
||||
{
|
||||
gViewPort->UpdateCursorState();
|
||||
}
|
||||
|
||||
virtual int GetAckIconHeight()
|
||||
{
|
||||
return ScreenHeight - gHUD.m_iFontHeight*3 - 6;
|
||||
}
|
||||
|
||||
virtual bool CanShowSpeakerLabels()
|
||||
{
|
||||
if( gViewPort && gViewPort->m_pScoreBoard )
|
||||
return !gViewPort->m_pScoreBoard->isVisible();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static CHLVoiceStatusHelper g_VoiceStatusHelper;
|
||||
|
||||
|
||||
extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
|
||||
extern cvar_t *sensitivity;
|
||||
cvar_t *cl_lw = NULL;
|
||||
|
||||
void ShutdownInput (void);
|
||||
|
||||
//DECLARE_MESSAGE(m_Logo, Logo)
|
||||
int __MsgFunc_Logo(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_Logo(pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
//DECLARE_MESSAGE(m_Logo, Logo)
|
||||
//LRC
|
||||
int __MsgFunc_HUDColor(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_HUDColor(pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
//LRC
|
||||
int __MsgFunc_SetFog(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
gHUD.MsgFunc_SetFog( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
//LRC
|
||||
int __MsgFunc_KeyedDLight(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
gHUD.MsgFunc_KeyedDLight( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
//LRC
|
||||
int __MsgFunc_SetSky(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
gHUD.MsgFunc_SetSky( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
#ifdef ENGINE_DEBUG
|
||||
// CONPRINT("## ResetHUD\n");
|
||||
#endif
|
||||
return gHUD.MsgFunc_ResetHUD(pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_InitHUD(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
#ifdef ENGINE_DEBUG
|
||||
// CONPRINT("## InitHUD\n");
|
||||
#endif
|
||||
gHUD.MsgFunc_InitHUD( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __MsgFunc_ViewMode(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
gHUD.MsgFunc_ViewMode( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_SetFOV( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_Concuss(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_Concuss( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_GameMode( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
return gHUD.MsgFunc_GameMode( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_WaterSplash( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
gHUD.MsgFunc_WaterSplash( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __MsgFunc_NewExplode( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
gHUD.MsgFunc_NewExplode( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// buz
|
||||
int __MsgFunc_GasMask(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
return gHUD.MsgFunc_GasMask( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
// buz
|
||||
int __MsgFunc_SpecTank(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
return gHUD.MsgFunc_SpecTank( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_HeadShield(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_HeadShield( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_Particle(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_Particle( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_DelParticle(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_DelParticle( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_WeaponAnim(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_WeaponAnim( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_WeaponBody(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_WeaponBody( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_WeaponSkin(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_WeaponSkin( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_SkyMarker(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_SkyMarker( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_WorldMarker(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_WorldMarker( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_CustomDecal(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_CustomDecal( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_StudioDecal(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_StudioDecal( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_PartEffect(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_PartEffect( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_LevelTime(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_LevelTime( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int __MsgFunc_BlurEffect(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
gHUD.MsgFunc_BlurEffect( pszName, iSize, pbuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TFFree Command Menu
|
||||
void __CmdFunc_OpenCommandMenu(void)
|
||||
{
|
||||
if ( gViewPort )
|
||||
{
|
||||
gViewPort->ShowCommandMenu( gViewPort->m_StandardMenu );
|
||||
}
|
||||
}
|
||||
|
||||
// TFC "special" command
|
||||
void __CmdFunc_InputPlayerSpecial(void)
|
||||
{
|
||||
if ( gViewPort )
|
||||
{
|
||||
gViewPort->InputPlayerSpecial();
|
||||
}
|
||||
}
|
||||
|
||||
void __CmdFunc_CloseCommandMenu(void)
|
||||
{
|
||||
if ( gViewPort )
|
||||
{
|
||||
gViewPort->InputSignalHideCommandMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void __CmdFunc_ForceCloseCommandMenu( void )
|
||||
{
|
||||
if ( gViewPort )
|
||||
{
|
||||
gViewPort->HideCommandMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void __CmdFunc_ToggleServerBrowser( void )
|
||||
{
|
||||
if ( gViewPort )
|
||||
{
|
||||
gViewPort->ToggleServerBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
// TFFree Command Menu Message Handlers
|
||||
int __MsgFunc_ValClass(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_ValClass( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_TeamNames(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_TeamNames( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_Feign(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_Feign( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_Detpack(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_Detpack( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_VGUIMenu(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_VGUIMenu( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_MOTD(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_MOTD( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_BuildSt(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_BuildSt( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_RandomPC(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_RandomPC( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_ServerName(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_ServerName( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_ScoreInfo(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_ScoreInfo( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_TeamScore(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_TeamScore( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_TeamInfo(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_TeamInfo( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_Spectator(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_Spectator( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_AllowSpec(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_AllowSpec( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __MsgFunc_MusicFade(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
return gHUD.MsgFunc_MusicFade( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
// buz
|
||||
int __MsgFunc_TextWindow(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
if (gViewPort)
|
||||
return gViewPort->MsgFunc_ShowTextWindow( pszName, iSize, pbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// buz
|
||||
int __MsgFunc_RainData(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
return gHUD.MsgFunc_RainData( pszName, iSize, pbuf );
|
||||
}
|
||||
|
||||
int MsgCustomDlight(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
vec3_t pos;
|
||||
pos.x = READ_COORD();
|
||||
pos.y = READ_COORD();
|
||||
pos.z = READ_COORD();
|
||||
float radius = (float)READ_BYTE() * 10;
|
||||
float life = (float)READ_BYTE() / 10;
|
||||
float decay = (float)READ_BYTE() * 10;
|
||||
|
||||
CDynLight *dl = CL_AllocDlight (0);
|
||||
|
||||
R_SetupLightParams( dl, pos, g_vecZero, radius, 0.0f, LIGHT_OMNI );
|
||||
|
||||
dl->color = Vector( 0.7f, 0.6f, 0.5f );
|
||||
dl->die = GET_CLIENT_TIME() + life;
|
||||
dl->decay = decay;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// debug command
|
||||
// usage: makelight [R G B] [radius] [life]\n" );
|
||||
void MakeLight( void )
|
||||
{
|
||||
CDynLight *dl = CL_AllocDlight( 0 );
|
||||
|
||||
if( CMD_ARGC() >= 4 )
|
||||
{
|
||||
dl->color[0] = Q_atof(CMD_ARGV( 1 ));
|
||||
dl->color[1] = Q_atof(CMD_ARGV( 2 ));
|
||||
dl->color[2] = Q_atof(CMD_ARGV( 3 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
dl->color = Vector( 0.7f, 0.6f, 0.5f );
|
||||
}
|
||||
|
||||
float radius;
|
||||
|
||||
if( CMD_ARGC() >= 5 )
|
||||
radius = Q_atof(CMD_ARGV( 4 ));
|
||||
else radius = 128.0f;
|
||||
|
||||
R_SetupLightParams( dl, GetVieworg(), g_vecZero, radius, 0.0f, LIGHT_OMNI );
|
||||
|
||||
if( CMD_ARGC() >= 6 )
|
||||
dl->die = GET_CLIENT_TIME() + Q_atof(CMD_ARGV( 5 ));
|
||||
else dl->die = GET_CLIENT_TIME() + 30.0f;
|
||||
}
|
||||
|
||||
void GammaGraphInit();
|
||||
|
||||
void CanUseInit( void ); // Wargon: Èêîíêà þçà.
|
||||
|
||||
// This is called every time the DLL is loaded
|
||||
void CHud :: Init( void )
|
||||
{
|
||||
static cl_entity_t head_shield;
|
||||
|
||||
GammaGraphInit();
|
||||
RadioIconInit(); // buz
|
||||
Hud2Init(); // buz
|
||||
SubtitleInit(); // buz
|
||||
TabPanelInit(); // buz
|
||||
|
||||
CanUseInit(); // Wargon: Èêîíêà þçà.
|
||||
|
||||
// pointer to headshield entity
|
||||
m_pHeadShieldEnt = &head_shield;
|
||||
|
||||
HOOK_MESSAGE( Logo );
|
||||
HOOK_MESSAGE( ResetHUD );
|
||||
HOOK_MESSAGE( GameMode );
|
||||
HOOK_MESSAGE( InitHUD );
|
||||
HOOK_MESSAGE( ViewMode );
|
||||
HOOK_MESSAGE( SetFOV );
|
||||
HOOK_MESSAGE( Concuss );
|
||||
HOOK_MESSAGE( HUDColor ); //LRC
|
||||
HOOK_MESSAGE( SetFog ); //LRC
|
||||
HOOK_MESSAGE( KeyedDLight ); //LRC
|
||||
HOOK_MESSAGE( SetSky ); //LRC
|
||||
HOOK_MESSAGE( GasMask ); //buz
|
||||
HOOK_MESSAGE( SpecTank ); //buz
|
||||
HOOK_MESSAGE( TextWindow ); // buz
|
||||
HOOK_MESSAGE( RainData );// buz
|
||||
HOOK_MESSAGE( Particle );// buz
|
||||
HOOK_MESSAGE( DelParticle );// buz
|
||||
gEngfuncs.pfnHookUserMsg( "mydlight", MsgCustomDlight );
|
||||
|
||||
// TFFree CommandMenu
|
||||
HOOK_COMMAND( "+commandmenu", OpenCommandMenu );
|
||||
HOOK_COMMAND( "-commandmenu", CloseCommandMenu );
|
||||
HOOK_COMMAND( "ForceCloseCommandMenu", ForceCloseCommandMenu );
|
||||
HOOK_COMMAND( "special", InputPlayerSpecial );
|
||||
HOOK_COMMAND( "togglebrowser", ToggleServerBrowser );
|
||||
gEngfuncs.pfnAddCommand( "makelight", MakeLight );
|
||||
|
||||
HOOK_MESSAGE( ValClass );
|
||||
HOOK_MESSAGE( TeamNames );
|
||||
HOOK_MESSAGE( Feign );
|
||||
HOOK_MESSAGE( Detpack );
|
||||
HOOK_MESSAGE( MOTD );
|
||||
HOOK_MESSAGE( BuildSt );
|
||||
HOOK_MESSAGE( RandomPC );
|
||||
HOOK_MESSAGE( ServerName );
|
||||
HOOK_MESSAGE( ScoreInfo );
|
||||
HOOK_MESSAGE( TeamScore );
|
||||
HOOK_MESSAGE( TeamInfo );
|
||||
|
||||
HOOK_MESSAGE( Spectator );
|
||||
HOOK_MESSAGE( AllowSpec );
|
||||
HOOK_MESSAGE( WaterSplash );
|
||||
HOOK_MESSAGE( NewExplode );
|
||||
HOOK_MESSAGE( HeadShield );
|
||||
|
||||
HOOK_MESSAGE( WeaponAnim );
|
||||
HOOK_MESSAGE( WeaponBody );
|
||||
HOOK_MESSAGE( WeaponSkin );
|
||||
|
||||
HOOK_MESSAGE( SkyMarker );
|
||||
HOOK_MESSAGE( WorldMarker );
|
||||
|
||||
HOOK_MESSAGE( StudioDecal );
|
||||
HOOK_MESSAGE( CustomDecal );
|
||||
|
||||
HOOK_MESSAGE( PartEffect );
|
||||
HOOK_MESSAGE( LevelTime );
|
||||
|
||||
HOOK_MESSAGE( BlurEffect );
|
||||
|
||||
// VGUI Menus
|
||||
HOOK_MESSAGE( VGUIMenu );
|
||||
|
||||
m_pZoomSpeed = gEngfuncs.pfnRegisterVariable( "cl_zoomspeed","100", 0 );
|
||||
CVAR_REGISTER( "hud_classautokill", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); // controls whether or not to suicide immediately on TF class switch
|
||||
CVAR_REGISTER( "hud_takesshots", "0", FCVAR_ARCHIVE );// controls whether or not to automatically take screenshots at the end of a round
|
||||
|
||||
HOOK_MESSAGE( MusicFade );
|
||||
|
||||
m_iLogo = 0;
|
||||
m_iFOV = 90; // buz - make 90, not 0
|
||||
m_iHUDColor = 0x00FFA000; //255,160,0 -- LRC
|
||||
|
||||
CVAR_REGISTER( "zoom_sensitivity_ratio", "1.2", 0 );
|
||||
default_fov = CVAR_REGISTER( "default_fov", "75", FCVAR_ARCHIVE );// buz: turn off
|
||||
m_pCvarStealMouse = CVAR_REGISTER( "hud_capturemouse", "1", FCVAR_ARCHIVE );
|
||||
m_pCvarDraw = CVAR_REGISTER( "hud_draw", "1", FCVAR_ARCHIVE );
|
||||
cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
|
||||
|
||||
cl_rollangle = gEngfuncs.pfnRegisterVariable ( "cl_rollangle", "0.65", FCVAR_CLIENTDLL|FCVAR_ARCHIVE );
|
||||
cl_rollspeed = gEngfuncs.pfnRegisterVariable ( "cl_rollspeed", "300", FCVAR_CLIENTDLL|FCVAR_ARCHIVE );
|
||||
|
||||
m_pSpriteList = NULL;
|
||||
|
||||
// Clear any old HUD list
|
||||
if ( m_pHudList )
|
||||
{
|
||||
HUDLIST *pList;
|
||||
while ( m_pHudList )
|
||||
{
|
||||
pList = m_pHudList;
|
||||
m_pHudList = m_pHudList->pNext;
|
||||
free( pList );
|
||||
}
|
||||
m_pHudList = NULL;
|
||||
}
|
||||
|
||||
// In case we get messages before the first update -- time will be valid
|
||||
m_flTime = 1.0;
|
||||
|
||||
m_Ammo.Init();
|
||||
m_HudStamina.Init();
|
||||
m_Health.Init();
|
||||
m_SayText.Init();
|
||||
m_Spectator.Init();
|
||||
m_Geiger.Init();
|
||||
m_Train.Init();
|
||||
m_Battery.Init();
|
||||
m_Flash.Init();
|
||||
m_Message.Init();
|
||||
m_StatusBar.Init();
|
||||
m_DeathNotice.Init();
|
||||
m_AmmoSecondary.Init();
|
||||
m_TextMessage.Init();
|
||||
m_StatusIcons.Init();
|
||||
m_Lensflare.Init();
|
||||
GetClientVoiceMgr()->Init(&g_VoiceStatusHelper, (vgui::Panel**)&gViewPort);
|
||||
|
||||
m_Menu.Init();
|
||||
|
||||
ServersInit();
|
||||
|
||||
MsgFunc_ResetHUD(0, 0, NULL );
|
||||
}
|
||||
|
||||
// CHud destructor
|
||||
// cleans up memory allocated for m_rg* arrays
|
||||
CHud :: ~CHud()
|
||||
{
|
||||
delete [] m_rghSprites;
|
||||
delete [] m_rgrcRects;
|
||||
delete [] m_rgszSpriteNames;
|
||||
|
||||
if ( m_pHudList )
|
||||
{
|
||||
HUDLIST *pList;
|
||||
while ( m_pHudList )
|
||||
{
|
||||
pList = m_pHudList;
|
||||
m_pHudList = m_pHudList->pNext;
|
||||
free( pList );
|
||||
}
|
||||
m_pHudList = NULL;
|
||||
}
|
||||
|
||||
ServersShutdown();
|
||||
}
|
||||
|
||||
// GetSpriteIndex()
|
||||
// searches through the sprite list loaded from hud.txt for a name matching SpriteName
|
||||
// returns an index into the gHUD.m_rghSprites[] array
|
||||
// returns 0 if sprite not found
|
||||
int CHud :: GetSpriteIndex( const char *SpriteName )
|
||||
{
|
||||
// look through the loaded sprite name list for SpriteName
|
||||
for ( int i = 0; i < m_iSpriteCount; i++ )
|
||||
{
|
||||
if ( strncmp( SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH ) == 0 )
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1; // invalid sprite
|
||||
}
|
||||
|
||||
void CHud :: VidInit( void )
|
||||
{
|
||||
m_flDeadTime = 0; // buz
|
||||
m_SpecTank_on = 0; // buz
|
||||
|
||||
memset( m_pHeadShieldEnt, 0, sizeof(cl_entity_t));
|
||||
m_pHeadShieldEnt->modelhandle = INVALID_HANDLE;
|
||||
m_pHeadShieldEnt->curstate.framerate = 1.0f;
|
||||
m_iHeadShieldState = SHIELD_OFF;
|
||||
m_flHeadShieldSwitchTime = 0.0f;
|
||||
CVAR_SET_FLOAT( "hud_draw", 1.0f );
|
||||
|
||||
m_flFOV = -1; // buz
|
||||
|
||||
m_scrinfo.iSize = sizeof(m_scrinfo);
|
||||
GetScreenInfo(&m_scrinfo);
|
||||
|
||||
// ----------
|
||||
// Load Sprites
|
||||
// ---------
|
||||
// m_hsprFont = LoadSprite("sprites/%d_font.spr");
|
||||
|
||||
m_hsprLogo = 0;
|
||||
m_hsprCursor = 0;
|
||||
|
||||
if (ScreenWidth < 640)
|
||||
m_iRes = 320;
|
||||
else
|
||||
m_iRes = 640;
|
||||
|
||||
// Only load this once
|
||||
if ( !m_pSpriteList )
|
||||
{
|
||||
// we need to load the hud.txt, and all sprites within
|
||||
m_pSpriteList = SPR_GetList("scripts/weapons/hud.txt", &m_iSpriteCountAllRes);
|
||||
|
||||
if (m_pSpriteList)
|
||||
{
|
||||
// count the number of sprites of the appropriate res
|
||||
m_iSpriteCount = 0;
|
||||
client_sprite_t *p = m_pSpriteList;
|
||||
for ( int j = 0; j < m_iSpriteCountAllRes; j++ )
|
||||
{
|
||||
if ( p->iRes == m_iRes )
|
||||
m_iSpriteCount++;
|
||||
p++;
|
||||
}
|
||||
|
||||
// allocated memory for sprite handle arrays
|
||||
m_rghSprites = new HSPRITE[m_iSpriteCount];
|
||||
m_rgrcRects = new wrect_t[m_iSpriteCount];
|
||||
m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH];
|
||||
|
||||
p = m_pSpriteList;
|
||||
int index = 0;
|
||||
for ( j = 0; j < m_iSpriteCountAllRes; j++ )
|
||||
{
|
||||
if ( p->iRes == m_iRes )
|
||||
{
|
||||
char sz[256];
|
||||
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
||||
m_rghSprites[index] = SPR_Load(sz);
|
||||
m_rgrcRects[index] = p->rc;
|
||||
strncpy( &m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH );
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have already have loaded the sprite reference from hud.txt, but
|
||||
// we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game)
|
||||
client_sprite_t *p = m_pSpriteList;
|
||||
int index = 0;
|
||||
for ( int j = 0; j < m_iSpriteCountAllRes; j++ )
|
||||
{
|
||||
if ( p->iRes == m_iRes )
|
||||
{
|
||||
char sz[256];
|
||||
sprintf( sz, "sprites/%s.spr", p->szSprite );
|
||||
m_rghSprites[index] = SPR_Load(sz);
|
||||
index++;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
// assumption: number_1, number_2, etc, are all listed and loaded sequentially
|
||||
m_HUD_number_0 = GetSpriteIndex( "number_0" );
|
||||
|
||||
m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top;
|
||||
|
||||
m_Ammo.VidInit();
|
||||
m_HudStamina.VidInit();
|
||||
m_Health.VidInit();
|
||||
m_Spectator.VidInit();
|
||||
m_Geiger.VidInit();
|
||||
m_Train.VidInit();
|
||||
m_Battery.VidInit();
|
||||
m_Flash.VidInit();
|
||||
m_Message.VidInit();
|
||||
m_StatusBar.VidInit();
|
||||
m_DeathNotice.VidInit();
|
||||
m_SayText.VidInit();
|
||||
m_Menu.VidInit();
|
||||
m_AmmoSecondary.VidInit();
|
||||
m_TextMessage.VidInit();
|
||||
m_StatusIcons.VidInit();
|
||||
m_Lensflare.VidInit();
|
||||
GetClientVoiceMgr()->VidInit();
|
||||
}
|
||||
|
||||
int CHud::MsgFunc_Logo(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
// update Train data
|
||||
m_iLogo = READ_BYTE();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//LRC
|
||||
int CHud::MsgFunc_HUDColor(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
m_iHUDColor = READ_LONG();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//float g_lastFOV = 0.0; buz
|
||||
|
||||
/*
|
||||
=================
|
||||
HUD_IsGame
|
||||
|
||||
=================
|
||||
*/
|
||||
int HUD_IsGame( const char *game )
|
||||
{
|
||||
const char *gamedir;
|
||||
char gd[ 1024 ];
|
||||
|
||||
gamedir = gEngfuncs.pfnGetGameDirectory();
|
||||
if ( gamedir && gamedir[0] )
|
||||
{
|
||||
COM_FileBase( gamedir, gd );
|
||||
if ( !stricmp( gd, game ) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
HUD_GetFOV
|
||||
|
||||
Returns last FOV
|
||||
=====================
|
||||
*/
|
||||
#if 0 // buz
|
||||
float HUD_GetFOV( void )
|
||||
{
|
||||
if ( gEngfuncs.pDemoAPI->IsRecording() )
|
||||
{
|
||||
// Write it
|
||||
int i = 0;
|
||||
unsigned char buf[ 100 ];
|
||||
|
||||
// Active
|
||||
*( float * )&buf[ i ] = g_lastFOV;
|
||||
i += sizeof( float );
|
||||
|
||||
Demo_WriteBuffer( TYPE_ZOOM, i, buf );
|
||||
}
|
||||
|
||||
if ( gEngfuncs.pDemoAPI->IsPlayingback() )
|
||||
{
|
||||
g_lastFOV = g_demozoom;
|
||||
}
|
||||
return g_lastFOV;
|
||||
}
|
||||
#endif
|
||||
|
||||
int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
int newfov = READ_BYTE();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CHud::AddHudElem(CHudBase *phudelem)
|
||||
{
|
||||
HUDLIST *pdl, *ptemp;
|
||||
|
||||
//phudelem->Think();
|
||||
|
||||
if (!phudelem)
|
||||
return;
|
||||
|
||||
pdl = (HUDLIST *)malloc(sizeof(HUDLIST));
|
||||
if (!pdl)
|
||||
return;
|
||||
|
||||
memset(pdl, 0, sizeof(HUDLIST));
|
||||
pdl->p = phudelem;
|
||||
|
||||
if (!m_pHudList)
|
||||
{
|
||||
m_pHudList = pdl;
|
||||
return;
|
||||
}
|
||||
|
||||
ptemp = m_pHudList;
|
||||
|
||||
while (ptemp->pNext)
|
||||
ptemp = ptemp->pNext;
|
||||
|
||||
ptemp->pNext = pdl;
|
||||
}
|
||||
|
||||
float CHud::GetSensitivity( void )
|
||||
{
|
||||
return m_flMouseSensitivity;
|
||||
}
|
832
cl_dll/hud.h
Normal file
832
cl_dll/hud.h
Normal file
@ -0,0 +1,832 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// hud.h
|
||||
//
|
||||
// class CHud declaration
|
||||
//
|
||||
// CHud handles the message, calculation, and drawing the HUD
|
||||
//
|
||||
|
||||
#pragma warning (disable:4018)
|
||||
|
||||
#define DO_TIMING
|
||||
|
||||
#define FOG_LIMIT 30000
|
||||
#define RGB_YELLOWISH 0x00FFA000 //255,160,0
|
||||
#define RGB_REDISH 0x00FF1010 //255,160,0
|
||||
#define RGB_GREENISH 0x0000A000 //0,160,0
|
||||
|
||||
#include "wrect.h"
|
||||
#include "windows.h"
|
||||
#include "cl_dll.h"
|
||||
#include "render_api.h"
|
||||
#include "enginecallback.h"
|
||||
#include "ammo.h"
|
||||
#include "mathlib.h"
|
||||
#include "timing.h"
|
||||
|
||||
#define DHN_DRAWZERO 1
|
||||
#define DHN_2DIGITS 2
|
||||
#define DHN_3DIGITS 4
|
||||
#define MIN_ALPHA 170
|
||||
|
||||
// headshield states
|
||||
#define SHIELD_ON 0
|
||||
#define SHIELD_OFF 1
|
||||
#define SHIELD_TURNING_ON 2
|
||||
#define SHIELD_TURNING_OFF 3
|
||||
|
||||
// headshield anims
|
||||
#define SHIELDANIM_IDLE 0
|
||||
#define SHIELDANIM_DRAW 1
|
||||
#define SHIELDANIM_HOLSTER 2
|
||||
|
||||
#define HUDELEM_ACTIVE 1
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} POSITION;
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_PLAYERS = 64,
|
||||
MAX_TEAMS = 64,
|
||||
MAX_TEAM_NAME = 16,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned char r,g,b,a;
|
||||
} RGBA;
|
||||
|
||||
typedef struct cvar_s cvar_t;
|
||||
|
||||
|
||||
#define HUD_ACTIVE 1
|
||||
#define HUD_INTERMISSION 2
|
||||
|
||||
#define MAX_PLAYER_NAME_LENGTH 32
|
||||
|
||||
#define MAX_MOTD_LENGTH 1536
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudBase
|
||||
{
|
||||
public:
|
||||
POSITION m_pos;
|
||||
int m_type;
|
||||
int m_iFlags; // active, moving,
|
||||
virtual ~CHudBase() {}
|
||||
virtual int Init( void ) {return 0;}
|
||||
virtual int VidInit( void ) {return 0;}
|
||||
virtual int Draw(float flTime) {return 0;}
|
||||
virtual void Think(void) {return;}
|
||||
virtual void Reset(void) {return;}
|
||||
virtual void InitHUDData( void ) {} // called every time a server is connected to
|
||||
|
||||
};
|
||||
|
||||
struct HUDLIST {
|
||||
CHudBase *p;
|
||||
HUDLIST *pNext;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
#include "..\game_shared\voice_status.h"
|
||||
#include "hud_spectator.h"
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudAmmo: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
void Think(void);
|
||||
void Reset(void);
|
||||
void UpdateCrosshair(); // buz
|
||||
int DrawWList(float flTime);
|
||||
int MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf);
|
||||
int MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf);
|
||||
int MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf);
|
||||
int MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
void SlotInput( int iSlot );
|
||||
void _cdecl UserCmd_Slot1( void );
|
||||
void _cdecl UserCmd_Slot2( void );
|
||||
void _cdecl UserCmd_Slot3( void );
|
||||
void _cdecl UserCmd_Slot4( void );
|
||||
void _cdecl UserCmd_Slot5( void );
|
||||
void _cdecl UserCmd_Slot6( void );
|
||||
void _cdecl UserCmd_Slot7( void );
|
||||
void _cdecl UserCmd_Slot8( void );
|
||||
void _cdecl UserCmd_Slot9( void );
|
||||
void _cdecl UserCmd_Slot10( void );
|
||||
void _cdecl UserCmd_Close( void );
|
||||
void _cdecl UserCmd_NextWeapon( void );
|
||||
void _cdecl UserCmd_PrevWeapon( void );
|
||||
|
||||
void LoadMenuSettings( void );
|
||||
|
||||
// buz: these variables loaded from file menu_settings.txt
|
||||
int m_menuSizeX;
|
||||
int m_menuSizeY;
|
||||
float m_menuScale;
|
||||
float m_menuMinAlpha;
|
||||
float m_menuAddAlpha;
|
||||
float m_menuSpeed;
|
||||
int m_menuRenderMode;
|
||||
int m_menuOfsX;
|
||||
int m_menuOfsY;
|
||||
int m_menuSpaceX;
|
||||
int m_menuSpaceY;
|
||||
int m_menuNumberSizeX;
|
||||
int m_menuNumberSizeY;
|
||||
|
||||
//private:
|
||||
float m_fFade;
|
||||
RGBA m_rgba;
|
||||
WEAPON *m_pWeapon;
|
||||
int m_HUD_bucket0;
|
||||
int m_HUD_selection;
|
||||
int m_mach; // buz
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
|
||||
class CHudAmmoSecondary: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
void Reset( void );
|
||||
int Draw(float flTime);
|
||||
|
||||
int MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
private:
|
||||
enum {
|
||||
MAX_SEC_AMMO_VALUES = 4
|
||||
};
|
||||
|
||||
int m_HUD_ammoicon; // sprite indices
|
||||
int m_iAmmoAmounts[MAX_SEC_AMMO_VALUES];
|
||||
float m_fFade;
|
||||
};
|
||||
|
||||
|
||||
#include "health.h"
|
||||
|
||||
|
||||
#define FADE_TIME 100
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudGeiger: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
int MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
private:
|
||||
int m_iGeigerRange;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudTrain: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
int MsgFunc_Train(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
private:
|
||||
HSPRITE m_hSprite;
|
||||
int m_iPos;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudLensflare: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
int DrawFlare( const Vector &forward, const Vector &lightdir, const Vector &lightorg );
|
||||
private:
|
||||
float flPlayerBlend;
|
||||
float flPlayerBlend2;
|
||||
float flPlayerBlend3;
|
||||
float flPlayerBlend4;
|
||||
float flPlayerBlend5;
|
||||
float flPlayerBlend6;
|
||||
|
||||
float Screenmx;
|
||||
float Screenmy;
|
||||
|
||||
float multi[10];
|
||||
|
||||
int scale[10];
|
||||
|
||||
int red[10];
|
||||
int green[10];
|
||||
int blue[10];
|
||||
|
||||
char text[10];
|
||||
float Lensx[10];
|
||||
float Lensy[10];
|
||||
|
||||
float Suncoordx;
|
||||
float Suncoordy;
|
||||
|
||||
float Sundistx;
|
||||
float Sundisty;
|
||||
|
||||
cvar_t *m_pCvarDraw;
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
// REMOVED: Vgui has replaced this.
|
||||
//
|
||||
/*
|
||||
class CHudMOTD : public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw( float flTime );
|
||||
void Reset( void );
|
||||
|
||||
int MsgFunc_MOTD( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
protected:
|
||||
static int MOTD_DISPLAY_TIME;
|
||||
char m_szMOTD[ MAX_MOTD_LENGTH ];
|
||||
float m_flActiveRemaining;
|
||||
int m_iLines;
|
||||
};
|
||||
*/
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudStatusBar : public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw( float flTime );
|
||||
void Reset( void );
|
||||
void ParseStatusString( int line_num );
|
||||
|
||||
int MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
protected:
|
||||
enum {
|
||||
MAX_STATUSTEXT_LENGTH = 128,
|
||||
MAX_STATUSBAR_VALUES = 8,
|
||||
MAX_STATUSBAR_LINES = 2,
|
||||
};
|
||||
|
||||
char m_szStatusText[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // a text string describing how the status bar is to be drawn
|
||||
char m_szStatusBar[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // the constructed bar that is drawn
|
||||
int m_iStatusValues[MAX_STATUSBAR_VALUES]; // an array of values for use in the status bar
|
||||
|
||||
int m_bReparseString; // set to TRUE whenever the m_szStatusBar needs to be recalculated
|
||||
|
||||
// an array of colors...one color for each line
|
||||
float *m_pflNameColors[MAX_STATUSBAR_LINES];
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
// REMOVED: Vgui has replaced this.
|
||||
//
|
||||
/*
|
||||
class CHudScoreboard: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
void InitHUDData( void );
|
||||
int VidInit( void );
|
||||
int Draw( float flTime );
|
||||
int DrawPlayers( int xoffset, float listslot, int nameoffset = 0, char *team = NULL ); // returns the ypos where it finishes drawing
|
||||
void UserCmd_ShowScores( void );
|
||||
void UserCmd_HideScores( void );
|
||||
int MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf );
|
||||
void DeathMsg( int killer, int victim );
|
||||
|
||||
int m_iNumTeams;
|
||||
|
||||
int m_iLastKilledBy;
|
||||
int m_fLastKillTime;
|
||||
int m_iPlayerNum;
|
||||
int m_iShowscoresHeld;
|
||||
|
||||
void GetAllPlayersInfo( void );
|
||||
private:
|
||||
struct cvar_s *cl_showpacketloss;
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
struct extra_player_info_t
|
||||
{
|
||||
short frags;
|
||||
short deaths;
|
||||
short playerclass;
|
||||
short teamnumber;
|
||||
char teamname[MAX_TEAM_NAME];
|
||||
};
|
||||
|
||||
struct team_info_t
|
||||
{
|
||||
char name[MAX_TEAM_NAME];
|
||||
short frags;
|
||||
short deaths;
|
||||
short ping;
|
||||
short packetloss;
|
||||
short ownteam;
|
||||
short players;
|
||||
int already_drawn;
|
||||
int scores_overriden;
|
||||
int teamnumber;
|
||||
};
|
||||
|
||||
extern hud_player_info_t g_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine
|
||||
extern extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll
|
||||
extern team_info_t g_TeamInfo[MAX_TEAMS+1];
|
||||
extern int g_IsSpectator[MAX_PLAYERS+1];
|
||||
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudDeathNotice : public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
void InitHUDData( void );
|
||||
int VidInit( void );
|
||||
int Draw( float flTime );
|
||||
int MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
private:
|
||||
int m_HUD_d_skull; // sprite index of skull icon
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudMenu : public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
void InitHUDData( void );
|
||||
int VidInit( void );
|
||||
void Reset( void );
|
||||
int Draw( float flTime );
|
||||
int MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
void SelectMenuItem( int menu_item );
|
||||
|
||||
int m_fMenuDisplayed;
|
||||
int m_bitsValidSlots;
|
||||
float m_flShutoffTime;
|
||||
int m_fWaitingForMore;
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudSayText : public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
void InitHUDData( void );
|
||||
int VidInit( void );
|
||||
int Draw( float flTime );
|
||||
int MsgFunc_SayText( const char *pszName, int iSize, void *pbuf );
|
||||
void SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex = -1 );
|
||||
void EnsureTextFitsInOneLineAndWrapIfHaveTo( int line );
|
||||
friend class CHudSpectator;
|
||||
|
||||
private:
|
||||
|
||||
struct cvar_s * m_HUD_saytext;
|
||||
struct cvar_s * m_HUD_saytext_time;
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudBattery: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
int MsgFunc_Battery(const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
private:
|
||||
HSPRITE m_hSprite1;
|
||||
HSPRITE m_hSprite2;
|
||||
wrect_t *m_prc1;
|
||||
wrect_t *m_prc2;
|
||||
int m_iBat;
|
||||
float m_fFade;
|
||||
int m_iHeight; // width of the battery innards
|
||||
};
|
||||
|
||||
class CHudStamina: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
int MsgFunc_Stamina(const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
private:
|
||||
HSPRITE m_hSprite1;
|
||||
HSPRITE m_hSprite2;
|
||||
wrect_t *m_prc1;
|
||||
wrect_t *m_prc2;
|
||||
int m_iStam;
|
||||
float m_fFade;
|
||||
int m_iHeight;
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
class CHudFlashlight: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
void Reset( void );
|
||||
int MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf );
|
||||
int MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
private:
|
||||
HSPRITE m_hSprite1;
|
||||
HSPRITE m_hSprite2;
|
||||
HSPRITE m_hBeam;
|
||||
wrect_t *m_prc1;
|
||||
wrect_t *m_prc2;
|
||||
wrect_t *m_prcBeam;
|
||||
float m_flBat;
|
||||
int m_iBat;
|
||||
int m_fOn;
|
||||
float m_fFade;
|
||||
int m_iWidth; // width of the battery innards
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
const int maxHUDMessages = 16;
|
||||
struct message_parms_t
|
||||
{
|
||||
client_textmessage_t *pMessage;
|
||||
float time;
|
||||
int x, y;
|
||||
int totalWidth, totalHeight;
|
||||
int width;
|
||||
int lines;
|
||||
int lineLength;
|
||||
int length;
|
||||
int r, g, b;
|
||||
int text;
|
||||
int fadeBlend;
|
||||
float charTime;
|
||||
float fadeTime;
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
|
||||
class CHudTextMessage: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
static char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size );
|
||||
static char *BufferedLocaliseTextString( const char *msg );
|
||||
char *LookupString( const char *msg_name, int *msg_dest = NULL );
|
||||
int MsgFunc_TextMsg(const char *pszName, int iSize, void *pbuf);
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
|
||||
class CHudMessage: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
int Draw(float flTime);
|
||||
int MsgFunc_HudText(const char *pszName, int iSize, void *pbuf);
|
||||
int MsgFunc_GameTitle(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
float FadeBlend( float fadein, float fadeout, float hold, float localTime );
|
||||
int XPosition( float x, int width, int lineWidth );
|
||||
int YPosition( float y, int height );
|
||||
|
||||
void MessageAdd( const char *pName, float time );
|
||||
void MessageAdd(client_textmessage_t * newMessage );
|
||||
void MessageDrawScan( client_textmessage_t *pMessage, float time );
|
||||
void MessageScanStart( void );
|
||||
void MessageScanNextChar( void );
|
||||
void Reset( void );
|
||||
|
||||
private:
|
||||
client_textmessage_t *m_pMessages[maxHUDMessages];
|
||||
float m_startTime[maxHUDMessages];
|
||||
message_parms_t m_parms;
|
||||
float m_gameTitleTime;
|
||||
client_textmessage_t *m_pGameTitle;
|
||||
|
||||
int m_HUD_title_life;
|
||||
int m_HUD_title_half;
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
#define MAX_SPRITE_NAME_LENGTH 24
|
||||
|
||||
class CHudStatusIcons: public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init( void );
|
||||
int VidInit( void );
|
||||
void Reset( void );
|
||||
int Draw(float flTime);
|
||||
int MsgFunc_StatusIcon(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
enum {
|
||||
MAX_ICONSPRITENAME_LENGTH = MAX_SPRITE_NAME_LENGTH,
|
||||
MAX_ICONSPRITES = 4,
|
||||
};
|
||||
|
||||
|
||||
//had to make these public so CHud could access them (to enable concussion icon)
|
||||
//could use a friend declaration instead...
|
||||
void EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue );
|
||||
void DisableIcon( char *pszIconName );
|
||||
|
||||
private:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char szSpriteName[MAX_ICONSPRITENAME_LENGTH];
|
||||
HSPRITE spr;
|
||||
wrect_t rc;
|
||||
unsigned char r, g, b;
|
||||
} icon_sprite_t;
|
||||
|
||||
icon_sprite_t m_IconList[MAX_ICONSPRITES];
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
//
|
||||
|
||||
//LRC - for the moment, skymode has only two settings
|
||||
#define SKY_OFF 0
|
||||
#define SKY_ON 1
|
||||
|
||||
class CHud
|
||||
{
|
||||
private:
|
||||
HUDLIST *m_pHudList;
|
||||
int m_iLogo;
|
||||
client_sprite_t *m_pSpriteList;
|
||||
int m_iSpriteCount;
|
||||
int m_iSpriteCountAllRes;
|
||||
float m_flMouseSensitivity;
|
||||
int m_iConcussionEffect;
|
||||
|
||||
public:
|
||||
HSPRITE m_hsprCursor;
|
||||
HSPRITE m_hsprLogo; // buz: make public
|
||||
float m_flTime; // the current client time
|
||||
float m_fOldTime; // the time at which the HUD was last redrawn
|
||||
double m_flTimeDelta; // the difference between flTime and fOldTime
|
||||
Vector m_vecOrigin;
|
||||
Vector m_vecAngles;
|
||||
|
||||
int m_iKeyBits;
|
||||
int m_iHideHUDDisplay;
|
||||
int m_iFOV;
|
||||
float m_flFOV; // buz - that's my FOV!
|
||||
int m_Teamplay;
|
||||
int m_iRes;
|
||||
cvar_t *m_pCvarStealMouse;
|
||||
cvar_t *m_pCvarDraw;
|
||||
cvar_t *m_pZoomSpeed; // buz
|
||||
|
||||
cl_entity_t *m_pHeadShieldEnt;
|
||||
int m_iHeadShieldState;
|
||||
float m_flHeadShieldSwitchTime;
|
||||
|
||||
int m_iViewModelIndex;
|
||||
|
||||
Vector m_vecSkyPos; //LRC
|
||||
int m_iSkyMode; //LRC
|
||||
|
||||
// buz: spec tank variables;
|
||||
int m_SpecTank_on;
|
||||
Vector m_SpecTank_point;
|
||||
float m_SpecTank_defYaw;
|
||||
float m_SpecTank_coneHor;
|
||||
float m_SpecTank_coneVer;
|
||||
float m_SpecTank_distFwd;
|
||||
float m_SpecTank_distUp;
|
||||
int m_SpecTank_Ammo;
|
||||
|
||||
float m_flBlurAmount;
|
||||
|
||||
// buz: die time
|
||||
float m_flDeadTime;
|
||||
|
||||
float m_flLevelTime;
|
||||
|
||||
int m_iFontHeight;
|
||||
int DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b );
|
||||
int DrawHudString(int x, int y, int iMaxX, char *szString, int r, int g, int b );
|
||||
int DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b );
|
||||
int DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b );
|
||||
int GetNumWidth(int iNumber, int iFlags);
|
||||
|
||||
int m_iHUDColor; //LRC
|
||||
|
||||
private:
|
||||
// the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded.
|
||||
// freed in ~CHud()
|
||||
HSPRITE *m_rghSprites; /*[HUD_SPRITE_COUNT]*/ // the sprites loaded from hud.txt
|
||||
wrect_t *m_rgrcRects; /*[HUD_SPRITE_COUNT]*/
|
||||
char *m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/
|
||||
|
||||
struct cvar_s *default_fov; // buz: turn off
|
||||
public:
|
||||
HSPRITE GetSprite( int index )
|
||||
{
|
||||
return (index < 0) ? 0 : m_rghSprites[index];
|
||||
}
|
||||
|
||||
wrect_t& GetSpriteRect( int index )
|
||||
{
|
||||
return m_rgrcRects[index];
|
||||
}
|
||||
|
||||
|
||||
int GetSpriteIndex( const char *SpriteName ); // gets a sprite index, for use in the m_rghSprites[] array
|
||||
|
||||
CHudAmmo m_Ammo;
|
||||
CHudStamina m_HudStamina;
|
||||
CHudHealth m_Health;
|
||||
CHudSpectator m_Spectator;
|
||||
CHudGeiger m_Geiger;
|
||||
CHudBattery m_Battery;
|
||||
CHudTrain m_Train;
|
||||
CHudFlashlight m_Flash;
|
||||
CHudMessage m_Message;
|
||||
CHudStatusBar m_StatusBar;
|
||||
CHudDeathNotice m_DeathNotice;
|
||||
CHudSayText m_SayText;
|
||||
CHudMenu m_Menu;
|
||||
CHudAmmoSecondary m_AmmoSecondary;
|
||||
CHudTextMessage m_TextMessage;
|
||||
CHudStatusIcons m_StatusIcons;
|
||||
CHudLensflare m_Lensflare;
|
||||
|
||||
|
||||
void Init( void );
|
||||
void VidInit( void );
|
||||
void Think(void);
|
||||
int Redraw( float flTime, int intermission );
|
||||
int UpdateClientData( client_data_t *cdata, float time );
|
||||
|
||||
CHud() : m_iSpriteCount(0), m_pHudList(NULL) {}
|
||||
~CHud(); // destructor, frees allocated memory
|
||||
|
||||
// user messages
|
||||
int _cdecl MsgFunc_Damage(const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_Logo(const char *pszName, int iSize, void *pbuf);
|
||||
int _cdecl MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf);
|
||||
void _cdecl MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf );
|
||||
void _cdecl MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf);
|
||||
int _cdecl MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_BlurEffect( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
int _cdecl MsgFunc_HUDColor(const char *pszName, int iSize, void *pbuf); //LRC
|
||||
void _cdecl MsgFunc_SetFog( const char *pszName, int iSize, void *pbuf ); //LRC
|
||||
void _cdecl MsgFunc_KeyedDLight( const char *pszName, int iSize, void *pbuf ); //LRC
|
||||
void _cdecl MsgFunc_SetSky( const char *pszName, int iSize, void *pbuf ); //LRC
|
||||
|
||||
int _cdecl MsgFunc_GasMask( const char *pszName, int iSize, void *pbuf ); // buz
|
||||
int _cdecl MsgFunc_SpecTank( const char *pszName, int iSize, void *pbuf ); // buz
|
||||
int _cdecl MsgFunc_MusicFade( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_RainData( const char *pszName, int iSize, void *pbuf ); // buz
|
||||
int _cdecl MsgFunc_WaterSplash( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_NewExplode( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_HeadShield( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
int _cdecl MsgFunc_Particle( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_DelParticle( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
// viewmodel messages
|
||||
int _cdecl MsgFunc_WeaponAnim( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_WeaponBody( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_WeaponSkin( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
// sky messages
|
||||
int _cdecl MsgFunc_SkyMarker( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_WorldMarker( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
// decal messages
|
||||
int _cdecl MsgFunc_CustomDecal( const char *pszName, int iSize, void *pbuf );
|
||||
int _cdecl MsgFunc_StudioDecal( const char *pszName, int iSize, void *pbuf );
|
||||
|
||||
// effect messages
|
||||
int _cdecl MsgFunc_PartEffect(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
int _cdecl MsgFunc_LevelTime(const char *pszName, int iSize, void *pbuf);
|
||||
|
||||
// Screen information
|
||||
SCREENINFO m_scrinfo;
|
||||
|
||||
int m_iWeaponBits;
|
||||
int m_fPlayerDead;
|
||||
int m_iIntermission;
|
||||
|
||||
// sprite indexes
|
||||
int m_HUD_number_0;
|
||||
|
||||
|
||||
void AddHudElem(CHudBase *p);
|
||||
|
||||
float GetSensitivity();
|
||||
};
|
||||
|
||||
class TeamFortressViewport;
|
||||
|
||||
extern CHud gHUD;
|
||||
extern TeamFortressViewport *gViewPort;
|
||||
|
||||
extern int g_iPlayerClass;
|
||||
extern int g_iTeamNumber;
|
||||
extern int g_iUser1;
|
||||
extern int g_iUser2;
|
||||
extern int g_iUser3;
|
18
cl_dll/hud_iface.h
Normal file
18
cl_dll/hud_iface.h
Normal file
@ -0,0 +1,18 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined( HUD_IFACEH )
|
||||
#define HUD_IFACEH
|
||||
#pragma once
|
||||
|
||||
#define EXPORT _declspec( dllexport )
|
||||
#define _DLLEXPORT __declspec( dllexport )
|
||||
|
||||
#include "../engine/cdll_int.h"
|
||||
extern cl_enginefunc_t gEngfuncs;
|
||||
|
||||
#endif
|
613
cl_dll/hud_msg.cpp
Normal file
613
cl_dll/hud_msg.cpp
Normal file
@ -0,0 +1,613 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// hud_msg.cpp
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
#include "r_efx.h"
|
||||
#include "studio.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_studio.h"
|
||||
#include "stringlib.h"
|
||||
#include "gl_rpart.h"
|
||||
|
||||
//LRC - the fogging fog
|
||||
float g_fFogColor[3];
|
||||
float g_fStartDist;
|
||||
float g_fEndDist;
|
||||
//int g_iFinalStartDist; //for fading
|
||||
int g_iFinalEndDist; //for fading
|
||||
float g_fFadeDuration; //negative = fading out
|
||||
extern engine_studio_api_t IEngineStudio;
|
||||
extern float v_idlescale;
|
||||
extern int g_iGunMode;
|
||||
|
||||
#define MAX_CLIENTS 32
|
||||
|
||||
void EV_HLDM_WaterSplash( float x, float y, float z, float ScaleSplash1, float ScaleSplash2 );
|
||||
|
||||
int CHud :: MsgFunc_WaterSplash( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
float X, Y, Z, ScaleSplash1, ScaleSplash2;
|
||||
|
||||
X = READ_COORD();
|
||||
Y = READ_COORD();
|
||||
Z = READ_COORD();
|
||||
ScaleSplash1 = READ_COORD();
|
||||
ScaleSplash2 = READ_COORD();
|
||||
|
||||
EV_HLDM_WaterSplash( X, Y, Z, ScaleSplash1, ScaleSplash2 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EV_HLDM_NewExplode( float x, float y, float z, float ScaleExplode1 );
|
||||
|
||||
int CHud :: MsgFunc_NewExplode( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
float X, Y, Z, ScaleExplode1;
|
||||
|
||||
X = READ_COORD();
|
||||
Y = READ_COORD();
|
||||
Z = READ_COORD();
|
||||
ScaleExplode1 = READ_COORD();
|
||||
|
||||
EV_HLDM_NewExplode( X, Y, Z, ScaleExplode1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// USER-DEFINED SERVER MESSAGE HANDLERS
|
||||
|
||||
int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
// clear all hud data
|
||||
HUDLIST *pList = m_pHudList;
|
||||
|
||||
while ( pList )
|
||||
{
|
||||
if ( pList->p )
|
||||
pList->p->Reset();
|
||||
pList = pList->pNext;
|
||||
}
|
||||
|
||||
// reset sensitivity
|
||||
m_flMouseSensitivity = 0;
|
||||
|
||||
// reset concussion effect
|
||||
m_iConcussionEffect = 0;
|
||||
|
||||
m_flLevelTime = -1.0f;
|
||||
|
||||
//LRC - reset fog
|
||||
m_flBlurAmount = 0;
|
||||
g_fStartDist = 0;
|
||||
g_fEndDist = 0;
|
||||
g_iGunMode = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CAM_ToFirstPerson(void);
|
||||
|
||||
void CHud :: MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
CAM_ToFirstPerson();
|
||||
}
|
||||
|
||||
void CHud :: MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
m_flLevelTime = -1.0f;
|
||||
|
||||
//LRC - clear the fog
|
||||
g_fStartDist = 0;
|
||||
g_fEndDist = 0;
|
||||
m_iSkyMode = SKY_OFF; //LRC
|
||||
|
||||
// prepare all hud data
|
||||
HUDLIST *pList = m_pHudList;
|
||||
|
||||
while (pList)
|
||||
{
|
||||
if ( pList->p )
|
||||
pList->p->InitHUDData();
|
||||
pList = pList->pNext;
|
||||
}
|
||||
|
||||
g_iGunMode = 0;
|
||||
}
|
||||
|
||||
//LRC
|
||||
void CHud :: MsgFunc_SetFog( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
g_fFogColor[ i ] = READ_BYTE();
|
||||
|
||||
g_fFadeDuration = READ_SHORT();
|
||||
g_fStartDist = READ_SHORT();
|
||||
|
||||
if (g_fFadeDuration > 0)
|
||||
{
|
||||
// // fading in
|
||||
// g_fStartDist = READ_SHORT();
|
||||
g_iFinalEndDist = READ_SHORT();
|
||||
// g_fStartDist = FOG_LIMIT;
|
||||
g_fEndDist = FOG_LIMIT;
|
||||
}
|
||||
else if (g_fFadeDuration < 0)
|
||||
{
|
||||
// // fading out
|
||||
// g_iFinalStartDist =
|
||||
g_iFinalEndDist = g_fEndDist = READ_SHORT();
|
||||
}
|
||||
else
|
||||
{
|
||||
// g_fStartDist = READ_SHORT();
|
||||
g_fEndDist = READ_SHORT();
|
||||
}
|
||||
}
|
||||
|
||||
//LRC
|
||||
void CHud :: MsgFunc_KeyedDLight( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
// CONPRINT("MSG:KeyedDLight");
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
// as-yet unused:
|
||||
// float decay; // drop this each second
|
||||
// float minlight; // don't add when contributing less
|
||||
// qboolean dark; // subtracts light instead of adding (doesn't seem to do anything?)
|
||||
|
||||
int iKey = READ_BYTE();
|
||||
dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight( iKey );
|
||||
|
||||
int bActive = READ_BYTE();
|
||||
if (!bActive)
|
||||
{
|
||||
// die instantly
|
||||
dl->die = gEngfuncs.GetClientTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
// never die
|
||||
dl->die = gEngfuncs.GetClientTime() + 1E6;
|
||||
|
||||
dl->origin[0] = READ_COORD();
|
||||
dl->origin[1] = READ_COORD();
|
||||
dl->origin[2] = READ_COORD();
|
||||
dl->radius = READ_BYTE();
|
||||
dl->color.r = READ_BYTE();
|
||||
dl->color.g = READ_BYTE();
|
||||
dl->color.b = READ_BYTE();
|
||||
}
|
||||
}
|
||||
|
||||
//LRC
|
||||
void CHud :: MsgFunc_SetSky( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
// CONPRINT("MSG:SetSky");
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
m_iSkyMode = READ_BYTE();
|
||||
m_vecSkyPos.x = READ_COORD();
|
||||
m_vecSkyPos.y = READ_COORD();
|
||||
m_vecSkyPos.z = READ_COORD();
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
m_Teamplay = READ_BYTE();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int CHud :: MsgFunc_Damage(const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
int armor, blood;
|
||||
Vector from;
|
||||
int i;
|
||||
float count;
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
armor = READ_BYTE();
|
||||
blood = READ_BYTE();
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
from[i] = READ_COORD();
|
||||
|
||||
count = (blood * 0.5) + (armor * 0.5);
|
||||
|
||||
if (count < 10)
|
||||
count = 10;
|
||||
|
||||
// TODO: kick viewangles, show damage visually
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
m_iConcussionEffect = READ_BYTE();
|
||||
if (m_iConcussionEffect)
|
||||
this->m_StatusIcons.EnableIcon("dmg_concuss",255,160,0);
|
||||
else
|
||||
this->m_StatusIcons.DisableIcon("dmg_concuss");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// buz: gasmask message
|
||||
int CHud :: MsgFunc_GasMask( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
studiohdr_t *pStudioHeader;
|
||||
mstudioseqdesc_t *pseq;
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
gHUD.m_pHeadShieldEnt->model = IEngineStudio.Mod_ForName( "models/v_gasmask.mdl", true );
|
||||
if( g_fRenderInitialized && RENDER_GET_PARM( PARM_WIDESCREEN, 0 ))
|
||||
gHUD.m_pHeadShieldEnt->curstate.fuser2 = 4.2f; // offset
|
||||
else gHUD.m_pHeadShieldEnt->curstate.fuser2 = 4.8f; // offset
|
||||
|
||||
// 0 is OFF; 1 is ON; 2 is fast switch to ON
|
||||
switch( READ_BYTE( ))
|
||||
{
|
||||
case 0:
|
||||
m_iHeadShieldState = SHIELD_TURNING_OFF;
|
||||
m_pHeadShieldEnt->curstate.animtime = gEngfuncs.GetClientTime();
|
||||
m_pHeadShieldEnt->curstate.sequence = SHIELDANIM_HOLSTER;
|
||||
|
||||
// get animation length in seconds
|
||||
pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata( gHUD.m_pHeadShieldEnt->model );
|
||||
pseq = (mstudioseqdesc_t *)((byte *)pStudioHeader + pStudioHeader->seqindex) + SHIELDANIM_HOLSTER;
|
||||
m_flHeadShieldSwitchTime = gEngfuncs.GetClientTime() + (pseq->numframes / pseq->fps);
|
||||
break;
|
||||
case 1:
|
||||
m_iHeadShieldState = SHIELD_TURNING_ON;
|
||||
m_pHeadShieldEnt->curstate.animtime = gEngfuncs.GetClientTime();
|
||||
m_pHeadShieldEnt->curstate.sequence = SHIELDANIM_DRAW;
|
||||
|
||||
// get animation length in seconds
|
||||
pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata( gHUD.m_pHeadShieldEnt->model );
|
||||
pseq = (mstudioseqdesc_t *)((byte *)pStudioHeader + pStudioHeader->seqindex) + SHIELDANIM_DRAW;
|
||||
m_flHeadShieldSwitchTime = gEngfuncs.GetClientTime() + (pseq->numframes / pseq->fps);
|
||||
break;
|
||||
case 2:
|
||||
m_iHeadShieldState = SHIELD_ON;
|
||||
m_pHeadShieldEnt->curstate.animtime = gEngfuncs.GetClientTime();
|
||||
m_pHeadShieldEnt->curstate.sequence = SHIELDANIM_IDLE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud::MsgFunc_HeadShield( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
studiohdr_t *pStudioHeader;
|
||||
mstudioseqdesc_t *pseq;
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
gHUD.m_pHeadShieldEnt->model = IEngineStudio.Mod_ForName( "models/v_headshield.mdl", true );
|
||||
|
||||
if( g_fRenderInitialized && RENDER_GET_PARM( PARM_WIDESCREEN, 0 ))
|
||||
gHUD.m_pHeadShieldEnt->curstate.fuser2 = 5.0f; // offset
|
||||
else gHUD.m_pHeadShieldEnt->curstate.fuser2 = 16.0f; // offset
|
||||
|
||||
// 0 is OFF; 1 is ON; 2 is fast switch to ON
|
||||
switch( READ_BYTE( ))
|
||||
{
|
||||
case 0:
|
||||
m_iHeadShieldState = SHIELD_TURNING_OFF;
|
||||
m_pHeadShieldEnt->curstate.animtime = gEngfuncs.GetClientTime();
|
||||
m_pHeadShieldEnt->curstate.sequence = SHIELDANIM_HOLSTER;
|
||||
|
||||
// get animation length in seconds
|
||||
pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata( gHUD.m_pHeadShieldEnt->model );
|
||||
pseq = (mstudioseqdesc_t *)((byte *)pStudioHeader + pStudioHeader->seqindex) + SHIELDANIM_HOLSTER;
|
||||
m_flHeadShieldSwitchTime = gEngfuncs.GetClientTime() + (pseq->numframes / pseq->fps);
|
||||
break;
|
||||
case 1:
|
||||
m_iHeadShieldState = SHIELD_TURNING_ON;
|
||||
m_pHeadShieldEnt->curstate.animtime = gEngfuncs.GetClientTime();
|
||||
m_pHeadShieldEnt->curstate.sequence = SHIELDANIM_DRAW;
|
||||
|
||||
// get animation length in seconds
|
||||
pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata( gHUD.m_pHeadShieldEnt->model );
|
||||
pseq = (mstudioseqdesc_t *)((byte *)pStudioHeader + pStudioHeader->seqindex) + SHIELDANIM_DRAW;
|
||||
m_flHeadShieldSwitchTime = gEngfuncs.GetClientTime() + (pseq->numframes / pseq->fps);
|
||||
break;
|
||||
case 2:
|
||||
m_iHeadShieldState = SHIELD_ON;
|
||||
m_pHeadShieldEnt->curstate.animtime = gEngfuncs.GetClientTime();
|
||||
m_pHeadShieldEnt->curstate.sequence = SHIELDANIM_IDLE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// buz: special tank message
|
||||
int CHud :: MsgFunc_SpecTank( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
m_SpecTank_on = READ_BYTE();
|
||||
if (m_SpecTank_on == 0) // turn off
|
||||
return 1;
|
||||
else if (m_SpecTank_on == 2) // only ammo update
|
||||
{
|
||||
m_SpecTank_Ammo = READ_LONG();
|
||||
m_Ammo.m_fFade = 200.0f;
|
||||
}
|
||||
else // turn on
|
||||
{
|
||||
m_SpecTank_point.x = READ_COORD();
|
||||
m_SpecTank_point.y = READ_COORD();
|
||||
m_SpecTank_point.z = READ_COORD();
|
||||
m_SpecTank_defYaw = READ_COORD();
|
||||
m_SpecTank_coneHor = READ_COORD();
|
||||
m_SpecTank_coneVer = READ_COORD();
|
||||
m_SpecTank_distFwd = READ_COORD();
|
||||
m_SpecTank_distUp = READ_COORD();
|
||||
m_SpecTank_Ammo = READ_LONG();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_MusicFade( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
MUSIC_FADE_VOLUME( (float)READ_SHORT() / 100.0f );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_Particle( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
int entindex = READ_SHORT();
|
||||
char *sz = READ_STRING();
|
||||
int attachment = READ_BYTE();
|
||||
|
||||
UTIL_CreateAurora( GET_ENTITY( entindex ), sz, attachment );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_DelParticle( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
int entindex = READ_SHORT();
|
||||
|
||||
UTIL_RemoveAurora( GET_ENTITY( entindex ));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_RainData( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
ParseRain();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_WeaponAnim( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
int sequence = READ_BYTE();
|
||||
float framerate = READ_BYTE() * 0.125f;
|
||||
|
||||
UTIL_WeaponAnimation( sequence, framerate );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_WeaponBody( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
GET_VIEWMODEL()->curstate.body = READ_BYTE();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_WeaponSkin( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
GET_VIEWMODEL()->curstate.skin = READ_BYTE();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 3d skybox
|
||||
int CHud :: MsgFunc_SkyMarker( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
tr.sky_origin.x = READ_COORD();
|
||||
tr.sky_origin.y = READ_COORD();
|
||||
tr.sky_origin.z = READ_COORD();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 3d skybox
|
||||
int CHud :: MsgFunc_WorldMarker( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
tr.sky_world_origin.x = READ_COORD();
|
||||
tr.sky_world_origin.y = READ_COORD();
|
||||
tr.sky_world_origin.z = READ_COORD();
|
||||
tr.sky_speed = READ_COORD();
|
||||
Msg( "sky_speed: %g\n", tr.sky_speed );
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_CustomDecal( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
char name[80];
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
Vector pos, normal;
|
||||
pos.x = READ_COORD();
|
||||
pos.y = READ_COORD();
|
||||
pos.z = READ_COORD();
|
||||
normal.x = READ_COORD() / 8192.0f;
|
||||
normal.y = READ_COORD() / 8192.0f;
|
||||
normal.z = READ_COORD() / 8192.0f;
|
||||
int entityIndex = READ_SHORT();
|
||||
int modelIndex = READ_SHORT();
|
||||
Q_strncpy( name, READ_STRING(), sizeof( name ));
|
||||
int flags = READ_BYTE();
|
||||
float angle = READ_ANGLE();
|
||||
|
||||
CreateDecal( pos, normal, angle, name, flags, entityIndex, modelIndex );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_StudioDecal( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
Vector vecEnd, vecNormal, vecScale = g_vecZero;
|
||||
char name[80];
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
vecEnd.x = READ_COORD();
|
||||
vecEnd.y = READ_COORD();
|
||||
vecEnd.z = READ_COORD();
|
||||
vecNormal.x = READ_COORD() * 0.001f;
|
||||
vecNormal.y = READ_COORD() * 0.001f;
|
||||
vecNormal.z = READ_COORD() * 0.001f;
|
||||
int entityIndex = READ_SHORT();
|
||||
int modelIndex = READ_SHORT();
|
||||
Q_strncpy( name, READ_STRING(), sizeof( name ));
|
||||
int flags = READ_BYTE();
|
||||
|
||||
modelstate_t state;
|
||||
state.sequence = READ_SHORT();
|
||||
state.frame = READ_SHORT();
|
||||
state.blending[0] = READ_BYTE();
|
||||
state.blending[1] = READ_BYTE();
|
||||
state.controller[0] = READ_BYTE();
|
||||
state.controller[1] = READ_BYTE();
|
||||
state.controller[2] = READ_BYTE();
|
||||
state.controller[3] = READ_BYTE();
|
||||
state.body = READ_BYTE();
|
||||
state.skin = READ_BYTE();
|
||||
int cacheID = READ_SHORT();
|
||||
|
||||
if( REMAIN_BYTES( ))
|
||||
{
|
||||
vecScale.x = READ_COORD() * 0.001f;
|
||||
vecScale.y = READ_COORD() * 0.001f;
|
||||
vecScale.z = READ_COORD() * 0.001f;
|
||||
}
|
||||
|
||||
cl_entity_t *ent = GET_ENTITY( entityIndex );
|
||||
|
||||
if( !ent )
|
||||
{
|
||||
// something very bad happens...
|
||||
ALERT( at_error, "StudioDecal: ent == NULL\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_StudioRenderer.PushEntityState( ent );
|
||||
g_StudioRenderer.ModelStateToEntity( ent, &state );
|
||||
|
||||
// restore model in case decalmessage was delivered early than delta-update
|
||||
if( !ent->model && modelIndex != 0 )
|
||||
ent->model = IEngineStudio.GetModelByIndex( modelIndex );
|
||||
|
||||
if( cacheID )
|
||||
{
|
||||
// tell the code about vertex lighting
|
||||
SetBits( ent->curstate.iuser1, CF_STATIC_ENTITY );
|
||||
ent->curstate.colormap = cacheID;
|
||||
}
|
||||
|
||||
if( !RENDER_GET_PARM( PARM_CLIENT_ACTIVE, 0 ) && FBitSet( ent->curstate.iuser1, CF_STATIC_ENTITY ))
|
||||
ent->curstate.startpos = vecScale; // restore scale here
|
||||
|
||||
if( !ent->model || ent->model->type != mod_studio )
|
||||
return 1;
|
||||
|
||||
g_StudioRenderer.StudioDecalShoot( vecNormal, vecEnd, name, ent, flags, &state );
|
||||
g_StudioRenderer.PopEntityState( ent );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_PartEffect( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
char name[80];
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
Vector pos, normal;
|
||||
pos.x = READ_COORD();
|
||||
pos.y = READ_COORD();
|
||||
pos.z = READ_COORD();
|
||||
normal.x = READ_COORD() / 8192.0f;
|
||||
normal.y = READ_COORD() / 8192.0f;
|
||||
normal.z = READ_COORD() / 8192.0f;
|
||||
Q_strncpy( name, READ_STRING(), sizeof( name ));
|
||||
|
||||
g_pParticles.CreateEffect( name, pos, normal );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_LevelTime( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
m_flLevelTime = READ_FLOAT();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHud :: MsgFunc_BlurEffect( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
m_flBlurAmount = (float)READ_SHORT() / 10000.0f;
|
||||
|
||||
v_idlescale = m_flBlurAmount * 100.0f;
|
||||
|
||||
// reset blur on a next level
|
||||
if( !RENDER_GET_PARM( PARM_CLIENT_ACTIVE, 0 ))
|
||||
{
|
||||
m_flBlurAmount = 0.0f;
|
||||
v_idlescale = 0.0f;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
521
cl_dll/hud_redraw.cpp
Normal file
521
cl_dll/hud_redraw.cpp
Normal file
@ -0,0 +1,521 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// hud_redraw.cpp
|
||||
//
|
||||
#include <math.h>
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "vgui_TeamFortressViewport.h"
|
||||
#include "vgui_hud.h"
|
||||
#include "triangleapi.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||||
#endif
|
||||
|
||||
// buz: for IsHardware check
|
||||
#include "r_studioint.h"
|
||||
#include "com_model.h"
|
||||
extern engine_studio_api_t IEngineStudio;
|
||||
|
||||
#include "vgui_TeamFortressViewport.h"
|
||||
#include "vgui_paranoiatext.h"// buz
|
||||
#include "gl_local.h"
|
||||
#include "gl_decals.h"
|
||||
|
||||
#define MAX_LOGO_FRAMES 56
|
||||
|
||||
// buz: spread value
|
||||
vec3_t g_vSpread;
|
||||
int g_iGunMode = 0;
|
||||
|
||||
void DrawBlurTest(float frametime); // buz
|
||||
extern int g_iVisibleMouse;
|
||||
|
||||
//float HUD_GetFOV( void ); buz
|
||||
|
||||
extern cvar_t *sensitivity;
|
||||
|
||||
// Think
|
||||
void CHud::Think(void)
|
||||
{
|
||||
// buz: calc dead time
|
||||
if (gHUD.m_Health.m_iHealth <= 0 && !m_flDeadTime)
|
||||
{
|
||||
m_flDeadTime = gEngfuncs.GetClientTime();
|
||||
}
|
||||
|
||||
// Wargon: Èñïðàâëåíèå áàãà ýôôåêòà grayscale, îñòàâàâøåãîñÿ ïîñëå çàãðóçêè èç ìåðòâîãî ñîñòîÿíèÿ.
|
||||
if (gHUD.m_Health.m_iHealth > 0)
|
||||
{
|
||||
m_flDeadTime = 0;
|
||||
}
|
||||
|
||||
float targetFOV;
|
||||
HUDLIST *pList = m_pHudList;
|
||||
static float lasttime = 0;
|
||||
|
||||
while (pList)
|
||||
{
|
||||
if (pList->p->m_iFlags & HUD_ACTIVE)
|
||||
pList->p->Think();
|
||||
pList = pList->pNext;
|
||||
}
|
||||
|
||||
if( g_iGunMode == 3 )
|
||||
targetFOV = 30;
|
||||
else if( g_iGunMode == 2 )
|
||||
targetFOV = 60;
|
||||
else targetFOV = default_fov->value;
|
||||
|
||||
static float lastFixedFov = 0;
|
||||
|
||||
if( m_flFOV < 0 )
|
||||
{
|
||||
m_flFOV = targetFOV;
|
||||
lasttime = gEngfuncs.GetClientTime();
|
||||
lastFixedFov = m_flFOV;
|
||||
}
|
||||
else
|
||||
{
|
||||
float curtime = gEngfuncs.GetClientTime();
|
||||
float mod = targetFOV - m_flFOV;
|
||||
if( mod < 0 ) mod *= -1;
|
||||
if( mod < 30 ) mod = 30;
|
||||
|
||||
if( g_iGunMode == 3 || lastFixedFov == 30 )
|
||||
mod *= 2; // õàêàìè õàëôà ïîëíèòñÿ (c)
|
||||
mod /= 30;
|
||||
|
||||
if( m_flFOV < targetFOV )
|
||||
{
|
||||
m_flFOV += (curtime - lasttime) * m_pZoomSpeed->value * mod;
|
||||
if( m_flFOV > targetFOV )
|
||||
{
|
||||
m_flFOV = targetFOV;
|
||||
lastFixedFov = m_flFOV;
|
||||
}
|
||||
}
|
||||
else if( m_flFOV > targetFOV )
|
||||
{
|
||||
m_flFOV -= (curtime - lasttime) * m_pZoomSpeed->value * mod;
|
||||
|
||||
if( m_flFOV < targetFOV )
|
||||
{
|
||||
m_flFOV = targetFOV;
|
||||
lastFixedFov = m_flFOV;
|
||||
}
|
||||
}
|
||||
lasttime = curtime;
|
||||
}
|
||||
|
||||
m_iFOV = m_flFOV;
|
||||
|
||||
// Set a new sensitivity
|
||||
if ( m_iFOV == default_fov->value )// buz: turn off
|
||||
{
|
||||
// reset to saved sensitivity
|
||||
m_flMouseSensitivity = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// set a new sensitivity that is proportional to the change from the FOV default
|
||||
m_flMouseSensitivity = sensitivity->value * (m_flFOV / (float)90) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
|
||||
}
|
||||
}
|
||||
|
||||
//LRC - fog fading values
|
||||
extern float g_fFadeDuration;
|
||||
extern float g_fStartDist;
|
||||
extern float g_fEndDist;
|
||||
//extern int g_iFinalStartDist;
|
||||
extern int g_iFinalEndDist;
|
||||
|
||||
void OrthoScope(void); // buz
|
||||
void OrthoVGUI(void); // buz
|
||||
extern vec3_t g_CrosshairAngle; // buz
|
||||
|
||||
#define CROSS_LENGTH 18.0f
|
||||
|
||||
// Redraw
|
||||
// step through the local data, placing the appropriate graphics & text as appropriate
|
||||
// returns 1 if they've changed, 0 otherwise
|
||||
int CHud :: Redraw( float flTime, int intermission )
|
||||
{
|
||||
m_fOldTime = m_flTime; // save time of previous redraw
|
||||
m_flTime = flTime;
|
||||
m_flTimeDelta = (double)m_flTime - m_fOldTime;
|
||||
static m_flShotTime = 0;
|
||||
|
||||
#if 0
|
||||
// g-cont. disabled for users request
|
||||
if( g_fRenderInitialized )
|
||||
DrawBlurTest( m_flTimeDelta );
|
||||
#endif
|
||||
//LRC - handle fog fading effects. (is this the right place for it?)
|
||||
if (g_fFadeDuration)
|
||||
{
|
||||
// Nicer might be to use some kind of logarithmic fade-in?
|
||||
double fFraction = m_flTimeDelta/g_fFadeDuration;
|
||||
// g_fStartDist -= (FOG_LIMIT - g_iFinalStartDist)*fFraction;
|
||||
g_fEndDist -= (FOG_LIMIT - g_iFinalEndDist)*fFraction;
|
||||
|
||||
// CONPRINT("FogFading: %f - %f, frac %f, time %f, final %d\n", g_fStartDist, g_fEndDist, fFraction, flTime, g_iFinalEndDist);
|
||||
|
||||
// cap it
|
||||
// if (g_fStartDist > FOG_LIMIT) g_fStartDist = FOG_LIMIT;
|
||||
if (g_fEndDist > FOG_LIMIT) g_fEndDist = FOG_LIMIT;
|
||||
// if (g_fStartDist < g_iFinalStartDist) g_fStartDist = g_iFinalStartDist;
|
||||
if (g_fEndDist < g_iFinalEndDist) g_fEndDist = g_iFinalEndDist;
|
||||
}
|
||||
|
||||
// Clock was reset, reset delta
|
||||
if ( m_flTimeDelta < 0 )
|
||||
m_flTimeDelta = 0;
|
||||
|
||||
if (g_iGunMode == 3) // buz: special sniper scope
|
||||
{
|
||||
if (IEngineStudio.IsHardware())
|
||||
OrthoScope();
|
||||
}
|
||||
|
||||
if (!IEngineStudio.IsHardware() && m_iHeadShieldState != 1 )
|
||||
DrawHudString(XRES(10), YRES(350), XRES(600), "Using Head Shield", 180, 180, 180);
|
||||
|
||||
if( r_stats.debug_surface != NULL )
|
||||
gEngfuncs.pfnDrawCharacter( XRES( 320 ), YRES( 240 ), '+', 128, 255, 92 );
|
||||
|
||||
OrthoVGUI(); // buz: panels background
|
||||
|
||||
// Bring up the scoreboard during intermission
|
||||
if (gViewPort)
|
||||
{
|
||||
if ( m_iIntermission && !intermission )
|
||||
{
|
||||
// Have to do this here so the scoreboard goes away
|
||||
m_iIntermission = intermission;
|
||||
gViewPort->HideCommandMenu();
|
||||
gViewPort->HideScoreBoard();
|
||||
// gViewPort->UpdateSpectatorPanel();
|
||||
}
|
||||
else if ( !m_iIntermission && intermission )
|
||||
{
|
||||
m_iIntermission = intermission;
|
||||
gViewPort->HideCommandMenu();
|
||||
gViewPort->HideVGUIMenu();
|
||||
gViewPort->ShowScoreBoard();
|
||||
// gViewPort->UpdateSpectatorPanel();
|
||||
|
||||
// Take a screenshot if the client's got the cvar set
|
||||
if ( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
|
||||
m_flShotTime = flTime + 1.0; // Take a screenshot in a second
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flShotTime && m_flShotTime < flTime)
|
||||
{
|
||||
gEngfuncs.pfnClientCmd("snapshot\n");
|
||||
m_flShotTime = 0;
|
||||
}
|
||||
|
||||
m_iIntermission = intermission;
|
||||
|
||||
// if no redrawing is necessary
|
||||
// return 0;
|
||||
|
||||
if ( m_pCvarDraw->value )
|
||||
{
|
||||
HUDLIST *pList = m_pHudList;
|
||||
|
||||
while (pList)
|
||||
{
|
||||
if ( !intermission )
|
||||
{
|
||||
if ( (pList->p->m_iFlags & HUD_ACTIVE) && !(m_iHideHUDDisplay & HIDEHUD_ALL) )
|
||||
pList->p->Draw(flTime);
|
||||
}
|
||||
else
|
||||
{ // it's an intermission, so only draw hud elements that are set to draw during intermissions
|
||||
if ( pList->p->m_iFlags & HUD_INTERMISSION )
|
||||
pList->p->Draw( flTime );
|
||||
}
|
||||
|
||||
pList = pList->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
// buz: draw crosshair
|
||||
// Wargon: Ïðèöåë ðèñóåòñÿ òîëüêî åñëè hud_draw = 1.
|
||||
if(( g_vSpread[0] && g_iGunMode == 1 && m_SpecTank_on == 0 ) && gHUD.m_pCvarDraw->value && cv_crosshair->value )
|
||||
{
|
||||
if( gViewPort && gViewPort->m_pParanoiaText && gViewPort->m_pParanoiaText->isVisible( ))
|
||||
return 1;
|
||||
|
||||
int barsize = XRES(g_iGunMode == 1 ? 9 : 6);
|
||||
int hW = ScreenWidth / 2;
|
||||
int hH = ScreenHeight / 2;
|
||||
float mod = (1/(tan(M_PI/180*(m_iFOV/2))));
|
||||
int dir = ((g_vSpread[0] * hW) / 500) * mod;
|
||||
// gEngfuncs.Con_Printf("mod is %f, %d\n", mod, m_iFOV);
|
||||
|
||||
if (g_CrosshairAngle[0] != 0 || g_CrosshairAngle[1] != 0)
|
||||
{
|
||||
// adjust for autoaim
|
||||
hW -= g_CrosshairAngle[1] * (ScreenWidth / m_iFOV);
|
||||
hH -= g_CrosshairAngle[0] * (ScreenWidth / m_iFOV);
|
||||
}
|
||||
|
||||
// g_vSpread[2] - is redish [0..500]
|
||||
// gEngfuncs.Con_Printf("received spread: %f\n", g_vSpread[2]);
|
||||
int c = 255 - (g_vSpread[2] * 0.5);
|
||||
|
||||
if( cv_crosshair->value > 1.0f )
|
||||
{
|
||||
// old Paranoia-style crosshair
|
||||
FillRGBA(hW - dir - barsize, hH, barsize, 1, 255, c, c, 200);
|
||||
FillRGBA(hW + dir, hH, barsize, 1, 255, c, c, 200);
|
||||
FillRGBA(hW, hH - dir - barsize, 1, barsize, 255, c, c, 200);
|
||||
FillRGBA(hW, hH + dir, 1, barsize, 255, c, c, 200);
|
||||
}
|
||||
else
|
||||
{
|
||||
// new crysis-style crosshair
|
||||
float flColor = 255.0f - (g_vSpread[2] * 0.5f);
|
||||
flColor = bound( 0.0f, flColor * (1.0f / 255.0f), 1.0f );
|
||||
|
||||
GL_TextureTarget( GL_NONE );
|
||||
|
||||
gEngfuncs.pTriAPI->RenderMode( kRenderTransColor );
|
||||
gEngfuncs.pTriAPI->Color4f( 1.0f, flColor, flColor, 0.8f );
|
||||
|
||||
gEngfuncs.pTriAPI->Begin( TRI_LINES );
|
||||
gEngfuncs.pTriAPI->Vertex3f( hW, hH - dir, 0.0f );
|
||||
gEngfuncs.pTriAPI->Vertex3f( hW, hH - ( CROSS_LENGTH * 1.2f ) - dir, 0.0f );
|
||||
gEngfuncs.pTriAPI->End();
|
||||
|
||||
gEngfuncs.pTriAPI->Begin( TRI_LINES );
|
||||
gEngfuncs.pTriAPI->Vertex3f( hW + dir, hH + dir, 0.0f );
|
||||
gEngfuncs.pTriAPI->Vertex3f( hW + CROSS_LENGTH + dir, hH + CROSS_LENGTH + dir, 0.0f );
|
||||
gEngfuncs.pTriAPI->End();
|
||||
|
||||
gEngfuncs.pTriAPI->Begin( TRI_LINES );
|
||||
gEngfuncs.pTriAPI->Vertex3f( hW - dir, hH + dir, 0.0f );
|
||||
gEngfuncs.pTriAPI->Vertex3f( hW - CROSS_LENGTH - dir, hH + CROSS_LENGTH + dir, 0.0f );
|
||||
gEngfuncs.pTriAPI->End();
|
||||
|
||||
GL_TextureTarget( GL_TEXTURE_2D );
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ScaleColors( int &r, int &g, int &b, int a )
|
||||
{
|
||||
float x = (float)a / 255;
|
||||
r = (int)(r * x);
|
||||
g = (int)(g * x);
|
||||
b = (int)(b * x);
|
||||
}
|
||||
|
||||
int CHud :: DrawHudString(int xpos, int ypos, int iMaxX, char *szIt, int r, int g, int b )
|
||||
{
|
||||
// draw the string until we hit the null character or a newline character
|
||||
for ( ; *szIt != 0 && *szIt != '\n'; szIt++ )
|
||||
{
|
||||
int next = xpos + gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
|
||||
if ( next > iMaxX )
|
||||
return xpos;
|
||||
|
||||
TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
|
||||
xpos = next;
|
||||
}
|
||||
|
||||
return xpos;
|
||||
}
|
||||
|
||||
int CHud :: DrawHudNumberString( int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b )
|
||||
{
|
||||
char szString[32];
|
||||
sprintf( szString, "%d", iNumber );
|
||||
return DrawHudStringReverse( xpos, ypos, iMinX, szString, r, g, b );
|
||||
|
||||
}
|
||||
|
||||
// draws a string from right to left (right-aligned)
|
||||
int CHud :: DrawHudStringReverse( int xpos, int ypos, int iMinX, char *szString, int r, int g, int b )
|
||||
{
|
||||
// find the end of the string
|
||||
for ( char *szIt = szString; *szIt != 0; szIt++ )
|
||||
{ // we should count the length?
|
||||
}
|
||||
|
||||
// iterate throug the string in reverse
|
||||
for ( szIt--; szIt != (szString-1); szIt-- )
|
||||
{
|
||||
int next = xpos - gHUD.m_scrinfo.charWidths[ *szIt ]; // variable-width fonts look cool
|
||||
if ( next < iMinX )
|
||||
return xpos;
|
||||
xpos = next;
|
||||
|
||||
TextMessageDrawChar( xpos, ypos, *szIt, r, g, b );
|
||||
}
|
||||
|
||||
return xpos;
|
||||
}
|
||||
|
||||
int CHud :: DrawHudNumber( int x, int y, int iFlags, int iNumber, int r, int g, int b)
|
||||
{
|
||||
int iWidth = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left;
|
||||
int k;
|
||||
|
||||
if (iNumber > 0)
|
||||
{
|
||||
// SPR_Draw 100's
|
||||
if (iNumber >= 100)
|
||||
{
|
||||
k = iNumber/100;
|
||||
SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
|
||||
x += iWidth;
|
||||
}
|
||||
else if (iFlags & (DHN_3DIGITS))
|
||||
{
|
||||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||||
x += iWidth;
|
||||
}
|
||||
|
||||
// SPR_Draw 10's
|
||||
if (iNumber >= 10)
|
||||
{
|
||||
k = (iNumber % 100)/10;
|
||||
SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
|
||||
SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
|
||||
x += iWidth;
|
||||
}
|
||||
else if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
|
||||
{
|
||||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||||
x += iWidth;
|
||||
}
|
||||
|
||||
// SPR_Draw ones
|
||||
k = iNumber % 10;
|
||||
SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b );
|
||||
SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k));
|
||||
x += iWidth;
|
||||
}
|
||||
else if (iFlags & DHN_DRAWZERO)
|
||||
{
|
||||
SPR_Set(GetSprite(m_HUD_number_0), r, g, b );
|
||||
|
||||
// SPR_Draw 100's
|
||||
if (iFlags & (DHN_3DIGITS))
|
||||
{
|
||||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||||
x += iWidth;
|
||||
}
|
||||
|
||||
if (iFlags & (DHN_3DIGITS | DHN_2DIGITS))
|
||||
{
|
||||
//SPR_DrawAdditive( 0, x, y, &rc );
|
||||
x += iWidth;
|
||||
}
|
||||
|
||||
// SPR_Draw ones
|
||||
|
||||
SPR_DrawAdditive( 0, x, y, &GetSpriteRect(m_HUD_number_0));
|
||||
x += iWidth;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
int CHud::GetNumWidth( int iNumber, int iFlags )
|
||||
{
|
||||
if (iFlags & (DHN_3DIGITS))
|
||||
return 3;
|
||||
|
||||
if (iFlags & (DHN_2DIGITS))
|
||||
return 2;
|
||||
|
||||
if (iNumber <= 0)
|
||||
{
|
||||
if (iFlags & (DHN_DRAWZERO))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iNumber < 10)
|
||||
return 1;
|
||||
|
||||
if (iNumber < 100)
|
||||
return 2;
|
||||
|
||||
return 3;
|
||||
|
||||
}
|
||||
|
||||
// buz
|
||||
void DrawBlurTest( float frametime )
|
||||
{
|
||||
static int blurstate = false;
|
||||
|
||||
if( gHUD.m_flBlurAmount > 0.0f && frametime )
|
||||
{
|
||||
if( !g_fRenderInitialized )
|
||||
{
|
||||
ALERT( at_error, "GL effects are not allowed\n" );
|
||||
gHUD.m_flBlurAmount = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
GLint val_r, val_g, val_b;
|
||||
pglGetIntegerv( GL_ACCUM_RED_BITS, &val_r );
|
||||
pglGetIntegerv( GL_ACCUM_GREEN_BITS, &val_g );
|
||||
pglGetIntegerv( GL_ACCUM_BLUE_BITS, &val_b );
|
||||
|
||||
if( !val_r || !val_g || !val_b )
|
||||
{
|
||||
ALERT( at_error, "Accumulation buffer is not present\n" );
|
||||
gHUD.m_flBlurAmount = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if( !blurstate )
|
||||
{
|
||||
// load entire screen first time
|
||||
pglAccum( GL_LOAD, 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
float blur = ( 51.0f - ( gHUD.m_flBlurAmount * 50.0f ));
|
||||
blur = bound( 0.0f, blur * frametime, 1.0f );
|
||||
pglReadBuffer( GL_BACK );
|
||||
pglAccum( GL_MULT, 1.0f - blur ); // scale contents of accumulation buffer
|
||||
pglAccum( GL_ACCUM, blur ); // add screen contents
|
||||
pglAccum( GL_RETURN, 1 ); // read result back
|
||||
}
|
||||
|
||||
blurstate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
blurstate = false;
|
||||
}
|
||||
}
|
1230
cl_dll/hud_servers.cpp
Normal file
1230
cl_dll/hud_servers.cpp
Normal file
File diff suppressed because it is too large
Load Diff
41
cl_dll/hud_servers.h
Normal file
41
cl_dll/hud_servers.h
Normal file
@ -0,0 +1,41 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined( HUD_SERVERSH )
|
||||
#define HUD_SERVERSH
|
||||
#pragma once
|
||||
|
||||
#define NET_CALLBACK /* */
|
||||
|
||||
// Dispatchers
|
||||
void NET_CALLBACK ListResponse( struct net_response_s *response );
|
||||
void NET_CALLBACK ServerResponse( struct net_response_s *response );
|
||||
void NET_CALLBACK PingResponse( struct net_response_s *response );
|
||||
void NET_CALLBACK RulesResponse( struct net_response_s *response );
|
||||
void NET_CALLBACK PlayersResponse( struct net_response_s *response );
|
||||
|
||||
void ServersInit( void );
|
||||
void ServersShutdown( void );
|
||||
void ServersThink( double time );
|
||||
void ServersCancel( void );
|
||||
|
||||
// Get list and get server info from each
|
||||
void ServersList( void );
|
||||
|
||||
// Query for IP / IPX LAN servers
|
||||
void BroadcastServersList( int clearpending );
|
||||
|
||||
void ServerPing( int server );
|
||||
void ServerRules( int server );
|
||||
void ServerPlayers( int server );
|
||||
|
||||
int ServersGetCount( void );
|
||||
const char *ServersGetInfo( int server );
|
||||
int ServersIsQuerying( void );
|
||||
void SortServers( const char *fieldname );
|
||||
|
||||
#endif // HUD_SERVERSH
|
98
cl_dll/hud_servers_priv.h
Normal file
98
cl_dll/hud_servers_priv.h
Normal file
@ -0,0 +1,98 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined( HUD_SERVERS_PRIVH )
|
||||
#define HUD_SERVERS_PRIVH
|
||||
#pragma once
|
||||
|
||||
#include "netadr.h"
|
||||
|
||||
class CHudServers
|
||||
{
|
||||
public:
|
||||
typedef struct request_s
|
||||
{
|
||||
struct request_s *next;
|
||||
netadr_t remote_address;
|
||||
int context;
|
||||
} request_t;
|
||||
|
||||
typedef struct server_s
|
||||
{
|
||||
struct server_s *next;
|
||||
netadr_t remote_address;
|
||||
char *info;
|
||||
int ping;
|
||||
} server_t;
|
||||
|
||||
CHudServers();
|
||||
~CHudServers();
|
||||
|
||||
void Think( double time );
|
||||
void QueryThink( void );
|
||||
int isQuerying( void );
|
||||
|
||||
int LoadMasterAddresses( int maxservers, int *count, netadr_t *padr );
|
||||
|
||||
void RequestList( void );
|
||||
void RequestBroadcastList( int clearpending );
|
||||
|
||||
void ServerPing( int server );
|
||||
void ServerRules( int server );
|
||||
void ServerPlayers( int server );
|
||||
|
||||
void CancelRequest( void );
|
||||
|
||||
int CompareServers( server_t *p1, server_t *p2 );
|
||||
|
||||
void ClearServerList( server_t **ppList );
|
||||
void ClearRequestList( request_t **ppList );
|
||||
|
||||
void AddServer( server_t **ppList, server_t *p );
|
||||
|
||||
void RemoveServerFromList( request_t **ppList, request_t *item );
|
||||
|
||||
request_t *FindRequest( int context, request_t *pList );
|
||||
|
||||
int ServerListSize( void );
|
||||
char *GetServerInfo( int server );
|
||||
int GetServerCount( void );
|
||||
void SortServers( const char *fieldname );
|
||||
|
||||
void ListResponse( struct net_response_s *response );
|
||||
void ServerResponse( struct net_response_s *response );
|
||||
void PingResponse( struct net_response_s *response );
|
||||
void RulesResponse( struct net_response_s *response );
|
||||
void PlayersResponse( struct net_response_s *response );
|
||||
private:
|
||||
|
||||
server_t *GetServer( int server );
|
||||
|
||||
//
|
||||
char m_szToken[ 1024 ];
|
||||
int m_nRequesting;
|
||||
int m_nDone;
|
||||
|
||||
double m_dStarted;
|
||||
|
||||
request_t *m_pServerList;
|
||||
request_t *m_pActiveList;
|
||||
|
||||
server_t *m_pServers;
|
||||
|
||||
int m_nServerCount;
|
||||
|
||||
int m_nActiveQueries;
|
||||
int m_nQuerying;
|
||||
double m_fElapsed;
|
||||
|
||||
request_t *m_pPingRequest;
|
||||
request_t *m_pRulesRequest;
|
||||
request_t *m_pPlayersRequest;
|
||||
};
|
||||
|
||||
#endif // HUD_SERVERS_PRIVH
|
1626
cl_dll/hud_spectator.cpp
Normal file
1626
cl_dll/hud_spectator.cpp
Normal file
File diff suppressed because it is too large
Load Diff
132
cl_dll/hud_spectator.h
Normal file
132
cl_dll/hud_spectator.h
Normal file
@ -0,0 +1,132 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#ifndef SPECTATOR_H
|
||||
#define SPECTATOR_H
|
||||
#pragma once
|
||||
|
||||
#include "cl_entity.h"
|
||||
|
||||
|
||||
|
||||
#define INSET_OFF 0
|
||||
#define INSET_CHASE_FREE 1
|
||||
#define INSET_IN_EYE 2
|
||||
#define INSET_MAP_FREE 3
|
||||
#define INSET_MAP_CHASE 4
|
||||
|
||||
#define MAX_SPEC_HUD_MESSAGES 8
|
||||
|
||||
|
||||
|
||||
#define OVERVIEW_TILE_SIZE 128 // don't change this
|
||||
#define OVERVIEW_MAX_LAYERS 1
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it )
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct overviewInfo_s {
|
||||
char map[64]; // cl.levelname or empty
|
||||
vec3_t origin; // center of map
|
||||
float zoom; // zoom of map images
|
||||
int layers; // how may layers do we have
|
||||
float layersHeights[OVERVIEW_MAX_LAYERS];
|
||||
char layersImages[OVERVIEW_MAX_LAYERS][255];
|
||||
qboolean rotated; // are map images rotated (90 degrees) ?
|
||||
|
||||
int insetWindowX;
|
||||
int insetWindowY;
|
||||
int insetWindowHeight;
|
||||
int insetWindowWidth;
|
||||
} overviewInfo_t;
|
||||
|
||||
typedef struct overviewEntity_s {
|
||||
|
||||
HSPRITE hSprite;
|
||||
struct cl_entity_s * entity;
|
||||
double killTime;
|
||||
} overviewEntity_t;
|
||||
|
||||
#define MAX_OVERVIEW_ENTITIES 128
|
||||
|
||||
class CHudSpectator : public CHudBase
|
||||
{
|
||||
public:
|
||||
void Reset();
|
||||
int ToggleInset(bool allowOff);
|
||||
void CheckSettings();
|
||||
void InitHUDData( void );
|
||||
bool AddOverviewEntityToList( HSPRITE sprite, cl_entity_t * ent, double killTime);
|
||||
void DeathMessage(int victim);
|
||||
bool AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname );
|
||||
void CheckOverviewEntities();
|
||||
void DrawOverview();
|
||||
void DrawOverviewEntities();
|
||||
void GetMapPosition( float * returnvec );
|
||||
void DrawOverviewLayer();
|
||||
void LoadMapSprites();
|
||||
bool ParseOverviewFile();
|
||||
bool IsActivePlayer(cl_entity_t * ent);
|
||||
void SetModes(int iMainMode, int iInsetMode);
|
||||
void HandleButtonsDown(int ButtonPressed);
|
||||
void HandleButtonsUp(int ButtonPressed);
|
||||
void FindNextPlayer( bool bReverse );
|
||||
void DirectorMessage( int iSize, void *pbuf );
|
||||
void SetSpectatorStartPosition();
|
||||
int Init();
|
||||
int VidInit();
|
||||
|
||||
int Draw(float flTime);
|
||||
|
||||
int m_iDrawCycle;
|
||||
client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES];
|
||||
char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128];
|
||||
int m_lastHudMessage;
|
||||
overviewInfo_t m_OverviewData;
|
||||
overviewEntity_t m_OverviewEntities[MAX_OVERVIEW_ENTITIES];
|
||||
int m_iObserverFlags;
|
||||
int m_iSpectatorNumber;
|
||||
|
||||
float m_mapZoom; // zoom the user currently uses
|
||||
vec3_t m_mapOrigin; // origin where user rotates around
|
||||
cvar_t * m_drawnames;
|
||||
cvar_t * m_drawcone;
|
||||
cvar_t * m_drawstatus;
|
||||
cvar_t * m_autoDirector;
|
||||
cvar_t * m_pip;
|
||||
|
||||
|
||||
qboolean m_chatEnabled;
|
||||
|
||||
vec3_t m_cameraOrigin; // a help camera
|
||||
vec3_t m_cameraAngles; // and it's angles
|
||||
|
||||
|
||||
private:
|
||||
vec3_t m_vPlayerPos[MAX_PLAYERS];
|
||||
HSPRITE m_hsprPlayerBlue;
|
||||
HSPRITE m_hsprPlayerRed;
|
||||
HSPRITE m_hsprPlayer;
|
||||
HSPRITE m_hsprCamera;
|
||||
HSPRITE m_hsprPlayerDead;
|
||||
HSPRITE m_hsprViewcone;
|
||||
HSPRITE m_hsprUnkownMap;
|
||||
HSPRITE m_hsprBeam;
|
||||
HSPRITE m_hCrosshair;
|
||||
|
||||
wrect_t m_crosshairRect;
|
||||
|
||||
struct model_s * m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame
|
||||
float m_flNextObserverInput;
|
||||
float m_zoomDelta;
|
||||
float m_moveDelta;
|
||||
int m_lastPrimaryObject;
|
||||
int m_lastSecondaryObject;
|
||||
};
|
||||
|
||||
#endif // SPECTATOR_H
|
54
cl_dll/hud_update.cpp
Normal file
54
cl_dll/hud_update.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// hud_update.cpp
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
int CL_ButtonBits( int );
|
||||
void CL_ResetButtonBits( int bits );
|
||||
|
||||
extern float v_idlescale;
|
||||
float in_fov;
|
||||
extern void HUD_SetCmdBits( int bits );
|
||||
|
||||
int CHud::UpdateClientData(client_data_t *cdata, float time)
|
||||
{
|
||||
memcpy(m_vecOrigin, cdata->origin, sizeof(vec3_t));
|
||||
memcpy(m_vecAngles, cdata->viewangles, sizeof(vec3_t));
|
||||
|
||||
m_iKeyBits = CL_ButtonBits( 0 );
|
||||
m_iWeaponBits = cdata->iWeaponBits;
|
||||
|
||||
in_fov = cdata->fov;
|
||||
|
||||
Think();
|
||||
|
||||
cdata->fov = m_flFOV;//m_iFOV; buz
|
||||
|
||||
// v_idlescale = m_iConcussionEffect;
|
||||
|
||||
CL_ResetButtonBits( m_iKeyBits );
|
||||
|
||||
// return 1 if in anything in the client_data struct has been changed, 0 otherwise
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
621
cl_dll/in_camera.cpp
Normal file
621
cl_dll/in_camera.cpp
Normal file
@ -0,0 +1,621 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "camera.h"
|
||||
#include "kbutton.h"
|
||||
#include "cvardef.h"
|
||||
#include "usercmd.h"
|
||||
#include "const.h"
|
||||
#include "camera.h"
|
||||
#include "in_defs.h"
|
||||
#include "gl_local.h"
|
||||
#include "windows.h"
|
||||
|
||||
float CL_KeyState (kbutton_t *key);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void DLLEXPORT CAM_Think( void );
|
||||
int DLLEXPORT CL_IsThirdPerson( void );
|
||||
void DLLEXPORT CL_CameraOffset( float *ofs );
|
||||
}
|
||||
|
||||
extern cl_enginefunc_t gEngfuncs;
|
||||
|
||||
//-------------------------------------------------- Constants
|
||||
|
||||
#define CAM_DIST_DELTA 1.0
|
||||
#define CAM_ANGLE_DELTA 2.5
|
||||
#define CAM_ANGLE_SPEED 2.5
|
||||
#define CAM_MIN_DIST 30.0
|
||||
#define CAM_ANGLE_MOVE .5
|
||||
#define MAX_ANGLE_DIFF 10.0
|
||||
#define PITCH_MAX 90.0
|
||||
#define PITCH_MIN 0
|
||||
#define YAW_MAX 135.0
|
||||
#define YAW_MIN -135.0
|
||||
|
||||
enum ECAM_Command
|
||||
{
|
||||
CAM_COMMAND_NONE = 0,
|
||||
CAM_COMMAND_TOTHIRDPERSON = 1,
|
||||
CAM_COMMAND_TOFIRSTPERSON = 2
|
||||
};
|
||||
|
||||
//-------------------------------------------------- Global Variables
|
||||
|
||||
cvar_t *cam_command;
|
||||
cvar_t *cam_snapto;
|
||||
cvar_t *cam_idealyaw;
|
||||
cvar_t *cam_idealpitch;
|
||||
cvar_t *cam_idealdist;
|
||||
cvar_t *cam_contain;
|
||||
|
||||
cvar_t *c_maxpitch;
|
||||
cvar_t *c_minpitch;
|
||||
cvar_t *c_maxyaw;
|
||||
cvar_t *c_minyaw;
|
||||
cvar_t *c_maxdistance;
|
||||
cvar_t *c_mindistance;
|
||||
|
||||
// pitch, yaw, dist
|
||||
vec3_t cam_ofs;
|
||||
|
||||
|
||||
// In third person
|
||||
int cam_thirdperson;
|
||||
int cam_mousemove; //true if we are moving the cam with the mouse, False if not
|
||||
int iMouseInUse=0;
|
||||
int cam_distancemove;
|
||||
extern int mouse_x, mouse_y; //used to determine what the current x and y values are
|
||||
int cam_old_mouse_x, cam_old_mouse_y; //holds the last ticks mouse movement
|
||||
POINT cam_mouse;
|
||||
//-------------------------------------------------- Local Variables
|
||||
|
||||
static kbutton_t cam_pitchup, cam_pitchdown, cam_yawleft, cam_yawright;
|
||||
static kbutton_t cam_in, cam_out, cam_move;
|
||||
|
||||
//-------------------------------------------------- Prototypes
|
||||
|
||||
void CAM_ToThirdPerson(void);
|
||||
void CAM_ToFirstPerson(void);
|
||||
void CAM_StartDistance(void);
|
||||
void CAM_EndDistance(void);
|
||||
|
||||
|
||||
//-------------------------------------------------- Local Functions
|
||||
|
||||
float MoveToward( float cur, float goal, float maxspeed )
|
||||
{
|
||||
if( cur != goal )
|
||||
{
|
||||
if( abs( cur - goal ) > 180.0 )
|
||||
{
|
||||
if( cur < goal )
|
||||
cur += 360.0;
|
||||
else
|
||||
cur -= 360.0;
|
||||
}
|
||||
|
||||
if( cur < goal )
|
||||
{
|
||||
if( cur < goal - 1.0 )
|
||||
cur += ( goal - cur ) / 4.0;
|
||||
else
|
||||
cur = goal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cur > goal + 1.0 )
|
||||
cur -= ( cur - goal ) / 4.0;
|
||||
else
|
||||
cur = goal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// bring cur back into range
|
||||
if( cur < 0 )
|
||||
cur += 360.0;
|
||||
else if( cur >= 360 )
|
||||
cur -= 360;
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------- Gobal Functions
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
|
||||
float *mins, *maxs; // size of the moving object
|
||||
vec3_t mins2, maxs2; // size when clipping against mosnters
|
||||
float *start, *end;
|
||||
trace_t trace;
|
||||
int type;
|
||||
edict_t *passedict;
|
||||
qboolean monsterclip;
|
||||
} moveclip_t;
|
||||
|
||||
extern trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
|
||||
|
||||
void DLLEXPORT CAM_Think( void )
|
||||
{
|
||||
vec3_t origin;
|
||||
vec3_t ext, pnt, camForward, camRight, camUp;
|
||||
moveclip_t clip;
|
||||
float dist;
|
||||
vec3_t camAngles;
|
||||
float flSensitivity;
|
||||
#ifdef LATER
|
||||
int i;
|
||||
#endif
|
||||
vec3_t viewangles;
|
||||
|
||||
switch( (int) cam_command->value )
|
||||
{
|
||||
case CAM_COMMAND_TOTHIRDPERSON:
|
||||
CAM_ToThirdPerson();
|
||||
break;
|
||||
|
||||
case CAM_COMMAND_TOFIRSTPERSON:
|
||||
CAM_ToFirstPerson();
|
||||
break;
|
||||
|
||||
case CAM_COMMAND_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !cam_thirdperson )
|
||||
return;
|
||||
|
||||
#ifdef LATER
|
||||
if ( cam_contain->value )
|
||||
{
|
||||
gEngfuncs.GetClientOrigin( origin );
|
||||
ext[0] = ext[1] = ext[2] = 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
camAngles[ PITCH ] = cam_idealpitch->value;
|
||||
camAngles[ YAW ] = cam_idealyaw->value;
|
||||
dist = cam_idealdist->value;
|
||||
//
|
||||
//movement of the camera with the mouse
|
||||
//
|
||||
if (cam_mousemove)
|
||||
{
|
||||
//get windows cursor position
|
||||
GetCursorPos (&cam_mouse);
|
||||
//check for X delta values and adjust accordingly
|
||||
//eventually adjust YAW based on amount of movement
|
||||
//don't do any movement of the cam using YAW/PITCH if we are zooming in/out the camera
|
||||
if (!cam_distancemove)
|
||||
{
|
||||
|
||||
//keep the camera within certain limits around the player (ie avoid certain bad viewing angles)
|
||||
if (cam_mouse.x>gEngfuncs.GetWindowCenterX())
|
||||
{
|
||||
//if ((camAngles[YAW]>=225.0)||(camAngles[YAW]<135.0))
|
||||
if (camAngles[YAW]<c_maxyaw->value)
|
||||
{
|
||||
camAngles[ YAW ] += (CAM_ANGLE_MOVE)*((cam_mouse.x-gEngfuncs.GetWindowCenterX())/2);
|
||||
}
|
||||
if (camAngles[YAW]>c_maxyaw->value)
|
||||
{
|
||||
|
||||
camAngles[YAW]=c_maxyaw->value;
|
||||
}
|
||||
}
|
||||
else if (cam_mouse.x<gEngfuncs.GetWindowCenterX())
|
||||
{
|
||||
//if ((camAngles[YAW]<=135.0)||(camAngles[YAW]>225.0))
|
||||
if (camAngles[YAW]>c_minyaw->value)
|
||||
{
|
||||
camAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((gEngfuncs.GetWindowCenterX()-cam_mouse.x)/2);
|
||||
|
||||
}
|
||||
if (camAngles[YAW]<c_minyaw->value)
|
||||
{
|
||||
camAngles[YAW]=c_minyaw->value;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//check for y delta values and adjust accordingly
|
||||
//eventually adjust PITCH based on amount of movement
|
||||
//also make sure camera is within bounds
|
||||
if (cam_mouse.y>gEngfuncs.GetWindowCenterY())
|
||||
{
|
||||
if(camAngles[PITCH]<c_maxpitch->value)
|
||||
{
|
||||
camAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2);
|
||||
}
|
||||
if (camAngles[PITCH]>c_maxpitch->value)
|
||||
{
|
||||
camAngles[PITCH]=c_maxpitch->value;
|
||||
}
|
||||
}
|
||||
else if (cam_mouse.y<gEngfuncs.GetWindowCenterY())
|
||||
{
|
||||
if (camAngles[PITCH]>c_minpitch->value)
|
||||
{
|
||||
camAngles[PITCH] -= (CAM_ANGLE_MOVE)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2);
|
||||
}
|
||||
if (camAngles[PITCH]<c_minpitch->value)
|
||||
{
|
||||
camAngles[PITCH]=c_minpitch->value;
|
||||
}
|
||||
}
|
||||
|
||||
//set old mouse coordinates to current mouse coordinates
|
||||
//since we are done with the mouse
|
||||
|
||||
if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 )
|
||||
{
|
||||
cam_old_mouse_x=cam_mouse.x*flSensitivity;
|
||||
cam_old_mouse_y=cam_mouse.y*flSensitivity;
|
||||
}
|
||||
else
|
||||
{
|
||||
cam_old_mouse_x=cam_mouse.x;
|
||||
cam_old_mouse_y=cam_mouse.y;
|
||||
}
|
||||
SetCursorPos (gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY());
|
||||
}
|
||||
}
|
||||
|
||||
//Nathan code here
|
||||
if( CL_KeyState( &cam_pitchup ) )
|
||||
camAngles[ PITCH ] += CAM_ANGLE_DELTA;
|
||||
else if( CL_KeyState( &cam_pitchdown ) )
|
||||
camAngles[ PITCH ] -= CAM_ANGLE_DELTA;
|
||||
|
||||
if( CL_KeyState( &cam_yawleft ) )
|
||||
camAngles[ YAW ] -= CAM_ANGLE_DELTA;
|
||||
else if( CL_KeyState( &cam_yawright ) )
|
||||
camAngles[ YAW ] += CAM_ANGLE_DELTA;
|
||||
|
||||
if( CL_KeyState( &cam_in ) )
|
||||
{
|
||||
dist -= CAM_DIST_DELTA;
|
||||
if( dist < CAM_MIN_DIST )
|
||||
{
|
||||
// If we go back into first person, reset the angle
|
||||
camAngles[ PITCH ] = 0;
|
||||
camAngles[ YAW ] = 0;
|
||||
dist = CAM_MIN_DIST;
|
||||
}
|
||||
|
||||
}
|
||||
else if( CL_KeyState( &cam_out ) )
|
||||
dist += CAM_DIST_DELTA;
|
||||
|
||||
if (cam_distancemove)
|
||||
{
|
||||
if (cam_mouse.y>gEngfuncs.GetWindowCenterY())
|
||||
{
|
||||
if(dist<c_maxdistance->value)
|
||||
{
|
||||
dist +=CAM_DIST_DELTA * ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2);
|
||||
}
|
||||
if (dist>c_maxdistance->value)
|
||||
{
|
||||
dist=c_maxdistance->value;
|
||||
}
|
||||
}
|
||||
else if (cam_mouse.y<gEngfuncs.GetWindowCenterY())
|
||||
{
|
||||
if (dist>c_mindistance->value)
|
||||
{
|
||||
dist -= (CAM_DIST_DELTA)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2);
|
||||
}
|
||||
if (dist<c_mindistance->value)
|
||||
{
|
||||
dist=c_mindistance->value;
|
||||
}
|
||||
}
|
||||
//set old mouse coordinates to current mouse coordinates
|
||||
//since we are done with the mouse
|
||||
cam_old_mouse_x=cam_mouse.x*gHUD.GetSensitivity();
|
||||
cam_old_mouse_y=cam_mouse.y*gHUD.GetSensitivity();
|
||||
SetCursorPos (gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY());
|
||||
}
|
||||
#ifdef LATER
|
||||
if( cam_contain->value )
|
||||
{
|
||||
// check new ideal
|
||||
VectorCopy( origin, pnt );
|
||||
AngleVectors( camAngles, camForward, camRight, camUp );
|
||||
for (i=0 ; i<3 ; i++)
|
||||
pnt[i] += -dist*camForward[i];
|
||||
|
||||
// check line from r_refdef.vieworg to pnt
|
||||
memset ( &clip, 0, sizeof ( moveclip_t ) );
|
||||
clip.trace = SV_ClipMoveToEntity( sv.edicts, r_refdef.vieworg, ext, ext, pnt );
|
||||
if( clip.trace.fraction == 1.0 )
|
||||
{
|
||||
// update ideal
|
||||
cam_idealpitch->value = camAngles[ PITCH ];
|
||||
cam_idealyaw->value = camAngles[ YAW ];
|
||||
cam_idealdist->value = dist;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// update ideal
|
||||
cam_idealpitch->value = camAngles[ PITCH ];
|
||||
cam_idealyaw->value = camAngles[ YAW ];
|
||||
cam_idealdist->value = dist;
|
||||
}
|
||||
|
||||
// Move towards ideal
|
||||
VectorCopy( cam_ofs, camAngles );
|
||||
|
||||
gEngfuncs.GetViewAngles( (float *)viewangles );
|
||||
|
||||
if( cam_snapto->value )
|
||||
{
|
||||
camAngles[ YAW ] = cam_idealyaw->value + viewangles[ YAW ];
|
||||
camAngles[ PITCH ] = cam_idealpitch->value + viewangles[ PITCH ];
|
||||
camAngles[ 2 ] = cam_idealdist->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( camAngles[ YAW ] - viewangles[ YAW ] != cam_idealyaw->value )
|
||||
camAngles[ YAW ] = MoveToward( camAngles[ YAW ], cam_idealyaw->value + viewangles[ YAW ], CAM_ANGLE_SPEED );
|
||||
|
||||
if( camAngles[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch->value )
|
||||
camAngles[ PITCH ] = MoveToward( camAngles[ PITCH ], cam_idealpitch->value + viewangles[ PITCH ], CAM_ANGLE_SPEED );
|
||||
|
||||
if( abs( camAngles[ 2 ] - cam_idealdist->value ) < 2.0 )
|
||||
camAngles[ 2 ] = cam_idealdist->value;
|
||||
else
|
||||
camAngles[ 2 ] += ( cam_idealdist->value - camAngles[ 2 ] ) / 4.0;
|
||||
}
|
||||
#ifdef LATER
|
||||
if( cam_contain->value )
|
||||
{
|
||||
// Test new position
|
||||
dist = camAngles[ ROLL ];
|
||||
camAngles[ ROLL ] = 0;
|
||||
|
||||
VectorCopy( origin, pnt );
|
||||
AngleVectors( camAngles, camForward, camRight, camUp );
|
||||
for (i=0 ; i<3 ; i++)
|
||||
pnt[i] += -dist*camForward[i];
|
||||
|
||||
// check line from r_refdef.vieworg to pnt
|
||||
memset ( &clip, 0, sizeof ( moveclip_t ) );
|
||||
ext[0] = ext[1] = ext[2] = 0.0;
|
||||
clip.trace = SV_ClipMoveToEntity( sv.edicts, r_refdef.vieworg, ext, ext, pnt );
|
||||
if( clip.trace.fraction != 1.0 )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
cam_ofs[ 0 ] = camAngles[ 0 ];
|
||||
cam_ofs[ 1 ] = camAngles[ 1 ];
|
||||
cam_ofs[ 2 ] = dist;
|
||||
}
|
||||
|
||||
extern void KeyDown (kbutton_t *b); // HACK
|
||||
extern void KeyUp (kbutton_t *b); // HACK
|
||||
|
||||
void CAM_PitchUpDown(void) { KeyDown( &cam_pitchup ); }
|
||||
void CAM_PitchUpUp(void) { KeyUp( &cam_pitchup ); }
|
||||
void CAM_PitchDownDown(void) { KeyDown( &cam_pitchdown ); }
|
||||
void CAM_PitchDownUp(void) { KeyUp( &cam_pitchdown ); }
|
||||
void CAM_YawLeftDown(void) { KeyDown( &cam_yawleft ); }
|
||||
void CAM_YawLeftUp(void) { KeyUp( &cam_yawleft ); }
|
||||
void CAM_YawRightDown(void) { KeyDown( &cam_yawright ); }
|
||||
void CAM_YawRightUp(void) { KeyUp( &cam_yawright ); }
|
||||
void CAM_InDown(void) { KeyDown( &cam_in ); }
|
||||
void CAM_InUp(void) { KeyUp( &cam_in ); }
|
||||
void CAM_OutDown(void) { KeyDown( &cam_out ); }
|
||||
void CAM_OutUp(void) { KeyUp( &cam_out ); }
|
||||
|
||||
void CAM_ToThirdPerson(void)
|
||||
{
|
||||
vec3_t viewangles;
|
||||
|
||||
#if !defined( _DEBUG )
|
||||
if ( gEngfuncs.GetMaxClients() > 1 )
|
||||
{
|
||||
// no thirdperson in multiplayer.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
gEngfuncs.GetViewAngles( (float *)viewangles );
|
||||
|
||||
if( !cam_thirdperson )
|
||||
{
|
||||
cam_thirdperson = 1;
|
||||
|
||||
cam_ofs[ YAW ] = viewangles[ YAW ];
|
||||
cam_ofs[ PITCH ] = viewangles[ PITCH ];
|
||||
cam_ofs[ 2 ] = CAM_MIN_DIST;
|
||||
}
|
||||
|
||||
gEngfuncs.Cvar_SetValue( "cam_command", 0 );
|
||||
}
|
||||
|
||||
void CAM_ToFirstPerson(void)
|
||||
{
|
||||
cam_thirdperson = 0;
|
||||
|
||||
gEngfuncs.Cvar_SetValue( "cam_command", 0 );
|
||||
}
|
||||
|
||||
void CAM_ToggleSnapto( void )
|
||||
{
|
||||
cam_snapto->value = !cam_snapto->value;
|
||||
}
|
||||
|
||||
void CAM_Init( void )
|
||||
{
|
||||
gEngfuncs.pfnAddCommand( "+campitchup", CAM_PitchUpDown );
|
||||
gEngfuncs.pfnAddCommand( "-campitchup", CAM_PitchUpUp );
|
||||
gEngfuncs.pfnAddCommand( "+campitchdown", CAM_PitchDownDown );
|
||||
gEngfuncs.pfnAddCommand( "-campitchdown", CAM_PitchDownUp );
|
||||
gEngfuncs.pfnAddCommand( "+camyawleft", CAM_YawLeftDown );
|
||||
gEngfuncs.pfnAddCommand( "-camyawleft", CAM_YawLeftUp );
|
||||
gEngfuncs.pfnAddCommand( "+camyawright", CAM_YawRightDown );
|
||||
gEngfuncs.pfnAddCommand( "-camyawright", CAM_YawRightUp );
|
||||
gEngfuncs.pfnAddCommand( "+camin", CAM_InDown );
|
||||
gEngfuncs.pfnAddCommand( "-camin", CAM_InUp );
|
||||
gEngfuncs.pfnAddCommand( "+camout", CAM_OutDown );
|
||||
gEngfuncs.pfnAddCommand( "-camout", CAM_OutUp );
|
||||
gEngfuncs.pfnAddCommand( "thirdperson", CAM_ToThirdPerson );
|
||||
gEngfuncs.pfnAddCommand( "firstperson", CAM_ToFirstPerson );
|
||||
gEngfuncs.pfnAddCommand( "+cammousemove",CAM_StartMouseMove);
|
||||
gEngfuncs.pfnAddCommand( "-cammousemove",CAM_EndMouseMove);
|
||||
gEngfuncs.pfnAddCommand( "+camdistance", CAM_StartDistance );
|
||||
gEngfuncs.pfnAddCommand( "-camdistance", CAM_EndDistance );
|
||||
gEngfuncs.pfnAddCommand( "snapto", CAM_ToggleSnapto );
|
||||
|
||||
cam_command = gEngfuncs.pfnRegisterVariable ( "cam_command", "0", 0 ); // tells camera to go to thirdperson
|
||||
cam_snapto = gEngfuncs.pfnRegisterVariable ( "cam_snapto", "0", 0 ); // snap to thirdperson view
|
||||
cam_idealyaw = gEngfuncs.pfnRegisterVariable ( "cam_idealyaw", "90", 0 ); // thirdperson yaw
|
||||
cam_idealpitch = gEngfuncs.pfnRegisterVariable ( "cam_idealpitch", "0", 0 ); // thirperson pitch
|
||||
cam_idealdist = gEngfuncs.pfnRegisterVariable ( "cam_idealdist", "64", 0 ); // thirdperson distance
|
||||
cam_contain = gEngfuncs.pfnRegisterVariable ( "cam_contain", "0", 0 ); // contain camera to world
|
||||
|
||||
c_maxpitch = gEngfuncs.pfnRegisterVariable ( "c_maxpitch", "90.0", 0 );
|
||||
c_minpitch = gEngfuncs.pfnRegisterVariable ( "c_minpitch", "0.0", 0 );
|
||||
c_maxyaw = gEngfuncs.pfnRegisterVariable ( "c_maxyaw", "135.0", 0 );
|
||||
c_minyaw = gEngfuncs.pfnRegisterVariable ( "c_minyaw", "-135.0", 0 );
|
||||
c_maxdistance = gEngfuncs.pfnRegisterVariable ( "c_maxdistance", "200.0", 0 );
|
||||
c_mindistance = gEngfuncs.pfnRegisterVariable ( "c_mindistance", "30.0", 0 );
|
||||
}
|
||||
|
||||
void CAM_ClearStates( void )
|
||||
{
|
||||
vec3_t viewangles;
|
||||
|
||||
gEngfuncs.GetViewAngles( (float *)viewangles );
|
||||
|
||||
cam_pitchup.state = 0;
|
||||
cam_pitchdown.state = 0;
|
||||
cam_yawleft.state = 0;
|
||||
cam_yawright.state = 0;
|
||||
cam_in.state = 0;
|
||||
cam_out.state = 0;
|
||||
|
||||
cam_thirdperson = 0;
|
||||
cam_command->value = 0;
|
||||
cam_mousemove=0;
|
||||
|
||||
cam_snapto->value = 0;
|
||||
cam_distancemove = 0;
|
||||
|
||||
cam_ofs[ 0 ] = 0.0;
|
||||
cam_ofs[ 1 ] = 0.0;
|
||||
cam_ofs[ 2 ] = CAM_MIN_DIST;
|
||||
|
||||
cam_idealpitch->value = viewangles[ PITCH ];
|
||||
cam_idealyaw->value = viewangles[ YAW ];
|
||||
cam_idealdist->value = CAM_MIN_DIST;
|
||||
}
|
||||
|
||||
void CAM_StartMouseMove(void)
|
||||
{
|
||||
float flSensitivity;
|
||||
|
||||
//only move the cam with mouse if we are in third person.
|
||||
if (cam_thirdperson)
|
||||
{
|
||||
//set appropriate flags and initialize the old mouse position
|
||||
//variables for mouse camera movement
|
||||
if (!cam_mousemove)
|
||||
{
|
||||
cam_mousemove=1;
|
||||
iMouseInUse=1;
|
||||
GetCursorPos (&cam_mouse);
|
||||
|
||||
if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 )
|
||||
{
|
||||
cam_old_mouse_x=cam_mouse.x*flSensitivity;
|
||||
cam_old_mouse_y=cam_mouse.y*flSensitivity;
|
||||
}
|
||||
else
|
||||
{
|
||||
cam_old_mouse_x=cam_mouse.x;
|
||||
cam_old_mouse_y=cam_mouse.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
//we are not in 3rd person view..therefore do not allow camera movement
|
||||
else
|
||||
{
|
||||
cam_mousemove=0;
|
||||
iMouseInUse=0;
|
||||
}
|
||||
}
|
||||
|
||||
//the key has been released for camera movement
|
||||
//tell the engine that mouse camera movement is off
|
||||
void CAM_EndMouseMove(void)
|
||||
{
|
||||
cam_mousemove=0;
|
||||
iMouseInUse=0;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------
|
||||
//routines to start the process of moving the cam in or out
|
||||
//using the mouse
|
||||
//----------------------------------------------------------
|
||||
void CAM_StartDistance(void)
|
||||
{
|
||||
//only move the cam with mouse if we are in third person.
|
||||
if (cam_thirdperson)
|
||||
{
|
||||
//set appropriate flags and initialize the old mouse position
|
||||
//variables for mouse camera movement
|
||||
if (!cam_distancemove)
|
||||
{
|
||||
cam_distancemove=1;
|
||||
cam_mousemove=1;
|
||||
iMouseInUse=1;
|
||||
GetCursorPos (&cam_mouse);
|
||||
cam_old_mouse_x=cam_mouse.x*gHUD.GetSensitivity();
|
||||
cam_old_mouse_y=cam_mouse.y*gHUD.GetSensitivity();
|
||||
}
|
||||
}
|
||||
//we are not in 3rd person view..therefore do not allow camera movement
|
||||
else
|
||||
{
|
||||
cam_distancemove=0;
|
||||
cam_mousemove=0;
|
||||
iMouseInUse=0;
|
||||
}
|
||||
}
|
||||
|
||||
//the key has been released for camera movement
|
||||
//tell the engine that mouse camera movement is off
|
||||
void CAM_EndDistance(void)
|
||||
{
|
||||
cam_distancemove=0;
|
||||
cam_mousemove=0;
|
||||
iMouseInUse=0;
|
||||
}
|
||||
|
||||
int DLLEXPORT CL_IsThirdPerson( void )
|
||||
{
|
||||
return (cam_thirdperson ? 1 : 0) || (g_iUser1 && (g_iUser2 == gEngfuncs.GetLocalPlayer()->index) );
|
||||
}
|
||||
|
||||
void DLLEXPORT CL_CameraOffset( float *ofs )
|
||||
{
|
||||
VectorCopy( cam_ofs, ofs );
|
||||
}
|
24
cl_dll/in_defs.h
Normal file
24
cl_dll/in_defs.h
Normal file
@ -0,0 +1,24 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined( IN_DEFSH )
|
||||
#define IN_DEFSH
|
||||
#pragma once
|
||||
|
||||
// up / down
|
||||
#define PITCH 0
|
||||
// left / right
|
||||
#define YAW 1
|
||||
// fall over
|
||||
#define ROLL 2
|
||||
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
void V_StartPitchDrift( void );
|
||||
void V_StopPitchDrift( void );
|
||||
|
||||
#endif
|
1051
cl_dll/input.cpp
Normal file
1051
cl_dll/input.cpp
Normal file
File diff suppressed because it is too large
Load Diff
963
cl_dll/inputw32.cpp
Normal file
963
cl_dll/inputw32.cpp
Normal file
@ -0,0 +1,963 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
// in_win.c -- windows 95 mouse and joystick code
|
||||
// 02/21/97 JCB Added extended DirectInput code to support external controllers.
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "camera.h"
|
||||
#include "kbutton.h"
|
||||
#include "cvardef.h"
|
||||
#include "usercmd.h"
|
||||
#include "const.h"
|
||||
#include "camera.h"
|
||||
#include "in_defs.h"
|
||||
#include "../engine/keydefs.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define MOUSE_BUTTON_COUNT 5
|
||||
|
||||
// Set this to 1 to show mouse cursor. Experimental
|
||||
int g_iVisibleMouse = 0;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void DLLEXPORT IN_ActivateMouse( void );
|
||||
void DLLEXPORT IN_DeactivateMouse( void );
|
||||
void DLLEXPORT IN_MouseEvent (int mstate);
|
||||
void DLLEXPORT IN_Accumulate (void);
|
||||
void DLLEXPORT IN_ClearStates (void);
|
||||
}
|
||||
|
||||
extern cl_enginefunc_t gEngfuncs;
|
||||
|
||||
extern int iMouseInUse;
|
||||
|
||||
extern kbutton_t in_strafe;
|
||||
extern kbutton_t in_mlook;
|
||||
extern kbutton_t in_speed;
|
||||
extern kbutton_t in_jlook;
|
||||
|
||||
extern cvar_t *m_pitch;
|
||||
extern cvar_t *m_yaw;
|
||||
extern cvar_t *m_forward;
|
||||
extern cvar_t *m_side;
|
||||
|
||||
extern cvar_t *lookstrafe;
|
||||
extern cvar_t *lookspring;
|
||||
extern cvar_t *cl_pitchdown;
|
||||
extern cvar_t *cl_pitchup;
|
||||
extern cvar_t *cl_yawspeed;
|
||||
extern cvar_t *cl_sidespeed;
|
||||
extern cvar_t *cl_forwardspeed;
|
||||
extern cvar_t *cl_pitchspeed;
|
||||
extern cvar_t *cl_movespeedkey;
|
||||
|
||||
// mouse variables
|
||||
cvar_t *m_filter;
|
||||
cvar_t *sensitivity;
|
||||
|
||||
int CL_IsDead( void ); // buz
|
||||
|
||||
int mouse_buttons;
|
||||
int mouse_oldbuttonstate;
|
||||
POINT current_pos;
|
||||
int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
|
||||
|
||||
static int restore_spi;
|
||||
static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1};
|
||||
static int mouseactive;
|
||||
int mouseinitialized;
|
||||
static int mouseparmsvalid;
|
||||
static int mouseshowtoggle = 1;
|
||||
|
||||
// joystick defines and variables
|
||||
// where should defines be moved?
|
||||
#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
|
||||
#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball
|
||||
#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V
|
||||
#define JOY_AXIS_X 0
|
||||
#define JOY_AXIS_Y 1
|
||||
#define JOY_AXIS_Z 2
|
||||
#define JOY_AXIS_R 3
|
||||
#define JOY_AXIS_U 4
|
||||
#define JOY_AXIS_V 5
|
||||
|
||||
enum _ControlList
|
||||
{
|
||||
AxisNada = 0,
|
||||
AxisForward,
|
||||
AxisLook,
|
||||
AxisSide,
|
||||
AxisTurn
|
||||
};
|
||||
|
||||
DWORD dwAxisFlags[JOY_MAX_AXES] =
|
||||
{
|
||||
JOY_RETURNX,
|
||||
JOY_RETURNY,
|
||||
JOY_RETURNZ,
|
||||
JOY_RETURNR,
|
||||
JOY_RETURNU,
|
||||
JOY_RETURNV
|
||||
};
|
||||
|
||||
DWORD dwAxisMap[ JOY_MAX_AXES ];
|
||||
DWORD dwControlMap[ JOY_MAX_AXES ];
|
||||
PDWORD pdwRawValue[ JOY_MAX_AXES ];
|
||||
|
||||
// none of these cvars are saved over a session
|
||||
// this means that advanced controller configuration needs to be executed
|
||||
// each time. this avoids any problems with getting back to a default usage
|
||||
// or when changing from one controller to another. this way at least something
|
||||
// works.
|
||||
cvar_t *in_joystick;
|
||||
cvar_t *joy_name;
|
||||
cvar_t *joy_advanced;
|
||||
cvar_t *joy_advaxisx;
|
||||
cvar_t *joy_advaxisy;
|
||||
cvar_t *joy_advaxisz;
|
||||
cvar_t *joy_advaxisr;
|
||||
cvar_t *joy_advaxisu;
|
||||
cvar_t *joy_advaxisv;
|
||||
cvar_t *joy_forwardthreshold;
|
||||
cvar_t *joy_sidethreshold;
|
||||
cvar_t *joy_pitchthreshold;
|
||||
cvar_t *joy_yawthreshold;
|
||||
cvar_t *joy_forwardsensitivity;
|
||||
cvar_t *joy_sidesensitivity;
|
||||
cvar_t *joy_pitchsensitivity;
|
||||
cvar_t *joy_yawsensitivity;
|
||||
cvar_t *joy_wwhack1;
|
||||
cvar_t *joy_wwhack2;
|
||||
|
||||
int joy_avail, joy_advancedinit, joy_haspov;
|
||||
DWORD joy_oldbuttonstate, joy_oldpovstate;
|
||||
|
||||
int joy_id;
|
||||
DWORD joy_flags;
|
||||
DWORD joy_numbuttons;
|
||||
|
||||
static JOYINFOEX ji;
|
||||
|
||||
/*
|
||||
===========
|
||||
Force_CenterView_f
|
||||
===========
|
||||
*/
|
||||
void Force_CenterView_f (void)
|
||||
{
|
||||
vec3_t viewangles;
|
||||
|
||||
if (!iMouseInUse)
|
||||
{
|
||||
gEngfuncs.GetViewAngles( (float *)viewangles );
|
||||
viewangles[PITCH] = 0;
|
||||
gEngfuncs.SetViewAngles( (float *)viewangles );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_ActivateMouse
|
||||
===========
|
||||
*/
|
||||
void DLLEXPORT IN_ActivateMouse (void)
|
||||
{
|
||||
if (mouseinitialized)
|
||||
{
|
||||
if (mouseparmsvalid)
|
||||
restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
|
||||
mouseactive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_DeactivateMouse
|
||||
===========
|
||||
*/
|
||||
void DLLEXPORT IN_DeactivateMouse (void)
|
||||
{
|
||||
if (mouseinitialized)
|
||||
{
|
||||
if (restore_spi)
|
||||
SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);
|
||||
|
||||
mouseactive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_StartupMouse
|
||||
===========
|
||||
*/
|
||||
void IN_StartupMouse (void)
|
||||
{
|
||||
if ( gEngfuncs.CheckParm ("-nomouse", NULL ) )
|
||||
return;
|
||||
|
||||
mouseinitialized = 1;
|
||||
mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0);
|
||||
|
||||
if (mouseparmsvalid)
|
||||
{
|
||||
if ( gEngfuncs.CheckParm ("-noforcemspd", NULL ) )
|
||||
newmouseparms[2] = originalmouseparms[2];
|
||||
|
||||
if ( gEngfuncs.CheckParm ("-noforcemaccel", NULL ) )
|
||||
{
|
||||
newmouseparms[0] = originalmouseparms[0];
|
||||
newmouseparms[1] = originalmouseparms[1];
|
||||
}
|
||||
|
||||
if ( gEngfuncs.CheckParm ("-noforcemparms", NULL ) )
|
||||
{
|
||||
newmouseparms[0] = originalmouseparms[0];
|
||||
newmouseparms[1] = originalmouseparms[1];
|
||||
newmouseparms[2] = originalmouseparms[2];
|
||||
}
|
||||
}
|
||||
|
||||
mouse_buttons = MOUSE_BUTTON_COUNT;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Shutdown
|
||||
===========
|
||||
*/
|
||||
void IN_Shutdown (void)
|
||||
{
|
||||
IN_DeactivateMouse ();
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_GetMousePos
|
||||
|
||||
Ask for mouse position from engine
|
||||
===========
|
||||
*/
|
||||
void IN_GetMousePos( int *mx, int *my )
|
||||
{
|
||||
gEngfuncs.GetMousePosition( mx, my );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_ResetMouse
|
||||
|
||||
FIXME: Call through to engine?
|
||||
===========
|
||||
*/
|
||||
void IN_ResetMouse( void )
|
||||
{
|
||||
SetCursorPos ( gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY() );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_MouseEvent
|
||||
===========
|
||||
*/
|
||||
void DLLEXPORT IN_MouseEvent (int mstate)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( iMouseInUse || g_iVisibleMouse )
|
||||
return;
|
||||
|
||||
// perform button actions
|
||||
for (i=0 ; i<mouse_buttons ; i++)
|
||||
{
|
||||
if ( (mstate & (1<<i)) &&
|
||||
!(mouse_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
gEngfuncs.Key_Event (K_MOUSE1 + i, 1);
|
||||
}
|
||||
|
||||
if ( !(mstate & (1<<i)) &&
|
||||
(mouse_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
gEngfuncs.Key_Event (K_MOUSE1 + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
mouse_oldbuttonstate = mstate;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_MouseMove
|
||||
===========
|
||||
*/
|
||||
void IN_MouseMove ( float frametime, usercmd_t *cmd)
|
||||
{
|
||||
int mx, my;
|
||||
vec3_t viewangles;
|
||||
|
||||
gEngfuncs.GetViewAngles( (float *)viewangles );
|
||||
|
||||
if ( in_mlook.state & 1)
|
||||
{
|
||||
V_StopPitchDrift ();
|
||||
}
|
||||
|
||||
//jjb - this disbles normal mouse control if the user is trying to
|
||||
// move the camera, or if the mouse cursor is visible or if we're in intermission
|
||||
if ( !iMouseInUse && !g_iVisibleMouse && !gHUD.m_iIntermission )
|
||||
{
|
||||
GetCursorPos (¤t_pos);
|
||||
|
||||
mx = current_pos.x - gEngfuncs.GetWindowCenterX() + mx_accum;
|
||||
my = current_pos.y - gEngfuncs.GetWindowCenterY() + my_accum;
|
||||
|
||||
mx_accum = 0;
|
||||
my_accum = 0;
|
||||
|
||||
if (m_filter->value)
|
||||
{
|
||||
mouse_x = (mx + old_mouse_x) * 0.5;
|
||||
mouse_y = (my + old_mouse_y) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_x = mx;
|
||||
mouse_y = my;
|
||||
}
|
||||
|
||||
old_mouse_x = mx;
|
||||
old_mouse_y = my;
|
||||
|
||||
if ( gHUD.GetSensitivity() != 0 )
|
||||
{
|
||||
mouse_x *= gHUD.GetSensitivity();
|
||||
mouse_y *= gHUD.GetSensitivity();
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_x *= sensitivity->value;
|
||||
mouse_y *= sensitivity->value;
|
||||
}
|
||||
|
||||
// buz: slower turning when in sniper mode
|
||||
if (gHUD.m_iFOV < 90)
|
||||
{
|
||||
mouse_x *= 0.5;
|
||||
mouse_y *= 0.5;
|
||||
}
|
||||
|
||||
// buz: remove turning if DEAD!
|
||||
if (CL_IsDead())
|
||||
{
|
||||
mouse_x = 0;
|
||||
mouse_y = 0;
|
||||
// CONPRINT("DEAD!\n");
|
||||
}
|
||||
|
||||
// add mouse X/Y movement to cmd
|
||||
if ( (in_strafe.state & 1) || (lookstrafe->value && (in_mlook.state & 1) ))
|
||||
cmd->sidemove += m_side->value * mouse_x;
|
||||
else
|
||||
viewangles[YAW] -= m_yaw->value * mouse_x;
|
||||
|
||||
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
|
||||
{
|
||||
viewangles[PITCH] += m_pitch->value * mouse_y;
|
||||
if (viewangles[PITCH] > cl_pitchdown->value)
|
||||
viewangles[PITCH] = cl_pitchdown->value;
|
||||
if (viewangles[PITCH] < -cl_pitchup->value)
|
||||
viewangles[PITCH] = -cl_pitchup->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((in_strafe.state & 1) && gEngfuncs.IsNoClipping() )
|
||||
{
|
||||
cmd->upmove -= m_forward->value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->forwardmove -= m_forward->value * mouse_y;
|
||||
}
|
||||
}
|
||||
|
||||
// if the mouse has moved, force it to the center, so there's room to move
|
||||
if ( mx || my )
|
||||
{
|
||||
IN_ResetMouse();
|
||||
}
|
||||
}
|
||||
|
||||
gEngfuncs.SetViewAngles( (float *)viewangles );
|
||||
|
||||
/*
|
||||
//#define TRACE_TEST
|
||||
#if defined( TRACE_TEST )
|
||||
{
|
||||
int mx, my;
|
||||
void V_Move( int mx, int my );
|
||||
IN_GetMousePos( &mx, &my );
|
||||
V_Move( mx, my );
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Accumulate
|
||||
===========
|
||||
*/
|
||||
void DLLEXPORT IN_Accumulate (void)
|
||||
{
|
||||
//only accumulate mouse if we are not moving the camera with the mouse
|
||||
if ( !iMouseInUse && !g_iVisibleMouse )
|
||||
{
|
||||
if (mouseactive)
|
||||
{
|
||||
GetCursorPos (¤t_pos);
|
||||
|
||||
mx_accum += current_pos.x - gEngfuncs.GetWindowCenterX();
|
||||
my_accum += current_pos.y - gEngfuncs.GetWindowCenterY();
|
||||
|
||||
// force the mouse to the center, so there's room to move
|
||||
IN_ResetMouse();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
IN_ClearStates
|
||||
===================
|
||||
*/
|
||||
void DLLEXPORT IN_ClearStates (void)
|
||||
{
|
||||
if ( !mouseactive )
|
||||
return;
|
||||
|
||||
mx_accum = 0;
|
||||
my_accum = 0;
|
||||
mouse_oldbuttonstate = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
IN_StartupJoystick
|
||||
===============
|
||||
*/
|
||||
void IN_StartupJoystick (void)
|
||||
{
|
||||
int numdevs;
|
||||
JOYCAPS jc;
|
||||
MMRESULT mmr;
|
||||
|
||||
// assume no joystick
|
||||
joy_avail = 0;
|
||||
|
||||
// abort startup if user requests no joystick
|
||||
if ( gEngfuncs.CheckParm ("-nojoy", NULL ) )
|
||||
return;
|
||||
|
||||
// verify joystick driver is present
|
||||
if ((numdevs = joyGetNumDevs ()) == 0)
|
||||
{
|
||||
gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// cycle through the joystick ids for the first valid one
|
||||
for (joy_id=0 ; joy_id<numdevs ; joy_id++)
|
||||
{
|
||||
memset (&ji, 0, sizeof(ji));
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = JOY_RETURNCENTERED;
|
||||
|
||||
if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
|
||||
break;
|
||||
}
|
||||
|
||||
// abort startup if we didn't find a valid joystick
|
||||
if (mmr != JOYERR_NOERROR)
|
||||
{
|
||||
gEngfuncs.Con_DPrintf ("joystick not found -- no valid joysticks (%x)\n\n", mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the capabilities of the selected joystick
|
||||
// abort startup if command fails
|
||||
memset (&jc, 0, sizeof(jc));
|
||||
if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
|
||||
{
|
||||
gEngfuncs.Con_DPrintf ("joystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
|
||||
return;
|
||||
}
|
||||
|
||||
// save the joystick's number of buttons and POV status
|
||||
joy_numbuttons = jc.wNumButtons;
|
||||
joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
|
||||
|
||||
// old button and POV states default to no buttons pressed
|
||||
joy_oldbuttonstate = joy_oldpovstate = 0;
|
||||
|
||||
// mark the joystick as available and advanced initialization not completed
|
||||
// this is needed as cvars are not available during initialization
|
||||
gEngfuncs.Con_Printf ("joystick found\n\n", mmr);
|
||||
joy_avail = 1;
|
||||
joy_advancedinit = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
RawValuePointer
|
||||
===========
|
||||
*/
|
||||
PDWORD RawValuePointer (int axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case JOY_AXIS_X:
|
||||
return &ji.dwXpos;
|
||||
case JOY_AXIS_Y:
|
||||
return &ji.dwYpos;
|
||||
case JOY_AXIS_Z:
|
||||
return &ji.dwZpos;
|
||||
case JOY_AXIS_R:
|
||||
return &ji.dwRpos;
|
||||
case JOY_AXIS_U:
|
||||
return &ji.dwUpos;
|
||||
case JOY_AXIS_V:
|
||||
return &ji.dwVpos;
|
||||
}
|
||||
// FIX: need to do some kind of error
|
||||
return &ji.dwXpos;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_AdvancedUpdate_f
|
||||
===========
|
||||
*/
|
||||
void Joy_AdvancedUpdate_f (void)
|
||||
{
|
||||
|
||||
// called once by IN_ReadJoystick and by user whenever an update is needed
|
||||
// cvars are now available
|
||||
int i;
|
||||
DWORD dwTemp;
|
||||
|
||||
// initialize all the maps
|
||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
dwAxisMap[i] = AxisNada;
|
||||
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
|
||||
pdwRawValue[i] = RawValuePointer(i);
|
||||
}
|
||||
|
||||
if( joy_advanced->value == 0.0)
|
||||
{
|
||||
// default joystick initialization
|
||||
// 2 axes only with joystick control
|
||||
dwAxisMap[JOY_AXIS_X] = AxisTurn;
|
||||
// dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
|
||||
dwAxisMap[JOY_AXIS_Y] = AxisForward;
|
||||
// dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( strcmp ( joy_name->string, "joystick") != 0 )
|
||||
{
|
||||
// notify user of advanced controller
|
||||
gEngfuncs.Con_Printf ("\n%s configured\n\n", joy_name->string);
|
||||
}
|
||||
|
||||
// advanced initialization here
|
||||
// data supplied by user via joy_axisn cvars
|
||||
dwTemp = (DWORD) joy_advaxisx->value;
|
||||
dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisy->value;
|
||||
dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisz->value;
|
||||
dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisr->value;
|
||||
dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisu->value;
|
||||
dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
dwTemp = (DWORD) joy_advaxisv->value;
|
||||
dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
|
||||
dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
|
||||
}
|
||||
|
||||
// compute the axes to collect from DirectInput
|
||||
joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
|
||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
if (dwAxisMap[i] != AxisNada)
|
||||
{
|
||||
joy_flags |= dwAxisFlags[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Commands
|
||||
===========
|
||||
*/
|
||||
void IN_Commands (void)
|
||||
{
|
||||
int i, key_index;
|
||||
DWORD buttonstate, povstate;
|
||||
|
||||
if (!joy_avail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// loop through the joystick buttons
|
||||
// key a joystick event or auxillary event for higher number buttons for each state change
|
||||
buttonstate = ji.dwButtons;
|
||||
for (i=0 ; i < (int)joy_numbuttons ; i++)
|
||||
{
|
||||
if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
gEngfuncs.Key_Event (key_index + i, 1);
|
||||
}
|
||||
|
||||
if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
key_index = (i < 4) ? K_JOY1 : K_AUX1;
|
||||
gEngfuncs.Key_Event (key_index + i, 0);
|
||||
}
|
||||
}
|
||||
joy_oldbuttonstate = buttonstate;
|
||||
|
||||
if (joy_haspov)
|
||||
{
|
||||
// convert POV information into 4 bits of state information
|
||||
// this avoids any potential problems related to moving from one
|
||||
// direction to another without going through the center position
|
||||
povstate = 0;
|
||||
if(ji.dwPOV != JOY_POVCENTERED)
|
||||
{
|
||||
if (ji.dwPOV == JOY_POVFORWARD)
|
||||
povstate |= 0x01;
|
||||
if (ji.dwPOV == JOY_POVRIGHT)
|
||||
povstate |= 0x02;
|
||||
if (ji.dwPOV == JOY_POVBACKWARD)
|
||||
povstate |= 0x04;
|
||||
if (ji.dwPOV == JOY_POVLEFT)
|
||||
povstate |= 0x08;
|
||||
}
|
||||
// determine which bits have changed and key an auxillary event for each change
|
||||
for (i=0 ; i < 4 ; i++)
|
||||
{
|
||||
if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
|
||||
{
|
||||
gEngfuncs.Key_Event (K_AUX29 + i, 1);
|
||||
}
|
||||
|
||||
if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
|
||||
{
|
||||
gEngfuncs.Key_Event (K_AUX29 + i, 0);
|
||||
}
|
||||
}
|
||||
joy_oldpovstate = povstate;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
IN_ReadJoystick
|
||||
===============
|
||||
*/
|
||||
int IN_ReadJoystick (void)
|
||||
{
|
||||
|
||||
memset (&ji, 0, sizeof(ji));
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = joy_flags;
|
||||
|
||||
if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
|
||||
{
|
||||
// this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
|
||||
// rather than having 32768 be the zero point, they have the zero point at 32668
|
||||
// go figure -- anyway, now we get the full resolution out of the device
|
||||
if (joy_wwhack1->value != 0.0)
|
||||
{
|
||||
ji.dwUpos += 100;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read error occurred
|
||||
// turning off the joystick seems too harsh for 1 read error,\
|
||||
// but what should be done?
|
||||
// Con_Printf ("IN_ReadJoystick: no response\n");
|
||||
// joy_avail = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_JoyMove
|
||||
===========
|
||||
*/
|
||||
void IN_JoyMove ( float frametime, usercmd_t *cmd )
|
||||
{
|
||||
float speed, aspeed;
|
||||
float fAxisValue, fTemp;
|
||||
int i;
|
||||
vec3_t viewangles;
|
||||
|
||||
gEngfuncs.GetViewAngles( (float *)viewangles );
|
||||
|
||||
|
||||
// complete initialization if first time in
|
||||
// this is needed as cvars are not available at initialization time
|
||||
if( joy_advancedinit != 1 )
|
||||
{
|
||||
Joy_AdvancedUpdate_f();
|
||||
joy_advancedinit = 1;
|
||||
}
|
||||
|
||||
// verify joystick is available and that the user wants to use it
|
||||
if (!joy_avail || !in_joystick->value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// collect the joystick data, if possible
|
||||
if (IN_ReadJoystick () != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_speed.state & 1)
|
||||
speed = cl_movespeedkey->value;
|
||||
else
|
||||
speed = 1;
|
||||
|
||||
aspeed = speed * frametime;
|
||||
|
||||
// loop through the axes
|
||||
for (i = 0; i < JOY_MAX_AXES; i++)
|
||||
{
|
||||
// get the floating point zero-centered, potentially-inverted data for the current axis
|
||||
fAxisValue = (float) *pdwRawValue[i];
|
||||
// move centerpoint to zero
|
||||
fAxisValue -= 32768.0;
|
||||
|
||||
if (joy_wwhack2->value != 0.0)
|
||||
{
|
||||
if (dwAxisMap[i] == AxisTurn)
|
||||
{
|
||||
// this is a special formula for the Logitech WingMan Warrior
|
||||
// y=ax^b; where a = 300 and b = 1.3
|
||||
// also x values are in increments of 800 (so this is factored out)
|
||||
// then bounds check result to level out excessively high spin rates
|
||||
fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
|
||||
if (fTemp > 14000.0)
|
||||
fTemp = 14000.0;
|
||||
// restore direction information
|
||||
fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
|
||||
}
|
||||
}
|
||||
|
||||
// convert range from -32768..32767 to -1..1
|
||||
fAxisValue /= 32768.0;
|
||||
|
||||
switch (dwAxisMap[i])
|
||||
{
|
||||
case AxisForward:
|
||||
if ((joy_advanced->value == 0.0) && (in_jlook.state & 1))
|
||||
{
|
||||
// user wants forward control to become look control
|
||||
if (fabs(fAxisValue) > joy_pitchthreshold->value)
|
||||
{
|
||||
// if mouse invert is on, invert the joystick pitch value
|
||||
// only absolute control support here (joy_advanced is 0)
|
||||
if (m_pitch->value < 0.0)
|
||||
{
|
||||
viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
|
||||
}
|
||||
V_StopPitchDrift();
|
||||
}
|
||||
else
|
||||
{
|
||||
// no pitch movement
|
||||
// disable pitch return-to-center unless requested by user
|
||||
// *** this code can be removed when the lookspring bug is fixed
|
||||
// *** the bug always has the lookspring feature on
|
||||
if(lookspring->value == 0.0)
|
||||
{
|
||||
V_StopPitchDrift();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// user wants forward control to be forward control
|
||||
if (fabs(fAxisValue) > joy_forwardthreshold->value)
|
||||
{
|
||||
cmd->forwardmove += (fAxisValue * joy_forwardsensitivity->value) * speed * cl_forwardspeed->value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisSide:
|
||||
if (fabs(fAxisValue) > joy_sidethreshold->value)
|
||||
{
|
||||
cmd->sidemove += (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisTurn:
|
||||
if ((in_strafe.state & 1) || (lookstrafe->value && (in_jlook.state & 1)))
|
||||
{
|
||||
// user wants turn control to become side control
|
||||
if (fabs(fAxisValue) > joy_sidethreshold->value)
|
||||
{
|
||||
cmd->sidemove -= (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// user wants turn control to be turn control
|
||||
if (fabs(fAxisValue) > joy_yawthreshold->value)
|
||||
{
|
||||
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
|
||||
{
|
||||
viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * aspeed * cl_yawspeed->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * speed * 180.0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AxisLook:
|
||||
if (in_jlook.state & 1)
|
||||
{
|
||||
if (fabs(fAxisValue) > joy_pitchthreshold->value)
|
||||
{
|
||||
// pitch movement detected and pitch movement desired by user
|
||||
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
|
||||
{
|
||||
viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * speed * 180.0;
|
||||
}
|
||||
V_StopPitchDrift();
|
||||
}
|
||||
else
|
||||
{
|
||||
// no pitch movement
|
||||
// disable pitch return-to-center unless requested by user
|
||||
// *** this code can be removed when the lookspring bug is fixed
|
||||
// *** the bug always has the lookspring feature on
|
||||
if( lookspring->value == 0.0 )
|
||||
{
|
||||
V_StopPitchDrift();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// bounds check pitch
|
||||
if (viewangles[PITCH] > cl_pitchdown->value)
|
||||
viewangles[PITCH] = cl_pitchdown->value;
|
||||
if (viewangles[PITCH] < -cl_pitchup->value)
|
||||
viewangles[PITCH] = -cl_pitchup->value;
|
||||
|
||||
gEngfuncs.SetViewAngles( (float *)viewangles );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Move
|
||||
===========
|
||||
*/
|
||||
void IN_Move ( float frametime, usercmd_t *cmd)
|
||||
{
|
||||
if ( !iMouseInUse && mouseactive )
|
||||
{
|
||||
IN_MouseMove ( frametime, cmd);
|
||||
}
|
||||
|
||||
IN_JoyMove ( frametime, cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Init
|
||||
===========
|
||||
*/
|
||||
void IN_Init (void)
|
||||
{
|
||||
m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE );
|
||||
sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE ); // user mouse sensitivity setting.
|
||||
|
||||
in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE );
|
||||
joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 );
|
||||
joy_advanced = gEngfuncs.pfnRegisterVariable ( "joyadvanced", "0", 0 );
|
||||
joy_advaxisx = gEngfuncs.pfnRegisterVariable ( "joyadvaxisx", "0", 0 );
|
||||
joy_advaxisy = gEngfuncs.pfnRegisterVariable ( "joyadvaxisy", "0", 0 );
|
||||
joy_advaxisz = gEngfuncs.pfnRegisterVariable ( "joyadvaxisz", "0", 0 );
|
||||
joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 );
|
||||
joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 );
|
||||
joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 );
|
||||
joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 );
|
||||
joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 );
|
||||
joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 );
|
||||
joy_yawthreshold = gEngfuncs.pfnRegisterVariable ( "joyyawthreshold", "0.15", 0 );
|
||||
joy_forwardsensitivity = gEngfuncs.pfnRegisterVariable ( "joyforwardsensitivity", "-1.0", 0 );
|
||||
joy_sidesensitivity = gEngfuncs.pfnRegisterVariable ( "joysidesensitivity", "-1.0", 0 );
|
||||
joy_pitchsensitivity = gEngfuncs.pfnRegisterVariable ( "joypitchsensitivity", "1.0", 0 );
|
||||
joy_yawsensitivity = gEngfuncs.pfnRegisterVariable ( "joyyawsensitivity", "-1.0", 0 );
|
||||
joy_wwhack1 = gEngfuncs.pfnRegisterVariable ( "joywwhack1", "0.0", 0 );
|
||||
joy_wwhack2 = gEngfuncs.pfnRegisterVariable ( "joywwhack2", "0.0", 0 );
|
||||
|
||||
gEngfuncs.pfnAddCommand ("force_centerview", Force_CenterView_f);
|
||||
gEngfuncs.pfnAddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f);
|
||||
|
||||
IN_StartupMouse ();
|
||||
IN_StartupJoystick ();
|
||||
}
|
18
cl_dll/kbutton.h
Normal file
18
cl_dll/kbutton.h
Normal file
@ -0,0 +1,18 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#if !defined( KBUTTONH )
|
||||
#define KBUTTONH
|
||||
#pragma once
|
||||
|
||||
typedef struct kbutton_s
|
||||
{
|
||||
int down[2]; // key nums holding it down
|
||||
int state; // low bit is down state
|
||||
} kbutton_t;
|
||||
|
||||
#endif // !KBUTTONH
|
364
cl_dll/lensflare.cpp
Normal file
364
cl_dll/lensflare.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "parsemsg.h"
|
||||
#include "vgui_TeamFortressViewport.h"
|
||||
#include "triangleapi.h"
|
||||
#include "ref_params.h"
|
||||
#include "event_api.h"
|
||||
#include "pm_defs.h"
|
||||
#include "pm_movevars.h"
|
||||
#include "gl_local.h"
|
||||
|
||||
int CHudLensflare :: Init( void )
|
||||
{
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
m_pCvarDraw = CVAR_REGISTER( "cl_lensflare", "1", FCVAR_ARCHIVE );
|
||||
|
||||
gHUD.AddHudElem( this );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudLensflare :: VidInit( void )
|
||||
{
|
||||
text[0] = SPR_Load("sprites/lens/lens1.spr");
|
||||
red[0] = green[0] = blue[0] = 1.0;
|
||||
scale[0] = 45;
|
||||
multi[0] = -0.45;
|
||||
|
||||
text[1] = SPR_Load("sprites/lens/lens2.spr");
|
||||
red[1] = green[0] = blue[0] = 1.0;
|
||||
scale[1] = 25;
|
||||
multi[1] = 0.2;
|
||||
|
||||
text[2] = SPR_Load("sprites/lens/glow1.spr");
|
||||
red[2] = 132/255;
|
||||
green[2] = 1.0;
|
||||
blue[2] = 153/255;
|
||||
scale[2] = 35;
|
||||
multi[2] = 0.3;
|
||||
|
||||
text[3] = SPR_Load("sprites/lens/glow2.spr");
|
||||
red[3] = 1.0;
|
||||
green[3] = 164/255;
|
||||
blue[3] = 164/255;
|
||||
scale[3] = 40;
|
||||
multi[3] = 0.46;
|
||||
|
||||
text[4] = SPR_Load("sprites/lens/lens3.spr");
|
||||
red[4] = 1.0;
|
||||
green[4] = 164/255;
|
||||
blue[4] = 164/255;
|
||||
scale[4] = 52;
|
||||
multi[4] = 0.5;
|
||||
|
||||
text[5] = SPR_Load("sprites/lens/lens2.spr");
|
||||
red[5] = green[5] = blue[5] = 1.0;
|
||||
scale[5] = 31;
|
||||
multi[5] = 0.54;
|
||||
|
||||
text[6] = SPR_Load("sprites/lens/lens2.spr");
|
||||
red[6] = 0.6;
|
||||
green[6] = 1.0;
|
||||
blue[6] = 0.6;
|
||||
scale[6] = 26;
|
||||
multi[6] = 0.64;
|
||||
|
||||
text[7] = SPR_Load("sprites/lens/glow1.spr");
|
||||
red[7] = 0.5;
|
||||
green[7] = 1.0;
|
||||
blue[7] = 0.5;
|
||||
scale[7] = 20;
|
||||
multi[7] = 0.77;
|
||||
|
||||
text[8] = SPR_Load("sprites/lens/lens2.spr");
|
||||
|
||||
text[9] = SPR_Load("sprites/lens/lens1.spr");
|
||||
|
||||
flPlayerBlend = 0.0;
|
||||
flPlayerBlend2 = 0.0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudLensflare :: DrawFlare( const Vector &forward, const Vector &lightdir, const Vector &lightorg )
|
||||
{
|
||||
flPlayerBlend = max( DotProduct( forward, lightdir ) - 0.85, 0.0 ) * 6.8;
|
||||
if( flPlayerBlend > 1.0 ) flPlayerBlend = 1.0;
|
||||
|
||||
flPlayerBlend4 = max( DotProduct( forward, lightdir ) - 0.90, 0.0 ) * 6.6;
|
||||
if( flPlayerBlend4 > 1.0 ) flPlayerBlend4 = 1.0;
|
||||
|
||||
flPlayerBlend6 = max( DotProduct( forward, lightdir ) - 0.80, 0.0 ) * 6.7;
|
||||
if( flPlayerBlend6 > 1.0 ) flPlayerBlend6 = 1.0;
|
||||
|
||||
flPlayerBlend2 = flPlayerBlend6 * 140.0 ;
|
||||
flPlayerBlend3 = flPlayerBlend * 190.0 ;
|
||||
flPlayerBlend5 = flPlayerBlend4 * 222.0 ;
|
||||
|
||||
Vector normal, point, screen;
|
||||
|
||||
if( cv_renderer->value ) R_WorldToScreen( lightorg, screen );
|
||||
else gEngfuncs.pTriAPI->WorldToScreen( (float *)&lightorg, screen );
|
||||
|
||||
Suncoordx = XPROJECT( screen[0] );
|
||||
Suncoordy = YPROJECT( screen[1] );
|
||||
|
||||
Screenmx = ScreenWidth / 2;
|
||||
Screenmy = ScreenHeight / 2;
|
||||
|
||||
Sundistx = Screenmx - Suncoordx;
|
||||
Sundisty = Screenmy - Suncoordy;
|
||||
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(SPR_Load("sprites/lens/lensflare2.spr")) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f( 0.97f, 0.6f, 0.02f, 1.0f );
|
||||
gEngfuncs.pTriAPI->Brightness( 0.3f );
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx + 190, Suncoordy + 190, 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx + 190, Suncoordy - 190, 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx - 190, Suncoordy - 190, 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx - 190, Suncoordy + 190, 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(SPR_Load("sprites/lens/glow2.spr")) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(1.0, 1.0 , 1.0, flPlayerBlend3/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend3/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx + 160, Suncoordy + 160, 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx + 160, Suncoordy - 160, 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx - 160, Suncoordy - 160, 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Suncoordx - 160, Suncoordy + 160, 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(SPR_Load("sprites/lens/glow3.spr")) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(1.0, 1.0 , 1.0, flPlayerBlend5/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend5/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(0, 0, 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(0, ScreenHeight, 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(ScreenWidth, ScreenHeight, 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(ScreenWidth, 0, 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
int i = 1;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
Lensx[i] = (Suncoordx + (Sundistx * multi[i]));
|
||||
Lensy[i] = (Suncoordy + (Sundisty * multi[i]));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(red[i], green[i] , green[i], flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] + scale[i], 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] + scale[i], Lensy[i] - scale[i], 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] - scale[i], 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx[i] - scale[i], Lensy[i] + scale[i], 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
int scale1 = 32;
|
||||
int Lensx1,Lensy1 = 0;
|
||||
Lensx1 = (Suncoordx + (Sundistx * 0.88));
|
||||
Lensy1 = (Suncoordy + (Sundisty * 0.88));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(0.9, 0.9 , 0.9, flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 + scale1, Lensy1 + scale1, 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 + scale1, Lensy1 - scale1, 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 - scale1, Lensy1 - scale1, 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 - scale1, Lensy1 + scale1, 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
i++;
|
||||
scale1 = 140;
|
||||
Lensx1 = (Suncoordx + (Sundistx * 1.1));
|
||||
Lensy1 = (Suncoordy + (Sundisty * 1.1));
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); //additive
|
||||
gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *) gEngfuncs.GetSpritePointer(text[i]) , 0);
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_NONE ); //no culling
|
||||
gEngfuncs.pTriAPI->Color4f(0.9, 0.9 , 0.9, flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Brightness(flPlayerBlend2/255.0);
|
||||
gEngfuncs.pTriAPI->Begin(TRI_QUADS); //start our quad
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 + scale1, Lensy1 + scale1, 0); //top left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 + scale1, Lensy1 - scale1, 0); //bottom left
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 - scale1, Lensy1 - scale1, 0); //bottom right
|
||||
gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);gEngfuncs.pTriAPI->Vertex3f(Lensx1 - scale1, Lensy1 + scale1, 0); //top right
|
||||
gEngfuncs.pTriAPI->End(); //end our list of vertexes
|
||||
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
|
||||
|
||||
gEngfuncs.pTriAPI->CullFace( TRI_FRONT );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudLensflare :: Draw( float flTime )
|
||||
{
|
||||
Vector forward, sundir, suntarget;
|
||||
pmtrace_t ptr;
|
||||
|
||||
if( m_pCvarDraw->value <= 0.0f )
|
||||
return 0;
|
||||
|
||||
forward = g_pViewParams->forward;
|
||||
|
||||
// draw flares for dynlights
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
CDynLight *pl = &tr.dlights[i];
|
||||
|
||||
if( pl->die < flTime || !pl->radius || !FBitSet( pl->flags, DLF_LENSFLARE ))
|
||||
continue;
|
||||
|
||||
if( pl->type == LIGHT_SPOT )
|
||||
sundir = pl->frustum.GetPlane( FRUSTUM_FAR )->normal;
|
||||
else sundir = ( pl->origin - g_pViewParams->vieworg ).Normalize();
|
||||
|
||||
suntarget = pl->origin;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( g_pViewParams->vieworg, suntarget, PM_GLASS_IGNORE, -1, &ptr );
|
||||
|
||||
if( DotProduct( forward, sundir ) >= 0.68f && !pl->frustum.CullSphere( GetVieworg(), 72.0f ) && ptr.fraction == 1.0f )
|
||||
{
|
||||
DrawFlare( forward, sundir, suntarget );
|
||||
}
|
||||
}
|
||||
|
||||
if( CVAR_TO_BOOL( v_sunshafts ))
|
||||
return 1; // don't mixing sunshafts and lensflares because this looks ugly
|
||||
|
||||
if( !tr.fogEnabled )
|
||||
{
|
||||
Vector skyVec = tr.sky_normal;
|
||||
|
||||
if( skyVec == g_vecZero )
|
||||
return 1; // no light_environment on a map
|
||||
|
||||
sundir = -skyVec.Normalize();
|
||||
suntarget = tr.cached_vieworigin + sundir * 32768.0f;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( tr.cached_vieworigin, suntarget, PM_GLASS_IGNORE, -1, &ptr );
|
||||
|
||||
if( DotProduct( forward, sundir ) >= 0.68f && R_SkyIsVisible() && gEngfuncs.PM_PointContents( ptr.endpos, null ) == CONTENTS_SKY )
|
||||
{
|
||||
DrawFlare( forward, sundir, suntarget );
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
187
cl_dll/menu.cpp
Normal file
187
cl_dll/menu.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// menu.cpp
|
||||
//
|
||||
// generic menu handler
|
||||
//
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "parsemsg.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vgui_TeamFortressViewport.h"
|
||||
|
||||
#define MAX_MENU_STRING 512
|
||||
char g_szMenuString[MAX_MENU_STRING];
|
||||
char g_szPrelocalisedMenuString[MAX_MENU_STRING];
|
||||
|
||||
int KB_ConvertString( char *in, char **ppout );
|
||||
|
||||
DECLARE_MESSAGE( m_Menu, ShowMenu );
|
||||
|
||||
int CHudMenu :: Init( void )
|
||||
{
|
||||
gHUD.AddHudElem( this );
|
||||
|
||||
HOOK_MESSAGE( ShowMenu );
|
||||
|
||||
InitHUDData();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CHudMenu :: InitHUDData( void )
|
||||
{
|
||||
m_fMenuDisplayed = 0;
|
||||
m_bitsValidSlots = 0;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void CHudMenu :: Reset( void )
|
||||
{
|
||||
g_szPrelocalisedMenuString[0] = 0;
|
||||
m_fWaitingForMore = FALSE;
|
||||
}
|
||||
|
||||
int CHudMenu :: VidInit( void )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CHudMenu :: Draw( float flTime )
|
||||
{
|
||||
// check for if menu is set to disappear
|
||||
if ( m_flShutoffTime > 0 )
|
||||
{
|
||||
if ( m_flShutoffTime <= gHUD.m_flTime )
|
||||
{ // times up, shutoff
|
||||
m_fMenuDisplayed = 0;
|
||||
m_iFlags &= ~HUD_ACTIVE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// don't draw the menu if the scoreboard is being shown
|
||||
if ( gViewPort && gViewPort->IsScoreBoardVisible() )
|
||||
return 1;
|
||||
|
||||
// draw the menu, along the left-hand side of the screen
|
||||
|
||||
// count the number of newlines
|
||||
int nlc = 0;
|
||||
for ( int i = 0; i < MAX_MENU_STRING && g_szMenuString[i] != '\0'; i++ )
|
||||
{
|
||||
if ( g_szMenuString[i] == '\n' )
|
||||
nlc++;
|
||||
}
|
||||
|
||||
// center it
|
||||
int y = (ScreenHeight/2) - ((nlc/2)*12) - 40; // make sure it is above the say text
|
||||
int x = 20;
|
||||
|
||||
i = 0;
|
||||
while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' )
|
||||
{
|
||||
gHUD.DrawHudString( x, y, 320, g_szMenuString + i, 255, 255, 255 );
|
||||
y += 12;
|
||||
|
||||
while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' && g_szMenuString[i] != '\n' )
|
||||
i++;
|
||||
if ( g_szMenuString[i] == '\n' )
|
||||
i++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// selects an item from the menu
|
||||
void CHudMenu :: SelectMenuItem( int menu_item )
|
||||
{
|
||||
// if menu_item is in a valid slot, send a menuselect command to the server
|
||||
if ( (menu_item > 0) && (m_bitsValidSlots & (1 << (menu_item-1))) )
|
||||
{
|
||||
char szbuf[32];
|
||||
sprintf( szbuf, "menuselect %d\n", menu_item );
|
||||
ClientCmd( szbuf );
|
||||
|
||||
// remove the menu
|
||||
m_fMenuDisplayed = 0;
|
||||
m_iFlags &= ~HUD_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Message handler for ShowMenu message
|
||||
// takes four values:
|
||||
// short: a bitfield of keys that are valid input
|
||||
// char : the duration, in seconds, the menu should stay up. -1 means is stays until something is chosen.
|
||||
// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, FALSE if it's the last string
|
||||
// string: menu string to display
|
||||
// if this message is never received, then scores will simply be the combined totals of the players.
|
||||
int CHudMenu :: MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
char *temp = NULL;
|
||||
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
m_bitsValidSlots = READ_SHORT();
|
||||
int DisplayTime = READ_CHAR();
|
||||
int NeedMore = READ_BYTE();
|
||||
|
||||
if ( DisplayTime > 0 )
|
||||
m_flShutoffTime = DisplayTime + gHUD.m_flTime;
|
||||
else
|
||||
m_flShutoffTime = -1;
|
||||
|
||||
if ( m_bitsValidSlots )
|
||||
{
|
||||
if ( !m_fWaitingForMore ) // this is the start of a new menu
|
||||
{
|
||||
strncpy( g_szPrelocalisedMenuString, READ_STRING(), MAX_MENU_STRING );
|
||||
}
|
||||
else
|
||||
{ // append to the current menu string
|
||||
strncat( g_szPrelocalisedMenuString, READ_STRING(), MAX_MENU_STRING - strlen(g_szPrelocalisedMenuString) );
|
||||
}
|
||||
g_szPrelocalisedMenuString[MAX_MENU_STRING-1] = 0; // ensure null termination (strncat/strncpy does not)
|
||||
|
||||
if ( !NeedMore )
|
||||
{ // we have the whole string, so we can localise it now
|
||||
strcpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString( g_szPrelocalisedMenuString ) );
|
||||
|
||||
// Swap in characters
|
||||
if ( KB_ConvertString( g_szMenuString, &temp ) )
|
||||
{
|
||||
strcpy( g_szMenuString, temp );
|
||||
free( temp );
|
||||
}
|
||||
}
|
||||
|
||||
m_fMenuDisplayed = 1;
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off
|
||||
m_iFlags &= ~HUD_ACTIVE;
|
||||
}
|
||||
|
||||
m_fWaitingForMore = NeedMore;
|
||||
|
||||
return 1;
|
||||
}
|
539
cl_dll/message.cpp
Normal file
539
cl_dll/message.cpp
Normal file
@ -0,0 +1,539 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// Message.cpp
|
||||
//
|
||||
// implementation of CHudMessage class
|
||||
//
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "parsemsg.h"
|
||||
|
||||
void SubtitleMessageAdd( client_textmessage_t *tempMessage ); // buz
|
||||
void ShowTip( client_textmessage_t *tempMessage ); // buz
|
||||
void VGuiAddScreenMessage( client_textmessage_t *msg ); // buz
|
||||
void VGuiAddPickupMessage( client_textmessage_t *msg ); // buz
|
||||
|
||||
// Wargon: Ñêðîëëÿùèéñÿ òåêñò.
|
||||
void VGuiAddScrollingMessage( client_textmessage_t *msg );
|
||||
|
||||
DECLARE_MESSAGE( m_Message, HudText )
|
||||
DECLARE_MESSAGE( m_Message, GameTitle )
|
||||
|
||||
// 1 Global client_textmessage_t for custom messages that aren't in the titles.txt
|
||||
client_textmessage_t g_pCustomMessage;
|
||||
char *g_pCustomName = "Custom";
|
||||
char g_pCustomText[1024];
|
||||
|
||||
int CHudMessage::Init(void)
|
||||
{
|
||||
HOOK_MESSAGE( HudText );
|
||||
HOOK_MESSAGE( GameTitle );
|
||||
|
||||
gHUD.AddHudElem(this);
|
||||
|
||||
Reset();
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
int CHudMessage::VidInit( void )
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
void CHudMessage::Reset( void )
|
||||
{
|
||||
memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages );
|
||||
memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages );
|
||||
|
||||
m_gameTitleTime = 0;
|
||||
m_pGameTitle = NULL;
|
||||
}
|
||||
|
||||
|
||||
float CHudMessage::FadeBlend( float fadein, float fadeout, float hold, float localTime )
|
||||
{
|
||||
float fadeTime = fadein + hold;
|
||||
float fadeBlend;
|
||||
|
||||
if ( localTime < 0 )
|
||||
return 0;
|
||||
|
||||
if ( localTime < fadein )
|
||||
{
|
||||
fadeBlend = 1 - ((fadein - localTime) / fadein);
|
||||
}
|
||||
else if ( localTime > fadeTime )
|
||||
{
|
||||
if ( fadeout > 0 )
|
||||
fadeBlend = 1 - ((localTime - fadeTime) / fadeout);
|
||||
else
|
||||
fadeBlend = 0;
|
||||
}
|
||||
else
|
||||
fadeBlend = 1;
|
||||
|
||||
return fadeBlend;
|
||||
}
|
||||
|
||||
|
||||
int CHudMessage::XPosition( float x, int width, int totalWidth )
|
||||
{
|
||||
int xPos;
|
||||
|
||||
if ( x == -1 )
|
||||
{
|
||||
xPos = (ScreenWidth - width) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( x < 0 )
|
||||
xPos = (1.0 + x) * ScreenWidth - totalWidth; // Alight right
|
||||
else
|
||||
xPos = x * ScreenWidth;
|
||||
}
|
||||
|
||||
if ( xPos + width > ScreenWidth )
|
||||
xPos = ScreenWidth - width;
|
||||
else if ( xPos < 0 )
|
||||
xPos = 0;
|
||||
|
||||
return xPos;
|
||||
}
|
||||
|
||||
|
||||
int CHudMessage::YPosition( float y, int height )
|
||||
{
|
||||
int yPos;
|
||||
|
||||
if ( y == -1 ) // Centered?
|
||||
yPos = (ScreenHeight - height) * 0.5;
|
||||
else
|
||||
{
|
||||
// Alight bottom?
|
||||
if ( y < 0 )
|
||||
yPos = (1.0 + y) * ScreenHeight - height; // Alight bottom
|
||||
else // align top
|
||||
yPos = y * ScreenHeight;
|
||||
}
|
||||
|
||||
if ( yPos + height > ScreenHeight )
|
||||
yPos = ScreenHeight - height;
|
||||
else if ( yPos < 0 )
|
||||
yPos = 0;
|
||||
|
||||
return yPos;
|
||||
}
|
||||
|
||||
|
||||
void CHudMessage::MessageScanNextChar( void )
|
||||
{
|
||||
int srcRed, srcGreen, srcBlue, destRed, destGreen, destBlue;
|
||||
int blend;
|
||||
|
||||
srcRed = m_parms.pMessage->r1;
|
||||
srcGreen = m_parms.pMessage->g1;
|
||||
srcBlue = m_parms.pMessage->b1;
|
||||
blend = 0; // Pure source
|
||||
|
||||
switch( m_parms.pMessage->effect )
|
||||
{
|
||||
// Fade-in / Fade-out
|
||||
case 0:
|
||||
case 1:
|
||||
destRed = destGreen = destBlue = 0;
|
||||
blend = m_parms.fadeBlend;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_parms.charTime += m_parms.pMessage->fadein;
|
||||
if ( m_parms.charTime > m_parms.time )
|
||||
{
|
||||
srcRed = srcGreen = srcBlue = 0;
|
||||
blend = 0; // pure source
|
||||
}
|
||||
else
|
||||
{
|
||||
float deltaTime = m_parms.time - m_parms.charTime;
|
||||
|
||||
destRed = destGreen = destBlue = 0;
|
||||
if ( m_parms.time > m_parms.fadeTime )
|
||||
{
|
||||
blend = m_parms.fadeBlend;
|
||||
}
|
||||
else if ( deltaTime > m_parms.pMessage->fxtime )
|
||||
blend = 0; // pure dest
|
||||
else
|
||||
{
|
||||
destRed = m_parms.pMessage->r2;
|
||||
destGreen = m_parms.pMessage->g2;
|
||||
destBlue = m_parms.pMessage->b2;
|
||||
blend = 255 - (deltaTime * (1.0/m_parms.pMessage->fxtime) * 255.0 + 0.5);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( blend > 255 )
|
||||
blend = 255;
|
||||
else if ( blend < 0 )
|
||||
blend = 0;
|
||||
|
||||
m_parms.r = ((srcRed * (255-blend)) + (destRed * blend)) >> 8;
|
||||
m_parms.g = ((srcGreen * (255-blend)) + (destGreen * blend)) >> 8;
|
||||
m_parms.b = ((srcBlue * (255-blend)) + (destBlue * blend)) >> 8;
|
||||
|
||||
if ( m_parms.pMessage->effect == 1 && m_parms.charTime != 0 )
|
||||
{
|
||||
if ( m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]) <= ScreenWidth )
|
||||
TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CHudMessage::MessageScanStart( void )
|
||||
{
|
||||
switch( m_parms.pMessage->effect )
|
||||
{
|
||||
// Fade-in / out with flicker
|
||||
case 1:
|
||||
case 0:
|
||||
m_parms.fadeTime = m_parms.pMessage->fadein + m_parms.pMessage->holdtime;
|
||||
|
||||
|
||||
if ( m_parms.time < m_parms.pMessage->fadein )
|
||||
{
|
||||
m_parms.fadeBlend = ((m_parms.pMessage->fadein - m_parms.time) * (1.0/m_parms.pMessage->fadein) * 255);
|
||||
}
|
||||
else if ( m_parms.time > m_parms.fadeTime )
|
||||
{
|
||||
if ( m_parms.pMessage->fadeout > 0 )
|
||||
m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
|
||||
else
|
||||
m_parms.fadeBlend = 255; // Pure dest (off)
|
||||
}
|
||||
else
|
||||
m_parms.fadeBlend = 0; // Pure source (on)
|
||||
m_parms.charTime = 0;
|
||||
|
||||
if ( m_parms.pMessage->effect == 1 && (rand()%100) < 10 )
|
||||
m_parms.charTime = 1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_parms.fadeTime = (m_parms.pMessage->fadein * m_parms.length) + m_parms.pMessage->holdtime;
|
||||
|
||||
if ( m_parms.time > m_parms.fadeTime && m_parms.pMessage->fadeout > 0 )
|
||||
m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255);
|
||||
else
|
||||
m_parms.fadeBlend = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time )
|
||||
{
|
||||
int i, j, length, width;
|
||||
const char *pText;
|
||||
unsigned char line[80];
|
||||
|
||||
pText = pMessage->pMessage;
|
||||
// Count lines
|
||||
m_parms.lines = 1;
|
||||
m_parms.time = time;
|
||||
m_parms.pMessage = pMessage;
|
||||
length = 0;
|
||||
width = 0;
|
||||
m_parms.totalWidth = 0;
|
||||
while ( *pText )
|
||||
{
|
||||
if ( *pText == '\n' )
|
||||
{
|
||||
m_parms.lines++;
|
||||
if ( width > m_parms.totalWidth )
|
||||
m_parms.totalWidth = width;
|
||||
width = 0;
|
||||
}
|
||||
else
|
||||
width += gHUD.m_scrinfo.charWidths[*pText];
|
||||
pText++;
|
||||
length++;
|
||||
}
|
||||
m_parms.length = length;
|
||||
m_parms.totalHeight = (m_parms.lines * gHUD.m_scrinfo.iCharHeight);
|
||||
|
||||
|
||||
m_parms.y = YPosition( pMessage->y, m_parms.totalHeight );
|
||||
pText = pMessage->pMessage;
|
||||
|
||||
m_parms.charTime = 0;
|
||||
|
||||
MessageScanStart();
|
||||
|
||||
for ( i = 0; i < m_parms.lines; i++ )
|
||||
{
|
||||
m_parms.lineLength = 0;
|
||||
m_parms.width = 0;
|
||||
while ( *pText && *pText != '\n' )
|
||||
{
|
||||
unsigned char c = *pText;
|
||||
line[m_parms.lineLength] = c;
|
||||
m_parms.width += gHUD.m_scrinfo.charWidths[c];
|
||||
m_parms.lineLength++;
|
||||
pText++;
|
||||
}
|
||||
pText++; // Skip LF
|
||||
line[m_parms.lineLength] = 0;
|
||||
|
||||
m_parms.x = XPosition( pMessage->x, m_parms.width, m_parms.totalWidth );
|
||||
|
||||
for ( j = 0; j < m_parms.lineLength; j++ )
|
||||
{
|
||||
m_parms.text = line[j];
|
||||
int next = m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ];
|
||||
MessageScanNextChar();
|
||||
|
||||
if ( m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth )
|
||||
TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b );
|
||||
m_parms.x = next;
|
||||
}
|
||||
|
||||
m_parms.y += gHUD.m_scrinfo.iCharHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CHudMessage::Draw( float fTime )
|
||||
{
|
||||
int i, drawn;
|
||||
client_textmessage_t *pMessage;
|
||||
float endTime;
|
||||
|
||||
drawn = 0;
|
||||
|
||||
// Fixup level transitions
|
||||
for ( i = 0; i < maxHUDMessages; i++ )
|
||||
{
|
||||
// Assume m_parms.time contains last time
|
||||
if ( m_pMessages[i] )
|
||||
{
|
||||
pMessage = m_pMessages[i];
|
||||
if ( m_startTime[i] > gHUD.m_flTime )
|
||||
m_startTime[i] = gHUD.m_flTime + m_parms.time - m_startTime[i] + 0.2; // Server takes 0.2 seconds to spawn, adjust for this
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < maxHUDMessages; i++ )
|
||||
{
|
||||
if ( m_pMessages[i] )
|
||||
{
|
||||
pMessage = m_pMessages[i];
|
||||
|
||||
// This is when the message is over
|
||||
switch( pMessage->effect )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
endTime = m_startTime[i] + pMessage->fadein + pMessage->fadeout + pMessage->holdtime;
|
||||
break;
|
||||
|
||||
// Fade in is per character in scanning messages
|
||||
case 2:
|
||||
endTime = m_startTime[i] + (pMessage->fadein * strlen( pMessage->pMessage )) + pMessage->fadeout + pMessage->holdtime;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( fTime <= endTime )
|
||||
{
|
||||
float messageTime = fTime - m_startTime[i];
|
||||
|
||||
// Draw the message
|
||||
// effect 0 is fade in/fade out
|
||||
// effect 1 is flickery credits
|
||||
// effect 2 is write out (training room)
|
||||
MessageDrawScan( pMessage, messageTime );
|
||||
|
||||
drawn++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The message is over
|
||||
m_pMessages[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the time -- to fix up level transitions
|
||||
m_parms.time = gHUD.m_flTime;
|
||||
// Don't call until we get another message
|
||||
if ( !drawn )
|
||||
m_iFlags &= ~HUD_ACTIVE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CHudMessage::MessageAdd( const char *pName, float time )
|
||||
{
|
||||
int i,j;
|
||||
client_textmessage_t *tempMessage;
|
||||
|
||||
for ( i = 0; i < maxHUDMessages; i++ )
|
||||
{
|
||||
if ( !m_pMessages[i] )
|
||||
{
|
||||
// Trim off a leading # if it's there
|
||||
if ( pName[0] == '#' )
|
||||
pName++;
|
||||
|
||||
tempMessage = TextMessageGet( pName );
|
||||
|
||||
// If we couldnt find it in the titles.txt, just create it
|
||||
if ( !tempMessage )
|
||||
{
|
||||
// buz: !-messages are only sentences.txt
|
||||
if (pName[0] == '!')
|
||||
return;
|
||||
|
||||
g_pCustomMessage.effect = 2;
|
||||
g_pCustomMessage.r1 = g_pCustomMessage.g1 = g_pCustomMessage.b1 = g_pCustomMessage.a1 = 100;
|
||||
g_pCustomMessage.r2 = 240;
|
||||
g_pCustomMessage.g2 = 110;
|
||||
g_pCustomMessage.b2 = 0;
|
||||
g_pCustomMessage.a2 = 0;
|
||||
g_pCustomMessage.x = -1; // Centered
|
||||
g_pCustomMessage.y = 0.7;
|
||||
g_pCustomMessage.fadein = 0.01;
|
||||
g_pCustomMessage.fadeout = 1.5;
|
||||
g_pCustomMessage.fxtime = 0.25;
|
||||
g_pCustomMessage.holdtime = 5;
|
||||
g_pCustomMessage.pName = g_pCustomName;
|
||||
strcpy( g_pCustomText, pName );
|
||||
g_pCustomMessage.pMessage = g_pCustomText;
|
||||
|
||||
tempMessage = &g_pCustomMessage;
|
||||
}
|
||||
else if (tempMessage->effect == 3) // buz: link into subtitle system
|
||||
{
|
||||
SubtitleMessageAdd( tempMessage );
|
||||
return;
|
||||
}
|
||||
else if (tempMessage->effect == 4) // buz: link into vgui screen messages system
|
||||
{
|
||||
VGuiAddScreenMessage( tempMessage );
|
||||
return;
|
||||
}
|
||||
else if (tempMessage->effect == 5) // buz: link into vgui pickup messages system
|
||||
{
|
||||
VGuiAddPickupMessage( tempMessage );
|
||||
return;
|
||||
}
|
||||
else if (tempMessage->effect == 6) // Wargon: Ñêðîëëÿùèéñÿ òåêñò.
|
||||
{
|
||||
VGuiAddScrollingMessage( tempMessage );
|
||||
return;
|
||||
}
|
||||
else if (tempMessage->effect >= 20 && tempMessage->effect < 30) // buz: link into tips system
|
||||
{
|
||||
ShowTip( tempMessage );
|
||||
return;
|
||||
}
|
||||
|
||||
for ( j = 0; j < maxHUDMessages; j++ )
|
||||
{
|
||||
if ( m_pMessages[j] )
|
||||
{
|
||||
// is this message already in the list
|
||||
if ( !strcmp( tempMessage->pMessage, m_pMessages[j]->pMessage ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get rid of any other messages in same location (only one displays at a time)
|
||||
if ( fabs( tempMessage->y - m_pMessages[j]->y ) < 0.0001 )
|
||||
{
|
||||
if ( fabs( tempMessage->x - m_pMessages[j]->x ) < 0.0001 )
|
||||
{
|
||||
m_pMessages[j] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_pMessages[i] = tempMessage;
|
||||
m_startTime[i] = time;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
BEGIN_READ( pbuf, iSize );
|
||||
|
||||
char *pString = READ_STRING();
|
||||
|
||||
MessageAdd( pString, gHUD.m_flTime );
|
||||
// Remember the time -- to fix up level transitions
|
||||
m_parms.time = gHUD.m_flTime;
|
||||
|
||||
// Turn on drawing
|
||||
if ( !(m_iFlags & HUD_ACTIVE) )
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int CHudMessage::MsgFunc_GameTitle( const char *pszName, int iSize, void *pbuf )
|
||||
{
|
||||
m_pGameTitle = TextMessageGet( "GAMETITLE" );
|
||||
if ( m_pGameTitle != NULL )
|
||||
{
|
||||
m_gameTitleTime = gHUD.m_flTime;
|
||||
|
||||
// Turn on drawing
|
||||
if ( !(m_iFlags & HUD_ACTIVE) )
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CHudMessage::MessageAdd(client_textmessage_t * newMessage )
|
||||
{
|
||||
m_parms.time = gHUD.m_flTime;
|
||||
|
||||
// Turn on drawing
|
||||
if ( !(m_iFlags & HUD_ACTIVE) )
|
||||
m_iFlags |= HUD_ACTIVE;
|
||||
|
||||
for ( int i = 0; i < maxHUDMessages; i++ )
|
||||
{
|
||||
if ( !m_pMessages[i] )
|
||||
{
|
||||
m_pMessages[i] = newMessage;
|
||||
m_startTime[i] = gHUD.m_flTime;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
31
cl_dll/overview.h
Normal file
31
cl_dll/overview.h
Normal file
@ -0,0 +1,31 @@
|
||||
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OVERVIEW_H
|
||||
#define OVERVIEW_H
|
||||
#pragma once
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles the drawing of the top-down map and all the things on it
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHudOverview : public CHudBase
|
||||
{
|
||||
public:
|
||||
int Init();
|
||||
int VidInit();
|
||||
|
||||
int Draw(float flTime);
|
||||
void InitHUDData( void );
|
||||
|
||||
private:
|
||||
HSPRITE m_hsprPlayer;
|
||||
HSPRITE m_hsprViewcone;
|
||||
};
|
||||
|
||||
|
||||
#endif // OVERVIEW_H
|
178
cl_dll/parsemsg.cpp
Normal file
178
cl_dll/parsemsg.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// parsemsg.cpp
|
||||
//
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "gl_local.h"
|
||||
|
||||
typedef unsigned char byte;
|
||||
#define true 1
|
||||
|
||||
static byte *gpBuf;
|
||||
static int giSize;
|
||||
static int giRead;
|
||||
static int giBadRead;
|
||||
|
||||
void BEGIN_READ( void *buf, int size )
|
||||
{
|
||||
giRead = 0;
|
||||
giBadRead = 0;
|
||||
giSize = size;
|
||||
gpBuf = (byte*)buf;
|
||||
}
|
||||
|
||||
|
||||
int READ_CHAR( void )
|
||||
{
|
||||
int c;
|
||||
|
||||
if (giRead + 1 > giSize)
|
||||
{
|
||||
giBadRead = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = (signed char)gpBuf[giRead];
|
||||
giRead++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int READ_BYTE( void )
|
||||
{
|
||||
int c;
|
||||
|
||||
if (giRead+1 > giSize)
|
||||
{
|
||||
giBadRead = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = (unsigned char)gpBuf[giRead];
|
||||
giRead++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int READ_SHORT( void )
|
||||
{
|
||||
int c;
|
||||
|
||||
if (giRead+2 > giSize)
|
||||
{
|
||||
giBadRead = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = (short)( gpBuf[giRead] + ( gpBuf[giRead+1] << 8 ) );
|
||||
|
||||
giRead += 2;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int READ_WORD( void )
|
||||
{
|
||||
return READ_SHORT();
|
||||
}
|
||||
|
||||
|
||||
int READ_LONG( void )
|
||||
{
|
||||
int c;
|
||||
|
||||
if (giRead+4 > giSize)
|
||||
{
|
||||
giBadRead = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = gpBuf[giRead] + (gpBuf[giRead + 1] << 8) + (gpBuf[giRead + 2] << 16) + (gpBuf[giRead + 3] << 24);
|
||||
|
||||
giRead += 4;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
float READ_FLOAT( void )
|
||||
{
|
||||
union
|
||||
{
|
||||
byte b[4];
|
||||
float f;
|
||||
int l;
|
||||
} dat;
|
||||
|
||||
dat.b[0] = gpBuf[giRead];
|
||||
dat.b[1] = gpBuf[giRead+1];
|
||||
dat.b[2] = gpBuf[giRead+2];
|
||||
dat.b[3] = gpBuf[giRead+3];
|
||||
giRead += 4;
|
||||
|
||||
// dat.l = LittleLong (dat.l);
|
||||
|
||||
return dat.f;
|
||||
}
|
||||
|
||||
char* READ_STRING( void )
|
||||
{
|
||||
static char string[2048];
|
||||
int l,c;
|
||||
|
||||
string[0] = 0;
|
||||
|
||||
l = 0;
|
||||
do
|
||||
{
|
||||
if ( giRead+1 > giSize )
|
||||
break; // no more characters
|
||||
|
||||
c = READ_CHAR();
|
||||
if (c == 0) break;
|
||||
string[l] = c;
|
||||
l++;
|
||||
} while (l < sizeof(string)-1);
|
||||
|
||||
string[l] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
float READ_COORD( void )
|
||||
{
|
||||
// g-cont. we loose precision here but keep old size of coord variable!
|
||||
if( g_fRenderInitialized && RENDER_GET_PARM( PARM_FEATURES, 0 ) & ENGINE_WRITE_LARGE_COORD )
|
||||
return (float)(READ_SHORT() * 1.0f);
|
||||
return (float)(READ_SHORT() * (1.0f / 8.0f));
|
||||
}
|
||||
|
||||
float READ_ANGLE( void )
|
||||
{
|
||||
return (float)(READ_CHAR() * (360.0/256));
|
||||
}
|
||||
|
||||
float READ_HIRESANGLE( void )
|
||||
{
|
||||
return (float)(READ_SHORT() * (360.0/65536));
|
||||
}
|
||||
|
||||
BOOL REMAIN_BYTES( void )
|
||||
{
|
||||
return giRead < giSize;
|
||||
}
|
38
cl_dll/parsemsg.h
Normal file
38
cl_dll/parsemsg.h
Normal file
@ -0,0 +1,38 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// parsemsg.h
|
||||
//
|
||||
|
||||
void BEGIN_READ( void *buf, int size );
|
||||
int READ_CHAR( void );
|
||||
int READ_BYTE( void );
|
||||
int READ_SHORT( void );
|
||||
int READ_WORD( void );
|
||||
int READ_LONG( void );
|
||||
float READ_FLOAT( void );
|
||||
char* READ_STRING( void );
|
||||
float READ_COORD( void );
|
||||
float READ_ANGLE( void );
|
||||
float READ_HIRESANGLE( void );
|
||||
BOOL REMAIN_BYTES( void );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
88
cl_dll/render/cl_dlight.h
Normal file
88
cl_dll/render/cl_dlight.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
cl_dlight.h - dynamic lighting description
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef CL_DLIGHT_H
|
||||
#define CL_DLIGHT_H
|
||||
|
||||
#define NUM_SHADOW_SPLITS 3 // four splits
|
||||
#define MAX_SHADOWMAPS (NUM_SHADOW_SPLITS + 1)
|
||||
|
||||
// dlight flags
|
||||
#define DLF_NOSHADOWS BIT( 0 )
|
||||
#define DLF_NOBUMP BIT( 1 )
|
||||
#define DLF_LENSFLARE BIT( 2 )
|
||||
#define DLF_CULLED BIT( 3 ) // light culled by scissor
|
||||
#define DLF_ASPECT3X4 BIT( 4 )
|
||||
#define DLF_ASPECT4X3 BIT( 5 )
|
||||
#define DLF_FLIPTEXTURE BIT( 6 )
|
||||
|
||||
class CDynLight
|
||||
{
|
||||
public:
|
||||
Vector origin;
|
||||
Vector angles;
|
||||
float radius;
|
||||
Vector color; // ignored for spotlights, they have a texture
|
||||
float die; // stop lighting after this time
|
||||
float decay; // drop this each second
|
||||
int key;
|
||||
int type; // light type
|
||||
bool update; // light needs update
|
||||
|
||||
matrix4x4 viewMatrix;
|
||||
matrix4x4 projectionMatrix; // light projection matrix
|
||||
matrix4x4 modelviewMatrix; // light modelview
|
||||
matrix4x4 lightviewProjMatrix; // lightview projection
|
||||
matrix4x4 textureMatrix[MAX_SHADOWMAPS]; // result texture matrix
|
||||
matrix4x4 shadowMatrix[MAX_SHADOWMAPS]; // result texture matrix
|
||||
GLfloat gl_shadowMatrix[MAX_SHADOWMAPS][16]; // cached matrices
|
||||
|
||||
Vector mins, maxs; // local bounds
|
||||
Vector absmin, absmax; // world bounds
|
||||
CFrustum frustum; // normal frustum
|
||||
CFrustum splitFrustum[MAX_SHADOWMAPS];
|
||||
|
||||
// scissor data
|
||||
float x, y, w, h;
|
||||
|
||||
// spotlight specific:
|
||||
int spotlightTexture; // spotlights only
|
||||
int shadowTexture[MAX_SHADOWMAPS]; // shadowmap for this light
|
||||
int cinTexturenum; // not gltexturenum!
|
||||
int lastframe; // cinematic lastframe
|
||||
int flags;
|
||||
float fov;
|
||||
|
||||
bool Expired( void )
|
||||
{
|
||||
if( die < GET_CLIENT_TIME( ))
|
||||
return true;
|
||||
if( radius <= 0.0f )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Active( void )
|
||||
{
|
||||
if( Expired( ))
|
||||
return false;
|
||||
if( FBitSet( flags, DLF_CULLED ))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif//CL_DLIGHT_H
|
1170
cl_dll/render/gl_aurora.cpp
Normal file
1170
cl_dll/render/gl_aurora.cpp
Normal file
File diff suppressed because it is too large
Load Diff
211
cl_dll/render/gl_aurora.h
Normal file
211
cl_dll/render/gl_aurora.h
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
r_particle.h - Laurie Cheers Aurora Particle System
|
||||
First implementation of 02/08/02 November235
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef GL_PARTICLE_H
|
||||
#define GL_PARTICLE_H
|
||||
|
||||
class CParticleType;
|
||||
class CParticleSystem;
|
||||
|
||||
#include "randomrange.h"
|
||||
|
||||
struct CParticle
|
||||
{
|
||||
CParticle *nextpart;
|
||||
CParticle *m_pOverlay; // for making multi-layered particles
|
||||
CParticleType *pType;
|
||||
|
||||
Vector origin;
|
||||
Vector velocity;
|
||||
Vector accel;
|
||||
Vector m_vecWind;
|
||||
|
||||
cl_entity_t *m_pEntity; // if not null, this particle is tied to the given entity
|
||||
|
||||
float m_fRed;
|
||||
float m_fGreen;
|
||||
float m_fBlue;
|
||||
float m_fRedStep;
|
||||
float m_fGreenStep;
|
||||
float m_fBlueStep;
|
||||
|
||||
float m_fAlpha;
|
||||
float m_fAlphaStep;
|
||||
|
||||
float frame;
|
||||
float m_fFrameStep;
|
||||
|
||||
float m_fAngle;
|
||||
float m_fAngleStep;
|
||||
|
||||
float m_fSize;
|
||||
float m_fSizeStep;
|
||||
|
||||
float m_fDrag;
|
||||
|
||||
float age;
|
||||
float age_death;
|
||||
float age_spray;
|
||||
};
|
||||
|
||||
class CParticleType
|
||||
{
|
||||
public:
|
||||
CParticleType( CParticleType *pNext = NULL );
|
||||
|
||||
// here is a particle system. Add a (set of) particles according to this type, and initialise their values.
|
||||
CParticle *CreateParticle( CParticleSystem *pSys );
|
||||
|
||||
// initialise this particle. Does not define velocity or age.
|
||||
void InitParticle( CParticle *pPart, CParticleSystem *pSys );
|
||||
|
||||
bool m_bIsDefined; // is this CParticleType just a placeholder?
|
||||
|
||||
int m_iRenderMode;
|
||||
int m_iDrawCond;
|
||||
RandomRange m_Bounce;
|
||||
RandomRange m_BounceFriction;
|
||||
bool m_bBouncing;
|
||||
|
||||
RandomRange m_Life;
|
||||
|
||||
RandomRange m_StartAlpha;
|
||||
RandomRange m_EndAlpha;
|
||||
RandomRange m_StartRed;
|
||||
RandomRange m_EndRed;
|
||||
RandomRange m_StartGreen;
|
||||
RandomRange m_EndGreen;
|
||||
RandomRange m_StartBlue;
|
||||
RandomRange m_EndBlue;
|
||||
|
||||
RandomRange m_StartSize;
|
||||
RandomRange m_SizeDelta;
|
||||
RandomRange m_EndSize;
|
||||
|
||||
RandomRange m_StartFrame;
|
||||
RandomRange m_EndFrame;
|
||||
RandomRange m_FrameRate; // incompatible with EndFrame
|
||||
bool m_bEndFrame;
|
||||
|
||||
RandomRange m_StartAngle;
|
||||
RandomRange m_AngleDelta;
|
||||
|
||||
RandomRange m_SprayRate;
|
||||
RandomRange m_SprayForce;
|
||||
RandomRange m_SprayPitch;
|
||||
RandomRange m_SprayYaw;
|
||||
RandomRange m_SprayRoll;
|
||||
|
||||
CParticleType *m_pSprayType;
|
||||
|
||||
RandomRange m_Gravity;
|
||||
RandomRange m_WindStrength;
|
||||
RandomRange m_WindYaw;
|
||||
|
||||
HSPRITE m_hSprite;
|
||||
CParticleType *m_pOverlayType;
|
||||
|
||||
RandomRange m_Drag;
|
||||
|
||||
CParticleType *m_pNext;
|
||||
char m_szName[32];
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AURORA_REMOVE = 0,
|
||||
AURORA_INVISIBLE,
|
||||
AURORA_DRAW,
|
||||
} AURSTATE;
|
||||
|
||||
class CParticleSystem
|
||||
{
|
||||
public:
|
||||
CParticleSystem( cl_entity_t *ent, const char *szFilename, int attachment = 0, float lifetime = 0.0f );
|
||||
~CParticleSystem( void );
|
||||
|
||||
void AllocateParticles( int iParticles );
|
||||
void CalculateDistance( void );
|
||||
CParticleType *GetType( const char *szName );
|
||||
CParticleType *AddPlaceholderType( const char *szName );
|
||||
CParticleType *ParseType( char *&szFile );
|
||||
|
||||
cl_entity_t *GetEntity() { return m_pEntity; }
|
||||
|
||||
// General functions
|
||||
AURSTATE UpdateSystem( float frametime ); // If this function returns false, the manager deletes the system
|
||||
void DrawSystem( void );
|
||||
CParticle *ActivateParticle( void ); // adds one of the free particles to the active list, and returns it for initialisation.
|
||||
// MUST CHECK WHETHER THIS RESULT IS NULL!
|
||||
// returns false if the particle has died
|
||||
bool UpdateParticle( CParticle *part, float frametime );
|
||||
void DrawParticle( CParticle *part, Vector &right, Vector &up );
|
||||
|
||||
// Utility functions that have to be public
|
||||
bool ParticleIsVisible( CParticle* part );
|
||||
|
||||
void MarkForDeletion( void );
|
||||
|
||||
static float CosLookup( int angle ) { return angle < 0 ? c_fCosTable[angle+360] : c_fCosTable[angle]; }
|
||||
static float SinLookup( int angle ) { return angle < -90 ? c_fCosTable[angle+450] : c_fCosTable[angle+90]; }
|
||||
|
||||
// Pointer to next system for linked list structure
|
||||
CParticleSystem *m_pNextSystem;
|
||||
|
||||
CParticle *m_pActiveParticle;
|
||||
float m_fViewerDist;
|
||||
cl_entity_t *m_pEntity;
|
||||
int m_iEntAttachment;
|
||||
int m_iKillCondition;
|
||||
int m_iLightingModel;
|
||||
matrix3x3 entityMatrix;
|
||||
int m_fHasProjectionLighting;
|
||||
float m_fLifeTime; // for auto-removed particles
|
||||
bool enable;
|
||||
|
||||
private:
|
||||
static float c_fCosTable[360 + 90];
|
||||
static bool c_bCosTableInit;
|
||||
|
||||
// the block of allocated particles
|
||||
CParticle *m_pAllParticles;
|
||||
|
||||
// First particles in the linked list for the active particles and the dead particles
|
||||
CParticle *m_pFreeParticle;
|
||||
CParticle *m_pMainParticle; // the "source" particle.
|
||||
|
||||
CParticleType *m_pFirstType;
|
||||
CParticleType *m_pMainType;
|
||||
};
|
||||
|
||||
class CParticleSystemManager
|
||||
{
|
||||
public:
|
||||
CParticleSystemManager( void );
|
||||
~CParticleSystemManager( void );
|
||||
void AddSystem( CParticleSystem* );
|
||||
CParticleSystem *FindSystem( CParticleSystem *pFirstSystem, cl_entity_t *pEntity );
|
||||
void MarkSystemForDeletion( CParticleSystem *pSys );
|
||||
void UpdateSystems( void );
|
||||
void ClearSystems( void );
|
||||
void SortSystems( void );
|
||||
private:
|
||||
CParticleSystem *m_pFirstSystem;
|
||||
};
|
||||
|
||||
extern CParticleSystemManager g_pParticleSystems; // buz
|
||||
|
||||
#endif//GL_PARTICLE_H
|
1055
cl_dll/render/gl_backend.cpp
Normal file
1055
cl_dll/render/gl_backend.cpp
Normal file
File diff suppressed because it is too large
Load Diff
228
cl_dll/render/gl_cubemaps.cpp
Normal file
228
cl_dll/render/gl_cubemaps.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
gl_cubemaps.cpp - tools for cubemaps search & handling
|
||||
Copyright (C) 2016 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "ref_params.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_decals.h"
|
||||
#include <mathlib.h>
|
||||
#include "gl_world.h"
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FindNearestCubeMap
|
||||
|
||||
find the nearest cubemap for a given point
|
||||
=================
|
||||
*/
|
||||
void CL_FindNearestCubeMap( const Vector &pos, mcubemap_t **result )
|
||||
{
|
||||
if( !result ) return;
|
||||
|
||||
float maxDist = 99999.0f;
|
||||
*result = NULL;
|
||||
|
||||
for( int i = 0; i < world->num_cubemaps; i++ )
|
||||
{
|
||||
mcubemap_t *check = &world->cubemaps[i];
|
||||
float dist = VectorDistance( check->origin, pos );
|
||||
|
||||
if( dist < maxDist )
|
||||
{
|
||||
*result = check;
|
||||
maxDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if( !*result )
|
||||
{
|
||||
// this may happens if map
|
||||
// doesn't have any cubemaps
|
||||
*result = &world->defaultCubemap;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FindNearestCubeMapForSurface
|
||||
|
||||
find the nearest cubemap on front of plane
|
||||
=================
|
||||
*/
|
||||
void CL_FindNearestCubeMapForSurface( const Vector &pos, const msurface_t *surf, mcubemap_t **result )
|
||||
{
|
||||
if( !result ) return;
|
||||
|
||||
float maxDist = 99999.0f;
|
||||
mplane_t plane;
|
||||
*result = NULL;
|
||||
|
||||
plane = *surf->plane;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
{
|
||||
plane.normal = -plane.normal;
|
||||
plane.dist = -plane.dist;
|
||||
}
|
||||
|
||||
for( int i = 0; i < world->num_cubemaps; i++ )
|
||||
{
|
||||
mcubemap_t *check = &world->cubemaps[i];
|
||||
float dist = VectorDistance( check->origin, pos );
|
||||
|
||||
if( dist < maxDist && PlaneDiff( check->origin, &plane ) >= 0.0f )
|
||||
{
|
||||
*result = check;
|
||||
maxDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if( *result ) return;
|
||||
|
||||
// fallback to default method
|
||||
CL_FindNearestCubeMap( pos, result );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FindTwoNearestCubeMap
|
||||
|
||||
find the two nearest cubemaps for a given point
|
||||
=================
|
||||
*/
|
||||
void CL_FindTwoNearestCubeMap( const Vector &pos, mcubemap_t **result1, mcubemap_t **result2 )
|
||||
{
|
||||
if( !result1 || !result2 )
|
||||
return;
|
||||
|
||||
float maxDist1 = 99999.0f;
|
||||
float maxDist2 = 99999.0f;
|
||||
*result1 = *result2 = NULL;
|
||||
|
||||
for( int i = 0; i < world->num_cubemaps; i++ )
|
||||
{
|
||||
mcubemap_t *check = &world->cubemaps[i];
|
||||
float dist = VectorDistance( check->origin, pos );
|
||||
|
||||
if( dist < maxDist1 )
|
||||
{
|
||||
*result1 = check;
|
||||
maxDist1 = dist;
|
||||
}
|
||||
else if( dist < maxDist2 && dist > maxDist1 )
|
||||
{
|
||||
*result2 = check;
|
||||
maxDist2 = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if( !*result1 )
|
||||
{
|
||||
// this may happens if map
|
||||
// doesn't have any cubemaps
|
||||
*result1 = &world->defaultCubemap;
|
||||
}
|
||||
|
||||
if( !*result2 )
|
||||
{
|
||||
// this may happens if map
|
||||
// doesn't have any cubemaps
|
||||
*result2 = *result1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FindTwoNearestCubeMapForSurface
|
||||
|
||||
find the two nearest cubemaps on front of plane
|
||||
=================
|
||||
*/
|
||||
void CL_FindTwoNearestCubeMapForSurface( const Vector &pos, const msurface_t *surf, mcubemap_t **result1, mcubemap_t **result2 )
|
||||
{
|
||||
if( !result1 || !result2 ) return;
|
||||
|
||||
float maxDist1 = 99999.0f;
|
||||
float maxDist2 = 99999.0f;
|
||||
mplane_t plane;
|
||||
*result1 = NULL;
|
||||
*result2 = NULL;
|
||||
|
||||
plane = *surf->plane;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
{
|
||||
plane.normal = -plane.normal;
|
||||
plane.dist = -plane.dist;
|
||||
}
|
||||
|
||||
for( int i = 0; i < world->num_cubemaps; i++ )
|
||||
{
|
||||
mcubemap_t *check = &world->cubemaps[i];
|
||||
float dist = VectorDistance( check->origin, pos );
|
||||
|
||||
if( dist < maxDist1 && PlaneDiff( check->origin, &plane ) >= 0.0f )
|
||||
{
|
||||
*result1 = check;
|
||||
maxDist1 = dist;
|
||||
}
|
||||
else if( dist < maxDist2 && dist > maxDist1 )
|
||||
{
|
||||
*result2 = check;
|
||||
maxDist2 = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if( *result1 )
|
||||
{
|
||||
if( !*result2 )
|
||||
*result2 = *result1;
|
||||
return;
|
||||
}
|
||||
|
||||
// fallback to default method
|
||||
CL_FindTwoNearestCubeMap( pos, result1, result2 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_BuildCubemaps_f
|
||||
|
||||
force to rebuilds all the cubemaps
|
||||
in the scene
|
||||
=================
|
||||
*/
|
||||
void CL_BuildCubemaps_f( void )
|
||||
{
|
||||
mcubemap_t *m = &world->defaultCubemap;
|
||||
FREE_TEXTURE( m->texture );
|
||||
m->valid = m->texture = false;
|
||||
|
||||
for( int i = 0; i < world->num_cubemaps; i++ )
|
||||
{
|
||||
mcubemap_t *m = &world->cubemaps[i];
|
||||
FREE_TEXTURE( m->texture );
|
||||
m->valid = m->texture = false;
|
||||
}
|
||||
|
||||
if( FBitSet( world->features, WORLD_HAS_SKYBOX ))
|
||||
world->build_default_cubemap = true;
|
||||
|
||||
world->rebuilding_cubemaps = CMREBUILD_CHECKING;
|
||||
world->loading_cubemaps = true;
|
||||
}
|
253
cl_dll/render/gl_cull.cpp
Normal file
253
cl_dll/render/gl_cull.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
gl_cull.cpp - render culling 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
#include "entity_types.h"
|
||||
#include "mathlib.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CullModel
|
||||
=============
|
||||
*/
|
||||
bool R_CullModel( cl_entity_t *e, const Vector &absmin, const Vector &absmax )
|
||||
{
|
||||
if( e == GET_VIEWMODEL( ) || e == gHUD.m_pHeadShieldEnt )
|
||||
{
|
||||
if( RI->params & RP_NONVIEWERREF )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// don't reflect this entity in mirrors
|
||||
if( FBitSet( e->curstate.effects, EF_NOREFLECT ) && FBitSet( RI->params, RP_MIRRORVIEW ))
|
||||
return true;
|
||||
|
||||
// draw only in mirrors
|
||||
if( FBitSet( e->curstate.effects, EF_REFLECTONLY ) && !FBitSet( RI->params, RP_MIRRORVIEW ))
|
||||
return true;
|
||||
|
||||
// never draw playermodel for himself flashlight while shadowpass is active
|
||||
if( FBitSet( RI->params, RP_SHADOWVIEW ) && RI->currentlight != NULL )
|
||||
{
|
||||
if( UTIL_IsLocal( e->index ) && RI->currentlight->key == FLASHLIGHT_KEY )
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
// don't cull local player because we draw legs instead
|
||||
if( RP_LOCALCLIENT( e ) && !FBitSet( RI->params, RP_THIRDPERSON ) && UTIL_IsLocal( RI->view.entity ))
|
||||
{
|
||||
// player can view himself from the portal camera
|
||||
if( !FBitSet( RI->params, RP_MIRRORVIEW|RP_SHADOWVIEW ))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return R_CullBox( absmin, absmax );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_CullBrushModel
|
||||
|
||||
Cull brush model by bbox
|
||||
================
|
||||
*/
|
||||
bool R_CullBrushModel( cl_entity_t *e )
|
||||
{
|
||||
gl_state_t *glm = GL_GetCache( e->hCachedMatrix );
|
||||
model_t *clmodel = e->model;
|
||||
Vector absmin, absmax;
|
||||
|
||||
if( !e || !e->model )
|
||||
return true;
|
||||
|
||||
// skybox entity
|
||||
if( e->curstate.renderfx == SKYBOX_ENTITY )
|
||||
{
|
||||
if( FBitSet( RI->params, RP_SHADOWVIEW ))
|
||||
return true;
|
||||
|
||||
Vector trans = GetVieworg() - tr.sky_origin;
|
||||
|
||||
if( tr.sky_speed )
|
||||
{
|
||||
trans = trans - (GetVieworg() - tr.sky_world_origin) / tr.sky_speed;
|
||||
Vector skypos = tr.sky_origin + (GetVieworg() - tr.sky_world_origin) / tr.sky_speed;
|
||||
tr.modelorg = skypos - e->origin;
|
||||
}
|
||||
else tr.modelorg = tr.sky_origin - e->origin;
|
||||
|
||||
absmin = e->origin + trans + clmodel->mins;
|
||||
absmax = e->origin + trans + clmodel->maxs;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( e->angles != g_vecZero )
|
||||
{
|
||||
absmin = e->origin - clmodel->radius;
|
||||
absmax = e->origin + clmodel->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
absmin = e->origin + clmodel->mins;
|
||||
absmax = e->origin + clmodel->maxs;
|
||||
}
|
||||
tr.modelorg = glm->GetModelOrigin();
|
||||
}
|
||||
|
||||
return R_CullModel( e, absmin, absmax );
|
||||
}
|
||||
|
||||
static bool R_SunLightShadow( void )
|
||||
{
|
||||
if( RI->currentlight && RI->currentlight->type == LIGHT_DIRECTIONAL && FBitSet( RI->params, RP_SHADOWVIEW ))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AllowFacePlaneCulling
|
||||
|
||||
allow to culling backfaces
|
||||
=================
|
||||
*/
|
||||
static bool R_AllowFacePlaneCulling( msurface_t *surf )
|
||||
{
|
||||
if( !glState.faceCull )
|
||||
return false;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_TWOSIDE ))
|
||||
return false;
|
||||
|
||||
if( !FBitSet( RI->params, RP_SHADOWVIEW ) && RI->currentlight && RI->currentlight->type == LIGHT_DIRECTIONAL )
|
||||
return false;
|
||||
|
||||
// don't cull transparent surfaces because we should be draw decals on them
|
||||
if( FBitSet( surf->flags, SURF_HAS_DECALS ) && !R_OpaqueEntity( RI->currententity ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullSurface
|
||||
|
||||
cull invisible surfaces
|
||||
=================
|
||||
*/
|
||||
int R_CullSurface( msurface_t *surf, const Vector &vieworg, CFrustum *frustum, int clipFlags )
|
||||
{
|
||||
cl_entity_t *e = RI->currententity;
|
||||
|
||||
if( !surf || !surf->texinfo || !surf->texinfo->texture )
|
||||
return CULL_OTHER;
|
||||
|
||||
if( FBitSet( RI->params, RP_WATERPASS ) && R_WaterEntity( e->model ))
|
||||
return CULL_OTHER; // don't render water from waterplane reflection
|
||||
|
||||
if( CVAR_TO_BOOL( r_nocull ))
|
||||
return CULL_VISIBLE;
|
||||
|
||||
if( R_SunLightShadow( ))
|
||||
return CULL_VISIBLE;
|
||||
|
||||
// because light or shadow passes required both sides for right self-shadowing
|
||||
if( R_AllowFacePlaneCulling( surf ))
|
||||
{
|
||||
float dist;
|
||||
|
||||
// can use normal.z for world (optimisation)
|
||||
if( FBitSet( RI->params, RP_DRAW_OVERVIEW ))
|
||||
{
|
||||
Vector orthonormal;
|
||||
|
||||
if( e == GET_ENTITY( 0 ) || R_StaticEntity( e ))
|
||||
{
|
||||
orthonormal.z = surf->plane->normal.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix4x4 m = matrix4x4( g_vecZero, e->angles );
|
||||
orthonormal = m.VectorRotate( surf->plane->normal );
|
||||
}
|
||||
|
||||
dist = orthonormal.z;
|
||||
}
|
||||
else dist = PlaneDiff( vieworg, surf->plane );
|
||||
|
||||
if( glState.faceCull == GL_FRONT || ( RI->params & RP_MIRRORVIEW ))
|
||||
{
|
||||
if( surf->flags & SURF_PLANEBACK )
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
}
|
||||
else if( glState.faceCull == GL_BACK )
|
||||
{
|
||||
if( surf->flags & SURF_PLANEBACK )
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( frustum && frustum->CullBox( surf->info->mins, surf->info->maxs, clipFlags ))
|
||||
return CULL_FRUSTUM;
|
||||
return CULL_VISIBLE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_CullNodeTopView
|
||||
|
||||
cull node by user rectangle (simple scissor)
|
||||
================
|
||||
*/
|
||||
bool R_CullNodeTopView( mnode_t *node )
|
||||
{
|
||||
Vector2D delta, size;
|
||||
Vector center, half, mins, maxs;
|
||||
|
||||
// build the node center and half-diagonal
|
||||
mins = node->minmaxs, maxs = node->minmaxs + 3;
|
||||
center = (mins + maxs) * 0.5f;
|
||||
half = maxs - center;
|
||||
|
||||
// cull against the screen frustum or the appropriate area's frustum.
|
||||
delta.x = center.x - world->orthocenter.x;
|
||||
delta.y = center.y - world->orthocenter.y;
|
||||
size.x = half.x + world->orthohalf.x;
|
||||
size.y = half.y + world->orthohalf.y;
|
||||
|
||||
return ( fabs( delta.x ) > size.x ) || ( fabs( delta.y ) > size.y );
|
||||
}
|
576
cl_dll/render/gl_debug.cpp
Normal file
576
cl_dll/render/gl_debug.cpp
Normal file
@ -0,0 +1,576 @@
|
||||
//
|
||||
// written by BUzer for HL: Paranoia modification
|
||||
//
|
||||
// 2006
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "r_studioint.h"
|
||||
#include "ref_params.h"
|
||||
#include "r_efx.h"
|
||||
#include "event_api.h"
|
||||
#include "pm_defs.h"
|
||||
#include "pmtrace.h"
|
||||
#include "triangleapi.h"
|
||||
#include "gl_local.h"
|
||||
#include "stringlib.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_shader.h"
|
||||
#include "vertex_fmt.h"
|
||||
|
||||
void GL_GpuMemUsage_f( void )
|
||||
{
|
||||
GLint cur_avail_mem_kb = 0;
|
||||
GLint total_mem_kb = 0;
|
||||
|
||||
if( glConfig.hardware_type == GLHW_NVIDIA )
|
||||
{
|
||||
pglGetIntegerv( GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb );
|
||||
pglGetIntegerv( GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX, &cur_avail_mem_kb );
|
||||
}
|
||||
|
||||
Msg( "TEX used memory %s\n", Q_memprint( RENDER_GET_PARM( PARM_TEX_MEMORY, 0 )));
|
||||
Msg( "VBO used memory %s\n", Q_memprint( tr.total_vbo_memory ));
|
||||
Msg( "GPU used memory %s\n", Q_memprint(( total_mem_kb - cur_avail_mem_kb ) * 1024 ));
|
||||
}
|
||||
|
||||
void DBG_PrintVertexVBOSizes( void )
|
||||
{
|
||||
if( developer_level < at_aiconsole )
|
||||
return;
|
||||
|
||||
ALERT( at_console, "sizeof( bvert_v0_gl21_t ) == %d bytes\n", sizeof( bvert_v0_gl21_t ));
|
||||
ALERT( at_console, "sizeof( bvert_v0_gl30_t ) == %d bytes\n", sizeof( bvert_v0_gl30_t ));
|
||||
ALERT( at_console, "sizeof( gvert_v0_gl21_t ) == %d bytes\n", sizeof( gvert_v0_gl21_t ));
|
||||
ALERT( at_console, "sizeof( gvert_v0_gl30_t ) == %d bytes\n", sizeof( gvert_v0_gl30_t ));
|
||||
ALERT( at_console, "sizeof( gvert_v1_gl21_t ) == %d bytes\n", sizeof( gvert_v1_gl21_t ));
|
||||
ALERT( at_console, "sizeof( gvert_v1_gl30_t ) == %d bytes\n", sizeof( gvert_v1_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v0_gl21_t ) == %d bytes\n", sizeof( svert_v0_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v0_gl30_t ) == %d bytes\n", sizeof( svert_v0_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v1_gl21_t ) == %d bytes\n", sizeof( svert_v1_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v1_gl30_t ) == %d bytes\n", sizeof( svert_v1_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v2_gl21_t ) == %d bytes\n", sizeof( svert_v2_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v2_gl30_t ) == %d bytes\n", sizeof( svert_v2_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v3_gl21_t ) == %d bytes\n", sizeof( svert_v3_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v3_gl30_t ) == %d bytes\n", sizeof( svert_v3_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v4_gl21_t ) == %d bytes\n", sizeof( svert_v4_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v4_gl30_t ) == %d bytes\n", sizeof( svert_v4_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v5_gl21_t ) == %d bytes\n", sizeof( svert_v5_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v5_gl30_t ) == %d bytes\n", sizeof( svert_v5_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v6_gl21_t ) == %d bytes\n", sizeof( svert_v6_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v6_gl30_t ) == %d bytes\n", sizeof( svert_v6_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v7_gl21_t ) == %d bytes\n", sizeof( svert_v7_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v7_gl30_t ) == %d bytes\n", sizeof( svert_v7_gl30_t ));
|
||||
ALERT( at_console, "sizeof( svert_v8_gl21_t ) == %d bytes\n", sizeof( svert_v8_gl21_t ));
|
||||
ALERT( at_console, "sizeof( svert_v8_gl30_t ) == %d bytes\n", sizeof( svert_v8_gl30_t ));
|
||||
}
|
||||
|
||||
// some simple helpers to draw a cube in the special way the ambient visualization wants
|
||||
static float *CubeSide( const vec3_t pos, float size, int vert )
|
||||
{
|
||||
static vec3_t side;
|
||||
|
||||
VectorCopy( pos, side );
|
||||
side[0] += (vert & 1) ? -size : size;
|
||||
side[1] += (vert & 2) ? -size : size;
|
||||
side[2] += (vert & 4) ? -size : size;
|
||||
|
||||
return side;
|
||||
}
|
||||
|
||||
static void CubeFace( const vec3_t org, int v0, int v1, int v2, int v3, float size, const byte *color )
|
||||
{
|
||||
uint scale = tr.lightstyle[0];
|
||||
uint unclamped[3];
|
||||
int col[3];
|
||||
|
||||
unclamped[0] = TEXTURE_TO_TEXGAMMA( color[0] ) * scale;
|
||||
unclamped[1] = TEXTURE_TO_TEXGAMMA( color[1] ) * scale;
|
||||
unclamped[2] = TEXTURE_TO_TEXGAMMA( color[2] ) * scale;
|
||||
|
||||
col[0] = min((unclamped[0] >> 7), 255 );
|
||||
col[1] = min((unclamped[1] >> 7), 255 );
|
||||
col[2] = min((unclamped[2] >> 7), 255 );
|
||||
|
||||
// pglColor3ub( col[0], col[1], col[2] );
|
||||
pglColor3ub( color[0], color[1], color[2] );
|
||||
pglVertex3fv( CubeSide( org, size, v0 ));
|
||||
pglVertex3fv( CubeSide( org, size, v1 ));
|
||||
pglVertex3fv( CubeSide( org, size, v2 ));
|
||||
pglVertex3fv( CubeSide( org, size, v3 ));
|
||||
}
|
||||
|
||||
void R_RenderLightProbe( mlightprobe_t *probe )
|
||||
{
|
||||
float rad = 4.0f;
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
|
||||
CubeFace( probe->origin, 4, 6, 2, 0, rad, probe->cube.color[0] );
|
||||
CubeFace( probe->origin, 7, 5, 1, 3, rad, probe->cube.color[1] );
|
||||
CubeFace( probe->origin, 0, 1, 5, 4, rad, probe->cube.color[2] );
|
||||
CubeFace( probe->origin, 3, 2, 6, 7, rad, probe->cube.color[3] );
|
||||
CubeFace( probe->origin, 2, 3, 1, 0, rad, probe->cube.color[4] );
|
||||
CubeFace( probe->origin, 4, 5, 7, 6, rad, probe->cube.color[5] );
|
||||
|
||||
pglEnd ();
|
||||
}
|
||||
|
||||
void R_RenderCubemap( mcubemap_t *cube )
|
||||
{
|
||||
float rad = (float)cube->size * 0.1f;
|
||||
byte color[3] = { 127, 127, 127 };
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
|
||||
CubeFace( cube->origin, 4, 6, 2, 0, rad, color );
|
||||
CubeFace( cube->origin, 7, 5, 1, 3, rad, color );
|
||||
CubeFace( cube->origin, 0, 1, 5, 4, rad, color );
|
||||
CubeFace( cube->origin, 3, 2, 6, 7, rad, color );
|
||||
CubeFace( cube->origin, 2, 3, 1, 0, rad, color );
|
||||
CubeFace( cube->origin, 4, 5, 7, 6, rad, color );
|
||||
|
||||
pglEnd ();
|
||||
}
|
||||
|
||||
void R_RenderLightProbeInternal( const Vector &origin, const Vector lightCube[] )
|
||||
{
|
||||
mlightprobe_t probe;
|
||||
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
probe.cube.color[i][0] = lightCube[i].x * 255;
|
||||
probe.cube.color[i][1] = lightCube[i].y * 255;
|
||||
probe.cube.color[i][2] = lightCube[i].z * 255;
|
||||
}
|
||||
probe.origin = origin;
|
||||
|
||||
R_RenderLightProbe( &probe );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_DrawAABB
|
||||
|
||||
===============
|
||||
*/
|
||||
static void R_DrawAABB( const Vector &absmin, const Vector &absmax, int contents )
|
||||
{
|
||||
vec3_t bbox[8];
|
||||
int i;
|
||||
|
||||
// compute a full bounding box
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
bbox[i][0] = ( i & 1 ) ? absmin[0] : absmax[0];
|
||||
bbox[i][1] = ( i & 2 ) ? absmin[1] : absmax[1];
|
||||
bbox[i][2] = ( i & 4 ) ? absmin[2] : absmax[2];
|
||||
}
|
||||
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglDisable( GL_DEPTH_TEST );
|
||||
|
||||
switch( contents )
|
||||
{
|
||||
case CONTENTS_EMPTY:
|
||||
pglColor4f( 0.5f, 1.0f, 0.0f, 1.0f ); // green for empty
|
||||
break;
|
||||
case CONTENTS_SOLID:
|
||||
pglColor4f( 1.0f, 0.0f, 0.0f, 1.0f ); // red for solid
|
||||
break;
|
||||
case CONTENTS_WATER:
|
||||
pglColor4f( 0.0f, 0.5f, 1.0f, 1.0f ); // blue for water
|
||||
break;
|
||||
default:
|
||||
pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); // gray as default
|
||||
break;
|
||||
}
|
||||
pglBegin( GL_LINES );
|
||||
|
||||
for( i = 0; i < 2; i += 1 )
|
||||
{
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i*2+0] );
|
||||
pglVertex3fv( bbox[i*2+1] );
|
||||
pglVertex3fv( bbox[i*2+4] );
|
||||
pglVertex3fv( bbox[i*2+5] );
|
||||
}
|
||||
|
||||
pglEnd();
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_RenderVisibleLeafs
|
||||
|
||||
===============
|
||||
*/
|
||||
static void R_RenderVisibleLeafs( void )
|
||||
{
|
||||
mleaf_t *leaf;
|
||||
int i;
|
||||
|
||||
// always skip the leaf 0, because is outside leaf
|
||||
for( i = 1, leaf = &worldmodel->leafs[1]; i < worldmodel->numleafs + 1; i++, leaf++ )
|
||||
{
|
||||
mextraleaf_t *eleaf = LEAF_INFO( leaf, worldmodel );
|
||||
|
||||
if( CHECKVISBIT( RI->view.pvsarray, leaf->cluster ) && ( leaf->efrags || leaf->nummarksurfaces ))
|
||||
{
|
||||
R_DrawAABB( eleaf->mins, eleaf->maxs, CONTENTS_WATER );
|
||||
R_DrawAABB( Vector( leaf->minmaxs ), Vector( leaf->minmaxs + 3 ), leaf->contents );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
DrawViewLeaf
|
||||
=============
|
||||
*/
|
||||
void DrawViewLeaf( void )
|
||||
{
|
||||
if( !CVAR_TO_BOOL( r_show_viewleaf ))
|
||||
return;
|
||||
|
||||
GL_Blend( GL_FALSE );
|
||||
R_RenderVisibleLeafs();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
DrawLightProbes
|
||||
=============
|
||||
*/
|
||||
void DrawLightProbes( void )
|
||||
{
|
||||
int i, j;
|
||||
mlightprobe_t *probe;
|
||||
mleaf_t *leaf;
|
||||
mextraleaf_t *info;
|
||||
|
||||
if( !CVAR_TO_BOOL( r_show_lightprobes ))
|
||||
return;
|
||||
|
||||
GL_Blend( GL_FALSE );
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
// draw the all visible probes
|
||||
for( i = 1; i < world->numleafs; i++ )
|
||||
{
|
||||
leaf = (mleaf_t *)&worldmodel->leafs[i];
|
||||
info = LEAF_INFO( leaf, worldmodel );
|
||||
|
||||
if( !CHECKVISBIT( RI->view.pvsarray, leaf->cluster ))
|
||||
continue; // not visible from player
|
||||
|
||||
for( j = 0; j < info->num_lightprobes; j++ )
|
||||
{
|
||||
probe = info->ambient_light + j;
|
||||
R_RenderLightProbe( probe );
|
||||
}
|
||||
}
|
||||
|
||||
pglColor3f( 1.0f, 1.0f, 1.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
DrawCubeMaps
|
||||
=============
|
||||
*/
|
||||
void DrawCubeMaps( void )
|
||||
{
|
||||
mcubemap_t *cm;
|
||||
|
||||
if( !CVAR_TO_BOOL( r_show_cubemaps ))
|
||||
return;
|
||||
|
||||
GL_Blend( GL_FALSE );
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
// draw the all cubemaps
|
||||
for( int i = 0; i < world->num_cubemaps; i++ )
|
||||
{
|
||||
cm = &world->cubemaps[i];
|
||||
R_RenderCubemap( cm );
|
||||
}
|
||||
|
||||
pglColor3f( 1.0f, 1.0f, 1.0f );
|
||||
}
|
||||
|
||||
void DBG_DrawBBox( const Vector &mins, const Vector &maxs )
|
||||
{
|
||||
Vector bbox[8];
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
bbox[i][0] = ( i & 1 ) ? mins[0] : maxs[0];
|
||||
bbox[i][1] = ( i & 2 ) ? mins[1] : maxs[1];
|
||||
bbox[i][2] = ( i & 4 ) ? mins[2] : maxs[2];
|
||||
}
|
||||
|
||||
pglColor4f( 1.0f, 0.0f, 1.0f, 1.0f ); // yellow bboxes for frustum
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglBegin( GL_LINES );
|
||||
|
||||
for( i = 0; i < 2; i += 1 )
|
||||
{
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i*2+0] );
|
||||
pglVertex3fv( bbox[i*2+1] );
|
||||
pglVertex3fv( bbox[i*2+4] );
|
||||
pglVertex3fv( bbox[i*2+5] );
|
||||
}
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
void DBG_DrawLightFrustum( void )
|
||||
{
|
||||
if( CVAR_TO_BOOL( r_scissor_light_debug ) && RP_NORMALPASS( ))
|
||||
{
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
CDynLight *pl = &tr.dlights[i];
|
||||
|
||||
if( !pl->Active( )) continue;
|
||||
|
||||
if( r_scissor_light_debug->value == 1.0f )
|
||||
{
|
||||
R_DrawScissorRectangle( pl->x, pl->y, pl->w, pl->h );
|
||||
}
|
||||
else if( r_scissor_light_debug->value == 2.0f )
|
||||
{
|
||||
if( pl->type == LIGHT_DIRECTIONAL )
|
||||
{
|
||||
for( int j = 0; j < NUM_SHADOW_SPLITS + 1; j++ )
|
||||
pl->splitFrustum[j].DrawFrustumDebug();
|
||||
}
|
||||
else pl->frustum.DrawFrustumDebug();
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_DrawBBox( pl->absmin, pl->absmax );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBG_DrawGlassScissors( void )
|
||||
{
|
||||
if( CVAR_TO_BOOL( r_scissor_glass_debug ) && RP_NORMALPASS( ))
|
||||
{
|
||||
// debug scissor code
|
||||
GL_BindShader( NULL );
|
||||
|
||||
// debug scissor code
|
||||
for( int k = 0; k < RI->frame.trans_list.Count(); k++ )
|
||||
{
|
||||
CTransEntry *entry = &RI->frame.trans_list[k];
|
||||
entry->RenderScissorDebug();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DrawTangentSpaces
|
||||
|
||||
Draws vertex tangent spaces for debugging
|
||||
================
|
||||
*/
|
||||
void DrawTangentSpaces( void )
|
||||
{
|
||||
float temp[3];
|
||||
float vecLen = 4.0f;
|
||||
|
||||
if( !CVAR_TO_BOOL( cv_show_tbn ))
|
||||
return;
|
||||
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglDisable( GL_DEPTH_TEST );
|
||||
GL_Blend( GL_FALSE );
|
||||
pglBegin( GL_LINES );
|
||||
|
||||
for( int i = 0; i < worldmodel->nummodelsurfaces; i++ )
|
||||
{
|
||||
msurface_t *surf = &worldmodel->surfaces[i];
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTURB|SURF_DRAWSKY ))
|
||||
continue;
|
||||
|
||||
bvert_t *mv = &world->vertexes[esrf->firstvertex];
|
||||
|
||||
for( int j = 0; j < esrf->numverts; j++, mv++ )
|
||||
{
|
||||
pglColor3f( 1.0f, 0.0f, 0.0f );
|
||||
pglVertex3fv( mv->vertex );
|
||||
VectorMA( mv->vertex, vecLen, Vector( mv->tangent ), temp );
|
||||
pglVertex3fv( temp );
|
||||
|
||||
pglColor3f( 0.0f, 1.0f, 0.0f );
|
||||
pglVertex3fv( mv->vertex );
|
||||
VectorMA( mv->vertex, vecLen, Vector( mv->binormal ), temp );
|
||||
pglVertex3fv( temp );
|
||||
|
||||
pglColor3f( 0.0f, 0.0f, 1.0f );
|
||||
pglVertex3fv( mv->vertex );
|
||||
VectorMA( mv->vertex, vecLen, Vector( mv->normal ), temp );
|
||||
pglVertex3fv( temp );
|
||||
}
|
||||
}
|
||||
|
||||
pglEnd();
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
}
|
||||
|
||||
void DrawWireFrame( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !CVAR_TO_BOOL( r_wireframe ))
|
||||
return;
|
||||
|
||||
pglEnable( GL_BLEND );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 0.99f );
|
||||
|
||||
pglDisable( GL_DEPTH_TEST );
|
||||
pglEnable( GL_LINE_SMOOTH );
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglEnable( GL_POLYGON_SMOOTH );
|
||||
pglHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
pglHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
for( i = 0; i < RI->frame.solid_faces.Count(); i++ )
|
||||
{
|
||||
if( RI->frame.solid_faces[i].m_bDrawType != DRAWTYPE_SURFACE )
|
||||
continue;
|
||||
|
||||
msurface_t *surf = RI->frame.solid_faces[i].m_pSurf;
|
||||
mextrasurf_t *es = surf->info;
|
||||
|
||||
pglBegin( GL_POLYGON );
|
||||
for( int j = 0; j < es->numverts; j++ )
|
||||
{
|
||||
bvert_t *v = &world->vertexes[es->firstvertex + j];
|
||||
pglVertex3fv( v->vertex + Vector( v->normal ) * 0.1f );
|
||||
}
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
pglColor4f( 0.0f, 1.0f, 0.0f, 0.99f );
|
||||
for( i = 0; i < RI->frame.trans_list.Count(); i++ )
|
||||
{
|
||||
if( RI->frame.trans_list[i].m_bDrawType != DRAWTYPE_SURFACE )
|
||||
continue;
|
||||
|
||||
msurface_t *surf = RI->frame.trans_list[i].m_pSurf;
|
||||
mextrasurf_t *es = surf->info;
|
||||
|
||||
pglBegin( GL_POLYGON );
|
||||
for( int j = 0; j < es->numverts; j++ )
|
||||
{
|
||||
bvert_t *v = &world->vertexes[es->firstvertex + j];
|
||||
pglVertex3fv( v->vertex + Vector( v->normal ) * 0.1f );
|
||||
}
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
pglDisable( GL_POLYGON_SMOOTH );
|
||||
pglDisable( GL_LINE_SMOOTH );
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
pglDisable( GL_BLEND );
|
||||
}
|
||||
|
||||
void DrawWirePoly( msurface_t *surf )
|
||||
{
|
||||
if( !surf ) return;
|
||||
|
||||
pglEnable( GL_BLEND );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||
pglColor4f( 0.5f, 1.0f, 0.36f, 0.99f );
|
||||
pglLineWidth( 4.0f );
|
||||
|
||||
pglDisable( GL_DEPTH_TEST );
|
||||
pglEnable( GL_LINE_SMOOTH );
|
||||
pglEnable( GL_POLYGON_SMOOTH );
|
||||
pglHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
pglHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
mextrasurf_t *es = surf->info;
|
||||
|
||||
pglBegin( GL_POLYGON );
|
||||
for( int j = 0; j < es->numverts; j++ )
|
||||
{
|
||||
bvert_t *v = &world->vertexes[es->firstvertex + j];
|
||||
pglVertex3fv( v->vertex + Vector( v->normal ) * 0.1f );
|
||||
}
|
||||
pglEnd();
|
||||
|
||||
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
pglDisable( GL_POLYGON_SMOOTH );
|
||||
pglDisable( GL_LINE_SMOOTH );
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
pglDisable( GL_BLEND );
|
||||
pglLineWidth( 1.0f );
|
||||
}
|
||||
|
||||
void R_ShowLightMaps( void )
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if( !CVAR_TO_BOOL( r_showlightmaps ))
|
||||
return;
|
||||
|
||||
index = r_showlightmaps->value - 1.0f;
|
||||
if( tr.lightmaps[index].state == LM_FREE )
|
||||
return;
|
||||
|
||||
GL_BindTexture( GL_TEXTURE0, tr.lightmaps[index].lightmap );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
GL_Setup2D();
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglVertex2f( 0.0f, 0.0f );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
pglVertex2f( glState.width, 0.0f );
|
||||
pglTexCoord2f( 1.0f, 1.0f );
|
||||
pglVertex2f( glState.width, glState.height );
|
||||
pglTexCoord2f( 0.0f, 1.0f );
|
||||
pglVertex2f( 0.0f, glState.height );
|
||||
pglEnd();
|
||||
|
||||
GL_Setup3D();
|
||||
}
|
1973
cl_dll/render/gl_decals.cpp
Normal file
1973
cl_dll/render/gl_decals.cpp
Normal file
File diff suppressed because it is too large
Load Diff
105
cl_dll/render/gl_decals.h
Normal file
105
cl_dll/render/gl_decals.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
gl_decals.h - decal project & rendering
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_DECALS_H
|
||||
#define GL_DECALS_H
|
||||
|
||||
class DecalGroup;
|
||||
class DecalGroupEntry
|
||||
{
|
||||
public:
|
||||
char m_DecalName[64];
|
||||
unsigned short gl_diffuse_id;
|
||||
unsigned short gl_normalmap_id;
|
||||
unsigned short gl_heightmap_id;
|
||||
unsigned short gl_specular_id; // specular
|
||||
int xsize, ysize;
|
||||
matdesc_t *matdesc; // pointer to settings
|
||||
float overlay;
|
||||
bool opaque; // solid decal doesn't use blend
|
||||
const DecalGroup *group; // get group name
|
||||
bool m_init;
|
||||
|
||||
void PreloadTextures( void );
|
||||
};
|
||||
|
||||
class DecalGroup
|
||||
{
|
||||
public:
|
||||
DecalGroup( const char *name, int numelems, DecalGroupEntry *source );
|
||||
~DecalGroup();
|
||||
|
||||
DecalGroupEntry *GetRandomDecal( void );
|
||||
DecalGroup *GetNext( void ) { return pnext; }
|
||||
const char *GetName( void ) { return m_chGroupName; }
|
||||
const char *GetName( void ) const { return m_chGroupName; }
|
||||
static DecalGroup *FindGroup( const char *name );
|
||||
DecalGroupEntry *FindEntry( const char *name );
|
||||
DecalGroupEntry *GetEntry( int num );
|
||||
static DecalGroupEntry *GetEntry( const char *name, int flags );
|
||||
private:
|
||||
char m_chGroupName[16];
|
||||
DecalGroupEntry *pEntryArray;
|
||||
DecalGroup *pnext;
|
||||
int size;
|
||||
};
|
||||
|
||||
typedef struct dvert_s
|
||||
{
|
||||
Vector vertex; // position
|
||||
Vector tangent; // tangent
|
||||
Vector binormal; // binormal
|
||||
Vector normal; // normal
|
||||
float stcoord0[4]; // ST texture coords + Decal coords
|
||||
float lmcoord0[4]; // LM texture coords for styles 0-1
|
||||
float lmcoord1[4]; // LM texture coords for styles 2-3
|
||||
byte styles[4]; // lightstyles
|
||||
} dvert_t;
|
||||
|
||||
// decal entry
|
||||
typedef struct brushdecal_s
|
||||
{
|
||||
// this part is goes to savelist
|
||||
byte flags;
|
||||
short entityIndex;
|
||||
Vector position;
|
||||
Vector impactPlaneNormal;
|
||||
float angle; // goes into scale
|
||||
const DecalGroupEntry *texinfo;
|
||||
|
||||
// verts & elems
|
||||
dvert_t *verts; // pointer to cache array
|
||||
word *elems; // pointer to index array
|
||||
byte numVerts;
|
||||
byte numElems;
|
||||
|
||||
// shader cache
|
||||
shader_t forwardScene;
|
||||
shader_t deferredScene;
|
||||
mextrasurf_t *surface;
|
||||
struct brushdecal_s *pnext; // linked list for each surface
|
||||
model_t *model;
|
||||
} brushdecal_t;
|
||||
|
||||
void DecalsInit( void );
|
||||
void ClearDecals( void );
|
||||
void DecalsShutdown( void );
|
||||
void R_RenderDecalsSolidList( drawlist_t drawlist_type );
|
||||
void R_RenderDecalsTransList( drawlist_t drawlist_type );
|
||||
void R_RenderDecalsTransEntry( CTransEntry *entry, drawlist_t drawlist_type );
|
||||
int SaveDecalList( decallist_t *pBaseList, int count );
|
||||
|
||||
#endif//GL_DECALS_H
|
554
cl_dll/render/gl_deferred.cpp
Normal file
554
cl_dll/render/gl_deferred.cpp
Normal file
@ -0,0 +1,554 @@
|
||||
/*
|
||||
gl_deferred.cpp - deferred rendering
|
||||
Copyright (C) 2018 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_shader.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SCENE_PASS = 0,
|
||||
LIGHT_PASS,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BILATERAL_PASS0 = 0,
|
||||
BILATERAL_PASS1,
|
||||
};
|
||||
|
||||
void GL_InitDefSceneFBO( void )
|
||||
{
|
||||
GLenum MRTBuffers[5] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_COLOR_ATTACHMENT4_EXT };
|
||||
int albedo_buffer;
|
||||
int normal_buffer;
|
||||
int smooth_buffer;
|
||||
int light0_buffer;
|
||||
int light1_buffer;
|
||||
int depth_buffer;
|
||||
|
||||
if( !GL_Support( R_FRAMEBUFFER_OBJECT ) || !GL_Support( R_DRAW_BUFFERS_EXT ))
|
||||
return;
|
||||
|
||||
// Create and set up the framebuffer
|
||||
tr.defscene_fbo = GL_AllocDrawbuffer( "*defscene", glState.width, glState.height, 1 );
|
||||
|
||||
// create textures
|
||||
albedo_buffer = CREATE_TEXTURE( "*albedo_rt", glState.width, glState.height, NULL, TF_RT_COLOR|TF_HAS_ALPHA );
|
||||
normal_buffer = CREATE_TEXTURE( "*normal_rt", glState.width, glState.height, NULL, TF_RT_NORMAL|TF_HAS_ALPHA );
|
||||
smooth_buffer = CREATE_TEXTURE( "*smooth_rt", glState.width, glState.height, NULL, TF_RT_COLOR|TF_HAS_ALPHA );
|
||||
light0_buffer = CREATE_TEXTURE( "*light0_rt", glState.width, glState.height, NULL, TF_RT_COLOR|TF_HAS_ALPHA );
|
||||
light1_buffer = CREATE_TEXTURE( "*light1_rt", glState.width, glState.height, NULL, TF_RT_COLOR|TF_HAS_ALPHA );
|
||||
depth_buffer = CREATE_TEXTURE( "*depth_rt", glState.width, glState.height, NULL, TF_RT_DEPTH );
|
||||
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, albedo_buffer, 0 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, normal_buffer, 1 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, smooth_buffer, 2 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, light0_buffer, 3 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, light1_buffer, 4 );
|
||||
GL_AttachDepthTextureToFBO( tr.defscene_fbo, depth_buffer );
|
||||
|
||||
pglDrawBuffersARB( ARRAYSIZE( MRTBuffers ), MRTBuffers );
|
||||
pglReadBuffer( GL_NONE );
|
||||
|
||||
// check the framebuffer status
|
||||
GL_CheckFBOStatus( tr.defscene_fbo );
|
||||
}
|
||||
|
||||
void GL_VidInitDefSceneFBO( void )
|
||||
{
|
||||
// resize attached textures
|
||||
GL_ResizeDrawbuffer( tr.defscene_fbo, glState.width, glState.height, 1 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, tr.defscene_fbo->colortarget[0], 0 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, tr.defscene_fbo->colortarget[1], 1 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, tr.defscene_fbo->colortarget[2], 2 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, tr.defscene_fbo->colortarget[3], 3 );
|
||||
GL_AttachColorTextureToFBO( tr.defscene_fbo, tr.defscene_fbo->colortarget[4], 4 );
|
||||
GL_AttachDepthTextureToFBO( tr.defscene_fbo, tr.defscene_fbo->depthtarget );
|
||||
}
|
||||
|
||||
void GL_InitDefLightFBO( void )
|
||||
{
|
||||
GLenum MRTBuffers[3] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };
|
||||
int normal_buffer;
|
||||
int light0_buffer;
|
||||
int light1_buffer;
|
||||
int depth_buffer;
|
||||
|
||||
if( !GL_Support( R_FRAMEBUFFER_OBJECT ) || !GL_Support( R_DRAW_BUFFERS_EXT ))
|
||||
return;
|
||||
|
||||
// Create and set up the framebuffer
|
||||
tr.deflight_fbo = GL_AllocDrawbuffer( "*deflight", glState.defWidth, glState.defHeight, 1 );
|
||||
|
||||
// create textures
|
||||
normal_buffer = CREATE_TEXTURE( "*normal_rs", glState.defWidth, glState.defHeight, NULL, TF_RT_NORMAL|TF_HAS_ALPHA );
|
||||
light0_buffer = CREATE_TEXTURE( "*light0_rs", glState.defWidth, glState.defHeight, NULL, TF_RT_COLOR|TF_HAS_ALPHA );
|
||||
light1_buffer = CREATE_TEXTURE( "*light1_rs", glState.defWidth, glState.defHeight, NULL, TF_RT_COLOR|TF_HAS_ALPHA );
|
||||
depth_buffer = CREATE_TEXTURE( "*depth_rs", glState.defWidth, glState.defHeight, NULL, TF_RT_DEPTH );
|
||||
|
||||
GL_AttachColorTextureToFBO( tr.deflight_fbo, normal_buffer, 0 );
|
||||
GL_AttachColorTextureToFBO( tr.deflight_fbo, light0_buffer, 1 );
|
||||
GL_AttachColorTextureToFBO( tr.deflight_fbo, light1_buffer, 2 );
|
||||
GL_AttachDepthTextureToFBO( tr.deflight_fbo, depth_buffer );
|
||||
|
||||
pglDrawBuffersARB( ARRAYSIZE( MRTBuffers ), MRTBuffers );
|
||||
pglReadBuffer( GL_NONE );
|
||||
|
||||
// check the framebuffer status
|
||||
GL_CheckFBOStatus( tr.deflight_fbo );
|
||||
}
|
||||
|
||||
void GL_VidInitDefLightFBO( void )
|
||||
{
|
||||
// resize attached textures
|
||||
GL_ResizeDrawbuffer( tr.deflight_fbo, glState.defWidth, glState.defHeight, 1 );
|
||||
GL_AttachColorTextureToFBO( tr.deflight_fbo, tr.deflight_fbo->colortarget[0], 0 );
|
||||
GL_AttachColorTextureToFBO( tr.deflight_fbo, tr.deflight_fbo->colortarget[1], 1 );
|
||||
GL_AttachColorTextureToFBO( tr.deflight_fbo, tr.deflight_fbo->colortarget[2], 2 );
|
||||
GL_AttachDepthTextureToFBO( tr.deflight_fbo, tr.deflight_fbo->depthtarget );
|
||||
}
|
||||
|
||||
void GL_VidInitDrawBuffers( void )
|
||||
{
|
||||
if( tr.defscene_fbo == NULL )
|
||||
GL_InitDefSceneFBO();
|
||||
else GL_VidInitDefSceneFBO();
|
||||
|
||||
if( tr.deflight_fbo == NULL )
|
||||
GL_InitDefLightFBO();
|
||||
else GL_VidInitDefLightFBO();
|
||||
|
||||
// unbind the framebuffer
|
||||
GL_BindDrawbuffer( NULL );
|
||||
}
|
||||
|
||||
void GL_SetupGBuffer( void )
|
||||
{
|
||||
// bind geometry fullscreen buffer
|
||||
if( FBitSet( RI->params, RP_DEFERREDSCENE ))
|
||||
GL_BindDrawbuffer( tr.defscene_fbo );
|
||||
|
||||
// bind light-pass downscaled buffer
|
||||
if( FBitSet( RI->params, RP_DEFERREDLIGHT ))
|
||||
GL_BindDrawbuffer( tr.deflight_fbo );
|
||||
|
||||
R_Clear( ~0 );
|
||||
}
|
||||
|
||||
void GL_ResetGBuffer( void )
|
||||
{
|
||||
GL_BindDrawbuffer( NULL );
|
||||
}
|
||||
|
||||
void GL_DrawScreenSpaceQuad( const vec3_t normals[4] )
|
||||
{
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, 1.0f );
|
||||
pglNormal3fv( normals[0] );
|
||||
pglVertex2f( 0.0f, 0.0f );
|
||||
pglTexCoord2f( 1.0f, 1.0f );
|
||||
pglNormal3fv( normals[3] );
|
||||
pglVertex2f( RI->view.port[2], 0.0f );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
pglNormal3fv( normals[2] );
|
||||
pglVertex2f( RI->view.port[2], RI->view.port[3] );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglNormal3fv( normals[1] );
|
||||
pglVertex2f( 0.0f, RI->view.port[3] );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_Setup2D
|
||||
=================
|
||||
*/
|
||||
void GL_SetupDeferred( void )
|
||||
{
|
||||
// set up full screen workspace
|
||||
pglMatrixMode( GL_PROJECTION );
|
||||
pglLoadIdentity();
|
||||
|
||||
pglOrtho( 0, RI->view.port[2], RI->view.port[3], 0, -99999, 99999 );
|
||||
|
||||
pglMatrixMode( GL_MODELVIEW );
|
||||
pglLoadIdentity();
|
||||
|
||||
GL_AlphaTest( GL_FALSE );
|
||||
GL_DepthMask( GL_FALSE );
|
||||
pglDisable( GL_DEPTH_TEST ); // older dirvers has issues with this
|
||||
|
||||
if( RI->currentlight != NULL )
|
||||
{
|
||||
GL_Blend( GL_TRUE );
|
||||
pglBlendFunc( GL_ONE, GL_ONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_Blend( GL_FALSE );
|
||||
}
|
||||
|
||||
GL_Cull( GL_FRONT );
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
pglViewport( 0, 0, RI->view.port[2], RI->view.port[3] );
|
||||
}
|
||||
|
||||
static void GL_DrawDeferred( word hProgram, int pass )
|
||||
{
|
||||
if( hProgram <= 0 )
|
||||
{
|
||||
GL_BindShader( NULL );
|
||||
return; // bad shader?
|
||||
}
|
||||
|
||||
// prepare deferred pass
|
||||
GL_SetupDeferred();
|
||||
|
||||
if( RI->currentshader != &glsl_programs[hProgram] )
|
||||
{
|
||||
// force to bind new shader
|
||||
GL_BindShader( &glsl_programs[hProgram] );
|
||||
}
|
||||
|
||||
glsl_program_t *shader = RI->currentshader;
|
||||
CDynLight *pl = RI->currentlight; // may be NULL
|
||||
Vector4D lightdir;
|
||||
float *v;
|
||||
|
||||
// setup specified uniforms (and texture bindings)
|
||||
for( int i = 0; i < shader->numUniforms; i++ )
|
||||
{
|
||||
uniform_t *u = &shader->uniforms[i];
|
||||
|
||||
switch( u->type )
|
||||
{
|
||||
case UT_COLORMAP:
|
||||
u->SetValue( tr.defscene_fbo->colortarget[0] );
|
||||
break;
|
||||
case UT_NORMALMAP:
|
||||
if( pass == LIGHT_PASS )
|
||||
u->SetValue( tr.deflight_fbo->colortarget[0] );
|
||||
else u->SetValue( tr.defscene_fbo->colortarget[1] );
|
||||
break;
|
||||
case UT_GLOSSMAP:
|
||||
u->SetValue( tr.defscene_fbo->colortarget[2] );
|
||||
break;
|
||||
case UT_VISLIGHTMAP0:
|
||||
if( pass == LIGHT_PASS )
|
||||
u->SetValue( tr.deflight_fbo->colortarget[1] );
|
||||
else u->SetValue( tr.defscene_fbo->colortarget[3] );
|
||||
break;
|
||||
case UT_VISLIGHTMAP1:
|
||||
if( pass == LIGHT_PASS )
|
||||
u->SetValue( tr.deflight_fbo->colortarget[2] );
|
||||
else u->SetValue( tr.defscene_fbo->colortarget[4] );
|
||||
break;
|
||||
case UT_DEPTHMAP:
|
||||
if( pass == LIGHT_PASS )
|
||||
u->SetValue( tr.deflight_fbo->depthtarget );
|
||||
else u->SetValue( tr.defscene_fbo->depthtarget );
|
||||
break;
|
||||
case UT_BSPPLANESMAP:
|
||||
u->SetValue( tr.packed_planes_texture );
|
||||
break;
|
||||
case UT_BSPNODESMAP:
|
||||
u->SetValue( tr.packed_nodes_texture );
|
||||
break;
|
||||
case UT_BSPLIGHTSMAP:
|
||||
u->SetValue( tr.packed_lights_texture );
|
||||
break;
|
||||
case UT_BSPMODELSMAP:
|
||||
u->SetValue( tr.packed_models_texture );
|
||||
break;
|
||||
case UT_SHADOWMAP:
|
||||
if( pl ) u->SetValue( pl->shadowTexture[0] );
|
||||
else u->SetValue( tr.fbo_light.GetTexture() );
|
||||
break;
|
||||
case UT_SHADOWMAP0:
|
||||
if( pl ) u->SetValue( pl->shadowTexture[0] );
|
||||
else u->SetValue( tr.depthTexture );
|
||||
break;
|
||||
case UT_SHADOWMAP1:
|
||||
if( pl ) u->SetValue( pl->shadowTexture[1] );
|
||||
else u->SetValue( tr.depthTexture );
|
||||
break;
|
||||
case UT_SHADOWMAP2:
|
||||
if( pl ) u->SetValue( pl->shadowTexture[2] );
|
||||
else u->SetValue( tr.depthTexture );
|
||||
break;
|
||||
case UT_SHADOWMAP3:
|
||||
if( pl ) u->SetValue( pl->shadowTexture[3] );
|
||||
else u->SetValue( tr.depthTexture );
|
||||
break;
|
||||
case UT_PROJECTMAP:
|
||||
if( pl && pl->type == LIGHT_SPOT )
|
||||
u->SetValue( pl->spotlightTexture );
|
||||
else u->SetValue( tr.whiteTexture );
|
||||
break;
|
||||
case UT_VIEWORIGIN:
|
||||
u->SetValue( RI->view.matrix[3][0], RI->view.matrix[3][1], RI->view.matrix[3][2] );
|
||||
break;
|
||||
case UT_LIGHTSTYLEVALUES:
|
||||
u->SetValue( &tr.lightstyle[0], MAX_LIGHTSTYLES );
|
||||
break;
|
||||
case UT_GAMMATABLE:
|
||||
u->SetValue( &tr.gamma_table[0][0], 64 );
|
||||
break;
|
||||
case UT_LIGHTTHRESHOLD:
|
||||
u->SetValue( tr.light_threshold );
|
||||
break;
|
||||
case UT_LIGHTSCALE:
|
||||
u->SetValue( tr.direct_scale );
|
||||
break;
|
||||
case UT_LIGHTGAMMA:
|
||||
u->SetValue( tr.light_gamma );
|
||||
break;
|
||||
case UT_ZFAR:
|
||||
u->SetValue( RI->view.farClip );
|
||||
break;
|
||||
case UT_SCREENSIZEINV:
|
||||
u->SetValue( 1.0f / (float)glState.width, 1.0f / (float)glState.height );
|
||||
break;
|
||||
case UT_DIFFUSEFACTOR:
|
||||
u->SetValue( tr.diffuseFactor );
|
||||
break;
|
||||
case UT_AMBIENTFACTOR:
|
||||
if( pl && pl->type == LIGHT_DIRECTIONAL )
|
||||
u->SetValue( tr.sun_ambient );
|
||||
else u->SetValue( tr.ambientFactor );
|
||||
break;
|
||||
case UT_SUNREFRACT:
|
||||
u->SetValue( tr.sun_refract );
|
||||
break;
|
||||
case UT_REALTIME:
|
||||
u->SetValue( (float)tr.time );
|
||||
break;
|
||||
case UT_FOGPARAMS:
|
||||
u->SetValue( tr.fogColor[0], tr.fogColor[1], tr.fogColor[2], tr.fogDensity );
|
||||
break;
|
||||
case UT_SHADOWPARMS:
|
||||
if( pl != NULL )
|
||||
{
|
||||
float shadowWidth = 1.0f / (float)RENDER_GET_PARM( PARM_TEX_WIDTH, pl->shadowTexture[0] );
|
||||
float shadowHeight = 1.0f / (float)RENDER_GET_PARM( PARM_TEX_HEIGHT, pl->shadowTexture[0] );
|
||||
// depth scale and bias and shadowmap resolution
|
||||
u->SetValue( shadowWidth, shadowHeight, -pl->projectionMatrix[2][2], pl->projectionMatrix[3][2] );
|
||||
}
|
||||
else u->SetValue( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
break;
|
||||
case UT_SHADOWMATRIX:
|
||||
if( pl ) u->SetValue( &pl->gl_shadowMatrix[0][0], MAX_SHADOWMAPS );
|
||||
break;
|
||||
case UT_SHADOWSPLITDIST:
|
||||
v = RI->view.parallelSplitDistances;
|
||||
u->SetValue( v[0], v[1], v[2], v[3] );
|
||||
break;
|
||||
case UT_TEXELSIZE:
|
||||
u->SetValue( 1.0f / (float)sunSize[0], 1.0f / (float)sunSize[1], 1.0f / (float)sunSize[2], 1.0f / (float)sunSize[3] );
|
||||
break;
|
||||
case UT_LIGHTDIR:
|
||||
if( pl )
|
||||
{
|
||||
if( pl->type == LIGHT_DIRECTIONAL ) lightdir = -tr.sky_normal;
|
||||
else lightdir = pl->frustum.GetPlane( FRUSTUM_FAR )->normal;
|
||||
u->SetValue( lightdir.x, lightdir.y, lightdir.z, pl->fov );
|
||||
}
|
||||
break;
|
||||
case UT_LIGHTDIFFUSE:
|
||||
if( pl ) u->SetValue( pl->color.x, pl->color.y, pl->color.z );
|
||||
break;
|
||||
case UT_LIGHTORIGIN:
|
||||
if( pl ) u->SetValue( pl->origin.x, pl->origin.y, pl->origin.z, ( 1.0f / pl->radius ));
|
||||
break;
|
||||
case UT_LIGHTVIEWPROJMATRIX:
|
||||
if( pl )
|
||||
{
|
||||
GLfloat gl_lightViewProjMatrix[16];
|
||||
pl->lightviewProjMatrix.CopyToArray( gl_lightViewProjMatrix );
|
||||
u->SetValue( &gl_lightViewProjMatrix[0] );
|
||||
}
|
||||
break;
|
||||
case UT_NUMVISIBLEMODELS:
|
||||
u->SetValue( world->num_visible_models );
|
||||
break;
|
||||
default:
|
||||
ALERT( at_error, "%s: unhandled uniform %s\n", RI->currentshader->name, u->name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GL_DrawScreenSpaceQuad( tr.screen_normals );
|
||||
}
|
||||
|
||||
static void GL_DrawBilateralFilter( word hProgram, int pass )
|
||||
{
|
||||
if( hProgram <= 0 )
|
||||
{
|
||||
GL_BindShader( NULL );
|
||||
return; // bad shader?
|
||||
}
|
||||
|
||||
if( RI->currentshader != &glsl_programs[hProgram] )
|
||||
{
|
||||
// force to bind new shader
|
||||
GL_BindShader( &glsl_programs[hProgram] );
|
||||
}
|
||||
|
||||
glsl_program_t *shader = RI->currentshader;
|
||||
|
||||
// setup specified uniforms (and texture bindings)
|
||||
for( int i = 0; i < shader->numUniforms; i++ )
|
||||
{
|
||||
uniform_t *u = &shader->uniforms[i];
|
||||
|
||||
switch( u->type )
|
||||
{
|
||||
case UT_COLORMAP:
|
||||
if( pass == BILATERAL_PASS0 )
|
||||
u->SetValue( tr.fbo_light.GetTexture() );
|
||||
else if( pass = BILATERAL_PASS1 )
|
||||
u->SetValue( tr.fbo_filter.GetTexture() );
|
||||
else u->SetValue( tr.defscene_fbo->colortarget[0] );
|
||||
break;
|
||||
case UT_DEPTHMAP:
|
||||
u->SetValue( tr.defscene_fbo->depthtarget );
|
||||
break;
|
||||
case UT_ZFAR:
|
||||
u->SetValue( RI->view.farClip );
|
||||
break;
|
||||
case UT_SCREENSIZEINV:
|
||||
if( pass == BILATERAL_PASS0 )
|
||||
u->SetValue( 1.0f / (float)glState.width, 0.0f );
|
||||
else if( pass = BILATERAL_PASS1 )
|
||||
u->SetValue( 0.0f, 1.0f / (float)glState.height );
|
||||
else u->SetValue( 1.0f / (float)glState.width, 1.0f / (float)glState.height );
|
||||
break;
|
||||
case UT_SHADOWPARMS:
|
||||
u->SetValue( RI->view.projectionMatrix[3][2], RI->view.projectionMatrix[2][2] );
|
||||
break;
|
||||
default:
|
||||
ALERT( at_error, "%s: unhandled uniform %s\n", RI->currentshader->name, u->name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RenderFSQ( glState.width, glState.height );
|
||||
}
|
||||
|
||||
void GL_SetupWorldLightPass( void )
|
||||
{
|
||||
tr.fbo_shadow.Bind(); // <- render to shadow texture
|
||||
|
||||
// FIXME! modelview isn't be changed anyway until current pass!!!
|
||||
// pglMatrixMode( GL_MODELVIEW );
|
||||
// pglLoadMatrixf( RI->glstate.modelviewMatrix );
|
||||
|
||||
GL_DrawDeferred( tr.defLightShader, LIGHT_PASS );
|
||||
GL_CleanupAllTextureUnits();
|
||||
|
||||
GL_Setup2D();
|
||||
tr.fbo_light.Bind(); // <- copy to fbo_light result of works complex light shader
|
||||
GL_BindShader( NULL );
|
||||
GL_BindTexture( GL_TEXTURE0, tr.fbo_shadow.GetTexture() );
|
||||
RenderFSQ( glState.width, glState.height );
|
||||
|
||||
if( tr.bilateralShader )
|
||||
{
|
||||
// apply bilateral filter
|
||||
tr.fbo_filter.Bind(); // <- bilateral pass0, filtering by width, store to fbo_filter
|
||||
GL_DrawBilateralFilter( tr.bilateralShader, BILATERAL_PASS0 );
|
||||
|
||||
tr.fbo_light.Bind(); // <- bilateral pass1, filtering by height, store back to fbo_light
|
||||
GL_DrawBilateralFilter( tr.bilateralShader, BILATERAL_PASS1 );
|
||||
}
|
||||
}
|
||||
|
||||
void GL_SetupDynamicPass( void )
|
||||
{
|
||||
if( !FBitSet( RI->view.flags, RF_HASDYNLIGHTS ))
|
||||
return;
|
||||
|
||||
pglEnable( GL_SCISSOR_TEST );
|
||||
CDynLight *pl = tr.dlights;
|
||||
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++, pl++ )
|
||||
{
|
||||
// deferred path are ignored sunlights
|
||||
if( pl->Expired( ) || pl->type == LIGHT_DIRECTIONAL )
|
||||
continue;
|
||||
|
||||
if( !pl->Active( )) continue;
|
||||
|
||||
if( !Mod_CheckBoxVisible( pl->absmin, pl->absmax ))
|
||||
continue;
|
||||
|
||||
if( R_CullFrustum( &pl->frustum ))
|
||||
continue;
|
||||
|
||||
float y2 = (float)RI->view.port[3] - pl->h - pl->y;
|
||||
pglScissor( pl->x, y2, pl->w, pl->h );
|
||||
RI->currentlight = pl;
|
||||
|
||||
GL_DrawDeferred( tr.defDynLightShader[pl->type], SCENE_PASS );
|
||||
}
|
||||
|
||||
pglDisable( GL_SCISSOR_TEST );
|
||||
RI->currentlight = NULL;
|
||||
}
|
||||
|
||||
void GL_SetupWorldScenePass( void )
|
||||
{
|
||||
mworldlight_t *wl;
|
||||
int i;
|
||||
|
||||
// debug
|
||||
for( i = 0, wl = world->worldlights; i < world->numworldlights; i++, wl++ )
|
||||
{
|
||||
if( wl->emittype == emit_ignored )
|
||||
continue;
|
||||
|
||||
if( !CHECKVISBIT( RI->view.vislight, i ))
|
||||
continue;
|
||||
r_stats.c_worldlights++;
|
||||
}
|
||||
|
||||
int type = CVAR_TO_BOOL( cv_deferred_full ) ? 1 : 0;
|
||||
GL_DrawDeferred( tr.defSceneShader[type], SCENE_PASS );
|
||||
|
||||
// also render a standard dynamic lights
|
||||
GL_SetupDynamicPass();
|
||||
}
|
||||
|
||||
void GL_DrawDeferredPass( void )
|
||||
{
|
||||
if( !tr.defSceneShader || !tr.defLightShader )
|
||||
return; // oops!
|
||||
|
||||
GL_ComputeScreenRays();
|
||||
|
||||
if( FBitSet( RI->params, RP_DEFERREDSCENE ))
|
||||
GL_SetupWorldScenePass();
|
||||
|
||||
if( FBitSet( RI->params, RP_DEFERREDLIGHT ))
|
||||
GL_SetupWorldLightPass();
|
||||
|
||||
GL_CleanupDrawState();
|
||||
GL_BindFBO( FBO_MAIN );
|
||||
GL_Setup3D();
|
||||
}
|
779
cl_dll/render/gl_dlight.cpp
Normal file
779
cl_dll/render/gl_dlight.cpp
Normal file
@ -0,0 +1,779 @@
|
||||
/*
|
||||
gl_dlight.cpp - dynamic lighting
|
||||
Copyright (C) 2014 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 "hud.h"
|
||||
#include <stringlib.h>
|
||||
#include "cl_util.h"
|
||||
#include "pm_defs.h"
|
||||
#include "event_api.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_studio.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
PROJECTED LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
===============
|
||||
CL_ClearDlights
|
||||
===============
|
||||
*/
|
||||
void CL_ClearDlights( void )
|
||||
{
|
||||
memset( tr.dlights, 0, sizeof( tr.dlights ));
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_AllocDlight
|
||||
===============
|
||||
*/
|
||||
CDynLight *CL_AllocDlight( int key )
|
||||
{
|
||||
CDynLight *dl;
|
||||
|
||||
// first look for an exact key match
|
||||
if( key )
|
||||
{
|
||||
dl = tr.dlights;
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++, dl++ )
|
||||
{
|
||||
if( dl->key == key )
|
||||
{
|
||||
// reuse this light
|
||||
return dl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float time = GET_CLIENT_TIME();
|
||||
|
||||
// then look for anything else
|
||||
dl = tr.dlights;
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++, dl++ )
|
||||
{
|
||||
if( dl->die < time && dl->key == 0 )
|
||||
{
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
dl->key = key;
|
||||
return dl;
|
||||
}
|
||||
}
|
||||
|
||||
dl = &tr.dlights[0];
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
dl->key = key;
|
||||
|
||||
return dl;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_DecayLights
|
||||
|
||||
===============
|
||||
*/
|
||||
void CL_DecayLights( void )
|
||||
{
|
||||
float time = GET_CLIENT_TIME();
|
||||
CDynLight *pl = tr.dlights;
|
||||
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++, pl++ )
|
||||
{
|
||||
if( !pl->radius ) continue;
|
||||
|
||||
pl->radius -= tr.frametime * pl->decay;
|
||||
if( pl->radius < 0.0f ) pl->radius = 0.0f;
|
||||
|
||||
if( pl->Expired( ))
|
||||
memset( pl, 0, sizeof( *pl ));
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================
|
||||
// HasDynamicLights
|
||||
//
|
||||
// Return count dynamic lights for current frame
|
||||
//=====================================
|
||||
int HasDynamicLights( void )
|
||||
{
|
||||
int numDlights = 0;
|
||||
|
||||
if( !worldmodel->lightdata || !CVAR_TO_BOOL( cv_dynamiclight ))
|
||||
return numDlights;
|
||||
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
CDynLight *pl = &tr.dlights[i];
|
||||
if( pl->Expired( )) continue;
|
||||
numDlights++;
|
||||
}
|
||||
|
||||
return numDlights;
|
||||
}
|
||||
|
||||
//=====================================
|
||||
// HasStaticLights
|
||||
//
|
||||
// Return count static lights for current frame
|
||||
//=====================================
|
||||
int HasStaticLights( void )
|
||||
{
|
||||
int i, numLights = 0;
|
||||
mworldlight_t *wl;
|
||||
|
||||
for( i = 0, wl = world->worldlights; i < world->numworldlights; i++, wl++ )
|
||||
{
|
||||
if( wl->emittype == emit_ignored )
|
||||
continue;
|
||||
|
||||
if( !CHECKVISBIT( RI->view.vislight, i ))
|
||||
continue;
|
||||
numLights++;
|
||||
}
|
||||
|
||||
return numLights;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
==================
|
||||
R_AnimateLight
|
||||
|
||||
==================
|
||||
*/
|
||||
void R_AnimateLight( void )
|
||||
{
|
||||
int i, k, flight, clight;
|
||||
float l, lerpfrac, backlerp;
|
||||
float scale = 1.0f;
|
||||
lightstyle_t *ls;
|
||||
|
||||
scale = tr.diffuseFactor;
|
||||
|
||||
if( tr.realframecount != 1 && !CVAR_TO_BOOL( r_lightstyles ))
|
||||
return;
|
||||
|
||||
// light animations
|
||||
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||
for( i = 0; i < MAX_LIGHTSTYLES; i++ )
|
||||
{
|
||||
ls = GET_LIGHTSTYLE( i );
|
||||
|
||||
if( !worldmodel->lightdata )
|
||||
{
|
||||
tr.lightstyle[i] = 256.0f * scale;
|
||||
continue;
|
||||
}
|
||||
|
||||
flight = (int)Q_floor( ls->time * 10.0f );
|
||||
clight = (int)Q_ceil( ls->time * 10.0f );
|
||||
lerpfrac = ( ls->time * 10 ) - flight;
|
||||
backlerp = 1.0f - lerpfrac;
|
||||
|
||||
if( !ls->length )
|
||||
{
|
||||
tr.lightstyle[i] = 256.0f * scale;
|
||||
continue;
|
||||
}
|
||||
else if( ls->length == 1 )
|
||||
{
|
||||
float value = ls->map[0];
|
||||
|
||||
// turn off the baked sunlight
|
||||
if( tr.sun_light_enabled && i == LS_SKY )
|
||||
value = (float)('a' - 'a');
|
||||
|
||||
// single length style so don't bother interpolating
|
||||
tr.lightstyle[i] = value * 22.0f * scale;
|
||||
continue;
|
||||
}
|
||||
else if( !ls->interp || !CVAR_TO_BOOL( r_lightstyle_lerping ))
|
||||
{
|
||||
tr.lightstyle[i] = ls->map[flight%ls->length] * 22.0f * scale;
|
||||
continue;
|
||||
}
|
||||
|
||||
// interpolate animating light
|
||||
// frame just gone
|
||||
k = ls->map[flight % ls->length];
|
||||
l = (float)( k * 22.0f ) * backlerp;
|
||||
|
||||
// upcoming frame
|
||||
k = ls->map[clight % ls->length];
|
||||
l += (float)( k * 22.0f ) * lerpfrac;
|
||||
|
||||
tr.lightstyle[i] = l * scale;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
GATHER DYNAMIC LIGHTING
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
R_LightsForPoint
|
||||
=================
|
||||
*/
|
||||
Vector R_LightsForPoint( const Vector &point, float radius )
|
||||
{
|
||||
Vector lightColor;
|
||||
|
||||
if( radius <= 0.0f )
|
||||
radius = 1.0f;
|
||||
|
||||
lightColor = g_vecZero;
|
||||
|
||||
for( int lnum = 0; lnum < MAX_DLIGHTS; lnum++ )
|
||||
{
|
||||
CDynLight *dl = &tr.dlights[lnum];
|
||||
float atten = 1.0f;
|
||||
|
||||
if( dl->type == LIGHT_DIRECTIONAL )
|
||||
continue;
|
||||
|
||||
if( dl->die < GET_CLIENT_TIME() || !dl->radius )
|
||||
continue;
|
||||
|
||||
Vector dir = (dl->origin - point);
|
||||
float dist = dir.Length();
|
||||
|
||||
if( !dist || dist > ( dl->radius + radius ))
|
||||
continue;
|
||||
|
||||
if( dl->frustum.CullSphere( point, radius ))
|
||||
continue;
|
||||
|
||||
atten = 1.0 - saturate( pow( dist * ( 1.0f / dl->radius ), 2.2f ));
|
||||
if( atten <= 0.0 ) continue; // fast reject
|
||||
|
||||
if( dl->type == LIGHT_SPOT )
|
||||
{
|
||||
Vector lightDir = dl->frustum.GetPlane( FRUSTUM_FAR )->normal.Normalize();
|
||||
float fov_x, fov_y;
|
||||
|
||||
// BUGBUG: we use 5:4 aspect not an 4:3
|
||||
if( dl->flags & DLF_ASPECT3X4 )
|
||||
fov_y = dl->fov * (5.0f / 4.0f);
|
||||
else if( dl->flags & DLF_ASPECT4X3 )
|
||||
fov_y = dl->fov * (4.0f / 5.0f);
|
||||
else fov_y = dl->fov;
|
||||
fov_x = dl->fov;
|
||||
|
||||
// spot attenuation
|
||||
float spotDot = DotProduct( dir.Normalize(), lightDir );
|
||||
fov_x = DEG2RAD( fov_x * 0.25f );
|
||||
fov_y = DEG2RAD( fov_y * 0.25f );
|
||||
float spotCos = cos( fov_x + fov_y );
|
||||
if( spotDot < spotCos ) continue;
|
||||
}
|
||||
|
||||
lightColor += (dl->color * 0.5f * atten);
|
||||
}
|
||||
|
||||
return lightColor;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_GetLightVectors
|
||||
|
||||
Get light vectors for entity
|
||||
================
|
||||
*/
|
||||
void R_GetLightVectors( cl_entity_t *pEnt, Vector &origin, Vector &angles )
|
||||
{
|
||||
// fill default case
|
||||
origin = pEnt->origin;
|
||||
angles = pEnt->angles;
|
||||
|
||||
// try to grab position from attachment
|
||||
if( pEnt->curstate.aiment > 0 && pEnt->curstate.movetype == MOVETYPE_FOLLOW )
|
||||
{
|
||||
cl_entity_t *pParent = GET_ENTITY( pEnt->curstate.aiment );
|
||||
studiohdr_t *pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata( pParent->model );
|
||||
|
||||
if( pParent && pParent->model && pStudioHeader != NULL )
|
||||
{
|
||||
// make sure what model really has attachements
|
||||
if( pEnt->curstate.body > 0 && ( pStudioHeader && pStudioHeader->numattachments > 0 ))
|
||||
{
|
||||
int num = bound( 1, pEnt->curstate.body, MAXSTUDIOATTACHMENTS );
|
||||
R_StudioAttachmentPosAng( pParent, num - 1, &origin, &angles );
|
||||
angles[PITCH] = -angles[PITCH]; // stupid quake bug
|
||||
}
|
||||
else if( pParent->curstate.movetype == MOVETYPE_STEP )
|
||||
{
|
||||
origin = pParent->origin;
|
||||
angles = pParent->angles;
|
||||
|
||||
// add the eye position for monster
|
||||
if( pParent->curstate.eflags & EFLAG_SLERP )
|
||||
origin += pStudioHeader->eyeposition;
|
||||
}
|
||||
else
|
||||
{
|
||||
origin = pParent->origin;
|
||||
angles = pParent->angles;
|
||||
}
|
||||
}
|
||||
}
|
||||
// all other parent types will be attached on the server
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_SetupLightTexture
|
||||
|
||||
Must be called after R_SetupLightParams
|
||||
================
|
||||
*/
|
||||
void R_SetupLightTexture( CDynLight *pl, int texture )
|
||||
{
|
||||
ASSERT( pl != NULL );
|
||||
|
||||
pl->spotlightTexture = texture;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_SetupLightParams
|
||||
================
|
||||
*/
|
||||
void R_SetupLightParams( CDynLight *pl, const Vector &origin, const Vector &angles, float radius, float fov, int type, int flags )
|
||||
{
|
||||
pl->type = bound( LIGHT_SPOT, type, LIGHT_DIRECTIONAL );
|
||||
|
||||
if( pl->type == LIGHT_OMNI )
|
||||
{
|
||||
for( int i = 0; i < MAX_SHADOWMAPS; i++ )
|
||||
pl->shadowTexture[i] = tr.depthCubemap; // stub
|
||||
|
||||
if( !GL_Support( R_TEXTURECUBEMAP_EXT ))
|
||||
flags |= DLF_NOSHADOWS;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < MAX_SHADOWMAPS; i++ )
|
||||
pl->shadowTexture[i] = tr.depthTexture; // stub
|
||||
}
|
||||
|
||||
if( pl->origin != origin || pl->angles != angles || pl->fov != fov || pl->radius != radius || pl->flags != flags )
|
||||
{
|
||||
pl->origin = origin;
|
||||
pl->angles = angles;
|
||||
pl->radius = radius;
|
||||
pl->flags = flags;
|
||||
pl->update = true;
|
||||
pl->fov = fov;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_SetupLightProjection
|
||||
|
||||
General setup light projections.
|
||||
Calling only once per frame
|
||||
================
|
||||
*/
|
||||
void R_SetupLightProjection( CDynLight *pl )
|
||||
{
|
||||
if( !pl->update )
|
||||
{
|
||||
if( pl->type != LIGHT_DIRECTIONAL )
|
||||
{
|
||||
if( !R_ScissorForFrustum( &pl->frustum, &pl->x, &pl->y, &pl->w, &pl->h ))
|
||||
SetBits( pl->flags, DLF_CULLED );
|
||||
else ClearBits( pl->flags, DLF_CULLED );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( pl->type == LIGHT_SPOT )
|
||||
{
|
||||
float fov_x, fov_y;
|
||||
|
||||
// BUGBUG: we use 5:4 aspect not an 4:3
|
||||
if( pl->flags & DLF_ASPECT3X4 )
|
||||
fov_y = pl->fov * (5.0f / 4.0f);
|
||||
else if( pl->flags & DLF_ASPECT4X3 )
|
||||
fov_y = pl->fov * (4.0f / 5.0f);
|
||||
else fov_y = pl->fov;
|
||||
|
||||
// e.g. for fake cinema projectors
|
||||
if( FBitSet( pl->flags, DLF_FLIPTEXTURE ))
|
||||
fov_x = -pl->fov;
|
||||
else fov_x = pl->fov;
|
||||
|
||||
pl->projectionMatrix.CreateProjection( fov_x, fov_y, Z_NEAR_LIGHT, pl->radius );
|
||||
pl->modelviewMatrix.CreateModelview(); // init quake world orientation
|
||||
pl->viewMatrix = matrix4x4( pl->origin, pl->angles );
|
||||
|
||||
// transform projector by position and angles
|
||||
pl->modelviewMatrix.ConcatRotate( -pl->angles.z, 1, 0, 0 );
|
||||
pl->modelviewMatrix.ConcatRotate( -pl->angles.x, 0, 1, 0 );
|
||||
pl->modelviewMatrix.ConcatRotate( -pl->angles.y, 0, 0, 1 );
|
||||
pl->modelviewMatrix.ConcatTranslate( -pl->origin.x, -pl->origin.y, -pl->origin.z );
|
||||
|
||||
pl->frustum.InitProjection( pl->viewMatrix, Z_NEAR_LIGHT, pl->radius, pl->fov, fov_y );
|
||||
pl->frustum.ComputeFrustumBounds( pl->absmin, pl->absmax );
|
||||
pl->frustum.DisablePlane( FRUSTUM_FAR ); // only use plane.normal
|
||||
}
|
||||
else if( pl->type == LIGHT_OMNI )
|
||||
{
|
||||
pl->modelviewMatrix.CreateModelview();
|
||||
pl->viewMatrix = matrix4x4( pl->origin, g_vecZero );
|
||||
pl->projectionMatrix.CreateProjection( 90.0f, 90.0f, Z_NEAR_LIGHT, pl->radius );
|
||||
|
||||
// transform omnilight by position
|
||||
pl->modelviewMatrix.ConcatTranslate( -pl->origin.x, -pl->origin.y, -pl->origin.z );
|
||||
|
||||
pl->frustum.InitBoxFrustum( pl->origin, pl->radius );
|
||||
pl->frustum.ComputeFrustumBounds( pl->absmin, pl->absmax );
|
||||
}
|
||||
else if( pl->type == LIGHT_DIRECTIONAL )
|
||||
{
|
||||
Vector skyDir, angles, up;
|
||||
|
||||
skyDir = tr.sky_normal.Normalize();
|
||||
VectorAngles2( skyDir, angles );
|
||||
AngleVectors( angles, NULL, NULL, up );
|
||||
|
||||
pl->viewMatrix.LookAt( tr.cached_vieworigin, skyDir, up );
|
||||
pl->modelviewMatrix = pl->viewMatrix;
|
||||
|
||||
ClearBounds( pl->absmin, pl->absmax );
|
||||
}
|
||||
else
|
||||
{
|
||||
HOST_ERROR( "R_SetupLightProjection: unknown light type %i\n", pl->type );
|
||||
}
|
||||
|
||||
if( pl->type != LIGHT_DIRECTIONAL )
|
||||
{
|
||||
matrix4x4 projectionView, s1;
|
||||
|
||||
projectionView = pl->projectionMatrix.Concat( pl->modelviewMatrix );
|
||||
pl->lightviewProjMatrix = projectionView;
|
||||
|
||||
s1.CreateTranslate( 0.5f, 0.5f, 0.5f );
|
||||
s1.ConcatScale( 0.5f, 0.5f, 0.5f );
|
||||
|
||||
pl->textureMatrix[0] = projectionView;
|
||||
pl->shadowMatrix[0] = s1.Concat( projectionView );
|
||||
|
||||
if( !R_ScissorForFrustum( &pl->frustum, &pl->x, &pl->y, &pl->w, &pl->h ))
|
||||
SetBits( pl->flags, DLF_CULLED );
|
||||
else ClearBits( pl->flags, DLF_CULLED );
|
||||
}
|
||||
|
||||
pl->update = false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_SetupDynamicLights
|
||||
================
|
||||
*/
|
||||
void R_SetupDynamicLights( void )
|
||||
{
|
||||
CDynLight *pl;
|
||||
dlight_t *dl;
|
||||
|
||||
for( int lnum = 0; lnum < MAX_ENGINE_DLIGHTS; lnum++ )
|
||||
{
|
||||
dl = GET_DYNAMIC_LIGHT( lnum );
|
||||
pl = &tr.dlights[MAX_ENGINE_DLIGHTS+lnum];
|
||||
|
||||
// NOTE: here we copies dlight settings 'as-is'
|
||||
// without reallocating by key because key may
|
||||
// be set indirectly without call CL_AllocDlight
|
||||
if( dl->die < GET_CLIENT_TIME() || !dl->radius )
|
||||
{
|
||||
// light is expired. Clear it
|
||||
memset( pl, 0, sizeof( *pl ));
|
||||
continue;
|
||||
}
|
||||
|
||||
pl->key = dl->key;
|
||||
pl->die = dl->die + tr.frametime;
|
||||
pl->decay = dl->decay;
|
||||
pl->color.x = dl->color.r * (1.0 / 255.0f);
|
||||
pl->color.y = dl->color.g * (1.0 / 255.0f);
|
||||
pl->color.z = dl->color.b * (1.0 / 255.0f);
|
||||
pl->origin = dl->origin;
|
||||
pl->radius = dl->radius;
|
||||
pl->type = LIGHT_OMNI;
|
||||
pl->update = true;
|
||||
|
||||
R_SetupLightProjection( pl );
|
||||
}
|
||||
|
||||
pl = tr.dlights;
|
||||
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++, pl++ )
|
||||
{
|
||||
if( pl->Expired( )) continue;
|
||||
R_SetupLightProjection( pl );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
WORLDLIGHTS PROCESSING
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
static vec_t LightDistanceFalloff( const mworldlight_t *wl, const Vector &direction )
|
||||
{
|
||||
Vector delta = direction;
|
||||
float dist = VectorNormalize( delta );
|
||||
float dot = 1.0f; // assume dot is 1.0f
|
||||
|
||||
dist = Q_max( dist, 1.0 );
|
||||
|
||||
switch( wl->emittype )
|
||||
{
|
||||
case emit_surface:
|
||||
return dot / (dist * dist);
|
||||
case emit_skylight:
|
||||
return dot;
|
||||
break;
|
||||
case emit_spotlight: // directional & positional
|
||||
case emit_point:
|
||||
// cull out stuff that's too far
|
||||
if( dist > wl->radius )
|
||||
return 0.0f;
|
||||
return dot / (dist * dist);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This method returns the effective intensity of a light as seen from
|
||||
// a particular point. PVS is used to speed up the task.
|
||||
//-----------------------------------------------------------------------------
|
||||
static float LightIntensityAtPoint( mworldlight_t *wl, const Vector &mid, bool skipZ )
|
||||
{
|
||||
lightzbuffer_t *pZBuf = world->shadowzbuffers;
|
||||
Vector direction;
|
||||
|
||||
// special case lights
|
||||
if( wl->emittype == emit_skylight )
|
||||
{
|
||||
// check to see if you can hit the sky texture
|
||||
Vector end = mid + wl->normal * -BOGUS_RANGE; // max_range * sqrt(3)
|
||||
msurface_t *surf = gEngfuncs.pEventAPI->EV_TraceSurface( 0, (float *)&mid, (float *)end );
|
||||
|
||||
// here, we didn't hit the sky, so we must be in shadow
|
||||
if( !surf || !FBitSet( surf->flags, SURF_DRAWSKY ))
|
||||
return 0.0f;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// all other lights
|
||||
|
||||
// check distance
|
||||
direction = wl->origin - mid;
|
||||
float ratio = LightDistanceFalloff( wl, direction );
|
||||
|
||||
// Early out for really low-intensity lights
|
||||
// That way we don't need to ray-cast or normalize
|
||||
float intensity = VectorMax( wl->intensity );
|
||||
|
||||
if( intensity * ratio < 4e-3 )
|
||||
return 0.0f;
|
||||
|
||||
if( skipZ ) return ratio;
|
||||
float dist = VectorNormalize( direction );
|
||||
|
||||
float flTraceDistance = dist;
|
||||
|
||||
// check if we are so close to the light that we shouldn't use our coarse z buf
|
||||
if( dist < 8 * SHADOW_ZBUF_RES )
|
||||
pZBuf = NULL;
|
||||
|
||||
LightShadowZBufferSample_t *pSample = NULL;
|
||||
Vector epnt = mid;
|
||||
|
||||
if( pZBuf )
|
||||
{
|
||||
pSample = &( pZBuf->GetSample( direction ));
|
||||
|
||||
if(( pSample->m_flHitDistance < pSample->m_flTraceDistance ) || ( pSample->m_flTraceDistance >= dist ))
|
||||
{
|
||||
// hit!
|
||||
if( dist > pSample->m_flHitDistance + 8 ) // shadow hit
|
||||
return 0;
|
||||
return ratio;
|
||||
}
|
||||
|
||||
// cache miss
|
||||
flTraceDistance = Q_max( 100.0f, 2.0f * dist ); // trace a little further for better caching
|
||||
epnt += direction * ( dist - flTraceDistance );
|
||||
}
|
||||
|
||||
pmtrace_t pm;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( wl->origin, epnt, PM_WORLD_ONLY, -1, &pm );
|
||||
// pm.fraction = 1.0f - pm.fraction;
|
||||
|
||||
float flHitDistance = ( pm.startsolid ) ? FLT_EPSILON : ( pm.fraction ) * flTraceDistance;
|
||||
|
||||
if( pSample )
|
||||
{
|
||||
pSample->m_flTraceDistance = flTraceDistance;
|
||||
pSample->m_flHitDistance = ( pm.fraction >= 1.0 ) ? 1.0e23 : flHitDistance;
|
||||
}
|
||||
|
||||
if( dist > flHitDistance + 8 )
|
||||
return 0.0f;
|
||||
|
||||
return ratio;
|
||||
}
|
||||
|
||||
static float LightIntensityInBox( mworldlight_t *wl, const Vector &mid, const Vector &mins, const Vector &maxs, bool skipZ )
|
||||
{
|
||||
float sphereRadius;
|
||||
float angle, sinAngle;
|
||||
float dist, distSqr;
|
||||
|
||||
// Choose the point closest on the box to the light to get max intensity
|
||||
// within the box....
|
||||
switch( wl->emittype )
|
||||
{
|
||||
case emit_spotlight: // directional & positional
|
||||
sphereRadius = (maxs - mid).Length();
|
||||
// first do a sphere/sphere check
|
||||
dist = (wl->origin - mid).Length();
|
||||
if( dist > (sphereRadius + wl->radius ))
|
||||
return 0;
|
||||
// PERFORMANCE: precalc this and store in the light?
|
||||
angle = acos( wl->stopdot2 );
|
||||
sinAngle = sin( angle );
|
||||
if( !IsSphereIntersectingCone( mid, sphereRadius, wl->origin, wl->normal, sinAngle, wl->stopdot2 ))
|
||||
return 0;
|
||||
// NOTE: fall through to radius check in point case
|
||||
case emit_point:
|
||||
distSqr = CalcSqrDistanceToAABB( mins, maxs, wl->origin );
|
||||
if( distSqr > wl->radius * wl->radius )
|
||||
return 0;
|
||||
break;
|
||||
case emit_surface: // directional & positional, fixed cone size
|
||||
sphereRadius = (maxs - mid).Length();
|
||||
// first do a sphere/sphere check
|
||||
dist = (wl->origin - mid).Length();
|
||||
if( dist > ( sphereRadius + wl->radius ))
|
||||
return 0;
|
||||
// PERFORMANCE: precalc this and store in the light?
|
||||
if( !IsSphereIntersectingCone( mid, sphereRadius, wl->origin, wl->normal, 1.0f, 0.0f ))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return LightIntensityAtPoint( wl, mid, skipZ );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_FindWorldLights
|
||||
|
||||
search for lights that potentially can lit bbox
|
||||
=================
|
||||
*/
|
||||
void R_FindWorldLights( const Vector &origin, const Vector &mins, const Vector &maxs, byte lights[MAXDYNLIGHTS], bool skipZ )
|
||||
{
|
||||
mworldlight_t *wl = world->worldlights;
|
||||
Vector absmin = origin + mins;
|
||||
Vector absmax = origin + maxs;
|
||||
vec2_t indexes[32];
|
||||
int count = 0;
|
||||
|
||||
for( int i = 0; i < world->numworldlights; i++, wl++ )
|
||||
{
|
||||
if( !Mod_BoxVisible( absmin, absmax, wl->pvs ))
|
||||
continue;
|
||||
|
||||
float ratio = LightIntensityInBox( wl, origin, mins, maxs, skipZ );
|
||||
|
||||
// no light contribution?
|
||||
if( ratio <= 0.0f ) continue;
|
||||
|
||||
Vector add = wl->intensity * ratio;
|
||||
float illum = VectorMax( add );
|
||||
//Msg( "#%i, type %d, illum %.5f, intensity %g %g %g\n", i, wl->emittype, illum, wl->intensity[0], wl->intensity[1], wl->intensity[2] );
|
||||
if( illum <= 4e-3 )
|
||||
continue;
|
||||
|
||||
if( count >= ARRAYSIZE( indexes ) / 2 )
|
||||
break;
|
||||
|
||||
indexes[count][0] = i;
|
||||
indexes[count][1] = illum;
|
||||
count++;
|
||||
}
|
||||
|
||||
memset( lights, 255, sizeof( byte ) * MAXDYNLIGHTS );
|
||||
get_next_light:
|
||||
float maxIllum = 0.0;
|
||||
int ignored = -1;
|
||||
int light = 255;
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( indexes[i][0] == -1.0f )
|
||||
continue;
|
||||
|
||||
// skylight has a maximum priority
|
||||
if( indexes[i][1] > maxIllum )
|
||||
{
|
||||
maxIllum = indexes[i][1];
|
||||
light = indexes[i][0];
|
||||
ignored = i;
|
||||
}
|
||||
}
|
||||
|
||||
if( ignored == -1 )
|
||||
return;
|
||||
|
||||
for( i = 0; i < (int)cv_deferred_maxlights->value && lights[i] != 255; i++ );
|
||||
if( i < (int)cv_deferred_maxlights->value )
|
||||
lights[i] = light; // nearest light for surf
|
||||
indexes[ignored][0] = -1; // this light is handled
|
||||
|
||||
// if( count > (int)cv_deferred_maxlights->value && i == (int)cv_deferred_maxlights->value )
|
||||
// Msg( "skipped light %i intensity %g, type %d\n", light, maxIllum, world->worldlights[light].emittype );
|
||||
goto get_next_light;
|
||||
}
|
1029
cl_dll/render/gl_export.cpp
Normal file
1029
cl_dll/render/gl_export.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1366
cl_dll/render/gl_export.h
Normal file
1366
cl_dll/render/gl_export.h
Normal file
File diff suppressed because it is too large
Load Diff
628
cl_dll/render/gl_framebuffer.cpp
Normal file
628
cl_dll/render/gl_framebuffer.cpp
Normal file
@ -0,0 +1,628 @@
|
||||
/*
|
||||
gl_framebuffer.cpp - framebuffer implementation class
|
||||
Copyright (C) 2014 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
#include <mathlib.h>
|
||||
#include <stringlib.h>
|
||||
|
||||
static gl_drawbuffer_t gl_drawbuffers[MAX_FRAMEBUFFERS];
|
||||
static int gl_num_drawbuffers;
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_AllocDrawbuffer
|
||||
==================
|
||||
*/
|
||||
gl_drawbuffer_t *GL_AllocDrawbuffer( const char *name, int width, int height, int depth )
|
||||
{
|
||||
gl_drawbuffer_t *fbo;
|
||||
int i;
|
||||
|
||||
if( !GL_Support( R_FRAMEBUFFER_OBJECT ))
|
||||
return NULL;
|
||||
|
||||
// find a free FBO slot
|
||||
for( i = 0, fbo = gl_drawbuffers; i < gl_num_drawbuffers; i++, fbo++ )
|
||||
if( !fbo->name[0] ) break;
|
||||
|
||||
if( i == gl_num_drawbuffers )
|
||||
{
|
||||
if( gl_num_drawbuffers == MAX_FRAMEBUFFERS )
|
||||
HOST_ERROR( "GL_AllocDrawBuffer: MAX_FRAMEBUFFERS limit exceeds\n" );
|
||||
gl_num_drawbuffers++;
|
||||
}
|
||||
|
||||
if( !GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
|
||||
{
|
||||
width = NearestPOW( width, true );
|
||||
height = NearestPOW( height, true );
|
||||
}
|
||||
|
||||
// fill it in
|
||||
Q_strncpy( fbo->name, name, sizeof( fbo->name ));
|
||||
|
||||
// make sure it's fit in limits
|
||||
fbo->width = Q_min( glConfig.max_2d_texture_size, width );
|
||||
fbo->height = Q_min( glConfig.max_2d_texture_size, height );
|
||||
fbo->depth = depth;
|
||||
|
||||
// generate the drawbuffer
|
||||
pglGenFramebuffers( 1, &fbo->id );
|
||||
|
||||
return fbo;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_ResizeDrawbuffer
|
||||
==================
|
||||
*/
|
||||
void GL_ResizeDrawbuffer( gl_drawbuffer_t *fbo, int width, int height, int depth )
|
||||
{
|
||||
ASSERT( fbo != NULL );
|
||||
|
||||
// fill it in
|
||||
fbo->width = width;
|
||||
fbo->height = height;
|
||||
fbo->depth = depth;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_AttachColorTextureToFBO
|
||||
==================
|
||||
*/
|
||||
void GL_AttachColorTextureToFBO( gl_drawbuffer_t *fbo, int texture, int colorIndex, int index )
|
||||
{
|
||||
GLuint target = RENDER_GET_PARM( PARM_TEX_TARGET, texture );
|
||||
GLuint format = RENDER_GET_PARM( PARM_TEX_GLFORMAT, texture );
|
||||
GLint width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
GLint height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
GLint depth = RENDER_GET_PARM( PARM_TEX_DEPTH, texture );
|
||||
|
||||
if( target == GL_TEXTURE_2D )
|
||||
{
|
||||
// set the texture
|
||||
fbo->colortarget[colorIndex] = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_2d_texture_size || fbo->height > glConfig.max_2d_texture_size )
|
||||
HOST_ERROR( "GL_AttachColorTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_2d_texture_size, fbo->height, glConfig.max_2d_texture_size );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
|
||||
pglTexImage2D( target, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// Bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// Set up the color attachment
|
||||
pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + colorIndex, GL_TEXTURE_2D, texture, 0 );
|
||||
}
|
||||
else if( target == GL_TEXTURE_CUBE_MAP_ARB )
|
||||
{
|
||||
// set the texture
|
||||
fbo->colortarget[colorIndex] = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_cubemap_size || fbo->height > glConfig.max_cubemap_size )
|
||||
HOST_ERROR( "GL_AttachColorTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_cubemap_size, fbo->height, glConfig.max_cubemap_size );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, format, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// set up the color attachment
|
||||
pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + colorIndex, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + index, texture, 0 );
|
||||
}
|
||||
else if( target == GL_TEXTURE_2D_ARRAY_EXT )
|
||||
{
|
||||
// Set the texture
|
||||
fbo->colortarget[colorIndex] = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height || depth != fbo->depth )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_2d_texture_size || fbo->height > glConfig.max_2d_texture_size || fbo->depth > glConfig.max_2d_texture_layers )
|
||||
HOST_ERROR( "GL_AttachColorTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_2d_texture_size, fbo->height, glConfig.max_2d_texture_size, fbo->depth, glConfig.max_2d_texture_layers );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
fbo->depth = RENDER_GET_PARM( PARM_TEX_DEPTH, texture );
|
||||
|
||||
pglTexImage3D( target, 0, format, fbo->width, fbo->height, fbo->depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// Set up the color attachment
|
||||
pglFramebufferTextureLayer( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + colorIndex, texture, 0, index );
|
||||
}
|
||||
else if( target == GL_TEXTURE_3D )
|
||||
{
|
||||
// Set the texture
|
||||
fbo->colortarget[colorIndex] = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height || depth != fbo->depth )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_3d_texture_size || fbo->height > glConfig.max_3d_texture_size || fbo->depth > glConfig.max_3d_texture_size )
|
||||
HOST_ERROR( "GL_AttachColorTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_3d_texture_size, fbo->height, glConfig.max_3d_texture_size, fbo->depth, glConfig.max_3d_texture_size );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
fbo->depth = RENDER_GET_PARM( PARM_TEX_DEPTH, texture );
|
||||
|
||||
pglTexImage3D( target, 0, format, fbo->width, fbo->height, fbo->depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// Set up the color attachment
|
||||
pglFramebufferTexture3D( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + colorIndex, GL_TEXTURE_3D, texture, 0, index );
|
||||
}
|
||||
else
|
||||
{
|
||||
HOST_ERROR( "GL_AttachColorTextureToFBO: bad texture target (%i)\n", target );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_AttachDepthTextureToFBO
|
||||
==================
|
||||
*/
|
||||
void GL_AttachDepthTextureToFBO( gl_drawbuffer_t *fbo, int texture, int index )
|
||||
{
|
||||
GLuint target = RENDER_GET_PARM( PARM_TEX_TARGET, texture );
|
||||
GLuint format = RENDER_GET_PARM( PARM_TEX_GLFORMAT, texture );
|
||||
GLint width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
GLint height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
GLint depth = RENDER_GET_PARM( PARM_TEX_DEPTH, texture );
|
||||
|
||||
if( target == GL_TEXTURE_2D )
|
||||
{
|
||||
// set the texture
|
||||
fbo->depthtarget = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_2d_texture_size || fbo->height > glConfig.max_2d_texture_size )
|
||||
HOST_ERROR( "GL_AttachDepthTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_2d_texture_size, fbo->height, glConfig.max_2d_texture_size );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
|
||||
pglTexImage2D( target, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// Bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// Set up the color attachment
|
||||
pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texture, 0 );
|
||||
}
|
||||
else if( target == GL_TEXTURE_CUBE_MAP_ARB )
|
||||
{
|
||||
// set the texture
|
||||
fbo->depthtarget = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_cubemap_size || fbo->height > glConfig.max_cubemap_size )
|
||||
HOST_ERROR( "GL_AttachDepthTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_cubemap_size, fbo->height, glConfig.max_cubemap_size );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
pglTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, format, fbo->width, fbo->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// set up the color attachment
|
||||
pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + index, texture, 0 );
|
||||
}
|
||||
else if( target == GL_TEXTURE_2D_ARRAY_EXT )
|
||||
{
|
||||
// Set the texture
|
||||
fbo->depthtarget = texture;
|
||||
|
||||
// if the drawbuffer has been resized
|
||||
if( width != fbo->width || height != fbo->height || depth != fbo->depth )
|
||||
{
|
||||
// check the dimensions
|
||||
if( fbo->width > glConfig.max_2d_texture_size || fbo->height > glConfig.max_2d_texture_size || fbo->depth > glConfig.max_2d_texture_layers )
|
||||
HOST_ERROR( "GL_AttachDepthTextureToFBO: size exceeds hardware limits (%i > %i or %i > %i or %i > %i)\n",
|
||||
fbo->width, glConfig.max_2d_texture_size, fbo->height, glConfig.max_2d_texture_size, fbo->depth, glConfig.max_2d_texture_layers );
|
||||
|
||||
// reallocate the texture
|
||||
GL_UpdateTexSize( texture, fbo->width, fbo->height, fbo->depth );
|
||||
GL_BindTexture( GL_KEEP_UNIT, texture );
|
||||
|
||||
// need to refresh real FBO size with possible hardware limitations
|
||||
fbo->width = RENDER_GET_PARM( PARM_TEX_WIDTH, texture );
|
||||
fbo->height = RENDER_GET_PARM( PARM_TEX_HEIGHT, texture );
|
||||
fbo->depth = RENDER_GET_PARM( PARM_TEX_DEPTH, texture );
|
||||
|
||||
pglTexImage3D( target, 0, format, fbo->width, fbo->height, fbo->depth, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
}
|
||||
|
||||
// bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// Set up the color attachment
|
||||
pglFramebufferTextureLayer( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texture, 0, index );
|
||||
}
|
||||
else
|
||||
{
|
||||
HOST_ERROR( "GL_AttachDepthTextureToFBO: bad texture target (%i)\n", target );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_CheckFBOStatus
|
||||
==================
|
||||
*/
|
||||
void GL_CheckFBOStatus( gl_drawbuffer_t *fbo )
|
||||
{
|
||||
const char *string;
|
||||
int status;
|
||||
|
||||
// bind the drawbuffer
|
||||
GL_BindDrawbuffer( fbo );
|
||||
|
||||
// check the framebuffer status
|
||||
status = pglCheckFramebufferStatus( GL_FRAMEBUFFER_EXT );
|
||||
|
||||
if( status == GL_FRAMEBUFFER_COMPLETE_EXT )
|
||||
return;
|
||||
|
||||
switch( status )
|
||||
{
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
string = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
string = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
string = "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
string = "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
|
||||
string = "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
string = "GL_FRAMEBUFFER_UNSUPPORTED";
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNDEFINED_EXT:
|
||||
string = "GL_FRAMEBUFFER_UNDEFINED";
|
||||
break;
|
||||
default:
|
||||
string = "UNKNOWN STATUS";
|
||||
break;
|
||||
}
|
||||
|
||||
HOST_ERROR( "GL_CheckFBOStatus: %s for '%s'\n", string, fbo->name );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_FreeDrawbuffers
|
||||
==================
|
||||
*/
|
||||
void GL_FreeDrawbuffers( void )
|
||||
{
|
||||
gl_drawbuffer_t *fbo;
|
||||
|
||||
// unbind the drawbuffer
|
||||
GL_BindDrawbuffer( NULL );
|
||||
|
||||
// delete all the drawbuffers
|
||||
for( int i = 0; i < gl_num_drawbuffers; i++ )
|
||||
{
|
||||
fbo = &gl_drawbuffers[i];
|
||||
pglDeleteFramebuffers( 1, &fbo->id );
|
||||
}
|
||||
|
||||
// NOTE: let the engine release attached textures
|
||||
memset( gl_drawbuffers, 0, sizeof( gl_drawbuffers ));
|
||||
gl_num_drawbuffers = 0;
|
||||
}
|
||||
|
||||
CFrameBuffer :: CFrameBuffer( void )
|
||||
{
|
||||
m_iFrameWidth = m_iFrameHeight = 0;
|
||||
m_iFrameBuffer = m_iDepthBuffer = 0;
|
||||
m_iTexture = m_iAttachment = 0;
|
||||
|
||||
m_bAllowFBO = false;
|
||||
}
|
||||
|
||||
CFrameBuffer :: ~CFrameBuffer( void )
|
||||
{
|
||||
// NOTE: static case will be failed
|
||||
Free();
|
||||
}
|
||||
|
||||
int CFrameBuffer :: m_iBufferNum = 0;
|
||||
|
||||
bool CFrameBuffer :: Init( FBO_TYPE type, GLuint width, GLuint height, GLuint flags )
|
||||
{
|
||||
Free(); // release old buffer
|
||||
|
||||
m_iFlags = flags;
|
||||
|
||||
if( !GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
|
||||
SetBits( m_iFlags, FBO_MAKEPOW );
|
||||
|
||||
if( FBitSet( m_iFlags, FBO_MAKEPOW ))
|
||||
{
|
||||
width = NearestPOW( width, true );
|
||||
height = NearestPOW( height, true );
|
||||
}
|
||||
|
||||
// clamp size to hardware limits
|
||||
if( type == FBO_CUBE )
|
||||
{
|
||||
m_iFrameWidth = bound( 0, width, glConfig.max_cubemap_size );
|
||||
m_iFrameHeight = bound( 0, height, glConfig.max_cubemap_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iFrameWidth = bound( 0, width, glConfig.max_2d_texture_size );
|
||||
m_iFrameHeight = bound( 0, height, glConfig.max_2d_texture_size );
|
||||
}
|
||||
|
||||
if( !m_iFrameWidth || !m_iFrameHeight )
|
||||
{
|
||||
ALERT( at_error, "CFrameBuffer( %i x %i ) invalid size\n", m_iFrameWidth, m_iFrameHeight );
|
||||
return false;
|
||||
}
|
||||
|
||||
// create FBO texture
|
||||
if( !FBitSet( m_iFlags, FBO_NOTEXTURE ))
|
||||
{
|
||||
int texFlags = (TF_NOMIPMAP|TF_CLAMP);
|
||||
|
||||
if( type == FBO_CUBE )
|
||||
SetBits( texFlags, TF_CUBEMAP );
|
||||
else if( type == FBO_DEPTH )
|
||||
SetBits( texFlags, TF_DEPTHMAP );
|
||||
|
||||
if( !FBitSet( m_iFlags, FBO_LINEAR ))
|
||||
SetBits( texFlags, TF_NEAREST );
|
||||
|
||||
if( FBitSet( m_iFlags, FBO_FLOAT ))
|
||||
SetBits( texFlags, TF_ARB_FLOAT );
|
||||
|
||||
if( FBitSet( m_iFlags, FBO_RECTANGLE ))
|
||||
SetBits( texFlags, TF_RECTANGLE );
|
||||
|
||||
if( FBitSet( m_iFlags, FBO_LUMINANCE ))
|
||||
SetBits( texFlags, TF_LUMINANCE );
|
||||
else if( type == FBO_COLOR )
|
||||
SetBits( texFlags, TF_HAS_ALPHA );
|
||||
|
||||
m_iTexture = CREATE_TEXTURE( va( "*framebuffer#%i", m_iBufferNum++ ), m_iFrameWidth, m_iFrameHeight, NULL, texFlags );
|
||||
}
|
||||
|
||||
m_bAllowFBO = (GL_Support( R_FRAMEBUFFER_OBJECT )) ? true : false;
|
||||
|
||||
if( m_bAllowFBO )
|
||||
{
|
||||
// frame buffer
|
||||
pglGenFramebuffers( 1, &m_iFrameBuffer );
|
||||
pglBindFramebuffer( GL_FRAMEBUFFER_EXT, m_iFrameBuffer );
|
||||
|
||||
// depth buffer
|
||||
pglGenRenderbuffers( 1, &m_iDepthBuffer );
|
||||
pglBindRenderbuffer( GL_RENDERBUFFER_EXT, m_iDepthBuffer );
|
||||
pglRenderbufferStorage( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_iFrameWidth, m_iFrameHeight );
|
||||
|
||||
// attach depthbuffer to framebuffer
|
||||
pglFramebufferRenderbuffer( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_iDepthBuffer );
|
||||
|
||||
// attach the framebuffer to our texture, which may be a depth texture
|
||||
if( type == FBO_DEPTH )
|
||||
{
|
||||
m_iAttachment = GL_DEPTH_ATTACHMENT_EXT;
|
||||
pglDrawBuffer( GL_NONE );
|
||||
pglReadBuffer( GL_NONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iAttachment = GL_COLOR_ATTACHMENT0_EXT;
|
||||
pglDrawBuffer( m_iAttachment );
|
||||
pglReadBuffer( m_iAttachment );
|
||||
}
|
||||
|
||||
if( m_iTexture != 0 )
|
||||
{
|
||||
GLuint target = RENDER_GET_PARM( PARM_TEX_TARGET, m_iTexture );
|
||||
GLuint texnum = RENDER_GET_PARM( PARM_TEX_TEXNUM, m_iTexture );
|
||||
|
||||
if( target == GL_TEXTURE_CUBE_MAP_ARB )
|
||||
{
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
|
||||
for( int i = 0; i < 6; i++ )
|
||||
pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, m_iAttachment, target + i, texnum, 0 );
|
||||
}
|
||||
else pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, m_iAttachment, target, texnum, 0 );
|
||||
}
|
||||
|
||||
m_bAllowFBO = ValidateFBO();
|
||||
pglBindFramebuffer( GL_FRAMEBUFFER_EXT, 0 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFrameBuffer :: Free( void )
|
||||
{
|
||||
if( !m_bAllowFBO ) return;
|
||||
|
||||
if( !FBitSet( m_iFlags, FBO_NOTEXTURE ) && m_iTexture != 0 )
|
||||
FREE_TEXTURE( m_iTexture );
|
||||
|
||||
pglDeleteRenderbuffers( 1, &m_iDepthBuffer );
|
||||
pglDeleteFramebuffers( 1, &m_iFrameBuffer );
|
||||
|
||||
m_iFrameWidth = m_iFrameHeight = 0;
|
||||
m_iFrameBuffer = m_iDepthBuffer = 0;
|
||||
m_iTexture = m_iAttachment = 0;
|
||||
|
||||
m_bAllowFBO = false;
|
||||
}
|
||||
|
||||
bool CFrameBuffer :: ValidateFBO( void )
|
||||
{
|
||||
if( !GL_Support( R_FRAMEBUFFER_OBJECT ))
|
||||
return false;
|
||||
|
||||
// check FBO status
|
||||
GLenum status = pglCheckFramebufferStatus( GL_FRAMEBUFFER_EXT );
|
||||
|
||||
switch( status )
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
return true;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
ALERT( at_error, "CFrameBuffer: attachment is NOT complete\n" );
|
||||
return false;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
ALERT( at_error, "CFrameBuffer: no image is attached to FBO\n" );
|
||||
return false;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
ALERT( at_error, "CFrameBuffer: attached images have different dimensions\n" );
|
||||
return false;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
ALERT( at_error, "CFrameBuffer: color attached images have different internal formats\n" );
|
||||
return false;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
ALERT( at_error, "CFrameBuffer: draw buffer incomplete\n" );
|
||||
return false;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
ALERT( at_error, "CFrameBuffere: read buffer incomplete\n" );
|
||||
return false;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
ALERT( at_error, "CFrameBuffer: unsupported by current FBO implementation\n" );
|
||||
return false;
|
||||
default:
|
||||
ALERT( at_error, "CFrameBuffer: unknown error\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CFrameBuffer :: Bind( GLuint texture, GLuint side )
|
||||
{
|
||||
if( !m_bAllowFBO ) return;
|
||||
|
||||
if( glState.frameBuffer != m_iFrameBuffer )
|
||||
{
|
||||
pglBindFramebuffer( GL_FRAMEBUFFER_EXT, m_iFrameBuffer );
|
||||
glState.frameBuffer = m_iFrameBuffer;
|
||||
}
|
||||
|
||||
// change texture if needs
|
||||
if( FBitSet( m_iFlags, FBO_NOTEXTURE ) && texture != 0 )
|
||||
{
|
||||
m_iTexture = texture;
|
||||
|
||||
GLuint target = RENDER_GET_PARM( PARM_TEX_TARGET, m_iTexture );
|
||||
GLuint texnum = RENDER_GET_PARM( PARM_TEX_TEXNUM, m_iTexture );
|
||||
|
||||
if( target == GL_TEXTURE_CUBE_MAP_ARB )
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side;
|
||||
|
||||
pglFramebufferTexture2D( GL_FRAMEBUFFER_EXT, m_iAttachment, target, texnum, 0 );
|
||||
}
|
||||
|
||||
ValidateFBO();
|
||||
}
|
63
cl_dll/render/gl_framebuffer.h
Normal file
63
cl_dll/render/gl_framebuffer.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
gl_framebuffer.h - framebuffer implementation class
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_FRAMEBUFFER_H
|
||||
#define GL_FRAMEBUFFER_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FBO_COLOR = 0, // only color texture is used
|
||||
FBO_DEPTH, // only depth texture is used
|
||||
FBO_CUBE, // only color texture as cubemap is side
|
||||
} FBO_TYPE;
|
||||
|
||||
#define FBO_MAKEPOW (1<<0) // round buffer size to nearest pow
|
||||
#define FBO_NOTEXTURE (1<<1) // don't create texture on initialization
|
||||
#define FBO_FLOAT (1<<2) // use float texture
|
||||
#define FBO_RECTANGLE (1<<3) // use rectangle texture
|
||||
#define FBO_LINEAR (1<<4) // use linear filtering
|
||||
#define FBO_LUMINANCE (1<<5) // force to luminance texture
|
||||
|
||||
class CFrameBuffer
|
||||
{
|
||||
public:
|
||||
CFrameBuffer();
|
||||
~CFrameBuffer();
|
||||
|
||||
bool Init( FBO_TYPE type, GLuint width, GLuint height, GLuint flags = 0 );
|
||||
void Bind( GLuint texture = 0, GLuint side = 0 );
|
||||
bool ValidateFBO( void );
|
||||
void Free( void );
|
||||
|
||||
unsigned int GetWidth( void ) const { return m_iFrameWidth; }
|
||||
unsigned int GetHeight( void ) const { return m_iFrameHeight; }
|
||||
int GetTexture( void ) const { return m_iTexture; }
|
||||
bool Active( void ) const { return m_bAllowFBO; }
|
||||
protected:
|
||||
static int m_iBufferNum; // single object for all instances
|
||||
private:
|
||||
GLuint m_iFrameWidth;
|
||||
GLuint m_iFrameHeight;
|
||||
GLint m_iTexture;
|
||||
|
||||
GLuint m_iFrameBuffer;
|
||||
GLuint m_iDepthBuffer;
|
||||
GLenum m_iAttachment; // attachment type
|
||||
bool m_bAllowFBO; // FBO is valid
|
||||
GLuint m_iFlags; // member FBO flags
|
||||
};
|
||||
|
||||
#endif//GL_FRAMEBUFFER_H
|
374
cl_dll/render/gl_frustum.cpp
Normal file
374
cl_dll/render/gl_frustum.cpp
Normal file
@ -0,0 +1,374 @@
|
||||
/*
|
||||
gl_frustum.cpp - frustum test implementation class
|
||||
Copyright (C) 2014 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "ref_params.h"
|
||||
#include "gl_local.h"
|
||||
#include <mathlib.h>
|
||||
#include <stringlib.h>
|
||||
|
||||
void CFrustum :: ClearFrustum( void )
|
||||
{
|
||||
memset( planes, 0, sizeof( planes ));
|
||||
clipFlags = 0;
|
||||
}
|
||||
|
||||
void CFrustum :: EnablePlane( int side )
|
||||
{
|
||||
ASSERT( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
// make sure what plane is ready
|
||||
if( planes[side].normal != g_vecZero )
|
||||
SetBits( clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void CFrustum :: DisablePlane( int side )
|
||||
{
|
||||
ASSERT( side >= 0 && side < FRUSTUM_PLANES );
|
||||
ClearBits( clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void CFrustum :: InitProjection( const matrix4x4 &view, float flZNear, float flZFar, float flFovX, float flFovY )
|
||||
{
|
||||
float xs, xc;
|
||||
Vector normal;
|
||||
|
||||
// horizontal fov used for left and right planes
|
||||
SinCos( DEG2RAD( flFovX ) * 0.5f, &xs, &xc );
|
||||
|
||||
// setup left plane
|
||||
normal = view.GetForward() * xs + view.GetRight() * -xc;
|
||||
SetPlane( FRUSTUM_LEFT, normal, DotProduct( view.GetOrigin(), normal ));
|
||||
|
||||
// setup right plane
|
||||
normal = view.GetForward() * xs + view.GetRight() * xc;
|
||||
SetPlane( FRUSTUM_RIGHT, normal, DotProduct( view.GetOrigin(), normal ));
|
||||
|
||||
// vertical fov used for top and bottom planes
|
||||
SinCos( DEG2RAD( flFovY ) * 0.5f, &xs, &xc );
|
||||
|
||||
// setup bottom plane
|
||||
normal = view.GetForward() * xs + view.GetUp() * -xc;
|
||||
SetPlane( FRUSTUM_BOTTOM, normal, DotProduct( view.GetOrigin(), normal ));
|
||||
|
||||
// setup top plane
|
||||
normal = view.GetForward() * xs + view.GetUp() * xc;
|
||||
SetPlane( FRUSTUM_TOP, normal, DotProduct( view.GetOrigin(), normal ));
|
||||
|
||||
// setup far plane
|
||||
SetPlane( FRUSTUM_FAR, -view.GetForward(), DotProduct( -view.GetForward(), ( view.GetOrigin() + view.GetForward() * flZFar )));
|
||||
|
||||
// no need to setup backplane for general view. It's only used for portals and mirrors
|
||||
if( flZNear == 0.0f ) return;
|
||||
|
||||
// setup near plane
|
||||
SetPlane( FRUSTUM_NEAR, view.GetForward(), DotProduct( view.GetForward(), ( view.GetOrigin() + view.GetForward() * flZNear )));
|
||||
}
|
||||
|
||||
void CFrustum :: InitOrthogonal( const matrix4x4 &view, float xLeft, float xRight, float yBottom, float yTop, float flZNear, float flZFar )
|
||||
{
|
||||
// setup the near and far planes
|
||||
float orgOffset = DotProduct( view.GetOrigin(), view.GetForward() );
|
||||
|
||||
SetPlane( FRUSTUM_FAR, -view.GetForward(), -flZNear - orgOffset );
|
||||
SetPlane( FRUSTUM_NEAR, view.GetForward(), flZFar + orgOffset );
|
||||
|
||||
// setup left and right planes
|
||||
orgOffset = DotProduct( view.GetOrigin(), view.GetRight() );
|
||||
|
||||
SetPlane( FRUSTUM_LEFT, view.GetRight(), xLeft + orgOffset );
|
||||
SetPlane( FRUSTUM_RIGHT, -view.GetRight(), -xRight - orgOffset );
|
||||
|
||||
// setup top and buttom planes
|
||||
orgOffset = DotProduct( view.GetOrigin(), view.GetUp() );
|
||||
|
||||
SetPlane( FRUSTUM_TOP, view.GetUp(), yTop + orgOffset );
|
||||
SetPlane( FRUSTUM_BOTTOM, -view.GetUp(), -yBottom - orgOffset );
|
||||
}
|
||||
|
||||
void CFrustum :: InitBoxFrustum( const Vector &org, float radius )
|
||||
{
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
// setup normal for each direction
|
||||
Vector normal = g_vecZero;
|
||||
normal[((i >> 1) + 1) % 3] = (i & 1) ? 1.0f : -1.0f;
|
||||
SetPlane( i, normal, DotProduct( org, normal ) - radius );
|
||||
}
|
||||
}
|
||||
|
||||
void CFrustum :: InitProjectionFromMatrix( const matrix4x4 &projection )
|
||||
{
|
||||
// left
|
||||
planes[FRUSTUM_LEFT].normal[0] = projection[0][3] + projection[0][0];
|
||||
planes[FRUSTUM_LEFT].normal[1] = projection[1][3] + projection[1][0];
|
||||
planes[FRUSTUM_LEFT].normal[2] = projection[2][3] + projection[2][0];
|
||||
planes[FRUSTUM_LEFT].dist = -(projection[3][3] + projection[3][0]);
|
||||
|
||||
// right
|
||||
planes[FRUSTUM_RIGHT].normal[0] = projection[0][3] - projection[0][0];
|
||||
planes[FRUSTUM_RIGHT].normal[1] = projection[1][3] - projection[1][0];
|
||||
planes[FRUSTUM_RIGHT].normal[2] = projection[2][3] - projection[2][0];
|
||||
planes[FRUSTUM_RIGHT].dist = -(projection[3][3] - projection[3][0]);
|
||||
|
||||
// bottom
|
||||
planes[FRUSTUM_BOTTOM].normal[0] = projection[0][3] + projection[0][1];
|
||||
planes[FRUSTUM_BOTTOM].normal[1] = projection[1][3] + projection[1][1];
|
||||
planes[FRUSTUM_BOTTOM].normal[2] = projection[2][3] + projection[2][1];
|
||||
planes[FRUSTUM_BOTTOM].dist = -(projection[3][3] + projection[3][1]);
|
||||
|
||||
// top
|
||||
planes[FRUSTUM_TOP].normal[0] = projection[0][3] - projection[0][1];
|
||||
planes[FRUSTUM_TOP].normal[1] = projection[1][3] - projection[1][1];
|
||||
planes[FRUSTUM_TOP].normal[2] = projection[2][3] - projection[2][1];
|
||||
planes[FRUSTUM_TOP].dist = -(projection[3][3] - projection[3][1]);
|
||||
|
||||
// near
|
||||
planes[FRUSTUM_NEAR].normal[0] = projection[0][3] + projection[0][2];
|
||||
planes[FRUSTUM_NEAR].normal[1] = projection[1][3] + projection[1][2];
|
||||
planes[FRUSTUM_NEAR].normal[2] = projection[2][3] + projection[2][2];
|
||||
planes[FRUSTUM_NEAR].dist = -(projection[3][3] + projection[3][2]);
|
||||
|
||||
// far
|
||||
planes[FRUSTUM_FAR].normal[0] = projection[0][3] - projection[0][2];
|
||||
planes[FRUSTUM_FAR].normal[1] = projection[1][3] - projection[1][2];
|
||||
planes[FRUSTUM_FAR].normal[2] = projection[2][3] - projection[2][2];
|
||||
planes[FRUSTUM_FAR].dist = -(projection[3][3] - projection[3][2]);
|
||||
|
||||
for( int i = 0; i < FRUSTUM_PLANES; i++ )
|
||||
{
|
||||
NormalizePlane( i );
|
||||
}
|
||||
}
|
||||
|
||||
void CFrustum :: SetPlane( int side, const Vector &vecNormal, float flDist )
|
||||
{
|
||||
ASSERT( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
planes[side].type = PlaneTypeForNormal( vecNormal );
|
||||
planes[side].signbits = SignbitsForPlane( vecNormal );
|
||||
planes[side].normal = vecNormal;
|
||||
planes[side].dist = flDist;
|
||||
|
||||
clipFlags |= BIT( side );
|
||||
}
|
||||
|
||||
void CFrustum :: NormalizePlane( int side )
|
||||
{
|
||||
ASSERT( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
// normalize
|
||||
float length = planes[side].normal.Length();
|
||||
|
||||
if( length )
|
||||
{
|
||||
float ilength = (1.0f / length);
|
||||
planes[side].normal.x *= ilength;
|
||||
planes[side].normal.y *= ilength;
|
||||
planes[side].normal.z *= ilength;
|
||||
planes[side].dist *= ilength;
|
||||
}
|
||||
|
||||
planes[side].type = PlaneTypeForNormal( planes[side].normal );
|
||||
planes[side].signbits = SignbitsForPlane( planes[side].normal );
|
||||
|
||||
clipFlags |= BIT( side );
|
||||
}
|
||||
|
||||
void CFrustum :: ComputeFrustumCorners( Vector corners[8] )
|
||||
{
|
||||
memset( corners, 0, sizeof( Vector ) * 8 );
|
||||
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_LEFT], &planes[FRUSTUM_TOP], &planes[FRUSTUM_FAR], corners[0] );
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_RIGHT], &planes[FRUSTUM_TOP], &planes[FRUSTUM_FAR], corners[1] );
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_LEFT], &planes[FRUSTUM_BOTTOM], &planes[FRUSTUM_FAR], corners[2] );
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_RIGHT], &planes[FRUSTUM_BOTTOM], &planes[FRUSTUM_FAR], corners[3] );
|
||||
|
||||
if( FBitSet( clipFlags, BIT( FRUSTUM_NEAR )))
|
||||
{
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_LEFT], &planes[FRUSTUM_TOP], &planes[FRUSTUM_NEAR], corners[4] );
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_RIGHT], &planes[FRUSTUM_TOP], &planes[FRUSTUM_NEAR], corners[5] );
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_LEFT], &planes[FRUSTUM_BOTTOM], &planes[FRUSTUM_NEAR], corners[6] );
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_RIGHT], &planes[FRUSTUM_BOTTOM], &planes[FRUSTUM_NEAR], corners[7] );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlanesGetIntersectionPoint( &planes[FRUSTUM_LEFT], &planes[FRUSTUM_RIGHT], &planes[FRUSTUM_TOP], corners[4] );
|
||||
corners[7] = corners[6] = corners[5] = corners[4];
|
||||
}
|
||||
}
|
||||
|
||||
void CFrustum :: ComputeFrustumBounds( Vector &mins, Vector &maxs )
|
||||
{
|
||||
Vector corners[8];
|
||||
|
||||
ComputeFrustumCorners( corners );
|
||||
|
||||
ClearBounds( mins, maxs );
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
AddPointToBounds( corners[i], mins, maxs );
|
||||
}
|
||||
|
||||
void CFrustum :: DrawFrustumDebug( void )
|
||||
{
|
||||
Vector bbox[8];
|
||||
|
||||
ComputeFrustumCorners( bbox );
|
||||
|
||||
// g-cont. frustum must be yellow :-)
|
||||
pglColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
|
||||
GL_BindTexture( GL_TEXTURE0, tr.whiteTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglBegin( GL_LINES );
|
||||
|
||||
for( int i = 0; i < 2; i += 1 )
|
||||
{
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i*2+0] );
|
||||
pglVertex3fv( bbox[i*2+1] );
|
||||
pglVertex3fv( bbox[i*2+4] );
|
||||
pglVertex3fv( bbox[i*2+5] );
|
||||
}
|
||||
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
bool CFrustum :: CullBox( const Vector &mins, const Vector &maxs, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
|
||||
if( CVAR_TO_BOOL( r_nocull ))
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = clipFlags;
|
||||
|
||||
for( int i = 0; i < FRUSTUM_PLANES; i++ )
|
||||
{
|
||||
if( !FBitSet( iClipFlags, BIT( i )))
|
||||
continue;
|
||||
|
||||
const mplane_t *p = &planes[i];
|
||||
|
||||
switch( p->signbits )
|
||||
{
|
||||
case 0:
|
||||
if( p->normal.x * maxs.x + p->normal.y * maxs.y + p->normal.z * maxs.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 1:
|
||||
if( p->normal.x * mins.x + p->normal.y * maxs.y + p->normal.z * maxs.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 2:
|
||||
if( p->normal.x * maxs.x + p->normal.y * mins.y + p->normal.z * maxs.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 3:
|
||||
if( p->normal.x * mins.x + p->normal.y * mins.y + p->normal.z * maxs.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 4:
|
||||
if( p->normal.x * maxs.x + p->normal.y * maxs.y + p->normal.z * mins.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 5:
|
||||
if( p->normal.x * mins.x + p->normal.y * maxs.y + p->normal.z * mins.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 6:
|
||||
if( p->normal.x * maxs.x + p->normal.y * mins.y + p->normal.z * mins.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 7:
|
||||
if( p->normal.x * mins.x + p->normal.y * mins.y + p->normal.z * mins.z < p->dist )
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CFrustum :: CullSphere( const Vector ¢re, float radius, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
|
||||
if( CVAR_TO_BOOL( r_nocull ))
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = clipFlags;
|
||||
|
||||
for( int i = 0; i < FRUSTUM_PLANES; i++ )
|
||||
{
|
||||
if( !FBitSet( iClipFlags, BIT( i )))
|
||||
continue;
|
||||
|
||||
const mplane_t *p = &planes[i];
|
||||
|
||||
if( DotProduct( centre, p->normal ) - p->dist <= -radius )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: could be optimize?
|
||||
bool CFrustum :: CullFrustum( CFrustum *frustum, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
Vector bbox[8];
|
||||
|
||||
if( CVAR_TO_BOOL( r_nocull ))
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = clipFlags;
|
||||
|
||||
frustum->ComputeFrustumCorners( bbox );
|
||||
|
||||
for( int i = 0; i < FRUSTUM_PLANES; i++ )
|
||||
{
|
||||
if( !FBitSet( iClipFlags, BIT( i )))
|
||||
continue;
|
||||
|
||||
const mplane_t *p = &planes[i];
|
||||
|
||||
for( int j = 0; j < 8; j++ )
|
||||
{
|
||||
// at least one point of other frustum intersect with our frustum
|
||||
if( DotProduct( bbox[j], p->normal ) - p->dist >= ON_EPSILON )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
60
cl_dll/render/gl_frustum.h
Normal file
60
cl_dll/render/gl_frustum.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
gl_frustum.h - frustum test implementation class
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_FRUSTUM_H
|
||||
#define GL_FRUSTUM_H
|
||||
|
||||
// don't change this order
|
||||
#define FRUSTUM_LEFT 0
|
||||
#define FRUSTUM_RIGHT 1
|
||||
#define FRUSTUM_BOTTOM 2
|
||||
#define FRUSTUM_TOP 3
|
||||
#define FRUSTUM_FAR 4
|
||||
#define FRUSTUM_NEAR 5
|
||||
#define FRUSTUM_PLANES 6
|
||||
|
||||
class CFrustum
|
||||
{
|
||||
public:
|
||||
void InitProjection( const matrix4x4 &view, float flZNear, float flZFar, float flFovX, float flFovY );
|
||||
void InitOrthogonal( const matrix4x4 &view, float xLeft, float xRight, float yBottom, float yTop, float flZNear, float flZFar );
|
||||
void InitBoxFrustum( const Vector &org, float radius ); // used for pointlights
|
||||
void InitProjectionFromMatrix( const matrix4x4 &projection );
|
||||
void SetPlane( int side, const mplane_t *plane ) { planes[side] = *plane; }
|
||||
void SetPlane( int side, const Vector &vecNormal, float flDist );
|
||||
void NormalizePlane( int side );
|
||||
const mplane_t *GetPlane( int side ) const { return &planes[side]; }
|
||||
const mplane_t *GetPlanes( void ) const { return &planes[0]; }
|
||||
unsigned int GetClipFlags( void ) const { return clipFlags; }
|
||||
void ComputeFrustumBounds( Vector &mins, Vector &maxs );
|
||||
void ComputeFrustumCorners( Vector bbox[8] );
|
||||
void DrawFrustumDebug( void );
|
||||
void ClearFrustum( void );
|
||||
|
||||
// cull methods
|
||||
bool CullBox( const Vector &mins, const Vector &maxs, int userClipFlags = 0 );
|
||||
bool CullSphere( const Vector ¢re, float radius, int userClipFlags = 0 );
|
||||
bool CullFrustum( CFrustum *frustum, int userClipFlags = 0 );
|
||||
|
||||
// plane manipulating
|
||||
void EnablePlane( int side );
|
||||
void DisablePlane( int side );
|
||||
private:
|
||||
mplane_t planes[FRUSTUM_PLANES];
|
||||
unsigned int clipFlags;
|
||||
};
|
||||
|
||||
#endif//GL_FRUSTUM_H
|
1775
cl_dll/render/gl_grass.cpp
Normal file
1775
cl_dll/render/gl_grass.cpp
Normal file
File diff suppressed because it is too large
Load Diff
116
cl_dll/render/gl_grass.h
Normal file
116
cl_dll/render/gl_grass.h
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
gl_grass.h - grass construct & rendering
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_GRASS_H
|
||||
#define GL_GRASS_H
|
||||
|
||||
#define GRASS_TEXTURES 256 // unique textures for grass (a byte limit, don't change)
|
||||
#define GRASS_ANIM_DIST 512.0f // if this is changed it must be changed in glsl too!
|
||||
#define MAX_GRASS_ELEMS 65536 // unsigned short limit
|
||||
#define MAX_GRASS_VERTS ( MAX_GRASS_ELEMS / 2 ) // ( numelems / 1.5 ) actually
|
||||
#define MAX_GRASS_BUSHES ( MAX_GRASS_VERTS / 16 ) // one bush contain 4 poly, so we have 2048 bushes max per one surface
|
||||
#define GRASS_SKY_DIST BOGUS_RANGE // in-world grass never reach this value
|
||||
|
||||
typedef struct grassentry_s
|
||||
{
|
||||
char name[16]; // name of level texture
|
||||
byte texture; // number in array of grass textures
|
||||
float density; // grass density (0 - 100)
|
||||
float min; // min grass scale
|
||||
float max; // max grass scale
|
||||
int seed; // seed for predictable random (auto-filled)
|
||||
} grassentry_t;
|
||||
|
||||
typedef struct grasstexture_s
|
||||
{
|
||||
char name[256]; // path to grass texture
|
||||
int gl_texturenum; // gl-texture
|
||||
} grasstexture_t;
|
||||
|
||||
typedef struct gvert_s
|
||||
{
|
||||
float center[4]; // used for rescale
|
||||
float normal[4]; // center + vertex[2] * vertex[3];
|
||||
float light[MAXLIGHTMAPS]; // packed color + unused entry
|
||||
float delux[MAXLIGHTMAPS]; // packed lightdir + unused entry
|
||||
byte styles[MAXLIGHTMAPS]; // styles on surface
|
||||
} gvert_t;
|
||||
|
||||
#define FGRASS_NODRAW BIT( 0 ) // grass shader is failed to build
|
||||
#define FGRASS_NODLIGHT BIT( 1 ) // grass dlight shader is failed to build
|
||||
#define FGRASS_NOSUNLIGHT BIT( 2 ) // grass dlight shader is failed to build
|
||||
#define FRGASS_SKYENTITY BIT( 3 ) // it's sky grass
|
||||
|
||||
// all the grassdata for one polygon and specified texture
|
||||
// stored into single vbo
|
||||
typedef struct grass_s
|
||||
{
|
||||
// shader cache
|
||||
shader_t forwardScene;
|
||||
shader_t forwardLightSpot;
|
||||
shader_t forwardLightOmni;
|
||||
shader_t forwardLightProj;
|
||||
shader_t deferredScene;
|
||||
shader_t deferredLight;
|
||||
shader_t forwardDepth;
|
||||
|
||||
byte texture; // not a real texture just index into array
|
||||
byte flags; // state flags
|
||||
unsigned short numVerts; // for glDrawRangeElementsEXT
|
||||
unsigned short numElems; // for glDrawElements
|
||||
unsigned int vbo, vao, ibo; // buffer objects
|
||||
unsigned short hCachedMatrix; // HACKHACK: get matrices
|
||||
byte lights[MAXDYNLIGHTS];/// light numbers
|
||||
unsigned int cacheSize; // debug info: uploaded cache size for this buffer
|
||||
} grass_t;
|
||||
|
||||
typedef void (*pfnCreateGrassBuffer)( grass_t *pOut, gvert_t *arrayxvert );
|
||||
typedef void (*pfnBindGrassBuffer)( grass_t *pOut, int attrFlags );
|
||||
|
||||
enum
|
||||
{
|
||||
GRASSLOADER_BASE = 0,
|
||||
GRASSLOADER_BASEBUMP,
|
||||
GRASSLOADER_COUNT,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pfnCreateGrassBuffer CreateBuffer;
|
||||
pfnBindGrassBuffer BindBuffer;
|
||||
const char* BufferName; // debug
|
||||
} grass_loader_t;
|
||||
|
||||
typedef struct grasshdr_s
|
||||
{
|
||||
Vector mins, maxs; // per-poly culling
|
||||
int count; // total bush count for this poly
|
||||
grass_t g[1]; // variable sized
|
||||
} grasshdr_t;
|
||||
|
||||
extern void R_GrassInit( void );
|
||||
extern void R_GrassShutdown( void );
|
||||
extern void R_GrassInitForSurface( msurface_t *surf );
|
||||
extern void R_RenderGrassOnList( void );
|
||||
extern void R_GrassSetupFrame( void );
|
||||
extern void R_RenderShadowGrassOnList( void );
|
||||
extern void R_DrawLightForGrass( CDynLight *pl );
|
||||
extern void R_AddGrassToDrawList( msurface_t *s, drawlist_t type );
|
||||
extern void R_PrecacheGrass( msurface_t *s, mextraleaf_t *leaf );
|
||||
extern void R_RemoveGrassForSurface( mextrasurf_t *es );
|
||||
extern void R_UnloadFarGrass( void );
|
||||
|
||||
#endif//GL_GRASS_H
|
757
cl_dll/render/gl_lightmap.cpp
Normal file
757
cl_dll/render/gl_lightmap.cpp
Normal file
@ -0,0 +1,757 @@
|
||||
/*
|
||||
gl_lightmap.cpp - generate lightmaps and uploading them
|
||||
Copyright (C) 2016 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "studio.h"
|
||||
#include "com_model.h"
|
||||
#include "ref_params.h"
|
||||
#include "gl_local.h"
|
||||
#include <stringlib.h>
|
||||
#include "gl_shader.h"
|
||||
#include "gl_world.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LIGHTMAP ALLOCATION
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
static int LM_AllocBlock( unsigned short w, unsigned short h, unsigned short *x, unsigned short *y )
|
||||
{
|
||||
gl_lightmap_t *lms = &tr.lightmaps[tr.current_lightmap_texture];
|
||||
unsigned short i, j, best, best2;
|
||||
|
||||
best = BLOCK_SIZE;
|
||||
|
||||
for( i = 0; i < BLOCK_SIZE - w; i++ )
|
||||
{
|
||||
best2 = 0;
|
||||
|
||||
for( j = 0; j < w; j++ )
|
||||
{
|
||||
if( lms->allocated[i+j] >= best )
|
||||
break;
|
||||
if( lms->allocated[i+j] > best2 )
|
||||
best2 = lms->allocated[i+j];
|
||||
}
|
||||
|
||||
if( j == w )
|
||||
{
|
||||
// this is a valid spot
|
||||
*x = i;
|
||||
*y = best = best2;
|
||||
}
|
||||
}
|
||||
|
||||
if( best + h > BLOCK_SIZE )
|
||||
{
|
||||
// current lightmap is full
|
||||
lms->state = LM_DONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
for( i = 0; i < w; i++ )
|
||||
lms->allocated[*x + i] = best + h;
|
||||
lms->state = LM_USED; // lightmap in use
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void LM_InitBlock( void )
|
||||
{
|
||||
word dummy;
|
||||
gl_lightmap_t *lms = &tr.lightmaps[tr.current_lightmap_texture];
|
||||
memset( lms->allocated, 0, sizeof( lms->allocated ));
|
||||
|
||||
// first block at pos 0,0 used as black lightmap for studiomodel
|
||||
LM_AllocBlock( 1, 1, &dummy, &dummy );
|
||||
}
|
||||
|
||||
static void LM_UploadPages( bool lightmap, bool deluxmap )
|
||||
{
|
||||
char lmName[16];
|
||||
byte lightBuf[4];
|
||||
byte deluxBuf[4];
|
||||
int i;
|
||||
|
||||
lightBuf[0] = 0;
|
||||
lightBuf[1] = 0;
|
||||
lightBuf[2] = 0;
|
||||
lightBuf[3] = 0;
|
||||
deluxBuf[0] = 127;
|
||||
deluxBuf[1] = 127;
|
||||
deluxBuf[2] = 255;
|
||||
deluxBuf[3] = 0;
|
||||
|
||||
for( i = 0; i < MAX_LIGHTMAPS && tr.lightmaps[i].state != LM_FREE; i++ )
|
||||
{
|
||||
gl_lightmap_t *lms = &tr.lightmaps[i];
|
||||
|
||||
if( lightmap && !lms->lightmap )
|
||||
{
|
||||
Q_snprintf( lmName, sizeof( lmName ), "*diffuse%i", i );
|
||||
lms->lightmap = CREATE_TEXTURE( lmName, BLOCK_SIZE, BLOCK_SIZE, NULL, TF_LIGHTMAP );
|
||||
|
||||
// also loading dummy blackpixel
|
||||
GL_BindTexture( GL_TEXTURE0, lms->lightmap );
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, lightBuf );
|
||||
}
|
||||
|
||||
if( deluxmap && !lms->deluxmap )
|
||||
{
|
||||
Q_snprintf( lmName, sizeof( lmName ), "*normals%i", i );
|
||||
lms->deluxmap = CREATE_TEXTURE( lmName, BLOCK_SIZE, BLOCK_SIZE, NULL, TF_DELUXMAP );
|
||||
|
||||
// also loading dummy blackpixel
|
||||
GL_BindTexture( GL_TEXTURE0, lms->deluxmap );
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, deluxBuf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LM_GoToNextPage( void )
|
||||
{
|
||||
gl_lightmap_t *lms = &tr.lightmaps[tr.current_lightmap_texture];
|
||||
|
||||
if( lms->state != LM_DONE ) return; // current atlas not completed
|
||||
|
||||
if( ++tr.current_lightmap_texture == MAX_LIGHTMAPS )
|
||||
HOST_ERROR( "MAX_LIGHTMAPS limit exceded\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
GL_BeginBuildingLightmaps
|
||||
|
||||
==================
|
||||
*/
|
||||
void GL_BeginBuildingLightmaps( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
// release old lightmaps first
|
||||
for( i = 0; i < MAX_LIGHTMAPS && tr.lightmaps[i].state != LM_FREE; i++ )
|
||||
{
|
||||
FREE_TEXTURE( tr.lightmaps[i].lightmap );
|
||||
FREE_TEXTURE( tr.lightmaps[i].deluxmap );
|
||||
}
|
||||
|
||||
memset( tr.lightmaps, 0, sizeof( tr.lightmaps ));
|
||||
tr.current_lightmap_texture = 0;
|
||||
LM_InitBlock();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_AllocLightmapForFace
|
||||
|
||||
NOTE: we don't loading lightmap here.
|
||||
just create lmcoords and set lmnum
|
||||
=================
|
||||
*/
|
||||
void GL_AllocLightmapForFace( msurface_t *surf )
|
||||
{
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
word smax, tmax;
|
||||
int map;
|
||||
|
||||
// always reject the tiled faces
|
||||
if( FBitSet( surf->flags, SURF_DRAWSKY ))
|
||||
return;
|
||||
|
||||
// no lightdata and no deluxdata
|
||||
if( !surf->samples && !esrf->normals )
|
||||
return;
|
||||
|
||||
int sample_size = Mod_SampleSizeForFace( surf );
|
||||
smax = ( surf->info->lightextents[0] / sample_size ) + 1;
|
||||
tmax = ( surf->info->lightextents[1] / sample_size ) + 1;
|
||||
new_page:
|
||||
// alloc blocks for all the styles on current page
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != LS_NONE; map++ )
|
||||
{
|
||||
if( !LM_AllocBlock( smax, tmax, &esrf->light_s[map], &esrf->light_t[map] ))
|
||||
{
|
||||
// current page is not enough room for next 1-4 blocks
|
||||
LM_GoToNextPage();
|
||||
LM_InitBlock();
|
||||
goto new_page;
|
||||
}
|
||||
}
|
||||
|
||||
// lightmap will be uploaded as far as player can see it
|
||||
esrf->lightmaptexturenum = tr.current_lightmap_texture;
|
||||
SetBits( surf->flags, SURF_LM_UPDATE|SURF_DM_UPDATE );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_AllocLightmapForFace
|
||||
|
||||
NOTE: we don't loading lightmap here.
|
||||
just create lmcoords and set lmnum
|
||||
=================
|
||||
*/
|
||||
bool GL_AllocLightmapForFace( mstudiosurface_t *surf )
|
||||
{
|
||||
word smax, tmax;
|
||||
int map;
|
||||
|
||||
smax = surf->lightextents[0] + 1;
|
||||
tmax = surf->lightextents[1] + 1;
|
||||
|
||||
// alloc blocks for all the styles on current page
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != LS_NONE; map++ )
|
||||
{
|
||||
if( !LM_AllocBlock( smax, tmax, &surf->light_s[map], &surf->light_t[map] ))
|
||||
{
|
||||
// current page is not enough room for next 1-4 blocks
|
||||
LM_GoToNextPage();
|
||||
LM_InitBlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// lightmap will be uploaded as far as player can see it
|
||||
surf->lightmaptexturenum = tr.current_lightmap_texture;
|
||||
SetBits( surf->flags, SURF_LM_UPDATE|SURF_DM_UPDATE );
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
GL_EndBuildingLightmaps
|
||||
=======================
|
||||
*/
|
||||
void GL_EndBuildingLightmaps( bool lightmap, bool deluxmap )
|
||||
{
|
||||
LM_UploadPages( lightmap, deluxmap );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_BuildLightMapForStyle
|
||||
|
||||
write lightmap into page for a given style
|
||||
=================
|
||||
*/
|
||||
static void R_BuildLightMapForStyle( msurface_t *surf, byte *dest, int style )
|
||||
{
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
int stride, size;
|
||||
int smax, tmax;
|
||||
int s, t;
|
||||
color24 *lm;
|
||||
byte *sm;
|
||||
|
||||
ASSERT( style >= 0 && style < MAXLIGHTMAPS );
|
||||
|
||||
// always reject the sky faces
|
||||
if( FBitSet( surf->flags, SURF_DRAWSKY ))
|
||||
return;
|
||||
|
||||
// no lightdata or style missed
|
||||
if( !surf->samples || surf->styles[style] == LS_NONE )
|
||||
return;
|
||||
|
||||
int sample_size = Mod_SampleSizeForFace( surf );
|
||||
smax = ( surf->info->lightextents[0] / sample_size ) + 1;
|
||||
tmax = ( surf->info->lightextents[1] / sample_size ) + 1;
|
||||
size = smax * tmax;
|
||||
|
||||
// jump to specified style
|
||||
lm = surf->samples + size * style;
|
||||
sm = esrf->shadows + size * style;
|
||||
|
||||
// put into texture format
|
||||
stride = (smax * 4) - (smax << 2);
|
||||
|
||||
for( t = 0; t < tmax; t++, dest += stride )
|
||||
{
|
||||
for( s = 0; s < smax; s++ )
|
||||
{
|
||||
dest[0] = TEXTURE_TO_TEXGAMMA( lm->r );
|
||||
dest[1] = TEXTURE_TO_TEXGAMMA( lm->g );
|
||||
dest[2] = TEXTURE_TO_TEXGAMMA( lm->b );
|
||||
|
||||
if( esrf->shadows != NULL )
|
||||
dest[3] = *sm++;
|
||||
else dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
lm++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_BuildLightMapForStyle
|
||||
|
||||
write lightmap into page for a given style
|
||||
=================
|
||||
*/
|
||||
static void R_BuildLightMapForStyle( mstudiosurface_t *surf, byte *dest, int style )
|
||||
{
|
||||
int stride, size;
|
||||
int smax, tmax;
|
||||
int s, t;
|
||||
color24 *lm;
|
||||
byte *sm;
|
||||
|
||||
ASSERT( style >= 0 && style < MAXLIGHTMAPS );
|
||||
|
||||
// no lightdata or style missed
|
||||
if( !surf->samples || surf->styles[style] == LS_NONE )
|
||||
return;
|
||||
|
||||
smax = surf->lightextents[0] + 1;
|
||||
tmax = surf->lightextents[1] + 1;
|
||||
size = smax * tmax;
|
||||
|
||||
// jump to specified style
|
||||
lm = surf->samples + size * style;
|
||||
sm = surf->shadows + size * style;
|
||||
|
||||
// put into texture format
|
||||
stride = (smax * 4) - (smax << 2);
|
||||
|
||||
for( t = 0; t < tmax; t++, dest += stride )
|
||||
{
|
||||
for( s = 0; s < smax; s++ )
|
||||
{
|
||||
dest[0] = TEXTURE_TO_TEXGAMMA( lm->r );
|
||||
dest[1] = TEXTURE_TO_TEXGAMMA( lm->g );
|
||||
dest[2] = TEXTURE_TO_TEXGAMMA( lm->b );
|
||||
|
||||
if( surf->shadows != NULL )
|
||||
dest[3] = *sm++;
|
||||
else dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
lm++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_BuildDeluxMapForStyle
|
||||
|
||||
write deluxmap into page for a given style
|
||||
=================
|
||||
*/
|
||||
static void R_BuildDeluxMapForStyle( msurface_t *surf, byte *dest, int style )
|
||||
{
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
int stride, size;
|
||||
int smax, tmax;
|
||||
int s, t;
|
||||
color24 *dm;
|
||||
|
||||
ASSERT( style >= 0 && style < MAXLIGHTMAPS );
|
||||
|
||||
// always reject the sky faces
|
||||
if( FBitSet( surf->flags, SURF_DRAWSKY ))
|
||||
return;
|
||||
|
||||
// no lightdata or style missed
|
||||
if( !esrf->normals || surf->styles[style] == LS_NONE )
|
||||
return;
|
||||
|
||||
int sample_size = Mod_SampleSizeForFace( surf );
|
||||
smax = ( surf->info->lightextents[0] / sample_size ) + 1;
|
||||
tmax = ( surf->info->lightextents[1] / sample_size ) + 1;
|
||||
size = smax * tmax;
|
||||
|
||||
// jump to specified style
|
||||
dm = esrf->normals + size * style;
|
||||
|
||||
// put into texture format
|
||||
stride = (smax * 4) - (smax << 2);
|
||||
|
||||
for( t = 0; t < tmax; t++, dest += stride )
|
||||
{
|
||||
for( s = 0; s < smax; s++ )
|
||||
{
|
||||
dest[0] = dm->r;
|
||||
dest[1] = dm->g;
|
||||
dest[2] = dm->b;
|
||||
dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
dm++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_BuildDeluxMapForStyle
|
||||
|
||||
write deluxmap into page for a given style
|
||||
=================
|
||||
*/
|
||||
static void R_BuildDeluxMapForStyle( mstudiosurface_t *surf, byte *dest, int style )
|
||||
{
|
||||
int stride, size;
|
||||
int smax, tmax;
|
||||
int s, t;
|
||||
color24 *dm;
|
||||
|
||||
ASSERT( style >= 0 && style < MAXLIGHTMAPS );
|
||||
|
||||
// no lightdata or style missed
|
||||
if( !surf->normals || surf->styles[style] == LS_NONE )
|
||||
return;
|
||||
|
||||
smax = surf->lightextents[0] + 1;
|
||||
tmax = surf->lightextents[1] + 1;
|
||||
size = smax * tmax;
|
||||
|
||||
// jump to specified style
|
||||
dm = surf->normals + size * style;
|
||||
|
||||
// put into texture format
|
||||
stride = (smax * 4) - (smax << 2);
|
||||
|
||||
for( t = 0; t < tmax; t++, dest += stride )
|
||||
{
|
||||
for( s = 0; s < smax; s++ )
|
||||
{
|
||||
dest[0] = dm->r;
|
||||
dest[1] = dm->g;
|
||||
dest[2] = dm->b;
|
||||
dest[3] = 255;
|
||||
|
||||
dest += 4;
|
||||
dm++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_UpdateLightMap
|
||||
|
||||
Combine and scale multiple lightmaps into the floating
|
||||
format in r_blocklights
|
||||
=================
|
||||
*/
|
||||
static void R_UpdateLightMap( msurface_t *surf )
|
||||
{
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
static byte buf[132*132*4];
|
||||
int map, smax, tmax;
|
||||
|
||||
// always reject the sky faces
|
||||
if( FBitSet( surf->flags, SURF_DRAWSKY ))
|
||||
return;
|
||||
|
||||
int sample_size = Mod_SampleSizeForFace( surf );
|
||||
smax = ( surf->info->lightextents[0] / sample_size ) + 1;
|
||||
tmax = ( surf->info->lightextents[1] / sample_size ) + 1;
|
||||
|
||||
// upload the lightmap
|
||||
if( surf->samples != NULL && FBitSet( surf->flags, SURF_LM_UPDATE ))
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, tr.lightmaps[esrf->lightmaptexturenum].lightmap );
|
||||
|
||||
// write lightmaps into page
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != LS_NONE; map++ )
|
||||
{
|
||||
R_BuildLightMapForStyle( surf, buf, map );
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, esrf->light_s[map], esrf->light_t[map], smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, buf );
|
||||
}
|
||||
}
|
||||
|
||||
ClearBits( surf->flags, SURF_LM_UPDATE );
|
||||
|
||||
// upload the deluxemap
|
||||
if( esrf->normals != NULL && FBitSet( surf->flags, SURF_DM_UPDATE ))
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, tr.lightmaps[esrf->lightmaptexturenum].deluxmap );
|
||||
|
||||
// write lightmaps into page
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != LS_NONE; map++ )
|
||||
{
|
||||
R_BuildDeluxMapForStyle( surf, buf, map );
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, esrf->light_s[map], esrf->light_t[map], smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, buf );
|
||||
}
|
||||
}
|
||||
|
||||
ClearBits( surf->flags, SURF_DM_UPDATE );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_UpdateLightMap
|
||||
|
||||
Combine and scale multiple lightmaps into the floating
|
||||
format in r_blocklights
|
||||
=================
|
||||
*/
|
||||
static void R_UpdateLightMap( mstudiosurface_t *surf )
|
||||
{
|
||||
static byte buf[512*512*4];
|
||||
int map, smax, tmax;
|
||||
|
||||
smax = surf->lightextents[0] + 1;
|
||||
tmax = surf->lightextents[1] + 1;
|
||||
|
||||
// upload the lightmap
|
||||
if( surf->samples != NULL && FBitSet( surf->flags, SURF_LM_UPDATE ))
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, tr.lightmaps[surf->lightmaptexturenum].lightmap );
|
||||
|
||||
// write lightmaps into page
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != LS_NONE; map++ )
|
||||
{
|
||||
R_BuildLightMapForStyle( surf, buf, map );
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, surf->light_s[map], surf->light_t[map], smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, buf );
|
||||
}
|
||||
}
|
||||
|
||||
ClearBits( surf->flags, SURF_LM_UPDATE );
|
||||
|
||||
// upload the deluxemap
|
||||
if( surf->normals != NULL && FBitSet( surf->flags, SURF_DM_UPDATE ))
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, tr.lightmaps[surf->lightmaptexturenum].deluxmap );
|
||||
|
||||
// write lightmaps into page
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != LS_NONE; map++ )
|
||||
{
|
||||
R_BuildDeluxMapForStyle( surf, buf, map );
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, surf->light_s[map], surf->light_t[map], smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, buf );
|
||||
}
|
||||
}
|
||||
|
||||
ClearBits( surf->flags, SURF_DM_UPDATE );
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
R_TextureCoords
|
||||
|
||||
fill vec2_t with texture coords
|
||||
========================
|
||||
*/
|
||||
void R_TextureCoords( msurface_t *surf, const Vector &vec, float *out )
|
||||
{
|
||||
float s, t;
|
||||
|
||||
s = DotProduct( vec, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3];
|
||||
s /= surf->texinfo->texture->width;
|
||||
|
||||
t = DotProduct( vec, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3];
|
||||
t /= surf->texinfo->texture->height;
|
||||
|
||||
out[0] = s;
|
||||
out[1] = t;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
R_GlobalCoords
|
||||
|
||||
fill vec2_t with global coords
|
||||
========================
|
||||
*/
|
||||
void R_GlobalCoords( msurface_t *surf, const Vector &point, float *out )
|
||||
{
|
||||
mfaceinfo_t *land = surf->texinfo->faceinfo;
|
||||
terrain_t *terra;
|
||||
Vector size;
|
||||
indexMap_t *im;
|
||||
|
||||
if( !land ) return;
|
||||
|
||||
terra = land->terrain;
|
||||
if( !terra ) return;
|
||||
|
||||
im = &terra->indexmap;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
size[i] = land->maxs[i] - land->mins[i];
|
||||
|
||||
out[2] = ( point[0] - land->mins[0] ) / size[0];
|
||||
out[3] = ( land->maxs[1] - point[1] ) / size[1];
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
R_GlobalCoords
|
||||
|
||||
fill vec2_t with global coords
|
||||
========================
|
||||
*/
|
||||
void R_GlobalCoords( msurface_t *surf, const Vector &point, const Vector &absmin, const Vector &absmax, float scale, float *out )
|
||||
{
|
||||
Vector size;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
size[i] = absmax[i] - absmin[i];
|
||||
|
||||
out[2] = (( point[0] - absmin[0] ) / size[0]) * scale;
|
||||
out[3] = (( absmax[1] - point[1] ) / size[1]) * scale;
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
R_LightmapCoords
|
||||
|
||||
fill Vector4D with lightstyle coords (two styles per array)
|
||||
========================
|
||||
*/
|
||||
void R_LightmapCoords( msurface_t *surf, const Vector &vec, float *coords, int style )
|
||||
{
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
float sample_size = Mod_SampleSizeForFace( surf );
|
||||
float s, t;
|
||||
|
||||
for( int i = 0; i < 2; i++ )
|
||||
{
|
||||
if( surf->styles[style+i] == LS_NONE )
|
||||
return; // end of styles
|
||||
|
||||
s = DotProduct( vec, surf->info->lmvecs[0] ) + surf->info->lmvecs[0][3];
|
||||
s -= surf->info->lightmapmins[0];
|
||||
s += esrf->light_s[style+i] * sample_size;
|
||||
s += sample_size * 0.5f;
|
||||
s /= BLOCK_SIZE * sample_size;
|
||||
|
||||
t = DotProduct( vec, surf->info->lmvecs[1] ) + surf->info->lmvecs[1][3];
|
||||
t -= surf->info->lightmapmins[1];
|
||||
t += esrf->light_t[style+i] * sample_size;
|
||||
t += sample_size * 0.5f;
|
||||
t /= BLOCK_SIZE * sample_size;
|
||||
|
||||
coords[i*2+0] = s;
|
||||
coords[i*2+1] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
R_LightmapCoords
|
||||
|
||||
fill Vector4D with lightstyle coords (two styles per array)
|
||||
========================
|
||||
*/
|
||||
void R_LightmapCoords( mstudiosurface_t *surf, const Vector &vec, const Vector lmvecs[2], float *coords, int style )
|
||||
{
|
||||
float s, t;
|
||||
|
||||
for( int i = 0; i < 2; i++ )
|
||||
{
|
||||
if( surf->styles[style+i] == LS_NONE )
|
||||
return; // end of styles
|
||||
|
||||
s = DotProduct( vec, lmvecs[0] ) + surf->light_s[style+i] + 0.5f;
|
||||
t = DotProduct( vec, lmvecs[1] ) + surf->light_t[style+i] + 0.5f;
|
||||
s /= (float)BLOCK_SIZE;
|
||||
t /= (float)BLOCK_SIZE;
|
||||
|
||||
coords[i*2+0] = s;
|
||||
coords[i*2+1] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_UpdateSurfaceParams
|
||||
|
||||
update some surface params
|
||||
if this was changed
|
||||
=================
|
||||
*/
|
||||
void R_UpdateSurfaceParams( msurface_t *surf )
|
||||
{
|
||||
mextrasurf_t *esrf = surf->info;
|
||||
cl_entity_t *e = RI->currententity;
|
||||
model_t *clmodel = e->model;
|
||||
|
||||
// check for lightmap modification
|
||||
if( FBitSet( surf->flags, SURF_LM_UPDATE|SURF_DM_UPDATE ))
|
||||
R_UpdateLightMap( surf );
|
||||
|
||||
if( FBitSet( surf->flags, SURF_MOVIE ))
|
||||
R_UpdateCinematic( surf );
|
||||
|
||||
// handle conveyor movement
|
||||
if( FBitSet( clmodel->flags, BIT( 0 )) && FBitSet( surf->flags, SURF_CONVEYOR ))
|
||||
{
|
||||
float flRate, flAngle;
|
||||
float flWidth, flConveyorSpeed;
|
||||
float sOffset, sy;
|
||||
float tOffset, cy;
|
||||
|
||||
flConveyorSpeed = (e->curstate.rendercolor.g<<8|e->curstate.rendercolor.b) / 16.0f;
|
||||
if( e->curstate.rendercolor.r ) flConveyorSpeed = -flConveyorSpeed;
|
||||
flWidth = (float)RENDER_GET_PARM( PARM_TEX_SRC_WIDTH, surf->texinfo->texture->gl_texturenum );
|
||||
|
||||
if( flWidth != 0.0f )
|
||||
{
|
||||
flRate = abs( flConveyorSpeed ) / flWidth;
|
||||
flAngle = ( flConveyorSpeed >= 0.0f ) ? 180.0f : 0.0f;
|
||||
|
||||
SinCos( DEG2RAD( flAngle ), &sy, &cy );
|
||||
sOffset = tr.time * cy * flRate;
|
||||
tOffset = tr.time * sy * flRate;
|
||||
|
||||
// make sure that we are positive
|
||||
if( sOffset < 0.0f ) sOffset += 1.0f + -(int)sOffset;
|
||||
if( tOffset < 0.0f ) tOffset += 1.0f + -(int)tOffset;
|
||||
|
||||
// make sure that we are in a [0,1] range
|
||||
sOffset = sOffset - (int)sOffset;
|
||||
tOffset = tOffset - (int)tOffset;
|
||||
|
||||
esrf->texofs[0] = sOffset;
|
||||
esrf->texofs[1] = tOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no conveyor
|
||||
esrf->texofs[0] = 0.0f;
|
||||
esrf->texofs[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no conveyor
|
||||
esrf->texofs[0] = 0.0f;
|
||||
esrf->texofs[1] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_UpdateSurfaceParams
|
||||
|
||||
update some surface params
|
||||
if this was changed
|
||||
=================
|
||||
*/
|
||||
void R_UpdateSurfaceParams( mstudiosurface_t *surf )
|
||||
{
|
||||
// check for lightmap modification
|
||||
if( FBitSet( surf->flags, SURF_LM_UPDATE|SURF_DM_UPDATE ))
|
||||
R_UpdateLightMap( surf );
|
||||
}
|
998
cl_dll/render/gl_local.h
Normal file
998
cl_dll/render/gl_local.h
Normal file
@ -0,0 +1,998 @@
|
||||
/*
|
||||
gl_local.h - renderer local definitions
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_LOCAL_H
|
||||
#define GL_LOCAL_H
|
||||
|
||||
#include "gl_export.h"
|
||||
#include "ref_params.h"
|
||||
#include "com_model.h"
|
||||
#include "r_studioint.h"
|
||||
#include "gl_framebuffer.h"
|
||||
#include "gl_frustum.h"
|
||||
#include "gl_primitive.h"
|
||||
#include "cl_dlight.h"
|
||||
#include "features.h"
|
||||
#include <utlarray.h>
|
||||
#include <matrix.h>
|
||||
|
||||
#define ACTUAL_GL_VERSION 30.0f
|
||||
|
||||
// limits
|
||||
#define MAX_REF_STACK 8 // pass depth
|
||||
#define MAX_VISIBLE_ENTS 4096 // total pack of frame ents
|
||||
#define MAX_SORTED_FACES 32768 // bmodels only
|
||||
#define MAX_SUBVIEW_FACES 1024 // mirrors, portals, monitors, water, puddles. NOTE: multipass faces can merge view passes
|
||||
#define MAX_OCCLUDED_FACES 1024 // mirrors + water
|
||||
#define MAX_SORTED_MESHES 2048 // studio only
|
||||
#define MAX_MOVIES 16 // max various movies per level
|
||||
#define MAX_MOVIE_TEXTURES 64 // max # of unique video textures per level
|
||||
#define MAX_LIGHTSTYLES 64 // a byte limit, don't modify
|
||||
#define MAX_LIGHTMAPS 256 // Xash3D supports up to 256 lightmaps
|
||||
#define MAX_DLIGHTS 64 // per one frame. unsigned int limit
|
||||
#define MAX_ENGINE_DLIGHTS 32
|
||||
#define MAX_LIGHTCACHE 2048 // unique models with instanced vertex lighting
|
||||
#define MAX_SHADOWS MAX_DLIGHTS
|
||||
#define MAX_SUBVIEW_TEXTURES 64 // total depth
|
||||
#define MAX_FRAMEBUFFERS MAX_SUBVIEW_TEXTURES
|
||||
#define MAX_FBO_ATTACHMENTS 8 // color attachments per FBO
|
||||
#define DEFAULT_CUBEMAP_SIZE 32 // same as in Source
|
||||
#define AMBIENT_EPSILON 0.001f // to avoid division by zero
|
||||
#define STAIR_INTERP_TIME 100.0f
|
||||
#define LIGHT_PROBES 10 // eight OBB corners, center and one reserved slot (NOTE: not all the probes will be used)
|
||||
#define LIGHT_SAMPLES 8 // GPU limitation for local arrays (very slowly if more than eight elements)
|
||||
#define MOD_FRAMES 20
|
||||
|
||||
#define WATER_TEXTURES 29
|
||||
#define WATER_ANIMTIME 20.0f
|
||||
|
||||
#define INVALID_HANDLE 0xFFFF // studio cache
|
||||
|
||||
#define FLASHLIGHT_KEY -666
|
||||
#define SUNLIGHT_KEY -777
|
||||
#define SKYBOX_ENTITY 70
|
||||
|
||||
#define LM_SAMPLE_SIZE 16
|
||||
#define LM_SAMPLE_EXTRASIZE 8
|
||||
|
||||
#define BLOCK_SIZE glConfig.block_size // lightmap blocksize
|
||||
#define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility
|
||||
#define BLOCK_SIZE_MAX 2048 // must match with engine const!!!
|
||||
#define SHADOW_SIZE 4096 // atlas size
|
||||
|
||||
#define WORLD_MATRIX 0 // must be 0 always
|
||||
#define REFPVS_RADIUS 2.0f // PVS radius for rendering
|
||||
#define Z_NEAR 4.0f
|
||||
#define Z_NEAR_LIGHT 0.1f
|
||||
#define BACKFACE_EPSILON 0.01f
|
||||
|
||||
#define CVAR_TO_BOOL( x ) ((x) && ((x)->value != 0.0f) ? true : false )
|
||||
|
||||
// VBO offsets
|
||||
#define OFFSET( type, var ) ((const void *)&(((type *)NULL)->var))
|
||||
#define R_OpaqueEntity( e ) (( (e)->curstate.rendermode == kRenderNormal ) || ( (e)->curstate.rendermode == kRenderTransAlpha ))
|
||||
#define R_ModelOpaque( rm ) (( rm == kRenderNormal ) || ( rm == kRenderTransAlpha ))
|
||||
#define R_StaticEntity( e ) ( (e)->origin == g_vecZero && (e)->angles == g_vecZero && (e)->curstate.renderfx != SKYBOX_ENTITY )
|
||||
#define R_FullBright() ( CVAR_TO_BOOL( r_fullbright ) || !worldmodel->lightdata )
|
||||
#define RP_OUTSIDE( leaf ) (((( leaf ) - worldmodel->leafs ) - 1 ) == -1 )
|
||||
#define R_WaterEntity( m ) ( FBitSet( m->flags, BIT( 2 )))
|
||||
|
||||
#define ScreenCopyRequired( x ) ((x) && FBitSet( (x)->status, SHADER_USE_SCREENCOPY ))
|
||||
#define IsReflectShader( x ) ((x) && FBitSet( (x)->status, SHADER_USE_CUBEMAPS ))
|
||||
|
||||
// refparams
|
||||
#define RP_NONE 0
|
||||
#define RP_THIRDPERSON BIT( 0 )
|
||||
#define RP_DRAW_WORLD BIT( 1 ) // otherwise it's player customization window
|
||||
#define RP_DRAW_OVERVIEW BIT( 2 ) // dev_overview is active
|
||||
#define RP_CLIPPLANE BIT( 3 ) // mirrors used
|
||||
#define RP_MERGE_PVS BIT( 4 ) // merge PVS with previous pass
|
||||
#define RP_MIRRORVIEW BIT( 5 ) // lock pvs at vieworg
|
||||
#define RP_ENVVIEW BIT( 6 ) // used for cubemapshot
|
||||
#define RP_SHADOWVIEW BIT( 7 ) // view through light
|
||||
#define RP_NOSHADOWS BIT( 8 ) // disable shadows for this pass
|
||||
#define RP_SKYVIEW BIT( 9 ) // render skyonly
|
||||
#define RP_WATERPASS BIT( 10 ) // it's mirorring plane for water surface
|
||||
#define RP_NOGRASS BIT( 11 ) // don't draw grass
|
||||
#define RP_DEFERREDSCENE BIT( 12 ) // render scene into geometry buffer
|
||||
#define RP_DEFERREDLIGHT BIT( 13 ) // render scene into low-res lightmap
|
||||
|
||||
// RI->view.changed
|
||||
#define RC_ORIGIN_CHANGED BIT( 0 ) // origin is changed from the previous frame
|
||||
#define RC_ANGLES_CHANGED BIT( 1 ) // angles is changed from the previous frame
|
||||
#define RC_VIEWLEAF_CHANGED BIT( 2 ) // viewleaf is changed
|
||||
#define RC_FOV_CHANGED BIT( 3 ) // FOV is changed
|
||||
#define RC_PVS_CHANGED BIT( 4 ) // now our PVS was potentially changed :-)
|
||||
#define RC_FRUSTUM_CHANGED BIT( 5 ) // now our frustum was potentially changed :-)
|
||||
#define RC_FORCE_UPDATE BIT( 6 ) // some cvar manipulations invoke updates of visible list
|
||||
|
||||
// RI->view.flags
|
||||
#define RF_SKYVISIBLE BIT( 0 ) // sky is visible for this frame
|
||||
#define RF_HASDYNLIGHTS BIT( 1 ) // pass have dynlights
|
||||
|
||||
#define RP_NONVIEWERREF (RP_MIRRORVIEW|RP_ENVVIEW|RP_SHADOWVIEW|RP_SKYVIEW)
|
||||
#define RP_LOCALCLIENT( e ) (gEngfuncs.GetLocalPlayer() && ((e)->index == gEngfuncs.GetLocalPlayer()->index && e->curstate.entityType == ET_PLAYER ))
|
||||
#define RP_NORMALPASS() ( FBitSet( RI->params, RP_NONVIEWERREF ) == 0 )
|
||||
#define RP_CUBEPASS() ( FBitSet( RI->params, RP_SKYVIEW|RP_ENVVIEW ))
|
||||
|
||||
#define TF_LIGHTMAP (TF_NOMIPMAP|TF_CLAMP|TF_ATLAS_PAGE|TF_HAS_ALPHA)
|
||||
#define TF_DELUXMAP (TF_CLAMP|TF_NOMIPMAP|TF_NORMALMAP|TF_ATLAS_PAGE)
|
||||
#define TF_IMAGE (TF_NOMIPMAP|TF_CLAMP)
|
||||
#define TF_SCREEN (TF_NOMIPMAP|TF_CLAMP)
|
||||
#define TF_SPOTLIGHT (TF_NOMIPMAP|TF_BORDER)
|
||||
#define TF_SHADOW (TF_NOMIPMAP|TF_CLAMP|TF_DEPTHMAP|TF_LUMINANCE)
|
||||
#define TF_SHADOW_CUBEMAP (TF_NOMIPMAP|TF_CLAMP|TF_CUBEMAP|TF_DEPTHMAP|TF_LUMINANCE)
|
||||
#define TF_RECTANGLE_SCREEN (TF_RECTANGLE|TF_NOMIPMAP|TF_CLAMP)
|
||||
#define TF_DEPTH (TF_NOMIPMAP|TF_CLAMP|TF_NEAREST|TF_DEPTHMAP|TF_LUMINANCE|TF_NOCOMPARE)
|
||||
#define TF_GRASS (TF_CLAMP)
|
||||
#define TF_DEPTHBUFF (TF_DEPTHMAP|TF_LUMINANCE|TF_NOCOMPARE)
|
||||
#define TF_STORAGE (TF_NEAREST|TF_RECTANGLE|TF_ARB_FLOAT|TF_HAS_ALPHA|TF_CLAMP|TF_NOMIPMAP)
|
||||
|
||||
#define TF_DEPTHBUFFER (TF_SCREEN|TF_DEPTHMAP|TF_NEAREST|TF_NOCOMPARE)
|
||||
#define TF_COLORBUFFER (TF_SCREEN|TF_NEAREST)
|
||||
|
||||
#define CULL_VISIBLE 0 // not culled
|
||||
#define CULL_BACKSIDE 1 // backside of transparent wall
|
||||
#define CULL_FRUSTUM 2 // culled by frustum
|
||||
#define CULL_OTHER 3 // culled by other reason
|
||||
|
||||
#define TF_RT_COLOR (TF_NEAREST|TF_CLAMP|TF_NOMIPMAP)
|
||||
#define TF_RT_NORMAL (TF_NEAREST|TF_CLAMP|TF_NOMIPMAP|TF_NORMALMAP)
|
||||
#define TF_RT_DEPTH (TF_NEAREST|TF_CLAMP|TF_NOMIPMAP|TF_DEPTHMAP|TF_NOCOMPARE)
|
||||
|
||||
#define MAT_ALL_EFFECTS (BRUSH_HAS_BUMP|BRUSH_HAS_SPECULAR|BRUSH_REFLECT|BRUSH_FULLBRIGHT)
|
||||
|
||||
#define FBO_MAIN 0
|
||||
|
||||
// light types
|
||||
#define LIGHT_SPOT 0 // standard projection light
|
||||
#define LIGHT_OMNI 1 // omnidirectional light
|
||||
#define LIGHT_DIRECTIONAL 2 // parallel light (sun light)
|
||||
|
||||
// helpers
|
||||
#define GetVForward() Vector( RI->view.matrix[0] )
|
||||
#define GetVRight() Vector( RI->view.matrix[1] )
|
||||
#define GetVLeft() -Vector(RI->view.matrix[1] )
|
||||
#define GetVUp() Vector( RI->view.matrix[2] )
|
||||
#define GetVieworg() RI->view.origin
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DRAWLIST_ALL = 0, // special case for decals
|
||||
DRAWLIST_SOLID,
|
||||
DRAWLIST_TRANS,
|
||||
DRAWLIST_LIGHT,
|
||||
DRAWLIST_SUBVIEW,
|
||||
DRAWLIST_SHADOW,
|
||||
} drawlist_t;
|
||||
|
||||
enum
|
||||
{
|
||||
BUMP_BASELIGHT_STYLE = 61,
|
||||
BUMP_ADDLIGHT_STYLE = 62,
|
||||
BUMP_LIGHTVECS_STYLE = 63,
|
||||
};
|
||||
|
||||
class DecalGroupEntry;
|
||||
typedef int (*cmpfunc)( const void *a, const void *b );
|
||||
typedef void (*pfnShaderCallback)( struct glsl_prog_s *shader );
|
||||
|
||||
// multiple output draw buffers
|
||||
typedef struct
|
||||
{
|
||||
char name[32];
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
int colortarget[MAX_FBO_ATTACHMENTS];
|
||||
int depthtarget;
|
||||
uint id;
|
||||
} gl_drawbuffer_t;
|
||||
|
||||
typedef struct gl_fbo_s
|
||||
{
|
||||
GLboolean init;
|
||||
GLuint framebuffer;
|
||||
GLuint renderbuffer;
|
||||
int texture;
|
||||
} gl_fbo_t;
|
||||
|
||||
typedef struct gl_movie_s
|
||||
{
|
||||
char name[32];
|
||||
void *state;
|
||||
float length; // total cinematic length
|
||||
long xres, yres; // size of cinematic
|
||||
} gl_movie_t;
|
||||
|
||||
typedef struct gl_texbuffer_s
|
||||
{
|
||||
int framebuffer;
|
||||
int texturenum;
|
||||
int texframe; // this frame texture was used
|
||||
matrix4x4 matrix; // texture matrix
|
||||
} gl_texbuffer_t;
|
||||
|
||||
class gl_state_t
|
||||
{
|
||||
public:
|
||||
GLfloat modelMatrix[16]; // matrix4x4( origin, angles, scale )
|
||||
matrix4x4 transform; // entity transformation matrix
|
||||
bool m_bSkyEntity;
|
||||
const Vector GetModelOrigin( void );
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LM_FREE = 0, // lightmap is clear
|
||||
LM_USED, // partially used, has free space
|
||||
LM_DONE, // completely full
|
||||
} lmstate_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
lmstate_t state;
|
||||
unsigned short allocated[BLOCK_SIZE_MAX];
|
||||
int lightmap;
|
||||
int deluxmap;
|
||||
} gl_lightmap_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short allocated[SHADOW_SIZE];
|
||||
CFrameBuffer shadowmap;
|
||||
} gl_shadowmap_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vector diffuse; // direct light color
|
||||
Vector normal; // direct light normal
|
||||
int ambientlight; // clip at 128
|
||||
int shadelight; // clip at 192 - ambientlight
|
||||
Vector ambient[6]; // cubemap 1x1 (single pixel per side)
|
||||
bool nointerp; // flickering light force nointerp
|
||||
} mstudiolight_t;
|
||||
|
||||
// NOTE: if this is changed it must be changed in studio.h and com_model.h too!!!
|
||||
typedef struct
|
||||
{
|
||||
float smoothness; // smoothness factor
|
||||
float detailScale[2]; // detail texture scales x, y
|
||||
float reflectScale; // reflection scale for translucent water
|
||||
float refractScale; // refraction scale for mirrors, windows, water
|
||||
float aberrationScale; // chromatic abberation
|
||||
float reliefScale; // relief-mapping
|
||||
struct matdef_s *effects; // hit, impact, particle effects etc
|
||||
|
||||
char name[64];
|
||||
unsigned short dt_texturenum; // detail texture load directly from material specific
|
||||
|
||||
char diffusemap[64];
|
||||
char normalmap[64];
|
||||
char glossmap[64];
|
||||
} matdesc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[64];
|
||||
char diffuse[64];
|
||||
unsigned short gl_diffuse_id; // diffuse texture
|
||||
unsigned short gl_heightmap_id;
|
||||
unsigned short width, height;
|
||||
byte maxHeight;
|
||||
byte numLayers; // layers that specified on heightmap
|
||||
byte *pixels; // pixels are immediately goes here
|
||||
} indexMap_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char pathes[MAX_LANDSCAPE_LAYERS][64]; // path to texture (may include extension etc)
|
||||
char names[MAX_LANDSCAPE_LAYERS][64]; // basenames
|
||||
matdesc_t *material[MAX_LANDSCAPE_LAYERS]; // layer settings
|
||||
float smoothness[MAX_LANDSCAPE_LAYERS]; // shader params
|
||||
unsigned short gl_diffuse_id; // diffuse texture array
|
||||
unsigned short gl_detail_id; // detail texture
|
||||
unsigned short gl_normalmap_id; // normalmap array
|
||||
unsigned short gl_specular_id; // specular array
|
||||
} layerMap_t;
|
||||
|
||||
typedef struct terrain_s
|
||||
{
|
||||
char name[16];
|
||||
indexMap_t indexmap;
|
||||
layerMap_t layermap;
|
||||
int numLayers; // count of array textures
|
||||
int tessSize;
|
||||
float texScale; // global texture scale
|
||||
bool valid; // if heightmap was actual
|
||||
} terrain_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int changed; // whats changed from last frame
|
||||
int flags; // some info about current frame (sets by renderer)
|
||||
|
||||
int entity; // playernum or camera edict
|
||||
Vector origin;
|
||||
Vector angles;
|
||||
Vector pvspoint;
|
||||
ref_overview_t over; // cached overview
|
||||
|
||||
int client_frame; // cached client frame
|
||||
bool novis_cached; // last value of r_novis variable
|
||||
bool lockpvs_cached; // last value of r_lockpvs variable
|
||||
|
||||
float fov_x; // actual fov_x
|
||||
float fov_y; // actual fov_y
|
||||
float farClip;
|
||||
float planedist; // for sort translucent surfaces
|
||||
float lodScale;
|
||||
|
||||
int port[4]; // cached view.port
|
||||
|
||||
CFrustum frustum; // view frustum
|
||||
CFrustum splitFrustum[MAX_SHADOWMAPS];
|
||||
float parallelSplitDistances[MAX_SHADOWMAPS]; // distances in camera space
|
||||
|
||||
matrix4x4 matrix; // untransformed viewmatrix
|
||||
matrix4x4 worldMatrix; // modelview for world
|
||||
matrix4x4 projectionMatrix; // gl frustum
|
||||
matrix4x4 worldProjectionMatrix; // worldviewMatrix * projectionMatrix
|
||||
|
||||
mleaf_t *leaf; // leaf where are vieworg located
|
||||
|
||||
vec3_t visMins; // visMins used for compute precision farclip
|
||||
vec3_t visMaxs;
|
||||
|
||||
float skyMins[2][6]; // sky texcoords
|
||||
float skyMaxs[2][6]; // sky texcoords
|
||||
|
||||
byte pvsarray[(MAX_MAP_LEAFS+7)/8]; // actual PVS for current frame
|
||||
byte visfaces[(MAX_MAP_FACES+7)/8]; // actual visible faces for current frame (world only)
|
||||
byte vislight[(MAX_MAP_WORLDLIGHTS+7)/8]; // visible lights per current frame
|
||||
} ref_viewcache_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// forward rendering lists
|
||||
CUtlArray<CSolidEntry> solid_faces;
|
||||
CUtlArray<CSolidEntry> solid_meshes;
|
||||
CUtlArray<CTransEntry> trans_list;
|
||||
CUtlArray<struct grass_s*> grass_list;
|
||||
CUtlArray<Vector> primverts; // primitive vertexes
|
||||
|
||||
// forward lighting lists
|
||||
CUtlArray<CSolidEntry> light_faces;
|
||||
CUtlArray<CSolidEntry> light_meshes;
|
||||
CUtlArray<struct grass_s*> light_grass;
|
||||
|
||||
msurface_t *subview_faces[MAX_SUBVIEW_FACES]; // 6 kb
|
||||
int num_subview_faces;
|
||||
} ref_drawlist_t;
|
||||
|
||||
// contain gl-friendly data that may keep from previous frame
|
||||
// to avoid to recompute it again
|
||||
typedef struct
|
||||
{
|
||||
int viewport[4]; // in OpenGL space
|
||||
|
||||
GLfloat modelviewMatrix[16]; // worldviewMatrix
|
||||
GLfloat projectionMatrix[16]; // projection matrix
|
||||
GLfloat modelviewProjectionMatrix[16];// send to engine
|
||||
} ref_glstate_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int params; // rendering parameters
|
||||
|
||||
// NEW STATE
|
||||
ref_viewcache_t view; // cached view
|
||||
ref_glstate_t glstate; // cached glstate
|
||||
ref_drawlist_t frame; // frame lists
|
||||
|
||||
// GLOBAL STATE
|
||||
mplane_t clipPlane;
|
||||
cl_entity_t *currententity;
|
||||
model_t *currentmodel;
|
||||
CDynLight *currentlight;
|
||||
struct glsl_prog_s *currentshader;
|
||||
msurface_t *reject_face; // avoid recursion to himself
|
||||
} ref_instance_t;
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
GL STATE MACHINE
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
enum
|
||||
{
|
||||
R_OPENGL_110 = 0, // base
|
||||
R_WGL_PROCADDRESS,
|
||||
R_ARB_VERTEX_BUFFER_OBJECT_EXT,
|
||||
R_ARB_VERTEX_ARRAY_OBJECT_EXT,
|
||||
R_TEXTURE_ARRAY_EXT, // shaders only
|
||||
R_EXT_GPU_SHADER4, // shaders only
|
||||
R_DRAW_BUFFERS_EXT,
|
||||
R_ARB_MULTITEXTURE,
|
||||
R_TEXTURECUBEMAP_EXT,
|
||||
R_SHADER_GLSL100_EXT,
|
||||
R_DRAW_RANGEELEMENTS_EXT,
|
||||
R_TEXTURE_3D_EXT,
|
||||
R_SHADER_OBJECTS_EXT,
|
||||
R_VERTEX_SHADER_EXT, // glsl vertex program
|
||||
R_FRAGMENT_SHADER_EXT, // glsl fragment program
|
||||
R_ARB_TEXTURE_NPOT_EXT,
|
||||
R_TEXTURE_2D_RECT_EXT,
|
||||
R_DEPTH_TEXTURE,
|
||||
R_SHADOW_EXT,
|
||||
R_FRAMEBUFFER_OBJECT,
|
||||
R_SEPARATE_BLENDFUNC_EXT,
|
||||
R_OCCLUSION_QUERIES_EXT,
|
||||
R_SEAMLESS_CUBEMAP,
|
||||
R_BINARY_SHADER_EXT,
|
||||
R_PARANOIA_EXT, // custom OpenGL32.dll with hacked function glDepthRange
|
||||
R_DEBUG_OUTPUT,
|
||||
R_EXTCOUNT, // must be last
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GL_KEEP_UNIT = -1, // alternative way - change the unit by GL_SelectTexture
|
||||
GL_TEXTURE0 = 0,
|
||||
GL_TEXTURE1,
|
||||
GL_TEXTURE2,
|
||||
GL_TEXTURE3,
|
||||
GL_TEXTURE4,
|
||||
GL_TEXTURE5,
|
||||
GL_TEXTURE6,
|
||||
GL_TEXTURE7,
|
||||
GL_TEXTURE8,
|
||||
GL_TEXTURE9,
|
||||
GL_TEXTURE10,
|
||||
GL_TEXTURE11,
|
||||
MAX_TEXTURE_UNITS
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool fCustomRendering;
|
||||
bool fClearScreen; // force clear if world shaders failed to build
|
||||
int fGamePaused;
|
||||
|
||||
double time; // cl.time
|
||||
double oldtime; // cl.oldtime
|
||||
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
|
||||
double saved_frametime; // push\pop
|
||||
|
||||
cl_entity_t *draw_entities[MAX_VISIBLE_ENTS]; // list of all pending entities for current frame
|
||||
int num_draw_entities; // count for actual rendering frame
|
||||
|
||||
int defaultTexture; // use for bad textures
|
||||
int skyboxTextures[6]; // skybox sides
|
||||
int normalmapTexture; // default normalmap
|
||||
int deluxemapTexture; // default deluxemap
|
||||
int vsdctCubeTexture; // Virtual Shadow Depth Cubemap Texture
|
||||
int whiteCubeTexture; // stub
|
||||
int depthTexture; // stub
|
||||
int depthCubemap; // stub
|
||||
int normalsFitting; // best fit normals
|
||||
|
||||
int defaultProjTexture; // fallback for missed textures
|
||||
int flashlightTexture; // flashlight projection texture
|
||||
int spotlightTexture[8];// reserve for eight textures
|
||||
int cinTextures[MAX_MOVIE_TEXTURES];
|
||||
gl_texbuffer_t subviewTextures[MAX_SUBVIEW_TEXTURES];
|
||||
int shadowTextures[MAX_SHADOWS];
|
||||
int shadowCubemaps[MAX_SHADOWS];
|
||||
int waterTextures[WATER_TEXTURES];
|
||||
int num_2D_shadows_used; // used shadow textures per full frame
|
||||
int num_CM_shadows_used; // used shadow textures per full frame
|
||||
int num_subview_used; // used mirror textures per full frame
|
||||
int num_cin_used; // used movie textures per full frame
|
||||
|
||||
int screen_color;
|
||||
int screen_depth;
|
||||
|
||||
int grayTexture;
|
||||
int whiteTexture;
|
||||
int blackTexture;
|
||||
int screenTexture;
|
||||
|
||||
CUtlArray<gl_state_t> cached_state;
|
||||
|
||||
gl_lightmap_t lightmaps[MAX_LIGHTMAPS];
|
||||
byte current_lightmap_texture;
|
||||
int packed_lights_texture;
|
||||
int packed_planes_texture;
|
||||
int packed_nodes_texture;
|
||||
int packed_models_texture;
|
||||
|
||||
gl_shadowmap_t shadowmap; // single atlas
|
||||
|
||||
// framebuffers
|
||||
CFrameBuffer fbo_shadow2D; // used for projection shadowmapping
|
||||
CFrameBuffer fbo_shadowCM; // used for omnidirectional shadowmapping
|
||||
CFrameBuffer sunShadowFBO[MAX_SHADOWMAPS]; // extra-large shadowmap for sun rendering
|
||||
CFrameBuffer fbo_light; // store lightmap
|
||||
CFrameBuffer fbo_filter; // store filtered lightmap
|
||||
CFrameBuffer fbo_shadow; // store shadowflags
|
||||
|
||||
gl_drawbuffer_t *defscene_fbo;
|
||||
gl_drawbuffer_t *deflight_fbo;
|
||||
word defSceneShader[2]; // geometry pass
|
||||
word defLightShader; // light pass
|
||||
word defDynLightShader[2];// dynamic light pass
|
||||
word bilateralShader; // upscale filter
|
||||
|
||||
// skybox shaders
|
||||
word skyboxEnv[2]; // skybox & sun
|
||||
word defSceneSky; // skybox & sun
|
||||
word defLightSky; // skybox & sun
|
||||
|
||||
// framebuffers
|
||||
gl_fbo_t frame_buffers[MAX_FRAMEBUFFERS];
|
||||
int num_framebuffers;
|
||||
|
||||
int realframecount; // not including passes
|
||||
int grassunloadframe; // unload too far grass to save video memory
|
||||
|
||||
Vector ambientLight; // at vieworg
|
||||
int waterlevel; // player waterlevel
|
||||
cl_entity_t *waterentity; // player inside
|
||||
|
||||
// fog params
|
||||
bool fogEnabled;
|
||||
Vector fogColor;
|
||||
float fogDensity;
|
||||
float fogSkyDensity;
|
||||
|
||||
// sky params
|
||||
Vector sky_origin;
|
||||
Vector sky_world_origin;
|
||||
float sky_speed;
|
||||
|
||||
Vector sky_normal; // sky vector
|
||||
Vector sky_ambient; // sky ambient color
|
||||
|
||||
// global ambient\direct factors
|
||||
float ambientFactor;
|
||||
float diffuseFactor;
|
||||
|
||||
float sun_refract;
|
||||
float sun_ambient;
|
||||
Vector sun_diffuse;
|
||||
|
||||
CDynLight *sunlight; // sun is active if not a NULL
|
||||
|
||||
Vector screen_normals[4]; // helper to transform world->screen space
|
||||
|
||||
float farclip; // max viewable distance
|
||||
float gravity; // particles used
|
||||
|
||||
float lightstyle[MAX_LIGHTSTYLES]; // value 0 - 65536
|
||||
gl_movie_t cinematics[MAX_MOVIES]; // precached cinematics
|
||||
|
||||
struct movevars_s *movevars;
|
||||
|
||||
// generic light that used to cache shaders
|
||||
CDynLight defaultlightSpot;
|
||||
CDynLight defaultlightOmni;
|
||||
CDynLight defaultlightProj;
|
||||
|
||||
matdesc_t *materials;
|
||||
unsigned int matcount;
|
||||
|
||||
|
||||
bool params_changed; // some cvars are toggled, shaders needs to recompile and resort
|
||||
bool local_client_added; // indicate what a local client already been added into renderlist
|
||||
bool sun_light_enabled; // map have a light_environment with valid direction
|
||||
bool lighting_changed; // r_lighting_modulate was changed
|
||||
bool shadows_notsupport; // no shadow textures
|
||||
bool show_uniforms_peak; // print the maxcount of used uniforms
|
||||
int glsl_valid_sequence; // reloas shaders while some render cvars was changed
|
||||
int total_vbo_memory; // statistics
|
||||
Vector4D gamma_table[64];
|
||||
|
||||
CDynLight dlights[MAX_DLIGHTS];
|
||||
|
||||
vec3_t ambient_color;
|
||||
float direct_scale;
|
||||
float light_gamma;
|
||||
float light_threshold;
|
||||
float smoothing_threshold;
|
||||
|
||||
// original player vieworg and angles
|
||||
Vector cached_vieworigin;
|
||||
Vector cached_viewangles;
|
||||
|
||||
struct mvbocache_s *vertex_light_cache[MAX_LIGHTCACHE]; // FIXME: make growable
|
||||
struct mvbocache_s *surface_light_cache[MAX_LIGHTCACHE];
|
||||
|
||||
// cull info
|
||||
Vector modelorg; // relative to viewpoint
|
||||
} ref_globals_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int c_world_leafs;
|
||||
unsigned int c_world_nodes; // walking by BSP tree
|
||||
|
||||
unsigned int c_culled_entities;
|
||||
unsigned int c_total_tris; // triangle count
|
||||
|
||||
unsigned int c_subview_passes;
|
||||
unsigned int c_shadow_passes;
|
||||
|
||||
unsigned int c_worldlights;
|
||||
unsigned int c_occlusion_culled; // culled by occlusion query
|
||||
|
||||
unsigned int c_screen_copy; // how many times screen was copied
|
||||
|
||||
unsigned int num_shader_binds;
|
||||
unsigned int num_flushes;
|
||||
|
||||
msurface_t *debug_surface;
|
||||
} ref_stats_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double compile_shader;
|
||||
double create_light_cache;
|
||||
double create_buffer_object;
|
||||
double total_buildtime;
|
||||
} ref_buildstats_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GLHW_GENERIC, // where everthing works the way it should
|
||||
GLHW_RADEON, // where you don't have proper GLSL support
|
||||
GLHW_NVIDIA // Geforce 8/9 class DX10 hardware
|
||||
} glHWType_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int width, height;
|
||||
int defWidth, defHeight;
|
||||
qboolean fullScreen;
|
||||
qboolean wideScreen;
|
||||
|
||||
int faceCull;
|
||||
int frontFace;
|
||||
int frameBuffer;
|
||||
|
||||
GLfloat depthmin;
|
||||
GLfloat depthmax;
|
||||
GLint depthmask;
|
||||
GLfloat identityMatrix[16];
|
||||
|
||||
ref_instance_t stack[MAX_REF_STACK];
|
||||
GLuint stack_position;
|
||||
} glState_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *renderer_string; // ptrs to OpenGL32.dll, use with caution
|
||||
const char *version_string;
|
||||
const char *vendor_string;
|
||||
|
||||
glHWType_t hardware_type;
|
||||
float version;
|
||||
|
||||
// list of supported extensions
|
||||
const char *extensions_string;
|
||||
bool extension[R_EXTCOUNT];
|
||||
|
||||
int block_size; // lightmap blocksize
|
||||
|
||||
int max_texture_units;
|
||||
GLint max_2d_texture_size;
|
||||
GLint max_3d_texture_size;
|
||||
GLint max_2d_texture_layers;
|
||||
GLint max_cubemap_size;
|
||||
GLint binary_formats;
|
||||
GLint num_formats;
|
||||
|
||||
int max_vertex_uniforms;
|
||||
int max_vertex_attribs;
|
||||
int max_varying_floats;
|
||||
int max_skinning_bones; // total bones that can be transformed with GLSL
|
||||
int peak_used_uniforms;
|
||||
} glConfig_t;
|
||||
|
||||
extern glState_t glState;
|
||||
extern glConfig_t glConfig;
|
||||
extern engine_studio_api_t IEngineStudio;
|
||||
extern float gldepthmin, gldepthmax;
|
||||
extern int sunSize[MAX_SHADOWMAPS];
|
||||
extern char r_speeds_msg[2048];
|
||||
extern char r_depth_msg[2048];
|
||||
extern model_t *worldmodel;
|
||||
extern int g_iGunMode;
|
||||
extern ref_stats_t r_stats;
|
||||
extern ref_buildstats_t r_buildstats;
|
||||
extern ref_instance_t *RI;
|
||||
extern ref_globals_t tr;
|
||||
|
||||
//
|
||||
// gl_backend.cpp
|
||||
//
|
||||
void R_InitRefState( void );
|
||||
void R_PushRefState( void );
|
||||
void R_PopRefState( void );
|
||||
void R_ResetRefState( void );
|
||||
ref_instance_t *R_GetPrevInstance( void );
|
||||
void CompressNormalizedVector( char outVec[3], const Vector &inVec );
|
||||
bool GL_BackendStartFrame( ref_viewpass_t *rvp, int params );
|
||||
void GL_BackendEndFrame( ref_viewpass_t *rvp, int params );
|
||||
int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame );
|
||||
void GL_BindDrawbuffer( gl_drawbuffer_t *framebuffer );
|
||||
void GL_DepthRange( GLfloat depthmin, GLfloat depthmax );
|
||||
void R_RenderQuadPrimitive( CSolidEntry *entry );
|
||||
void GL_LoadMatrix( const matrix4x4 &source );
|
||||
void GL_LoadTexMatrix( const matrix4x4 &source );
|
||||
void GL_BindFrameBuffer( int buffer, int texture );
|
||||
void R_Speeds_Printf( const char *msg, ... );
|
||||
int R_AllocFrameBuffer( int viewport[4] );
|
||||
void GL_CheckVertexArrayBinding( void );
|
||||
void R_FreeFrameBuffer( int buffer );
|
||||
void GL_CleanupAllTextureUnits( void );
|
||||
void GL_ComputeScreenRays( void );
|
||||
void GL_DisableAllTexGens( void );
|
||||
void GL_DepthMask( GLint enable );
|
||||
void GL_FrontFace( GLenum front );
|
||||
void GL_ClipPlane( bool enable );
|
||||
void GL_BindFBO( GLuint buffer );
|
||||
void GL_AlphaTest( GLint enable );
|
||||
void GL_DepthTest( GLint enable );
|
||||
void GL_CleanupDrawState( void );
|
||||
void GL_SetDefaultState( void );
|
||||
void GL_Blend( GLint enable );
|
||||
void GL_Cull( GLenum cull );
|
||||
void GL_Setup2D( void );
|
||||
void GL_Setup3D( void );
|
||||
|
||||
//
|
||||
// gl_cubemaps.cpp
|
||||
//
|
||||
void CL_FindNearestCubeMap( const Vector &pos, mcubemap_t **result );
|
||||
void CL_FindTwoNearestCubeMap( const Vector &pos, mcubemap_t **result1, mcubemap_t **result2 );
|
||||
void CL_FindNearestCubeMapForSurface( const Vector &pos, const msurface_t *surf, mcubemap_t **result );
|
||||
void CL_FindTwoNearestCubeMapForSurface( const Vector &pos, const msurface_t *surf, mcubemap_t **result1, mcubemap_t **result2 );
|
||||
void CL_BuildCubemaps_f( void );
|
||||
|
||||
//
|
||||
// gl_cull.cpp
|
||||
//
|
||||
bool R_CullModel( cl_entity_t *e, const Vector &mins, const Vector &maxs );
|
||||
int R_CullSurface( msurface_t *surf, const Vector &vieworg, CFrustum *frustum, int clipFlags = 0 );
|
||||
bool R_CullBrushModel( cl_entity_t *e );
|
||||
bool R_CullNodeTopView( mnode_t *node );
|
||||
|
||||
#define R_CullBox( mins, maxs ) ( RI->view.frustum.CullBox( mins, maxs ))
|
||||
#define R_CullSphere( centre, radius ) ( RI->view.frustum.CullSphere( centre, radius ))
|
||||
#define R_CullFrustum( otherFrustum ) ( RI->view.frustum.CullFrustum( otherFrustum ))
|
||||
|
||||
//
|
||||
// gl_debug.cpp
|
||||
//
|
||||
void DBG_PrintVertexVBOSizes( void );
|
||||
void DBG_DrawLightFrustum( void );
|
||||
void DBG_DrawGlassScissors( void );
|
||||
void DrawLightProbes( void );
|
||||
void R_ShowLightMaps( void );
|
||||
void R_RenderLightProbeInternal( const Vector &origin, const Vector lightCube[] );
|
||||
void DBG_DrawBBox( const Vector &mins, const Vector &maxs );
|
||||
void DrawWirePoly( msurface_t *surf );
|
||||
void DrawTangentSpaces( void );
|
||||
void DrawWireFrame( void );
|
||||
void DrawViewLeaf( void );
|
||||
void DrawCubeMaps( void );
|
||||
|
||||
//
|
||||
// gl_deferred.cpp
|
||||
//
|
||||
void GL_SetupGBuffer( void );
|
||||
void GL_ResetGBuffer( void );
|
||||
void GL_DrawDeferredPass( void );
|
||||
|
||||
//
|
||||
// gl_framebuffer.c
|
||||
//
|
||||
gl_drawbuffer_t *GL_AllocDrawbuffer( const char *name, int width, int height, int depth = 1 );
|
||||
void GL_ResizeDrawbuffer( gl_drawbuffer_t *fbo, int width, int height, int depth = 1 );
|
||||
void GL_AttachColorTextureToFBO( gl_drawbuffer_t *fbo, int textrue, int colorIndex, int side = 0 );
|
||||
void GL_AttachDepthTextureToFBO( gl_drawbuffer_t *fbo, int texture, int side = 0 );
|
||||
void GL_CheckFBOStatus( gl_drawbuffer_t *fbo );
|
||||
void GL_VidInitDrawBuffers( void );
|
||||
void GL_FreeDrawbuffers( void );
|
||||
|
||||
//
|
||||
// gl_lightmap.cpp
|
||||
//
|
||||
void R_UpdateSurfaceParams( msurface_t *surf );
|
||||
void R_UpdateSurfaceParams( struct mstudiosurface_s *surf );
|
||||
void GL_BeginBuildingLightmaps( void );
|
||||
void GL_AllocLightmapForFace( msurface_t *surf );
|
||||
bool GL_AllocLightmapForFace( struct mstudiosurface_s *surf );
|
||||
void GL_EndBuildingLightmaps( bool lightmap, bool deluxmap );
|
||||
void R_TextureCoords( msurface_t *surf, const Vector &vec, float *out );
|
||||
void R_GlobalCoords( msurface_t *surf, const Vector &point, float *out );
|
||||
void R_GlobalCoords( msurface_t *surf, const Vector &point, const Vector &absmin, const Vector &absmax, float scale, float *out );
|
||||
void R_LightmapCoords( msurface_t *surf, const Vector &vec, float *coords, int style );
|
||||
void R_LightmapCoords( struct mstudiosurface_s *surf, const Vector &vec, const Vector lmvecs[2], float *coords, int style );
|
||||
|
||||
//
|
||||
// gl_rlight.cpp
|
||||
//
|
||||
CDynLight *CL_AllocDlight( int key );
|
||||
void R_GetLightVectors( cl_entity_t *pEnt, Vector &origin, Vector &angles );
|
||||
void R_SetupLightParams( CDynLight *pl, const Vector &origin, const Vector &angles, float radius, float fov, int type, int flags = 0 );
|
||||
void R_FindWorldLights( const Vector &origin, const Vector &mins, const Vector &maxs, byte lights[MAXDYNLIGHTS], bool skipZ = false );
|
||||
void R_LightForStudio( const Vector &point, mstudiolight_t *light, bool ambient );
|
||||
void R_PointAmbientFromLeaf( const Vector &point, mstudiolight_t *light );
|
||||
void R_LightForSky( const Vector &point, mstudiolight_t *light );
|
||||
void R_LightVec( const Vector &point, mstudiolight_t *light, bool ambient );
|
||||
Vector R_LightsForPoint( const Vector &point, float radius );
|
||||
void R_SetupLightTexture( CDynLight *pl, int texture );
|
||||
void R_SetupDynamicLights( void );
|
||||
void CL_ClearDlights( void );
|
||||
void R_AnimateLight( void );
|
||||
int HasDynamicLights( void );
|
||||
int HasStaticLights( void );
|
||||
void CL_DecayLights( void );
|
||||
|
||||
//
|
||||
// gl_rmain.cpp
|
||||
//
|
||||
void R_ClearScene( void );
|
||||
int R_ComputeFxBlend( cl_entity_t *e );
|
||||
void R_RenderScene( const ref_viewpass_t *rvp, int params );
|
||||
qboolean R_AddEntity( struct cl_entity_s *clent, int entityType );
|
||||
bool R_WorldToScreen( const Vector &point, Vector &screen );
|
||||
void R_ScreenToWorld( const Vector &screen, Vector &point );
|
||||
void R_SetupProjectionMatrix( float fov_x, float fov_y, matrix4x4 &m );
|
||||
unsigned short GL_CacheState( const Vector &origin, const Vector &angles, bool skyentity = false );
|
||||
void R_MarkWorldVisibleFaces( model_t *model );
|
||||
gl_state_t *GL_GetCache( word hCachedMatrix );
|
||||
void R_DrawParticles( qboolean trans );
|
||||
void R_SetupGLstate( void );
|
||||
void R_RenderTransList( void );
|
||||
void R_SetupFrustum( void );
|
||||
void R_Clear( int bitMask );
|
||||
|
||||
//
|
||||
// gl_rmisc.cpp
|
||||
//
|
||||
void R_NewMap( void );
|
||||
void R_VidInit( void );
|
||||
void CL_InitMaterials( void );
|
||||
matdesc_t *CL_FindMaterial( const char *name );
|
||||
void R_LoadLandscapes( const char *filename );
|
||||
terrain_t *R_FindTerrain( const char *texname );
|
||||
void R_InitDynLightShaders( void );
|
||||
void R_InitShadowTextures( void );
|
||||
void R_FreeLandscapes( void );
|
||||
|
||||
//
|
||||
// gl_rsurf.cpp
|
||||
//
|
||||
texture_t *R_TextureAnimation( msurface_t *s );
|
||||
void GL_InitRandomTable( void );
|
||||
|
||||
//
|
||||
// gl_shader.cpp
|
||||
//
|
||||
const char *GL_PretifyListOptions( const char *options, bool newlines = false );
|
||||
word GL_FindUberShader( const char *glname, const char *options = "" );
|
||||
word GL_FindShader( const char *glname, const char *vpname, const char *fpname, const char *options = "" );
|
||||
void GL_SetShaderDirective( char *options, const char *directive );
|
||||
void GL_AddShaderDirective( char *options, const char *directive );
|
||||
void GL_AddShaderFeature( word shaderNum, int feature );
|
||||
void GL_CheckTextureAlpha( char *options, int texturenum );
|
||||
void GL_EncodeNormal( char *options, int texturenum );
|
||||
void GL_BindShader( struct glsl_prog_s *shader );
|
||||
void GL_FreeUberShaders( void );
|
||||
void GL_InitGPUShaders( void );
|
||||
void GL_FreeGPUShaders( void );
|
||||
|
||||
//
|
||||
// gl_shadows.cpp
|
||||
//
|
||||
void R_RenderShadowmaps( void );
|
||||
void R_RenderDeferredShadows( void );
|
||||
|
||||
//
|
||||
// gl_movie.cpp
|
||||
//
|
||||
void R_InitCinematics( void );
|
||||
void R_FreeCinematics( void );
|
||||
int R_PrecacheCinematic( const char *cinname );
|
||||
int R_AllocateCinematicTexture( unsigned int txFlags );
|
||||
void R_UpdateCinematic( const msurface_t *surf );
|
||||
void R_UpdateCinSound( cl_entity_t *e );
|
||||
|
||||
//
|
||||
// gl_mirror.cpp
|
||||
//
|
||||
void R_RenderSubview( void );
|
||||
|
||||
//
|
||||
// gl_scene.cpp
|
||||
//
|
||||
void R_CheckChanges( void );
|
||||
void R_InitDefaultLights( void );
|
||||
|
||||
//
|
||||
// gl_sky.cpp
|
||||
//
|
||||
void R_AddSkyBoxSurface( msurface_t *fa );
|
||||
void R_DrawSkyBox( void );
|
||||
|
||||
//
|
||||
// gl_postprocess.cpp
|
||||
//
|
||||
void InitPostTextures( void );
|
||||
void InitPostEffects( void );
|
||||
void RenderDOF( void );
|
||||
void RenderUnderwaterBlur( void );
|
||||
void RenderNerveGasBlur( void );
|
||||
void RenderMonochrome( void );
|
||||
void RenderSunShafts( void );
|
||||
void RenderFSQ( int wide, int tall );
|
||||
|
||||
//
|
||||
// gl_world_new.cpp
|
||||
//
|
||||
void Mod_ThrowModelInstances( void );
|
||||
void Mod_PrepareModelInstances( void );
|
||||
void GL_LoadAndRebuildCubemaps( int refParams );
|
||||
void Mod_SetOrthoBounds( const float *mins, const float *maxs );
|
||||
bool Mod_CheckLayerNameForSurf( msurface_t *surf, const char *checkName );
|
||||
bool Mod_CheckLayerNameForPixel( mfaceinfo_t *land, const Vector &point, const char *checkName );
|
||||
int Mod_FatPVS( model_t *model, const vec3_t org, float radius, byte *visbuffer, int visbytes, bool merge, bool fullvis );
|
||||
void Mod_FindStaticLights( byte *vislight, byte lights[MAXDYNLIGHTS], const Vector &origin );
|
||||
void R_ProcessWorldData( model_t *mod, qboolean create, const byte *buffer );
|
||||
bool R_AddSurfaceToDrawList( msurface_t *surf, drawlist_t type );
|
||||
void R_MarkVisibleLights( byte lights[MAXDYNLIGHTS] );
|
||||
gl_texbuffer_t *Surf_GetSubview( mextrasurf_t *es );
|
||||
void R_RenderTransSurface( CTransEntry *entry );
|
||||
int Mod_SampleSizeForFace( msurface_t *surf );
|
||||
bool Surf_CheckSubview( mextrasurf_t *es, bool puddle = false );
|
||||
void R_RenderDynLightList( bool solid );
|
||||
void R_MarkSubmodelVisibleFaces( void );
|
||||
void Mod_InitBSPModelsTexture( void );
|
||||
void R_UpdateSubmodelParams( void );
|
||||
void Mod_ResortFaces( void );
|
||||
|
||||
//
|
||||
// gl_world.cpp
|
||||
//
|
||||
void R_RenderDeferredBrushList( void );
|
||||
void R_RenderSolidBrushList( void );
|
||||
void R_RenderShadowBrushList( void );
|
||||
void R_RenderSurfOcclusionList( void );
|
||||
|
||||
//
|
||||
// rain.cpp
|
||||
//
|
||||
void R_DrawWeather( void );
|
||||
void ParseRain( void );
|
||||
void ResetRain( void );
|
||||
void InitRain( void );
|
||||
|
||||
#endif//GL_LOCAL_H
|
37
cl_dll/render/gl_material.h
Normal file
37
cl_dll/render/gl_material.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
gl_material.h - visible material settings
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_MATERIAL_H
|
||||
#define GL_MATERIAL_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PHYSMODEL_BRDF = 0, // BRDF as default
|
||||
PHYSMODEL_DOOM3, // obsolete lighting model like Doom3
|
||||
PHYSMODEL_FOLIAGE, // two-side rendering, vegetation lighting model
|
||||
PHYSMODEL_GLASS, // translucent surface
|
||||
PHYSMODEL_SKIN, // human skin lighting model
|
||||
PHYSMODEL_HAIR, // anisotropic lighting model for hairs
|
||||
PHYSMODEL_EYES, // eyes physical model
|
||||
} physmodel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
physmodel_t physModel;
|
||||
struct matdef_s *effects; // material common effects (decals, particles, etc)
|
||||
} gl_material_t;
|
||||
|
||||
#endif//GL_MATERIAL_H
|
230
cl_dll/render/gl_movie.cpp
Normal file
230
cl_dll/render/gl_movie.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
gl_movie.cpp - draw screen movie surfaces
|
||||
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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_world.h"
|
||||
#include "mathlib.h"
|
||||
#include "event_api.h"
|
||||
#include <stringlib.h>
|
||||
|
||||
int R_PrecacheCinematic( const char *cinname )
|
||||
{
|
||||
int load_sound = 0;
|
||||
|
||||
if( !cinname || !*cinname )
|
||||
return -1;
|
||||
|
||||
if( *cinname == '*' )
|
||||
{
|
||||
if( g_iXashEngineBuildNumber >= 4256 )
|
||||
load_sound = 1;
|
||||
cinname++;
|
||||
}
|
||||
|
||||
// not AVI file
|
||||
if( Q_stricmp( UTIL_FileExtension( cinname ), "avi" ))
|
||||
return -1;
|
||||
|
||||
// first check for co-existing
|
||||
for( int i = 0; i < MAX_MOVIES; i++ )
|
||||
{
|
||||
if( !Q_stricmp( tr.cinematics[i].name, cinname ))
|
||||
{
|
||||
// already existed
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// found an empty slot
|
||||
for( i = 0; i < MAX_MOVIES; i++ )
|
||||
{
|
||||
if( !tr.cinematics[i].name[0] )
|
||||
break;
|
||||
}
|
||||
|
||||
if( i == MAX_MOVIES )
|
||||
{
|
||||
ALERT( at_error, "R_PrecacheCinematic: cinematic list limit exceeded\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// register new cinematic
|
||||
Q_strncpy( tr.cinematics[i].name, cinname, sizeof( tr.cinematics[0].name ));
|
||||
if( tr.cinematics[i].state )
|
||||
{
|
||||
ALERT( at_warning, "Reused cin state %i with %s\n", i, tr.cinematics[i].name );
|
||||
FREE_CINEMATIC( tr.cinematics[i].state );
|
||||
}
|
||||
|
||||
ALERT( at_console, "Loading cinematic %s [%s]\n", cinname, load_sound ? "sound" : "muted" );
|
||||
tr.cinematics[i].state = OPEN_CINEMATIC( tr.cinematics[i].name, load_sound );
|
||||
|
||||
// grab info about movie
|
||||
if( tr.cinematics[i].state != NULL )
|
||||
CIN_GET_VIDEO_INFO( tr.cinematics[i].state, &tr.cinematics[i].xres, &tr.cinematics[i].yres, &tr.cinematics[i].length );
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void R_InitCinematics( void )
|
||||
{
|
||||
const char *name, *ext;
|
||||
|
||||
// make sure what we have texture to draw cinematics
|
||||
if( !FBitSet( world->features, WORLD_HAS_MOVIES ))
|
||||
return;
|
||||
|
||||
for( int i = 1; i < 1024; i++ )
|
||||
{
|
||||
name = gRenderfuncs.GetFileByIndex( i );
|
||||
|
||||
if( !name || !*name ) break; // end of files array
|
||||
|
||||
ext = UTIL_FileExtension( name );
|
||||
if( Q_stricmp( ext, "avi" )) continue; // not AVI
|
||||
|
||||
if( R_PrecacheCinematic( name ) == -1 )
|
||||
break; // full
|
||||
}
|
||||
}
|
||||
|
||||
void R_FreeCinematics( void )
|
||||
{
|
||||
for( int i = 0; i < MAX_MOVIES; i++ )
|
||||
{
|
||||
if( tr.cinematics[i].state )
|
||||
{
|
||||
ALERT( at_notice, "release cinematic %s\n", tr.cinematics[i].name );
|
||||
FREE_CINEMATIC( tr.cinematics[i].state );
|
||||
}
|
||||
}
|
||||
|
||||
memset( tr.cinematics, 0, sizeof( tr.cinematics ));
|
||||
|
||||
for( i = 0; i < MAX_MOVIE_TEXTURES; i++ )
|
||||
{
|
||||
if( !tr.cinTextures[i] ) break;
|
||||
FREE_TEXTURE( tr.cinTextures[i] );
|
||||
}
|
||||
|
||||
memset( tr.cinTextures, 0, sizeof( tr.cinTextures ));
|
||||
}
|
||||
|
||||
int R_AllocateCinematicTexture( unsigned int txFlags )
|
||||
{
|
||||
int i = tr.num_cin_used;
|
||||
|
||||
if( i >= MAX_MOVIE_TEXTURES )
|
||||
{
|
||||
ALERT( at_error, "R_AllocateCinematicTexture: cine textures limit exceeded!\n" );
|
||||
return 0; // disable
|
||||
}
|
||||
tr.num_cin_used++;
|
||||
|
||||
if( !tr.cinTextures[i] )
|
||||
{
|
||||
char txName[16];
|
||||
|
||||
Q_snprintf( txName, sizeof( txName ), "*cinematic%i", i );
|
||||
|
||||
// create new cinematic texture
|
||||
// NOTE: dimension of texture is no matter because CIN_UPLOAD_FRAME will be rescale texture
|
||||
tr.cinTextures[i] = CREATE_TEXTURE( txName, 256, 256, NULL, txFlags );
|
||||
}
|
||||
|
||||
return (i+1);
|
||||
}
|
||||
|
||||
void R_UpdateCinematic( const msurface_t *surf )
|
||||
{
|
||||
if( !RI->currententity->curstate.body )
|
||||
return; // just disabled
|
||||
|
||||
// draw the cinematic
|
||||
mextrasurf_t *es = surf->info;
|
||||
|
||||
// found the corresponding cinstate
|
||||
const char *cinname = gRenderfuncs.GetFileByIndex( RI->currententity->curstate.sequence );
|
||||
int cinhandle = R_PrecacheCinematic( cinname );
|
||||
|
||||
if( cinhandle >= 0 && es->cintexturenum <= 0 )
|
||||
es->cintexturenum = R_AllocateCinematicTexture( TF_NOMIPMAP );
|
||||
|
||||
if( cinhandle == -1 || es->cintexturenum <= 0 || CIN_IS_ACTIVE( tr.cinematics[cinhandle].state ) == false )
|
||||
{
|
||||
// cinematic textures limit exceeded, so remove SURF_MOVIE flag
|
||||
((msurface_t *)surf)->flags &= ~SURF_MOVIE;
|
||||
return;
|
||||
}
|
||||
|
||||
gl_movie_t *cin = &tr.cinematics[cinhandle];
|
||||
float cin_time;
|
||||
|
||||
if( FBitSet( RI->currententity->curstate.iuser1, CF_LOOPED_MOVIE ))
|
||||
{
|
||||
// advances cinematic time
|
||||
cin_time = fmod( RI->currententity->curstate.fuser2, cin->length );
|
||||
}
|
||||
else
|
||||
{
|
||||
cin_time = RI->currententity->curstate.fuser2;
|
||||
}
|
||||
|
||||
// read the next frame
|
||||
int cin_frame = CIN_GET_FRAME_NUMBER( cin->state, cin_time );
|
||||
|
||||
// upload the new frame
|
||||
if( cin_frame != es->checkcount )
|
||||
{
|
||||
GL_SelectTexture( GL_TEXTURE0 ); // doesn't matter. select 0-th unit just as default
|
||||
byte *raw = CIN_GET_FRAMEDATA( cin->state, cin_frame );
|
||||
CIN_UPLOAD_FRAME( tr.cinTextures[es->cintexturenum-1], cin->xres, cin->yres, cin->xres, cin->yres, raw );
|
||||
es->checkcount = cin_frame;
|
||||
}
|
||||
}
|
||||
|
||||
void R_UpdateCinSound( cl_entity_t *e )
|
||||
{
|
||||
if( g_iXashEngineBuildNumber < 4256 )
|
||||
return; // too old for this feature
|
||||
|
||||
if( !e->curstate.body || !FBitSet( e->curstate.iuser1, CF_MOVIE_SOUND ))
|
||||
return; // just disabled
|
||||
|
||||
// found the corresponding cinstate
|
||||
const char *cinname = gRenderfuncs.GetFileByIndex( e->curstate.sequence );
|
||||
int cinhandle = R_PrecacheCinematic( cinname );
|
||||
|
||||
if( cinhandle == -1 || CIN_IS_ACTIVE( tr.cinematics[cinhandle].state ) == false )
|
||||
return;
|
||||
|
||||
gl_movie_t *cin = &tr.cinematics[cinhandle];
|
||||
float cin_time;
|
||||
|
||||
if( FBitSet( e->curstate.iuser1, CF_LOOPED_MOVIE ))
|
||||
{
|
||||
// advances cinematic time
|
||||
cin_time = fmod( e->curstate.fuser2, cin->length );
|
||||
}
|
||||
else
|
||||
{
|
||||
cin_time = e->curstate.fuser2;
|
||||
}
|
||||
|
||||
// stream avi sound
|
||||
CIN_UPDATE_SOUND( cin->state, e->index, VOL_NORM, ATTN_IDLE, cin_time );
|
||||
}
|
231
cl_dll/render/gl_occlusion.cpp
Normal file
231
cl_dll/render/gl_occlusion.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
gl_occlusion.cpp - occlusion query implementation class
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2015 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "gl_local.h"
|
||||
#include <utlarray.h>
|
||||
#include "gl_occlusion.h"
|
||||
#include "gl_world.h"
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_AllocOcclusionQuery
|
||||
|
||||
===============
|
||||
*/
|
||||
void GL_AllocOcclusionQuery( msurface_t *surf )
|
||||
{
|
||||
if( !GL_Support( R_OCCLUSION_QUERIES_EXT ) || surf->info->query )
|
||||
return;
|
||||
|
||||
pglGenQueriesARB( 1, &surf->info->query );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_DeleteOcclusionQuery
|
||||
|
||||
===============
|
||||
*/
|
||||
void GL_DeleteOcclusionQuery( msurface_t *surf )
|
||||
{
|
||||
if( !GL_Support( R_OCCLUSION_QUERIES_EXT ) || !surf->info->query )
|
||||
return;
|
||||
|
||||
pglDeleteQueriesARB( 1, &surf->info->query );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_DrawOcclusionCube
|
||||
|
||||
===============
|
||||
*/
|
||||
static void GL_DrawOcclusionCube( const Vector &absmin, const Vector &absmax )
|
||||
{
|
||||
vec3_t bbox[8];
|
||||
int i;
|
||||
|
||||
// compute a full bounding box
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
bbox[i][0] = ( i & 1 ) ? absmin[0] : absmax[0];
|
||||
bbox[i][1] = ( i & 2 ) ? absmin[1] : absmax[1];
|
||||
bbox[i][2] = ( i & 4 ) ? absmin[2] : absmax[2];
|
||||
}
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
pglVertex3fv( bbox[g_boxpnt[i][0]] );
|
||||
pglVertex3fv( bbox[g_boxpnt[i][1]] );
|
||||
pglVertex3fv( bbox[g_boxpnt[i][2]] );
|
||||
pglVertex3fv( bbox[g_boxpnt[i][3]] );
|
||||
}
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_TestSurfaceOcclusion
|
||||
|
||||
===============
|
||||
*/
|
||||
void GL_TestSurfaceOcclusion( msurface_t *surf )
|
||||
{
|
||||
mextrasurf_t *es = surf->info;
|
||||
Vector absmin, absmax;
|
||||
word cached_matrix;
|
||||
Vector normal;
|
||||
|
||||
if( !es->query || FBitSet( surf->flags, SURF_QUEUED ))
|
||||
return; // we already have the query
|
||||
|
||||
if( !es->parent ) cached_matrix = WORLD_MATRIX;
|
||||
else cached_matrix = es->parent->hCachedMatrix;
|
||||
gl_state_t *glm = GL_GetCache( cached_matrix );
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
normal = -surf->plane->normal;
|
||||
else normal = surf->plane->normal;
|
||||
|
||||
// place above surface
|
||||
absmin = es->mins + normal * 5.0f;
|
||||
absmax = es->maxs + normal * 5.0f;
|
||||
ExpandBounds( absmin, absmax, 2.0f );
|
||||
|
||||
if( cached_matrix != WORLD_MATRIX )
|
||||
TransformAABB( glm->transform, es->mins, es->maxs, absmin, absmax );
|
||||
pglBeginQueryARB( GL_SAMPLES_PASSED_ARB, es->query );
|
||||
GL_DrawOcclusionCube( absmin, absmax );
|
||||
pglEndQueryARB( GL_SAMPLES_PASSED_ARB );
|
||||
|
||||
// now we have a valid query
|
||||
SetBits( surf->flags, SURF_QUEUED );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_TestSurfaceOcclusion
|
||||
|
||||
===============
|
||||
*/
|
||||
void GL_DebugSurfaceOcclusion( msurface_t *surf )
|
||||
{
|
||||
mextrasurf_t *es = surf->info;
|
||||
Vector absmin, absmax;
|
||||
word cached_matrix;
|
||||
Vector normal;
|
||||
|
||||
if( !FBitSet( surf->flags, SURF_QUEUED ))
|
||||
return; // draw only queue
|
||||
|
||||
if( !es->parent ) cached_matrix = WORLD_MATRIX;
|
||||
else cached_matrix = es->parent->hCachedMatrix;
|
||||
gl_state_t *glm = GL_GetCache( cached_matrix );
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
normal = -surf->plane->normal;
|
||||
else normal = surf->plane->normal;
|
||||
|
||||
// place above surface
|
||||
absmin = es->mins + normal * 5.0f;
|
||||
absmax = es->maxs + normal * 5.0f;
|
||||
ExpandBounds( absmin, absmax, 2.0f );
|
||||
|
||||
if( cached_matrix != WORLD_MATRIX )
|
||||
TransformAABB( glm->transform, es->mins, es->maxs, absmin, absmax );
|
||||
GL_DrawOcclusionCube( absmin, absmax );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderOcclusionList
|
||||
================
|
||||
*/
|
||||
void R_RenderSurfOcclusionList( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !RP_NORMALPASS() || !CVAR_TO_BOOL( r_occlusion_culling ))
|
||||
return;
|
||||
|
||||
if( !RI->frame.num_subview_faces )
|
||||
return;
|
||||
|
||||
pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
GL_DepthMask( GL_FALSE );
|
||||
GL_AlphaTest( GL_FALSE );
|
||||
GL_BindShader( NULL );
|
||||
|
||||
for( i = 0; i < RI->frame.num_subview_faces; i++ )
|
||||
GL_TestSurfaceOcclusion( RI->frame.subview_faces[i] );
|
||||
|
||||
pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
GL_DepthMask( GL_TRUE );
|
||||
pglFlush();
|
||||
|
||||
if( r_occlusion_culling->value < 2.0f )
|
||||
return;
|
||||
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
GL_Blend( GL_FALSE );
|
||||
|
||||
for( i = 0; i < RI->frame.num_subview_faces; i++ )
|
||||
GL_DebugSurfaceOcclusion( RI->frame.subview_faces[i] );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_SurfaceOccluded
|
||||
================
|
||||
*/
|
||||
bool GL_SurfaceOccluded( msurface_t *surf )
|
||||
{
|
||||
mextrasurf_t *es = surf->info;
|
||||
GLuint sampleCount = 0;
|
||||
GLint available = false;
|
||||
|
||||
if( !RP_NORMALPASS() || !CVAR_TO_BOOL( r_occlusion_culling ))
|
||||
return false;
|
||||
|
||||
if( !es->query ) return false;
|
||||
|
||||
if( !FBitSet( surf->flags, SURF_QUEUED ))
|
||||
{
|
||||
// occlusion is no more actual
|
||||
ClearBits( surf->flags, SURF_OCCLUDED );
|
||||
return false;
|
||||
}
|
||||
|
||||
// i hope results will be arrived on a next frame...
|
||||
pglGetQueryObjectivARB( es->query, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
|
||||
|
||||
// NOTE: if we can't get actual information about query results
|
||||
// assume that object was visible and cull him with default methods: frustum, pvs etc
|
||||
if( !available ) return false;
|
||||
|
||||
pglGetQueryObjectuivARB( es->query, GL_QUERY_RESULT_ARB, &sampleCount );
|
||||
ClearBits( surf->flags, SURF_QUEUED ); // we catch the results, so query is outdated
|
||||
if( sampleCount == 0 ) SetBits( surf->flags, SURF_OCCLUDED );
|
||||
else ClearBits( surf->flags, SURF_OCCLUDED );
|
||||
if( !sampleCount ) r_stats.c_occlusion_culled++;
|
||||
|
||||
return (FBitSet( surf->flags, SURF_OCCLUDED ) != 0);
|
||||
}
|
25
cl_dll/render/gl_occlusion.h
Normal file
25
cl_dll/render/gl_occlusion.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
gl_occlusion.h - occlusion query implementation
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_OCCLUSION_H
|
||||
#define GL_OCCLUSION_H
|
||||
|
||||
void GL_AllocOcclusionQuery( msurface_t *surf );
|
||||
void GL_DeleteOcclusionQuery( msurface_t *surf );
|
||||
bool GL_SurfaceOccluded( msurface_t *surf );
|
||||
void GL_TestSurfaceOcclusion( msurface_t *surf );
|
||||
|
||||
#endif//GL_OCCLUSION_H
|
600
cl_dll/render/gl_postprocess.cpp
Normal file
600
cl_dll/render/gl_postprocess.cpp
Normal file
@ -0,0 +1,600 @@
|
||||
//
|
||||
// written by BUzer for HL: Paranoia modification
|
||||
//
|
||||
// 2006
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "gl_local.h"
|
||||
#include "mathlib.h"
|
||||
#include "gl_shader.h"
|
||||
#include "stringlib.h"
|
||||
#include "gl_world.h"
|
||||
|
||||
extern int g_iGunMode;
|
||||
|
||||
#define DEAD_GRAYSCALE_TIME 5.0f
|
||||
#define TARGET_SIZE 256
|
||||
|
||||
cvar_t *v_posteffects;
|
||||
cvar_t *v_grayscale;
|
||||
cvar_t *v_sunshafts;
|
||||
|
||||
// post-process shaders
|
||||
class CBasePostEffects
|
||||
{
|
||||
public:
|
||||
word blurShader[2]; // e.g. underwater blur
|
||||
word dofShader; // iron sight with dof
|
||||
word monoShader; // monochrome effect
|
||||
word genSunShafts; // sunshafts effect
|
||||
word drawSunShafts; // sunshafts effect
|
||||
int target_rgb[2];
|
||||
float grayScaleFactor;
|
||||
float blurFactor[2];
|
||||
bool m_bUseTarget;
|
||||
|
||||
// DOF parameters
|
||||
float m_flCachedDepth;
|
||||
float m_flLastDepth;
|
||||
float m_flStartDepth;
|
||||
float m_flOffsetDepth;
|
||||
float m_flStartTime;
|
||||
float m_flDelayTime;
|
||||
int g_iGunLastMode;
|
||||
float m_flStartLength;
|
||||
float m_flOffsetLength;
|
||||
float m_flLastLength;
|
||||
float m_flDOFStartTime;
|
||||
|
||||
// sunshafts variables
|
||||
Vector m_vecSunLightColor;
|
||||
Vector m_vecSunPosition;
|
||||
|
||||
void InitScreenColor( void );
|
||||
void InitScreenDepth( void );
|
||||
void InitTargetColor( int slot );
|
||||
void RequestScreenColor( void );
|
||||
void RequestScreenDepth( void );
|
||||
void RequestTargetCopy( int slot );
|
||||
bool ProcessDepthOfField( void );
|
||||
bool ProcessSunShafts( void );
|
||||
void InitDepthOfField( void );
|
||||
void SetNormalViewport( void );
|
||||
void SetTargetViewport( void );
|
||||
bool Begin( void );
|
||||
void End( void );
|
||||
};
|
||||
|
||||
void CBasePostEffects :: InitScreenColor( void )
|
||||
{
|
||||
if( tr.screen_color )
|
||||
{
|
||||
FREE_TEXTURE( tr.screen_color );
|
||||
tr.screen_color = 0;
|
||||
}
|
||||
|
||||
tr.screen_color = CREATE_TEXTURE( "*screencolor", glState.width, glState.height, NULL, TF_COLORBUFFER );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: InitScreenDepth( void )
|
||||
{
|
||||
if( tr.screen_depth )
|
||||
{
|
||||
FREE_TEXTURE( tr.screen_depth );
|
||||
tr.screen_depth = 0;
|
||||
}
|
||||
|
||||
tr.screen_depth = CREATE_TEXTURE( "*screendepth", glState.width, glState.height, NULL, TF_DEPTHBUFFER );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: InitTargetColor( int slot )
|
||||
{
|
||||
if( target_rgb[slot] )
|
||||
{
|
||||
FREE_TEXTURE( target_rgb[slot] );
|
||||
target_rgb[slot] = 0;
|
||||
}
|
||||
|
||||
target_rgb[slot] = CREATE_TEXTURE( va( "*target%i", slot ), TARGET_SIZE, TARGET_SIZE, NULL, TF_IMAGE );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: RequestScreenColor( void )
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, tr.screen_color );
|
||||
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glState.width, glState.height );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: RequestScreenDepth( void )
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, tr.screen_depth );
|
||||
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glState.width, glState.height );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: RequestTargetCopy( int slot )
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, target_rgb[slot] );
|
||||
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, TARGET_SIZE, TARGET_SIZE );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: SetNormalViewport( void )
|
||||
{
|
||||
pglViewport( RI->glstate.viewport[0], RI->glstate.viewport[1], RI->glstate.viewport[2], RI->glstate.viewport[3] );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: SetTargetViewport( void )
|
||||
{
|
||||
pglViewport( 0, 0, TARGET_SIZE, TARGET_SIZE );
|
||||
}
|
||||
|
||||
void CBasePostEffects :: InitDepthOfField( void )
|
||||
{
|
||||
g_iGunLastMode = 1;
|
||||
}
|
||||
|
||||
bool CBasePostEffects :: ProcessDepthOfField( void )
|
||||
{
|
||||
if( !CVAR_TO_BOOL( r_dof ) || g_iGunMode == 0 )
|
||||
return false; // disabled or unitialized
|
||||
|
||||
if( g_iGunMode != g_iGunLastMode )
|
||||
{
|
||||
if( g_iGunMode == 1 )
|
||||
{
|
||||
// disable iron sight
|
||||
m_flStartLength = m_flLastLength;
|
||||
m_flOffsetLength = -m_flStartLength;
|
||||
m_flDOFStartTime = tr.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
// enable iron sight
|
||||
m_flStartLength = m_flLastLength;
|
||||
m_flOffsetLength = r_dof_focal_length->value;
|
||||
m_flDOFStartTime = tr.time;
|
||||
}
|
||||
|
||||
|
||||
// ALERT( at_console, "Iron sight changed( %i )\n", g_iGunMode );
|
||||
g_iGunLastMode = g_iGunMode;
|
||||
}
|
||||
|
||||
if( g_iGunLastMode == 1 && m_flDOFStartTime == 0.0f )
|
||||
return false; // iron sight disabled
|
||||
|
||||
if( !Begin( )) return false;
|
||||
|
||||
if( m_flDOFStartTime != 0.0f )
|
||||
{
|
||||
float flDegree = (tr.time - m_flDOFStartTime) / 0.3f;
|
||||
|
||||
if( flDegree >= 1.0f )
|
||||
{
|
||||
// all done. holds the final value
|
||||
m_flLastLength = m_flStartLength + m_flOffsetLength;
|
||||
m_flDOFStartTime = 0.0f; // done
|
||||
}
|
||||
else
|
||||
{
|
||||
// evaluate focal length
|
||||
m_flLastLength = m_flStartLength + m_flOffsetLength * flDegree;
|
||||
}
|
||||
}
|
||||
|
||||
float zNear = Z_NEAR; // fixed
|
||||
float zFar = RI->view.farClip;
|
||||
float depthValue = 0.0f;
|
||||
|
||||
// get current depth value
|
||||
pglReadPixels( glState.width >> 1, glState.height >> 1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthValue );
|
||||
depthValue = RemapVal( depthValue, 0.0, 0.8, 0.0, 1.0 );
|
||||
depthValue = -zFar * zNear / ( depthValue * ( zFar - zNear ) - zFar ); // linearize it
|
||||
float holdTime = bound( 0.01f, r_dof_hold_time->value, 0.5f );
|
||||
float changeTime = bound( 0.1f, r_dof_change_time->value, 2.0f );
|
||||
|
||||
if( Q_round( m_flCachedDepth, 10 ) != Q_round( depthValue, 10 ))
|
||||
{
|
||||
m_flStartTime = 0.0f; // cancelling changes
|
||||
m_flDelayTime = tr.time; // make sure what focal point is not changed more than 0.5 secs
|
||||
m_flStartDepth = m_flLastDepth; // get last valid depth
|
||||
m_flOffsetDepth = depthValue - m_flStartDepth;
|
||||
m_flCachedDepth = depthValue;
|
||||
}
|
||||
|
||||
if(( tr.time - m_flDelayTime ) > holdTime && m_flStartTime == 0.0f && m_flDelayTime != 0.0f )
|
||||
{
|
||||
// begin the change depth
|
||||
m_flStartTime = tr.time;
|
||||
}
|
||||
|
||||
if( m_flStartTime != 0.0f )
|
||||
{
|
||||
float flDegree = (tr.time - m_flStartTime) / changeTime;
|
||||
|
||||
if( flDegree >= 1.0f )
|
||||
{
|
||||
// all done. holds the final value
|
||||
m_flLastDepth = m_flStartDepth + m_flOffsetDepth;
|
||||
m_flStartTime = m_flDelayTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// evaluate focal depth
|
||||
m_flLastDepth = m_flStartDepth + m_flOffsetDepth * flDegree;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasePostEffects :: ProcessSunShafts( void )
|
||||
{
|
||||
if( !CVAR_TO_BOOL( v_sunshafts ))
|
||||
return false;
|
||||
|
||||
if( !FBitSet( world->features, WORLD_HAS_SKYBOX ))
|
||||
return false;
|
||||
|
||||
if( tr.sky_normal == g_vecZero )
|
||||
return false;
|
||||
|
||||
// update blur params
|
||||
blurFactor[0] = 0.15f;
|
||||
blurFactor[1] = 0.15f;
|
||||
|
||||
if( tr.sun_light_enabled ) m_vecSunLightColor = tr.sun_diffuse;
|
||||
else m_vecSunLightColor = tr.sky_ambient * (1.0f/128.0f) * tr.diffuseFactor;
|
||||
Vector sunPos = tr.cached_vieworigin + tr.sky_normal * 1000.0;
|
||||
ColorNormalize( m_vecSunLightColor, m_vecSunLightColor );
|
||||
|
||||
Vector ndc, view;
|
||||
|
||||
// project sunpos to screen
|
||||
R_TransformWorldToDevice( sunPos, ndc );
|
||||
R_TransformDeviceToScreen( ndc, m_vecSunPosition );
|
||||
m_vecSunPosition.z = DotProduct( -tr.sky_normal, GetVForward( ));
|
||||
|
||||
if( m_vecSunPosition.z < 0.01f )
|
||||
return false; // fade out
|
||||
|
||||
// convert to screen pixels
|
||||
m_vecSunPosition.x = m_vecSunPosition.x / glState.width;
|
||||
m_vecSunPosition.y = m_vecSunPosition.y / glState.height;
|
||||
|
||||
return Begin();
|
||||
}
|
||||
|
||||
bool CBasePostEffects :: Begin( void )
|
||||
{
|
||||
// we are in cubemap rendering mode
|
||||
if( !RP_NORMALPASS( ))
|
||||
return false;
|
||||
|
||||
if( !CVAR_TO_BOOL( v_posteffects ))
|
||||
return false;
|
||||
|
||||
GL_Setup2D();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBasePostEffects :: End( void )
|
||||
{
|
||||
GL_CleanUpTextureUnits( 0 );
|
||||
GL_BindShader( NULL );
|
||||
GL_Setup3D();
|
||||
}
|
||||
|
||||
static CBasePostEffects post;
|
||||
|
||||
void InitPostEffects( void )
|
||||
{
|
||||
char options[MAX_OPTIONS_LENGTH];
|
||||
|
||||
v_posteffects = CVAR_REGISTER( "gl_posteffects", "1", FCVAR_ARCHIVE );
|
||||
v_sunshafts = CVAR_REGISTER( "gl_sunshafts", "1", FCVAR_ARCHIVE );
|
||||
v_grayscale = CVAR_REGISTER( "gl_grayscale", "0", 0 );
|
||||
|
||||
memset( &post, 0, sizeof( post ));
|
||||
|
||||
// monochrome effect
|
||||
post.monoShader = GL_FindShader( "postfx/monochrome", "postfx/generic", "postfx/monochrome" );
|
||||
|
||||
// gaussian blur for X
|
||||
GL_SetShaderDirective( options, "BLUR_X" );
|
||||
post.blurShader[0] = GL_FindShader( "postfx/gaussblur", "postfx/generic", "postfx/gaussblur", options );
|
||||
|
||||
// gaussian blur for Y
|
||||
GL_SetShaderDirective( options, "BLUR_Y" );
|
||||
post.blurShader[1] = GL_FindShader( "postfx/gaussblur", "postfx/generic", "postfx/gaussblur", options );
|
||||
|
||||
// DOF with bokeh
|
||||
post.dofShader = GL_FindShader( "postfx/dofbokeh", "postfx/generic", "postfx/dofbokeh" );
|
||||
|
||||
// prepare sunshafts
|
||||
post.genSunShafts = GL_FindShader( "postfx/genshafts", "postfx/generic", "postfx/genshafts" );
|
||||
|
||||
// render sunshafts
|
||||
post.drawSunShafts = GL_FindShader( "postfx/drawshafts", "postfx/generic", "postfx/drawshafts" );
|
||||
}
|
||||
|
||||
void InitPostTextures( void )
|
||||
{
|
||||
post.InitScreenColor();
|
||||
post.InitScreenDepth();
|
||||
post.InitTargetColor( 0 );
|
||||
post.InitDepthOfField();
|
||||
}
|
||||
|
||||
static float GetGrayscaleFactor( void )
|
||||
{
|
||||
float grayscale = v_grayscale->value;
|
||||
|
||||
if( gHUD.m_flDeadTime )
|
||||
{
|
||||
float fact = (tr.time - gHUD.m_flDeadTime) / DEAD_GRAYSCALE_TIME;
|
||||
|
||||
fact = Q_min( fact, 1.0f );
|
||||
grayscale = Q_max( fact, grayscale );
|
||||
}
|
||||
|
||||
return grayscale;
|
||||
}
|
||||
|
||||
// rectangle version
|
||||
void RenderFSQ( void )
|
||||
{
|
||||
float screenWidth = (float)glState.width;
|
||||
float screenHeight = (float)glState.height;
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, screenHeight );
|
||||
pglVertex2f( 0.0f, 0.0f );
|
||||
pglTexCoord2f( screenWidth, screenHeight );
|
||||
pglVertex2f( screenWidth, 0.0f );
|
||||
pglTexCoord2f( screenWidth, 0.0f );
|
||||
pglVertex2f( screenWidth, screenHeight );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglVertex2f( 0.0f, screenHeight );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
void RenderFSQ( int wide, int tall )
|
||||
{
|
||||
float screenWidth = (float)wide;
|
||||
float screenHeight = (float)tall;
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, 1.0f );
|
||||
pglNormal3fv( tr.screen_normals[0] );
|
||||
pglVertex2f( 0.0f, 0.0f );
|
||||
pglTexCoord2f( 1.0f, 1.0f );
|
||||
pglNormal3fv( tr.screen_normals[1] );
|
||||
pglVertex2f( screenWidth, 0.0f );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
pglNormal3fv( tr.screen_normals[2] );
|
||||
pglVertex2f( screenWidth, screenHeight );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglNormal3fv( tr.screen_normals[3] );
|
||||
pglVertex2f( 0.0f, screenHeight );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
void GL_DrawScreenSpaceQuad( void )
|
||||
{
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, 1.0f );
|
||||
pglNormal3fv( tr.screen_normals[0] );
|
||||
pglVertex3f( 0.0f, 0.0f, 0.0f );
|
||||
pglNormal3fv( tr.screen_normals[1] );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglVertex3f( 0.0f, glState.height, 0.0f );
|
||||
pglNormal3fv( tr.screen_normals[2] );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
pglVertex3f( glState.width, glState.height, 0.0f );
|
||||
pglNormal3fv( tr.screen_normals[3] );
|
||||
pglTexCoord2f( 1.0f, 1.0f );
|
||||
pglVertex3f( glState.width, 0.0f, 0.0f );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
void V_RenderPostEffect( word hProgram )
|
||||
{
|
||||
if( hProgram <= 0 )
|
||||
{
|
||||
GL_BindShader( NULL );
|
||||
return; // bad shader?
|
||||
}
|
||||
|
||||
if( RI->currentshader != &glsl_programs[hProgram] )
|
||||
{
|
||||
// force to bind new shader
|
||||
GL_BindShader( &glsl_programs[hProgram] );
|
||||
}
|
||||
|
||||
glsl_program_t *shader = RI->currentshader;
|
||||
|
||||
// setup specified uniforms (and texture bindings)
|
||||
for( int i = 0; i < shader->numUniforms; i++ )
|
||||
{
|
||||
uniform_t *u = &shader->uniforms[i];
|
||||
|
||||
switch( u->type )
|
||||
{
|
||||
case UT_SCREENMAP:
|
||||
if( post.m_bUseTarget ) // HACKHACK
|
||||
u->SetValue( post.target_rgb[0] );
|
||||
else u->SetValue( tr.screen_color );
|
||||
break;
|
||||
case UT_DEPTHMAP:
|
||||
u->SetValue( tr.screen_depth );
|
||||
break;
|
||||
case UT_COLORMAP:
|
||||
u->SetValue( post.target_rgb[0] );
|
||||
break;
|
||||
case UT_GRAYSCALE:
|
||||
u->SetValue( post.grayScaleFactor );
|
||||
break;
|
||||
case UT_BLURFACTOR:
|
||||
u->SetValue( post.blurFactor[0], post.blurFactor[1] );
|
||||
break;
|
||||
case UT_SCREENSIZEINV:
|
||||
u->SetValue( 1.0f / (float)glState.width, 1.0f / (float)glState.height );
|
||||
break;
|
||||
case UT_SCREENWIDTH:
|
||||
u->SetValue( (float)glState.width );
|
||||
break;
|
||||
case UT_SCREENHEIGHT:
|
||||
u->SetValue( (float)glState.height );
|
||||
break;
|
||||
case UT_FOCALDEPTH:
|
||||
u->SetValue( post.m_flLastDepth );
|
||||
break;
|
||||
case UT_FOCALLENGTH:
|
||||
u->SetValue( post.m_flLastLength );
|
||||
break;
|
||||
case UT_DOFDEBUG:
|
||||
u->SetValue( CVAR_TO_BOOL( r_dof_debug ));
|
||||
break;
|
||||
case UT_FSTOP:
|
||||
u->SetValue( r_dof_fstop->value );
|
||||
break;
|
||||
case UT_ZFAR:
|
||||
u->SetValue( RI->view.farClip );
|
||||
break;
|
||||
case UT_GAMMATABLE:
|
||||
u->SetValue( &tr.gamma_table[0][0], 64 );
|
||||
break;
|
||||
case UT_DIFFUSEFACTOR:
|
||||
u->SetValue( tr.diffuseFactor );
|
||||
break;
|
||||
case UT_AMBIENTFACTOR:
|
||||
u->SetValue( tr.ambientFactor );
|
||||
break;
|
||||
case UT_SUNREFRACT:
|
||||
u->SetValue( tr.sun_refract );
|
||||
break;
|
||||
case UT_REALTIME:
|
||||
u->SetValue( (float)tr.time );
|
||||
break;
|
||||
case UT_LIGHTDIFFUSE:
|
||||
u->SetValue( post.m_vecSunLightColor.x, post.m_vecSunLightColor.y, post.m_vecSunLightColor.z );
|
||||
break;
|
||||
case UT_LIGHTORIGIN:
|
||||
u->SetValue( post.m_vecSunPosition.x, post.m_vecSunPosition.y, post.m_vecSunPosition.z );
|
||||
break;
|
||||
case UT_FOGPARAMS:
|
||||
u->SetValue( tr.fogColor[0], tr.fogColor[1], tr.fogColor[2], tr.fogDensity );
|
||||
break;
|
||||
default:
|
||||
ALERT( at_error, "%s: unhandled uniform %s\n", RI->currentshader->name, u->name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// render a fullscreen quad
|
||||
RenderFSQ( glState.width, glState.height );
|
||||
}
|
||||
|
||||
void RenderBlur( float blurX, float blurY )
|
||||
{
|
||||
if( !blurX && !blurY )
|
||||
return;
|
||||
|
||||
// update blur params
|
||||
post.blurFactor[0] = blurX;
|
||||
post.blurFactor[1] = blurY;
|
||||
|
||||
if( !post.Begin( )) return;
|
||||
|
||||
// do vertical blur
|
||||
post.RequestScreenColor();
|
||||
V_RenderPostEffect( post.blurShader[0] );
|
||||
|
||||
// do horizontal blur
|
||||
post.RequestScreenColor();
|
||||
V_RenderPostEffect( post.blurShader[1] );
|
||||
|
||||
post.End();
|
||||
}
|
||||
|
||||
void RenderMonochrome( void )
|
||||
{
|
||||
post.grayScaleFactor = GetGrayscaleFactor();
|
||||
if( post.grayScaleFactor <= 0.0f ) return;
|
||||
|
||||
if( !post.Begin( )) return;
|
||||
|
||||
// apply monochromatic
|
||||
post.RequestScreenColor();
|
||||
V_RenderPostEffect( post.monoShader );
|
||||
|
||||
post.End();
|
||||
}
|
||||
|
||||
void RenderUnderwaterBlur( void )
|
||||
{
|
||||
if( !CVAR_TO_BOOL( cv_water ) || tr.waterlevel < 3 )
|
||||
return;
|
||||
|
||||
float factor = sin( tr.time * 0.1f * ( M_PI * 2.7f ));
|
||||
float blurX = RemapVal( factor, -1.0f, 1.0f, 0.18f, 0.23f );
|
||||
float blurY = RemapVal( factor, -1.0f, 1.0f, 0.15f, 0.24f );
|
||||
|
||||
RenderBlur( blurX, blurY );
|
||||
}
|
||||
|
||||
void RenderNerveGasBlur( void )
|
||||
{
|
||||
if( gHUD.m_flBlurAmount <= 0.0f )
|
||||
return;
|
||||
|
||||
float factor = sin( tr.time * 0.4f * ( M_PI * 1.7f ));
|
||||
float blurX = RemapVal( factor, -1.0f, 1.0f, 0.0f, 0.3f );
|
||||
float blurY = RemapVal( factor, -1.0f, 1.0f, 0.0f, 0.3f );
|
||||
|
||||
blurX = bound( 0.0f, blurX, gHUD.m_flBlurAmount );
|
||||
blurY = bound( 0.0f, blurY, gHUD.m_flBlurAmount );
|
||||
|
||||
RenderBlur( blurX, blurY );
|
||||
}
|
||||
|
||||
void RenderDOF( void )
|
||||
{
|
||||
if( !post.ProcessDepthOfField( ))
|
||||
return;
|
||||
|
||||
post.RequestScreenColor();
|
||||
post.RequestScreenDepth();
|
||||
V_RenderPostEffect( post.dofShader );
|
||||
|
||||
post.End();
|
||||
}
|
||||
|
||||
void RenderSunShafts( void )
|
||||
{
|
||||
if( !post.ProcessSunShafts( ))
|
||||
return;
|
||||
|
||||
post.RequestScreenColor();
|
||||
post.RequestScreenDepth();
|
||||
|
||||
// we operate in small window to increase speedup
|
||||
post.SetTargetViewport();
|
||||
V_RenderPostEffect( post.genSunShafts );
|
||||
post.RequestTargetCopy( 0 );
|
||||
|
||||
post.m_bUseTarget = true;
|
||||
V_RenderPostEffect( post.blurShader[0] );
|
||||
post.RequestTargetCopy( 0 );
|
||||
V_RenderPostEffect( post.blurShader[1] );
|
||||
post.RequestTargetCopy( 0 );
|
||||
post.m_bUseTarget = false;
|
||||
|
||||
// back to normal size
|
||||
post.SetNormalViewport();
|
||||
V_RenderPostEffect( post.drawSunShafts );
|
||||
|
||||
post.End();
|
||||
}
|
99
cl_dll/render/gl_primitive.cpp
Normal file
99
cl_dll/render/gl_primitive.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
gl_primitive.cpp - rendering primitives
|
||||
Copyright (C) 2018 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 "hud.h"
|
||||
#include <stringlib.h>
|
||||
#include "cl_util.h"
|
||||
#include "pm_defs.h"
|
||||
#include "event_api.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_studio.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
|
||||
void CSolidEntry :: SetRenderPrimitive( const Vector verts[4], const Vector4D &color, int texture, int rendermode )
|
||||
{
|
||||
m_bDrawType = DRAWTYPE_QUAD;
|
||||
m_iStartVertex = RI->frame.primverts.Count();
|
||||
|
||||
for( int i = 0; i < 4; i++ )
|
||||
RI->frame.primverts.AddToTail( verts[i] );
|
||||
m_iColor = PackRGBA( color.x * 255, color.y * 255, color.z * 255, color.w * 255 );
|
||||
m_iRenderMode = rendermode;
|
||||
m_hTexture = texture;
|
||||
}
|
||||
|
||||
void CSolidEntry :: SetRenderSurface( msurface_t *surface, word hProgram )
|
||||
{
|
||||
m_bDrawType = DRAWTYPE_SURFACE;
|
||||
m_pSurf = surface;
|
||||
m_pParentEntity = RI->currententity;
|
||||
m_pRenderModel = RI->currentmodel;
|
||||
m_hProgram = hProgram;
|
||||
}
|
||||
|
||||
void CSolidEntry :: SetRenderMesh( vbomesh_t *mesh, word hProgram )
|
||||
{
|
||||
m_bDrawType = DRAWTYPE_MESH;
|
||||
m_pMesh = mesh;
|
||||
m_pParentEntity = RI->currententity;
|
||||
m_pRenderModel = RI->currentmodel;
|
||||
m_hProgram = hProgram;
|
||||
}
|
||||
|
||||
void CTransEntry :: ComputeViewDistance( const Vector &absmin, const Vector &absmax )
|
||||
{
|
||||
#if 1
|
||||
m_flViewDist = CalcSqrDistanceToAABB( absmin, absmax, GetVieworg( ));
|
||||
#else
|
||||
Vector origin = (absmin + absmax) * 0.5f;
|
||||
m_flViewDist = DotProduct( origin, GetVForward() ) - RI->view.planedist;
|
||||
// m_flViewDist = VectorDistance2( origin, GetVieworg( ));
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTransEntry :: ComputeScissor( const Vector &absmin, const Vector &absmax )
|
||||
{
|
||||
ComputeViewDistance( absmin, absmax );
|
||||
|
||||
if( R_ScissorForAABB( absmin, absmax, &m_vecRect.x, &m_vecRect.y, &m_vecRect.z, &m_vecRect.w ))
|
||||
m_bScissorReady = true;
|
||||
else m_bScissorReady = false;
|
||||
}
|
||||
|
||||
void CTransEntry :: RequestScreenColor( void )
|
||||
{
|
||||
if( !m_bScissorReady ) return;
|
||||
|
||||
float y2 = (float)RI->view.port[3] - m_vecRect.w - m_vecRect.y;
|
||||
GL_BindTexture( GL_TEXTURE0, tr.screen_color );
|
||||
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, m_vecRect.x, y2, m_vecRect.x, y2, m_vecRect.z, m_vecRect.w );
|
||||
}
|
||||
|
||||
void CTransEntry :: RequestScreenDepth( void )
|
||||
{
|
||||
if( !m_bScissorReady ) return;
|
||||
|
||||
float y2 = (float)RI->view.port[3] - m_vecRect.w - m_vecRect.y;
|
||||
GL_BindTexture( GL_TEXTURE0, tr.screen_depth );
|
||||
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, m_vecRect.x, y2, m_vecRect.x, y2, m_vecRect.z, m_vecRect.w );
|
||||
}
|
||||
|
||||
void CTransEntry :: RenderScissorDebug( void )
|
||||
{
|
||||
if( !m_bScissorReady ) return;
|
||||
|
||||
R_DrawScissorRectangle( m_vecRect.x, m_vecRect.y, m_vecRect.z, m_vecRect.w );
|
||||
}
|
80
cl_dll/render/gl_primitive.h
Normal file
80
cl_dll/render/gl_primitive.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
gl_primitive.h - render primitives
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_PRIMITIVE_H
|
||||
#define GL_PRIMITIVE_H
|
||||
|
||||
#define DRAWTYPE_UNKNOWN 0
|
||||
#define DRAWTYPE_SURFACE 1
|
||||
#define DRAWTYPE_MESH 2
|
||||
#define DRAWTYPE_QUAD 3
|
||||
|
||||
//#pragma pack(1)
|
||||
|
||||
class CSolidEntry
|
||||
{
|
||||
public:
|
||||
void SetRenderPrimitive( const Vector verts[4], const Vector4D &color, int texture, int rendermode );
|
||||
void SetRenderSurface( msurface_t *surface, word hProgram );
|
||||
void SetRenderMesh( struct vbomesh_s *mesh, word hProgram );
|
||||
virtual bool IsTranslucent( void ) { return false; }
|
||||
int GetType( void ) { return m_bDrawType; }
|
||||
|
||||
byte m_bDrawType; // type of entry
|
||||
|
||||
union
|
||||
{
|
||||
cl_entity_t *m_pParentEntity; // pointer to parent entity
|
||||
int m_iRenderMode; // rendermode for primitive
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
model_t *m_pRenderModel; // render model
|
||||
int m_iStartVertex; // offset in global heap
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
unsigned short m_hProgram; // handle to glsl program (may be 0)
|
||||
unsigned short m_hTexture; // texture for primitive
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
struct vbomesh_s *m_pMesh; // NULL or mesh
|
||||
msurface_t *m_pSurf; // NULL or surface
|
||||
int m_iColor; // primitive color
|
||||
};
|
||||
};
|
||||
|
||||
class CTransEntry : public CSolidEntry
|
||||
{
|
||||
public:
|
||||
void ComputeViewDistance( const Vector &absmin, const Vector &absmax );
|
||||
void ComputeScissor( const Vector &absmin, const Vector &absmax );
|
||||
virtual bool IsTranslucent( void ) { return true; }
|
||||
void RequestScreenColor( void );
|
||||
void RequestScreenDepth( void );
|
||||
void RenderScissorDebug( void );
|
||||
|
||||
float m_flViewDist;
|
||||
Vector4D m_vecRect;
|
||||
bool m_bScissorReady : 1;
|
||||
};
|
||||
//#pragma pack()
|
||||
|
||||
#endif//GL_PRIMITIVE_H
|
1218
cl_dll/render/gl_rmain.cpp
Normal file
1218
cl_dll/render/gl_rmain.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1202
cl_dll/render/gl_rmisc.cpp
Normal file
1202
cl_dll/render/gl_rmisc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1181
cl_dll/render/gl_rpart.cpp
Normal file
1181
cl_dll/render/gl_rpart.cpp
Normal file
File diff suppressed because it is too large
Load Diff
144
cl_dll/render/gl_rpart.h
Normal file
144
cl_dll/render/gl_rpart.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
gl_rpart.h - quake-like particles
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_RPART_H
|
||||
#define GL_RPART_H
|
||||
|
||||
#include "randomrange.h"
|
||||
|
||||
#define MAX_PARTICLES 8192
|
||||
#define MAX_PARTINFOS 256 // various types of part-system
|
||||
|
||||
// built-in particle-system flags
|
||||
#define FPART_BOUNCE (1<<0) // makes a bouncy particle
|
||||
#define FPART_FRICTION (1<<1)
|
||||
#define FPART_VERTEXLIGHT (1<<2) // give some ambient light for it
|
||||
#define FPART_STRETCH (1<<3)
|
||||
#define FPART_UNDERWATER (1<<4)
|
||||
#define FPART_INSTANT (1<<5)
|
||||
#define FPART_ADDITIVE (1<<6)
|
||||
#define FPART_NOTWATER (1<<7) // don't spawn in water
|
||||
|
||||
class CQuakePart
|
||||
{
|
||||
public:
|
||||
Vector m_vecOrigin; // position for current frame
|
||||
Vector m_vecLastOrg; // position from previous frame
|
||||
|
||||
Vector m_vecVelocity; // linear velocity
|
||||
Vector m_vecAccel;
|
||||
Vector m_vecColor;
|
||||
Vector m_vecColorVelocity;
|
||||
float m_flAlpha;
|
||||
float m_flAlphaVelocity;
|
||||
float m_flRadius;
|
||||
float m_flRadiusVelocity;
|
||||
float m_flLength;
|
||||
float m_flLengthVelocity;
|
||||
float m_flRotation; // texture ROLL angle
|
||||
float m_flBounceFactor;
|
||||
|
||||
CQuakePart *pNext; // linked list
|
||||
int m_hTexture;
|
||||
|
||||
float m_flTime;
|
||||
int m_iFlags;
|
||||
|
||||
bool Evaluate( float gravity );
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NORMAL_IGNORE = 0,
|
||||
NORMAL_OFFSET,
|
||||
NORMAL_DIRECTION,
|
||||
NORMAL_OFS_DIR,
|
||||
};
|
||||
|
||||
class CQuakePartInfo
|
||||
{
|
||||
public:
|
||||
char m_szName[32]; // effect name
|
||||
|
||||
struct model_s *m_pSprite; // sprite
|
||||
int m_hTexture; // tga texture
|
||||
|
||||
RandomRange offset[3];
|
||||
RandomRange velocity[3];
|
||||
RandomRange accel[3];
|
||||
RandomRange color[3];
|
||||
RandomRange colorVel[3];
|
||||
RandomRange alpha;
|
||||
RandomRange alphaVel;
|
||||
RandomRange radius;
|
||||
RandomRange radiusVel;
|
||||
RandomRange length;
|
||||
RandomRange lengthVel;
|
||||
RandomRange rotation;
|
||||
RandomRange bounce;
|
||||
RandomRange frame;
|
||||
RandomRange count; // particle count
|
||||
|
||||
int normal; // how to use normal
|
||||
int flags; // particle flags
|
||||
};
|
||||
|
||||
class CQuakePartSystem
|
||||
{
|
||||
CQuakePart *m_pActiveParticles;
|
||||
CQuakePart *m_pFreeParticles;
|
||||
CQuakePart m_pParticles[MAX_PARTICLES];
|
||||
|
||||
CQuakePartInfo m_pPartInfo[MAX_PARTINFOS];
|
||||
int m_iNumPartInfo;
|
||||
|
||||
// private partsystem shaders
|
||||
int m_hDefaultParticle;
|
||||
int m_hSparks;
|
||||
int m_hSmoke;
|
||||
int m_hWaterSplash;
|
||||
|
||||
cvar_t *m_pAllowParticles;
|
||||
cvar_t *m_pParticleLod;
|
||||
public:
|
||||
CQuakePartSystem( void );
|
||||
virtual ~CQuakePartSystem( void );
|
||||
|
||||
void Clear( void );
|
||||
void Update( void );
|
||||
void FreeParticle( CQuakePart *pCur );
|
||||
CQuakePart *AllocParticle( void );
|
||||
bool AddParticle( CQuakePart *src, int texture = 0, int flags = 0 );
|
||||
void ParsePartInfos( const char *filename );
|
||||
bool ParsePartInfo( CQuakePartInfo *info, char *&pfile );
|
||||
bool ParseRandomVector( char *&pfile, RandomRange out[3] );
|
||||
int ParseParticleFlags( char *pfile );
|
||||
CQuakePartInfo *FindPartInfo( const char *name );
|
||||
void CreateEffect( const char *name, const Vector &origin, const Vector &normal );
|
||||
|
||||
// example presets
|
||||
void ExplosionParticles( const Vector &pos );
|
||||
void BulletParticles( const Vector &org, const Vector &dir );
|
||||
void BubbleParticles( const Vector &org, int count, float magnitude );
|
||||
void SparkParticles( const Vector &org, const Vector &dir );
|
||||
void RicochetSparks( const Vector &org, float scale );
|
||||
void SmokeParticles( const Vector &pos, int count );
|
||||
void GunSmoke( const Vector &pos, int count );
|
||||
};
|
||||
|
||||
extern CQuakePartSystem g_pParticles;
|
||||
|
||||
#endif//GL_RPART_H
|
99
cl_dll/render/gl_rsurf.cpp
Normal file
99
cl_dll/render/gl_rsurf.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
gl_rsurf.cpp - surface-related code
|
||||
Copyright (C) 2013 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
|
||||
static int rtable[MOD_FRAMES][MOD_FRAMES];
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TextureAnimation
|
||||
|
||||
Returns the proper texture for a given time and base texture
|
||||
===============
|
||||
*/
|
||||
texture_t *R_TextureAnimation( msurface_t *s )
|
||||
{
|
||||
texture_t *base = s->texinfo->texture;
|
||||
int count, reletive = 0;
|
||||
|
||||
if(( RI->currententity != NULL ) && ( RI->currententity->curstate.frame != 0.0f ))
|
||||
{
|
||||
if( base->alternate_anims )
|
||||
base = base->alternate_anims;
|
||||
}
|
||||
|
||||
if( !base->anim_total )
|
||||
return base;
|
||||
|
||||
if( base->name[0] == '-' )
|
||||
{
|
||||
int tx = (int)((s->texturemins[0] + (base->width << 16)) / base->width) % MOD_FRAMES;
|
||||
int ty = (int)((s->texturemins[1] + (base->height << 16)) / base->height) % MOD_FRAMES;
|
||||
reletive = rtable[tx][ty] % base->anim_total;
|
||||
}
|
||||
else
|
||||
{
|
||||
reletive = (int)(tr.time * 20) % base->anim_total;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
||||
while( base->anim_min > reletive || base->anim_max <= reletive )
|
||||
{
|
||||
base = base->anim_next;
|
||||
|
||||
if( !base )
|
||||
{
|
||||
ALERT( at_error, "R_TextureAnimation: broken loop\n" );
|
||||
return s->texinfo->texture;
|
||||
}
|
||||
|
||||
if( ++count > MOD_FRAMES )
|
||||
{
|
||||
ALERT( at_error, "R_TextureAnimation: infinite loop\n" );
|
||||
return s->texinfo->texture;
|
||||
}
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
WORLD MODEL
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
void GL_InitRandomTable( void )
|
||||
{
|
||||
int tu, tv;
|
||||
|
||||
// make random predictable
|
||||
RANDOM_SEED( 255 );
|
||||
|
||||
for( tu = 0; tu < MOD_FRAMES; tu++ )
|
||||
{
|
||||
for( tv = 0; tv < MOD_FRAMES; tv++ )
|
||||
{
|
||||
rtable[tu][tv] = RANDOM_LONG( 0, 0x7FFF );
|
||||
}
|
||||
}
|
||||
|
||||
RANDOM_SEED( 0 );
|
||||
}
|
548
cl_dll/render/gl_scene.cpp
Normal file
548
cl_dll/render/gl_scene.cpp
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
gl_scene.cpp - scene management
|
||||
Copyright (C) 2016 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "camera.h"
|
||||
#include "entity_types.h"
|
||||
#include "gl_local.h"
|
||||
#include <mathlib.h>
|
||||
#include "gl_aurora.h"
|
||||
#include "gl_rpart.h"
|
||||
#include "gl_studio.h"
|
||||
#include "gl_sprite.h"
|
||||
#include "event_api.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
#include "screenfade.h"
|
||||
#include "shake.h"
|
||||
|
||||
/*
|
||||
===============
|
||||
R_CheckChanges
|
||||
===============
|
||||
*/
|
||||
void R_CheckChanges( void )
|
||||
{
|
||||
static bool fog_enabled_old;
|
||||
bool settings_changed = false;
|
||||
|
||||
if( FBitSet( r_showlightmaps->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
float lightmap = bound( 0.0f, r_showlightmaps->value, MAX_LIGHTMAPS );
|
||||
CVAR_SET_FLOAT( "r_showlightmaps", lightmap );
|
||||
ClearBits( r_showlightmaps->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( FBitSet( r_studio_decals->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
float maxStudioDecals = bound( 10.0f, r_studio_decals->value, 256.0f );
|
||||
CVAR_SET_FLOAT( "r_studio_decals", maxStudioDecals );
|
||||
ClearBits( r_studio_decals->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( FBitSet( cv_deferred_maxlights->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
float maxDeferredLights = bound( 1, cv_deferred_maxlights->value, MAXDYNLIGHTS );
|
||||
if( maxDeferredLights != cv_deferred_maxlights->value )
|
||||
CVAR_SET_FLOAT( "gl_deferred_maxlights", maxDeferredLights );
|
||||
ClearBits( cv_deferred_maxlights->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( FBitSet( cv_deferred_tracebmodels->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_deferred_tracebmodels->flags, FCVAR_CHANGED );
|
||||
tr.params_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_recursion_depth->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
float depth = bound( 0.0f, r_recursion_depth->value, MAX_REF_STACK - 2 );
|
||||
CVAR_SET_FLOAT( "gl_recursion_depth", depth );
|
||||
ClearBits( r_recursion_depth->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( FBitSet( r_drawentities->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_drawentities->flags, FCVAR_CHANGED );
|
||||
tr.params_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_lightstyles->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_lightstyles->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_cubemaps->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_cubemaps->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_deferred->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_deferred->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_lightmap->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_lightmap->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_allow_mirrors->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_allow_mirrors->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_realtime_puddles->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_realtime_puddles->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_detailtextures->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_detailtextures->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_fullbright->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_fullbright->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_sunshadows->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_sunshadows->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_sun_allowed->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_sun_allowed->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_parallax->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_parallax->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_specular->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_specular->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_grass_shadows->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_grass_shadows->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_shadows->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_shadows->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_bump->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_bump->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_brdf->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( cv_brdf->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_test->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( r_test->flags, FCVAR_CHANGED );
|
||||
R_StudioClearLightCache();
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( r_grass->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
if( worldmodel != NULL )
|
||||
{
|
||||
for( int i = 0; i < worldmodel->numsurfaces; i++ )
|
||||
SetBits( worldmodel->surfaces[i].flags, SURF_GRASS_UPDATE );
|
||||
}
|
||||
ClearBits( r_grass->flags, FCVAR_CHANGED );
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( FBitSet( cv_gamma->flags, FCVAR_CHANGED ) || FBitSet( cv_brightness->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
if( worldmodel != NULL )
|
||||
{
|
||||
for( int i = 0; i < worldmodel->numsurfaces; i++ )
|
||||
SetBits( worldmodel->surfaces[i].flags, SURF_LM_UPDATE|SURF_GRASS_UPDATE );
|
||||
}
|
||||
R_StudioClearLightCache();
|
||||
}
|
||||
|
||||
if( tr.fogEnabled != fog_enabled_old )
|
||||
{
|
||||
fog_enabled_old = tr.fogEnabled;
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if( settings_changed )
|
||||
{
|
||||
tr.glsl_valid_sequence++; // now all uber-shaders are invalidate and possible need for recompile
|
||||
tr.params_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ClearScene
|
||||
===============
|
||||
*/
|
||||
void R_ClearScene( void )
|
||||
{
|
||||
if( !g_fRenderInitialized ) return;
|
||||
|
||||
CL_DecayLights();
|
||||
|
||||
tr.time = GET_CLIENT_TIME();
|
||||
tr.oldtime = GET_CLIENT_OLDTIME();
|
||||
tr.frametime = tr.time - tr.oldtime;
|
||||
tr.saved_frametime = tr.frametime; // backup
|
||||
|
||||
memset( &r_stats, 0, sizeof( r_stats ));
|
||||
|
||||
tr.local_client_added = false;
|
||||
tr.num_draw_entities = 0;
|
||||
tr.cached_state.Purge(); // invalidate cache
|
||||
GET_ENTITY( 0 )->hCachedMatrix = GL_CacheState( g_vecZero, g_vecZero );
|
||||
|
||||
tr.num_2D_shadows_used = tr.num_CM_shadows_used = 0;
|
||||
tr.sun_light_enabled = false;
|
||||
|
||||
if( r_sunshadows->value > 2.0f )
|
||||
CVAR_SET_FLOAT( "gl_sun_shadows", 2.0f );
|
||||
else if( r_sunshadows->value < 0.0f )
|
||||
CVAR_SET_FLOAT( "gl_sun_shadows", 0.0f );
|
||||
|
||||
if( tr.shadows_notsupport )
|
||||
CVAR_SET_FLOAT( "r_shadows", 0.0f );
|
||||
|
||||
R_CheckChanges();
|
||||
|
||||
if( tr.params_changed )
|
||||
R_InitDynLightShaders();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ComputeFxBlend
|
||||
===============
|
||||
*/
|
||||
int R_ComputeFxBlend( cl_entity_t *e )
|
||||
{
|
||||
int blend = 0, renderAmt;
|
||||
float offset, dist;
|
||||
Vector tmp;
|
||||
|
||||
offset = ((int)e->index ) * 363.0f; // Use ent index to de-sync these fx
|
||||
renderAmt = e->curstate.renderamt;
|
||||
|
||||
switch( e->curstate.renderfx )
|
||||
{
|
||||
case kRenderFxPulseSlowWide:
|
||||
blend = renderAmt + 0x40 * sin( tr.time * 2 + offset );
|
||||
break;
|
||||
case kRenderFxPulseFastWide:
|
||||
blend = renderAmt + 0x40 * sin( tr.time * 8 + offset );
|
||||
break;
|
||||
case kRenderFxPulseSlow:
|
||||
blend = renderAmt + 0x10 * sin( tr.time * 2 + offset );
|
||||
break;
|
||||
case kRenderFxPulseFast:
|
||||
blend = renderAmt + 0x10 * sin( tr.time * 8 + offset );
|
||||
break;
|
||||
// JAY: HACK for now -- not time based
|
||||
case kRenderFxFadeSlow:
|
||||
if( renderAmt > 0 )
|
||||
renderAmt -= 1;
|
||||
else renderAmt = 0;
|
||||
blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxFadeFast:
|
||||
if( renderAmt > 3 )
|
||||
renderAmt -= 4;
|
||||
else renderAmt = 0;
|
||||
blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxSolidSlow:
|
||||
if( renderAmt < 255 )
|
||||
renderAmt += 1;
|
||||
else renderAmt = 255;
|
||||
blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxSolidFast:
|
||||
if( renderAmt < 252 )
|
||||
renderAmt += 4;
|
||||
else renderAmt = 255;
|
||||
blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxStrobeSlow:
|
||||
blend = 20 * sin( tr.time * 4 + offset );
|
||||
if( blend < 0 ) blend = 0;
|
||||
else blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxStrobeFast:
|
||||
blend = 20 * sin( tr.time * 16 + offset );
|
||||
if( blend < 0 ) blend = 0;
|
||||
else blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxStrobeFaster:
|
||||
blend = 20 * sin( tr.time * 36 + offset );
|
||||
if( blend < 0 ) blend = 0;
|
||||
else blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxFlickerSlow:
|
||||
blend = 20 * (sin( tr.time * 2 ) + sin( tr.time * 17 + offset ));
|
||||
if( blend < 0 ) blend = 0;
|
||||
else blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxFlickerFast:
|
||||
blend = 20 * (sin( tr.time * 16 ) + sin( tr.time * 23 + offset ));
|
||||
if( blend < 0 ) blend = 0;
|
||||
else blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxHologram:
|
||||
case kRenderFxDistort:
|
||||
tmp = e->origin - GetVieworg();
|
||||
dist = DotProduct( tmp, GetVForward( ));
|
||||
|
||||
// Turn off distance fade
|
||||
if( e->curstate.renderfx == kRenderFxDistort )
|
||||
dist = 1;
|
||||
|
||||
if( dist <= 0 )
|
||||
{
|
||||
blend = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
renderAmt = 180;
|
||||
if( dist <= 100 ) blend = renderAmt;
|
||||
else blend = (int) ((1.0f - ( dist - 100 ) * ( 1.0f / 400.0f )) * renderAmt );
|
||||
blend += RANDOM_LONG( -32, 31 );
|
||||
}
|
||||
break;
|
||||
case kRenderFxGlowShell: // safe current renderamt because it's shell scale!
|
||||
case kRenderFxDeadPlayer: // safe current renderamt because it's player index!
|
||||
blend = renderAmt;
|
||||
break;
|
||||
case kRenderFxNone:
|
||||
case kRenderFxClampMinScale:
|
||||
default:
|
||||
if( e->curstate.rendermode == kRenderNormal )
|
||||
blend = 255;
|
||||
else blend = renderAmt;
|
||||
break;
|
||||
}
|
||||
|
||||
if( e->model->type != mod_brush || R_WaterEntity( e->model ))
|
||||
{
|
||||
// NOTE: never pass sprites with rendercolor '0 0 0' it's a stupid Valve Hammer Editor bug
|
||||
if( !e->curstate.rendercolor.r && !e->curstate.rendercolor.g && !e->curstate.rendercolor.b )
|
||||
e->curstate.rendercolor.r = e->curstate.rendercolor.g = e->curstate.rendercolor.b = 255;
|
||||
}
|
||||
|
||||
// apply scale to studiomodels and sprites only
|
||||
if( e->model && e->model->type != mod_brush && !e->curstate.scale )
|
||||
e->curstate.scale = 1.0f;
|
||||
|
||||
blend = bound( 0, blend, 255 );
|
||||
|
||||
return blend;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_AddEntity
|
||||
===============
|
||||
*/
|
||||
qboolean R_AddEntity( struct cl_entity_s *clent, int entityType )
|
||||
{
|
||||
if( !CVAR_TO_BOOL( r_drawentities ))
|
||||
return false; // not allow to drawing
|
||||
|
||||
if( !clent || !clent->model )
|
||||
return false; // if set to invisible, skip
|
||||
|
||||
if( clent->curstate.effects & EF_NODRAW )
|
||||
return false; // done
|
||||
|
||||
if( entityType == ET_PLAYER && RP_LOCALCLIENT( clent ))
|
||||
{
|
||||
if( tr.local_client_added )
|
||||
return false; // already present in list
|
||||
tr.local_client_added = true;
|
||||
}
|
||||
|
||||
if( clent->curstate.renderfx == 71 ) // dynamic light
|
||||
{
|
||||
CDynLight *dl = CL_AllocDlight( clent->curstate.number );
|
||||
|
||||
float radius = clent->curstate.renderamt * 8.0f;
|
||||
float fov = clent->curstate.scale;
|
||||
int tex = 0, flags = 0, type;
|
||||
Vector origin, angles;
|
||||
|
||||
if( clent->curstate.scale ) // spotlight
|
||||
{
|
||||
int i = bound( 0, clent->curstate.rendermode, 7 );
|
||||
tex = tr.spotlightTexture[i];
|
||||
type = LIGHT_SPOT;
|
||||
}
|
||||
else type = LIGHT_OMNI;
|
||||
|
||||
if( clent->curstate.effects & EF_NOSHADOW )
|
||||
flags |= DLF_NOSHADOWS;
|
||||
|
||||
if( clent->curstate.effects & EF_NOBUMP )
|
||||
flags |= DLF_NOBUMP;
|
||||
|
||||
if( clent->curstate.effects & EF_LENSFLARE )
|
||||
flags |= DLF_LENSFLARE;
|
||||
|
||||
R_GetLightVectors( clent, origin, angles );
|
||||
R_SetupLightParams( dl, origin, angles, radius, clent->curstate.scale, type, flags );
|
||||
R_SetupLightTexture( dl, tex );
|
||||
|
||||
dl->color[0] = (float)clent->curstate.rendercolor.r / 128;
|
||||
dl->color[1] = (float)clent->curstate.rendercolor.g / 128;
|
||||
dl->color[2] = (float)clent->curstate.rendercolor.b / 128;
|
||||
dl->die = tr.time + 0.05f;
|
||||
|
||||
return true; // no reason to drawing this entity
|
||||
}
|
||||
else if( clent->curstate.renderfx == 72 ) // dynamic light with avi file
|
||||
{
|
||||
if( !clent->curstate.sequence )
|
||||
return true; // bad avi file
|
||||
|
||||
CDynLight *dl = CL_AllocDlight( clent->curstate.number );
|
||||
|
||||
if( dl->spotlightTexture == tr.spotlightTexture[1] )
|
||||
return true; // bad avi file
|
||||
|
||||
float radius = clent->curstate.renderamt * 8.0f;
|
||||
float fov = clent->curstate.scale;
|
||||
Vector origin, angles;
|
||||
int flags = DLF_ASPECT3X4; // fit to film01.avi aspect
|
||||
|
||||
// found the corresponding cinstate
|
||||
const char *cinname = gRenderfuncs.GetFileByIndex( clent->curstate.sequence );
|
||||
int hCin = R_PrecacheCinematic( cinname );
|
||||
|
||||
if( hCin >= 0 && !dl->cinTexturenum )
|
||||
dl->cinTexturenum = R_AllocateCinematicTexture( TF_SPOTLIGHT );
|
||||
|
||||
if( hCin == -1 || dl->cinTexturenum <= 0 || !CIN_IS_ACTIVE( tr.cinematics[hCin].state ))
|
||||
{
|
||||
// cinematic textures limit exceeded or movie not found
|
||||
dl->spotlightTexture = tr.spotlightTexture[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
gl_movie_t *cin = &tr.cinematics[hCin];
|
||||
float cin_time;
|
||||
|
||||
// advances cinematic time
|
||||
cin_time = fmod( clent->curstate.fuser2, cin->length );
|
||||
|
||||
// read the next frame
|
||||
int cin_frame = CIN_GET_FRAME_NUMBER( cin->state, cin_time );
|
||||
|
||||
if( cin_frame != dl->lastframe )
|
||||
{
|
||||
// upload the new frame
|
||||
byte *raw = CIN_GET_FRAMEDATA( cin->state, cin_frame );
|
||||
CIN_UPLOAD_FRAME( tr.cinTextures[dl->cinTexturenum-1], cin->xres, cin->yres, cin->xres, cin->yres, raw );
|
||||
dl->lastframe = cin_frame;
|
||||
}
|
||||
|
||||
if( clent->curstate.effects & EF_NOSHADOW )
|
||||
flags |= DLF_NOSHADOWS;
|
||||
|
||||
if( clent->curstate.effects & EF_NOBUMP )
|
||||
flags |= DLF_NOBUMP;
|
||||
|
||||
R_GetLightVectors( clent, origin, angles );
|
||||
R_SetupLightParams( dl, origin, angles, radius, clent->curstate.scale, LIGHT_SPOT, flags );
|
||||
R_SetupLightTexture( dl, tr.cinTextures[dl->cinTexturenum-1] );
|
||||
|
||||
dl->color[0] = (float)clent->curstate.rendercolor.r / 128;
|
||||
dl->color[1] = (float)clent->curstate.rendercolor.g / 128;
|
||||
dl->color[2] = (float)clent->curstate.rendercolor.b / 128;
|
||||
dl->die = GET_CLIENT_TIME() + 0.05f;
|
||||
|
||||
return true; // no reason to drawing this entity
|
||||
}
|
||||
|
||||
if( clent->curstate.effects & EF_SCREENMOVIE )
|
||||
{
|
||||
// update cin sound properly
|
||||
R_UpdateCinSound( clent );
|
||||
}
|
||||
|
||||
clent->curstate.renderamt = R_ComputeFxBlend( clent );
|
||||
|
||||
if( !R_OpaqueEntity( clent ))
|
||||
{
|
||||
if( clent->curstate.renderamt <= 0.0f )
|
||||
return true; // invisible
|
||||
}
|
||||
#if 0
|
||||
if( clent->model->type == mod_brush && CVAR_TO_BOOL( r_test ))
|
||||
return true;
|
||||
#endif
|
||||
if( clent->model->type == mod_brush )
|
||||
clent->hCachedMatrix = GL_CacheState( clent->origin, clent->angles, ( clent->curstate.renderfx == SKYBOX_ENTITY ));
|
||||
clent->curstate.entityType = entityType;
|
||||
|
||||
// mark static entity as visible
|
||||
if( entityType == ET_FRAGMENTED )
|
||||
{
|
||||
// non-solid statics wants a new lighting too :-)
|
||||
SetBits( clent->curstate.iuser1, CF_STATIC_ENTITY );
|
||||
clent->visframe = tr.realframecount;
|
||||
}
|
||||
|
||||
if( tr.num_draw_entities < MAX_VISIBLE_ENTS )
|
||||
{
|
||||
tr.draw_entities[tr.num_draw_entities] = clent;
|
||||
tr.num_draw_entities++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
1357
cl_dll/render/gl_shader.cpp
Normal file
1357
cl_dll/render/gl_shader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
262
cl_dll/render/gl_shader.h
Normal file
262
cl_dll/render/gl_shader.h
Normal file
@ -0,0 +1,262 @@
|
||||
/*
|
||||
gl_shader.h - shader parsing and handling
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_SHADER_H
|
||||
#define GL_SHADER_H
|
||||
|
||||
#define MAX_OPTIONS_LENGTH 512
|
||||
#define MAX_GLSL_PROGRAMS 4096
|
||||
|
||||
#define SHADER_VERTEX_COMPILED BIT( 0 )
|
||||
#define SHADER_FRAGMENT_COMPILED BIT( 1 )
|
||||
#define SHADER_PROGRAM_LINKED BIT( 2 )
|
||||
#define SHADER_UBERSHADER BIT( 3 )
|
||||
#define SHADER_TRANSLUCENT BIT( 4 )
|
||||
#define SHADER_USE_CUBEMAPS BIT( 5 )
|
||||
#define SHADER_USE_SCREENCOPY BIT( 6 )
|
||||
#define SHADER_ADDITIVE BIT( 7 )
|
||||
|
||||
#define SHADER_STATUS_OK ( SHADER_PROGRAM_LINKED|SHADER_VERTEX_COMPILED|SHADER_FRAGMENT_COMPILED )
|
||||
#define CheckShader( shader ) ( shader && shader->status == SHADER_STATUS_OK )
|
||||
|
||||
enum
|
||||
{
|
||||
ATTR_INDEX_POSITION = 0,
|
||||
ATTR_INDEX_TANGENT,
|
||||
ATTR_INDEX_BINORMAL,
|
||||
ATTR_INDEX_NORMAL,
|
||||
ATTR_INDEX_TEXCOORD0, // texture coord
|
||||
ATTR_INDEX_TEXCOORD1, // lightmap coord (styles0-1)
|
||||
ATTR_INDEX_TEXCOORD2, // lightmap coord (styles2-3)
|
||||
ATTR_INDEX_BONE_INDEXES, // studiomodels only
|
||||
ATTR_INDEX_BONE_WEIGHTS, // studiomodels only
|
||||
ATTR_INDEX_LIGHT_STYLES, // brushmodels only
|
||||
ATTR_INDEX_LIGHT_COLOR, // studio & grass
|
||||
ATTR_INDEX_LIGHT_VECS, // studio & grass
|
||||
ATTR_INDEX_LIGHT_NUMS0, // brushmodels only
|
||||
ATTR_INDEX_LIGHT_NUMS1, // brushmodels only
|
||||
};
|
||||
|
||||
// shader->attribs
|
||||
#define FATTR_POSITION BIT( 0 )
|
||||
#define FATTR_TANGENT BIT( 1 )
|
||||
#define FATTR_BINORMAL BIT( 2 )
|
||||
#define FATTR_NORMAL BIT( 3 )
|
||||
#define FATTR_TEXCOORD0 BIT( 4 )
|
||||
#define FATTR_TEXCOORD1 BIT( 5 )
|
||||
#define FATTR_TEXCOORD2 BIT( 6 )
|
||||
#define FATTR_BONE_INDEXES BIT( 7 )
|
||||
#define FATTR_BONE_WEIGHTS BIT( 8 )
|
||||
#define FATTR_LIGHT_STYLES BIT( 9 )
|
||||
#define FATTR_LIGHT_COLOR BIT( 10 )
|
||||
#define FATTR_LIGHT_VECS BIT( 11 )
|
||||
#define FATTR_LIGHT_NUMS0 BIT( 12 )
|
||||
#define FATTR_LIGHT_NUMS1 BIT( 13 )
|
||||
|
||||
// uniform->flags
|
||||
#define UFL_GLOBAL_PARM BIT( 0 )
|
||||
#define UFL_TEXTURE_UNIT BIT( 1 )
|
||||
|
||||
// uniform->type
|
||||
typedef enum
|
||||
{
|
||||
UT_COLORMAP = 0,
|
||||
UT_DEPTHMAP,
|
||||
UT_NORMALMAP,
|
||||
UT_GLOSSMAP,
|
||||
UT_DETAILMAP,
|
||||
UT_PROJECTMAP, // spotlight texture
|
||||
UT_SHADOWMAP0,
|
||||
UT_SHADOWMAP1,
|
||||
UT_SHADOWMAP2,
|
||||
UT_SHADOWMAP3,
|
||||
UT_SHADOWMAP,
|
||||
UT_LIGHTMAP,
|
||||
UT_DELUXEMAP,
|
||||
UT_DECALMAP,
|
||||
UT_SCREENMAP,
|
||||
UT_VISLIGHTMAP0,
|
||||
UT_VISLIGHTMAP1,
|
||||
UT_ENVMAP0,
|
||||
UT_ENVMAP1,
|
||||
UT_ENVMAP,
|
||||
UT_GLOWMAP,
|
||||
UT_HEIGHTMAP,
|
||||
UT_LAYERMAP,
|
||||
UT_FRAGDATA0,
|
||||
UT_FRAGDATA1,
|
||||
UT_FRAGDATA2,
|
||||
UT_BSPPLANESMAP,
|
||||
UT_BSPNODESMAP,
|
||||
UT_BSPLIGHTSMAP,
|
||||
UT_BSPMODELSMAP,
|
||||
UT_FITNORMALMAP,
|
||||
UT_MODELMATRIX,
|
||||
UT_REFLECTMATRIX,
|
||||
UT_BONESARRAY,
|
||||
UT_BONEQUATERNION,
|
||||
UT_BONEPOSITION,
|
||||
UT_SCREENSIZEINV,
|
||||
UT_ZFAR,
|
||||
UT_LIGHTSTYLEVALUES,
|
||||
UT_LIGHTSTYLES,
|
||||
UT_REALTIME,
|
||||
UT_DETAILSCALE,
|
||||
UT_FOGPARAMS,
|
||||
UT_SHADOWPARMS,
|
||||
UT_TEXOFFSET,
|
||||
UT_VIEWORIGIN,
|
||||
UT_VIEWRIGHT,
|
||||
UT_RENDERCOLOR,
|
||||
UT_RENDERALPHA,
|
||||
UT_SMOOTHNESS,
|
||||
UT_SHADOWMATRIX,
|
||||
UT_SHADOWSPLITDIST,
|
||||
UT_TEXELSIZE,
|
||||
UT_GAMMATABLE,
|
||||
UT_LIGHTDIR,
|
||||
UT_LIGHTDIFFUSE,
|
||||
UT_LIGHTSHADE,
|
||||
UT_LIGHTORIGIN,
|
||||
UT_LIGHTVIEWPROJMATRIX,
|
||||
UT_DIFFUSEFACTOR,
|
||||
UT_AMBIENTFACTOR,
|
||||
UT_AMBIENTCUBE,
|
||||
UT_SUNREFRACT,
|
||||
UT_LERPFACTOR,
|
||||
UT_REFRACTSCALE,
|
||||
UT_REFLECTSCALE,
|
||||
UT_ABERRATIONSCALE,
|
||||
UT_BOXMINS,
|
||||
UT_BOXMAXS,
|
||||
UT_CUBEORIGIN,
|
||||
UT_CUBEMIPCOUNT,
|
||||
UT_LIGHTNUMS0,
|
||||
UT_LIGHTNUMS1,
|
||||
UT_GRASSPARAMS,
|
||||
UT_RELIEFPARAMS,
|
||||
UT_BLURFACTOR,
|
||||
UT_SCREENWIDTH,
|
||||
UT_SCREENHEIGHT,
|
||||
UT_FOCALDEPTH,
|
||||
UT_FOCALLENGTH,
|
||||
UT_DOFDEBUG,
|
||||
UT_FSTOP,
|
||||
UT_GRAYSCALE,
|
||||
UT_LIGHTGAMMA,
|
||||
UT_LIGHTSCALE,
|
||||
UT_LIGHTTHRESHOLD,
|
||||
UT_NUMVISIBLEMODELS,
|
||||
UT_UNDEFINED,
|
||||
} uniformType_t;
|
||||
|
||||
union unicache_t
|
||||
{
|
||||
unicache_t( int v0 ) { iValue[0] = v0; iValue[1] = iValue[2] = iValue[3] = 0; }
|
||||
unicache_t( int v0, int v1 ) { iValue[0] = v0; iValue[1] = v1; iValue[2] = iValue[3] = 0; }
|
||||
unicache_t( int v0, int v1, int v2 ) { iValue[0] = v0; iValue[1] = v1; iValue[2] = v2; iValue[3] = 0; }
|
||||
unicache_t( int v0, int v1, int v2, int v3 ) { iValue[0] = v0; iValue[1] = v1; iValue[2] = v2; iValue[3] = v3; }
|
||||
unicache_t( float v0 ) { fValue[0] = v0; fValue[1] = fValue[2] = fValue[3] = 0.0f; }
|
||||
unicache_t( float v0, float v1 ) { fValue[0] = v0; fValue[1] = v1; fValue[2] = fValue[3] = 0.0f; }
|
||||
unicache_t( float v0, float v1, float v2 ) { fValue[0] = v0; fValue[1] = v1; fValue[2] = v2; fValue[3] = 0.0f; }
|
||||
unicache_t( float v0, float v1, float v2, float v3 ) { fValue[0] = v0; fValue[1] = v1; fValue[2] = v2; fValue[3] = v3; }
|
||||
|
||||
float fValue[4];
|
||||
int iValue[4];
|
||||
};
|
||||
|
||||
class uniform_t
|
||||
{
|
||||
public:
|
||||
char name[MAX_QPATH];
|
||||
uniformType_t type;
|
||||
int size;
|
||||
uint format;
|
||||
int location;
|
||||
int unit; // texture unit
|
||||
int flags; // hints
|
||||
unicache_t cache;
|
||||
|
||||
// helpers
|
||||
void SetValue( float v0 )
|
||||
{
|
||||
unicache_t pack( v0 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( float v0, float v1 )
|
||||
{
|
||||
unicache_t pack( v0, v1 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( float v0, float v1, float v2 )
|
||||
{
|
||||
unicache_t pack( v0, v1, v2 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( float v0, float v1, float v2, float v3 )
|
||||
{
|
||||
unicache_t pack( v0, v1, v2, v3 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( int v0 )
|
||||
{
|
||||
unicache_t pack( v0 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( int v0, int v1 )
|
||||
{
|
||||
unicache_t pack( v0, v1 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( int v0, int v1, int v2 )
|
||||
{
|
||||
unicache_t pack( v0, v1, v2 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
void SetValue( int v0, int v1, int v2, GLint v3 )
|
||||
{
|
||||
unicache_t pack( v0, v1, v2, v3 );
|
||||
SetValue( &pack );
|
||||
}
|
||||
|
||||
// passed any data here
|
||||
void SetValue( const void *pdata, int count = -1 );
|
||||
int GetSizeInBytes( void );
|
||||
};
|
||||
|
||||
typedef struct glsl_prog_s
|
||||
{
|
||||
char name[64];
|
||||
char options[MAX_OPTIONS_LENGTH]; // UberShader preprocess agrs
|
||||
GLhandleARB handle;
|
||||
unsigned short status;
|
||||
struct glsl_prog_s *nextHash;
|
||||
unsigned short attribs;
|
||||
uniform_t *uniforms;
|
||||
int numUniforms;
|
||||
} glsl_program_t;
|
||||
|
||||
extern glsl_program_t glsl_programs[MAX_GLSL_PROGRAMS];
|
||||
extern int num_glsl_programs;
|
||||
|
||||
#endif//GL_SHADER_H
|
138
cl_dll/render/gl_shadowmap.cpp
Normal file
138
cl_dll/render/gl_shadowmap.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
gl_shadowmap.cpp - render shadowmaps for directional lights
|
||||
Copyright (C) 2018 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "gl_local.h"
|
||||
#include <mathlib.h>
|
||||
#include <stringlib.h>
|
||||
#include "gl_studio.h"
|
||||
#include "gl_sprite.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
#include "pm_defs.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
SHADOWMAP ALLOCATION
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
static void SM_InitBlock( void )
|
||||
{
|
||||
gl_shadowmap_t *sms = &tr.shadowmap;
|
||||
memset( sms->allocated, 0, sizeof( sms->allocated ));
|
||||
sms->shadowmap.Init( FBO_DEPTH, SHADOW_SIZE, SHADOW_SIZE );
|
||||
}
|
||||
|
||||
static int SM_AllocBlock( unsigned short w, unsigned short h, unsigned short *x, unsigned short *y )
|
||||
{
|
||||
gl_shadowmap_t *sms = &tr.shadowmap;
|
||||
unsigned short i, j, best, best2;
|
||||
|
||||
best = SHADOW_SIZE;
|
||||
|
||||
for( i = 0; i < SHADOW_SIZE - w; i++ )
|
||||
{
|
||||
best2 = 0;
|
||||
|
||||
for( j = 0; j < w; j++ )
|
||||
{
|
||||
if( sms->allocated[i+j] >= best )
|
||||
break;
|
||||
if( sms->allocated[i+j] > best2 )
|
||||
best2 = sms->allocated[i+j];
|
||||
}
|
||||
|
||||
if( j == w )
|
||||
{
|
||||
// this is a valid spot
|
||||
*x = i;
|
||||
*y = best = best2;
|
||||
}
|
||||
}
|
||||
|
||||
// atlas is full
|
||||
if( best + h > SHADOW_SIZE )
|
||||
return false;
|
||||
|
||||
for( i = 0; i < w; i++ )
|
||||
sms->allocated[*x + i] = best + h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderShadowScene
|
||||
|
||||
fast version of R_RenderScene: no colors, no texcords etc
|
||||
================
|
||||
*/
|
||||
void R_RenderShadow( mworldlight_t *wl )
|
||||
{
|
||||
if( !wl->shadow_w || !wl->shadow_h )
|
||||
{
|
||||
wl->shadow_w = 256;
|
||||
wl->shadow_h = 256;
|
||||
SM_AllocBlock( wl->shadow_w, wl->shadow_h, &wl->shadow_x, &wl->shadow_y );
|
||||
}
|
||||
}
|
||||
|
||||
void R_RenderDeferredShadows( void )
|
||||
{
|
||||
unsigned int oldFBO;
|
||||
mworldlight_t *wl;
|
||||
int i;
|
||||
|
||||
if( R_FullBright() || !CVAR_TO_BOOL( r_shadows ) || tr.fGamePaused )
|
||||
return;
|
||||
|
||||
if( FBitSet( RI->params, ( RP_NOSHADOWS|RP_ENVVIEW|RP_SKYVIEW )))
|
||||
return;
|
||||
|
||||
// check for static lights
|
||||
if( !HasStaticLights( )) return;
|
||||
|
||||
R_PushRefState(); // make refinst backup
|
||||
oldFBO = glState.frameBuffer;
|
||||
|
||||
for( i = 0, wl = world->worldlights; i < world->numworldlights; i++, wl++ )
|
||||
{
|
||||
if( wl->emittype == emit_ignored )
|
||||
continue;
|
||||
|
||||
// single visible check
|
||||
if( !CHECKVISBIT( RI->view.vislight, i ))
|
||||
continue;
|
||||
|
||||
switch( wl->emittype )
|
||||
{
|
||||
case emit_surface:
|
||||
R_RenderShadow( wl );
|
||||
break;
|
||||
}
|
||||
|
||||
R_ResetRefState(); // restore ref instance
|
||||
}
|
||||
|
||||
R_PopRefState(); // restore ref instance
|
||||
|
||||
// restore FBO state
|
||||
GL_BindFBO( oldFBO );
|
||||
GL_BindShader( NULL );
|
||||
}
|
658
cl_dll/render/gl_shadows.cpp
Normal file
658
cl_dll/render/gl_shadows.cpp
Normal file
@ -0,0 +1,658 @@
|
||||
/*
|
||||
gl_shadows.cpp - render shadowmaps for directional lights
|
||||
Copyright (C) 2012 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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "const.h"
|
||||
#include "gl_local.h"
|
||||
#include <mathlib.h>
|
||||
#include <stringlib.h>
|
||||
#include "gl_studio.h"
|
||||
#include "gl_sprite.h"
|
||||
#include "gl_world.h"
|
||||
#include "gl_grass.h"
|
||||
#include "pm_defs.h"
|
||||
|
||||
static Vector light_sides[] =
|
||||
{
|
||||
Vector( 0.0f, 0.0f, 90.0f ), // GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
|
||||
Vector( 0.0f, 180.0f, -90.0f ), // GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
|
||||
Vector( 0.0f, 90.0f, 0.0f ), // GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
|
||||
Vector( 0.0f, 270.0f, 180.0f ), // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
|
||||
Vector(-90.0f, 180.0f, -90.0f ), // GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
|
||||
Vector( 90.0f, 0.0f, 90.0f ), // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
|
||||
};
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
SHADOW RENDERING
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
int R_AllocateShadowTexture( bool copyToImage = true )
|
||||
{
|
||||
int i = tr.num_2D_shadows_used;
|
||||
|
||||
if( i >= MAX_SHADOWS )
|
||||
{
|
||||
ALERT( at_error, "R_AllocateShadowTexture: shadow textures limit exceeded!\n" );
|
||||
return 0; // disable
|
||||
}
|
||||
|
||||
int texture = tr.shadowTextures[i];
|
||||
tr.num_2D_shadows_used++;
|
||||
|
||||
if( !tr.shadowTextures[i] )
|
||||
{
|
||||
char txName[16];
|
||||
|
||||
Q_snprintf( txName, sizeof( txName ), "*shadow2D%i", i );
|
||||
|
||||
tr.shadowTextures[i] = CREATE_TEXTURE( txName, RI->view.port[2], RI->view.port[3], NULL, TF_SHADOW );
|
||||
texture = tr.shadowTextures[i];
|
||||
}
|
||||
|
||||
if( copyToImage )
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, texture );
|
||||
pglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, RI->view.port[0], RI->view.port[1], RI->view.port[2], RI->view.port[3], 0 );
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
int R_AllocateShadowCubemap( int side, bool copyToImage = true )
|
||||
{
|
||||
int texture = 0;
|
||||
|
||||
if( side != 0 )
|
||||
{
|
||||
int i = (tr.num_CM_shadows_used - 1);
|
||||
|
||||
if( i >= MAX_SHADOWS )
|
||||
{
|
||||
ALERT( at_error, "R_AllocateShadowCubemap: shadow cubemaps limit exceeded!\n" );
|
||||
return 0; // disable
|
||||
}
|
||||
|
||||
texture = tr.shadowCubemaps[i];
|
||||
|
||||
if( !tr.shadowCubemaps[i] )
|
||||
{
|
||||
ALERT( at_error, "R_AllocateShadowCubemap: cubemap not initialized!\n" );
|
||||
return 0; // disable
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = tr.num_CM_shadows_used;
|
||||
|
||||
if( i >= MAX_SHADOWS )
|
||||
{
|
||||
ALERT( at_error, "R_AllocateShadowCubemap: shadow cubemaps limit exceeded!\n" );
|
||||
return 0; // disable
|
||||
}
|
||||
|
||||
texture = tr.shadowCubemaps[i];
|
||||
tr.num_CM_shadows_used++;
|
||||
|
||||
if( !tr.shadowCubemaps[i] )
|
||||
{
|
||||
char txName[16];
|
||||
|
||||
Q_snprintf( txName, sizeof( txName ), "*shadowCM%i", i );
|
||||
|
||||
tr.shadowCubemaps[i] = CREATE_TEXTURE( txName, RI->view.port[2], RI->view.port[3], NULL, TF_SHADOW_CUBEMAP );
|
||||
texture = tr.shadowCubemaps[i];
|
||||
}
|
||||
}
|
||||
|
||||
if( copyToImage )
|
||||
{
|
||||
GL_BindTexture( GL_TEXTURE0, texture );
|
||||
pglCopyTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, 0, GL_DEPTH_COMPONENT, RI->view.port[0], RI->view.port[1], RI->view.port[2], RI->view.port[3], 0 );
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static int R_ComputeCropBounds( const matrix4x4 &lightViewProjection, Vector bounds[2] )
|
||||
{
|
||||
Vector worldBounds[2];
|
||||
int numCasters = 0;
|
||||
ref_instance_t *prevRI = R_GetPrevInstance();
|
||||
CFrustum frustum;
|
||||
|
||||
ClearBounds( bounds[0], bounds[1] );
|
||||
|
||||
frustum.InitProjectionFromMatrix( lightViewProjection );
|
||||
|
||||
// FIXME: nearplane culled studiomodels incorrectly. disabled for now
|
||||
frustum.DisablePlane( FRUSTUM_NEAR );
|
||||
frustum.DisablePlane( FRUSTUM_FAR );
|
||||
|
||||
for( int i = 0; i < prevRI->frame.solid_faces.Count(); i++ )
|
||||
{
|
||||
CSolidEntry *entry = &prevRI->frame.solid_faces[i];
|
||||
|
||||
if( entry->m_bDrawType != DRAWTYPE_SURFACE )
|
||||
continue;
|
||||
|
||||
mextrasurf_t *es = entry->m_pSurf->info;
|
||||
RI->currentmodel = es->parent->model;
|
||||
RI->currententity = es->parent;
|
||||
msurface_t *s = entry->m_pSurf;
|
||||
|
||||
bool worldpos = R_StaticEntity( RI->currententity );
|
||||
if( !worldpos ) continue; // world polys only
|
||||
|
||||
if( es->grass && CVAR_TO_BOOL( r_grass ))
|
||||
{
|
||||
// already included surface minmax
|
||||
worldBounds[0] = es->grass->mins;
|
||||
worldBounds[1] = es->grass->maxs;
|
||||
}
|
||||
else
|
||||
{
|
||||
worldBounds[0] = es->mins;
|
||||
worldBounds[1] = es->maxs;
|
||||
}
|
||||
|
||||
if( frustum.CullBox( worldBounds[0], worldBounds[1] ))
|
||||
continue;
|
||||
|
||||
for( int j = 0; j < 8; j++ )
|
||||
{
|
||||
Vector4D point;
|
||||
point.x = worldBounds[(j >> 0) & 1].x;
|
||||
point.y = worldBounds[(j >> 1) & 1].y;
|
||||
point.z = worldBounds[(j >> 2) & 1].z;
|
||||
point.w = 1.0f;
|
||||
|
||||
Vector4D transf = lightViewProjection.VectorTransform( point );
|
||||
|
||||
transf.x /= transf.w;
|
||||
transf.y /= transf.w;
|
||||
transf.z /= transf.w;
|
||||
|
||||
AddPointToBounds( transf, bounds[0], bounds[1] );
|
||||
}
|
||||
numCasters++;
|
||||
}
|
||||
|
||||
// add studio models too
|
||||
for( i = 0; i < prevRI->frame.solid_meshes.Count(); i++ )
|
||||
{
|
||||
if( !R_StudioGetBounds( &prevRI->frame.solid_meshes[i], worldBounds ))
|
||||
continue;
|
||||
|
||||
if( frustum.CullBox( worldBounds[0], worldBounds[1] ))
|
||||
continue;
|
||||
|
||||
for( int j = 0; j < 8; j++ )
|
||||
{
|
||||
Vector4D point;
|
||||
point.x = worldBounds[(j >> 0) & 1].x;
|
||||
point.y = worldBounds[(j >> 1) & 1].y;
|
||||
point.z = worldBounds[(j >> 2) & 1].z;
|
||||
point.w = 1.0f;
|
||||
|
||||
Vector4D transf = lightViewProjection.VectorTransform( point );
|
||||
transf.x /= transf.w;
|
||||
transf.y /= transf.w;
|
||||
transf.z /= transf.w;
|
||||
|
||||
AddPointToBounds( transf, bounds[0], bounds[1] );
|
||||
}
|
||||
numCasters++;
|
||||
}
|
||||
|
||||
return numCasters;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetupLightDirectional
|
||||
===============
|
||||
*/
|
||||
void R_SetupLightDirectional( CDynLight *pl, int split )
|
||||
{
|
||||
matrix4x4 projectionMatrix, cropMatrix, s1;
|
||||
Vector splitFrustumCorners[8];
|
||||
Vector splitFrustumBounds[2];
|
||||
Vector splitFrustumClipBounds[2];
|
||||
Vector casterBounds[2];
|
||||
Vector cropBounds[2];
|
||||
int i;
|
||||
|
||||
RI->view.splitFrustum[split].ComputeFrustumCorners( splitFrustumCorners );
|
||||
|
||||
ClearBounds( splitFrustumBounds[0], splitFrustumBounds[1] );
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
AddPointToBounds( splitFrustumCorners[i], splitFrustumBounds[0], splitFrustumBounds[1] );
|
||||
|
||||
// find the bounding box of the current split in the light's view space
|
||||
ClearBounds( cropBounds[0], cropBounds[1] );
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
Vector4D point( splitFrustumCorners[i] );
|
||||
Vector4D transf = pl->viewMatrix.VectorTransform( point );
|
||||
|
||||
transf.x /= transf.w;
|
||||
transf.y /= transf.w;
|
||||
transf.z /= transf.w;
|
||||
|
||||
AddPointToBounds( transf, cropBounds[0], cropBounds[1] );
|
||||
}
|
||||
|
||||
projectionMatrix.CreateOrthoRH( cropBounds[0].x, cropBounds[1].x, cropBounds[0].y, cropBounds[1].y, -cropBounds[1].z, -cropBounds[0].z );
|
||||
|
||||
matrix4x4 viewProjectionMatrix = projectionMatrix.Concat( pl->viewMatrix );
|
||||
|
||||
int numCasters = R_ComputeCropBounds( viewProjectionMatrix, casterBounds );
|
||||
|
||||
// find the bounding box of the current split in the light's clip space
|
||||
ClearBounds( splitFrustumClipBounds[0], splitFrustumClipBounds[1] );
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
Vector4D point( splitFrustumCorners[i] );
|
||||
Vector4D transf = viewProjectionMatrix.VectorTransform( point );
|
||||
|
||||
transf.x /= transf.w;
|
||||
transf.y /= transf.w;
|
||||
transf.z /= transf.w;
|
||||
|
||||
AddPointToBounds( transf, splitFrustumClipBounds[0], splitFrustumClipBounds[1] );
|
||||
}
|
||||
|
||||
// scene-dependent bounding volume
|
||||
cropBounds[0].x = Q_max( casterBounds[0].x, splitFrustumClipBounds[0].x );
|
||||
cropBounds[0].y = Q_max( casterBounds[0].y, splitFrustumClipBounds[0].y );
|
||||
cropBounds[0].z = Q_min( casterBounds[0].z, splitFrustumClipBounds[0].z );
|
||||
cropBounds[1].x = Q_min( casterBounds[1].x, splitFrustumClipBounds[1].x );
|
||||
cropBounds[1].y = Q_min( casterBounds[1].y, splitFrustumClipBounds[1].y );
|
||||
cropBounds[1].z = Q_max( casterBounds[1].z, splitFrustumClipBounds[1].z );
|
||||
|
||||
if( numCasters == 0 )
|
||||
{
|
||||
cropBounds[0] = splitFrustumClipBounds[0];
|
||||
cropBounds[1] = splitFrustumClipBounds[1];
|
||||
}
|
||||
|
||||
cropMatrix.Crop( cropBounds[0], cropBounds[1] );
|
||||
pl->projectionMatrix = cropMatrix.Concat( projectionMatrix );
|
||||
|
||||
s1.CreateTranslate( 0.5f, 0.5f, 0.5f );
|
||||
s1.ConcatScale( 0.5f, 0.5f, 0.5f );
|
||||
|
||||
viewProjectionMatrix = pl->projectionMatrix.Concat( pl->modelviewMatrix );
|
||||
|
||||
// NOTE: texture matrix is not used. Save it for pssm show split debug tool
|
||||
pl->textureMatrix[split] = pl->projectionMatrix;
|
||||
|
||||
// build shadow matrices for each split
|
||||
pl->shadowMatrix[split] = s1.Concat( viewProjectionMatrix );
|
||||
pl->shadowMatrix[split].CopyToArray( pl->gl_shadowMatrix[split] );
|
||||
|
||||
RI->view.frustum.InitProjectionFromMatrix( viewProjectionMatrix );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ShadowPassSetupViewCache
|
||||
===============
|
||||
*/
|
||||
static void R_ShadowPassSetupViewCache( CDynLight *pl, int split = 0 )
|
||||
{
|
||||
memcpy( RI->glstate.viewport, RI->view.port, sizeof( RI->glstate.viewport ));
|
||||
|
||||
RI->view.farClip = pl->radius;
|
||||
RI->view.origin = pl->origin;
|
||||
|
||||
// setup the screen FOV
|
||||
RI->view.fov_x = pl->fov;
|
||||
RI->view.fov_y = pl->fov;
|
||||
|
||||
// setup frustum
|
||||
if( pl->type == LIGHT_DIRECTIONAL )
|
||||
{
|
||||
pl->splitFrustum[split] = RI->view.splitFrustum[split];
|
||||
RI->view.matrix = pl->viewMatrix;
|
||||
R_SetupLightDirectional( pl, split );
|
||||
}
|
||||
else if( pl->type == LIGHT_OMNI )
|
||||
{
|
||||
RI->view.angles = light_sides[split]; // this is cube side of course
|
||||
RI->view.matrix = matrix4x4( RI->view.origin, RI->view.angles );
|
||||
RI->view.frustum.InitProjection( RI->view.matrix, 0.1f, pl->radius, 90.0f, 90.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
RI->view.matrix = pl->viewMatrix;
|
||||
RI->view.frustum = pl->frustum;
|
||||
}
|
||||
|
||||
if( pl->type == LIGHT_OMNI )
|
||||
{
|
||||
RI->view.worldMatrix.CreateModelview();
|
||||
RI->view.worldMatrix.ConcatRotate( -light_sides[split].z, 1, 0, 0 );
|
||||
RI->view.worldMatrix.ConcatRotate( -light_sides[split].x, 0, 1, 0 );
|
||||
RI->view.worldMatrix.ConcatRotate( -light_sides[split].y, 0, 0, 1 );
|
||||
RI->view.worldMatrix.ConcatTranslate( -pl->origin.x, -pl->origin.y, -pl->origin.z );
|
||||
RI->view.projectionMatrix = pl->projectionMatrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
// matrices already computed
|
||||
RI->view.worldMatrix = pl->modelviewMatrix;
|
||||
RI->view.projectionMatrix = pl->projectionMatrix;
|
||||
}
|
||||
|
||||
RI->view.worldProjectionMatrix = RI->view.projectionMatrix.Concat( RI->view.worldMatrix );
|
||||
RI->view.worldProjectionMatrix.CopyToArray( RI->glstate.modelviewProjectionMatrix );
|
||||
RI->view.projectionMatrix.CopyToArray( RI->glstate.projectionMatrix );
|
||||
RI->view.worldMatrix.CopyToArray( RI->glstate.modelviewMatrix );
|
||||
|
||||
RI->currentlight = pl;
|
||||
|
||||
R_MarkWorldVisibleFaces( worldmodel );
|
||||
|
||||
msurface_t *surf;
|
||||
mextrasurf_t *esrf;
|
||||
int i, j;
|
||||
|
||||
// add all studio models, mark visible bmodels
|
||||
for( i = 0; i < tr.num_draw_entities; i++ )
|
||||
{
|
||||
RI->currententity = tr.draw_entities[i];
|
||||
RI->currentmodel = RI->currententity->model;
|
||||
|
||||
switch( RI->currentmodel->type )
|
||||
{
|
||||
case mod_studio:
|
||||
R_AddStudioToDrawList( RI->currententity );
|
||||
break;
|
||||
case mod_brush:
|
||||
R_MarkSubmodelVisibleFaces();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// create drawlist for faces, do additional culling for world faces
|
||||
for( i = 0; i < world->numsortedfaces; i++ )
|
||||
{
|
||||
ASSERT( world->sortedfaces != NULL );
|
||||
|
||||
j = world->sortedfaces[i];
|
||||
|
||||
ASSERT( j >= 0 && j < worldmodel->numsurfaces );
|
||||
|
||||
if( CHECKVISBIT( RI->view.visfaces, j ))
|
||||
{
|
||||
surf = worldmodel->surfaces + j;
|
||||
esrf = surf->info;
|
||||
|
||||
// submodel faces already passed through this
|
||||
// operation but world is not
|
||||
if( FBitSet( surf->flags, SURF_OF_SUBMODEL ))
|
||||
{
|
||||
RI->currententity = esrf->parent;
|
||||
RI->currentmodel = RI->currententity->model;
|
||||
|
||||
R_AddGrassToDrawList( surf, DRAWLIST_SHADOW );
|
||||
}
|
||||
else
|
||||
{
|
||||
RI->currententity = GET_ENTITY( 0 );
|
||||
RI->currentmodel = RI->currententity->model;
|
||||
|
||||
esrf->parent = RI->currententity; // setup dynamic upcast
|
||||
|
||||
R_AddGrassToDrawList( surf, DRAWLIST_SHADOW );
|
||||
|
||||
if( R_CullSurface( surf, GetVieworg(), &RI->view.frustum ))
|
||||
{
|
||||
CLEARVISBIT( RI->view.visfaces, j ); // not visible
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// only opaque faces interesting us
|
||||
if( R_OpaqueEntity( RI->currententity ))
|
||||
{
|
||||
R_AddSurfaceToDrawList( surf, DRAWLIST_SHADOW );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_ShadowPassSetupGL
|
||||
=============
|
||||
*/
|
||||
static void R_ShadowPassSetupGL( const CDynLight *pl )
|
||||
{
|
||||
R_SetupGLstate();
|
||||
|
||||
pglEnable( GL_POLYGON_OFFSET_FILL );
|
||||
|
||||
if( RI->currentlight->type == LIGHT_DIRECTIONAL )
|
||||
{
|
||||
if( r_shadows->value > 2.0f )
|
||||
pglPolygonOffset( 3.0f, 0.0f );
|
||||
else pglPolygonOffset( 2.0f, 0.0f );
|
||||
GL_Cull( GL_NONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( r_shadows->value > 2.0f )
|
||||
pglPolygonOffset( 2.0f, 0.0f );
|
||||
else pglPolygonOffset( 1.0f, 0.0f );
|
||||
GL_Cull( GL_FRONT );
|
||||
}
|
||||
|
||||
// HACKHACK to ignore paranoia opengl32.dll
|
||||
GL_DepthRange( 0.0001f, 1.0f );
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
GL_AlphaTest( GL_FALSE );
|
||||
GL_DepthMask( GL_TRUE );
|
||||
GL_Blend( GL_FALSE );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_ShadowPassEndGL
|
||||
=============
|
||||
*/
|
||||
static void R_ShadowPassEndGL( void )
|
||||
{
|
||||
pglDisable( GL_POLYGON_OFFSET_FILL );
|
||||
GL_DepthRange( gldepthmin, gldepthmax );
|
||||
pglPolygonOffset( -1, -2 );
|
||||
r_stats.c_shadow_passes++;
|
||||
GL_Cull( GL_FRONT );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderShadowScene
|
||||
|
||||
fast version of R_RenderScene: no colors, no texcords etc
|
||||
================
|
||||
*/
|
||||
void R_RenderShadowScene( CDynLight *pl, int split = 0 )
|
||||
{
|
||||
RI->params = RP_SHADOWVIEW;
|
||||
bool using_fbo = false;
|
||||
|
||||
if( pl->type == LIGHT_DIRECTIONAL )
|
||||
{
|
||||
if( tr.sunShadowFBO[split].Active( ))
|
||||
{
|
||||
RI->view.port[2] = RI->view.port[3] = sunSize[split];
|
||||
|
||||
pl->shadowTexture[split] = tr.sunShadowFBO[split].GetTexture();
|
||||
tr.sunShadowFBO[split].Bind();
|
||||
using_fbo = true;
|
||||
}
|
||||
else RI->view.port[2] = RI->view.port[3] = 512; // simple size if FBO was missed
|
||||
}
|
||||
else
|
||||
{
|
||||
if( tr.fbo_shadow2D.Active( ))
|
||||
{
|
||||
RI->view.port[2] = tr.fbo_shadow2D.GetWidth();
|
||||
RI->view.port[3] = tr.fbo_shadow2D.GetHeight();
|
||||
|
||||
pl->shadowTexture[0] = R_AllocateShadowTexture( false );
|
||||
tr.fbo_shadow2D.Bind( pl->shadowTexture[0] );
|
||||
using_fbo = true;
|
||||
}
|
||||
else RI->view.port[2] = RI->view.port[3] = 512;
|
||||
}
|
||||
|
||||
R_ShadowPassSetupViewCache( pl, split );
|
||||
R_ShadowPassSetupGL( pl );
|
||||
|
||||
pglClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
R_RenderShadowBrushList();
|
||||
R_RenderShadowStudioList();
|
||||
R_DrawParticles( false );
|
||||
R_ShadowPassEndGL();
|
||||
|
||||
if( !using_fbo )
|
||||
pl->shadowTexture[split] = R_AllocateShadowTexture();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderShadowCubeSide
|
||||
|
||||
fast version of R_RenderScene: no colors, no texcords etc
|
||||
================
|
||||
*/
|
||||
void R_RenderShadowCubeSide( CDynLight *pl, int side )
|
||||
{
|
||||
RI->params = RP_SHADOWVIEW;
|
||||
bool using_fbo = false;
|
||||
|
||||
if( tr.fbo_shadowCM.Active( ))
|
||||
{
|
||||
RI->view.port[2] = tr.fbo_shadowCM.GetWidth();
|
||||
RI->view.port[3] = tr.fbo_shadowCM.GetHeight();
|
||||
|
||||
pl->shadowTexture[0] = R_AllocateShadowCubemap( side, false );
|
||||
tr.fbo_shadowCM.Bind( pl->shadowTexture[0], side );
|
||||
using_fbo = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// same size if FBO was missed
|
||||
RI->view.port[2] = RI->view.port[3] = 512;
|
||||
using_fbo = false;
|
||||
}
|
||||
|
||||
R_ShadowPassSetupViewCache( pl, side );
|
||||
R_ShadowPassSetupGL( pl );
|
||||
|
||||
pglClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
R_RenderShadowBrushList();
|
||||
R_RenderShadowStudioList();
|
||||
R_DrawParticles( false );
|
||||
R_ShadowPassEndGL();
|
||||
|
||||
if( !using_fbo )
|
||||
pl->shadowTexture[0] = R_AllocateShadowCubemap( side );
|
||||
}
|
||||
|
||||
void R_RenderShadowmaps( void )
|
||||
{
|
||||
unsigned int oldFBO;
|
||||
|
||||
if( R_FullBright() || !CVAR_TO_BOOL( r_shadows ) || tr.fGamePaused )
|
||||
return;
|
||||
|
||||
if( FBitSet( RI->params, ( RP_NOSHADOWS|RP_ENVVIEW|RP_SKYVIEW )))
|
||||
return;
|
||||
|
||||
// check for dynamic lights
|
||||
if( !HasDynamicLights( )) return;
|
||||
|
||||
R_PushRefState(); // make refinst backup
|
||||
oldFBO = glState.frameBuffer;
|
||||
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
CDynLight *pl = &tr.dlights[i];
|
||||
|
||||
if( !pl->Active() || FBitSet( pl->flags, DLF_NOSHADOWS ))
|
||||
continue;
|
||||
|
||||
if( pl->type == LIGHT_OMNI )
|
||||
{
|
||||
// need GL_EXT_gpu_shader4 for cubemap shadows
|
||||
if( !GL_Support( R_TEXTURECUBEMAP_EXT ) || !GL_Support( R_EXT_GPU_SHADER4 ))
|
||||
continue;
|
||||
|
||||
if( !Mod_CheckBoxVisible( pl->absmin, pl->absmax ))
|
||||
continue;
|
||||
|
||||
if( R_CullBox( pl->absmin, pl->absmax ))
|
||||
continue;
|
||||
|
||||
for( int j = 0; j < 6; j++ )
|
||||
{
|
||||
R_RenderShadowCubeSide( pl, j );
|
||||
R_ResetRefState(); // restore ref instance
|
||||
}
|
||||
}
|
||||
else if( pl->type == LIGHT_SPOT )
|
||||
{
|
||||
if( !Mod_CheckBoxVisible( pl->absmin, pl->absmax ))
|
||||
continue;
|
||||
|
||||
if( R_CullBox( pl->absmin, pl->absmax ))
|
||||
continue;
|
||||
|
||||
R_RenderShadowScene( pl );
|
||||
R_ResetRefState(); // restore ref instance
|
||||
}
|
||||
else if( pl->type == LIGHT_DIRECTIONAL )
|
||||
{
|
||||
if( !CVAR_TO_BOOL( r_sunshadows ) || tr.sky_normal.z >= 0.0f )
|
||||
continue; // shadows are invisible
|
||||
|
||||
for( int j = 0; j <= NUM_SHADOW_SPLITS; j++ )
|
||||
{
|
||||
// PSSM: draw all the splits
|
||||
R_RenderShadowScene( pl, j );
|
||||
R_ResetRefState(); // restore ref instance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R_PopRefState(); // restore ref instance
|
||||
// restore FBO state
|
||||
GL_BindFBO( oldFBO );
|
||||
GL_BindShader( NULL );
|
||||
RI->currentlight = NULL;
|
||||
}
|
1272
cl_dll/render/gl_shadows.new
Normal file
1272
cl_dll/render/gl_shadows.new
Normal file
File diff suppressed because it is too large
Load Diff
373
cl_dll/render/gl_sky.cpp
Normal file
373
cl_dll/render/gl_sky.cpp
Normal file
@ -0,0 +1,373 @@
|
||||
//
|
||||
// written by BUzer for HL: Paranoia modification
|
||||
//
|
||||
// 2006
|
||||
|
||||
#include "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_shader.h"
|
||||
|
||||
#define MAX_CLIP_VERTS 128 // skybox clip vertices
|
||||
|
||||
static const int r_skyTexOrder[6] = { 0, 2, 1, 3, 4, 5 };
|
||||
|
||||
static const Vector skyclip[6] =
|
||||
{
|
||||
Vector( 1, 1, 0 ),
|
||||
Vector( 1, -1, 0 ),
|
||||
Vector( 0, -1, 1 ),
|
||||
Vector( 0, 1, 1 ),
|
||||
Vector( 1, 0, 1 ),
|
||||
Vector( -1, 0, 1 )
|
||||
};
|
||||
|
||||
// 1 = s, 2 = t, 3 = 2048
|
||||
static const int st_to_vec[6][3] =
|
||||
{
|
||||
{ 3, -1, 2 },
|
||||
{ -3, 1, 2 },
|
||||
{ 1, 3, 2 },
|
||||
{ -1, -3, 2 },
|
||||
{ -2, -1, 3 }, // 0 degrees yaw, look straight up
|
||||
{ 2, -1, -3 } // look straight down
|
||||
};
|
||||
|
||||
// s = [0]/[2], t = [1]/[2]
|
||||
static const int vec_to_st[6][3] =
|
||||
{
|
||||
{ -2, 3, 1 },
|
||||
{ 2, 3, -1 },
|
||||
{ 1, 3, 2 },
|
||||
{ -1, 3, -2 },
|
||||
{ -2, -1, 3 },
|
||||
{ -2, 1, -3 }
|
||||
};
|
||||
|
||||
static void DrawSkyPolygon( int nump, Vector vecs[] )
|
||||
{
|
||||
int i, j, axis;
|
||||
float s, t, dv;
|
||||
Vector v, av;
|
||||
|
||||
// decide which face it maps to
|
||||
v = g_vecZero;
|
||||
|
||||
for( i = 0; i < nump; i++ )
|
||||
v += vecs[i];
|
||||
|
||||
av[0] = fabs( v[0] );
|
||||
av[1] = fabs( v[1] );
|
||||
av[2] = fabs( v[2] );
|
||||
|
||||
if( av[0] > av[1] && av[0] > av[2] )
|
||||
axis = (v[0] < 0) ? 1 : 0;
|
||||
else if( av[1] > av[2] && av[1] > av[0] )
|
||||
axis = (v[1] < 0) ? 3 : 2;
|
||||
else axis = (v[2] < 0) ? 5 : 4;
|
||||
|
||||
// project new texture coords
|
||||
for( i = 0; i < nump; i++ )
|
||||
{
|
||||
j = vec_to_st[axis][2];
|
||||
dv = (j > 0) ? (vecs[i])[j-1] : -(vecs[i])[-j-1];
|
||||
|
||||
j = vec_to_st[axis][0];
|
||||
s = (j < 0) ? -vecs[i][-j-1] / dv : (vecs[i])[j-1] / dv;
|
||||
|
||||
j = vec_to_st[axis][1];
|
||||
t = (j < 0) ? -(vecs[i])[-j-1] / dv : (vecs[i])[j-1] / dv;
|
||||
|
||||
if( s < RI->view.skyMins[0][axis] ) RI->view.skyMins[0][axis] = s;
|
||||
if( t < RI->view.skyMins[1][axis] ) RI->view.skyMins[1][axis] = t;
|
||||
if( s > RI->view.skyMaxs[0][axis] ) RI->view.skyMaxs[0][axis] = s;
|
||||
if( t > RI->view.skyMaxs[1][axis] ) RI->view.skyMaxs[1][axis] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ClipSkyPolygon
|
||||
==============
|
||||
*/
|
||||
static void ClipSkyPolygon( int nump, Vector vecs[], int stage )
|
||||
{
|
||||
bool front, back;
|
||||
float dists[MAX_CLIP_VERTS + 1];
|
||||
int sides[MAX_CLIP_VERTS + 1];
|
||||
Vector newv[2][MAX_CLIP_VERTS + 1];
|
||||
int newc[2];
|
||||
float d, e;
|
||||
int i;
|
||||
|
||||
if( nump > MAX_CLIP_VERTS )
|
||||
HOST_ERROR( "ClipSkyPolygon: MAX_CLIP_VERTS\n" );
|
||||
loc1:
|
||||
if( stage == 6 )
|
||||
{
|
||||
// fully clipped, so draw it
|
||||
DrawSkyPolygon( nump, vecs );
|
||||
return;
|
||||
}
|
||||
|
||||
front = back = false;
|
||||
const Vector &norm = skyclip[stage];
|
||||
|
||||
for( i = 0; i < nump; i++ )
|
||||
{
|
||||
d = DotProduct( vecs[i], norm );
|
||||
if( d > ON_EPSILON )
|
||||
{
|
||||
front = true;
|
||||
sides[i] = SIDE_FRONT;
|
||||
}
|
||||
else if( d < -ON_EPSILON )
|
||||
{
|
||||
back = true;
|
||||
sides[i] = SIDE_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
sides[i] = SIDE_ON;
|
||||
}
|
||||
dists[i] = d;
|
||||
}
|
||||
|
||||
if( !front || !back )
|
||||
{
|
||||
// not clipped
|
||||
stage++;
|
||||
goto loc1;
|
||||
}
|
||||
|
||||
// clip it
|
||||
sides[i] = sides[0];
|
||||
dists[i] = dists[0];
|
||||
vecs[i] = vecs[0];
|
||||
newc[0] = newc[1] = 0;
|
||||
|
||||
for( i = 0; i < nump; i++ )
|
||||
{
|
||||
switch( sides[i] )
|
||||
{
|
||||
case SIDE_FRONT:
|
||||
newv[0][newc[0]] = vecs[i];
|
||||
newc[0]++;
|
||||
break;
|
||||
case SIDE_BACK:
|
||||
newv[1][newc[1]] = vecs[i];
|
||||
newc[1]++;
|
||||
break;
|
||||
case SIDE_ON:
|
||||
newv[0][newc[0]] = vecs[i];
|
||||
newc[0]++;
|
||||
newv[1][newc[1]] = vecs[i];
|
||||
newc[1]++;
|
||||
break;
|
||||
}
|
||||
|
||||
if( sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i] )
|
||||
continue;
|
||||
|
||||
d = dists[i] / ( dists[i] - dists[i+1] );
|
||||
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
e = (vecs[i])[j] + d * ( (vecs[i+1])[j] - (vecs[i])[j] );
|
||||
newv[0][newc[0]][j] = e;
|
||||
newv[1][newc[1]][j] = e;
|
||||
}
|
||||
newc[0]++;
|
||||
newc[1]++;
|
||||
}
|
||||
|
||||
// continue
|
||||
ClipSkyPolygon( newc[0], newv[0], stage + 1 );
|
||||
ClipSkyPolygon( newc[1], newv[1], stage + 1 );
|
||||
}
|
||||
|
||||
static void MakeSkyVec( float s, float t, int axis )
|
||||
{
|
||||
int j, k, farclip;
|
||||
Vector v, b;
|
||||
|
||||
farclip = RI->view.farClip;
|
||||
|
||||
b[0] = s * (farclip >> 1);
|
||||
b[1] = t * (farclip >> 1);
|
||||
b[2] = (farclip >> 1);
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
k = st_to_vec[axis][j];
|
||||
v[j] = (k < 0) ? -b[-k-1] : b[k-1];
|
||||
v[j] += GetVieworg()[j];
|
||||
}
|
||||
|
||||
// avoid bilerp seam
|
||||
s = (s + 1.0f) * 0.5f;
|
||||
t = (t + 1.0f) * 0.5f;
|
||||
|
||||
if( s < ( 1.0f / 512.0f ))
|
||||
s = (1.0f / 512.0f);
|
||||
else if( s > ( 511.0f / 512.0f ))
|
||||
s = (511.0f / 512.0f);
|
||||
if( t < ( 1.0f / 512.0f ))
|
||||
t = (1.0f / 512.0f);
|
||||
else if( t > ( 511.0f / 512.0f ))
|
||||
t = (511.0f / 512.0f);
|
||||
|
||||
t = 1.0f - t;
|
||||
|
||||
pglTexCoord2f( s, t );
|
||||
pglVertex3fv( v );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AddSkyBoxSurface
|
||||
=================
|
||||
*/
|
||||
void R_AddSkyBoxSurface( msurface_t *fa )
|
||||
{
|
||||
Vector verts[MAX_CLIP_VERTS];
|
||||
|
||||
// calculate vertex values for sky box
|
||||
for( glpoly_t *p = fa->polys; p; p = p->next )
|
||||
{
|
||||
if( p->numverts >= MAX_CLIP_VERTS )
|
||||
HOST_ERROR( "R_AddSkyBoxSurface: numverts >= MAX_CLIP_VERTS\n" );
|
||||
|
||||
for( int i = 0; i < p->numverts; i++ )
|
||||
{
|
||||
verts[i][0] = p->verts[i][0] - GetVieworg().x;
|
||||
verts[i][1] = p->verts[i][1] - GetVieworg().y;
|
||||
verts[i][2] = p->verts[i][2] - GetVieworg().z;
|
||||
}
|
||||
|
||||
ClipSkyPolygon( p->numverts, verts, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static void GL_DrawSkySide( int skyside )
|
||||
{
|
||||
pglBegin( GL_QUADS );
|
||||
MakeSkyVec( RI->view.skyMins[0][skyside], RI->view.skyMins[1][skyside], skyside );
|
||||
MakeSkyVec( RI->view.skyMins[0][skyside], RI->view.skyMaxs[1][skyside], skyside );
|
||||
MakeSkyVec( RI->view.skyMaxs[0][skyside], RI->view.skyMaxs[1][skyside], skyside );
|
||||
MakeSkyVec( RI->view.skyMaxs[0][skyside], RI->view.skyMins[1][skyside], skyside );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
static void GL_DrawSkySide( word hProgram, int skyside )
|
||||
{
|
||||
if( hProgram <= 0 )
|
||||
{
|
||||
GL_BindShader( NULL );
|
||||
GL_BindTexture( GL_TEXTURE0, tr.skyboxTextures[r_skyTexOrder[skyside]] );
|
||||
GL_DrawSkySide( skyside );
|
||||
return; // old method
|
||||
}
|
||||
|
||||
if( RI->currentshader != &glsl_programs[hProgram] )
|
||||
{
|
||||
// force to bind new shader
|
||||
GL_BindShader( &glsl_programs[hProgram] );
|
||||
}
|
||||
|
||||
Vector sky_color = (tr.sun_light_enabled) ? tr.sun_diffuse : tr.sky_ambient * (1.0f/128.0f) * tr.diffuseFactor;
|
||||
Vector sky_vec = tr.sky_normal.Normalize();
|
||||
glsl_program_t *shader = RI->currentshader;
|
||||
|
||||
ColorNormalize( sky_color, sky_color );
|
||||
|
||||
// setup specified uniforms (and texture bindings)
|
||||
for( int i = 0; i < shader->numUniforms; i++ )
|
||||
{
|
||||
uniform_t *u = &shader->uniforms[i];
|
||||
|
||||
switch( u->type )
|
||||
{
|
||||
case UT_COLORMAP:
|
||||
u->SetValue( tr.skyboxTextures[r_skyTexOrder[skyside]] );
|
||||
break;
|
||||
case UT_LIGHTDIR:
|
||||
u->SetValue( sky_vec.x, sky_vec.y, sky_vec.z );
|
||||
break;
|
||||
case UT_LIGHTDIFFUSE:
|
||||
u->SetValue( sky_color.x, sky_color.y, sky_color.z );
|
||||
break;
|
||||
case UT_VIEWORIGIN:
|
||||
u->SetValue( GetVieworg().x, GetVieworg().y, GetVieworg().z );
|
||||
break;
|
||||
case UT_FOGPARAMS:
|
||||
u->SetValue( tr.fogColor[0], tr.fogColor[1], tr.fogColor[2], tr.fogDensity * 0.5f );
|
||||
break;
|
||||
case UT_ZFAR:
|
||||
u->SetValue( RI->view.farClip );
|
||||
break;
|
||||
default:
|
||||
ALERT( at_error, "%s: unhandled uniform %s\n", RI->currentshader->name, u->name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GL_DrawSkySide( skyside );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_DrawSkybox
|
||||
==============
|
||||
*/
|
||||
void R_DrawSkyBox( void )
|
||||
{
|
||||
bool drawSun = true;
|
||||
float fogDenstity = tr.fogDensity;
|
||||
word hSkyShader = 0;
|
||||
int i;
|
||||
|
||||
if( !FBitSet( RI->view.flags, RF_SKYVISIBLE ))
|
||||
return;
|
||||
|
||||
GL_DepthRange( 0.9f, 1.0f );
|
||||
GL_DepthMask( GL_FALSE );
|
||||
GL_Blend( GL_FALSE );
|
||||
GL_AlphaTest( GL_FALSE );
|
||||
|
||||
// clipplane cut the sky if drawing through mirror. Disable it
|
||||
GL_ClipPlane( false );
|
||||
|
||||
int type = tr.sun_light_enabled ? 1 : 0;
|
||||
|
||||
if( FBitSet( RI->params, RP_SKYVIEW ) || ( FBitSet( RI->params, RP_WATERPASS ) && CVAR_TO_BOOL( cv_specular )))
|
||||
drawSun = false;
|
||||
|
||||
// disable sky fogging while underwater
|
||||
if( tr.waterlevel >= 3 || FBitSet( RI->params, RP_SKYVIEW ))
|
||||
fogDenstity = 0.0f;
|
||||
|
||||
// make sure what light_environment is present
|
||||
if( tr.sky_normal != g_vecZero && drawSun )
|
||||
{
|
||||
if( FBitSet( RI->params, RP_DEFERREDSCENE ))
|
||||
hSkyShader = tr.defSceneSky;
|
||||
else if( FBitSet( RI->params, RP_DEFERREDLIGHT ))
|
||||
hSkyShader = tr.defLightSky;
|
||||
else hSkyShader = tr.skyboxEnv[type];
|
||||
}
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( RI->view.skyMins[0][i] >= RI->view.skyMaxs[0][i] || RI->view.skyMins[1][i] >= RI->view.skyMaxs[1][i] )
|
||||
continue;
|
||||
|
||||
GL_DrawSkySide( hSkyShader, i );
|
||||
}
|
||||
|
||||
GL_ClipPlane( true );
|
||||
GL_DepthMask( GL_TRUE );
|
||||
|
||||
// back to normal depth range
|
||||
GL_DepthRange( gldepthmin, gldepthmax );
|
||||
}
|
733
cl_dll/render/gl_slight.cpp
Normal file
733
cl_dll/render/gl_slight.cpp
Normal file
@ -0,0 +1,733 @@
|
||||
/*
|
||||
gl_slight.cpp - static lighting
|
||||
Copyright (C) 2019 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 "hud.h"
|
||||
#include <stringlib.h>
|
||||
#include "cl_util.h"
|
||||
#include "pm_defs.h"
|
||||
#include "event_api.h"
|
||||
#include "gl_local.h"
|
||||
#include "gl_studio.h"
|
||||
#include "gl_world.h"
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
#define AMBIENT_CUBE_SCALE 1.0f
|
||||
|
||||
// lightpoint flags
|
||||
#define LIGHTINFO_HITSKY (1<<0)
|
||||
#define LIGHTINFO_AVERAGE (1<<1) // compute average color from lightmap
|
||||
#define LIGHTINFO_STYLES (1<<2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t diffuse;
|
||||
vec3_t average;
|
||||
colorVec lightmap;
|
||||
vec3_t normal;
|
||||
msurface_t *surf; // may be NULL
|
||||
float fraction; // hit fraction
|
||||
vec3_t origin;
|
||||
int status;
|
||||
} lightpoint_t;
|
||||
|
||||
static vec_t g_anorms[NUMVERTEXNORMALS][3] =
|
||||
{
|
||||
#include "anorms.h"
|
||||
};
|
||||
|
||||
static Vector g_BoxDirections[6] =
|
||||
{
|
||||
Vector( 1.0f, 0.0f, 0.0f ),
|
||||
Vector(-1.0f, 0.0f, 0.0f ),
|
||||
Vector( 0.0f, 1.0f, 0.0f ),
|
||||
Vector( 0.0f, -1.0f, 0.0f ),
|
||||
Vector( 0.0f, 0.0f, 1.0f ),
|
||||
Vector( 0.0f, 0.0f, -1.0f ),
|
||||
};
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
AMBIENT & DIFFUSE LIGHTING
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
R_FindAmbientSkyLight
|
||||
=================
|
||||
*/
|
||||
static mworldlight_t *R_FindAmbientSkyLight( void )
|
||||
{
|
||||
// find any ambient lights
|
||||
for( int i = 0; i < world->numworldlights; i++ )
|
||||
{
|
||||
if( world->worldlights[i].emittype == emit_skylight )
|
||||
return &world->worldlights[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightTraceFilter
|
||||
=================
|
||||
*/
|
||||
static int R_LightTraceFilter( physent_t *pe )
|
||||
{
|
||||
if( !pe || !pe->model )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_GetDirectLightFromSurface
|
||||
=================
|
||||
*/
|
||||
static bool R_GetDirectLightFromSurface( msurface_t *surf, const Vector &point, lightpoint_t *info )
|
||||
{
|
||||
mextrasurf_t *es = surf->info;
|
||||
float ds, dt, s, t;
|
||||
color24 *lm, *dm;
|
||||
mtexinfo_t *tex;
|
||||
int map, size;
|
||||
|
||||
tex = surf->texinfo;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWSKY ))
|
||||
{
|
||||
info->status |= LIGHTINFO_HITSKY;
|
||||
return false; // no lightmaps
|
||||
}
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||
return false; // no lightmaps
|
||||
|
||||
s = DotProduct( point, es->lmvecs[0] ) + es->lmvecs[0][3];
|
||||
t = DotProduct( point, es->lmvecs[1] ) + es->lmvecs[1][3];
|
||||
|
||||
if( s < es->lightmapmins[0] || t < es->lightmapmins[1] )
|
||||
return false;
|
||||
|
||||
ds = s - es->lightmapmins[0];
|
||||
dt = t - es->lightmapmins[1];
|
||||
|
||||
if( ds > es->lightextents[0] || dt > es->lightextents[1] )
|
||||
return false;
|
||||
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
int sample_size = Mod_SampleSizeForFace( surf );
|
||||
int smax = (es->lightextents[0] / sample_size) + 1;
|
||||
int tmax = (es->lightextents[1] / sample_size) + 1;
|
||||
ds /= sample_size;
|
||||
dt /= sample_size;
|
||||
|
||||
lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
colorVec localDiffuse = { 0, 0, 0, 0 };
|
||||
size = smax * tmax;
|
||||
|
||||
if( es->normals )
|
||||
{
|
||||
Vector vec_x, vec_y, vec_z;
|
||||
matrix3x3 mat;
|
||||
|
||||
dm = es->normals + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
|
||||
// flat TBN for better results
|
||||
vec_x = Vector( surf->info->lmvecs[0] );
|
||||
vec_y = Vector( surf->info->lmvecs[1] );
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
vec_z = -surf->plane->normal;
|
||||
else vec_z = surf->plane->normal;
|
||||
|
||||
// create tangent space rotational matrix
|
||||
mat.SetForward( vec_x.Normalize( ));
|
||||
mat.SetRight( -vec_y.Normalize( ));
|
||||
mat.SetUp( vec_z.Normalize( ));
|
||||
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
{
|
||||
float f = (1.0f / 128.0f);
|
||||
Vector normal = Vector(((float)dm->r - 128.0f) * f, ((float)dm->g - 128.0f) * f, ((float)dm->b - 128.0f) * f);
|
||||
uint scale = tr.lightstyle[surf->styles[map]]; // style modifier
|
||||
mworldlight_t *pSkyLight = NULL;
|
||||
Vector localDir = g_vecZero;
|
||||
Vector sky_color = g_vecZero;
|
||||
|
||||
// rotate from tangent to model space
|
||||
localDir = mat.VectorRotate( normal );
|
||||
|
||||
// add local dir into main
|
||||
info->normal += localDir * (float)scale; // direction factor
|
||||
|
||||
// compute diffuse color
|
||||
localDiffuse.r += TEXTURE_TO_TEXGAMMA( lm->r ) * scale;
|
||||
localDiffuse.g += TEXTURE_TO_TEXGAMMA( lm->g ) * scale;
|
||||
localDiffuse.b += TEXTURE_TO_TEXGAMMA( lm->b ) * scale;
|
||||
|
||||
lm += size; // skip to next lightmap
|
||||
dm += size; // skip to next deluxemap
|
||||
}
|
||||
|
||||
info->lightmap.r = Q_min(( localDiffuse.r >> 7 ), 255 );
|
||||
info->lightmap.g = Q_min(( localDiffuse.g >> 7 ), 255 );
|
||||
info->lightmap.b = Q_min(( localDiffuse.b >> 7 ), 255 );
|
||||
info->diffuse.x = (float)info->lightmap.r * (1.0f / 255.0f);
|
||||
info->diffuse.y = (float)info->lightmap.g * (1.0f / 255.0f);
|
||||
info->diffuse.z = (float)info->lightmap.b * (1.0f / 255.0f);
|
||||
if( info->normal == g_vecZero ) info->normal = vec_z; // fixup some cases
|
||||
info->normal = info->normal.Normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
{
|
||||
uint scale = tr.lightstyle[surf->styles[map]];
|
||||
|
||||
// compute diffuse color
|
||||
localDiffuse.r += TEXTURE_TO_TEXGAMMA( lm->r ) * scale;
|
||||
localDiffuse.g += TEXTURE_TO_TEXGAMMA( lm->g ) * scale;
|
||||
localDiffuse.b += TEXTURE_TO_TEXGAMMA( lm->b ) * scale;
|
||||
lm += size; // skip to next lightmap
|
||||
}
|
||||
|
||||
info->lightmap.r = Q_min(( localDiffuse.r >> 7 ), 255 );
|
||||
info->lightmap.g = Q_min(( localDiffuse.g >> 7 ), 255 );
|
||||
info->lightmap.b = Q_min(( localDiffuse.b >> 7 ), 255 );
|
||||
info->diffuse.x = (float)info->lightmap.r * (1.0f / 255.0f);
|
||||
info->diffuse.y = (float)info->lightmap.g * (1.0f / 255.0f);
|
||||
info->diffuse.z = (float)info->lightmap.b * (1.0f / 255.0f);
|
||||
}
|
||||
|
||||
if(( surf->styles[0] != 0 && surf->styles[0] != LS_SKY ) || surf->styles[1] != 255 )
|
||||
SetBits( info->status, LIGHTINFO_STYLES );
|
||||
|
||||
// also collect the average value
|
||||
if( FBitSet( info->status, LIGHTINFO_AVERAGE ))
|
||||
{
|
||||
Vector localAverage = g_vecZero;
|
||||
lm = surf->samples;
|
||||
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
{
|
||||
float scale = tr.lightstyle[surf->styles[map]];
|
||||
|
||||
for( int i = 0; i < size; i++, lm++ )
|
||||
{
|
||||
localAverage.x += (float)TEXTURE_TO_TEXGAMMA( lm->r ) * scale;
|
||||
localAverage.y += (float)TEXTURE_TO_TEXGAMMA( lm->g ) * scale;
|
||||
localAverage.z += (float)TEXTURE_TO_TEXGAMMA( lm->b ) * scale;
|
||||
}
|
||||
|
||||
localAverage *= (1.0f / (float)size );
|
||||
}
|
||||
|
||||
info->average.x = Q_min( localAverage.x * (1.0f / 128.0f), 255.0f ) * (1.0f / 255.0f);
|
||||
info->average.y = Q_min( localAverage.y * (1.0f / 128.0f), 255.0f ) * (1.0f / 255.0f);
|
||||
info->average.z = Q_min( localAverage.z * (1.0f / 128.0f), 255.0f ) * (1.0f / 255.0f);
|
||||
}
|
||||
|
||||
info->surf = surf;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveLightPoint
|
||||
=================
|
||||
*/
|
||||
static bool R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, const Vector &start, const Vector &end, lightpoint_t *info )
|
||||
{
|
||||
float front, back;
|
||||
float frac, midf;
|
||||
int side;
|
||||
msurface_t *surf;
|
||||
Vector mid;
|
||||
|
||||
// didn't hit anything
|
||||
if( !node || node->contents < 0 )
|
||||
return false;
|
||||
|
||||
// calculate mid point
|
||||
front = PlaneDiff( start, node->plane );
|
||||
back = PlaneDiff( end, node->plane );
|
||||
|
||||
side = front < 0.0f;
|
||||
if(( back < 0.0f ) == side )
|
||||
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, start, end, info );
|
||||
|
||||
frac = front / ( front - back );
|
||||
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
VectorLerp( start, frac, end, mid );
|
||||
|
||||
// co down front side
|
||||
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, start, mid, info ))
|
||||
return true; // hit something
|
||||
|
||||
if(( back < 0.0f ) == side )
|
||||
return false;// didn't hit anything
|
||||
|
||||
// check for impact on this node
|
||||
surf = model->surfaces + node->firstsurface;
|
||||
|
||||
for( int i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
{
|
||||
if( R_GetDirectLightFromSurface( surf, mid, info ))
|
||||
{
|
||||
info->fraction = midf;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, mid, end, info );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightPoint
|
||||
=================
|
||||
*/
|
||||
static bool R_LightPoint( model_t *model, mnode_t *node, const Vector &start, const Vector &end, mstudiolight_t *light, bool ambient, float *fraction )
|
||||
{
|
||||
float factor = (ambient) ? 0.6f : 0.9f;
|
||||
lightpoint_t info;
|
||||
|
||||
memset( &info, 0, sizeof( lightpoint_t ));
|
||||
info.fraction = *fraction = 1.0f;
|
||||
info.origin = start;
|
||||
|
||||
if( R_RecursiveLightPoint( model, node, 0.0f, 1.0f, start, end, &info ))
|
||||
{
|
||||
float total = Q_max( Q_max( info.lightmap.r, info.lightmap.g ), info.lightmap.b );
|
||||
if( total == 0.0f ) total = 1.0f;
|
||||
|
||||
info.normal *= (total * factor);
|
||||
light->shadelight = info.normal.Length();
|
||||
light->ambientlight = total - light->shadelight;
|
||||
|
||||
if( total > 0.0f )
|
||||
{
|
||||
light->diffuse.x = (float)info.lightmap.r * ( 1.0f / total );
|
||||
light->diffuse.y = (float)info.lightmap.g * ( 1.0f / total );
|
||||
light->diffuse.z = (float)info.lightmap.b * ( 1.0f / total );
|
||||
}
|
||||
else light->diffuse = Vector( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
if( light->ambientlight > 128 )
|
||||
light->ambientlight = 128;
|
||||
|
||||
if( light->ambientlight + light->shadelight > 255 )
|
||||
light->shadelight = 255 - light->ambientlight;
|
||||
light->normal = info.normal.Normalize();
|
||||
*fraction = info.fraction;
|
||||
light->nointerp = FBitSet( info.status, LIGHTINFO_STYLES ) ? true : false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
ComputeLightmapColorFromPoint
|
||||
=================
|
||||
*/
|
||||
static void ComputeLightmapColorFromPoint( lightpoint_t *info, mworldlight_t* pSkylight, float scale, Vector &radcolor, bool average )
|
||||
{
|
||||
if( !info->surf && FBitSet( info->status, LIGHTINFO_HITSKY ))
|
||||
{
|
||||
if( pSkylight )
|
||||
{
|
||||
radcolor += pSkylight->intensity * scale * 0.5f * (1.0f / 255.0f);
|
||||
}
|
||||
else if( world->numworldlights <= 0 ) // old bsp format?
|
||||
{
|
||||
Vector skyAmbient = tr.sky_ambient * (1.0f / 128.0f) * tr.diffuseFactor;
|
||||
radcolor += skyAmbient * scale * 0.5f * (1.0f / 255.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( info->surf != NULL )
|
||||
{
|
||||
Vector reflectivity;
|
||||
byte rgba[4];
|
||||
Vector color;
|
||||
|
||||
GET_EXTRA_PARAMS( info->surf->texinfo->texture->gl_texturenum, &rgba[0], &rgba[1], &rgba[2], &rgba[3] );
|
||||
reflectivity.x = TextureToLinear( rgba[0] );
|
||||
reflectivity.y = TextureToLinear( rgba[1] );
|
||||
reflectivity.z = TextureToLinear( rgba[2] );
|
||||
|
||||
if( average ) color = info->average * scale;
|
||||
else color = info->diffuse * scale;
|
||||
#if 0
|
||||
if( reflectivity != g_vecZero )
|
||||
color *= reflectivity;
|
||||
#endif
|
||||
radcolor += color;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes ambient lighting along a specified ray.
|
||||
// Ray represents a cone, tanTheta is the tan of the inner cone angle
|
||||
//-----------------------------------------------------------------------------
|
||||
static void R_CalcRayAmbientLighting( const Vector &vStart, const Vector &vEnd, mworldlight_t *pSkyLight, float tanTheta, Vector &color )
|
||||
{
|
||||
cl_entity_t *ent = NULL;
|
||||
model_t *model = worldmodel;
|
||||
lightpoint_t info;
|
||||
pmtrace_t tr0;
|
||||
|
||||
memset( &info, 0, sizeof( lightpoint_t ));
|
||||
SetBits( info.status, LIGHTINFO_AVERAGE );
|
||||
info.fraction = 1.0f;
|
||||
info.origin = vStart;
|
||||
color = g_vecZero;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
gEngfuncs.pEventAPI->EV_PlayerTraceExt( (float *)&vStart, (float *)&vEnd, PM_WORLD_ONLY, R_LightTraceFilter, &tr0 );
|
||||
|
||||
if( tr0.allsolid || tr0.startsolid || tr0.fraction == 1.0f )
|
||||
return; // doesn't hit anything
|
||||
|
||||
if( gEngfuncs.pEventAPI->EV_IndexFromTrace( &tr0 ) != -1 )
|
||||
ent = GET_ENTITY( gEngfuncs.pEventAPI->EV_IndexFromTrace( &tr0 ));
|
||||
|
||||
if( ent ) model = ent->model;
|
||||
|
||||
// Now that we've got a ray, see what surface we've hit
|
||||
R_RecursiveLightPoint( model, &model->nodes[model->hulls[0].firstclipnode], 0.0f, 1.0f, vStart, vEnd, &info );
|
||||
|
||||
Vector delta = vEnd - vStart;
|
||||
|
||||
// compute the approximate radius of a circle centered around the intersection point
|
||||
float dist = delta.Length() * tanTheta * info.fraction;
|
||||
|
||||
// until 20" we use the point sample, then blend in the average until we're covering 40"
|
||||
// This is attempting to model the ray as a cone - in the ideal case we'd simply sample all
|
||||
// luxels in the intersection of the cone with the surface. Since we don't have surface
|
||||
// neighbor information computed we'll just approximate that sampling with a blend between
|
||||
// a point sample and the face average.
|
||||
// This yields results that are similar in that aliasing is reduced at distance while
|
||||
// point samples provide accuracy for intersections with near geometry
|
||||
float scaleAvg = RemapValClamped( dist, 20, 40, 0.0f, 1.0f );
|
||||
|
||||
// don't have luxel UV, so just use average sample
|
||||
if( !info.surf ) scaleAvg = 1.0f;
|
||||
|
||||
float scaleSample = 1.0f - scaleAvg;
|
||||
|
||||
if( scaleAvg != 0.0f )
|
||||
{
|
||||
ComputeLightmapColorFromPoint( &info, pSkyLight, scaleAvg, color, true );
|
||||
}
|
||||
|
||||
if( scaleSample != 0.0f )
|
||||
{
|
||||
ComputeLightmapColorFromPoint( &info, pSkyLight, scaleSample, color, false );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PointAmbientFromAxisAlignedSamples
|
||||
|
||||
fast ambient comptation
|
||||
=================
|
||||
*/
|
||||
static bool R_PointAmbientFromAxisAlignedSamples( const Vector &p1, mstudiolight_t *light )
|
||||
{
|
||||
// use lightprobes instead
|
||||
if( world->numleaflights && world->leafs )
|
||||
return false;
|
||||
|
||||
mworldlight_t *pSkyLight = R_FindAmbientSkyLight();
|
||||
Vector radcolor[NUMVERTEXNORMALS];
|
||||
Vector lightBoxColor[6], p2;
|
||||
lightpoint_t info;
|
||||
|
||||
// sample world only along cardinal axes
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
memset( &info, 0, sizeof( lightpoint_t ));
|
||||
SetBits( info.status, LIGHTINFO_AVERAGE );
|
||||
info.fraction = 1.0f;
|
||||
info.origin = p1;
|
||||
|
||||
VectorMA( p1, 65536.0f * 1.74f, g_BoxDirections[i], p2 );
|
||||
|
||||
// now that we've got a ray, see what surface we've hit
|
||||
if( !R_RecursiveLightPoint( worldmodel, worldmodel->nodes, 0.0f, 1.0f, p1, p2, &info ))
|
||||
continue;
|
||||
|
||||
ComputeLightmapColorFromPoint( &info, pSkyLight, 1.0f, light->ambient[i], true );
|
||||
light->ambient[i] *= AMBIENT_CUBE_SCALE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PointAmbientFromSphericalSamples
|
||||
|
||||
reconstruct the ambient lighting for a leaf
|
||||
at the given position in worldspace
|
||||
=================
|
||||
*/
|
||||
static bool R_PointAmbientFromSphericalSamples( const Vector &p1, mstudiolight_t *light )
|
||||
{
|
||||
// use lightprobes instead
|
||||
if( world->numleaflights && world->leafs )
|
||||
return false;
|
||||
|
||||
// Figure out the color that rays hit when shot out from this position.
|
||||
float tanTheta = tan( VERTEXNORMAL_CONE_INNER_ANGLE );
|
||||
mworldlight_t *pSkylight = R_FindAmbientSkyLight();
|
||||
Vector radcolor[NUMVERTEXNORMALS];
|
||||
Vector lightBoxColor[6], p2;
|
||||
|
||||
// sample world by casting N rays distributed across a sphere
|
||||
for( int i = 0; i < NUMVERTEXNORMALS; i++ )
|
||||
{
|
||||
// FIXME: a good optimization would be to scale this per leaf
|
||||
VectorMA( p1, 65536.0f * 1.74f, g_anorms[i], p2 );
|
||||
|
||||
R_CalcRayAmbientLighting( p1, p2, pSkylight, tanTheta, radcolor[i] );
|
||||
}
|
||||
|
||||
// accumulate samples into radiant box
|
||||
for( int j = 0; j < 6; j++ )
|
||||
{
|
||||
float t = 0.0f;
|
||||
|
||||
VectorClear( light->ambient[j] );
|
||||
|
||||
for( int i = 0; i < NUMVERTEXNORMALS; i++ )
|
||||
{
|
||||
float c = DotProduct( g_anorms[i], g_BoxDirections[j] );
|
||||
|
||||
if( c > 0.0f )
|
||||
{
|
||||
VectorMA( light->ambient[j], c, radcolor[i], light->ambient[j] );
|
||||
t += c;
|
||||
}
|
||||
}
|
||||
|
||||
VectorScale( light->ambient[j], ( 1.0 / t ) * AMBIENT_CUBE_SCALE, light->ambient[j] );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_PointAmbientFromLeaf
|
||||
|
||||
reconstruct the ambient lighting for a leaf
|
||||
at the given position in worldspace
|
||||
=================
|
||||
*/
|
||||
void R_PointAmbientFromLeaf( const Vector &point, mstudiolight_t *light )
|
||||
{
|
||||
memset( light->ambient, 0, sizeof( light->ambient ));
|
||||
|
||||
if( r_lighting_extended->value > 1.0f )
|
||||
{
|
||||
if( R_PointAmbientFromSphericalSamples( point, light ))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( R_PointAmbientFromAxisAlignedSamples( point, light ))
|
||||
return;
|
||||
}
|
||||
|
||||
mleaf_t *leaf = Mod_PointInLeaf( point, worldmodel->nodes );
|
||||
mextraleaf_t *info = LEAF_INFO( leaf, worldmodel );
|
||||
mlightprobe_t *pAmbientProbe = info->ambient_light;
|
||||
float totalFactor = 0.0f;
|
||||
int i;
|
||||
|
||||
if( info->num_lightprobes > 0 )
|
||||
{
|
||||
for( i = 0; i < info->num_lightprobes; i++, pAmbientProbe++ )
|
||||
{
|
||||
// do an inverse squared distance weighted average of the samples
|
||||
// to reconstruct the original function
|
||||
float dist = (pAmbientProbe->origin - point).LengthSqr();
|
||||
float factor = 1.0f / (dist + 1.0f);
|
||||
totalFactor += factor;
|
||||
|
||||
for( int j = 0; j < 6; j++ )
|
||||
{
|
||||
Vector v;
|
||||
|
||||
v.x = (float)pAmbientProbe->cube.color[j][0] * (1.0f / 255.0f);
|
||||
v.y = (float)pAmbientProbe->cube.color[j][1] * (1.0f / 255.0f);
|
||||
v.z = (float)pAmbientProbe->cube.color[j][2] * (1.0f / 255.0f);
|
||||
|
||||
light->ambient[j] += v * factor;
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
light->ambient[i] *= (1.0f / totalFactor) * AMBIENT_CUBE_SCALE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightIdentity
|
||||
=================
|
||||
*/
|
||||
static void R_LightIdentity( mstudiolight_t *light )
|
||||
{
|
||||
// get default values
|
||||
light->diffuse.x = (float)TEXTURE_TO_TEXGAMMA( 255 ) / 255.0f;
|
||||
light->diffuse.y = (float)TEXTURE_TO_TEXGAMMA( 255 ) / 255.0f;
|
||||
light->diffuse.z = (float)TEXTURE_TO_TEXGAMMA( 255 ) / 255.0f;
|
||||
light->normal = Vector( 0.0f, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightMin
|
||||
=================
|
||||
*/
|
||||
static void R_LightMin( mstudiolight_t *light )
|
||||
{
|
||||
// get minlight values
|
||||
light->diffuse.x = (float)TEXTURE_TO_TEXGAMMA( 10 ) / 255.0f;
|
||||
light->diffuse.y = (float)TEXTURE_TO_TEXGAMMA( 10 ) / 255.0f;
|
||||
light->diffuse.z = (float)TEXTURE_TO_TEXGAMMA( 10 ) / 255.0f;
|
||||
light->normal = Vector( 0.0f, 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightVec
|
||||
|
||||
check bspmodels to get light from
|
||||
=================
|
||||
*/
|
||||
void R_LightVec( const Vector &point, mstudiolight_t *light, bool ambient )
|
||||
{
|
||||
memset( light, 0 , sizeof( *light ));
|
||||
|
||||
if( worldmodel && worldmodel->lightdata )
|
||||
{
|
||||
Vector p0 = point + Vector( 0.0f, 0.0f, 8.0f );
|
||||
Vector p1 = point + Vector( 0.0f, 0.0f, -512.0f );
|
||||
float last_fraction = 1.0f, fraction;
|
||||
Vector start = point;
|
||||
mstudiolight_t probe;
|
||||
|
||||
for( int i = 0; i < MAX_PHYSENTS; i++ )
|
||||
{
|
||||
physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( i );
|
||||
Vector offset, start_l, end_l;
|
||||
matrix3x4 matrix;
|
||||
mnode_t *pnodes;
|
||||
|
||||
if( !pe || !pe->model || pe->model->type != mod_brush )
|
||||
continue; // skip non-bsp models
|
||||
|
||||
pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
|
||||
// rotate start and end into the models frame of reference
|
||||
if( pe->angles != g_vecZero )
|
||||
{
|
||||
matrix = matrix3x4( pe->origin, pe->angles );
|
||||
start_l = matrix.VectorITransform( p0 );
|
||||
end_l = matrix.VectorITransform( p1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
start_l = p0 - pe->origin;
|
||||
end_l = p1 - pe->origin;
|
||||
}
|
||||
|
||||
memset( &probe, 0 , sizeof( probe ));
|
||||
if( !R_LightPoint( pe->model, pnodes, start_l, end_l, &probe, ambient, &fraction ))
|
||||
continue; // didn't hit anything
|
||||
|
||||
if( fraction < last_fraction )
|
||||
{
|
||||
last_fraction = fraction;
|
||||
*light = probe;
|
||||
|
||||
if( light->diffuse != g_vecZero )
|
||||
return; // we get light now
|
||||
}
|
||||
|
||||
// get light from bmodels too
|
||||
if( !CVAR_TO_BOOL( r_lighting_extended ))
|
||||
return; // get light from world and out
|
||||
}
|
||||
|
||||
R_LightMin( light );
|
||||
}
|
||||
else
|
||||
{
|
||||
R_LightIdentity( light );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightForSky
|
||||
=================
|
||||
*/
|
||||
void R_LightForSky( const Vector &point, mstudiolight_t *light )
|
||||
{
|
||||
if( tr.sun_light_enabled )
|
||||
{
|
||||
light->diffuse = tr.sun_diffuse;
|
||||
}
|
||||
else
|
||||
{
|
||||
light->diffuse = tr.sky_ambient * ( 1.0f / 128.0f ) * tr.diffuseFactor;
|
||||
}
|
||||
|
||||
// FIXME: this is correct?
|
||||
light->normal = -tr.sky_normal;
|
||||
light->ambientlight = 128;
|
||||
light->shadelight = 192;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightForStudio
|
||||
|
||||
given light for a studiomodel
|
||||
=================
|
||||
*/
|
||||
void R_LightForStudio( const Vector &point, mstudiolight_t *light, bool ambient )
|
||||
{
|
||||
R_LightVec( point, light, ambient );
|
||||
R_PointAmbientFromLeaf( point, light );
|
||||
}
|
595
cl_dll/render/gl_sprite.cpp
Normal file
595
cl_dll/render/gl_sprite.cpp
Normal file
@ -0,0 +1,595 @@
|
||||
/*
|
||||
gl_sprite.cpp - sprite model rendering
|
||||
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 "hud.h"
|
||||
#include "cl_util.h"
|
||||
#include "gl_local.h"
|
||||
#include <mathlib.h>
|
||||
#include "gl_sprite.h"
|
||||
#include "gl_studio.h"
|
||||
#include "event_api.h"
|
||||
#include "pm_defs.h"
|
||||
#include "studio.h"
|
||||
#include "triangleapi.h"
|
||||
|
||||
CSpriteModelRenderer g_SpriteRenderer;
|
||||
|
||||
/*
|
||||
====================
|
||||
Init
|
||||
|
||||
====================
|
||||
*/
|
||||
void CSpriteModelRenderer :: Init( void )
|
||||
{
|
||||
// Set up some variables shared with engine
|
||||
m_pCvarLerping = IEngineStudio.GetCvar( "r_sprite_lerping" );
|
||||
m_pCvarLighting = IEngineStudio.GetCvar( "r_sprite_lighting" );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CSpriteModelRenderer
|
||||
|
||||
====================
|
||||
*/
|
||||
CSpriteModelRenderer :: CSpriteModelRenderer( void )
|
||||
{
|
||||
m_pCurrentEntity = NULL;
|
||||
m_pCvarLerping = NULL;
|
||||
m_pCvarLighting = NULL;
|
||||
m_pSpriteHeader = NULL;
|
||||
m_pRenderModel = NULL;
|
||||
}
|
||||
|
||||
CSpriteModelRenderer :: ~CSpriteModelRenderer( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GetSpriteFrame
|
||||
|
||||
================
|
||||
*/
|
||||
mspriteframe_t *CSpriteModelRenderer :: GetSpriteFrame( int frame, float yaw )
|
||||
{
|
||||
mspritegroup_t *pspritegroup;
|
||||
mspriteframe_t *pspriteframe = NULL;
|
||||
|
||||
if( frame < 0 )
|
||||
{
|
||||
frame = 0;
|
||||
}
|
||||
else if( frame >= m_pSpriteHeader->numframes )
|
||||
{
|
||||
ALERT( at_warning, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, m_pRenderModel->name );
|
||||
frame = m_pSpriteHeader->numframes - 1;
|
||||
}
|
||||
|
||||
if( m_pSpriteHeader->frames[frame].type == SPR_SINGLE )
|
||||
{
|
||||
pspriteframe = (mspriteframe_t *)m_pSpriteHeader->frames[frame].frameptr;
|
||||
}
|
||||
else if( m_pSpriteHeader->frames[frame].type == SPR_GROUP )
|
||||
{
|
||||
pspritegroup = (mspritegroup_t *)m_pSpriteHeader->frames[frame].frameptr;
|
||||
|
||||
float *pintervals = pspritegroup->intervals;
|
||||
int numframes = pspritegroup->numframes;
|
||||
float fullinterval = pintervals[numframes-1];
|
||||
|
||||
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
|
||||
// are positive, so we don't have to worry about division by zero
|
||||
float targettime = m_clTime - ((int)( m_clTime / fullinterval )) * fullinterval;
|
||||
|
||||
for( int i = 0; i < (numframes - 1); i++ )
|
||||
{
|
||||
if( pintervals[i] > targettime )
|
||||
break;
|
||||
}
|
||||
pspriteframe = pspritegroup->frames[i];
|
||||
}
|
||||
else if( m_pSpriteHeader->frames[frame].type == FRAME_ANGLED )
|
||||
{
|
||||
int angleframe = (int)(Q_rint(( RI->view.angles[YAW] - yaw + 45.0f ) / 360 * 8 ) - 4) & 7;
|
||||
|
||||
// doom-style sprite monsters
|
||||
pspritegroup = (mspritegroup_t *)m_pSpriteHeader->frames[frame].frameptr;
|
||||
pspriteframe = pspritegroup->frames[angleframe];
|
||||
}
|
||||
|
||||
return pspriteframe;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CSpriteModelRenderer
|
||||
|
||||
Compute renderer origin (include parent movement, sky movement, etc)
|
||||
================
|
||||
*/
|
||||
void CSpriteModelRenderer :: SpriteComputeOrigin( cl_entity_t *e )
|
||||
{
|
||||
sprite_origin = e->origin; // set render origin
|
||||
|
||||
// link sprite with parent (if present)
|
||||
if( e->curstate.aiment > 0 && e->curstate.movetype == MOVETYPE_FOLLOW )
|
||||
{
|
||||
cl_entity_t *parent = GET_ENTITY( e->curstate.aiment );
|
||||
|
||||
if( parent && parent->model )
|
||||
{
|
||||
if( parent->model->type == mod_studio && e->curstate.body > 0 )
|
||||
{
|
||||
int num = bound( 1, e->curstate.body, MAXSTUDIOATTACHMENTS );
|
||||
sprite_origin = R_StudioAttachmentPos( parent, num - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite_origin = parent->origin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( e->curstate.renderfx == SKYBOX_ENTITY )
|
||||
{
|
||||
Vector trans = GetVieworg() - tr.sky_origin;
|
||||
|
||||
if( tr.sky_speed )
|
||||
{
|
||||
trans = trans - (GetVieworg() - tr.sky_world_origin) / tr.sky_speed;
|
||||
Vector skypos = tr.sky_origin + (GetVieworg() - tr.sky_world_origin) / tr.sky_speed;
|
||||
tr.modelorg = skypos - sprite_origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.modelorg = tr.sky_origin - sprite_origin;
|
||||
}
|
||||
|
||||
sprite_origin += trans; // move to the sky position
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.modelorg = sprite_origin;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SspriteComputeBBox
|
||||
|
||||
Compute a full bounding box for reference
|
||||
================
|
||||
*/
|
||||
void CSpriteModelRenderer :: SpriteComputeBBox( cl_entity_t *e, Vector bbox[8] )
|
||||
{
|
||||
// always compute origin first
|
||||
if( bbox != NULL ) SpriteComputeOrigin( e );
|
||||
|
||||
// copy original bbox (no rotation for sprites)
|
||||
sprite_absmin = e->model->mins;
|
||||
sprite_absmax = e->model->maxs;
|
||||
|
||||
float scale = 1.0f;
|
||||
|
||||
if( e->curstate.scale > 0.0f )
|
||||
scale = e->curstate.scale;
|
||||
|
||||
sprite_absmin *= scale;
|
||||
sprite_absmax *= scale;
|
||||
|
||||
sprite_absmin += sprite_origin;
|
||||
sprite_absmax += sprite_origin;
|
||||
|
||||
// compute a full bounding box
|
||||
for( int i = 0; bbox != NULL && i < 8; i++ )
|
||||
{
|
||||
bbox[i][0] = ( i & 1 ) ? sprite_absmin[0] : sprite_absmax[0];
|
||||
bbox[i][1] = ( i & 2 ) ? sprite_absmin[1] : sprite_absmax[1];
|
||||
bbox[i][2] = ( i & 4 ) ? sprite_absmin[2] : sprite_absmax[2];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CullSpriteModel
|
||||
|
||||
Cull sprite model by bbox
|
||||
================
|
||||
*/
|
||||
bool CSpriteModelRenderer :: CullSpriteModel( void )
|
||||
{
|
||||
if( !m_pSpriteHeader )
|
||||
return true;
|
||||
|
||||
SpriteComputeBBox( m_pCurrentEntity, NULL );
|
||||
|
||||
return R_CullModel( m_pCurrentEntity, sprite_absmin, sprite_absmax );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GlowSightDistance
|
||||
|
||||
Calc sight distance for glow-sprites
|
||||
================
|
||||
*/
|
||||
float CSpriteModelRenderer :: GlowSightDistance( void )
|
||||
{
|
||||
pmtrace_t tr;
|
||||
|
||||
float dist = (sprite_origin - GetVieworg( )).Length();
|
||||
|
||||
if( !FBitSet( RI->params, RP_MIRRORVIEW ))
|
||||
{
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( GetVieworg(), sprite_origin, PM_GLASS_IGNORE, -1, &tr );
|
||||
|
||||
if((( 1.0f - tr.fraction ) * dist ) > 8.0f )
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_GlowSightDistance
|
||||
|
||||
Set sprite brightness factor
|
||||
================
|
||||
*/
|
||||
float CSpriteModelRenderer :: SpriteGlowBlend( int rendermode, int renderfx, int alpha, float &scale )
|
||||
{
|
||||
float dist = GlowSightDistance();
|
||||
float brightness;
|
||||
|
||||
if( dist <= 0 ) return 0.0f; // occluded
|
||||
|
||||
if( renderfx == kRenderFxNoDissipation )
|
||||
return (float)alpha * (1.0f / 255.0f);
|
||||
|
||||
scale = 0.0f; // variable sized glow
|
||||
|
||||
brightness = 19000.0 / ( dist * dist );
|
||||
brightness = bound( 0.05f, brightness, 1.0f );
|
||||
|
||||
// make the glow fixed size in screen space, taking into consideration the scale setting.
|
||||
if( scale == 0.0f ) scale = 1.0f;
|
||||
scale *= dist * ( 1.0f / 200.0f );
|
||||
|
||||
return brightness;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SpriteOccluded
|
||||
|
||||
Do occlusion test for glow-sprites
|
||||
================
|
||||
*/
|
||||
int CSpriteModelRenderer :: SpriteOccluded( int &alpha, float &pscale )
|
||||
{
|
||||
// always compute origin first
|
||||
SpriteComputeOrigin( m_pCurrentEntity );
|
||||
|
||||
if( m_pCurrentEntity->curstate.rendermode == kRenderGlow )
|
||||
{
|
||||
// don't reflect this entity in mirrors
|
||||
if( FBitSet( m_pCurrentEntity->curstate.effects, EF_NOREFLECT ) && FBitSet( RI->params, RP_MIRRORVIEW ))
|
||||
return true;
|
||||
|
||||
// draw only in mirrors
|
||||
if( FBitSet( m_pCurrentEntity->curstate.effects, EF_REFLECTONLY ) && !FBitSet( RI->params, RP_MIRRORVIEW ))
|
||||
return true;
|
||||
|
||||
// original glow occlusion code by BUzer from Paranoia
|
||||
if( m_pCurrentEntity->curstate.renderfx == kRenderFxNoDissipation && CVAR_TO_BOOL( v_glows ))
|
||||
{
|
||||
mspriteframe_t *frame = GetSpriteFrame( m_pCurrentEntity->curstate.frame, m_pCurrentEntity->angles[YAW] );
|
||||
Vector left = Vector( 0.0f, ( frame->left * pscale ) / 5.0f, 0.0f );
|
||||
Vector right = Vector( 0.0f, ( frame->right * pscale ) / 5.0f, 0.0f );
|
||||
matrix4x4 sprite_transform = RI->view.matrix;
|
||||
|
||||
sprite_transform.SetOrigin( sprite_origin );
|
||||
Vector aleft = sprite_transform.VectorTransform( left );
|
||||
Vector aright = sprite_transform.VectorTransform( right );
|
||||
Vector dist = aright - aleft;
|
||||
|
||||
float dst = DotProduct( GetVForward(), sprite_origin - GetVieworg() );
|
||||
dst = bound( 0.0f, dst, 64.0f );
|
||||
dst = dst / 64.0f;
|
||||
|
||||
int numtraces = GLOW_NUM_TRACES;
|
||||
if( numtraces < 1 ) numtraces = 1;
|
||||
Vector step = dist * (1.0f / ( numtraces + 1 ));
|
||||
float frac = 1.0f / numtraces;
|
||||
float totalfrac = 0.0f;
|
||||
|
||||
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
|
||||
|
||||
for( int j = 0; j < numtraces; j++ )
|
||||
{
|
||||
Vector start = aleft + step * (j+1);
|
||||
|
||||
pmtrace_t pmtrace;
|
||||
gEngfuncs.pEventAPI->EV_PlayerTrace( GetVieworg(), start, PM_GLASS_IGNORE|PM_STUDIO_IGNORE, -1, &pmtrace );
|
||||
|
||||
if( pmtrace.fraction == 1.0f )
|
||||
totalfrac += frac;
|
||||
}
|
||||
|
||||
float targetalpha = totalfrac;
|
||||
float blend;
|
||||
|
||||
if( m_pCurrentEntity->latched.sequencetime > targetalpha )
|
||||
{
|
||||
m_pCurrentEntity->latched.sequencetime -= tr.frametime * GLOW_INTERP_SPEED;
|
||||
if( m_pCurrentEntity->latched.sequencetime <= targetalpha )
|
||||
m_pCurrentEntity->latched.sequencetime = targetalpha;
|
||||
}
|
||||
else if( m_pCurrentEntity->latched.sequencetime < targetalpha )
|
||||
{
|
||||
m_pCurrentEntity->latched.sequencetime += tr.frametime * GLOW_INTERP_SPEED;
|
||||
if( m_pCurrentEntity->latched.sequencetime >= targetalpha )
|
||||
m_pCurrentEntity->latched.sequencetime = targetalpha;
|
||||
}
|
||||
|
||||
blend = m_pCurrentEntity->latched.sequencetime * dst;
|
||||
alpha *= blend;
|
||||
|
||||
if( blend <= 0.01f )
|
||||
return true; // faded
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector screenVec;
|
||||
float blend;
|
||||
|
||||
WorldToScreen( sprite_origin, screenVec );
|
||||
|
||||
if( screenVec[0] < RI->view.port[0] || screenVec[0] > RI->view.port[0] + RI->view.port[2] )
|
||||
return true; // out of screen
|
||||
if( screenVec[1] < RI->view.port[1] || screenVec[1] > RI->view.port[1] + RI->view.port[3] )
|
||||
return true; // out of screen
|
||||
|
||||
blend = SpriteGlowBlend( m_pCurrentEntity->curstate.rendermode, m_pCurrentEntity->curstate.renderfx, alpha, pscale );
|
||||
alpha *= blend;
|
||||
|
||||
if( blend <= 0.01f )
|
||||
return true; // faded
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( CullSpriteModel( ))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
DrawSpriteQuad
|
||||
|
||||
=================
|
||||
*/
|
||||
void CSpriteModelRenderer :: DrawSpriteQuad( mspriteframe_t *frame, const Vector &org, const Vector &right, const Vector &up, float scale )
|
||||
{
|
||||
Vector point;
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, 1.0f );
|
||||
point = org + up * (frame->down * scale);
|
||||
point = point + right * (frame->left * scale);
|
||||
pglVertex3fv( point );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
point = org + up * (frame->up * scale);
|
||||
point = point + right * (frame->left * scale);
|
||||
pglVertex3fv( point );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
point = org + up * (frame->up * scale);
|
||||
point = point + right * (frame->right * scale);
|
||||
pglVertex3fv( point );
|
||||
pglTexCoord2f( 1.0f, 1.0f );
|
||||
point = org + up * (frame->down * scale);
|
||||
point = point + right * (frame->right * scale);
|
||||
pglVertex3fv( point );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
int CSpriteModelRenderer :: SpriteHasLightmap( int texFormat )
|
||||
{
|
||||
if( m_pCvarLighting->value == 0 )
|
||||
return false;
|
||||
|
||||
if( texFormat != SPR_ALPHTEST )
|
||||
return false;
|
||||
|
||||
if( FBitSet( m_pCurrentEntity->curstate.effects, EF_FULLBRIGHT ))
|
||||
return false;
|
||||
|
||||
if( m_pCurrentEntity->curstate.renderamt <= 127 )
|
||||
return false;
|
||||
|
||||
switch( m_pCurrentEntity->curstate.rendermode )
|
||||
{
|
||||
case kRenderNormal:
|
||||
case kRenderTransAlpha:
|
||||
case kRenderTransTexture:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_DrawSpriteModel
|
||||
=================
|
||||
*/
|
||||
void CSpriteModelRenderer :: AddSpriteModelToDrawList( cl_entity_t *e, bool update )
|
||||
{
|
||||
// obviously we can't update sprites...
|
||||
if( update ) return;
|
||||
|
||||
m_pCurrentEntity = RI->currententity;
|
||||
|
||||
IEngineStudio.GetTimes( &m_nFrameCount, &m_clTime, &m_clOldTime );
|
||||
|
||||
m_pRenderModel = m_pCurrentEntity->model;
|
||||
m_pSpriteHeader = (msprite_t *)Mod_Extradata( m_pRenderModel );
|
||||
|
||||
if( !m_pSpriteHeader ) return;
|
||||
|
||||
int alpha = m_pCurrentEntity->curstate.renderamt;
|
||||
float scale = m_pCurrentEntity->curstate.scale;
|
||||
int rendermode = m_pCurrentEntity->curstate.rendermode;
|
||||
|
||||
if( SpriteOccluded( alpha, scale ))
|
||||
return; // sprite culled
|
||||
|
||||
if( m_pSpriteHeader->texFormat == SPR_ALPHTEST )
|
||||
{
|
||||
if( rendermode != kRenderGlow && rendermode != kRenderTransAdd )
|
||||
rendermode = kRenderTransAlpha;
|
||||
}
|
||||
|
||||
Vector color, color2;
|
||||
|
||||
// add basecolor (any rendermode can have colored sprite)
|
||||
color[0] = (float)m_pCurrentEntity->curstate.rendercolor.r * ( 1.0f / 255.0f );
|
||||
color[1] = (float)m_pCurrentEntity->curstate.rendercolor.g * ( 1.0f / 255.0f );
|
||||
color[2] = (float)m_pCurrentEntity->curstate.rendercolor.b * ( 1.0f / 255.0f );
|
||||
|
||||
if( SpriteHasLightmap( m_pSpriteHeader->texFormat ))
|
||||
{
|
||||
gEngfuncs.pTriAPI->LightAtPoint( sprite_origin, (float *)&color2 );
|
||||
color2 *= (1.0f / 255.0f);
|
||||
color *= color2;
|
||||
}
|
||||
|
||||
mspriteframe_t *frame = GetSpriteFrame( m_pCurrentEntity->curstate.frame, m_pCurrentEntity->angles[YAW] );
|
||||
|
||||
int type = m_pSpriteHeader->type;
|
||||
|
||||
// automatically roll parallel sprites if requested
|
||||
if( m_pCurrentEntity->angles[ROLL] != 0.0f && type == SPR_FWD_PARALLEL )
|
||||
type = SPR_FWD_PARALLEL_ORIENTED;
|
||||
|
||||
Vector v_forward, v_right, v_up;
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case SPR_ORIENTED:
|
||||
{
|
||||
AngleVectors( m_pCurrentEntity->angles, v_forward, v_right, v_up );
|
||||
sprite_origin = sprite_origin - v_forward * 0.01f; // to avoid z-fighting
|
||||
}
|
||||
break;
|
||||
case SPR_FACING_UPRIGHT:
|
||||
{
|
||||
v_right.x = sprite_origin.y - GetVieworg().y;
|
||||
v_right.y = -(sprite_origin.x - GetVieworg().x);
|
||||
v_right.z = 0.0f;
|
||||
v_up.x = v_up.y = 0.0f;
|
||||
v_up.z = 1.0f;
|
||||
v_right = v_right.Normalize();
|
||||
}
|
||||
break;
|
||||
case SPR_FWD_PARALLEL_UPRIGHT:
|
||||
{
|
||||
float dot = GetVForward().z;
|
||||
if(( dot > 0.999848f ) || ( dot < -0.999848f )) // cos(1 degree) = 0.999848
|
||||
return; // invisible
|
||||
|
||||
v_right.x = GetVForward().y;
|
||||
v_right.y = -GetVForward().x;
|
||||
v_right.z = 0.0f;
|
||||
v_up.x = v_up.y = 0.0f;
|
||||
v_up.z = 1.0f;
|
||||
v_right = v_right.Normalize();
|
||||
}
|
||||
break;
|
||||
case SPR_FWD_PARALLEL_ORIENTED:
|
||||
{
|
||||
float angle = m_pCurrentEntity->angles[ROLL] * (M_PI * 2.0f / 360.0f);
|
||||
float sr, cr;
|
||||
|
||||
SinCos( angle, &sr, &cr );
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
v_right[i] = (GetVLeft()[i] * cr + GetVUp()[i] * sr);
|
||||
v_up[i] = GetVLeft()[i] * -sr + GetVUp()[i] * cr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPR_FWD_PARALLEL: // normal sprite
|
||||
default:
|
||||
{
|
||||
v_right = GetVLeft();
|
||||
v_up = GetVUp();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
float flAlpha = (float)alpha * ( 1.0f / 255.0f );
|
||||
|
||||
if( m_pCurrentEntity->curstate.rendermode == kRenderGlow && m_pCurrentEntity->curstate.renderfx == kRenderFxNoDissipation )
|
||||
{
|
||||
if( CVAR_TO_BOOL( v_glows ))
|
||||
{
|
||||
flAlpha = m_pCurrentEntity->curstate.renderamt * ( 1.0f/ 255.0f );
|
||||
color *= (float)alpha * ( 1.0f/ 255.0f );
|
||||
}
|
||||
}
|
||||
|
||||
Vector point[4];
|
||||
Vector4D spriteColor;
|
||||
Vector absmin, absmax;
|
||||
|
||||
spriteColor = Vector4D( color[0], color[1], color[2], flAlpha );
|
||||
point[0] = sprite_origin + v_up * (frame->down * scale);
|
||||
point[0] = point[0] + v_right * (frame->left * scale);
|
||||
point[1] = sprite_origin + v_up * (frame->up * scale);
|
||||
point[1] = point[1] + v_right * (frame->left * scale);
|
||||
point[2] = sprite_origin + v_up * (frame->up * scale);
|
||||
point[2] = point[2] + v_right * (frame->right * scale);
|
||||
point[3] = sprite_origin + v_up * (frame->down * scale);
|
||||
point[3] = point[3] + v_right * (frame->right * scale);
|
||||
|
||||
// more precision bounds than sprite_absmin\absmax
|
||||
ClearBounds( absmin, absmax );
|
||||
for( int i = 0; i < 4; i++ )
|
||||
AddPointToBounds( point[i], absmin, absmax );
|
||||
|
||||
CTransEntry entry;
|
||||
entry.SetRenderPrimitive( point, spriteColor, frame->gl_texturenum, rendermode );
|
||||
entry.ComputeViewDistance( absmin, absmax );
|
||||
RI->frame.trans_list.AddToTail( entry );
|
||||
}
|
||||
|
||||
mspriteframe_t *CSpriteModelRenderer :: GetSpriteFrame( const model_t *m_pSpriteModel, int frame )
|
||||
{
|
||||
if(( m_pSpriteHeader = (msprite_t *)Mod_Extradata( (model_t *)m_pSpriteModel )) == NULL )
|
||||
return NULL;
|
||||
|
||||
m_pCurrentEntity = NULL;
|
||||
return GetSpriteFrame( frame, 0.0f );
|
||||
}
|
112
cl_dll/render/gl_sprite.h
Normal file
112
cl_dll/render/gl_sprite.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
gl_sprite.h - sprite model rendering
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef GL_SPRITE_H
|
||||
#define GL_SPRITE_H
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
#define GLOW_NUM_TRACES 5
|
||||
#define GLOW_INTERP_SPEED 2.0f // time to fade glows
|
||||
|
||||
/*
|
||||
====================
|
||||
CSpriteModelRenderer
|
||||
|
||||
====================
|
||||
*/
|
||||
class CSpriteModelRenderer
|
||||
{
|
||||
public:
|
||||
// Construction/Destruction
|
||||
CSpriteModelRenderer( void );
|
||||
virtual ~CSpriteModelRenderer( void );
|
||||
|
||||
// Initialization
|
||||
virtual void Init( void );
|
||||
private:
|
||||
// Get Sprite description for frame
|
||||
virtual mspriteframe_t *GetSpriteFrame( int frame, float yaw );
|
||||
|
||||
virtual void SpriteComputeOrigin( cl_entity_t *e );
|
||||
|
||||
virtual void SpriteComputeBBox( cl_entity_t *e, Vector bbox[8] );
|
||||
|
||||
virtual bool CullSpriteModel( void );
|
||||
|
||||
virtual float GlowSightDistance( void );
|
||||
|
||||
virtual float SpriteGlowBlend( int rendermode, int renderfx, int alpha, float &scale );
|
||||
|
||||
virtual int SpriteOccluded( int &alpha, float &pscale );
|
||||
|
||||
virtual void DrawSpriteQuad( mspriteframe_t *frame, const Vector &org, const Vector &right, const Vector &up, float scale );
|
||||
|
||||
virtual int SpriteHasLightmap( int texFormat );
|
||||
|
||||
inline void *Mod_Extradata( model_t *mod )
|
||||
{
|
||||
if( mod && mod->type == mod_sprite )
|
||||
return mod->cache.data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vector sprite_origin;
|
||||
Vector sprite_absmin, sprite_absmax;
|
||||
|
||||
// Client clock
|
||||
double m_clTime;
|
||||
// Old Client clock
|
||||
double m_clOldTime;
|
||||
// Current render frame #
|
||||
int m_nFrameCount;
|
||||
|
||||
// Cvars that sprite model code needs to reference
|
||||
cvar_t *m_pCvarLerping; // Use lerping for animation?
|
||||
cvar_t *m_pCvarLighting; // lighting mode
|
||||
|
||||
// The entity which we are currently rendering.
|
||||
cl_entity_t *m_pCurrentEntity;
|
||||
|
||||
// The model for the entity being rendered
|
||||
model_t *m_pRenderModel;
|
||||
|
||||
// Current model rendermode
|
||||
int m_iRenderMode;
|
||||
|
||||
// Pointer to header block for sprite model data
|
||||
msprite_t *m_pSpriteHeader;
|
||||
|
||||
// engine stuff (backend)
|
||||
public:
|
||||
void AddSpriteModelToDrawList( cl_entity_t *e, bool update = false );
|
||||
|
||||
// Draw generic spritemodel
|
||||
mspriteframe_t *GetSpriteFrame( const model_t *m_pSpriteModel, int frame );
|
||||
};
|
||||
|
||||
extern CSpriteModelRenderer g_SpriteRenderer;
|
||||
|
||||
inline mspriteframe_t *R_GetSpriteFrame( const model_t *m_pSpriteModel, int frame )
|
||||
{
|
||||
return g_SpriteRenderer.GetSpriteFrame( m_pSpriteModel, frame );
|
||||
}
|
||||
|
||||
inline void R_AddSpriteToDrawList( cl_entity_t *e, bool update = false )
|
||||
{
|
||||
g_SpriteRenderer.AddSpriteModelToDrawList( e, update );
|
||||
}
|
||||
|
||||
#endif// GL_SPRITE_H
|
744
cl_dll/render/gl_studio.h
Normal file
744
cl_dll/render/gl_studio.h
Normal file
@ -0,0 +1,744 @@
|
||||
/*
|
||||
gl_studio.h - studio model rendering
|
||||
this code written for Paranoia 2: Savior modification
|
||||
Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#ifndef GL_STUDIO_H
|
||||
#define GL_STUDIO_H
|
||||
|
||||
#include "pmtrace.h"
|
||||
#include "studio.h"
|
||||
#include <utllinkedlist.h>
|
||||
#include <utlarray.h>
|
||||
#include <stringlib.h>
|
||||
#include "gl_decals.h"
|
||||
#include "gl_studiodecal.h"
|
||||
#include "trace.h"
|
||||
#include "bs_defs.h"
|
||||
#include "ikcontext.h"
|
||||
#include "jigglebones.h"
|
||||
#include "tbnfile.h"
|
||||
|
||||
#define EVENT_CLIENT 5000 // less than this value it's a server-side studio events
|
||||
#define MAX_MODEL_MESHES (MAXSTUDIOBODYPARTS * MAXSTUDIOMODELS)
|
||||
#define SHADE_LAMBERT 1.495f
|
||||
#define MAXARRAYVERTS 65536 // max vertices per studio submodel
|
||||
|
||||
#define MAX_SEQBLENDS 8 // must be power of two
|
||||
#define MASK_SEQBLENDS (MAX_SEQBLENDS - 1)
|
||||
|
||||
#define MF_STATIC_BOUNDS BIT( 0 ) // this model is a env_static. don't recalc bounds every frame
|
||||
#define MF_CUSTOM_LIGHTGRID BIT( 1 ) // model has special attahaments that was accepted as light probe start points
|
||||
#define MF_VERTEX_LIGHTING BIT( 2 ) // model has the custom vertex lighting (loading from level)
|
||||
#define MF_SURFACE_LIGHTING BIT( 3 ) // model has the custom surface lighting (loading from level)
|
||||
#define MF_VL_BAD_CACHE BIT( 4 ) // for some reasons this model can't be instanced with a vertex lighting (bad crc, mismatch vertexcount etc)
|
||||
#define MF_INIT_SMOOTHSTAIRS BIT( 5 )
|
||||
#define MF_ATTACHMENTS_DONE BIT( 6 )
|
||||
#define MF_POSITION_CHANGED BIT( 7 )
|
||||
|
||||
// studiorenderer modes
|
||||
#define DRAWSTUDIO_NORMAL 0 // as default
|
||||
#define DRAWSTUDIO_VIEWMODEL 1 // rendeging viewmodel
|
||||
#define DRAWSTUDIO_HEADSHIELD 2 // headshield or gasmask
|
||||
#define DRAWSTUDIO_RUNEVENTS 3 // run events of studiomodel
|
||||
|
||||
#define LIGHTSTATIC_NONE 0
|
||||
#define LIGHTSTATIC_VERTEX 1
|
||||
#define LIGHTSTATIC_SURFACE 2
|
||||
|
||||
#define TBNSTATE_INACTIVE 0
|
||||
#define TBNSTATE_LOADING 1
|
||||
#define TBNSTATE_GENERATE 2
|
||||
|
||||
// holds temporary data
|
||||
typedef struct
|
||||
{
|
||||
int firstvertex;
|
||||
int numvertices;
|
||||
int firstindex;
|
||||
int numindices;
|
||||
int lightmapnum;
|
||||
} StudioMesh_t;
|
||||
|
||||
// new blending sequence system
|
||||
typedef struct
|
||||
{
|
||||
float blendtime; // time to blend between current and previous sequence
|
||||
int sequence; // previous sequence number
|
||||
float cycle; // cycle where sequence was changed
|
||||
float fadeout;
|
||||
bool gaitseq;
|
||||
} mstudioblendseq_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float frame;
|
||||
int sequence;
|
||||
float gaitframe;
|
||||
int gaitsequence;
|
||||
|
||||
// for smooth stair climbing
|
||||
float stairtime;
|
||||
float stairoldz;
|
||||
} mstudiolerp_t;
|
||||
|
||||
// source vertex data (106 bytes here)
|
||||
typedef struct xvert_s
|
||||
{
|
||||
Vector vertex; // position
|
||||
Vector normal; // normal
|
||||
Vector tangent; // tangent
|
||||
Vector binormal; // binormal
|
||||
float stcoord[4]; // ST texture coords
|
||||
float lmcoord0[4]; // LM texture coords
|
||||
float lmcoord1[4]; // LM texture coords
|
||||
char boneid[4]; // control bones
|
||||
byte weight[4]; // boneweights
|
||||
float light[MAXLIGHTMAPS]; // packed color
|
||||
float deluxe[MAXLIGHTMAPS]; // packed lightdir
|
||||
byte styles[MAXLIGHTMAPS]; // lightstyles
|
||||
word m_MeshVertexIndex; // index into the mesh's vertex list (decals only)
|
||||
} svert_t;
|
||||
|
||||
typedef void (*pfnCreateStudioBuffer)( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
typedef void (*pfnBindStudioBuffer)( vbomesh_t *pOut, int attrFlags );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pfnCreateStudioBuffer CreateBuffer;
|
||||
pfnBindStudioBuffer BindBuffer;
|
||||
const char* BufferName; // debug
|
||||
} mesh_loader_t;
|
||||
|
||||
class CBaseBoneSetup : public CStudioBoneSetup
|
||||
{
|
||||
public:
|
||||
virtual void debugMsg( char *szFmt, ... );
|
||||
virtual mstudioanim_t *GetAnimSourceData( mstudioseqdesc_t *pseqdesc );
|
||||
virtual void debugLine( const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest = false, float duration = 0.0f );
|
||||
};
|
||||
|
||||
/*
|
||||
====================
|
||||
CStudioModelRenderer
|
||||
|
||||
====================
|
||||
*/
|
||||
class CStudioModelRenderer
|
||||
{
|
||||
public:
|
||||
// Construction/Destruction
|
||||
CStudioModelRenderer( void );
|
||||
virtual ~CStudioModelRenderer( void );
|
||||
|
||||
// Initialization
|
||||
void Init( void );
|
||||
|
||||
void VidInit( void );
|
||||
|
||||
// Look up animation data for sequence
|
||||
mstudioanim_t *StudioGetAnim ( model_t *pModel, mstudioseqdesc_t *pseqdesc );
|
||||
|
||||
// precache vertexlit mesh
|
||||
void CreateStudioCacheVL( const char *modelname, int cacheID );
|
||||
|
||||
// precache lightmapped mesh
|
||||
void CreateStudioCacheFL( const char *modelname, int cacheID );
|
||||
|
||||
// throw all the meshes when the engine is shutting down
|
||||
void FreeStudioCacheVL( void );
|
||||
void FreeStudioCacheFL( void );
|
||||
private:
|
||||
// Local interfaces
|
||||
|
||||
// Extract bbox from current sequence
|
||||
int StudioExtractBbox ( studiohdr_t *phdr, int sequence, Vector &mins, Vector &maxs );
|
||||
|
||||
// Compute a full bounding box for current sequence
|
||||
int StudioComputeBBox ( void );
|
||||
|
||||
float CalcStairSmoothValue( float oldz, float newz, float smoothtime, float smoothvalue );
|
||||
|
||||
const Vector StudioGetOrigin( void );
|
||||
|
||||
// Interpolate model position and angles and set up matrices
|
||||
void StudioSetUpTransform( void );
|
||||
|
||||
// Set up model bone positions
|
||||
void StudioSetupBones( void );
|
||||
|
||||
// Find final attachment points
|
||||
void StudioCalcAttachments( matrix3x4 bones[] );
|
||||
|
||||
void AddBlendSequence( int oldseq, int newseq, float prevframe, bool gaitseq = false );
|
||||
|
||||
void BlendSequence( Vector pos[], Vector4D q[], mstudioblendseq_t *pseqblend );
|
||||
|
||||
void UpdateIKLocks( CIKContext *pIK );
|
||||
|
||||
void CalculateIKLocks( CIKContext *pIK );
|
||||
|
||||
// Merge cached bones with current bones for model
|
||||
void StudioMergeBones( matrix3x4 &transform, matrix3x4 bones[], matrix3x4 cached_bones[], model_t *pModel, model_t *pParentModel );
|
||||
|
||||
// Determine interpolation fraction
|
||||
float StudioEstimateInterpolant( void );
|
||||
|
||||
// Determine current gaitframe for rendering
|
||||
float StudioEstimateGaitFrame ( mstudioseqdesc_t *pseqdesc );
|
||||
|
||||
// Determine current frame for rendering
|
||||
float StudioEstimateFrame ( mstudioseqdesc_t *pseqdesc );
|
||||
|
||||
void StudioInterpolateControllers( cl_entity_t *e, float dadt );
|
||||
|
||||
void StudioInterpolatePoseParams( cl_entity_t *e, float dadt );
|
||||
|
||||
// Apply special effects to transform matrix
|
||||
void StudioFxTransform( cl_entity_t *ent, matrix3x4 &transform );
|
||||
|
||||
void ComputeSkinMatrix( mstudioboneweight_t *boneweights, const matrix3x4 worldtransform[], matrix3x4 &result );
|
||||
|
||||
void ComputeSkinMatrix( svert_t *vertex, const matrix3x4 worldtransform[], matrix3x4 &result );
|
||||
|
||||
int StudioCheckLOD( void );
|
||||
|
||||
//calc bodies and get pointers to him
|
||||
int StudioSetupModel ( int bodypart, mstudiomodel_t **ppsubmodel, msubmodel_t **ppvbomodel );
|
||||
|
||||
void DrawMeshFromBuffer( const vbomesh_t *mesh );
|
||||
|
||||
void DeleteVBOMesh( vbomesh_t *mesh );
|
||||
|
||||
// Process studio client events
|
||||
void StudioClientEvents( void );
|
||||
|
||||
void StudioLighting( float *lv, int bone, int flags, const Vector &normal );
|
||||
|
||||
void StudioStaticLight( cl_entity_t *ent, mstudiolight_t *light );
|
||||
void CacheVertexLight( cl_entity_t *ent );
|
||||
void CacheSurfaceLight( cl_entity_t *ent );
|
||||
void StudioFormatAttachment( Vector &point );
|
||||
|
||||
word ChooseStudioProgram( studiohdr_t *phdr, mstudiomaterial_t *mat, bool lightpass );
|
||||
|
||||
void AddMeshToDrawList( studiohdr_t *phdr, vbomesh_t *mesh, bool lightpass );
|
||||
|
||||
void AddBodyPartToDrawList( studiohdr_t *phdr, mbodypart_t *bodyparts, int bodypart, bool lightpass );
|
||||
|
||||
bool CheckBoneCache( float f );
|
||||
|
||||
word ShaderSceneForward( mstudiomaterial_t *mat, int lightmode, bool bone_weighting, int numbones );
|
||||
word ShaderLightForward( CDynLight *dl, mstudiomaterial_t *mat, bool bone_weighting, int numbones );
|
||||
word ShaderSceneDeferred( mstudiomaterial_t *mat, bool bone_weighting, int numbones );
|
||||
word ShaderLightDeferred( mstudiomaterial_t *mat, bool bone_weighting, int numbones );
|
||||
word ShaderSceneDepth( mstudiomaterial_t *mat, bool bone_weighting, int numbones );
|
||||
word ShaderDecalForward( studiodecal_t *pDecal, bool has_vertexlight );
|
||||
|
||||
// Debug drawing
|
||||
void StudioDrawDebug( cl_entity_t *e );
|
||||
|
||||
void StudioDrawHulls( int iHitbox = -1 );
|
||||
|
||||
void StudioDrawAbsBBox( void );
|
||||
|
||||
void StudioDrawBones( void );
|
||||
|
||||
void StudioDrawAttachments( bool bCustomFov );
|
||||
|
||||
int HeadShieldThink( void );
|
||||
|
||||
// intermediate structure. Used only for build unique submodels
|
||||
struct TmpModel_t
|
||||
{
|
||||
char name[64];
|
||||
mstudiomodel_t *pmodel;
|
||||
msubmodel_t *pout;
|
||||
};
|
||||
|
||||
struct BoneCache_t
|
||||
{
|
||||
float frame; // product of StudioEstimateFrame, not a curstate.frame!
|
||||
short sequence;
|
||||
byte blending[2];
|
||||
byte controller[4];
|
||||
byte mouthopen;
|
||||
matrix3x4 transform; // cached transform because ent->angles\ent->origin doesn't contains interpolation info
|
||||
float poseparam[MAXSTUDIOPOSEPARAM];
|
||||
|
||||
// special fields for player
|
||||
short gaitsequence;
|
||||
float gaitframe;
|
||||
};
|
||||
|
||||
struct StudioAttachment_t
|
||||
{
|
||||
char name[MAXSTUDIONAME];
|
||||
matrix3x4 local; // local position
|
||||
Vector origin; // attachment pos
|
||||
Vector angles; // VectorAngles
|
||||
Vector dir; // old method
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int m_VertCount; // Number of used vertices
|
||||
int m_Indices[2][7]; // Indices into the clip verts array of the used vertices
|
||||
bool m_Pass; // Helps us avoid copying the m_Indices array by using double-buffering
|
||||
int m_ClipVertCount; // Add vertices we've started with and had to generate due to clipping
|
||||
svert_t m_ClipVerts[16];
|
||||
int m_ClipFlags[16]; // Union of the decal triangle clip flags above for each vert
|
||||
} DecalClipState_t;
|
||||
|
||||
typedef CUtlArray<studiodecal_t> StudioDecalList_t;
|
||||
typedef CUtlArray<int> CIntVector;
|
||||
|
||||
enum
|
||||
{
|
||||
MESHLOADER_BASE = 0,
|
||||
MESHLOADER_BASEBUMP,
|
||||
MESHLOADER_VLIGHT,
|
||||
MESHLOADER_VLIGHTBUMP,
|
||||
MESHLOADER_WEIGHT,
|
||||
MESHLOADER_WEIGHTBUMP,
|
||||
MESHLOADER_LIGHTMAP,
|
||||
MESHLOADER_LIGHTMAPBUMP,
|
||||
MESHLOADER_GENERIC,
|
||||
MESHLOADER_COUNT,
|
||||
};
|
||||
|
||||
struct ModelInstance_t
|
||||
{
|
||||
cl_entity_t *m_pEntity;
|
||||
|
||||
// Need to store off the model. When it changes, we lose all instance data..
|
||||
model_t *m_pModel;
|
||||
StudioDecalList_t m_DecalList; // new decal list for each instance
|
||||
int m_DecalCount; // just used as timestamp for calculate decal depth
|
||||
int info_flags;
|
||||
|
||||
// NOTE: each decal applied while model has some pose
|
||||
// keep it in this array for each model and dump into
|
||||
// savefile to properly restored decal positions
|
||||
CUtlArray<modelstate_t> pose_stamps;
|
||||
|
||||
mstudiocache_t *m_VlCache; // valid only for env_statics that have vertexlight data
|
||||
mstudiocache_t *m_FlCache; // valid only for env_statics that have surfacelight data
|
||||
byte styles[MAXLIGHTMAPS];// actual only if MF_VERTEX_LIGHTING|MF_SURFACE_LIGHTING bit is set
|
||||
|
||||
// bounds info
|
||||
Vector absmin;
|
||||
Vector absmax;
|
||||
float radius;
|
||||
Vector origin; // transformed origin
|
||||
|
||||
BoneCache_t bonecache; // just compare to avoid recalc bones every frame
|
||||
|
||||
// attachments
|
||||
StudioAttachment_t attachment[MAXSTUDIOATTACHMENTS];
|
||||
int numattachments;
|
||||
|
||||
byte m_controller[MAXSTUDIOCONTROLLERS];
|
||||
float m_poseparameter[MAXSTUDIOPOSEPARAM]; // blends for traditional studio models
|
||||
float m_oldposeparams[MAXSTUDIOPOSEPARAM]; // latched values
|
||||
mstudioblendseq_t m_seqblend[MAX_SEQBLENDS];
|
||||
int m_current_seqblend;
|
||||
|
||||
// sequence blends stuff
|
||||
mstudiolerp_t lerp;
|
||||
|
||||
CJiggleBones *m_pJiggleBones;
|
||||
CIKContext m_ik;
|
||||
// attached cubemaps
|
||||
mcubemap_t *cubemap[2];
|
||||
float lerpFactor;
|
||||
|
||||
mstudiomaterial_t *materials; // shaders cache
|
||||
|
||||
// light interpolation
|
||||
mstudiolight_t oldlight;
|
||||
mstudiolight_t newlight;
|
||||
mstudiolight_t light; // cached light values
|
||||
|
||||
float lighttimecheck;
|
||||
bool light_update;
|
||||
byte lights[MAXDYNLIGHTS]; // dynamic lights cache
|
||||
|
||||
matrix3x4 m_protationmatrix;
|
||||
matrix3x4 m_pbones[MAXSTUDIOBONES]; // bone to pose
|
||||
matrix3x4 m_pwpnbones[MAXSTUDIOBONES];
|
||||
Vector4D m_glstudiobones[MAXSTUDIOBONES*3]; // GLSL-friendly compacted matrix4x3
|
||||
Vector4D m_glweaponbones[MAXSTUDIOBONES*3]; // GLSL-friendly compacted matrix4x3
|
||||
|
||||
// GLSL cached arrays
|
||||
Vector4D m_studioquat[MAXSTUDIOBONES];
|
||||
Vector m_studiopos[MAXSTUDIOBONES];
|
||||
Vector4D m_weaponquat[MAXSTUDIOBONES];
|
||||
Vector m_weaponpos[MAXSTUDIOBONES];
|
||||
GLfloat m_glmatrix[16];
|
||||
|
||||
unsigned int cached_frame; // to avoid compute bones more than once per frame
|
||||
unsigned int visframe; // model is visible this frame
|
||||
};
|
||||
|
||||
struct DecalBuildInfo_t
|
||||
{
|
||||
// this part is constant all time while decal is build
|
||||
const DecalGroupEntry* m_pTexInfo;
|
||||
modelstate_t* modelState;
|
||||
dmodelvertlight_t* modelLight;
|
||||
Vector vecLocalNormal;
|
||||
Vector vecLocalEnd;
|
||||
Vector2D vecDecalScale;
|
||||
bool m_UseClipVert;
|
||||
int decalDepth;
|
||||
byte decalFlags;
|
||||
int poseState;
|
||||
studiodecal_t *current;
|
||||
float m_Radius;
|
||||
|
||||
// this part is changed for each mesh
|
||||
vbomesh_t* m_pModelMesh;
|
||||
StudioMesh_t* m_pDecalMesh;
|
||||
dvertlight_t* m_pVertexLight;
|
||||
DecalVertexInfo_t* m_pVertexInfo;
|
||||
CUtlArray<svert_t> m_Vertices;
|
||||
CUtlArray<unsigned int> m_Indices;
|
||||
};
|
||||
|
||||
// keep model instances for each entity
|
||||
CUtlLinkedList< ModelInstance_t, word > m_ModelInstances;
|
||||
|
||||
// decal stuff
|
||||
bool ComputePoseToDecal( const Vector &vecStart, const Vector &vecEnd );
|
||||
void AddDecalToModel( DecalBuildInfo_t& buildInfo );
|
||||
void AddDecalToMesh( DecalBuildInfo_t& buildInfo );
|
||||
void AllocDecalForMesh( DecalBuildInfo_t& build );
|
||||
void ProjectDecalOntoMesh( DecalBuildInfo_t& build );
|
||||
bool IsFrontFacing( const svert_t *vert );
|
||||
void DecalCreateBuffer( DecalBuildInfo_t& build, studiodecal_t *pDecal );
|
||||
bool TransformToDecalSpace( DecalBuildInfo_t& build, const svert_t *vert, Vector2D& uv );
|
||||
matrix3x3 GetDecalRotateTransform( byte vertexBone );
|
||||
void AddTriangleToDecal( DecalBuildInfo_t& build, int i1, int i2, int i3 );
|
||||
int ComputeClipFlags( Vector2D const& uv );
|
||||
bool ClipDecal( DecalBuildInfo_t& build, int i1, int i2, int i3, int *pClipFlags );
|
||||
void ConvertMeshVertexToDecalVertex( DecalBuildInfo_t& build, int vertIndex, svert_t *out );
|
||||
void ClipTriangleAgainstPlane( DecalClipState_t& state, int normalInd, int flag, float val );
|
||||
int IntersectPlane( DecalClipState_t& state, int start, int end, int normalInd, float val );
|
||||
word AddVertexToDecal( DecalBuildInfo_t& build, int vertIndex );
|
||||
word AddVertexToDecal( DecalBuildInfo_t& build, svert_t *vert );
|
||||
void AddClippedDecalToTriangle( DecalBuildInfo_t& build, DecalClipState_t& clipState );
|
||||
void ComputeDecalTBN( DecalBuildInfo_t& build );
|
||||
void PurgeDecals( ModelInstance_t *inst );
|
||||
void PurgeDecals( cl_entity_t *pEnt );
|
||||
bool StudioSetEntity( cl_entity_t *pEnt );
|
||||
bool StudioSetEntity( CSolidEntry *entry );
|
||||
bool IsModelInstanceValid( ModelInstance_t *inst );
|
||||
bool StudioSetupInstance( void );
|
||||
void DestroyInstance( word handle );
|
||||
void SetDecalUniforms( studiodecal_t *pDecal );
|
||||
void DrawDecal( CSolidEntry *entry, GLenum cull = GL_FRONT );
|
||||
|
||||
mstudiocache_t *CreateStudioCache( void *dml = NULL, int lightmode = LIGHTSTATIC_NONE );
|
||||
void DeleteStudioCache( mstudiocache_t **ppcache );
|
||||
void DestroyMeshCache( void );
|
||||
|
||||
void CreateStudioCacheVL( dmodelvertlight_t *dml, int cacheID );
|
||||
void CreateStudioCacheFL( dmodelfacelight_t *dml, int cacheID );
|
||||
void PrecacheStudioShaders( void );
|
||||
void LoadStudioMaterials( void );
|
||||
void FreeStudioMaterials( void );
|
||||
|
||||
void UpdateInstanceMaterials( void );
|
||||
void ClearInstanceData( bool create );
|
||||
|
||||
// set uniforms data for specified shader
|
||||
void DrawSingleMesh( CSolidEntry *mesh, bool force );
|
||||
|
||||
void SetupSubmodelVerts( const mstudiomodel_t *pSubModel, const matrix3x4 bones[], void *dml, int lightmode );
|
||||
void MeshCreateBuffer( vbomesh_t *pDst, const mstudiomesh_t *pSrc, const StudioMesh_t *pMeshInfo, int lightmode );
|
||||
void AllocLightmapsForMesh( StudioMesh_t *pCurMesh, const dmodelfacelight_t *dfl );
|
||||
bool CalcLightmapAxis( mstudiosurface_t *surf, const dfacelight_t *fl, const dmodelfacelight_t *dfl );
|
||||
static void CreateBufferBaseGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferBaseGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferBaseBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferBaseBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferVLightGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferVLightGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferVLightBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferVLightBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferWeightGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferWeightGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferWeightBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferWeightBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferLightMapGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferLightMapGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferLightMapBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferLightMapBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferGenericGL21( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
static void CreateBufferGenericGL30( vbomesh_t *pOut, svert_t *arrayxvert );
|
||||
|
||||
static void BindBufferBaseGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferBaseGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferBaseBumpGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferBaseBumpGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferVLightGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferVLightGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferVLightBumpGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferVLightBumpGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferWeightGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferWeightGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferWeightBumpGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferWeightBumpGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferLightMapGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferLightMapGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferLightMapBumpGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferLightMapBumpGL30( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferGenericGL21( vbomesh_t *pOut, int attrFlags );
|
||||
static void BindBufferGenericGL30( vbomesh_t *pOut, int attrFlags );
|
||||
|
||||
static void CreateIndexBuffer( vbomesh_t *pOut, unsigned int *arrayelems );
|
||||
static void BindIndexBuffer( vbomesh_t *pOut );
|
||||
|
||||
static int SortSolidMeshes( const CSolidEntry *a, const CSolidEntry *b );
|
||||
|
||||
unsigned int ComputeAttribFlags( int numbones, bool has_bumpmap, bool has_boneweights, bool has_vertexlight, bool has_lightmap );
|
||||
unsigned int SelectMeshLoader( int numbones, bool has_bumpmap, bool has_boneweights, bool has_vertexlight, bool has_lightmap );
|
||||
|
||||
static mesh_loader_t m_pfnMeshLoaderGL21[MESHLOADER_COUNT];
|
||||
static mesh_loader_t m_pfnMeshLoaderGL30[MESHLOADER_COUNT];
|
||||
|
||||
bool m_fShootDecal; // disable all interpolations and bonecache
|
||||
float m_flViewmodelFov; // custom fov for viewmodel
|
||||
int m_iDrawModelType; // various modes of rendering
|
||||
|
||||
// Cvars that studio model code needs to reference
|
||||
cvar_t *m_pCvarHiModels; // Use high quality models?
|
||||
cvar_t *m_pCvarDrawViewModel;
|
||||
cvar_t *m_pCvarHand; // handness
|
||||
cvar_t *m_pCvarViewmodelFov;
|
||||
cvar_t *m_pCvarHeadShieldFov;
|
||||
cvar_t *m_pCvarLegsOffset;
|
||||
cvar_t *m_pCvarDrawLegs;
|
||||
cvar_t *m_pCvarCompatible;
|
||||
cvar_t *m_pCvarLodScale;
|
||||
cvar_t *m_pCvarLodBias;
|
||||
|
||||
CBaseBoneSetup m_boneSetup;
|
||||
|
||||
// current mesh material
|
||||
mstudiomaterial_t *m_pCurrentMaterial;
|
||||
|
||||
ModelInstance_t *m_pModelInstance;
|
||||
|
||||
// Pointer to header block for studio model data
|
||||
studiohdr_t *m_pStudioHeader;
|
||||
mstudiocache_t *m_pStudioCache; // only valid while mesh is build
|
||||
|
||||
msubmodel_t *m_pVboModel;
|
||||
mstudiomodel_t *m_pSubModel;
|
||||
StudioMesh_t m_pTempMesh[MAXSTUDIOSKINS]; // temp structure
|
||||
|
||||
// used by PushEntity\PopEntity
|
||||
entity_state_t m_savestate;
|
||||
Vector m_saveorigin;
|
||||
Vector m_saveangles;
|
||||
|
||||
Vector m_bonelightvecs[MAXSTUDIOBONES]; // debug used this
|
||||
Vector m_arrayverts[MAXARRAYVERTS];
|
||||
svert_t m_arrayxvert[MAXARRAYVERTS];
|
||||
dmodeltbn_t *m_tbnverts; // variable sized
|
||||
unsigned int m_arrayelems[MAXARRAYVERTS*3];
|
||||
unsigned int m_nNumArrayVerts;
|
||||
unsigned int m_nNumArrayElems;
|
||||
unsigned int m_nNumLightVerts;
|
||||
unsigned int m_nNumLightFaces;
|
||||
unsigned int m_nNumTBNVerts;
|
||||
unsigned int m_nNumTempVerts; // used to conversion to fan sequence
|
||||
|
||||
// decal building stuff
|
||||
matrix3x4 m_pdecaltransform[MAXSTUDIOBONES]; // decal->world
|
||||
matrix3x4 m_pworldtransform[MAXSTUDIOBONES]; // world->decal
|
||||
|
||||
// firstperson legs stuff
|
||||
model_t *m_pPlayerLegsModel;
|
||||
int m_iTBNState;
|
||||
public:
|
||||
void DestroyAllModelInstances( void );
|
||||
|
||||
int StudioGetBounds( cl_entity_t *e, Vector bounds[2] );
|
||||
int StudioGetBounds( CSolidEntry *entry, Vector bounds[2] );
|
||||
bool StudioLoadTBN( void );
|
||||
bool StudioSaveTBN( void );
|
||||
|
||||
void PushEntityState( cl_entity_t *ent );
|
||||
void PopEntityState( cl_entity_t *ent );
|
||||
void EntityToModelState( modelstate_t *state, const cl_entity_t *ent );
|
||||
void ModelStateToEntity( cl_entity_t *ent, const modelstate_t *state );
|
||||
void StudioDecalShoot( const Vector &vecNorm, const Vector &vecEnd, const char *name, cl_entity_t *ent, int flags, modelstate_t *state );
|
||||
void StudioDecalShoot( struct pmtrace_s *tr, const char *name, bool visent = false );
|
||||
int StudioDecalList( decallist_t *pList, int count );
|
||||
void StudioClearDecals( void );
|
||||
void RemoveAllDecals( int entityIndex );
|
||||
|
||||
void UpdateLatchedVars( cl_entity_t *e, qboolean reset );
|
||||
|
||||
void ProcessUserData( model_t *mod, qboolean create, const byte *buffer );
|
||||
|
||||
void LoadLocalMatrix( int bone, mstudioboneinfo_t *boneinfo );
|
||||
|
||||
void AddStudioModelToDrawList( cl_entity_t *e, bool update = false );
|
||||
|
||||
void StudioGetAttachment( const cl_entity_t *ent, int iAttachment, Vector *pos, Vector *ang, Vector *dir );
|
||||
|
||||
// Process viewmodel events (at start the frame so muzzleflashes will be correct added)
|
||||
void RunViewModelEvents( void );
|
||||
|
||||
bool ComputeCustomFov( matrix4x4 &projMatrix, matrix4x4 &worldViewProjMatrix );
|
||||
|
||||
void RestoreNormalFov( matrix4x4 &projMatrix, matrix4x4 &worldViewProjMatrix );
|
||||
|
||||
// Draw view model (at end the frame)
|
||||
void DrawViewModel( void );
|
||||
|
||||
// draw head shield (after viewmodel)
|
||||
void DrawHeadShield( void );
|
||||
|
||||
void RenderDeferredStudioList( void );
|
||||
|
||||
void RenderSolidStudioList( void );
|
||||
|
||||
void RenderShadowStudioList( void );
|
||||
|
||||
void RenderDebugStudioList( bool bViewModel );
|
||||
|
||||
void RenderDynLightList( bool solid );
|
||||
|
||||
void RenderTransMesh( CTransEntry *entry );
|
||||
|
||||
void BuildMeshListForLight( CDynLight *pl, bool solid );
|
||||
|
||||
void DrawLightForMeshList( CDynLight *pl );
|
||||
|
||||
int CacheCount( void ) { return m_ModelInstances.Count(); }
|
||||
|
||||
void ClearLightCache( void );
|
||||
};
|
||||
|
||||
extern CStudioModelRenderer g_StudioRenderer;
|
||||
|
||||
// implementation of drawing funcs
|
||||
inline void R_RunViewmodelEvents( void ) { g_StudioRenderer.RunViewModelEvents(); }
|
||||
inline void R_DrawViewModel( void ) { g_StudioRenderer.DrawViewModel(); }
|
||||
inline void R_DrawHeadShield( void ) { g_StudioRenderer.DrawHeadShield(); }
|
||||
inline void R_ProcessStudioData( model_t *mod, qboolean create, const byte *buffer )
|
||||
{
|
||||
if( mod->type == mod_studio )
|
||||
g_StudioRenderer.ProcessUserData( mod, create, buffer );
|
||||
}
|
||||
|
||||
inline int R_CreateStudioDecalList( decallist_t *pList, int count )
|
||||
{
|
||||
return g_StudioRenderer.StudioDecalList( pList, count );
|
||||
}
|
||||
|
||||
inline void R_ClearStudioDecals( void )
|
||||
{
|
||||
g_StudioRenderer.StudioClearDecals();
|
||||
}
|
||||
|
||||
inline int R_StudioGetBounds( cl_entity_t *e, Vector bounds[2] )
|
||||
{
|
||||
return g_StudioRenderer.StudioGetBounds( e, bounds );
|
||||
}
|
||||
|
||||
inline int R_StudioGetBounds( CSolidEntry *entry, Vector bounds[2] )
|
||||
{
|
||||
return g_StudioRenderer.StudioGetBounds( entry, bounds );
|
||||
}
|
||||
|
||||
inline void R_RenderDeferredStudioList( void )
|
||||
{
|
||||
g_StudioRenderer.RenderDeferredStudioList();
|
||||
}
|
||||
|
||||
inline void R_RenderSolidStudioList( void )
|
||||
{
|
||||
g_StudioRenderer.RenderSolidStudioList();
|
||||
}
|
||||
|
||||
inline void R_RenderTransMesh( CTransEntry *entry )
|
||||
{
|
||||
g_StudioRenderer.RenderTransMesh( entry );
|
||||
}
|
||||
|
||||
inline void R_RenderLightForTransMeshes( void )
|
||||
{
|
||||
g_StudioRenderer.RenderDynLightList( false );
|
||||
}
|
||||
|
||||
inline void R_RenderShadowStudioList( void )
|
||||
{
|
||||
g_StudioRenderer.RenderShadowStudioList();
|
||||
}
|
||||
|
||||
inline void R_RenderDebugStudioList( bool bViewModel )
|
||||
{
|
||||
g_StudioRenderer.RenderDebugStudioList( bViewModel );
|
||||
}
|
||||
|
||||
inline void R_AddStudioToDrawList( cl_entity_t *e, bool update = false )
|
||||
{
|
||||
g_StudioRenderer.AddStudioModelToDrawList( e, update );
|
||||
}
|
||||
|
||||
inline void R_StudioClearLightCache( void )
|
||||
{
|
||||
g_StudioRenderer.ClearLightCache();
|
||||
}
|
||||
|
||||
inline void R_StudioAttachmentPosAng( const cl_entity_t *ent, int num, Vector *pos, Vector *ang )
|
||||
{
|
||||
g_StudioRenderer.StudioGetAttachment( ent, num, pos, ang, NULL );
|
||||
}
|
||||
|
||||
inline void R_StudioAttachmentPosDir( const cl_entity_t *ent, int num, Vector *pos, Vector *dir )
|
||||
{
|
||||
g_StudioRenderer.StudioGetAttachment( ent, num, pos, NULL, dir );
|
||||
}
|
||||
|
||||
inline Vector R_StudioAttachmentPos( const cl_entity_t *ent, int num )
|
||||
{
|
||||
Vector pos = g_vecZero;
|
||||
|
||||
g_StudioRenderer.StudioGetAttachment( ent, num, &pos, NULL, NULL );
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
inline Vector R_StudioAttachmentAng( const cl_entity_t *ent, int num )
|
||||
{
|
||||
Vector ang = g_vecZero;
|
||||
|
||||
g_StudioRenderer.StudioGetAttachment( ent, num, NULL, &ang, NULL );
|
||||
|
||||
return ang;
|
||||
}
|
||||
|
||||
inline void R_UpdateLatchedVars( cl_entity_t *e, qboolean reset )
|
||||
{
|
||||
g_StudioRenderer.UpdateLatchedVars( e, reset );
|
||||
}
|
||||
|
||||
#endif// GL_STUDIO_H
|
5448
cl_dll/render/gl_studio.old
Normal file
5448
cl_dll/render/gl_studio.old
Normal file
File diff suppressed because it is too large
Load Diff
3885
cl_dll/render/gl_studio_draw.cpp
Normal file
3885
cl_dll/render/gl_studio_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2164
cl_dll/render/gl_studio_init.cpp
Normal file
2164
cl_dll/render/gl_studio_init.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user