03 Oct 2010
This commit is contained in:
parent
e22ec1a233
commit
2ed0925353
|
@ -35,11 +35,12 @@ void CL_WriteDemoMessage( sizebuf_t *msg, int head_size )
|
|||
|
||||
void CL_WriteDemoHeader( const char *name )
|
||||
{
|
||||
int i, j, len;
|
||||
char buf_data[MAX_MSGLEN];
|
||||
entity_state_t *state, nullstate;
|
||||
movevars_t nullmovevars;
|
||||
sizebuf_t buf;
|
||||
int i, len;
|
||||
delta_info_t *dt;
|
||||
|
||||
MsgDev( D_INFO, "recording to %s.\n", name );
|
||||
cls.demofile = FS_Open( name, "wb" );
|
||||
|
@ -91,7 +92,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
// user messages
|
||||
for( i = 0; i < MAX_USER_MESSAGES; i++ )
|
||||
{
|
||||
if( clgame.msg[i].name[0] )
|
||||
if( clgame.msg[i].name[0] && clgame.msg[i].number >= svc_lastmsg )
|
||||
{
|
||||
BF_WriteByte( &buf, svc_usermessage );
|
||||
BF_WriteString( &buf, clgame.msg[i].name );
|
||||
|
@ -110,6 +111,26 @@ void CL_WriteDemoHeader( const char *name )
|
|||
|
||||
}
|
||||
|
||||
// delta tables
|
||||
for( i = 0; i < Delta_NumTables( ); i++ )
|
||||
{
|
||||
dt = Delta_FindStructByIndex( i );
|
||||
|
||||
for( j = 0; j < dt->numFields; j++ )
|
||||
{
|
||||
Delta_WriteTableField( &buf, i, &dt->pFields[j] );
|
||||
|
||||
if( BF_GetNumBytesWritten( &buf ) > ( BF_GetMaxBytes( &buf ) / 2 ))
|
||||
{
|
||||
// write it out
|
||||
len = LittleLong( BF_GetNumBytesWritten( &buf ));
|
||||
FS_Write( cls.demofile, &len, 4 );
|
||||
FS_Write( cls.demofile, BF_GetData( &buf ), len );
|
||||
BF_Clear( &buf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// baselines
|
||||
Mem_Set( &nullstate, 0, sizeof( nullstate ));
|
||||
Mem_Set( &nullmovevars, 0, sizeof( nullmovevars ));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2009 ©
|
||||
// cl_video.c - roq video player
|
||||
// cl_video.c - avi video player
|
||||
//=======================================================================
|
||||
|
||||
#include "common.h"
|
||||
|
@ -235,6 +235,9 @@ SCR_StopCinematic
|
|||
*/
|
||||
void SCR_StopCinematic( void )
|
||||
{
|
||||
if( cls.state != ca_cinematic )
|
||||
return;
|
||||
|
||||
AVI_CloseVideo( cin_state );
|
||||
S_StopStreaming();
|
||||
cin_time = 0.0f;
|
||||
|
|
|
@ -232,14 +232,7 @@ void Key_EnumCmds_f( void );
|
|||
void Key_SetKeyDest( int key_dest );
|
||||
|
||||
//
|
||||
// cinematic.c
|
||||
//
|
||||
void CIN_Init( void );
|
||||
void CIN_ReadChunk( cinematics_t *cin );
|
||||
byte *CIN_ReadNextFrame( cinematics_t *cin, bool silent );
|
||||
|
||||
//
|
||||
// movie.c
|
||||
// avikit.c
|
||||
//
|
||||
typedef struct movie_state_s movie_state_t;
|
||||
long AVI_GetVideoFrameNumber( movie_state_t *Avi, float time );
|
||||
|
|
|
@ -1,449 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2009 ©
|
||||
// cinematic.c - decompress RoQ audio & video
|
||||
//=======================================================================
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "byteorder.h"
|
||||
|
||||
#define RoQ_READ_BLOCK 0x4000
|
||||
#define RoQ_ReadRaw() read = min( sizeof( raw ), remaining ); remaining -= read; FS_Read( cin->file, raw, read );
|
||||
#define RoQ_ReadByte( x ) if( bpos >= read ) { RoQ_ReadRaw (); bpos = 0; } (x) = raw[bpos++];
|
||||
#define RoQ_ReadShort( x ) if( bpos+1 == read ) { c = raw[bpos]; RoQ_ReadRaw (); (x)=(raw[0] << 8)|c; bpos=1; } \
|
||||
else { if( bpos+1 > read ) { RoQ_ReadRaw (); bpos = 0; } (x)=(raw[bpos+1] << 8)|raw[bpos]; bpos+=2; }
|
||||
#define RoQ_ReadFlag() if( vqflg_pos < 0 ) { RoQ_ReadShort( vqflg ); vqflg_pos = 7; } \
|
||||
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; vqflg_pos--;
|
||||
|
||||
static short snd_sqr_arr[256];
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_Init
|
||||
==================
|
||||
*/
|
||||
void RoQ_Init( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 128; i++ )
|
||||
{
|
||||
snd_sqr_arr[i] = i * i;
|
||||
snd_sqr_arr[i + 128] = -(i * i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ReadChunk
|
||||
==================
|
||||
*/
|
||||
void RoQ_ReadChunk( cinematics_t *cin )
|
||||
{
|
||||
droqchunk_t *chunk = &cin->chunk;
|
||||
|
||||
FS_Read( cin->file, &chunk->id, sizeof( short ));
|
||||
FS_Read( cin->file, &chunk->size, sizeof( int ));
|
||||
FS_Read( cin->file, &chunk->argument, sizeof( short ));
|
||||
|
||||
chunk->id = LittleShort( chunk->id );
|
||||
chunk->size = LittleLong( chunk->size );
|
||||
chunk->argument = LittleShort( chunk->argument );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_SkipBlock
|
||||
==================
|
||||
*/
|
||||
static _inline void RoQ_SkipBlock( cinematics_t *cin, int size )
|
||||
{
|
||||
FS_Seek( cin->file, size, SEEK_CUR );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_SkipChunk
|
||||
==================
|
||||
*/
|
||||
void RoQ_SkipChunk( cinematics_t *cin )
|
||||
{
|
||||
RoQ_SkipBlock( cin, cin->chunk.size );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ReadInfo
|
||||
==================
|
||||
*/
|
||||
void RoQ_ReadInfo( cinematics_t *cin )
|
||||
{
|
||||
short t[4];
|
||||
|
||||
FS_Read( cin->file, t, sizeof( short ) * 4 );
|
||||
|
||||
if( cin->width != LittleShort( t[0] ) || cin->height != LittleShort( t[1] ))
|
||||
{
|
||||
cin->width = LittleShort( t[0] );
|
||||
cin->height = LittleShort( t[1] );
|
||||
|
||||
if( cin->vid_buffer )
|
||||
Mem_Free( cin->vid_buffer );
|
||||
|
||||
// default to 255 for alpha
|
||||
if( cin->mempool )
|
||||
cin->vid_buffer = Mem_Alloc( cin->mempool, cin->width * cin->height * 4 * 2 );
|
||||
else cin->vid_buffer = Mem_Alloc( cls.mempool, cin->width * cin->height * 4 * 2 );
|
||||
|
||||
Mem_Set( cin->vid_buffer, 0xFF, cin->width * cin->height * 4 * 2 );
|
||||
cin->vid_pic[0] = cin->vid_buffer;
|
||||
cin->vid_pic[1] = cin->vid_buffer + cin->width * cin->height * 4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ReadCodebook
|
||||
==================
|
||||
*/
|
||||
void RoQ_ReadCodebook( cinematics_t *cin )
|
||||
{
|
||||
int nv1, nv2;
|
||||
droqchunk_t *chunk = &cin->chunk;
|
||||
|
||||
nv1 = (chunk->argument >> 8) & 0xFF;
|
||||
if( !nv1 ) nv1 = 256;
|
||||
|
||||
nv2 = chunk->argument & 0xFF;
|
||||
if( !nv2 && ( nv1 * 6 < chunk->size ))
|
||||
nv2 = 256;
|
||||
|
||||
FS_Read( cin->file, cin->cells, sizeof( dcell_t) * nv1 );
|
||||
FS_Read( cin->file, cin->qcells, sizeof( dquadcell_t ) * nv2 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ApplyVector2x2
|
||||
==================
|
||||
*/
|
||||
static void RoQ_DecodeBlock( byte *dst0, byte *dst1, const byte *src0, const byte *src1, float u, float v )
|
||||
{
|
||||
int c[3];
|
||||
|
||||
// convert YCbCr to RGB
|
||||
VectorSet( c, 1.402f * v, -0.34414f * u - 0.71414f * v, 1.772f * u );
|
||||
|
||||
// 1st pixel
|
||||
dst0[0] = bound( 0, c[0] + src0[0], 255 );
|
||||
dst0[1] = bound( 0, c[1] + src0[0], 255 );
|
||||
dst0[2] = bound( 0, c[2] + src0[0], 255 );
|
||||
|
||||
// 2nd pixel
|
||||
dst0[4] = bound( 0, c[0] + src0[1], 255 );
|
||||
dst0[5] = bound( 0, c[1] + src0[1], 255 );
|
||||
dst0[6] = bound( 0, c[2] + src0[1], 255 );
|
||||
|
||||
// 3rd pixel
|
||||
dst1[0] = bound( 0, c[0] + src1[0], 255 );
|
||||
dst1[1] = bound( 0, c[1] + src1[0], 255 );
|
||||
dst1[2] = bound( 0, c[2] + src1[0], 255 );
|
||||
|
||||
// 4th pixel
|
||||
dst1[4] = bound( 0, c[0] + src1[1], 255 );
|
||||
dst1[5] = bound( 0, c[1] + src1[1], 255 );
|
||||
dst1[6] = bound( 0, c[2] + src1[1], 255 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ApplyVector2x2
|
||||
==================
|
||||
*/
|
||||
static void RoQ_ApplyVector2x2( cinematics_t *cin, int x, int y, const dcell_t *cell )
|
||||
{
|
||||
byte *dst0, *dst1;
|
||||
|
||||
dst0 = cin->vid_pic[0] + (y * cin->width + x) * 4;
|
||||
dst1 = dst0 + cin->width * 4;
|
||||
|
||||
RoQ_DecodeBlock( dst0, dst1, cell->y, cell->y+2, (float)((int)cell->u - 128), (float)((int)cell->v - 128));
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ApplyVector4x4
|
||||
==================
|
||||
*/
|
||||
static void RoQ_ApplyVector4x4( cinematics_t *cin, int x, int y, const dcell_t *cell )
|
||||
{
|
||||
byte *dst0, *dst1;
|
||||
byte p[4];
|
||||
float u, v;
|
||||
|
||||
u = (float)((int)cell->u - 128);
|
||||
v = (float)((int)cell->v - 128);
|
||||
|
||||
p[0] = p[1] = cell->y[0];
|
||||
p[2] = p[3] = cell->y[1];
|
||||
dst0 = cin->vid_pic[0] + (y * cin->width + x) * 4; dst1 = dst0 + cin->width * 4;
|
||||
RoQ_DecodeBlock( dst0, dst0+8, p, p+2, u, v );
|
||||
RoQ_DecodeBlock( dst1, dst1+8, p, p+2, u, v );
|
||||
|
||||
p[0] = p[1] = cell->y[2];
|
||||
p[2] = p[3] = cell->y[3];
|
||||
dst0 += cin->width * 4 * 2; dst1 += cin->width * 4 * 2;
|
||||
RoQ_DecodeBlock( dst0, dst0+8, p, p+2, u, v );
|
||||
RoQ_DecodeBlock( dst1, dst1+8, p, p+2, u, v );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ApplyMotion4x4
|
||||
==================
|
||||
*/
|
||||
static void RoQ_ApplyMotion4x4( cinematics_t *cin, int x, int y, byte mv, char mean_x, char mean_y )
|
||||
{
|
||||
int x0, y0;
|
||||
byte *src, *dst;
|
||||
|
||||
// calc source coords
|
||||
x0 = x + 8 - (mv >> 4) - mean_x;
|
||||
y0 = y + 8 - (mv & 0xF) - mean_y;
|
||||
|
||||
src = cin->vid_pic[1] + (y0 * cin->width + x0) * 4;
|
||||
dst = cin->vid_pic[0] + (y * cin->width + x) * 4;
|
||||
|
||||
for( y = 0; y < 4; y++, src += cin->width * 4, dst += cin->width * 4 )
|
||||
Mem_Copy( dst, src, 4 * 4 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ApplyMotion8x8
|
||||
==================
|
||||
*/
|
||||
static void RoQ_ApplyMotion8x8( cinematics_t *cin, int x, int y, byte mv, char mean_x, char mean_y )
|
||||
{
|
||||
int x0, y0;
|
||||
byte *src, *dst;
|
||||
|
||||
// calc source coords
|
||||
x0 = x + 8 - (mv >> 4) - mean_x;
|
||||
y0 = y + 8 - (mv & 0xF) - mean_y;
|
||||
|
||||
src = cin->vid_pic[1] + (y0 * cin->width + x0) * 4;
|
||||
dst = cin->vid_pic[0] + (y * cin->width + x) * 4;
|
||||
|
||||
for( y = 0; y < 8; y++, src += cin->width * 4, dst += cin->width * 4 )
|
||||
Mem_Copy( dst, src, 8 * 4 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ReadVideo
|
||||
==================
|
||||
*/
|
||||
byte *RoQ_ReadVideo( cinematics_t *cin )
|
||||
{
|
||||
droqchunk_t *chunk = &cin->chunk;
|
||||
int i, vqflg, vqflg_pos, vqid;
|
||||
int xpos, ypos, x, y, xp, yp;
|
||||
byte c, *tp;
|
||||
dquadcell_t *qcell;
|
||||
byte raw[RoQ_READ_BLOCK];
|
||||
uint remaining, bpos, read;
|
||||
|
||||
vqflg = 0;
|
||||
vqflg_pos = -1;
|
||||
xpos = ypos = 0;
|
||||
|
||||
for( bpos = read = 0, remaining = chunk->size; bpos < read || remaining; )
|
||||
{
|
||||
for( yp = ypos; yp < ypos + 16; yp += 8 )
|
||||
{
|
||||
for( xp = xpos; xp < xpos + 16; xp += 8 )
|
||||
{
|
||||
RoQ_ReadFlag ();
|
||||
|
||||
switch( vqid )
|
||||
{
|
||||
case RoQ_ID_MOT:
|
||||
break;
|
||||
case RoQ_ID_FCC:
|
||||
RoQ_ReadByte( c );
|
||||
RoQ_ApplyMotion8x8( cin, xp, yp, c, ( char )((chunk->argument >> 8) & 0xff), (char)(chunk->argument & 0xff) );
|
||||
break;
|
||||
case RoQ_ID_SLD:
|
||||
RoQ_ReadByte( c );
|
||||
qcell = cin->qcells + c;
|
||||
RoQ_ApplyVector4x4( cin, xp, yp, cin->cells + qcell->idx[0] );
|
||||
RoQ_ApplyVector4x4( cin, xp+4, yp, cin->cells + qcell->idx[1] );
|
||||
RoQ_ApplyVector4x4( cin, xp, yp+4, cin->cells + qcell->idx[2] );
|
||||
RoQ_ApplyVector4x4( cin, xp+4, yp+4, cin->cells + qcell->idx[3] );
|
||||
break;
|
||||
case RoQ_ID_CCC:
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
x = xp; if( i & 0x01 ) x += 4;
|
||||
y = yp; if( i & 0x02 ) y += 4;
|
||||
|
||||
RoQ_ReadFlag ();
|
||||
|
||||
switch( vqid )
|
||||
{
|
||||
case RoQ_ID_MOT:
|
||||
break;
|
||||
case RoQ_ID_FCC:
|
||||
RoQ_ReadByte( c );
|
||||
RoQ_ApplyMotion4x4( cin, x, y, c, (char)((chunk->argument>>8) & 0xff), (char)(chunk->argument & 0xff ));
|
||||
break;
|
||||
case RoQ_ID_SLD:
|
||||
RoQ_ReadByte( c );
|
||||
qcell = cin->qcells + c;
|
||||
RoQ_ApplyVector2x2( cin, x, y, cin->cells + qcell->idx[0] );
|
||||
RoQ_ApplyVector2x2( cin, x+2, y, cin->cells + qcell->idx[1] );
|
||||
RoQ_ApplyVector2x2( cin, x, y+2, cin->cells + qcell->idx[2] );
|
||||
RoQ_ApplyVector2x2( cin, x+2, y+2, cin->cells + qcell->idx[3] );
|
||||
break;
|
||||
case RoQ_ID_CCC:
|
||||
RoQ_ReadByte( c );
|
||||
RoQ_ApplyVector2x2( cin, x, y, cin->cells + c );
|
||||
RoQ_ReadByte( c );
|
||||
RoQ_ApplyVector2x2( cin, x+2, y, cin->cells + c );
|
||||
RoQ_ReadByte( c );
|
||||
RoQ_ApplyVector2x2( cin, x, y+2, cin->cells + c );
|
||||
RoQ_ReadByte( c );
|
||||
RoQ_ApplyVector2x2( cin, x+2, y+2, cin->cells + c );
|
||||
break;
|
||||
default:
|
||||
MsgDev( D_WARN, "Unknown vq code: %d\n", vqid );
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MsgDev( D_WARN, "Unknown vq code: %d\n", vqid );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xpos += 16;
|
||||
if( xpos >= cin->width )
|
||||
{
|
||||
xpos -= cin->width;
|
||||
|
||||
ypos += 16;
|
||||
if( ypos >= cin->height )
|
||||
{
|
||||
RoQ_SkipBlock( cin, remaining ); // ignore remaining trash
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( cin->frame++ == 0 )
|
||||
{
|
||||
// copy initial values to back buffer for motion
|
||||
Mem_Copy( cin->vid_pic[1], cin->vid_pic[0], cin->width * cin->height * 4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// swap buffers
|
||||
tp = cin->vid_pic[0]; cin->vid_pic[0] = cin->vid_pic[1]; cin->vid_pic[1] = tp;
|
||||
}
|
||||
return cin->vid_pic[1];
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RoQ_ReadAudio
|
||||
==================
|
||||
*/
|
||||
void RoQ_ReadAudio( cinematics_t *cin )
|
||||
{
|
||||
int snd_left, snd_right;
|
||||
byte raw[RoQ_READ_BLOCK];
|
||||
short samples[RoQ_READ_BLOCK];
|
||||
droqchunk_t *chunk = &cin->chunk;
|
||||
uint i, remaining, read;
|
||||
|
||||
if( chunk->id == RoQ_SOUND_MONO )
|
||||
{
|
||||
snd_left = chunk->argument;
|
||||
snd_right = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
snd_left = chunk->argument & 0xff00;
|
||||
snd_right = (chunk->argument & 0xff) << 8;
|
||||
}
|
||||
|
||||
for( remaining = chunk->size; remaining > 0; remaining -= read )
|
||||
{
|
||||
read = min( sizeof( raw ), remaining );
|
||||
FS_Read( cin->file, raw, read );
|
||||
|
||||
if( chunk->id == RoQ_SOUND_MONO )
|
||||
{
|
||||
for( i = 0; i < read; i++ )
|
||||
{
|
||||
snd_left += snd_sqr_arr[raw[i]];
|
||||
samples[i] = (short)snd_left;
|
||||
snd_left = (short)snd_left;
|
||||
}
|
||||
S_RawSamples( read, cin->s_rate, 2, 1, (byte *)samples );
|
||||
}
|
||||
else if( chunk->id == RoQ_SOUND_STEREO )
|
||||
{
|
||||
for( i = 0; i < read; i += 2 )
|
||||
{
|
||||
snd_left += snd_sqr_arr[raw[i]];
|
||||
samples[i+0] = (short)snd_left;
|
||||
snd_left = (short)snd_left;
|
||||
|
||||
snd_right += snd_sqr_arr[raw[i+1]];
|
||||
samples[i+1] = (short)snd_right;
|
||||
snd_right = (short)snd_right;
|
||||
}
|
||||
S_RawSamples( read / 2, cin->s_rate, 2, 2, (byte *)samples );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CIN_Init( void )
|
||||
{
|
||||
RoQ_Init();
|
||||
}
|
||||
|
||||
void CIN_ReadChunk( cinematics_t *cin )
|
||||
{
|
||||
RoQ_ReadChunk( cin );
|
||||
}
|
||||
|
||||
byte *CIN_ReadNextFrame( cinematics_t *cin, bool silent )
|
||||
{
|
||||
droqchunk_t *chunk = &cin->chunk;
|
||||
|
||||
while( !FS_Eof( cin->file ))
|
||||
{
|
||||
RoQ_ReadChunk( cin );
|
||||
|
||||
if( FS_Eof( cin->file ))
|
||||
return NULL;
|
||||
if( chunk->size <= 0 )
|
||||
continue;
|
||||
|
||||
if( chunk->id == RoQ_INFO )
|
||||
RoQ_ReadInfo( cin );
|
||||
else if( !silent && ( chunk->id == RoQ_SOUND_MONO || chunk->id == RoQ_SOUND_STEREO ))
|
||||
RoQ_ReadAudio( cin );
|
||||
else if( chunk->id == RoQ_QUAD_VQ )
|
||||
return RoQ_ReadVideo( cin );
|
||||
else if( chunk->id == RoQ_QUAD_CODEBOOK )
|
||||
RoQ_ReadCodebook( cin );
|
||||
else RoQ_SkipChunk( cin );
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -122,10 +122,6 @@ SOURCE=.\build.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cinematic.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\client\cl_cmds.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -120,8 +120,6 @@ bool Host_InitRender( void )
|
|||
ri.GetLocalPlayer = CL_GetLocalPlayer;
|
||||
ri.GetMaxClients = CL_GetMaxClients;
|
||||
ri.DrawTriangles = Tri_DrawTriangles;
|
||||
ri.RoQ_ReadChunk = CIN_ReadChunk;
|
||||
ri.RoQ_ReadNextFrame = CIN_ReadNextFrame;
|
||||
ri.WndProc = IN_WndProc;
|
||||
|
||||
Sys_LoadLibrary( host_video->string, &render_dll );
|
||||
|
|
|
@ -73,7 +73,7 @@ typedef struct server_s
|
|||
|
||||
int hostflags; // misc server flags: predicting etc
|
||||
|
||||
string name; // map name, or cinematic name
|
||||
string name; // map name
|
||||
string startspot; // player_start name on nextmap
|
||||
|
||||
char configstrings[MAX_CONFIGSTRINGS][CS_SIZE];
|
||||
|
|
|
@ -831,6 +831,56 @@ void SV_Configstrings_f( sv_client_t *cl )
|
|||
BF_WriteString( &cl->netchan.message, cmd );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_UserMessages_f
|
||||
==================
|
||||
*/
|
||||
void SV_UserMessages_f( sv_client_t *cl )
|
||||
{
|
||||
int start;
|
||||
sv_user_message_t *message;
|
||||
string cmd;
|
||||
|
||||
if( cl->state != cs_connected )
|
||||
{
|
||||
MsgDev( D_INFO, "usermessages is not valid from the console\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// handle the case of a level changing while a client was connecting
|
||||
if( com.atoi( Cmd_Argv( 1 )) != svs.spawncount )
|
||||
{
|
||||
MsgDev( D_INFO, "usermessages from different level\n" );
|
||||
SV_New_f( cl );
|
||||
return;
|
||||
}
|
||||
|
||||
start = com.atoi( Cmd_Argv( 2 ));
|
||||
|
||||
// write a packet full of data
|
||||
while( BF_GetNumBytesWritten( &cl->netchan.message ) < ( MAX_MSGLEN / 2 ) && start < MAX_USER_MESSAGES )
|
||||
{
|
||||
message = &svgame.msg[start];
|
||||
if( message->name[0] )
|
||||
{
|
||||
BF_WriteByte( &cl->netchan.message, svc_usermessage );
|
||||
BF_WriteString( &cl->netchan.message, message->name );
|
||||
BF_WriteByte( &cl->netchan.message, message->number );
|
||||
BF_WriteByte( &cl->netchan.message, (byte)message->size );
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
if( start == MAX_USER_MESSAGES ) com.snprintf( cmd, MAX_STRING, "cmd deltainfo %i 0 0\n", svs.spawncount );
|
||||
else com.snprintf( cmd, MAX_STRING, "cmd usermsgs %i %i\n", svs.spawncount, start );
|
||||
|
||||
// send next command
|
||||
BF_WriteByte( &cl->netchan.message, svc_stufftext );
|
||||
BF_WriteString( &cl->netchan.message, cmd );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_DeltaInfo_f
|
||||
|
@ -890,55 +940,6 @@ void SV_DeltaInfo_f( sv_client_t *cl )
|
|||
BF_WriteString( &cl->netchan.message, cmd );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_UserMessages_f
|
||||
==================
|
||||
*/
|
||||
void SV_UserMessages_f( sv_client_t *cl )
|
||||
{
|
||||
int start;
|
||||
sv_user_message_t *message;
|
||||
string cmd;
|
||||
|
||||
if( cl->state != cs_connected )
|
||||
{
|
||||
MsgDev( D_INFO, "usermessages is not valid from the console\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// handle the case of a level changing while a client was connecting
|
||||
if( com.atoi( Cmd_Argv( 1 )) != svs.spawncount )
|
||||
{
|
||||
MsgDev( D_INFO, "usermessages from different level\n" );
|
||||
SV_New_f( cl );
|
||||
return;
|
||||
}
|
||||
|
||||
start = com.atoi( Cmd_Argv( 2 ));
|
||||
|
||||
// write a packet full of data
|
||||
while( BF_GetNumBytesWritten( &cl->netchan.message ) < ( MAX_MSGLEN / 2 ) && start < MAX_USER_MESSAGES )
|
||||
{
|
||||
message = &svgame.msg[start];
|
||||
if( message->name[0] )
|
||||
{
|
||||
BF_WriteByte( &cl->netchan.message, svc_usermessage );
|
||||
BF_WriteString( &cl->netchan.message, message->name );
|
||||
BF_WriteByte( &cl->netchan.message, message->number );
|
||||
BF_WriteByte( &cl->netchan.message, (byte)message->size );
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
if( start == MAX_USER_MESSAGES ) com.snprintf( cmd, MAX_STRING, "cmd deltainfo %i 0 0\n", svs.spawncount );
|
||||
else com.snprintf( cmd, MAX_STRING, "cmd usermsgs %i %i\n", svs.spawncount, start );
|
||||
|
||||
// send next command
|
||||
BF_WriteByte( &cl->netchan.message, svc_stufftext );
|
||||
BF_WriteString( &cl->netchan.message, cmd );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Baselines_f
|
||||
|
|
|
@ -76,7 +76,7 @@ typedef struct
|
|||
{
|
||||
vec3_t position;
|
||||
char name[64]; // same as CS_SIZE
|
||||
short entityIndex;
|
||||
short entityIndex; // FIXME: replace with pointer to entity ?
|
||||
byte depth;
|
||||
byte flags;
|
||||
|
||||
|
@ -86,36 +86,6 @@ typedef struct
|
|||
vec3_t impactPlaneNormal;
|
||||
} decallist_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
byte *mempool;
|
||||
|
||||
droqchunk_t chunk;
|
||||
dcell_t cells[256];
|
||||
dquadcell_t qcells[256];
|
||||
|
||||
byte *vid_buffer;
|
||||
byte *vid_pic[2];
|
||||
byte *pic;
|
||||
byte *pic_pending;
|
||||
|
||||
bool new_frame;
|
||||
|
||||
int s_rate;
|
||||
int s_width;
|
||||
int s_channels;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
file_t *file;
|
||||
int headerlen;
|
||||
|
||||
float time; // curtime for first cinematic frame
|
||||
uint frame;
|
||||
} cinematics_t;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
|
@ -199,10 +169,6 @@ typedef struct render_imp_s
|
|||
struct cl_entity_s *(*GetLocalPlayer)( void );
|
||||
int (*GetMaxClients)( void );
|
||||
void (*DrawTriangles)( int fTrans );
|
||||
|
||||
// RoQ decoder imports
|
||||
void (*RoQ_ReadChunk)( cinematics_t *cin );
|
||||
byte *(*RoQ_ReadNextFrame)( cinematics_t *cin, bool silent );
|
||||
} render_imp_t;
|
||||
|
||||
#endif//RENDER_API_H
|
|
@ -90,22 +90,17 @@ S_CreateDefaultSound
|
|||
static wavdata_t *S_CreateDefaultSound( void )
|
||||
{
|
||||
wavdata_t *sc;
|
||||
int i;
|
||||
|
||||
sc = Z_Malloc( sizeof( wavdata_t ));
|
||||
|
||||
sc->rate = 22050;
|
||||
sc->width = 2;
|
||||
sc->channels = 1;
|
||||
sc->samples = 11025;
|
||||
sc->loopStart = -1;
|
||||
sc->rate = SOUND_DMA_SPEED;
|
||||
sc->samples = SOUND_DMA_SPEED;
|
||||
sc->size = sc->samples * sc->width * sc->channels;
|
||||
sc->buffer = Z_Malloc( sc->size );
|
||||
|
||||
// create silent sound
|
||||
for( i = 0; i < sc->samples; i++ )
|
||||
((short *)sc->buffer)[i] = i;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
|
|
390
vid_gl/r_cin.c
390
vid_gl/r_cin.c
|
@ -1,390 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2009 ©
|
||||
// r_cin.c - plays videotextures
|
||||
//=======================================================================
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
#define MAX_CINEMATICS 256
|
||||
|
||||
typedef struct r_cinhandle_s
|
||||
{
|
||||
uint id;
|
||||
char *name;
|
||||
cinematics_t *cin;
|
||||
texture_t *image;
|
||||
struct r_cinhandle_s *prev, *next;
|
||||
} r_cinhandle_t;
|
||||
|
||||
static byte *r_cinMemPool;
|
||||
|
||||
static r_cinhandle_t *r_cinematics;
|
||||
static r_cinhandle_t r_cinematics_headnode, *r_free_cinematics;
|
||||
|
||||
#define Cin_Malloc( size ) Mem_Alloc( r_cinMemPool, size )
|
||||
#define Cin_Free( data ) Mem_Free( data )
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ReadNextRoQFrame
|
||||
==================
|
||||
*/
|
||||
static byte *R_ReadNextRoQFrame( cinematics_t *cin )
|
||||
{
|
||||
return ri.RoQ_ReadNextFrame( cin, true );
|
||||
}
|
||||
|
||||
static void R_ReadRoQChunk( cinematics_t *cin )
|
||||
{
|
||||
ri.RoQ_ReadChunk( cin );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_RunRoQ
|
||||
==================
|
||||
*/
|
||||
static void R_RunRoQ( cinematics_t *cin )
|
||||
{
|
||||
uint frame;
|
||||
|
||||
frame = (RI.refdef.time - cin->time) * (float)(RoQ_FRAMERATE);
|
||||
if( frame <= cin->frame ) return;
|
||||
|
||||
if( frame > cin->frame + 1 )
|
||||
cin->time = RI.refdef.time - cin->frame / RoQ_FRAMERATE;
|
||||
|
||||
cin->pic = cin->pic_pending;
|
||||
cin->pic_pending = R_ReadNextRoQFrame( cin );
|
||||
|
||||
if( !cin->pic_pending )
|
||||
{
|
||||
FS_Seek( cin->file, cin->headerlen, SEEK_SET );
|
||||
cin->frame = 0;
|
||||
cin->pic_pending = R_ReadNextRoQFrame( cin );
|
||||
cin->time = RI.refdef.time;
|
||||
}
|
||||
cin->new_frame = true;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_StopRoQ
|
||||
==================
|
||||
*/
|
||||
static void R_StopRoQ( cinematics_t *cin )
|
||||
{
|
||||
cin->frame = 0;
|
||||
cin->time = 0.0f; // done
|
||||
cin->pic = NULL;
|
||||
cin->pic_pending = NULL;
|
||||
|
||||
if( cin->file )
|
||||
{
|
||||
FS_Close( cin->file );
|
||||
cin->file = 0;
|
||||
}
|
||||
if( cin->name )
|
||||
{
|
||||
Mem_Free( (char *)cin->name );
|
||||
cin->name = NULL;
|
||||
}
|
||||
if( cin->vid_buffer )
|
||||
{
|
||||
Mem_Free( cin->vid_buffer );
|
||||
cin->vid_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_OpenCinematics
|
||||
==================
|
||||
*/
|
||||
static cinematics_t *R_OpenCinematics( char *filename )
|
||||
{
|
||||
file_t *file;
|
||||
cinematics_t *cin = NULL;
|
||||
droqchunk_t *chunk = &cin->chunk;
|
||||
|
||||
if(( file = FS_Open( filename, "rb" )) == NULL )
|
||||
return NULL;
|
||||
|
||||
cin = Cin_Malloc( sizeof( cinematics_t ));
|
||||
cin->name = filename;
|
||||
cin->file = file;
|
||||
cin->mempool = r_cinMemPool;
|
||||
|
||||
// read header
|
||||
R_ReadRoQChunk( cin );
|
||||
|
||||
chunk = &cin->chunk;
|
||||
if( chunk->id != RoQ_HEADER1 || chunk->size != RoQ_HEADER2 || chunk->argument != RoQ_HEADER3 )
|
||||
{
|
||||
R_StopRoQ( cin );
|
||||
Cin_Free( cin );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cin->headerlen = FS_Tell( cin->file );
|
||||
cin->frame = 0;
|
||||
cin->pic = cin->pic_pending = R_ReadNextRoQFrame( cin );
|
||||
cin->time = RI.refdef.time;
|
||||
cin->new_frame = true;
|
||||
|
||||
return cin;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ResampleCinematicFrame
|
||||
==================
|
||||
*/
|
||||
static texture_t *R_ResampleCinematicFrame( r_cinhandle_t *handle )
|
||||
{
|
||||
texture_t *image;
|
||||
cinematics_t *cin = handle->cin;
|
||||
static rgbdata_t r_cin;
|
||||
|
||||
if( !cin->pic )
|
||||
return NULL;
|
||||
|
||||
if( !handle->image )
|
||||
{
|
||||
r_cin.width = cin->width;
|
||||
r_cin.height = cin->height;
|
||||
r_cin.type = PF_RGB_24;
|
||||
r_cin.size = cin->width * cin->height * 3;
|
||||
r_cin.flags = 0;
|
||||
r_cin.palette = NULL;
|
||||
r_cin.buffer = cin->pic;
|
||||
r_cin.numMips = r_cin.depth = 1;
|
||||
handle->image = R_LoadTexture( handle->name, &r_cin, 3, TF_CINEMATIC );
|
||||
cin->new_frame = false;
|
||||
}
|
||||
|
||||
if( !cin->new_frame )
|
||||
return handle->image;
|
||||
|
||||
cin->new_frame = false;
|
||||
|
||||
image = handle->image;
|
||||
GL_Bind( 0, image );
|
||||
if( image->srcWidth != cin->width || image->srcHeight != cin->height )
|
||||
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, image->srcWidth, image->srcHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, cin->pic );
|
||||
else pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, image->srcWidth, image->srcHeight, GL_RGBA, GL_UNSIGNED_BYTE, cin->pic );
|
||||
|
||||
image->srcWidth = cin->width;
|
||||
image->srcHeight = cin->height;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
R_CinList_f
|
||||
==================
|
||||
*/
|
||||
void R_CinList_f( void )
|
||||
{
|
||||
cinematics_t *cin;
|
||||
texture_t *image;
|
||||
r_cinhandle_t *handle, *hnode;
|
||||
|
||||
Msg( "Active cintematics:" );
|
||||
hnode = &r_cinematics_headnode;
|
||||
handle = hnode->prev;
|
||||
if( handle == hnode )
|
||||
{
|
||||
Msg( " none\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Msg( "\n" );
|
||||
do {
|
||||
cin = handle->cin;
|
||||
image = handle->image;
|
||||
if( cin == NULL ) break; // this should never happens
|
||||
|
||||
if( image && (cin->width != image->width || cin->height != image->height) )
|
||||
Msg( "%s %i(%i)x%i(%i) f:%i\n", cin->name, cin->width, image->width, cin->height, image->height, cin->frame );
|
||||
else Msg( "%s %ix%i f:%i\n", cin->name, cin->width, cin->height, cin->frame );
|
||||
|
||||
handle = handle->next;
|
||||
} while( handle != hnode );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_InitCinematics
|
||||
==================
|
||||
*/
|
||||
void R_InitCinematics( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
r_cinMemPool = Mem_AllocPool( "Cinematics" );
|
||||
r_cinematics = Cin_Malloc( sizeof( r_cinhandle_t ) * MAX_CINEMATICS );
|
||||
|
||||
// link cinemtics
|
||||
r_free_cinematics = r_cinematics;
|
||||
r_cinematics_headnode.id = 0;
|
||||
r_cinematics_headnode.prev = &r_cinematics_headnode;
|
||||
r_cinematics_headnode.next = &r_cinematics_headnode;
|
||||
|
||||
for( i = 0; i < MAX_CINEMATICS - 1; i++ )
|
||||
{
|
||||
if( i < MAX_CINEMATICS - 1 )
|
||||
r_cinematics[i].next = &r_cinematics[i+1];
|
||||
r_cinematics[i].id = i + 1;
|
||||
}
|
||||
|
||||
Cmd_AddCommand( "cinlist", R_CinList_f, "display loaded videos list" );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_RunAllCinematics
|
||||
==================
|
||||
*/
|
||||
void R_RunAllCinematics( void )
|
||||
{
|
||||
r_cinhandle_t *handle, *hnode, *next;
|
||||
|
||||
hnode = &r_cinematics_headnode;
|
||||
for( handle = hnode->prev; handle != hnode; handle = next )
|
||||
{
|
||||
next = handle->prev;
|
||||
R_RunRoQ( handle->cin );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_UploadCinematics
|
||||
==================
|
||||
*/
|
||||
texture_t *R_UploadCinematics( uint id )
|
||||
{
|
||||
if( id > 0 && id < MAX_CINEMATICS )
|
||||
return R_ResampleCinematicFrame( r_cinematics + id - 1 );
|
||||
return tr.defaultTexture; // assume error
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_StartCinematic
|
||||
==================
|
||||
*/
|
||||
uint R_StartCinematics( const char *arg )
|
||||
{
|
||||
char *name = NULL;
|
||||
string uploadName;
|
||||
size_t name_size;
|
||||
cinematics_t *cin = NULL;
|
||||
r_cinhandle_t *handle, *hnode, *next;
|
||||
|
||||
name_size = com.strlen( "media/" ) + com.strlen( arg ) + com.strlen( ".roq" ) + 1;
|
||||
name = Cin_Malloc( name_size );
|
||||
com.snprintf( name, name_size, "media/%s", arg );
|
||||
FS_DefaultExtension( name, ".roq" );
|
||||
|
||||
// find cinematics with the same name
|
||||
hnode = &r_cinematics_headnode;
|
||||
for( handle = hnode->prev; handle != hnode; handle = next )
|
||||
{
|
||||
next = handle->prev;
|
||||
|
||||
// reuse
|
||||
if( !com.stricmp( handle->cin->name, name ) )
|
||||
{
|
||||
Cin_Free( name );
|
||||
return handle->id;
|
||||
}
|
||||
}
|
||||
|
||||
// open the file, read header, etc
|
||||
cin = R_OpenCinematics( name );
|
||||
|
||||
// take a free cinematic handle if possible
|
||||
if( !r_free_cinematics || !cin )
|
||||
{
|
||||
Cin_Free( name );
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle = r_free_cinematics;
|
||||
r_free_cinematics = handle->next;
|
||||
|
||||
com.snprintf( uploadName, sizeof( uploadName ), "***r_cinematic%i***", handle->id-1 );
|
||||
name_size = com.strlen( uploadName ) + 1;
|
||||
handle->name = Cin_Malloc( name_size );
|
||||
Mem_Copy( handle->name, uploadName, name_size );
|
||||
handle->cin = cin;
|
||||
|
||||
// put handle at the start of the list
|
||||
handle->prev = &r_cinematics_headnode;
|
||||
handle->next = r_cinematics_headnode.next;
|
||||
handle->next->prev = handle;
|
||||
handle->prev->next = handle;
|
||||
|
||||
return handle->id;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_FreeCinematics
|
||||
=================
|
||||
*/
|
||||
void R_FreeCinematics( uint id )
|
||||
{
|
||||
r_cinhandle_t *handle;
|
||||
|
||||
handle = r_cinematics + id - 1;
|
||||
if( !handle->cin )
|
||||
return;
|
||||
|
||||
R_StopRoQ( handle->cin );
|
||||
Cin_Free( handle->cin );
|
||||
handle->cin = NULL;
|
||||
|
||||
// already freed ?
|
||||
if( !handle->name ) return;
|
||||
Cin_Free( handle->name );
|
||||
handle->name = NULL;
|
||||
|
||||
// remove from linked active list
|
||||
handle->prev->next = handle->next;
|
||||
handle->next->prev = handle->prev;
|
||||
|
||||
// insert into linked free list
|
||||
handle->next = r_free_cinematics;
|
||||
r_free_cinematics = handle;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ShutdownCinematics
|
||||
==================
|
||||
*/
|
||||
void R_ShutdownCinematics( void )
|
||||
{
|
||||
r_cinhandle_t *handle, *hnode, *next;
|
||||
|
||||
if( !r_cinMemPool )
|
||||
return;
|
||||
|
||||
hnode = &r_cinematics_headnode;
|
||||
for( handle = hnode->prev; handle != hnode; handle = next )
|
||||
{
|
||||
next = handle->prev;
|
||||
R_FreeCinematics( handle->id );
|
||||
}
|
||||
|
||||
Cin_Free( r_cinematics );
|
||||
Mem_FreePool( &r_cinMemPool );
|
||||
|
||||
Cmd_RemoveCommand( "cinlist" );
|
||||
}
|
|
@ -73,8 +73,6 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f
|
|||
pic_mbuffer.shaderkey = shader->sortkey;
|
||||
pic_mbuffer.infokey -= 4;
|
||||
|
||||
// upload video right before rendering
|
||||
if( shader->flags & SHADER_VIDEOMAP ) R_UploadCinematicShader( shader );
|
||||
R_PushMesh( &pic_mesh, MF_TRIFAN|shader->features | ( r_shownormals->integer ? MF_NORMALS : 0 ));
|
||||
|
||||
if( oldframe != glState.draw_frame )
|
||||
|
@ -355,9 +353,6 @@ static void Tri_DrawPolygon( void )
|
|||
if( triState.noCulling )
|
||||
triState.features |= MF_NOCULL;
|
||||
|
||||
// upload video right before rendering
|
||||
if( shader->flags & SHADER_VIDEOMAP )
|
||||
R_UploadCinematicShader( shader );
|
||||
R_PushMesh( &tri_mesh, triState.features );
|
||||
|
||||
if( oldframe != glState.draw_frame )
|
||||
|
|
|
@ -1,719 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// r_draw.c - draw 2d pictures
|
||||
//=======================================================================
|
||||
|
||||
#include "r_local.h"
|
||||
#include "mathlib.h"
|
||||
#include "matrix_lib.h"
|
||||
#include "triangle_api.h"
|
||||
|
||||
static vec4_t pic_xyz[4] = { {0,0,0,1}, {0,0,0,1}, {0,0,0,1}, {0,0,0,1} };
|
||||
static vec2_t pic_st[4];
|
||||
static rgba_t pic_colors[4];
|
||||
static mesh_t pic_mesh = { 4, 6, pic_xyz, pic_xyz, NULL, NULL, pic_st, NULL, pic_colors, NULL, NULL };
|
||||
meshbuffer_t pic_mbuffer;
|
||||
|
||||
/*
|
||||
===============
|
||||
R_DrawSetColor
|
||||
===============
|
||||
*/
|
||||
void R_DrawSetColor( const rgba_t color )
|
||||
{
|
||||
if( color ) Vector4Copy( color, glState.draw_color );
|
||||
else Vector4Set( glState.draw_color, 255, 255, 255, 255 );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_DrawStretchPic
|
||||
===============
|
||||
*/
|
||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t handle )
|
||||
{
|
||||
int bcolor;
|
||||
ref_shader_t *shader;
|
||||
static int oldframe;
|
||||
|
||||
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]))
|
||||
return;
|
||||
|
||||
// lower-left
|
||||
Vector2Set( pic_xyz[0], x, y );
|
||||
Vector2Set( pic_st[0], s1, t1 );
|
||||
Vector4Copy( glState.draw_color, pic_colors[0] );
|
||||
bcolor = *(int *)pic_colors[0];
|
||||
|
||||
// lower-right
|
||||
Vector2Set( pic_xyz[1], x+w, y );
|
||||
Vector2Set( pic_st[1], s2, t1 );
|
||||
*(int *)pic_colors[1] = bcolor;
|
||||
|
||||
// upper-right
|
||||
Vector2Set( pic_xyz[2], x+w, y+h );
|
||||
Vector2Set( pic_st[2], s2, t2 );
|
||||
*(int *)pic_colors[2] = bcolor;
|
||||
|
||||
// upper-left
|
||||
Vector2Set( pic_xyz[3], x, y+h );
|
||||
Vector2Set( pic_st[3], s1, t2 );
|
||||
*(int *)pic_colors[3] = bcolor;
|
||||
|
||||
if( pic_mbuffer.shaderkey != (int)shader->sortkey || -pic_mbuffer.infokey-1+4 > MAX_ARRAY_VERTS )
|
||||
{
|
||||
if( pic_mbuffer.shaderkey )
|
||||
{
|
||||
pic_mbuffer.infokey = -1;
|
||||
R_RenderMeshBuffer( &pic_mbuffer );
|
||||
}
|
||||
}
|
||||
|
||||
tr.iRenderMode = glState.draw_rendermode;
|
||||
pic_mbuffer.shaderkey = shader->sortkey;
|
||||
pic_mbuffer.infokey -= 4;
|
||||
|
||||
// upload video right before rendering
|
||||
if( shader->flags & SHADER_VIDEOMAP ) R_UploadCinematicShader( shader );
|
||||
R_PushMesh( &pic_mesh, MF_TRIFAN|shader->features | ( r_shownormals->integer ? MF_NORMALS : 0 ));
|
||||
|
||||
if( oldframe != glState.draw_frame )
|
||||
{
|
||||
if( pic_mbuffer.shaderkey != shader->sortkey )
|
||||
{
|
||||
// will be rendering on next call
|
||||
oldframe = glState.draw_frame;
|
||||
return;
|
||||
}
|
||||
if( pic_mbuffer.shaderkey )
|
||||
{
|
||||
pic_mbuffer.infokey = -1;
|
||||
R_RenderMeshBuffer( &pic_mbuffer );
|
||||
}
|
||||
oldframe = glState.draw_frame;
|
||||
}
|
||||
}
|
||||
/*
|
||||
=================
|
||||
R_ResampleTexture
|
||||
=================
|
||||
*/
|
||||
static byte *R_ResampleTexture( const byte *indata, int inwidth, int inheight, int outwidth, int outheight )
|
||||
{
|
||||
int i, j, f, inwidth3 = inwidth * 3;
|
||||
uint frac, fracstep;
|
||||
static byte *resampled = NULL;
|
||||
byte *inrow, *out;
|
||||
|
||||
if( !indata ) return NULL;
|
||||
|
||||
resampled = Mem_Realloc( r_temppool, resampled, outwidth * outheight * 4 );
|
||||
fracstep = inwidth * 0x10000 / outwidth;
|
||||
out = resampled;
|
||||
|
||||
for( i = 0; i < outheight; i++)
|
||||
{
|
||||
inrow = (byte *)indata + inwidth3 * (i * inheight/outheight);
|
||||
frac = fracstep>>1;
|
||||
j = outwidth - 4;
|
||||
|
||||
while( j >= 0 )
|
||||
{
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
j -= 4;
|
||||
}
|
||||
if( j & 2 )
|
||||
{
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
out += 2;
|
||||
}
|
||||
if( j & 1 )
|
||||
{
|
||||
f = (frac >> 16)*3;
|
||||
*out++ = inrow[f+0];
|
||||
*out++ = inrow[f+1];
|
||||
*out++ = inrow[f+2];
|
||||
frac += fracstep;
|
||||
out += 1;
|
||||
}
|
||||
}
|
||||
return resampled;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_DrawStretchRaw
|
||||
=============
|
||||
*/
|
||||
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, bool dirty )
|
||||
{
|
||||
byte *raw;
|
||||
|
||||
if( 1 )//!GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
|
||||
{
|
||||
int width = 1, height = 1;
|
||||
|
||||
// check the dimensions
|
||||
while( width < cols ) width <<= 1;
|
||||
while( height < rows ) height <<= 1;
|
||||
|
||||
if( cols != width || rows != height )
|
||||
{
|
||||
raw = R_ResampleTexture( data, cols, rows, width, height );
|
||||
cols = width;
|
||||
rows = height;
|
||||
// Host_Error( "R_DrawStretchRaw: size is not a power of two (%i x %i)\n", cols, rows );
|
||||
}
|
||||
}
|
||||
else raw = (byte *)data;
|
||||
|
||||
if( cols > glConfig.max_2d_texture_size )
|
||||
Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", cols, glConfig.max_2d_texture_size );
|
||||
if( rows > glConfig.max_2d_texture_size )
|
||||
Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", rows, glConfig.max_2d_texture_size );
|
||||
|
||||
if( pic_mbuffer.infokey != -1 )
|
||||
{
|
||||
R_RenderMeshBuffer( &pic_mbuffer );
|
||||
pic_mbuffer.infokey = -1;
|
||||
}
|
||||
|
||||
GL_Bind( 0, tr.cinTexture );
|
||||
|
||||
if( cols == tr.cinTexture->width && rows == tr.cinTexture->height )
|
||||
{
|
||||
if( dirty ) pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGR, GL_UNSIGNED_BYTE, raw );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.cinTexture->width = cols;
|
||||
tr.cinTexture->height = rows;
|
||||
if( dirty ) pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGR, GL_UNSIGNED_BYTE, raw );
|
||||
}
|
||||
|
||||
R_CheckForErrors();
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0, 0 );
|
||||
pglVertex2f( x, y );
|
||||
pglTexCoord2f( 1, 0 );
|
||||
pglVertex2f( x + w, y );
|
||||
pglTexCoord2f( 1, 1 );
|
||||
pglVertex2f( x + w, y + h );
|
||||
pglTexCoord2f( 0, 1 );
|
||||
pglVertex2f( x, y + h );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
void R_DrawGetParms( int *w, int *h, int *f, int frame, shader_t handle )
|
||||
{
|
||||
ref_shader_t *shader;
|
||||
int cur = 0;
|
||||
|
||||
if( !w && !h && !f ) return;
|
||||
|
||||
// assume error
|
||||
if( w ) *w = 0;
|
||||
if( h ) *h = 0;
|
||||
if( f ) *f = 1;
|
||||
|
||||
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]))
|
||||
return;
|
||||
|
||||
if( !shader->num_stages || !shader->stages[0].textures[0] )
|
||||
return;
|
||||
|
||||
if( shader->stages[0].textures[0] && shader->stages[0].num_textures && frame > 0 )
|
||||
cur = bound( 0, frame, shader->stages[0].num_textures );
|
||||
|
||||
if( w ) *w = (int)shader->stages[0].textures[cur]->srcWidth;
|
||||
if( h ) *h = (int)shader->stages[0].textures[cur]->srcHeight;
|
||||
if( f ) *f = (int)shader->stages[0].num_textures;
|
||||
}
|
||||
|
||||
void R_DrawSetParms( shader_t handle, kRenderMode_t rendermode, int frame )
|
||||
{
|
||||
ref_shader_t *shader;
|
||||
|
||||
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]) || !shader->num_stages )
|
||||
return;
|
||||
|
||||
if( glState.draw_rendermode != rendermode )
|
||||
{
|
||||
if( pic_mbuffer.shaderkey )
|
||||
{
|
||||
pic_mbuffer.infokey = -1;
|
||||
R_RenderMeshBuffer( &pic_mbuffer );
|
||||
}
|
||||
}
|
||||
glState.draw_rendermode = rendermode;
|
||||
|
||||
if( !shader->stages[0].num_textures )
|
||||
return;
|
||||
|
||||
// change frame if need
|
||||
if( shader->stages[0].flags & SHADERSTAGE_FRAMES )
|
||||
{
|
||||
// make sure what frame inbound
|
||||
glState.draw_frame = bound( 0, frame, shader->stages[0].num_textures - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
TRIAPI IMPLEMENTATION
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
#define MAX_TRIVERTS 1024
|
||||
#define MAX_TRIELEMS MAX_TRIVERTS * 6
|
||||
#define MAX_TRIANGLES MAX_TRIELEMS / 3
|
||||
|
||||
static vec4_t tri_vertex[MAX_TRIVERTS];
|
||||
static vec4_t tri_normal[MAX_TRIVERTS];
|
||||
static vec2_t tri_coords[MAX_TRIVERTS];
|
||||
static rgba_t tri_colors[MAX_TRIVERTS];
|
||||
static elem_t tri_elems[MAX_TRIELEMS];
|
||||
static mesh_t tri_mesh;
|
||||
static bool tri_caps[3];
|
||||
meshbuffer_t tri_mbuffer;
|
||||
tristate_t triState;
|
||||
|
||||
static void Tri_ClearBounds( void )
|
||||
{
|
||||
// clear bounds that uses for polygon lighting
|
||||
VectorClear( triState.lightingOrigin );
|
||||
ClearBounds( triState.mins, triState.maxs );
|
||||
}
|
||||
|
||||
static void Tri_DrawPolygon( void )
|
||||
{
|
||||
ref_shader_t *shader;
|
||||
static int i, oldframe;
|
||||
|
||||
if( tri_caps[TRI_SHADER] )
|
||||
shader = &r_shaders[triState.currentShader];
|
||||
else shader = tr.fillShader;
|
||||
|
||||
tri_mesh.numVerts = triState.numVertex;
|
||||
tri_mesh.numElems = triState.numIndex;
|
||||
|
||||
if( triState.hasNormals )
|
||||
tri_mesh.normalsArray = tri_normal;
|
||||
else tri_mesh.normalsArray = NULL; // no normals
|
||||
|
||||
if( triState.numColor == 1 )
|
||||
{
|
||||
// global color for all vertexes
|
||||
for( i = 0; i < triState.numVertex - 1; i++ )
|
||||
Vector4Copy( tri_colors[0], tri_colors[i+1] );
|
||||
}
|
||||
|
||||
// compute lightingOrigin
|
||||
VectorAverage( triState.mins, triState.maxs, triState.lightingOrigin );
|
||||
|
||||
tri_mesh.vertexArray = tri_vertex;
|
||||
tri_mesh.stCoordArray = tri_coords;
|
||||
tri_mesh.colorsArray = tri_colors;
|
||||
tri_mesh.elems = tri_elems;
|
||||
|
||||
if( tri_mbuffer.shaderkey != (int)shader->sortkey || -tri_mbuffer.infokey-1+256 > MAX_ARRAY_VERTS )
|
||||
{
|
||||
if( tri_mbuffer.shaderkey )
|
||||
{
|
||||
tri_mbuffer.infokey = -1;
|
||||
R_RenderMeshBuffer( &tri_mbuffer );
|
||||
Tri_ClearBounds();
|
||||
}
|
||||
}
|
||||
|
||||
tr.iRenderMode = triState.currentRenderMode;
|
||||
tri_mbuffer.shaderkey = shader->sortkey;
|
||||
tri_mbuffer.infokey -= triState.numVertex;
|
||||
|
||||
triState.features = shader->features;
|
||||
triState.features |= MF_COLORS;
|
||||
if( r_shownormals->integer || triState.hasNormals )
|
||||
triState.features |= MF_NORMALS;
|
||||
|
||||
if( triState.noCulling )
|
||||
triState.features |= MF_NOCULL;
|
||||
|
||||
// upload video right before rendering
|
||||
if( shader->flags & SHADER_VIDEOMAP )
|
||||
R_UploadCinematicShader( shader );
|
||||
R_PushMesh( &tri_mesh, triState.features );
|
||||
|
||||
if( oldframe != glState.draw_frame )
|
||||
{
|
||||
if( tri_mbuffer.shaderkey != shader->sortkey )
|
||||
{
|
||||
// will be rendering on next call
|
||||
oldframe = glState.draw_frame;
|
||||
return;
|
||||
}
|
||||
if( tri_mbuffer.shaderkey )
|
||||
{
|
||||
tri_mbuffer.infokey = -1;
|
||||
R_RenderMeshBuffer( &tri_mbuffer );
|
||||
Tri_ClearBounds();
|
||||
}
|
||||
oldframe = glState.draw_frame;
|
||||
}
|
||||
triState.numVertex = triState.numIndex = triState.numColor = 0;
|
||||
}
|
||||
|
||||
static void Tri_CheckOverflow( int numIndices, int numVertices )
|
||||
{
|
||||
if( numIndices > MAX_TRIELEMS )
|
||||
Host_Error( "Tri_Overflow: %i > MAX_TRIELEMS\n", numIndices );
|
||||
if( numVertices > MAX_TRIVERTS )
|
||||
Host_Error( "Tri_Overflow: %i > MAX_TRIVERTS\n", numVertices );
|
||||
|
||||
if( triState.numIndex + numIndices <= MAX_TRIELEMS && triState.numVertex + numVertices <= MAX_TRIVERTS )
|
||||
return;
|
||||
|
||||
Tri_DrawPolygon();
|
||||
}
|
||||
|
||||
void Tri_Fog( float flFogColor[3], float flStart, float flEnd, int bOn )
|
||||
{
|
||||
// ignore fog calls from TriApi callbacks
|
||||
// to avoid strange artefacts and other issues
|
||||
if( triState.fActive ) return;
|
||||
|
||||
// change fog params
|
||||
triState.fogColor[0] = bound( 0.0f, flFogColor[0], 1.0f );
|
||||
triState.fogColor[1] = bound( 0.0f, flFogColor[1], 1.0f );
|
||||
triState.fogColor[2] = bound( 0.0f, flFogColor[2], 1.0f );
|
||||
triState.fogColor[3] = 1.0f;
|
||||
triState.fogStartDist = min( flStart, flEnd );
|
||||
triState.fogEndDist = max( flStart, flEnd );
|
||||
triState.fogEnabled = bOn;
|
||||
}
|
||||
|
||||
void Tri_CullFace( int mode )
|
||||
{
|
||||
if( mode == TRI_FRONT )
|
||||
triState.noCulling = false;
|
||||
else if( mode == TRI_NONE )
|
||||
triState.noCulling = true;
|
||||
}
|
||||
|
||||
void Tri_RenderMode( const kRenderMode_t mode )
|
||||
{
|
||||
triState.currentRenderMode = mode;
|
||||
}
|
||||
|
||||
void Tri_Vertex3f( const float x, const float y, const float z )
|
||||
{
|
||||
uint oldIndex = triState.numIndex;
|
||||
|
||||
switch( triState.drawMode )
|
||||
{
|
||||
case TRI_LINES:
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
if( triState.vertexState++ == 1 )
|
||||
{
|
||||
Tri_Vertex3f( x + 1, y + 1, z + 1 );
|
||||
triState.vertexState = 0;
|
||||
triState.checkFlush = true; // flush for long sequences of quads.
|
||||
}
|
||||
break;
|
||||
case TRI_TRIANGLES:
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
if( triState.vertexState++ == 2 )
|
||||
{
|
||||
triState.vertexState = 0;
|
||||
triState.checkFlush = true; // flush for long sequences of triangles.
|
||||
}
|
||||
break;
|
||||
case TRI_QUADS:
|
||||
if( triState.vertexState++ < 3 )
|
||||
{
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've already done triangle (0, 1, 2), now draw (2, 3, 0)
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 1;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 3;
|
||||
triState.vertexState = 0;
|
||||
triState.checkFlush = true; // flush for long sequences of quads.
|
||||
}
|
||||
break;
|
||||
case TRI_TRIANGLE_STRIP:
|
||||
if( triState.numVertex + triState.vertexState > MAX_TRIVERTS )
|
||||
{
|
||||
// This is a strip that's too big for us to buffer.
|
||||
// (We can't just flush the buffer because we have to keep
|
||||
// track of the last two vertices.
|
||||
Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIVERTS\n", triState.numVertex + triState.vertexState );
|
||||
}
|
||||
if( triState.numIndex > MAX_TRIELEMS )
|
||||
{
|
||||
// This is a strip that's too big for us to buffer.
|
||||
// (We can't just flush the buffer because we have to keep
|
||||
// track of the last two vertices.
|
||||
Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIELEMS\n", triState.numIndex );
|
||||
}
|
||||
if( triState.vertexState++ < 3 )
|
||||
{
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// flip triangles between clockwise and counter clockwise
|
||||
if( triState.vertexState & 1 )
|
||||
{
|
||||
// draw triangle [n-2 n-1 n]
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 2;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 1;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw triangle [n-1 n-2 n]
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 1;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 2;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TRI_POLYGON:
|
||||
case TRI_TRIANGLE_FAN: // same as polygon
|
||||
if( triState.numVertex + triState.vertexState > MAX_TRIVERTS )
|
||||
{
|
||||
// This is a polygon or fan that's too big for us to buffer.
|
||||
// (We can't just flush the buffer because we have to keep
|
||||
// track of the starting vertex.
|
||||
Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIVERTS\n", triState.numVertex + triState.vertexState );
|
||||
}
|
||||
if( triState.vertexState++ < 3 )
|
||||
{
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw triangle [0 n-1 n]
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - ( triState.vertexState - 1 );
|
||||
tri_elems[triState.numIndex++] = triState.numVertex - 1;
|
||||
tri_elems[triState.numIndex++] = triState.numVertex;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Tri_SetVertex: unknown mode: %i\n", triState.drawMode );
|
||||
break;
|
||||
}
|
||||
|
||||
// copy current vertex
|
||||
tri_vertex[triState.numVertex][0] = x;
|
||||
tri_vertex[triState.numVertex][1] = y;
|
||||
tri_vertex[triState.numVertex][2] = z;
|
||||
tri_vertex[triState.numVertex][3] = 1;
|
||||
|
||||
// for compute lighting origin
|
||||
AddPointToBounds( tri_vertex[triState.numVertex], triState.mins, triState.maxs );
|
||||
|
||||
triState.numVertex++;
|
||||
|
||||
// flush buffer if needed
|
||||
if( triState.checkFlush )
|
||||
Tri_CheckOverflow( triState.numIndex - oldIndex, triState.vertexState );
|
||||
}
|
||||
|
||||
void Tri_Color4ub( const byte r, const byte g, const byte b, const byte a )
|
||||
{
|
||||
tri_colors[triState.numVertex][0] = r;
|
||||
tri_colors[triState.numVertex][1] = g;
|
||||
tri_colors[triState.numVertex][2] = b;
|
||||
tri_colors[triState.numVertex][3] = a;
|
||||
triState.numColor++;
|
||||
}
|
||||
|
||||
void Tri_Normal3f( const float x, const float y, const float z )
|
||||
{
|
||||
triState.hasNormals = true; // curstate has normals
|
||||
tri_normal[triState.numVertex][0] = x;
|
||||
tri_normal[triState.numVertex][1] = y;
|
||||
tri_normal[triState.numVertex][2] = z;
|
||||
tri_normal[triState.numVertex][3] = 1;
|
||||
}
|
||||
|
||||
void Tri_TexCoord2f( const float u, const float v )
|
||||
{
|
||||
tri_coords[triState.numVertex][0] = u;
|
||||
tri_coords[triState.numVertex][1] = v;
|
||||
}
|
||||
|
||||
void Tri_Bind( shader_t handle, int frame )
|
||||
{
|
||||
ref_shader_t *shader;
|
||||
|
||||
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]))
|
||||
{
|
||||
MsgDev( D_ERROR, "TriBind: bad shader %i\n", handle );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !shader->num_stages || !shader->stages[0].textures[0] )
|
||||
{
|
||||
MsgDev( D_ERROR, "TriBind: bad shader %i\n", handle );
|
||||
return;
|
||||
}
|
||||
|
||||
triState.currentShader = handle;
|
||||
|
||||
// FIXME: scan stages while( frame < stage->num_textures ) ?
|
||||
if( shader->stages[0].textures[0] && shader->stages[0].num_textures && frame > 0 )
|
||||
glState.draw_frame = bound( 0, frame, shader->stages[0].num_textures );
|
||||
}
|
||||
|
||||
void Tri_Enable( int cap )
|
||||
{
|
||||
if( cap < 0 || cap > TRI_MAXCAPS ) return;
|
||||
tri_caps[cap] = true;
|
||||
}
|
||||
|
||||
void Tri_Disable( int cap )
|
||||
{
|
||||
if( cap < 0 || cap > TRI_MAXCAPS ) return;
|
||||
tri_caps[cap] = false;
|
||||
}
|
||||
|
||||
void Tri_Begin( int mode )
|
||||
{
|
||||
triState.drawMode = mode;
|
||||
triState.vertexState = 0;
|
||||
triState.checkFlush = false;
|
||||
triState.hasNormals = false;
|
||||
}
|
||||
|
||||
void Tri_End( void )
|
||||
{
|
||||
if( triState.numIndex )
|
||||
Tri_DrawPolygon();
|
||||
}
|
||||
|
||||
void Tri_RenderCallback( int fTrans )
|
||||
{
|
||||
if( RI.refdef.flags & RDF_NOWORLDMODEL )
|
||||
return;
|
||||
|
||||
triState.fActive = true;
|
||||
|
||||
if( fTrans ) GL_SetState( GLSTATE_NO_DEPTH_TEST );
|
||||
R_LoadIdentity ();
|
||||
Tri_ClearBounds ();
|
||||
|
||||
pglColor4f( 1, 1, 1, 1 );
|
||||
|
||||
RI.currententity = RI.previousentity = NULL;
|
||||
RI.currentmodel = NULL;
|
||||
|
||||
tri_mbuffer.infokey = -1;
|
||||
tri_mbuffer.shaderkey = 0;
|
||||
triState.numColor = 0;
|
||||
|
||||
ri.DrawTriangles( fTrans );
|
||||
|
||||
// fulsh remaining tris
|
||||
if( tri_mbuffer.infokey != -1 )
|
||||
{
|
||||
R_RenderMeshBuffer( &tri_mbuffer );
|
||||
tri_mbuffer.infokey = -1;
|
||||
}
|
||||
|
||||
triState.fActive = false;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Set2DMode
|
||||
===============
|
||||
*/
|
||||
void R_Set2DMode( bool enable )
|
||||
{
|
||||
if( enable )
|
||||
{
|
||||
if( glState.in2DMode )
|
||||
return;
|
||||
|
||||
// set 2D virtual screen size
|
||||
pglScissor( 0, 0, glState.width, glState.height );
|
||||
pglViewport( 0, 0, glState.width, glState.height );
|
||||
pglMatrixMode( GL_PROJECTION );
|
||||
pglLoadIdentity();
|
||||
pglOrtho( 0, glState.width, glState.height, 0, -99999, 99999 );
|
||||
pglMatrixMode( GL_MODELVIEW );
|
||||
pglLoadIdentity();
|
||||
|
||||
GL_Cull( 0 );
|
||||
GL_SetState( GLSTATE_NO_DEPTH_TEST );
|
||||
|
||||
pglColor4f( 1, 1, 1, 1 );
|
||||
|
||||
glState.in2DMode = true;
|
||||
RI.currententity = RI.previousentity = NULL;
|
||||
RI.currentmodel = NULL;
|
||||
|
||||
pic_mbuffer.infokey = -1;
|
||||
pic_mbuffer.shaderkey = 0;
|
||||
|
||||
// reset TriApi state too in case we want use it in 2d mode
|
||||
Tri_ClearBounds ();
|
||||
|
||||
tri_mbuffer.infokey = -1;
|
||||
tri_mbuffer.shaderkey = 0;
|
||||
triState.numColor = 0;
|
||||
triState.fActive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( pic_mbuffer.infokey != -1 )
|
||||
{
|
||||
R_RenderMeshBuffer( &pic_mbuffer );
|
||||
pic_mbuffer.infokey = -1;
|
||||
}
|
||||
|
||||
// fulsh remaining tris
|
||||
if( tri_mbuffer.infokey != -1 )
|
||||
{
|
||||
R_RenderMeshBuffer( &tri_mbuffer );
|
||||
tri_mbuffer.infokey = -1;
|
||||
}
|
||||
|
||||
triState.fActive = false;
|
||||
glState.in2DMode = false;
|
||||
}
|
||||
}
|
|
@ -82,7 +82,6 @@ typedef enum
|
|||
TF_LIGHTMAP = BIT(11), // no resample etc
|
||||
} texFlags_t;
|
||||
|
||||
#define TF_CINEMATIC ( TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP|TF_NOMIPMAP )
|
||||
#define TF_PORTALMAP ( TF_NOMIPMAP|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP )
|
||||
#define TF_SHADOWMAP ( TF_NOMIPMAP|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_DEPTHMAP )
|
||||
|
||||
|
@ -481,16 +480,6 @@ void ColorToBytes( const float *color, byte *colorBytes );
|
|||
void R_InitBloomTextures( void );
|
||||
void R_BloomBlend( const ref_params_t *fd );
|
||||
|
||||
//
|
||||
// r_cin.c
|
||||
//
|
||||
void R_InitCinematics( void );
|
||||
void R_ShutdownCinematics( void );
|
||||
uint R_StartCinematics( const char *arg );
|
||||
void R_FreeCinematics( uint id );
|
||||
void R_RunAllCinematics( void );
|
||||
texture_t *R_UploadCinematics( uint id );
|
||||
|
||||
//
|
||||
// r_cull.c
|
||||
//
|
||||
|
|
|
@ -1731,9 +1731,6 @@ void R_BeginFrame( bool clearScene )
|
|||
GL_UpdateGammaRamp();
|
||||
}
|
||||
|
||||
// run cinematic passes on shaders
|
||||
R_RunAllCinematics();
|
||||
|
||||
// go into 2D mode
|
||||
R_Set2DMode( true );
|
||||
|
||||
|
|
|
@ -367,9 +367,6 @@ meshbuffer_t *R_AddMeshToList( int type, mfog_t *fog, ref_shader_t *shader, int
|
|||
meshbuf = &list->meshbuffer_opaque[list->num_opaque_meshes++];
|
||||
}
|
||||
|
||||
if( shader->flags & SHADER_VIDEOMAP )
|
||||
R_UploadCinematicShader( shader );
|
||||
|
||||
meshbuf->sortkey = MB_ENTITY2NUM( RI.currententity ) | MB_FOG2NUM( fog ) | type;
|
||||
meshbuf->shaderkey = shader->sortkey;
|
||||
meshbuf->infokey = infokey;
|
||||
|
|
|
@ -1008,7 +1008,6 @@ static void R_InitMedia( void )
|
|||
R_InitMeshLists();
|
||||
R_InitGLSLPrograms();
|
||||
R_InitImages();
|
||||
R_InitCinematics ();
|
||||
R_InitShaders();
|
||||
R_InitModels();
|
||||
R_InitDecals();
|
||||
|
@ -1040,7 +1039,6 @@ static void R_FreeMedia( void )
|
|||
R_ShutdownShadows();
|
||||
R_ShutdownModels();
|
||||
R_ShutdownShaders();
|
||||
R_ShutdownCinematics ();
|
||||
R_ShutdownImages();
|
||||
R_ShutdownGLSLPrograms();
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ static bool r_shaderNoCompress;
|
|||
static bool r_shaderNearest;
|
||||
static bool r_shaderHasDlightPass;
|
||||
|
||||
#define Shader_FreePassCinematics( s ) if((s)->cinHandle ) { R_FreeCinematics((s)->cinHandle ); (s)->cinHandle = 0; }
|
||||
#define Shader_CopyString( str ) com.stralloc( r_shaderpool, str, __FILE__, __LINE__ )
|
||||
#define Shader_Malloc( size ) Mem_Alloc( r_shaderpool, size )
|
||||
#define Shader_Free( data ) Mem_Free( data )
|
||||
|
@ -1329,8 +1328,6 @@ static bool Shaderpass_MapExt( ref_shader_t *shader, ref_stage_t *pass, int addF
|
|||
string name;
|
||||
token_t tok;
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
|
||||
if( pass->num_textures )
|
||||
{
|
||||
if( pass->num_textures == MAX_STAGE_TEXTURES )
|
||||
|
@ -1421,7 +1418,6 @@ static bool Shaderpass_AnimMapExt( ref_shader_t *shader, ref_stage_t *pass, int
|
|||
float anim_fps;
|
||||
token_t tok;
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
flags = Shader_SetImageFlags( shader ) | addFlags;
|
||||
|
||||
pass->tcgen = TCGEN_BASE;
|
||||
|
@ -1475,8 +1471,6 @@ static bool Shaderpass_CubeMapExt( ref_shader_t *shader, ref_stage_t *pass, int
|
|||
string name;
|
||||
token_t tok;
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
|
||||
if( pass->num_textures )
|
||||
{
|
||||
if( pass->num_textures == MAX_STAGE_TEXTURES )
|
||||
|
@ -1555,27 +1549,6 @@ static bool Shaderpass_ShadeCubeMap( ref_shader_t *shader, ref_stage_t *pass, sc
|
|||
return Shaderpass_CubeMapExt( shader, pass, TF_CLAMP, TCGEN_REFLECTION_CELLSHADE, script );
|
||||
}
|
||||
|
||||
static bool Shaderpass_VideoMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script )
|
||||
{
|
||||
token_t tok;
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
|
||||
if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok ))
|
||||
{
|
||||
MsgDev( D_ERROR, "missing parameters for 'videoMap' in shader '%s'\n", shader->name );
|
||||
return false;
|
||||
}
|
||||
|
||||
pass->tcgen = TCGEN_BASE;
|
||||
pass->cinHandle = R_StartCinematics( tok.string );
|
||||
pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP|SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES);
|
||||
pass->animFrequency[0] = pass->animFrequency[1] = 0.0f;
|
||||
pass->anim_offset = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Shaderpass_NormalMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script )
|
||||
{
|
||||
int flags;
|
||||
|
@ -1589,8 +1562,6 @@ static bool Shaderpass_NormalMap( ref_shader_t *shader, ref_stage_t *pass, scrip
|
|||
return false;
|
||||
}
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
|
||||
flags = Shader_SetImageFlags( shader );
|
||||
if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok ))
|
||||
{
|
||||
|
@ -1659,8 +1630,6 @@ static bool Shaderpass_Material( ref_shader_t *shader, ref_stage_t *pass, script
|
|||
return false;
|
||||
}
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
|
||||
if( pass->num_textures )
|
||||
{
|
||||
pass->num_textures = 0;
|
||||
|
@ -1781,8 +1750,6 @@ static bool Shaderpass_Distortion( ref_shader_t *shader, ref_stage_t *pass, scri
|
|||
return false;
|
||||
}
|
||||
|
||||
Shader_FreePassCinematics( pass );
|
||||
|
||||
if( pass->num_textures )
|
||||
{
|
||||
pass->num_textures = 0;
|
||||
|
@ -2376,7 +2343,6 @@ static const ref_parsekey_t shaderpasskeys[] =
|
|||
{ "animMap", Shaderpass_AnimMap },
|
||||
{ "cubeMap", Shaderpass_CubeMap },
|
||||
{ "shadeCubeMap", Shaderpass_ShadeCubeMap },
|
||||
{ "videoMap", Shaderpass_VideoMap },
|
||||
{ "clampMap", Shaderpass_ClampMap },
|
||||
{ "animClampMap", Shaderpass_AnimClampMap },
|
||||
{ "normalMap", Shaderpass_NormalMap },
|
||||
|
@ -2688,9 +2654,6 @@ void Shader_TouchImages( ref_shader_t *shader, e_free free_unused )
|
|||
{
|
||||
stage = &shader->stages[i];
|
||||
|
||||
if( free_unused != FREE_IGNORE && stage->cinHandle )
|
||||
Shader_FreePassCinematics( stage );
|
||||
|
||||
for( j = 0; j < stage->num_textures; j++ )
|
||||
{
|
||||
// prolonge registration for all shader textures
|
||||
|
@ -2732,7 +2695,6 @@ void Shader_FreeShader( ref_shader_t *shader, e_free free_unused )
|
|||
uint i, hashKey;
|
||||
ref_shader_t *cur, **prev;
|
||||
shader_t handle;
|
||||
ref_stage_t *pass;
|
||||
|
||||
ASSERT( shader );
|
||||
|
||||
|
@ -2777,12 +2739,6 @@ void Shader_FreeShader( ref_shader_t *shader, e_free free_unused )
|
|||
}
|
||||
}
|
||||
|
||||
if( free_unused != FREE_IGNORE && shader->flags & SHADER_VIDEOMAP )
|
||||
{
|
||||
for( i = 0, pass = shader->stages; i < shader->num_stages; i++, pass++ )
|
||||
Shader_FreePassCinematics( pass );
|
||||
}
|
||||
|
||||
if( free_unused != FREE_IGNORE )
|
||||
{
|
||||
// free all allocated memory by shader
|
||||
|
@ -3275,8 +3231,6 @@ void Shader_Finish( ref_shader_t *s )
|
|||
pass->anim_offset = pass->num_textures; // alt-anim is missing
|
||||
pass->animFrequency[1] = 0.0f;
|
||||
}
|
||||
if( pass->cinHandle )
|
||||
s->flags |= SHADER_VIDEOMAP;
|
||||
if( pass->flags & SHADERSTAGE_LIGHTMAP )
|
||||
s->flags |= SHADER_HASLIGHTMAP;
|
||||
if( pass->program )
|
||||
|
@ -3380,19 +3334,6 @@ void Shader_Finish( ref_shader_t *s )
|
|||
Shader_TouchImages( s, FREE_IGNORE );
|
||||
}
|
||||
|
||||
void R_UploadCinematicShader( const ref_shader_t *shader )
|
||||
{
|
||||
int j;
|
||||
ref_stage_t *pass;
|
||||
|
||||
// upload cinematics
|
||||
for( j = 0, pass = shader->stages; j < shader->num_stages; j++, pass++ )
|
||||
{
|
||||
if( pass->cinHandle )
|
||||
pass->textures[0] = R_UploadCinematics( pass->cinHandle );
|
||||
}
|
||||
}
|
||||
|
||||
void R_DeformvBBoxForShader( const ref_shader_t *shader, vec3_t ebbox )
|
||||
{
|
||||
int dv;
|
||||
|
|
|
@ -56,7 +56,7 @@ typedef enum
|
|||
SHADER_POLYGONOFFSET = BIT(4),
|
||||
SHADER_CULL_FRONT = BIT(5),
|
||||
SHADER_CULL_BACK = BIT(6),
|
||||
SHADER_VIDEOMAP = BIT(7),
|
||||
SHADER_DEFAULTED = BIT(7),
|
||||
SHADER_MATERIAL = BIT(8),
|
||||
SHADER_DEFORM_NORMAL = BIT(9),
|
||||
SHADER_ENTITY_MERGABLE = BIT(10),
|
||||
|
@ -67,7 +67,6 @@ typedef enum
|
|||
SHADER_PORTAL_CAPTURE1 = BIT(15),
|
||||
SHADER_PORTAL_CAPTURE2 = BIT(16),
|
||||
SHADER_RENDERMODE = BIT(17),
|
||||
SHADER_DEFAULTED = BIT(18),
|
||||
SHADER_PORTAL_CAPTURE = (SHADER_PORTAL_CAPTURE1|SHADER_PORTAL_CAPTURE1),
|
||||
SHADER_CULL = (SHADER_CULL_FRONT|SHADER_CULL_BACK),
|
||||
|
||||
|
@ -288,8 +287,6 @@ typedef struct ref_stage_s
|
|||
word numtcMods;
|
||||
tcMod_t *tcMods;
|
||||
|
||||
uint cinHandle;
|
||||
|
||||
const char *program;
|
||||
word program_type;
|
||||
|
||||
|
@ -357,7 +354,6 @@ void R_ShaderSetMiptexFlags( uint addFlags );
|
|||
void R_ShaderSetRenderMode( kRenderMode_t mode, bool twoSided );
|
||||
void R_SetAnimFrequency( float anim_fps );
|
||||
void R_ShaderAddStageIntervals( float interval );
|
||||
void R_UploadCinematicShader( const ref_shader_t *shader );
|
||||
void R_DeformvBBoxForShader( const ref_shader_t *shader, vec3_t ebbox );
|
||||
|
||||
#endif // R_SHADER_H
|
|
@ -122,10 +122,6 @@ SOURCE=.\r_bloom.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_cin.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\r_cull.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
Reference in New Issue