Exemple #1
0
idScreenRect R_CalcLightScissorRectangle( viewLight_t *vLight )
{
	idScreenRect		r;
	srfTriangles_t		*tri;
	idPlane				eye, clip;
	idVec3				ndc;
	
	if( vLight->lightDef->parms.pointLight )
	{
		idBounds			bounds;
		idRenderLightLocal	*lightDef = vLight->lightDef;
		tr.viewDef->viewFrustum.ProjectionBounds( idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), bounds );
		return R_ScreenRectFromViewFrustumBounds( bounds );
	}
	
	if( r_useClippedLightScissors.GetInteger() == 2 )
	{
		return R_ClippedLightScissorRectangle( vLight );
	}
	r.Clear();
	
	tri = vLight->lightDef->frustumTris;
	
	for( int i = 0; i < tri->numVerts; i++ )
	{
		R_TransformModelToClip( tri->verts[i].xyz, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
		
		// if it is near clipped, clip the winding polygons to the view frustum
		if( clip[3] <= 1 )
		{
			c_clippedLight++;
			
			if( r_useClippedLightScissors.GetInteger() )
			{
				return R_ClippedLightScissorRectangle( vLight );
			}
			else
			{
				r.x1 = r.y1 = 0;
				r.x2 = ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 ) - 1;
				r.y2 = ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 ) - 1;
				return r;
			}
		}
		R_TransformClipToDevice( clip, ndc );
		
		float windowX = 0.5f * ( 1.0f + ndc[0] ) * ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 );
		float windowY = 0.5f * ( 1.0f + ndc[1] ) * ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 );
		
		if( windowX > tr.viewDef->scissor.x2 )
		{
			windowX = tr.viewDef->scissor.x2;
		}
		else if( windowX < tr.viewDef->scissor.x1 )
		{
			windowX = tr.viewDef->scissor.x1;
		}
		
		if( windowY > tr.viewDef->scissor.y2 )
		{
			windowY = tr.viewDef->scissor.y2;
		}
		else if( windowY < tr.viewDef->scissor.y1 )
		{
			windowY = tr.viewDef->scissor.y1;
		}
		r.AddPoint( windowX, windowY );
	}
	
	// add the fudge boundary
	r.Expand();
	
	c_unclippedLight++;
	
	return r;
}
Exemple #2
0
/*
===================
R_EntityDefDynamicModel

Issues a deferred entity callback if necessary.
If the model isn't dynamic, it returns the original.
Returns the cached dynamic model if present, otherwise creates
it and any necessary overlays
===================
*/
idRenderModel *R_EntityDefDynamicModel( idRenderEntityLocal *def )
{
	bool callbackUpdate;
	
	// allow deferred entities to construct themselves
	if( def->parms.callback )
	{
		callbackUpdate = R_IssueEntityDefCallback( def );
	}
	else
	{
		callbackUpdate = false;
	}
	idRenderModel *model = def->parms.hModel;
	
	if( !model )
	{
		common->Error( "R_EntityDefDynamicModel: NULL model" );
	}
	
	if( model->IsDynamicModel() == DM_STATIC )
	{
		def->dynamicModel = NULL;
		def->dynamicModelFrameCount = 0;
		return model;
	}
	
	// continously animating models (particle systems, etc) will have their snapshot updated every single view
	if( callbackUpdate || ( model->IsDynamicModel() == DM_CONTINUOUS && def->dynamicModelFrameCount != tr.frameCount ) )
	{
		R_ClearEntityDefDynamicModel( def );
	}
	
	// if we don't have a snapshot of the dynamic model, generate it now
	if( !def->dynamicModel )
	{
		// instantiate the snapshot of the dynamic model, possibly reusing memory from the cached snapshot
		def->cachedDynamicModel = model->InstantiateDynamicModel( &def->parms, tr.viewDef, def->cachedDynamicModel );
		
		if( def->cachedDynamicModel )
		{
			// add any overlays to the snapshot of the dynamic model
			if( def->overlay && !r_skipOverlays.GetBool() )
			{
				def->overlay->AddOverlaySurfacesToModel( def->cachedDynamicModel );
			}
			else
			{
				idRenderModelOverlay::RemoveOverlaySurfacesFromModel( def->cachedDynamicModel );
			}
			
			if( r_checkBounds.GetBool() )
			{
				idBounds b = def->cachedDynamicModel->Bounds();
				
				if( b[0][0] < def->referenceBounds[0][0] - CHECK_BOUNDS_EPSILON ||
						b[0][1] < def->referenceBounds[0][1] - CHECK_BOUNDS_EPSILON ||
						b[0][2] < def->referenceBounds[0][2] - CHECK_BOUNDS_EPSILON ||
						b[1][0] > def->referenceBounds[1][0] + CHECK_BOUNDS_EPSILON ||
						b[1][1] > def->referenceBounds[1][1] + CHECK_BOUNDS_EPSILON ||
						b[1][2] > def->referenceBounds[1][2] + CHECK_BOUNDS_EPSILON )
				{
					common->Printf( "entity %i dynamic model exceeded reference bounds\n", def->index );
				}
			}
		}
		def->dynamicModel = def->cachedDynamicModel;
		def->dynamicModelFrameCount = tr.frameCount;
	}
	
	// set model depth hack value
	if( def->dynamicModel && model->DepthHack() != 0.0f && tr.viewDef )
	{
		idPlane eye, clip;
		idVec3	ndc;
		
		R_TransformModelToClip( def->parms.origin, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
		R_TransformClipToDevice( clip, ndc );
		
		def->parms.modelDepthHack = model->DepthHack() * ( 1.0f - ndc.z );
	}
	
	// FIXME: if any of the surfaces have deforms, create a frame-temporary model with references to the
	// undeformed surfaces.  This would allow deforms to be light interacting.
	return def->dynamicModel;
}
Exemple #3
0
/*
======================
R_ClippedLightScissorRectangle
======================
*/
idScreenRect R_ClippedLightScissorRectangle( viewLight_t *vLight )
{
	int							i, j;
	const idRenderLightLocal	*light = vLight->lightDef;
	idScreenRect				r;
	idFixedWinding				w;
	
	r.Clear();
	
	for( i = 0; i < 6; i++ )
	{
		const idWinding *ow = light->frustumWindings[i];
		
		// projected lights may have one of the frustums degenerated
		if( !ow )
		{
			continue;
		}
		
		// the light frustum planes face out from the light,
		// so the planes that have the view origin on the negative
		// side will be the "back" faces of the light, which must have
		// some fragment inside the portalStack to be visible
		if( light->frustum[i].Distance( tr.viewDef->renderView.vieworg ) >= 0 )
		{
			continue;
		}
		w = *ow;
		
		// now check the winding against each of the frustum planes
		for( j = 0; j < 5; j++ )
		{
			if( !w.ClipInPlace( -tr.viewDef->frustum[j] ) )
			{
				break;
			}
		}
		
		// project these points to the screen and add to bounds
		for( j = 0; j < w.GetNumPoints(); j++ )
		{
			idPlane		eye, clip;
			idVec3		ndc;
			
			R_TransformModelToClip( w[j].ToVec3(), tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
			
			if( clip[3] <= 0.01f )
			{
				clip[3] = 0.01f;
			}
			R_TransformClipToDevice( clip, ndc );
			
			float windowX = 0.5f * ( 1.0f + ndc[0] ) * ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 );
			float windowY = 0.5f * ( 1.0f + ndc[1] ) * ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 );
			
			if( windowX > tr.viewDef->scissor.x2 )
			{
				windowX = tr.viewDef->scissor.x2;
			}
			else if( windowX < tr.viewDef->scissor.x1 )
			{
				windowX = tr.viewDef->scissor.x1;
			}
			
			if( windowY > tr.viewDef->scissor.y2 )
			{
				windowY = tr.viewDef->scissor.y2;
			}
			else if( windowY < tr.viewDef->scissor.y1 )
			{
				windowY = tr.viewDef->scissor.y1;
			}
			r.AddPoint( windowX, windowY );
		}
	}
	
	// add the fudge boundary
	r.Expand();
	
	return r;
}
/*
===================
R_EntityDefDynamicModel

This is also called by the game code for idRenderWorldLocal::ModelTrace(), and idRenderWorldLocal::Trace() which is bad for performance...

Issues a deferred entity callback if necessary.
If the model isn't dynamic, it returns the original.
Returns the cached dynamic model if present, otherwise creates it.
===================
*/
idRenderModel* R_EntityDefDynamicModel( idRenderEntityLocal* def )
{
	if( def->dynamicModelFrameCount == tr.frameCount )
	{
		return def->dynamicModel;
	}
	
	// allow deferred entities to construct themselves
	bool callbackUpdate;
	if( def->parms.callback != NULL )
	{
		SCOPED_PROFILE_EVENT( "R_IssueEntityDefCallback" );
		callbackUpdate = R_IssueEntityDefCallback( def );
	}
	else
	{
		callbackUpdate = false;
	}
	
	idRenderModel* model = def->parms.hModel;
	
	if( model == NULL )
	{
		common->Error( "R_EntityDefDynamicModel: NULL model" );
		return NULL;
	}
	
	if( model->IsDynamicModel() == DM_STATIC )
	{
		def->dynamicModel = NULL;
		def->dynamicModelFrameCount = 0;
		return model;
	}
	
	// continously animating models (particle systems, etc) will have their snapshot updated every single view
	if( callbackUpdate || ( model->IsDynamicModel() == DM_CONTINUOUS && def->dynamicModelFrameCount != tr.frameCount ) )
	{
		R_ClearEntityDefDynamicModel( def );
	}
	
	// if we don't have a snapshot of the dynamic model, generate it now
	if( def->dynamicModel == NULL )
	{
	
		SCOPED_PROFILE_EVENT( "InstantiateDynamicModel" );
		
		// instantiate the snapshot of the dynamic model, possibly reusing memory from the cached snapshot
		def->cachedDynamicModel = model->InstantiateDynamicModel( &def->parms, tr.viewDef, def->cachedDynamicModel );
		
		if( def->cachedDynamicModel != NULL && r_checkBounds.GetBool() )
		{
			idBounds b = def->cachedDynamicModel->Bounds();
			if(	b[0][0] < def->localReferenceBounds[0][0] - CHECK_BOUNDS_EPSILON ||
					b[0][1] < def->localReferenceBounds[0][1] - CHECK_BOUNDS_EPSILON ||
					b[0][2] < def->localReferenceBounds[0][2] - CHECK_BOUNDS_EPSILON ||
					b[1][0] > def->localReferenceBounds[1][0] + CHECK_BOUNDS_EPSILON ||
					b[1][1] > def->localReferenceBounds[1][1] + CHECK_BOUNDS_EPSILON ||
					b[1][2] > def->localReferenceBounds[1][2] + CHECK_BOUNDS_EPSILON )
			{
				common->Printf( "entity %i dynamic model exceeded reference bounds\n", def->index );
			}
		}
		
		def->dynamicModel = def->cachedDynamicModel;
		def->dynamicModelFrameCount = tr.frameCount;
	}
	
	// set model depth hack value
	if( def->dynamicModel != NULL && model->DepthHack() != 0.0f && tr.viewDef != NULL )
	{
		idPlane eye, clip;
		idVec3 ndc;
		R_TransformModelToClip( def->parms.origin, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
		R_TransformClipToDevice( clip, ndc );
		def->parms.modelDepthHack = model->DepthHack() * ( 1.0f - ndc.z );
	}
	else
	{
		def->parms.modelDepthHack = 0.0f;
	}
	
	return def->dynamicModel;
}