Need to test: localassetbrowser preview related floaters hgfloatertexteditor maps media textures! Currently very hacky web browser alpha masks on avatars bumpmaps Are all sky components appearing? LLViewerDynamicTexture (texture baking, browser, animated textures, anim previews, etc) Snapshot related features Customize avatar vfs floater UI textures in general Texture priority issues
632 lines
22 KiB
C++
632 lines
22 KiB
C++
/**
|
|
* @file llvoicevisualizer.cpp
|
|
* @brief Draws in-world speaking indicators.
|
|
*
|
|
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2000-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
//----------------------------------------------------------------------
|
|
// Voice Visualizer
|
|
// author: JJ Ventrella
|
|
// (information about this stuff can be found in "llvoicevisualizer.h")
|
|
//----------------------------------------------------------------------
|
|
#include "llviewerprecompiledheaders.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llglheaders.h"
|
|
#include "llsphere.h"
|
|
#include "llvoicevisualizer.h"
|
|
#include "llviewercamera.h"
|
|
#include "llviewerobject.h"
|
|
#include "llimagegl.h"
|
|
#include "llviewertexturelist.h"
|
|
#include "llvoiceclient.h"
|
|
#include "llrender.h"
|
|
|
|
//brent's wave image
|
|
//29de489d-0491-fb00-7dab-f9e686d31e83
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// sound symbol constants
|
|
//--------------------------------------------------------------------------------------
|
|
const F32 HEIGHT_ABOVE_HEAD = 0.3f; // how many meters vertically above the av's head the voice symbol will appear
|
|
const F32 RED_THRESHOLD = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; // value above which speaking amplitude causes the voice symbol to turn red
|
|
const F32 GREEN_THRESHOLD = 0.2f; // value above which speaking amplitude causes the voice symbol to turn green
|
|
const F32 FADE_OUT_DURATION = 0.4f; // how many seconds it takes for a pair of waves to fade away
|
|
const F32 EXPANSION_RATE = 1.0f; // how many seconds it takes for the waves to expand to twice their original size
|
|
const F32 EXPANSION_MAX = 1.5f; // maximum size scale to which the waves can expand before popping back to 1.0
|
|
const F32 WAVE_WIDTH_SCALE = 0.03f; // base width of the waves
|
|
const F32 WAVE_HEIGHT_SCALE = 0.02f; // base height of the waves
|
|
const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when quiet (below green threshold)
|
|
const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture
|
|
const F32 DOT_OPACITY = 0.7f; // how opaque the dot is
|
|
const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// gesticulation constants
|
|
//--------------------------------------------------------------------------------------
|
|
const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f;
|
|
const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f;
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// other constants
|
|
//--------------------------------------------------------------------------------------
|
|
const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.
|
|
const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
// handles parameter updates
|
|
//------------------------------------------------------------------
|
|
static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue)
|
|
{
|
|
// Note: Ignore the specific event value, we look up the ones we want
|
|
LLVoiceVisualizer::setPreferences();
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// Initialize the statics
|
|
//------------------------------------------------------------------
|
|
bool LLVoiceVisualizer::sPrefsInitialized = false;
|
|
BOOL LLVoiceVisualizer::sLipSyncEnabled = FALSE;
|
|
F32* LLVoiceVisualizer::sOoh = NULL;
|
|
F32* LLVoiceVisualizer::sAah = NULL;
|
|
U32 LLVoiceVisualizer::sOohs = 0;
|
|
U32 LLVoiceVisualizer::sAahs = 0;
|
|
F32 LLVoiceVisualizer::sOohAahRate = 0.0f;
|
|
F32* LLVoiceVisualizer::sOohPowerTransfer = NULL;
|
|
U32 LLVoiceVisualizer::sOohPowerTransfers = 0;
|
|
F32 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f;
|
|
F32* LLVoiceVisualizer::sAahPowerTransfer = NULL;
|
|
U32 LLVoiceVisualizer::sAahPowerTransfers = 0;
|
|
F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f;
|
|
|
|
|
|
//-----------------------------------------------
|
|
// constructor
|
|
//-----------------------------------------------
|
|
LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
|
|
:LLHUDEffect( type )
|
|
{
|
|
mCurrentTime = mTimer.getTotalSeconds();
|
|
mPreviousTime = mCurrentTime;
|
|
mStartTime = mCurrentTime;
|
|
mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f );
|
|
mSpeakingAmplitude = 0.0f;
|
|
mCurrentlySpeaking = false;
|
|
mVoiceEnabled = false;
|
|
mMinGesticulationAmplitude = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE;
|
|
mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;
|
|
mSoundSymbol.mActive = true;
|
|
mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f );
|
|
|
|
mTimer.reset();
|
|
|
|
const char* sound_level_img[] =
|
|
{
|
|
"041ee5a0-cb6a-9ac5-6e49-41e9320507d5.j2c",
|
|
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
|
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
|
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
|
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
|
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
|
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c"
|
|
};
|
|
|
|
for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
|
|
{
|
|
mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
|
|
mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI);
|
|
mSoundSymbol.mWaveActive [i] = false;
|
|
mSoundSymbol.mWaveOpacity [i] = 1.0f;
|
|
mSoundSymbol.mWaveExpansion [i] = 1.0f;
|
|
}
|
|
|
|
mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
|
|
|
|
// The first instance loads the initial state from prefs.
|
|
if (!sPrefsInitialized)
|
|
{
|
|
setPreferences();
|
|
|
|
// Set up our listener to get updates on all prefs values we care about.
|
|
gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
|
gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
|
gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
|
gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
|
gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
|
gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
|
|
|
sPrefsInitialized = true;
|
|
}
|
|
|
|
}//---------------------------------------------------
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )
|
|
{
|
|
mMinGesticulationAmplitude = m;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m )
|
|
{
|
|
mMaxGesticulationAmplitude = m;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setVoiceEnabled( bool v )
|
|
{
|
|
mVoiceEnabled = v;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setStartSpeaking()
|
|
{
|
|
mStartTime = mTimer.getTotalSeconds();
|
|
mCurrentlySpeaking = true;
|
|
mSoundSymbol.mActive = true;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
bool LLVoiceVisualizer::getCurrentlySpeaking()
|
|
{
|
|
return mCurrentlySpeaking;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setStopSpeaking()
|
|
{
|
|
mCurrentlySpeaking = false;
|
|
mSpeakingAmplitude = 0.0f;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )
|
|
{
|
|
mSpeakingAmplitude = a;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setPreferences( )
|
|
{
|
|
sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled");
|
|
sOohAahRate = gSavedSettings.getF32("LipSyncOohAahRate");
|
|
|
|
std::string oohString = gSavedSettings.getString("LipSyncOoh");
|
|
lipStringToF32s (oohString, sOoh, sOohs);
|
|
|
|
std::string aahString = gSavedSettings.getString("LipSyncAah");
|
|
lipStringToF32s (aahString, sAah, sAahs);
|
|
|
|
std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer");
|
|
lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers);
|
|
sOohPowerTransfersf = (F32) sOohPowerTransfers;
|
|
|
|
std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer");
|
|
lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers);
|
|
sAahPowerTransfersf = (F32) sAahPowerTransfers;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
// convert a string of digits to an array of floats.
|
|
// the result for each digit is the value of the
|
|
// digit multiplied by 0.11
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s )
|
|
{
|
|
delete[] out_F32s; // get rid of the current array
|
|
|
|
count_F32s = in_string.length();
|
|
if (count_F32s == 0)
|
|
{
|
|
// we don't like zero length arrays
|
|
|
|
count_F32s = 1;
|
|
out_F32s = new F32[1];
|
|
out_F32s[0] = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
out_F32s = new F32[count_F32s];
|
|
|
|
for (U32 i=0; i<count_F32s; i++)
|
|
{
|
|
// we convert the characters 0 to 9 to their numeric value
|
|
// anything else we take the low order four bits with a ceiling of 9
|
|
|
|
U8 digit = in_string[i];
|
|
U8 four_bits = digit % 16;
|
|
if (four_bits > 9)
|
|
{
|
|
four_bits = 9;
|
|
}
|
|
out_F32s[i] = 0.11f * (F32) four_bits;
|
|
}
|
|
}
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// find the amount to blend the ooh and aah mouth morphs
|
|
//--------------------------------------------------------------------------
|
|
void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah )
|
|
{
|
|
if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking )
|
|
{
|
|
U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude);
|
|
if (transfer_index >= sOohPowerTransfers)
|
|
{
|
|
transfer_index = sOohPowerTransfers - 1;
|
|
}
|
|
F32 transfer_ooh = sOohPowerTransfer[transfer_index];
|
|
|
|
transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude);
|
|
if (transfer_index >= sAahPowerTransfers)
|
|
{
|
|
transfer_index = sAahPowerTransfers - 1;
|
|
}
|
|
F32 transfer_aah = sAahPowerTransfer[transfer_index];
|
|
|
|
F64 current_time = mTimer.getTotalSeconds();
|
|
F64 elapsed_time = current_time - mStartTime;
|
|
U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate);
|
|
U32 elapsed_oohs = elapsed_frames % sOohs;
|
|
U32 elapsed_aahs = elapsed_frames % sAahs;
|
|
|
|
ooh = transfer_ooh * sOoh[elapsed_oohs];
|
|
aah = transfer_aah * sAah[elapsed_aahs];
|
|
|
|
/*
|
|
llinfos << " elapsed frames " << elapsed_frames
|
|
<< " ooh " << ooh
|
|
<< " aah " << aah
|
|
<< " transfer ooh" << transfer_ooh
|
|
<< " transfer aah" << transfer_aah
|
|
<< " start time " << mStartTime
|
|
<< " current time " << current_time
|
|
<< " elapsed time " << elapsed_time
|
|
<< " elapsed oohs " << elapsed_oohs
|
|
<< " elapsed aahs " << elapsed_aahs
|
|
<< llendl;
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
ooh = 0.0f;
|
|
aah = 0.0f;
|
|
}
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
// this method is inherited from HUD Effect
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::render()
|
|
{
|
|
if ( ! mVoiceEnabled )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( mSoundSymbol.mActive )
|
|
{
|
|
mPreviousTime = mCurrentTime;
|
|
mCurrentTime = mTimer.getTotalSeconds();
|
|
|
|
//---------------------------------------------------------------
|
|
// set the sound symbol position over the source (avatar's head)
|
|
//---------------------------------------------------------------
|
|
mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD;
|
|
|
|
//---------------------------------------------------------------
|
|
// some gl state
|
|
//---------------------------------------------------------------
|
|
LLGLSPipelineAlpha alpha_blend;
|
|
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
|
|
|
|
//-------------------------------------------------------------
|
|
// create coordinates of the geometry for the dot
|
|
//-------------------------------------------------------------
|
|
LLViewerCamera* camera = LLViewerCamera::getInstance();
|
|
LLVector3 l = camera->getLeftAxis() * DOT_SIZE;
|
|
LLVector3 u = camera->getUpAxis() * DOT_SIZE;
|
|
|
|
LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
|
|
LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
|
|
LLVector3 topLeft = mSoundSymbol.mPosition + l + u;
|
|
LLVector3 topRight = mSoundSymbol.mPosition - l + u;
|
|
|
|
//-----------------------------
|
|
// bind texture 0 (the dot)
|
|
//-----------------------------
|
|
gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]);
|
|
|
|
//-------------------------------------------------------------
|
|
// now render the dot
|
|
//-------------------------------------------------------------
|
|
gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );
|
|
|
|
gGL.begin( LLRender::TRIANGLE_STRIP );
|
|
gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV );
|
|
gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
|
|
gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
|
|
gGL.end();
|
|
|
|
gGL.begin( LLRender::TRIANGLE_STRIP );
|
|
gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
|
|
gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV );
|
|
gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
|
|
gGL.end();
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// if currently speaking, trigger waves (1 through 6) based on speaking amplitude
|
|
//--------------------------------------------------------------------------------------
|
|
if ( mCurrentlySpeaking )
|
|
{
|
|
F32 min = 0.2f;
|
|
F32 max = 0.7f;
|
|
F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min );
|
|
|
|
// in case mSpeakingAmplitude > max....
|
|
if ( fraction > 1.0f )
|
|
{
|
|
fraction = 1.0f;
|
|
}
|
|
|
|
S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) );
|
|
|
|
for (int i=0; i<level+1; i++)
|
|
{
|
|
mSoundSymbol.mWaveActive [i] = true;
|
|
mSoundSymbol.mWaveOpacity [i] = 1.0f;
|
|
mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
|
|
}
|
|
|
|
} // if currently speaking
|
|
|
|
//---------------------------------------------------
|
|
// determine color
|
|
//---------------------------------------------------
|
|
F32 red = 0.0f;
|
|
F32 green = 0.0f;
|
|
F32 blue = 0.0f;
|
|
if ( mSpeakingAmplitude < RED_THRESHOLD )
|
|
{
|
|
if ( mSpeakingAmplitude < GREEN_THRESHOLD )
|
|
{
|
|
red = BASE_BRIGHTNESS;
|
|
green = BASE_BRIGHTNESS;
|
|
blue = BASE_BRIGHTNESS;
|
|
}
|
|
else
|
|
{
|
|
//---------------------------------------------------
|
|
// fade from gray to bright green
|
|
//---------------------------------------------------
|
|
F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD );
|
|
red = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
|
|
green = BASE_BRIGHTNESS + fraction * ( 1.0f - BASE_BRIGHTNESS );
|
|
blue = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//---------------------------------------------------
|
|
// redish
|
|
//---------------------------------------------------
|
|
red = 1.0f;
|
|
green = 0.2f;
|
|
blue = 0.2f;
|
|
}
|
|
|
|
for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
|
|
{
|
|
if ( mSoundSymbol.mWaveActive[i] )
|
|
{
|
|
F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION;
|
|
|
|
mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction;
|
|
|
|
if ( mSoundSymbol.mWaveOpacity[i] < 0.0f )
|
|
{
|
|
mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
|
|
mSoundSymbol.mWaveOpacity [i] = 0.0f;
|
|
mSoundSymbol.mWaveActive [i] = false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------
|
|
// This is where we calculate the expansion of the waves - that is, the
|
|
// rate at which they are scaled greater than 1.0 so that they grow over time.
|
|
//----------------------------------------------------------------------------------
|
|
F32 timeSlice = (F32)( mCurrentTime - mPreviousTime );
|
|
F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE;
|
|
mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed );
|
|
|
|
if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX )
|
|
{
|
|
mSoundSymbol.mWaveExpansion[i] = 1.0f;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------
|
|
// create geometry for the wave billboard textures
|
|
//----------------------------------------------------------------------------------
|
|
F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i];
|
|
F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];
|
|
|
|
LLVector3 l = camera->getLeftAxis() * width;
|
|
LLVector3 u = camera->getUpAxis() * height;
|
|
|
|
LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
|
|
LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
|
|
LLVector3 topLeft = mSoundSymbol.mPosition + l + u;
|
|
LLVector3 topRight = mSoundSymbol.mPosition - l + u;
|
|
|
|
gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );
|
|
gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]);
|
|
|
|
|
|
//---------------------------------------------------
|
|
// now, render the mofo
|
|
//---------------------------------------------------
|
|
gGL.begin( LLRender::TRIANGLE_STRIP );
|
|
gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV );
|
|
gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
|
|
gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
|
|
gGL.end();
|
|
|
|
gGL.begin( LLRender::TRIANGLE_STRIP );
|
|
gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
|
|
gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV );
|
|
gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
|
|
gGL.end();
|
|
|
|
} //if ( mSoundSymbol.mWaveActive[i] )
|
|
|
|
}// for loop
|
|
|
|
}//if ( mSoundSymbol.mActive )
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )
|
|
{
|
|
mVoiceSourceWorldPosition = p;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
//---------------------------------------------------
|
|
VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel()
|
|
{
|
|
VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default
|
|
|
|
//-----------------------------------------------------------------------------------------
|
|
// Within the range of gesticulation amplitudes, the sound signal is split into
|
|
// three equal amplitude regimes, each specifying one of three gesticulation levels.
|
|
//-----------------------------------------------------------------------------------------
|
|
F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude;
|
|
|
|
if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH; }
|
|
else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM; }
|
|
else if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f ) { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW; }
|
|
|
|
return gesticulationLevel;
|
|
|
|
}//---------------------------------------------------
|
|
|
|
|
|
|
|
//------------------------------------
|
|
// Destructor
|
|
//------------------------------------
|
|
LLVoiceVisualizer::~LLVoiceVisualizer()
|
|
{
|
|
}//----------------------------------------------
|
|
|
|
|
|
//---------------------------------------------------
|
|
// "packData" is inherited from HUDEffect
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys)
|
|
{
|
|
// Pack the default data
|
|
LLHUDEffect::packData(mesgsys);
|
|
|
|
// TODO -- pack the relevant data for voice effects
|
|
// we'll come up with some cool configurations....TBD
|
|
//U8 packed_data[41];
|
|
//mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
|
|
U8 packed_data = 0;
|
|
mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------
|
|
// "unpackData" is inherited from HUDEffect
|
|
//---------------------------------------------------
|
|
void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
|
|
{
|
|
// TODO -- find the speaker, unpack binary data, set the properties of this effect
|
|
/*
|
|
LLHUDEffect::unpackData(mesgsys, blocknum);
|
|
LLUUID source_id;
|
|
LLUUID target_id;
|
|
S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
|
|
if (size != 1)
|
|
{
|
|
llwarns << "Voice effect with bad size " << size << llendl;
|
|
return;
|
|
}
|
|
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum);
|
|
*/
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
// this method is inherited from HUD Effect
|
|
//------------------------------------------------------------------
|
|
void LLVoiceVisualizer::markDead()
|
|
{
|
|
mCurrentlySpeaking = false;
|
|
mVoiceEnabled = false;
|
|
mSoundSymbol.mActive = false;
|
|
|
|
LLHUDEffect::markDead();
|
|
}//------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|