Example #1
0
int R_MarkLightsLeaf( dlight_t *light, int bit, mleaf_t *pLeaf )
{
	int countMarked = 0;
	for ( int i = 0; i < pLeaf->dispCount; i++ )
	{
		IDispInfo *pDispInfo = MLeaf_Disaplcement( pLeaf, i );

		SurfaceHandle_t parentSurfID = pDispInfo->GetParent();
		if ( parentSurfID )
		{
			// Don't redo all this work if we already hit this surface and decided it's lit by this light.
			msurfacelighting_t *pLighting = SurfaceLighting( parentSurfID );
			if( !R_IsDLightAlreadyMarked( pLighting, bit) )
			{
				// Do a different test for displacement surfaces.
				Vector bmin, bmax;
				MSurf_DispInfo( parentSurfID )->GetBoundingBox( bmin, bmax );
				if ( IsBoxIntersectingSphere(bmin, bmax, light->origin, light->GetRadius()) )
				{
					R_MarkSurfaceDLight( parentSurfID, pLighting, bit );
					countMarked++;
				}
			}
		}
	}

	SurfaceHandle_t *pHandle = &host_state.worldbrush->marksurfaces[pLeaf->firstmarksurface];
	for ( int i = 0; i < pLeaf->nummarksurfaces; i++ )
	{
		SurfaceHandle_t surfID = pHandle[i];
		ASSERT_SURF_VALID( surfID );
		
		// only process leaf surfaces
		if ( MSurf_Flags( surfID ) & SURFDRAW_NODE )
			continue;

		// Don't redo all this work if we already hit this surface and decided it's lit by this light.
		msurfacelighting_t *pLighting = SurfaceLighting( surfID );
		if(R_IsDLightAlreadyMarked(pLighting, bit))
			continue;

		float dist = DotProduct( light->origin, MSurf_Plane( surfID ).normal) - MSurf_Plane( surfID ).dist;
		
		if ( dist > light->GetRadius() || dist < -light->GetRadius() )
			continue;

		countMarked += R_TryLightMarkSurface( light, pLighting, surfID, bit );
	}
	return countMarked;
}
void R_MarkLightsLeaf( dlight_t *light, int bit, mleaf_t *pLeaf )
{
	for( CDispIterator it=pLeaf->GetDispIterator(); it.IsValid(); )
	{
		CDispLeafLink *pCur = it.Inc();

		// get current displacement surface info
		IDispInfo *pDispInfo = static_cast<IDispInfo*>( pCur->m_pDispInfo );

		int parentSurfID = pDispInfo->GetParent();
		if ( parentSurfID )
		{
			// Don't redo all this work if we already hit this surface and decided it's lit by this light.
			msurfacelighting_t *pLighting = SurfaceLighting( parentSurfID );
			if( !R_IsDLightAlreadyMarked( pLighting, bit) )
			{
				// Do a different test for displacement surfaces.
				Vector bmin, bmax;
				MSurf_DispInfo( parentSurfID )->GetBoundingBox( bmin, bmax );
				if ( SphereToAABBIntersection( light->origin, light->radius, bmin, bmax ) )
				{
					R_MarkSurfaceDLight( pLighting, bit ); 
				}
			}
		}
	}

	for ( int i = 0; i < pLeaf->nummarksurfaces; i++ )
	{
		int surfID = host_state.worldmodel->brush.marksurfaces[pLeaf->firstmarksurface + i];
		ASSERT_SURF_VALID( surfID );
		
		// only process leaf surfaces
		if ( MSurf_Flags( surfID ) & SURFDRAW_NODE )
			continue;

		// Don't redo all this work if we already hit this surface and decided it's lit by this light.
		msurfacelighting_t *pLighting = SurfaceLighting( surfID );
		if(R_IsDLightAlreadyMarked(pLighting, bit))
			continue;

		float dist = DotProduct( light->origin, MSurf_Plane( surfID ).normal) - MSurf_Plane( surfID ).dist;
		
		if ( dist > light->radius || dist < -light->radius )
			continue;

		R_TryLightMarkSurface( light, pLighting, surfID, bit );
	}
}
Example #3
0
// ----------------------------------------------------------------------------- //
// Add/remove decals
// ----------------------------------------------------------------------------- //
DispDecalHandle_t CDispInfo::NotifyAddDecal( decal_t *pDecal )
{
    // FIXME: Add decal retirement...
//	if( m_Decals.Size() < MAX_DISP_DECALS )
//		return;

    // Create a new decal, link it in
    DispDecalHandle_t h = s_DispDecals.Alloc( true );

    // When linking, insert it in sorted order based on material enumeration ID
    // This will help us when rendering later
    int last = DISP_DECAL_HANDLE_INVALID;
    int i = m_FirstDecal;
    int enumerationId = pDecal->material->GetEnumerationID();
    while( i != s_DispDecals.InvalidIndex() )
    {
        int testId = s_DispDecals[i].m_pDecal->material->GetEnumerationID();
        if (enumerationId <= testId)
            break;

        last = i;
        i = s_DispDecals.Next(i);
    }

    // NOTE: when the list is used in multimode, we can't use LinkBefore( i, INVALID_INDEX ),
    // since the Head and Tail of the linked list are meaningless...

    if ( last != DISP_DECAL_HANDLE_INVALID )
        s_DispDecals.LinkAfter( last, h );
    else
    {
        s_DispDecals.LinkBefore( m_FirstDecal, h );
        m_FirstDecal = h;
    }

    CDispDecal *pDispDecal = &s_DispDecals[h];
    pDispDecal->m_pDecal = pDecal;
    pDispDecal->m_FirstFragment = DISP_DECAL_FRAGMENT_HANDLE_INVALID;
    pDispDecal->m_nVerts = 0;
    pDispDecal->m_nTris = 0;

    // Setup a basis for it.
    CDecalVert *pOutVerts = NULL;
    R_SetupDecalClip(
        pOutVerts,
        pDispDecal->m_pDecal,
        MSurf_Plane( m_ParentSurfID ).normal,
        pDispDecal->m_pDecal->material,
        pDispDecal->m_TextureSpaceBasis,
        pDispDecal->m_DecalWorldScale );

    // Recurse and precalculate which nodes this thing can touch.
    SetupDecalNodeIntersect(
        m_pPowerInfo->m_RootNode,
        0,			// node bit index into CDispDecal::m_NodeIntersects
        pDispDecal,
        0 );

    return h;
}
// returns surfID
static int FASTCALL FindIntersectionSurfaceAtLeaf( mleaf_t *pLeaf, 
					float start, float end, Vector& c, LightVecState_t& state )
{
	Vector pt;
	int closestSurfID = -1;

	// Adds displacements in the leaf to a list of displacements to test at the end
	AddDisplacementsInLeafToTestList( pLeaf, state );

	// Add non-displacement surfaces
	// Since there's no BSP tree here, we gotta test *all* surfaces! (blech)
	for ( int i = 0; i < pLeaf->nummarksurfaces; i++ )
	{
		int surfID = host_state.worldmodel->brush.marksurfaces[pLeaf->firstmarksurface + i];
		ASSERT_SURF_VALID( surfID );

		// Don't add surfaces that have displacement; they are handled above
		// In fact, don't even set the vis frame; we need it unset for translucent
		// displacement code
		if ( SurfaceHasDispInfo(surfID) )
			continue;

		if ( MSurf_Flags( surfID ) & (SURFDRAW_NODE | SURFDRAW_NODRAW | SURFDRAW_WATERSURFACE) )
			continue;

		cplane_t* pPlane = &MSurf_Plane( surfID );

		// Backface cull...
		if (DotProduct( pPlane->normal, state.m_Ray.m_Delta ) > 0.f)
			continue;

		float startDotN = DotProduct( state.m_Ray.m_Start, pPlane->normal );
		float deltaDotN = DotProduct( state.m_Ray.m_Delta, pPlane->normal );

		float front = startDotN + start * deltaDotN - pPlane->dist;
		float back = startDotN + end * deltaDotN - pPlane->dist;
		
		int side = front < 0.f;

		// Blow it off if it doesn't split the plane...
		if ( (back < 0.f) == side )
			continue;

		// Don't test a surface that is farther away from the closest found intersection
		float frac = front / (front-back);
		if (frac >= state.m_HitFrac)
			continue;

		float mid = start * (1.0f - frac) + end * frac;

		// Check this surface to see if there's an intersection
		if (FindIntersectionAtSurface( surfID, mid, c, state ))
		{
			closestSurfID = surfID;
		}
	}

	// Return the closest surface hit
	return closestSurfID;
}
Example #5
0
int R_TryLightMarkSurface( dlight_t *light, msurfacelighting_t *pLighting, SurfaceHandle_t surfID, int bit )
{
	// Make sure this light actually intersects the surface cache of the surfaces it hits
	mtexinfo_t	*tex;

	// FIXME: No worky for brush models

	// Find the perpendicular distance to the surface we're lighting
	// NOTE: Allow some stuff that's slightly behind it because view models can get behind walls
	// FIXME: We should figure out a better way to deal with view models
	float perpDistSq = DotProduct (light->origin, MSurf_Plane( surfID ).normal) - MSurf_Plane( surfID ).dist;
	if (perpDistSq < DLIGHT_BEHIND_PLANE_DIST)
		return 0;

	perpDistSq *= perpDistSq;

	float flInPlaneRadiusSq = light->GetRadiusSquared() - perpDistSq;
	if (flInPlaneRadiusSq <= 0)
		return 0;

	tex = MSurf_TexInfo( surfID );

	Vector2D mins, maxs;
	mins.Init( pLighting->m_LightmapMins[0], pLighting->m_LightmapMins[1] ); 
	maxs.Init( mins.x + pLighting->m_LightmapExtents[0], mins.y + pLighting->m_LightmapExtents[1] );

	// Project light center into texture coordinates
	Vector2D vecCircleCenter;
	vecCircleCenter.x = DotProduct (light->origin, tex->lightmapVecsLuxelsPerWorldUnits[0].AsVector3D()) + 
		tex->lightmapVecsLuxelsPerWorldUnits[0][3];
	vecCircleCenter.y = DotProduct (light->origin, tex->lightmapVecsLuxelsPerWorldUnits[1].AsVector3D()) + 
		tex->lightmapVecsLuxelsPerWorldUnits[1][3];

	// convert from world space to luxel space and convert to int
	float flInPlaneLuxelRadius = sqrtf( flInPlaneRadiusSq * tex->luxelsPerWorldUnit * tex->luxelsPerWorldUnit );

	// Does the circle intersect the square?
	if ( !IsCircleIntersectingRectangle( mins, maxs, vecCircleCenter, flInPlaneLuxelRadius ) )
		return 0;

	// Ok, mark the surface as using this light.
	R_MarkSurfaceDLight( surfID, pLighting, bit); 
	return 1;
}