PageRenderTime 31ms CodeModel.GetById 2ms app.highlight 25ms 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
  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
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llwaterparammanager.h"
 30
 31#include "llrender.h"
 32
 33#include "pipeline.h"
 34#include "llsky.h"
 35
 36#include "lldiriterator.h"
 37#include "llfloaterreg.h"
 38#include "llsliderctrl.h"
 39#include "llspinctrl.h"
 40#include "llcheckboxctrl.h"
 41#include "lluictrlfactory.h"
 42#include "llviewercontrol.h"
 43#include "llviewercamera.h"
 44#include "llcombobox.h"
 45#include "lllineeditor.h"
 46#include "llsdserialize.h"
 47
 48#include "v4math.h"
 49#include "llviewercontrol.h"
 50#include "lldrawpoolwater.h"
 51#include "llagent.h"
 52#include "llagentcamera.h"
 53#include "llviewerregion.h"
 54
 55#include "llwlparammanager.h"
 56#include "llwaterparamset.h"
 57
 58#include "curl/curl.h"
 59
 60LLWaterParamManager::LLWaterParamManager() :
 61	mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"),
 62	mFogDensity(4, "waterFogDensity", 2),
 63	mUnderWaterFogMod(0.25, "underWaterFogMod"),
 64	mNormalScale(2.f, 2.f, 2.f, "normScale"),
 65	mFresnelScale(0.5f, "fresnelScale"),
 66	mFresnelOffset(0.4f, "fresnelOffset"),
 67	mScaleAbove(0.025f, "scaleAbove"),
 68	mScaleBelow(0.2f, "scaleBelow"),
 69	mBlurMultiplier(0.1f, "blurMultiplier"),
 70	mWave1Dir(.5f, .5f, "wave1Dir"),
 71	mWave2Dir(.5f, .5f, "wave2Dir"),
 72	mDensitySliderValue(1.0f),
 73	mWaterFogKS(1.0f)
 74{
 75}
 76
 77LLWaterParamManager::~LLWaterParamManager()
 78{
 79}
 80
 81void LLWaterParamManager::loadAllPresets()
 82{
 83	// First, load system (coming out of the box) water presets.
 84	loadPresetsFromDir(getSysDir());
 85
 86	// Then load user presets. Note that user day presets will modify any system ones already loaded.
 87	loadPresetsFromDir(getUserDir());
 88}
 89
 90void LLWaterParamManager::loadPresetsFromDir(const std::string& dir)
 91{
 92	LL_INFOS2("AppInit", "Shaders") << "Loading water presets from " << dir << LL_ENDL;
 93
 94	LLDirIterator dir_iter(dir, "*.xml");
 95	while (1)
 96	{
 97		std::string file;
 98		if (!dir_iter.next(file))
 99		{
100			break; // no more files
101		}
102
103		std::string path = dir + file;
104		if (!loadPreset(path))
105		{
106			llwarns << "Error loading water preset from " << path << llendl;
107		}
108	}
109}
110
111bool LLWaterParamManager::loadPreset(const std::string& path)
112{
113	llifstream xml_file;
114	std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
115
116	xml_file.open(path.c_str());
117	if (!xml_file)
118	{
119		return false;
120	}
121
122	LL_DEBUGS2("AppInit", "Shaders") << "Loading water " << name << LL_ENDL;
123
124	LLSD params_data;
125	LLPointer<LLSDParser> parser = new LLSDXMLParser();
126	parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
127	xml_file.close();
128
129	if (hasParamSet(name))
130	{
131		setParamSet(name, params_data);
132	}
133	else
134	{
135		addParamSet(name, params_data);
136	}
137
138	return true;
139}
140
141void LLWaterParamManager::savePreset(const std::string & name)
142{
143	llassert(!name.empty());
144
145	// make an empty llsd
146	LLSD paramsData(LLSD::emptyMap());
147	std::string pathName(getUserDir() + LLURI::escape(name) + ".xml");
148
149	// fill it with LLSD windlight params
150	paramsData = mParamList[name].getAll();
151
152	// write to file
153	llofstream presetsXML(pathName);
154	LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
155	formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
156	presetsXML.close();
157
158	propagateParameters();
159}
160
161void LLWaterParamManager::propagateParameters(void)
162{
163	// bind the variables only if we're using shaders
164	if(gPipeline.canUseVertexShaders())
165	{
166		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
167		end_shaders = LLViewerShaderMgr::instance()->endShaders();
168		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
169		{
170			if (shaders_iter->mProgramObject != 0
171				&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
172			{
173				shaders_iter->mUniformsDirty = TRUE;
174			}
175		}
176	}
177
178	bool err;
179	F32 fog_density_slider = 
180		log(mCurParams.getFloat(mFogDensity.mName, err)) / 
181		log(mFogDensity.mBase);
182
183	setDensitySliderValue(fog_density_slider);
184}
185
186void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
187{
188	if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
189	{
190		shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::getInstance()->getRotatedLightDir().mV);
191		shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
192		shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV);
193		shader->uniform1f("waterFogEnd", LLDrawPoolWater::sWaterFogEnd);
194		shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);
195		shader->uniform1f("waterFogDensity", getFogDensity());
196		shader->uniform1f("waterFogKS", mWaterFogKS);
197		shader->uniform4f("distance_multiplier", 0, 0, 0, 0);
198	}
199}
200
201void LLWaterParamManager::applyParams(const LLSD& params, bool interpolate)
202{
203	if (params.size() == 0)
204	{
205		llwarns << "Undefined water params" << llendl;
206		return;
207	}
208
209	if (interpolate)
210	{
211		LLWLParamManager::getInstance()->mAnimator.startInterpolation(params);
212	}
213	else
214	{
215		mCurParams.setAll(params);
216	}
217}
218
219static LLFastTimer::DeclareTimer FTM_UPDATE_WATERPARAM("Update Water Params");
220
221void LLWaterParamManager::update(LLViewerCamera * cam)
222{
223	LLFastTimer ftm(FTM_UPDATE_WATERPARAM);
224	
225	// update the shaders and the menu
226	propagateParameters();
227	
228	// only do this if we're dealing with shaders
229	if(gPipeline.canUseVertexShaders()) 
230	{
231		//transform water plane to eye space
232		glh::vec3f norm(0.f, 0.f, 1.f);
233		glh::vec3f p(0.f, 0.f, gAgent.getRegion()->getWaterHeight()+0.1f);
234		
235		F32 modelView[16];
236		for (U32 i = 0; i < 16; i++)
237		{
238			modelView[i] = (F32) gGLModelView[i];
239		}
240
241		glh::matrix4f mat(modelView);
242		glh::matrix4f invtrans = mat.inverse().transpose();
243		glh::vec3f enorm;
244		glh::vec3f ep;
245		invtrans.mult_matrix_vec(norm, enorm);
246		enorm.normalize();
247		mat.mult_matrix_vec(p, ep);
248
249		mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
250
251		LLVector3 sunMoonDir;
252		if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) 	 
253		{ 	 
254			sunMoonDir = gSky.getSunDirection(); 	 
255		} 	 
256		else  	 
257		{ 	 
258			sunMoonDir = gSky.getMoonDirection(); 	 
259		}
260		sunMoonDir.normVec();
261		mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);
262
263		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
264		end_shaders = LLViewerShaderMgr::instance()->endShaders();
265		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
266		{
267			if (shaders_iter->mProgramObject != 0
268				&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
269			{
270				shaders_iter->mUniformsDirty = TRUE;
271			}
272		}
273	}
274}
275
276bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet& param)
277{
278	// add a new one if not one there already
279	preset_map_t::iterator mIt = mParamList.find(name);
280	if(mIt == mParamList.end()) 
281	{	
282		mParamList[name] = param;
283		mPresetListChangeSignal();
284		return true;
285	}
286
287	return false;
288}
289
290BOOL LLWaterParamManager::addParamSet(const std::string& name, LLSD const & param)
291{
292	LLWaterParamSet param_set;
293	param_set.setAll(param);
294	return addParamSet(name, param_set);
295}
296
297bool LLWaterParamManager::getParamSet(const std::string& name, LLWaterParamSet& param)
298{
299	// find it and set it
300	preset_map_t::iterator mIt = mParamList.find(name);
301	if(mIt != mParamList.end()) 
302	{
303		param = mParamList[name];
304		param.mName = name;
305		return true;
306	}
307
308	return false;
309}
310
311bool LLWaterParamManager::hasParamSet(const std::string& name)
312{
313	LLWaterParamSet dummy;
314	return getParamSet(name, dummy);
315}
316
317bool LLWaterParamManager::setParamSet(const std::string& name, LLWaterParamSet& param)
318{
319	mParamList[name] = param;
320
321	return true;
322}
323
324bool LLWaterParamManager::setParamSet(const std::string& name, const LLSD & param)
325{
326	// quick, non robust (we won't be working with files, but assets) check
327	if(!param.isMap()) 
328	{
329		return false;
330	}
331	
332	mParamList[name].setAll(param);
333
334	return true;
335}
336
337bool LLWaterParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
338{
339	// remove from param list
340	preset_map_t::iterator it = mParamList.find(name);
341	if (it == mParamList.end())
342	{
343		LL_WARNS("WindLight") << "No water preset named " << name << LL_ENDL;
344		return false;
345	}
346
347	mParamList.erase(it);
348
349	// remove from file system if requested
350	if (delete_from_disk)
351	{
352		if (gDirUtilp->deleteFilesInDir(getUserDir(), LLURI::escape(name) + ".xml") < 1)
353		{
354			LL_WARNS("WindLight") << "Error removing water preset " << name << " from disk" << LL_ENDL;
355		}
356	}
357
358	// signal interested parties
359	mPresetListChangeSignal();
360	return true;
361}
362
363bool LLWaterParamManager::isSystemPreset(const std::string& preset_name) const
364{
365	// *TODO: file system access is excessive here.
366	return gDirUtilp->fileExists(getSysDir() + LLURI::escape(preset_name) + ".xml");
367}
368
369void LLWaterParamManager::getPresetNames(preset_name_list_t& presets) const
370{
371	presets.clear();
372
373	for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
374	{
375		presets.push_back(it->first);
376	}
377}
378
379void LLWaterParamManager::getPresetNames(preset_name_list_t& user_presets, preset_name_list_t& system_presets) const
380{
381	user_presets.clear();
382	system_presets.clear();
383
384	for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
385	{
386		if (isSystemPreset(it->first))
387		{
388			system_presets.push_back(it->first);
389		}
390		else
391		{
392			user_presets.push_back(it->first);
393		}
394	}
395}
396
397void LLWaterParamManager::getUserPresetNames(preset_name_list_t& user_presets) const
398{
399	preset_name_list_t dummy;
400	getPresetNames(user_presets, dummy);
401}
402
403boost::signals2::connection LLWaterParamManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb)
404{
405	return mPresetListChangeSignal.connect(cb);
406}
407
408F32 LLWaterParamManager::getFogDensity(void)
409{
410	bool err;
411
412	F32 fogDensity = mCurParams.getFloat("waterFogDensity", err);
413	
414	// modify if we're underwater
415	const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f;
416	F32 camera_height = gAgentCamera.getCameraPositionAgent().mV[2];
417	if(camera_height <= water_height)
418	{
419		// raise it to the underwater fog density modifier
420		fogDensity = pow(fogDensity, mCurParams.getFloat("underWaterFogMod", err));
421	}
422
423	return fogDensity;
424}
425
426// virtual static
427void LLWaterParamManager::initSingleton()
428{
429	LL_DEBUGS("Windlight") << "Initializing water" << LL_ENDL;
430	loadAllPresets();
431	LLEnvManagerNew::instance().usePrefs();
432}
433
434// static
435std::string LLWaterParamManager::getSysDir()
436{
437	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "");
438}
439
440// static
441std::string LLWaterParamManager::getUserDir()
442{
443	return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/water", "");
444}