//----------------------------------------------------------------------------- // 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; }
//----------------------------------------------------------------------------- // A method to get the material color + texture coordinate //----------------------------------------------------------------------------- IMaterial* BrushModel_GetLightingAndMaterial( const Vector &start, const Vector &end, Vector &diffuseLightColor, Vector &baseColor) { float textureS, textureT; IMaterial *material; int surfID = R_LightVec( start, end, true, diffuseLightColor, &textureS, &textureT ); if( !IS_SURF_VALID( surfID ) || !MSurf_TexInfo( surfID ) ) { // Con_Printf( "didn't hit anything\n" ); return 0; } else { material = MSurf_TexInfo( surfID )->material; material->GetLowResColorSample( textureS, textureT, baseColor.Base() ); // Con_Printf( "%s: diff: %f %f %f base: %f %f %f\n", material->GetName(), diffuseLightColor[0], diffuseLightColor[1], diffuseLightColor[2], baseColor[0], baseColor[1], baseColor[2] ); return material; } }
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; }
//----------------------------------------------------------------------------- // 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; }