Exemplo n.º 1
0
// returns a surfID
static SurfaceHandle_t FindIntersectionSurfaceAtNode( mnode_t *node, float t, 
	Vector& c, LightVecState_t& state )
{
	SurfaceHandle_t surfID = SurfaceHandleFromIndex( node->firstsurface );
	for (int i=0 ; i<node->numsurfaces ; ++i, ++surfID)
	{
		// Don't immediately return when we hit sky; 
		// we may actually hit another surface
		if (MSurf_Flags( surfID ) & SURFDRAW_SKY)
		{
			state.m_nSkySurfID = surfID;
			continue;
		}

		// Don't let water surfaces affect us
		if (MSurf_Flags( surfID ) & SURFDRAW_WATERSURFACE)
			continue;

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

	return SURFACE_HANDLE_INVALID;
}
Exemplo n.º 2
0
// 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;
}
Exemplo n.º 3
0
//-----------------------------------------------------------------------------
// Tests a particular surface
//-----------------------------------------------------------------------------
static bool FASTCALL FindIntersectionAtSurface( int surfID, float f, 
	Vector& c, LightVecState_t& state )
{
	// no lightmaps on this surface? punt...
	// FIXME: should be water surface?
	if (MSurf_Flags( surfID ) & SURFDRAW_NOLIGHT)
		return false;	

	// Compute the actual point
	Vector pt;
	VectorMA( state.m_Ray.m_Start, f, state.m_Ray.m_Delta, pt );

	mtexinfo_t* pTex = MSurf_TexInfo( surfID );
	
	// See where in lightmap space our intersection point is 
	float s, t;
	s = DotProduct (pt, pTex->lightmapVecsLuxelsPerWorldUnits[0].AsVector3D()) + 
		pTex->lightmapVecsLuxelsPerWorldUnits[0][3];
	t = DotProduct (pt, pTex->lightmapVecsLuxelsPerWorldUnits[1].AsVector3D()) + 
		pTex->lightmapVecsLuxelsPerWorldUnits[1][3];

	// Not in the bounds of our lightmap? punt...
	msurfacelighting_t *pLighting = SurfaceLighting( surfID );
	if( s < pLighting->m_pLightmapMins[0] || 
		t < pLighting->m_pLightmapMins[1] )
		return false;	
	
	// assuming a square lightmap (FIXME: which ain't always the case),
	// lets see if it lies in that rectangle. If not, punt...
	float ds = s - pLighting->m_pLightmapMins[0];
	float dt = t - pLighting->m_pLightmapMins[1];
	if( ds > pLighting->m_pLightmapExtents[0] || dt > pLighting->m_pLightmapExtents[1] )
		return false;	

	// Store off the hit distance...
	state.m_HitFrac = f;

	// You heard the man!
	ComputeTextureCoordsAtIntersection( pTex, pt, state.m_pTextureS, state.m_pTextureT );

#ifdef USE_CONVARS
	if( 1 )
#else
	if (r_avglight.GetInt())
#endif
	{
		// This is the faster path; it looks slightly different though
		ComputeLightmapColorFromAverage( pLighting, state.m_bUseLightStyles, c );
	}
	else
	{
		// Compute lightmap coords
		ComputeLightmapCoordsAtIntersection( pLighting, ds, dt, state.m_pLightmapS, state.m_pLightmapT );
		
		// Check out the value of the lightmap at the intersection point
		ComputeLightmapColor( surfID, (int)ds, (int)dt, state.m_bUseLightStyles, c );
	}

	return true;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
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 );
	}
}
Exemplo n.º 6
0
//-----------------------------------------------------------------------------
// Tests a particular surface
//-----------------------------------------------------------------------------
static bool FASTCALL FindIntersectionAtSurface( SurfaceHandle_t surfID, float f, 
	Vector& c, LightVecState_t& state )
{
	// no lightmaps on this surface? punt...
	// FIXME: should be water surface?
	if (MSurf_Flags( surfID ) & SURFDRAW_NOLIGHT)
		return false;	

	// Compute the actual point
	Vector pt;
	VectorMA( state.m_Ray.m_Start, f, state.m_Ray.m_Delta, pt );

	mtexinfo_t* pTex = MSurf_TexInfo( surfID );
	
	// See where in lightmap space our intersection point is 
	float s, t;
	s = DotProduct (pt, pTex->lightmapVecsLuxelsPerWorldUnits[0].AsVector3D()) + 
		pTex->lightmapVecsLuxelsPerWorldUnits[0][3];
	t = DotProduct (pt, pTex->lightmapVecsLuxelsPerWorldUnits[1].AsVector3D()) + 
		pTex->lightmapVecsLuxelsPerWorldUnits[1][3];

	// Not in the bounds of our lightmap? punt...
	msurfacelighting_t *pLighting = SurfaceLighting( surfID );
	if( s < pLighting->m_LightmapMins[0] || 
		t < pLighting->m_LightmapMins[1] )
		return false;	
	
	// assuming a square lightmap (FIXME: which ain't always the case),
	// lets see if it lies in that rectangle. If not, punt...
	float ds = s - pLighting->m_LightmapMins[0];
	float dt = t - pLighting->m_LightmapMins[1];
	if ( !pLighting->m_LightmapExtents[0] && !pLighting->m_LightmapExtents[1] )
	{
		worldbrushdata_t *pBrushData = host_state.worldbrush;

		// 
		float	lightMaxs[2];
		lightMaxs[ 0 ] = pLighting->m_LightmapMins[0];
		lightMaxs[ 1 ] = pLighting->m_LightmapMins[1];
		int i;
		for (i=0 ; i<MSurf_VertCount( surfID ); i++)
		{
			int e = pBrushData->vertindices[MSurf_FirstVertIndex( surfID )+i];
			mvertex_t *v = &pBrushData->vertexes[e];
			
			int j;
			for ( j=0 ; j<2 ; j++)
			{
				float sextent, textent;
				sextent = DotProduct (v->position, pTex->lightmapVecsLuxelsPerWorldUnits[0].AsVector3D()) + 
					pTex->lightmapVecsLuxelsPerWorldUnits[0][3] - pLighting->m_LightmapMins[0];
				textent = DotProduct (v->position, pTex->lightmapVecsLuxelsPerWorldUnits[1].AsVector3D()) + 
					pTex->lightmapVecsLuxelsPerWorldUnits[1][3] - pLighting->m_LightmapMins[1];

				if ( sextent > lightMaxs[ 0 ] )
				{
					lightMaxs[ 0 ] = sextent;
				}
				if ( textent > lightMaxs[ 1 ] )
				{
					lightMaxs[ 1 ] = textent;
				}
			}
		}
		if( ds > lightMaxs[0] || dt > lightMaxs[1] )
			return false;	
	}
	else
	{
		if( ds > pLighting->m_LightmapExtents[0] || dt > pLighting->m_LightmapExtents[1] )
			return false;	
	}

	// Store off the hit distance...
	state.m_HitFrac = f;

	// You heard the man!
	ComputeTextureCoordsAtIntersection( pTex, pt, state.m_pTextureS, state.m_pTextureT );

#ifdef USE_CONVARS
	if ( r_avglight.GetInt() )
#else
	if ( 1 )
#endif
	{
		// This is the faster path; it looks slightly different though
		ComputeLightmapColorFromAverage( pLighting, state.m_bUseLightStyles, c );
	}
	else
	{
		// Compute lightmap coords
		ComputeLightmapCoordsAtIntersection( pLighting, ds, dt, state.m_pLightmapS, state.m_pLightmapT );
		
		// Check out the value of the lightmap at the intersection point
		ComputeLightmapColor( surfID, (int)ds, (int)dt, state.m_bUseLightStyles, c );
	}

	return true;
}
Exemplo n.º 7
0
// Mark the surface as changed by the specified dlight (so its texture gets updated when 
// it comes time to render).
inline void R_MarkSurfaceDLight( SurfaceHandle_t surfID, msurfacelighting_t *pLighting, int bit)
{
	pLighting->m_nDLightFrame = r_framecount;
	pLighting->m_fDLightBits |= bit;
	MSurf_Flags( surfID ) |= SURFDRAW_HASDLIGHT;
}