diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index c86d37e283..b008a20aa7 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -231,22 +231,10 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio; delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; - __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], - _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET], - _clientSamples[delayedChannelIndex], - _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET]); - __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], - delayBufferSample[0], delayBufferSample[1]); - - // perform the MMX add (with saturation) of two correct and delayed samples - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addedSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - // assign the results from the result of the mmx arithmetic - _clientSamples[s + goodChannelOffset] = shortResults[3]; - _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] = shortResults[2]; - _clientSamples[delayedChannelIndex] = shortResults[1]; - _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] = shortResults[0]; + _clientSamples[s + goodChannelOffset] += correctBufferSample[0]; + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] += correctBufferSample[1]; + _clientSamples[delayedChannelIndex] += delayBufferSample[0]; + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] += delayBufferSample[1]; } // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid @@ -266,74 +254,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; } - int i = 0; - - while (i + 3 < numSamplesDelay) { - // handle the first cases where we can MMX add four samples at once + for (int i = 0; i < numSamplesDelay; i++) { int parentIndex = i * 2; - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], - _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio); - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; - _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[0]; - - // push the index - i += 4; - } - - int parentIndex = i * 2; - - if (i + 2 < numSamplesDelay) { - // MMX add only three delayed samples - - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], - 0); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, - 0); - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; - - } else if (i + 1 < numSamplesDelay) { - // MMX add two delayed samples - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], - 0, 0); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); - - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; - - } else if (i < numSamplesDelay) { - // MMX add a single delayed sample - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], 0, 0, 0); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, 0, 0, 0); - - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; } } } else { diff --git a/examples/avatarLocalLight.js b/examples/avatarLocalLight.js index 57f9d84ffe..225ed4d755 100644 --- a/examples/avatarLocalLight.js +++ b/examples/avatarLocalLight.js @@ -10,12 +10,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var localLightDirections = [ {x: 1.0, y:0.0, z: 0.0}, {x: 0.0, y:1.0, z: 1.0}, {x: 0.0, y:0.0, z: 1.0}, {x: 1.0, y:1.0, z: 1.0} ]; -var localLightColors = [ {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0} ]; +var localLightDirections = [ {x: 1.0, y:1.0, z: 0.0}, {x: 0.0, y:1.0, z: 1.0} ]; +var localLightColors = [ {x: 0.0, y:1.0, z: 0.0}, {x: 1.0, y:0.0, z: 0.0} ]; var currentSelection = 0; var currentNumLights = 1; var maxNumLights = 2; +var currentNumAvatars = 0; +var avatarHashIDs = []; function keyPressEvent(event) { @@ -43,7 +45,8 @@ function keyPressEvent(event) { localLightColors[currentSelection].x = 0.0; } - MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection); + setAllLightColors(); + print("CHANGE RED light " + currentSelection + " color (" + localLightColors[currentSelection].x + ", " + localLightColors[currentSelection].y + ", " + localLightColors[currentSelection].z + " )" ); } else if (event.text == "6" ) { localLightColors[currentSelection].y += 0.01; @@ -51,7 +54,8 @@ function keyPressEvent(event) { localLightColors[currentSelection].y = 0.0; } - MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection); + setAllLightColors(); + print("CHANGE GREEN light " + currentSelection + " color (" + localLightColors[currentSelection].x + ", " + localLightColors[currentSelection].y + ", " + localLightColors[currentSelection].z + " )" ); } else if (event.text == "7" ) { localLightColors[currentSelection].z += 0.01; @@ -59,7 +63,8 @@ function keyPressEvent(event) { localLightColors[currentSelection].z = 0.0; } - MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection); + setAllLightColors(); + print("CHANGE BLUE light " + currentSelection + " color (" + localLightColors[currentSelection].x + ", " + localLightColors[currentSelection].y + ", " + localLightColors[currentSelection].z + " )" ); } else if (event.text == "8" ) { localLightDirections[currentSelection].x += 0.01; @@ -67,7 +72,8 @@ function keyPressEvent(event) { localLightDirections[currentSelection].x = -1.0; } - MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + setAllLightDirections(); + print("PLUS X light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); } else if (event.text == "9" ) { localLightDirections[currentSelection].x -= 0.01; @@ -75,52 +81,117 @@ function keyPressEvent(event) { localLightDirections[currentSelection].x = 1.0; } - MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + setAllLightDirections(); + print("MINUS X light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); } - else if (event.text == "[" ) { + else if (event.text == "0" ) { localLightDirections[currentSelection].y += 0.01; if (localLightDirections[currentSelection].y > 1.0) { localLightDirections[currentSelection].y = -1.0; } - MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + setAllLightDirections(); + print("PLUS Y light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); } - else if (event.text == "]" ) { + else if (event.text == "-" ) { localLightDirections[currentSelection].y -= 0.01; if (localLightDirections[currentSelection].y < -1.0) { localLightDirections[currentSelection].y = 1.0; } - MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + setAllLightDirections(); + print("MINUS Y light " + currentSelection + " direction (" + localLightDirections[currentSelection].x + ", " + localLightDirections[currentSelection].y + ", " + localLightDirections[currentSelection].z + " )" ); } else if (event.text == "," ) { if (currentNumLights + 1 <= maxNumLights) { - var darkGrayColor = {x:0.3, y:0.3, z:0.3}; - - // default light - localLightColors[currentNumLights].x = darkGrayColor.x; - localLightColors[currentNumLights].y = darkGrayColor.y; - localLightColors[currentNumLights].z = darkGrayColor.z; - - MyAvatar.addLocalLight(); - MyAvatar.setLocalLightColor(localLightColors[currentNumLights], currentNumLights); - MyAvatar.setLocalLightDirection(localLightDirections[currentNumLights], currentNumLights); - ++currentNumLights; + + for (var i = 0; i < currentNumAvatars; i++) { + AvatarManager.addAvatarLocalLight(i); + + for (var j = 0; j < currentNumLights; j++) { + AvatarManager.setAvatarLightColor(localLightColors[j], j, i); + AvatarManager.setAvatarLightDirection(localLightDirections[j], j, i); + } + } } + + print("ADD LIGHT, number of lights " + currentNumLights); } else if (event.text == "." ) { if (currentNumLights - 1 >= 0 ) { - - // no light contribution - localLightColors[currentNumLights - 1].x = 0.0; - localLightColors[currentNumLights - 1].y = 0.0; - localLightColors[currentNumLights - 1].z = 0.0; - - MyAvatar.removeLocalLight(); --currentNumLights; + + for (var i = 0; i < currentNumAvatars; i++) { + AvatarManager.removeAvatarLocalLight(i); + + for (var j = 0; j < currentNumLights; j++) { + AvatarManager.setAvatarLightColor(localLightColors[j], j, i); + AvatarManager.setAvatarLightDirection(localLightDirections[j], j, i); + } + } + } + + print("REMOVE LIGHT, number of lights " + currentNumLights); } } +function updateLocalLights() +{ + // new avatars, so add lights + var numAvatars = AvatarManager.getNumAvatars(); + if (numAvatars != currentNumAvatars) { + + for (var i = 0; i < numAvatars; i++) { + var id = AvatarManager.getAvatarHashKey(i); + + // check if avatar has already been registered + var hasRegistered = false; + for (var j = 0; j < numAvatars; j++) { + if (avatarHashIDs[j] == id) { + hasRegistered = true; + break; + } + } + + // add new id and set light params + if (!hasRegistered) { + + avatarHashIDs.push(id); + AvatarManager.addAvatarLocalLight(i); + + // set color and direction for new avatar + for (var j = 0; j < maxNumLights; j++) { + AvatarManager.setAvatarLightColor(localLightColors[j], j, i); + AvatarManager.setAvatarLightDirection(localLightDirections[j], j, i); + } + } + } + + currentNumAvatars = numAvatars; + } +} + +function setAllLightColors() +{ + for (var i = 0; i < currentNumAvatars; i++) { + for (var j = 0; j < maxNumLights; j++) { + AvatarManager.setAvatarLightColor(localLightColors[j], j, i); + } + } +} + +function setAllLightDirections() +{ + for (var i = 0; i < currentNumAvatars; i++) { + for (var j = 0; j < maxNumLights; j++) { + AvatarManager.setAvatarLightDirection(localLightDirections[j], j, i); + } + } +} + +// main +Script.update.connect(updateLocalLights); Controller.keyPressEvent.connect(keyPressEvent); + diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7219a019d4..bc6db5d7b6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3643,6 +3643,8 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); + scriptEngine->registerGlobalObject("AvatarManager", &_avatarManager); + #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); #endif diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index fd8f2d836b..461956b3c7 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -60,7 +60,7 @@ Avatar::Avatar() : _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _collisionGroups(0), - _numLocalLights(2), + _numLocalLights(0), _initialized(false), _shouldRenderBillboard(true) { @@ -82,23 +82,6 @@ void Avatar::init() { _skeletonModel.init(); _initialized = true; _shouldRenderBillboard = (getLODDistance() >= BILLBOARD_LOD_DISTANCE); - - for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { - _localLightColors[i] = glm::vec3(0.0f, 0.0f, 0.0f); - _localLightDirections[i] = glm::vec3(0.0f, 0.0f, 0.0f); - } - - glm::vec3 darkGrayColor(0.4f, 0.4f, 0.4f); - glm::vec3 greenColor(0.0f, 1.0f, 0.0f); - glm::vec3 directionX(1.0f, 0.0f, 0.0f); - glm::vec3 directionY(0.0f, 1.0f, 0.0f); - - // initialize local lights - _localLightColors[0] = darkGrayColor; - _localLightColors[1] = darkGrayColor; - - _localLightDirections[0] = directionX; - _localLightDirections[1] = directionY; } glm::vec3 Avatar::getChestPosition() const { diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index debe6489ea..bc84aa6b87 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -158,3 +158,56 @@ void AvatarManager::clearOtherAvatars() { } _myAvatar->clearLookAtTargetAvatar(); } + +Avatar* AvatarManager::getAvatarFromIndex(int avatarIndex) { + Avatar* avatar = NULL; + int numAvatars = _avatarHash.count(); + if (avatarIndex < numAvatars) { + QUuid key = (_avatarHash.keys())[avatarIndex]; + + const AvatarSharedPointer& avatarPointer = _avatarHash.value(key); + avatar = static_cast(avatarPointer.data()); + } + + return avatar; +} + +void AvatarManager::addAvatarLocalLight(int avatarIndex) { + Avatar* avatar = getAvatarFromIndex(avatarIndex); + if (avatar) { + avatar->addLocalLight(); + } +} + +void AvatarManager::removeAvatarLocalLight(int avatarIndex) { + Avatar* avatar = getAvatarFromIndex(avatarIndex); + if (avatar) { + avatar->removeLocalLight(); + } +} + +void AvatarManager::setAvatarLightDirection(const glm::vec3& direction, int lightIndex, int avatarIndex) { + Avatar* avatar = getAvatarFromIndex(avatarIndex); + if (avatar) { + avatar->setLocalLightDirection(direction, lightIndex); + } +} + +void AvatarManager::setAvatarLightColor(const glm::vec3& color, int lightIndex, int avatarIndex) { + Avatar* avatar = getAvatarFromIndex(avatarIndex); + if (avatar) { + avatar->setLocalLightColor(color, lightIndex); + } +} + +int AvatarManager::getNumAvatars() { + return _avatarHash.count(); +} + +QString AvatarManager::getAvatarHashKey(int index) { + QString id = ((_avatarHash.keys())[index]).toString(); + std::string idString = id.toStdString(); + return id; +} + + diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 048844ddf2..f2b5904883 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -24,6 +24,7 @@ class MyAvatar; class AvatarManager : public AvatarHashMap { Q_OBJECT + public: AvatarManager(QObject* parent = 0); @@ -36,6 +37,14 @@ public: void clearOtherAvatars(); +public slots: + void setAvatarLightColor(const glm::vec3& color, int lightIndex, int avatarIndex); + void setAvatarLightDirection(const glm::vec3& direction, int lightIndex, int avatarIndex); + void removeAvatarLocalLight(int avatarIndex); + void addAvatarLocalLight(int avatarIndex); + int getNumAvatars(); + QString getAvatarHashKey(int index); + private: AvatarManager(const AvatarManager& other); @@ -44,6 +53,8 @@ private: AvatarSharedPointer newSharedAvatar(); + Avatar* getAvatarFromIndex(int avatarIndex); + // virtual override AvatarHash::iterator erase(const AvatarHash::iterator& iterator); diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 8cba6d72b0..6c7ecd1cad 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -135,7 +135,6 @@ void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() { const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; const float LOUDNESS_EPSILON = 0.000001f; - float oldNextOutputTrailingLoudness = _nextOutputTrailingLoudness; if (nextLoudness >= _nextOutputTrailingLoudness) { _nextOutputTrailingLoudness = nextLoudness; } else { @@ -145,12 +144,6 @@ void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() { _nextOutputTrailingLoudness = 0; } } - - // fixes bug on Windows where _nextOutputTrailingLoudness sometimes becomes NaN. In that case, - // revert _nextOutputTrailingLoudness to its previous value - if (isNaN(_nextOutputTrailingLoudness)) { - _nextOutputTrailingLoudness = oldNextOutputTrailingLoudness; - } } bool PositionalAudioRingBuffer::shouldBeAddedToMix() {