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 ); } }
// returns surfID static SurfaceHandle_t R_LightVecDisplacementChain( LightVecState_t& state, bool bUseLightStyles, Vector& c ) { // test the ray against displacements SurfaceHandle_t surfID = SURFACE_HANDLE_INVALID; for ( int i = 0; i < state.m_LightTestDisps.Count(); i++ ) { float dist; Vector2D luv, tuv; IDispInfo *pDispInfo = state.m_LightTestDisps[i]; if (pDispInfo->TestRay( state.m_Ray, 0.0f, state.m_HitFrac, dist, &luv, &tuv )) { // It hit it, and at a point closer than the previously computed // nearest intersection point state.m_HitFrac = dist; surfID = pDispInfo->GetParent(); ComputeLightmapColor( surfID, (int)luv.x, (int)luv.y, bUseLightStyles, c ); if (state.m_pLightmapS && state.m_pLightmapT) { ComputeLightmapCoordsAtIntersection( SurfaceLighting(surfID), (int)luv.x, (int)luv.y, state.m_pLightmapS, state.m_pLightmapT ); } if (state.m_pTextureS && state.m_pTextureT) { *state.m_pTextureS = tuv.x; *state.m_pTextureT = tuv.y; } } } return surfID; }
// returns surfID static int R_LightVecDisplacementChain( LightVecState_t& state, bool bUseLightStyles, Vector& c ) { // test the ray against displacements int surfID = -1; IDispInfo *pDispInfo = state.m_LightTestChain.GetHead(); for( ; pDispInfo; pDispInfo = pDispInfo->GetNextInRayCastChain() ) { float dist; Vector2D luv, tuv; if (pDispInfo->TestRay( state.m_Ray, 0.0f, state.m_HitFrac, dist, &luv, &tuv )) { // It hit it, and at a point closer than the previously computed // nearest intersection point state.m_HitFrac = dist; surfID = pDispInfo->GetParent(); ComputeLightmapColor( surfID, (int)luv.x, (int)luv.y, bUseLightStyles, c ); if (state.m_pLightmapS && state.m_pLightmapT) { ComputeLightmapCoordsAtIntersection( SurfaceLighting(surfID), (int)luv.x, (int)luv.y, state.m_pLightmapS, state.m_pLightmapT ); } if (state.m_pTextureS && state.m_pTextureT) { *state.m_pTextureS = tuv.x; *state.m_pTextureT = tuv.y; } } } return surfID; }
//----------------------------------------------------------------------------- // 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; }
/* ============= R_MarkLights ============= */ void R_MarkLights (dlight_t *light, int bit, mnode_t *node) { cplane_t *splitplane; float dist; int i; if (node->contents >= 0) { // This is a leaf, so check displacement surfaces and leaf faces R_MarkLightsLeaf( light, bit, (mleaf_t*)node ); return; } splitplane = node->plane; dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; if (dist > light->radius) { R_MarkLights (light, bit, node->children[0]); return; } if (dist < -light->radius) { R_MarkLights (light, bit, node->children[1]); return; } // mark the polygons int surfID = node->firstsurface; for (i=0 ; i<node->numsurfaces ; i++, surfID++) { // 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; R_TryLightMarkSurface( light, pLighting, surfID, bit ); } R_MarkLights( light, bit, node->children[0] ); R_MarkLights( light, bit, node->children[1] ); }
//----------------------------------------------------------------------------- // Computes the lightmap color at a particular point //----------------------------------------------------------------------------- static void ComputeLightmapColor( SurfaceHandle_t surfID, int ds, int dt, bool bUseLightStyles, Vector& c ) { msurfacelighting_t *pLighting = SurfaceLighting( surfID ); ColorRGBExp32* pLightmap = pLighting->m_pSamples; if( !pLightmap ) { static int messagecount = 0; if ( ++messagecount < 10 ) { // Stop spamming. I heard you already!!! ConMsg( "hit surface has no samples\n" ); } return; } int smax = ( pLighting->m_LightmapExtents[0] ) + 1; int tmax = ( pLighting->m_LightmapExtents[1] ) + 1; int offset = smax * tmax; if ( SurfHasBumpedLightmaps( surfID ) ) { offset *= ( NUM_BUMP_VECTS + 1 ); } pLightmap += dt * smax + ds; int nMaxMaps = bUseLightStyles ? MAXLIGHTMAPS : 1; for (int maps = 0 ; maps < nMaxMaps && pLighting->m_nStyles[maps] != 255 ; ++maps) { float scale = LightStyleValue( pLighting->m_nStyles[maps] ); c[0] += TexLightToLinear( pLightmap->r, pLightmap->exponent ) * scale; c[1] += TexLightToLinear( pLightmap->g, pLightmap->exponent ) * scale; c[2] += TexLightToLinear( pLightmap->b, pLightmap->exponent ) * scale; // Check version 32 in source safe for some debugging crap pLightmap += offset; } }
//----------------------------------------------------------------------------- // 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; }