llwaterparammanager.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llwaterparammanager.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 "llviewercontrol.h"
00044 #include "llviewercamera.h"
00045 #include "llcombobox.h"
00046 #include "lllineeditor.h"
00047 #include "llsdserialize.h"
00048 
00049 #include "v4math.h"
00050 #include "llviewerdisplay.h"
00051 #include "llviewercontrol.h"
00052 #include "llviewerwindow.h"
00053 #include "lldrawpoolwater.h"
00054 #include "llagent.h"
00055 #include "llviewerregion.h"
00056 
00057 #include "llwlparammanager.h"
00058 #include "llwaterparamset.h"
00059 #include "llpostprocess.h"
00060 #include "llfloaterwater.h"
00061 
00062 #include "curl/curl.h"
00063 
00064 LLWaterParamManager * LLWaterParamManager::sInstance = NULL;
00065 
00066 LLWaterParamManager::LLWaterParamManager() :
00067         mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"),
00068         mFogDensity(4, "waterFogDensity", 2),
00069         mUnderWaterFogMod(0.25, "underWaterFogMod"),
00070         mNormalScale(2.f, 2.f, 2.f, "normScale"),
00071         mFresnelScale(0.5f, "fresnelScale"),
00072         mFresnelOffset(0.4f, "fresnelOffset"),
00073         mScaleAbove(0.025f, "scaleAbove"),
00074         mScaleBelow(0.2f, "scaleBelow"),
00075         mBlurMultiplier(0.1f, "blurMultiplier"),
00076         mWave1Dir(.5f, .5f, "wave1Dir"),
00077         mWave2Dir(.5f, .5f, "wave2Dir"),
00078         mDensitySliderValue(1.0f),
00079         mWaterFogKS(1.0f)
00080 {
00081 }
00082 
00083 LLWaterParamManager::~LLWaterParamManager()
00084 {
00085 }
00086 
00087 void LLWaterParamManager::loadAllPresets(const LLString& file_name)
00088 {
00089         LLString path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));
00090         LL_INFOS2("AppInit", "Shaders") << "Loading water settings from " << path_name << LL_ENDL;
00091 
00092         //mParamList.clear();
00093         
00094         bool found = true;                      
00095         while(found) 
00096         {
00097                 std::string name;
00098                 found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
00099 
00100                 LL_DEBUGS2("AppInit", "Shaders") << "name: " << name << LL_ENDL;
00101                 
00102                 // if we have one
00103                 if(found) 
00104                 {
00105                         // bugfix for SL-46920: preventing filenames that break stuff.
00106                         char * curl_str = curl_unescape(name.c_str(), name.size());
00107                         std::string unescaped_name(curl_str);
00108                         curl_free(curl_str);
00109                         curl_str = NULL;
00110 
00111                         // not much error checking here since we're getting rid of this
00112                         std::string water_name = unescaped_name.substr(0, unescaped_name.size() - 4);
00113                 
00114                         LLString cur_path(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", name));
00115                         LL_DEBUGS2("AppInit", "Shaders") << "Loading water from " << cur_path << LL_ENDL;
00116                         
00117                         std::ifstream water_xml(cur_path.c_str());
00118                         if (water_xml)
00119                         {
00120                                 LLSD water_data(LLSD::emptyMap());
00121                                 LLPointer<LLSDParser> parser = new LLSDXMLParser();
00122                                 parser->parse(water_xml, water_data, LLSDSerialize::SIZE_UNLIMITED);
00123 
00124                                 addParamSet(water_name, water_data);
00125                         }
00126                 }
00127         }
00128 }
00129 
00130 void LLWaterParamManager::loadPreset(const LLString & name)
00131 {
00132         // bugfix for SL-46920: preventing filenames that break stuff.
00133         char * curl_str = curl_escape(name.c_str(), name.size());
00134         std::string escaped_filename(curl_str);
00135         curl_free(curl_str);
00136         curl_str = NULL;
00137 
00138         escaped_filename += ".xml";
00139 
00140         std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
00141         llinfos << "Loading water settings from " << pathName << llendl;
00142 
00143         std::ifstream presetsXML(pathName.c_str());
00144 
00145         if (presetsXML)
00146         {
00147                 LLSD paramsData(LLSD::emptyMap());
00148 
00149                 LLPointer<LLSDParser> parser = new LLSDXMLParser();
00150 
00151                 parser->parse(presetsXML, paramsData, LLSDSerialize::SIZE_UNLIMITED);
00152 
00153                 std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
00154                 if(mIt == mParamList.end())
00155                 {
00156                         addParamSet(name, paramsData);
00157                 }
00158                 else 
00159                 {
00160                         setParamSet(name, paramsData);
00161                 }
00162         } 
00163         else 
00164         {
00165                 llwarns << "Can't find " << name << llendl;
00166                 return;
00167         }
00168 
00169         getParamSet(name, mCurParams);
00170 
00171         propagateParameters();
00172 }
00173 
00174 void LLWaterParamManager::savePreset(const LLString & name)
00175 {
00176         // bugfix for SL-46920: preventing filenames that break stuff.
00177         char * curl_str = curl_escape(name.c_str(), name.size());
00178         std::string escaped_filename(curl_str);
00179         curl_free(curl_str);
00180         curl_str = NULL;
00181 
00182         escaped_filename += ".xml";
00183 
00184         // make an empty llsd
00185         LLSD paramsData(LLSD::emptyMap());
00186         std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
00187 
00188         // fill it with LLSD windlight params
00189         paramsData = mParamList[name].getAll();
00190 
00191         // write to file
00192         std::ofstream presetsXML(pathName.c_str());
00193         LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
00194         formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
00195         presetsXML.close();
00196 
00197         propagateParameters();
00198 }
00199 
00200 
00201 void LLWaterParamManager::propagateParameters(void)
00202 {
00203         // bind the variables only if we're using shaders
00204         if(gPipeline.canUseVertexShaders())
00205         {
00206                 LLShaderMgr::shader_iter shaders_iter, end_shaders;
00207                 end_shaders = LLShaderMgr::endShaders();
00208                 for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
00209                 {
00210                         if (shaders_iter->mProgramObject != 0
00211                                 && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
00212                         {
00213                                 shaders_iter->mUniformsDirty = TRUE;
00214                         }
00215                 }
00216         }
00217 
00218         bool err;
00219         F32 fog_density_slider = 
00220                 log(mCurParams.getFloat(mFogDensity.mName, err)) / 
00221                 log(mFogDensity.mBase);
00222 
00223         setDensitySliderValue(fog_density_slider);
00224 }
00225 
00226 void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
00227 {
00228         if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
00229         {
00230                 shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, LLWLParamManager::instance()->getRotatedLightDir().mV);
00231                 shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
00232                 shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV);
00233                 shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);
00234                 shader->uniform1f("waterFogDensity", getFogDensity());
00235                 shader->uniform1f("waterFogKS", mWaterFogKS);
00236                 shader->uniform4f("distance_multiplier", 0, 0, 0, 0);
00237         }
00238 }
00239 
00240 void LLWaterParamManager::update(LLViewerCamera * cam)
00241 {
00242         LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
00243         
00244         // update the shaders and the menu
00245         propagateParameters();
00246         
00247         // sync menus if they exist
00248         if(LLFloaterWater::isOpen()) 
00249         {
00250                 LLFloaterWater::instance()->syncMenu();
00251         }
00252 
00253         stop_glerror();
00254 
00255         // only do this if we're dealing with shaders
00256         if(gPipeline.canUseVertexShaders()) 
00257         {
00258                 //transform water plane to eye space
00259                 glh::vec3f norm(0.f, 0.f, 1.f);
00260                 glh::vec3f p(0.f, 0.f, gAgent.getRegion()->getWaterHeight()+0.1f);
00261                 
00262                 F32 modelView[16];
00263                 for (U32 i = 0; i < 16; i++)
00264                 {
00265                         modelView[i] = (F32) gGLModelView[i];
00266                 }
00267 
00268                 glh::matrix4f mat(modelView);
00269                 glh::matrix4f invtrans = mat.inverse().transpose();
00270                 glh::vec3f enorm;
00271                 glh::vec3f ep;
00272                 invtrans.mult_matrix_vec(norm, enorm);
00273                 enorm.normalize();
00274                 mat.mult_matrix_vec(p, ep);
00275 
00276                 mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
00277 
00278                 LLVector3 sunMoonDir;
00279                 if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS)      
00280                 {        
00281                         sunMoonDir = gSky.getSunDirection();     
00282                 }        
00283                 else     
00284                 {        
00285                         sunMoonDir = gSky.getMoonDirection();    
00286                 }
00287                 sunMoonDir.normVec();
00288                 mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);
00289 
00290                 LLShaderMgr::shader_iter shaders_iter, end_shaders;
00291                 end_shaders = LLShaderMgr::endShaders();
00292                 for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
00293                 {
00294                         if (shaders_iter->mProgramObject != 0
00295                                 && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
00296                         {
00297                                 shaders_iter->mUniformsDirty = TRUE;
00298                         }
00299                 }
00300         }
00301 }
00302 
00303 // static
00304 void LLWaterParamManager::initClass(void)
00305 {
00306         instance();
00307 }
00308 
00309 // static
00310 void LLWaterParamManager::cleanupClass(void)
00311 {
00312         delete sInstance;
00313         sInstance = NULL;
00314 }
00315 
00316 bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet& param)
00317 {
00318         // add a new one if not one there already
00319         std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
00320         if(mIt == mParamList.end()) 
00321         {       
00322                 mParamList[name] = param;
00323                 return true;
00324         }
00325 
00326         return false;
00327 }
00328 
00329 BOOL LLWaterParamManager::addParamSet(const std::string& name, LLSD const & param)
00330 {
00331         // add a new one if not one there already
00332         std::map<std::string, LLWaterParamSet>::const_iterator finder = mParamList.find(name);
00333         if(finder == mParamList.end())
00334         {
00335                 mParamList[name].setAll(param);
00336                 return TRUE;
00337         }
00338         else
00339         {
00340                 return FALSE;
00341         }
00342 }
00343 
00344 bool LLWaterParamManager::getParamSet(const std::string& name, LLWaterParamSet& param)
00345 {
00346         // find it and set it
00347         std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
00348         if(mIt != mParamList.end()) 
00349         {
00350                 param = mParamList[name];
00351                 param.mName = name;
00352                 return true;
00353         }
00354 
00355         return false;
00356 }
00357 
00358 bool LLWaterParamManager::setParamSet(const std::string& name, LLWaterParamSet& param)
00359 {
00360         mParamList[name] = param;
00361 
00362         return true;
00363 }
00364 
00365 bool LLWaterParamManager::setParamSet(const std::string& name, const LLSD & param)
00366 {
00367         // quick, non robust (we won't be working with files, but assets) check
00368         if(!param.isMap()) 
00369         {
00370                 return false;
00371         }
00372         
00373         mParamList[name].setAll(param);
00374 
00375         return true;
00376 }
00377 
00378 bool LLWaterParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
00379 {
00380         // remove from param list
00381         std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
00382         if(mIt != mParamList.end()) 
00383         {
00384                 mParamList.erase(mIt);
00385         }
00386 
00387         if(delete_from_disk)
00388         {
00389                 LLString path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));
00390                 
00391                 // use full curl escaped name
00392                 char * curl_str = curl_escape(name.c_str(), name.size());
00393                 std::string escaped_name(curl_str);
00394                 curl_free(curl_str);
00395                 curl_str = NULL;
00396                 
00397                 gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml");
00398         }
00399 
00400         return true;
00401 }
00402 
00403 F32 LLWaterParamManager::getFogDensity(void)
00404 {
00405         bool err;
00406 
00407         F32 fogDensity = mCurParams.getFloat("waterFogDensity", err);
00408         
00409         // modify if we're underwater
00410         const F32 water_height = gAgent.getRegion()->getWaterHeight();
00411         F32 camera_height = gAgent.getCameraPositionAgent().mV[2];
00412         if(camera_height <= water_height)
00413         {
00414                 // raise it to the underwater fog density modifier
00415                 fogDensity = pow(fogDensity, mCurParams.getFloat("underWaterFogMod", err));
00416         }
00417 
00418         return fogDensity;
00419 }
00420 
00421 // static
00422 LLWaterParamManager * LLWaterParamManager::instance()
00423 {
00424         if(NULL == sInstance)
00425         {
00426                 sInstance = new LLWaterParamManager();
00427 
00428                 sInstance->loadAllPresets("");
00429 
00430                 sInstance->getParamSet("Default", sInstance->mCurParams);
00431         }
00432 
00433         return sInstance;
00434 }

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