Example #1
0
int R_DrawCinematic( msurface_t *surf, texture_t *t )
{
	if( !RI.currententity->curstate.body )
	{
		GL_Bind( GL_TEXTURE0, t->gl_texturenum );
		return 0;	// just disabled
	}

	// draw the cinematic
	mextrasurf_t *es = SURF_INFO( surf, RI.currentmodel );

	// found the corresponding cinstate
	const char *cinname = gEngfuncs.pEventAPI->EV_EventForIndex( RI.currententity->curstate.sequence );
	int cinhandle = R_PrecacheCinematic( cinname );

	if( cinhandle >= 0 && es->mirrortexturenum <= 0 )
		es->mirrortexturenum = R_AllocateCinematicTexture( TF_SCREEN );

	if( cinhandle == -1 || es->mirrortexturenum <= 0 || CIN_IS_ACTIVE( tr.cinematics[cinhandle].state ) == false )
	{
		// cinematic textures limit exceeded, so remove SURF_MOVIE flag
		GL_Bind( GL_TEXTURE0, t->gl_texturenum );
		surf->flags &= ~SURF_MOVIE;
		return 0;
	}

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

	if( 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_frame != es->checkcount )
	{
		GL_SelectTexture( GL_TEXTURE0 );

		// upload the new frame
		byte *raw = CIN_GET_FRAMEDATA( cin->state, cin_frame );
		CIN_UPLOAD_FRAME( tr.cinTextures[es->mirrortexturenum-1], cin->xres, cin->yres, cin->xres, cin->yres, raw );
		es->checkcount = cin_frame;
	}
	else
	{
		// have valid cinematic texture
		GL_Bind( GL_TEXTURE0, tr.cinTextures[es->mirrortexturenum-1] );
	}

	return 1;
}
Example #2
0
/*
================
R_BeginDrawMirror

Setup texture matrix for mirror texture
================
*/
void R_BeginDrawMirror( msurface_t *fa )
{
	matrix4x4		m1, m2, matrix;
	GLfloat		genVector[4][4];
	mextrasurf_t	*es;
	int		i;

	es = SURF_INFO( fa, RI.currentmodel );
	Matrix4x4_Copy( matrix, es->mirrormatrix );

	Matrix4x4_LoadIdentity( m1 );
	Matrix4x4_ConcatScale( m1, 0.5f );
	Matrix4x4_Concat( m2, m1, matrix );

	Matrix4x4_LoadIdentity( m1 );
	Matrix4x4_ConcatTranslate( m1, 0.5f, 0.5f, 0.5f );
	Matrix4x4_Concat( matrix, m1, m2 );

	for( i = 0; i < 4; i++ )
	{
		genVector[0][i] = i == 0 ? 1 : 0;
		genVector[1][i] = i == 1 ? 1 : 0;
		genVector[2][i] = i == 2 ? 1 : 0;
		genVector[3][i] = i == 3 ? 1 : 0;
	}

	GL_TexGen( GL_S, GL_OBJECT_LINEAR );
	GL_TexGen( GL_T, GL_OBJECT_LINEAR );
	GL_TexGen( GL_R, GL_OBJECT_LINEAR );
	GL_TexGen( GL_Q, GL_OBJECT_LINEAR );

	pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] );
	pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] );
	pglTexGenfv( GL_R, GL_OBJECT_PLANE, genVector[2] );
	pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] );

	GL_LoadTexMatrix( matrix );
}
Example #3
0
/*
=================
R_FindBmodelMirrors

Check all bmodel surfaces and make personal mirror chain
=================
*/
void R_FindBmodelMirrors( cl_entity_t *e, qboolean static_entity )
{
	mextrasurf_t	*extrasurf;
	vec3_t		mins, maxs;
	msurface_t	*psurf;
	model_t		*clmodel;
	qboolean		rotated;
	int		i, clipFlags;

	clmodel = e->model;

	if( static_entity )
	{
		Matrix4x4_LoadIdentity( RI.objectMatrix );

		if( R_CullBox( clmodel->mins, clmodel->maxs, RI.clipFlags ))
			return;

		VectorCopy( RI.cullorigin, tr.modelorg );
		clipFlags = RI.clipFlags;
	}
	else
	{
		if( !VectorIsNull( e->angles ))
		{
			for( i = 0; i < 3; i++ )
			{
				mins[i] = e->origin[i] - clmodel->radius;
				maxs[i] = e->origin[i] + clmodel->radius;
			}
			rotated = true;
		}
		else
		{
			VectorAdd( e->origin, clmodel->mins, mins );
			VectorAdd( e->origin, clmodel->maxs, maxs );
			rotated = false;
		}

		if( R_CullBox( mins, maxs, RI.clipFlags ))
			return;

		if( !VectorIsNull( e->origin ) || !VectorIsNull( e->angles ))
		{
			if( rotated ) Matrix4x4_CreateFromEntity( RI.objectMatrix, e->angles, e->origin, 1.0f );
			else Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, 1.0f );
		}
		else Matrix4x4_LoadIdentity( RI.objectMatrix );

		e->visframe = tr.framecount; // visible

		if( rotated ) Matrix4x4_VectorITransform( RI.objectMatrix, RI.cullorigin, tr.modelorg );
		else VectorSubtract( RI.cullorigin, e->origin, tr.modelorg );

		clipFlags = 0;
	}

	psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
	for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
	{
		if(!( psurf->flags & SURF_REFLECT ))
			continue;

		if( R_CullSurface( psurf, clipFlags ))
			continue;

		extrasurf = SURF_INFO( psurf, RI.currentmodel );
		extrasurf->mirrorchain = tr.mirror_entities[tr.num_mirror_entities].chain;
		tr.mirror_entities[tr.num_mirror_entities].chain = extrasurf;
	}

	// store new mirror entity
	if( !static_entity && tr.mirror_entities[tr.num_mirror_entities].chain != NULL )
	{
		tr.mirror_entities[tr.num_mirror_entities].ent = RI.currententity;
		tr.num_mirror_entities++;
	}
}
Example #4
0
/*
================
R_RecursiveMirrorNode
================
*/
void R_RecursiveMirrorNode( mnode_t *node, uint clipflags )
{
	mextrasurf_t	*extrasurf;
	const mplane_t	*clipplane;
	int		i, clipped;
	msurface_t	*surf, **mark;
	mleaf_t		*pleaf;
	int		c, side;
	float		dot;

	if( node->contents == CONTENTS_SOLID )
		return; // hit a solid leaf

	if( node->visframe != tr.visframecount )
		return;

	if( clipflags )
	{
		for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ )
		{
			if(!( clipflags & ( 1<<i )))
				continue;

			clipped = BoxOnPlaneSide( node->minmaxs, node->minmaxs + 3, clipplane );
			if( clipped == 2 ) return;
			if( clipped == 1 ) clipflags &= ~(1<<i);
		}
	}

	// if a leaf node, draw stuff
	if( node->contents < 0 )
	{
		pleaf = (mleaf_t *)node;

		mark = pleaf->firstmarksurface;
		c = pleaf->nummarksurfaces;

		if( c )
		{
			do
			{
				(*mark)->visframe = tr.framecount;
				mark++;
			} while( --c );
		}
		return;
	}

	// node is just a decision point, so go down the apropriate sides

	// find which side of the node we are on
	dot = PlaneDiff( tr.modelorg, node->plane );
	side = (dot >= 0) ? 0 : 1;

	// recurse down the children, front side first
	R_RecursiveMirrorNode( node->children[side], clipflags );

	// draw stuff
	for( c = node->numsurfaces, surf = cl.worldmodel->surfaces + node->firstsurface; c; c--, surf++ )
	{
		if(!( surf->flags & SURF_REFLECT ))
			continue;

		if( R_CullSurface( surf, clipflags ))
			continue;

		extrasurf = SURF_INFO( surf, RI.currentmodel );
		extrasurf->mirrorchain = tr.mirror_entities[0].chain;
		tr.mirror_entities[0].chain = extrasurf;
	}

	// recurse down the back side
	R_RecursiveMirrorNode( node->children[!side], clipflags );
}
Example #5
0
/*
================
R_ReLightGrass

We already have a valid spot on texture
Just find lightmap point and update grass color
================
*/
void R_ReLightGrass( msurface_t *surf, bool force )
{
	mextrasurf_t *es = SURF_INFO( surf, RI.currentmodel );
	grasshdr_t *hdr = es->grass;

	if( !hdr ) return;

	for( int maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++ )
	{
		if( force || ( RI.lightstylevalue[surf->styles[maps]] != hdr->cached_light[maps] ))
		{
			unsigned int lightcolor[3];
			grass_t *g = hdr->g;

			for( int i = 0; i < hdr->count; i++, g++ )
			{
				if( !RI.currentmodel->lightdata )
				{
					// just to get fullbright
					g->color[0] = g->color[1] = g->color[2] = 255;
					continue;
				}

				if( !surf->samples )
				{
					// no light here
					g->color[0] = g->color[1] = g->color[2] = 0;
					continue;
				}

				mtexinfo_t *tex = surf->texinfo;

				// NOTE: don't need to call R_LightForPoint here because we already have a valid surface spot
				// just read lightmap color and out
				int s = (DotProduct( g->pos, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0]) / LM_SAMPLE_SIZE;
				int t = (DotProduct( g->pos, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1]) / LM_SAMPLE_SIZE;
				color24 *lm = surf->samples + (t * ((surf->extents[0] / LM_SAMPLE_SIZE ) + 1) + s);
				int size = ((surf->extents[0] / LM_SAMPLE_SIZE) + 1) * ((surf->extents[1] / LM_SAMPLE_SIZE) + 1);
				lightcolor[0] = lightcolor[1] = lightcolor[2] = 0;

				for( int map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
				{
					unsigned int scale = RI.lightstylevalue[surf->styles[map]];

					lightcolor[0] += TEXTURE_TO_TEXGAMMA( lm->r ) * scale;
					lightcolor[1] += TEXTURE_TO_TEXGAMMA( lm->g ) * scale;
					lightcolor[2] += TEXTURE_TO_TEXGAMMA( lm->b ) * scale;
					lm += size; // skip to next lightmap
				}

				// convert to normal rangle
				g->color[0] = min((lightcolor[0] >> 7), 255 );
				g->color[1] = min((lightcolor[1] >> 7), 255 );
				g->color[2] = min((lightcolor[2] >> 7), 255 );

				for( int j = 0; j < 16; j++ )
					*(int *)g->mesh[j].c = *(int *)g->color;
			}

			// NOTE: 'maps' used twice but is no matter because we breaking main cycle
			for( maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++ )
				hdr->cached_light[maps] = RI.lightstylevalue[surf->styles[maps]];

			break;
		}
	}
Example #6
0
/*
=================
R_CullSurface

cull invisible surfaces
=================
*/
bool R_CullSurfaceExt( msurface_t *surf, const mplane_t frustum[6], unsigned int clipflags )
{
	mextrasurf_t	*info;
	cl_entity_t	*e = RI.currententity;

	if( !surf || !surf->texinfo || !surf->texinfo->texture )
		return true;

	if( surf->flags & SURF_WATERCSG && !( RI.currententity->curstate.effects & EF_NOWATERCSG ))
		return true;

	if( surf->flags & SURF_NOCULL )
		return false;

	// don't cull transparent surfaces because we should be draw decals on them
	if( surf->pdecals && ( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ))
		return false;

	if( r_nocull->value )
		return false;

	// world surfaces can be culled by vis frame too
	if( RI.currententity == GET_ENTITY( 0 ) && surf->visframe != tr.framecount )
		return true;

	if( r_faceplanecull->value && glState.faceCull != 0 )
	{
		if(!(surf->flags & SURF_DRAWTURB) || !RI.currentWaveHeight )
		{
			if( surf->plane->normal != g_vecZero )
			{
				float	dist;

				if( RI.drawOrtho ) dist = surf->plane->normal[2];
				else dist = PlaneDiff( tr.modelorg, surf->plane );

				if( glState.faceCull == GL_FRONT || ( RI.params & RP_MIRRORVIEW ))
				{
					if( surf->flags & SURF_PLANEBACK )
					{
						if( dist >= -BACKFACE_EPSILON )
							return true; // wrong side
					}
					else
					{
						if( dist <= BACKFACE_EPSILON )
							return true; // wrong side
					}
				}
				else if( glState.faceCull == GL_BACK )
				{
					if( surf->flags & SURF_PLANEBACK )
					{
						if( dist <= BACKFACE_EPSILON )
							return true; // wrong side
					}
					else
					{
						if( dist >= -BACKFACE_EPSILON )
							return true; // wrong side
					}
				}
			}
		}
	}

	info = SURF_INFO( surf, RI.currentmodel );

	return ( clipflags && R_CullBoxExt( frustum, info->mins, info->maxs, clipflags ));
}