03 Oct 2010

This commit is contained in:
g-cont 2010-10-03 00:00:00 +04:00 committed by Alibek Omarov
parent e22ec1a233
commit 2ed0925353
20 changed files with 83 additions and 1759 deletions

View File

@ -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 ));

View File

@ -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;

View File

@ -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 );

View File

@ -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;
}

View File

@ -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

View 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 );

View File

@ -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];

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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" );
}

View File

@ -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 )

View File

@ -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;
}
}

View File

@ -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
//

View File

@ -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 );

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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