Skip to content

Commit

Permalink
client: basic adaption of movie playback to the new API
Browse files Browse the repository at this point in the history
  • Loading branch information
a1batross authored and SNMetamorph committed Dec 13, 2024
1 parent 61b3612 commit 6633ccc
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 50 deletions.
8 changes: 5 additions & 3 deletions client/enginecallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,11 @@ inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex(
#define FREE_CINEMATIC (*gRenderfuncs.AVI_FreeVideo)
#define CIN_IS_ACTIVE (*gRenderfuncs.AVI_IsActive)
#define CIN_GET_VIDEO_INFO (*gRenderfuncs.AVI_GetVideoInfo)
#define CIN_GET_FRAME_NUMBER (*gRenderfuncs.AVI_GetVideoFrameNumber)
#define CIN_GET_FRAMEDATA (*gRenderfuncs.AVI_GetVideoFrame)
#define CIN_UPDATE_SOUND (*gRenderfuncs.AVI_StreamSound)
// #define CIN_GET_FRAME_NUMBER (*gRenderfuncs.AVI_GetVideoFrameNumber)
// #define CIN_GET_FRAMEDATA (*gRenderfuncs.AVI_GetVideoFrame)
// #define CIN_UPDATE_SOUND (*gRenderfuncs.AVI_StreamSound)
#define CIN_THINK (*gRenderfuncs.AVI_Think)
#define CIN_SET_PARM (*gRenderfuncs.AVI_SetParm)

// glcommands
#define GL_SelectTexture (*gRenderfuncs.GL_SelectTexture)
Expand Down
6 changes: 5 additions & 1 deletion client/render/gl_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,13 @@ typedef struct gl_fbo_s
typedef struct gl_movie_s
{
char name[32];
void *state;
struct movie_state_s *state;
float length; // total cinematic length
int xres, yres; // size of cinematic

bool finished;
bool sound_set;
bool texture_set;
} gl_movie_t;

typedef struct gl_texbuffer_s
Expand Down
73 changes: 37 additions & 36 deletions client/render/gl_movie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ int R_PrecacheCinematic( const char *cinname )
if( !cinname || !*cinname )
return -1;

if( *cinname == '*' )
{
cinname++;
}

// not AVI file
if( Q_stricmp( UTIL_FileExtension( cinname ), "avi" ))
const char *ext = UTIL_FileExtension( cinname );
if( Q_stricmp( ext, "avi" ) && Q_stricmp( ext, "webm" )) // with ffmpeg we don't really have a limit here
return -1;

int i;
Expand Down Expand Up @@ -68,7 +64,13 @@ int R_PrecacheCinematic( const char *cinname )
}

ALERT( at_console, "Loading cinematic %s [%s]\n", cinname, "sound" );
tr.cinematics[i].state = OPEN_CINEMATIC( tr.cinematics[i].name, true );

// FIXME: engine is hardcoded to load file in media/ folder, must be fixed on engine side
const char *p = tr.cinematics[i].name;
if( !Q_strnicmp( p, "media/", 6 ))
p += 6;

tr.cinematics[i].state = (movie_state_s *)OPEN_CINEMATIC( p, true );

// grab info about movie
if( tr.cinematics[i].state != NULL )
Expand All @@ -79,6 +81,8 @@ int R_PrecacheCinematic( const char *cinname )

void R_InitCinematics( void )
{
// a1ba: this function is useless lmao
// it's called before WORLD_HAS_MOVIES bit set
const char *name, *ext;

// make sure what we have texture to draw cinematics
Expand Down Expand Up @@ -162,6 +166,7 @@ void R_UpdateCinematic( const msurface_t *surf )
if( cinhandle >= 0 && es->cintexturenum <= 0 )
es->cintexturenum = R_AllocateCinematicTexture( TF_NOMIPMAP );

// a1ba: isn't this kinda stupid? If movie isn't active anymore, we will never draw movie on it again
if( cinhandle == -1 || es->cintexturenum <= 0 || CIN_IS_ACTIVE( tr.cinematics[cinhandle].state ) == false )
{
// cinematic textures limit exceeded, so remove SURF_MOVIE flag
Expand All @@ -170,28 +175,18 @@ void R_UpdateCinematic( const msurface_t *surf )
}

gl_movie_t *cin = &tr.cinematics[cinhandle];
float cin_time;

if( FBitSet( RI->currententity->curstate.iuser1, CF_LOOPED_MOVIE ))
{
// advances cinematic time
cin_time = fmod( RI->currententity->curstate.fuser2, cin->length );
}
else
{
cin_time = RI->currententity->curstate.fuser2;
}

// read the next frame
int cin_frame = CIN_GET_FRAME_NUMBER( cin->state, cin_time );
if( cin->finished )
return;

// upload the new frame
if( cin_frame != es->checkcount )
if( !cin->texture_set )
{
GL_SelectTexture( GL_TEXTURE0 ); // doesn't matter. select 0-th unit just as default
byte *raw = CIN_GET_FRAMEDATA( cin->state, cin_frame );
CIN_UPLOAD_FRAME( tr.cinTextures[es->cintexturenum-1], cin->xres, cin->yres, cin->xres, cin->yres, raw );
es->checkcount = cin_frame;
CIN_SET_PARM( cin->state,
AVI_RENDER_TEXNUM, tr.cinTextures[es->cintexturenum-1],
AVI_RENDER_W, cin->xres,
AVI_RENDER_H, cin->yres,
AVI_PARM_LAST );
cin->texture_set = true;
}
}

Expand All @@ -208,18 +203,24 @@ void R_UpdateCinSound( cl_entity_t *e )
return;

gl_movie_t *cin = &tr.cinematics[cinhandle];
float cin_time;

if( FBitSet( e->curstate.iuser1, CF_LOOPED_MOVIE ))
if( cin->finished )
return;

if( !cin->sound_set )
{
// advances cinematic time
cin_time = fmod( e->curstate.fuser2, cin->length );
CIN_SET_PARM( cin->state,
AVI_ENTNUM, e->index,
AVI_VOLUME, static_cast<int>( VOL_NORM * 255 ),
AVI_ATTN, ATTN_NORM,
AVI_PARM_LAST );
cin->sound_set = true;
}
else

if( !CIN_THINK( cin->state )) // TODO: make a video manager that will call this each frame
{
cin_time = e->curstate.fuser2;
if( FBitSet( RI->currententity->curstate.iuser1, CF_LOOPED_MOVIE ))
CIN_SET_PARM( cin->state, AVI_REWIND, AVI_PARM_LAST );
else cin->finished = true;
}

// stream avi sound
CIN_UPDATE_SOUND( cin->state, e->index, VOL_NORM, ATTN_IDLE, cin_time );
}
}
29 changes: 19 additions & 10 deletions client/render/gl_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,19 +496,28 @@ static bool R_HandleLightEntity(cl_entity_t *ent)
return true;
}

// TODO: move this to a common function in gl_movie.cpp
gl_movie_t *cin = &tr.cinematics[hCin];

// advances cinematic time
float cin_time = fmod(entity.GetCinTime(), cin->length);

// read the next frame
int cin_frame = CIN_GET_FRAME_NUMBER(cin->state, cin_time);
if (cin_frame != dlight->lastframe)
if( !cin->finished )
{
// upload the new frame
byte *raw = CIN_GET_FRAMEDATA(cin->state, cin_frame);
CIN_UPLOAD_FRAME(tr.cinTextures[dlight->cinTexturenum - 1], cin->xres, cin->yres, cin->xres, cin->yres, raw);
dlight->lastframe = cin_frame;
if( !cin->texture_set )
{
CIN_SET_PARM( cin->state, AVI_RENDER_TEXNUM, tr.cinTextures[dlight->cinTexturenum - 1],
AVI_RENDER_W, cin->xres,
AVI_RENDER_H, cin->yres,
AVI_PARM_LAST );
cin->texture_set = true;
}

// running think here because we're usually thinking with audio, but dlight doesn't have audio

if( !CIN_THINK( cin->state )); // probably should be moved to some kind of global manager that will tick each frame
{
if( FBitSet( RI->currententity->curstate.iuser1, CF_LOOPED_MOVIE ))
CIN_SET_PARM( cin->state, AVI_REWIND, AVI_PARM_LAST );
else cin->finished = true;
}
}

if (entity.DisableShadows())
Expand Down

0 comments on commit 6633ccc

Please sign in to comment.