llwlparammanager.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llwlparammanager.h"
00035 
00036 #include "pipeline.h"
00037 #include "llsky.h"
00038 
00039 #include "llsliderctrl.h"
00040 #include "llspinctrl.h"
00041 #include "llcheckboxctrl.h"
00042 #include "lluictrlfactory.h"
00043 #include "llviewercamera.h"
00044 #include "llcombobox.h"
00045 #include "lllineeditor.h"
00046 #include "llsdserialize.h"
00047 
00048 #include "v4math.h"
00049 #include "llviewerdisplay.h"
00050 #include "llviewercontrol.h"
00051 #include "llviewerwindow.h"
00052 #include "lldrawpoolwater.h"
00053 #include "llagent.h"
00054 #include "llviewerregion.h"
00055 
00056 #include "llwlparamset.h"
00057 #include "llpostprocess.h"
00058 #include "llfloaterwindlight.h"
00059 #include "llfloaterdaycycle.h"
00060 #include "llfloaterenvsettings.h"
00061 
00062 #include "curl/curl.h"
00063 
00064 LLWLParamManager * LLWLParamManager::sInstance = NULL;
00065 
00066 LLWLParamManager::LLWLParamManager() :
00067 
00068         //set the defaults for the controls
00069         // index is from sWLUniforms in pipeline.cpp line 979
00070 
00072         mSunDeltaYaw(180.0f),
00073         mSceneLightStrength(2.0f),
00074         mWLGamma(1.0f, "gamma"),
00075 
00076         mBlueHorizon(0.25f, 0.25f, 1.0f, 1.0f, "blue_horizon", "WLBlueHorizon"),
00077         mHazeDensity(1.0f, 1.0f, 1.0f, 0.5f, "haze_density"),
00078         mBlueDensity(0.25f, 0.25f, 0.25f, 1.0f, "blue_density", "WLBlueDensity"),
00079         mDensityMult(1.0f, "density_multiplier", 1000),
00080         mHazeHorizon(1.0f, 1.0f, 1.0f, 0.5f, "haze_horizon"),
00081         mMaxAlt(4000.0f, "max_y"),
00082 
00083         // Lighting
00084         mLightnorm(0.f, 0.707f, -0.707f, 1.f, "lightnorm"),
00085         mSunlight(0.5f, 0.5f, 0.5f, 1.0f, "sunlight_color", "WLSunlight"),
00086         mAmbient(0.5f, 0.75f, 1.0f, 1.19f, "ambient", "WLAmbient"),
00087         mGlow(18.0f, 0.0f, -0.01f, 1.0f, "glow"),
00088 
00089         // Clouds
00090         mCloudColor(0.5f, 0.5f, 0.5f, 1.0f, "cloud_color", "WLCloudColor"),
00091         mCloudMain(0.5f, 0.5f, 0.125f, 1.0f, "cloud_pos_density1"),
00092         mCloudCoverage(0.0f, "cloud_shadow"),
00093         mCloudDetail(0.0f, 0.0f, 0.0f, 1.0f, "cloud_pos_density2"),
00094         mDistanceMult(1.0f, "distance_multiplier"),
00095         mCloudScale(0.42f, "cloud_scale"),
00096 
00097         // sky dome
00098         mDomeOffset(0.96f),
00099         mDomeRadius(15000.f)
00100 {
00101 }
00102 
00103 LLWLParamManager::~LLWLParamManager()
00104 {
00105 }
00106 
00107 void LLWLParamManager::loadPresets(const LLString& file_name)
00108 {
00109         // if fileName exists, use legacy loading form the big file, otherwise, search the sky 
00110         // directory, and add the list
00111         if(file_name != "") 
00112         {
00113                 LLString path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", file_name));
00114                 LL_INFOS2("AppInit", "Shaders") << "Loading WindLight settings from " << path_name << LL_ENDL;
00115 
00116                 llifstream presetsXML(path_name.c_str());
00117         
00118                 if (presetsXML)
00119                 {
00120                         LLSD paramsData(LLSD::emptyMap());
00121 
00122                         LLPointer<LLSDParser> parser = new LLSDXMLParser();
00123 
00124                         parser->parse(presetsXML, paramsData, LLSDSerialize::SIZE_UNLIMITED);
00125 
00126                         LLSD::map_const_iterator endParams = paramsData.endMap();
00127                         for(LLSD::map_const_iterator curParams = paramsData.beginMap();
00128                                 curParams != endParams;
00129                                 ++curParams)
00130                         {
00131                                 addParamSet(curParams->first, curParams->second);
00132                         }
00133                 }
00134         }
00135         
00136         // otherwise, search the sky directory and find things there
00137         else
00138         {
00139                 LLString path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));
00140                 LL_INFOS2("AppInit", "Shaders") << "Loading WindLight settings from " << path_name << LL_ENDL;
00141         
00142                 //mParamList.clear();
00143                 
00144                 bool found = true;                      
00145                 while(found) 
00146                 {
00147                         std::string name;
00148                         found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
00149 
00150                         LL_DEBUGS2("AppInit", "Shaders") << "name: " << name << LL_ENDL;
00151                         
00152                         // if we have one
00153                         if(found) 
00154                         {
00155                                 // bugfix for SL-46920: preventing filenames that break stuff.
00156                                 char * curl_str = curl_unescape(name.c_str(), name.size());
00157                                 std::string unescaped_name(curl_str);
00158                                 curl_free(curl_str);
00159                                 curl_str = NULL;
00160 
00161                                 // not much error checking here since we're getting rid of this
00162                                 std::string sky_name = unescaped_name.substr(0, unescaped_name.size() - 4);
00163                         
00164                                 LLString cur_path(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", name));
00165                                 LL_DEBUGS2("AppInit", "Shaders") << "Loading sky from " << cur_path << LL_ENDL;
00166                                 
00167                                 std::ifstream sky_xml(cur_path.c_str());
00168                                 if (sky_xml)
00169                                 {
00170                                         LLSD sky_data(LLSD::emptyMap());
00171                                         LLPointer<LLSDParser> parser = new LLSDXMLParser();
00172                                         parser->parse(sky_xml, sky_data, LLSDSerialize::SIZE_UNLIMITED);
00173 
00174                                         addParamSet(sky_name, sky_data);
00175                                 }
00176                         }
00177                 }
00178         }
00179 }
00180 
00181 void LLWLParamManager::savePresets(const LLString & fileName)
00182 {
00183         LLSD paramsData(LLSD::emptyMap());
00184         
00185         LLString pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", fileName));
00186 
00187         for(std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.begin();
00188                 mIt != mParamList.end();
00189                 ++mIt) 
00190         {
00191                 paramsData[mIt->first] = mIt->second.getAll();
00192         }
00193 
00194         std::ofstream presetsXML(pathName.c_str());
00195 
00196         LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
00197 
00198         formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
00199 
00200         presetsXML.close();
00201 }
00202 
00203 void LLWLParamManager::loadPreset(const LLString & name)
00204 {
00205         // bugfix for SL-46920: preventing filenames that break stuff.
00206         char * curl_str = curl_escape(name.c_str(), name.size());
00207         std::string escaped_filename(curl_str);
00208         curl_free(curl_str);
00209         curl_str = NULL;
00210 
00211         escaped_filename += ".xml";
00212 
00213         std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename));
00214         llinfos << "Loading WindLight sky setting from " << pathName << llendl;
00215 
00216         std::ifstream presetsXML(pathName.c_str());
00217 
00218         if (presetsXML)
00219         {
00220                 LLSD paramsData(LLSD::emptyMap());
00221 
00222                 LLPointer<LLSDParser> parser = new LLSDXMLParser();
00223 
00224                 parser->parse(presetsXML, paramsData, LLSDSerialize::SIZE_UNLIMITED);
00225 
00226                 std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
00227                 if(mIt == mParamList.end())
00228                 {
00229                         addParamSet(name, paramsData);
00230                 }
00231                 else 
00232                 {
00233                         setParamSet(name, paramsData);
00234                 }
00235         } 
00236         else 
00237         {
00238                 llwarns << "Can't find " << name << llendl;
00239                 return;
00240         }
00241 
00242         getParamSet(name, mCurParams);
00243 
00244         propagateParameters();
00245 }
00246 
00247 void LLWLParamManager::savePreset(const LLString & name)
00248 {
00249         // bugfix for SL-46920: preventing filenames that break stuff.
00250         char * curl_str = curl_escape(name.c_str(), name.size());
00251         std::string escaped_filename(curl_str);
00252         curl_free(curl_str);
00253         curl_str = NULL;
00254 
00255         escaped_filename += ".xml";
00256 
00257         // make an empty llsd
00258         LLSD paramsData(LLSD::emptyMap());
00259         std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename));
00260 
00261         // fill it with LLSD windlight params
00262         paramsData = mParamList[name].getAll();
00263 
00264         // write to file
00265         std::ofstream presetsXML(pathName.c_str());
00266         LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
00267         formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
00268         presetsXML.close();
00269 
00270         propagateParameters();
00271 }
00272 
00273 void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)
00274 {
00275         if (gPipeline.canUseWindLightShaders())
00276         {
00277                 mCurParams.update(shader);
00278         }
00279 
00280         if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)
00281         {
00282                 shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, mRotatedLightDir.mV);
00283                 shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
00284         } 
00285 
00286         else if (shader->mShaderGroup == LLGLSLShader::SG_SKY)
00287         {
00288                 shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, mClampedLightDir.mV);
00289         }
00290 
00291         shader->uniform1f("scene_light_strength", mSceneLightStrength);
00292         
00293 }
00294 
00295 void LLWLParamManager::propagateParameters(void)
00296 {
00297         LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
00298         
00299         LLVector4 sunDir;
00300         LLVector4 moonDir;
00301 
00302         // set the sun direction from SunAngle and EastAngle
00303         F32 sinTheta = sin(mCurParams.getEastAngle());
00304         F32 cosTheta = cos(mCurParams.getEastAngle());
00305 
00306         F32 sinPhi = sin(mCurParams.getSunAngle());
00307         F32 cosPhi = cos(mCurParams.getSunAngle());
00308 
00309         sunDir.mV[0] = -sinTheta * cosPhi;
00310         sunDir.mV[1] = sinPhi;
00311         sunDir.mV[2] = cosTheta * cosPhi;
00312         sunDir.mV[3] = 0;
00313 
00314         moonDir = -sunDir;
00315 
00316         // is the normal from the sun or the moon
00317         if(sunDir.mV[1] >= 0)
00318         {
00319                 mLightDir = sunDir;
00320         }
00321         else if(sunDir.mV[1] < 0 && sunDir.mV[1] > NIGHTTIME_ELEVATION_COS)
00322         {
00323                 // clamp v1 to 0 so sun never points up and causes weirdness on some machines
00324                 LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]);
00325                 vec.mV[1] = 0;
00326                 vec.normVec();
00327                 mLightDir = LLVector4(vec, 0.f);
00328         }
00329         else
00330         {
00331                 mLightDir = moonDir;
00332         }
00333 
00334         // calculate the clamp lightnorm for sky (to prevent ugly banding in sky
00335         // when haze goes below the horizon
00336         mClampedLightDir = sunDir;
00337 
00338         if (mClampedLightDir.mV[1] < -0.1f)
00339         {
00340                 mClampedLightDir.mV[1] = -0.1f;
00341         }
00342 
00343         mCurParams.set("lightnorm", mLightDir);
00344 
00345         // bind the variables for all shaders only if we're using WindLight
00346         LLShaderMgr::shader_iter shaders_iter, end_shaders;
00347         end_shaders = LLShaderMgr::endShaders();
00348         for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter) 
00349         {
00350                 if (shaders_iter->mProgramObject != 0
00351                         && (gPipeline.canUseWindLightShaders()
00352                                 || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
00353                 {
00354                         shaders_iter->mUniformsDirty = TRUE;
00355                 }
00356         }
00357 
00358         // get the cfr version of the sun's direction
00359         LLVector3 cfrSunDir(sunDir.mV[2], sunDir.mV[0], sunDir.mV[1]);
00360 
00361         // set direction and don't allow overriding
00362         gSky.setSunDirection(cfrSunDir, LLVector3(0,0,0));
00363         gSky.setOverrideSun(TRUE);
00364 }
00365 
00366 void LLWLParamManager::update(LLViewerCamera * cam)
00367 {
00368         LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
00369         
00370         // update clouds, sun, and general
00371         mCurParams.updateCloudScrolling();
00372         
00373         // update only if running
00374         if(mAnimator.mIsRunning) 
00375         {
00376                 mAnimator.update(mCurParams);
00377         }
00378 
00379         // update the shaders and the menu
00380         propagateParameters();
00381         
00382         // sync menus if they exist
00383         if(LLFloaterWindLight::isOpen()) 
00384         {
00385                 LLFloaterWindLight::instance()->syncMenu();
00386         }
00387         if(LLFloaterDayCycle::isOpen()) 
00388         {
00389                 LLFloaterDayCycle::instance()->syncMenu();
00390         }
00391         if(LLFloaterEnvSettings::isOpen()) 
00392         {
00393                 LLFloaterEnvSettings::instance()->syncMenu();
00394         }
00395 
00396         F32 camYaw = cam->getYaw();
00397 
00398         stop_glerror();
00399 
00400         // *TODO: potential optimization - this block may only need to be
00401         // executed some of the time.  For example for water shaders only.
00402         {
00403                 F32 camYawDelta = mSunDeltaYaw * DEG_TO_RAD;
00404                 
00405                 LLVector3 lightNorm3(mLightDir);        
00406                 lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f));
00407                 mRotatedLightDir = LLVector4(lightNorm3, 0.f);
00408 
00409                 LLShaderMgr::shader_iter shaders_iter, end_shaders;
00410                 end_shaders = LLShaderMgr::endShaders();
00411                 for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
00412                 {
00413                         if (shaders_iter->mProgramObject != 0
00414                                 && (gPipeline.canUseWindLightShaders()
00415                                 || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
00416                         {
00417                                 shaders_iter->mUniformsDirty = TRUE;
00418                         }
00419                 }
00420         }
00421 }
00422 
00423 // static
00424 void LLWLParamManager::initClass(void)
00425 {
00426         instance();
00427 }
00428 
00429 // static
00430 void LLWLParamManager::cleanupClass()
00431 {
00432         delete sInstance;
00433         sInstance = NULL;
00434 }
00435 
00436 void LLWLParamManager::resetAnimator(F32 curTime, bool run)
00437 {
00438         mAnimator.setTrack(mDay.mTimeMap, mDay.mDayRate, 
00439                 curTime, run);
00440 
00441         return;
00442 }
00443 bool LLWLParamManager::addParamSet(const std::string& name, LLWLParamSet& param)
00444 {
00445         // add a new one if not one there already
00446         std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
00447         if(mIt == mParamList.end()) 
00448         {       
00449                 mParamList[name] = param;
00450                 return true;
00451         }
00452 
00453         return false;
00454 }
00455 
00456 BOOL LLWLParamManager::addParamSet(const std::string& name, LLSD const & param)
00457 {
00458         // add a new one if not one there already
00459         std::map<std::string, LLWLParamSet>::const_iterator finder = mParamList.find(name);
00460         if(finder == mParamList.end())
00461         {
00462                 mParamList[name].setAll(param);
00463                 return TRUE;
00464         }
00465         else
00466         {
00467                 return FALSE;
00468         }
00469 }
00470 
00471 bool LLWLParamManager::getParamSet(const std::string& name, LLWLParamSet& param)
00472 {
00473         // find it and set it
00474         std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
00475         if(mIt != mParamList.end()) 
00476         {
00477                 param = mParamList[name];
00478                 param.mName = name;
00479                 return true;
00480         }
00481 
00482         return false;
00483 }
00484 
00485 bool LLWLParamManager::setParamSet(const std::string& name, LLWLParamSet& param)
00486 {
00487         mParamList[name] = param;
00488 
00489         return true;
00490 }
00491 
00492 bool LLWLParamManager::setParamSet(const std::string& name, const LLSD & param)
00493 {
00494         // quick, non robust (we won't be working with files, but assets) check
00495         if(!param.isMap()) 
00496         {
00497                 return false;
00498         }
00499         
00500         mParamList[name].setAll(param);
00501 
00502         return true;
00503 }
00504 
00505 bool LLWLParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
00506 {
00507         // remove from param list
00508         std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
00509         if(mIt != mParamList.end()) 
00510         {
00511                 mParamList.erase(mIt);
00512         }
00513 
00514         F32 key;
00515 
00516         // remove all references
00517         bool stat = true;
00518         do 
00519         {
00520                 // get it
00521                 stat = mDay.getKey(name, key);
00522                 if(stat == false) 
00523                 {
00524                         break;
00525                 }
00526 
00527                 // and remove
00528                 stat = mDay.removeKey(key);
00529 
00530         } while(stat == true);
00531         
00532         if(delete_from_disk)
00533         {
00534                 LLString path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));
00535                 
00536                 // use full curl escaped name
00537                 char * curl_str = curl_escape(name.c_str(), name.size());
00538                 std::string escaped_name(curl_str);
00539                 curl_free(curl_str);
00540                 curl_str = NULL;
00541                 
00542                 gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml");
00543         }
00544 
00545         return true;
00546 }
00547 
00548 
00549 // static
00550 LLWLParamManager * LLWLParamManager::instance()
00551 {
00552         if(NULL == sInstance)
00553         {
00554                 sInstance = new LLWLParamManager();
00555 
00556                 sInstance->loadPresets("");
00557 
00558                 // load the day
00559                 sInstance->mDay.loadDayCycle("Default.xml");
00560 
00561                 // *HACK - sets cloud scrolling to what we want... fix this better in the future
00562                 sInstance->getParamSet("Default", sInstance->mCurParams);
00563 
00564                 // set it to noon
00565                 sInstance->resetAnimator(0.5, true);
00566 
00567                 // but use linden time sets it to what the estate is
00568                 sInstance->mAnimator.mUseLindenTime = true;
00569         }
00570 
00571         return sInstance;
00572 }

Generated on Fri May 16 08:34:25 2008 for SecondLife by  doxygen 1.5.5