00001
00032
00033
00034
00035
00036
00037 #include "llviewerprecompiledheaders.h"
00038 #include "llviewercontrol.h"
00039 #include "llglheaders.h"
00040 #include "llsphere.h"
00041 #include "llvoicevisualizer.h"
00042 #include "llviewercamera.h"
00043 #include "llviewerobject.h"
00044 #include "llimagegl.h"
00045 #include "llviewerimage.h"
00046 #include "llviewerimagelist.h"
00047 #include "llvoiceclient.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056 const F32 HEIGHT_ABOVE_HEAD = 0.3f;
00057 const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
00058 const F32 GREEN_THRESHOLD = 0.2f;
00059 const F32 FADE_OUT_DURATION = 0.4f;
00060 const F32 EXPANSION_RATE = 1.0f;
00061 const F32 EXPANSION_MAX = 1.5f;
00062 const F32 WAVE_WIDTH_SCALE = 0.03f;
00063 const F32 WAVE_HEIGHT_SCALE = 0.02f;
00064 const F32 BASE_BRIGHTNESS = 0.7f;
00065 const F32 DOT_SIZE = 0.05f;
00066 const F32 DOT_OPACITY = 0.7f;
00067 const F32 WAVE_MOTION_RATE = 1.5f;
00068
00069
00070
00071
00072 const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f;
00073 const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f;
00074
00075
00076
00077
00078 const F32 ONE_HALF = 1.0f;
00079 const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f );
00080
00081
00082
00083
00084 LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
00085 :LLHUDEffect( type )
00086 {
00087 mCurrentTime = mTimer.getTotalSeconds();
00088 mPreviousTime = mCurrentTime;
00089 mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f );
00090 mSpeakingAmplitude = 0.0f;
00091 mCurrentlySpeaking = false;
00092 mVoiceEnabled = false;
00093 mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE;
00094 mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;
00095 mSoundSymbol.mActive = true;
00096 mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f );
00097
00098 mTimer.reset();
00099
00100 LLUUID sound_level_img[] =
00101 {
00102 LLUUID(gSavedSettings.getString("VoiceImageLevel0")),
00103 LLUUID(gSavedSettings.getString("VoiceImageLevel1")),
00104 LLUUID(gSavedSettings.getString("VoiceImageLevel2")),
00105 LLUUID(gSavedSettings.getString("VoiceImageLevel3")),
00106 LLUUID(gSavedSettings.getString("VoiceImageLevel4")),
00107 LLUUID(gSavedSettings.getString("VoiceImageLevel5")),
00108 LLUUID(gSavedSettings.getString("VoiceImageLevel6"))
00109 };
00110
00111 for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
00112 {
00113 mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
00114 mSoundSymbol.mTexture [i] = gImageList.getUIImageByID(sound_level_img[i]);
00115 mSoundSymbol.mWaveActive [i] = false;
00116 mSoundSymbol.mWaveOpacity [i] = 1.0f;
00117 mSoundSymbol.mWaveExpansion [i] = 1.0f;
00118 }
00119
00120 }
00121
00122
00123 void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )
00124 {
00125 mMinGesticulationAmplitude = m;
00126
00127 }
00128
00129
00130 void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m )
00131 {
00132 mMaxGesticulationAmplitude = m;
00133
00134 }
00135
00136
00137 void LLVoiceVisualizer::setVoiceEnabled( bool v )
00138 {
00139 mVoiceEnabled = v;
00140
00141 }
00142
00143
00144 void LLVoiceVisualizer::setStartSpeaking()
00145 {
00146 mCurrentlySpeaking = true;
00147 mSoundSymbol.mActive = true;
00148
00149 }
00150
00151
00152
00153 bool LLVoiceVisualizer::getCurrentlySpeaking()
00154 {
00155 return mCurrentlySpeaking;
00156
00157 }
00158
00159
00160
00161 void LLVoiceVisualizer::setStopSpeaking()
00162 {
00163 mCurrentlySpeaking = false;
00164 mSpeakingAmplitude = 0.0f;
00165
00166 }
00167
00168
00169
00170 void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )
00171 {
00172 mSpeakingAmplitude = a;
00173
00174 }
00175
00176
00177
00178
00179
00180 void LLVoiceVisualizer::render()
00181 {
00182 if ( ! mVoiceEnabled )
00183 {
00184 return;
00185 }
00186
00187 if ( mSoundSymbol.mActive )
00188 {
00189 mPreviousTime = mCurrentTime;
00190 mCurrentTime = mTimer.getTotalSeconds();
00191
00192
00193
00194
00195 mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD;
00196
00197
00198
00199
00200 LLGLEnable tex( GL_TEXTURE_2D );
00201 LLGLEnable blend( GL_BLEND );
00202
00203
00204
00205
00206 LLVector3 l = gCamera->getLeftAxis() * DOT_SIZE;
00207 LLVector3 u = gCamera->getUpAxis() * DOT_SIZE;
00208
00209 LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
00210 LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
00211 LLVector3 topLeft = mSoundSymbol.mPosition + l + u;
00212 LLVector3 topRight = mSoundSymbol.mPosition - l + u;
00213
00214
00215
00216
00217 mSoundSymbol.mTexture[0]->bind();
00218
00219
00220
00221
00222 glColor4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );
00223
00224 glBegin( GL_TRIANGLE_STRIP );
00225 glTexCoord2i( 0, 0 ); glVertex3fv( bottomLeft.mV );
00226 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
00227 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
00228 glEnd();
00229
00230 glBegin( GL_TRIANGLE_STRIP );
00231 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
00232 glTexCoord2i( 1, 1 ); glVertex3fv( topRight.mV );
00233 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
00234 glEnd();
00235
00236
00237
00238
00239
00240
00241 if ( mCurrentlySpeaking )
00242 {
00243 F32 min = 0.2f;
00244 F32 max = 0.7f;
00245 F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min );
00246
00247
00248 if ( fraction > 1.0f )
00249 {
00250 fraction = 1.0f;
00251 }
00252
00253 S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) );
00254
00255 for (int i=0; i<level+1; i++)
00256 {
00257 mSoundSymbol.mWaveActive [i] = true;
00258 mSoundSymbol.mWaveOpacity [i] = 1.0f;
00259 mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
00260 }
00261
00262 }
00263
00264
00265
00266
00267 F32 red = 0.0f;
00268 F32 green = 0.0f;
00269 F32 blue = 0.0f;
00270 if ( mSpeakingAmplitude < RED_THRESHOLD )
00271 {
00272 if ( mSpeakingAmplitude < GREEN_THRESHOLD )
00273 {
00274 red = BASE_BRIGHTNESS;
00275 green = BASE_BRIGHTNESS;
00276 blue = BASE_BRIGHTNESS;
00277 }
00278 else
00279 {
00280
00281
00282
00283 F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD );
00284 red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
00285 green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS );
00286 blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
00287 }
00288 }
00289 else
00290 {
00291
00292
00293
00294 red = 1.0f;
00295 green = 0.2f;
00296 blue = 0.2f;
00297 }
00298
00299 for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
00300 {
00301 if ( mSoundSymbol.mWaveActive[i] )
00302 {
00303 F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION;
00304
00305 mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction;
00306
00307 if ( mSoundSymbol.mWaveOpacity[i] < 0.0f )
00308 {
00309 mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
00310 mSoundSymbol.mWaveOpacity [i] = 0.0f;
00311 mSoundSymbol.mWaveActive [i] = false;
00312 }
00313
00314
00315
00316
00317
00318 F32 timeSlice = (F32)( mCurrentTime - mPreviousTime );
00319 F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE;
00320 mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed );
00321
00322 if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX )
00323 {
00324 mSoundSymbol.mWaveExpansion[i] = 1.0f;
00325 }
00326
00327
00328
00329
00330 F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i];
00331 F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];
00332
00333 LLVector3 l = gCamera->getLeftAxis() * width;
00334 LLVector3 u = gCamera->getUpAxis() * height;
00335
00336 LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
00337 LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
00338 LLVector3 topLeft = mSoundSymbol.mPosition + l + u;
00339 LLVector3 topRight = mSoundSymbol.mPosition - l + u;
00340
00341 glColor4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );
00342 mSoundSymbol.mTexture[i]->bind();
00343
00344
00345
00346
00347 glBegin( GL_TRIANGLE_STRIP );
00348 glTexCoord2i( 0, 0 ); glVertex3fv( bottomLeft.mV );
00349 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
00350 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
00351 glEnd();
00352
00353 glBegin( GL_TRIANGLE_STRIP );
00354 glTexCoord2i( 1, 0 ); glVertex3fv( bottomRight.mV );
00355 glTexCoord2i( 1, 1 ); glVertex3fv( topRight.mV );
00356 glTexCoord2i( 0, 1 ); glVertex3fv( topLeft.mV );
00357 glEnd();
00358
00359 }
00360
00361 }
00362
00363 }
00364
00365 }
00366
00367
00368
00369
00370
00371
00372 void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )
00373 {
00374 mVoiceSourceWorldPosition = p;
00375
00376 }
00377
00378
00379 VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel()
00380 {
00381 VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF;
00382
00383
00384
00385
00386
00387 F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude;
00388
00389 if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.66666f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; }
00390 else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.33333f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; }
00391 else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; }
00392
00393 return gesticulationLevel;
00394
00395 }
00396
00397
00398
00399
00400
00401
00402 LLVoiceVisualizer::~LLVoiceVisualizer()
00403 {
00404 }
00405
00406
00407
00408
00409
00410 void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys)
00411 {
00412
00413 LLHUDEffect::packData(mesgsys);
00414
00415
00416
00417
00418
00419 U8 packed_data = 0;
00420 mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1);
00421 }
00422
00423
00424
00425
00426
00427 void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
00428 {
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 }
00443
00444
00445
00446
00447
00448 void LLVoiceVisualizer::markDead()
00449 {
00450 mCurrentlySpeaking = false;
00451 mVoiceEnabled = false;
00452 mSoundSymbol.mActive = false;
00453
00454 }
00455
00456
00457
00458
00459
00460
00461
00462