aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvoicevisualizer.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:04 -0500
committerJacek Antonelli2008-08-15 23:45:04 -0500
commit117e22047c5752352342d64e3fb7ce00a4eb8113 (patch)
treee32de2cfba0dda8705ae528fcd1fbe23ba075685 /linden/indra/newview/llvoicevisualizer.cpp
parentSecond Life viewer sources 1.18.0.6 (diff)
downloadmeta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.zip
meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.gz
meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.bz2
meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.xz
Second Life viewer sources 1.18.1.2
Diffstat (limited to 'linden/indra/newview/llvoicevisualizer.cpp')
-rw-r--r--linden/indra/newview/llvoicevisualizer.cpp431
1 files changed, 431 insertions, 0 deletions
diff --git a/linden/indra/newview/llvoicevisualizer.cpp b/linden/indra/newview/llvoicevisualizer.cpp
new file mode 100644
index 0000000..fca2226
--- /dev/null
+++ b/linden/indra/newview/llvoicevisualizer.cpp
@@ -0,0 +1,431 @@
1//----------------------------------------------------------------------
2// Voice Visualizer
3// author: JJ Ventrella
4// (information about this stuff can be found in "llvoicevisualizer.h")
5//----------------------------------------------------------------------
6#include "llviewerprecompiledheaders.h"
7#include "llviewercontrol.h"
8#include "llglheaders.h"
9#include "llsphere.h"
10#include "llvoicevisualizer.h"
11#include "llviewercamera.h"
12#include "llviewerobject.h"
13#include "llimagegl.h"
14#include "llviewerimage.h"
15#include "llviewerimagelist.h"
16#include "llvoiceclient.h"
17
18//brent's wave image
19//29de489d-0491-fb00-7dab-f9e686d31e83
20
21
22//--------------------------------------------------------------------------------------
23// sound symbol constants
24//--------------------------------------------------------------------------------------
25const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear
26const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red
27const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green
28const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away
29const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size
30const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0
31const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves
32const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves
33const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold)
34const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture
35const F32 DOT_OPACITY = 0.7f; // how opaque the dot is
36const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude
37
38//--------------------------------------------------------------------------------------
39// gesticulation constants
40//--------------------------------------------------------------------------------------
41const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f;
42const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f;
43
44//--------------------------------------------------------------------------------------
45// other constants
46//--------------------------------------------------------------------------------------
47const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.
48const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL
49
50//-----------------------------------------------
51// constructor
52//-----------------------------------------------
53LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
54:LLHUDEffect( type )
55{
56 mCurrentTime = mTimer.getTotalSeconds();
57 mPreviousTime = mCurrentTime;
58 mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f );
59 mSpeakingAmplitude = 0.0f;
60 mCurrentlySpeaking = false;
61 mVoiceEnabled = false;
62 mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE;
63 mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;
64 mSoundSymbol.mActive = true;
65 mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f );
66
67 mTimer.reset();
68
69 LLUUID sound_level_img[] =
70 {
71 LLUUID(gSavedSettings.getString("VoiceImageLevel0")),
72 LLUUID(gSavedSettings.getString("VoiceImageLevel1")),
73 LLUUID(gSavedSettings.getString("VoiceImageLevel2")),
74 LLUUID(gSavedSettings.getString("VoiceImageLevel3")),
75 LLUUID(gSavedSettings.getString("VoiceImageLevel4")),
76 LLUUID(gSavedSettings.getString("VoiceImageLevel5")),
77 LLUUID(gSavedSettings.getString("VoiceImageLevel6"))
78 };
79
80 for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
81 {
82 mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
83 mSoundSymbol.mTexture [i] = gImageList.getUIImageByID(sound_level_img[i]);
84 mSoundSymbol.mWaveActive [i] = false;
85 mSoundSymbol.mWaveOpacity [i] = 1.0f;
86 mSoundSymbol.mWaveExpansion [i] = 1.0f;
87 }
88
89}//---------------------------------------------------
90
91//---------------------------------------------------
92void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )
93{
94 mMinGesticulationAmplitude = m;
95
96}//---------------------------------------------------
97
98//---------------------------------------------------
99void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m )
100{
101 mMaxGesticulationAmplitude = m;
102
103}//---------------------------------------------------
104
105//---------------------------------------------------
106void LLVoiceVisualizer::setVoiceEnabled( bool v )
107{
108 mVoiceEnabled = v;
109
110}//---------------------------------------------------
111
112//---------------------------------------------------
113void LLVoiceVisualizer::setStartSpeaking()
114{
115 mCurrentlySpeaking = true;
116 mSoundSymbol.mActive = true;
117
118}//---------------------------------------------------
119
120
121//---------------------------------------------------
122bool LLVoiceVisualizer::getCurrentlySpeaking()
123{
124 return mCurrentlySpeaking;
125
126}//---------------------------------------------------
127
128
129//---------------------------------------------------
130void LLVoiceVisualizer::setStopSpeaking()
131{
132 mCurrentlySpeaking = false;
133 mSpeakingAmplitude = 0.0f;
134
135}//---------------------------------------------------
136
137
138//---------------------------------------------------
139void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )
140{
141 mSpeakingAmplitude = a;
142
143}//---------------------------------------------------
144
145
146//---------------------------------------------------
147// this method is inherited from HUD Effect
148//---------------------------------------------------
149void LLVoiceVisualizer::render()
150{
151 if ( ! mVoiceEnabled )
152 {
153 return;
154 }
155
156 if ( mSoundSymbol.mActive )
157 {
158 mPreviousTime = mCurrentTime;
159 mCurrentTime = mTimer.getTotalSeconds();
160
161 //---------------------------------------------------------------
162 // set the sound symbol position over the source (avatar's head)
163 //---------------------------------------------------------------
164 mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD;
165
166 //---------------------------------------------------------------
167 // some gl state
168 //---------------------------------------------------------------
169 LLGLEnable tex( GL_TEXTURE_2D );
170 LLGLEnable blend( GL_BLEND );
171
172 //-------------------------------------------------------------
173 // create coordinates of the geometry for the dot
174 //-------------------------------------------------------------
175 LLVector3 l = gCamera->getLeftAxis() * DOT_SIZE;
176 LLVector3 u = gCamera->getUpAxis() * DOT_SIZE;
177
178 LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
179 LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
180 LLVector3 topLeft = mSoundSymbol.mPosition + l + u;
181 LLVector3 topRight = mSoundSymbol.mPosition - l + u;
182
183 //-----------------------------
184 // bind texture 0 (the dot)
185 //-----------------------------
186 mSoundSymbol.mTexture[0]->bind();
187
188 //-------------------------------------------------------------
189 // now render the dot
190 //-------------------------------------------------------------
191 glColor4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );
192
193 glBegin( GL_TRIANGLE_STRIP );
194 glTexCoord2i( 0, 0 ); glVertex3fv( bottomLeft.mV );
195 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
196 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
197 glEnd();
198
199 glBegin( GL_TRIANGLE_STRIP );
200 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
201 glTexCoord2i( 1, 1 ); glVertex3fv( topRight.mV );
202 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
203 glEnd();
204
205
206
207 //--------------------------------------------------------------------------------------
208 // if currently speaking, trigger waves (1 through 6) based on speaking amplitude
209 //--------------------------------------------------------------------------------------
210 if ( mCurrentlySpeaking )
211 {
212 F32 min = 0.2f;
213 F32 max = 0.7f;
214 F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min );
215
216 // in case mSpeakingAmplitude > max....
217 if ( fraction > 1.0f )
218 {
219 fraction = 1.0f;
220 }
221
222 S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) );
223
224 for (int i=0; i<level+1; i++)
225 {
226 mSoundSymbol.mWaveActive [i] = true;
227 mSoundSymbol.mWaveOpacity [i] = 1.0f;
228 mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
229 }
230
231 } // if currently speaking
232
233 //---------------------------------------------------
234 // determine color
235 //---------------------------------------------------
236 F32 red = 0.0f;
237 F32 green = 0.0f;
238 F32 blue = 0.0f;
239 if ( mSpeakingAmplitude < RED_THRESHOLD )
240 {
241 if ( mSpeakingAmplitude < GREEN_THRESHOLD )
242 {
243 red = BASE_BRIGHTNESS;
244 green = BASE_BRIGHTNESS;
245 blue = BASE_BRIGHTNESS;
246 }
247 else
248 {
249 //---------------------------------------------------
250 // fade from gray to bright green
251 //---------------------------------------------------
252 F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD );
253 red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
254 green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS );
255 blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
256 }
257 }
258 else
259 {
260 //---------------------------------------------------
261 // redish
262 //---------------------------------------------------
263 red = 1.0f;
264 green = 0.2f;
265 blue = 0.2f;
266 }
267
268 for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
269 {
270 if ( mSoundSymbol.mWaveActive[i] )
271 {
272 F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION;
273
274 mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction;
275
276 if ( mSoundSymbol.mWaveOpacity[i] < 0.0f )
277 {
278 mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
279 mSoundSymbol.mWaveOpacity [i] = 0.0f;
280 mSoundSymbol.mWaveActive [i] = false;
281 }
282
283 //----------------------------------------------------------------------------------
284 // This is where we calculate the expansion of the waves - that is, the
285 // rate at which they are scaled greater than 1.0 so that they grow over time.
286 //----------------------------------------------------------------------------------
287 F32 timeSlice = (F32)( mCurrentTime - mPreviousTime );
288 F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE;
289 mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed );
290
291 if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX )
292 {
293 mSoundSymbol.mWaveExpansion[i] = 1.0f;
294 }
295
296 //----------------------------------------------------------------------------------
297 // create geometry for the wave billboard textures
298 //----------------------------------------------------------------------------------
299 F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i];
300 F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];
301
302 LLVector3 l = gCamera->getLeftAxis() * width;
303 LLVector3 u = gCamera->getUpAxis() * height;
304
305 LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
306 LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
307 LLVector3 topLeft = mSoundSymbol.mPosition + l + u;
308 LLVector3 topRight = mSoundSymbol.mPosition - l + u;
309
310 glColor4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );
311 mSoundSymbol.mTexture[i]->bind();
312
313 //---------------------------------------------------
314 // now, render the mofo
315 //---------------------------------------------------
316 glBegin( GL_TRIANGLE_STRIP );
317 glTexCoord2i( 0, 0 ); glVertex3fv( bottomLeft.mV );
318 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
319 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
320 glEnd();
321
322 glBegin( GL_TRIANGLE_STRIP );
323 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
324 glTexCoord2i( 1, 1 ); glVertex3fv( topRight.mV );
325 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
326 glEnd();
327
328 } //if ( mSoundSymbol.mWaveActive[i] )
329
330 }// for loop
331
332 }//if ( mSoundSymbol.mActive )
333
334}//---------------------------------------------------
335
336
337
338
339
340//---------------------------------------------------
341void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )
342{
343 mVoiceSourceWorldPosition = p;
344
345}//---------------------------------------------------
346
347//---------------------------------------------------
348VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel()
349{
350 VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default
351
352 //-----------------------------------------------------------------------------------------
353 // Within the range of gesticulation amplitudes, the sound signal is split into
354 // three equal amplitude regimes, each specifying one of three gesticulation levels.
355 //-----------------------------------------------------------------------------------------
356 F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude;
357
358 if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.66666f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; }
359 else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.33333f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; }
360 else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; }
361
362 return gesticulationLevel;
363
364}//---------------------------------------------------
365
366
367
368//------------------------------------
369// Destructor
370//------------------------------------
371LLVoiceVisualizer::~LLVoiceVisualizer()
372{
373}//----------------------------------------------
374
375
376//---------------------------------------------------
377// "packData" is inherited from HUDEffect
378//---------------------------------------------------
379void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys)
380{
381 // Pack the default data
382 LLHUDEffect::packData(mesgsys);
383
384 // TODO -- pack the relevant data for voice effects
385 // we'll come up with some cool configurations....TBD
386 //U8 packed_data[41];
387 //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
388 U8 packed_data = 0;
389 mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1);
390}
391
392
393//---------------------------------------------------
394// "unpackData" is inherited from HUDEffect
395//---------------------------------------------------
396void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
397{
398 // TODO -- find the speaker, unpack binary data, set the properties of this effect
399 /*
400 LLHUDEffect::unpackData(mesgsys, blocknum);
401 LLUUID source_id;
402 LLUUID target_id;
403 S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
404 if (size != 1)
405 {
406 llwarns << "Voice effect with bad size " << size << llendl;
407 return;
408 }
409 mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum);
410 */
411}
412
413
414//------------------------------------------------------------------
415// this method is inherited from HUD Effect
416//------------------------------------------------------------------
417void LLVoiceVisualizer::markDead()
418{
419 mCurrentlySpeaking = false;
420 mVoiceEnabled = false;
421 mSoundSymbol.mActive = false;
422
423}//------------------------------------------------------------------
424
425
426
427
428
429
430
431