PageRenderTime 31ms CodeModel.GetById 1ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llwlparamset.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 388 lines | 264 code | 55 blank | 69 comment | 63 complexity | 71730a7ec6c478613eafe2a23eab2c5c MD5 | raw file
  1/**
  2 * @file llwlparamset.cpp
  3 * @brief Implementation for the LLWLParamSet class.
  4 *
  5 * $LicenseInfo:firstyear=2005&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 "llwlparamset.h"
 30#include "llwlanimator.h"
 31
 32#include "llwlparammanager.h"
 33#include "llglslshader.h"
 34#include "lluictrlfactory.h"
 35#include "llsliderctrl.h"
 36
 37#include <llgl.h>
 38
 39#include <sstream>
 40
 41LLWLParamSet::LLWLParamSet(void) :
 42	mName("Unnamed Preset"),
 43	mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f)	
 44{
 45/* REMOVE or init the LLSD
 46	const std::map<std::string, LLVector4>::value_type hardcodedPreset[] = {
 47		std::make_pair("lightnorm",				LLVector4(0.f, 0.707f, -0.707f, 0.f)),
 48		std::make_pair("sunlight_color",		LLVector4(0.6f, 0.6f, 2.83f, 2.27f)),
 49		std::make_pair("ambient",				LLVector4(0.27f, 0.33f, 0.44f, 1.19f)),
 50		std::make_pair("blue_horizon",			LLVector4(0.3f, 0.4f, 0.9f, 1.f)),
 51		std::make_pair("blue_density",			LLVector4(0.3f, 0.4f, 0.8f, 1.f)),
 52		std::make_pair("haze_horizon",			LLVector4(0.6f, 0.6f, 0.6f, 1.f)),
 53		std::make_pair("haze_density",			LLVector4(0.3f, 0.3f, 0.3f, 1.f)),
 54		std::make_pair("cloud_shadow",			LLVector4(0.f, 0.f, 0.f, 0.f)),
 55		std::make_pair("density_multiplier",	LLVector4(0.001f, 0.001f, 0.001f, 0.001f)),
 56		std::make_pair("distance_multiplier",	LLVector4(1.f, 1.f, 1.f, 1.f)),
 57		std::make_pair("max_y",					LLVector4(600.f, 600.f, 600.f, 0.f)),
 58		std::make_pair("glow",					LLVector4(15.f, 0.001f, -0.03125f, 0.f)),
 59		std::make_pair("cloud_color",			LLVector4(0.0f, 0.0f, 0.0f, 0.0f)),
 60		std::make_pair("cloud_pos_density1",	LLVector4(0.f, 0.f, 0.f, 1.f)),
 61		std::make_pair("cloud_pos_density2",	LLVector4(0.f, 0.f, 0.f, 1.f)),
 62		std::make_pair("cloud_scale",			LLVector4(0.42f, 0.f, 0.f, 1.f)),
 63		std::make_pair("gamma",					LLVector4(2.0f, 2.0f, 2.0f, 0.0f)),
 64	};
 65	std::map<std::string, LLVector4>::value_type const * endHardcodedPreset = 
 66		hardcodedPreset + LL_ARRAY_SIZE(hardcodedPreset);
 67
 68	mParamValues.insert(hardcodedPreset, endHardcodedPreset);
 69*/
 70}
 71
 72static LLFastTimer::DeclareTimer FTM_WL_PARAM_UPDATE("WL Param Update");
 73
 74void LLWLParamSet::update(LLGLSLShader * shader) const 
 75{	
 76	LLFastTimer t(FTM_WL_PARAM_UPDATE);
 77
 78	for(LLSD::map_const_iterator i = mParamValues.beginMap();
 79		i != mParamValues.endMap();
 80		++i)
 81	{
 82		
 83
 84		const std::string& param = i->first;
 85		
 86		if(	param == "star_brightness" || param == "preset_num" || param == "sun_angle" ||
 87			param == "east_angle" || param == "enable_cloud_scroll" ||
 88			param == "cloud_scroll_rate" || param == "lightnorm" ) 
 89		{
 90			continue;
 91		}
 92		
 93		if(param == "cloud_pos_density1") 
 94		{
 95			LLVector4 val;
 96			val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset;
 97			val.mV[1] = F32(i->second[1].asReal()) + mCloudScrollYOffset;
 98			val.mV[2] = (F32) i->second[2].asReal();
 99			val.mV[3] = (F32) i->second[3].asReal();
100			stop_glerror();
101			shader->uniform4fv(param, 1, val.mV);
102			stop_glerror();
103		} 
104		else // param is the uniform name
105		{
106			LLVector4 val;
107			
108			// handle all the different cases
109			if(i->second.isArray() && i->second.size() == 4) 
110			{
111				val.mV[0] = (F32) i->second[0].asReal();
112				val.mV[1] = (F32) i->second[1].asReal();
113				val.mV[2] = (F32) i->second[2].asReal();
114				val.mV[3] = (F32) i->second[3].asReal();															
115			} 
116			else if(i->second.isReal()) 
117			{
118				val.mV[0] = (F32) i->second.asReal();
119			} 
120			else if(i->second.isInteger()) 
121			{
122				val.mV[0] = (F32) i->second.asReal();
123			} 
124			else if(i->second.isBoolean())
125			{
126				val.mV[0] = i->second.asBoolean();
127			}
128			stop_glerror();
129			shader->uniform4fv(param, 1, val.mV);
130			stop_glerror();
131		}
132	}
133}
134
135void LLWLParamSet::set(const std::string& paramName, float x) 
136{	
137	// handle case where no array
138	if(mParamValues[paramName].isReal()) 
139	{
140		mParamValues[paramName] = x;
141	} 
142	
143	// handle array
144	else if(mParamValues[paramName].isArray() &&
145			mParamValues[paramName][0].isReal())
146	{
147		mParamValues[paramName][0] = x;
148	}
149}
150
151void LLWLParamSet::set(const std::string& paramName, float x, float y) {
152	mParamValues[paramName][0] = x;
153	mParamValues[paramName][1] = y;
154}
155
156void LLWLParamSet::set(const std::string& paramName, float x, float y, float z) 
157{
158	mParamValues[paramName][0] = x;
159	mParamValues[paramName][1] = y;
160	mParamValues[paramName][2] = z;
161}
162
163void LLWLParamSet::set(const std::string& paramName, float x, float y, float z, float w) 
164{
165	mParamValues[paramName][0] = x;
166	mParamValues[paramName][1] = y;
167	mParamValues[paramName][2] = z;
168	mParamValues[paramName][3] = w;
169}
170
171void LLWLParamSet::set(const std::string& paramName, const float * val) 
172{
173	mParamValues[paramName][0] = val[0];
174	mParamValues[paramName][1] = val[1];
175	mParamValues[paramName][2] = val[2];
176	mParamValues[paramName][3] = val[3];
177}
178
179void LLWLParamSet::set(const std::string& paramName, const LLVector4 & val) 
180{
181	mParamValues[paramName][0] = val.mV[0];
182	mParamValues[paramName][1] = val.mV[1];
183	mParamValues[paramName][2] = val.mV[2];
184	mParamValues[paramName][3] = val.mV[3];
185}
186
187void LLWLParamSet::set(const std::string& paramName, const LLColor4 & val) 
188{
189	mParamValues[paramName][0] = val.mV[0];
190	mParamValues[paramName][1] = val.mV[1];
191	mParamValues[paramName][2] = val.mV[2];
192	mParamValues[paramName][3] = val.mV[3];
193}
194
195LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error) 
196{
197	
198	// test to see if right type
199	LLSD cur_val = mParamValues.get(paramName);
200	if (!cur_val.isArray()) 
201	{
202		error = true;
203		return LLVector4(0,0,0,0);
204	}
205	
206	LLVector4 val;
207	val.mV[0] = (F32) cur_val[0].asReal();
208	val.mV[1] = (F32) cur_val[1].asReal();
209	val.mV[2] = (F32) cur_val[2].asReal();
210	val.mV[3] = (F32) cur_val[3].asReal();
211	
212	error = false;
213	return val;
214}
215
216F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error) 
217{
218	
219	// test to see if right type
220	LLSD cur_val = mParamValues.get(paramName);
221	if (cur_val.isArray() && cur_val.size() != 0) 
222	{
223		error = false;
224		return (F32) cur_val[0].asReal();	
225	}
226	
227	if(cur_val.isReal())
228	{
229		error = false;
230		return (F32) cur_val.asReal();
231	}
232	
233	error = true;
234	return 0;
235}
236
237
238
239void LLWLParamSet::setSunAngle(float val) 
240{
241	// keep range 0 - 2pi
242	if(val > F_TWO_PI || val < 0)
243	{
244		F32 num = val / F_TWO_PI;
245		num -= floor(num);
246		val = F_TWO_PI * num;
247	}
248
249	mParamValues["sun_angle"] = val;
250}
251
252
253void LLWLParamSet::setEastAngle(float val) 
254{
255	// keep range 0 - 2pi
256	if(val > F_TWO_PI || val < 0)
257	{
258		F32 num = val / F_TWO_PI;
259		num -= floor(num);
260		val = F_TWO_PI * num;
261	}
262
263	mParamValues["east_angle"] = val;
264}
265
266
267void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)
268{
269	// set up the iterators
270
271	// keep cloud positions and coverage the same
272	/// TODO masking will do this later
273	F32 cloudPos1X = (F32) mParamValues["cloud_pos_density1"][0].asReal();
274	F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal();
275	F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal();
276	F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal();
277	F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal();
278
279	LLSD srcVal;
280	LLSD destVal;
281
282	// Iterate through values
283	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
284	{
285
286		// If param exists in both src and dest, set the holder variables, otherwise skip
287		if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))
288		{
289			srcVal = src.mParamValues[iter->first];
290			destVal = dest.mParamValues[iter->first];
291		}
292		else
293		{
294			continue;
295		}
296		
297		if(iter->second.isReal())									// If it's a real, interpolate directly
298		{
299			iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight);
300		}
301		else if(iter->second.isArray() && iter->second[0].isReal()	// If it's an array of reals, loop through the reals and interpolate on those
302				&& iter->second.size() == srcVal.size() && iter->second.size() == destVal.size())
303		{
304			// Actually do interpolation: old value + (difference in values * factor)
305			for(int i=0; i < iter->second.size(); ++i) 
306			{
307				// iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal();	// old way of doing it -- equivalent but one more operation
308				iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight);
309			}
310		}
311		else														// Else, skip
312		{
313			continue;
314		}		
315	}
316
317	// now mix the extra parameters
318	setStarBrightness((1 - weight) * (F32) src.getStarBrightness()
319		+ weight * (F32) dest.getStarBrightness());
320
321	llassert(src.getSunAngle() >= - F_PI && 
322					src.getSunAngle() <= 3 * F_PI);
323	llassert(dest.getSunAngle() >= - F_PI && 
324					dest.getSunAngle() <= 3 * F_PI);
325	llassert(src.getEastAngle() >= 0 && 
326					src.getEastAngle() <= 4 * F_PI);
327	llassert(dest.getEastAngle() >= 0 && 
328					dest.getEastAngle() <= 4 * F_PI);
329
330	// sun angle and east angle require some handling to make sure
331	// they go in circles.  Yes quaternions would work better.
332	F32 srcSunAngle = src.getSunAngle();
333	F32 destSunAngle = dest.getSunAngle();
334	F32 srcEastAngle = src.getEastAngle();
335	F32 destEastAngle = dest.getEastAngle();
336	
337	if(fabsf(srcSunAngle - destSunAngle) > F_PI) 
338	{
339		if(srcSunAngle > destSunAngle) 
340		{
341			destSunAngle += 2 * F_PI;
342		} 
343		else 
344		{
345			srcSunAngle += 2 * F_PI;
346		}
347	}
348
349	if(fabsf(srcEastAngle - destEastAngle) > F_PI) 
350	{
351		if(srcEastAngle > destEastAngle) 
352		{
353			destEastAngle += 2 * F_PI;
354		} 
355		else 
356		{
357			srcEastAngle += 2 * F_PI;
358		}
359	}
360
361	setSunAngle((1 - weight) * srcSunAngle + weight * destSunAngle);
362	setEastAngle((1 - weight) * srcEastAngle + weight * destEastAngle);
363	
364	// now setup the sun properly
365
366	// reset those cloud positions
367	mParamValues["cloud_pos_density1"][0] = cloudPos1X;
368	mParamValues["cloud_pos_density1"][1] = cloudPos1Y;
369	mParamValues["cloud_pos_density2"][0] = cloudPos2X;
370	mParamValues["cloud_pos_density2"][1] = cloudPos2Y;
371	mParamValues["cloud_shadow"][0] = cloudCover;
372}
373
374void LLWLParamSet::updateCloudScrolling(void) 
375{
376	static LLTimer s_cloud_timer;
377
378	F64 delta_t = s_cloud_timer.getElapsedTimeAndResetF64();
379
380	if(getEnableCloudScrollX())
381	{
382		mCloudScrollXOffset += F32(delta_t * (getCloudScrollX() - 10.f) / 100.f);
383	}
384	if(getEnableCloudScrollY())
385	{
386		mCloudScrollYOffset += F32(delta_t * (getCloudScrollY() - 10.f) / 100.f);
387	}
388}