//----------------------------------------------- // Synapse Gaming - Lighting System // Copyright © Synapse Gaming 2003 // Written by John Kabus //----------------------------------------------- #include "lightingSystem/sgLighting.h" #include "lightingSystem/sgLightManager.h" #include "lightingSystem/sgLightingModel.h" #include "lightingSystem/sgMissionLightingFilter.h" #include "interior/interiorInstance.h" #include "terrain/terrData.h" #include "game/shadow.h" #include "lightingSystem/sgLightObject.h" #include "sim/netConnection.h" #include "editor/worldEditor.h" #include "platform/profiler.h" bool LightManager::sgLightingProperties[sgPropertyCount]; bool LightManager::sgUseSelfIlluminationColor = false; ColorF LightManager::sgSelfIlluminationColor(0.0f, 0.0f, 0.0f); bool LightManager::sgFilterZones = false; S32 LightManager::sgZones[2] = {-1, -1}; bool LightManager::sgDynamicParticleSystemLighting = true; bool LightManager::sgBlendedTerrainDynamicLighting = true; U32 LightManager::sgLightingProfileQuality = LightManager::lpqtProduction; bool LightManager::sgLightingProfileAllowShadows = true; LightInfo LightManager::sgDefaultLight; bool LightManager::sgDetailMaps = true; S32 LightManager::sgMaxBestLights = 10; bool LightManager::sgUseDynamicShadows = true; U32 LightManager::sgDynamicLightingOcclusionQuality = dlqtFourSample; U32 LightManager::sgDynamicShadowQuality = 0; bool LightManager::sgMultipleDynamicShadows = true; bool LightManager::sgInGUIEditor = false; bool sgRelightFilter::sgFilterRelight = false; bool sgRelightFilter::sgFilterRelightVisible = true; bool sgRelightFilter::sgFilterRelightByDistance = true; F32 sgRelightFilter::sgFilterRelightByDistanceRadius = 60; Point3F sgRelightFilter::sgFilterRelightByDistancePosition; U32 sgStatistics::sgInteriorLexelCount = 0; U32 sgStatistics::sgInteriorLexelTime = 0; U32 sgStatistics::sgInteriorLexelDiffuseCount = 0; U32 sgStatistics::sgInteriorObjectCount = 0; U32 sgStatistics::sgInteriorObjectIncludedCount = 0; U32 sgStatistics::sgInteriorObjectIlluminationCount = 0; U32 sgStatistics::sgInteriorSurfaceIncludedCount = 0; U32 sgStatistics::sgInteriorSurfaceIlluminationCount = 0; U32 sgStatistics::sgInteriorSurfaceIlluminatedCount = 0; U32 sgStatistics::sgInteriorSurfaceSmoothedCount = 0; U32 sgStatistics::sgInteriorSurfaceSmoothedLexelCount = 0; U32 sgStatistics::sgInteriorSurfaceSetupTime = 0; U32 sgStatistics::sgInteriorSurfaceSetupCount = 0; U32 sgStatistics::sgInteriorSurfaceMergeTime = 0; U32 sgStatistics::sgInteriorSurfaceMergeCount = 0; U32 sgStatistics::sgStaticMeshSurfaceOccluderCount = 0; U32 sgStatistics::sgTerrainLexelCount = 0; U32 sgStatistics::sgTerrainLexelTime = 0; sgInteriorDynamicLightingCache::sgCacheEntry sgInteriorDynamicLightingCache::sgCache; sgDTSDynamicLightingCache::sgCacheEntry sgDTSDynamicLightingCache::sgCache; LightInfo::LightInfo() { mType = Vector; mPos = Point3F(0.0f, 0.0f, 0.0f); mDirection = Point3F(0.0f, 0.0f, 1.0f); mColor = ColorF(0.0f, 0.0f, 0.0f); mAmbient = ColorF(0.0f, 0.0f, 0.0f); mRadius = 1; mScore = 0; sgSpotAngle = 90.0f; sgAssignedToTSObject = false; sgCastsShadows = true; sgDiffuseRestrictZone = false; sgAmbientRestrictZone = false; sgZone[0] = -1; sgZone[1] = -1; sgLocalAmbientAmount = 0.0f; sgSmoothSpotLight = false; sgDoubleSidedAmbient = false; sgAssignedToParticleSystem = false; sgLightingModelName = NULL; sgUseNormals = true; sgSpotPlane = PlaneF(0.0f, 0.0f, 0.0f, 0.0f); sgDTSLightingOcclusionAdjust = 1.0f; sgMoveSnapshotId = 0; sgTrackMoveSnapshot = false; sgLightingTransform.identity(); } bool LightInfo::sgIsInZone(S32 zone) { if((zone == sgZone[0]) || (zone ==sgZone[1])) return true; return false; } bool LightInfo::sgAllowDiffuseZoneLighting(S32 zone) { if(!sgDiffuseRestrictZone) return true; if(sgIsInZone(zone)) return true; return false; } void LightInfoList::sgRegisterLight(LightInfo *light) { if(!light) return; // just add the light, we'll try to scan for dupes later... push_back(light); } void LightInfoList::sgUnregisterLight(LightInfo *light) { // remove all of them... LightInfoList &list = *this; for(U32 i=0; i 2); } LightInfo *LightManager::sgGetSpecialLight(sgSpecialLightTypesEnum type) { if(sgSpecialLights[type]) return sgSpecialLights[type]; // return a default light... return &sgDefaultLight; } void LightManager::sgRegisterGlobalLight(LightInfo *light) { sgRegisteredGlobalLights.sgRegisterLight(light); } void LightManager::sgRegisterGlobalLights(bool staticlighting) { // make sure we're clean... sgUnregisterAllLights(); // ask all light objects to register themselves... SimSet *lightset = Sim::getLightSet(); for(SimObject **itr=lightset->begin(); itr!=lightset->end(); itr++) (*itr)->registerLights(this, staticlighting); } void LightManager::sgUnregisterAllLights() { sgRegisteredGlobalLights.clear(); sgRegisteredLocalLights.clear(); dMemset(&sgSpecialLights, 0, sizeof(sgSpecialLights)); } void LightManager::sgGetAllUnsortedLights(LightInfoList &list) { list.clear(); list.merge(sgRegisteredGlobalLights); list.merge(sgRegisteredLocalLights); // find dupes... dQsort(list.address(), list.size(), sizeof(LightInfo*), sgSortLightsByAddress); LightInfo *last = NULL; for(U32 i=0; igetNumCurrZones(); i++) { if(obj->getCurrZone(i) == 0) { outside = true; break; } } sgSetProperty(sgReceiveSunLightProp, obj->receiveSunLight); sgSetProperty(sgAdaptiveSelfIlluminationProp, obj->useAdaptiveSelfIllumination); sgSetProperty(sgCustomAmbientLightingProp, obj->useCustomAmbientLighting); sgSetProperty(sgCustomAmbientForSelfIlluminationProp, obj->customAmbientForSelfIllumination); ColorF ambientColor; ColorF selfillum = obj->customAmbientLighting * 0.5f; LightInfo *sun = sgGetSpecialLight(sgSunLightType); if(obj->getLightingAmbientColor(&ambientColor)) { const F32 directionalFactor = 0.5f; const F32 ambientFactor = 0.5f; dMemset(&obj->mLightingInfo.smAmbientLight, 0, sizeof(obj->mLightingInfo.smAmbientLight)); LightInfo &light = obj->mLightingInfo.smAmbientLight; light.mType = LightInfo::Ambient; light.mDirection = VectorF(0.0f, 0.0f, -1.0f); light.sgCastsShadows = sun->sgCastsShadows; // players, vehicles, ... if(obj->overrideOptions) { if(outside) { light.mType = LightInfo::Vector; light.mDirection = sun->mDirection; } //else //{ light.mColor = ambientColor * directionalFactor; light.mAmbient = ambientColor * ambientFactor; //} }// beyond here are the static dts options... else if(sgAllowDiffuseCustomAmbient()) { light.mColor = obj->customAmbientLighting * 0.5f; light.mAmbient = obj->customAmbientLighting * 0.5f; } else if(sgAllowReceiveSunLight() && sun) { light.mType = LightInfo::Vector; if(outside) light.mDirection = sun->mDirection; if(obj->receiveLMLighting) light.mColor = ambientColor * 0.8f; else light.mColor = sun->mColor; light.mAmbient = sun->mAmbient; } else if(obj->receiveLMLighting) { light.mColor = ambientColor * directionalFactor; light.mAmbient = ambientColor * ambientFactor; } if(sgAllowCollectSelfIlluminationColor()) { selfillum = light.mAmbient + light.mColor; selfillum.clamp(); } light.mPos = light.mDirection * -10000.0f; sgRegisterLocalLight(&obj->mLightingInfo.smAmbientLight); } // install assigned baked lights from simgroup... // step one get the objects... U32 i; NetConnection *connection = NetConnection::getConnectionToServer(); for(i=0; ilightIds.size(); i++) { SimObject *sim = connection->resolveGhost(obj->lightIds[i]); if(!sim) continue; sgLightObject *light = dynamic_cast(sim); if(!light) continue; sgLightObjectData *data = static_cast(light->getDataBlock()); if((data) && (data->sgStatic) && (data->mLightOn) && (light->mEnable)) { light->mLight.sgAssignedToTSObject = true; sgRegisterLocalLight(&light->mLight); } } // step three install dynamic lights... sgUseSelfIlluminationColor = sgGetProperty(sgAdaptiveSelfIlluminationProp); if(sgUseSelfIlluminationColor) sgSelfIlluminationColor = selfillum; sgSetupZoneLighting(true, obj); sgFindBestLights(obj, obj->getRenderWorldBox(), sgMaxBestLights, Point3F(0.0f, 0.0f, 0.0f), false); sgInstallLights(); PROFILE_END(); } void LightManager::sgSetupLights(SceneObject *obj, const Point3F &camerapos, const Point3F &cameradir, F32 viewdist, S32 maxlights) { sgResetLights(); sgSetupZoneLighting(true, obj); Box3F box; box.max = camerapos + Point3F(viewdist, viewdist, viewdist); box.min = camerapos - Point3F(viewdist, viewdist, viewdist); sgFindBestLights(obj, box, maxlights, cameradir, true); } void LightManager::sgSetupLights(SceneObject *obj, const Box3F &box, S32 maxlights) { sgResetLights(); sgSetupZoneLighting(true, obj); sgFindBestLights(obj, box, maxlights, Point3F(0.0f, 0.0f, 0.0f), true); } void LightManager::sgInstallLights() { U32 count = getMin(U32(sgBestLights.size()), U32(8)); glEnable(GL_LIGHTING); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (const F32 *)ColorF(0.0f, 0.0f, 0.0f, 0.0f)); for(U32 i=0; isgLightingModelName); lightingmodel.sgSetState(light); U32 gllight = GL_LIGHT0 + i; glEnable(gllight); lightingmodel.sgLightingGL(gllight); lightingmodel.sgResetState(); } } void LightManager::sgResetLights() { sgSetupZoneLighting(false, NULL); sgRegisteredLocalLights.clear(); sgBestLights.clear(); // ok these seem weird, but dts rendering changes them... glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (const F32 *)ColorF(0.0f, 0.0f, 0.0f, 0.0f)); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (const F32 *)ColorF(1.0f, 1.0f, 1.0f, 1.0f)); for(S32 i=7; i>=0; i--) glDisable(GL_LIGHT0 + i); glDisable(GL_LIGHTING); } void LightManager::sgFindBestLights(SceneObject *obj, const Box3F &box, S32 maxlights, const Point3F &viewdi, bool camerabased) { sgBestLights.clear(); // gets them all and removes any dupes... sgGetAllUnsortedLights(sgBestLights); SphereF sphere; box.getCenter(&sphere.center); sphere.radius = Point3F(box.max - sphere.center).len(); for(U32 i=0; imScore > 0) && (i < maxlights)) continue; sgBestLights.setSize(i); break; } } void LightManager::sgScoreLight(LightInfo *light, SceneObject *obj, const Box3F &box, const SphereF &sphere, bool camerabased) { if(sgFilterZones && light->sgDiffuseRestrictZone) { bool allowdiffuse = false; if(sgZones[0] > -1) { if(light->sgAllowDiffuseZoneLighting(sgZones[0])) allowdiffuse = true; else if(sgZones[1] > -1) { if(light->sgAllowDiffuseZoneLighting(sgZones[1])) allowdiffuse = true; } } if(!allowdiffuse) { light->mScore = 0; return; } } F32 distintensity = 1.0f; F32 colorintensity = 1.0f; F32 weight = SG_LIGHTMANAGER_DYNAMIC_PRIORITY; if(camerabased) { sgLightingModel &model = sgLightingModelManager::sgGetLightingModel(light->sgLightingModelName); model.sgSetState(light); F32 maxrad = model.sgGetMaxRadius(true); model.sgResetState(); Point3F vect = sphere.center - light->mPos; F32 dist = vect.len(); F32 distlightview = sphere.radius + maxrad; if(distlightview <= 0.0f) distintensity = 0.0f; else { distintensity = 1.0f - (dist / distlightview); distintensity = mClampF(distintensity, 0.0f, 1.0f); } } else { // side test... if((light->mType == LightInfo::Spot) || (light->mType == LightInfo::SGStaticSpot)) { bool anyfront = false; F32 x, y, z; for(U32 i=0; i<8; i++) { if(i & 0x1) x = box.max.x; else x = box.min.x; if(i & 0x2) y = box.max.y; else y = box.min.y; if(i & 0x4) z = box.max.z; else z = box.min.z; if(light->sgSpotPlane.whichSide(Point3F(x, y, z)) == PlaneF::Back) continue; anyfront = true; break; } if(!anyfront) { light->mScore = 0; return; } } if((light->mType == LightInfo::Vector) || (light->mType == LightInfo::Ambient)) { colorintensity = (light->mColor.red + light->mAmbient.red) * 0.346f + (light->mColor.green + light->mAmbient.green) * 0.588f + (light->mColor.blue + light->mAmbient.blue) * 0.070f; distintensity = 1; weight = SG_LIGHTMANAGER_SUN_PRIORITY; } else { if(light->sgAssignedToParticleSystem) { colorintensity = SG_PARTICLESYSTEMLIGHT_FIXED_INTENSITY; } else { colorintensity = (light->mColor.red * 0.3333f) + (light->mColor.green * 0.3333f) + (light->mColor.blue * 0.3333f); } sgLightingModel &model = sgLightingModelManager::sgGetLightingModel(light->sgLightingModelName); model.sgSetState(light); distintensity = model.sgScoreLight(light, sphere); model.sgResetState(); if(light->sgAssignedToTSObject) weight = SG_LIGHTMANAGER_ASSIGNED_PRIORITY; else if((light->mType == LightInfo::SGStaticPoint) || (light->mType == LightInfo::SGStaticSpot)) weight = SG_LIGHTMANAGER_STATIC_PRIORITY; if(((light->mType == LightInfo::SGStaticPoint) || (light->mType == LightInfo::SGStaticSpot)) && light->sgCastsShadows && (distintensity > 0.0f) && (sgDynamicLightingOcclusionQuality < dlqtNoShadows) && obj->useLightingOcclusion) { sgDTSDynamicLightingCache::sgCacheEntry *entry = sgDTSDynamicLightingCache::sgFindCacheEntry((void *)obj, light); if((!entry->info.sgAlreadyProcessed) || (entry->info.sgLastObjectMoveSnapshotId != obj->moveSnapshotId) || (entry->info.sgLastLightMoveSnapshotId != light->sgMoveSnapshotId)) { entry->info.sgAlreadyProcessed = true; entry->info.sgLastObjectMoveSnapshotId = obj->moveSnapshotId; entry->info.sgLastLightMoveSnapshotId = light->sgMoveSnapshotId; U32 shadowcalcs = 0; F32 shadowamount = 0.0f; F32 x, y, z; RayInfo info; obj->disableCollision(); U32 samples = (sgDynamicLightingOcclusionQuality < dlqtCenterSample) ? 7 : 1; for(U32 a=0; amPos; if((sgDynamicLightingOcclusionQuality > dlqtSevenSample) && (mDot(planenorm, lightdir) > 0.0f)) continue; shadowcalcs++; if(gClientContainer.castRay(light->mPos, pos, ShadowCasterObjectType, &info)) shadowamount += 1.0f; } obj->enableCollision(); entry->info.sgCachedLightingMultiplier = 1.0f - (shadowamount / ((F32)shadowcalcs)); } distintensity *= entry->info.sgCachedLightingMultiplier; light->sgDTSLightingOcclusionAdjust = entry->info.sgCachedLightingMultiplier; } else light->sgDTSLightingOcclusionAdjust = 1.0f; } } F32 intensity = colorintensity * distintensity; if(intensity < SG_MIN_LEXEL_INTENSITY) intensity = 0.0f; light->mScore = S32(intensity * weight * 1024.0f); } void LightManager::sgInit() { for(U32 i=0; i= 4)); } void LightManager::sgGetFilteredLightColor(ColorF &color, ColorF &ambient, S32 objectzone) { sgMissionLightingFilter *filterbasezone = NULL; sgMissionLightingFilter *filtercurrentzone = NULL; SimSet *filters = Sim::getsgMissionLightingFilterSet(); for(SimObject ** itr = filters->begin(); itr != filters->end(); itr++) { sgMissionLightingFilter *filter = dynamic_cast(*itr); if(!filter) continue; S32 zone = filter->getCurrZone(0); if(zone == 0) filterbasezone = filter; if(zone == objectzone) { filtercurrentzone = filter; break; } } if(filtercurrentzone) filterbasezone = filtercurrentzone; if(!filterbasezone) return; sgMissionLightingFilterData *datablock = (sgMissionLightingFilterData *)filterbasezone->getDataBlock(); if(!datablock) return; ColorF composite = datablock->sgLightingFilter * datablock->sgLightingIntensity; color *= composite; color.clamp(); ambient *= composite; ambient.clamp(); if(!datablock->sgCinematicFilter) return; // must use the lighting filter intensity // to lock the reference value relative // to the lighting intensity composite = datablock->sgCinematicFilterReferenceColor * datablock->sgCinematicFilterReferenceIntensity * datablock->sgLightingIntensity; F32 intensity = color.red + color.green + color.blue + ambient.red + ambient.green + ambient.blue; F32 intensityref = composite.red + composite.green + composite.blue; intensity -= intensityref; // blue is too intense... if(intensity > 0.0f) intensity *= 0.25f; F32 redoffset = 1.0f - ((intensity) * 0.1f * datablock->sgCinematicFilterAmount); F32 blueoffset = 1.0f + ((intensity) * 0.1f * datablock->sgCinematicFilterAmount); F32 greenoffset = 1.0f - ((1.0f - getMin(redoffset, blueoffset)) * 0.5f); ColorF multiplier = ColorF(redoffset, greenoffset, blueoffset); color *= multiplier; color.clamp(); ambient *= multiplier; ambient.clamp(); } void LightManager::sgSetupZoneLighting(bool enable, SimObject *sobj) { sgFilterZones = false; // these must be -2... sgZones[0] = -2; sgZones[1] = -2; if(!enable) return; if(dynamic_cast(sobj)) return; SceneObject *obj = dynamic_cast(sobj); if(!obj) return; sgFilterZones = true; U32 count = getMin(obj->getNumCurrZones(), U32(2)); for(U32 i=0; igetCurrZone(i); } } void LightManager::sgSetupExposureRendering() { if(!dglDoesSupportARBMultitexture()) return; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, SG_LIGHTING_OVERBRIGHT_AMOUNT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); } void LightManager::sgResetExposureRendering() { if(!dglDoesSupportARBMultitexture()) return; glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, SG_LIGHTING_NORMAL_AMOUNT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } // adds proper support for self-illumination... void LightManager::sgSetAmbientSelfIllumination(LightInfo *lightinfo, F32 *lightColor, F32 *ambientColor) { //LightInfo *lightInfo = (LightInfo *)lightinfo; if(sgAllowCollectSelfIlluminationColor()) { if(lightinfo->mType == LightInfo::Vector) sgSelfIlluminationColor = ColorF(lightColor[0], lightColor[1], lightColor[2]); else sgSelfIlluminationColor = ColorF(ambientColor[0], ambientColor[1], ambientColor[2]); } } void sgStatistics::sgClear() { sgInteriorLexelCount = 0; sgInteriorLexelTime = 0; sgInteriorLexelDiffuseCount = 0; sgInteriorObjectCount = 0; sgInteriorObjectIncludedCount = 0; sgInteriorObjectIlluminationCount = 0; sgInteriorSurfaceIncludedCount = 0; sgInteriorSurfaceIlluminationCount = 0; sgInteriorSurfaceIlluminatedCount = 0; sgInteriorSurfaceSmoothedCount = 0; sgInteriorSurfaceSmoothedLexelCount = 0; sgInteriorSurfaceSetupTime = 0; sgInteriorSurfaceSetupCount = 0; sgInteriorSurfaceMergeTime = 0; sgInteriorSurfaceMergeCount = 0; sgStaticMeshSurfaceOccluderCount = 0; sgTerrainLexelCount = 0; sgTerrainLexelTime = 0; } void sgStatistics::sgPrint() { Con::printf(""); Con::printf(" Lighting Pack lighting system stats:"); Con::printf(" Interior Lexel Count: %d", sgInteriorLexelCount); Con::printf(" Interior Lexel Time (ms): %f", F32(sgInteriorLexelTime) / getMax(1.0f, F32(sgInteriorLexelCount))); Con::printf(" Interior Lexel Time Total (ms): %d", sgInteriorLexelTime); Con::printf(" Interior Lexel Diffuse Count: %d", sgInteriorLexelDiffuseCount); Con::printf(" Interior Object Count: %d", sgInteriorObjectCount); Con::printf(" Interior Object Included Count: %d", sgInteriorObjectIncludedCount); Con::printf(" Interior Object Illumination Count: %d", sgInteriorObjectIlluminationCount); Con::printf(" Interior Surface Included Count: %d", sgInteriorSurfaceIncludedCount); Con::printf(" Interior Surface Illumination Count: %d", sgInteriorSurfaceIlluminationCount); Con::printf(" Interior Surface Illuminated Count: %d", sgInteriorSurfaceIlluminatedCount); Con::printf(" Interior Surface Smoothed Count: %d", sgInteriorSurfaceSmoothedCount); Con::printf(" Interior Surface Smoothed Lexel Count: %d", sgInteriorSurfaceSmoothedLexelCount); Con::printf(" Interior Surface Setup Count: %d", sgInteriorSurfaceSetupCount); Con::printf(" Interior Surface Setup Time Total (ms): %d", sgInteriorSurfaceSetupTime); Con::printf(" Interior Surface Merge Count: %d", sgInteriorSurfaceMergeCount); Con::printf(" Interior Surface Merge Time Total (ms): %d", sgInteriorSurfaceMergeTime); Con::printf(" Static Mesh Surface Occluder Count: %d", sgStaticMeshSurfaceOccluderCount); Con::printf(" Terrain Lexel Count: %d", sgTerrainLexelCount); Con::printf(" Terrain Lexel Time (ms): %f", F32(sgTerrainLexelTime) / getMax(1.0f, F32(sgTerrainLexelCount))); Con::printf(" Terrain Lexel Time Total (ms): %d", sgTerrainLexelTime); } S32 QSORT_CALLBACK LightManager::sgSortLightsByAddress(const void* a, const void* b) { return ((*(LightInfo**)b) - (*(LightInfo**)a)); } S32 QSORT_CALLBACK LightManager::sgSortLightsByScore(const void* a, const void* b) { return((*(LightInfo**)b)->mScore - (*(LightInfo**)a)->mScore); } void sgRelightFilter::sgInit() { Con::addVariable("SceneLighting::sgFilterRelight", TypeBool, &sgRelightFilter::sgFilterRelight); Con::addVariable("SceneLighting::sgFilterRelightVisible", TypeBool, &sgRelightFilter::sgFilterRelightVisible); Con::addVariable("SceneLighting::sgFilterRelightByDistance", TypeBool, &sgRelightFilter::sgFilterRelightByDistance); Con::addVariable("SceneLighting::sgFilterRelightByDistanceRadius", TypeF32, &sgRelightFilter::sgFilterRelightByDistanceRadius); Con::addVariable("SceneLighting::sgFilterRelightByDistancePosition", TypePoint3F, &sgRelightFilter::sgFilterRelightByDistancePosition); } bool sgRelightFilter::sgAllowLighting(const Box3F &box, bool forcefilter) { if((sgRelightFilter::sgFilterRelight && sgRelightFilter::sgFilterRelightByDistance) || forcefilter) { if(!sgRelightFilter::sgFilterRelightVisible) return false; Point3F min = EditTSCtrl::smCamPos; min.x = min.x - sgRelightFilter::sgFilterRelightByDistanceRadius; min.y = min.y - sgRelightFilter::sgFilterRelightByDistanceRadius; min.z = min.z - sgRelightFilter::sgFilterRelightByDistanceRadius; Point3F max = EditTSCtrl::smCamPos; max.x = max.x + sgRelightFilter::sgFilterRelightByDistanceRadius; max.y = max.y + sgRelightFilter::sgFilterRelightByDistanceRadius; max.z = max.z + sgRelightFilter::sgFilterRelightByDistanceRadius; Box3F lightbox(min, max); if(!box.isOverlapped(lightbox)) return false; } return true; } void sgRelightFilter::sgRenderAllowedObjects(void *editor) { U32 i; WorldEditor *worldeditor = (WorldEditor *)editor; Vector objects; gServerContainer.findObjects(InteriorObjectType, sgFindObjectsCallback, &objects); const ColorI color(255, 0, 255); for(i = 0; i < objects.size(); i++) { SceneObject * obj = objects[i]; if(worldeditor->objClassIgnored(obj)) continue; if(!sgRelightFilter::sgAllowLighting(obj->getWorldBox(), true)) continue; worldeditor->renderObjectBox(obj, color); } }