From fdf5860c4f68540a024ab4c6bcc0fa185285293c Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 18 Jun 2015 10:39:58 -0700 Subject: [PATCH 01/37] Refactor playSound. --- libraries/audio-client/src/AudioClient.cpp | 69 +++++++++++++++++++ libraries/audio-client/src/AudioClient.h | 5 ++ libraries/entities-renderer/CMakeLists.txt | 6 -- .../src/EntityTreeRenderer.cpp | 61 +--------------- .../src/EntityTreeRenderer.h | 1 - libraries/script-engine/CMakeLists.txt | 2 +- .../src/AudioScriptingInterface.cpp | 20 +----- 7 files changed, 80 insertions(+), 84 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 84022d0fb9..6d8095ccf0 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -45,6 +45,7 @@ extern "C" { #include #include #include +#include #include #include "AudioInjector.h" @@ -1338,3 +1339,71 @@ void AudioClient::audioStateChanged(QAudio::State state) { emit audioFinished(); } } + +AudioInjector* AudioClient::playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position) { + if (soundUrl.isEmpty()) { + return NULL; + } + auto soundCache = DependencyManager::get(); + if (soundCache.isNull()) { + return NULL; + } + SharedSoundPointer sound = soundCache.data()->getSound(QUrl(soundUrl)); + if (sound.isNull() || !sound->isReady()) { + return NULL; + } + + // Quiet sound aren't really heard at all, so we can compress everything to the range [1-c, 1], if we play it all. + const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes. + const float compressedVolume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE); + + // This is quite similar to AudioScriptingInterface::playSound() and should probably be refactored. + AudioInjectorOptions options; + options.stereo = sound->isStereo(); + options.position = position; + options.volume = compressedVolume; + + QByteArray samples = sound->getByteArray(); + if (stretchFactor == 1.0f) { + return playSound(samples, options); + } + + soxr_io_spec_t spec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I); + soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_MQ, 0); + const int channelCount = sound->isStereo() ? 2 : 1; + const int standardRate = AudioConstants::SAMPLE_RATE; + const int resampledRate = standardRate * stretchFactor; + const int nInputSamples = samples.size() / sizeof(int16_t); + const int nOutputSamples = nInputSamples * stretchFactor; + QByteArray resampled(nOutputSamples * sizeof(int16_t), '\0'); + const int16_t* receivedSamples = reinterpret_cast(samples.data()); + soxr_error_t soxError = soxr_oneshot(standardRate, resampledRate, channelCount, + receivedSamples, nInputSamples, NULL, + reinterpret_cast(resampled.data()), nOutputSamples, NULL, + &spec, &qualitySpec, 0); + if (soxError) { + qCDebug(audioclient) << "Unable to resample" << soundUrl << "from" << nInputSamples << "@" << standardRate << "to" << nOutputSamples << "@" << resampledRate; + resampled = samples; + } + return playSound(resampled, options); +} + +AudioInjector* AudioClient::playSound(const QByteArray& buffer, const AudioInjectorOptions options) { + QThread* injectorThread = new QThread(); + injectorThread->setObjectName("Audio Injector Thread"); + + AudioInjector* injector = new AudioInjector(buffer, options); + injector->setLocalAudioInterface(this); + + injector->moveToThread(injectorThread); + + // start injecting when the injector thread starts + connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); + + // connect the right slots and signals for AudioInjector and thread cleanup + connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit); + connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); + + injectorThread->start(); + return injector; +} diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index d2492e1064..93afb71fef 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -40,6 +40,7 @@ #include #include +#include "AudioInjector.h" #include "AudioIOStats.h" #include "AudioNoiseGate.h" @@ -130,6 +131,10 @@ public: static const float CALLBACK_ACCELERATOR_RATIO; + AudioInjector* playSound(const QByteArray& buffer, const AudioInjectorOptions options); + AudioInjector* playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position); + + public slots: void start(); void stop(); diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 19cc8d8412..40ca1ccbc9 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -17,10 +17,4 @@ find_package(PolyVox REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES}) -# for changing the pitch of collision sounds -add_dependency_external_projects(soxr) -find_package(Soxr REQUIRED) -target_link_libraries(${TARGET_NAME} ${SOXR_LIBRARIES}) -target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SOXR_INCLUDE_DIRS}) - link_hifi_libraries(shared gpu script-engine render render-utils) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e1bd01547e..f2d015960c 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -27,10 +28,6 @@ #include #include #include -#include -#include -#include - #include "EntityTreeRenderer.h" @@ -57,7 +54,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf _wantScripts(wantScripts), _entitiesScriptEngine(NULL), _sandboxScriptEngine(NULL), - _localAudioInterface(NULL), _lastMouseEventValid(false), _viewState(viewState), _scriptingServices(scriptingServices), @@ -1057,7 +1053,6 @@ void EntityTreeRenderer::checkAndCallUnload(const EntityItemID& entityID) { } } - void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision) { EntityItemPointer entity = entityTree->findEntityByEntityItemID(id); if (!entity) { @@ -1101,60 +1096,10 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT return; } - auto soundCache = DependencyManager::get(); - if (soundCache.isNull()) { - return; - } - SharedSoundPointer sound = soundCache.data()->getSound(QUrl(collisionSoundURL)); - if (sound.isNull() || !sound->isReady()) { - return; - } - - // This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all. - const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes. - float volume = energyFactorOfFull; - volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE); - - // This is quite similar to AudioScriptingInterface::playSound() and should probably be refactored. - AudioInjectorOptions options; - options.stereo = sound->isStereo(); - options.position = position; - options.volume = volume; - // Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2) const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f; - QByteArray samples = sound->getByteArray(); - soxr_io_spec_t spec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I); - soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_MQ, 0); - const int channelCount = sound->isStereo() ? 2 : 1; - const float factor = log(1.0f + (entity->getMinimumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); - const int standardRate = AudioConstants::SAMPLE_RATE; - const int resampledRate = standardRate * factor; - const int nInputSamples = samples.size() / sizeof(int16_t); - const int nOutputSamples = nInputSamples * factor; - QByteArray resampled(nOutputSamples * sizeof(int16_t), '\0'); - const int16_t* receivedSamples = reinterpret_cast(samples.data()); - soxr_error_t soxError = soxr_oneshot(standardRate, resampledRate, channelCount, - receivedSamples, nInputSamples, NULL, - reinterpret_cast(resampled.data()), nOutputSamples, NULL, - &spec, &qualitySpec, 0); - if (soxError) { - qCDebug(entitiesrenderer) << "Unable to resample" << collisionSoundURL << "from" << nInputSamples << "@" << standardRate << "to" << nOutputSamples << "@" << resampledRate; - resampled = samples; - } - - AudioInjector* injector = new AudioInjector(resampled, options); - injector->setLocalAudioInterface(_localAudioInterface); - injector->triggerDeleteAfterFinish(); - QThread* injectorThread = new QThread(); - injectorThread->setObjectName("Audio Injector Thread"); - injector->moveToThread(injectorThread); - // start injecting when the injector thread starts - connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); - // connect the right slots and signals for AudioInjector and thread cleanup - connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit); - connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); - injectorThread->start(); + const float stretchFactor = log(1.0f + (entity->getMinimumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); + DependencyManager::get()->playSound(collisionSoundURL, energyFactorOfFull, stretchFactor, position); } void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index e491524c78..56a8208eb4 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -158,7 +158,6 @@ private: QHash _entityScripts; void playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision); - AbstractAudioInterface* _localAudioInterface; // So we can render collision sounds bool _lastMouseEventValid; MouseEvent _lastMouseEvent; diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 99d9149c3a..78db92b4f1 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -7,4 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared octree gpu model fbx entities animation audio physics) +link_hifi_libraries(shared octree gpu model fbx entities animation audio audio-client physics) diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index 9e3e924933..0b55ed1bca 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -11,6 +11,7 @@ #include "AudioScriptingInterface.h" +#include "AudioClient.h" #include "ScriptAudioInjector.h" #include "ScriptEngineLogging.h" @@ -46,24 +47,7 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(Sound* sound, const Audi AudioInjectorOptions optionsCopy = injectorOptions; optionsCopy.stereo = sound->isStereo(); - QThread* injectorThread = new QThread(); - injectorThread->setObjectName("Audio Injector Thread"); - - AudioInjector* injector = new AudioInjector(sound, optionsCopy); - injector->setLocalAudioInterface(_localAudioInterface); - - injector->moveToThread(injectorThread); - - // start injecting when the injector thread starts - connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); - - // connect the right slots and signals for AudioInjector and thread cleanup - connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit); - connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); - - injectorThread->start(); - - return new ScriptAudioInjector(injector); + return new ScriptAudioInjector(DependencyManager::get()->playSound(sound->getByteArray(), optionsCopy)); } else { qCDebug(scriptengine) << "AudioScriptingInterface::playSound called with null Sound object."; From 1047703718f444d1b929d331b82b0289d2ed153f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Jun 2015 11:18:56 -0700 Subject: [PATCH 02/37] Tidy address bar code Re-enable and reposition mouse drag areas Remove unused graphics assets Remove unused includes --- interface/resources/images/darkgreyarrow.png | Bin 369 -> 0 bytes interface/resources/images/lightgreyarrow.png | Bin 369 -> 0 bytes interface/resources/images/lightgreyarrow.svg | 11 --- .../{darkgreyarrow.svg => right-arrow.svg} | 0 interface/resources/images/sepline.png | Bin 127 -> 0 bytes interface/resources/images/sepline.svg | 3 - interface/resources/qml/AddressBarDialog.qml | 63 +++++++++--------- .../src/EntityTreeRenderer.cpp | 3 - 8 files changed, 31 insertions(+), 49 deletions(-) delete mode 100644 interface/resources/images/darkgreyarrow.png delete mode 100644 interface/resources/images/lightgreyarrow.png delete mode 100644 interface/resources/images/lightgreyarrow.svg rename interface/resources/images/{darkgreyarrow.svg => right-arrow.svg} (100%) delete mode 100644 interface/resources/images/sepline.png delete mode 100644 interface/resources/images/sepline.svg diff --git a/interface/resources/images/darkgreyarrow.png b/interface/resources/images/darkgreyarrow.png deleted file mode 100644 index 4c9a8a2bbf69185a4a64bce1da6460ba0996b57a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369 zcmV-%0gnEOP)#J37rGx zfCU5K0F*EXn*jn2z`>A!gh|+IazDrdr7hPcmkYG{a=qSbFG(VdizKWliWIIVL7;~F zz%mj7mJGa_ZzTYH!IkTO>IBS0)x-4v90dY1-mc!7rvP9LH^S1rHOjMGO#bqtwd7GQ zqYKap3SiDa?Yb*E0JeO>sZZXOO>RaVA=N=PxrNp++2j^Flud5IP|ly%>AG%ziE>G^ z{94IKldkKYaCg{O49egM?gpEqyisSWVOOSzx`L}jp$vX=Iu7qIf$Mn|gRb&yz(bT?YD?ay+nz0Xi}X@b^0xL?KLG{+pmtFIQSBgb P00000NkvXXu0mjfAz_+$ diff --git a/interface/resources/images/lightgreyarrow.png b/interface/resources/images/lightgreyarrow.png deleted file mode 100644 index 1e221f3c73af148b0cde671a1d14ffdf9d43d75f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 369 zcmV-%0gnEOP)%^Hu`8V`qj`n;EIrpw7JNlQCp83a5T3eZtj_~t zrD7I4wj)DAr`U0xZ>a76s-r1fv6B%QU#+){ERVC^5>WL;y<XA9r8U7y*M$)1X#ML@Un$<^*$3PU?JUszyK(FG zOM=x~pRP9e$8qUVKYYf - - - - - - - - diff --git a/interface/resources/images/darkgreyarrow.svg b/interface/resources/images/right-arrow.svg similarity index 100% rename from interface/resources/images/darkgreyarrow.svg rename to interface/resources/images/right-arrow.svg diff --git a/interface/resources/images/sepline.png b/interface/resources/images/sepline.png deleted file mode 100644 index 959fcee72f740ca4de861595bf835dacad79b9fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU@+uhV_;yApCv5Gz`!6`;u=vBoS#-wo>-L1 z;Fyx1l&avFo0y&&l$w}QS$HzlhJk@W(bL5-q~cc6ojsMG>)13B7?ao~+B+FJdy3pF fuRLd9kzml|VXm>1eSCv~fq}u()z4*}Q$iB}btNK7 diff --git a/interface/resources/images/sepline.svg b/interface/resources/images/sepline.svg deleted file mode 100644 index 32afaf7148..0000000000 --- a/interface/resources/images/sepline.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -2015-06-12 18:23ZCanvas 1 Navi Bar diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 70cb22dc4d..7fa182fd93 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -45,6 +45,36 @@ DialogContainer { property int inputAreaHeight: 56.0 * root.scale // Height of the background's input area property int inputAreaStep: (height - inputAreaHeight) / 2 + MouseArea { + // Drag the icon + width: parent.height + height: parent.height + x: 0 + y: 0 + drag { + target: root + minimumX: -parent.inputAreaStep + minimumY: -parent.inputAreaStep + maximumX: root.parent ? root.maximumX : 0 + maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0 + } + } + + MouseArea { + // Drag the input rectangle + width: parent.width - parent.height + height: parent.inputAreaHeight + x: parent.height + y: parent.inputAreaStep + drag { + target: root + minimumX: -parent.inputAreaStep + minimumY: -parent.inputAreaStep + maximumX: root.parent ? root.maximumX : 0 + maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0 + } + } + Image { id: backArrow @@ -71,7 +101,7 @@ DialogContainer { Image { id: forwardArrow - source: "../images/darkgreyarrow.svg" + source: "../images/right-arrow.svg" anchors { fill: parent @@ -111,37 +141,6 @@ DialogContainer { addressBarDialog.loadAddress(addressLine.text) } } - - MouseArea { - // Drag the icon - width: parent.height - height: parent.height - x: 0 - y: 0 - drag { - target: root - minimumX: -parent.inputAreaStep - minimumY: -parent.inputAreaStep - maximumX: root.parent ? root.maximumX : 0 - maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0 - } - } - - /* - MouseArea { - // Drag the input rectangle - width: parent.width - parent.height - height: parent.inputAreaHeight - x: parent.height - y: parent.inputAreaStep - drag { - target: root - minimumX: -parent.inputAreaStep - minimumY: -parent.inputAreaStep - maximumX: root.parent ? root.maximumX : 0 - maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0 - } - }*/ } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e1bd01547e..61a0c0dbb5 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -48,9 +48,6 @@ #include "RenderablePolyVoxEntityItem.h" #include "EntitiesRendererLogging.h" -#include "DependencyManager.h" -#include "AddressManager.h" - EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, AbstractScriptingServicesInterface* scriptingServices) : OctreeRenderer(), From bffc1a38a7838fb96936cb926e5db07e63fc70e9 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 18 Jun 2015 12:33:05 -0700 Subject: [PATCH 03/37] Separate DC offset rejection, and call it all the time --- libraries/audio-client/src/AudioClient.cpp | 5 +++ libraries/audio-client/src/AudioNoiseGate.cpp | 44 ++++++++++++------- libraries/audio-client/src/AudioNoiseGate.h | 1 + 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 84022d0fb9..aea4d66cae 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -786,6 +786,11 @@ void AudioClient::handleAudioInput() { delete[] inputAudioSamples; + // Remove DC offset + if (!_isStereoInput && !_audioSourceInjectEnabled) { + _inputGate.removeDCOffset(networkAudioSamples, numNetworkSamples); + } + // only impose the noise gate and perform tone injection if we are sending mono audio if (!_isStereoInput && !_audioSourceInjectEnabled && _isNoiseGateEnabled) { _inputGate.gateSamples(networkAudioSamples, numNetworkSamples); diff --git a/libraries/audio-client/src/AudioNoiseGate.cpp b/libraries/audio-client/src/AudioNoiseGate.cpp index 77f230809f..062d21fb96 100644 --- a/libraries/audio-client/src/AudioNoiseGate.cpp +++ b/libraries/audio-client/src/AudioNoiseGate.cpp @@ -33,6 +33,33 @@ AudioNoiseGate::AudioNoiseGate() : } +void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) { + // + // DC Offset correction + // + // Measure the DC offset over a trailing number of frames, and remove it from the input signal. + // This causes the noise background measurements and server muting to be more accurate. Many off-board + // ADC's have a noticeable DC offset. + // + const float DC_OFFSET_AVERAGING = 0.99f; + float measuredDcOffset = 0.0f; + // Remove trailing DC offset from samples + for (int i = 0; i < numSamples; i++) { + measuredDcOffset += samples[i]; + samples[i] -= (int16_t) _dcOffset; + //samples[i] = 0; + } + // Update measured DC offset + measuredDcOffset /= numSamples; + if (_dcOffset == 0.0f) { + // On first frame, copy over measured offset + _dcOffset = measuredDcOffset; + } else { + _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; + } +} + + void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { // // Impose Noise Gate @@ -61,17 +88,12 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { const int NOISE_GATE_WIDTH = 5; const int NOISE_GATE_CLOSE_FRAME_DELAY = 5; const int NOISE_GATE_FRAMES_TO_AVERAGE = 5; - const float DC_OFFSET_AVERAGING = 0.99f; - - // Check clipping, adjust DC offset, and check if should open noise gate - float measuredDcOffset = 0.0f; + + // Check clipping, and check if should open noise gate _didClipInLastFrame = false; for (int i = 0; i < numSamples; i++) { - measuredDcOffset += samples[i]; - samples[i] -= (int16_t) _dcOffset; thisSample = std::abs(samples[i]); - if (thisSample >= ((float) AudioConstants::MAX_SAMPLE_VALUE * CLIPPING_THRESHOLD)) { _didClipInLastFrame = true; } @@ -83,14 +105,6 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { } } - measuredDcOffset /= numSamples; - if (_dcOffset == 0.0f) { - // On first frame, copy over measured offset - _dcOffset = measuredDcOffset; - } else { - _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; - } - _lastLoudness = fabs(loudness / numSamples); if (_quietestFrame > _lastLoudness) { diff --git a/libraries/audio-client/src/AudioNoiseGate.h b/libraries/audio-client/src/AudioNoiseGate.h index bfb9ec28d5..8cb1155938 100644 --- a/libraries/audio-client/src/AudioNoiseGate.h +++ b/libraries/audio-client/src/AudioNoiseGate.h @@ -21,6 +21,7 @@ public: AudioNoiseGate(); void gateSamples(int16_t* samples, int numSamples); + void removeDCOffset(int16_t* samples, int numSamples); bool clippedInLastFrame() const { return _didClipInLastFrame; } float getMeasuredFloor() const { return _measuredFloor; } From e46a8208728311b401e3f55bfec5cd617123521c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 18 Jun 2015 12:37:50 -0700 Subject: [PATCH 04/37] remove debug --- libraries/audio-client/src/AudioNoiseGate.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioNoiseGate.cpp b/libraries/audio-client/src/AudioNoiseGate.cpp index 062d21fb96..8766a20cdf 100644 --- a/libraries/audio-client/src/AudioNoiseGate.cpp +++ b/libraries/audio-client/src/AudioNoiseGate.cpp @@ -39,7 +39,7 @@ void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) { // // Measure the DC offset over a trailing number of frames, and remove it from the input signal. // This causes the noise background measurements and server muting to be more accurate. Many off-board - // ADC's have a noticeable DC offset. + // ADC's have a noticeable DC offset. // const float DC_OFFSET_AVERAGING = 0.99f; float measuredDcOffset = 0.0f; @@ -47,7 +47,6 @@ void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) { for (int i = 0; i < numSamples; i++) { measuredDcOffset += samples[i]; samples[i] -= (int16_t) _dcOffset; - //samples[i] = 0; } // Update measured DC offset measuredDcOffset /= numSamples; From 2b4146125f8da04fac811b2d996bc6f67b1a6521 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 16:27:06 -0700 Subject: [PATCH 05/37] adding logic to check points of line are inside bounds --- .../entities/src/EntityScriptingInterface.cpp | 41 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 4 ++ libraries/entities/src/LineEntityItem.cpp | 3 +- libraries/entities/src/LineEntityItem.h | 2 +- libraries/shared/src/RegisteredMetaTypes.cpp | 10 +++++ libraries/shared/src/RegisteredMetaTypes.h | 1 + 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index a091c786b7..e8de8b723b 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -442,6 +442,40 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID, return true; } +bool EntityScriptingInterface::setPoints(QUuid entityID, std::function actor) { + if (_entityTree) { + return false; + } + + EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID; + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::Line) { + return false; + } + + auto now = usecTimestampNow(); + + LineEntityItem* lineEntity = static_cast(entity.get()); + _entityTree->lockForWrite(); + bool success = actor(*lineEntity); + entity->setLastEdited(now); + entity->setLastBroadcast(now); + _entityTree->unlock(); + + _entityTree->lockForRead(); + EntityItemProperties properties = entity->getProperties(); + _entityTree->unlock(); + + properties.setLastEdited(now); + + queueEntityMessage(PacketTypeEntityEdit, entityID, properties); + return success; +} + bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) { return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) { polyVoxEntity.setSphere(center, radius, value); @@ -460,6 +494,13 @@ bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) { }); } +bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector& points) { + return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool + { + return lineEntity.setLinePoints(points); + }); +} + bool EntityScriptingInterface::actionWorker(const QUuid& entityID, std::function actor) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c6bc43c8c6..17183264b9 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -22,6 +22,7 @@ #include #include #include "PolyVoxEntityItem.h" +#include "LineEntityItem.h" #include "EntityEditPacketSender.h" @@ -121,6 +122,8 @@ public slots: Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value); Q_INVOKABLE bool setVoxel(QUuid entityID, const glm::vec3& position, int value); Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); + + Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); Q_INVOKABLE void dumpTree() const; @@ -157,6 +160,7 @@ signals: private: bool actionWorker(const QUuid& entityID, std::function actor); bool setVoxels(QUuid entityID, std::function actor); + bool setPoints(QUuid entityID, std::function actor); void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 094536f63a..6bc8c94f2f 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -85,7 +85,7 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } -void LineEntityItem::setLinePoints(const QVector& points) { +bool LineEntityItem::setLinePoints(const QVector& points) { QVector sanitizedPoints; int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { @@ -103,6 +103,7 @@ void LineEntityItem::setLinePoints(const QVector& points) { } _points = sanitizedPoints; _pointsChanged = true; + return true; } int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 5151244b3c..0918dd2d06 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -54,7 +54,7 @@ class LineEntityItem : public EntityItem { void setLineWidth(float lineWidth){ _lineWidth = lineWidth; } float getLineWidth() const{ return _lineWidth; } - void setLinePoints(const QVector& points); + bool setLinePoints(const QVector& points); const QVector& getLinePoints() const{ return _points; } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 241f835a46..5ad29abc08 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -93,6 +93,16 @@ QVector qVectorVec3FromScriptValue(const QScriptValue& array){ return newVector; } +void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& vector ) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + glm::vec3 newVec3 = glm::vec3(); + vec3FromScriptValue(array.property(i), newVec3); + vector << newVec3; + } +} + QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2) { QScriptValue obj = engine->newObject(); obj.setProperty("x", vec2.x); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 1dcc85107a..231878ab3a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -58,6 +58,7 @@ void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); +void qVectorVec3FromScriptValue( const QScriptValue& array, QVector vector); class PickRay { public: From 6a5deaaef127524259cf192a5b4b747d13174784 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 16:54:39 -0700 Subject: [PATCH 06/37] returning true from set line points --- libraries/entities/src/EntityScriptingInterface.cpp | 3 ++- libraries/shared/src/RegisteredMetaTypes.cpp | 2 ++ libraries/shared/src/RegisteredMetaTypes.h | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index e8de8b723b..69b31468d2 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -443,7 +443,7 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID, } bool EntityScriptingInterface::setPoints(QUuid entityID, std::function actor) { - if (_entityTree) { + if (!_entityTree) { return false; } @@ -453,6 +453,7 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::functiongetType(); + if (entityType != EntityTypes::Line) { return false; } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 5ad29abc08..50f87fe258 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -20,6 +20,7 @@ static int vec4MetaTypeId = qRegisterMetaType(); static int vec3MetaTypeId = qRegisterMetaType(); +static int qVectorVec3MetaTypeId = qRegisterMetaType>(); static int vec2MetaTypeId = qRegisterMetaType(); static int quatMetaTypeId = qRegisterMetaType(); static int xColorMetaTypeId = qRegisterMetaType(); @@ -31,6 +32,7 @@ static int collisionMetaTypeId = qRegisterMetaType(); void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue); qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue); + qScriptRegisterMetaType(engine, qVectorVec3ToScriptValue, qVectorVec3FromScriptValue); qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue); qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 231878ab3a..2ea2bb52fa 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -57,8 +57,9 @@ QScriptValue qURLToScriptValue(QScriptEngine* engine, const QUrl& url); void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorVec3FromScriptValue( const QScriptValue& array, QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); -void qVectorVec3FromScriptValue( const QScriptValue& array, QVector vector); + class PickRay { public: From 8183e7393d6b8ee0baab8d9a5782917a0a5d14c0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 17:00:27 -0700 Subject: [PATCH 07/37] adding check for points inside bounds' --- libraries/entities/src/LineEntityItem.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 6bc8c94f2f..955e827d92 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -86,22 +86,19 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { } bool LineEntityItem::setLinePoints(const QVector& points) { - QVector sanitizedPoints; int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); // Make sure all of our points are valid numbers. // Must be greater than 0 because vector component is set to 0 if it is invalid data. Also should never be greater than TREE_SCALE - if ( (point.x > 0 && point.x < TREE_SCALE) && (point.y > 0 && point.y < TREE_SCALE) && (point.z > 0 && point.z < TREE_SCALE) ) { - sanitizedPoints << point; - } else { - ++invalidPoints; + if ( (point.x <= 0 || point.x >= TREE_SCALE) || (point.y <= 0 || point.y >= TREE_SCALE) || (point.z <= 0 || point.z >= TREE_SCALE) ) { + return false; } } if (invalidPoints > 0) { qDebug() << "Line with" << invalidPoints << "INVALID POINTS"; } - _points = sanitizedPoints; + _points = points; _pointsChanged = true; return true; } From 709508857c36f88953de2f5f2cac8cb9182f89cc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Jun 2015 17:39:31 -0700 Subject: [PATCH 08/37] Delete maximum rolling backup file if it exists before rolling backup --- libraries/octree/src/OctreePersistThread.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index a80d071851..bb6f62ef84 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -350,6 +350,19 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { if (rule.extensionFormat.contains("%N")) { if (rule.maxBackupVersions > 0) { qCDebug(octree) << "Rolling old backup versions for rule" << rule.name << "..."; + + // Delete maximum rolling file because rename() fails on Windows if target exists + QString backupMaxExtensionN = rule.extensionFormat; + backupMaxExtensionN.replace(QString("%N"), QString::number(rule.maxBackupVersions)); + QString backupMaxFilenameN = _filename + backupMaxExtensionN; + QFile backupMaxFileN(backupMaxFilenameN); + if (backupMaxFileN.exists()) { + int result = remove(qPrintable(backupMaxFilenameN)); + if (result != 0) { + qCDebug(octree) << "ERROR deleting old backup file " << backupMaxFilenameN; + } + } + for(int n = rule.maxBackupVersions - 1; n > 0; n--) { QString backupExtensionN = rule.extensionFormat; QString backupExtensionNplusOne = rule.extensionFormat; From 830a8b69090437baa8f9acc5ae07975007157244 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 18:14:03 -0700 Subject: [PATCH 09/37] checking for bounds and modified paint script to start a new line entity if user paints outside of line entity's bounding box --- examples/paint.js | 70 +++++++++++++---------- libraries/entities/src/LineEntityItem.cpp | 12 ++-- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index c0cc93afc7..384b4916f3 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -13,14 +13,15 @@ // Script.include('lineRider.js') var MAX_POINTS_PER_LINE = 30; -var LINE_LIFETIME = 60 * 5 //5 minute lifetime +var DRAWING_DISTANCE = 5; +var LINE_DIMENSIONS = 5; var colorPalette = [{ red: 236, green: 208, blue: 120 }, { - red: 217, + red: 214, green: 91, blue: 67 }, { @@ -69,7 +70,7 @@ function hydraCheck() { //************ Mouse Paint ************************** function MousePaint() { - var DRAWING_DISTANCE = 2; + var lines = []; var deletedLines = []; var isDrawing = false; @@ -92,7 +93,7 @@ function MousePaint() { var points = []; - var BRUSH_SIZE = 0.02; + var BRUSH_SIZE = .05; var brush = Entities.addEntity({ type: 'Sphere', @@ -111,45 +112,46 @@ function MousePaint() { function newLine(point) { + if (!point) { + return; + } line = Entities.addEntity({ - position: MyAvatar.position, + position: point, type: "Line", color: currentColor, dimensions: { - x: 10, - y: 10, - z: 10 + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS }, - lineWidth: LINE_WIDTH, - lifetime: LINE_LIFETIME + lineWidth: LINE_WIDTH }); points = []; - if (point) { - - points.push(point); - path.push(point); - } + points.push(point); + path.push(point); lines.push(line); } function mouseMoveEvent(event) { + var point = computePoint(event) + Entities.editEntity(brush, { + position: point + }); + if (!isDrawing) { return; } - var pickRay = Camera.computePickRay(event.x, event.y); - var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); - var point = Vec3.sum(Camera.getPosition(), addVector); points.push(point); path.push(point); - Entities.editEntity(line, { - linePoints: points - }); - Entities.editEntity(brush, { - position: point - }); + var success = Entities.setAllPoints(line, points); + if (!success) { + //We're out of bounds of entity bounding box, so start a new line + newLine(point) + return; + } if (points.length === MAX_POINTS_PER_LINE) { @@ -158,6 +160,8 @@ function MousePaint() { } } + + function undoStroke() { var deletedLine = lines.pop(); var deletedLineProps = Entities.getEntityProperties(deletedLine); @@ -172,13 +176,14 @@ function MousePaint() { } function mousePressEvent(event) { - if(!event.isLeftButton) { + if (!event.isLeftButton) { isDrawing = false; return; } lineRider.mousePressEvent(event); path = []; - newLine(); + var point = computePoint(event); + newLine(point); isDrawing = true; @@ -198,14 +203,14 @@ function MousePaint() { if (event.text === "z") { undoStroke(); } - if(event.text === "x") { + if (event.text === "x") { redoStroke(); } } function cleanup() { lines.forEach(function(line) { - Entities.deleteEntity(line); + // Entities.deleteEntity(line); }); Entities.deleteEntity(brush); lineRider.cleanup(); @@ -255,6 +260,7 @@ function HydraPaint() { var maxLineWidth = 10; var currentLineWidth = minLineWidth; var MIN_PAINT_TRIGGER_THRESHOLD = .01; + var LINE_LIFETIME = 20; var COLOR_CHANGE_TIME_FACTOR = 0.1; var RIGHT_BUTTON_1 = 7 @@ -331,7 +337,7 @@ function HydraPaint() { z: 10 }, lineWidth: 5, - lifetime: LINE_LIFETIME + // lifetime: LINE_LIFETIME }); this.points = []; if (point) { @@ -482,6 +488,12 @@ function HydraPaint() { } +function computePoint(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); + return Vec3.sum(Camera.getPosition(), addVector); +} + function randFloat(low, high) { return low + Math.random() * (high - low); } diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 955e827d92..0686f64a89 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -86,17 +86,21 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { } bool LineEntityItem::setLinePoints(const QVector& points) { - int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); // Make sure all of our points are valid numbers. // Must be greater than 0 because vector component is set to 0 if it is invalid data. Also should never be greater than TREE_SCALE if ( (point.x <= 0 || point.x >= TREE_SCALE) || (point.y <= 0 || point.y >= TREE_SCALE) || (point.z <= 0 || point.z >= TREE_SCALE) ) { + qDebug() << "Point is outside domain bounds"; return false; } - } - if (invalidPoints > 0) { - qDebug() << "Line with" << invalidPoints << "INVALID POINTS"; + glm::vec3 pos = getPosition(); + glm::vec3 halfBox = getDimensions() * 0.5f; + if ( (point.x < pos.x - halfBox.x || point.x > pos.x + halfBox.x) || (point.y < pos.y - halfBox.y || point.y > pos.y + halfBox.y) || (point.z < pos.z - halfBox.z || point.z > pos.z + halfBox.z) ) { + qDebug() << "Point is outside entity's bounding box"; + return false; + } + } _points = points; _pointsChanged = true; From 7293330cedd59d56c3de620d61741adda1647df4 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 18:17:02 -0700 Subject: [PATCH 10/37] fixed indentation and lines delete when user exits to help with large model.svo/json file size --- examples/paint.js | 2 +- libraries/shared/src/RegisteredMetaTypes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 384b4916f3..c1ea71597b 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -210,7 +210,7 @@ function MousePaint() { function cleanup() { lines.forEach(function(line) { - // Entities.deleteEntity(line); + Entities.deleteEntity(line); }); Entities.deleteEntity(brush); lineRider.cleanup(); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 2ea2bb52fa..0a6795d285 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -57,7 +57,7 @@ QScriptValue qURLToScriptValue(QScriptEngine* engine, const QUrl& url); void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); -void qVectorVec3FromScriptValue( const QScriptValue& array, QVector& vector); +void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); From 0e177a3e31a5a44b06d5d6791de76426852f0403 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 18:23:09 -0700 Subject: [PATCH 11/37] deleted unnessary line break --- libraries/shared/src/RegisteredMetaTypes.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 0a6795d285..f5f39cd3f6 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -60,7 +60,6 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); - class PickRay { public: PickRay() : origin(0.0f), direction(0.0f) { } From 1eaf5ae82a5202707c2f71bf32a5253214a35806 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 10:37:57 -0700 Subject: [PATCH 12/37] fixed utilities file to be able to be referenced by other files --- examples/utilities.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/utilities.js b/examples/utilities.js index 3844e23e14..3c2423c914 100644 --- a/examples/utilities.js +++ b/examples/utilities.js @@ -9,7 +9,13 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -function hslToRgb(hslColor) { +////***************** UTILITIES ************************************* + +map = function(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} + +hslToRgb = function (hslColor) { var h = hslColor.hue; var s = hslColor.sat; var l = hslColor.light; @@ -42,15 +48,13 @@ function hslToRgb(hslColor) { } -function map(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); -} -function randFloat(low, high) { + +randFloat = function(low, high) { return low + Math.random() * (high - low); } -function randInt(low, high) { +randInt = function(low, high) { return Math.floor(randFloat(low, high)); } \ No newline at end of file From dc10e15e965bd6aa6b9591d5c94e821903edd97f Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Jun 2015 14:20:00 -0700 Subject: [PATCH 13/37] Put the common stuff on AudioInjector rather than AudioClient, so that assignment-client (which depends on script-engine) does not need to depend on audio-client. --- libraries/audio-client/src/AudioClient.cpp | 69 ------------------- libraries/audio-client/src/AudioClient.h | 4 -- libraries/audio/CMakeLists.txt | 8 ++- libraries/audio/src/AudioInjector.cpp | 65 +++++++++++++++++ libraries/audio/src/AudioInjector.h | 4 ++ .../src/EntityTreeRenderer.cpp | 7 +- libraries/script-engine/CMakeLists.txt | 2 +- .../src/AudioScriptingInterface.cpp | 3 +- 8 files changed, 83 insertions(+), 79 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 6d8095ccf0..84022d0fb9 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -45,7 +45,6 @@ extern "C" { #include #include #include -#include #include #include "AudioInjector.h" @@ -1339,71 +1338,3 @@ void AudioClient::audioStateChanged(QAudio::State state) { emit audioFinished(); } } - -AudioInjector* AudioClient::playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position) { - if (soundUrl.isEmpty()) { - return NULL; - } - auto soundCache = DependencyManager::get(); - if (soundCache.isNull()) { - return NULL; - } - SharedSoundPointer sound = soundCache.data()->getSound(QUrl(soundUrl)); - if (sound.isNull() || !sound->isReady()) { - return NULL; - } - - // Quiet sound aren't really heard at all, so we can compress everything to the range [1-c, 1], if we play it all. - const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes. - const float compressedVolume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE); - - // This is quite similar to AudioScriptingInterface::playSound() and should probably be refactored. - AudioInjectorOptions options; - options.stereo = sound->isStereo(); - options.position = position; - options.volume = compressedVolume; - - QByteArray samples = sound->getByteArray(); - if (stretchFactor == 1.0f) { - return playSound(samples, options); - } - - soxr_io_spec_t spec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I); - soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_MQ, 0); - const int channelCount = sound->isStereo() ? 2 : 1; - const int standardRate = AudioConstants::SAMPLE_RATE; - const int resampledRate = standardRate * stretchFactor; - const int nInputSamples = samples.size() / sizeof(int16_t); - const int nOutputSamples = nInputSamples * stretchFactor; - QByteArray resampled(nOutputSamples * sizeof(int16_t), '\0'); - const int16_t* receivedSamples = reinterpret_cast(samples.data()); - soxr_error_t soxError = soxr_oneshot(standardRate, resampledRate, channelCount, - receivedSamples, nInputSamples, NULL, - reinterpret_cast(resampled.data()), nOutputSamples, NULL, - &spec, &qualitySpec, 0); - if (soxError) { - qCDebug(audioclient) << "Unable to resample" << soundUrl << "from" << nInputSamples << "@" << standardRate << "to" << nOutputSamples << "@" << resampledRate; - resampled = samples; - } - return playSound(resampled, options); -} - -AudioInjector* AudioClient::playSound(const QByteArray& buffer, const AudioInjectorOptions options) { - QThread* injectorThread = new QThread(); - injectorThread->setObjectName("Audio Injector Thread"); - - AudioInjector* injector = new AudioInjector(buffer, options); - injector->setLocalAudioInterface(this); - - injector->moveToThread(injectorThread); - - // start injecting when the injector thread starts - connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); - - // connect the right slots and signals for AudioInjector and thread cleanup - connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit); - connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); - - injectorThread->start(); - return injector; -} diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 93afb71fef..1dca218973 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -131,10 +131,6 @@ public: static const float CALLBACK_ACCELERATOR_RATIO; - AudioInjector* playSound(const QByteArray& buffer, const AudioInjectorOptions options); - AudioInjector* playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position); - - public slots: void start(); void stop(); diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index c2d5c8aca9..c03f588d94 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -7,4 +7,10 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(networking shared) \ No newline at end of file +# we use libsoxr for resampling +add_dependency_external_projects(soxr) +find_package(Soxr REQUIRED) +target_link_libraries(${TARGET_NAME} ${SOXR_LIBRARIES}) +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SOXR_INCLUDE_DIRS}) + +link_hifi_libraries(networking shared) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 675a3b8b28..480f13c54a 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -16,10 +16,12 @@ #include #include #include +#include #include "AbstractAudioInterface.h" #include "AudioRingBuffer.h" #include "AudioLogging.h" +#include "SoundCache.h" #include "AudioInjector.h" @@ -284,3 +286,66 @@ void AudioInjector::stopAndDeleteLater() { stop(); QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection); } + +AudioInjector* AudioInjector::playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position) { + if (soundUrl.isEmpty()) { + return NULL; + } + auto soundCache = DependencyManager::get(); + if (soundCache.isNull()) { + return NULL; + } + SharedSoundPointer sound = soundCache.data()->getSound(QUrl(soundUrl)); + if (sound.isNull() || !sound->isReady()) { + return NULL; + } + + AudioInjectorOptions options; + options.stereo = sound->isStereo(); + options.position = position; + options.volume = volume; + + QByteArray samples = sound->getByteArray(); + if (stretchFactor == 1.0f) { + return playSound(samples, options, NULL); + } + + soxr_io_spec_t spec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I); + soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_MQ, 0); + const int channelCount = sound->isStereo() ? 2 : 1; + const int standardRate = AudioConstants::SAMPLE_RATE; + const int resampledRate = standardRate * stretchFactor; + const int nInputSamples = samples.size() / sizeof(int16_t); + const int nOutputSamples = nInputSamples * stretchFactor; + QByteArray resampled(nOutputSamples * sizeof(int16_t), '\0'); + const int16_t* receivedSamples = reinterpret_cast(samples.data()); + soxr_error_t soxError = soxr_oneshot(standardRate, resampledRate, channelCount, + receivedSamples, nInputSamples, NULL, + reinterpret_cast(resampled.data()), nOutputSamples, NULL, + &spec, &qualitySpec, 0); + if (soxError) { + qCDebug(audio) << "Unable to resample" << soundUrl << "from" << nInputSamples << "@" << standardRate << "to" << nOutputSamples << "@" << resampledRate; + resampled = samples; + } + return playSound(resampled, options, NULL); +} + +AudioInjector* AudioInjector::playSound(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface) { + QThread* injectorThread = new QThread(); + injectorThread->setObjectName("Audio Injector Thread"); + + AudioInjector* injector = new AudioInjector(buffer, options); + injector->setLocalAudioInterface(localInterface); + + injector->moveToThread(injectorThread); + + // start injecting when the injector thread starts + connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); + + // connect the right slots and signals for AudioInjector and thread cleanup + connect(injector, &AudioInjector::destroyed, injectorThread, &QThread::quit); + connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); + + injectorThread->start(); + return injector; +} diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 0513b70bd8..806a4ea33e 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -45,6 +45,10 @@ public: bool isLocalOnly() const { return _options.localOnly; } void setLocalAudioInterface(AbstractAudioInterface* localAudioInterface) { _localAudioInterface = localAudioInterface; } + + static AudioInjector* playSound(const QByteArray& buffer, const AudioInjectorOptions options, AbstractAudioInterface* localInterface); + static AudioInjector* playSound(const QString& soundUrl, const float volume, const float stretchFactor, const glm::vec3 position); + public slots: void injectAudio(); void restart(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index f2d015960c..f96ae38a41 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -1095,11 +1094,15 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) { return; } + // Quiet sound aren't really heard at all, so we can compress everything to the range [1-c, 1], if we play it all. + const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes. + const float volume = (energyFactorOfFull * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE); + // Shift the pitch down by ln(1 + (size / COLLISION_SIZE_FOR_STANDARD_PITCH)) / ln(2) const float COLLISION_SIZE_FOR_STANDARD_PITCH = 0.2f; const float stretchFactor = log(1.0f + (entity->getMinimumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); - DependencyManager::get()->playSound(collisionSoundURL, energyFactorOfFull, stretchFactor, position); + AudioInjector::playSound(collisionSoundURL, volume, stretchFactor, position); } void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 78db92b4f1..99d9149c3a 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -7,4 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared octree gpu model fbx entities animation audio audio-client physics) +link_hifi_libraries(shared octree gpu model fbx entities animation audio physics) diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index 0b55ed1bca..161c7b7118 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -11,7 +11,6 @@ #include "AudioScriptingInterface.h" -#include "AudioClient.h" #include "ScriptAudioInjector.h" #include "ScriptEngineLogging.h" @@ -47,7 +46,7 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(Sound* sound, const Audi AudioInjectorOptions optionsCopy = injectorOptions; optionsCopy.stereo = sound->isStereo(); - return new ScriptAudioInjector(DependencyManager::get()->playSound(sound->getByteArray(), optionsCopy)); + return new ScriptAudioInjector(AudioInjector::playSound(sound->getByteArray(), optionsCopy, _localAudioInterface)); } else { qCDebug(scriptengine) << "AudioScriptingInterface::playSound called with null Sound object."; From 7cf7f0df1a49002fda2ed0748ea8c2064f7a4881 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Jun 2015 14:38:43 -0700 Subject: [PATCH 14/37] Remove #include that was introduced in version 1 that is not needed in final. --- libraries/audio-client/src/AudioClient.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 53c8397a37..aeea7c07c1 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -40,7 +40,6 @@ #include #include -#include "AudioInjector.h" #include "AudioIOStats.h" #include "AudioNoiseGate.h" From 1734d5e584a52b1bd2cf2baff2b09377bc36c39a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 15:05:55 -0700 Subject: [PATCH 15/37] Fix recalculateMeshBoxes being called outside of mutex --- libraries/render-utils/src/Model.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1b991f2179..795e184735 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -545,11 +545,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // we can use the AABox's ray intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { - - if (!_calculatedMeshBoxesValid) { - recalculateMeshBoxes(pickAgainstTriangles); - } - float bestDistance = std::numeric_limits::max(); float distanceToSubMesh; @@ -560,6 +555,11 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // If we hit the models box, then consider the submeshes... _mutex.lock(); + + if (!_calculatedMeshBoxesValid) { + recalculateMeshBoxes(pickAgainstTriangles); + } + foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { From a7f291154b0a39ad59be65013aadf900605609be Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 16:28:58 -0700 Subject: [PATCH 16/37] Add lock around recalculateMeshPartOffsets call --- libraries/render-utils/src/Model.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 795e184735..086139c646 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1811,7 +1811,9 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // We need to make sure we have valid offsets calculated before we can render if (!_calculatedMeshPartOffsetValid) { + _mutex.lock(); recalculateMeshPartOffsets(); + _mutex.unlock(); } auto textureCache = DependencyManager::get(); From 1371f775ee23cdb3b397b92def310eca4c1e5f11 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 16:51:13 -0700 Subject: [PATCH 17/37] Add mutex lock around access to Model::_calculatedMeshPartOffset --- libraries/render-utils/src/Model.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 086139c646..1397512f4a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2021,7 +2021,9 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran } } + _mutex.lock(); qint64 offset = _calculatedMeshPartOffset[QPair(meshIndex, partIndex)]; + _mutex.unlock(); if (part.quadIndices.size() > 0) { batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); From dbec1aad0c682b098afb38b2820cdb055c9d869f Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 18:54:28 -0700 Subject: [PATCH 18/37] line entity points are now local to entity position. Changed paint script to reflect this --- .../src/RenderableLineEntityItem.cpp | 6 ++--- libraries/entities/src/EntityItemProperties.h | 2 ++ .../entities/src/EntityScriptingInterface.cpp | 10 +++++++ .../entities/src/EntityScriptingInterface.h | 1 + libraries/entities/src/LineEntityItem.cpp | 27 ++++++++++++++----- libraries/entities/src/LineEntityItem.h | 2 ++ 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 65407c74e7..4b94992d59 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -43,9 +43,9 @@ void RenderableLineEntityItem::render(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - // TODO: Figure out clean , efficient way to do relative line positioning. For now we'll just use absolute positioning. - //batch.setModelTransform(getTransformToCenter()); - batch.setModelTransform(Transform()); + Transform transform = Transform(); + transform.setTranslation(getPosition()); + batch.setModelTransform(transform); batch._glLineWidth(getLineWidth()); if (getLinePoints().size() > 1) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 068bc98f7e..5f33da52f8 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -197,6 +197,8 @@ public: QString getSimulatorIDAsString() const { return _simulatorID.toString().mid(1,36).toUpper(); } void setVoxelDataDirty() { _voxelDataChanged = true; } + + void setLinePointsDirty() {_linePointsChanged = true; } void setCreated(QDateTime& v); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 69b31468d2..c9f7378bc8 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -471,8 +471,10 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::functiongetProperties(); _entityTree->unlock(); + properties.setLinePointsDirty(); properties.setLastEdited(now); + queueEntityMessage(PacketTypeEntityEdit, entityID, properties); return success; } @@ -502,6 +504,14 @@ bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector bool + { + return lineEntity.appendPoint(point); + }); + +} + bool EntityScriptingInterface::actionWorker(const QUuid& entityID, std::function actor) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 17183264b9..12c8688816 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -124,6 +124,7 @@ public slots: Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); + Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); Q_INVOKABLE void dumpTree() const; diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 0686f64a89..fccf57c7c7 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -23,6 +23,7 @@ const float LineEntityItem::DEFAULT_LINE_WIDTH = 2.0f; +const int LineEntityItem::MAX_POINTS_PER_LINE = 70; EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -85,18 +86,30 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } +bool LineEntityItem::appendPoint(const glm::vec3& point) { + if (_points.size() > MAX_POINTS_PER_LINE - 1) { + qDebug() << "MAX POINTS REACHED!"; + return false; + } + glm::vec3 halfBox = getDimensions() * 0.5f; + if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { + qDebug() << "Point is outside entity's bounding box"; + return false; + } + _points << point; + _pointsChanged = true; + return true; +} + bool LineEntityItem::setLinePoints(const QVector& points) { + if (points.size() > MAX_POINTS_PER_LINE) { + return false; + } for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); - // Make sure all of our points are valid numbers. - // Must be greater than 0 because vector component is set to 0 if it is invalid data. Also should never be greater than TREE_SCALE - if ( (point.x <= 0 || point.x >= TREE_SCALE) || (point.y <= 0 || point.y >= TREE_SCALE) || (point.z <= 0 || point.z >= TREE_SCALE) ) { - qDebug() << "Point is outside domain bounds"; - return false; - } glm::vec3 pos = getPosition(); glm::vec3 halfBox = getDimensions() * 0.5f; - if ( (point.x < pos.x - halfBox.x || point.x > pos.x + halfBox.x) || (point.y < pos.y - halfBox.y || point.y > pos.y + halfBox.y) || (point.z < pos.z - halfBox.z || point.z > pos.z + halfBox.z) ) { + if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { qDebug() << "Point is outside entity's bounding box"; return false; } diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 0918dd2d06..6d0f00ef04 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -55,6 +55,7 @@ class LineEntityItem : public EntityItem { float getLineWidth() const{ return _lineWidth; } bool setLinePoints(const QVector& points); + bool appendPoint(const glm::vec3& point); const QVector& getLinePoints() const{ return _points; } @@ -68,6 +69,7 @@ class LineEntityItem : public EntityItem { virtual void debugDump() const; static const float DEFAULT_LINE_WIDTH; + static const int MAX_POINTS_PER_LINE; protected: rgbColor _color; From 8bc9fc2e1f9c59edbd65c9d321b380d68f70d966 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 18:58:09 -0700 Subject: [PATCH 19/37] simplified paint.js script to allow for faster iteration and more thorough testing --- examples/paint.js | 383 +++++----------------------------------------- 1 file changed, 40 insertions(+), 343 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index c1ea71597b..ebda5e2e18 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -10,11 +10,9 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -Script.include('lineRider.js') -var MAX_POINTS_PER_LINE = 30; -var DRAWING_DISTANCE = 5; -var LINE_DIMENSIONS = 5; + +var LINE_DIMENSIONS = 1; +var LIFETIME = 6000; var colorPalette = [{ red: 236, @@ -41,15 +39,6 @@ var colorPalette = [{ var currentColorIndex = 0; var currentColor = colorPalette[currentColorIndex]; - - -if (hydraCheck() === true) { - HydraPaint(); -} else { - MousePaint(); -} - - function cycleColor() { currentColor = colorPalette[++currentColorIndex]; if (currentColorIndex === colorPalette.length - 1) { @@ -58,40 +47,15 @@ function cycleColor() { } -function hydraCheck() { - var numberOfButtons = Controller.getNumberOfButtons(); - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); - return hydrasConnected; //hydrasConnected; -} - -//************ Mouse Paint ************************** +MousePaint(); function MousePaint() { - + var DRAWING_DISTANCE = 5; var lines = []; - var deletedLines = []; var isDrawing = false; - var path = []; - - var lineRider = new LineRider(); - lineRider.addStartHandler(function() { - var points = []; - //create points array from list of all points in path - path.forEach(function(point) { - points.push(point); - }); - lineRider.setPath(points); - }); - - var LINE_WIDTH = 7; - var line; - var points = []; - + var line, linePosition; var BRUSH_SIZE = .05; @@ -102,7 +66,11 @@ function MousePaint() { y: 0, z: 0 }, - color: currentColor, + color: { + red: 100, + green: 10, + blue: 100 + }, dimensions: { x: BRUSH_SIZE, y: BRUSH_SIZE, @@ -111,12 +79,10 @@ function MousePaint() { }); - function newLine(point) { - if (!point) { - return; - } + function newLine(position) { + linePosition = position; line = Entities.addEntity({ - position: point, + position: position, type: "Line", color: currentColor, dimensions: { @@ -124,44 +90,34 @@ function MousePaint() { y: LINE_DIMENSIONS, z: LINE_DIMENSIONS }, - lineWidth: LINE_WIDTH + linePoints: [], + lineWidth: LINE_WIDTH, + lifetime: LIFETIME }); - points = []; - points.push(point); - path.push(point); lines.push(line); } function mouseMoveEvent(event) { - var point = computePoint(event) + var worldPoint = computeWorldPoint(event); Entities.editEntity(brush, { - position: point + position: worldPoint }); if (!isDrawing) { return; } - points.push(point); - path.push(point); - var success = Entities.setAllPoints(line, points); + var localPoint = computeLocalPoint(event) + var success = Entities.appendPoint(line, localPoint); + if (!success) { - //We're out of bounds of entity bounding box, so start a new line - newLine(point) - return; - } - - - if (points.length === MAX_POINTS_PER_LINE) { - //We need to start a new line! - newLine(point); + newLine(worldPoint); + Entities.appendPoint(line, computeLocalPoint(event)); } } - - function undoStroke() { var deletedLine = lines.pop(); var deletedLineProps = Entities.getEntityProperties(deletedLine); @@ -175,18 +131,26 @@ function MousePaint() { lines.push(restoredLine); } + function computeWorldPoint(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); + return Vec3.sum(Camera.getPosition(), addVector); + } + + function computeLocalPoint(event) { + + var localPoint = Vec3.subtract(computeWorldPoint(event), linePosition); + return localPoint; + } + function mousePressEvent(event) { if (!event.isLeftButton) { isDrawing = false; return; } - lineRider.mousePressEvent(event); - path = []; - var point = computePoint(event); - newLine(point); + newLine(computeWorldPoint(event)); isDrawing = true; - } function mouseReleaseEvent() { @@ -208,16 +172,16 @@ function MousePaint() { } } + + function cleanup() { lines.forEach(function(line) { - Entities.deleteEntity(line); + // Entities.deleteEntity(line); }); Entities.deleteEntity(brush); - lineRider.cleanup(); } - Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseMoveEvent.connect(mouseMoveEvent); @@ -227,273 +191,6 @@ function MousePaint() { } - -//*****************HYDRA PAINT ******************************************* - - - -function HydraPaint() { - - - - var lineRider = new LineRider(); - lineRider.addStartHandler(function() { - var points = []; - //create points array from list of all points in path - rightController.path.forEach(function(point) { - points.push(point); - }); - lineRider.setPath(points); - }); - - var LEFT = 0; - var RIGHT = 1; - - var currentTime = 0; - - - var minBrushSize = .02; - var maxBrushSize = .04 - - - var minLineWidth = 5; - var maxLineWidth = 10; - var currentLineWidth = minLineWidth; - var MIN_PAINT_TRIGGER_THRESHOLD = .01; - var LINE_LIFETIME = 20; - var COLOR_CHANGE_TIME_FACTOR = 0.1; - - var RIGHT_BUTTON_1 = 7 - var RIGHT_BUTTON_2 = 8 - var RIGHT_BUTTON_3 = 9; - var RIGHT_BUTTON_4 = 10 - - var LEFT_BUTTON_1 = 1; - var LEFT_BUTTON_2 = 2; - var LEFT_BUTTON_3 = 3; - var LEFT_BUTTON_4 = 4; - - var STROKE_SMOOTH_FACTOR = 1; - - var MIN_DRAW_DISTANCE = 0.2; - var MAX_DRAW_DISTANCE = 0.4; - - function controller(side, undoButton, redoButton, cycleColorButton, startRideButton) { - this.triggerHeld = false; - this.triggerThreshold = 0.9; - this.side = side; - this.palm = 2 * side; - this.tip = 2 * side + 1; - this.trigger = side; - this.lines = []; - this.deletedLines = [] //just an array of properties objects - this.isPainting = false; - - this.undoButton = undoButton; - this.undoButtonPressed = false; - this.prevUndoButtonPressed = false; - - this.redoButton = redoButton; - this.redoButtonPressed = false; - this.prevRedoButtonPressed = false; - - this.cycleColorButton = cycleColorButton; - this.cycleColorButtonPressed = false; - this.prevColorCycleButtonPressed = false; - - this.startRideButton = startRideButton; - this.startRideButtonPressed = false; - this.prevStartRideButtonPressed = false; - - this.strokeCount = 0; - this.currentBrushSize = minBrushSize; - this.points = []; - this.path = []; - - this.brush = Entities.addEntity({ - type: 'Sphere', - position: { - x: 0, - y: 0, - z: 0 - }, - color: currentColor, - dimensions: { - x: minBrushSize, - y: minBrushSize, - z: minBrushSize - } - }); - - - this.newLine = function(point) { - this.line = Entities.addEntity({ - position: MyAvatar.position, - type: "Line", - color: currentColor, - dimensions: { - x: 10, - y: 10, - z: 10 - }, - lineWidth: 5, - // lifetime: LINE_LIFETIME - }); - this.points = []; - if (point) { - this.points.push(point); - this.path.push(point); - } - this.lines.push(this.line); - } - - this.update = function(deltaTime) { - this.updateControllerState(); - this.avatarPalmOffset = Vec3.subtract(this.palmPosition, MyAvatar.position); - this.projectedForwardDistance = Vec3.dot(Quat.getFront(Camera.getOrientation()), this.avatarPalmOffset); - this.mappedPalmOffset = map(this.projectedForwardDistance, -.5, .5, MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE); - this.tipDirection = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - this.offsetVector = Vec3.multiply(this.mappedPalmOffset, this.tipDirection); - this.drawPoint = Vec3.sum(this.palmPosition, this.offsetVector); - this.currentBrushSize = map(this.triggerValue, 0, 1, minBrushSize, maxBrushSize); - Entities.editEntity(this.brush, { - position: this.drawPoint, - dimensions: { - x: this.currentBrushSize, - y: this.currentBrushSize, - z: this.currentBrushSize - }, - color: currentColor - }); - if (this.triggerValue > MIN_PAINT_TRIGGER_THRESHOLD) { - if (!this.isPainting) { - this.isPainting = true; - this.newLine(); - this.path = []; - } - if (this.strokeCount % STROKE_SMOOTH_FACTOR === 0) { - this.paint(this.drawPoint); - } - this.strokeCount++; - } else if (this.triggerValue < MIN_PAINT_TRIGGER_THRESHOLD && this.isPainting) { - this.releaseTrigger(); - } - - this.oldPalmPosition = this.palmPosition; - this.oldTipPosition = this.tipPosition; - } - - this.releaseTrigger = function() { - this.isPainting = false; - - } - - - this.updateControllerState = function() { - this.undoButtonPressed = Controller.isButtonPressed(this.undoButton); - this.redoButtonPressed = Controller.isButtonPressed(this.redoButton); - this.cycleColorButtonPressed = Controller.isButtonPressed(this.cycleColorButton); - this.startRideButtonPressed = Controller.isButtonPressed(this.startRideButton); - - //This logic gives us button release - if (this.prevUndoButtonPressed === true && this.undoButtonPressed === false) { - //User released undo button, so undo - this.undoStroke(); - } - if (this.prevRedoButtonPressed === true && this.redoButtonPressed === false) { - this.redoStroke(); - } - - if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { - cycleColor(); - Entities.editEntity(this.brush, { - color: currentColor - }); - } - if (this.prevStartRideButtonPressed === true && this.startRideButtonPressed === false) { - lineRider.toggleRide(); - } - this.prevRedoButtonPressed = this.redoButtonPressed; - this.prevUndoButtonPressed = this.undoButtonPressed; - this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; - this.prevStartRideButtonPressed = this.startRideButtonPressed; - - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - this.triggerValue = Controller.getTriggerValue(this.trigger); - } - - this.undoStroke = function() { - var deletedLine = this.lines.pop(); - var deletedLineProps = Entities.getEntityProperties(deletedLine); - this.deletedLines.push(deletedLineProps); - Entities.deleteEntity(deletedLine); - } - - this.redoStroke = function() { - var restoredLine = Entities.addEntity(this.deletedLines.pop()); - Entities.addEntity(restoredLine); - this.lines.push(restoredLine); - } - - this.paint = function(point) { - - currentLineWidth = map(this.triggerValue, 0, 1, minLineWidth, maxLineWidth); - this.points.push(point); - this.path.push(point); - Entities.editEntity(this.line, { - linePoints: this.points, - lineWidth: currentLineWidth, - }); - if (this.points.length > MAX_POINTS_PER_LINE) { - this.newLine(point); - } - } - - this.cleanup = function() { - Entities.deleteEntity(this.brush); - this.lines.forEach(function(line) { - Entities.deleteEntity(line); - }); - } - } - - function update(deltaTime) { - rightController.update(deltaTime); - leftController.update(deltaTime); - currentTime += deltaTime; - } - - function cleanup() { - rightController.cleanup(); - leftController.cleanup(); - lineRider.cleanup(); - } - - function mousePressEvent(event) { - lineRider.mousePressEvent(event); - } - - function vectorIsZero(v) { - return v.x === 0 && v.y === 0 && v.z === 0; - } - - - var rightController = new controller(RIGHT, RIGHT_BUTTON_3, RIGHT_BUTTON_4, RIGHT_BUTTON_1, RIGHT_BUTTON_2); - var leftController = new controller(LEFT, LEFT_BUTTON_3, LEFT_BUTTON_4, LEFT_BUTTON_1, LEFT_BUTTON_2); - - Script.update.connect(update); - Script.scriptEnding.connect(cleanup); - Controller.mousePressEvent.connect(mousePressEvent); - -} - -function computePoint(event) { - var pickRay = Camera.computePickRay(event.x, event.y); - var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); - return Vec3.sum(Camera.getPosition(), addVector); -} - function randFloat(low, high) { return low + Math.random() * (high - low); } From 18014e968df0f19b69dd862e83d24bb505844ea5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 19:00:42 -0700 Subject: [PATCH 20/37] removed horizontal "line break" style comment blocks --- examples/utilities.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/utilities.js b/examples/utilities.js index 3c2423c914..b60576b23e 100644 --- a/examples/utilities.js +++ b/examples/utilities.js @@ -9,13 +9,13 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -////***************** UTILITIES ************************************* + map = function(value, min1, max1, min2, max2) { return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); } -hslToRgb = function (hslColor) { +hslToRgb = function(hslColor) { var h = hslColor.hue; var s = hslColor.sat; var l = hslColor.light; From 8fcff2d64875f766e1306ba454324cd069ddcdb2 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 19:03:47 -0700 Subject: [PATCH 21/37] changed indent spacing to 4 spaces --- examples/utilities.js | 58 +++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/examples/utilities.js b/examples/utilities.js index b60576b23e..85e27079a8 100644 --- a/examples/utilities.js +++ b/examples/utilities.js @@ -12,49 +12,49 @@ map = function(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); } hslToRgb = function(hslColor) { - var h = hslColor.hue; - var s = hslColor.sat; - var l = hslColor.light; - var r, g, b; + var h = hslColor.hue; + var s = hslColor.sat; + var l = hslColor.light; + var r, g, b; - if (s == 0) { - r = g = b = l; // achromatic - } else { - var hue2rgb = function hue2rgb(p, q, t) { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; + if (s == 0) { + r = g = b = l; // achromatic + } else { + var hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); } - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - - return { - red: Math.round(r * 255), - green: Math.round(g * 255), - blue: Math.round(b * 255) - }; + return { + red: Math.round(r * 255), + green: Math.round(g * 255), + blue: Math.round(b * 255) + }; } randFloat = function(low, high) { - return low + Math.random() * (high - low); + return low + Math.random() * (high - low); } randInt = function(low, high) { - return Math.floor(randFloat(low, high)); + return Math.floor(randFloat(low, high)); } \ No newline at end of file From 362d9a24817577ddae17d51147eb64717eb449c5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 10:35:00 -0700 Subject: [PATCH 22/37] syncing brush sphere with line color --- examples/paint.js | 2 +- libraries/entities/src/QuadEntityItem.cpp | 9 +++++++++ libraries/entities/src/QuadEntityItem.h | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 libraries/entities/src/QuadEntityItem.cpp create mode 100644 libraries/entities/src/QuadEntityItem.h diff --git a/examples/paint.js b/examples/paint.js index ebda5e2e18..3f4a08cb28 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -83,7 +83,7 @@ function MousePaint() { linePosition = position; line = Entities.addEntity({ position: position, - type: "Line", + type: "Quad", color: currentColor, dimensions: { x: LINE_DIMENSIONS, diff --git a/libraries/entities/src/QuadEntityItem.cpp b/libraries/entities/src/QuadEntityItem.cpp new file mode 100644 index 0000000000..0ac04129be --- /dev/null +++ b/libraries/entities/src/QuadEntityItem.cpp @@ -0,0 +1,9 @@ +// +// QuadEntityItem.cpp +// hifi +// +// Created by eric levin on 6/22/15. +// +// + +#include "QuadEntityItem.h" diff --git a/libraries/entities/src/QuadEntityItem.h b/libraries/entities/src/QuadEntityItem.h new file mode 100644 index 0000000000..64f733d6b5 --- /dev/null +++ b/libraries/entities/src/QuadEntityItem.h @@ -0,0 +1,14 @@ +// +// QuadEntityItem.h +// hifi +// +// Created by eric levin on 6/22/15. +// +// + +#ifndef __hifi__QuadEntityItem__ +#define __hifi__QuadEntityItem__ + +#include + +#endif /* defined(__hifi__QuadEntityItem__) */ From 1b69563b29b855f448c64acf2608369818b59b5d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 11:06:40 -0700 Subject: [PATCH 23/37] changed quad back to line; --- examples/paint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/paint.js b/examples/paint.js index 3f4a08cb28..ebda5e2e18 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -83,7 +83,7 @@ function MousePaint() { linePosition = position; line = Entities.addEntity({ position: position, - type: "Quad", + type: "Line", color: currentColor, dimensions: { x: LINE_DIMENSIONS, From 6c84e5ad77464ccca34d1b4de3a3b2ab7a45571d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 11:08:40 -0700 Subject: [PATCH 24/37] actually syncing brush to line color --- examples/paint.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index ebda5e2e18..20196601df 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -66,11 +66,7 @@ function MousePaint() { y: 0, z: 0 }, - color: { - red: 100, - green: 10, - blue: 100 - }, + color: currentColor, dimensions: { x: BRUSH_SIZE, y: BRUSH_SIZE, From 4cd1c529876b21c02e5948a343f1ef423009d377 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Jun 2015 11:20:48 -0700 Subject: [PATCH 25/37] Fixing HMD position offset bug in picking & stereo rendering in HMD --- interface/src/Application.cpp | 7 + interface/src/devices/OculusManager.cpp | 163 ++++++++++++++++----- interface/src/devices/OculusManager.h | 128 +--------------- interface/src/ui/ApplicationCompositor.cpp | 8 +- 4 files changed, 138 insertions(+), 168 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 35f10b724e..b0d91f8619 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4748,3 +4748,10 @@ mat4 Application::getEyePose(int eye) const { return mat4(); } + +mat4 Application::getHeadPose() const { + if (isHMDMode()) { + return OculusManager::getHeadPose(); + } + return mat4(); +} diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 53b3702cca..82c5ff90c6 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -11,10 +11,10 @@ // #include "InterfaceConfig.h" - #include "OculusManager.h" #include "ui/overlays/Text3DOverlay.h" +#include #include #include #include @@ -37,7 +37,6 @@ #include "InterfaceLogging.h" #include "Application.h" - template void for_each_eye(Function function) { for (ovrEyeType eye = ovrEyeType::ovrEye_Left; @@ -54,6 +53,71 @@ void for_each_eye(const ovrHmd & hmd, Function function) { function(eye); } } +enum CalibrationState { + UNCALIBRATED, + WAITING_FOR_DELTA, + WAITING_FOR_ZERO, + WAITING_FOR_ZERO_HELD, + CALIBRATED +}; + +inline glm::mat4 toGlm(const ovrMatrix4f & om) { + return glm::transpose(glm::make_mat4(&om.M[0][0])); +} + +inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) { + return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true)); +} + +inline glm::vec3 toGlm(const ovrVector3f & ov) { + return glm::make_vec3(&ov.x); +} + +inline glm::vec2 toGlm(const ovrVector2f & ov) { + return glm::make_vec2(&ov.x); +} + +inline glm::ivec2 toGlm(const ovrVector2i & ov) { + return glm::ivec2(ov.x, ov.y); +} + +inline glm::uvec2 toGlm(const ovrSizei & ov) { + return glm::uvec2(ov.w, ov.h); +} + +inline glm::quat toGlm(const ovrQuatf & oq) { + return glm::make_quat(&oq.x); +} + +inline glm::mat4 toGlm(const ovrPosef & op) { + glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation)); + glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position)); + return translation * orientation; +} + +inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) { + ovrMatrix4f result; + glm::mat4 transposed(glm::transpose(m)); + memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16); + return result; +} + +inline ovrVector3f ovrFromGlm(const glm::vec3 & v) { + return{ v.x, v.y, v.z }; +} + +inline ovrVector2f ovrFromGlm(const glm::vec2 & v) { + return{ v.x, v.y }; +} + +inline ovrSizei ovrFromGlm(const glm::uvec2 & v) { + return{ (int)v.x, (int)v.y }; +} + +inline ovrQuatf ovrFromGlm(const glm::quat & q) { + return{ q.x, q.y, q.z, q.w }; +} + #ifdef Q_OS_WIN @@ -171,9 +235,9 @@ private: } }; -SwapFramebufferWrapper* OculusManager::_swapFbo{ nullptr }; -MirrorFramebufferWrapper* OculusManager::_mirrorFbo{ nullptr }; -ovrLayerEyeFov OculusManager::_sceneLayer; +SwapFramebufferWrapper* _swapFbo{ nullptr }; +MirrorFramebufferWrapper* _mirrorFbo{ nullptr }; +ovrLayerEyeFov _sceneLayer; #else @@ -182,39 +246,43 @@ GlWindow* OculusManager::_outputWindow{ nullptr }; #endif -bool OculusManager::_isConnected = false; -ovrHmd OculusManager::_ovrHmd; -ovrFovPort OculusManager::_eyeFov[ovrEye_Count]; -ovrVector3f OculusManager::_eyeOffset[ovrEye_Count]; -ovrEyeRenderDesc OculusManager::_eyeRenderDesc[ovrEye_Count]; -ovrSizei OculusManager::_renderTargetSize; -glm::mat4 OculusManager::_eyeProjection[ovrEye_Count]; -unsigned int OculusManager::_frameIndex = 0; -bool OculusManager::_frameTimingActive = false; -Camera* OculusManager::_camera = NULL; -ovrEyeType OculusManager::_activeEye = ovrEye_Count; -bool OculusManager::_hswDismissed = false; +static bool _isConnected = false; +static ovrHmd _ovrHmd; +static ovrFovPort _eyeFov[ovrEye_Count]; +static ovrVector3f _eyeOffset[ovrEye_Count]; +static ovrEyeRenderDesc _eyeRenderDesc[ovrEye_Count]; +static ovrSizei _renderTargetSize; +static glm::mat4 _eyeProjection[ovrEye_Count]; +static unsigned int _frameIndex = 0; +static bool _frameTimingActive = false; +static Camera* _camera = NULL; +static ovrEyeType _activeEye = ovrEye_Count; +static bool _hswDismissed = false; -float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f; -float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE; -float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f; -float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE; -quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec -float OculusManager::CALIBRATION_MESSAGE_DISTANCE = 2.5f; -OculusManager::CalibrationState OculusManager::_calibrationState; -glm::vec3 OculusManager::_calibrationPosition; -glm::quat OculusManager::_calibrationOrientation; -quint64 OculusManager::_calibrationStartTime; -int OculusManager::_calibrationMessage = 0; -glm::vec3 OculusManager::_eyePositions[ovrEye_Count]; +static const float CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f; +static const float CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE; +static const float CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f; +static const float CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE; +static const quint64 CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec +static const float CALIBRATION_MESSAGE_DISTANCE = 2.5f; +static CalibrationState _calibrationState; +static glm::vec3 _calibrationPosition; +static glm::quat _calibrationOrientation; +static quint64 _calibrationStartTime; +static int _calibrationMessage = 0; +static glm::vec3 _eyePositions[ovrEye_Count]; // TODO expose this as a developer toggle -bool OculusManager::_eyePerFrameMode = false; -ovrEyeType OculusManager::_lastEyeRendered = ovrEye_Count; -ovrSizei OculusManager::_recommendedTexSize = { 0, 0 }; -float OculusManager::_offscreenRenderScale = 1.0; +static bool _eyePerFrameMode = false; +static ovrEyeType _lastEyeRendered = ovrEye_Count; +static ovrSizei _recommendedTexSize = { 0, 0 }; +static float _offscreenRenderScale = 1.0; static glm::mat4 _combinedProjection; static ovrPosef _eyeRenderPoses[ovrEye_Count]; -ovrRecti OculusManager::_eyeViewports[ovrEye_Count]; +static ovrRecti _eyeViewports[ovrEye_Count]; +static ovrVector3f _eyeOffsets[ovrEye_Count]; + +glm::vec3 OculusManager::getLeftEyePosition() { return _eyePositions[ovrEye_Left]; } +glm::vec3 OculusManager::getRightEyePosition() { return _eyePositions[ovrEye_Right]; } void OculusManager::connect(QOpenGLContext* shareContext) { qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING; @@ -267,6 +335,8 @@ void OculusManager::connect(QOpenGLContext* shareContext) { _eyeFov[eye] = _ovrHmd->DefaultEyeFov[eye]; _eyeProjection[eye] = toGlm(ovrMatrix4f_Projection(_eyeFov[eye], DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded)); + ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_ovrHmd, eye, _eyeFov[eye]); + _eyeOffsets[eye] = erd.HmdToEyeViewOffset; }); ovrFovPort combinedFov = _ovrHmd->MaxEyeFov[0]; combinedFov.RightTan = _ovrHmd->MaxEyeFov[1].RightTan; @@ -389,7 +459,7 @@ void OculusManager::disconnect() { } } -void OculusManager::positionCalibrationBillboard(Text3DOverlay* billboard) { +void positionCalibrationBillboard(Text3DOverlay* billboard) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); glm::quat headOrientation = myAvatar->getHeadOrientation(); headOrientation.x = 0; @@ -400,7 +470,7 @@ void OculusManager::positionCalibrationBillboard(Text3DOverlay* billboard) { billboard->setRotation(headOrientation); } -void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) { +void calibrate(const glm::vec3& position, const glm::quat& orientation) { static QString instructionMessage = "Hold still to calibrate"; static QString progressMessage; static Text3DOverlay* billboard; @@ -605,9 +675,8 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const } trackerPosition = bodyOrientation * trackerPosition; - static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } }; ovrPosef eyePoses[ovrEye_Count]; - ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); + ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, _eyeOffsets, eyePoses, nullptr); #ifndef Q_OS_WIN ovrHmd_BeginFrame(_ovrHmd, _frameIndex); #endif @@ -721,7 +790,18 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const ovrHmd_EndFrame(_ovrHmd, _eyeRenderPoses, _eyeTextures); glCanvas->makeCurrent(); #endif - + + + // in order to account account for changes in the pick ray caused by head movement + // we need to force a mouse move event on every frame (perhaps we could change this + // to based on the head moving a minimum distance from the last position in which we + // sent?) + { + QMouseEvent mouseEvent(QEvent::MouseMove, glCanvas->mapFromGlobal(QCursor::pos()), + Qt::NoButton, Qt::NoButton, 0); + qApp->mouseMoveEvent(&mouseEvent, 0); + } + } @@ -826,3 +906,8 @@ mat4 OculusManager::getEyeProjection(int eye) { mat4 OculusManager::getEyePose(int eye) { return toGlm(_eyeRenderPoses[eye]); } + +mat4 OculusManager::getHeadPose() { + ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); + return toGlm(ts.HeadPose.ThePose); +} \ No newline at end of file diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 89ec8a55f6..9d9f091296 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -13,8 +13,6 @@ #ifndef hifi_OculusManager_h #define hifi_OculusManager_h -#include - #include #include #include @@ -23,17 +21,7 @@ #include "RenderArgs.h" class QOpenGLContext; - class Camera; -class GlWindow; -class PalmData; -class Text3DOverlay; - -#ifdef Q_OS_WIN -struct SwapFramebufferWrapper; -struct MirrorFramebufferWrapper; -#endif - /// Handles interaction with the Oculus Rift. class OculusManager { @@ -57,124 +45,14 @@ public: static void overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane); - static glm::vec3 getLeftEyePosition() { return _eyePositions[ovrEye_Left]; } - static glm::vec3 getRightEyePosition() { return _eyePositions[ovrEye_Right]; } + static glm::vec3 getLeftEyePosition(); + static glm::vec3 getRightEyePosition(); static int getHMDScreen(); static glm::mat4 getEyeProjection(int eye); static glm::mat4 getEyePose(int eye); - -private: - static void initSdk(); - static void shutdownSdk(); - - static bool _isConnected; - static glm::vec3 _eyePositions[ovrEye_Count]; - static ovrHmd _ovrHmd; - static ovrFovPort _eyeFov[ovrEye_Count]; - static ovrVector3f _eyeOffset[ovrEye_Count]; - static glm::mat4 _eyeProjection[ovrEye_Count]; - static ovrEyeRenderDesc _eyeRenderDesc[ovrEye_Count]; - static ovrRecti _eyeViewports[ovrEye_Count]; - static ovrSizei _renderTargetSize; - static unsigned int _frameIndex; - static bool _frameTimingActive; - static Camera* _camera; - static ovrEyeType _activeEye; - static bool _hswDismissed; - - static void calibrate(const glm::vec3 position, const glm::quat orientation); - enum CalibrationState { - UNCALIBRATED, - WAITING_FOR_DELTA, - WAITING_FOR_ZERO, - WAITING_FOR_ZERO_HELD, - CALIBRATED - }; - static void positionCalibrationBillboard(Text3DOverlay* message); - static float CALIBRATION_DELTA_MINIMUM_LENGTH; - static float CALIBRATION_DELTA_MINIMUM_ANGLE; - static float CALIBRATION_ZERO_MAXIMUM_LENGTH; - static float CALIBRATION_ZERO_MAXIMUM_ANGLE; - static quint64 CALIBRATION_ZERO_HOLD_TIME; - static float CALIBRATION_MESSAGE_DISTANCE; - static CalibrationState _calibrationState; - static glm::vec3 _calibrationPosition; - static glm::quat _calibrationOrientation; - static quint64 _calibrationStartTime; - static int _calibrationMessage; - // TODO drop this variable and use the existing 'Developer | Render | Scale Resolution' value - static ovrSizei _recommendedTexSize; - static float _offscreenRenderScale; - static bool _eyePerFrameMode; - static ovrEyeType _lastEyeRendered; -#ifdef Q_OS_WIN - static SwapFramebufferWrapper* _swapFbo; - static MirrorFramebufferWrapper* _mirrorFbo; - static ovrLayerEyeFov _sceneLayer; -#else - static ovrTexture _eyeTextures[ovrEye_Count]; - static GlWindow* _outputWindow; -#endif + static glm::mat4 getHeadPose(); }; - -inline glm::mat4 toGlm(const ovrMatrix4f & om) { - return glm::transpose(glm::make_mat4(&om.M[0][0])); -} - -inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) { - return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true)); -} - -inline glm::vec3 toGlm(const ovrVector3f & ov) { - return glm::make_vec3(&ov.x); -} - -inline glm::vec2 toGlm(const ovrVector2f & ov) { - return glm::make_vec2(&ov.x); -} - -inline glm::ivec2 toGlm(const ovrVector2i & ov) { - return glm::ivec2(ov.x, ov.y); -} - -inline glm::uvec2 toGlm(const ovrSizei & ov) { - return glm::uvec2(ov.w, ov.h); -} - -inline glm::quat toGlm(const ovrQuatf & oq) { - return glm::make_quat(&oq.x); -} - -inline glm::mat4 toGlm(const ovrPosef & op) { - glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation)); - glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position)); - return translation * orientation; -} - -inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) { - ovrMatrix4f result; - glm::mat4 transposed(glm::transpose(m)); - memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16); - return result; -} - -inline ovrVector3f ovrFromGlm(const glm::vec3 & v) { - return{ v.x, v.y, v.z }; -} - -inline ovrVector2f ovrFromGlm(const glm::vec2 & v) { - return{ v.x, v.y }; -} - -inline ovrSizei ovrFromGlm(const glm::uvec2 & v) { - return{ (int)v.x, (int)v.y }; -} - -inline ovrQuatf ovrFromGlm(const glm::quat & q) { - return{ q.x, q.y, q.z, q.w }; -} - #endif // hifi_OculusManager_h diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 8e8290f060..bb6ea8f1e8 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -334,12 +334,12 @@ void ApplicationCompositor::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& or // Intersection UI overlay space glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; - glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius; - intersectionWithUi += overlayPosition; + glm::vec3 worldSpaceIntersection = (glm::normalize(worldSpaceDirection) * _oculusUIRadius) + overlayPosition; + glm::vec3 worldSpaceHeadPosition = (overlayOrientation * glm::vec3(qApp->getHeadPose()[3])) + overlayPosition; // Intersection in world space - origin = overlayPosition; - direction = glm::normalize(intersectionWithUi - origin); + origin = worldSpaceHeadPosition; + direction = glm::normalize(worldSpaceIntersection - worldSpaceHeadPosition); } //Caculate the click location using one of the sixense controllers. Scale is not applied From a9eccb687ad8e0408ab742916d5c915d5fd33fae Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 22 Jun 2015 11:26:17 -0700 Subject: [PATCH 26/37] fix for double store on index path lookup --- libraries/networking/src/AddressManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index a8ed54fdd1..591b844aed 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -308,6 +308,9 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const handlePath(returnedPath, trigger); } } else { + // we're going to hit the index path, set that as the _newHostLookupPath + _newHostLookupPath = INDEX_PATH; + // we didn't override the path or get one back - ask the DS for the viewpoint of its index path // which we will jump to if it exists emit pathChangeRequired(INDEX_PATH); @@ -479,6 +482,7 @@ bool AddressManager::handleViewpoint(const QString& viewpointString, bool should // We use _newHostLookupPath to determine if the client has already stored its last address // before moving to a new host thanks to the information in the same lookup URL. + if (definitelyPathOnly || (!pathString.isEmpty() && pathString != _newHostLookupPath)) { addCurrentAddressToHistory(LookupTrigger::UserInput); } From e66206ec4fb7ae32cb70016f1a109c1ec026e809 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 22 Jun 2015 11:29:44 -0700 Subject: [PATCH 27/37] Fixed tooltip position relative to the cursor --- interface/resources/qml/Tooltip.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/Tooltip.qml b/interface/resources/qml/Tooltip.qml index 0ad3efc5a5..c836030ba1 100644 --- a/interface/resources/qml/Tooltip.qml +++ b/interface/resources/qml/Tooltip.qml @@ -7,8 +7,9 @@ Hifi.Tooltip { id: root HifiConstants { id: hifi } // FIXME adjust position based on the edges of the screen - x: lastMousePosition.x + 20 - y: lastMousePosition.y + 5 + x: (lastMousePosition.x > surfaceSize.width/2) ? lastMousePosition.x - 140 : lastMousePosition.x + 20 + //y: lastMousePosition.y + 5 + y: (lastMousePosition.y > surfaceSize.height/2) ? lastMousePosition.y - 70 : lastMousePosition.y + 5 implicitWidth: border.implicitWidth implicitHeight: border.implicitHeight From ff21c222451f87e4c234ea9999f15cb9ec58de30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 22 Jun 2015 11:56:07 -0700 Subject: [PATCH 28/37] fix AC crash with no controller scripting interface --- libraries/script-engine/src/ScriptEngine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 182a0aea8d..0945a556f2 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -317,7 +317,10 @@ void ScriptEngine::init() { registerAnimationTypes(this); registerAvatarTypes(this); registerAudioMetaTypes(this); - _controllerScriptingInterface->registerControllerTypes(this); + + if (_controllerScriptingInterface) { + _controllerScriptingInterface->registerControllerTypes(this); + } qScriptRegisterMetaType(this, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly); qScriptRegisterMetaType(this, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue); From 8c9deb9d160b2c822e37af90960878a84f71f4d1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Jun 2015 12:04:55 -0700 Subject: [PATCH 29/37] Removing flickering mouse cursor in HMD --- interface/src/ui/ApplicationCompositor.cpp | 29 ---------------------- interface/src/ui/ApplicationCompositor.h | 1 - 2 files changed, 30 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 8e8290f060..28fbd813d1 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -394,42 +394,13 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi void ApplicationCompositor::renderPointers(gpu::Batch& batch) { if (qApp->isHMDMode() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { //If we are in oculus, render reticle later - if (_lastMouseMove == 0) { - _lastMouseMove = usecTimestampNow(); - } QPoint position = QPoint(qApp->getTrueMouseX(), qApp->getTrueMouseY()); - - static const int MAX_IDLE_TIME = 3; - if (_reticlePosition[MOUSE] != position) { - _lastMouseMove = usecTimestampNow(); - } else if (usecTimestampNow() - _lastMouseMove > MAX_IDLE_TIME * USECS_PER_SECOND) { - //float pitch = 0.0f, yaw = 0.0f, roll = 0.0f; // radians - //OculusManager::getEulerAngles(yaw, pitch, roll); - glm::quat orientation = qApp->getHeadOrientation(); // (glm::vec3(pitch, yaw, roll)); - glm::vec3 result; - - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - if (calculateRayUICollisionPoint(myAvatar->getEyePosition(), - myAvatar->getOrientation() * orientation * IDENTITY_FRONT, - result)) { - glm::vec3 lookAtDirection = glm::inverse(myAvatar->getOrientation()) * (result - myAvatar->getDefaultEyePosition()); - glm::vec2 spericalPos = directionToSpherical(glm::normalize(lookAtDirection)); - glm::vec2 screenPos = sphericalToScreen(spericalPos); - position = QPoint(screenPos.x, screenPos.y); - // FIXME - //glCanvas->cursor().setPos(glCanvas->mapToGlobal(position)); - } else { - qDebug() << "No collision point"; - } - } - _reticlePosition[MOUSE] = position; _reticleActive[MOUSE] = true; _magActive[MOUSE] = _magnifier; _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; } else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { - _lastMouseMove = 0; //only render controller pointer if we aren't already rendering a mouse pointer _reticleActive[MOUSE] = false; _magActive[MOUSE] = false; diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 0063319796..fc0b37127f 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -97,7 +97,6 @@ private: QPoint _reticlePosition[NUMBER_OF_RETICLES]; bool _magActive[NUMBER_OF_RETICLES]; float _magSizeMult[NUMBER_OF_RETICLES]; - quint64 _lastMouseMove{ 0 }; bool _magnifier{ true }; float _alpha{ 1.0f }; From 1cfc0b2e42eca983031e62760b6c8424559fbcd0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Jun 2015 12:06:08 -0700 Subject: [PATCH 30/37] Fixing mac/linux compilation --- interface/src/devices/OculusManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 82c5ff90c6..9d7146cbe7 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -235,14 +235,14 @@ private: } }; -SwapFramebufferWrapper* _swapFbo{ nullptr }; -MirrorFramebufferWrapper* _mirrorFbo{ nullptr }; -ovrLayerEyeFov _sceneLayer; +static SwapFramebufferWrapper* _swapFbo{ nullptr }; +static MirrorFramebufferWrapper* _mirrorFbo{ nullptr }; +static ovrLayerEyeFov _sceneLayer; #else -ovrTexture OculusManager::_eyeTextures[ovrEye_Count]; -GlWindow* OculusManager::_outputWindow{ nullptr }; +static ovrTexture _eyeTextures[ovrEye_Count]; +static GlWindow* _outputWindow{ nullptr }; #endif From 9014e8c03838a8cbf5d097a61af8496429414522 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 15:34:46 -0700 Subject: [PATCH 31/37] increased dimensions for line entity --- examples/paint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/paint.js b/examples/paint.js index 20196601df..31ffd02506 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -11,7 +11,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -var LINE_DIMENSIONS = 1; +var LINE_DIMENSIONS = 5; var LIFETIME = 6000; var colorPalette = [{ From b7c728a794668c905252e6719c6d25b0a9045a55 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 22 Jun 2015 15:40:02 -0700 Subject: [PATCH 32/37] assert AvatarMotionState unhooked before delete --- interface/src/avatar/Avatar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 731c69979e..0213afb675 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -107,6 +107,7 @@ Avatar::Avatar() : } Avatar::~Avatar() { + assert(_motionState == nullptr); for(auto attachment : _unusedAttachments) { delete attachment; } From ce9dfc098b0a9353bf9ceb8982e994497da12002 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 22 Jun 2015 15:40:26 -0700 Subject: [PATCH 33/37] unhook motionstate before removing avatar --- interface/src/avatar/AvatarManager.cpp | 12 +++++++----- interface/src/avatar/AvatarManager.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 51fae3439a..88f550d68c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -114,6 +114,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // DO NOT update or fade out uninitialized Avatars ++avatarIterator; } else if (avatar->shouldDie()) { + removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); avatarIterator = _avatarHash.erase(avatarIterator); } else { @@ -163,12 +164,13 @@ AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWe } // protected -void AvatarManager::removeAvatarMotionState(Avatar* avatar) { - AvatarMotionState* motionState= avatar->_motionState; +void AvatarManager::removeAvatarMotionState(AvatarSharedPointer avatar) { + auto rawPointer = std::static_pointer_cast(avatar); + AvatarMotionState* motionState= rawPointer->_motionState; if (motionState) { // clean up physics stuff motionState->clearObjectBackPointer(); - avatar->_motionState = nullptr; + rawPointer->_motionState = nullptr; _avatarMotionStates.remove(motionState); _motionStatesToAdd.remove(motionState); _motionStatesToDelete.push_back(motionState); @@ -181,7 +183,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) { if (avatarIterator != _avatarHash.end()) { std::shared_ptr avatar = std::dynamic_pointer_cast(avatarIterator.value()); if (avatar != _myAvatar && avatar->isInitialized()) { - removeAvatarMotionState(avatar.get()); + removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); _avatarHash.erase(avatarIterator); } @@ -197,7 +199,7 @@ void AvatarManager::clearOtherAvatars() { // don't remove myAvatar or uninitialized avatars from the list ++avatarIterator; } else { - removeAvatarMotionState(avatar.get()); + removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); avatarIterator = _avatarHash.erase(avatarIterator); } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index b4482c5a34..9d1c94a47e 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -73,7 +73,7 @@ private: // virtual overrides virtual AvatarSharedPointer newSharedAvatar(); virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer); - void removeAvatarMotionState(Avatar* avatar); + void removeAvatarMotionState(AvatarSharedPointer avatar); virtual void removeAvatar(const QUuid& sessionUUID); QVector _avatarFades; From ce3d1bd9a4ae2a519388c00c8c5bf076fbec81fa Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Mon, 22 Jun 2015 16:19:31 -0700 Subject: [PATCH 34/37] Fix the 2D text overlay backgrounds to stop using a previously bound texture --- interface/src/ui/overlays/TextOverlay.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index e709bbd9fc..1a8b74dea8 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -80,6 +80,7 @@ void TextOverlay::render(RenderArgs* args) { glm::vec2 topLeft(left, top); glm::vec2 bottomRight(right, bottom); + glBindTexture(GL_TEXTURE_2D, 0); DependencyManager::get()->renderQuad(topLeft, bottomRight, quadColor); const int leftAdjust = -1; // required to make text render relative to left edge of bounds From f833121032d0f8309ca5e0ce25d0b0c43b9ba3c5 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Mon, 22 Jun 2015 19:55:52 -0700 Subject: [PATCH 35/37] Fixing the initial missing UI on retina displays, again --- interface/src/Application.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b0d91f8619..a2b5cc8b00 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1063,9 +1063,7 @@ void Application::resizeGL() { auto offscreenUi = DependencyManager::get(); auto canvasSize = _glWidget->size(); - if (canvasSize != offscreenUi->getWindow()->size()) { - offscreenUi->resize(canvasSize); - } + offscreenUi->resize(canvasSize); _glWidget->makeCurrent(); } From cf579ab275b192683b1c449b592686738e6bbf58 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 23 Jun 2015 09:52:29 -0700 Subject: [PATCH 36/37] fixed bullet size to be smaller --- examples/controllers/hydra/gun.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index 7d024e2fd3..26eee029af 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -181,7 +181,7 @@ function entityCollisionWithEntity(entity1, entity2, collision) { } function shootBullet(position, velocity, grenade) { - var BULLET_SIZE = 0.10; + var BULLET_SIZE = .09; var BULLET_LIFETIME = 10.0; var BULLET_GRAVITY = -0.25; var GRENADE_VELOCITY = 15.0; From b1190bee6e75772032ff4881cabebbf2759e976c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 23 Jun 2015 14:13:13 -0700 Subject: [PATCH 37/37] deleted empty files I accidently committed. --- libraries/entities/src/QuadEntityItem.cpp | 9 --------- libraries/entities/src/QuadEntityItem.h | 14 -------------- 2 files changed, 23 deletions(-) delete mode 100644 libraries/entities/src/QuadEntityItem.cpp delete mode 100644 libraries/entities/src/QuadEntityItem.h diff --git a/libraries/entities/src/QuadEntityItem.cpp b/libraries/entities/src/QuadEntityItem.cpp deleted file mode 100644 index 0ac04129be..0000000000 --- a/libraries/entities/src/QuadEntityItem.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// QuadEntityItem.cpp -// hifi -// -// Created by eric levin on 6/22/15. -// -// - -#include "QuadEntityItem.h" diff --git a/libraries/entities/src/QuadEntityItem.h b/libraries/entities/src/QuadEntityItem.h deleted file mode 100644 index 64f733d6b5..0000000000 --- a/libraries/entities/src/QuadEntityItem.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// QuadEntityItem.h -// hifi -// -// Created by eric levin on 6/22/15. -// -// - -#ifndef __hifi__QuadEntityItem__ -#define __hifi__QuadEntityItem__ - -#include - -#endif /* defined(__hifi__QuadEntityItem__) */