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
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
00103 if(found)
00104 {
00105
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
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
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
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
00185 LLSD paramsData(LLSD::emptyMap());
00186 std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
00187
00188
00189 paramsData = mParamList[name].getAll();
00190
00191
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
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
00245 propagateParameters();
00246
00247
00248 if(LLFloaterWater::isOpen())
00249 {
00250 LLFloaterWater::instance()->syncMenu();
00251 }
00252
00253 stop_glerror();
00254
00255
00256 if(gPipeline.canUseVertexShaders())
00257 {
00258
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
00304 void LLWaterParamManager::initClass(void)
00305 {
00306 instance();
00307 }
00308
00309
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
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
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
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
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
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
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
00410 const F32 water_height = gAgent.getRegion()->getWaterHeight();
00411 F32 camera_height = gAgent.getCameraPositionAgent().mV[2];
00412 if(camera_height <= water_height)
00413 {
00414
00415 fogDensity = pow(fogDensity, mCurParams.getFloat("underWaterFogMod", err));
00416 }
00417
00418 return fogDensity;
00419 }
00420
00421
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 }