PageRenderTime 30ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llwaterparammanager.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 444 lines | 328 code | 70 blank | 46 comment | 42 complexity | 36f71b757bad00839bdb1fe8a2dc173c MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llwaterparammanager.cpp
  3. * @brief Implementation for the LLWaterParamManager class.
  4. *
  5. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llwaterparammanager.h"
  28. #include "llrender.h"
  29. #include "pipeline.h"
  30. #include "llsky.h"
  31. #include "lldiriterator.h"
  32. #include "llfloaterreg.h"
  33. #include "llsliderctrl.h"
  34. #include "llspinctrl.h"
  35. #include "llcheckboxctrl.h"
  36. #include "lluictrlfactory.h"
  37. #include "llviewercontrol.h"
  38. #include "llviewercamera.h"
  39. #include "llcombobox.h"
  40. #include "lllineeditor.h"
  41. #include "llsdserialize.h"
  42. #include "v4math.h"
  43. #include "llviewercontrol.h"
  44. #include "lldrawpoolwater.h"
  45. #include "llagent.h"
  46. #include "llagentcamera.h"
  47. #include "llviewerregion.h"
  48. #include "llwlparammanager.h"
  49. #include "llwaterparamset.h"
  50. #include "curl/curl.h"
  51. LLWaterParamManager::LLWaterParamManager() :
  52. mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"),
  53. mFogDensity(4, "waterFogDensity", 2),
  54. mUnderWaterFogMod(0.25, "underWaterFogMod"),
  55. mNormalScale(2.f, 2.f, 2.f, "normScale"),
  56. mFresnelScale(0.5f, "fresnelScale"),
  57. mFresnelOffset(0.4f, "fresnelOffset"),
  58. mScaleAbove(0.025f, "scaleAbove"),
  59. mScaleBelow(0.2f, "scaleBelow"),
  60. mBlurMultiplier(0.1f, "blurMultiplier"),
  61. mWave1Dir(.5f, .5f, "wave1Dir"),
  62. mWave2Dir(.5f, .5f, "wave2Dir"),
  63. mDensitySliderValue(1.0f),
  64. mWaterFogKS(1.0f)
  65. {
  66. }
  67. LLWaterParamManager::~LLWaterParamManager()
  68. {
  69. }
  70. void LLWaterParamManager::loadAllPresets()
  71. {
  72. // First, load system (coming out of the box) water presets.
  73. loadPresetsFromDir(getSysDir());
  74. // Then load user presets. Note that user day presets will modify any system ones already loaded.
  75. loadPresetsFromDir(getUserDir());
  76. }
  77. void LLWaterParamManager::loadPresetsFromDir(const std::string& dir)
  78. {
  79. LL_INFOS2("AppInit", "Shaders") << "Loading water presets from " << dir << LL_ENDL;
  80. LLDirIterator dir_iter(dir, "*.xml");
  81. while (1)
  82. {
  83. std::string file;
  84. if (!dir_iter.next(file))
  85. {
  86. break; // no more files
  87. }
  88. std::string path = dir + file;
  89. if (!loadPreset(path))
  90. {
  91. llwarns << "Error loading water preset from " << path << llendl;
  92. }
  93. }
  94. }
  95. bool LLWaterParamManager::loadPreset(const std::string& path)
  96. {
  97. llifstream xml_file;
  98. std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
  99. xml_file.open(path.c_str());
  100. if (!xml_file)
  101. {
  102. return false;
  103. }
  104. LL_DEBUGS2("AppInit", "Shaders") << "Loading water " << name << LL_ENDL;
  105. LLSD params_data;
  106. LLPointer<LLSDParser> parser = new LLSDXMLParser();
  107. parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
  108. xml_file.close();
  109. if (hasParamSet(name))
  110. {
  111. setParamSet(name, params_data);
  112. }
  113. else
  114. {
  115. addParamSet(name, params_data);
  116. }
  117. return true;
  118. }
  119. void LLWaterParamManager::savePreset(const std::string & name)
  120. {
  121. llassert(!name.empty());
  122. // make an empty llsd
  123. LLSD paramsData(LLSD::emptyMap());
  124. std::string pathName(getUserDir() + LLURI::escape(name) + ".xml");
  125. // fill it with LLSD windlight params
  126. paramsData = mParamList[name].getAll();
  127. // write to file
  128. llofstream presetsXML(pathName);
  129. LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
  130. formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
  131. presetsXML.close();
  132. propagateParameters();
  133. }
  134. void LLWaterParamManager::propagateParameters(void)
  135. {
  136. // bind the variables only if we're using shaders
  137. if(gPipeline.canUseVertexShaders())
  138. {
  139. LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
  140. end_shaders = LLViewerShaderMgr::instance()->endShaders();
  141. for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
  142. {
  143. if (shaders_iter->mProgramObject != 0
  144. && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
  145. {
  146. shaders_iter->mUniformsDirty = TRUE;
  147. }
  148. }
  149. }
  150. bool err;
  151. F32 fog_density_slider =
  152. log(mCurParams.getFloat(mFogDensity.mName, err)) /
  153. log(mFogDensity.mBase);
  154. setDensitySliderValue(fog_density_slider);
  155. }
  156. void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
  157. {
  158. if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
  159. {
  160. shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::getInstance()->getRotatedLightDir().mV);
  161. shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
  162. shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV);
  163. shader->uniform1f("waterFogEnd", LLDrawPoolWater::sWaterFogEnd);
  164. shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);
  165. shader->uniform1f("waterFogDensity", getFogDensity());
  166. shader->uniform1f("waterFogKS", mWaterFogKS);
  167. shader->uniform4f("distance_multiplier", 0, 0, 0, 0);
  168. }
  169. }
  170. void LLWaterParamManager::applyParams(const LLSD& params, bool interpolate)
  171. {
  172. if (params.size() == 0)
  173. {
  174. llwarns << "Undefined water params" << llendl;
  175. return;
  176. }
  177. if (interpolate)
  178. {
  179. LLWLParamManager::getInstance()->mAnimator.startInterpolation(params);
  180. }
  181. else
  182. {
  183. mCurParams.setAll(params);
  184. }
  185. }
  186. static LLFastTimer::DeclareTimer FTM_UPDATE_WATERPARAM("Update Water Params");
  187. void LLWaterParamManager::update(LLViewerCamera * cam)
  188. {
  189. LLFastTimer ftm(FTM_UPDATE_WATERPARAM);
  190. // update the shaders and the menu
  191. propagateParameters();
  192. // only do this if we're dealing with shaders
  193. if(gPipeline.canUseVertexShaders())
  194. {
  195. //transform water plane to eye space
  196. glh::vec3f norm(0.f, 0.f, 1.f);
  197. glh::vec3f p(0.f, 0.f, gAgent.getRegion()->getWaterHeight()+0.1f);
  198. F32 modelView[16];
  199. for (U32 i = 0; i < 16; i++)
  200. {
  201. modelView[i] = (F32) gGLModelView[i];
  202. }
  203. glh::matrix4f mat(modelView);
  204. glh::matrix4f invtrans = mat.inverse().transpose();
  205. glh::vec3f enorm;
  206. glh::vec3f ep;
  207. invtrans.mult_matrix_vec(norm, enorm);
  208. enorm.normalize();
  209. mat.mult_matrix_vec(p, ep);
  210. mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
  211. LLVector3 sunMoonDir;
  212. if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS)
  213. {
  214. sunMoonDir = gSky.getSunDirection();
  215. }
  216. else
  217. {
  218. sunMoonDir = gSky.getMoonDirection();
  219. }
  220. sunMoonDir.normVec();
  221. mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);
  222. LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
  223. end_shaders = LLViewerShaderMgr::instance()->endShaders();
  224. for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
  225. {
  226. if (shaders_iter->mProgramObject != 0
  227. && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
  228. {
  229. shaders_iter->mUniformsDirty = TRUE;
  230. }
  231. }
  232. }
  233. }
  234. bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet& param)
  235. {
  236. // add a new one if not one there already
  237. preset_map_t::iterator mIt = mParamList.find(name);
  238. if(mIt == mParamList.end())
  239. {
  240. mParamList[name] = param;
  241. mPresetListChangeSignal();
  242. return true;
  243. }
  244. return false;
  245. }
  246. BOOL LLWaterParamManager::addParamSet(const std::string& name, LLSD const & param)
  247. {
  248. LLWaterParamSet param_set;
  249. param_set.setAll(param);
  250. return addParamSet(name, param_set);
  251. }
  252. bool LLWaterParamManager::getParamSet(const std::string& name, LLWaterParamSet& param)
  253. {
  254. // find it and set it
  255. preset_map_t::iterator mIt = mParamList.find(name);
  256. if(mIt != mParamList.end())
  257. {
  258. param = mParamList[name];
  259. param.mName = name;
  260. return true;
  261. }
  262. return false;
  263. }
  264. bool LLWaterParamManager::hasParamSet(const std::string& name)
  265. {
  266. LLWaterParamSet dummy;
  267. return getParamSet(name, dummy);
  268. }
  269. bool LLWaterParamManager::setParamSet(const std::string& name, LLWaterParamSet& param)
  270. {
  271. mParamList[name] = param;
  272. return true;
  273. }
  274. bool LLWaterParamManager::setParamSet(const std::string& name, const LLSD & param)
  275. {
  276. // quick, non robust (we won't be working with files, but assets) check
  277. if(!param.isMap())
  278. {
  279. return false;
  280. }
  281. mParamList[name].setAll(param);
  282. return true;
  283. }
  284. bool LLWaterParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
  285. {
  286. // remove from param list
  287. preset_map_t::iterator it = mParamList.find(name);
  288. if (it == mParamList.end())
  289. {
  290. LL_WARNS("WindLight") << "No water preset named " << name << LL_ENDL;
  291. return false;
  292. }
  293. mParamList.erase(it);
  294. // remove from file system if requested
  295. if (delete_from_disk)
  296. {
  297. if (gDirUtilp->deleteFilesInDir(getUserDir(), LLURI::escape(name) + ".xml") < 1)
  298. {
  299. LL_WARNS("WindLight") << "Error removing water preset " << name << " from disk" << LL_ENDL;
  300. }
  301. }
  302. // signal interested parties
  303. mPresetListChangeSignal();
  304. return true;
  305. }
  306. bool LLWaterParamManager::isSystemPreset(const std::string& preset_name) const
  307. {
  308. // *TODO: file system access is excessive here.
  309. return gDirUtilp->fileExists(getSysDir() + LLURI::escape(preset_name) + ".xml");
  310. }
  311. void LLWaterParamManager::getPresetNames(preset_name_list_t& presets) const
  312. {
  313. presets.clear();
  314. for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
  315. {
  316. presets.push_back(it->first);
  317. }
  318. }
  319. void LLWaterParamManager::getPresetNames(preset_name_list_t& user_presets, preset_name_list_t& system_presets) const
  320. {
  321. user_presets.clear();
  322. system_presets.clear();
  323. for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
  324. {
  325. if (isSystemPreset(it->first))
  326. {
  327. system_presets.push_back(it->first);
  328. }
  329. else
  330. {
  331. user_presets.push_back(it->first);
  332. }
  333. }
  334. }
  335. void LLWaterParamManager::getUserPresetNames(preset_name_list_t& user_presets) const
  336. {
  337. preset_name_list_t dummy;
  338. getPresetNames(user_presets, dummy);
  339. }
  340. boost::signals2::connection LLWaterParamManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb)
  341. {
  342. return mPresetListChangeSignal.connect(cb);
  343. }
  344. F32 LLWaterParamManager::getFogDensity(void)
  345. {
  346. bool err;
  347. F32 fogDensity = mCurParams.getFloat("waterFogDensity", err);
  348. // modify if we're underwater
  349. const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f;
  350. F32 camera_height = gAgentCamera.getCameraPositionAgent().mV[2];
  351. if(camera_height <= water_height)
  352. {
  353. // raise it to the underwater fog density modifier
  354. fogDensity = pow(fogDensity, mCurParams.getFloat("underWaterFogMod", err));
  355. }
  356. return fogDensity;
  357. }
  358. // virtual static
  359. void LLWaterParamManager::initSingleton()
  360. {
  361. LL_DEBUGS("Windlight") << "Initializing water" << LL_ENDL;
  362. loadAllPresets();
  363. LLEnvManagerNew::instance().usePrefs();
  364. }
  365. // static
  366. std::string LLWaterParamManager::getSysDir()
  367. {
  368. return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "");
  369. }
  370. // static
  371. std::string LLWaterParamManager::getUserDir()
  372. {
  373. return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/water", "");
  374. }