From 16f4cffbd3c2d9d187ccf2cfbad1b171a60c28a0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 31 Oct 2014 12:19:26 -0700 Subject: [PATCH 01/16] Center HMD HUD and magnifiers on default eye position --- interface/src/ui/ApplicationOverlay.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index d8d2213d8f..37bba98ecc 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -380,7 +380,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glPushMatrix(); const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getHead()->getEyePosition(); + const glm::vec3& position = myAvatar->getDefaultEyePosition(); glm::mat4 rotation = glm::toMat4(orientation); @@ -414,7 +414,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { renderTexturedHemisphere(); - renderPointersOculus(myAvatar->getHead()->getEyePosition()); + renderPointersOculus(myAvatar->getDefaultEyePosition()); glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); @@ -1220,7 +1220,7 @@ void ApplicationOverlay::renderTexturedHemisphere() { Application* application = Application::getInstance(); MyAvatar* myAvatar = application->getAvatar(); const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getHead()->getEyePosition(); + const glm::vec3& position = myAvatar->getDefaultEyePosition(); glm::mat4 rotation = glm::toMat4(orientation); From 170e328f5a496145afecba3ba0d0f0e50ac3c02a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 31 Oct 2014 12:40:16 -0700 Subject: [PATCH 02/16] Fix similar problem for HMD third person view getUprightHeadPosition() changes with avatar lean. --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0752f9fa9e..1ec8078f53 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -620,8 +620,8 @@ void Application::paintGL() { } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f; - _myCamera.setPosition(_myAvatar->getUprightHeadPosition() + - _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale()); + _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale()); if (OculusManager::isConnected()) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } else { From 8e58e6e3b00321a59ce2ecd56830d63f1aff9e1d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 31 Oct 2014 12:48:30 -0700 Subject: [PATCH 03/16] Remove unused methods --- interface/src/avatar/Avatar.cpp | 4 ---- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/MyAvatar.cpp | 4 ---- interface/src/avatar/MyAvatar.h | 1 - 4 files changed, 10 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 59c8c90d1c..e29f68e585 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -1057,10 +1057,6 @@ float Avatar::getPelvisFloatingHeight() const { return -_skeletonModel.getBindExtents().minimum.y; } -float Avatar::getPelvisToHeadLength() const { - return glm::distance(_position, getHead()->getPosition()); -} - void Avatar::setShowDisplayName(bool showDisplayName) { if (!Menu::getInstance()->isOptionChecked(MenuOption::NamesAboveHeads)) { _displayNameAlpha = 0.0f; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 29fb4cf241..376e229d0c 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -230,7 +230,6 @@ protected: float getSkeletonHeight() const; float getHeadHeight() const; float getPelvisFloatingHeight() const; - float getPelvisToHeadLength() const; glm::vec3 getDisplayNamePosition(); void renderDisplayName(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 623631d5e5..2f7a123e4b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1004,10 +1004,6 @@ bool MyAvatar::isLookingAtLeftEye() { return _isLookingAtLeftEye; } -glm::vec3 MyAvatar::getUprightHeadPosition() const { - return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f); -} - glm::vec3 MyAvatar::getDefaultEyePosition() const { return _position + getWorldAlignedOrientation() * _skeletonModel.getDefaultEyeModelPosition(); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index aa3d569e2f..326e0e2665 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -66,7 +66,6 @@ public: const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } - glm::vec3 getUprightHeadPosition() const; glm::vec3 getDefaultEyePosition() const; bool getShouldRenderLocally() const { return _shouldRender; } From 02f9bb489f47e54e15c8d76e63aaf553a2492b0c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 31 Oct 2014 12:49:21 -0700 Subject: [PATCH 04/16] Fix some build warnings while in the vicinity --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2f7a123e4b..79ab9eda81 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -416,7 +416,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getGeometryCache()->renderSphere(0.2, 10, 10); + Application::getInstance()->getGeometryCache()->renderSphere(0.2f, 10.0f, 10.0f); glPopMatrix(); // Head Sphere @@ -424,7 +424,7 @@ void MyAvatar::renderDebugBodyPoints() { glPushMatrix(); glColor4f(0, 1, 0, .5f); glTranslatef(position.x, position.y, position.z); - Application::getInstance()->getGeometryCache()->renderSphere(0.15, 10, 10); + Application::getInstance()->getGeometryCache()->renderSphere(0.15f, 10.0f, 10.0f); glPopMatrix(); } From a9040c1a53170b580dccb6f3aedc84eb811a6582 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 31 Oct 2014 15:15:44 -0700 Subject: [PATCH 05/16] Minor adjustment to Oculus pick ray calc --- interface/src/ui/ApplicationOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 37bba98ecc..4d2c710be7 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -183,7 +183,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc float dist = sqrt(x * x + y * y); float z = -sqrt(1.0f - dist * dist); - glm::vec3 relativePosition = myAvatar->getHead()->getEyePosition() + + glm::vec3 relativePosition = myAvatar->getDefaultEyePosition() + glm::normalize(myAvatar->getOrientation() * glm::vec3(x, y, z)); //Rotate the UI pick ray by the avatar orientation From af74fc09b946a8c449fcb1a53b9ba9884813d96b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 1 Nov 2014 02:42:22 +0100 Subject: [PATCH 06/16] Adds AudioDevice mute functionality to ScriptEngine --- examples/audioMuteExample.js | 50 +++++++++++++++++++ interface/src/Application.cpp | 3 ++ .../AudioDeviceScriptingInterface.cpp | 8 +++ .../scripting/AudioDeviceScriptingInterface.h | 6 +++ 4 files changed, 67 insertions(+) create mode 100644 examples/audioMuteExample.js diff --git a/examples/audioMuteExample.js b/examples/audioMuteExample.js new file mode 100644 index 0000000000..efdd39e5aa --- /dev/null +++ b/examples/audioMuteExample.js @@ -0,0 +1,50 @@ +// +// audioMuteExample.js +// examples +// +// Created by Thijs Wenker on 10/31/14. +// Copyright 2014 High Fidelity, Inc. +// +// This example shows how to use the AudioDevice mute functions. +// Press the MUTE/UNMUTE button to see it function. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var toggleMuteButton = Overlays.addOverlay("text", { + x: 50, + y: 50, + width: 190, + height: 50, + backgroundColor: { red: 255, green: 255, blue: 255}, + color: { red: 255, green: 0, blue: 0}, + font: {size: 30}, + topMargin: 10 +}); + +function muteButtonText() { + print("Audio Muted: " + AudioDevice.getMuted()); +} + +function onMuteStateChanged() { + Overlays.editOverlay(toggleMuteButton, + AudioDevice.getMuted() ? {text: "UNMUTE", leftMargin: 10} : {text: "MUTE", leftMargin: 38}); + print("Audio Muted: " + AudioDevice.getMuted()); +} + +function mousePressEvent(event) { + if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleMuteButton) { + AudioDevice.toggleMute() + } +} + +function scriptEnding() { + Overlays.deleteOverlay(toggleMuteButton); +} + +onMuteStateChanged(); + +AudioDevice.muteToggled.connect(onMuteStateChanged); +Controller.mousePressEvent.connect(mousePressEvent); +Script.scriptEnding.connect(scriptEnding); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0752f9fa9e..1a293628b7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1966,6 +1966,9 @@ void Application::init() { connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector, &AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection); + connect(getAudio(), &Audio::muteToggled, AudioDeviceScriptingInterface::getInstance(), + &AudioDeviceScriptingInterface::muteToggled, Qt::DirectConnection); + // save settings when avatar changes connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings); } diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp index bcb5fc308d..e3826a24ea 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.cpp +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -78,3 +78,11 @@ void AudioDeviceScriptingInterface::setReverb(bool reverb) { void AudioDeviceScriptingInterface::setReverbOptions(const AudioEffectOptions* options) { Application::getInstance()->getAudio()->setReverbOptions(options); } + +void AudioDeviceScriptingInterface::toggleMute() { + Application::getInstance()->getAudio()->toggleMute(); +} + +bool AudioDeviceScriptingInterface::getMuted() { + return Application::getInstance()->getAudio()->getMuted(); +} diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.h b/interface/src/scripting/AudioDeviceScriptingInterface.h index 45bdbc92e2..b7febaea07 100644 --- a/interface/src/scripting/AudioDeviceScriptingInterface.h +++ b/interface/src/scripting/AudioDeviceScriptingInterface.h @@ -41,6 +41,12 @@ public slots: void setInputVolume(float volume); void setReverb(bool reverb); void setReverbOptions(const AudioEffectOptions* options); + + bool getMuted(); + void toggleMute(); + +signals: + void muteToggled(); }; #endif // hifi_AudioDeviceScriptingInterface_h From 3b56f613e23a596d6f4d1a8e623e7e34995dce08 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Nov 2014 13:21:51 -0800 Subject: [PATCH 07/16] Cone render function, some cleanup of GeometryCache methods. --- .../src/renderer/DeferredLightingEffect.cpp | 6 + .../src/renderer/DeferredLightingEffect.h | 3 + interface/src/renderer/GeometryCache.cpp | 133 +++++++++++++++--- interface/src/renderer/GeometryCache.h | 2 + 4 files changed, 126 insertions(+), 18 deletions(-) diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index f1668629da..7a3f648e37 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -73,6 +73,12 @@ void DeferredLightingEffect::renderWireCube(float size) { releaseSimpleProgram(); } +void DeferredLightingEffect::renderSolidCone(float base, float height, int slices, int stacks) { + bindSimpleProgram(); + Application::getInstance()->getGeometryCache()->renderCone(base, height, slices, stacks); + releaseSimpleProgram(); +} + void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient, const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, float linearAttenuation, float quadraticAttenuation) { diff --git a/interface/src/renderer/DeferredLightingEffect.h b/interface/src/renderer/DeferredLightingEffect.h index 33fe6b474d..ce8b2b9759 100644 --- a/interface/src/renderer/DeferredLightingEffect.h +++ b/interface/src/renderer/DeferredLightingEffect.h @@ -47,6 +47,9 @@ public: //// Renders a wireframe cube with the simple program. void renderWireCube(float size); + + //// Renders a solid cone with the simple program. + void renderSolidCone(float base, float height, int slices, int stacks); /// Adds a point light to render for the current frame. void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f), diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index c3b0a58263..5aa4012cc3 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -110,15 +110,18 @@ void GeometryCache::renderHemisphere(int slices, int stacks) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } +const int NUM_VERTICES_PER_TRIANGLE = 3; +const int NUM_TRIANGLES_PER_QUAD = 2; +const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD; +const int NUM_COORDS_PER_VERTEX = 3; +const int NUM_BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat); +const int NUM_BYTES_PER_INDEX = sizeof(GLushort); void GeometryCache::renderSphere(float radius, int slices, int stacks) { VerticesIndices& vbo = _sphereVBOs[IntPair(slices, stacks)]; - int vertices = slices * (stacks - 1) + 2; - const int NUM_VERTICES_PER_TRIANGLE = 3; - const int NUM_TRIANGLES_PER_QUAD = 2; - int indices = slices * NUM_TRIANGLES_PER_QUAD * NUM_VERTICES_PER_TRIANGLE * (stacks - 1) + slices * NUM_TRIANGLES_PER_QUAD * NUM_VERTICES_PER_TRIANGLE; - if (vbo.first == 0) { - const int NUM_COORDS_PER_VERTEX = 3; + int vertices = slices * (stacks - 1) + 2; + int indices = slices * stacks * NUM_VERTICES_PER_TRIANGULATED_QUAD; + if (vbo.first == 0) { GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX]; GLfloat* vertex = vertexData; @@ -148,8 +151,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) { glGenBuffers(1, &vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first); - const int BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat); - glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); delete[] vertexData; GLushort* indexData = new GLushort[indices]; @@ -192,8 +194,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) { glGenBuffers(1, &vbo.second); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); - const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); delete[] indexData; } else { @@ -239,8 +240,7 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) { glGenBuffers(1, &vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first); - const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat); - glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); delete[] vertexData; GLushort* indexData = new GLushort[indices]; @@ -263,8 +263,7 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) { glGenBuffers(1, &vbo.second); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); - const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); delete[] indexData; } else { @@ -313,8 +312,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) { glGenBuffers(1, &vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first); - const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat); - glBufferData(GL_ARRAY_BUFFER, 2 * vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); delete[] vertexData; GLushort* indexData = new GLushort[indices]; @@ -337,8 +335,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) { glGenBuffers(1, &vbo.second); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); - const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); delete[] indexData; } else { @@ -360,6 +357,106 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } +void GeometryCache::renderCone(float base, float height, int slices, int stacks) { + VerticesIndices& vbo = _halfCylinderVBOs[IntPair(slices, stacks)]; + int vertices = (stacks + 2) * slices; + int baseTriangles = slices - 2; + int indices = NUM_VERTICES_PER_TRIANGULATED_QUAD * slices * stacks + NUM_VERTICES_PER_TRIANGLE * baseTriangles; + if (vbo.first == 0) { + GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX * 2]; + GLfloat* vertex = vertexData; + // cap + for (int i = 0; i < slices; i++) { + float theta = TWO_PI * i / slices; + + //normals + *(vertex++) = 0.0f; + *(vertex++) = 0.0f; + *(vertex++) = -1.0f; + + // vertices + *(vertex++) = cosf(theta); + *(vertex++) = sinf(theta); + *(vertex++) = 0.0f; + } + // body + for (int i = 0; i <= stacks; i++) { + float z = (float)i / stacks; + float radius = 1.0f - z; + + for (int j = 0; j < slices; j++) { + float theta = TWO_PI * j / slices; + + //normals + *(vertex++) = cosf(theta) / SQUARE_ROOT_OF_2; + *(vertex++) = sinf(theta) / SQUARE_ROOT_OF_2; + *(vertex++) = 1.0f / SQUARE_ROOT_OF_2; + + // vertices + *(vertex++) = radius * cosf(theta); + *(vertex++) = radius * sinf(theta); + *(vertex++) = z; + } + } + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < baseTriangles; i++) { + *(index++) = 0; + *(index++) = i + 1; + *(index++) = i + 2; + } + for (int i = 1; i <= stacks; i++) { + GLushort bottom = i * slices; + GLushort top = bottom + slices; + for (int j = 0; j < slices; j++) { + int next = (j + 1) % slices; + + *(index++) = bottom + j; + *(index++) = top + next; + *(index++) = top + j; + + *(index++) = bottom + j; + *(index++) = bottom + next; + *(index++) = top + next; + } + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + int stride = NUM_VERTICES_PER_TRIANGULATED_QUAD * sizeof(float); + glNormalPointer(GL_FLOAT, stride, 0); + glVertexPointer(NUM_COORDS_PER_VERTEX, GL_FLOAT, stride, (const void *)(NUM_COORDS_PER_VERTEX * sizeof(float))); + + glPushMatrix(); + glScalef(base, base, height); + + glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + + glPopMatrix(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + void GeometryCache::renderGrid(int xDivisions, int yDivisions) { QOpenGLBuffer& buffer = _gridBuffers[IntPair(xDivisions, yDivisions)]; int vertices = (xDivisions + 1 + yDivisions + 1) * 2; diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 4ed6c9943d..bb6a19b1a9 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -42,6 +42,7 @@ public: void renderSphere(float radius, int slices, int stacks); void renderSquare(int xDivisions, int yDivisions); void renderHalfCylinder(int slices, int stacks); + void renderCone(float base, float height, int slices, int stacks); void renderGrid(int xDivisions, int yDivisions); /// Loads geometry from the specified URL. @@ -71,6 +72,7 @@ private: QHash _sphereVBOs; QHash _squareVBOs; QHash _halfCylinderVBOs; + QHash _coneVBOs; QHash _gridBuffers; QHash > _networkGeometry; From 1763d8f7f08f9b16d2723ce7131841c0d5c76426 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Nov 2014 17:29:19 -0800 Subject: [PATCH 08/16] Switch to using cones/spheres (as opposed to screen-aligned quads) with depth testing for light geometry. --- .../shaders/deferred_light_limited.vert | 48 ++----------------- interface/resources/shaders/point_light.frag | 7 ++- interface/resources/shaders/spot_light.frag | 7 ++- .../src/renderer/DeferredLightingEffect.cpp | 27 ++++++++++- 4 files changed, 40 insertions(+), 49 deletions(-) diff --git a/interface/resources/shaders/deferred_light_limited.vert b/interface/resources/shaders/deferred_light_limited.vert index 8a69632f44..849d14bda4 100644 --- a/interface/resources/shaders/deferred_light_limited.vert +++ b/interface/resources/shaders/deferred_light_limited.vert @@ -11,50 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the radius (hard cutoff) of the light effect -uniform float radius; - void main(void) { - // find the right "right" direction - vec3 firstRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(0.0, 1.0, 0.0)); - vec3 secondRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(1.0, 0.0, 0.0)); - vec3 right = mix(firstRightCandidate, secondRightCandidate, step(length(firstRightCandidate), length(secondRightCandidate))); - right = normalize(right); - - // and the "up" - vec3 up = cross(right, gl_LightSource[1].spotDirection); - - // and the "back," which depends on whether this is a spot light - vec3 back = -gl_LightSource[1].spotDirection * step(gl_LightSource[1].spotCosCutoff, 0.0); - - // find the eight corners of the bounds - vec4 c0 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (-up - right + back), 1.0); - vec4 c1 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (-up + right + back), 1.0); - vec4 c2 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (up - right + back), 1.0); - vec4 c3 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (up + right + back), 1.0); - vec4 c4 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (-up - right + gl_LightSource[1].spotDirection), 1.0); - vec4 c5 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (-up + right + gl_LightSource[1].spotDirection), 1.0); - vec4 c6 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (up - right + gl_LightSource[1].spotDirection), 1.0); - vec4 c7 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz + - radius * (up + right + gl_LightSource[1].spotDirection), 1.0); - - // find their projected extents - vec2 extents = max( - max(max(gl_Vertex.xy * (c0.xy / max(c0.w, 0.001)), gl_Vertex.xy * (c1.xy / max(c1.w, 0.001))), - max(gl_Vertex.xy * (c2.xy / max(c2.w, 0.001)), gl_Vertex.xy * (c3.xy / max(c3.w, 0.001)))), - max(max(gl_Vertex.xy * (c4.xy / max(c4.w, 0.001)), gl_Vertex.xy * (c5.xy / max(c5.w, 0.001))), - max(gl_Vertex.xy * (c6.xy / max(c6.w, 0.001)), gl_Vertex.xy * (c7.xy / max(c7.w, 0.001))))); - - // make sure they don't extend beyond the screen - extents = min(extents, vec2(1.0, 1.0)); - - gl_Position = vec4(gl_Vertex.xy * extents, 0.0, 1.0); - gl_TexCoord[0] = vec4(dot(gl_Position, gl_ObjectPlaneS[3]), dot(gl_Position, gl_ObjectPlaneT[3]), 0.0, 1.0); + gl_Position = ftransform(); + vec4 projected = gl_Position / gl_Position.w; + gl_TexCoord[0] = vec4(dot(projected, gl_ObjectPlaneS[3]), dot(projected, gl_ObjectPlaneT[3]), 0.0, 1.0); } diff --git a/interface/resources/shaders/point_light.frag b/interface/resources/shaders/point_light.frag index 31de0fe7d2..b9ba638885 100644 --- a/interface/resources/shaders/point_light.frag +++ b/interface/resources/shaders/point_light.frag @@ -39,8 +39,13 @@ uniform vec2 depthTexCoordScale; uniform float radius; void main(void) { + // get the depth and exit early if it doesn't pass the test + float depth = texture2D(depthMap, gl_TexCoord[0].st).r; + if (depth < gl_FragCoord.z) { + discard; + } // compute the view space position using the depth - float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + float z = near / (depth * depthScale - 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); // get the normal from the map diff --git a/interface/resources/shaders/spot_light.frag b/interface/resources/shaders/spot_light.frag index 33469be0c7..a496abd7b2 100644 --- a/interface/resources/shaders/spot_light.frag +++ b/interface/resources/shaders/spot_light.frag @@ -39,8 +39,13 @@ uniform vec2 depthTexCoordScale; uniform float radius; void main(void) { + // get the depth and exit early if it doesn't pass the test + float depth = texture2D(depthMap, gl_TexCoord[0].st).r; + if (depth < gl_FragCoord.z) { + discard; + } // compute the view space position using the depth - float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0); + float z = near / (depth * depthScale - 1.0); vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); // get the normal from the map diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 7a3f648e37..e1af5e5046 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -222,11 +222,16 @@ void DeferredLightingEffect::render() { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_CULL_FACE); + glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients); glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients); + // enlarge the scales slightly to account for tesselation + const float SCALE_EXPANSION = 0.1f; + if (!_pointLights.isEmpty()) { _pointLight.bind(); _pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal); @@ -244,7 +249,12 @@ void DeferredLightingEffect::render() { glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation); glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation); - renderFullscreenQuad(); + glPushMatrix(); + glTranslatef(light.position.x, light.position.y, light.position.z); + + Application::getInstance()->getGeometryCache()->renderSphere(light.radius * (1.0f + SCALE_EXPANSION), 32, 32); + + glPopMatrix(); } _pointLights.clear(); @@ -271,7 +281,18 @@ void DeferredLightingEffect::render() { glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent); glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff)); - renderFullscreenQuad(); + glPushMatrix(); + glTranslatef(light.position.x, light.position.y, light.position.z); + glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light.direction); + glm::vec3 axis = glm::axis(spotRotation); + glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); + + glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); + float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); + Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), + expandedRadius, 32, 8); + + glPopMatrix(); } _spotLights.clear(); @@ -291,6 +312,8 @@ void DeferredLightingEffect::render() { freeFBO->release(); + glDisable(GL_CULL_FACE); + // now transfer the lit region to the primary fbo glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glColorMask(true, true, true, false); From feabd1d5b35e73c4ee8cd3c698c2c1ab3746a72b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Nov 2014 18:08:56 -0800 Subject: [PATCH 09/16] Use a fullscreen quad when we're actually inside the light influence. --- .../src/renderer/DeferredLightingEffect.cpp | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index e1af5e5046..c4a7a2482a 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -232,6 +232,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.1f; + const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); + if (!_pointLights.isEmpty()) { _pointLight.bind(); _pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal); @@ -250,9 +252,24 @@ void DeferredLightingEffect::render() { glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation); glPushMatrix(); - glTranslatef(light.position.x, light.position.y, light.position.z); - Application::getInstance()->getGeometryCache()->renderSphere(light.radius * (1.0f + SCALE_EXPANSION), 32, 32); + float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); + if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius) { + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + renderFullscreenQuad(); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + } else { + glTranslatef(light.position.x, light.position.y, light.position.z); + Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 32, 32); + } glPopMatrix(); } @@ -282,15 +299,30 @@ void DeferredLightingEffect::render() { glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff)); glPushMatrix(); - glTranslatef(light.position.x, light.position.y, light.position.z); - glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light.direction); - glm::vec3 axis = glm::axis(spotRotation); - glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); - glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); - Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), - expandedRadius, 32, 8); + float edgeRadius = expandedRadius / glm::cos(light.cutoff); + if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius) { + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + renderFullscreenQuad(); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + } else { + glTranslatef(light.position.x, light.position.y, light.position.z); + glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light.direction); + glm::vec3 axis = glm::axis(spotRotation); + glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); + glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); + Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), + expandedRadius, 32, 8); + } glPopMatrix(); } From 892987d68ab2df7816908dabce0c62415573b1ce Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Nov 2014 18:13:33 -0800 Subject: [PATCH 10/16] Increase tesselation to minimize artifacts. --- interface/src/renderer/DeferredLightingEffect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index c4a7a2482a..5445b7511b 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -268,7 +268,7 @@ void DeferredLightingEffect::render() { } else { glTranslatef(light.position.x, light.position.y, light.position.z); - Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 32, 32); + Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 64, 64); } glPopMatrix(); @@ -321,7 +321,7 @@ void DeferredLightingEffect::render() { glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), - expandedRadius, 32, 8); + expandedRadius, 64, 32); } glPopMatrix(); From a0e0c47701525959ee9c209c7cb4f52e8e5caed9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Nov 2014 18:27:24 -0800 Subject: [PATCH 11/16] Depth value tweak. --- interface/src/renderer/DeferredLightingEffect.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 5445b7511b..6e96d106cc 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -256,6 +256,7 @@ void DeferredLightingEffect::render() { float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius) { glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -1.0f); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -304,6 +305,7 @@ void DeferredLightingEffect::render() { float edgeRadius = expandedRadius / glm::cos(light.cutoff); if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius) { glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -1.0f); glMatrixMode(GL_PROJECTION); glPushMatrix(); From fb4c1d38eb48ee41cab9f5976a93f57b6849a582 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 4 Nov 2014 19:04:31 -0800 Subject: [PATCH 12/16] Set Oculus camera fov/aspect ratio. --- interface/src/devices/OculusManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 23cd52d946..7e43de9dda 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -126,6 +126,7 @@ void OculusManager::connect() { if (!_camera) { _camera = new Camera; + configureCamera(*_camera, 0, 0); // no need to use screen dimensions; they're ignored } if (!_programInitialized) { @@ -420,7 +421,7 @@ void OculusManager::endFrameTiming() { //Sets the camera FoV and aspect ratio void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) { #ifdef HAVE_LIBOVR - camera.setAspectRatio((float)_renderTargetSize.w / _renderTargetSize.h); + camera.setAspectRatio(_renderTargetSize.w * 0.5f / _renderTargetSize.h); camera.setFieldOfView(atan(_eyeFov[0].UpTan) * DEGREES_PER_RADIAN * 2.0f); #endif } From 2c667d209d3b99a04aaebe2dfdcf8bd4178fb0a5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:10:05 -0800 Subject: [PATCH 13/16] make the AudioInjectorScriptingInterface a singleton --- interface/src/Application.cpp | 3 ++ .../audio/src/AudioScriptingInterface.cpp | 47 +++++++++---------- libraries/audio/src/AudioScriptingInterface.h | 18 +++++-- libraries/script-engine/src/ScriptEngine.cpp | 2 +- libraries/script-engine/src/ScriptEngine.h | 4 +- 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d8b612bc3..f62a9e8e30 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -450,6 +450,9 @@ Application::~Application() { _audio.thread()->quit(); _audio.thread()->wait(); + // kill any audio injectors that are still around + + _octreeProcessor.terminate(); _voxelHideShowThread.terminate(); _voxelEditSender.terminate(); diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index 43c7d35c1d..ac0d3751bd 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -11,6 +11,15 @@ #include "AudioScriptingInterface.h" +AudioScriptingInterface& AudioScriptingInterface::getInstance() { + static AudioScriptingInterface staticInstance; + return staticInstance; +} + +void AudioScriptingInterface::stopAllInjectors() { + +} + AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) { if (sound->isStereo()) { @@ -23,15 +32,18 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjec injector->moveToThread(injectorThread); // start injecting when the injector thread starts - connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio())); + connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); // connect the right slots and signals so that the AudioInjector is killed once the injection is complete - connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater())); - connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit())); - connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater())); + connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater); + connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit); + connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped); + connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); injectorThread->start(); + _activeInjectors.insert(injector); + return injector; } @@ -45,24 +57,9 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) { return (injector != NULL); } -void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay, - const AudioInjectorOptions* injectorOptions) { - - Sound* sound = new Sound(volume, frequency, duration, decay); - AudioInjector* injector = new AudioInjector(sound, *injectorOptions); - sound->setParent(injector); - - QThread* injectorThread = new QThread(); - - injector->moveToThread(injectorThread); - - // start injecting when the injector thread starts - connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio())); - - // connect the right slots and signals so that the AudioInjector is killed once the injection is complete - connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater())); - connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit())); - connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater())); - - injectorThread->start(); -} +void AudioScriptingInterface::injectorStopped() { + qDebug() << "Removing" << sender() << "from active injectors"; + qDebug() << _activeInjectors.size(); + _activeInjectors.remove(static_cast(sender())); + qDebug() << _activeInjectors.size(); +} \ No newline at end of file diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index 343eac304c..3655aff766 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -19,12 +19,20 @@ const AudioInjectorOptions DEFAULT_INJECTOR_OPTIONS; class AudioScriptingInterface : public QObject { Q_OBJECT +public: + static AudioScriptingInterface& getInstance(); + + void stopAllInjectors(); public slots: - static AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL); - static void stopInjector(AudioInjector* injector); - static bool isInjectorPlaying(AudioInjector* injector); - static void startDrumSound(float volume, float frequency, float duration, float decay, - const AudioInjectorOptions* injectorOptions = NULL); + AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL); + void stopInjector(AudioInjector* injector); + bool isInjectorPlaying(AudioInjector* injector); + + void injectorStopped(); + +private: + AudioScriptingInterface() {}; + QSet _activeInjectors; }; #endif // hifi_AudioScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fb98124fc9..7445822f55 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -290,7 +290,7 @@ void ScriptEngine::init() { qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); registerGlobalObject("Script", this); - registerGlobalObject("Audio", &_audioScriptingInterface); + registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Entities", &_entityScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index d556475859..456134dd5c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -141,9 +141,7 @@ private: static VoxelsScriptingInterface _voxelsScriptingInterface; static EntityScriptingInterface _entityScriptingInterface; - AbstractControllerScriptingInterface* _controllerScriptingInterface; - AudioScriptingInterface _audioScriptingInterface; - AvatarData* _avatarData; + AbstractControllerScriptingInterface* _controllerScriptingInterface; AvatarData* _avatarData; QString _scriptName; QString _fileNameString; Quat _quatLibrary; From f8874daab6375119d6ad69c721358bc2a8ef2f6f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:10:22 -0800 Subject: [PATCH 14/16] remove the voxel drumming script --- examples/voxelDrumming.js | 167 -------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 examples/voxelDrumming.js diff --git a/examples/voxelDrumming.js b/examples/voxelDrumming.js deleted file mode 100644 index 1b320ed755..0000000000 --- a/examples/voxelDrumming.js +++ /dev/null @@ -1,167 +0,0 @@ -// -// voxelDrumming.js -// examples -// -// Created by Brad Hefta-Gaub on 2/14/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Overlays, Controller, and Audio classes -// -// It adds Hydra controller "fingertip on voxels" drumming -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Menu.addMenuItem({ - menuName: "Developer > Hand Options", - menuItemName: "Voxel Drumming", - isCheckable: true, - isChecked: false - }); - -var collisionCenter = new Array(); -collisionCenter[0] = { x: 0, y: 0, z: 0}; -collisionCenter[1] = { x: 0, y: 0, z: 0}; - -var collisionAge = new Array(); -collisionAge[0] = 0; -collisionAge[1] = 0; - -var collisionDuration = new Array(); -collisionDuration[0] = 0; -collisionDuration[1] = 0; - -var isColliding = new Array(); -isColliding[0] = false; -isColliding[1] = false; - -var highlightVoxel = Overlays.addOverlay("cube", - { - position: { x: 0, y: 0, z: 0}, - size: 0, - color: { red: 0, green: 0, blue: 0 }, - visible: false, - lineWidth: 3, - solid: false - }); - -var collisionBubble = new Array(); -collisionBubble[0] = Overlays.addOverlay("sphere", - { - position: { x: 0, y: 0, z: 0}, - size: 0, - color: { red: 0, green: 0, blue: 0 }, - alpha: 0.5, - visible: false - }); -collisionBubble[1] = Overlays.addOverlay("sphere", - { - position: { x: 0, y: 0, z: 0}, - size: 0, - color: { red: 0, green: 0, blue: 0 }, - alpha: 0.5, - visible: false - }); - -var audioOptions = new AudioInjectionOptions(); -audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z }; -audioOptions.volume = 1; - - -function clamp(valueToClamp, minValue, maxValue) { - return Math.max(minValue, Math.min(maxValue, valueToClamp)); -} - -function produceCollisionSound(deltaTime, palm, voxelDetail) { - // Collision between finger and a voxel plays sound - - var palmVelocity = Controller.getSpatialControlVelocity(palm * 2); - var speed = Vec3.length(palmVelocity); - var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1); - - var LOWEST_FREQUENCY = 100.0; - var HERTZ_PER_RGB = 3.0; - var DECAY_PER_SAMPLE = 0.0005; - var DURATION_MAX = 2.0; - var MIN_VOLUME = 0.1; - var volume = MIN_VOLUME + clamp(speed, 0.0, (1.0 - MIN_VOLUME)); - var duration = volume; - - collisionCenter[palm] = fingerTipPosition; - collisionAge[palm] = deltaTime; - collisionDuration[palm] = duration; - - var voxelBrightness = voxelDetail.red + voxelDetail.green + voxelDetail.blue; - var frequency = LOWEST_FREQUENCY + (voxelBrightness * HERTZ_PER_RGB); - - audioOptions.position = fingerTipPosition; - Audio.startDrumSound(volume, frequency, DURATION_MAX, DECAY_PER_SAMPLE, audioOptions); -} - -function update(deltaTime) { - // Voxel Drumming with fingertips if enabled - if (Menu.isOptionChecked("Voxel Drumming")) { - - for (var palm = 0; palm < 2; palm++) { - var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1); - - var voxel = Voxels.getVoxelEnclosingPoint(fingerTipPosition); - if (voxel.s > 0) { - if (!isColliding[palm]) { - // Collision has just started - isColliding[palm] = true; - produceCollisionSound(deltaTime, palm, voxel); - - // Set highlight voxel - Overlays.editOverlay(highlightVoxel, - { - position: { x: voxel.x, y: voxel.y, z: voxel.z}, - size: voxel.s + 0.002, - color: { red: voxel.red + 128, green: voxel.green + 128, blue: voxel.blue + 128 }, - visible: true - }); - } - } else { - if (isColliding[palm]) { - // Collision has just ended - isColliding[palm] = false; - Overlays.editOverlay(highlightVoxel, { visible: false }); - } - } - - if (collisionAge[palm] > 0) { - collisionAge[palm] += deltaTime; - } - - // If hand/voxel collision has happened, render a little expanding sphere - if (collisionAge[palm] > 0) { - var opacity = clamp(1 - (collisionAge[palm] / collisionDuration[palm]), 0, 1); - var size = collisionAge[palm] * 0.25; - - Overlays.editOverlay(collisionBubble[palm], - { - position: { x: collisionCenter[palm].x, y: collisionCenter[palm].y, z: collisionCenter[palm].z}, - size: size, - color: { red: 255, green: 0, blue: 0 }, - alpha: 0.5 * opacity, - visible: true - }); - - if (collisionAge[palm] > collisionDuration[palm]) { - collisionAge[palm] = 0; - Overlays.editOverlay(collisionBubble[palm], { visible: false }); - } - } - } // palm loop - } // menu item check -} -Script.update.connect(update); - -function scriptEnding() { - Overlays.deleteOverlay(highlightVoxel); - Overlays.deleteOverlay(collisionBubble[0]); - Overlays.deleteOverlay(collisionBubble[1]); - Menu.removeMenuItem("Developer > Hand Options","Voxel Drumming"); -} -Script.scriptEnding.connect(scriptEnding); From 663167d6844f1d7b63e3b71149c6bf0644f34e8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:37:22 -0800 Subject: [PATCH 15/16] wait on AudioInjectors when shutting down interface --- interface/src/Application.cpp | 2 +- libraries/audio/src/AudioInjector.cpp | 3 +++ libraries/audio/src/AudioInjector.h | 2 ++ .../audio/src/AudioScriptingInterface.cpp | 20 +++++++++++++------ libraries/audio/src/AudioScriptingInterface.h | 4 +++- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f62a9e8e30..ff4a23ceaf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -451,7 +451,7 @@ Application::~Application() { _audio.thread()->wait(); // kill any audio injectors that are still around - + AudioScriptingInterface::getInstance().stopAllInjectors(); _octreeProcessor.terminate(); _voxelHideShowThread.terminate(); diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 31c135fd58..87de9ede8b 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -26,6 +26,7 @@ AudioInjector::AudioInjector(QObject* parent) : _sound(NULL), _options(), _shouldStop(false), + _isFinished(false), _currentSendPosition(0) { } @@ -34,6 +35,7 @@ AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorO _sound(sound), _options(injectorOptions), _shouldStop(false), + _isFinished(false), _currentSendPosition(0) { } @@ -161,5 +163,6 @@ void AudioInjector::injectAudio() { } } + _isFinished = true; emit finished(); } diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index af9b5e55d1..1f070a77b0 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -27,6 +27,7 @@ public: AudioInjector(QObject* parent); AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions); + bool isFinished() const { return _isFinished; } int getCurrentSendPosition() const { return _currentSendPosition; } public slots: void injectAudio(); @@ -39,6 +40,7 @@ private: Sound* _sound; AudioInjectorOptions _options; bool _shouldStop; + bool _isFinished; int _currentSendPosition; }; diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index ac0d3751bd..f78bdb0614 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -17,7 +17,18 @@ AudioScriptingInterface& AudioScriptingInterface::getInstance() { } void AudioScriptingInterface::stopAllInjectors() { - + QList >::iterator injector = _activeInjectors.begin(); + while (injector != _activeInjectors.end()) { + if (!injector->isNull()) { + injector->data()->stop(); + + while (injector->data() && !injector->data()->isFinished()) { + // wait for this injector to go down + } + } + + injector = _activeInjectors.erase(injector); + } } AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) { @@ -42,7 +53,7 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjec injectorThread->start(); - _activeInjectors.insert(injector); + _activeInjectors.append(QPointer(injector)); return injector; } @@ -58,8 +69,5 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) { } void AudioScriptingInterface::injectorStopped() { - qDebug() << "Removing" << sender() << "from active injectors"; - qDebug() << _activeInjectors.size(); - _activeInjectors.remove(static_cast(sender())); - qDebug() << _activeInjectors.size(); + _activeInjectors.removeAll(QPointer(reinterpret_cast(sender()))); } \ No newline at end of file diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index 3655aff766..6179111f59 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -12,6 +12,8 @@ #ifndef hifi_AudioScriptingInterface_h #define hifi_AudioScriptingInterface_h +#include + #include "AudioInjector.h" #include "Sound.h" @@ -32,7 +34,7 @@ public slots: private: AudioScriptingInterface() {}; - QSet _activeInjectors; + QList< QPointer > _activeInjectors; }; #endif // hifi_AudioScriptingInterface_h From 2e8118300faa9596df88f693f4a794958f2c61e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 11:11:37 -0800 Subject: [PATCH 16/16] fix for two member variable declarations on same line --- libraries/script-engine/src/ScriptEngine.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 456134dd5c..f96b4655a9 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -141,7 +141,8 @@ private: static VoxelsScriptingInterface _voxelsScriptingInterface; static EntityScriptingInterface _entityScriptingInterface; - AbstractControllerScriptingInterface* _controllerScriptingInterface; AvatarData* _avatarData; + AbstractControllerScriptingInterface* _controllerScriptingInterface; + AvatarData* _avatarData; QString _scriptName; QString _fileNameString; Quat _quatLibrary;