diff --git a/client/client.plg b/client/client.plg
new file mode 100644
index 00000000..33666b63
--- /dev/null
+++ b/client/client.plg
@@ -0,0 +1,16 @@
+
+
+
+Build Log
+
+--------------------Configuration: client - Win32 Debug--------------------
+
+Command Lines
+
+
+
+Results
+client.dll - 0 error(s), 0 warning(s)
+
+
+
diff --git a/client/global/utils.cpp b/client/global/utils.cpp
index de98919d..ff0777ec 100644
--- a/client/global/utils.cpp
+++ b/client/global/utils.cpp
@@ -298,7 +298,7 @@ client_sprite_t *SPR_GetList( const char *psz, int *piCount )
*piCount = iSprCount;
return NULL;
}
-
+
char *token;
const char *plist = pfile;
int depth = 0;
@@ -564,7 +564,7 @@ void V_RenderPlaque( void )
const char *levelshot;
levelshot = CVAR_GET_STRING( "cl_levelshot_name" );
- if( !strcmp( levelshot, "" )) levelshot = "$blackimage";
+ if( !strcmp( levelshot, "" )) levelshot = "*black";
// logo that shows up while upload next level
DrawImageRectangle( SPR_Load( levelshot ));
diff --git a/client/hud/hud.cpp b/client/hud/hud.cpp
index 7b774dc0..86d43ca6 100644
--- a/client/hud/hud.cpp
+++ b/client/hud/hud.cpp
@@ -123,7 +123,7 @@ void CHud :: VidInit( void )
}
else
{
- ALERT( at_warning, "hud.shader couldn't load\n" );
+ ALERT( at_warning, "hud.txt couldn't load\n" );
CVAR_SET_FLOAT( "hud_draw", 0 );
return;
}
@@ -283,7 +283,7 @@ int CHud :: Redraw( float flTime )
if( !m_iIntermission )
{
if(( pList->p->m_iFlags & HUD_ACTIVE ) && !(m_iHideHUDDisplay & HIDEHUD_ALL ))
- pList->p->Draw(flTime);
+ pList->p->Draw( flTime );
}
else
{
diff --git a/client/hud/hud.h b/client/hud/hud.h
index ae04be8f..92fcf73f 100644
--- a/client/hud/hud.h
+++ b/client/hud/hud.h
@@ -591,10 +591,11 @@ private:
// when the hud.txt and associated sprites are loaded. freed in ~CHud()
HSPRITE *m_rghSprites; // the sprites loaded from hud.txt
wrect_t *m_rgrcRects;
+ wrect_t nullRect;
char *m_rgszSpriteNames;
public:
HSPRITE GetSprite( int index ) { return (index < 0) ? 0 : m_rghSprites[index]; }
- wrect_t& GetSpriteRect( int index ) { return m_rgrcRects[index]; }
+ wrect_t& GetSpriteRect( int index ) { return (index < 0) ? nullRect : m_rgrcRects[index]; }
int InitMessages( void ); // init hud messages
int GetSpriteIndex( const char *SpriteName );
diff --git a/engine/client/cl_effects.c b/engine/client/cl_effects.c
index 4c4eb7be..3c5cd547 100644
--- a/engine/client/cl_effects.c
+++ b/engine/client/cl_effects.c
@@ -226,7 +226,7 @@ void CL_AddDLights( void )
dl = cl_dlights;
for( i = 0; i < MAX_DLIGHTS; i++, dl++ )
{
- if( dl->radius ) re->AddDynLight( dl->origin, dl->color, dl->radius );
+ if( dl->radius ) re->AddDynLight( dl->origin, dl->color, dl->radius, -1 );
}
}
@@ -917,7 +917,7 @@ void CL_TestEntities( void )
================
CL_TestLights
-If cl_testlights is set, create 32 lights models
+if cl_testlights is set, create 32 lights models
================
*/
void CL_TestLights( void )
@@ -944,7 +944,7 @@ void CL_TestLights( void )
dl.color[2] = (((i%6)+1) & 4)>>2;
dl.radius = 200;
- if( !re->AddDynLight( dl.origin, dl.color, dl.radius ))
+ if( !re->AddDynLight( dl.origin, dl.color, dl.radius, -1 ))
break;
}
}
diff --git a/engine/common/menu.c b/engine/common/menu.c
index 8ac02ba6..b141ac8c 100644
--- a/engine/common/menu.c
+++ b/engine/common/menu.c
@@ -557,6 +557,7 @@ void PF_loadcredits( void )
if(!creditsBuffer)
{
+Msg( "load credits\n" );
// load credits if needed
creditsBuffer = FS_LoadFile( s, &count );
if( count )
diff --git a/engine/engine.plg b/engine/engine.plg
new file mode 100644
index 00000000..45d2c2f7
--- /dev/null
+++ b/engine/engine.plg
@@ -0,0 +1,16 @@
+
+
+
+Build Log
+
+--------------------Configuration: engine - Win32 Debug--------------------
+
+Command Lines
+
+
+
+Results
+engine.dll - 0 error(s), 0 warning(s)
+
+
+
diff --git a/engine/server/server.h b/engine/server/server.h
index 051d60d1..05f0792d 100644
--- a/engine/server/server.h
+++ b/engine/server/server.h
@@ -245,6 +245,7 @@ typedef struct
{
bool initialized; // sv_init has completed
double realtime; // always increasing, no clamping, etc
+ double timestart; // just for profiling
char mapname[CS_SIZE]; // current mapname
char comment[CS_SIZE]; // map name, e.t.c.
diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c
index b0a8916c..881e6bb3 100644
--- a/engine/server/sv_client.c
+++ b/engine/server/sv_client.c
@@ -513,6 +513,8 @@ void SV_PutClientInServer( edict_t *ent )
SV_LinkEdict( ent ); // m_pmatrix calculated here, so we need call this before pe->CreatePlayer
ent->pvServerData->physbody = pe->CreatePlayer( ent, SV_GetModelPtr( ent ), ent->v.origin, ent->v.m_pmatrix );
Mem_EmptyPool( svgame.temppool ); // all tempstrings can be freed now
+
+ MsgDev( D_INFO, "level loaded at %g sec\n", Sys_DoubleTime() - svs.timestart );
}
/*
@@ -739,10 +741,11 @@ void SV_BeginDownload_f( sv_client_t *cl )
if( !allow_download->integer || !cl->download )
{
MsgDev( D_ERROR, "SV_BeginDownload_f: couldn't download %s to %s\n", name, cl->name );
- if( cl->download ) cl->download = NULL;
+ if( cl->download ) Mem_Free( cl->download );
MSG_WriteByte( &cl->netchan.message, svc_download );
MSG_WriteShort( &cl->netchan.message, -1 );
MSG_WriteByte( &cl->netchan.message, 0 );
+ cl->download = NULL;
return;
}
diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c
index 45c7ac6c..217d857e 100644
--- a/engine/server/sv_init.c
+++ b/engine/server/sv_init.c
@@ -160,6 +160,7 @@ void SV_SpawnServer( const char *server, const char *savename )
Msg( "SpawnServer [%s]\n", server );
+ svs.timestart = Sys_DoubleTime ();
svs.spawncount++; // any partially connected client will be restarted
sv.state = ss_dead;
Host_SetServerState( sv.state );
diff --git a/launch/imagelib/imagelib.h b/launch/imagelib/imagelib.h
index dec2d930..229735f9 100644
--- a/launch/imagelib/imagelib.h
+++ b/launch/imagelib/imagelib.h
@@ -64,9 +64,9 @@ typedef struct imglib_s
const saveformat_t *saveformats;
// current 2d image state
- int width;
- int height;
- byte depth; // num layers in
+ word width;
+ word height;
+ word depth; // num layers in
byte num_mips; // build mipmaps
uint type; // main type switcher
uint flags; // additional image flags
@@ -499,7 +499,7 @@ extern const bpc_desc_t PFDesc[];
void Image_RoundDimensions( int *scaled_width, int *scaled_height );
byte *Image_ResampleInternal( const void *indata, int inwidth, int inheight, int outwidth, int outheight, int intype );
-byte *Image_FlipInternal( const byte *in, int *srcwidth, int *srcheight, int type, int flags );
+byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int type, int flags );
void Image_FreeImage( rgbdata_t *pack );
void Image_Save( const char *filename, rgbdata_t *pix );
size_t Image_DXTGetLinearSize( int type, int width, int height, int depth, int rgbcount );
diff --git a/launch/imagelib/img_bmp.c b/launch/imagelib/img_bmp.c
index 70953e31..755d73b8 100644
--- a/launch/imagelib/img_bmp.c
+++ b/launch/imagelib/img_bmp.c
@@ -43,7 +43,7 @@ bool Image_LoadBMP( const char *name, const byte *buffer, size_t filesize )
// bogus file header check
if( bhdr.reserved0 != 0 ) return false;
- if( memcmp(bhdr.id, "BM", 2 ))
+ if( memcmp( bhdr.id, "BM", 2 ))
{
MsgDev( D_ERROR, "Image_LoadBMP: only Windows-style BMP files supported (%s)\n", name );
return false;
diff --git a/launch/imagelib/img_dds.c b/launch/imagelib/img_dds.c
index a14fd681..18aeaa9a 100644
--- a/launch/imagelib/img_dds.c
+++ b/launch/imagelib/img_dds.c
@@ -1447,7 +1447,7 @@ void Image_SetPixelFormat( int width, int height, int depth )
image.SizeOfPlane = image.bps * image.curheight;
image.SizeOfData = image.SizeOfPlane * image.curdepth;
- // NOTE: size of current miplevel or cubemap side, not total (filesize - sizeof(header))
+ // NOTE: size of current miplevel or cubemap side, not total (filesize - sizeof( header ))
image.SizeOfFile = Image_DXTGetLinearSize( image.type, width, height, depth, image.bits_count / 8 );
}
@@ -2224,12 +2224,13 @@ bool Image_DecompressRGBA( uint target, int level, int intformat, uint width, ui
switch( PFDesc[intformat].format )
{
case PF_RGB_16:
- for( i = 0, col = (color16 *)fin; i < width * height; i++, col += sizeof( color16 ))
+ for( i = 0, col = (color16 *)fin; i < width * height; i++ )
{
fout[(i<<2)+0] = col->r << 3;
fout[(i<<2)+1] = col->g << 2;
fout[(i<<2)+2] = col->b << 3;
fout[(i<<2)+3] = 255;
+ col += sizeof( color16 );
}
break;
case PF_RGB_24:
@@ -2273,13 +2274,14 @@ bool Image_DecompressRGBA( uint target, int level, int intformat, uint width, ui
void Image_DecompressDDS( const byte *buffer, uint target )
{
- int i, size = 0;
- int w = image.curwidth;
- int h = image.curheight;
- int d = image.curdepth;
+ int i, size = 0;
+ int w = image.curwidth;
+ int h = image.curheight;
+ int d = image.curdepth;
// filter by cubemap side
- if( image.filter != CB_HINT_NO && image.filter != target ) return;
+ if( image.filter != CB_HINT_NO && image.filter != target )
+ return;
switch( image.type )
{
@@ -2315,7 +2317,7 @@ void Image_DecompressDDS( const byte *buffer, uint target )
default: Sys_Error( "Image_DecompressDDS: unknown image format\n" );
}
- for( i = 0; i < image.cur_mips; i++, buffer += size )
+ for( i = 0; i < image.cur_mips; i++ )
{
Image_SetPixelFormat( w, h, d );
size = image.SizeOfFile;
@@ -2323,6 +2325,7 @@ void Image_DecompressDDS( const byte *buffer, uint target )
if(!image.decompress( target, i, image.type, w, h, size, buffer ))
break; // there were errors
w = (w+1)>>1, h = (h+1)>>1, d = (d+1)>>1; // calc size of next mip
+ buffer += size;
}
}
@@ -2351,7 +2354,6 @@ bool Image_ForceDecompress( void )
case PF_ATI1N: return true; // hey, how called your OpenGL extension, ATI ?
case PF_ATI2N: return true;
}
-
return false;
}
diff --git a/launch/imagelib/img_jpg.c b/launch/imagelib/img_jpg.c
index 4e3ae0cd..34d2d75b 100644
--- a/launch/imagelib/img_jpg.c
+++ b/launch/imagelib/img_jpg.c
@@ -310,7 +310,7 @@ int jpeg_readmarkers( void )
void jpeg_decompress( void )
{
- // decompress jpeg file (Baseline algorithm)
+ // decompress jpeg file (baseline algorithm)
register int x, y, i, j, k, l, c;
int X, Y, H, V, plane, scaleh[3], scalev[3];
static float vector[64], dct[64];
diff --git a/launch/imagelib/img_main.c b/launch/imagelib/img_main.c
index 09839d44..075a6f80 100644
--- a/launch/imagelib/img_main.c
+++ b/launch/imagelib/img_main.c
@@ -125,7 +125,7 @@ void Image_Reset( void )
rgbdata_t *ImagePack( void )
{
- rgbdata_t *pack = Mem_Alloc( Sys.imagepool, sizeof(rgbdata_t));
+ rgbdata_t *pack = Mem_Alloc( Sys.imagepool, sizeof( rgbdata_t ));
if( image.cubemap && image.num_sides != 6 )
{
@@ -158,6 +158,7 @@ rgbdata_t *ImagePack( void )
pack->bitsCount = image.bits_count;
pack->flags = image.flags;
pack->palette = image.palette;
+
return pack;
}
@@ -355,7 +356,10 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size )
{
com.snprintf( sidename, MAX_STRING, "%s%s.%s", loadname, cmap->type[i].suf, format->ext );
if( FS_AddSideToPack( sidename, cmap->type[i].flags )) // process flags to flip some sides
+ {
+ Mem_Free( f );
break; // loaded
+ }
}
Mem_Free( f );
}
diff --git a/launch/imagelib/img_pcx.c b/launch/imagelib/img_pcx.c
index 70ceed03..dcdccd24 100644
--- a/launch/imagelib/img_pcx.c
+++ b/launch/imagelib/img_pcx.c
@@ -62,12 +62,12 @@ bool Image_LoadPCX( const char *name, const byte *buffer, size_t filesize )
for (x = 0; x < image.width && fin < enddata;)
{
dataByte = *fin++;
- if(dataByte >= 0xC0)
+ if( dataByte >= 0xC0 )
{
- if (fin >= enddata) break;
+ if( fin >= enddata ) break;
x2 = x + (dataByte & 0x3F);
dataByte = *fin++;
- if (x2 > image.width) x2 = image.width; // technically an error
+ if( x2 > image.width ) x2 = image.width; // technically an error
while(x < x2) pix[x++] = dataByte;
}
else pix[x++] = dataByte;
diff --git a/launch/imagelib/img_tga.c b/launch/imagelib/img_tga.c
index 4b26475a..ab7e3322 100644
--- a/launch/imagelib/img_tga.c
+++ b/launch/imagelib/img_tga.c
@@ -12,31 +12,31 @@ Image_LoadTGA
*/
bool Image_LoadTGA( const char *name, const byte *buffer, size_t filesize )
{
- int x, y, pix_inc, row_inc;
- int red, green, blue, alpha;
- int runlen, alphabits;
- byte *p, *pixbuf;
- const byte *fin, *enddata;
- byte palette[256*4];
+ int i, columns, rows, row_inc, row, col;
+ byte *buf_p, *pixbuf, *targa_rgba;
+ byte palette[256][4], red = 0, green = 0, blue = 0, alpha = 0;
+ int readpixelcount, pixelcount;
+ bool compressed;
tga_t targa_header;
if( filesize < sizeof( tga_t ))
return false;
- fin = buffer;
- enddata = fin + filesize;
+ buf_p = (byte *)buffer;
+ targa_header.id_length = *buf_p++;
+ targa_header.colormap_type = *buf_p++;
+ targa_header.image_type = *buf_p++;
- targa_header.id_length = *fin++;
- targa_header.colormap_type = *fin++;
- targa_header.image_type = *fin++;
-
- targa_header.colormap_index = BuffLittleShort( fin ); fin += 2;
- targa_header.colormap_length = BuffLittleShort( fin ); fin += 2;
- targa_header.colormap_size = *fin++;
- targa_header.x_origin = BuffLittleShort( fin ); fin += 2;
- targa_header.y_origin = BuffLittleShort( fin ); fin += 2;
- targa_header.width = image.width = BuffLittleShort( fin ); fin += 2;
- targa_header.height = image.height = BuffLittleShort( fin );fin += 2;
+ targa_header.colormap_index = buf_p[0] + buf_p[1] * 256; buf_p += 2;
+ targa_header.colormap_length = buf_p[0] + buf_p[1] * 256; buf_p += 2;
+ targa_header.colormap_size = *buf_p; buf_p += 1;
+ targa_header.x_origin = LittleShort( *((short *)buf_p )); buf_p += 2;
+ targa_header.y_origin = LittleShort( *((short *)buf_p )); buf_p += 2;
+ targa_header.width = image.width = LittleShort(*((short *)buf_p)); buf_p += 2;
+ targa_header.height = image.height = LittleShort(*((short *)buf_p)); buf_p += 2;
+ targa_header.pixel_size = *buf_p++;
+ targa_header.attributes = *buf_p++;
+ if( targa_header.id_length != 0 ) buf_p += targa_header.id_length; // skip TARGA image comment
// check for tga file
if(!Image_ValidSize( name )) return false;
@@ -45,328 +45,155 @@ bool Image_LoadTGA( const char *name, const byte *buffer, size_t filesize )
image.num_mips = 1;
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
- targa_header.pixel_size = *fin++;
- targa_header.attributes = *fin++;
- // end of header
-
- // skip TARGA image comment ( usually 0 bytes )
- fin += targa_header.id_length;
-
- // read/skip the colormap if present (note: according to the TARGA spec it
- // can be present even on truecolor or greyscale images, just not used by
- // the image data)
- if( targa_header.colormap_type )
+ if( targa_header.image_type == 1 || targa_header.image_type == 9 )
{
- if( targa_header.colormap_length > 256 )
+ // uncompressed colormapped image
+ if( targa_header.pixel_size != 8 )
{
- MsgDev( D_ERROR, "Image_LoadTGA: only up to 256 colormap_length supported\n" );
+ MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 8 bit images supported for type 1 and 9\n", name );
+ return false;
+ }
+ if( targa_header.colormap_length != 256 )
+ {
+ MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 8 bit colormaps are supported for type 1 and 9\n", name );
return false;
}
if( targa_header.colormap_index )
{
- MsgDev( D_ERROR, "Image_LoadTGA: colormap_index not supported\n" );
+ MsgDev( D_WARN, "Image_LoadTGA: (%s) colormap_index is not supported for type 1 and 9\n", name );
return false;
}
if( targa_header.colormap_size == 24 )
{
- for( x = 0; x < targa_header.colormap_length; x++ )
+ for( i = 0; i < targa_header.colormap_length; i++ )
{
- palette[x*4+2] = *fin++;
- palette[x*4+1] = *fin++;
- palette[x*4+0] = *fin++;
- palette[x*4+3] = 255;
+ palette[i][2] = *buf_p++;
+ palette[i][1] = *buf_p++;
+ palette[i][0] = *buf_p++;
+ palette[i][3] = 255;
}
}
else if( targa_header.colormap_size == 32 )
{
- for( x = 0; x < targa_header.colormap_length; x++ )
+ for( i = 0; i < targa_header.colormap_length; i++ )
{
- palette[x*4+2] = *fin++;
- palette[x*4+1] = *fin++;
- palette[x*4+0] = *fin++;
- palette[x*4+3] = *fin++;
+ palette[i][2] = *buf_p++;
+ palette[i][1] = *buf_p++;
+ palette[i][0] = *buf_p++;
+ palette[i][3] = *buf_p++;
}
}
else
{
- Msg("Image_LoadTGA: Only 32 and 24 bit colormap_size supported\n");
+ MsgDev( D_WARN, "Image_LoadTGA: (%s) only 24 and 32 bit colormaps are supported for type 1 and 9\n", name );
return false;
}
}
-
- // check our pixel_size restrictions according to image_type
- switch (targa_header.image_type & ~8)
+ else if( targa_header.image_type == 2 || targa_header.image_type == 10 )
{
- case 2:
- if( targa_header.pixel_size != 24 && targa_header.pixel_size != 32 )
+ // uncompressed or RLE compressed RGB
+ if( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 )
{
- MsgDev(D_ERROR, "LoadTGA: (%s) have unsupported pixel size '%d', for type '%d'\n", name, targa_header.pixel_size, targa_header.image_type );
+ MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 32 or 24 bit images supported for type 2 and 10\n", name );
return false;
}
- break;
- case 3:
- // set up a palette to make the loader easier
- for( x = 0; x < 256; x++ )
- {
- palette[x*4+2] = x;
- palette[x*4+1] = x;
- palette[x*4+0] = x;
- palette[x*4+3] = 255;
- }
- // fall through to colormap case
- case 1:
+ }
+ else if( targa_header.image_type == 3 || targa_header.image_type == 11 )
+ {
+ // uncompressed greyscale
if( targa_header.pixel_size != 8 )
{
- MsgDev( D_ERROR, "Image_LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n" );
+ MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 8 bit images supported for type 3 and 11\n", name );
return false;
}
- break;
- default:
- MsgDev(D_ERROR, "Image_LoadTGA: (%s) is unsupported image type '%i'\n", name, targa_header.image_type );
- return false;
}
- if( targa_header.attributes & 0x10 )
- {
- MsgDev( D_WARN, "Image_LoadTGA: (%s): top right and bottom right origin are not supported\n", name );
- return false;
- }
+ columns = targa_header.width;
+ rows = targa_header.height;
- // number of attribute bits per pixel, we only support 0 or 8
- alphabits = targa_header.attributes & 0x0F;
- if( alphabits != 8 && alphabits != 0 )
- {
- MsgDev( D_WARN, "LoadTGA: (%s) have invalid attributes '%i'\n", name, alphabits );
- return false;
- }
-
- image.flags |= alphabits ? IMAGE_HAS_ALPHA : 0;
image.size = image.width * image.height * 4;
- image.rgba = Mem_Alloc( Sys.imagepool, image.size );
+ targa_rgba = image.rgba = Mem_Alloc( Sys.imagepool, image.size );
- // If bit 5 of attributes isn't set, the image has been stored from bottom to top
- if(!(targa_header.attributes & 0x20))
+ // if bit 5 of attributes isn't set, the image has been stored from bottom to top
+ if( targa_header.attributes & 0x20 )
{
- pixbuf = image.rgba + (image.height - 1) * image.width * 4;
- row_inc = -image.width * 4 * 2;
+ pixbuf = targa_rgba;
+ row_inc = 0;
}
else
{
- pixbuf = image.rgba;
- row_inc = 0;
+ pixbuf = targa_rgba + ( rows - 1 ) * columns * 4;
+ row_inc = -columns * 4 * 2;
}
- x = y = 0;
- red = green = blue = alpha = 255;
- pix_inc = 1;
- if((targa_header.image_type & ~8) == 2) pix_inc = targa_header.pixel_size / 8;
-
- switch( targa_header.image_type )
+ compressed = ( targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11 );
+ for( row = col = 0; row < rows; )
{
- case 1: // colormapped, uncompressed
- case 3: // greyscale, uncompressed
- if( fin + image.width * image.height * pix_inc > enddata )
- break;
- for( y = 0; y < image.height; y++, pixbuf += row_inc )
- {
- for( x = 0; x < image.width; x++ )
- {
- p = palette + *fin++ * 4;
- *pixbuf++ = p[0];
- *pixbuf++ = p[1];
- *pixbuf++ = p[2];
- *pixbuf++ = p[3];
- }
- }
- break;
- case 2:
- // BGR or BGRA, uncompressed
- if( fin + image.width * image.height * pix_inc > enddata )
- break;
- if( targa_header.pixel_size == 32 && alphabits )
- {
- for( y = 0;y < image.height;y++, pixbuf += row_inc )
- {
- for( x = 0;x < image.width;x++, fin += pix_inc )
- {
- *pixbuf++ = fin[2];
- *pixbuf++ = fin[1];
- *pixbuf++ = fin[0];
- *pixbuf++ = fin[3];
+ pixelcount = 0x10000;
+ readpixelcount = 0x10000;
- if( fin[2] != fin[1] || fin[1] != fin[0] )
- image.flags |= IMAGE_HAS_COLOR;
- }
- }
- }
- else // 24 bits
+ if( compressed )
{
- for( y = 0; y < image.height; y++, pixbuf += row_inc )
- {
- for( x = 0;x < image.width; x++, fin += pix_inc )
- {
- *pixbuf++ = fin[2];
- *pixbuf++ = fin[1];
- *pixbuf++ = fin[0];
- *pixbuf++ = 255;
-
- if( fin[2] != fin[1] || fin[1] != fin[0] )
- image.flags |= IMAGE_HAS_COLOR;
- }
- }
+ pixelcount = *buf_p++;
+ if( pixelcount & 0x80 ) // run-length packet
+ readpixelcount = 1;
+ pixelcount = 1 + ( pixelcount & 0x7f );
}
- break;
- case 9: // colormapped, RLE
- case 11: // greyscale, RLE
- for( y = 0; y < image.height; y++, pixbuf += row_inc )
+
+ while( pixelcount-- && ( row < rows ) )
{
- for( x = 0; x < image.width; )
+ if( readpixelcount-- > 0 )
{
- if( fin >= enddata ) break; // error - truncated file
- runlen = *fin++;
- if( runlen & 0x80 )
+ switch( targa_header.image_type )
{
- // RLE - all pixels the same color
- runlen += 1 - 0x80;
- if( fin + pix_inc > enddata )
- break; // error - truncated file
- if( x + runlen > image.width )
- break; // error - line exceeds width
- p = palette + *fin++ * 4;
- red = p[0];
- green = p[1];
- blue = p[2];
- alpha = p[3];
- for( ; runlen--; x++ )
+ case 1:
+ case 9:
+ // colormapped image
+ blue = *buf_p++;
+ red = palette[blue][0];
+ green = palette[blue][1];
+ alpha = palette[blue][3];
+ blue = palette[blue][2];
+ if( alpha != 255 ) image.flags |= IMAGE_HAS_ALPHA;
+ break;
+ case 2:
+ case 10:
+ // 24 or 32 bit image
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alpha = 255;
+ if( targa_header.pixel_size == 32 )
{
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alpha;
- }
- }
- else
- {
- // uncompressed - all pixels different color
- runlen++;
- if( fin + pix_inc * runlen > enddata )
- break; // error - truncated file
- if( x + runlen > image.width )
- break; // error - line exceeds width
- for( ; runlen--; x++ )
- {
- p = palette + *fin++ * 4;
- *pixbuf++ = p[0];
- *pixbuf++ = p[1];
- *pixbuf++ = p[2];
- *pixbuf++ = p[3];
-
- if( p[0] != p[1] || p[1] != p[2] )
- image.flags |= IMAGE_HAS_COLOR;
+ alpha = *buf_p++;
+ if( alpha != 255 )
+ image.flags |= IMAGE_HAS_ALPHA;
}
+ break;
+ case 3:
+ case 11:
+ // greyscale image
+ blue = green = red = *buf_p++;
+ alpha = 255;
+ break;
}
}
- }
- break;
- case 10:
- // BGR or BGRA, RLE
- if( targa_header.pixel_size == 32 && alphabits )
- {
- for( y = 0; y < image.height; y++, pixbuf += row_inc )
- {
- for (x = 0; x < image.width; )
- {
- if( fin >= enddata ) break; // error - truncated file
- runlen = *fin++;
- if( runlen & 0x80 )
- {
- // RLE - all pixels the same color
- runlen += 1 - 0x80;
- if( fin + pix_inc > enddata ) break; // error - truncated file
- if( x + runlen > image.width) break; // error - line exceeds width
- red = fin[2];
- green = fin[1];
- blue = fin[0];
- alpha = fin[3];
- fin += pix_inc;
- for( ; runlen--; x++)
- {
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alpha;
- }
- }
- else
- {
- // uncompressed - all pixels different color
- runlen++;
- if( fin + pix_inc * runlen > enddata ) break; // error - truncated file
- if( x + runlen > image.width ) break; // error - line exceeds width
- for( ;runlen--; x++, fin += pix_inc )
- {
- *pixbuf++ = fin[2];
- *pixbuf++ = fin[1];
- *pixbuf++ = fin[0];
- *pixbuf++ = fin[3];
- if( fin[2] != fin[1] || fin[1] != fin[0] )
- image.flags |= IMAGE_HAS_COLOR;
- }
- }
- }
+ if( red != green || green != blue )
+ image.flags |= IMAGE_HAS_COLOR;
+
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = alpha;
+ if( ++col == columns )
+ {
+ // run spans across rows
+ row++;
+ col = 0;
+ pixbuf += row_inc;
}
}
- else
- {
- for( y = 0; y < image.height; y++, pixbuf += row_inc )
- {
- for (x = 0; x < image.width; )
- {
- if( fin >= enddata ) break; // error - truncated file
- runlen = *fin++;
- if( runlen & 0x80 )
- {
- // RLE - all pixels the same color
- runlen += 1 - 0x80;
- if( fin + pix_inc > enddata ) break; // error - truncated file
- if( x + runlen > image.width )break; // error - line exceeds width
- red = fin[2];
- green = fin[1];
- blue = fin[0];
- alpha = 255;
- fin += pix_inc;
- for( ;runlen--; x++ )
- {
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alpha;
- }
- }
- else
- {
- // uncompressed - all pixels different color
- runlen++;
- if( fin + pix_inc * runlen > enddata ) break; // error - truncated file
- if( x + runlen > image.width ) break; // error - line exceeds width
- for ( ; runlen--; x++, fin += pix_inc)
- {
- *pixbuf++ = fin[2];
- *pixbuf++ = fin[1];
- *pixbuf++ = fin[0];
- *pixbuf++ = 255;
-
- if( fin[2] != fin[1] || fin[1] != fin[0] )
- image.flags |= IMAGE_HAS_COLOR;
- }
- }
- }
- }
- }
- break;
- // unknown image_type
- default: return false;
}
return true;
}
diff --git a/launch/imagelib/img_utils.c b/launch/imagelib/img_utils.c
index 1f2829cc..866667b9 100644
--- a/launch/imagelib/img_utils.c
+++ b/launch/imagelib/img_utils.c
@@ -615,12 +615,12 @@ bool Image_Copy8bitRGBA( const byte *in, byte *out, int pixels )
if( !image.d_currentpal )
{
- MsgDev(D_ERROR,"Image_Copy8bitRGBA: no palette set\n");
+ MsgDev( D_ERROR, "Image_Copy8bitRGBA: no palette set\n" );
return false;
}
if( !in )
{
- MsgDev(D_ERROR,"Image_Copy8bitRGBA: no input image\n");
+ MsgDev( D_ERROR, "Image_Copy8bitRGBA: no input image\n" );
return false;
}
@@ -1181,11 +1181,11 @@ byte *Image_FloodInternal( const byte *indata, int inwidth, int inheight, int ou
Image_Flip
================
*/
-byte *Image_FlipInternal( const byte *in, int *srcwidth, int *srcheight, int type, int flags )
+byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int type, int flags )
{
int i, x, y;
- int width = *srcwidth;
- int height = *srcheight;
+ word width = *srcwidth;
+ word height = *srcheight;
int samples = PFDesc[type].bpp;
bool flip_x = ( flags & IMAGE_FLIP_X ) ? true : false;
bool flip_y = ( flags & IMAGE_FLIP_Y ) ? true : false;
@@ -1290,6 +1290,7 @@ rgbdata_t *Image_DecompressInternal( rgbdata_t *pic )
case PF_RGBA_GN:
case PF_RGBA_32:
case PF_ABGR_128F:
+ pic->type = PF_RGBA_32;
return pic; // just change type
}
@@ -1303,15 +1304,17 @@ rgbdata_t *Image_DecompressInternal( rgbdata_t *pic )
image.num_mips = 0; // clear mipcount
buf = image.rgba;
- for( i = 0, offset = 0; i < numsides; i++, buf += offset )
+ for( i = 0, offset = 0; i < numsides; i++ )
{
Image_SetPixelFormat( image.curwidth, image.curheight, image.curdepth );
offset = image.SizeOfFile; // move pointer
Image_DecompressDDS( buf, target + i );
+ buf += offset;
}
// now we can change type to RGBA
- if( image.filter != CB_HINT_NO ) image.flags &= ~IMAGE_CUBEMAP; // side extracted
+ if( image.filter != CB_HINT_NO )
+ image.flags &= ~IMAGE_CUBEMAP; // side extracted
image.type = PF_RGBA_32;
FS_FreeImage( pic ); // free original
diff --git a/launch/imagelib/img_vtf.c b/launch/imagelib/img_vtf.c
index 838805f2..5edbcb71 100644
--- a/launch/imagelib/img_vtf.c
+++ b/launch/imagelib/img_vtf.c
@@ -111,7 +111,7 @@ size_t Image_VTFCalcMipmapSize( vtf_t *hdr, int mipNum )
================
Image_VTFCalcImageSize
-main image size not included header or lowres
+main image size without header and lowres
================
*/
size_t Image_VTFCalcImageSize( vtf_t *hdr, bool oldformat )
@@ -201,7 +201,7 @@ void Image_VTFSwapBuffer( vtf_t *hdr, const byte *input, size_t input_size, bool
Mem_Copy((byte *)input, image.tempbuffer, out_size );
if( ignore_mips ) image.num_mips = 1;
if( texture ) Mem_Free( texture );
- image.size = out_size; // merge out size
+ image.size = out_size; // merge out size (minus envmap or identical)
}
/*
@@ -235,7 +235,8 @@ bool Image_LoadVTF( const char *name, const byte *buffer, size_t filesize )
}
i = LittleLong( vtf.ver_minor );
- if( i == VTF_SUBVERSION0 && vtf.hdr_size == 64 ) oldformat = true; // 7.0 hasn't envmap for cubemap images
+ if( i == VTF_SUBVERSION0 && vtf.hdr_size == 64 )
+ oldformat = true; // 7.0 hasn't envmap for cubemap images
// all other subversions are valid
image.width = LittleShort( vtf.width );
diff --git a/launch/imagelib/img_wad.c b/launch/imagelib/img_wad.c
index e9f0f19f..7832d461 100644
--- a/launch/imagelib/img_wad.c
+++ b/launch/imagelib/img_wad.c
@@ -154,12 +154,12 @@ bool Image_LoadWAL( const char *name, const byte *buffer, size_t filesize )
int i, flags, value, contents; // wal additional parms
const byte *fin;
- if( filesize < (int)sizeof(wal))
+ if( filesize < (int)sizeof( wal ))
{
MsgDev( D_ERROR, "Image_LoadWAL: file (%s) have invalid size\n", name );
return false;
}
- Mem_Copy( &wal, buffer, sizeof(wal));
+ Mem_Copy( &wal, buffer, sizeof( wal ));
flags = LittleLong(wal.flags);
value = LittleLong(wal.value);
@@ -215,7 +215,7 @@ bool Image_LoadFLT( const char *name, const byte *buffer, size_t filesize )
if( Sys.app_name == HOST_NORMAL && !fs_wadsupport->integer )
return false;
- if(filesize < (int)sizeof(flat))
+ if(filesize < (int)sizeof( flat ))
{
MsgDev( D_ERROR, "Image_LoadFLAT: file (%s) have invalid size\n", name );
return false;
@@ -322,7 +322,7 @@ bool Image_LoadLMP( const char *name, const byte *buffer, size_t filesize )
else
{
fin = (byte *)buffer;
- Mem_Copy(&lmp, fin, sizeof(lmp));
+ Mem_Copy( &lmp, fin, sizeof( lmp ));
image.width = LittleLong( lmp.width );
image.height = LittleLong( lmp.height );
rendermode = LUMP_NORMAL;
@@ -379,11 +379,11 @@ bool Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
return false;
}
- Mem_Copy( &mip, buffer, sizeof(mip));
- image.width = LittleLong(mip.width);
- image.height = LittleLong(mip.height);
+ Mem_Copy( &mip, buffer, sizeof( mip ));
+ image.width = LittleLong( mip.width );
+ image.height = LittleLong( mip.height );
if(!Image_ValidSize( name )) return false;
- for(i = 0; i < 4; i++) ofs[i] = LittleLong(mip.offsets[i]);
+ for( i = 0; i < 4; i++ ) ofs[i] = LittleLong( mip.offsets[i] );
pixels = image.width * image.height;
image.depth = 1;
diff --git a/launch/launch.plg b/launch/launch.plg
new file mode 100644
index 00000000..67644887
--- /dev/null
+++ b/launch/launch.plg
@@ -0,0 +1,64 @@
+
+
+
+Build Log
+
+--------------------Configuration: launch - Win32 Release--------------------
+
+Command Lines
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC7.tmp" with contents
+[
+/nologo /MD /W3 /GX /O2 /I "./" /I "imagelib" /I "../public" /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"..\temp\launch\!release/" /Fd"..\temp\launch\!release/" /FD /c
+"D:\Xash3D\src_main\launch\memlib.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC7.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC8.tmp" with contents
+[
+zlib.lib png.lib user32.lib gdi32.lib advapi32.lib winmm.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /out:"..\temp\launch\!release/launch.dll" /implib:"..\temp\launch\!release/launch.lib" /libpath:"./imagelib" /opt:nowin98
+"\Xash3D\src_main\temp\launch\!release\cmd.obj"
+"\Xash3D\src_main\temp\launch\!release\console.obj"
+"\Xash3D\src_main\temp\launch\!release\cpuinfo.obj"
+"\Xash3D\src_main\temp\launch\!release\crclib.obj"
+"\Xash3D\src_main\temp\launch\!release\cvar.obj"
+"\Xash3D\src_main\temp\launch\!release\export.obj"
+"\Xash3D\src_main\temp\launch\!release\filesystem.obj"
+"\Xash3D\src_main\temp\launch\!release\img_bmp.obj"
+"\Xash3D\src_main\temp\launch\!release\img_dds.obj"
+"\Xash3D\src_main\temp\launch\!release\img_jpg.obj"
+"\Xash3D\src_main\temp\launch\!release\img_main.obj"
+"\Xash3D\src_main\temp\launch\!release\img_pcx.obj"
+"\Xash3D\src_main\temp\launch\!release\img_png.obj"
+"\Xash3D\src_main\temp\launch\!release\img_tga.obj"
+"\Xash3D\src_main\temp\launch\!release\img_utils.obj"
+"\Xash3D\src_main\temp\launch\!release\img_vtf.obj"
+"\Xash3D\src_main\temp\launch\!release\img_wad.obj"
+"\Xash3D\src_main\temp\launch\!release\memlib.obj"
+"\Xash3D\src_main\temp\launch\!release\network.obj"
+"\Xash3D\src_main\temp\launch\!release\parselib.obj"
+"\Xash3D\src_main\temp\launch\!release\patch.obj"
+"\Xash3D\src_main\temp\launch\!release\stdlib.obj"
+"\Xash3D\src_main\temp\launch\!release\system.obj"
+"\Xash3D\src_main\temp\launch\!release\utils.obj"
+]
+Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC8.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC9.bat" with contents
+[
+@echo off
+copy \Xash3D\src_main\temp\launch\!release\launch.dll "D:\Xash3D\bin\launch.dll"
+]
+Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC9.bat"
+Compiling...
+memlib.c
+Linking...
+ Creating library ..\temp\launch\!release/launch.lib and object ..\temp\launch\!release/launch.exp
+Output Window
+Performing Custom Build Step on \Xash3D\src_main\temp\launch\!release\launch.dll
+‘Є®ЇЁа®ў ® д ©«®ў: 1.
+
+
+
+Results
+launch.dll - 0 error(s), 0 warning(s)
+
+
+
diff --git a/launch/memlib.c b/launch/memlib.c
index 937535e4..d349998e 100644
--- a/launch/memlib.c
+++ b/launch/memlib.c
@@ -1408,9 +1408,10 @@ void _mem_printlist( size_t minallocationsize )
Mem_Check();
Msg("memory pool list:\n"" ^3size name\n");
- for (pool = poolchain; pool; pool = pool->next)
+ for( pool = poolchain; pool; pool = pool->next )
{
- Msg("%5luk (%5luk actual) %s (%+3li byte change)\n", (dword) ((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name, (long)pool->totalsize - pool->lastchecksize );
+ // poolnames can contain color symbols, make sure what color is reset
+ Msg( "%5luk (%5luk actual) %s (^7%+3li byte change)\n", (dword) ((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name, (long)pool->totalsize - pool->lastchecksize );
pool->lastchecksize = pool->totalsize;
for( mem = pool->chain; mem; mem = mem->next )
if( mem->size >= minallocationsize )
diff --git a/physic/cm_model.c b/physic/cm_model.c
index 98ff44d6..43d3523f 100644
--- a/physic/cm_model.c
+++ b/physic/cm_model.c
@@ -467,10 +467,16 @@ void BSP_LoadPlanes( lump_t *l )
for( i = 0; i < count; i++, in++, out++ )
{
- for( j = 0; j < 3; j++ )
- out->normal[j] = LittleFloat(in->normal[j]);
+ out->signbits = 0;
+ out->type = PLANE_NONAXIAL;
+
+ for( j = 0; j < 3; j++ )
+ {
+ out->normal[j] = LittleFloat( in->normal[j] );
+ if( out->normal[j] < 0.0f ) out->signbits |= (1<normal[j] == 1.0f ) out->type = j;
+ }
out->dist = LittleFloat( in->dist );
- PlaneClassify( out ); // automatic plane classify
}
}
diff --git a/public/engine_api.h b/public/engine_api.h
index 7f42e118..ce16a4cf 100644
--- a/public/engine_api.h
+++ b/public/engine_api.h
@@ -119,24 +119,6 @@ typedef struct trace_s
};
} trace_t;
-_inline void PlaneClassify( cplane_t *p )
-{
- // for optimized plane comparisons
- if( p->normal[0] == 1 || p->normal[0] == -1 )
- p->type = PLANE_X;
- else if( p->normal[1] == 1 || p->normal[1] == -1 )
- p->type = PLANE_Y;
- else if( p->normal[2] == 1 || p->normal[2] == -1 )
- p->type = PLANE_Z;
- else p->type = 3; // needs alternate calc
-
- // for BoxOnPlaneSide
- p->signbits = 0;
- if( p->normal[0] < 0 ) p->signbits |= 1;
- if( p->normal[1] < 0 ) p->signbits |= 2;
- if( p->normal[2] < 0 ) p->signbits |= 4;
-}
-
/*
=================
CategorizePlane
diff --git a/public/launch_api.h b/public/launch_api.h
index 82e889f3..2ce989fb 100644
--- a/public/launch_api.h
+++ b/public/launch_api.h
@@ -372,12 +372,12 @@ typedef enum
typedef struct rgbdata_s
{
- int width; // image width
- int height; // image height
- word depth; // multi-layer volume
+ word width; // image width
+ word height; // image height
+ word depth; // multi-layer volume
byte numMips; // mipmap count
byte bitsCount; // RGB bits count
- word type; // compression type
+ uint type; // compression type
uint flags; // misc image flags
byte *palette; // palette if present
byte *buffer; // image buffer
diff --git a/public/qfiles_ref.h b/public/qfiles_ref.h
index a38acd69..37aab199 100644
--- a/public/qfiles_ref.h
+++ b/public/qfiles_ref.h
@@ -586,7 +586,7 @@ typedef struct
========================================================================
*/
-#define IDMD3HEADER (('3'<<24)+('P'<<16)+('D'<<8)+'I') // little-endian "IDP3"
+#define ALIASMODHEADER (('3'<<24)+('P'<<16)+('D'<<8)+'I') // little-endian "IDP3"
#define MD3_ALIAS_VERSION 15
#define MD3_ALIAS_MAX_LODS 4
@@ -667,119 +667,6 @@ typedef struct
int ofs_end;
} dmd3header_t;
-/*
-========================================================================
-
-.SKM and .SKP models file formats
-
-========================================================================
-*/
-
-#define SKMHEADER (('1'<<24)+('M'<<16)+('K'<<8)+'S') // little-endian "SKM1"
-
-#define SKM_MAX_NAME 64
-#define SKM_MAX_MESHES 32
-#define SKM_MAX_FRAMES 65536
-#define SKM_MAX_TRIS 65536
-#define SKM_MAX_VERTS (SKM_MAX_TRIS * 3)
-#define SKM_MAX_BONES 256
-#define SKM_MAX_SHADERS 256
-#define SKM_MAX_FILESIZE 16777216
-#define SKM_MAX_ATTACHMENTS SKM_MAX_BONES
-#define SKM_MAX_LODS 4
-
-// model format related flags
-#define SKM_BONEFLAG_ATTACH 1
-#define SKM_MODELTYPE 2 // (hierarchical skeletal pose)
-
-typedef struct
-{
- char id[4]; // SKMHEADER
- uint type;
- uint filesize; // size of entire model file
-
- uint num_bones;
- uint num_meshes;
-
- // this offset is relative to the file
- uint ofs_meshes;
-} dskmheader_t;
-
-// there may be more than one of these
-typedef struct
-{
- // these offsets are relative to the file
- char shadername[SKM_MAX_NAME]; // name of the shader to use
- char meshname[SKM_MAX_NAME];
-
- uint num_verts;
- uint num_tris;
- uint num_references;
- uint ofs_verts;
- uint ofs_texcoords;
- uint ofs_indices;
- uint ofs_references;
-} dskmmesh_t;
-
-// one or more of these per vertex
-typedef struct
-{
- float origin[3]; // vertex location (these blend)
- float influence; // influence fraction (these must add up to 1)
- float normal[3]; // surface normal (these blend)
- uint bonenum; // number of the bone
-} dskmbonevert_t;
-
-// variable size, parsed sequentially
-typedef struct
-{
- uint numweights;
- // immediately followed by 1 or more ddpmbonevert_t structures
- dskmbonevert_t verts[1];
-} dskmvertex_t;
-
-typedef struct
-{
- float st[2];
-} dskmcoord_t;
-
-typedef struct
-{
- char id[4]; // SKMHEADER
- uint type;
- uint filesize; // size of entire model file
-
- uint num_bones;
- uint num_frames;
-
- // these offsets are relative to the file
- uint ofs_bones;
- uint ofs_frames;
-} dskpheader_t;
-
-// one per bone
-typedef struct
-{
- // name examples: upperleftarm leftfinger1 leftfinger2 hand, etc
- char name[SKM_MAX_NAME];
- signed int parent; // parent bone number
- uint flags; // flags for the bone
-} dskpbone_t;
-
-typedef struct
-{
- float quat[4];
- float origin[3];
-} dskpbonepose_t;
-
-// immediately followed by bone positions for the frame
-typedef struct
-{
- // name examples: idle_1 idle_2 idle_3 shoot_1 shoot_2 shoot_3, etc
- char name[SKM_MAX_NAME];
- uint ofs_bonepositions;
-} dskpframe_t;
-
/*
==============================================================================
SAVE FILE
diff --git a/public/render_api.h b/public/render_api.h
index 4df290fe..1d16c543 100644
--- a/public/render_api.h
+++ b/public/render_api.h
@@ -70,7 +70,7 @@ typedef struct render_exp_s
// prepare frame to rendering
bool (*AddRefEntity)( edict_t *pRefEntity, int ed_type, float lerp );
- bool (*AddDynLight)( vec3_t org, vec3_t color, float intensity );
+ bool (*AddDynLight)( vec3_t org, vec3_t color, float intensity, shader_t shader );
bool (*AddPolygon)( const poly_t *poly );
bool (*AddLightStyle)( int stylenum, vec3_t color );
void (*ClearScene)( void );
diff --git a/render/r_alias.c b/render/r_alias.c
index 11149291..fd458d3c 100644
--- a/render/r_alias.c
+++ b/render/r_alias.c
@@ -72,279 +72,6 @@ static void Mod_AliasBuildMeshesForFrame0( ref_model_t *mod )
}
}
-
-#ifdef QUAKE2_JUNK
-
-/*
-==============================================================================
-
-MD2 MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_AliasCalculateVertexNormals
-=================
-*/
-static void Mod_AliasCalculateVertexNormals( int numElems, elem_t *elems, int numVerts, maliasvertex_t *v )
-{
- int i, j, k, vertRemap[MD2_MAX_VERTS];
- vec3_t dir1, dir2, normal, trnormals[MD2_MAX_TRIANGLES];
- int numUniqueVerts, uniqueVerts[MD2_MAX_VERTS];
- byte latlongs[MD2_MAX_VERTS][2];
-
- // count unique verts
- for( i = 0, numUniqueVerts = 0; i < numVerts; i++ )
- {
- for( j = 0; j < numUniqueVerts; j++ )
- {
- if( VectorCompare( v[uniqueVerts[j]].point, v[i].point ) )
- {
- vertRemap[i] = j;
- break;
- }
- }
-
- if( j == numUniqueVerts )
- {
- vertRemap[i] = numUniqueVerts;
- uniqueVerts[numUniqueVerts++] = i;
- }
- }
-
- for( i = 0, j = 0; i < numElems; i += 3, j++ )
- {
- // calculate two mostly perpendicular edge directions
- VectorSubtract( v[elems[i+0]].point, v[elems[i+1]].point, dir1 );
- VectorSubtract( v[elems[i+2]].point, v[elems[i+1]].point, dir2 );
-
- // we have two edge directions, we can calculate a third vector from
- // them, which is the direction of the surface normal
- CrossProduct( dir1, dir2, trnormals[j] );
- VectorNormalize( trnormals[j] );
- }
-
- // sum all triangle normals
- for( i = 0; i < numUniqueVerts; i++ )
- {
- VectorClear( normal );
-
- for( j = 0, k = 0; j < numElems; j += 3, k++ )
- {
- if( vertRemap[elems[j+0]] == i || vertRemap[elems[j+1]] == i || vertRemap[elems[j+2]] == i )
- VectorAdd( normal, trnormals[k], normal );
- }
-
- VectorNormalize( normal );
- NormToLatLong( normal, latlongs[i] );
- }
-
- // copy normals back
- for( i = 0; i < numVerts; i++ )
- *(short *)v[i].latlong = *(short *)latlongs[vertRemap[i]];
-}
-
-/*
-=================
-Mod_LoadAliasMD2Model
-=================
-*/
-void Mod_LoadAliasMD2Model( ref_model_t *mod, ref_model_t *parent, void *buffer )
-{
- int i, j, k;
- int version, framesize;
- float skinwidth, skinheight;
- int numverts, numelems;
- int indremap[MD2_MAX_TRIANGLES*3];
- elem_t ptempelem[MD2_MAX_TRIANGLES*3], ptempstelem[MD2_MAX_TRIANGLES*3];
- dmd2_t *pinmodel;
- dstvert_t *pinst;
- dtriangle_t *pintri;
- daliasframe_t *pinframe;
- elem_t *poutelem;
- maliasmodel_t *poutmodel;
- maliasmesh_t *poutmesh;
- vec2_t *poutcoord;
- maliasframe_t *poutframe;
- maliasvertex_t *poutvertex;
- maliasskin_t *poutskin;
-
- pinmodel = ( dmd2_t * )buffer;
- version = LittleLong( pinmodel->version );
- framesize = LittleLong( pinmodel->framesize );
-
- if( version != MD2_ALIAS_VERSION )
- Host_Error( ERR_DROP, "%s has wrong version number (%i should be %i)",
- mod->name, version, MD2_ALIAS_VERSION );
-
- mod->type = mod_alias;
- mod->aliasmodel = poutmodel = Mod_Malloc( mod, sizeof( maliasmodel_t ) );
- mod->radius = 0;
- ClearBounds( mod->mins, mod->maxs );
-
- // byte swap the header fields and sanity check
- skinwidth = LittleLong( pinmodel->skinwidth );
- skinheight = LittleLong( pinmodel->skinheight );
-
- if( skinwidth <= 0 )
- Host_Error( ERR_DROP, "model %s has invalid skin width", mod->name );
- if( skinheight <= 0 )
- Host_Error( ERR_DROP, "model %s has invalid skin height", mod->name );
-
- poutmodel->numframes = LittleLong( pinmodel->num_frames );
- poutmodel->numskins = LittleLong( pinmodel->num_skins );
-
- if( poutmodel->numframes > MD2_MAX_FRAMES )
- Host_Error( ERR_DROP, "model %s has too many frames", mod->name );
- else if( poutmodel->numframes <= 0 )
- Host_Error( ERR_DROP, "model %s has no frames", mod->name );
- if( poutmodel->numskins > MD2_MAX_SKINS )
- Host_Error( ERR_DROP, "model %s has too many skins", mod->name );
- else if( poutmodel->numskins < 0 )
- Host_Error( ERR_DROP, "model %s has invalid number of skins", mod->name );
-
- poutmodel->numtags = 0;
- poutmodel->tags = NULL;
- poutmodel->nummeshes = 1;
-
- poutmesh = poutmodel->meshes = Mod_Malloc( mod, sizeof( maliasmesh_t ) );
- Q_strncpyz( poutmesh->name, "default", MD3_MAX_PATH );
-
- poutmesh->numverts = LittleLong( pinmodel->num_xyz );
- poutmesh->numtris = LittleLong( pinmodel->num_tris );
-
- if( poutmesh->numverts <= 0 )
- Host_Error( "model %s has no vertices\n", mod->name );
- else if( poutmesh->numverts > MD2_MAX_VERTS )
- Host_Error( "model %s has too many vertices\n", mod->name );
- if( poutmesh->numtris > MD2_MAX_TRIANGLES )
- Host_Error( "model %s has too many triangles\n", mod->name );
- else if( poutmesh->numtris <= 0 )
- Host_Error( "model %s has no triangles\n", mod->name );
-
- numelems = poutmesh->numtris * 3;
- poutelem = poutmesh->elems = Mod_Malloc( mod, numelems * sizeof( elem_t ) );
-
- //
- // load triangle lists
- //
- pintri = ( dtriangle_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_tris ) );
- pinst = ( dstvert_t * ) ( ( byte * )pinmodel + LittleLong( pinmodel->ofs_st ) );
-
- for( i = 0, k = 0; i < poutmesh->numtris; i++, k += 3 )
- {
- for( j = 0; j < 3; j++ )
- {
- ptempelem[k+j] = ( elem_t )LittleShort( pintri[i].index_xyz[j] );
- ptempstelem[k+j] = ( elem_t )LittleShort( pintri[i].index_st[j] );
- }
- }
-
- //
- // build list of unique vertexes
- //
- numverts = 0;
- memset( indremap, -1, MD2_MAX_TRIANGLES * 3 * sizeof( int ) );
-
- for( i = 0; i < numelems; i++ )
- {
- if( indremap[i] != -1 )
- continue;
-
- // remap duplicates
- for( j = i + 1; j < numelems; j++ )
- {
- if( ( ptempelem[j] == ptempelem[i] )
- && ( pinst[ptempstelem[j]].s == pinst[ptempstelem[i]].s )
- && ( pinst[ptempstelem[j]].t == pinst[ptempstelem[i]].t ) )
- {
- indremap[j] = i;
- poutelem[j] = numverts;
- }
- }
-
- // add unique vertex
- indremap[i] = i;
- poutelem[i] = numverts++;
- }
-
- MsgDev( "%s: remapped %i verts to %i (%i tris)\n", mod->name, poutmesh->numverts, numverts, poutmesh->numtris );
-
- poutmesh->numverts = numverts;
-
- //
- // load base s and t vertices
- //
- poutcoord = poutmesh->stArray = Mod_Malloc( mod, numverts * sizeof( vec2_t ) );
-
- for( i = 0; i < numelems; i++ )
- {
- if( indremap[i] == i )
- {
- poutcoord[poutelem[i]][0] = ( (float)LittleShort( pinst[ptempstelem[i]].s ) + 0.5 ) / skinwidth;
- poutcoord[poutelem[i]][1] = ( (float)LittleShort( pinst[ptempstelem[i]].t ) + 0.5 ) / skinheight;
- }
- }
-
- //
- // load the frames
- //
- poutframe = poutmodel->frames = Mod_Malloc( mod, poutmodel->numframes * ( sizeof( maliasframe_t ) + numverts * sizeof( maliasvertex_t ) ) );
- poutvertex = poutmesh->vertexes = ( maliasvertex_t *)( ( byte * )poutframe + poutmodel->numframes * sizeof( maliasframe_t ) );
-
- for( i = 0; i < poutmodel->numframes; i++, poutframe++, poutvertex += numverts )
- {
- pinframe = ( daliasframe_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_frames ) + i * framesize );
-
- for( j = 0; j < 3; j++ )
- {
- poutframe->scale[j] = LittleFloat( pinframe->scale[j] );
- poutframe->translate[j] = LittleFloat( pinframe->translate[j] );
- }
-
- for( j = 0; j < numelems; j++ )
- { // verts are all 8 bit, so no swapping needed
- if( indremap[j] == j )
- {
- poutvertex[poutelem[j]].point[0] = (short)pinframe->verts[ptempelem[j]].v[0];
- poutvertex[poutelem[j]].point[1] = (short)pinframe->verts[ptempelem[j]].v[1];
- poutvertex[poutelem[j]].point[2] = (short)pinframe->verts[ptempelem[j]].v[2];
- }
- }
-
- Mod_AliasCalculateVertexNormals( numelems, poutelem, numverts, poutvertex );
-
- VectorCopy( poutframe->translate, poutframe->mins );
- VectorMA( poutframe->translate, 255, poutframe->scale, poutframe->maxs );
- poutframe->radius = RadiusFromBounds( poutframe->mins, poutframe->maxs );
-
- mod->radius = max( mod->radius, poutframe->radius );
- AddPointToBounds( poutframe->mins, mod->mins, mod->maxs );
- AddPointToBounds( poutframe->maxs, mod->mins, mod->maxs );
- }
-
- //
- // build S and T vectors for frame 0
- //
- Mod_AliasBuildMeshesForFrame0( mod );
-
-
- // register all skins
- poutskin = poutmodel->skins = Mod_Malloc( mod, poutmodel->numskins * sizeof( maliasskin_t ) );
-
- for( i = 0; i < poutmodel->numskins; i++, poutskin++ )
- {
- if( LittleLong( pinmodel->ofs_skins ) == -1 )
- continue;
- poutskin->shader = R_RegisterSkin( ( char * )pinmodel + LittleLong( pinmodel->ofs_skins ) + i*MD2_MAX_SKINNAME );
- }
- mod->touchFrame = tr.registration_sequence; // register model
-}
-
-#endif
-
/*
==============================================================================
@@ -469,9 +196,9 @@ void Mod_LoadAliasMD3Model( ref_model_t *mod, ref_model_t *parent, const void *b
poutmesh = poutmodel->meshes = ( maliasmesh_t * )buf;
for( i = 0; i < poutmodel->nummeshes; i++, poutmesh++ )
{
- if( pinmesh->id != IDMD3HEADER )
+ if( pinmesh->id != ALIASMODHEADER )
Host_Error( "mesh %s in model %s has wrong id (%s should be %s)\n",
- pinmesh->name, mod->name, pinmesh->id, IDMD3HEADER );
+ pinmesh->name, mod->name, pinmesh->id, ALIASMODHEADER );
com.strncpy( poutmesh->name, pinmesh->name, MD3_MAX_PATH );
@@ -505,7 +232,8 @@ void Mod_LoadAliasMD3Model( ref_model_t *mod, ref_model_t *parent, const void *b
poutskin = poutmesh->skins = ( maliasskin_t * )buf; buf += sizeof( maliasskin_t ) * poutmesh->numskins;
for( j = 0; j < poutmesh->numskins; j++, pinskin++, poutskin++ )
{
- poutskin->shader = R_RegisterSkin( pinskin->name );
+ FS_StripExtension( pinskin->name );
+ poutskin->shader = R_LoadShader( pinskin->name, SHADER_ALIAS, false, 0, SHADER_INVALID );
R_DeformvBBoxForShader( poutskin->shader, ebbox );
}
@@ -1006,10 +734,6 @@ bool R_CullAliasModel( ref_entity_t *e )
shader = R_FindShaderForSkinFile( e->customSkin, mesh->name );
else if( e->customShader )
shader = e->customShader;
-#ifdef QUAKE2_JUNK
- else if( ( e->skinNum >= 0 ) && ( e->skinNum < aliasmodel->numskins ) )
- shader = aliasmodel->skins[e->skinNum].shader;
-#endif
else if( mesh->numskins )
{
for( j = 0; j < mesh->numskins; j++ )
@@ -1089,10 +813,6 @@ void R_AddAliasModelToList( ref_entity_t *e )
shader = R_FindShaderForSkinFile( e->customSkin, mesh->name );
else if( e->customShader )
shader = e->customShader;
-#ifdef QUAKE2_JUNK
- else if( ( e->skinNum >= 0 ) && ( e->skinNum < aliasmodel->numskins ) )
- shader = aliasmodel->skins[e->skinNum].shader;
-#endif
else if( mesh->numskins )
{
for( j = 0; j < mesh->numskins; j++ )
diff --git a/render/r_backend.c b/render/r_backend.c
index 651b24c4..a1777124 100644
--- a/render/r_backend.c
+++ b/render/r_backend.c
@@ -22,22 +22,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mathlib.h"
#include "quatlib.h"
-#define FTABLE_SIZE_POW 10
-#define FTABLE_SIZE ( 1<pointer );
+
+ if( r_features & MF_ENABLENORMALS )
{
- pglVertexPointer( 3, GL_FLOAT, 16, vertsArray );
-
- if( r_features & MF_ENABLENORMALS )
- {
- r_normalsEnabled = true;
- pglEnableClientState( GL_NORMAL_ARRAY );
- pglNormalPointer( GL_FLOAT, 16, normalsArray );
- }
+ r_normalsEnabled = true;
+ R_UpdateVertexBuffer( tr.normalBuffer, normalsArray, numverts * sizeof( vec4_t ));
+ pglEnableClientState( GL_NORMAL_ARRAY );
+ pglNormalPointer( GL_FLOAT, 16, tr.normalBuffer->pointer );
}
if( GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT ))
@@ -509,16 +508,15 @@ void R_FlushArrays( void )
else if( r_backacc.numColors > 1 )
{
pglEnableClientState( GL_COLOR_ARRAY );
- if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
- pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
+ R_UpdateVertexBuffer( tr.colorsBuffer, colorArray, r_backacc.numVerts * sizeof( rgba_t ));
+ pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tr.colorsBuffer->pointer );
}
if( r_drawelements->integer || glState.in2DMode || RI.refdef.rdflags & RDF_NOWORLDMODEL )
{
if( GL_Support( R_DRAW_RANGEELEMENTS_EXT ))
pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
- else
- pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
+ else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
}
if( r_backacc.numColors > 1 )
@@ -934,22 +932,15 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
case TCGEN_BASE:
GL_DisableAllTexGens();
- if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
- {
- pglTexCoordPointer( 2, GL_FLOAT, 0, coordsArray );
- return true;
- }
- break;
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], coordsArray, r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
+ return true;
case TCGEN_LIGHTMAP:
GL_DisableAllTexGens();
- if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
- {
- pglTexCoordPointer( 2, GL_FLOAT, 0, lightmapCoordsArray[r_lightmapStyleNum[unit]] );
- return true;
- }
- break;
-
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], lightmapCoordsArray[r_lightmapStyleNum[unit]], r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
+ return true;
case TCGEN_ENVIRONMENT:
{
float depth, *n;
@@ -977,12 +968,9 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
GL_DisableAllTexGens();
- if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
- {
- pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] );
- return true;
- }
- break;
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
+ return true;
}
case TCGEN_VECTOR:
@@ -1143,34 +1131,23 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
GL_DisableAllTexGens();
- if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
- {
- pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] );
- return false;
- }
- break;
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
+ return false;
}
case TCGEN_SVECTORS:
GL_DisableAllTexGens();
-
- if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
- {
- pglTexCoordPointer( 4, GL_FLOAT, 0, sVectorsArray );
- return true;
- }
- break;
-
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t ));
+ pglTexCoordPointer( 4, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer );
+ return true;
case TCGEN_PROJECTION_SHADOW:
GL_SetTexCoordArrayMode( 0 );
GL_DisableAllTexGens();
Matrix4_Multiply( r_currentCastGroup->worldviewProjectionMatrix, RI.objectMatrix, matrix );
break;
-
- default:
- break;
+ default: break;
}
-
return identityMatrix;
}
@@ -1268,9 +1245,8 @@ static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit
tex = R_ShaderpassTex( pass, unit );
GL_Bind( unit, tex );
- if( unit && !pass->program )
- pglEnable( GL_TEXTURE_2D );
- GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ) );
+ if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D );
+ GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ));
identityMatrix = R_VertexTCBase( pass, unit, result );
@@ -2805,8 +2781,7 @@ static void R_DrawTriangles( void )
if( GL_Support( R_DRAW_RANGEELEMENTS_EXT ))
pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
- else
- pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
+ else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
}
/*
@@ -2825,9 +2800,7 @@ static void R_DrawNormals( void )
for( i = 0; i < r_backacc.numVerts; i++ )
{
pglVertex3fv( vertsArray[i] );
- pglVertex3f( vertsArray[i][0] + normalsArray[i][0],
- vertsArray[i][1] + normalsArray[i][1],
- vertsArray[i][2] + normalsArray[i][2] );
+ pglVertex3f( vertsArray[i][0] + normalsArray[i][0], vertsArray[i][1] + normalsArray[i][1], vertsArray[i][2] + normalsArray[i][2] );
}
pglEnd();
}
diff --git a/render/r_backend.h b/render/r_backend.h
index 2ce82e5d..ec5bc3ba 100644
--- a/render/r_backend.h
+++ b/render/r_backend.h
@@ -31,9 +31,7 @@ enum
VBO_VERTS,
VBO_NORMALS,
VBO_COLORS,
-// VBO_INDEXES,
VBO_TC0,
-
VBO_ENDMARKER
};
@@ -55,24 +53,27 @@ extern vec4_t *sVectorsArray;
extern vec2_t *coordsArray;
extern vec2_t *lightmapCoordsArray[LM_STYLES];
extern rgba_t colorArray[MAX_ARRAY_VERTS];
-
-extern int r_numVertexBufferObjects;
-extern GLuint r_vertexBufferObjects[MAX_VERTEX_BUFFER_OBJECTS];
-
extern int r_features;
//===================================================================
+typedef struct ref_buffer_s
+{
+ byte *pointer;
+ int size;
+ uint usage;
+ uint bufNum;
+} ref_buffer_t;
typedef struct
{
- uint numVerts;
- uint numElems;
- uint numColors;
+ uint numVerts;
+ uint numElems;
+ uint numColors;
- uint c_totalVerts;
- uint c_totalTris;
- uint c_totalFlushes;
- uint c_totalKeptLocks;
+ uint c_totalVerts;
+ uint c_totalTris;
+ uint c_totalFlushes;
+ uint c_totalKeptLocks;
} ref_backacc_t;
typedef struct
@@ -80,6 +81,14 @@ typedef struct
// renderer global variables
int registration_sequence;
+ // vbo stuff
+ int numVertexBufferObjects;
+ ref_buffer_t vertexBufferObjects[MAX_VERTEX_BUFFER_OBJECTS];
+ ref_buffer_t *vertexBuffer;
+ ref_buffer_t *normalBuffer;
+ ref_buffer_t *colorsBuffer;
+ ref_buffer_t *tcoordBuffer[MAX_TEXTURE_UNITS];
+
// builtin textures
texture_t *cinTexture; // cinematic texture
texture_t *portaltexture1; // portal view
@@ -98,6 +107,7 @@ typedef struct
texture_t *lightmapTextures[MAX_TEXTURES];
// builtin shaders
+ ref_shader_t *defaultShader; // generic black texture
} ref_globals_t;
extern ref_globals_t tr;
@@ -121,6 +131,11 @@ void R_BackendResetPassMask( void );
void R_DrawPhysDebug( void );
+void R_InitVertexBuffers( void );
+void R_ShutdownVertexBuffers( void );
+ref_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage );
+void R_UpdateVertexBuffer( ref_buffer_t *vertexBuffer, const void *data, size_t size );
+
void R_LockArrays( int numverts );
void R_UnlockArrays( void );
void R_UnlockArrays( void );
@@ -386,14 +401,15 @@ typedef struct
bool initializedMedia;
int activeTMU;
- GLuint *currentTextures;
- GLenum *currentEnvModes;
- bool *texIdentityMatrix;
- int *genSTEnabled; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R
- int *texCoordArrayMode; // 0 - disabled, 1 - enabled, 2 - cubemap
+ GLuint currentTextures[MAX_TEXTURE_UNITS];
+ GLenum currentEnvModes[MAX_TEXTURE_UNITS];
+ GLboolean texIdentityMatrix[MAX_TEXTURE_UNITS];
+ GLint genSTEnabled[MAX_TEXTURE_UNITS]; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R
+ GLint texCoordArrayMode[MAX_TEXTURE_UNITS]; // 0 - disabled, 1 - enabled, 2 - cubemap
+
vec4_t draw_color;
- kRenderMode_t draw_rendermode; // rendermode for drawing
- int draw_frame; // will be reset after each drawing
+ kRenderMode_t draw_rendermode; // rendermode for drawing
+ int draw_frame; // will be reset after each drawing
int faceCull;
int frontFace;
diff --git a/render/r_backend.old b/render/r_backend.old
new file mode 100644
index 00000000..3814a09a
--- /dev/null
+++ b/render/r_backend.old
@@ -0,0 +1,2845 @@
+/*
+Copyright (C) 2002-2007 Victor Luchits
+
+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 2
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "r_local.h"
+#include "mathlib.h"
+#include "quatlib.h"
+
+#define FTABLE_SIZE_POW 10
+#define FTABLE_SIZE ( 1<integer )
+ r_identityLighting = (int)( 255.0f / pow( 2, max( 0, floor( r_overbrightbits->value ) ) ) );
+ else
+ r_identityLighting = 255;
+
+ // build lookup tables
+ for( i = 0; i < FTABLE_SIZE; i++ )
+ {
+ t = (float)i / (float)FTABLE_SIZE;
+
+ r_sintable[i] = sin( t * M_PI2 );
+
+ if( t < 0.25 )
+ r_triangletable[i] = t * 4.0;
+ else if( t < 0.75 )
+ r_triangletable[i] = 2 - 4.0 * t;
+ else
+ r_triangletable[i] = ( t - 0.75 ) * 4.0 - 1.0;
+
+ if( t < 0.5 )
+ r_squaretable[i] = 1.0f;
+ else
+ r_squaretable[i] = -1.0f;
+
+ r_sawtoothtable[i] = t;
+ r_inversesawtoothtable[i] = 1.0 - t;
+ }
+
+ for( i = 0; i < 256; i++ )
+ r_sintableByte[i] = sin( (float)i / 255.0 * M_PI2 );
+
+ // init the noise table
+ srand( 1001 );
+
+ for( i = 0; i < NOISE_SIZE; i++ )
+ {
+ r_noisetable[i] = (float)( ( ( rand() / (float)RAND_MAX ) * 2.0 - 1.0 ) );
+ r_noiseperm[i] = (unsigned char)( rand() / (float)RAND_MAX * 255 );
+ }
+
+ // init dynamic lights pass
+ memset( &r_dlightsPass, 0, sizeof( ref_stage_t ) );
+ r_dlightsPass.flags = SHADERSTAGE_DLIGHT;
+ r_dlightsPass.glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ONE;
+
+ // init fog pass
+ memset( &r_fogPass, 0, sizeof( ref_stage_t ) );
+ r_fogPass.tcgen = TCGEN_FOG;
+ r_fogPass.rgbGen.type = RGBGEN_FOG;
+ r_fogPass.alphaGen.type = ALPHAGEN_IDENTITY;
+ r_fogPass.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_DECAL;
+ r_fogPass.glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA;
+
+ // the very first lightmap pass is reserved for GL_REPLACE or GL_MODULATE
+ Mem_Set( r_lightmapPasses, 0, sizeof( r_lightmapPasses ));
+ r_lightmapPasses[0].rgbGen.args = r_lightmapPassesArgs[0];
+
+ // the rest are GL_ADD
+ for( i = 1; i < MAX_TEXTURE_UNITS+1; i++ )
+ {
+ r_lightmapPasses[i].flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_ADD;
+ r_lightmapPasses[i].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE;
+ r_lightmapPasses[i].tcgen = TCGEN_LIGHTMAP;
+ r_lightmapPasses[i].alphaGen.type = ALPHAGEN_IDENTITY;
+ r_lightmapPasses[i].rgbGen.args = r_lightmapPassesArgs[i];
+ }
+
+ // init optional GLSL program passes
+ memset( r_GLSLpasses, 0, sizeof( r_GLSLpasses ) );
+ r_GLSLpasses[0].flags = SHADERSTAGE_DLIGHT|SHADERSTAGE_BLEND_ADD;
+ r_GLSLpasses[0].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE;
+
+ r_GLSLpasses[1].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
+ r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR;
+ r_GLSLpasses[1].tcgen = TCGEN_BASE;
+ r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY;
+ r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY;
+ Mem_Copy( &r_GLSLpasses[2], &r_GLSLpasses[1], sizeof( ref_stage_t ) );
+
+ r_GLSLpasses[3].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
+ r_GLSLpasses[3].glState = GLSTATE_DEPTHFUNC_EQ /*|GLSTATE_OFFSET_FILL*/|GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR;
+ r_GLSLpasses[3].tcgen = TCGEN_PROJECTION_SHADOW;
+ r_GLSLpasses[3].rgbGen.type = RGBGEN_IDENTITY;
+ r_GLSLpasses[3].alphaGen.type = ALPHAGEN_IDENTITY;
+ r_GLSLpasses[3].program = DEFAULT_GLSL_SHADOWMAP_PROGRAM;
+ r_GLSLpasses[3].program_type = PROGRAM_TYPE_SHADOWMAP;
+
+ Mem_Set( &r_GLSLpassOutline, 0, sizeof( r_GLSLpassOutline ) );
+ r_GLSLpassOutline.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
+ r_GLSLpassOutline.glState = GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO|GLSTATE_DEPTHWRITE;
+ r_GLSLpassOutline.rgbGen.type = RGBGEN_OUTLINE;
+ r_GLSLpassOutline.alphaGen.type = ALPHAGEN_OUTLINE;
+ r_GLSLpassOutline.tcgen = TCGEN_NONE;
+ r_GLSLpassOutline.program = DEFAULT_GLSL_OUTLINE_PROGRAM;
+ r_GLSLpassOutline.program_type = PROGRAM_TYPE_OUTLINE;
+}
+
+/*
+==============
+R_BackendShutdown
+==============
+*/
+void R_BackendShutdown( void )
+{
+ R_ShutdownVertexBuffers ();
+}
+
+/*
+==============
+R_FastSin
+==============
+*/
+float R_FastSin( float t )
+{
+ return FTABLE_EVALUATE( r_sintable, t );
+}
+
+/*
+=============
+R_LatLongToNorm
+=============
+*/
+void R_LatLongToNorm( const byte latlong[2], vec3_t out )
+{
+ float sin_a, sin_b, cos_a, cos_b;
+
+ cos_a = r_sintableByte[( latlong[0] + 64 ) & 255];
+ sin_a = r_sintableByte[latlong[0]];
+ cos_b = r_sintableByte[( latlong[1] + 64 ) & 255];
+ sin_b = r_sintableByte[latlong[1]];
+
+ VectorSet( out, cos_b * sin_a, sin_b * sin_a, cos_a );
+}
+
+/*
+==============
+R_TableForFunc
+==============
+*/
+static float *R_TableForFunc( unsigned int func )
+{
+ switch( func )
+ {
+ case WAVEFORM_SIN:
+ return r_sintable;
+ case WAVEFORM_TRIANGLE:
+ return r_triangletable;
+ case WAVEFORM_SQUARE:
+ return r_squaretable;
+ case WAVEFORM_SAWTOOTH:
+ return r_sawtoothtable;
+ case WAVEFORM_INVERSESAWTOOTH:
+ return r_inversesawtoothtable;
+
+ case WAVEFORM_NOISE:
+ return r_sintable; // default to sintable
+ }
+
+ // assume error
+ Host_Error( "R_TableForFunc: unknown function\n" );
+
+ return NULL;
+}
+
+/*
+==============
+R_BackendGetNoiseValue
+==============
+*/
+float R_BackendGetNoiseValue( float x, float y, float z, float t )
+{
+ int i;
+ int ix, iy, iz, it;
+ float fx, fy, fz, ft;
+ float front[4], back[4];
+ float fvalue, bvalue, value[2], finalvalue;
+
+ ix = ( int )floor( x );
+ fx = x - ix;
+ iy = ( int )floor( y );
+ fy = y - iy;
+ iz = ( int )floor( z );
+ fz = z - iz;
+ it = ( int )floor( t );
+ ft = t - it;
+
+ for( i = 0; i < 2; i++ )
+ {
+ front[0] = r_noisetable[NOISE_INDEX( ix, iy, iz, it + i )];
+ front[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz, it + i )];
+ front[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz, it + i )];
+ front[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz, it + i )];
+
+ back[0] = r_noisetable[NOISE_INDEX( ix, iy, iz + 1, it + i )];
+ back[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz + 1, it + i )];
+ back[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz + 1, it + i )];
+ back[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz + 1, it + i )];
+
+ fvalue = NOISE_LERP( NOISE_LERP( front[0], front[1], fx ), NOISE_LERP( front[2], front[3], fx ), fy );
+ bvalue = NOISE_LERP( NOISE_LERP( back[0], back[1], fx ), NOISE_LERP( back[2], back[3], fx ), fy );
+ value[i] = NOISE_LERP( fvalue, bvalue, fz );
+ }
+
+ finalvalue = NOISE_LERP( value[0], value[1], ft );
+
+ return finalvalue;
+}
+
+/*
+==============
+R_BackendResetCounters
+==============
+*/
+void R_BackendResetCounters( void )
+{
+ memset( &r_backacc, 0, sizeof( r_backacc ) );
+}
+
+/*
+==============
+R_BackendStartFrame
+==============
+*/
+void R_BackendStartFrame( void )
+{
+ r_speeds_msg[0] = '\0';
+ R_BackendResetCounters();
+}
+
+/*
+==============
+R_BackendEndFrame
+==============
+*/
+void R_BackendEndFrame( void )
+{
+ // unlock arrays if any
+ R_UnlockArrays();
+
+ // clean up texture units
+ R_CleanUpTextureUnits( 1 );
+
+ if( r_speeds->integer && !( RI.refdef.rdflags & RDF_NOWORLDMODEL ) )
+ {
+ switch( r_speeds->integer )
+ {
+ case 1:
+ default:
+ com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
+ "%4i wpoly %4i leafs %4i verts %4i tris %4i flushes %3i locks",
+ c_brush_polys,
+ c_world_leafs,
+ r_backacc.c_totalVerts,
+ r_backacc.c_totalTris,
+ r_backacc.c_totalFlushes,
+ r_backacc.c_totalKeptLocks
+ );
+ break;
+ case 2:
+ com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
+ "lvs: %5i node: %5i farclip: %6.f",
+ r_mark_leaves,
+ r_world_node,
+ RI.farClip
+ );
+ break;
+ case 3:
+ com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
+ "polys\\ents: %5i\\%5i sort\\draw: %5i\\%i",
+ r_add_polys, r_add_entities,
+ r_sort_meshes, r_draw_meshes
+ );
+ break;
+ case 4:
+ if( r_debug_surface )
+ {
+ com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
+ "%s", r_debug_surface->shader->name );
+
+ if( r_debug_surface->fog && r_debug_surface->fog->shader
+ && r_debug_surface->fog->shader != r_debug_surface->shader )
+ {
+ com.strncat( r_speeds_msg, "\n", sizeof( r_speeds_msg ) );
+ com.strncat( r_speeds_msg, r_debug_surface->fog->shader->name, sizeof( r_speeds_msg ) );
+ }
+ }
+ break;
+ case 5:
+ com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ),
+ "%.1f %.1f %.1f (%.1f,%.1f,%.1f)",
+ RI.refdef.vieworg[0], RI.refdef.vieworg[1], RI.refdef.vieworg[2],
+ RI.refdef.viewangles[0], RI.refdef.viewangles[1], RI.refdef.viewangles[2]
+ );
+ break;
+ }
+ }
+}
+
+/*
+==============
+R_LockArrays
+==============
+*/
+void R_LockArrays( int numverts )
+{
+ if( r_arraysLocked ) return;
+
+ R_UpdateVertexBuffer( tr.vertexBuffer, vertsArray, numverts * sizeof( vec4_t ));
+ pglVertexPointer( 3, GL_FLOAT, 16, tr.vertexBuffer->pointer );
+
+ if( r_features & MF_ENABLENORMALS )
+ {
+ r_normalsEnabled = true;
+ R_UpdateVertexBuffer( tr.normalBuffer, normalsArray, numverts * sizeof( vec4_t ));
+ pglEnableClientState( GL_NORMAL_ARRAY );
+ pglNormalPointer( GL_FLOAT, 16, tr.normalBuffer->pointer );
+ }
+
+ if( GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT ))
+ pglLockArraysEXT( 0, numverts );
+
+ r_arraysLocked = true;
+}
+
+/*
+==============
+R_UnlockArrays
+==============
+*/
+void R_UnlockArrays( void )
+{
+ if( !r_arraysLocked )
+ return;
+
+ if(GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT ))
+ pglUnlockArraysEXT();
+
+ if( r_normalsEnabled )
+ {
+ r_normalsEnabled = false;
+ pglDisableClientState( GL_NORMAL_ARRAY );
+ }
+ r_arraysLocked = false;
+}
+
+/*
+==============
+R_ClearArrays
+==============
+*/
+void R_ClearArrays( void )
+{
+ int i;
+
+ r_backacc.numVerts = 0;
+ r_backacc.numElems = 0;
+ r_backacc.numColors = 0;
+
+ vertsArray = inVertsArray;
+ elemsArray = inElemsArray;
+ normalsArray = inNormalsArray;
+ sVectorsArray = inSVectorsArray;
+ coordsArray = inCoordsArray;
+ for( i = 0; i < LM_STYLES; i++ )
+ lightmapCoordsArray[i] = inLightmapCoordsArray[i];
+}
+
+/*
+==============
+R_FlushArrays
+==============
+*/
+void R_FlushArrays( void )
+{
+ if( !r_backacc.numVerts || !r_backacc.numElems )
+ return;
+
+ if( r_backacc.numColors == 1 )
+ {
+ pglColor4ubv( colorArray[0] );
+ }
+ else if( r_backacc.numColors > 1 )
+ {
+ pglEnableClientState( GL_COLOR_ARRAY );
+ R_UpdateVertexBuffer( tr.colorsBuffer, colorArray, r_backacc.numVerts * sizeof( rgba_t ));
+ pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tr.colorsBuffer->pointer );
+ }
+
+ if( r_drawelements->integer || glState.in2DMode || RI.refdef.rdflags & RDF_NOWORLDMODEL )
+ {
+ if( GL_Support( R_DRAW_RANGEELEMENTS_EXT ))
+ pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
+ else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
+ }
+
+ if( r_backacc.numColors > 1 )
+ pglDisableClientState( GL_COLOR_ARRAY );
+
+ r_backacc.c_totalTris += r_backacc.numElems / 3;
+ r_backacc.c_totalFlushes++;
+}
+
+/*
+==============
+GL_DisableAllTexGens
+==============
+*/
+static _inline void GL_DisableAllTexGens( void )
+{
+ GL_EnableTexGen( GL_S, 0 );
+ GL_EnableTexGen( GL_T, 0 );
+ GL_EnableTexGen( GL_R, 0 );
+ GL_EnableTexGen( GL_Q, 0 );
+}
+
+/*
+==============
+R_CleanUpTextureUnits
+==============
+*/
+static void R_CleanUpTextureUnits( int last )
+{
+ int i;
+
+ for( i = glState.activeTMU; i > last - 1; i-- )
+ {
+ GL_DisableAllTexGens();
+ GL_SetTexCoordArrayMode( 0 );
+
+ pglDisable( GL_TEXTURE_2D );
+ GL_SelectTexture( i - 1 );
+ }
+}
+
+/*
+================
+R_DeformVertices
+================
+*/
+void R_DeformVertices( void )
+{
+ uint i, j, k;
+ double args[4], temp;
+ float deflect, *quad[4];
+ const float *table;
+ const deform_t *deformv;
+ vec3_t tv, rot_centre;
+
+ deformv = &r_currentShader->deforms[0];
+ for( i = 0; i < r_currentShader->numDeforms; i++, deformv++ )
+ {
+ switch( deformv->type )
+ {
+ case DEFORM_NONE:
+ break;
+
+ case DEFORM_WAVE:
+ table = R_TableForFunc( deformv->func.type );
+
+ // Deflect vertex along its normal by wave amount
+ if( deformv->func.args[3] == 0 )
+ {
+ temp = deformv->func.args[2];
+ deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0];
+
+ for( j = 0; j < r_backacc.numVerts; j++ )
+ VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
+ }
+ else
+ {
+ args[0] = deformv->func.args[0];
+ args[1] = deformv->func.args[1];
+ args[2] = deformv->func.args[2] + deformv->func.args[3] * r_currentShaderTime;
+ args[3] = deformv->args[0];
+
+ for( j = 0; j < r_backacc.numVerts; j++ )
+ {
+ temp = args[2] + args[3] * ( inVertsArray[j][0] + inVertsArray[j][1] + inVertsArray[j][2] );
+ deflect = FTABLE_EVALUATE( table, temp ) * args[1] + args[0];
+ VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
+ }
+ }
+ break;
+
+ case DEFORM_NORMAL:
+ // without this * 0.1f deformation looks wrong, although q3a doesn't have it
+ args[0] = deformv->func.args[3] * r_currentShaderTime * 0.1f;
+ args[1] = deformv->func.args[1];
+
+ for( j = 0; j < r_backacc.numVerts; j++ )
+ {
+ VectorScale( inVertsArray[j], 0.98f, tv );
+ inNormalsArray[j][0] += args[1] *R_BackendGetNoiseValue( tv[0], tv[1], tv[2], args[0] );
+ inNormalsArray[j][1] += args[1] *R_BackendGetNoiseValue( tv[0] + 100, tv[1], tv[2], args[0] );
+ inNormalsArray[j][2] += args[1] *R_BackendGetNoiseValue( tv[0] + 200, tv[1], tv[2], args[0] );
+ VectorNormalizeFast( inNormalsArray[j] );
+ }
+ break;
+
+ case DEFORM_MOVE:
+ table = R_TableForFunc( deformv->func.type );
+ temp = deformv->func.args[2] + r_currentShaderTime * deformv->func.args[3];
+ deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0];
+
+ for( j = 0; j < r_backacc.numVerts; j++ )
+ VectorMA( inVertsArray[j], deflect, deformv->args, inVertsArray[j] );
+ break;
+
+ case DEFORM_BULGE:
+ args[0] = deformv->args[0];
+ args[1] = deformv->args[1];
+ args[2] = r_currentShaderTime * deformv->args[2];
+
+ for( j = 0; j < r_backacc.numVerts; j++ )
+ {
+ temp = ( coordsArray[j][0] * args[0] + args[2] ) / M_PI2;
+ deflect = R_FastSin( temp ) * args[1];
+ VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
+ }
+ break;
+
+ case DEFORM_AUTOSPRITE:
+ {
+ vec4_t *v;
+ vec2_t *st;
+ elem_t *elem;
+ float radius;
+ vec3_t point, v_centre, v_right, v_up;
+
+ if( r_backacc.numVerts % 4 || r_backacc.numElems % 6 )
+ break;
+
+ if( RI.currententity && (RI.currentmodel != r_worldmodel) )
+ {
+ Matrix_TransformVector( RI.currententity->axis, RI.vright, v_right );
+ Matrix_TransformVector( RI.currententity->axis, RI.vup, v_up );
+ }
+ else
+ {
+ VectorCopy( RI.vright, v_right );
+ VectorCopy( RI.vup, v_up );
+ }
+
+ radius = RI.currententity->scale;
+ if( radius && radius != 1.0f )
+ {
+ radius = 1.0f / radius;
+ VectorScale( v_right, radius, v_right );
+ VectorScale( v_up, radius, v_up );
+ }
+
+ for( k = 0, v = inVertsArray, st = coordsArray, elem = elemsArray; k < r_backacc.numVerts; k += 4, v += 4, st += 4, elem += 6 )
+ {
+ for( j = 0; j < 3; j++ )
+ v_centre[j] = (v[0][j] + v[1][j] + v[2][j] + v[3][j]) * 0.25;
+
+ VectorSubtract( v[0], v_centre, point );
+ radius = VectorLength( point ) * 0.707106f; // 1.0f / sqrt(2)
+
+ // very similar to R_PushSprite
+ VectorMA( v_centre, -radius, v_up, point );
+ VectorMA( point, -radius, v_right, v[0] );
+ VectorMA( point, radius, v_right, v[3] );
+
+ VectorMA( v_centre, radius, v_up, point );
+ VectorMA( point, -radius, v_right, v[1] );
+ VectorMA( point, radius, v_right, v[2] );
+
+ // reset texcoords
+ Vector2Set( st[0], 0, 1 );
+ Vector2Set( st[1], 0, 0 );
+ Vector2Set( st[2], 1, 0 );
+ Vector2Set( st[3], 1, 1 );
+
+ // trifan elems
+ elem[0] = k;
+ elem[1] = k + 2 - 1;
+ elem[2] = k + 2;
+
+ elem[3] = k;
+ elem[4] = k + 3 - 1;
+ elem[5] = k + 3;
+ }
+ }
+ break;
+
+ case DEFORM_AUTOSPRITE2:
+ if( r_backacc.numElems % 6 )
+ break;
+
+ for( k = 0; k < r_backacc.numElems; k += 6 )
+ {
+ int long_axis = 0, short_axis = 0;
+ vec3_t axis, tmp;
+ float len[3];
+ vec3_t m0[3], m1[3], m2[3], result[3];
+
+ quad[0] = ( float * )( inVertsArray + elemsArray[k+0] );
+ quad[1] = ( float * )( inVertsArray + elemsArray[k+1] );
+ quad[2] = ( float * )( inVertsArray + elemsArray[k+2] );
+
+ for( j = 2; j >= 0; j-- )
+ {
+ quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] );
+
+ if( !VectorCompare( quad[3], quad[0] ) &&
+ !VectorCompare( quad[3], quad[1] ) &&
+ !VectorCompare( quad[3], quad[2] ) )
+ {
+ break;
+ }
+ }
+
+ // build a matrix were the longest axis of the billboard is the Y-Axis
+ VectorSubtract( quad[1], quad[0], m0[0] );
+ VectorSubtract( quad[2], quad[0], m0[1] );
+ VectorSubtract( quad[2], quad[1], m0[2] );
+ len[0] = DotProduct( m0[0], m0[0] );
+ len[1] = DotProduct( m0[1], m0[1] );
+ len[2] = DotProduct( m0[2], m0[2] );
+
+ if( ( len[2] > len[1] ) && ( len[2] > len[0] ) )
+ {
+ if( len[1] > len[0] )
+ {
+ long_axis = 1;
+ short_axis = 0;
+ }
+ else
+ {
+ long_axis = 0;
+ short_axis = 1;
+ }
+ }
+ else if( ( len[1] > len[2] ) && ( len[1] > len[0] ) )
+ {
+ if( len[2] > len[0] )
+ {
+ long_axis = 2;
+ short_axis = 0;
+ }
+ else
+ {
+ long_axis = 0;
+ short_axis = 2;
+ }
+ }
+ else if( ( len[0] > len[1] ) && ( len[0] > len[2] ) )
+ {
+ if( len[2] > len[1] )
+ {
+ long_axis = 2;
+ short_axis = 1;
+ }
+ else
+ {
+ long_axis = 1;
+ short_axis = 2;
+ }
+ }
+
+ if( !len[long_axis] )
+ break;
+ len[long_axis] = Q_RSqrt( len[long_axis] );
+ VectorScale( m0[long_axis], len[long_axis], axis );
+
+ if( DotProduct( m0[long_axis], m0[short_axis] ) )
+ {
+ VectorCopy( axis, m0[1] );
+ if( axis[0] || axis[1] )
+ VectorVectors( m0[1], m0[0], m0[2] );
+ else
+ VectorVectors( m0[1], m0[2], m0[0] );
+ }
+ else
+ {
+ if( !len[short_axis] )
+ break;
+ len[short_axis] = Q_RSqrt( len[short_axis] );
+ VectorScale( m0[short_axis], len[short_axis], m0[0] );
+ VectorCopy( axis, m0[1] );
+ CrossProduct( m0[0], m0[1], m0[2] );
+ }
+
+ for( j = 0; j < 3; j++ )
+ rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25;
+
+ if( RI.currententity && ( RI.currentmodel != r_worldmodel ) )
+ {
+ VectorAdd( RI.currententity->origin, rot_centre, tv );
+ VectorSubtract( RI.viewOrigin, tv, tmp );
+ Matrix_TransformVector( RI.currententity->axis, tmp, tv );
+ }
+ else
+ {
+ VectorCopy( rot_centre, tv );
+ VectorSubtract( RI.viewOrigin, tv, tv );
+ }
+
+ // filter any longest-axis-parts off the camera-direction
+ deflect = -DotProduct( tv, axis );
+
+ VectorMA( tv, deflect, axis, m1[2] );
+ VectorNormalizeFast( m1[2] );
+ VectorCopy( axis, m1[1] );
+ CrossProduct( m1[1], m1[2], m1[0] );
+
+ Matrix_Transpose( m1, m2 );
+ Matrix_Multiply( m2, m0, result );
+
+ for( j = 0; j < 4; j++ )
+ {
+ VectorSubtract( quad[j], rot_centre, tv );
+ Matrix_TransformVector( result, tv, quad[j] );
+ VectorAdd( rot_centre, quad[j], quad[j] );
+ }
+ }
+ break;
+
+ case DEFORM_PROJECTION_SHADOW:
+ R_DeformVPlanarShadow( r_backacc.numVerts, inVertsArray[0] );
+ break;
+
+ case DEFORM_AUTOPARTICLE:
+ {
+ float scale;
+ vec3_t m0[3], m1[3], m2[3], result[3];
+
+ if( r_backacc.numElems % 6 )
+ break;
+
+ if( RI.currententity && ( RI.currentmodel != r_worldmodel ) )
+ Matrix4_Matrix( RI.modelviewMatrix, m1 );
+ else
+ Matrix4_Matrix( RI.worldviewMatrix, m1 );
+
+ Matrix_Transpose( m1, m2 );
+
+ for( k = 0; k < r_backacc.numElems; k += 6 )
+ {
+ quad[0] = ( float * )( inVertsArray + elemsArray[k+0] );
+ quad[1] = ( float * )( inVertsArray + elemsArray[k+1] );
+ quad[2] = ( float * )( inVertsArray + elemsArray[k+2] );
+
+ for( j = 2; j >= 0; j-- )
+ {
+ quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] );
+
+ if( !VectorCompare( quad[3], quad[0] ) &&
+ !VectorCompare( quad[3], quad[1] ) &&
+ !VectorCompare( quad[3], quad[2] ) )
+ {
+ break;
+ }
+ }
+
+ Matrix_FromPoints( quad[0], quad[1], quad[2], m0 );
+ Matrix_Multiply( m2, m0, result );
+
+ // hack a scale up to keep particles from disappearing
+ scale = ( quad[0][0] - RI.viewOrigin[0] ) * RI.vpn[0] + ( quad[0][1] - RI.viewOrigin[1] ) * RI.vpn[1] + ( quad[0][2] - RI.viewOrigin[2] ) * RI.vpn[2];
+ if( scale < 20 )
+ scale = 1.5;
+ else
+ scale = 1.5 + scale * 0.006f;
+
+ for( j = 0; j < 3; j++ )
+ rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25;
+
+ for( j = 0; j < 4; j++ )
+ {
+ VectorSubtract( quad[j], rot_centre, tv );
+ Matrix_TransformVector( result, tv, quad[j] );
+ VectorMA( rot_centre, scale, quad[j], quad[j] );
+ }
+ }
+ }
+ break;
+ case DEFORM_OUTLINE:
+ // Deflect vertex along its normal by outline amount
+ deflect = RI.currententity->outlineHeight * r_outlines_scale->value;
+ for( j = 0; j < r_backacc.numVerts; j++ )
+ VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] );
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+==============
+R_VertexTCBase
+==============
+*/
+static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix )
+{
+ unsigned int i;
+ float *outCoords;
+ bool identityMatrix = false;
+
+ Matrix4_Identity( matrix );
+
+ switch( pass->tcgen )
+ {
+ case TCGEN_BASE:
+ GL_DisableAllTexGens();
+
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], coordsArray, r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, coordsArray );
+ return true;
+ case TCGEN_LIGHTMAP:
+ GL_DisableAllTexGens();
+
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], lightmapCoordsArray[r_lightmapStyleNum[unit]], r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, lightmapCoordsArray[r_lightmapStyleNum[unit]] );
+ return true;
+ case TCGEN_ENVIRONMENT:
+ {
+ float depth, *n;
+ vec3_t projection, transform;
+
+ if( glState.in2DMode )
+ return true;
+
+ if( !( RI.params & RP_SHADOWMAPVIEW ) )
+ {
+ VectorSubtract( RI.viewOrigin, RI.currententity->origin, projection );
+ Matrix_TransformVector( RI.currententity->axis, projection, transform );
+
+ outCoords = tUnitCoordsArray[unit][0];
+ for( i = 0, n = normalsArray[0]; i < r_backacc.numVerts; i++, outCoords += 2, n += 4 )
+ {
+ VectorSubtract( transform, vertsArray[i], projection );
+ VectorNormalizeFast( projection );
+
+ depth = DotProduct( n, projection ); depth += depth;
+ outCoords[0] = 0.5 + ( n[1] * depth - projection[1] ) * 0.5;
+ outCoords[1] = 0.5 - ( n[2] * depth - projection[2] ) * 0.5;
+ }
+ }
+
+ GL_DisableAllTexGens();
+
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] );
+ return true;
+ }
+
+ case TCGEN_VECTOR:
+ {
+ GLfloat genVector[2][4];
+
+ for( i = 0; i < 3; i++ )
+ {
+ genVector[0][i] = pass->tcgenVec[i];
+ genVector[1][i] = pass->tcgenVec[i+4];
+ }
+ genVector[0][3] = genVector[1][3] = 0;
+
+ matrix[12] = pass->tcgenVec[3];
+ matrix[13] = pass->tcgenVec[7];
+
+ GL_SetTexCoordArrayMode( 0 );
+ GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR );
+ GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR );
+ GL_EnableTexGen( GL_R, 0 );
+ GL_EnableTexGen( GL_Q, 0 );
+ pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] );
+ pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] );
+ return false;
+ }
+ case TCGEN_PROJECTION:
+ {
+ mat4x4_t m1, m2;
+ GLfloat genVector[4][4];
+
+ GL_SetTexCoordArrayMode( 0 );
+
+ Matrix4_Copy( RI.worldviewProjectionMatrix, matrix );
+
+ Matrix4_Identity( m1 );
+ Matrix4_Scale( m1, 0.5, 0.5, 0.5 );
+ Matrix4_Multiply( m1, matrix, m2 );
+
+ Matrix4_Identity( m1 );
+ Matrix4_Translate( m1, 0.5, 0.5, 0.5 );
+ Matrix4_Multiply( m1, m2, matrix );
+
+ for( i = 0; i < 4; i++ )
+ {
+ genVector[0][i] = i == 0 ? 1 : 0;
+ genVector[1][i] = i == 1 ? 1 : 0;
+ genVector[2][i] = i == 2 ? 1 : 0;
+ genVector[3][i] = i == 3 ? 1 : 0;
+ }
+
+ GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR );
+ GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR );
+ GL_EnableTexGen( GL_R, GL_OBJECT_LINEAR );
+ GL_EnableTexGen( GL_Q, GL_OBJECT_LINEAR );
+
+ pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] );
+ pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] );
+ pglTexGenfv( GL_R, GL_OBJECT_PLANE, genVector[2] );
+ pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] );
+ return false;
+ }
+
+ case TCGEN_REFLECTION_CELLSHADE:
+ if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
+ {
+ vec3_t dir;
+ mat4x4_t m;
+
+ R_LightForOrigin( RI.currententity->lightingOrigin, dir, NULL, NULL, RI.currentmodel->radius * RI.currententity->scale );
+
+ Matrix4_Identity( m );
+
+ // rotate direction
+ Matrix_TransformVector( RI.currententity->axis, dir, &m[0] );
+ VectorNormalizeLength( &m[0] );
+
+ VectorVectors( &m[0], &m[4], &m[8] );
+ Matrix4_Transpose( m, matrix );
+ }
+ case TCGEN_REFLECTION:
+ GL_EnableTexGen( GL_S, GL_REFLECTION_MAP_ARB );
+ GL_EnableTexGen( GL_T, GL_REFLECTION_MAP_ARB );
+ GL_EnableTexGen( GL_R, GL_REFLECTION_MAP_ARB );
+ GL_EnableTexGen( GL_Q, 0 );
+ return true;
+
+ case TCGEN_FOG:
+ {
+ int fogPtype;
+ cplane_t *fogPlane;
+ ref_shader_t *fogShader;
+ vec3_t viewtofog;
+ float fogNormal[3], vpnNormal[3];
+ float dist, vdist, fogDist, vpnDist;
+
+ fogPlane = r_texFog->visibleplane;
+ fogShader = r_texFog->shader;
+
+ matrix[0] = matrix[5] = 1.0/(fogShader->fog_dist - fogShader->fog_clearDist);
+ matrix[13] = 1.5f/(float)FOG_TEXTURE_HEIGHT;
+
+ // distance to fog
+ dist = RI.fog_dist_to_eye[r_texFog-r_worldbrushmodel->fogs];
+
+ if( r_currentShader->flags & SHADER_SKYPARMS )
+ {
+ if( dist > 0 )
+ VectorMA( RI.viewOrigin, -dist, fogPlane->normal, viewtofog );
+ else
+ VectorCopy( RI.viewOrigin, viewtofog );
+ }
+ else
+ {
+ VectorCopy( RI.currententity->origin, viewtofog );
+ }
+
+ // some math tricks to take entity's rotation matrix into account
+ // for fog texture coordinates calculations:
+ // M is rotation matrix, v is vertex, t is transform vector
+ // n is plane's normal, d is plane's dist, r is view origin
+ // (M*v + t)*n - d = (M*n)*v - ((d - t*n))
+ // (M*v + t - r)*n = (M*n)*v - ((r - t)*n)
+ fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale;
+ fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale;
+ fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale;
+ fogPtype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) );
+ fogDist = ( fogPlane->dist - DotProduct( viewtofog, fogPlane->normal ) );
+
+ vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * RI.currententity->scale;
+ vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * RI.currententity->scale;
+ vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * RI.currententity->scale;
+ vpnDist = ( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] ) + fogShader->fog_clearDist;
+
+ outCoords = tUnitCoordsArray[unit][0];
+ if( dist < 0 )
+ { // camera is inside the fog brush
+ for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 )
+ {
+ outCoords[0] = DotProduct( vertsArray[i], vpnNormal ) - vpnDist;
+ if( fogPtype < 3 )
+ outCoords[1] = -( vertsArray[i][fogPtype] - fogDist );
+ else
+ outCoords[1] = -( DotProduct( vertsArray[i], fogNormal ) - fogDist );
+ }
+ }
+ else
+ {
+ for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 )
+ {
+ if( fogPtype < 3 )
+ vdist = vertsArray[i][fogPtype] - fogDist;
+ else
+ vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist;
+ outCoords[0] = ( ( vdist < 0 ) ? ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist ) : 0.0f );
+ outCoords[1] = -vdist;
+ }
+ }
+
+ GL_DisableAllTexGens();
+
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t ));
+ pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] );
+ return false;
+ }
+
+ case TCGEN_SVECTORS:
+ GL_DisableAllTexGens();
+ R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t ));
+ pglTexCoordPointer( 4, GL_FLOAT, 0, sVectorsArray );
+ return true;
+ case TCGEN_PROJECTION_SHADOW:
+ GL_SetTexCoordArrayMode( 0 );
+ GL_DisableAllTexGens();
+ Matrix4_Multiply( r_currentCastGroup->worldviewProjectionMatrix, RI.objectMatrix, matrix );
+ break;
+ default: break;
+ }
+ return identityMatrix;
+}
+
+/*
+================
+R_ApplyTCMods
+================
+*/
+static void R_ApplyTCMods( const ref_stage_t *pass, mat4x4_t result )
+{
+ int i;
+ const float *table;
+ double t1, t2, sint, cost;
+ mat4x4_t m1, m2;
+ const tcMod_t *tcmod;
+
+ for( i = 0, tcmod = pass->tcMods; i < pass->numtcMods; i++, tcmod++ )
+ {
+ switch( tcmod->type )
+ {
+ case TCMOD_ROTATE:
+ cost = tcmod->args[0] * r_currentShaderTime;
+ sint = R_FastSin( cost );
+ cost = R_FastSin( cost + 0.25 );
+ m2[0] = cost, m2[1] = sint, m2[12] = 0.5f * ( sint - cost + 1 );
+ m2[4] = -sint, m2[5] = cost, m2[13] = -0.5f * ( sint + cost - 1 );
+ Matrix4_Copy2D( result, m1 );
+ Matrix4_Multiply2D( m2, m1, result );
+ break;
+ case TCMOD_SCALE:
+ Matrix4_Scale2D( result, tcmod->args[0], tcmod->args[1] );
+ break;
+ case TCMOD_TURB:
+ t1 = ( 1.0 / 4.0 );
+ t2 = tcmod->args[2] + r_currentShaderTime * tcmod->args[3];
+ Matrix4_Scale2D( result, 1 + ( tcmod->args[1] * R_FastSin( t2 ) + tcmod->args[0] ) * t1, 1 + ( tcmod->args[1] * R_FastSin( t2 + 0.25 ) + tcmod->args[0] ) * t1 );
+ break;
+ case TCMOD_STRETCH:
+ table = R_TableForFunc( tcmod->args[0] );
+ t2 = tcmod->args[3] + r_currentShaderTime * tcmod->args[4];
+ t1 = FTABLE_EVALUATE( table, t2 ) * tcmod->args[2] + tcmod->args[1];
+ t1 = t1 ? 1.0f / t1 : 1.0f;
+ t2 = 0.5f - 0.5f * t1;
+ Matrix4_Stretch2D( result, t1, t2 );
+ break;
+ case TCMOD_SCROLL:
+ t1 = tcmod->args[0] * r_currentShaderTime;
+ t2 = tcmod->args[1] * r_currentShaderTime;
+ if( pass->program_type != PROGRAM_TYPE_DISTORTION )
+ { // HACK HACK HACK
+ t1 = t1 - floor( t1 );
+ t2 = t2 - floor( t2 );
+ }
+ Matrix4_Translate2D( result, t1, t2 );
+ break;
+ case TCMOD_TRANSFORM:
+ m2[0] = tcmod->args[0], m2[1] = tcmod->args[2], m2[12] = tcmod->args[4],
+ m2[5] = tcmod->args[1], m2[4] = tcmod->args[3], m2[13] = tcmod->args[5];
+ Matrix4_Copy2D( result, m1 );
+ Matrix4_Multiply2D( m2, m1, result );
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+==============
+R_ShaderpassTex
+==============
+*/
+static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit )
+{
+ if( pass->flags & SHADERSTAGE_ANIMFREQUENCY && pass->animFrequency && pass->num_textures )
+ return pass->textures[(int)( pass->animFrequency * r_currentShaderTime ) % pass->num_textures];
+ if( pass->flags & SHADERSTAGE_LIGHTMAP )
+ return tr.lightmapTextures[r_superLightStyle->lightmapNum[r_lightmapStyleNum[unit]]];
+ if( pass->flags & SHADERSTAGE_PORTALMAP )
+ return tr.portaltexture1;
+ return ( pass->textures[0] ? pass->textures[0] : tr.defaultTexture );
+}
+
+/*
+================
+R_BindShaderpass
+================
+*/
+static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit )
+{
+ mat4x4_t m1, m2, result;
+ bool identityMatrix;
+
+ if( !tex )
+ tex = R_ShaderpassTex( pass, unit );
+
+ GL_Bind( unit, tex );
+ if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D );
+ GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ));
+
+ identityMatrix = R_VertexTCBase( pass, unit, result );
+
+ if( pass->numtcMods )
+ {
+ identityMatrix = false;
+ R_ApplyTCMods( pass, result );
+ }
+
+ if( pass->tcgen == TCGEN_REFLECTION || pass->tcgen == TCGEN_REFLECTION_CELLSHADE )
+ {
+ Matrix4_Transpose( RI.modelviewMatrix, m1 );
+ Matrix4_Copy( result, m2 );
+ Matrix4_Multiply( m2, m1, result );
+ GL_LoadTexMatrix( result );
+ return;
+ }
+
+ if( identityMatrix )
+ GL_LoadIdentityTexMatrix();
+ else
+ GL_LoadTexMatrix( result );
+}
+
+/*
+================
+R_ModifyColor
+================
+*/
+void R_ModifyColor( const ref_stage_t *pass )
+{
+ uint i;
+ int c, bits;
+ double temp;
+ float *table, a;
+ vec3_t t, v, style;
+ byte *bArray, *inArray, rgba[4] = { 255, 255, 255, 255 };
+ bool noArray, identityAlpha, entityAlpha;
+ const waveFunc_t *rgbgenfunc, *alphagenfunc;
+
+ noArray = ( pass->flags & SHADERSTAGE_NOCOLORARRAY ) && !r_colorFog;
+ r_backacc.numColors = noArray ? 1 : r_backacc.numVerts;
+ bits = ( r_overbrightbits->integer > 0 ) && !( r_ignorehwgamma->integer ) ? r_overbrightbits->integer : 0;
+
+ bArray = colorArray[0];
+ inArray = inColorsArray[0][0];
+
+ if( pass->rgbGen.type == RGBGEN_IDENTITY_LIGHTING )
+ {
+ entityAlpha = identityAlpha = false;
+ memset( bArray, r_identityLighting, sizeof( rgba_t ) * r_backacc.numColors );
+ }
+ else if( pass->rgbGen.type == RGBGEN_EXACT_VERTEX )
+ {
+ entityAlpha = identityAlpha = false;
+ memcpy( bArray, inArray, sizeof( rgba_t ) * r_backacc.numColors );
+ }
+ else
+ {
+ entityAlpha = false;
+ identityAlpha = true;
+ memset( bArray, 255, sizeof( rgba_t ) * r_backacc.numColors );
+
+ switch( pass->rgbGen.type )
+ {
+ case RGBGEN_IDENTITY:
+ break;
+ case RGBGEN_CONST:
+ rgba[0] = R_FloatToByte( pass->rgbGen.args[0] );
+ rgba[1] = R_FloatToByte( pass->rgbGen.args[1] );
+ rgba[2] = R_FloatToByte( pass->rgbGen.args[2] );
+
+ for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_WAVE:
+ rgbgenfunc = pass->rgbGen.func;
+ if( rgbgenfunc->type == WAVEFORM_NOISE )
+ {
+ temp = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + rgbgenfunc->args[2] ) * rgbgenfunc->args[3] );
+ }
+ else
+ {
+ table = R_TableForFunc( rgbgenfunc->type );
+ temp = r_currentShaderTime * rgbgenfunc->args[3] + rgbgenfunc->args[2];
+ temp = FTABLE_EVALUATE( table, temp ) * rgbgenfunc->args[1] + rgbgenfunc->args[0];
+ }
+
+ temp = temp * rgbgenfunc->args[1] + rgbgenfunc->args[0];
+ a = pass->rgbGen.args[0] * temp; rgba[0] = a <= 0 ? 0 : R_FloatToByte( a );
+ a = pass->rgbGen.args[1] * temp; rgba[1] = a <= 0 ? 0 : R_FloatToByte( a );
+ a = pass->rgbGen.args[2] * temp; rgba[2] = a <= 0 ? 0 : R_FloatToByte( a );
+
+ for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_ENTITY:
+ entityAlpha = true;
+ identityAlpha = ( RI.currententity->color[3] == 255 );
+
+ for( i = 0, c = *(int *)RI.currententity->color; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_OUTLINE:
+ identityAlpha = ( RI.currententity->outlineColor[3] == 255 );
+
+ for( i = 0, c = *(int *)RI.currententity->outlineColor; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_ONE_MINUS_ENTITY:
+ rgba[0] = 255 - RI.currententity->color[0];
+ rgba[1] = 255 - RI.currententity->color[1];
+ rgba[2] = 255 - RI.currententity->color[2];
+
+ for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_VERTEX:
+ VectorSet( style, -1, -1, -1 );
+
+ if( !r_superLightStyle || r_superLightStyle->vertexStyles[1] == 255 )
+ {
+ VectorSet( style, 1, 1, 1 );
+ if( r_superLightStyle && r_superLightStyle->vertexStyles[0] != 255 )
+ VectorCopy( r_lightStyles[r_superLightStyle->vertexStyles[0]].rgb, style );
+ }
+
+ if( style[0] == style[1] && style[1] == style[2] && style[2] == 1 )
+ {
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
+ {
+ bArray[0] = inArray[0] >> bits;
+ bArray[1] = inArray[1] >> bits;
+ bArray[2] = inArray[2] >> bits;
+ }
+ }
+ else
+ {
+ int j;
+ float *tc;
+ vec3_t temp[MAX_ARRAY_VERTS];
+
+ memset( temp, 0, sizeof( vec3_t ) * r_backacc.numColors );
+
+ for( j = 0; j < LM_STYLES && r_superLightStyle->vertexStyles[j] != 255; j++ )
+ {
+ VectorCopy( r_lightStyles[r_superLightStyle->vertexStyles[j]].rgb, style );
+ if( VectorCompare( style, vec3_origin ) )
+ continue;
+
+ inArray = inColorsArray[j][0];
+ for( i = 0, tc = temp[0]; i < r_backacc.numColors; i++, tc += 3, inArray += 4 )
+ {
+ tc[0] += ( inArray[0] >> bits ) * style[0];
+ tc[1] += ( inArray[1] >> bits ) * style[1];
+ tc[2] += ( inArray[2] >> bits ) * style[2];
+ }
+ }
+
+ for( i = 0, tc = temp[0]; i < r_backacc.numColors; i++, tc += 3, bArray += 4 )
+ {
+ bArray[0] = bound( 0, tc[0], 255 );
+ bArray[1] = bound( 0, tc[1], 255 );
+ bArray[2] = bound( 0, tc[2], 255 );
+ }
+ }
+ break;
+ case RGBGEN_ONE_MINUS_VERTEX:
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
+ {
+ bArray[0] = 255 - ( inArray[0] >> bits );
+ bArray[1] = 255 - ( inArray[1] >> bits );
+ bArray[2] = 255 - ( inArray[2] >> bits );
+ }
+ break;
+ case RGBGEN_LIGHTING_DIFFUSE:
+ if( RI.currententity )
+ R_LightForEntity( RI.currententity, bArray );
+ break;
+ case RGBGEN_LIGHTING_DIFFUSE_ONLY:
+ if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
+ {
+ vec4_t diffuse;
+
+ if( RI.currententity->flags & RF_FULLBRIGHT )
+ VectorSet( diffuse, 1, 1, 1 );
+ else
+ R_LightForOrigin( RI.currententity->lightingOrigin, t, NULL, diffuse, RI.currentmodel->radius * RI.currententity->scale );
+
+ rgba[0] = R_FloatToByte( diffuse[0] );
+ rgba[1] = R_FloatToByte( diffuse[1] );
+ rgba[2] = R_FloatToByte( diffuse[2] );
+
+ for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ }
+ break;
+ case RGBGEN_LIGHTING_AMBIENT_ONLY:
+ if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) )
+ {
+ vec4_t ambient;
+
+ if( RI.currententity->flags & RF_FULLBRIGHT )
+ VectorSet( ambient, 1, 1, 1 );
+ else
+ R_LightForOrigin( RI.currententity->lightingOrigin, t, ambient, NULL, RI.currentmodel->radius * RI.currententity->scale );
+
+ rgba[0] = R_FloatToByte( ambient[0] );
+ rgba[1] = R_FloatToByte( ambient[1] );
+ rgba[2] = R_FloatToByte( ambient[2] );
+
+ for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ }
+ break;
+ case RGBGEN_FOG:
+ for( i = 0, c = *(int *)r_texFog->shader->fog_color; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_CUSTOM:
+ c = (int)pass->rgbGen.args[0];
+ for( i = 0, c = R_GetCustomColor( c ); i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ case RGBGEN_ENVIRONMENT:
+ for( i = 0, c = *(int *)mapConfig.environmentColor; i < r_backacc.numColors; i++, bArray += 4 )
+ *(int *)bArray = c;
+ break;
+ default:
+ break;
+ }
+ }
+
+ bArray = colorArray[0];
+ inArray = inColorsArray[0][0];
+
+ switch( pass->alphaGen.type )
+ {
+ case ALPHAGEN_IDENTITY:
+ if( identityAlpha )
+ break;
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ bArray[3] = 255;
+ break;
+ case ALPHAGEN_CONST:
+ c = R_FloatToByte( pass->alphaGen.args[0] );
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ bArray[3] = c;
+ break;
+ case ALPHAGEN_WAVE:
+ alphagenfunc = pass->alphaGen.func;
+ if( alphagenfunc->type == WAVEFORM_NOISE )
+ {
+ a = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + alphagenfunc->args[2] ) * alphagenfunc->args[3] );
+ }
+ else
+ {
+ table = R_TableForFunc( alphagenfunc->type );
+ a = alphagenfunc->args[2] + r_currentShaderTime * alphagenfunc->args[3];
+ a = FTABLE_EVALUATE( table, a );
+ }
+
+ a = a * alphagenfunc->args[1] + alphagenfunc->args[0];
+ c = a <= 0 ? 0 : R_FloatToByte( a );
+
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ bArray[3] = c;
+ break;
+ case ALPHAGEN_PORTAL:
+ VectorAdd( vertsArray[0], RI.currententity->origin, v );
+ VectorSubtract( RI.viewOrigin, v, t );
+ a = VectorLength( t ) * pass->alphaGen.args[0];
+ a = bound( 0.0f, a, 1.0f );
+ c = R_FloatToByte( a );
+
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ bArray[3] = c;
+ break;
+ case ALPHAGEN_VERTEX:
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
+ bArray[3] = inArray[3];
+ break;
+ case ALPHAGEN_ONE_MINUS_VERTEX:
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 )
+ bArray[3] = 255 - inArray[3];
+ break;
+ case ALPHAGEN_ENTITY:
+ if( entityAlpha )
+ break;
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ bArray[3] = RI.currententity->color[3];
+ break;
+ case ALPHAGEN_OUTLINE:
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ bArray[3] = RI.currententity->outlineColor[3];
+ break;
+ case ALPHAGEN_SPECULAR:
+ VectorSubtract( RI.viewOrigin, RI.currententity->origin, t );
+ if( !Matrix_Compare( RI.currententity->axis, axis_identity ) )
+ Matrix_TransformVector( RI.currententity->axis, t, v );
+ else
+ VectorCopy( t, v );
+
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ {
+ VectorSubtract( v, vertsArray[i], t );
+ c = VectorLength( t );
+ a = DotProduct( t, normalsArray[i] ) / max( 0.1, c );
+ a = pow( a, pass->alphaGen.args[0] );
+ bArray[3] = a <= 0 ? 0 : R_FloatToByte( a );
+ }
+ break;
+ case ALPHAGEN_DOT:
+ if( !Matrix_Compare( RI.currententity->axis, axis_identity ) )
+ Matrix_TransformVector( RI.currententity->axis, RI.vpn, v );
+ else
+ VectorCopy( RI.vpn, v );
+
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ {
+ a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a;
+ bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) );
+ }
+ break;
+ case ALPHAGEN_ONE_MINUS_DOT:
+ if( !Matrix_Compare( RI.currententity->axis, axis_identity ) )
+ Matrix_TransformVector( RI.currententity->axis, RI.vpn, v );
+ else
+ VectorCopy( RI.vpn, v );
+
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ {
+ a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a;a = 1.0f - a;
+ bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) );
+ }
+ default:
+ break;
+ }
+
+ if( r_colorFog )
+ {
+ float dist, vdist;
+ cplane_t *fogPlane;
+ vec3_t viewtofog;
+ float fogNormal[3], vpnNormal[3];
+ float fogDist, vpnDist, fogShaderDistScale;
+ int fogptype;
+ bool alphaFog;
+ int blendsrc, blenddst;
+
+ blendsrc = pass->glState & GLSTATE_SRCBLEND_MASK;
+ blenddst = pass->glState & GLSTATE_DSTBLEND_MASK;
+ if(( blendsrc != GLSTATE_SRCBLEND_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_SRC_ALPHA ) && ( blendsrc != GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ))
+ alphaFog = false;
+ else alphaFog = true;
+
+ fogPlane = r_colorFog->visibleplane;
+ fogShaderDistScale = 1.0 / (r_colorFog->shader->fog_dist - r_colorFog->shader->fog_clearDist);
+ dist = RI.fog_dist_to_eye[r_colorFog-r_worldbrushmodel->fogs];
+
+ if( r_currentShader->flags & SHADER_SKYPARMS )
+ {
+ if( dist > 0 )
+ VectorScale( fogPlane->normal, -dist, viewtofog );
+ else
+ VectorClear( viewtofog );
+ }
+ else
+ {
+ VectorCopy( RI.currententity->origin, viewtofog );
+ }
+
+ vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * fogShaderDistScale * RI.currententity->scale;
+ vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * fogShaderDistScale * RI.currententity->scale;
+ vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * fogShaderDistScale * RI.currententity->scale;
+ vpnDist = (( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] )
+ + r_colorFog->shader->fog_clearDist) * fogShaderDistScale;
+
+ bArray = colorArray[0];
+ if( dist < 0 )
+ { // camera is inside the fog
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ {
+ temp = DotProduct( vertsArray[i], vpnNormal ) - vpnDist;
+ c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF;
+
+ if( alphaFog )
+ {
+ bArray[3] = ( bArray[3] * c ) >> 16;
+ }
+ else
+ {
+ bArray[0] = ( bArray[0] * c ) >> 16;
+ bArray[1] = ( bArray[1] * c ) >> 16;
+ bArray[2] = ( bArray[2] * c ) >> 16;
+ }
+ }
+ }
+ else
+ {
+ fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale;
+ fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale;
+ fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale;
+ fogptype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) );
+ fogDist = fogPlane->dist - DotProduct( viewtofog, fogPlane->normal );
+
+ for( i = 0; i < r_backacc.numColors; i++, bArray += 4 )
+ {
+ if( fogptype < 3 )
+ vdist = vertsArray[i][fogptype] - fogDist;
+ else
+ vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist;
+
+ if( vdist < 0 )
+ {
+ temp = ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist );
+ c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF;
+
+ if( alphaFog )
+ {
+ bArray[3] = ( bArray[3] * c ) >> 16;
+ }
+ else
+ {
+ bArray[0] = ( bArray[0] * c ) >> 16;
+ bArray[1] = ( bArray[1] * c ) >> 16;
+ bArray[2] = ( bArray[2] * c ) >> 16;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+================
+R_ShaderpassBlendmode
+================
+*/
+static int R_ShaderpassBlendmode( int passFlags )
+{
+ if( passFlags & SHADERSTAGE_BLEND_REPLACE )
+ return GL_REPLACE;
+ if( passFlags & SHADERSTAGE_BLEND_MODULATE )
+ return GL_MODULATE;
+ if( passFlags & SHADERSTAGE_BLEND_ADD )
+ return GL_ADD;
+ if( passFlags & SHADERSTAGE_BLEND_DECAL )
+ return GL_DECAL;
+ return 0;
+}
+
+/*
+================
+R_SetShaderState
+================
+*/
+static void R_SetShaderState( void )
+{
+ int state;
+
+ // Face culling
+ if( !gl_cull->integer || ( r_features & MF_NOCULL ))
+ GL_Cull( 0 );
+ else if( r_currentShader->flags & SHADER_CULL_FRONT )
+ GL_Cull( GL_FRONT );
+ else if( r_currentShader->flags & SHADER_CULL_BACK )
+ GL_Cull( GL_BACK );
+ else GL_Cull( 0 );
+
+ state = 0;
+ if( r_currentShader->flags & SHADER_POLYGONOFFSET || RI.params & RP_SHADOWMAPVIEW )
+ state |= GLSTATE_OFFSET_FILL;
+ if( r_currentShader->type == SHADER_FLARE )
+ state |= GLSTATE_NO_DEPTH_TEST;
+ r_currentShaderState = state;
+}
+
+/*
+================
+R_RenderMeshGeneric
+================
+*/
+void R_RenderMeshGeneric( void )
+{
+ const ref_stage_t *pass = r_accumPasses[0];
+
+ R_BindShaderpass( pass, NULL, 0 );
+ R_ModifyColor( pass );
+
+ if( pass->flags & SHADERSTAGE_BLEND_REPLACE )
+ GL_TexEnv( GL_REPLACE );
+ else
+ GL_TexEnv( GL_MODULATE );
+ GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ));
+
+ R_FlushArrays();
+}
+
+/*
+================
+R_RenderMeshMultitextured
+================
+*/
+void R_RenderMeshMultitextured( void )
+{
+ int i;
+ const ref_stage_t *pass = r_accumPasses[0];
+
+ R_BindShaderpass( pass, NULL, 0 );
+ R_ModifyColor( pass );
+
+ GL_TexEnv( GL_MODULATE );
+ GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX );
+
+ for( i = 1; i < r_numAccumPasses; i++ )
+ {
+ pass = r_accumPasses[i];
+ R_BindShaderpass( pass, NULL, i );
+ GL_TexEnv( R_ShaderpassBlendmode( pass->flags ) );
+ }
+
+ R_FlushArrays();
+}
+
+/*
+================
+R_RenderMeshCombined
+================
+*/
+void R_RenderMeshCombined( void )
+{
+ int i;
+ const ref_stage_t *pass = r_accumPasses[0];
+
+ R_BindShaderpass( pass, NULL, 0 );
+ R_ModifyColor( pass );
+
+ GL_TexEnv( GL_MODULATE );
+ GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX );
+
+ for( i = 1; i < r_numAccumPasses; i++ )
+ {
+ pass = r_accumPasses[i];
+ R_BindShaderpass( pass, NULL, i );
+
+ if( pass->flags & ( SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_BLEND_MODULATE ))
+ {
+ GL_TexEnv( GL_MODULATE );
+ }
+ else if( pass->flags & SHADERSTAGE_BLEND_ADD )
+ {
+ // these modes are best set with TexEnv, Combine4 would need much more setup
+ GL_TexEnv( GL_ADD );
+ }
+ else if( pass->flags & SHADERSTAGE_BLEND_DECAL )
+ {
+ // mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, they're added
+ // this way it can be possible to use GL_DECAL in both texture-units, while still looking good
+ // normal mutlitexturing would multiply the alpha-channel which looks ugly
+ GL_TexEnv( GL_COMBINE_ARB );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD );
+
+ pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
+
+ pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
+
+ pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
+ pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
+ }
+ else
+ {
+ Com_Assert( 1 );
+ }
+ }
+
+ R_FlushArrays();
+}
+
+/*
+================
+R_RenderMeshGLSL_Material
+================
+*/
+static void R_RenderMeshGLSL_Material( void )
+{
+ int i, tcgen;
+ int state;
+ bool breakIntoPasses = false;
+ int program, object;
+ int programFeatures = 0;
+ texture_t *base, *normalmap, *glossmap, *decalmap;
+ mat4x4_t unused;
+ vec3_t lightDir = { 0.0f, 0.0f, 0.0f };
+ vec4_t ambient = { 0.0f, 0.0f, 0.0f, 0.0f }, diffuse = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float offsetmappingScale;
+ superLightStyle_t *lightStyle;
+ ref_stage_t *pass = r_accumPasses[0];
+
+ // handy pointers
+ base = pass->textures[0];
+ normalmap = pass->textures[1];
+ glossmap = pass->textures[2];
+ decalmap = pass->textures[3];
+
+ Com_Assert( normalmap == NULL );
+
+ if( normalmap->samples == 4 )
+ offsetmappingScale = r_offsetmapping_scale->value * r_currentShader->offsetmapping_scale;
+ else // no alpha in normalmap, don't bother with offset mapping
+ offsetmappingScale = 0;
+
+ if( GL_Support( R_GLSL_BRANCHING ))
+ programFeatures |= PROGRAM_APPLY_BRANCHING;
+ if( GL_Support( R_GLSL_NO_HALF_TYPES ))
+ programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES;
+ if( RI.params & RP_CLIPPLANE )
+ programFeatures |= PROGRAM_APPLY_CLIPPING;
+
+ if( r_currentMeshBuffer->infokey > 0 )
+ {
+ // world surface
+ int srcAlpha = (pass->flags & SHADERSTAGE_BLEND_DECAL);
+
+ // CHECKTHIS: this is right ?
+ srcAlpha |= (pass->glState & (GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA));
+
+ if( !( r_offsetmapping->integer & 1 ) )
+ offsetmappingScale = 0;
+
+ if( r_lightmap->integer || ( r_currentDlightBits && !pass->textures[5] ) )
+ {
+ if( !srcAlpha )
+ base = tr.whiteTexture; // white
+ else
+ programFeatures |= PROGRAM_APPLY_BASETEX_ALPHA_ONLY;
+ }
+
+ // we use multipass for dynamic lights, so bind the white texture
+ // instead of base in GLSL program and add another modulative pass (diffusemap)
+ if( !r_lightmap->integer && ( r_currentDlightBits && !pass->textures[5] ) )
+ {
+ breakIntoPasses = true;
+ r_GLSLpasses[1] = *pass;
+ r_GLSLpasses[1].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_MODULATE;
+ r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0);
+
+ // decal
+ if( decalmap )
+ {
+ r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY;
+ r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY;
+
+ r_GLSLpasses[2] = *pass;
+ r_GLSLpasses[2].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_DECAL;
+ r_GLSLpasses[2].glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0);
+ r_GLSLpasses[2].textures[0] = decalmap;
+ }
+
+ if( offsetmappingScale <= 0 )
+ {
+ r_GLSLpasses[1].program = r_GLSLpasses[2].program = NULL;
+ r_GLSLpasses[1].program_type = r_GLSLpasses[2].program_type = PROGRAM_TYPE_NONE;
+ }
+ else
+ {
+ r_GLSLpasses[1].textures[2] = r_GLSLpasses[2].textures[2] = NULL; // no specular
+ r_GLSLpasses[1].textures[3] = r_GLSLpasses[2].textures[3] = NULL; // no decal
+ r_GLSLpasses[1].textures[6] = r_GLSLpasses[6].textures[2] = ((texture_t *)1); // HACKHACK no ambient
+ }
+ }
+ }
+ else if( ( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY )
+ { // polys
+ if( !( r_offsetmapping->integer & 2 ) )
+ offsetmappingScale = 0;
+
+ R_BuildTangentVectors( r_backacc.numVerts, vertsArray, normalsArray, coordsArray, r_backacc.numElems/3, elemsArray, inSVectorsArray );
+ }
+ else
+ { // models
+ if( !( r_offsetmapping->integer & 4 ) )
+ offsetmappingScale = 0;
+ }
+
+ tcgen = pass->tcgen; // store the original tcgen
+
+ pass->tcgen = TCGEN_BASE;
+ R_BindShaderpass( pass, base, 0 );
+ if( !breakIntoPasses )
+ {
+ // calculate the fragment color
+ R_ModifyColor( pass );
+ }
+ else
+ { // rgbgen identity (255,255,255,255)
+ r_backacc.numColors = 1;
+ colorArray[0][0] = colorArray[0][1] = colorArray[0][2] = colorArray[0][3] = 255;
+ }
+
+ // set shaderpass state (blending, depthwrite, etc)
+ state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
+ GL_SetState( state );
+
+ // don't waste time on processing GLSL programs with zero colormask
+ if( RI.params & RP_SHADOWMAPVIEW )
+ {
+ pass->tcgen = tcgen; // restore original tcgen
+ R_FlushArrays();
+ return;
+ }
+
+ // we only send S-vectors to GPU and recalc T-vectors as cross product
+ // in vertex shader
+ pass->tcgen = TCGEN_SVECTORS;
+ GL_Bind( 1, normalmap ); // normalmap
+ GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
+ R_VertexTCBase( pass, 1, unused );
+
+ if( glossmap && r_lighting_glossintensity->value )
+ {
+ programFeatures |= PROGRAM_APPLY_SPECULAR;
+ GL_Bind( 2, glossmap ); // gloss
+ GL_SetTexCoordArrayMode( 0 );
+ }
+
+ if( decalmap && !breakIntoPasses )
+ {
+ programFeatures |= PROGRAM_APPLY_DECAL;
+ GL_Bind( 3, decalmap ); // decal
+ GL_SetTexCoordArrayMode( 0 );
+ }
+
+ if( offsetmappingScale > 0 )
+ programFeatures |= r_offsetmapping_reliefmapping->integer ? PROGRAM_APPLY_RELIEFMAPPING : PROGRAM_APPLY_OFFSETMAPPING;
+
+ if( r_currentMeshBuffer->infokey > 0 )
+ { // world surface
+ lightStyle = r_superLightStyle;
+
+ // bind lightmap textures and set program's features for lightstyles
+ if( r_superLightStyle && r_superLightStyle->lightmapNum[0] >= 0 )
+ {
+ pass->tcgen = TCGEN_LIGHTMAP;
+
+ for( i = 0; i < LM_STYLES && r_superLightStyle->lightmapStyles[i] != 255; i++ )
+ {
+ programFeatures |= ( PROGRAM_APPLY_LIGHTSTYLE0 << i );
+
+ r_lightmapStyleNum[i+4] = i;
+ GL_Bind( i+4, tr.lightmapTextures[r_superLightStyle->lightmapNum[i]] ); // lightmap
+ GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
+ R_VertexTCBase( pass, i+4, unused );
+ }
+
+ if( i == 1 )
+ {
+ vec_t *rgb = r_lightStyles[r_superLightStyle->lightmapStyles[0]].rgb;
+
+ // PROGRAM_APPLY_FB_LIGHTMAP indicates that there's no need to renormalize
+ // the lighting vector for specular (saves 3 adds, 3 muls and 1 normalize per pixel)
+ if( rgb[0] == 1 && rgb[1] == 1 && rgb[2] == 1 )
+ programFeatures |= PROGRAM_APPLY_FB_LIGHTMAP;
+ }
+ }
+
+ if( !pass->textures[6] && !VectorCompare( mapConfig.ambient, vec3_origin ) )
+ {
+ VectorCopy( mapConfig.ambient, ambient );
+ programFeatures |= PROGRAM_APPLY_AMBIENT_COMPENSATION;
+ }
+ }
+ else
+ {
+ vec3_t temp;
+
+ lightStyle = NULL;
+ programFeatures |= PROGRAM_APPLY_DIRECTIONAL_LIGHT;
+
+ if( ( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY )
+ {
+ VectorCopy( r_polys[-r_currentMeshBuffer->infokey-1].normal, lightDir );
+ Vector4Set( ambient, 0, 0, 0, 0 );
+ Vector4Set( diffuse, 1, 1, 1, 1 );
+ }
+ else if( RI.currententity )
+ {
+ if( RI.currententity->flags & RF_FULLBRIGHT )
+ {
+ Vector4Set( ambient, 1, 1, 1, 1 );
+ Vector4Set( diffuse, 1, 1, 1, 1 );
+ }
+ else
+ {
+ // get weighted incoming direction of world and dynamic lights
+ R_LightForOrigin( RI.currententity->lightingOrigin, temp, ambient, diffuse,
+ RI.currententity->model ? RI.currententity->model->radius * RI.currententity->scale : 0 );
+
+ if( RI.currententity->flags & EF_MINLIGHT )
+ {
+ if( ambient[0] <= 0.1f || ambient[1] <= 0.1f || ambient[2] <= 0.1f )
+ VectorSet( ambient, 0.1f, 0.1f, 0.1f );
+ }
+
+ // rotate direction
+ Matrix_TransformVector( RI.currententity->axis, temp, lightDir );
+ }
+ }
+ }
+
+ pass->tcgen = tcgen; // restore original tcgen
+
+ program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
+ object = R_GetProgramObject( program );
+ if( object )
+ {
+ pglUseProgramObjectARB( object );
+
+ // update uniforms
+ R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, lightDir, ambient, diffuse, lightStyle,
+ true, 0, 0, 0, offsetmappingScale );
+
+ R_FlushArrays();
+
+ pglUseProgramObjectARB( 0 );
+ }
+
+ if( breakIntoPasses )
+ {
+ unsigned int oDB = r_currentDlightBits; // HACK HACK HACK
+ superLightStyle_t *oSL = r_superLightStyle;
+
+ R_AccumulatePass( &r_GLSLpasses[0] ); // dynamic lighting pass
+
+ if( offsetmappingScale )
+ {
+ r_superLightStyle = NULL;
+ r_currentDlightBits = 0;
+ }
+
+ R_AccumulatePass( &r_GLSLpasses[1] ); // modulate (diffusemap)
+
+ if( decalmap )
+ R_AccumulatePass( &r_GLSLpasses[2] ); // alpha-blended decal texture
+
+ if( offsetmappingScale )
+ {
+ r_superLightStyle = oSL;
+ r_currentDlightBits = oDB;
+ }
+ }
+}
+
+/*
+================
+R_RenderMeshGLSL_Distortion
+================
+*/
+static void R_RenderMeshGLSL_Distortion( void )
+{
+ int state, tcgen;
+ int program, object;
+ int programFeatures = 0;
+ mat4x4_t unused;
+ ref_stage_t *pass = r_accumPasses[0];
+ texture_t *portaltexture1, *portaltexture2;
+ bool frontPlane;
+
+ if( !( RI.params & ( RP_PORTALCAPTURED|RP_PORTALCAPTURED2 )))
+ return;
+
+ if( GL_Support( R_GLSL_BRANCHING ))
+ programFeatures |= PROGRAM_APPLY_BRANCHING;
+ if( GL_Support( R_GLSL_NO_HALF_TYPES ))
+ programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES;
+ if( RI.params & RP_CLIPPLANE )
+ programFeatures |= PROGRAM_APPLY_CLIPPING;
+
+ portaltexture1 = ( RI.params & RP_PORTALCAPTURED ) ? tr.portaltexture1 : tr.blackTexture;
+ portaltexture2 = ( RI.params & RP_PORTALCAPTURED2 ) ? tr.portaltexture2 : tr.blackTexture;
+
+ frontPlane = (PlaneDiff( RI.viewOrigin, &RI.portalPlane ) > 0 ? true : false);
+
+ tcgen = pass->tcgen; // store the original tcgen
+
+ R_BindShaderpass( pass, pass->textures[0], 0 ); // dudvmap
+
+ // calculate the fragment color
+ R_ModifyColor( pass );
+
+ if( frontPlane )
+ {
+ if( pass->alphaGen.type != ALPHAGEN_IDENTITY )
+ programFeatures |= PROGRAM_APPLY_DISTORTION_ALPHA;
+ }
+
+ // set shaderpass state (blending, depthwrite, etc)
+ state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
+ GL_SetState( state );
+
+ if( pass->textures[1] /* && ( RI.params & RP_PORTALCAPTURED )*/ )
+ {
+ // eyeDot
+ programFeatures |= PROGRAM_APPLY_EYEDOT;
+
+ pass->tcgen = TCGEN_SVECTORS;
+ GL_Bind( 1, pass->textures[1] ); // normalmap
+ GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY );
+ R_VertexTCBase( pass, 1, unused );
+ }
+
+ GL_Bind( 2, portaltexture1 ); // reflection
+ GL_Bind( 3, portaltexture2 ); // refraction
+
+ pass->tcgen = tcgen; // restore original tcgen
+
+ // update uniforms
+ program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
+ object = R_GetProgramObject( program );
+ if( object )
+ {
+ pglUseProgramObjectARB( object );
+
+ R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL,
+ frontPlane, tr.portaltexture1->width, tr.portaltexture1->height, 0, 0 );
+
+ R_FlushArrays();
+
+ pglUseProgramObjectARB( 0 );
+ }
+}
+
+/*
+================
+R_RenderMeshGLSL_Shadowmap
+================
+*/
+static void R_RenderMeshGLSL_Shadowmap( void )
+{
+ int i;
+ int state;
+ int program, object;
+ int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0;
+ ref_stage_t *pass = r_accumPasses[0];
+
+ if( r_shadows_pcf->integer == 2 )
+ programFeatures |= PROGRAM_APPLY_PCF2x2;
+ else if( r_shadows_pcf->integer == 3 )
+ programFeatures |= PROGRAM_APPLY_PCF3x3;
+
+ // update uniforms
+ program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
+ object = R_GetProgramObject( program );
+ if( !object )
+ return;
+
+ for( i = 0, r_currentCastGroup = r_shadowGroups; i < r_numShadowGroups; i++, r_currentCastGroup++ )
+ {
+ if( !( r_currentShadowBits & r_currentCastGroup->bit ) )
+ continue;
+
+ R_BindShaderpass( pass, r_currentCastGroup->depthTexture, 0 );
+
+ pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );
+ pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
+
+ // calculate the fragment color
+ R_ModifyColor( pass );
+
+ // set shaderpass state (blending, depthwrite, etc)
+ state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
+ GL_SetState( state );
+
+ pglUseProgramObjectARB( object );
+
+ R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true,
+ r_currentCastGroup->depthTexture->width, r_currentCastGroup->depthTexture->height,
+ r_currentCastGroup->projDist, 0 );
+
+ R_FlushArrays();
+
+ pglUseProgramObjectARB( 0 );
+
+ pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
+ }
+}
+
+/*
+================
+R_RenderMeshGLSL_Outline
+================
+*/
+static void R_RenderMeshGLSL_Outline( void )
+{
+ int faceCull;
+ int state;
+ int program, object;
+ int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0;
+ ref_stage_t *pass = r_accumPasses[0];
+
+ if( RI.params & RP_CLIPPLANE )
+ programFeatures |= PROGRAM_APPLY_CLIPPING;
+
+ // update uniforms
+ program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures );
+ object = R_GetProgramObject( program );
+ if( !object )
+ return;
+
+ faceCull = glState.faceCull;
+ GL_Cull( GL_BACK );
+
+ GL_SelectTexture( 0 );
+ GL_SetTexCoordArrayMode( 0 );
+
+ // calculate the fragment color
+ R_ModifyColor( pass );
+
+ // set shaderpass state (blending, depthwrite, etc)
+ state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX;
+ GL_SetState( state );
+
+ pglUseProgramObjectARB( object );
+
+ R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true,
+ 0, 0, RI.currententity->outlineHeight * r_outlines_scale->value, 0 );
+
+ R_FlushArrays();
+
+ pglUseProgramObjectARB( 0 );
+
+ GL_Cull( faceCull );
+}
+
+/*
+================
+R_RenderMeshGLSLProgrammed
+================
+*/
+static void R_RenderMeshGLSLProgrammed( void )
+{
+ const ref_stage_t *pass = ( ref_stage_t * )r_accumPasses[0];
+
+ switch( pass->program_type )
+ {
+ case PROGRAM_TYPE_MATERIAL:
+ R_RenderMeshGLSL_Material();
+ break;
+ case PROGRAM_TYPE_DISTORTION:
+ R_RenderMeshGLSL_Distortion();
+ break;
+ case PROGRAM_TYPE_SHADOWMAP:
+ R_RenderMeshGLSL_Shadowmap();
+ break;
+ case PROGRAM_TYPE_OUTLINE:
+ R_RenderMeshGLSL_Outline ();
+ break;
+ default:
+ MsgDev( D_WARN, "Unknown GLSL program type %i\n", pass->program_type );
+ break;
+ }
+}
+
+/*
+================
+R_RenderAccumulatedPasses
+================
+*/
+static void R_RenderAccumulatedPasses( void )
+{
+ const ref_stage_t *pass = r_accumPasses[0];
+
+ R_CleanUpTextureUnits( r_numAccumPasses );
+
+ if( pass->program )
+ {
+ r_numAccumPasses = 0;
+ R_RenderMeshGLSLProgrammed();
+ return;
+ }
+ if( pass->flags & SHADERSTAGE_DLIGHT )
+ {
+ r_numAccumPasses = 0;
+ R_AddDynamicLights( r_currentDlightBits, r_currentShaderState | ( pass->glState & r_currentShaderPassMask ));
+ return;
+ }
+ if( pass->flags & SHADERSTAGE_STENCILSHADOW )
+ {
+ r_numAccumPasses = 0;
+ R_PlanarShadowPass( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ));
+ return;
+ }
+
+ if( r_numAccumPasses == 1 )
+ R_RenderMeshGeneric();
+ else if( GL_Support( R_COMBINE_EXT ))
+ R_RenderMeshCombined();
+ else
+ R_RenderMeshMultitextured();
+
+ r_numAccumPasses = 0;
+}
+
+/*
+================
+R_AccumulatePass
+================
+*/
+static void R_AccumulatePass( ref_stage_t *pass )
+{
+ bool accumulate, renderNow;
+ const ref_stage_t *prevPass;
+
+ // for depth texture we render light's view to, ignore passes that do not write into depth buffer
+ if( ( RI.params & RP_SHADOWMAPVIEW ) && !( pass->glState & GLSTATE_DEPTHWRITE ))
+ return;
+
+ // see if there are any free texture units
+ renderNow = ( pass->flags & ( SHADERSTAGE_DLIGHT|SHADERSTAGE_STENCILSHADOW ) ) || pass->program;
+ accumulate = ( r_numAccumPasses < glConfig.max_texture_units ) && !renderNow;
+
+ if( accumulate )
+ {
+ if( !r_numAccumPasses )
+ {
+ r_accumPasses[r_numAccumPasses++] = pass;
+ return;
+ }
+
+ // ok, we've got several passes, diff against the previous
+ prevPass = r_accumPasses[r_numAccumPasses-1];
+
+ // see if depthfuncs and colors are good
+ if(
+ (( prevPass->glState ^ pass->glState ) & GLSTATE_DEPTHFUNC_EQ ) ||
+ ( pass->glState & GLSTATE_ALPHAFUNC ) ||
+ ( pass->rgbGen.type != RGBGEN_IDENTITY ) ||
+ ( pass->alphaGen.type != ALPHAGEN_IDENTITY ) ||
+ ( ( prevPass->glState & GLSTATE_ALPHAFUNC ) && !( pass->glState & GLSTATE_DEPTHFUNC_EQ ))
+ )
+ accumulate = false;
+
+ // see if blendmodes are good
+ if( accumulate )
+ {
+ int mode, prevMode;
+
+ mode = R_ShaderpassBlendmode( pass->flags );
+ if( mode )
+ {
+ prevMode = R_ShaderpassBlendmode( prevPass->flags );
+
+ if( GL_Support( R_COMBINE_EXT ))
+ {
+ if( prevMode == GL_REPLACE )
+ accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : true;
+ else if( prevMode == GL_ADD )
+ accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT );
+ else if( prevMode == GL_MODULATE )
+ accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE );
+ else
+ accumulate = false;
+ }
+ else /* if( GL_Support( R_ARB_MULTITEXTURE ))*/
+ {
+ if( prevMode == GL_REPLACE )
+ accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : ( mode != GL_DECAL );
+ else if( prevMode == GL_ADD )
+ accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT );
+ else if( prevMode == GL_MODULATE )
+ accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE );
+ else
+ accumulate = false;
+ }
+ }
+ else
+ {
+ accumulate = false;
+ }
+ }
+ }
+
+ // no, failed to accumulate
+ if( !accumulate )
+ {
+ if( r_numAccumPasses )
+ R_RenderAccumulatedPasses();
+ }
+
+ r_accumPasses[r_numAccumPasses++] = pass;
+ if( renderNow )
+ R_RenderAccumulatedPasses();
+}
+
+/*
+================
+R_SetupLightmapMode
+================
+*/
+void R_SetupLightmapMode( void )
+{
+ r_lightmapPasses[0].tcgen = TCGEN_LIGHTMAP;
+ r_lightmapPasses[0].rgbGen.type = RGBGEN_IDENTITY;
+ r_lightmapPasses[0].alphaGen.type = ALPHAGEN_IDENTITY;
+ r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE;
+ r_lightmapPasses[0].glState &= ~( GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK|GLSTATE_DEPTHFUNC_EQ );
+ r_lightmapPasses[0].flags |= SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE;
+// r_lightmapPasses[0].glState |= GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO;
+ if( r_lightmap->integer ) r_lightmapPasses[0].glState |= GLSTATE_DEPTHWRITE;
+}
+
+/*
+================
+R_RenderMeshBuffer
+================
+*/
+void R_RenderMeshBuffer( const meshbuffer_t *mb )
+{
+ int i;
+ msurface_t *surf;
+ ref_stage_t *pass;
+ mfog_t *fog;
+
+ if( !r_backacc.numVerts || !r_backacc.numElems )
+ {
+ R_ClearArrays();
+ return;
+ }
+
+ surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL;
+ if( surf )
+ r_superLightStyle = &r_superLightStyles[surf->superLightStyle];
+ else
+ r_superLightStyle = NULL;
+ r_currentMeshBuffer = mb;
+
+ MB_NUM2SHADER( mb->shaderkey, r_currentShader );
+
+ if( glState.in2DMode )
+ {
+ r_currentShaderTime = Sys_DoubleTime();
+ }
+ else
+ {
+ r_currentShaderTime = (double)RI.refdef.time;
+ if( RI.currententity )
+ {
+ r_currentShaderTime -= (double)RI.currententity->shaderTime;
+ if( r_currentShaderTime < 0 ) r_currentShaderTime = 0;
+ }
+ }
+
+ if( !r_triangleOutlines )
+ R_SetShaderState();
+
+ if( r_currentShader->numDeforms )
+ R_DeformVertices();
+
+ if( r_features & MF_KEEPLOCK )
+ r_backacc.c_totalKeptLocks++;
+ else
+ R_UnlockArrays();
+
+ if( r_triangleOutlines )
+ {
+ R_LockArrays( r_backacc.numVerts );
+
+ if( RI.params & RP_TRISOUTLINES )
+ R_DrawTriangles();
+ if( RI.params & RP_SHOWNORMALS )
+ R_DrawNormals();
+
+ R_ClearArrays();
+ return;
+ }
+
+ // extract the fog volume number from sortkey
+ if( !r_worldmodel )
+ fog = NULL;
+ else
+ MB_NUM2FOG( mb->sortkey, fog );
+ if( fog && !fog->shader )
+ fog = NULL;
+
+ // can we fog the geometry with alpha texture?
+ r_texFog = ( fog && ( ( r_currentShader->sort <= SORT_ALPHATEST &&
+ ( r_currentShader->flags & (SHADER_DEPTHWRITE|SHADER_SKYPARMS))) || r_currentShader->fog_dist ) ) ? fog : NULL;
+
+ // check if the fog volume is present but we can't use alpha texture
+ r_colorFog = ( fog && !r_texFog ) ? fog : NULL;
+
+ if( r_currentShader->type == SHADER_FLARE )
+ r_currentDlightBits = 0;
+ else
+ r_currentDlightBits = surf ? mb->dlightbits : 0;
+
+ r_currentShadowBits = mb->shadowbits & RI.shadowBits;
+
+ R_LockArrays( r_backacc.numVerts );
+
+ // accumulate passes for dynamic merging
+ for( i = 0, pass = r_currentShader->stages; i < r_currentShader->num_stages; i++, pass++ )
+ {
+ if( !pass->program )
+ {
+ if( pass->flags & SHADERSTAGE_LIGHTMAP )
+ {
+ int j, k, l, u;
+
+ // no valid lightmaps, goodbye
+ if( !r_superLightStyle || r_superLightStyle->lightmapNum[0] < 0 || r_superLightStyle->lightmapStyles[0] == 255 )
+ continue;
+
+ // try to apply lightstyles
+ if(( !( pass->glState & (GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK)) || ( pass->flags & SHADERSTAGE_BLEND_MODULATE )) && ( pass->rgbGen.type == RGBGEN_IDENTITY ) && ( pass->alphaGen.type == ALPHAGEN_IDENTITY ))
+ {
+ vec3_t colorSum, color;
+
+ // the first pass is always GL_MODULATE or GL_REPLACE
+ // other passes are GL_ADD
+ r_lightmapPasses[0] = *pass;
+
+ for( j = 0, l = 0, u = 0; j < LM_STYLES && r_superLightStyle->lightmapStyles[j] != 255; j++ )
+ {
+ VectorCopy( r_lightStyles[r_superLightStyle->lightmapStyles[j]].rgb, colorSum );
+ VectorClear( color );
+
+ for( ; ; l++ )
+ {
+ for( k = 0; k < 3; k++ )
+ {
+ colorSum[k] -= color[k];
+ color[k] = bound( 0, colorSum[k], 1 );
+ }
+
+ if( l )
+ {
+ if( !color[0] && !color[1] && !color[2] )
+ break;
+ if( l == MAX_TEXTURE_UNITS+1 )
+ r_lightmapPasses[0] = r_lightmapPasses[1];
+ u = l % ( MAX_TEXTURE_UNITS+1 );
+ }
+
+ if( VectorCompare( color, colorWhite ) )
+ {
+ r_lightmapPasses[u].rgbGen.type = RGBGEN_IDENTITY;
+ }
+ else
+ {
+ if( !l )
+ {
+ r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE;
+ r_lightmapPasses[0].flags |= SHADERSTAGE_BLEND_MODULATE;
+ }
+ r_lightmapPasses[u].rgbGen.type = RGBGEN_CONST;
+ VectorCopy( color, r_lightmapPasses[u].rgbGen.args );
+ }
+
+ if( r_lightmap->integer && !l )
+ R_SetupLightmapMode();
+ R_AccumulatePass( &r_lightmapPasses[u] );
+ r_lightmapStyleNum[r_numAccumPasses - 1] = j;
+ }
+ }
+ }
+ else
+ {
+ if( r_lightmap->integer )
+ {
+ R_SetupLightmapMode();
+ pass = r_lightmapPasses;
+ }
+ R_AccumulatePass( pass );
+ r_lightmapStyleNum[r_numAccumPasses - 1] = 0;
+ }
+ continue;
+ }
+ else if( r_lightmap->integer && ( r_currentShader->flags & SHADER_HASLIGHTMAP ))
+ continue;
+ if(( pass->flags & SHADERSTAGE_PORTALMAP ) && !( RI.params & RP_PORTALCAPTURED ))
+ continue;
+ if(( pass->flags & SHADERSTAGE_DETAIL ) && !r_detailtextures->integer )
+ continue;
+ if(( pass->flags & SHADERSTAGE_DLIGHT ) && !r_currentDlightBits )
+ continue;
+ }
+
+ R_AccumulatePass( pass );
+ }
+
+ // accumulate dynamic lights pass and fog pass if any
+ if( r_currentDlightBits && !( r_currentShader->flags & SHADER_NO_MODULATIVE_DLIGHTS ))
+ {
+ if( !r_lightmap->integer || !( r_currentShader->flags & SHADER_HASLIGHTMAP ))
+ R_AccumulatePass( &r_dlightsPass );
+ }
+
+ if( r_currentShadowBits && ( r_currentShader->sort >= SORT_OPAQUE ) && ( r_currentShader->sort <= SORT_ALPHATEST ))
+ R_AccumulatePass( &r_GLSLpasses[3] );
+
+ if( GL_Support( R_SHADER_GLSL100_EXT ) && RI.currententity && RI.currententity->outlineHeight && r_outlines_scale->value > 0
+ && ( r_currentShader->sort == SORT_OPAQUE ) && ( r_currentShader->flags & SHADER_CULL_FRONT ) )
+ R_AccumulatePass( &r_GLSLpassOutline );
+
+ if( r_texFog && r_texFog->shader )
+ {
+ r_fogPass.textures[0] = tr.fogTexture;
+ if( !r_currentShader->num_stages || r_currentShader->fog_dist || ( r_currentShader->flags & SHADER_SKYPARMS ) )
+ r_fogPass.glState &= ~GLSTATE_DEPTHFUNC_EQ;
+ else r_fogPass.glState |= GLSTATE_DEPTHFUNC_EQ;
+ R_AccumulatePass( &r_fogPass );
+ }
+
+ // flush any remaining passes
+ if( r_numAccumPasses )
+ R_RenderAccumulatedPasses();
+
+ R_ClearArrays();
+
+ pglMatrixMode( GL_MODELVIEW );
+}
+
+/*
+================
+R_BackendCleanUpTextureUnits
+================
+*/
+void R_BackendCleanUpTextureUnits( void )
+{
+ R_CleanUpTextureUnits( 1 );
+
+ GL_LoadIdentityTexMatrix();
+ pglMatrixMode( GL_MODELVIEW );
+
+ GL_DisableAllTexGens();
+ GL_SetTexCoordArrayMode( 0 );
+}
+
+/*
+================
+R_BackendSetPassMask
+================
+*/
+void R_BackendSetPassMask( int mask )
+{
+ r_currentShaderPassMask = mask;
+}
+
+/*
+================
+R_BackendResetPassMask
+================
+*/
+void R_BackendResetPassMask( void )
+{
+ r_currentShaderPassMask = GLSTATE_MASK;
+}
+
+/*
+================
+R_BackendBeginTriangleOutlines
+================
+*/
+void R_BackendBeginTriangleOutlines( void )
+{
+ r_triangleOutlines = true;
+ pglColor4fv( colorWhite );
+
+ GL_Cull( 0 );
+ GL_SetState( GLSTATE_NO_DEPTH_TEST );
+ pglDisable( GL_TEXTURE_2D );
+ pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+}
+
+/*
+================
+R_BackendEndTriangleOutlines
+================
+*/
+void R_BackendEndTriangleOutlines( void )
+{
+ r_triangleOutlines = false;
+ pglColor4fv( colorWhite );
+ GL_SetState( 0 );
+ pglEnable( GL_TEXTURE_2D );
+ pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+}
+
+/*
+================
+R_SetColorForOutlines
+================
+*/
+static _inline void R_SetColorForOutlines( void )
+{
+ int type = r_currentMeshBuffer->sortkey & 3;
+
+ switch( type )
+ {
+ case MB_MODEL:
+ if( r_currentMeshBuffer->infokey < 0 )
+ pglColor4fv( colorRed );
+ else
+ pglColor4fv( colorWhite );
+ break;
+ case MB_SPRITE:
+ pglColor4fv( colorBlue );
+ break;
+ case MB_POLY:
+ pglColor4fv( colorGreen );
+ break;
+ }
+}
+
+/*
+================
+R_DrawTriangles
+================
+*/
+static void R_DrawTriangles( void )
+{
+ if( r_showtris->integer == 2 )
+ R_SetColorForOutlines();
+
+ if( GL_Support( R_DRAW_RANGEELEMENTS_EXT ))
+ pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
+ else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray );
+}
+
+/*
+================
+R_DrawNormals
+================
+*/
+static void R_DrawNormals( void )
+{
+ unsigned int i;
+
+ if( r_shownormals->integer == 2 )
+ R_SetColorForOutlines();
+
+ pglBegin( GL_LINES );
+ for( i = 0; i < r_backacc.numVerts; i++ )
+ {
+ pglVertex3fv( vertsArray[i] );
+ pglVertex3f( vertsArray[i][0] + normalsArray[i][0], vertsArray[i][1] + normalsArray[i][1], vertsArray[i][2] + normalsArray[i][2] );
+ }
+ pglEnd();
+}
+
+static void R_DrawLine( int color, int numpoints, const float *points, const int *elements )
+{
+ int i = numpoints - 1;
+ vec3_t p0, p1;
+
+ VectorSet( p0, points[i*3+0], points[i*3+1], points[i*3+2] );
+ if( r_physbdebug->integer == 1 ) ConvertPositionToGame( p0 );
+
+ for( i = 0; i < numpoints; i++ )
+ {
+ VectorSet( p1, points[i*3+0], points[i*3+1], points[i*3+2] );
+ if( r_physbdebug->integer == 1 ) ConvertPositionToGame( p1 );
+
+ pglColor4fv( UnpackRGBA( color ));
+ pglVertex3fv( p0 );
+ pglVertex3fv( p1 );
+
+ VectorCopy( p1, p0 );
+ }
+}
+
+/*
+================
+R_DrawPhysDebug
+================
+*/
+void R_DrawPhysDebug( void )
+{
+ if( r_physbdebug->integer )
+ {
+ // physic debug
+ pglLoadMatrixf( RI.worldviewMatrix );
+ pglBegin( GL_LINES );
+ ri.ShowCollision( R_DrawLine );
+ pglEnd();
+ }
+}
\ No newline at end of file
diff --git a/render/r_bloom.c b/render/r_bloom.c
index 8cf0a23c..d2c65afd 100644
--- a/render/r_bloom.c
+++ b/render/r_bloom.c
@@ -377,7 +377,6 @@ static void R_Bloom_GeneratexDiamonds( void )
scale = r_bloom_intensity->value * 0.5f;
break;
default:
-// case 8:
k = 4;
diamond = &Diamond8x[0][0];
scale = r_bloom_intensity->value * 0.3f;
diff --git a/render/r_image.c b/render/r_image.c
index 4b98c19f..834887ea 100644
--- a/render/r_image.c
+++ b/render/r_image.c
@@ -276,10 +276,6 @@ void R_SetTextureParameters( void )
for( i = 0, texture = r_textures; i < r_numTextures; i++, texture++ )
{
if( !texture->texnum ) continue; // free slot
-
-
- continue;
-
GL_Bind( GL_TEXTURE0, texture );
if( texture->flags & TF_DEPTHMAP )
@@ -558,13 +554,10 @@ static void R_TextureFormat( texture_t *tex, bool compress )
}
}
-void R_RoundImageDimensions( int *width, int *height, int *depth )
+void R_RoundImageDimensions( int *width, int *height, int *depth, bool force )
{
int scaledWidth, scaledHeight, scaledDepth;
- if( GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
- return; // nothing to resample
-
if( *depth > 1 && !GL_Support( R_TEXTURE_3D_EXT ))
return; // nothing to resample
@@ -572,10 +565,13 @@ void R_RoundImageDimensions( int *width, int *height, int *depth )
scaledHeight = *height;
scaledDepth = *depth;
- // find nearest power of two, rounding down if desired
- scaledWidth = NearestPOW( scaledWidth, gl_round_down->integer );
- scaledHeight = NearestPOW( scaledHeight, gl_round_down->integer );
- scaledDepth = NearestPOW( scaledDepth, gl_round_down->integer );
+ if( force || !GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
+ {
+ // find nearest power of two, rounding down if desired
+ scaledWidth = NearestPOW( scaledWidth, gl_round_down->integer );
+ scaledHeight = NearestPOW( scaledHeight, gl_round_down->integer );
+ scaledDepth = NearestPOW( scaledDepth, gl_round_down->integer );
+ }
if( image_desc.tflags & TF_SKYSIDE )
{
@@ -874,7 +870,7 @@ bool R_GetPixelFormat( const char *name, rgbdata_t *pic, uint tex_flags )
else image_desc.texType = TEX_GENERIC;
// calc immediate buffers
- R_RoundImageDimensions( &w, &h, &d );
+ R_RoundImageDimensions( &w, &h, &d, false );
image_desc.source = Mem_Alloc( r_imagepool, s * 4 ); // source buffer
image_desc.scaled = Mem_Alloc( r_imagepool, w * h * d * 4 ); // scaled buffer
@@ -1541,6 +1537,37 @@ static rgbdata_t *R_IncludeDepthmap( rgbdata_t *in1, rgbdata_t *in2 )
return in1;
}
+/*
+================
+R_ClearPixels
+
+clear specified area: color or alpha
+================
+*/
+static rgbdata_t *R_ClearPixels( rgbdata_t *in, bool clearAlpha )
+{
+ int i;
+ byte *pic;
+
+ // make sure what we processing RGBA images
+ in = R_ForceImageToRGBA( in );
+ pic = in->buffer;
+
+ if( clearAlpha )
+ {
+ for( i = 0; i < in->width * in->height && in->flags & IMAGE_HAS_ALPHA; i++ )
+ pic[(i<<2)+3] = 0xFF;
+ }
+ else
+ {
+ // clear color or greyscale image otherwise
+ for( i = 0; i < in->width * in->height; i++ )
+ pic[(i<<2)+0] = pic[(i<<2)+1] = pic[(i<<2)+2] = 0xFF;
+ }
+ return in;
+}
+
+
/*
=================
R_ParseAdd
@@ -2528,6 +2555,7 @@ static rgbdata_t *R_ParseDepthmap( script_t *script, int *samples, texFlags_t *f
return NULL;
}
+ *samples = 3;
pic2 = R_LoadImage( script, token.string, NULL, 0, &samples2, flags );
if( !pic2 ) return pic1; // don't free normalmap
@@ -2558,6 +2586,65 @@ static rgbdata_t *R_ParseDepthmap( script_t *script, int *samples, texFlags_t *f
return R_IncludeDepthmap( pic1, pic2 );
}
+/*
+=================
+R_ParseClearPixels
+=================
+*/
+static rgbdata_t *R_ParseClearPixels( script_t *script, int *samples, texFlags_t *flags )
+{
+ token_t token;
+ rgbdata_t *pic;
+ bool clearAlpha;
+
+ Com_ReadToken( script, 0, &token );
+ if( com.stricmp( token.string, "(" ))
+ {
+ MsgDev( D_WARN, "expected '(', found '%s' instead for 'clearPixels'\n", token.string );
+ return NULL;
+ }
+
+ if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token ))
+ {
+ MsgDev( D_WARN, "missing parameters for 'clearPixels'\n" );
+ return NULL;
+ }
+
+ pic = R_LoadImage( script, token.string, NULL, 0, samples, flags );
+ if( !pic ) return NULL;
+
+ Com_ReadToken( script, 0, &token );
+ if( !com.stricmp( token.string, "alpha" ))
+ {
+ Com_ReadToken( script, 0, &token );
+ clearAlpha = true;
+ }
+ else if( !com.stricmp( token.string, "color" ))
+ {
+ Com_ReadToken( script, 0, &token );
+ clearAlpha = false;
+ }
+ else if( !com.stricmp( token.string, ")" ))
+ {
+ Com_SaveToken( script, &token );
+ clearAlpha = false; // clear color as default
+ }
+ else Com_ReadToken( script, 0, &token ); // skip unknown token
+
+ if( com.stricmp( token.string, ")" ))
+ {
+ MsgDev( D_WARN, "expected ')', found '%s' instead for 'clearPixels'\n", token.string );
+ FS_FreeImage( pic );
+ return NULL;
+ }
+
+ *samples = clearAlpha ? 3 : 1;
+ if( clearAlpha ) *flags &= ~TF_ALPHA;
+ *flags &= ~TF_INTENSITY;
+
+ return R_ClearPixels( pic, clearAlpha );
+}
+
/*
=================
R_LoadImage
@@ -2595,6 +2682,8 @@ static rgbdata_t *R_LoadImage( script_t *script, const char *name, const byte *b
return R_ParseSmoothNormals( script, samples, flags );
else if( !com.stricmp( name, "mergeDepthmap" ))
return R_ParseDepthmap( script, samples, flags );
+ else if( !com.stricmp( name, "clearPixels" ))
+ return R_ParseClearPixels( script, samples, flags );
else if( !com.stricmp( name, "Studio" ))
return R_ParseStudioSkin( script, samples, flags );
else if( !com.stricmp( name, "Sprite" ))
@@ -2661,7 +2750,15 @@ void GL_GenerateMipmaps( const byte *buffer, texture_t *tex, int side )
void GL_TexFilter( texture_t *tex )
{
// set texture filter
- if( tex->flags & TF_NOMIPMAP )
+ if( tex->flags & TF_DEPTHMAP )
+ {
+ pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, r_textureDepthFilter );
+ pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, r_textureDepthFilter );
+
+ if( GL_Support( R_ANISOTROPY_EXT ))
+ pglTexParameterf( tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f );
+ }
+ else if( tex->flags & TF_NOMIPMAP )
{
pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -2717,7 +2814,7 @@ static void R_UploadTexture( rgbdata_t *pic, texture_t *tex )
tex->width = tex->srcWidth;
tex->height = tex->srcHeight;
- R_RoundImageDimensions( &tex->width, &tex->height, &tex->depth );
+ R_RoundImageDimensions( &tex->width, &tex->height, &tex->depth, false );
// check if it should be compressed
if( !gl_compress_textures->integer || (tex->flags & TF_UNCOMPRESSED))
@@ -2734,7 +2831,6 @@ static void R_UploadTexture( rgbdata_t *pic, texture_t *tex )
case PF_DXT5: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
default: dxtformat = false; break;
}
-
pglGenTextures( 1, &tex->texnum );
GL_Bind( GL_TEXTURE0, tex );
@@ -3357,7 +3453,7 @@ static rgbdata_t *R_InitCoronaTexture( int *flags, int *samples )
R_InitScreenTexture
==================
*/
-static void R_InitScreenTexture( texture_t **texture, const char *name, int id, int screenWidth, int screenHeight, int size, int flags, int samples )
+static void R_InitScreenTexture( texture_t **ptr, const char *name, int id, int screenWidth, int screenHeight, int size, int flags, int samples )
{
int limit;
int width, height;
@@ -3367,43 +3463,36 @@ static void R_InitScreenTexture( texture_t **texture, const char *name, int id,
limit = glConfig.max_2d_texture_size;
if( size ) limit = min( limit, size );
- if( GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
- {
- width = min( screenWidth, limit );
- height = min( screenHeight, limit );
- }
- else
- {
- limit = min( limit, min( screenWidth, screenHeight ));
- for( size = 2; size <= limit; size <<= 1 );
- width = height = size >> 1;
- }
+ limit = min( limit, min( screenWidth, screenHeight ));
+ for( size = 2; size <= limit; size <<= 1 );
+ width = height = size >> 1;
- if( !( *texture ) || ( *texture )->width != width || ( *texture )->height != height )
+ if( !(*ptr) || (*ptr)->width != width || (*ptr)->height != height )
{
byte *data = NULL;
- if( !*texture )
+ if( !*ptr )
{
- string uploadName;
+ string name;
- com.snprintf( uploadName, sizeof( uploadName ), "***%s%i***", name, id );
+ com.snprintf( name, sizeof( name ), "***%s%i***", name, id );
r_screen.width = width;
r_screen.height = height;
- r_screen.depth = r_screen.numMips = 1;
r_screen.type = PF_RGB_24;
r_screen.buffer = data;
+ r_screen.depth = r_screen.numMips = 1;
r_screen.size = width * height * samples;
- *texture = R_LoadTexture( uploadName, &r_screen, samples, flags );
+ *ptr = R_LoadTexture( name, &r_screen, samples, flags );
return;
}
- GL_Bind( 0, *texture );
- ( *texture )->width = width;
- ( *texture )->height = height;
- R_Upload32( &data, width, height, flags, &( ( *texture )->width ), &( ( *texture )->height ),
- &( ( *texture )->samples ), false );
+ GL_Bind( 0, *ptr );
+ (*ptr)->width = width;
+ (*ptr)->height = height;
+ R_RoundImageDimensions(&((*ptr)->width), &((*ptr)->height), &((*ptr)->depth), true );
+ pglTexImage2D( GL_TEXTURE_2D, 0, (*ptr)->format, (*ptr)->width, (*ptr)->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
+ GL_TexFilter( *ptr );
}
}
@@ -3643,254 +3732,4 @@ void R_ShutdownImages( void )
r_numTextures = 0;
tr.portaltexture1 = NULL;
tr.portaltexture2 = NULL;
-}
-
-// to be removed
-/*
-===============
-R_UploadFormat
-===============
-*/
-static int R_UploadFormat( int samples, bool noCompress )
-{
- int bits = r_texturebits->integer;
-
- if( GL_Support( R_TEXTURE_COMPRESSION_EXT ) && !noCompress )
- {
- if( samples == 3 )
- return GL_COMPRESSED_RGB_ARB;
- return GL_COMPRESSED_RGBA_ARB;
- }
-
- if( samples == 3 )
- {
- if( bits == 16 )
- return GL_RGB5;
- else if( bits == 32 )
- return GL_RGB8;
- return GL_RGB;
- }
-
- if( bits == 16 )
- return GL_RGBA4;
- else if( bits == 32 )
- return GL_RGBA8;
- return GL_RGBA;
-}
-
-/*
-===============
-R_Upload32
-===============
-*/
-void R_Upload32( byte **data, int width, int height, int flags, int *upload_width, int *upload_height, int *samples, bool subImage )
-{
- int i, c, comp, format;
- int target, target2;
- int numTextures;
- uint *scaled = NULL;
- int scaledWidth, scaledHeight;
-
- Com_Assert( samples == NULL );
-
- if( GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
- {
- scaledWidth = width;
- scaledHeight = height;
- }
- else
- {
- for( scaledWidth = 1; scaledWidth < width; scaledWidth <<= 1 );
- for( scaledHeight = 1; scaledHeight < height; scaledHeight <<= 1 );
- }
-
- if( flags & TF_SKYSIDE )
- {
- // let people sample down the sky textures for speed
- scaledWidth >>= r_skymip->integer;
- scaledHeight >>= r_skymip->integer;
- }
- else if( !( flags & TF_NOPICMIP ) )
- {
- // let people sample down the world textures for speed
- scaledWidth >>= r_picmip->integer;
- scaledHeight >>= r_picmip->integer;
- }
-
- // don't ever bother with > maxSize textures
- if( flags & TF_CUBEMAP )
- {
- numTextures = 6;
- target = GL_TEXTURE_CUBE_MAP_ARB;
- target2 = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
- scaledWidth = bound( 1, scaledWidth, glConfig.max_cubemap_texture_size );
- scaledHeight = bound( 1, scaledHeight, glConfig.max_cubemap_texture_size );
- }
- else
- {
- numTextures = 1;
- target = GL_TEXTURE_2D;
- target2 = GL_TEXTURE_2D;
- scaledWidth = bound( 1, scaledWidth, glConfig.max_2d_texture_size );
- scaledHeight = bound( 1, scaledHeight, glConfig.max_2d_texture_size );
- }
-
- if( upload_width )
- *upload_width = scaledWidth;
- if( upload_height )
- *upload_height = scaledHeight;
-
- // scan the texture for any non-255 alpha
- if( flags & ( TF_NORGB|TF_NOALPHA ) )
- {
- byte *scan;
-
- if( flags & TF_NORGB )
- {
- for( i = 0; i < numTextures && data[i]; i++ )
- {
- scan = ( byte * )data[i];
- for( c = width * height; c > 0; c--, scan += 4 )
- scan[0] = scan[1] = scan[2] = 255;
- }
- }
- else if( *samples == 4 )
- {
- for( i = 0; i < numTextures && data[i]; i++ )
- {
- scan = ( byte * )data[i] + 3;
- for( c = width * height; c > 0; c--, scan += 4 )
- *scan = 255;
- }
- *samples = 3;
- }
- }
-
- if( flags & TF_DEPTHMAP )
- {
- comp = GL_DEPTH_COMPONENT;
- format = GL_DEPTH_COMPONENT;
- }
- else
- {
- comp = R_UploadFormat( *samples, flags & TF_UNCOMPRESSED );
- format = GL_RGBA;
- }
-
- if( flags & TF_DEPTHMAP )
- {
- pglTexParameteri( target, GL_TEXTURE_MIN_FILTER, r_textureDepthFilter );
- pglTexParameteri( target, GL_TEXTURE_MAG_FILTER, r_textureDepthFilter );
-
- if( GL_Support( R_ANISOTROPY_EXT ))
- pglTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
- }
- else if( !( flags & TF_NOMIPMAP ) )
- {
- pglTexParameteri( target, GL_TEXTURE_MIN_FILTER, r_textureMinFilter );
- pglTexParameteri( target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter );
-
- if( GL_Support( R_ANISOTROPY_EXT ))
- pglTexParameterf( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_anisotropy->value );
- }
- else
- {
- pglTexParameteri( target, GL_TEXTURE_MIN_FILTER, r_textureMagFilter );
- pglTexParameteri( target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter );
-
- if( GL_Support( R_ANISOTROPY_EXT ))
- pglTexParameterf( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f );
- }
-
- // clamp if required
- if( !( flags & TF_CLAMP ) )
- {
- pglTexParameteri( target, GL_TEXTURE_WRAP_S, GL_REPEAT );
- pglTexParameteri( target, GL_TEXTURE_WRAP_T, GL_REPEAT );
- }
- else if( GL_Support( R_CLAMPTOEDGE_EXT ))
- {
- pglTexParameteri( target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
- pglTexParameteri( target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
- }
- else
- {
- pglTexParameteri( target, GL_TEXTURE_WRAP_S, GL_CLAMP );
- pglTexParameteri( target, GL_TEXTURE_WRAP_T, GL_CLAMP );
- }
-
- if(( scaledWidth == width ) && ( scaledHeight == height ) && ( flags & TF_NOMIPMAP ))
- {
- if( subImage )
- {
- for( i = 0; i < numTextures; i++, target2++ )
- pglTexSubImage2D( target2, 0, 0, 0, scaledWidth, scaledHeight, format, GL_UNSIGNED_BYTE, data[i] );
- }
- else
- {
- for( i = 0; i < numTextures; i++, target2++ )
- pglTexImage2D( target2, 0, comp, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_BYTE, data[i] );
- }
- }
- else
- {
- bool driverMipmap = GL_Support( R_SGIS_MIPMAPS_EXT ) && !(flags & TF_CUBEMAP);
-
- for( i = 0; i < numTextures; i++, target2++ )
- {
- unsigned int *mip;
-
- if( scaledWidth == width && scaledHeight == height && driverMipmap )
- {
- mip = (uint *)(data[i]);
- }
- else
- {
- mip = NULL;
-
- // resample the texture
- if( data[i] )
- {
- R_ResampleTexture( data[i], width, height, scaledWidth, scaledHeight, false );
- mip = (uint *)image_desc.scaled;
- }
- }
-
- // automatic mipmaps generation
- if( !( flags & TF_NOMIPMAP ) && mip && driverMipmap )
- pglTexParameteri( target2, GL_GENERATE_MIPMAP_SGIS, GL_TRUE );
-
- if( subImage )
- pglTexSubImage2D( target2, 0, 0, 0, scaledWidth, scaledHeight, format, GL_UNSIGNED_BYTE, mip );
- else
- pglTexImage2D( target2, 0, comp, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_BYTE, mip );
-
- // mipmaps generation
- if( !( flags & TF_NOMIPMAP ) && mip && !driverMipmap )
- {
- int w, h;
- int miplevel = 0;
-
- w = scaledWidth;
- h = scaledHeight;
- while( w > 1 || h > 1 )
- {
- R_BuildMipMap( (byte *)mip, w, h, false );
-
- w >>= 1;
- h >>= 1;
- if( w < 1 )
- w = 1;
- if( h < 1 )
- h = 1;
- miplevel++;
-
- if( subImage )
- pglTexSubImage2D( target2, miplevel, 0, 0, w, h, format, GL_UNSIGNED_BYTE, mip );
- else
- pglTexImage2D( target2, miplevel, comp, w, h, 0, format, GL_UNSIGNED_BYTE, mip );
- }
- }
- }
- }
}
\ No newline at end of file
diff --git a/render/r_local.h b/render/r_local.h
index fb0006d5..8f3819ec 100644
--- a/render/r_local.h
+++ b/render/r_local.h
@@ -76,11 +76,9 @@ typedef enum
TF_DEPTHMAP = BIT(5), // custom texture filter used
TF_INTENSITY = BIT(5),
TF_ALPHA = BIT(6),
- TF_NORGB = BIT(7), // QFusion legacy. convert to funcs?
- TF_NOALPHA = BIT(8),
- TF_SKYSIDE = BIT(9),
- TF_CLAMP = BIT(10),
- TF_NOMIPMAP = BIT(11),
+ TF_SKYSIDE = BIT(7),
+ TF_CLAMP = BIT(8),
+ TF_NOMIPMAP = BIT(9),
} texFlags_t;
#define TF_CINEMATIC ( TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP|TF_NOMIPMAP )
@@ -298,6 +296,7 @@ extern cvar_t *r_lerpmodels;
extern cvar_t *r_ignorehwgamma;
extern cvar_t *r_overbrightbits;
extern cvar_t *r_mapoverbrightbits;
+extern cvar_t *r_vertexbuffers;
extern cvar_t *r_lefthand;
extern cvar_t *r_physbdebug;
extern cvar_t *r_check_errors;
@@ -504,7 +503,6 @@ void R_TextureList_f( void );
void R_SetTextureParameters( void );
void R_ShowTextures( void );
-void R_Upload32( byte **data, int width, int height, int flags, int *upload_width, int *upload_height, int *samples, bool subImage );
texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, int samples, texFlags_t flags );
texture_t *R_FindTexture( const char *name, const byte *buf, size_t size, texFlags_t flags );
@@ -668,8 +666,9 @@ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_
//
// r_register.c
//
-void R_Restart( void );
-void R_Shutdown( bool verbose );
+void R_NewMap( void );
+bool R_Init( bool full );
+void R_Shutdown( bool full );
//
// r_opengl.c
@@ -701,16 +700,6 @@ struct skinfile_s *R_SkinFile_Load( const char *name );
struct skinfile_s *R_RegisterSkinFile( const char *name );
ref_shader_t *R_FindShaderForSkinFile( const struct skinfile_s *skinfile, const char *meshname );
-//
-// r_skm.c
-//
-bool R_CullSkeletalModel( ref_entity_t *e );
-void R_AddSkeletalModelToList( ref_entity_t *e );
-void R_DrawSkeletalModel( const meshbuffer_t *mb );
-float R_SkeletalModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs );
-int R_SkeletalGetBoneInfo( const ref_model_t *mod, int bonenum, char *name, size_t name_size, int *flags );
-void R_SkeletalGetBonePose( const ref_model_t *mod, int bonenum, int frame, bonepose_t *bonepose );
-
//
// r_warp.c
//
diff --git a/render/r_main.c b/render/r_main.c
index b2b859c2..fd0678d0 100644
--- a/render/r_main.c
+++ b/render/r_main.c
@@ -691,7 +691,6 @@ static void R_PushCorona( const meshbuffer_t *mb )
R_PushMesh( &spr_mesh, MF_NOCULL | MF_TRIFAN | shader->features );
}
-#ifdef QUAKE2_JUNK
/*
=================
R_PushSpriteModel
@@ -709,7 +708,6 @@ bool R_PushSpriteModel( const meshbuffer_t *mb )
return R_PushSprite( mb, e->rotation, frame->origin_x, frame->origin_x - frame->width, frame->height - frame->origin_y, -frame->origin_y );
}
-#endif
/*
=================
@@ -734,7 +732,6 @@ bool R_PushSpritePoly( const meshbuffer_t *mb )
return R_PushSprite( mb, e->rotation, -e->radius, e->radius, e->radius, -e->radius );
}
-#ifdef QUAKE2_JUNK
/*
=================
R_AddSpriteModelToList
@@ -775,7 +772,6 @@ static void R_AddSpriteModelToList( ref_entity_t *e )
if( mb )
mb->shaderkey |= ( bound( 1, 0x4000 - (unsigned int)dist, 0x4000 - 1 ) << 12 );
}
-#endif
/*
=================
@@ -1005,13 +1001,15 @@ static void R_SetupFrustum( void )
for( i = 0; i < 4; i++ )
{
+ RI.frustum[i].type = PLANE_NONAXIAL;
RI.frustum[i].dist = DotProduct( RI.viewOrigin, RI.frustum[i].normal );
- PlaneClassify( &RI.frustum[i] );
+ RI.frustum[i].signbits = SignbitsForPlane( &RI.frustum[i] );
}
VectorMA( RI.viewOrigin, RI.farClip, RI.vpn, farPoint );
+ RI.frustum[i].type = PLANE_NONAXIAL;
RI.frustum[i].dist = DotProduct( farPoint, RI.frustum[i].normal );
- PlaneClassify( &RI.frustum[i] );
+ RI.frustum[i].signbits = SignbitsForPlane( &RI.frustum[i] );
}
/*
@@ -1362,10 +1360,8 @@ static void R_CategorizeEntities( void )
if( !( RI.currententity->renderfx & ( RF_NOSHADOW|RF_PLANARSHADOW ) ) )
R_AddShadowCaster( RI.currententity ); // build groups and mark shadow casters
break;
-#ifdef QUAKE2_JUNK
case mod_sprite:
break;
-#endif
default:
Host_Error( "%s: bad modeltype\n", RI.currentmodel->name );
break;
@@ -1405,18 +1401,15 @@ static void R_CullEntities( void )
culled = R_CullAliasModel( e );
break;
case mod_studio:
- culled = R_CullSkeletalModel( e );
+ culled = true;
break;
case mod_brush:
culled = R_CullBrushModel( e );
break;
-#ifdef QUAKE2_JUNK
case mod_sprite:
culled = false;
break;
-#endif
- default:
- break;
+ default: break;
}
break;
case RT_SPRITE:
@@ -1517,16 +1510,12 @@ add:
R_AddAliasModelToList( e );
break;
case mod_studio:
- R_AddSkeletalModelToList( e );
break;
-#ifdef QUAKE2_JUNK
case mod_sprite:
if( !shadowmap )
R_AddSpriteModelToList( e );
break;
-#endif
- default:
- break;
+ default: break;
}
break;
case RT_SPRITE:
@@ -2390,19 +2379,21 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type, float lerpfrac )
return result;
}
-bool R_AddDynamicLight( vec3_t org, vec3_t color, float intensity )
+bool R_AddDynamicLight( vec3_t org, vec3_t color, float intensity, shader_t handle )
{
- dlight_t *dl;
+ dlight_t *dl;
+ ref_shader_t *shader;
if(( r_numDlights >= MAX_DLIGHTS ) || (intensity == 0) || ( VectorIsNull( color )))
return false;
-
+ if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle])->name)
+ shader = NULL;
dl = &r_dlights[r_numDlights++];
VectorCopy( org, dl->origin );
VectorCopy( color, dl->color );
dl->intensity = intensity * DLIGHT_SCALE;
- dl->shader = NULL; // FIXME;
+ dl->shader = shader;
R_LightBounds( org, dl->intensity, dl->mins, dl->maxs );
diff --git a/render/r_math.c b/render/r_math.c
index 9b535c49..77ecc14b 100644
--- a/render/r_math.c
+++ b/render/r_math.c
@@ -295,6 +295,37 @@ void AdjustFov( float *fov_x, float *fov_y, float width, float height, bool lock
else *fov_y = y;
}
+/*
+=================
+SignbitsForPlane
+
+fast box on planeside test
+=================
+*/
+int SignbitsForPlane( const cplane_t *out )
+{
+ int bits, i;
+
+ for( i = bits = 0; i < 3; i++ )
+ if( out->normal[i] < 0.0f ) bits |= 1<= 1.0f ) return PLANE_X;
+ if( normal[1] >= 1.0f ) return PLANE_Y;
+ if( normal[2] >= 1.0f ) return PLANE_Z;
+ return PLANE_NONAXIAL;
+}
+
+
/*
=================
PlaneFromPoints
@@ -309,7 +340,4 @@ void PlaneFromPoints( vec3_t verts[3], cplane_t *plane )
CrossProduct( v2, v1, plane->normal );
VectorNormalize( plane->normal );
plane->dist = DotProduct( verts[0], plane->normal );
-
- // FIXME: needs to a plane classify ?
- //PlaneClassify( plane );
}
\ No newline at end of file
diff --git a/render/r_math.h b/render/r_math.h
index d9878718..fd9a20f9 100644
--- a/render/r_math.h
+++ b/render/r_math.h
@@ -26,7 +26,7 @@ extern const mat4x4_t mat4x4_identity;
void Matrix4_Identity( mat4x4_t m );
void Matrix4_Copy( const mat4x4_t m1, mat4x4_t m2 );
-bool Matrix4_Compare( const mat4x4_t m1, const mat4x4_t m2 );
+bool Matrix4_Compare( const mat4x4_t m1, const mat4x4_t m2 );
void Matrix4_Multiply( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out );
void Matrix4_MultiplyFast( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out );
void Matrix4_Rotate( mat4x4_t m, vec_t angle, vec_t x, vec_t y, vec_t z );
@@ -46,5 +46,7 @@ void Matrix4_Stretch2D( mat4x4_t m, vec_t s, vec_t t );
float CalcFov( float fov_x, float width, float height );
void AdjustFov( float *fov_x, float *fov_y, float width, float height, bool lock_x );
void PlaneFromPoints( vec3_t verts[3], cplane_t *plane );
+int SignbitsForPlane( const cplane_t *out );
+int PlaneTypeForNormal( const vec3_t normal );
#endif /*__R_MATH_H__*/
diff --git a/render/r_mesh.c b/render/r_mesh.c
index ed17118d..11767f58 100644
--- a/render/r_mesh.c
+++ b/render/r_mesh.c
@@ -174,6 +174,107 @@ static void R_ISortMeshBuffers( meshbuffer_t *meshes, int num_meshes )
}
}
+/*
+=======================================================================
+
+VERTEX BUFFERS
+
+=======================================================================
+*/
+/*
+=================
+R_UpdateVertexBuffer
+=================
+*/
+void R_UpdateVertexBuffer( ref_buffer_t *vertexBuffer, const void *data, size_t size )
+{
+ if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
+ {
+ vertexBuffer->pointer = (char *)data;
+ return;
+ }
+
+ if( !r_vertexbuffers->integer )
+ {
+ vertexBuffer->pointer = (char *)data;
+ pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
+ return;
+ }
+
+ vertexBuffer->pointer = NULL;
+ pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->bufNum );
+ pglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, 0, size, data );
+}
+
+/*
+=================
+R_AllocVertexBuffer
+=================
+*/
+ref_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage )
+{
+ ref_buffer_t *vertexBuffer;
+
+ if( tr.numVertexBufferObjects == MAX_VERTEX_BUFFER_OBJECTS )
+ Host_Error( "RB_AllocVertexBuffer: MAX_VERTEX_BUFFER_OBJECTS limit exceeds\n" );
+
+ vertexBuffer = &tr.vertexBufferObjects[tr.numVertexBufferObjects++];
+
+ vertexBuffer->pointer = NULL;
+ vertexBuffer->size = size;
+ vertexBuffer->usage = usage;
+
+ if(!GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
+ return vertexBuffer;
+
+ pglGenBuffersARB( 1, &vertexBuffer->bufNum );
+ pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->bufNum );
+ pglBufferDataARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->size, NULL, vertexBuffer->usage );
+
+ return vertexBuffer;
+}
+
+/*
+=================
+R_InitVertexBuffers
+=================
+*/
+void R_InitVertexBuffers( void )
+{
+ int i;
+
+ tr.vertexBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_STREAM_DRAW_ARB );
+ tr.colorsBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( rgba_t ), GL_STREAM_DRAW_ARB );
+ tr.normalBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_STREAM_DRAW_ARB );
+ for( i = 0; i < MAX_TEXTURE_UNITS; i++ )
+ tr.tcoordBuffer[i] = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_STREAM_DRAW_ARB );
+}
+
+/*
+=================
+R_ShutdownVertexBuffers
+=================
+*/
+void R_ShutdownVertexBuffers( void )
+{
+ ref_buffer_t *vertexBuffer;
+ int i;
+
+ if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT ))
+ {
+ Mem_Set( tr.vertexBufferObjects, 0, sizeof( tr.vertexBufferObjects ));
+ tr.numVertexBufferObjects = 0;
+ return;
+ }
+
+ pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
+ for( i = 0, vertexBuffer = tr.vertexBufferObjects; i < tr.numVertexBufferObjects; i++, vertexBuffer++ )
+ pglDeleteBuffersARB( 1, &vertexBuffer->bufNum );
+
+ Mem_Set( tr.vertexBufferObjects, 0, sizeof( tr.vertexBufferObjects ));
+ tr.numVertexBufferObjects = 0;
+}
+
/*
=================
R_ReAllocMeshList
@@ -364,7 +465,6 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm
case mod_alias:
R_DrawAliasModel( mb );
break;
-#ifdef QUAKE2_JUNK
case mod_sprite:
R_PushSpriteModel( mb );
@@ -372,9 +472,7 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm
R_TranslateForEntity( RI.currententity );
R_RenderMeshBuffer( mb );
break;
-#endif
case mod_studio:
- R_DrawSkeletalModel( mb );
break;
default:
Com_Assert( 1 ); // shut up compiler
diff --git a/render/r_model.c b/render/r_model.c
index 81c0d22e..82fdf7a4 100644
--- a/render/r_model.c
+++ b/render/r_model.c
@@ -88,7 +88,6 @@ static int loadmodel_numshaderrefs;
static mshaderref_t *loadmodel_shaderrefs;
void Mod_LoadAliasMD3Model( ref_model_t *mod, ref_model_t *parent, const void *buffer );
-void Mod_LoadSkeletalModel( ref_model_t *mod, ref_model_t *parent, const void *buffer );
void Mod_LoadBrushModel( ref_model_t *mod, ref_model_t *parent, const void *buffer );
ref_model_t *Mod_LoadModel( ref_model_t *mod, bool crash );
@@ -102,8 +101,7 @@ static byte *mod_mempool;
static modelformatdescriptor_t mod_supportedformats[] =
{
-{ IDMD3HEADER, MD3_ALIAS_MAX_LODS, Mod_LoadAliasMD3Model }, // Quake III Arena .md3 models
-{ SKMHEADER, SKM_MAX_LODS, Mod_LoadSkeletalModel }, // Skeletal models
+{ ALIASMODHEADER, MD3_ALIAS_MAX_LODS, Mod_LoadAliasMD3Model }, // Quake III Arena .md3 models
{ IDBSPMODHEADER, 0, Mod_LoadBrushModel }, // Quake III Arena .bsp models
{ RBBSPMODHEADER, 0, Mod_LoadBrushModel }, // SOF2 and JK2 .bsp models
{ QFBSPMODHEADER, 0, Mod_LoadBrushModel }, // QFusion .bsp models
@@ -422,7 +420,7 @@ ref_model_t *Mod_ForName( const char *name, bool crash )
FS_StripExtension( shortname );
// load level-of-detail models
- for( i = mod->numlods = 0; i < descr->maxLods; i++ )
+ for( mod->numlods = i = 0; i < descr->maxLods; i++ )
{
com.snprintf( lodname, sizeof( lodname ), "%s_%i.%s", shortname, i+1, ext );
buf = (uint *)FS_LoadFile( lodname, NULL );
@@ -1322,7 +1320,7 @@ static void Mod_LoadFogs( const lump_t *l, const lump_t *brLump, const lump_t *b
for( i = 0; i < count; i++, in++, out++ )
{
- out->shader = R_RegisterShader( in->shader );
+ out->shader = R_LoadShader( in->shader, SHADER_TEXTURE, false, 0, SHADER_INVALID );
p = LittleLong( in->brushnum );
if( p == -1 )
continue;
@@ -2037,63 +2035,6 @@ void Mod_LoadBrushModel( ref_model_t *mod, ref_model_t *parent, const void *buff
else bmodel->numsubmodels = 0;
}
}
-
-#ifdef QUAKE2_JUNK
-
-/*
-==============================================================================
-
-SPRITE MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_LoadSpriteModel
-=================
-*/
-void Mod_LoadSpriteModel( ref_model_t *mod, ref_model_t *parent, void *buffer )
-{
- int i;
- dsprite_t *sprin;
- smodel_t *sprout;
- dsprframe_t *sprinframe;
- sframe_t *sproutframe;
-
- sprin = (dsprite_t *)buffer;
-
- if( LittleLong( sprin->version ) != SPRITE_VERSION )
- Host_Error( ERR_DROP, "%s has wrong version number (%i should be %i)",
- mod->name, LittleLong( sprin->version ), SPRITE_VERSION );
-
- mod->extradata = sprout = Mod_Malloc( mod, sizeof( smodel_t ) );
- sprout->numframes = LittleLong( sprin->numframes );
-
- sprinframe = sprin->frames;
- sprout->frames = sproutframe = Mod_Malloc( mod, sizeof( sframe_t ) * sprout->numframes );
-
- mod->radius = 0;
- ClearBounds( mod->mins, mod->maxs );
-
- // byte swap everything
- for( i = 0; i < sprout->numframes; i++, sprinframe++, sproutframe++ )
- {
- sproutframe->width = LittleLong( sprinframe->width );
- sproutframe->height = LittleLong( sprinframe->height );
- sproutframe->origin_x = LittleLong( sprinframe->origin_x );
- sproutframe->origin_y = LittleLong( sprinframe->origin_y );
- sproutframe->shader = R_RegisterPic( sprinframe->name );
- sproutframe->radius = sqrt( sproutframe->width * sproutframe->width + sproutframe->height * sproutframe->height );
- mod->radius = max( mod->radius, sproutframe->radius );
- }
-
- mod->type = mod_sprite;
- mod->touchFrame = tr.registration_sequence; // register model
-}
-
-#endif
-
//=============================================================================
/*
@@ -2122,7 +2063,7 @@ void R_BeginRegistration( const char *mapname, const dvis_t *visData )
if( com.strcmp( r_models[0].name, fullname ))
{
Mod_FreeModel( &r_models[0] );
- RI.surfmbuffers = NULL;
+ R_NewMap ();
}
else
{
diff --git a/render/r_model.h b/render/r_model.h
index 366b74d5..8e7ce14e 100644
--- a/render/r_model.h
+++ b/render/r_model.h
@@ -243,73 +243,11 @@ typedef struct
/*
==============================================================================
-SKELETAL MODELS
+STUDIO MODELS
==============================================================================
*/
-//
-// in memory representation
-//
-#define SKM_MAX_WEIGHTS 4
-
-//
-// in memory representation
-//
-typedef struct
-{
- ref_shader_t *shader;
-} mskskin_t;
-
-typedef struct
-{
- char name[SKM_MAX_NAME];
-
- float *influences;
- unsigned int *bones;
-
- unsigned int numverts;
- vec4_t *xyzArray;
- vec4_t *normalsArray;
- vec2_t *stArray;
- vec4_t *sVectorsArray;
-
- unsigned int numtris;
- elem_t *elems;
-
- unsigned int numreferences;
- unsigned int *references;
-
- mskskin_t skin;
-} mskmesh_t;
-
-typedef struct
-{
- char name[SKM_MAX_NAME];
- signed int parent;
- unsigned int flags;
-} mskbone_t;
-
-typedef struct
-{
- vec3_t mins, maxs;
- float radius;
- bonepose_t *boneposes;
-} mskframe_t;
-
-typedef struct
-{
- unsigned int numbones;
- mskbone_t *bones;
-
- unsigned int nummeshes;
- mskmesh_t *meshes;
-
- unsigned int numframes;
- mskframe_t *frames;
- bonepose_t *invbaseposes;
-} mskmodel_t;
-
/*
==============================================================================
@@ -317,32 +255,27 @@ SPRITE MODELS
==============================================================================
*/
-
-#ifdef QUAKE2_JUNK
-
//
// in memory representation
//
typedef struct
{
- int width, height;
- int origin_x, origin_y; // raster coordinates inside pic
+ int width, height;
+ int origin_x, origin_y; // raster coordinates inside pic
- char name[SPRITE_MAX_NAME];
- ref_shader_t *shader;
+ char name[64];
+ ref_shader_t *shader;
- float mins[3], maxs[3];
- float radius;
+ float mins[3], maxs[3];
+ float radius;
} sframe_t;
typedef struct
{
- int numframes;
+ int numframes;
sframe_t *frames;
} smodel_t;
-#endif
-
//===================================================================
//
@@ -379,18 +312,15 @@ void R_InitModels( void );
void R_ShutdownModels( void );
void Mod_ClearAll( void );
-ref_model_t *Mod_ForName( const char *name, bool crash );
+ref_model_t *Mod_ForName( const char *name, bool crash );
mleaf_t *Mod_PointInLeaf( float *p, ref_model_t *model );
byte *Mod_ClusterPVS( int cluster, ref_model_t *model );
+uint Mod_Handle( ref_model_t *mod );
+ref_model_t *Mod_ForHandle( unsigned int elem );
-unsigned int Mod_Handle( ref_model_t *mod );
-ref_model_t *Mod_ForHandle( unsigned int elem );
-
-#define Mod_Malloc( mod, size ) Mem_Alloc( ( mod )->mempool, size )
+#define Mod_Malloc( mod, size ) Mem_Alloc(( mod )->mempool, size )
#define Mod_Free( data ) Mem_Free( data )
-
void Mod_StripLODSuffix( char *name );
-
void Mod_Modellist_f( void );
#endif /*__R_MODEL_H__*/
diff --git a/render/r_poly.c b/render/r_poly.c
index 928c7517..bca5c7d7 100644
--- a/render/r_poly.c
+++ b/render/r_poly.c
@@ -502,11 +502,11 @@ int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], in
VectorCopy( axis[i], fragmentPlanes[i*2].normal );
fragmentPlanes[i*2].dist = d - radius;
- PlaneClassify( &fragmentPlanes[i*2] );
+ fragmentPlanes[i*2].type = PlaneTypeForNormal( fragmentPlanes[i*2].normal );
VectorNegate( axis[i], fragmentPlanes[i*2+1].normal );
fragmentPlanes[i*2+1].dist = -d - radius;
- PlaneClassify( &fragmentPlanes[i*2+1] );
+ fragmentPlanes[i*2+1].type = PlaneTypeForNormal( fragmentPlanes[i*2+1].normal );
}
R_RecursiveFragmentNode ();
diff --git a/render/r_program.c b/render/r_program.c
index 58bca97f..2fabe90c 100644
--- a/render/r_program.c
+++ b/render/r_program.c
@@ -22,14 +22,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "r_local.h"
-#define APPLICATION "Xash3D"
-#define MAX_GLSL_PROGRAMS 1024
+#define APPLICATION "Xash3D"
+#define MAX_GLSL_PROGRAMS 1024
+#define R_GLSLProgramCopyString( str ) com.stralloc( r_glslProgramsPool, str, __FILE__, __LINE__ )
typedef struct
{
- int bit;
- const char *define;
- const char *suffix;
+ int bit;
+ const char *define;
+ const char *suffix;
} glsl_feature_t;
typedef struct
@@ -77,9 +78,9 @@ R_InitGLSLPrograms
*/
void R_InitGLSLPrograms( void )
{
- int features = 0;
+ int features = 0;
- memset( r_glslprograms, 0, sizeof( r_glslprograms ) );
+ Mem_Set( r_glslprograms, 0, sizeof( r_glslprograms ));
if( !GL_Support( R_SHADER_GLSL100_EXT ))
return;
@@ -109,21 +110,6 @@ void R_InitGLSLPrograms( void )
R_RegisterGLSLProgram( DEFAULT_GLSL_OUTLINE_PROGRAM, r_defaultOutlineGLSLProgram, 0|features );
}
-/*
-================
-R_GLSLProgramCopyString
-================
-*/
-static char *R_GLSLProgramCopyString( const char *in )
-{
- char *out;
-
- out = Mem_Alloc( r_glslProgramsPool, ( strlen( in ) + 1 ) );
- strcpy( out, in );
-
- return out;
-}
-
/*
================
R_DeleteGLSLProgram
@@ -151,7 +137,7 @@ static void R_DeleteGLSLProgram( glsl_program_t *program )
if( program->name )
Mem_Free( program->name );
- memset( program, 0, sizeof( glsl_program_t ) );
+ Mem_Set( program, 0, sizeof( glsl_program_t ));
}
/*
@@ -1008,10 +994,10 @@ R_ProgramList_f
*/
void R_ProgramList_f( void )
{
- int i;
+ int i;
glsl_program_t *program;
- string fullName;
- const char **header;
+ string fullName;
+ const char **header;
Msg( "------------------\n" );
for( i = 0, program = r_glslprograms; i < MAX_GLSL_PROGRAMS; i++, program++ )
@@ -1020,7 +1006,7 @@ void R_ProgramList_f( void )
break;
com.strncpy( fullName, program->name, sizeof( fullName ) );
- header = R_ProgramFeatures2Defines( program->features, fullName, sizeof( fullName ) );
+ header = R_ProgramFeatures2Defines( program->features, fullName, sizeof( fullName ));
Msg( " %3i %s\n", i+1, fullName );
}
@@ -1118,16 +1104,11 @@ R_GetProgramUniformLocations
*/
static void R_GetProgramUniformLocations( glsl_program_t *program )
{
- int i;
- int locBaseTexture,
- locNormalmapTexture,
- locGlossTexture,
- locDecalTexture,
- locLightmapTexture[LM_STYLES],
- locDuDvMapTexture,
- locReflectionTexture,
- locRefractionTexture,
- locShadowmapTexture;
+ int i;
+ int locBaseTexture, locNormalmapTexture, locGlossTexture;
+ int locDecalTexture, locLightmapTexture[LM_STYLES];
+ int locDuDvMapTexture, locReflectionTexture;
+ int locRefractionTexture, locShadowmapTexture;
char uniformName[128];
program->locEyeOrigin = pglGetUniformLocationARB( program->object, "EyeOrigin" );
@@ -1174,25 +1155,17 @@ static void R_GetProgramUniformLocations( glsl_program_t *program )
program->locProjDistance = pglGetUniformLocationARB( program->object, "ProjDistance" );
- if( locBaseTexture >= 0 )
- pglUniform1iARB( locBaseTexture, 0 );
- if( locDuDvMapTexture >= 0 )
- pglUniform1iARB( locDuDvMapTexture, 0 );
+ if( locBaseTexture >= 0 ) pglUniform1iARB( locBaseTexture, 0 );
+ if( locDuDvMapTexture >= 0 ) pglUniform1iARB( locDuDvMapTexture, 0 );
- if( locNormalmapTexture >= 0 )
- pglUniform1iARB( locNormalmapTexture, 1 );
- if( locGlossTexture >= 0 )
- pglUniform1iARB( locGlossTexture, 2 );
- if( locDecalTexture >= 0 )
- pglUniform1iARB( locDecalTexture, 3 );
+ if( locNormalmapTexture >= 0 ) pglUniform1iARB( locNormalmapTexture, 1 );
+ if( locGlossTexture >= 0 ) pglUniform1iARB( locGlossTexture, 2 );
+ if( locDecalTexture >= 0 ) pglUniform1iARB( locDecalTexture, 3 );
- if( locReflectionTexture >= 0 )
- pglUniform1iARB( locReflectionTexture, 2 );
- if( locRefractionTexture >= 0 )
- pglUniform1iARB( locRefractionTexture, 3 );
+ if( locReflectionTexture >= 0 ) pglUniform1iARB( locReflectionTexture, 2 );
+ if( locRefractionTexture >= 0 ) pglUniform1iARB( locRefractionTexture, 3 );
- if( locShadowmapTexture >= 0 )
- pglUniform1iARB( locShadowmapTexture, 0 );
+ if( locShadowmapTexture >= 0 ) pglUniform1iARB( locShadowmapTexture, 0 );
for( i = 0; i < LM_STYLES; i++ )
{
@@ -1208,8 +1181,8 @@ R_ShutdownGLSLPrograms
*/
void R_ShutdownGLSLPrograms( void )
{
- int i;
- glsl_program_t *program;
+ int i;
+ glsl_program_t *program;
if( !r_glslProgramsPool )
return;
@@ -1225,4 +1198,4 @@ void R_ShutdownGLSLPrograms( void )
}
Mem_FreePool( &r_glslProgramsPool );
-}
+}
\ No newline at end of file
diff --git a/render/r_public.h b/render/r_public.h
index 787bc314..3188d3c2 100644
--- a/render/r_public.h
+++ b/render/r_public.h
@@ -26,21 +26,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_POLY_VERTS 3000
#define MAX_POLYS 2048
-// skm flags
-#define SKM_ATTACHMENT_BONE 1
-
typedef struct
{
vec3_t axis[3];
vec3_t origin;
} orientation_t;
-typedef struct
-{
- quat_t quat;
- vec3_t origin;
-} bonepose_t;
-
typedef struct
{
float rgb[3]; // 0.0 - 2.0
@@ -132,13 +123,11 @@ typedef struct entity_s
vec3_t movedir; // forward vector that computed on a server
vec3_t origin, origin2;
vec3_t lightingOrigin;
- bonepose_t *boneposes; // pretransformed boneposes for current frame
/*
** previous data for lerping
*/
int oldframe;
- bonepose_t *oldboneposes; // pretransformed boneposes for old frame
/*
** texturing
@@ -171,35 +160,22 @@ typedef struct entity_s
void R_ModelBounds( const struct ref_model_s *model, vec3_t mins, vec3_t maxs );
struct ref_model_s *R_RegisterModel( const char *name );
-struct ref_shader_s *R_RegisterPic( const char *name );
-struct ref_shader_s *R_RegisterShader( const char *name );
-struct ref_shader_s *R_RegisterSkin( const char *name );
struct skinfile_s *R_RegisterSkinFile( const char *name );
-void R_ClearScene( void );
-void R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, const struct ref_shader_s *shader );
-bool R_AddPolyToScene( const poly_t *poly );
-void R_AddLightStyleToScene( int style, float r, float g, float b );
-void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader );
-void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, bool redraw );
-
-void R_SetCustomColor( int num, int r, int g, int b );
-void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius );
-
-bool R_LerpTag( orientation_t *orient, const struct ref_model_s *mod, int oldframe, int frame, float lerpfrac,
- const char *name );
-
-int R_SkeletalGetNumBones( const struct ref_model_s *mod, int *numFrames );
-int R_SkeletalGetBoneInfo( const struct ref_model_s *mod, int bone, char *name, size_t name_size, int *flags );
-void R_SkeletalGetBonePose( const struct ref_model_s *mod, int bone, int frame, bonepose_t *bonepose );
-
-int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts,
- int maxfragments, fragment_t *fragments );
-
-void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out );
+void R_ClearScene( void );
+void R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, const struct ref_shader_s *shader );
+bool R_AddPolyToScene( const poly_t *poly );
+void R_AddLightStyleToScene( int style, float r, float g, float b );
+void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader );
+void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, bool redraw );
+void R_SetCustomColor( int num, int r, int g, int b );
+void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius );
+bool R_LerpTag( orientation_t *orient, const struct ref_model_s *mod, int oldframe, int frame, float lerpfrac, const char *name );
+int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts,
+ int maxfragments, fragment_t *fragments );
+void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out );
const char *R_SpeedsMessage( char *out, size_t size );
-void GLimp_AppActivate( bool active );
// Xash renderer exports
bool R_Init( bool full );
diff --git a/render/r_register.c b/render/r_register.c
index cb190607..71243cef 100644
--- a/render/r_register.c
+++ b/render/r_register.c
@@ -41,6 +41,7 @@ cvar_t *r_ignorehwgamma;
cvar_t *r_check_errors;
cvar_t *r_overbrightbits;
cvar_t *r_mapoverbrightbits;
+cvar_t *r_vertexbuffers;
cvar_t *r_flares;
cvar_t *r_flaresize;
cvar_t *r_flarefade;
@@ -533,6 +534,7 @@ void GL_InitCommands( void )
r_ignorehwgamma = Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" );
r_overbrightbits = Cvar_Get( "r_overbrightbits", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "renderer overbright bits" );
r_mapoverbrightbits = Cvar_Get( "r_mapoverbrightbits", "2", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "current map overbright bits" );
+ r_vertexbuffers = Cvar_Get( "r_vertexbuffers", "0", CVAR_ARCHIVE, "store vertex data in VBOs" );
r_detailtextures = Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE, "enable or disable detail textures" );
r_flares = Cvar_Get( "r_flares", "0", CVAR_ARCHIVE, "enable flares rendering" );
@@ -550,7 +552,7 @@ void GL_InitCommands( void )
r_fastsky = Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE, "enable algorhytem fo fast sky rendering (for old machines)" );
r_portalonly = Cvar_Get( "r_portalonly", "0", 0, "render only portals" );
r_portalmaps = Cvar_Get( "r_portalmaps", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "use portal maps for portal rendering" );
- r_portalmaps_maxtexsize = Cvar_Get( "r_portalmaps_maxtexsize", "800", CVAR_ARCHIVE, "portal maps texture dims" );
+ r_portalmaps_maxtexsize = Cvar_Get( "r_portalmaps_maxtexsize", "512", CVAR_ARCHIVE, "portal maps texture dims" );
r_allow_software = Cvar_Get( "r_allow_software", "0", 0, "allow OpenGL software emulation" );
r_3dlabs_broken = Cvar_Get( "r_3dlabs_broken", "1", CVAR_ARCHIVE, "3dLabs renderer issues" );
@@ -650,7 +652,7 @@ void GL_InitBackend( void )
if(FS_GetParmFromCmdLine( "-dev", dev_level ))
glw_state.developer = com.atoi( dev_level );
- GL_SetDefaultState(); // FIXME stupid name for allocate arrays
+ GL_SetDefaultState();
}
void GL_ShutdownBackend( void )
@@ -800,21 +802,7 @@ GL_SetDefaultState
*/
static void GL_SetDefaultState( void )
{
- // FIXME: dynamically allocate these?
- static GLuint r_currentTextures[MAX_TEXTURE_UNITS];
- static int r_currentEnvModes[MAX_TEXTURE_UNITS];
- static bool r_texIdentityMatrix[MAX_TEXTURE_UNITS];
- static int r_genSTEnabled[MAX_TEXTURE_UNITS];
- static int r_texCoordArrayMode[MAX_TEXTURE_UNITS];
-
Mem_Set( &glState, 0, sizeof( glState ));
-
- glState.currentTextures = r_currentTextures;
- glState.currentEnvModes = r_currentEnvModes;
- glState.texIdentityMatrix = r_texIdentityMatrix;
- glState.genSTEnabled = r_genSTEnabled;
- glState.texCoordArrayMode = r_texCoordArrayMode;
-
GL_SetDefaultTexState ();
glState.initializedMedia = false;
@@ -1028,11 +1016,6 @@ void GL_InitExtensions( void )
Image_Init( NULL, flags );
glw_state.initialized = true;
-
- // gl_ext_vertex_buffer_object is crashy..
- // FIXME: QFusion render bug
- Cvar_Set( "gl_vertex_buffer_object", "0" );
- GL_SetExtension( R_ARB_VERTEX_BUFFER_OBJECT_EXT, false );
}
/*
@@ -1136,4 +1119,26 @@ void R_Shutdown( bool full )
// shut down OS specific OpenGL stuff like contexts, etc.
R_Free_OpenGL();
}
+}
+
+/*
+===============
+R_NewMap
+
+do some cleanup operations
+===============
+*/
+void R_NewMap( void )
+{
+ R_ShutdownOcclusionQueries();
+ R_FreeMeshLists();
+
+ R_InitMeshLists();
+ R_InitOcclusionQueries();
+
+ R_InitLightStyles(); // clear lightstyles
+ R_InitCustomColors(); // clear custom colors
+
+ GL_SetDefaultTexState ();
+ Mem_Set( &RI, 0, sizeof( refinst_t ));
}
\ No newline at end of file
diff --git a/render/r_shader.c b/render/r_shader.c
index b33af99f..d0d62bab 100644
--- a/render/r_shader.c
+++ b/render/r_shader.c
@@ -1444,10 +1444,10 @@ static bool Shaderpass_NormalMap( ref_shader_t *shader, ref_stage_t *pass, scrip
static bool Shaderpass_Material( ref_shader_t *shader, ref_stage_t *pass, script_t *script )
{
- int flags;
- float bumpScale = 0;
- string name;
- token_t tok;
+ int flags;
+ float bumpScale = 0;
+ const char *name;
+ token_t tok;
if( !GL_Support( R_SHADER_GLSL100_EXT ))
{
@@ -1469,17 +1469,24 @@ static bool Shaderpass_Material( ref_shader_t *shader, ref_stage_t *pass, script
pass->flags &= ~(SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES);
}
- com.strncpy( name, tok.string, sizeof( name ));
flags = Shader_SetImageFlags( shader );
- while( 1 )
- {
- if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok ))
- break;
+ if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok ));
+ return false;
- com.strncat( name, " ", sizeof( name ));
- com.strncat( name, tok.string, sizeof( name ));
+ if( !com.stricmp( tok.string, "$rgb" ))
+ {
+ if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok ));
+ return false;
+ name = va( "clearPixels( \"%s\", alpha );", tok.string );
}
+ else if( !com.stricmp( tok.string, "$alpha" ))
+ {
+ if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok ));
+ return false;
+ name = va( "clearPixels( \"%s\", color );", tok.string );
+ }
+ else name = tok.string;
pass->textures[0] = Shader_FindImage( shader, name, flags );
if( pass->textures[0] == tr.defaultTexture )
@@ -2398,6 +2405,11 @@ void R_ShaderDump_f( void )
Msg( "^1%s%s\n", name, cache->buffer );
}
+void R_RegisterBuiltinShaders( void )
+{
+ tr.defaultShader = R_LoadShader( "*black", SHADER_NOMIP, true, (TF_NOMIPMAP|TF_NOPICMIP), SHADER_UNKNOWN );
+}
+
void R_InitShaders( void )
{
script_t *script;
@@ -2432,6 +2444,8 @@ void R_InitShaders( void )
r_spriteFrequency = 0.0f;
r_numSpriteTextures = 0;
r_spriteRenderMode = kRenderNormal;
+
+ R_RegisterBuiltinShaders ();
}
void Shader_TouchImages( ref_shader_t *shader, bool free_unused )
@@ -3518,14 +3532,14 @@ ref_shader_t *R_LoadShader( const char *name, int type, bool forceDefault, int a
shortname[length] = 0;
// see if already loaded
- hashKey = Com_HashKey( name, SHADERS_HASH_SIZE );
+ hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE );
for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash )
{
if( shader->type != type || ( shader->type == ignoreType ))
continue;
- if( !com.stricmp( shader->name, name ))
+ if( !com.stricmp( shader->name, shortname ))
{
// prolonge registration
Shader_TouchImages( shader, false );
@@ -3634,21 +3648,4 @@ void R_ShaderSetRenderMode( kRenderMode_t mode )
void R_ShaderAddSpriteIntervals( float interval )
{
r_spriteFrequency += interval;
-}
-
-
-// FIXME: get rid of this
-ref_shader_t *R_RegisterPic( const char *name )
-{
- return R_LoadShader( name, SHADER_NOMIP, false, 0, SHADER_INVALID );
-}
-
-ref_shader_t *R_RegisterShader( const char *name )
-{
- return R_LoadShader( name, SHADER_TEXTURE, false, 0, SHADER_INVALID );
-}
-
-ref_shader_t *R_RegisterSkin( const char *name )
-{
- return R_LoadShader( name, SHADER_ALIAS, false, 0, SHADER_INVALID );
-}
+}
\ No newline at end of file
diff --git a/render/r_shadow.c b/render/r_shadow.c
index 2888f87c..7d50857c 100644
--- a/render/r_shadow.c
+++ b/render/r_shadow.c
@@ -288,10 +288,18 @@ bool R_AddShadowCaster( ref_entity_t *ent )
r_numShadowGroups++;
add:
// get model bounds
- if( ent->model->type == mod_alias )
+ switch( ent->model->type )
+ {
+ case mod_alias:
R_AliasModelBBox( ent, mins, maxs );
- else
- R_SkeletalModelBBox( ent, mins, maxs );
+ break;
+ case mod_studio:
+ break;
+ default:
+ VectorClear( mins );
+ VectorClear( maxs );
+ break;
+ }
for( i = 0; i < 3; i++ )
{
diff --git a/render/r_skin.c b/render/r_skin.c
index 64316813..3e8132f4 100644
--- a/render/r_skin.c
+++ b/render/r_skin.c
@@ -20,143 +20,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "r_local.h"
+#define SkinFile_CopyString( str ) com.stralloc( r_skinsPool, str, __FILE__, __LINE__ )
+
typedef struct
{
- char *meshname;
- ref_shader_t *shader;
+ char *meshname;
+ ref_shader_t *shader;
} mesh_shader_pair_t;
typedef struct skinfile_s
{
- char *name;
-
+ char *name;
mesh_shader_pair_t *pairs;
- int numpairs;
+ int numpairs;
} skinfile_t;
-static skinfile_t r_skinfiles[MAX_SKINFILES];
-static byte *r_skinsPool;
-
-// Com_ParseExt it's temporary stuff
-#define MAX_TOKEN_CHARS 1024
-char com_token[MAX_TOKEN_CHARS];
-
-/*
-==============
-COM_ParseExt
-
-Parse a token out of a string
-==============
-*/
-char *COM_ParseExt( const char **data_p, bool nl )
-{
- int c;
- int len;
- const char *data;
- bool newlines = false;
-
- data = *data_p;
- len = 0;
- com_token[0] = 0;
-
- if (!data)
- {
- *data_p = NULL;
- return "";
- }
-
-// skip whitespace
-skipwhite:
- while ( (c = *data) <= ' ')
- {
- if (c == 0)
- {
- *data_p = NULL;
- return "";
- }
- if (c == '\n')
- newlines = true;
- data++;
- }
-
- if ( newlines && !nl )
- {
- *data_p = data;
- return com_token;
- }
-
- // skip // comments
- if (c == '/' && data[1] == '/')
- {
- data += 2;
-
- while (*data && *data != '\n')
- data++;
- goto skipwhite;
- }
-
- // skip /* */ comments
- if (c == '/' && data[1] == '*')
- {
- data += 2;
-
- while (1)
- {
- if (!*data)
- break;
- if (*data != '*' || *(data+1) != '/')
- data++;
- else
- {
- data += 2;
- break;
- }
- }
- goto skipwhite;
- }
-
- // handle quoted strings specially
- if (c == '\"')
- {
- data++;
- while (1)
- {
- c = *data++;
- if (c=='\"' || !c)
- {
- if (len == MAX_TOKEN_CHARS)
- len = 0;
- com_token[len] = 0;
- *data_p = data;
- return com_token;
- }
- if (len < MAX_TOKEN_CHARS)
- {
- com_token[len] = c;
- len++;
- }
- }
- }
-
-// parse a regular word
- do
- {
- if (len < MAX_TOKEN_CHARS)
- {
- com_token[len] = c;
- len++;
- }
- data++;
- c = *data;
- } while (c>32);
-
- if (len == MAX_TOKEN_CHARS)
- len = 0;
- com_token[len] = 0;
-
- *data_p = data;
- return com_token;
-}
+static skinfile_t r_skinfiles[MAX_SKINFILES];
+static byte *r_skinsPool;
/*
================
@@ -166,23 +46,7 @@ R_InitSkinFiles
void R_InitSkinFiles( void )
{
r_skinsPool = Mem_AllocPool( "Skins" );
-
- memset( r_skinfiles, 0, sizeof( r_skinfiles ) );
-}
-
-/*
-================
-SkinFile_CopyString
-================
-*/
-static char *SkinFile_CopyString( const char *in )
-{
- char *out;
-
- out = Mem_Alloc( r_skinsPool, ( strlen( in ) + 1 ) );
- strcpy( out, in );
-
- return out;
+ Mem_Set( r_skinfiles, 0, sizeof( r_skinfiles ));
}
/*
@@ -192,15 +56,14 @@ SkinFile_FreeSkinFile
*/
static void SkinFile_FreeSkinFile( skinfile_t *skinfile )
{
- int i;
+ int i;
for( i = 0; i < skinfile->numpairs; i++ )
Mem_Free( skinfile->pairs[i].meshname );
Mem_Free( skinfile->pairs );
Mem_Free( skinfile->name );
-
- memset( skinfile, 0, sizeof( skinfile_t ) );
+ Mem_Set( skinfile, 0, sizeof( skinfile_t ));
}
/*
@@ -232,33 +95,40 @@ SkinFile_ParseBuffer
*/
static int SkinFile_ParseBuffer( char *buffer, mesh_shader_pair_t *pairs )
{
- int numpairs;
- char *ptr, *t, *token;
+ int numpairs;
+ string skinname;
+ string meshname;
+ script_t *script;
+ token_t tok;
- ptr = buffer;
+ script = Com_OpenScript( "skinfile", buffer, com.strlen( buffer ));
numpairs = 0;
- while( ptr )
+ while( 1 )
{
- token = COM_ParseExt( &ptr, false );
- if( !token[0] )
- continue;
-
- t = strchr( token, ',' );
- if( !t )
- continue;
- if( *( t+1 ) == '\0' || *( t+1 ) == '\n' )
- continue;
+ if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) // skip tag
+ break;
+ if( !com.strcmp( tok.string, "," ))
+ {
+ if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &tok ))
+ continue; // tag without shadername
+ com.strncpy( skinname, tok.string, sizeof( skinname ));
+ FS_StripExtension( skinname );
+ }
+ else
+ {
+ com.strncpy( meshname, tok.string, sizeof( meshname ));
+ continue; // waiting for ','
+ }
if( pairs )
{
- *t = 0;
- pairs[numpairs].meshname = SkinFile_CopyString( token );
- pairs[numpairs].shader = R_RegisterSkin( token + strlen( token ) + 1 );
+ pairs[numpairs].meshname = SkinFile_CopyString( meshname );
+ pairs[numpairs].shader = R_LoadShader( skinname, SHADER_ALIAS, false, 0, SHADER_INVALID );
}
-
numpairs++;
}
+ Com_CloseScript( script );
return numpairs;
}
diff --git a/render/r_skm.c b/render/r_skm.c
index 103eb5bd..0cb023a1 100644
--- a/render/r_skm.c
+++ b/render/r_skm.c
@@ -284,7 +284,8 @@ void Mod_LoadSkeletalModel( ref_model_t *mod, ref_model_t *parent, const void *b
com.strncpy( poutmesh->name, pinmesh->meshname, sizeof( poutmesh->name ) );
Mod_StripLODSuffix( poutmesh->name );
- poutmesh->skin.shader = R_RegisterSkin( pinmesh->shadername );
+ FS_StripExtension( pinmesh->shadername );
+ poutmesh->skin.shader = R_LoadShader( pinmesh->shadername, SHADER_ALIAS, false, 0, SHADER_INVALID );
R_DeformvBBoxForShader( poutmesh->skin.shader, ebbox );
pinreferences = ( elem_t *)( ( byte * )pinmodel + LittleLong( pinmesh->ofs_references ) );
diff --git a/render/r_sky.c b/render/r_sky.c
index 863069fb..73629769 100644
--- a/render/r_sky.c
+++ b/render/r_sky.c
@@ -253,22 +253,12 @@ Draw dummy skybox side to prevent the HOM effect
*/
static void R_DrawBlackBottom( skydome_t *skydome )
{
- int features;
- ref_shader_t *shader;
+ int features;
- // FIXME: register another shader instead maybe?
- shader = R_OcclusionShader ();
-
- features = shader->features;
+ features = tr.defaultShader->features;
if( r_shownormals->integer )
features |= MF_NORMALS;
-
- // HACKHACK skies ought not to write to depth buffer
- shader->flags &= ~SHADER_DEPTHWRITE;
- shader->stages[0].glState &= ~GLSTATE_DEPTHWRITE;
- R_DrawSkySide( skydome, 5, shader, features );
- shader->stages[0].glState |= GLSTATE_DEPTHWRITE;
- shader->flags |= SHADER_DEPTHWRITE;
+ R_DrawSkySide( skydome, 5, tr.defaultShader, features );
}
/*
@@ -370,8 +360,7 @@ void R_DrawSky( ref_shader_t *shader )
for( i = 0; i < 5; i++ )
{
- if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] ||
- RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
+ if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
continue;
flush = true;
@@ -382,9 +371,7 @@ void R_DrawSky( ref_shader_t *shader )
skydome->meshes[i].stArray = skydome->sphereStCoords[i];
R_PushMesh( &skydome->meshes[i], features );
}
-
- if( flush )
- R_RenderMeshBuffer( mbuffer );
+ if( flush ) R_RenderMeshBuffer( mbuffer );
}
if( skydome->nearboxShaders[0] )
diff --git a/render/r_surf.c b/render/r_surf.c
index 2d98473f..7e7465e2 100644
--- a/render/r_surf.c
+++ b/render/r_surf.c
@@ -335,10 +335,10 @@ R_RecursiveWorldNode
*/
static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipflags, unsigned int dlightbits )
{
- unsigned int i, newDlightbits;
- unsigned int bit;
- const cplane_t *clipplane;
- mleaf_t *pleaf;
+ uint i, newDlightbits;
+ const cplane_t *clipplane;
+ int clipped;
+ mleaf_t *pleaf;
while( 1 )
{
@@ -347,18 +347,16 @@ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipflags, unsigne
if( clipflags )
{
- for( i = sizeof( RI.frustum )/sizeof( RI.frustum[0] ), bit = 1, clipplane = RI.frustum; i > 0; i--, bit<<=1, clipplane++ )
+ for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ )
{
- if( clipflags & bit )
- {
- int clipped = BoxOnPlaneSide( node->mins, node->maxs, clipplane );
- if( clipped == 2 )
- return;
- if( clipped == 1 )
- clipflags &= ~bit; // node is entirely on screen
- }
+ if(!(clipflags & (1<mins, node->maxs, clipplane );
+ if( clipped == 2 ) return;
+ if( clipped == 1 ) clipflags &= ~(1<plane )
break;
@@ -368,16 +366,16 @@ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipflags, unsigne
{
float dist;
- for( i = 0, bit = 1; i < r_numDlights; i++, bit <<= 1 )
+ for( i = 0; i < r_numDlights; i++ )
{
- if( !( dlightbits & bit ) )
+ if( !( dlightbits & (1<plane );
if( dist < -r_dlights[i].intensity )
- dlightbits &= ~bit;
+ dlightbits &= ~(1<numleafs, pleaf = r_worldbrushmodel->leafs; j > 0; j--, pleaf++ )
{
@@ -455,16 +453,15 @@ static void R_LinearShadowLeafs( void )
continue;
cpf = RI.clipFlags;
- for( i = sizeof( RI.frustum )/sizeof( RI.frustum[0] ), bit = 1, clipplane = RI.frustum; i > 0; i--, bit<<=1, clipplane++ )
+
+ for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ )
{
int clipped = BoxOnPlaneSide( pleaf->mins, pleaf->maxs, clipplane );
- if( clipped == 2 )
- break;
- if( clipped == 1 )
- cpf &= ~bit; // leaf is entirely on screen
+ if( clipped == 2 ) break;
+ if( clipped == 1 ) cpf &= ~(1<firstVisSurface, cpf );
c_world_leafs++;
}
diff --git a/render/render.dsp b/render/render.dsp
index f2025775..90ccb029 100644
--- a/render/render.dsp
+++ b/render/render.dsp
@@ -194,10 +194,6 @@ SOURCE=.\r_skin.c
# End Source File
# Begin Source File
-SOURCE=.\r_skm.c
-# End Source File
-# Begin Source File
-
SOURCE=.\r_sky.c
# End Source File
# Begin Source File
diff --git a/render/render.plg b/render/render.plg
index c5158a88..66e34829 100644
--- a/render/render.plg
+++ b/render/render.plg
@@ -6,6 +6,51 @@
--------------------Configuration: render - Win32 Debug--------------------
Command Lines
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD5.tmp" with contents
+[
+/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\render\!debug/" /Fo"..\temp\render\!debug/" /Fd"..\temp\render\!debug/" /FD /c
+"D:\Xash3D\src_main\render\r_image.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD5.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD6.tmp" with contents
+[
+msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\render\!debug/render.pdb" /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\temp\render\!debug/render.dll" /implib:"..\temp\render\!debug/render.lib" /pdbtype:sept
+"\Xash3D\src_main\temp\render\!debug\cin.obj"
+"\Xash3D\src_main\temp\render\!debug\r_alias.obj"
+"\Xash3D\src_main\temp\render\!debug\r_backend.obj"
+"\Xash3D\src_main\temp\render\!debug\r_bloom.obj"
+"\Xash3D\src_main\temp\render\!debug\r_cin.obj"
+"\Xash3D\src_main\temp\render\!debug\r_cull.obj"
+"\Xash3D\src_main\temp\render\!debug\r_draw.obj"
+"\Xash3D\src_main\temp\render\!debug\r_image.obj"
+"\Xash3D\src_main\temp\render\!debug\r_light.obj"
+"\Xash3D\src_main\temp\render\!debug\r_main.obj"
+"\Xash3D\src_main\temp\render\!debug\r_math.obj"
+"\Xash3D\src_main\temp\render\!debug\r_mesh.obj"
+"\Xash3D\src_main\temp\render\!debug\r_model.obj"
+"\Xash3D\src_main\temp\render\!debug\r_opengl.obj"
+"\Xash3D\src_main\temp\render\!debug\r_poly.obj"
+"\Xash3D\src_main\temp\render\!debug\r_program.obj"
+"\Xash3D\src_main\temp\render\!debug\r_register.obj"
+"\Xash3D\src_main\temp\render\!debug\r_shader.obj"
+"\Xash3D\src_main\temp\render\!debug\r_shadow.obj"
+"\Xash3D\src_main\temp\render\!debug\r_skin.obj"
+"\Xash3D\src_main\temp\render\!debug\r_sky.obj"
+"\Xash3D\src_main\temp\render\!debug\r_surf.obj"
+]
+Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD6.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD7.bat" with contents
+[
+@echo off
+copy \Xash3D\src_main\temp\render\!debug\render.dll "D:\Xash3D\bin\render.dll"
+]
+Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD7.bat"
+Compiling...
+r_image.c
+Linking...
+Output Window
+Performing Custom Build Step on \Xash3D\src_main\temp\render\!debug\render.dll
+‘Є®ЇЁа®ў ® д ©«®ў: 1.
diff --git a/server/global/client.cpp b/server/global/client.cpp
index 28bf8b45..7783c75c 100644
--- a/server/global/client.cpp
+++ b/server/global/client.cpp
@@ -1134,12 +1134,13 @@ const char *GetGameDescription( void )
{
char token[256];
char szbuffer[128];
- char *pfile = (char *)LOAD_FILE( "gameinfo.txt", NULL );
+ char *afile, *pfile = (char *)LOAD_FILE( "gameinfo.txt", NULL );
memset( text, 0, sizeof( text ));
if( pfile )
{
+ afile = pfile;
while( pfile )
{
if( !stricmp( token, "title" ))
@@ -1155,7 +1156,7 @@ const char *GetGameDescription( void )
}
pfile = COM_ParseFile( pfile, token );
}
- COM_FreeFile( pfile );
+ COM_FreeFile( afile );
return text;
}
return "Half-Life";
diff --git a/server/global/utils.cpp b/server/global/utils.cpp
index db297537..2aa3be28 100644
--- a/server/global/utils.cpp
+++ b/server/global/utils.cpp
@@ -1397,6 +1397,7 @@ void UTIL_PrecacheResourse( void )
char *pfile = (char *)LOAD_FILE( "scripts/precache.txt", NULL );
if( pfile )
{
+ char *afile = pfile;
while( pfile )
{
if( !stricmp( token, "entity" ))
@@ -1436,7 +1437,7 @@ void UTIL_PrecacheResourse( void )
}
pfile = COM_ParseFile( pfile, token );
}
- COM_FreeFile( pfile );
+ COM_FreeFile( afile );
}
}
diff --git a/server/monsters/player.cpp b/server/monsters/player.cpp
index 80c47425..af8f7727 100644
--- a/server/monsters/player.cpp
+++ b/server/monsters/player.cpp
@@ -3859,23 +3859,24 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse )
{
gEvilImpulse101 = TRUE;
char *pfile = (char *)LOAD_FILE( "scripts/impulse101.txt", NULL );
- int ItemName [256];
+ int ItemName[256];
int count = 0;
char token[32];
- if(pfile)
+ if( pfile )
{
- while ( pfile )
+ char *afile = pfile;
+ while( pfile )
{
- //parsing impulse101.txt
- pfile = COM_ParseFile(pfile, token);
- if(strlen(token))
+ // parsing impulse101.txt
+ pfile = COM_ParseFile( pfile, token );
+ if(strlen( token ))
{
- ItemName[ count ] = ALLOC_STRING( (char *)token );
+ ItemName[count] = ALLOC_STRING( (char *)token );
count++;
}
}
- COM_FreeFile( pfile );
+ COM_FreeFile( afile );
for( int i = 0; i < count; i++ )
GiveNamedItem( (char *)STRING( ItemName[i]) );
}
diff --git a/server/server.plg b/server/server.plg
new file mode 100644
index 00000000..2aaf2920
--- /dev/null
+++ b/server/server.plg
@@ -0,0 +1,100 @@
+
+
+
+Build Log
+
+--------------------Configuration: server - Win32 Debug--------------------
+
+Command Lines
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBB.tmp" with contents
+[
+/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "ents" /I "game" /I "global" /I "monsters" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\server\!debug/" /Fo"..\temp\server\!debug/" /Fd"..\temp\server\!debug/" /FD /c
+"D:\Xash3D\src_main\server\global\client.cpp"
+]
+Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBB.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBC.tmp" with contents
+[
+msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\server\!debug/server.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /def:".\server.def" /out:"..\temp\server\!debug/server.dll" /implib:"..\temp\server\!debug/server.lib" /pdbtype:sept
+"\Xash3D\src_main\temp\server\!debug\ai_sound.obj"
+"\Xash3D\src_main\temp\server\!debug\animating.obj"
+"\Xash3D\src_main\temp\server\!debug\animation.obj"
+"\Xash3D\src_main\temp\server\!debug\apache.obj"
+"\Xash3D\src_main\temp\server\!debug\barnacle.obj"
+"\Xash3D\src_main\temp\server\!debug\barney.obj"
+"\Xash3D\src_main\temp\server\!debug\basebrush.obj"
+"\Xash3D\src_main\temp\server\!debug\baseentity.obj"
+"\Xash3D\src_main\temp\server\!debug\basefunc.obj"
+"\Xash3D\src_main\temp\server\!debug\basefx.obj"
+"\Xash3D\src_main\temp\server\!debug\baseinfo.obj"
+"\Xash3D\src_main\temp\server\!debug\baseitem.obj"
+"\Xash3D\src_main\temp\server\!debug\baselogic.obj"
+"\Xash3D\src_main\temp\server\!debug\basemonster.obj"
+"\Xash3D\src_main\temp\server\!debug\basemover.obj"
+"\Xash3D\src_main\temp\server\!debug\baseother.obj"
+"\Xash3D\src_main\temp\server\!debug\basepath.obj"
+"\Xash3D\src_main\temp\server\!debug\basephys.obj"
+"\Xash3D\src_main\temp\server\!debug\baserockets.obj"
+"\Xash3D\src_main\temp\server\!debug\basetank.obj"
+"\Xash3D\src_main\temp\server\!debug\basetrigger.obj"
+"\Xash3D\src_main\temp\server\!debug\baseutil.obj"
+"\Xash3D\src_main\temp\server\!debug\baseweapon.obj"
+"\Xash3D\src_main\temp\server\!debug\baseworld.obj"
+"\Xash3D\src_main\temp\server\!debug\client.obj"
+"\Xash3D\src_main\temp\server\!debug\combat.obj"
+"\Xash3D\src_main\temp\server\!debug\decals.obj"
+"\Xash3D\src_main\temp\server\!debug\defaultai.obj"
+"\Xash3D\src_main\temp\server\!debug\dll_int.obj"
+"\Xash3D\src_main\temp\server\!debug\flyingmonster.obj"
+"\Xash3D\src_main\temp\server\!debug\game.obj"
+"\Xash3D\src_main\temp\server\!debug\gamerules.obj"
+"\Xash3D\src_main\temp\server\!debug\generic.obj"
+"\Xash3D\src_main\temp\server\!debug\globals.obj"
+"\Xash3D\src_main\temp\server\!debug\gman.obj"
+"\Xash3D\src_main\temp\server\!debug\hassassin.obj"
+"\Xash3D\src_main\temp\server\!debug\headcrab.obj"
+"\Xash3D\src_main\temp\server\!debug\hgrunt.obj"
+"\Xash3D\src_main\temp\server\!debug\leech.obj"
+"\Xash3D\src_main\temp\server\!debug\legacy.obj"
+"\Xash3D\src_main\temp\server\!debug\lights.obj"
+"\Xash3D\src_main\temp\server\!debug\multiplay_gamerules.obj"
+"\Xash3D\src_main\temp\server\!debug\nodes.obj"
+"\Xash3D\src_main\temp\server\!debug\osprey.obj"
+"\Xash3D\src_main\temp\server\!debug\parent.obj"
+"\Xash3D\src_main\temp\server\!debug\player.obj"
+"\Xash3D\src_main\temp\server\!debug\rat.obj"
+"\Xash3D\src_main\temp\server\!debug\roach.obj"
+"\Xash3D\src_main\temp\server\!debug\saverestore.obj"
+"\Xash3D\src_main\temp\server\!debug\scientist.obj"
+"\Xash3D\src_main\temp\server\!debug\scripted.obj"
+"\Xash3D\src_main\temp\server\!debug\sfx.obj"
+"\Xash3D\src_main\temp\server\!debug\singleplay_gamerules.obj"
+"\Xash3D\src_main\temp\server\!debug\sound.obj"
+"\Xash3D\src_main\temp\server\!debug\squadmonster.obj"
+"\Xash3D\src_main\temp\server\!debug\talkmonster.obj"
+"\Xash3D\src_main\temp\server\!debug\teamplay_gamerules.obj"
+"\Xash3D\src_main\temp\server\!debug\turret.obj"
+"\Xash3D\src_main\temp\server\!debug\utils.obj"
+"\Xash3D\src_main\temp\server\!debug\weapon_generic.obj"
+"\Xash3D\src_main\temp\server\!debug\zombie.obj"
+]
+Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBC.tmp"
+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBD.bat" with contents
+[
+@echo off
+copy \Xash3D\src_main\temp\server\!debug\server.dll "D:\Xash3D\bin\server.dll"
+]
+Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBD.bat"
+Compiling...
+client.cpp
+Linking...
+Output Window
+Performing Custom Build Step on \Xash3D\src_main\temp\server\!debug\server.dll
+‘Є®ЇЁа®ў ® д ©«®ў: 1.
+
+
+
+Results
+server.dll - 0 error(s), 0 warning(s)
+
+
+
diff --git a/todo.log b/todo.log
index 27d642bc..0a122e8d 100644
--- a/todo.log
+++ b/todo.log
@@ -11,9 +11,6 @@ fopen
возвращал.
fopen завешивает приложение, даже если перепутать местами + и a, при установке режима!
-Memory Leaks:
-Filesystem Pool растет на 4 килобайта после смены карты
-
Отложенные задачи:
1. Поддержка loop для ogg vorbis
2. переписать studiomdl для использования VFS
@@ -98,7 +95,7 @@ Beta 13.12.08
64. ImageLoading from old render OK
65. envshot, skyshot swap angles to right pos
66. ShaderSystem from old render OK
-67. fixup NPOT textures loading (screen textures)
+67. fixup NPOT textures loading (screen textures) OK
68. add new shader types OK
69. implement oldareabits OK
70. repair fog texture OK
@@ -107,9 +104,16 @@ Beta 13.12.08
73. shaders pasring OK
74. fixup 3D textures loading OK
75. ignore shader errors - just throw warnings OK
-76. launch.dll ->release gl_invalid_enum
+76. launch.dll ->release gl_invalid_enum OK
77. debug shader_free_unused mechanism OK
-78. fix changemap errors
-79. memory trash in render.dll
-
-
+78. fix changemap errors OK
+79. memory trash in render.dll OK
+80. implement $rgb, $alpha OK
+89. get rid of R_Upload32 OK
+90. get rid of Com_ParseExt OK
+91. Xash backend extensions
+92. implement VBO OK
+93. implement sky rotate
+94. make default sky shader, R_SetupSky
+95. support for custom tables (external)
+96. implement sprite format
diff --git a/vsound/s_load.c b/vsound/s_load.c
index 8e5073d8..75276201 100644
--- a/vsound/s_load.c
+++ b/vsound/s_load.c
@@ -261,6 +261,7 @@ static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info )
if( samples < info->samples )
{
MsgDev( D_ERROR, "S_LoadWAV: %s has a bad loop length\n", name );
+ Mem_Free( buffer );
return false;
}
}