From 737e41887811766c4021b44858bbfebbd4a93e69 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 13 Jun 2015 10:02:54 -0700 Subject: [PATCH 001/121] Revert "Revert "Merge pull request #5106 from jherico/render_cursor"" This reverts commit 0cdc2b53fe7815bba21a98ecbdfd91bcbb2898f5. --- interface/resources/images/arrow.png | Bin 0 -> 3562 bytes interface/src/Application.cpp | 3 +- interface/src/devices/OculusManager.cpp | 5 +- interface/src/devices/TV3DManager.cpp | 18 +- interface/src/ui/ApplicationOverlay.cpp | 642 ++++++------------ interface/src/ui/ApplicationOverlay.h | 53 +- libraries/render-utils/src/GeometryCache.cpp | 15 + libraries/render-utils/src/GeometryCache.h | 3 + .../render-utils/src/standardDrawTexture.slf | 24 + .../src/standardTransformPNTC.slv | 33 + 10 files changed, 327 insertions(+), 469 deletions(-) create mode 100644 interface/resources/images/arrow.png create mode 100644 libraries/render-utils/src/standardDrawTexture.slf create mode 100644 libraries/render-utils/src/standardTransformPNTC.slv diff --git a/interface/resources/images/arrow.png b/interface/resources/images/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..408881b5856eb47a30875e3e56d5864721161587 GIT binary patch literal 3562 zcmdUt`#;nD8^_v>&Q++7{9N_Zsz0M==* zod*CASSkfH0KhjS_b&hd`q(~4J0M#M?u(ox0DvNG?~zad?EY9Ph;*vvAOHXp=Hz0J z=|L}3w2K>L>R8^PZ{I7O2$vdaap<*#Uu|_gIy~UBicJicDlZ z#oT*?_=N1+o**hKQJS&OwQ2S|FMIjks+^{Z*q`l9A9H%nCjQ}c>;Esnf^cn5k*X9 zDtIJvM-E6hnmauB8V%s$m0YR(j6(AOYaQ=Zxaf|nXhd}U)5Il`{<|J=u`8-l2Sk+)w2fZTFpVq+^VNbOIHDWEzXw;!TEupOl!#6bSK1;*{YJ|c(d%UezwJosB zc=QMJ+fywpC=OIGT`wp7eo4?o-Kyti6+y{Jdkx&njTs4=L~;x?`X$w+4)SuSIXQJ7 z;%Z)Hey~5FtC%13ZoZkBJQ8*cCYk7&2G7(TD)XtyWAc3?k#+2 zSg#k#mdRYRgv~@}Xlfje8{_+BNfv2R`Fs}BbLcl>eN-Ll zMq8jYR7x=HKDvahQ;p)T@CmDn4b1Nh(-MoAGg{jUe@WM|HsDuQOMVVAOFPKspjE0i z^C8vZ%pJ%+uK%uMP2K<22L?4~Io;K?zlnUro6GjvZ49$6g1A#&a2?86$9#wCOcS%C zb7}sG62)C19qs#(J5bIzi7QG=>-u$yEsR=h>f(-34m0xR(${nu&{RhA&@Mg7`B#`P zhV5a20jVJ##O)R@7r(@&R%V1)k5!_PR;jZ%Nic^nQe9LZq&r0-(CXstay#9kZWT(y zdgH7OM)5F71^WF%`v@Z|XC$dE{=2L=mdYTn>$X5itWF7S%qGfL>f`G0z@vPRSW|2% zzLM%PjXHas*`f@r_~wQ}Gmu43 z5G-)iN^`2uk6mWYBtokb!0*#IwiWpKfC!6##XRQBC1`bV$0fxT!VRorXxhHGe*NoA zdt6ZxwAvV!ZiN`4;o>WhDAGg8(B`wek@fWhHJ(dW4MtCkbqC#y7JcedE@AK> zMB$xO&3k{;t&x;emmKUb zowqJ(lDd|Eb9|sC!Ygpx87ARjG#b5XFF{X9cXw1L?RMHVsRnMv$I0lQd^=+#V#@$MlpA5irYfng==?oLWQ=QK^D$Ky_U!*jQH#m zjVjH$7E1+|ase%BK+M|o{iTaQ(Ml4H1$pu8=4el6V&M__e7G&_O(9<;GE^Al=TpLf zxO&AC{>m}9nRav|v8Os%CgDtTL=_WpJt#}L4rmX;ZoUwBsJ>kVxxfDKL-u*4inEt~ zepM8kiQ750nR9cof?+F3&-L4?2*iEAb9@@Ud-g}wloO$m!0J7N70PeSEAq6p3OKcD zep<3P?;@P-BzLYtBN~F-LxAwG5KLr9GB*Xf%Wrfd?2tQ{5+_qIEe`S;h*BXPA9!7* z{O#kEZB7c7JjG)*ytp`?abYuf2GbW035JF@wq+^JD38vuuKEw%F$L!JOIq~=P8ymV zjt6yfX60aCNrHV1;cN&@dcdu!k|na6-H;<1X+!&G)r4i5?y*WzOxI>K;!yduCwQRw zp)oRGk=9n3Lq4Fc>bY<x^GMN*P>x zcT=W7G2!>9k+a{t5kw;+2YqAccKgH6tOWRO&IL`{vOX8<_+#gs2a?glJn|}=3`vz{ zHAviptXq=nB%o57Oo#&v(9S0q<1wQCaMM$X_~?zvlB$ z{BS{j>8BHv>(J^Cw&VWjNl%$l^~FK0xgm}RHN;P_yMCbJkgqy!`%3TxmFo>4xWOMOk)+EW^_O9C7dZ>}I8Kh? zj}RS#{?`Mw|KiNv1NTC!8{_L%x!B03r-qWd`3rX$w%2JIqbaP0;T@MIu#e4!O_jj9 z<#;=AYz=r`={Y4aD2T>=*o5mw?KfuiR+fF=OW1)P@;v$;gLp~OWmI`C8Lwoc_?A2G z8WZjK)fU#5&sGhWjChlZ8*bHMkESnnvKsURQ^7~i%5%;9utUpqF}fdSqfACu_qEX4 zp@vXlm3Du40m?O>|E>T2`lg zkA8{BTL{+P!L`w6k!iPQ#a#f=|m#Qf(WK|Ir2F`ayL>?xU&W1IW5W%|H^ z!@V6^Km}^O#=A4H!qZs`D;m4uMCc;TUi*(Pr73>oa{>8VKq2hz#bW*--8Nf%b$@+! zHoF^Jp|5>CN4DvW)pU)?%g3N~Y6FGpe0l}{L^6G`j-fi~Y@`DQ5BtMg5BbtdGn`80 zlhZ=aS9n=RRb*}nf8eMeJDEc8%&t(^e!P8ZC+e-xs;70|LZCeN?35MHzihjDJDea% z_nQ6_6TRHs&%{vEqnm%C6bpLLKSPBjQ&ibGJ*2EF0a>wL|BHog#{CKrZI>`=PhmuX z1|o8of6J{XA8}XluF6Ue3=0>|PEYY5F8#6~g%gS*=5Vs(@K@8a<4r38-e(uhuy6R~b&w4cQHxqLICs#~XeF!9xRs?fdLjDOKWTh7 R^nCyTaI$x`E7(oB_+R=!c8UN1 literal 0 HcmV?d00001 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22cbad6775..0757e6790f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -955,6 +955,7 @@ void Application::paintGL() { glPushMatrix(); glLoadIdentity(); displaySide(&renderArgs, _myCamera); + _applicationOverlay.displayOverlayTexture(&renderArgs); glPopMatrix(); renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; @@ -974,8 +975,6 @@ void Application::paintGL() { 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - _applicationOverlay.displayOverlayTexture(); } if (!OculusManager::isConnected() || OculusManager::allowSwap()) { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index a7383ae4bb..414c7f6199 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -615,12 +615,10 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const renderArgs->_renderSide = RenderArgs::MONO; qApp->displaySide(renderArgs, *_camera, false); - qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera); + qApp->getApplicationOverlay().displayOverlayTextureHmd(renderArgs, *_camera); }); _activeEye = ovrEye_Count; - glPopMatrix(); - gpu::FramebufferPointer finalFbo; //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { @@ -631,6 +629,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const finalFbo = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } + glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 09edb03e5a..b0a2ff7e3b 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -12,6 +12,7 @@ #include "InterfaceConfig.h" #include +#include #include #include "gpu/GLBackend.h" @@ -106,21 +107,20 @@ void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) { _activeEye = &eye; glViewport(portalX, portalY, portalW, portalH); glScissor(portalX, portalY, portalW, portalH); + + glm::mat4 projection = glm::frustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); + float fov = atan(1.0f / projection[1][1]); + projection = glm::translate(projection, vec3(eye.modelTranslation, 0, 0)); + eyeCamera.setProjection(projection); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); // reset projection matrix - glFrustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); // set left view frustum - GLfloat p[4][4]; - // Really? - glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0])); - float cotangent = p[1][1]; - GLfloat fov = atan(1.0f / cotangent); - glTranslatef(eye.modelTranslation, 0.0, 0.0); // translate to cancel parallax - + glLoadMatrixf(glm::value_ptr(projection)); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); renderArgs->_renderSide = RenderArgs::MONO; qApp->displaySide(renderArgs, eyeCamera, false); - qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); + qApp->getApplicationOverlay().displayOverlayTexture(renderArgs); _activeEye = NULL; }, [&]{ // render right side view diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 0c1783f8ac..ba0d3a60a9 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -14,13 +14,16 @@ #include #include +#include + #include +#include #include -#include #include #include -#include #include +#include +#include #include "AudioClient.h" #include "audio/AudioIOStatsRenderer.h" @@ -33,6 +36,9 @@ #include "Util.h" #include "ui/Stats.h" +#include "../../libraries/render-utils/standardTransformPNTC_vert.h" +#include "../../libraries/render-utils/standardDrawTexture_frag.h" + // Used to animate the magnification windows const float MAG_SPEED = 0.08f; @@ -114,27 +120,6 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } } -void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) { - glPushMatrix(); { - glm::vec3 axis = glm::axis(orientation); - glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z); - glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f); - glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f); - glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f); - glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f); - - // TODO: this version of renderQuad() needs to take a color - glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha }; - - - - DependencyManager::get()->renderQuad(topLeft, bottomLeft, bottomRight, topRight, - glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), - glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), - reticleColor, _reticleQuad); - } glPopMatrix(); -} - ApplicationOverlay::ApplicationOverlay() : _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)), _textureAspectRatio(1.0f), @@ -148,7 +133,8 @@ ApplicationOverlay::ApplicationOverlay() : _previousMagnifierBottomLeft(), _previousMagnifierBottomRight(), _previousMagnifierTopLeft(), - _previousMagnifierTopRight() + _previousMagnifierTopRight(), + _framebufferObject(nullptr) { memset(_reticleActive, 0, sizeof(_reticleActive)); memset(_magActive, 0, sizeof(_reticleActive)); @@ -195,16 +181,17 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { //Handle fading and deactivation/activation of UI // Render 2D overlay - glMatrixMode(GL_PROJECTION); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - _overlays.buildFramebufferObject(); - _overlays.bind(); + buildFramebufferObject(); + + _framebufferObject->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, size.x, size.y); + glMatrixMode(GL_PROJECTION); glPushMatrix(); { const float NEAR_CLIP = -10000; const float FAR_CLIP = 10000; @@ -226,6 +213,22 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { renderPointers(); renderDomainConnectionStatusBorder(); + if (_newUiTexture) { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, _newUiTexture); + DependencyManager::get()->renderUnitQuad(); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + } + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); } glPopMatrix(); @@ -235,258 +238,160 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { glEnable(GL_LIGHTING); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - _overlays.release(); + _framebufferObject->release(); } -// A quick and dirty solution for compositing the old overlay -// texture with the new one -template -void with_each_texture(GLuint firstPassTexture, GLuint secondPassTexture, F f) { - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - if (firstPassTexture) { - glBindTexture(GL_TEXTURE_2D, firstPassTexture); - f(); +gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() { + if (!_standardDrawPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + gpu::Shader::makeProgram((*program)); + + auto state = gpu::StatePointer(new gpu::State()); + + // enable decal blend + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); } - if (secondPassTexture) { - glBindTexture(GL_TEXTURE_2D, secondPassTexture); - f(); - } - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); + + return _standardDrawPipeline; } +void ApplicationOverlay::bindCursorTexture(gpu::Batch& batch, uint8_t cursorIndex) { + auto& cursorManager = Cursor::Manager::instance(); + auto cursor = cursorManager.getCursor(cursorIndex); + auto iconId = cursor->getIcon(); + if (!_cursors.count(iconId)) { + auto iconPath = cursorManager.getIconImage(cursor->getIcon()); + _cursors[iconId] = DependencyManager::get()-> + getImageTexture(iconPath); + } + batch.setUniformTexture(0, _cursors[iconId]); +} + +#define CURSOR_PIXEL_SIZE 32.0f + // Draws the FBO texture for the screen -void ApplicationOverlay::displayOverlayTexture() { +void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { if (_alpha == 0.0f) { return; } - glMatrixMode(GL_PROJECTION); - glPushMatrix(); { - glLoadIdentity(); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height()); + + renderArgs->_context->syncCache(); - static const glm::vec2 topLeft(-1, 1); - static const glm::vec2 bottomRight(1, -1); - static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); - static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); - with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { - DependencyManager::get()->renderQuad( - topLeft, bottomRight, - texCoordTopLeft, texCoordBottomRight, - glm::vec4(1.0f, 1.0f, 1.0f, _alpha)); - }); + gpu::Batch batch; + Transform model; + //DependencyManager::get()->bindSimpleProgram(batch, true); + batch.setPipeline(getDrawPipeline()); + batch.setModelTransform(Transform()); + batch.setProjectionTransform(mat4()); + batch.setViewTransform(model); + batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + DependencyManager::get()->renderUnitQuad(batch, vec4(vec3(1), _alpha)); - if (!_crosshairTexture) { - _crosshairTexture = DependencyManager::get()-> - getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); - } + //draw the mouse pointer + glm::vec2 canvasSize = qApp->getCanvasSize(); - //draw the mouse pointer - glm::vec2 canvasSize = qApp->getCanvasSize(); - glm::vec2 mouseSize = 32.0f / canvasSize; - auto mouseTopLeft = topLeft * mouseSize; - auto mouseBottomRight = bottomRight * mouseSize; - vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); - mousePosition /= canvasSize; - mousePosition *= 2.0f; - mousePosition -= 1.0f; - mousePosition.y *= -1.0f; + // Get the mouse coordinates and convert to NDC [-1, 1] + vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); + mousePosition /= canvasSize; + mousePosition *= 2.0f; + mousePosition -= 1.0f; + mousePosition.y *= -1.0f; + model.setTranslation(vec3(mousePosition, 0)); + glm::vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; + model.setScale(vec3(mouseSize, 1.0f)); + batch.setModelTransform(model); + bindCursorTexture(batch); + glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; + DependencyManager::get()->renderUnitQuad(batch, vec4(1)); + renderArgs->_context->render(batch); +} - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); - glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; - DependencyManager::get()->renderQuad( - mouseTopLeft + mousePosition, mouseBottomRight + mousePosition, - texCoordTopLeft, texCoordBottomRight, - reticleColor); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glDisable(GL_TEXTURE_2D); - } glPopMatrix(); + +static gpu::BufferPointer _hemiVertices; +static gpu::BufferPointer _hemiIndices; +static int _hemiIndexCount{ 0 }; + +glm::vec2 getPolarCoordinates(const PalmData& palm) { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + auto avatarOrientation = myAvatar->getOrientation(); + auto eyePos = myAvatar->getDefaultEyePosition(); + glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); + // Direction of the tip relative to the eye + glm::vec3 tipDirection = tip - eyePos; + // orient into avatar space + tipDirection = glm::inverse(avatarOrientation) * tipDirection; + // Normalize for trig functions + tipDirection = glm::normalize(tipDirection); + // Convert to polar coordinates + glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y)); + return polar; } // Draws the FBO texture for Oculus rift. -void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { +void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { if (_alpha == 0.0f) { return; } - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glDisable(GL_LIGHTING); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.01f); + renderArgs->_context->syncCache(); + gpu::Batch batch; + batch.setPipeline(getDrawPipeline()); + batch._glDisable(GL_DEPTH_TEST); + batch._glDisable(GL_CULL_FACE); + batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + batch.setProjectionTransform(whichCamera.getProjection()); + batch.setViewTransform(Transform()); - //Update and draw the magnifiers MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - const glm::quat& orientation = myAvatar->getOrientation(); - // Always display the HMD overlay relative to the camera position but - // remove the HMD pose offset. This results in an overlay that sticks with you - // even in third person mode, but isn't drawn at a fixed distance. - glm::vec3 position = whichCamera.getPosition(); - position -= qApp->getCamera()->getHmdPosition(); - const float scale = myAvatar->getScale() * _oculusUIRadius; - -// glm::vec3 eyeOffset = setEyeOffsetPosition; - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); { - glTranslatef(position.x, position.y, position.z); - glm::mat4 rotation = glm::toMat4(orientation); - glMultMatrixf(&rotation[0][0]); - glScalef(scale, scale, scale); - for (int i = 0; i < NUMBER_OF_RETICLES; i++) { - - if (_magActive[i]) { - _magSizeMult[i] += MAG_SPEED; - if (_magSizeMult[i] > 1.0f) { - _magSizeMult[i] = 1.0f; - } - } else { - _magSizeMult[i] -= MAG_SPEED; - if (_magSizeMult[i] < 0.0f) { - _magSizeMult[i] = 0.0f; - } - } - - if (_magSizeMult[i] > 0.0f) { - //Render magnifier, but dont show border for mouse magnifier - glm::vec2 projection = screenToOverlay(glm::vec2(_reticlePosition[MOUSE].x(), - _reticlePosition[MOUSE].y())); - with_each_texture(_overlays.getTexture(), 0, [&] { - renderMagnifier(projection, _magSizeMult[i], i != MOUSE); - }); - } - } - - glDepthMask(GL_FALSE); - glDisable(GL_ALPHA_TEST); - - static float textureFOV = 0.0f, textureAspectRatio = 1.0f; - if (textureFOV != _textureFov || - textureAspectRatio != _textureAspectRatio) { - textureFOV = _textureFov; - textureAspectRatio = _textureAspectRatio; - - _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80); - } + const quat& avatarOrientation = myAvatar->getOrientation(); + quat hmdOrientation = qApp->getCamera()->getHmdRotation(); + vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition(); + mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition); + batch.setModelTransform(Transform(overlayXfm)); + drawSphereSection(batch); - with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { - _overlays.render(); - }); - if (!Application::getInstance()->isMouseHidden()) { - renderPointersOculus(); + bindCursorTexture(batch); + auto geometryCache = DependencyManager::get(); + vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); + //Controller Pointers + for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + glm::vec2 polar = getPolarCoordinates(palm); + // Convert to quaternion + mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + // Render reticle at location + geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); } - glDepthMask(GL_TRUE); - glDisable(GL_TEXTURE_2D); - - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_LIGHTING); - } glPopMatrix(); + } + + //Mouse Pointer + if (_reticleActive[MOUSE]) { + glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), + _reticlePosition[MOUSE].y())); + mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); + } + + renderArgs->_context->render(batch); } -// Draws the FBO texture for 3DTV. -void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) { - if (_alpha == 0.0f) { - return; - } - - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - const glm::vec3& viewMatrixTranslation = qApp->getViewMatrixTranslation(); - - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - - glMatrixMode(GL_MODELVIEW); - - glPushMatrix(); - glLoadIdentity(); - // Transform to world space - glm::quat rotation = whichCamera.getRotation(); - glm::vec3 axis2 = glm::axis(rotation); - glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z); - glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z); - - // Translate to the front of the camera - glm::vec3 pos = whichCamera.getPosition(); - glm::quat rot = myAvatar->getOrientation(); - glm::vec3 axis = glm::axis(rot); - - glTranslatef(pos.x, pos.y, pos.z); - glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z); - - glm::vec4 overlayColor = {1.0f, 1.0f, 1.0f, _alpha}; - - //Render - const GLfloat distance = 1.0f; - - const GLfloat halfQuadHeight = distance * tan(fov); - const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio; - const GLfloat quadWidth = halfQuadWidth * 2.0f; - const GLfloat quadHeight = halfQuadHeight * 2.0f; - - GLfloat x = -halfQuadWidth; - GLfloat y = -halfQuadHeight; - glDisable(GL_DEPTH_TEST); - - with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { - DependencyManager::get()->renderQuad(glm::vec3(x, y + quadHeight, -distance), - glm::vec3(x + quadWidth, y + quadHeight, -distance), - glm::vec3(x + quadWidth, y, -distance), - glm::vec3(x, y, -distance), - glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f), - glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f), - overlayColor); - }); - - if (!_crosshairTexture) { - _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + - "images/sixense-reticle.png"); - } - - //draw the mouse pointer - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); - glm::vec2 canvasSize = qApp->getCanvasSize(); - const float reticleSize = 40.0f / canvasSize.x * quadWidth; - x -= reticleSize / 2.0f; - y += reticleSize / 2.0f; - const float mouseX = (qApp->getMouseX() / (float)canvasSize.x) * quadWidth; - const float mouseY = (1.0 - (qApp->getMouseY() / (float)canvasSize.y)) * quadHeight; - - glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; - - DependencyManager::get()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance), - glm::vec3(x + mouseX + reticleSize, y + mouseY, -distance), - glm::vec3(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance), - glm::vec3(x + mouseX, y + mouseY - reticleSize, -distance), - glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), - glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), - reticleColor, _reticleQuad); - - glEnable(GL_DEPTH_TEST); - - glPopMatrix(); - - glDepthMask(GL_TRUE); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glEnable(GL_LIGHTING); -} void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { cursorPos *= qApp->getCanvasSize(); @@ -516,22 +421,6 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi direction = glm::normalize(intersectionWithUi - origin); } -glm::vec2 getPolarCoordinates(const PalmData& palm) { - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - auto avatarOrientation = myAvatar->getOrientation(); - auto eyePos = myAvatar->getDefaultEyePosition(); - glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); - // Direction of the tip relative to the eye - glm::vec3 tipDirection = tip - eyePos; - // orient into avatar space - tipDirection = glm::inverse(avatarOrientation) * tipDirection; - // Normalize for trig functions - tipDirection = glm::normalize(tipDirection); - // Convert to polar coordinates - glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y)); - return polar; -} - //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { QPoint rv; @@ -582,13 +471,9 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { - //lazily load crosshair texture - if (_crosshairTexture == 0) { - _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); - } - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //glEnable(GL_TEXTURE_2D); + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glActiveTexture(GL_TEXTURE0); //bindCursorTexture(); @@ -750,43 +635,6 @@ void ApplicationOverlay::renderControllerPointers() { } } -void ApplicationOverlay::renderPointersOculus() { - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); - glDisable(GL_DEPTH_TEST); - - glMatrixMode(GL_MODELVIEW); - - //Controller Pointers - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { - PalmData& palm = myAvatar->getHand()->getPalms()[i]; - if (palm.isActive()) { - glm::vec2 polar = getPolarCoordinates(palm); - // Convert to quaternion - glm::quat orientation = glm::quat(glm::vec3(polar.y, -polar.x, 0.0f)); - // Render reticle at location - renderReticle(orientation, _alpha); - } - } - - //Mouse Pointer - if (_reticleActive[MOUSE]) { - glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), - _reticlePosition[MOUSE].y())); - glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); - renderReticle(orientation, _alpha); - } - - glEnable(GL_DEPTH_TEST); - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); -} - //Renders a small magnification of the currently bound texture at the coordinates void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) { if (!_magnifier) { @@ -1067,119 +915,109 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { } } -ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : - _vertices(0), - _indices(0), - _framebufferObject(NULL), - _vbo(0, 0) { -} -ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() { - cleanupVBO(); - if (_framebufferObject != NULL) { - delete _framebufferObject; +void ApplicationOverlay::buildHemiVertices( + const float fov, const float aspectRatio, const int slices, const int stacks) { + static float textureFOV = 0.0f, textureAspectRatio = 1.0f; + if (textureFOV == fov && textureAspectRatio == aspectRatio) { + return; } -} -void ApplicationOverlay::TexturedHemisphere::bind() { - _framebufferObject->bind(); -} + textureFOV = fov; + textureAspectRatio = aspectRatio; + + auto geometryCache = DependencyManager::get(); + + _hemiVertices = gpu::BufferPointer(new gpu::Buffer()); + _hemiIndices = gpu::BufferPointer(new gpu::Buffer()); -void ApplicationOverlay::TexturedHemisphere::release() { - _framebufferObject->release(); -} -void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, - const float aspectRatio, - const int slices, - const int stacks) { if (fov >= PI) { qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; } - // Cleanup old VBO if necessary - cleanupVBO(); - + //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm - // Compute number of vertices needed - _vertices = slices * stacks; - + vec3 pos; + vec2 uv; // Compute vertices positions and texture UV coordinate - TextureVertex* vertexData = new TextureVertex[_vertices]; - TextureVertex* vertexPtr = &vertexData[0]; + // Create and write to buffer for (int i = 0; i < stacks; i++) { - float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f + uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f // abs(theta) <= fov / 2.0f - float pitch = -fov * (stacksRatio - 0.5f); - + float pitch = -fov * (uv.y - 0.5f); for (int j = 0; j < slices; j++) { - float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f + uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f // abs(phi) <= fov * aspectRatio / 2.0f - float yaw = -fov * aspectRatio * (slicesRatio - 0.5f); - - vertexPtr->position = getPoint(yaw, pitch); - vertexPtr->uv.x = slicesRatio; - vertexPtr->uv.y = stacksRatio; - vertexPtr++; + float yaw = -fov * aspectRatio * (uv.x - 0.5f); + pos = getPoint(yaw, pitch); + static const vec4 color(1); + _hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos); + _hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv); + _hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color); } } - // Create and write to buffer - glGenBuffers(1, &_vbo.first); - glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); - static const int BYTES_PER_VERTEX = sizeof(TextureVertex); - glBufferData(GL_ARRAY_BUFFER, _vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); - delete[] vertexData; - // Compute number of indices needed static const int VERTEX_PER_TRANGLE = 3; static const int TRIANGLE_PER_RECTANGLE = 2; int numberOfRectangles = (slices - 1) * (stacks - 1); - _indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; + _hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; // Compute indices order - GLushort* indexData = new GLushort[_indices]; - GLushort* indexPtr = indexData; + std::vector indices; for (int i = 0; i < stacks - 1; i++) { for (int j = 0; j < slices - 1; j++) { GLushort bottomLeftIndex = i * slices + j; GLushort bottomRightIndex = bottomLeftIndex + 1; GLushort topLeftIndex = bottomLeftIndex + slices; GLushort topRightIndex = topLeftIndex + 1; - - *(indexPtr++) = topLeftIndex; - *(indexPtr++) = bottomLeftIndex; - *(indexPtr++) = topRightIndex; - - *(indexPtr++) = topRightIndex; - *(indexPtr++) = bottomLeftIndex; - *(indexPtr++) = bottomRightIndex; + // FIXME make a z-order curve for better vertex cache locality + indices.push_back(topLeftIndex); + indices.push_back(bottomLeftIndex); + indices.push_back(topRightIndex); + + indices.push_back(topRightIndex); + indices.push_back(bottomLeftIndex); + indices.push_back(bottomRightIndex); } } - // Create and write to buffer - glGenBuffers(1, &_vbo.second); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); - static const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); - delete[] indexData; + _hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]); } -void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { - if (_vbo.first != 0) { - glDeleteBuffers(1, &_vbo.first); - _vbo.first = 0; - } - if (_vbo.second != 0) { - glDeleteBuffers(1, &_vbo.second); - _vbo.second = 0; - } + +void ApplicationOverlay::drawSphereSection(gpu::Batch& batch) { + buildHemiVertices(_textureFov, _textureAspectRatio, 80, 80); + static const int VERTEX_DATA_SLOT = 0; + static const int TEXTURE_DATA_SLOT = 1; + static const int COLOR_DATA_SLOT = 2; + gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone + streamFormat->setAttribute(gpu::Stream::POSITION, VERTEX_DATA_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); + streamFormat->setAttribute(gpu::Stream::TEXCOORD, TEXTURE_DATA_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_DATA_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA)); + batch.setInputFormat(streamFormat); + + static const int VERTEX_STRIDE = sizeof(vec3) + sizeof(vec2) + sizeof(vec4); + gpu::BufferView posView(_hemiVertices, 0, _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); + gpu::BufferView uvView(_hemiVertices, sizeof(vec3), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element); + gpu::BufferView colView(_hemiVertices, sizeof(vec3) + sizeof(vec2), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); + batch.setInputBuffer(VERTEX_DATA_SLOT, posView); + batch.setInputBuffer(TEXTURE_DATA_SLOT, uvView); + batch.setInputBuffer(COLOR_DATA_SLOT, colView); + batch.setIndexBuffer(gpu::UINT16, _hemiIndices, 0); + batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount); } -void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { + +GLuint ApplicationOverlay::getOverlayTexture() { + return _framebufferObject->texture(); +} + +void ApplicationOverlay::buildFramebufferObject() { auto canvasSize = qApp->getCanvasSize(); QSize fboSize = QSize(canvasSize.x, canvasSize.y); if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) { - // Already build + // Already built return; } @@ -1188,7 +1026,7 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { } _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); - glBindTexture(GL_TEXTURE_2D, getTexture()); + glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); @@ -1198,38 +1036,6 @@ void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { glBindTexture(GL_TEXTURE_2D, 0); } -//Renders a hemisphere with texture coordinates. -void ApplicationOverlay::TexturedHemisphere::render() { - if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) { - qDebug() << "TexturedHemisphere::render(): Incorrect initialisation"; - return; - } - - glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - static const int STRIDE = sizeof(TextureVertex); - static const void* VERTEX_POINTER = 0; - static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3); - glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER); - glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER); - - glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -GLuint ApplicationOverlay::TexturedHemisphere::getTexture() { - return _framebufferObject->texture(); -} - glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { glm::vec2 result; // Compute yaw diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index eb397fe3c6..e8b5a77b1f 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -33,9 +33,9 @@ public: ~ApplicationOverlay(); void renderOverlay(RenderArgs* renderArgs); - void displayOverlayTexture(); - void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov); - void displayOverlayTextureHmd(Camera& whichCamera); + void displayOverlayTexture(RenderArgs* renderArgs); + void displayOverlayTextureStereo(RenderArgs* renderArgs, Camera& whichCamera, float aspectRatio, float fov); + void displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera); QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; @@ -59,6 +59,7 @@ public: glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; + GLuint getOverlayTexture(); static glm::vec2 directionToSpherical(const glm::vec3 & direction); static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); @@ -66,38 +67,12 @@ public: static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); private: - // Interleaved vertex data - struct TextureVertex { - glm::vec3 position; - glm::vec2 uv; - }; - - typedef QPair VerticesIndices; - class TexturedHemisphere { - public: - TexturedHemisphere(); - ~TexturedHemisphere(); - - void bind(); - void release(); - GLuint getTexture(); - - void buildFramebufferObject(); - void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks); - void render(); - - private: - void cleanupVBO(); - - GLuint _vertices; - GLuint _indices; - QOpenGLFramebufferObject* _framebufferObject; - VerticesIndices _vbo; - }; - + void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); + void drawSphereSection(gpu::Batch& batch); float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; - void renderReticle(glm::quat orientation, float alpha); - void renderPointers();; + QOpenGLFramebufferObject* _framebufferObject; + + void renderPointers(); void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder); void renderControllerPointers(); @@ -109,10 +84,12 @@ private: void renderDomainConnectionStatusBorder(); void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); - TexturedHemisphere _overlays; + void buildFramebufferObject(); float _textureFov; float _textureAspectRatio; + int _hemiVerticesID{ GeometryCache::UNKNOWN_ID }; + enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES }; bool _reticleActive[NUMBER_OF_RETICLES]; @@ -125,8 +102,6 @@ private: float _alpha = 1.0f; float _oculusUIRadius; float _trailingAudioLoudness; - - gpu::TexturePointer _crosshairTexture; QMap _cursors; @@ -149,6 +124,10 @@ private: glm::vec3 _previousMagnifierTopLeft; glm::vec3 _previousMagnifierTopRight; + gpu::PipelinePointer _standardDrawPipeline; + + gpu::PipelinePointer getDrawPipeline(); + }; #endif // hifi_ApplicationOverlay_h diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 303d63bef8..3066fd4890 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1179,6 +1179,21 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co batch.draw(gpu::QUADS, 4, 0); } +void GeometryCache::renderUnitQuad(const glm::vec4& color, int id) { + gpu::Batch batch; + renderUnitQuad(batch, color, id); + gpu::GLBackend::renderBatch(batch); +} + +void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) { + static const glm::vec2 topLeft(-1, 1); + static const glm::vec2 bottomRight(1, -1); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); + renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color, id); +} + + void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, const glm::vec4& color, int id) { diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index b438eb2d3b..76e03f8669 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -155,6 +155,9 @@ public: void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); + void renderUnitQuad(const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID); + void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID); + void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID) { renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); } void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID) diff --git a/libraries/render-utils/src/standardDrawTexture.slf b/libraries/render-utils/src/standardDrawTexture.slf new file mode 100644 index 0000000000..4fbeb6eb7f --- /dev/null +++ b/libraries/render-utils/src/standardDrawTexture.slf @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// standardDrawTexture.frag +// fragment shader +// +// Created by Sam Gateau on 6/10/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the texture +uniform sampler2D colorMap; + +varying vec2 varTexcoord; +varying vec4 varColor; + + +void main(void) { + vec4 color = texture2D(colorMap, varTexcoord); + gl_FragColor = color * varColor; +} diff --git a/libraries/render-utils/src/standardTransformPNTC.slv b/libraries/render-utils/src/standardTransformPNTC.slv new file mode 100644 index 0000000000..fd2c28049f --- /dev/null +++ b/libraries/render-utils/src/standardTransformPNTC.slv @@ -0,0 +1,33 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// standardTransformPNTC.slv +// vertex shader +// +// Created by Sam Gateau on 6/10/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec3 varNormal; +varying vec2 varTexcoord; +varying vec4 varColor; + +void main(void) { + varTexcoord = gl_MultiTexCoord0.xy; + varColor = gl_Color; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> + <$transformModelToEyeDir(cam, obj, gl_Normal, varNormal)$> + varNormal = normalize(varNormal); +} \ No newline at end of file From 49f4ab99df0272a260d9b559f4d249eda21b00ab Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 13 Jun 2015 10:03:10 -0700 Subject: [PATCH 002/121] Revert "Revert "Fix broken identity transforms on OSX"" This reverts commit 1feceec0c7b5b3c6d2225c26ddbb56a605bd99a4. --- libraries/gpu/src/gpu/GLBackendTransform.cpp | 25 +++++++------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 3f760e4cc8..4e524ec24a 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -133,11 +133,11 @@ void GLBackend::updateTransform() { } if (_transform._invalidModel || _transform._invalidView) { + if (_transform._lastMode != GL_MODELVIEW) { + glMatrixMode(GL_MODELVIEW); + _transform._lastMode = GL_MODELVIEW; + } if (!_transform._model.isIdentity()) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } Transform::Mat4 modelView; if (!_transform._view.isIdentity()) { Transform mvx; @@ -147,19 +147,12 @@ void GLBackend::updateTransform() { _transform._model.getMatrix(modelView); } glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); + } else if (!_transform._view.isIdentity()) { + Transform::Mat4 modelView; + _transform._view.getInverseMatrix(modelView); + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); } else { - if (!_transform._view.isIdentity()) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } - Transform::Mat4 modelView; - _transform._view.getInverseMatrix(modelView); - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else { - // TODO: eventually do something about the matrix when neither view nor model is specified? - // glLoadIdentity(); - } + glLoadIdentity(); } (void) CHECK_GL_ERROR(); } From e44b21ee0bef85200a1d1ed48cd2d24463be9023 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 13 Jun 2015 10:36:52 -0700 Subject: [PATCH 003/121] Working on functional overlays --- interface/src/Application.cpp | 11 ++++++----- interface/src/ui/ApplicationOverlay.cpp | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0757e6790f..cee203f733 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -878,11 +878,6 @@ void Application::paintGL() { PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(&renderArgs); - } - glEnable(GL_LINE_SMOOTH); if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { @@ -977,6 +972,12 @@ void Application::paintGL() { glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } + { + PerformanceTimer perfTimer("renderOverlay"); + _applicationOverlay.renderOverlay(&renderArgs); + } + + if (!OculusManager::isConnected() || OculusManager::allowSwap()) { _glWidget->swapBuffers(); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ba0d3a60a9..cb17569b86 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -275,7 +275,7 @@ void ApplicationOverlay::bindCursorTexture(gpu::Batch& batch, uint8_t cursorInde // Draws the FBO texture for the screen void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { - if (_alpha == 0.0f) { + if (_alpha == 0.0f || !_framebufferObject) { return; } @@ -335,7 +335,7 @@ glm::vec2 getPolarCoordinates(const PalmData& palm) { // Draws the FBO texture for Oculus rift. void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { - if (_alpha == 0.0f) { + if (_alpha == 0.0f || !_framebufferObject) { return; } From 00d8fe75ab7296919a6bcf5baac10287ca946726 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 13 Jun 2015 17:36:08 -0700 Subject: [PATCH 004/121] Breaking up overlay into rendering and compositing classes --- interface/src/Application.cpp | 102 ++- interface/src/Application.h | 42 +- interface/src/Camera.cpp | 16 - interface/src/Camera.h | 14 +- interface/src/audio/AudioToolBox.h | 2 +- interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/devices/OculusManager.cpp | 49 +- interface/src/devices/OculusManager.h | 3 + interface/src/devices/SixenseManager.cpp | 2 +- interface/src/devices/TV3DManager.cpp | 2 +- .../src/scripting/HMDScriptingInterface.cpp | 6 +- .../src/scripting/HMDScriptingInterface.h | 4 +- interface/src/ui/ApplicationCompositor.cpp | 757 ++++++++++++++++++ interface/src/ui/ApplicationCompositor.h | 118 +++ interface/src/ui/ApplicationOverlay.cpp | 746 +---------------- interface/src/ui/ApplicationOverlay.h | 84 +- interface/src/ui/PreferencesDialog.cpp | 4 +- interface/src/ui/overlays/Overlays.cpp | 2 +- libraries/render-utils/src/GeometryCache.cpp | 21 + libraries/render-utils/src/GeometryCache.h | 6 +- 20 files changed, 1032 insertions(+), 952 deletions(-) create mode 100644 interface/src/ui/ApplicationCompositor.cpp create mode 100644 interface/src/ui/ApplicationCompositor.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cee203f733..b540751c8d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -333,8 +333,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _cursorVisible(true), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), - _touchAvgX(0.0f), - _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), _enableProcessOctreeThread(true), @@ -840,7 +838,7 @@ void Application::initializeUi() { VrMenu::executeQueuedLambdas(); offscreenUi->setMouseTranslator([this](const QPointF& p){ if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p)); + glm::vec2 pos = _compositor.screenToOverlay(toGlm(p)); return QPointF(pos.x, pos.y); } return QPointF(p); @@ -950,7 +948,7 @@ void Application::paintGL() { glPushMatrix(); glLoadIdentity(); displaySide(&renderArgs, _myCamera); - _applicationOverlay.displayOverlayTexture(&renderArgs); + _compositor.displayOverlayTexture(&renderArgs); glPopMatrix(); renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; @@ -1551,8 +1549,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { _keyboardMouseDevice.mousePressEvent(event); if (event->button() == Qt::LeftButton) { - _mouseDragStartedX = getTrueMouseX(); - _mouseDragStartedY = getTrueMouseY(); + _mouseDragStarted = getTrueMouse(); _mousePressed = true; if (mouseOnScreen()) { @@ -1654,22 +1651,18 @@ void Application::touchUpdateEvent(QTouchEvent* event) { bool validTouch = false; if (activeWindow() == _window) { const QList& tPoints = event->touchPoints(); - _touchAvgX = 0.0f; - _touchAvgY = 0.0f; + _touchAvg = vec2(); int numTouches = tPoints.count(); if (numTouches > 1) { for (int i = 0; i < numTouches; ++i) { - _touchAvgX += tPoints[i].pos().x(); - _touchAvgY += tPoints[i].pos().y(); + _touchAvg += toGlm(tPoints[i].pos()); } - _touchAvgX /= (float)(numTouches); - _touchAvgY /= (float)(numTouches); + _touchAvg /= (float)(numTouches); validTouch = true; } } if (!_isTouchPressed) { - _touchDragStartedAvgX = _touchAvgX; - _touchDragStartedAvgY = _touchAvgY; + _touchDragStartedAvg = _touchAvg; } _isTouchPressed = validTouch; } @@ -1705,8 +1698,7 @@ void Application::touchEndEvent(QTouchEvent* event) { _keyboardMouseDevice.touchEndEvent(event); // put any application specific touch behavior below here.. - _touchDragStartedAvgX = _touchAvgX; - _touchDragStartedAvgY = _touchAvgY; + _touchDragStartedAvg = _touchAvg; _isTouchPressed = false; } @@ -1855,9 +1847,9 @@ void Application::setFullscreen(bool fullscreen) { Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen); } -// The following code block is useful on platforms that can have a visible -// app menu in a fullscreen window. However the OSX mechanism hides the -// application menu for fullscreen apps, so the check is not required. + // The following code block is useful on platforms that can have a visible + // app menu in a fullscreen window. However the OSX mechanism hides the + // application menu for fullscreen apps, so the check is not required. #ifndef Q_OS_MAC if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { if (fullscreen) { @@ -1927,11 +1919,6 @@ void Application::setEnableVRMode(bool enableVRMode) { OculusManager::recalibrate(); } else { OculusManager::abandonCalibration(); - - _mirrorCamera.setHmdPosition(glm::vec3()); - _mirrorCamera.setHmdRotation(glm::quat()); - _myCamera.setHmdPosition(glm::vec3()); - _myCamera.setHmdRotation(glm::quat()); } resizeGL(); @@ -1943,44 +1930,34 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { - return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && - getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); + ivec2 mouse = getMouse(); + if (!glm::all(glm::greaterThanEqual(mouse, ivec2()))) { + return false; + } + ivec2 size = toGlm(_glWidget->getDeviceSize()); + if (!glm::all(glm::lessThanEqual(mouse, size))) { + return false; + } } return true; } -int Application::getMouseX() const { +ivec2 Application::getMouse() const { if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.x; + return _compositor.screenToOverlay(getTrueMouse()); } - return getTrueMouseX(); + return getTrueMouse(); } -int Application::getMouseY() const { +ivec2 Application::getMouseDragStarted() const { if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.y; + return _compositor.screenToOverlay(getTrueMouseDragStarted()); } - return getTrueMouseY(); + return getTrueMouseDragStarted(); } -int Application::getMouseDragStartedX() const { - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), - getTrueMouseDragStartedY())); - return pos.x; - } - return getTrueMouseDragStartedX(); -} - -int Application::getMouseDragStartedY() const { - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), - getTrueMouseDragStartedY())); - return pos.y; - } - return getTrueMouseDragStartedY(); +ivec2 Application::getTrueMouseDragStarted() const { + return _mouseDragStarted; } FaceTracker* Application::getActiveFaceTracker() { @@ -3127,7 +3104,7 @@ PickRay Application::computePickRay(float x, float y) const { y /= size.y; PickRay result; if (isHMDMode()) { - getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); + getApplicationCompositor().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); } else { if (QThread::currentThread() == activeRenderingThread) { getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction); @@ -4809,12 +4786,8 @@ QSize Application::getDeviceSize() const { return _glWidget->getDeviceSize(); } -int Application::getTrueMouseX() const { - return _glWidget->mapFromGlobal(QCursor::pos()).x(); -} - -int Application::getTrueMouseY() const { - return _glWidget->mapFromGlobal(QCursor::pos()).y(); +ivec2 Application::getTrueMouse() const { + return toGlm(_glWidget->mapFromGlobal(QCursor::pos())); } bool Application::isThrottleRendering() const { @@ -4844,3 +4817,18 @@ qreal Application::getDevicePixelRatio() { return _window ? _window->windowHandle()->devicePixelRatio() : 1.0; } +mat4 Application::getEyeProjection(int eye) const { + if (isHMDMode()) { + return OculusManager::getEyeProjection(eye); + } + + return _viewFrustum.getProjection(); +} + +mat4 Application::getEyePose(int eye) const { + if (isHMDMode()) { + return OculusManager::getEyePose(eye); + } + + return mat4(); +} diff --git a/interface/src/Application.h b/interface/src/Application.h index 68bf60781a..bb5c50687a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -69,6 +69,7 @@ #include "ui/UpdateDialog.h" #include "ui/overlays/Overlays.h" #include "ui/ApplicationOverlay.h" +#include "ui/ApplicationCompositor.h" #include "ui/RunningScriptsWidget.h" #include "ui/ToolWindow.h" #include "ui/UserInputMapper.h" @@ -222,15 +223,21 @@ public: const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } bool mouseOnScreen() const; - int getMouseX() const; - int getMouseY() const; - glm::ivec2 getTrueMousePosition() const; - int getTrueMouseX() const; - int getTrueMouseY() const; - int getMouseDragStartedX() const; - int getMouseDragStartedY() const; - int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } - int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } + + ivec2 getMouse() const; + ivec2 getTrueMouse() const; + ivec2 getMouseDragStarted() const; + ivec2 getTrueMouseDragStarted() const; + + // TODO get rid of these and use glm types directly + int getMouseX() const { return getMouse().x; } + int getMouseY() const { return getMouse().y; } + int getTrueMouseX() const { return getTrueMouse().x; } + int getTrueMouseY() const { return getTrueMouse().y; } + int getMouseDragStartedX() const { return getMouseDragStarted().x; } + int getMouseDragStartedY() const { return getMouseDragStarted().y; } + int getTrueMouseDragStartedX() const { return getTrueMouseDragStarted().x; } + int getTrueMouseDragStartedY() const { return getTrueMouseDragStarted().y; } bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); @@ -239,6 +246,8 @@ public: QSystemTrayIcon* getTrayIcon() { return _trayIcon; } ApplicationOverlay& getApplicationOverlay() { return _applicationOverlay; } const ApplicationOverlay& getApplicationOverlay() const { return _applicationOverlay; } + ApplicationCompositor& getApplicationCompositor() { return _compositor; } + const ApplicationCompositor& getApplicationCompositor() const { return _compositor; } Overlays& getOverlays() { return _overlays; } float getFps() const { return _fps; } @@ -333,6 +342,9 @@ public: bool isHMDMode() const; glm::quat getHeadOrientation() const; glm::vec3 getHeadPosition() const; + glm::mat4 getHeadPose() const; + glm::mat4 getEyePose(int eye) const; + glm::mat4 getEyeProjection(int eye) const; QRect getDesirableApplicationGeometry(); RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; } @@ -584,18 +596,17 @@ private: Environment _environment; bool _cursorVisible; - int _mouseDragStartedX; - int _mouseDragStartedY; + ivec2 _mouseDragStarted; + quint64 _lastMouseMove; bool _lastMouseMoveWasSimulated; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; - float _touchAvgX; - float _touchAvgY; - float _touchDragStartedAvgX; - float _touchDragStartedAvgY; + vec2 _touchAvg; + vec2 _touchDragStartedAvg; + bool _isTouchPressed; // true if multitouch has been pressed (clear when finished) bool _mousePressed; // true if mouse has been pressed (clear when finished) @@ -676,6 +687,7 @@ private: Overlays _overlays; ApplicationOverlay _applicationOverlay; + ApplicationCompositor _compositor; }; #endif // hifi_Application_h diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e501b91dea..42ac30dbf3 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -49,8 +49,6 @@ Camera::Camera() : _mode(CAMERA_MODE_THIRD_PERSON), _position(0.0f, 0.0f, 0.0f), _projection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), 16.0f/9.0f, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)), - _hmdPosition(), - _hmdRotation(), _isKeepLookingAt(false), _lookingAt(0.0f, 0.0f, 0.0f) { @@ -74,20 +72,6 @@ void Camera::setRotation(const glm::quat& rotation) { } } -void Camera::setHmdPosition(const glm::vec3& hmdPosition) { - _hmdPosition = hmdPosition; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } -} - -void Camera::setHmdRotation(const glm::quat& hmdRotation) { - _hmdRotation = hmdRotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } -} - void Camera::setMode(CameraMode mode) { _mode = mode; emit modeUpdated(modeToString(mode)); diff --git a/interface/src/Camera.h b/interface/src/Camera.h index fc1dbcaf00..6eed39cf16 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -45,26 +45,22 @@ public: void setRotation(const glm::quat& rotation); void setProjection(const glm::mat4 & projection); - void setHmdPosition(const glm::vec3& hmdPosition); - void setHmdRotation(const glm::quat& hmdRotation); void setMode(CameraMode m); - glm::quat getRotation() const { return _rotation * _hmdRotation; } + glm::quat getRotation() const { return _rotation; } const glm::mat4& getProjection() const { return _projection; } - const glm::vec3& getHmdPosition() const { return _hmdPosition; } - const glm::quat& getHmdRotation() const { return _hmdRotation; } CameraMode getMode() const { return _mode; } public slots: QString getModeString() const; void setModeString(const QString& mode); - glm::vec3 getPosition() const { return _position + _hmdPosition; } + glm::vec3 getPosition() const { return _position; } void setPosition(const glm::vec3& position); - void setOrientation(const glm::quat& orientation) { setRotation(orientation); } glm::quat getOrientation() const { return getRotation(); } - + void setOrientation(const glm::quat& orientation) { setRotation(orientation); } + PickRay computePickRay(float x, float y); // These only work on independent cameras @@ -86,8 +82,6 @@ private: glm::vec3 _position; glm::quat _rotation; glm::mat4 _projection; - glm::vec3 _hmdPosition; - glm::quat _hmdRotation; bool _isKeepLookingAt; glm::vec3 _lookingAt; }; diff --git a/interface/src/audio/AudioToolBox.h b/interface/src/audio/AudioToolBox.h index e07e6857aa..ea2ef9f96a 100644 --- a/interface/src/audio/AudioToolBox.h +++ b/interface/src/audio/AudioToolBox.h @@ -14,7 +14,7 @@ #include #include -#include +#include class AudioToolBox : public Dependency { SINGLETON_DEPENDENCY diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c4e08b5dba..2b3997077b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1559,7 +1559,6 @@ void MyAvatar::renderLaserPointers() { //Gets the tip position for the laser pointer glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) { - const ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); glm::vec3 direction = glm::normalize(palm->getTipPosition() - palm->getPosition()); glm::vec3 position = palm->getPosition(); @@ -1568,7 +1567,8 @@ glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) { glm::vec3 result; - if (applicationOverlay.calculateRayUICollisionPoint(position, direction, result)) { + const auto& compositor = Application::getInstance()->getApplicationCompositor(); + if (compositor.calculateRayUICollisionPoint(position, direction, result)) { return result; } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 414c7f6199..f9d354e809 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -104,7 +104,9 @@ bool OculusManager::_eyePerFrameMode = false; ovrEyeType OculusManager::_lastEyeRendered = ovrEye_Count; ovrSizei OculusManager::_recommendedTexSize = { 0, 0 }; float OculusManager::_offscreenRenderScale = 1.0; - +static glm::mat4 _eyeProjections[ovrEye_Count]; +static glm::mat4 _combinedProjection; +static ovrPosef _eyeRenderPoses[ovrEye_Count]; void OculusManager::initSdk() { ovr_Initialize(); @@ -173,9 +175,15 @@ void OculusManager::connect() { _eyeTextures[eye].Header.API = ovrRenderAPI_OpenGL; _eyeTextures[eye].Header.TextureSize = _renderTargetSize; _eyeTextures[eye].Header.RenderViewport.Pos = { 0, 0 }; + ovrMatrix4f eyeProjection = ovrMatrix4f_Projection(_ovrHmd->MaxEyeFov[eye], DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + _eyeProjections[eye] = toGlm(eyeProjection); }); _eyeTextures[ovrEye_Right].Header.RenderViewport.Pos.x = _recommendedTexSize.w; + ovrFovPort combinedFov = _ovrHmd->MaxEyeFov[0]; + combinedFov.RightTan = _ovrHmd->MaxEyeFov[1].RightTan; + _combinedProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded)); + ovrHmd_SetEnabledCaps(_ovrHmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); ovrHmd_ConfigureTracking(_ovrHmd, ovrTrackingCap_Orientation | ovrTrackingCap_Position | @@ -566,7 +574,6 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const ovrPosef eyePoses[ovrEye_Count]; ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr); ovrHmd_BeginFrame(_ovrHmd, _frameIndex); - static ovrPosef eyeRenderPose[ovrEye_Count]; //Render each eye into an fbo for_each_eye(_ovrHmd, [&](ovrEyeType eye){ // If we're in eye-per-frame mode, only render one eye @@ -576,29 +583,17 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const return; } _lastEyeRendered = _activeEye = eye; - eyeRenderPose[eye] = eyePoses[eye]; + _eyeRenderPoses[eye] = eyePoses[eye]; // Set the camera rotation for this eye - orientation.x = eyeRenderPose[eye].Orientation.x; - orientation.y = eyeRenderPose[eye].Orientation.y; - orientation.z = eyeRenderPose[eye].Orientation.z; - orientation.w = eyeRenderPose[eye].Orientation.w; - - // Update the application camera with the latest HMD position - whichCamera.setHmdPosition(trackerPosition); - whichCamera.setHmdRotation(orientation); - + vec3 eyePosition = toGlm(_eyeRenderPoses[eye].Position); + eyePosition = whichCamera.getRotation() * eyePosition; + quat eyeRotation = toGlm(_eyeRenderPoses[eye].Orientation); + // Update our camera to what the application camera is doing - _camera->setRotation(whichCamera.getRotation()); - _camera->setPosition(whichCamera.getPosition()); + _camera->setRotation(whichCamera.getRotation() * eyeRotation); + _camera->setPosition(whichCamera.getPosition() + eyePosition); configureCamera(*_camera); - - // Store the latest left and right eye render locations for things that need to know - glm::vec3 thisEyePosition = position + trackerPosition + - (bodyOrientation * glm::quat(orientation.x, orientation.y, orientation.z, orientation.w) * - glm::vec3(_eyeRenderDesc[eye].HmdToEyeViewOffset.x, _eyeRenderDesc[eye].HmdToEyeViewOffset.y, _eyeRenderDesc[eye].HmdToEyeViewOffset.z)); - - _eyePositions[eye] = thisEyePosition; _camera->update(1.0f / Application::getInstance()->getFps()); glMatrixMode(GL_PROJECTION); @@ -615,7 +610,8 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const renderArgs->_renderSide = RenderArgs::MONO; qApp->displaySide(renderArgs, *_camera, false); - qApp->getApplicationOverlay().displayOverlayTextureHmd(renderArgs, *_camera); + //qApp->getApplicationCompositor().displayOverlayTexture(renderArgs); + qApp->getApplicationCompositor().displayOverlayTextureHmd(renderArgs, eye); }); _activeEye = ovrEye_Count; @@ -661,7 +657,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); //Renders the distorted mesh onto the screen - renderDistortionMesh(eyeRenderPose); + renderDistortionMesh(_eyeRenderPoses); glBindTexture(GL_TEXTURE_2D, 0); #endif glCanvas->swapBuffers(); @@ -877,3 +873,10 @@ int OculusManager::getHMDScreen() { return hmdScreenIndex; } +mat4 OculusManager::getEyeProjection(int eye) { + return _eyeProjections[eye]; +} + +mat4 OculusManager::getEyePose(int eye) { + return toGlm(_eyeRenderPoses[eye]); +} \ No newline at end of file diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 799f07ea35..1dfce7ee7e 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -81,6 +81,9 @@ public: static glm::vec3 getRightEyePosition() { return _eyePositions[ovrEye_Right]; } static int getHMDScreen(); + + static glm::mat4 getEyeProjection(int eye); + static glm::mat4 getEyePose(int eye); private: static void initSdk(); diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index f1a762e64f..5934d2630c 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -489,7 +489,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) || Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { - pos = qApp->getApplicationOverlay().getPalmClickLocation(palm); + pos = qApp->getApplicationCompositor().getPalmClickLocation(palm); } else { // Get directon relative to avatar orientation glm::vec3 direction = glm::inverse(avatar->getOrientation()) * palm->getFingerDirection(); diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index b0a2ff7e3b..41e549a861 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -120,7 +120,7 @@ void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) { glLoadIdentity(); renderArgs->_renderSide = RenderArgs::MONO; qApp->displaySide(renderArgs, eyeCamera, false); - qApp->getApplicationOverlay().displayOverlayTexture(renderArgs); + qApp->getApplicationCompositor().displayOverlayTexture(renderArgs); _activeEye = NULL; }, [&]{ // render right side view diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index f258fd695c..f65d638ccc 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -25,9 +25,9 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { glm::vec3 direction = orientation * glm::vec3(0.0f, 0.0f, -1.0f); - ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); + const auto& compositor = Application::getInstance()->getApplicationCompositor(); - return applicationOverlay.calculateRayUICollisionPoint(position, direction, result); + return compositor.calculateRayUICollisionPoint(position, direction, result); } QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) { @@ -40,7 +40,7 @@ QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* conte glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * (hudIntersection - sphereCenter); glm::quat rotation = ::rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), direction); glm::vec3 eulers = ::safeEulerAngles(rotation); - return qScriptValueFromValue(engine, Application::getInstance()->getApplicationOverlay() + return qScriptValueFromValue(engine, Application::getInstance()->getApplicationCompositor() .sphericalToOverlay(glm::vec2(eulers.y, -eulers.x))); } return QScriptValue::NullValue; diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 9b0f8dc4d1..4bcced1fa2 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -27,11 +27,11 @@ public: static QScriptValue getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine); public slots: - void toggleMagnifier() { Application::getInstance()->getApplicationOverlay().toggleMagnifier(); }; + void toggleMagnifier() { Application::getInstance()->getApplicationCompositor().toggleMagnifier(); }; private: HMDScriptingInterface() {}; - bool getMagnifier() const { return Application::getInstance()->getApplicationOverlay().hasMagnifier(); }; + bool getMagnifier() const { return Application::getInstance()->getApplicationCompositor().hasMagnifier(); }; bool isHMDMode() const { return Application::getInstance()->isHMDMode(); } bool getHUDLookAtPosition3D(glm::vec3& result) const; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp new file mode 100644 index 0000000000..f6a79f2bc2 --- /dev/null +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -0,0 +1,757 @@ +// +// ApplicationCompositor.cpp +// interface/src/ui/overlays +// +// Created by Benjamin Arnold on 5/27/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "InterfaceConfig.h" + +#include "ApplicationCompositor.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + + +#include "AudioClient.h" +#include "audio/AudioIOStatsRenderer.h" +#include "audio/AudioScope.h" +#include "audio/AudioToolBox.h" +#include "Application.h" +#include "devices/CameraToolBox.h" + +#include "Util.h" +#include "ui/Stats.h" + +#include "../../libraries/render-utils/standardTransformPNTC_vert.h" +#include "../../libraries/render-utils/standardDrawTexture_frag.h" + +// Used to animate the magnification windows +static const float MAG_SPEED = 0.08f; + +static const quint64 MSECS_TO_USECS = 1000ULL; + +static const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; +static const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; +static const float reticleSize = TWO_PI / 100.0f; + +static const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; +static const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; + +static const float CURSOR_PIXEL_SIZE = 32.0f; +static const float MOUSE_PITCH_RANGE = 1.0f * PI; +static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; +static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); + +static gpu::BufferPointer _hemiVertices; +static gpu::BufferPointer _hemiIndices; +static int _hemiIndexCount{ 0 }; + +// Return a point's cartesian coordinates on a sphere from pitch and yaw +glm::vec3 getPoint(float yaw, float pitch) { + return glm::vec3(glm::cos(-pitch) * (-glm::sin(yaw)), + glm::sin(-pitch), + glm::cos(-pitch) * (-glm::cos(yaw))); +} + + +//Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should +//be multiplied by dir and added to origin to get the location of the collision +bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, float* result) +{ + //Source: http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection + + //Compute A, B and C coefficients + float a = glm::dot(dir, dir); + float b = 2 * glm::dot(dir, origin); + float c = glm::dot(origin, origin) - (r * r); + + //Find discriminant + float disc = b * b - 4 * a * c; + + // if discriminant is negative there are no real roots, so return + // false as ray misses sphere + if (disc < 0) { + return false; + } + + // compute q as described above + float distSqrt = sqrtf(disc); + float q; + if (b < 0) { + q = (-b - distSqrt) / 2.0; + } else { + q = (-b + distSqrt) / 2.0; + } + + // compute t0 and t1 + float t0 = q / a; + float t1 = c / q; + + // make sure t0 is smaller than t1 + if (t0 > t1) { + // if t0 is bigger than t1 swap them around + float temp = t0; + t0 = t1; + t1 = temp; + } + + // if t1 is less than zero, the object is in the ray's negative direction + // and consequently the ray misses the sphere + if (t1 < 0) { + return false; + } + + // if t0 is less than zero, the intersection point is at t1 + if (t0 < 0) { + *result = t1; + return true; + } else { // else the intersection point is at t0 + *result = t0; + return true; + } +} + +ApplicationCompositor::ApplicationCompositor() { + memset(_reticleActive, 0, sizeof(_reticleActive)); + memset(_magActive, 0, sizeof(_reticleActive)); + memset(_magSizeMult, 0, sizeof(_magSizeMult)); + + auto geometryCache = DependencyManager::get(); + + _reticleQuad = geometryCache->allocateID(); + _magnifierQuad = geometryCache->allocateID(); + _audioRedQuad = geometryCache->allocateID(); + _audioGreenQuad = geometryCache->allocateID(); + _audioBlueQuad = geometryCache->allocateID(); + _domainStatusBorder = geometryCache->allocateID(); + _magnifierBorder = geometryCache->allocateID(); +} + +ApplicationCompositor::~ApplicationCompositor() { +} + +void ApplicationCompositor::bindCursorTexture(gpu::Batch& batch, uint8_t cursorIndex) { + auto& cursorManager = Cursor::Manager::instance(); + auto cursor = cursorManager.getCursor(cursorIndex); + auto iconId = cursor->getIcon(); + if (!_cursors.count(iconId)) { + auto iconPath = cursorManager.getIconImage(cursor->getIcon()); + _cursors[iconId] = DependencyManager::get()-> + getImageTexture(iconPath); + } + batch.setUniformTexture(0, _cursors[iconId]); +} + + +// Draws the FBO texture for the screen +void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { + if (_alpha == 0.0f) { + return; + } + + GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); + if (!texture) { + return; + } + renderArgs->_context->syncCache(); + auto geometryCache = DependencyManager::get(); + + gpu::Batch batch; + geometryCache->useSimpleDrawPipeline(batch); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch.setProjectionTransform(mat4()); + batch._glBindTexture(GL_TEXTURE_2D, texture); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); + + // Doesn't actually render + renderPointers(); + + + //draw the mouse pointer + vec2 canvasSize = qApp->getCanvasSize(); + + // Get the mouse coordinates and convert to NDC [-1, 1] + vec2 mousePosition = vec2(qApp->getMouse()); + mousePosition /= canvasSize; + mousePosition *= 2.0f; + mousePosition -= 1.0f; + mousePosition.y *= -1.0f; + + Transform model; + model.setTranslation(vec3(mousePosition, 0)); + vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; + model.setScale(vec3(mouseSize, 1.0f)); + batch.setModelTransform(model); + bindCursorTexture(batch); + vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; + geometryCache->renderUnitQuad(batch, vec4(1)); + renderArgs->_context->render(batch); +} + + +vec2 getPolarCoordinates(const PalmData& palm) { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + auto avatarOrientation = myAvatar->getOrientation(); + auto eyePos = myAvatar->getDefaultEyePosition(); + glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); + // Direction of the tip relative to the eye + glm::vec3 tipDirection = tip - eyePos; + // orient into avatar space + tipDirection = glm::inverse(avatarOrientation) * tipDirection; + // Normalize for trig functions + tipDirection = glm::normalize(tipDirection); + // Convert to polar coordinates + glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y)); + return polar; +} + +// Draws the FBO texture for Oculus rift. +void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int eye) { + if (_alpha == 0.0f) { + return; + } + + GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); + if (!texture) { + return; + } + + renderArgs->_context->syncCache(); + auto geometryCache = DependencyManager::get(); + + gpu::Batch batch; + DependencyManager::get()->useSimpleDrawPipeline(batch); + batch._glDisable(GL_DEPTH_TEST); + batch._glDisable(GL_CULL_FACE); + batch._glBindTexture(GL_TEXTURE_2D, texture); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + batch.setViewTransform(Transform()); + batch.setProjectionTransform(qApp->getEyeProjection(eye)); + mat4 eyePose = qApp->getEyePose(eye); + glm::mat4 overlayXfm = glm::inverse(eyePose); + batch.setModelTransform(overlayXfm); + drawSphereSection(batch); + + // Doesn't actually render + renderPointers(); + vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); + + bindCursorTexture(batch); + + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + //Controller Pointers + for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + glm::vec2 polar = getPolarCoordinates(palm); + // Convert to quaternion + mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + // Render reticle at location + geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); + } + } + + //Mouse Pointer + if (_reticleActive[MOUSE]) { + glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), + _reticlePosition[MOUSE].y())); + mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); + } + + renderArgs->_context->render(batch); +} + + +void ApplicationCompositor::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { + cursorPos *= qApp->getCanvasSize(); + const glm::vec2 projection = screenToSpherical(cursorPos); + // The overlay space orientation of the mouse coordinates + const glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); + // FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE. + // Now we need to account for the actual camera position relative to the overlay + glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT); + + + // We need the RAW camera orientation and position, because this is what the overlay is + // rendered relative to + const glm::vec3 overlayPosition = qApp->getCamera()->getPosition(); + const glm::quat overlayOrientation = qApp->getCamera()->getRotation(); + + // Intersection UI overlay space + glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; + glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius; + intersectionWithUi += overlayPosition; + + // Intersection in world space + origin = overlayPosition; + direction = glm::normalize(intersectionWithUi - origin); +} + +//Caculate the click location using one of the sixense controllers. Scale is not applied +QPoint ApplicationCompositor::getPalmClickLocation(const PalmData *palm) const { + QPoint rv; + auto canvasSize = qApp->getCanvasSize(); + if (qApp->isHMDMode()) { + glm::vec2 polar = getPolarCoordinates(*palm); + glm::vec2 point = sphericalToScreen(-polar); + rv.rx() = point.x; + rv.ry() = point.y; + } else { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + glm::dmat4 projection; + qApp->getProjectionMatrix(&projection); + glm::quat invOrientation = glm::inverse(myAvatar->getOrientation()); + glm::vec3 eyePos = myAvatar->getDefaultEyePosition(); + glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); + glm::vec3 tipPos = invOrientation * (tip - eyePos); + + glm::vec4 clipSpacePos = glm::vec4(projection * glm::dvec4(tipPos, 1.0)); + glm::vec3 ndcSpacePos; + if (clipSpacePos.w != 0) { + ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w; + } + + rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * canvasSize.x); + rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * canvasSize.y); + } + return rv; +} + +//Finds the collision point of a world space ray +bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + + glm::quat inverseOrientation = glm::inverse(myAvatar->getOrientation()); + + glm::vec3 relativePosition = inverseOrientation * (position - myAvatar->getDefaultEyePosition()); + glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction); + + float t; + if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){ + result = position + direction * t; + return true; + } + + return false; +} + +//Renders optional pointers +void ApplicationCompositor::renderPointers() { + //glEnable(GL_TEXTURE_2D); + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + //glActiveTexture(GL_TEXTURE0); + //bindCursorTexture(); + + 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; + renderControllerPointers(); + } + //glBindTexture(GL_TEXTURE_2D, 0); + //glDisable(GL_TEXTURE_2D); +} + +void ApplicationCompositor::renderControllerPointers() { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + + //Static variables used for storing controller state + static quint64 pressedTime[NUMBER_OF_RETICLES] = { 0ULL, 0ULL, 0ULL }; + static bool isPressed[NUMBER_OF_RETICLES] = { false, false, false }; + static bool stateWhenPressed[NUMBER_OF_RETICLES] = { false, false, false }; + + const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); + + for (unsigned int palmIndex = 2; palmIndex < 4; palmIndex++) { + const int index = palmIndex - 1; + + const PalmData* palmData = NULL; + + if (palmIndex >= handData->getPalms().size()) { + return; + } + + if (handData->getPalms()[palmIndex].isActive()) { + palmData = &handData->getPalms()[palmIndex]; + } else { + continue; + } + + int controllerButtons = palmData->getControllerButtons(); + + //Check for if we should toggle or drag the magnification window + if (controllerButtons & BUTTON_3) { + if (isPressed[index] == false) { + //We are now dragging the window + isPressed[index] = true; + //set the pressed time in us + pressedTime[index] = usecTimestampNow(); + stateWhenPressed[index] = _magActive[index]; + } + } else if (isPressed[index]) { + isPressed[index] = false; + //If the button was only pressed for < 250 ms + //then disable it. + + const int MAX_BUTTON_PRESS_TIME = 250 * MSECS_TO_USECS; + if (usecTimestampNow() < pressedTime[index] + MAX_BUTTON_PRESS_TIME) { + _magActive[index] = !stateWhenPressed[index]; + } + } + + //if we have the oculus, we should make the cursor smaller since it will be + //magnified + if (qApp->isHMDMode()) { + + QPoint point = getPalmClickLocation(palmData); + + _reticlePosition[index] = point; + + //When button 2 is pressed we drag the mag window + if (isPressed[index]) { + _magActive[index] = true; + } + + // If oculus is enabled, we draw the crosshairs later + continue; + } + + auto canvasSize = qApp->getCanvasSize(); + int mouseX, mouseY; + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { + QPoint res = getPalmClickLocation(palmData); + mouseX = res.x(); + mouseY = res.y(); + } else { + // Get directon relative to avatar orientation + glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); + + // Get the angles, scaled between (-0.5,0.5) + float xAngle = (atan2(direction.z, direction.x) + M_PI_2); + float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); + + // Get the pixel range over which the xAngle and yAngle are scaled + float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); + + mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle); + mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle); + } + + //If the cursor is out of the screen then don't render it + if (mouseX < 0 || mouseX >= (int)canvasSize.x || mouseY < 0 || mouseY >= (int)canvasSize.y) { + _reticleActive[index] = false; + continue; + } + _reticleActive[index] = true; + + + const float reticleSize = 40.0f; + + mouseX -= reticleSize / 2.0f; + mouseY += reticleSize / 2.0f; + + + glm::vec2 topLeft(mouseX, mouseY); + glm::vec2 bottomRight(mouseX + reticleSize, mouseY - reticleSize); + glm::vec2 texCoordTopLeft(0.0f, 0.0f); + glm::vec2 texCoordBottomRight(1.0f, 1.0f); + + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, + glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f)); + + } +} + +//Renders a small magnification of the currently bound texture at the coordinates +void ApplicationCompositor::renderMagnifier(const glm::vec2& magPos, float sizeMult, bool showBorder) { + if (!_magnifier) { + return; + } + auto canvasSize = qApp->getCanvasSize(); + + const int widgetWidth = canvasSize.x; + const int widgetHeight = canvasSize.y; + + const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; + const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; + // Magnification Texture Coordinates + const float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; + const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; + const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; + const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; + + const float newHalfWidth = halfWidth * MAGNIFY_MULT; + const float newHalfHeight = halfHeight * MAGNIFY_MULT; + //Get yaw / pitch value for the corners + const glm::vec2 topLeftYawPitch = overlayToSpherical(glm::vec2(magPos.x - newHalfWidth, + magPos.y - newHalfHeight)); + const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth, + magPos.y + newHalfHeight)); + + const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y); + const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y); + const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y); + const glm::vec3 topRight = getPoint(bottomRightYawPitch.x, topLeftYawPitch.y); + + auto geometryCache = DependencyManager::get(); + + if (bottomLeft != _previousMagnifierBottomLeft || bottomRight != _previousMagnifierBottomRight + || topLeft != _previousMagnifierTopLeft || topRight != _previousMagnifierTopRight) { + QVector border; + border << topLeft; + border << bottomLeft; + border << bottomRight; + border << topRight; + border << topLeft; + geometryCache->updateVertices(_magnifierBorder, border, glm::vec4(1.0f, 0.0f, 0.0f, _alpha)); + + _previousMagnifierBottomLeft = bottomLeft; + _previousMagnifierBottomRight = bottomRight; + _previousMagnifierTopLeft = topLeft; + _previousMagnifierTopRight = topRight; + } + + glPushMatrix(); { + if (showBorder) { + glDisable(GL_TEXTURE_2D); + glLineWidth(1.0f); + //Outer Line + geometryCache->renderVertices(gpu::LINE_STRIP, _magnifierBorder); + glEnable(GL_TEXTURE_2D); + } + glm::vec4 magnifierColor = { 1.0f, 1.0f, 1.0f, _alpha }; + + DependencyManager::get()->renderQuad(bottomLeft, bottomRight, topRight, topLeft, + glm::vec2(magnifyULeft, magnifyVBottom), + glm::vec2(magnifyURight, magnifyVBottom), + glm::vec2(magnifyURight, magnifyVTop), + glm::vec2(magnifyULeft, magnifyVTop), + magnifierColor, _magnifierQuad); + + } glPopMatrix(); +} + +void ApplicationCompositor::buildHemiVertices( + const float fov, const float aspectRatio, const int slices, const int stacks) { + static float textureFOV = 0.0f, textureAspectRatio = 1.0f; + if (textureFOV == fov && textureAspectRatio == aspectRatio) { + return; + } + + textureFOV = fov; + textureAspectRatio = aspectRatio; + + auto geometryCache = DependencyManager::get(); + + _hemiVertices = gpu::BufferPointer(new gpu::Buffer()); + _hemiIndices = gpu::BufferPointer(new gpu::Buffer()); + + + if (fov >= PI) { + qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; + } + + //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm + + vec3 pos; + vec2 uv; + // Compute vertices positions and texture UV coordinate + // Create and write to buffer + for (int i = 0; i < stacks; i++) { + uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f + // abs(theta) <= fov / 2.0f + float pitch = -fov * (uv.y - 0.5f); + for (int j = 0; j < slices; j++) { + uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f + // abs(phi) <= fov * aspectRatio / 2.0f + float yaw = -fov * aspectRatio * (uv.x - 0.5f); + pos = getPoint(yaw, pitch); + static const vec4 color(1); + _hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos); + _hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv); + _hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color); + } + } + + // Compute number of indices needed + static const int VERTEX_PER_TRANGLE = 3; + static const int TRIANGLE_PER_RECTANGLE = 2; + int numberOfRectangles = (slices - 1) * (stacks - 1); + _hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; + + // Compute indices order + std::vector indices; + for (int i = 0; i < stacks - 1; i++) { + for (int j = 0; j < slices - 1; j++) { + GLushort bottomLeftIndex = i * slices + j; + GLushort bottomRightIndex = bottomLeftIndex + 1; + GLushort topLeftIndex = bottomLeftIndex + slices; + GLushort topRightIndex = topLeftIndex + 1; + // FIXME make a z-order curve for better vertex cache locality + indices.push_back(topLeftIndex); + indices.push_back(bottomLeftIndex); + indices.push_back(topRightIndex); + + indices.push_back(topRightIndex); + indices.push_back(bottomLeftIndex); + indices.push_back(bottomRightIndex); + } + } + _hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]); +} + + +void ApplicationCompositor::drawSphereSection(gpu::Batch& batch) { + buildHemiVertices(_textureFov, _textureAspectRatio, 80, 80); + static const int VERTEX_DATA_SLOT = 0; + static const int TEXTURE_DATA_SLOT = 1; + static const int COLOR_DATA_SLOT = 2; + gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone + streamFormat->setAttribute(gpu::Stream::POSITION, VERTEX_DATA_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); + streamFormat->setAttribute(gpu::Stream::TEXCOORD, TEXTURE_DATA_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_DATA_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA)); + batch.setInputFormat(streamFormat); + + static const int VERTEX_STRIDE = sizeof(vec3) + sizeof(vec2) + sizeof(vec4); + gpu::BufferView posView(_hemiVertices, 0, _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); + gpu::BufferView uvView(_hemiVertices, sizeof(vec3), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element); + gpu::BufferView colView(_hemiVertices, sizeof(vec3) + sizeof(vec2), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); + batch.setInputBuffer(VERTEX_DATA_SLOT, posView); + batch.setInputBuffer(TEXTURE_DATA_SLOT, uvView); + batch.setInputBuffer(COLOR_DATA_SLOT, colView); + batch.setIndexBuffer(gpu::UINT16, _hemiIndices, 0); + batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount); +} + + +glm::vec2 ApplicationCompositor::directionToSpherical(const glm::vec3& direction) { + glm::vec2 result; + // Compute yaw + glm::vec3 normalProjection = glm::normalize(glm::vec3(direction.x, 0.0f, direction.z)); + result.x = glm::acos(glm::dot(IDENTITY_FRONT, normalProjection)); + if (glm::dot(IDENTITY_RIGHT, normalProjection) > 0.0f) { + result.x = -glm::abs(result.x); + } else { + result.x = glm::abs(result.x); + } + // Compute pitch + result.y = angleBetween(IDENTITY_UP, direction) - PI_OVER_TWO; + + return result; +} + +glm::vec3 ApplicationCompositor::sphericalToDirection(const glm::vec2& sphericalPos) { + glm::quat rotation(glm::vec3(sphericalPos.y, sphericalPos.x, 0.0f)); + return rotation * IDENTITY_FRONT; +} + +glm::vec2 ApplicationCompositor::screenToSpherical(const glm::vec2& screenPos) { + auto screenSize = qApp->getCanvasSize(); + glm::vec2 result; + result.x = -(screenPos.x / screenSize.x - 0.5f); + result.y = (screenPos.y / screenSize.y - 0.5f); + result.x *= MOUSE_YAW_RANGE; + result.y *= MOUSE_PITCH_RANGE; + + return result; +} + +glm::vec2 ApplicationCompositor::sphericalToScreen(const glm::vec2& sphericalPos) { + glm::vec2 result = sphericalPos; + result.x *= -1.0; + result /= MOUSE_RANGE; + result += 0.5f; + result *= qApp->getCanvasSize(); + return result; +} + +glm::vec2 ApplicationCompositor::sphericalToOverlay(const glm::vec2& sphericalPos) const { + glm::vec2 result = sphericalPos; + result.x *= -1.0; + result /= _textureFov; + result.x /= _textureAspectRatio; + result += 0.5f; + result *= qApp->getCanvasSize(); + return result; +} + +glm::vec2 ApplicationCompositor::overlayToSpherical(const glm::vec2& overlayPos) const { + glm::vec2 result = overlayPos; + result /= qApp->getCanvasSize(); + result -= 0.5f; + result *= _textureFov; + result.x *= _textureAspectRatio; + result.x *= -1.0f; + return result; +} + +glm::vec2 ApplicationCompositor::screenToOverlay(const glm::vec2& screenPos) const { + return sphericalToOverlay(screenToSpherical(screenPos)); +} + +glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) const { + return sphericalToScreen(overlayToSpherical(overlayPos)); +} diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h new file mode 100644 index 0000000000..61bbafaba7 --- /dev/null +++ b/interface/src/ui/ApplicationCompositor.h @@ -0,0 +1,118 @@ +// +// Created by Bradley Austin Davis Arnold on 2015/06/13 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ApplicationOverlayCompositor_h +#define hifi_ApplicationOverlayCompositor_h + +#include +#include + +#include +#include +#include +#include + +class Camera; +class PalmData; +class RenderArgs; + +const float MAGNIFY_WIDTH = 220.0f; +const float MAGNIFY_HEIGHT = 100.0f; +const float MAGNIFY_MULT = 2.0f; + +const float DEFAULT_HMD_UI_ANGULAR_SIZE = 72.0f; + +// Handles the drawing of the overlays to the screen +// TODO, move divide up the rendering, displaying and input handling +// facilities of this class +class ApplicationCompositor : public QObject { + Q_OBJECT +public: + ApplicationCompositor(); + ~ApplicationCompositor(); + + void displayOverlayTexture(RenderArgs* renderArgs); + void displayOverlayTextureHmd(RenderArgs* renderArgs, int eye); + + QPoint getPalmClickLocation(const PalmData *palm) const; + bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; + + bool hasMagnifier() const { return _magnifier; } + void toggleMagnifier() { _magnifier = !_magnifier; } + + float getHmdUIAngularSize() const { return _hmdUIAngularSize; } + void setHmdUIAngularSize(float hmdUIAngularSize) { _hmdUIAngularSize = hmdUIAngularSize; } + + // Converter from one frame of reference to another. + // Frame of reference: + // Direction: Ray that represents the spherical values + // Screen: Position on the screen (x,y) + // Spherical: Pitch and yaw that gives the position on the sphere we project on (yaw,pitch) + // Overlay: Position on the overlay (x,y) + // (x,y) in Overlay are similar than (x,y) in Screen except they can be outside of the bound of te screen. + // This allows for picking outside of the screen projection in 3D. + glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; + glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; + glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; + glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; + void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; + GLuint getOverlayTexture(); + + static glm::vec2 directionToSpherical(const glm::vec3 & direction); + static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); + static glm::vec2 screenToSpherical(const glm::vec2 & screenPos); + static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); + +private: + void displayOverlayTextureStereo(RenderArgs* renderArgs, float aspectRatio, float fov); + void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); + void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); + void drawSphereSection(gpu::Batch& batch); + + void renderPointers(); + void renderMagnifier(const glm::vec2& magPos, float sizeMult, bool showBorder); + + void renderControllerPointers(); + void renderPointersOculus(); + + float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; + float _textureFov{ glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE) }; + float _textureAspectRatio{ 1.0f }; + int _hemiVerticesID{ GeometryCache::UNKNOWN_ID }; + + enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES }; + bool _reticleActive[NUMBER_OF_RETICLES]; + 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 }; + float _oculusUIRadius{ 1.0f }; + + QMap _cursors; + + int _reticleQuad; + int _magnifierQuad; + int _audioRedQuad; + int _audioGreenQuad; + int _audioBlueQuad; + int _domainStatusBorder; + int _magnifierBorder; + + int _previousBorderWidth{ -1 }; + int _previousBorderHeight{ -1 }; + + glm::vec3 _previousMagnifierBottomLeft; + glm::vec3 _previousMagnifierBottomRight; + glm::vec3 _previousMagnifierTopLeft; + glm::vec3 _previousMagnifierTopRight; +}; + +#endif // hifi_ApplicationOverlayCompositor_h diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index cb17569b86..ea56eed73d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -36,114 +36,20 @@ #include "Util.h" #include "ui/Stats.h" -#include "../../libraries/render-utils/standardTransformPNTC_vert.h" -#include "../../libraries/render-utils/standardDrawTexture_frag.h" - -// Used to animate the magnification windows -const float MAG_SPEED = 0.08f; - -const quint64 MSECS_TO_USECS = 1000ULL; - const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; -const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; -const float reticleSize = TWO_PI / 100.0f; - - +const int AUDIO_METER_GAP = 5; +const int MUTE_ICON_PADDING = 10; const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; -static const float MOUSE_PITCH_RANGE = 1.0f * PI; -static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; -static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); - -// Return a point's cartesian coordinates on a sphere from pitch and yaw -glm::vec3 getPoint(float yaw, float pitch) { - return glm::vec3(glm::cos(-pitch) * (-glm::sin(yaw)), - glm::sin(-pitch), - glm::cos(-pitch) * (-glm::cos(yaw))); -} - -//Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should -//be multiplied by dir and added to origin to get the location of the collision -bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, float* result) -{ - //Source: http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection - - //Compute A, B and C coefficients - float a = glm::dot(dir, dir); - float b = 2 * glm::dot(dir, origin); - float c = glm::dot(origin, origin) - (r * r); - - //Find discriminant - float disc = b * b - 4 * a * c; - - // if discriminant is negative there are no real roots, so return - // false as ray misses sphere - if (disc < 0) { - return false; - } - - // compute q as described above - float distSqrt = sqrtf(disc); - float q; - if (b < 0) { - q = (-b - distSqrt) / 2.0; - } else { - q = (-b + distSqrt) / 2.0; - } - - // compute t0 and t1 - float t0 = q / a; - float t1 = c / q; - - // make sure t0 is smaller than t1 - if (t0 > t1) { - // if t0 is bigger than t1 swap them around - float temp = t0; - t0 = t1; - t1 = temp; - } - - // if t1 is less than zero, the object is in the ray's negative direction - // and consequently the ray misses the sphere - if (t1 < 0) { - return false; - } - - // if t0 is less than zero, the intersection point is at t1 - if (t0 < 0) { - *result = t1; - return true; - } else { // else the intersection point is at t0 - *result = t0; - return true; - } -} - ApplicationOverlay::ApplicationOverlay() : - _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)), - _textureAspectRatio(1.0f), - _lastMouseMove(0), - _magnifier(true), _alpha(1.0f), - _oculusUIRadius(1.0f), _trailingAudioLoudness(0.0f), _previousBorderWidth(-1), _previousBorderHeight(-1), - _previousMagnifierBottomLeft(), - _previousMagnifierBottomRight(), - _previousMagnifierTopLeft(), - _previousMagnifierTopRight(), _framebufferObject(nullptr) { - memset(_reticleActive, 0, sizeof(_reticleActive)); - memset(_magActive, 0, sizeof(_reticleActive)); - memset(_magSizeMult, 0, sizeof(_magSizeMult)); - auto geometryCache = DependencyManager::get(); - - _reticleQuad = geometryCache->allocateID(); - _magnifierQuad = geometryCache->allocateID(); _audioRedQuad = geometryCache->allocateID(); _audioGreenQuad = geometryCache->allocateID(); _audioBlueQuad = geometryCache->allocateID(); @@ -159,7 +65,7 @@ ApplicationOverlay::ApplicationOverlay() : auto offscreenUi = DependencyManager::get(); offscreenUi->lockTexture(textureId); assert(!glGetError()); - std::swap(_newUiTexture, textureId); + std::swap(_uiTexture, textureId); if (textureId) { offscreenUi->releaseTexture(textureId); } @@ -172,13 +78,10 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - Overlays& overlays = qApp->getOverlays(); - - _textureFov = glm::radians(_hmdUIAngularSize); - glm::vec2 size = qApp->getCanvasSize(); - _textureAspectRatio = aspect(size); - //Handle fading and deactivation/activation of UI + Overlays& overlays = qApp->getOverlays(); + glm::vec2 size = qApp->getCanvasSize(); + // TODO Handle fading and deactivation/activation of UI // Render 2D overlay glDisable(GL_DEPTH_TEST); @@ -210,10 +113,8 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { overlays.renderHUD(renderArgs); - renderPointers(); - renderDomainConnectionStatusBorder(); - if (_newUiTexture) { + if (_uiTexture) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -221,7 +122,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, _newUiTexture); + glBindTexture(GL_TEXTURE_2D, _uiTexture); DependencyManager::get()->renderUnitQuad(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); @@ -241,472 +142,6 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { _framebufferObject->release(); } -gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() { - if (!_standardDrawPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); - auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - gpu::Shader::makeProgram((*program)); - - auto state = gpu::StatePointer(new gpu::State()); - - // enable decal blend - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - - _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); - } - - return _standardDrawPipeline; -} - -void ApplicationOverlay::bindCursorTexture(gpu::Batch& batch, uint8_t cursorIndex) { - auto& cursorManager = Cursor::Manager::instance(); - auto cursor = cursorManager.getCursor(cursorIndex); - auto iconId = cursor->getIcon(); - if (!_cursors.count(iconId)) { - auto iconPath = cursorManager.getIconImage(cursor->getIcon()); - _cursors[iconId] = DependencyManager::get()-> - getImageTexture(iconPath); - } - batch.setUniformTexture(0, _cursors[iconId]); -} - -#define CURSOR_PIXEL_SIZE 32.0f - -// Draws the FBO texture for the screen -void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { - if (_alpha == 0.0f || !_framebufferObject) { - return; - } - - renderArgs->_context->syncCache(); - - gpu::Batch batch; - Transform model; - //DependencyManager::get()->bindSimpleProgram(batch, true); - batch.setPipeline(getDrawPipeline()); - batch.setModelTransform(Transform()); - batch.setProjectionTransform(mat4()); - batch.setViewTransform(model); - batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - DependencyManager::get()->renderUnitQuad(batch, vec4(vec3(1), _alpha)); - - //draw the mouse pointer - glm::vec2 canvasSize = qApp->getCanvasSize(); - - // Get the mouse coordinates and convert to NDC [-1, 1] - vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); - mousePosition /= canvasSize; - mousePosition *= 2.0f; - mousePosition -= 1.0f; - mousePosition.y *= -1.0f; - model.setTranslation(vec3(mousePosition, 0)); - glm::vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; - model.setScale(vec3(mouseSize, 1.0f)); - batch.setModelTransform(model); - bindCursorTexture(batch); - glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; - DependencyManager::get()->renderUnitQuad(batch, vec4(1)); - renderArgs->_context->render(batch); -} - - -static gpu::BufferPointer _hemiVertices; -static gpu::BufferPointer _hemiIndices; -static int _hemiIndexCount{ 0 }; - -glm::vec2 getPolarCoordinates(const PalmData& palm) { - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - auto avatarOrientation = myAvatar->getOrientation(); - auto eyePos = myAvatar->getDefaultEyePosition(); - glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm); - // Direction of the tip relative to the eye - glm::vec3 tipDirection = tip - eyePos; - // orient into avatar space - tipDirection = glm::inverse(avatarOrientation) * tipDirection; - // Normalize for trig functions - tipDirection = glm::normalize(tipDirection); - // Convert to polar coordinates - glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y)); - return polar; -} - -// Draws the FBO texture for Oculus rift. -void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { - if (_alpha == 0.0f || !_framebufferObject) { - return; - } - - renderArgs->_context->syncCache(); - - gpu::Batch batch; - batch.setPipeline(getDrawPipeline()); - batch._glDisable(GL_DEPTH_TEST); - batch._glDisable(GL_CULL_FACE); - batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - batch.setProjectionTransform(whichCamera.getProjection()); - batch.setViewTransform(Transform()); - - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - const quat& avatarOrientation = myAvatar->getOrientation(); - quat hmdOrientation = qApp->getCamera()->getHmdRotation(); - vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition(); - mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition); - batch.setModelTransform(Transform(overlayXfm)); - drawSphereSection(batch); - - - bindCursorTexture(batch); - auto geometryCache = DependencyManager::get(); - vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); - //Controller Pointers - for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { - PalmData& palm = myAvatar->getHand()->getPalms()[i]; - if (palm.isActive()) { - glm::vec2 polar = getPolarCoordinates(palm); - // Convert to quaternion - mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); - mat4 reticleXfm = overlayXfm * pointerXfm; - reticleXfm = glm::scale(reticleXfm, reticleScale); - batch.setModelTransform(reticleXfm); - // Render reticle at location - geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); - } - } - - //Mouse Pointer - if (_reticleActive[MOUSE]) { - glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), - _reticlePosition[MOUSE].y())); - mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); - mat4 reticleXfm = overlayXfm * pointerXfm; - reticleXfm = glm::scale(reticleXfm, reticleScale); - batch.setModelTransform(reticleXfm); - geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); - } - - renderArgs->_context->render(batch); -} - - -void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { - cursorPos *= qApp->getCanvasSize(); - const glm::vec2 projection = screenToSpherical(cursorPos); - // The overlay space orientation of the mouse coordinates - const glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); - // FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE. - // Now we need to account for the actual camera position relative to the overlay - glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT); - - - const glm::vec3& hmdPosition = qApp->getCamera()->getHmdPosition(); - const glm::quat& hmdOrientation = qApp->getCamera()->getHmdRotation(); - - // We need the RAW camera orientation and position, because this is what the overlay is - // rendered relative to - const glm::vec3 overlayPosition = qApp->getCamera()->getPosition() - hmdPosition; - const glm::quat overlayOrientation = qApp->getCamera()->getRotation() * glm::inverse(hmdOrientation); - - // Intersection UI overlay space - glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; - glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius; - intersectionWithUi += overlayPosition; - - // Intersection in world space - origin = overlayPosition + hmdPosition; - direction = glm::normalize(intersectionWithUi - origin); -} - -//Caculate the click location using one of the sixense controllers. Scale is not applied -QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { - QPoint rv; - auto canvasSize = qApp->getCanvasSize(); - if (qApp->isHMDMode()) { - glm::vec2 polar = getPolarCoordinates(*palm); - glm::vec2 point = sphericalToScreen(-polar); - rv.rx() = point.x; - rv.ry() = point.y; - } else { - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - glm::dmat4 projection; - qApp->getProjectionMatrix(&projection); - glm::quat invOrientation = glm::inverse(myAvatar->getOrientation()); - glm::vec3 eyePos = myAvatar->getDefaultEyePosition(); - glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); - glm::vec3 tipPos = invOrientation * (tip - eyePos); - - glm::vec4 clipSpacePos = glm::vec4(projection * glm::dvec4(tipPos, 1.0)); - glm::vec3 ndcSpacePos; - if (clipSpacePos.w != 0) { - ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w; - } - - rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * canvasSize.x); - rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * canvasSize.y); - } - return rv; -} - -//Finds the collision point of a world space ray -bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - - glm::quat inverseOrientation = glm::inverse(myAvatar->getOrientation()); - - glm::vec3 relativePosition = inverseOrientation * (position - myAvatar->getDefaultEyePosition()); - glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction); - - float t; - if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){ - result = position + direction * t; - return true; - } - - return false; -} - -//Renders optional pointers -void ApplicationOverlay::renderPointers() { - //glEnable(GL_TEXTURE_2D); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - //glActiveTexture(GL_TEXTURE0); - //bindCursorTexture(); - - 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; - renderControllerPointers(); - } - //glBindTexture(GL_TEXTURE_2D, 0); - //glDisable(GL_TEXTURE_2D); -} - -void ApplicationOverlay::renderControllerPointers() { - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - - //Static variables used for storing controller state - static quint64 pressedTime[NUMBER_OF_RETICLES] = { 0ULL, 0ULL, 0ULL }; - static bool isPressed[NUMBER_OF_RETICLES] = { false, false, false }; - static bool stateWhenPressed[NUMBER_OF_RETICLES] = { false, false, false }; - - const HandData* handData = DependencyManager::get()->getMyAvatar()->getHandData(); - - for (unsigned int palmIndex = 2; palmIndex < 4; palmIndex++) { - const int index = palmIndex - 1; - - const PalmData* palmData = NULL; - - if (palmIndex >= handData->getPalms().size()) { - return; - } - - if (handData->getPalms()[palmIndex].isActive()) { - palmData = &handData->getPalms()[palmIndex]; - } else { - continue; - } - - int controllerButtons = palmData->getControllerButtons(); - - //Check for if we should toggle or drag the magnification window - if (controllerButtons & BUTTON_3) { - if (isPressed[index] == false) { - //We are now dragging the window - isPressed[index] = true; - //set the pressed time in us - pressedTime[index] = usecTimestampNow(); - stateWhenPressed[index] = _magActive[index]; - } - } else if (isPressed[index]) { - isPressed[index] = false; - //If the button was only pressed for < 250 ms - //then disable it. - - const int MAX_BUTTON_PRESS_TIME = 250 * MSECS_TO_USECS; - if (usecTimestampNow() < pressedTime[index] + MAX_BUTTON_PRESS_TIME) { - _magActive[index] = !stateWhenPressed[index]; - } - } - - //if we have the oculus, we should make the cursor smaller since it will be - //magnified - if (qApp->isHMDMode()) { - - QPoint point = getPalmClickLocation(palmData); - - _reticlePosition[index] = point; - - //When button 2 is pressed we drag the mag window - if (isPressed[index]) { - _magActive[index] = true; - } - - // If oculus is enabled, we draw the crosshairs later - continue; - } - - auto canvasSize = qApp->getCanvasSize(); - int mouseX, mouseY; - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { - QPoint res = getPalmClickLocation(palmData); - mouseX = res.x(); - mouseY = res.y(); - } else { - // Get directon relative to avatar orientation - glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); - - // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + M_PI_2); - float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); - - // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); - - mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle); - mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle); - } - - //If the cursor is out of the screen then don't render it - if (mouseX < 0 || mouseX >= (int)canvasSize.x || mouseY < 0 || mouseY >= (int)canvasSize.y) { - _reticleActive[index] = false; - continue; - } - _reticleActive[index] = true; - - - const float reticleSize = 40.0f; - - mouseX -= reticleSize / 2.0f; - mouseY += reticleSize / 2.0f; - - - glm::vec2 topLeft(mouseX, mouseY); - glm::vec2 bottomRight(mouseX + reticleSize, mouseY - reticleSize); - glm::vec2 texCoordTopLeft(0.0f, 0.0f); - glm::vec2 texCoordBottomRight(1.0f, 1.0f); - - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, - glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f)); - - } -} - -//Renders a small magnification of the currently bound texture at the coordinates -void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) { - if (!_magnifier) { - return; - } - auto canvasSize = qApp->getCanvasSize(); - - const int widgetWidth = canvasSize.x; - const int widgetHeight = canvasSize.y; - - const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; - const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; - // Magnification Texture Coordinates - const float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; - const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; - const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; - const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; - - const float newHalfWidth = halfWidth * MAGNIFY_MULT; - const float newHalfHeight = halfHeight * MAGNIFY_MULT; - //Get yaw / pitch value for the corners - const glm::vec2 topLeftYawPitch = overlayToSpherical(glm::vec2(magPos.x - newHalfWidth, - magPos.y - newHalfHeight)); - const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth, - magPos.y + newHalfHeight)); - - const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y); - const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y); - const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y); - const glm::vec3 topRight = getPoint(bottomRightYawPitch.x, topLeftYawPitch.y); - - auto geometryCache = DependencyManager::get(); - - if (bottomLeft != _previousMagnifierBottomLeft || bottomRight != _previousMagnifierBottomRight - || topLeft != _previousMagnifierTopLeft || topRight != _previousMagnifierTopRight) { - QVector border; - border << topLeft; - border << bottomLeft; - border << bottomRight; - border << topRight; - border << topLeft; - geometryCache->updateVertices(_magnifierBorder, border, glm::vec4(1.0f, 0.0f, 0.0f, _alpha)); - - _previousMagnifierBottomLeft = bottomLeft; - _previousMagnifierBottomRight = bottomRight; - _previousMagnifierTopLeft = topLeft; - _previousMagnifierTopRight = topRight; - } - - glPushMatrix(); { - if (showBorder) { - glDisable(GL_TEXTURE_2D); - glLineWidth(1.0f); - //Outer Line - geometryCache->renderVertices(gpu::LINE_STRIP, _magnifierBorder); - glEnable(GL_TEXTURE_2D); - } - glm::vec4 magnifierColor = { 1.0f, 1.0f, 1.0f, _alpha }; - - DependencyManager::get()->renderQuad(bottomLeft, bottomRight, topRight, topLeft, - glm::vec2(magnifyULeft, magnifyVBottom), - glm::vec2(magnifyURight, magnifyVBottom), - glm::vec2(magnifyURight, magnifyVTop), - glm::vec2(magnifyULeft, magnifyVTop), - magnifierColor, _magnifierQuad); - - } glPopMatrix(); -} - -const int AUDIO_METER_GAP = 5; -const int MUTE_ICON_PADDING = 10; - void ApplicationOverlay::renderCameraToggle() { if (Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)) { return; @@ -915,101 +350,10 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { } } - -void ApplicationOverlay::buildHemiVertices( - const float fov, const float aspectRatio, const int slices, const int stacks) { - static float textureFOV = 0.0f, textureAspectRatio = 1.0f; - if (textureFOV == fov && textureAspectRatio == aspectRatio) { - return; - } - - textureFOV = fov; - textureAspectRatio = aspectRatio; - - auto geometryCache = DependencyManager::get(); - - _hemiVertices = gpu::BufferPointer(new gpu::Buffer()); - _hemiIndices = gpu::BufferPointer(new gpu::Buffer()); - - - if (fov >= PI) { - qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; - } - - //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm - - vec3 pos; - vec2 uv; - // Compute vertices positions and texture UV coordinate - // Create and write to buffer - for (int i = 0; i < stacks; i++) { - uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f - // abs(theta) <= fov / 2.0f - float pitch = -fov * (uv.y - 0.5f); - for (int j = 0; j < slices; j++) { - uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f - // abs(phi) <= fov * aspectRatio / 2.0f - float yaw = -fov * aspectRatio * (uv.x - 0.5f); - pos = getPoint(yaw, pitch); - static const vec4 color(1); - _hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos); - _hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv); - _hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color); - } - } - - // Compute number of indices needed - static const int VERTEX_PER_TRANGLE = 3; - static const int TRIANGLE_PER_RECTANGLE = 2; - int numberOfRectangles = (slices - 1) * (stacks - 1); - _hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; - - // Compute indices order - std::vector indices; - for (int i = 0; i < stacks - 1; i++) { - for (int j = 0; j < slices - 1; j++) { - GLushort bottomLeftIndex = i * slices + j; - GLushort bottomRightIndex = bottomLeftIndex + 1; - GLushort topLeftIndex = bottomLeftIndex + slices; - GLushort topRightIndex = topLeftIndex + 1; - // FIXME make a z-order curve for better vertex cache locality - indices.push_back(topLeftIndex); - indices.push_back(bottomLeftIndex); - indices.push_back(topRightIndex); - - indices.push_back(topRightIndex); - indices.push_back(bottomLeftIndex); - indices.push_back(bottomRightIndex); - } - } - _hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]); -} - - -void ApplicationOverlay::drawSphereSection(gpu::Batch& batch) { - buildHemiVertices(_textureFov, _textureAspectRatio, 80, 80); - static const int VERTEX_DATA_SLOT = 0; - static const int TEXTURE_DATA_SLOT = 1; - static const int COLOR_DATA_SLOT = 2; - gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone - streamFormat->setAttribute(gpu::Stream::POSITION, VERTEX_DATA_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - streamFormat->setAttribute(gpu::Stream::TEXCOORD, TEXTURE_DATA_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_DATA_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA)); - batch.setInputFormat(streamFormat); - - static const int VERTEX_STRIDE = sizeof(vec3) + sizeof(vec2) + sizeof(vec4); - gpu::BufferView posView(_hemiVertices, 0, _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); - gpu::BufferView uvView(_hemiVertices, sizeof(vec3), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element); - gpu::BufferView colView(_hemiVertices, sizeof(vec3) + sizeof(vec2), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); - batch.setInputBuffer(VERTEX_DATA_SLOT, posView); - batch.setInputBuffer(TEXTURE_DATA_SLOT, uvView); - batch.setInputBuffer(COLOR_DATA_SLOT, colView); - batch.setIndexBuffer(gpu::UINT16, _hemiIndices, 0); - batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount); -} - - GLuint ApplicationOverlay::getOverlayTexture() { + if (!_framebufferObject) { + return 0; + } return _framebufferObject->texture(); } @@ -1036,71 +380,3 @@ void ApplicationOverlay::buildFramebufferObject() { glBindTexture(GL_TEXTURE_2D, 0); } -glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { - glm::vec2 result; - // Compute yaw - glm::vec3 normalProjection = glm::normalize(glm::vec3(direction.x, 0.0f, direction.z)); - result.x = glm::acos(glm::dot(IDENTITY_FRONT, normalProjection)); - if (glm::dot(IDENTITY_RIGHT, normalProjection) > 0.0f) { - result.x = -glm::abs(result.x); - } else { - result.x = glm::abs(result.x); - } - // Compute pitch - result.y = angleBetween(IDENTITY_UP, direction) - PI_OVER_TWO; - - return result; -} - -glm::vec3 ApplicationOverlay::sphericalToDirection(const glm::vec2& sphericalPos) { - glm::quat rotation(glm::vec3(sphericalPos.y, sphericalPos.x, 0.0f)); - return rotation * IDENTITY_FRONT; -} - -glm::vec2 ApplicationOverlay::screenToSpherical(const glm::vec2& screenPos) { - auto screenSize = qApp->getCanvasSize(); - glm::vec2 result; - result.x = -(screenPos.x / screenSize.x - 0.5f); - result.y = (screenPos.y / screenSize.y - 0.5f); - result.x *= MOUSE_YAW_RANGE; - result.y *= MOUSE_PITCH_RANGE; - - return result; -} - -glm::vec2 ApplicationOverlay::sphericalToScreen(const glm::vec2& sphericalPos) { - glm::vec2 result = sphericalPos; - result.x *= -1.0; - result /= MOUSE_RANGE; - result += 0.5f; - result *= qApp->getCanvasSize(); - return result; -} - -glm::vec2 ApplicationOverlay::sphericalToOverlay(const glm::vec2& sphericalPos) const { - glm::vec2 result = sphericalPos; - result.x *= -1.0; - result /= _textureFov; - result.x /= _textureAspectRatio; - result += 0.5f; - result *= qApp->getCanvasSize(); - return result; -} - -glm::vec2 ApplicationOverlay::overlayToSpherical(const glm::vec2& overlayPos) const { - glm::vec2 result = overlayPos; - result /= qApp->getCanvasSize(); - result -= 0.5f; - result *= _textureFov; - result.x *= _textureAspectRatio; - result.x *= -1.0f; - return result; -} - -glm::vec2 ApplicationOverlay::screenToOverlay(const glm::vec2& screenPos) const { - return sphericalToOverlay(screenToSpherical(screenPos)); -} - -glm::vec2 ApplicationOverlay::overlayToScreen(const glm::vec2& overlayPos) const { - return sphericalToScreen(overlayToSpherical(overlayPos)); -} diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index e8b5a77b1f..dc21fba194 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -13,16 +13,8 @@ #define hifi_ApplicationOverlay_h #include -class Camera; -class Overlays; class QOpenGLFramebufferObject; -const float MAGNIFY_WIDTH = 220.0f; -const float MAGNIFY_HEIGHT = 100.0f; -const float MAGNIFY_MULT = 2.0f; - -const float DEFAULT_HMD_UI_ANGULAR_SIZE = 72.0f; - // Handles the drawing of the overlays to the screen // TODO, move divide up the rendering, displaying and input handling // facilities of this class @@ -33,83 +25,19 @@ public: ~ApplicationOverlay(); void renderOverlay(RenderArgs* renderArgs); - void displayOverlayTexture(RenderArgs* renderArgs); - void displayOverlayTextureStereo(RenderArgs* renderArgs, Camera& whichCamera, float aspectRatio, float fov); - void displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera); - - QPoint getPalmClickLocation(const PalmData *palm) const; - bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; - - bool hasMagnifier() const { return _magnifier; } - void toggleMagnifier() { _magnifier = !_magnifier; } - - float getHmdUIAngularSize() const { return _hmdUIAngularSize; } - void setHmdUIAngularSize(float hmdUIAngularSize) { _hmdUIAngularSize = hmdUIAngularSize; } - - // Converter from one frame of reference to another. - // Frame of reference: - // Direction: Ray that represents the spherical values - // Screen: Position on the screen (x,y) - // Spherical: Pitch and yaw that gives the position on the sphere we project on (yaw,pitch) - // Overlay: Position on the overlay (x,y) - // (x,y) in Overlay are similar than (x,y) in Screen except they can be outside of the bound of te screen. - // This allows for picking outside of the screen projection in 3D. - glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; - glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; - glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; - glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; - void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; GLuint getOverlayTexture(); - static glm::vec2 directionToSpherical(const glm::vec3 & direction); - static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); - static glm::vec2 screenToSpherical(const glm::vec2 & screenPos); - static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); - private: - void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); - void drawSphereSection(gpu::Batch& batch); - float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; - QOpenGLFramebufferObject* _framebufferObject; - void renderPointers(); - void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder); - - void renderControllerPointers(); - void renderPointersOculus(); - void renderAudioMeter(); void renderCameraToggle(); void renderStatsAndLogs(); void renderDomainConnectionStatusBorder(); - void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); - void buildFramebufferObject(); - - float _textureFov; - float _textureAspectRatio; - int _hemiVerticesID{ GeometryCache::UNKNOWN_ID }; - - - enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES }; - bool _reticleActive[NUMBER_OF_RETICLES]; - QPoint _reticlePosition[NUMBER_OF_RETICLES]; - bool _magActive[NUMBER_OF_RETICLES]; - float _magSizeMult[NUMBER_OF_RETICLES]; - quint64 _lastMouseMove; - bool _magnifier; - float _alpha = 1.0f; - float _oculusUIRadius; float _trailingAudioLoudness; - - - QMap _cursors; - - GLuint _newUiTexture{ 0 }; + GLuint _uiTexture{ 0 }; - int _reticleQuad; - int _magnifierQuad; int _audioRedQuad; int _audioGreenQuad; int _audioBlueQuad; @@ -119,15 +47,7 @@ private: int _previousBorderWidth; int _previousBorderHeight; - glm::vec3 _previousMagnifierBottomLeft; - glm::vec3 _previousMagnifierBottomRight; - glm::vec3 _previousMagnifierTopLeft; - glm::vec3 _previousMagnifierTopRight; - - gpu::PipelinePointer _standardDrawPipeline; - - gpu::PipelinePointer getDrawPipeline(); - + QOpenGLFramebufferObject* _framebufferObject; }; #endif // hifi_ApplicationOverlay_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index febd6f90bf..eca250a428 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -175,7 +175,7 @@ void PreferencesDialog::loadPreferences() { ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond()); - ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getHmdUIAngularSize()); + ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationCompositor().getHmdUIAngularSize()); SixenseManager& sixense = SixenseManager::getInstance(); ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed()); @@ -239,7 +239,7 @@ void PreferencesDialog::savePreferences() { qApp->setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value()); - qApp->getApplicationOverlay().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value()); + qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value()); SixenseManager& sixense = SixenseManager::getInstance(); sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 6e579ed4c4..1bb81319e4 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -258,7 +258,7 @@ void Overlays::deleteOverlay(unsigned int id) { unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { glm::vec2 pointCopy = point; if (qApp->isHMDMode()) { - pointCopy = qApp->getApplicationOverlay().screenToOverlay(point); + pointCopy = qApp->getApplicationCompositor().screenToOverlay(point); } QReadLocker lock(&_lock); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 3066fd4890..98067e1b81 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -28,6 +28,9 @@ #include "RenderUtilsLogging.h" #include "GeometryCache.h" +#include "standardTransformPNTC_vert.h" +#include "standardDrawTexture_frag.h" + //#define WANT_DEBUG const int GeometryCache::UNKNOWN_ID = -1; @@ -1817,6 +1820,23 @@ QSharedPointer GeometryCache::createResource(const QUrl& url, const QS return geometry.staticCast(); } +void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch) { + if (!_standardDrawPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + gpu::Shader::makeProgram((*program)); + + auto state = gpu::StatePointer(new gpu::State()); + + // enable decal blend + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); + } + batch.setPipeline(_standardDrawPipeline); +} + const float NetworkGeometry::NO_HYSTERESIS = -1.0f; NetworkGeometry::NetworkGeometry(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, @@ -2385,3 +2405,4 @@ int NetworkMesh::getTranslucentPartCount(const FBXMesh& fbxMesh) const { } return count; } + diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 76e03f8669..2155586f4b 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -252,6 +252,9 @@ public: /// \param delayLoad if true, don't load the geometry immediately; wait until load is first requested QSharedPointer getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); + /// Set a batch to the simple pipeline, returning the previous pipeline + void useSimpleDrawPipeline(gpu::Batch& batch); + protected: virtual QSharedPointer createResource(const QUrl& url, @@ -269,6 +272,7 @@ private: int vertexSize; }; + gpu::PipelinePointer _standardDrawPipeline; QHash _cubeVerticies; QHash _cubeColors; gpu::BufferPointer _wireCubeIndexBuffer; @@ -276,7 +280,7 @@ private: QHash _solidCubeVertices; QHash _solidCubeColors; gpu::BufferPointer _solidCubeIndexBuffer; - + class BatchItemDetails { public: static int population; From ba13b7820c751bf9c18b06f8c62974cd47010227 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 16 Jun 2015 09:58:03 -0700 Subject: [PATCH 005/121] Working on overlay refactor --- interface/src/Application.cpp | 249 +++++++++-------- interface/src/Application.h | 37 +-- interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/ui/ApplicationCompositor.cpp | 205 ++++++++++++-- interface/src/ui/ApplicationCompositor.h | 30 +- interface/src/ui/ApplicationOverlay.cpp | 288 ++++++++++++++------ interface/src/ui/ApplicationOverlay.h | 26 +- libraries/entities/src/EntityItemID.h | 2 +- libraries/render-utils/src/TextRenderer.cpp | 21 ++ libraries/shared/src/GLMHelpers.h | 15 + 10 files changed, 590 insertions(+), 287 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b540751c8d..6270c8f597 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -321,15 +321,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _viewFrustum(), _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), - _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _firstRun("firstRun", true), _previousScriptLocation("LastScriptLocation"), _scriptsLocationHandle("scriptsLocation"), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), _viewTransform(), - _scaleMirror(1.0f), - _rotateMirror(0.0f), - _raiseMirror(0.0f), _cursorVisible(true), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), @@ -905,11 +901,13 @@ void Application::paintGL() { } } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { +#if 0 _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); +#endif } // Update camera position @@ -951,14 +949,13 @@ void Application::paintGL() { _compositor.displayOverlayTexture(&renderArgs); glPopMatrix(); - renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { - _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderRearViewMirror(&renderArgs, _mirrorViewRect); - } - - renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; + //renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; + //if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { + // _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); + //} else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + // renderRearViewMirror(&renderArgs, _mirrorViewRect); + //} + //renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; auto finalFbo = DependencyManager::get()->render(&renderArgs); @@ -1050,10 +1047,12 @@ void Application::resizeGL() { offscreenUi->resize(_glWidget->size()); _glWidget->makeCurrent(); +#if 0 // update Stats width // let's set horizontal offset to give stats some margin to mirror int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset); +#endif } void Application::updateProjectionMatrix() { @@ -1269,37 +1268,37 @@ void Application::keyPressEvent(QKeyEvent* event) { Menu::getInstance()->triggerOption(MenuOption::Chat); break; - case Qt::Key_Up: - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - if (!isShifted) { - _scaleMirror *= 0.95f; - } else { - _raiseMirror += 0.05f; - } - } - break; + //case Qt::Key_Up: + // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + // if (!isShifted) { + // _scaleMirror *= 0.95f; + // } else { + // _raiseMirror += 0.05f; + // } + // } + // break; - case Qt::Key_Down: - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - if (!isShifted) { - _scaleMirror *= 1.05f; - } else { - _raiseMirror -= 0.05f; - } - } - break; + //case Qt::Key_Down: + // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + // if (!isShifted) { + // _scaleMirror *= 1.05f; + // } else { + // _raiseMirror -= 0.05f; + // } + // } + // break; - case Qt::Key_Left: - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - _rotateMirror += PI / 20.0f; - } - break; + //case Qt::Key_Left: + // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + // _rotateMirror += PI / 20.0f; + // } + // break; - case Qt::Key_Right: - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - _rotateMirror -= PI / 20.0f; - } - break; + //case Qt::Key_Right: + // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + // _rotateMirror -= PI / 20.0f; + // } + // break; #if 0 case Qt::Key_I: @@ -1562,11 +1561,12 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { // stop propagation return; } - +#if 0 if (_rearMirrorTools->mousePressEvent(getMouseX(), getMouseY())) { // stop propagation return; } +#endif } // nobody handled this - make it an action event on the _window object @@ -1617,12 +1617,14 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { if (event->button() == Qt::LeftButton) { _mousePressed = false; +#if 0 if (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && mouseOnScreen()) { // let's set horizontal offset to give stats some margin to mirror int horizontalOffset = MIRROR_VIEW_WIDTH; Stats::getInstance()->checkClick(getMouseX(), getMouseY(), getMouseDragStartedX(), getMouseDragStartedY(), horizontalOffset); } +#endif // fire an action end event HFActionEvent actionEvent(HFActionEvent::endType(), @@ -2137,7 +2139,9 @@ void Application::init() { DependencyManager::get()->init(); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); +#if 0 _mirrorCamera.setMode(CAMERA_MODE_MIRROR); +#endif OculusManager::connect(); if (OculusManager::isConnected()) { @@ -2209,12 +2213,13 @@ void Application::init() { _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); +#if 0 _rearMirrorTools = new RearMirrorTools(_mirrorViewRect); - connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); +#endif // initialize the GlowEffect with our widget bool glow = Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect); @@ -3115,6 +3120,7 @@ PickRay Application::computePickRay(float x, float y) const { return result; } +#if 0 QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); @@ -3133,15 +3139,14 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); - QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindFramebuffer(GL_FRAMEBUFFER, 0); - return image; } +#endif ViewFrustum* Application::getViewFrustum() { #ifdef DEBUG @@ -3331,9 +3336,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se // flip x if in mirror mode (also requires reversing winding order for backface culling) if (theCamera.getMode() == CAMERA_MODE_MIRROR) { - glScalef(-1.0f, 1.0f, 1.0f); - glFrontFace(GL_CW); - + //glScalef(-1.0f, 1.0f, 1.0f); + //glFrontFace(GL_CW); } else { glFrontFace(GL_CCW); } @@ -3356,7 +3360,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se viewTransform.setTranslation(theCamera.getPosition()); viewTransform.setRotation(rotation); if (theCamera.getMode() == CAMERA_MODE_MIRROR) { - viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); + //viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); } if (renderArgs->_renderSide != RenderArgs::MONO) { glm::mat4 invView = glm::inverse(_untranslatedViewMatrix); @@ -3623,78 +3627,83 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { return screenPoint; } -void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { - // Grab current viewport to reset it at the end - int viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - float aspect = (float)region.width() / region.height(); - float fov = MIRROR_FIELD_OF_VIEW; - - // bool eyeRelativeCamera = false; - if (billboard) { - fov = BILLBOARD_FIELD_OF_VIEW; // degees - _mirrorCamera.setPosition(_myAvatar->getPosition() + - _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); - - } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { - _mirrorCamera.setPosition(_myAvatar->getChestPosition() + - _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); - - } else { // HEAD zoom level - // FIXME note that the positioing of the camera relative to the avatar can suffer limited - // precision as the user's position moves further away from the origin. Thus at - // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways - // wildly as you rotate your avatar because the floating point values are becoming - // larger, squeezing out the available digits of precision you have available at the - // human scale for camera positioning. - - // Previously there was a hack to correct this using the mechanism of repositioning - // the avatar at the origin of the world for the purposes of rendering the mirror, - // but it resulted in failing to render the avatar's head model in the mirror view - // when in first person mode. Presumably this was because of some missed culling logic - // that was not accounted for in the hack. - - // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further - // investigated in order to adapt the technique while fixing the head rendering issue, - // but the complexity of the hack suggests that a better approach - _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); - } - _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); - _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); - - // set the bounds of rear mirror view - if (billboard) { - QSize size = DependencyManager::get()->getFrameBufferSize(); - glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - } else { - // if not rendering the billboard, the region is in device independent coordinates; must convert to device - QSize size = DependencyManager::get()->getFrameBufferSize(); - float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); - int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; - glViewport(x, size.height() - y - height, width, height); - glScissor(x, size.height() - y - height, width, height); - } - bool updateViewFrustum = false; - updateProjectionMatrix(_mirrorCamera, updateViewFrustum); - glEnable(GL_SCISSOR_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // render rear mirror view - glPushMatrix(); - displaySide(renderArgs, _mirrorCamera, true, billboard); - glPopMatrix(); - - if (!billboard) { - _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); - } - - // reset Viewport and projection matrix - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - glDisable(GL_SCISSOR_TEST); - updateProjectionMatrix(_myCamera, updateViewFrustum); -} +//void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { +// // Grab current viewport to reset it at the end +// int viewport[4]; +// glGetIntegerv(GL_VIEWPORT, viewport); +// float aspect = (float)region.width() / region.height(); +// float fov = MIRROR_FIELD_OF_VIEW; +// +// // bool eyeRelativeCamera = false; +// if (billboard) { +// fov = BILLBOARD_FIELD_OF_VIEW; // degees +// _mirrorCamera.setPosition(_myAvatar->getPosition() + +// _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); +// +// } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { +// _mirrorCamera.setPosition(_myAvatar->getChestPosition() + +// _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); +// +// } else { // HEAD zoom level +// // FIXME note that the positioing of the camera relative to the avatar can suffer limited +// // precision as the user's position moves further away from the origin. Thus at +// // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways +// // wildly as you rotate your avatar because the floating point values are becoming +// // larger, squeezing out the available digits of precision you have available at the +// // human scale for camera positioning. +// +// // Previously there was a hack to correct this using the mechanism of repositioning +// // the avatar at the origin of the world for the purposes of rendering the mirror, +// // but it resulted in failing to render the avatar's head model in the mirror view +// // when in first person mode. Presumably this was because of some missed culling logic +// // that was not accounted for in the hack. +// +// // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further +// // investigated in order to adapt the technique while fixing the head rendering issue, +// // but the complexity of the hack suggests that a better approach +// _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + +// _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); +// } +// _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); +// _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); +// +// // set the bounds of rear mirror view +// if (billboard) { +// QSize size = DependencyManager::get()->getFrameBufferSize(); +// glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); +// glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); +// } else { +// // if not rendering the billboard, the region is in device independent coordinates; must convert to device +// QSize size = DependencyManager::get()->getFrameBufferSize(); +// float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); +// int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; +// glViewport(x, size.height() - y - height, width, height); +// glScissor(x, size.height() - y - height, width, height); +// } +// bool updateViewFrustum = false; +// updateProjectionMatrix(_mirrorCamera, updateViewFrustum); +// glEnable(GL_SCISSOR_TEST); +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +// +// // render rear mirror view +// glMatrixMode(GL_MODELVIEW); +// glPushMatrix(); +// glLoadIdentity(); +// glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); +// renderArgs->_context->syncCache(); +// displaySide(renderArgs, _mirrorCamera, true, billboard); +// glMatrixMode(GL_MODELVIEW); +// glPopMatrix(); +// +// if (!billboard) { +// _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); +// } +// +// // reset Viewport and projection matrix +// glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); +// glDisable(GL_SCISSOR_TEST); +// updateProjectionMatrix(_myCamera, updateViewFrustum); +//} void Application::resetSensors() { DependencyManager::get()->reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index bb5c50687a..6f30bbf560 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -109,15 +109,6 @@ static const QString FST_EXTENSION = ".fst"; static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees static const float BILLBOARD_DISTANCE = 5.56f; // meters -static const int MIRROR_VIEW_TOP_PADDING = 5; -static const int MIRROR_VIEW_LEFT_PADDING = 10; -static const int MIRROR_VIEW_WIDTH = 265; -static const int MIRROR_VIEW_HEIGHT = 215; -static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; -static const float MIRROR_REARVIEW_DISTANCE = 0.722f; -static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f; -static const float MIRROR_FIELD_OF_VIEW = 30.0f; - static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS_PER_SECOND; static const QString INFO_HELP_PATH = "html/interface-welcome.html"; @@ -482,6 +473,7 @@ private slots: void faceTrackerMuteToggled(); void setCursorVisible(bool visible); + //void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false); private: void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size); @@ -516,7 +508,6 @@ private: glm::vec3 getSunDirection(); void updateShadowMap(RenderArgs* renderArgs); - void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false); void setMenuShortcutsEnabled(bool enabled); static void attachNewHeadToNode(Node *newNode); @@ -564,31 +555,21 @@ private: OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers - KeyboardMouseDevice _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad - - UserInputMapper _userInputMapper; // User input mapper allowing to mapp different real devices to the action channels that the application has to offer - - MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - - Camera _myCamera; // My view onto the world - Camera _mirrorCamera; // Cammera for mirror view - QRect _mirrorViewRect; - RearMirrorTools* _rearMirrorTools; + KeyboardMouseDevice _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad + UserInputMapper _userInputMapper; // User input mapper allowing to mapp different real devices to the action channels that the application has to offer + MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) + Camera _myCamera; // My view onto the world - Setting::Handle _firstRun; - Setting::Handle _previousScriptLocation; - Setting::Handle _scriptsLocationHandle; - Setting::Handle _fieldOfView; + Setting::Handle _firstRun; + Setting::Handle _previousScriptLocation; + Setting::Handle _scriptsLocationHandle; + Setting::Handle _fieldOfView; Transform _viewTransform; glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; glm::mat4 _projectionMatrix; - float _scaleMirror; - float _rotateMirror; - float _raiseMirror; - static const int CASCADED_SHADOW_MATRIX_COUNT = 4; glm::mat4 _shadowMatrices[CASCADED_SHADOW_MATRIX_COUNT]; glm::vec3 _shadowDistances; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2b3997077b..e86fd26705 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1458,9 +1458,10 @@ void MyAvatar::maybeUpdateBillboard() { return; } } + /* gpu::Context context(new gpu::GLBackend()); RenderArgs renderArgs(&context); - QImage image = Application::getInstance()->renderAvatarBillboard(&renderArgs); + QImage image = qApp->renderAvatarBillboard(&renderArgs); _billboard.clear(); QBuffer buffer(&_billboard); buffer.open(QIODevice::WriteOnly); @@ -1468,6 +1469,7 @@ void MyAvatar::maybeUpdateBillboard() { _billboardValid = true; sendBillboardPacket(); + */ } void MyAvatar::increaseSize() { diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index f6a79f2bc2..ab5014dfaa 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -41,6 +41,7 @@ static const float MAG_SPEED = 0.08f; static const quint64 MSECS_TO_USECS = 1000ULL; +static const quint64 TOOLTIP_DELAY = 2000000ULL; static const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; static const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; @@ -57,6 +58,8 @@ static const glm::vec2 MOUSE_RANGE(MOUSE_YAW_RANGE, MOUSE_PITCH_RANGE); static gpu::BufferPointer _hemiVertices; static gpu::BufferPointer _hemiIndices; static int _hemiIndexCount{ 0 }; +EntityItemID ApplicationCompositor::_noItemId; + // Return a point's cartesian coordinates on a sphere from pitch and yaw glm::vec3 getPoint(float yaw, float pitch) { @@ -132,11 +135,32 @@ ApplicationCompositor::ApplicationCompositor() { _reticleQuad = geometryCache->allocateID(); _magnifierQuad = geometryCache->allocateID(); - _audioRedQuad = geometryCache->allocateID(); - _audioGreenQuad = geometryCache->allocateID(); - _audioBlueQuad = geometryCache->allocateID(); - _domainStatusBorder = geometryCache->allocateID(); _magnifierBorder = geometryCache->allocateID(); + + auto entityScriptingInterface = DependencyManager::get(); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { + if (_hoverItemId != entityItemID) { + _hoverItemId = entityItemID; + _hoverItemEnterUsecs = usecTimestampNow(); + auto properties = entityScriptingInterface->getEntityProperties(_hoverItemId); + _hoverItemHref = properties.getHref(); + auto cursor = Cursor::Manager::instance().getCursor(); + if (!_hoverItemHref.isEmpty()) { + cursor->setIcon(Cursor::Icon::LINK); + } else { + cursor->setIcon(Cursor::Icon::DEFAULT); + } + } + }); + + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const MouseEvent& event) { + if (_hoverItemId == entityItemID) { + _hoverItemId = _noItemId; + _hoverItemHref.clear(); + auto cursor = Cursor::Manager::instance().getCursor(); + cursor->setIcon(Cursor::Icon::DEFAULT); + } + }); } ApplicationCompositor::~ApplicationCompositor() { @@ -154,13 +178,26 @@ void ApplicationCompositor::bindCursorTexture(gpu::Batch& batch, uint8_t cursorI batch.setUniformTexture(0, _cursors[iconId]); } - // Draws the FBO texture for the screen void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { if (_alpha == 0.0f) { return; } + vec2 canvasSize = qApp->getCanvasSize(); + + _textureAspectRatio = aspect(canvasSize); + + if (_hoverItemId != _noItemId) { + quint64 hoverDuration = usecTimestampNow() - _hoverItemEnterUsecs; + if (!_hoverItemHref.isEmpty() && hoverDuration > TOOLTIP_DELAY) { + // TODO Enable and position the tooltip + } + } + + //Handle fading and deactivation/activation of UI + gpu::Batch batch; + GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); if (!texture) { return; @@ -168,7 +205,6 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { renderArgs->_context->syncCache(); auto geometryCache = DependencyManager::get(); - gpu::Batch batch; geometryCache->useSimpleDrawPipeline(batch); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); @@ -179,17 +215,12 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); // Doesn't actually render - renderPointers(); - + renderPointers(batch); //draw the mouse pointer - vec2 canvasSize = qApp->getCanvasSize(); - // Get the mouse coordinates and convert to NDC [-1, 1] - vec2 mousePosition = vec2(qApp->getMouse()); - mousePosition /= canvasSize; - mousePosition *= 2.0f; - mousePosition -= 1.0f; + vec2 mousePosition = toNormalizedDeviceScale(vec2(qApp->getMouse()), canvasSize); + // Invert the Y axis mousePosition.y *= -1.0f; Transform model; @@ -250,7 +281,7 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int drawSphereSection(batch); // Doesn't actually render - renderPointers(); + renderPointers(batch); vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); bindCursorTexture(batch); @@ -360,7 +391,7 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi } //Renders optional pointers -void ApplicationCompositor::renderPointers() { +void ApplicationCompositor::renderPointers(gpu::Batch& batch) { //glEnable(GL_TEXTURE_2D); //glEnable(GL_BLEND); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -374,7 +405,7 @@ void ApplicationCompositor::renderPointers() { _lastMouseMove = usecTimestampNow(); } QPoint position = QPoint(qApp->getTrueMouseX(), qApp->getTrueMouseY()); - + static const int MAX_IDLE_TIME = 3; if (_reticlePosition[MOUSE] != position) { _lastMouseMove = usecTimestampNow(); @@ -383,11 +414,11 @@ void ApplicationCompositor::renderPointers() { //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)) { + 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); @@ -398,7 +429,7 @@ void ApplicationCompositor::renderPointers() { qDebug() << "No collision point"; } } - + _reticlePosition[MOUSE] = position; _reticleActive[MOUSE] = true; _magActive[MOUSE] = _magnifier; @@ -409,13 +440,14 @@ void ApplicationCompositor::renderPointers() { //only render controller pointer if we aren't already rendering a mouse pointer _reticleActive[MOUSE] = false; _magActive[MOUSE] = false; - renderControllerPointers(); + renderControllerPointers(batch); } //glBindTexture(GL_TEXTURE_2D, 0); //glDisable(GL_TEXTURE_2D); } + -void ApplicationCompositor::renderControllerPointers() { +void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); //Static variables used for storing controller state @@ -526,7 +558,7 @@ void ApplicationCompositor::renderControllerPointers() { } //Renders a small magnification of the currently bound texture at the coordinates -void ApplicationCompositor::renderMagnifier(const glm::vec2& magPos, float sizeMult, bool showBorder) { +void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2& magPos, float sizeMult, bool showBorder) { if (!_magnifier) { return; } @@ -755,3 +787,128 @@ glm::vec2 ApplicationCompositor::screenToOverlay(const glm::vec2& screenPos) con glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) const { return sphericalToScreen(overlayToSpherical(overlayPos)); } + +#if 0 + +gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() { + if (!_standardDrawPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + gpu::Shader::makeProgram((*program)); + + auto state = gpu::StatePointer(new gpu::State()); + + // enable decal blend + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); + } + + return _standardDrawPipeline; +} + + +// Draws the FBO texture for the screen +void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { + if (_alpha == 0.0f) { + return; + } + + renderArgs->_context->syncCache(); + + gpu::Batch batch; + Transform model; + //DependencyManager::get()->bindSimpleProgram(batch, true); + batch.setPipeline(getDrawPipeline()); + batch.setModelTransform(Transform()); + batch.setProjectionTransform(mat4()); + batch.setViewTransform(model); + batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + DependencyManager::get()->renderUnitQuad(batch, vec4(vec3(1), _alpha)); + + //draw the mouse pointer + glm::vec2 canvasSize = qApp->getCanvasSize(); + + // Get the mouse coordinates and convert to NDC [-1, 1] + vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); + mousePosition /= canvasSize; + mousePosition *= 2.0f; + mousePosition -= 1.0f; + mousePosition.y *= -1.0f; + model.setTranslation(vec3(mousePosition, 0)); + glm::vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; + model.setScale(vec3(mouseSize, 1.0f)); + batch.setModelTransform(model); + bindCursorTexture(batch); + glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; + DependencyManager::get()->renderUnitQuad(batch, vec4(1)); + renderArgs->_context->render(batch); +} + + + +// Draws the FBO texture for Oculus rift. +void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { + if (_alpha == 0.0f) { + return; + } + + renderArgs->_context->syncCache(); + + gpu::Batch batch; + batch.setPipeline(getDrawPipeline()); + batch._glDisable(GL_DEPTH_TEST); + batch._glDisable(GL_CULL_FACE); + batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + batch.setProjectionTransform(whichCamera.getProjection()); + batch.setViewTransform(Transform()); + + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + const quat& avatarOrientation = myAvatar->getOrientation(); + quat hmdOrientation = qApp->getCamera()->getHmdRotation(); + vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition(); + mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition); + batch.setModelTransform(Transform(overlayXfm)); + drawSphereSection(batch); + + + bindCursorTexture(batch); + auto geometryCache = DependencyManager::get(); + vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); + //Controller Pointers + for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + glm::vec2 polar = getPolarCoordinates(palm); + // Convert to quaternion + mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + // Render reticle at location + geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); + } + } + + //Mouse Pointer + if (_reticleActive[MOUSE]) { + glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), + _reticlePosition[MOUSE].y())); + mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + mat4 reticleXfm = overlayXfm * pointerXfm; + reticleXfm = glm::scale(reticleXfm, reticleScale); + batch.setModelTransform(reticleXfm); + geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); + } + + renderArgs->_context->render(batch); +} + + + +#endif diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 61bbafaba7..5145e14006 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -6,12 +6,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_ApplicationOverlayCompositor_h -#define hifi_ApplicationOverlayCompositor_h +#ifndef hifi_ApplicationCompositor_h +#define hifi_ApplicationCompositor_h #include #include +#include #include #include #include @@ -61,7 +62,7 @@ public: glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; - GLuint getOverlayTexture(); + GLuint getOverlayTexture() const; static glm::vec2 directionToSpherical(const glm::vec3 & direction); static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); @@ -74,12 +75,17 @@ private: void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); void drawSphereSection(gpu::Batch& batch); - void renderPointers(); - void renderMagnifier(const glm::vec2& magPos, float sizeMult, bool showBorder); - - void renderControllerPointers(); - void renderPointersOculus(); - + void renderPointers(gpu::Batch& batch); + void renderMagnifier(gpu::Batch& batch, const glm::vec2& magPos, float sizeMult, bool showBorder); + void renderControllerPointers(gpu::Batch& batch); + void renderPointersOculus(gpu::Batch& batch); + + // Support for hovering and tooltips + static EntityItemID _noItemId; + EntityItemID _hoverItemId{ _noItemId }; + QString _hoverItemHref; + quint64 _hoverItemEnterUsecs{ 0 }; + float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; float _textureFov{ glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE) }; float _textureAspectRatio{ 1.0f }; @@ -100,10 +106,6 @@ private: int _reticleQuad; int _magnifierQuad; - int _audioRedQuad; - int _audioGreenQuad; - int _audioBlueQuad; - int _domainStatusBorder; int _magnifierBorder; int _previousBorderWidth{ -1 }; @@ -115,4 +117,4 @@ private: glm::vec3 _previousMagnifierTopRight; }; -#endif // hifi_ApplicationOverlayCompositor_h +#endif // hifi_ApplicationCompositor_h diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ea56eed73d..989cec4345 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -39,15 +39,21 @@ const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; const int AUDIO_METER_GAP = 5; const int MUTE_ICON_PADDING = 10; -const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; +const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; +static const int MIRROR_VIEW_TOP_PADDING = 5; +static const int MIRROR_VIEW_LEFT_PADDING = 10; +static const int MIRROR_VIEW_WIDTH = 265; +static const int MIRROR_VIEW_HEIGHT = 215; +static const int STATS_HORIZONTAL_OFFSET = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; +static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; +static const float MIRROR_REARVIEW_DISTANCE = 0.722f; +static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f; +static const float MIRROR_FIELD_OF_VIEW = 30.0f; + ApplicationOverlay::ApplicationOverlay() : - _alpha(1.0f), - _trailingAudioLoudness(0.0f), - _previousBorderWidth(-1), - _previousBorderHeight(-1), - _framebufferObject(nullptr) + _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)) { auto geometryCache = DependencyManager::get(); _audioRedQuad = geometryCache->allocateID(); @@ -82,67 +88,70 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { Overlays& overlays = qApp->getOverlays(); glm::vec2 size = qApp->getCanvasSize(); // TODO Handle fading and deactivation/activation of UI - - // Render 2D overlay + + + // TODO First render the mirror to the mirror FBO + + + // Now render the overlay components together into a single texture + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + static const float NEAR_CLIP = -10000; + static const float FAR_CLIP = 10000; + batch._glDisable(GL_DEPTH); + batch._glDisable(GL_LIGHTING); + batch._glEnable(GL_BLEND); + renderAudioMeter(batch); + renderCameraToggle(batch); + renderStatsAndLogs(batch); + renderDomainConnectionStatusBorder(batch); + renderQmlUi(batch); + + // Execute the batch into our framebuffer + buildFramebufferObject(); + _overlayFramebuffer->bind(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, size.x, size.y); + mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(glm::value_ptr(legacyProjection)); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - buildFramebufferObject(); - - _framebufferObject->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport(0, 0, size.x, size.y); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); { - const float NEAR_CLIP = -10000; - const float FAR_CLIP = 10000; - glLoadIdentity(); - glOrtho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP); - - glMatrixMode(GL_MODELVIEW); - - renderAudioMeter(); - renderCameraToggle(); - - renderStatsAndLogs(); - - // give external parties a change to hook in - emit qApp->renderingOverlay(); - - overlays.renderHUD(renderArgs); - - renderDomainConnectionStatusBorder(); - if (_uiTexture) { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, _uiTexture); - DependencyManager::get()->renderUnitQuad(); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - } - glLoadIdentity(); - - - glMatrixMode(GL_PROJECTION); - } glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + glPushMatrix(); + glLoadIdentity(); - _framebufferObject->release(); + // give external parties a change to hook in + //emit qApp->renderingOverlay(); + overlays.renderHUD(renderArgs); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); + _overlayFramebuffer->release(); } -void ApplicationOverlay::renderCameraToggle() { +void ApplicationOverlay::renderQmlUi(gpu::Batch& batch) { + if (_uiTexture) { + batch.setProjectionTransform(mat4()); + batch.setModelTransform(mat4()); + batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); + auto geometryCache = DependencyManager::get(); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + } +} + +void ApplicationOverlay::renderCameraToggle(gpu::Batch& batch) { + /* if (Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)) { return; } @@ -158,9 +167,11 @@ void ApplicationOverlay::renderCameraToggle() { } DependencyManager::get()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, boxed); + */ } -void ApplicationOverlay::renderAudioMeter() { +void ApplicationOverlay::renderAudioMeter(gpu::Batch& batch) { + /* auto audio = DependencyManager::get(); // Audio VU Meter and Mute Icon @@ -274,9 +285,90 @@ void ApplicationOverlay::renderAudioMeter() { audioLevel, AUDIO_METER_HEIGHT, quadColor, _audioBlueQuad); } + */ } -void ApplicationOverlay::renderStatsAndLogs() { +void ApplicationOverlay::renderRearView(gpu::Batch& batch) { + // // Grab current viewport to reset it at the end + // int viewport[4]; + // glGetIntegerv(GL_VIEWPORT, viewport); + // float aspect = (float)region.width() / region.height(); + // float fov = MIRROR_FIELD_OF_VIEW; + + // // bool eyeRelativeCamera = false; + // if (billboard) { + // fov = BILLBOARD_FIELD_OF_VIEW; // degees + // _mirrorCamera.setPosition(_myAvatar->getPosition() + + // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); + + // } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { + // _mirrorCamera.setPosition(_myAvatar->getChestPosition() + + // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); + + // } else { // HEAD zoom level + // // FIXME note that the positioing of the camera relative to the avatar can suffer limited + // // precision as the user's position moves further away from the origin. Thus at + // // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways + // // wildly as you rotate your avatar because the floating point values are becoming + // // larger, squeezing out the available digits of precision you have available at the + // // human scale for camera positioning. + + // // Previously there was a hack to correct this using the mechanism of repositioning + // // the avatar at the origin of the world for the purposes of rendering the mirror, + // // but it resulted in failing to render the avatar's head model in the mirror view + // // when in first person mode. Presumably this was because of some missed culling logic + // // that was not accounted for in the hack. + + // // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further + // // investigated in order to adapt the technique while fixing the head rendering issue, + // // but the complexity of the hack suggests that a better approach + // _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + + // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); + // } + // _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); + // _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); + + // // set the bounds of rear mirror view + // if (billboard) { + // QSize size = DependencyManager::get()->getFrameBufferSize(); + // glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + // glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + // } else { + // // if not rendering the billboard, the region is in device independent coordinates; must convert to device + // QSize size = DependencyManager::get()->getFrameBufferSize(); + // float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); + // int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; + // glViewport(x, size.height() - y - height, width, height); + // glScissor(x, size.height() - y - height, width, height); + // } + // bool updateViewFrustum = false; + // updateProjectionMatrix(_mirrorCamera, updateViewFrustum); + // glEnable(GL_SCISSOR_TEST); + // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // // render rear mirror view + // glMatrixMode(GL_MODELVIEW); + // glPushMatrix(); + // glLoadIdentity(); + // glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); + // renderArgs->_context->syncCache(); + // displaySide(renderArgs, _mirrorCamera, true, billboard); + // glMatrixMode(GL_MODELVIEW); + // glPopMatrix(); + + // if (!billboard) { + // _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); + // } + + // // reset Viewport and projection matrix + // glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + // glDisable(GL_SCISSOR_TEST); + // updateProjectionMatrix(_myCamera, updateViewFrustum); + //} +} + +void ApplicationOverlay::renderStatsAndLogs(gpu::Batch& batch) { + /* Application* application = Application::getInstance(); QSharedPointer bandwidthRecorder = DependencyManager::get(); @@ -284,7 +376,7 @@ void ApplicationOverlay::renderStatsAndLogs() { NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); // Display stats and log text onscreen - glLineWidth(1.0f); + batch._glLineWidth(1.0f); glPointSize(1.0f); // Determine whether to compute timing details @@ -297,10 +389,9 @@ void ApplicationOverlay::renderStatsAndLogs() { if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { // let's set horizontal offset to give stats some margin to mirror - int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; int voxelPacketsToProcess = octreePacketProcessor.packetsToProcessCount(); // Onscreen text about position, servers, etc - Stats::getInstance()->display(WHITE_TEXT, horizontalOffset, application->getFps(), + Stats::getInstance()->display(WHITE_TEXT, STATS_HORIZONTAL_OFFSET, application->getFps(), bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond(), bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond(), bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(), @@ -320,56 +411,73 @@ void ApplicationOverlay::renderStatsAndLogs() { 0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT); } nodeBoundsDisplay.drawOverlay(); + */ } -void ApplicationOverlay::renderDomainConnectionStatusBorder() { +void ApplicationOverlay::renderDomainConnectionStatusBorder(gpu::Batch& batch) { + auto geometryCache = DependencyManager::get(); + std::once_flag once; + std::call_once(once, [&] { + QVector points; + static const float B = 0.99; + points.push_back(vec2(-B)); + points.push_back(vec2(B, -B)); + points.push_back(vec2(B)); + points.push_back(vec2(-B, B)); + points.push_back(vec2(-B)); + geometryCache->updateVertices(_domainStatusBorder, points, CONNECTION_STATUS_BORDER_COLOR); + }); auto nodeList = DependencyManager::get(); + if (nodeList && !nodeList->getDomainHandler().isConnected()) { - auto geometryCache = DependencyManager::get(); - auto canvasSize = qApp->getCanvasSize(); - if ((int)canvasSize.x != _previousBorderWidth || (int)canvasSize.y != _previousBorderHeight) { - glm::vec4 color(CONNECTION_STATUS_BORDER_COLOR[0], - CONNECTION_STATUS_BORDER_COLOR[1], - CONNECTION_STATUS_BORDER_COLOR[2], 1.0f); + batch.setProjectionTransform(mat4()); + batch.setModelTransform(mat4()); + batch.setUniformTexture(0, DependencyManager::get()->getWhiteTexture()); + batch._glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH); - QVector border; - border << glm::vec2(0, 0); - border << glm::vec2(0, canvasSize.y); - border << glm::vec2(canvasSize.x, canvasSize.y); - border << glm::vec2(canvasSize.x, 0); - border << glm::vec2(0, 0); - geometryCache->updateVertices(_domainStatusBorder, border, color); - _previousBorderWidth = canvasSize.x; - _previousBorderHeight = canvasSize.y; - } + // TODO animate the disconnect border for some excitement while not connected? + //double usecs = usecTimestampNow(); + //double secs = usecs / 1000000.0; + //float scaleAmount = 1.0f + (0.01f * sin(secs * 5.0f)); + //batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount))); - glLineWidth(CONNECTION_STATUS_BORDER_LINE_WIDTH); - - geometryCache->renderVertices(gpu::LINE_STRIP, _domainStatusBorder); + geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder); } } GLuint ApplicationOverlay::getOverlayTexture() { - if (!_framebufferObject) { + if (!_overlayFramebuffer) { return 0; } - return _framebufferObject->texture(); + return _overlayFramebuffer->texture(); } void ApplicationOverlay::buildFramebufferObject() { + if (!_mirrorFramebuffer) { + _mirrorFramebuffer = new QOpenGLFramebufferObject(QSize(MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT), QOpenGLFramebufferObject::Depth); + glBindTexture(GL_TEXTURE_2D, _mirrorFramebuffer->texture()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + glBindTexture(GL_TEXTURE_2D, 0); + } + auto canvasSize = qApp->getCanvasSize(); QSize fboSize = QSize(canvasSize.x, canvasSize.y); - if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) { + if (_overlayFramebuffer && fboSize == _overlayFramebuffer->size()) { // Already built return; } - if (_framebufferObject != NULL) { - delete _framebufferObject; + if (_overlayFramebuffer) { + delete _overlayFramebuffer; } - _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); + _overlayFramebuffer = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index dc21fba194..9dd846d9bf 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -29,13 +29,16 @@ public: private: - void renderAudioMeter(); - void renderCameraToggle(); - void renderStatsAndLogs(); - void renderDomainConnectionStatusBorder(); + void renderAudioMeter(gpu::Batch& batch); + void renderCameraToggle(gpu::Batch& batch); + void renderStatsAndLogs(gpu::Batch& batch); + void renderDomainConnectionStatusBorder(gpu::Batch& batch); + void renderRearView(gpu::Batch& batch); + void renderQmlUi(gpu::Batch& batch); void buildFramebufferObject(); - float _alpha = 1.0f; - float _trailingAudioLoudness; + + float _alpha{ 1.0f }; + float _trailingAudioLoudness{ 0.0f }; GLuint _uiTexture{ 0 }; int _audioRedQuad; @@ -44,10 +47,15 @@ private: int _domainStatusBorder; int _magnifierBorder; - int _previousBorderWidth; - int _previousBorderHeight; + float _scaleMirror{ 1.0f }; + float _rotateMirror{ 0.0f }; + float _raiseMirror{ 0.0f }; - QOpenGLFramebufferObject* _framebufferObject; + + ivec2 _previousBorderSize{ -1 }; + QRect _mirrorViewRect; + QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr }; + QOpenGLFramebufferObject* _mirrorFramebuffer{ nullptr }; }; #endif // hifi_ApplicationOverlay_h diff --git a/libraries/entities/src/EntityItemID.h b/libraries/entities/src/EntityItemID.h index 547907625d..7f55005a17 100644 --- a/libraries/entities/src/EntityItemID.h +++ b/libraries/entities/src/EntityItemID.h @@ -14,7 +14,7 @@ #include - +#include #include #include #include diff --git a/libraries/render-utils/src/TextRenderer.cpp b/libraries/render-utils/src/TextRenderer.cpp index 87cf9b2728..c815c5f179 100644 --- a/libraries/render-utils/src/TextRenderer.cpp +++ b/libraries/render-utils/src/TextRenderer.cpp @@ -434,6 +434,8 @@ glm::vec2 Font::drawString(float x, float y, const QString & str, fromGlm(MatrixStack::projection().top())); if (effectType == TextRenderer::OUTLINE_EFFECT) { _program->setUniformValue("Outline", true); + } else { + _program->setUniformValue("Outline", false); } // Needed? glEnable(GL_TEXTURE_2D); @@ -539,6 +541,25 @@ glm::vec2 TextRenderer::computeExtent(const QString & str) const { return glm::vec2(0.1f,0.1f); } +static gpu::PipelinePointer _textDrawPipeline; + +void TextRenderer::useTextPipeline(gpu::Batch& batch) { + if (!_textDrawPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(sdf_text_vert))); + auto fs = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(sdf_text_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, fs)); + gpu::Shader::makeProgram((*program)); + + auto state = gpu::StatePointer(new gpu::State()); + // enable decal blend + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + _textDrawPipeline.reset(gpu::Pipeline::create(program, state)); + } + batch.setPipeline(_textDrawPipeline); + batch._glBindTexture(GL_TEXTURE_2D, this->_font->_texture->textureId()); +} + + float TextRenderer::draw(float x, float y, const QString & str, const glm::vec4& color, const glm::vec2 & bounds) { glm::vec4 actualColor(color); diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 9b7cca70ee..54fe6492cf 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -122,6 +122,21 @@ float aspect(const T& t) { return (float)t.x / (float)t.y; } +// Take values in an arbitrary range [0, size] and convert them to the range [0, 1] +template +T toUnitScale(const T& value, const T& size) { + return value / size; +} + +// Take values in an arbitrary range [0, size] and convert them to the range [0, 1] +template +T toNormalizedDeviceScale(const T& value, const T& size) { + vec2 result = toUnitScale(value, size); + result *= 2.0f; + result -= 1.0f; + return result; +} + #define YAW(euler) euler.y #define PITCH(euler) euler.x #define ROLL(euler) euler.z From 02d33f6086f98092c5168401597740f2ba549e77 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 16 Jun 2015 12:14:42 -0700 Subject: [PATCH 006/121] Working on overlay rendering --- interface/src/ui/ApplicationOverlay.cpp | 74 +++++++++++---------- interface/src/ui/ApplicationOverlay.h | 1 + libraries/render-utils/src/TextRenderer.cpp | 21 ------ 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 989cec4345..6471fcfb16 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -85,55 +85,33 @@ ApplicationOverlay::~ApplicationOverlay() { void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - Overlays& overlays = qApp->getOverlays(); glm::vec2 size = qApp->getCanvasSize(); // TODO Handle fading and deactivation/activation of UI - // TODO First render the mirror to the mirror FBO - - // Now render the overlay components together into a single texture - gpu::Batch batch; - auto geometryCache = DependencyManager::get(); - geometryCache->useSimpleDrawPipeline(batch); - static const float NEAR_CLIP = -10000; - static const float FAR_CLIP = 10000; - batch._glDisable(GL_DEPTH); - batch._glDisable(GL_LIGHTING); - batch._glEnable(GL_BLEND); - renderAudioMeter(batch); - renderCameraToggle(batch); - renderStatsAndLogs(batch); - renderDomainConnectionStatusBorder(batch); - renderQmlUi(batch); - // Execute the batch into our framebuffer buildFramebufferObject(); _overlayFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, size.x, size.y); - mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(glm::value_ptr(legacyProjection)); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + // Now render the overlay components together into a single texture + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + batch._glDisable(GL_DEPTH); + batch._glDisable(GL_LIGHTING); + batch._glEnable(GL_BLEND); - // give external parties a change to hook in - //emit qApp->renderingOverlay(); - overlays.renderHUD(renderArgs); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + renderOverlays(batch, renderArgs); + + renderAudioMeter(batch); + renderCameraToggle(batch); + renderStatsAndLogs(batch); + renderDomainConnectionStatusBorder(batch); + renderQmlUi(batch); renderArgs->_context->syncCache(); renderArgs->_context->render(batch); @@ -150,6 +128,30 @@ void ApplicationOverlay::renderQmlUi(gpu::Batch& batch) { } } +void ApplicationOverlay::renderOverlays(gpu::Batch& batch, RenderArgs* renderArgs) { + static const float NEAR_CLIP = -10000; + static const float FAR_CLIP = 10000; + glm::vec2 size = qApp->getCanvasSize(); + mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(glm::value_ptr(legacyProjection)); + glMatrixMode(GL_MODELVIEW); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // give external parties a change to hook in + emit qApp->renderingOverlay(); + qApp->getOverlays().renderHUD(renderArgs); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); +} + void ApplicationOverlay::renderCameraToggle(gpu::Batch& batch) { /* if (Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 9dd846d9bf..9076d61b18 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -35,6 +35,7 @@ private: void renderDomainConnectionStatusBorder(gpu::Batch& batch); void renderRearView(gpu::Batch& batch); void renderQmlUi(gpu::Batch& batch); + void renderOverlays(gpu::Batch& batch, RenderArgs* renderArgs); void buildFramebufferObject(); float _alpha{ 1.0f }; diff --git a/libraries/render-utils/src/TextRenderer.cpp b/libraries/render-utils/src/TextRenderer.cpp index c815c5f179..87cf9b2728 100644 --- a/libraries/render-utils/src/TextRenderer.cpp +++ b/libraries/render-utils/src/TextRenderer.cpp @@ -434,8 +434,6 @@ glm::vec2 Font::drawString(float x, float y, const QString & str, fromGlm(MatrixStack::projection().top())); if (effectType == TextRenderer::OUTLINE_EFFECT) { _program->setUniformValue("Outline", true); - } else { - _program->setUniformValue("Outline", false); } // Needed? glEnable(GL_TEXTURE_2D); @@ -541,25 +539,6 @@ glm::vec2 TextRenderer::computeExtent(const QString & str) const { return glm::vec2(0.1f,0.1f); } -static gpu::PipelinePointer _textDrawPipeline; - -void TextRenderer::useTextPipeline(gpu::Batch& batch) { - if (!_textDrawPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(sdf_text_vert))); - auto fs = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(sdf_text_frag))); - auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, fs)); - gpu::Shader::makeProgram((*program)); - - auto state = gpu::StatePointer(new gpu::State()); - // enable decal blend - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - _textDrawPipeline.reset(gpu::Pipeline::create(program, state)); - } - batch.setPipeline(_textDrawPipeline); - batch._glBindTexture(GL_TEXTURE_2D, this->_font->_texture->textureId()); -} - - float TextRenderer::draw(float x, float y, const QString & str, const glm::vec4& color, const glm::vec2 & bounds) { glm::vec4 actualColor(color); From 659fa2387c0b76dd2e9561fbcccb7867715dc90f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 16 Jun 2015 21:00:13 -0700 Subject: [PATCH 007/121] Working on overlays / stats --- interface/resources/qml/Stats.qml | 147 +++++ interface/resources/qml/Tooltip.qml | 29 + interface/src/Application.cpp | 2 + interface/src/ui/ApplicationCompositor.cpp | 165 +---- interface/src/ui/ApplicationCompositor.h | 1 + interface/src/ui/ApplicationOverlay.cpp | 103 ++- interface/src/ui/ApplicationOverlay.h | 14 +- interface/src/ui/Stats.cpp | 620 +++++++----------- interface/src/ui/Stats.h | 128 +++- .../render-utils/src/OffscreenQmlSurface.cpp | 4 +- libraries/ui/src/Tooltip.cpp | 51 ++ libraries/ui/src/Tooltip.h | 45 ++ 12 files changed, 671 insertions(+), 638 deletions(-) create mode 100644 interface/resources/qml/Stats.qml create mode 100644 interface/resources/qml/Tooltip.qml create mode 100644 libraries/ui/src/Tooltip.cpp create mode 100644 libraries/ui/src/Tooltip.h diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml new file mode 100644 index 0000000000..6173b8517d --- /dev/null +++ b/interface/resources/qml/Stats.qml @@ -0,0 +1,147 @@ +import Hifi 1.0 as Hifi +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +Hifi.Stats { + id: root + objectName: "Stats" + implicitHeight: row.height + implicitWidth: row.width + readonly property int sTATS_GENERAL_MIN_WIDTH: 165 + readonly property int sTATS_PING_MIN_WIDTH: 190 + readonly property int sTATS_GEO_MIN_WIDTH: 240 + readonly property int sTATS_OCTREE_MIN_WIDTH: 410 + + onParentChanged: { + root.x = parent.width - root.width; + } + + Row { + z: 100 + id: row + spacing: 8 + Rectangle { + width: generalCol.width + 8; + height: generalCol.height + 8; + color: "#99333333"; + + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } + } + + Column { + id: generalCol + spacing: 4; x: 4; y: 4; + width: sTATS_GENERAL_MIN_WIDTH + Text { color: "white"; text: "Servers: " + root.serverCount } + Text { color: "white"; text: "Avatars: " + root.avatarCount } + Text { color: "white"; text: "Framerate: " + root.framerate } + Text { color: "white"; text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount } + Text { color: "white"; text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2) } + } + } + + Rectangle { + width: pingCol.width + 8 + height: pingCol.height + 8 + color: "#99333333" + visible: root.audioPing != -2 + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } + } + Column { + id: pingCol + spacing: 4; x: 4; y: 4; + width: sTATS_PING_MIN_WIDTH + Text { color: "white"; text: "Audio ping: " + root.audioPing } + Text { color: "white"; text: "Avatar ping: " + root.avatarPing } + Text { color: "white"; text: "Entities avg ping: " + root.entitiesPing } + Text { color: "white"; text: "Voxel max ping: " + 0; visible: root.expanded; } + } + } + Rectangle { + width: geoCol.width + height: geoCol.height + color: "#99333333" + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } + } + Column { + spacing: 4 + id: geoCol + width: sTATS_GEO_MIN_WIDTH + Text { + color: "white"; + text: "Position: " + root.position.x.toFixed(1) + ", " + + root.position.y.toFixed(1) + ", " + root.position.z.toFixed(1) + } + Text { + color: "white"; + text: "Velocity: " + root.velocity.toFixed(1) + } + Text { + color: "white"; + text: "Yaw: " + root.yaw.toFixed(1) + } + Text { + color: "white"; + visible: root.expanded; + text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " + + root.avatarMixerPps + "pps"; + } + Text { + color: "white"; + visible: root.expanded; + text: "Downloads: "; + } + } + } + Rectangle { + width: octreeCol.width + 8 + height: octreeCol.height + 8 + color: "#99333333" + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } + } + Column { + id: octreeCol + spacing: 4; x: 4; y: 4; + width: sTATS_OCTREE_MIN_WIDTH + Text { + color: "white"; + text: "Triangles: " + root.triangles + + " / Quads: " + root.quads + " / Material Switches: " + root.materialSwitches + } + Text { + color: "white"; + visible: root.expanded; + text: "\tMesh Parts Rendered Opaque: " + root.meshOpaque + + " / Translucent: " + root.meshTranslucent; + } + Text { + color: "white"; + visible: root.expanded; + text: "\tOpaque considered: " + root.opaqueConsidered + + " / Out of view: " + root.opaqueOutOfView + " / Too small: " + root.opaqueTooSmall; + } + Text { + color: "white"; + visible: !root.expanded + text: "Octree Elements Server: "; + } + } + } + } + + Connections { + target: root.parent + onWidthChanged: { + root.x = root.parent.width - root.width; + } + } +} + diff --git a/interface/resources/qml/Tooltip.qml b/interface/resources/qml/Tooltip.qml new file mode 100644 index 0000000000..f1504317e2 --- /dev/null +++ b/interface/resources/qml/Tooltip.qml @@ -0,0 +1,29 @@ +import Hifi 1.0 as Hifi +import QtQuick 2.3 as Original +import "controls" +import "styles" + +Hifi.Tooltip { + id: root + HifiConstants { id: hifi } + x: lastMousePosition.x + y: lastMousePosition.y + implicitWidth: border.implicitWidth + implicitHeight: border.implicitHeight + + Border { + id: border + anchors.fill: parent + implicitWidth: text.implicitWidth + implicitHeight: Math.max(text.implicitHeight, 64) + + Text { + id: text + anchors.fill: parent + anchors.margins: 16 + font.pixelSize: hifi.fonts.pixelSize / 2 + text: root.text + wrapMode: Original.Text.WordWrap + } + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6270c8f597..2aa718a27c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -88,6 +88,7 @@ #include #include #include +#include #include #include #include @@ -822,6 +823,7 @@ void Application::initializeUi() { LoginDialog::registerType(); MessageDialog::registerType(); VrMenu::registerType(); + Tooltip::registerType(); auto offscreenUi = DependencyManager::get(); offscreenUi->create(_glWidget->context()->contextHandle()); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index ab5014dfaa..b0c21cf77d 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "AudioClient.h" @@ -41,7 +42,7 @@ static const float MAG_SPEED = 0.08f; static const quint64 MSECS_TO_USECS = 1000ULL; -static const quint64 TOOLTIP_DELAY = 2000000ULL; +static const quint64 TOOLTIP_DELAY = 500 * MSECS_TO_USECS; static const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; static const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; @@ -59,7 +60,7 @@ static gpu::BufferPointer _hemiVertices; static gpu::BufferPointer _hemiIndices; static int _hemiIndexCount{ 0 }; EntityItemID ApplicationCompositor::_noItemId; - +static QString _tooltipId; // Return a point's cartesian coordinates on a sphere from pitch and yaw glm::vec3 getPoint(float yaw, float pitch) { @@ -159,6 +160,11 @@ ApplicationCompositor::ApplicationCompositor() { _hoverItemHref.clear(); auto cursor = Cursor::Manager::instance().getCursor(); cursor->setIcon(Cursor::Icon::DEFAULT); + if (!_tooltipId.isEmpty()) { + qDebug() << "Closing tooltip " << _tooltipId; + Tooltip::closeTip(_tooltipId); + _tooltipId.clear(); + } } }); } @@ -166,6 +172,7 @@ ApplicationCompositor::ApplicationCompositor() { ApplicationCompositor::~ApplicationCompositor() { } + void ApplicationCompositor::bindCursorTexture(gpu::Batch& batch, uint8_t cursorIndex) { auto& cursorManager = Cursor::Manager::instance(); auto cursor = cursorManager.getCursor(cursorIndex); @@ -184,17 +191,10 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { return; } + updateTooltips(); + vec2 canvasSize = qApp->getCanvasSize(); - _textureAspectRatio = aspect(canvasSize); - - if (_hoverItemId != _noItemId) { - quint64 hoverDuration = usecTimestampNow() - _hoverItemEnterUsecs; - if (!_hoverItemHref.isEmpty() && hoverDuration > TOOLTIP_DELAY) { - // TODO Enable and position the tooltip - } - } - //Handle fading and deactivation/activation of UI gpu::Batch batch; @@ -262,6 +262,11 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int return; } + vec2 canvasSize = qApp->getCanvasSize(); + _textureAspectRatio = aspect(canvasSize); + + updateTooltips(); + renderArgs->_context->syncCache(); auto geometryCache = DependencyManager::get(); @@ -392,13 +397,6 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi //Renders optional pointers void ApplicationCompositor::renderPointers(gpu::Batch& batch) { - //glEnable(GL_TEXTURE_2D); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - //glActiveTexture(GL_TEXTURE0); - //bindCursorTexture(); - if (qApp->isHMDMode() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { //If we are in oculus, render reticle later if (_lastMouseMove == 0) { @@ -442,8 +440,6 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) { _magActive[MOUSE] = false; renderControllerPointers(batch); } - //glBindTexture(GL_TEXTURE_2D, 0); - //glDisable(GL_TEXTURE_2D); } @@ -718,7 +714,6 @@ void ApplicationCompositor::drawSphereSection(gpu::Batch& batch) { batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount); } - glm::vec2 ApplicationCompositor::directionToSpherical(const glm::vec3& direction) { glm::vec2 result; // Compute yaw @@ -788,127 +783,13 @@ glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) co return sphericalToScreen(overlayToSpherical(overlayPos)); } -#if 0 - -gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() { - if (!_standardDrawPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); - auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - gpu::Shader::makeProgram((*program)); - - auto state = gpu::StatePointer(new gpu::State()); - - // enable decal blend - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - - _standardDrawPipeline.reset(gpu::Pipeline::create(program, state)); - } - - return _standardDrawPipeline; -} - - -// Draws the FBO texture for the screen -void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { - if (_alpha == 0.0f) { - return; - } - - renderArgs->_context->syncCache(); - - gpu::Batch batch; - Transform model; - //DependencyManager::get()->bindSimpleProgram(batch, true); - batch.setPipeline(getDrawPipeline()); - batch.setModelTransform(Transform()); - batch.setProjectionTransform(mat4()); - batch.setViewTransform(model); - batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - DependencyManager::get()->renderUnitQuad(batch, vec4(vec3(1), _alpha)); - - //draw the mouse pointer - glm::vec2 canvasSize = qApp->getCanvasSize(); - - // Get the mouse coordinates and convert to NDC [-1, 1] - vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); - mousePosition /= canvasSize; - mousePosition *= 2.0f; - mousePosition -= 1.0f; - mousePosition.y *= -1.0f; - model.setTranslation(vec3(mousePosition, 0)); - glm::vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; - model.setScale(vec3(mouseSize, 1.0f)); - batch.setModelTransform(model); - bindCursorTexture(batch); - glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; - DependencyManager::get()->renderUnitQuad(batch, vec4(1)); - renderArgs->_context->render(batch); -} - - - -// Draws the FBO texture for Oculus rift. -void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { - if (_alpha == 0.0f) { - return; - } - - renderArgs->_context->syncCache(); - - gpu::Batch batch; - batch.setPipeline(getDrawPipeline()); - batch._glDisable(GL_DEPTH_TEST); - batch._glDisable(GL_CULL_FACE); - batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - batch.setProjectionTransform(whichCamera.getProjection()); - batch.setViewTransform(Transform()); - - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - const quat& avatarOrientation = myAvatar->getOrientation(); - quat hmdOrientation = qApp->getCamera()->getHmdRotation(); - vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition(); - mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition); - batch.setModelTransform(Transform(overlayXfm)); - drawSphereSection(batch); - - - bindCursorTexture(batch); - auto geometryCache = DependencyManager::get(); - vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); - //Controller Pointers - for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { - PalmData& palm = myAvatar->getHand()->getPalms()[i]; - if (palm.isActive()) { - glm::vec2 polar = getPolarCoordinates(palm); - // Convert to quaternion - mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); - mat4 reticleXfm = overlayXfm * pointerXfm; - reticleXfm = glm::scale(reticleXfm, reticleScale); - batch.setModelTransform(reticleXfm); - // Render reticle at location - geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); +void ApplicationCompositor::updateTooltips() { + if (_hoverItemId != _noItemId) { + quint64 hoverDuration = usecTimestampNow() - _hoverItemEnterUsecs; + if (_hoverItemEnterUsecs != UINT64_MAX && !_hoverItemHref.isEmpty() && hoverDuration > TOOLTIP_DELAY) { + // TODO Enable and position the tooltip + _hoverItemEnterUsecs = UINT64_MAX; + _tooltipId = Tooltip::showTip("URL: " + _hoverItemHref); } } - - //Mouse Pointer - if (_reticleActive[MOUSE]) { - glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(), - _reticlePosition[MOUSE].y())); - mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); - mat4 reticleXfm = overlayXfm * pointerXfm; - reticleXfm = glm::scale(reticleXfm, reticleScale); - batch.setModelTransform(reticleXfm); - geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); - } - - renderArgs->_context->render(batch); } - - - -#endif diff --git a/interface/src/ui/ApplicationCompositor.h b/interface/src/ui/ApplicationCompositor.h index 5145e14006..0063319796 100644 --- a/interface/src/ui/ApplicationCompositor.h +++ b/interface/src/ui/ApplicationCompositor.h @@ -74,6 +74,7 @@ private: void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); void drawSphereSection(gpu::Batch& batch); + void updateTooltips(); void renderPointers(gpu::Batch& batch); void renderMagnifier(gpu::Batch& batch, const glm::vec2& magPos, float sizeMult, bool showBorder); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 6471fcfb16..86f06ba7fa 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -50,6 +50,8 @@ static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; static const float MIRROR_REARVIEW_DISTANCE = 0.722f; static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; +static const float ORTHO_NEAR_CLIP = -10000; +static const float ORTHO_FAR_CLIP = 10000; ApplicationOverlay::ApplicationOverlay() : @@ -85,6 +87,7 @@ ApplicationOverlay::~ApplicationOverlay() { void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); + Stats::getInstance()->updateStats(); glm::vec2 size = qApp->getCanvasSize(); // TODO Handle fading and deactivation/activation of UI @@ -98,41 +101,38 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { glViewport(0, 0, size.x, size.y); // Now render the overlay components together into a single texture - gpu::Batch batch; - auto geometryCache = DependencyManager::get(); - geometryCache->useSimpleDrawPipeline(batch); - batch._glDisable(GL_DEPTH); - batch._glDisable(GL_LIGHTING); - batch._glEnable(GL_BLEND); + //renderOverlays(renderArgs); + //renderAudioMeter(renderArgs); + //renderCameraToggle(renderArgs); + //renderStatsAndLogs(renderArgs); - renderOverlays(batch, renderArgs); - renderAudioMeter(batch); - renderCameraToggle(batch); - renderStatsAndLogs(batch); - renderDomainConnectionStatusBorder(batch); - renderQmlUi(batch); + renderDomainConnectionStatusBorder(renderArgs); + renderQmlUi(renderArgs); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); _overlayFramebuffer->release(); } -void ApplicationOverlay::renderQmlUi(gpu::Batch& batch) { +void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { if (_uiTexture) { + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + batch._glDisable(GL_DEPTH_TEST); + batch._glDisable(GL_LIGHTING); + batch._glEnable(GL_BLEND); batch.setProjectionTransform(mat4()); batch.setModelTransform(mat4()); batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); - auto geometryCache = DependencyManager::get(); geometryCache->renderUnitQuad(batch, glm::vec4(1)); + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); } } -void ApplicationOverlay::renderOverlays(gpu::Batch& batch, RenderArgs* renderArgs) { - static const float NEAR_CLIP = -10000; - static const float FAR_CLIP = 10000; +void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { glm::vec2 size = qApp->getCanvasSize(); - mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, NEAR_CLIP, FAR_CLIP); + mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadMatrixf(glm::value_ptr(legacyProjection)); @@ -152,8 +152,7 @@ void ApplicationOverlay::renderOverlays(gpu::Batch& batch, RenderArgs* renderArg glMatrixMode(GL_MODELVIEW); } -void ApplicationOverlay::renderCameraToggle(gpu::Batch& batch) { - /* +void ApplicationOverlay::renderCameraToggle(RenderArgs* renderArgs) { if (Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)) { return; } @@ -169,11 +168,9 @@ void ApplicationOverlay::renderCameraToggle(gpu::Batch& batch) { } DependencyManager::get()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, boxed); - */ } -void ApplicationOverlay::renderAudioMeter(gpu::Batch& batch) { - /* +void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { auto audio = DependencyManager::get(); // Audio VU Meter and Mute Icon @@ -287,10 +284,9 @@ void ApplicationOverlay::renderAudioMeter(gpu::Batch& batch) { audioLevel, AUDIO_METER_HEIGHT, quadColor, _audioBlueQuad); } - */ } -void ApplicationOverlay::renderRearView(gpu::Batch& batch) { +void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { // // Grab current viewport to reset it at the end // int viewport[4]; // glGetIntegerv(GL_VIEWPORT, viewport); @@ -369,37 +365,18 @@ void ApplicationOverlay::renderRearView(gpu::Batch& batch) { //} } -void ApplicationOverlay::renderStatsAndLogs(gpu::Batch& batch) { - /* - Application* application = Application::getInstance(); - QSharedPointer bandwidthRecorder = DependencyManager::get(); - - const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor(); - NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); +void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { // Display stats and log text onscreen - batch._glLineWidth(1.0f); - glPointSize(1.0f); // Determine whether to compute timing details bool shouldDisplayTimingDetail = Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && - Menu::getInstance()->isOptionChecked(MenuOption::Stats) && - Stats::getInstance()->isExpanded(); + Menu::getInstance()->isOptionChecked(MenuOption::Stats); //&& + // Stats::getInstance()->isExpanded(); if (shouldDisplayTimingDetail != PerformanceTimer::isActive()) { PerformanceTimer::setActive(shouldDisplayTimingDetail); } - - if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { - // let's set horizontal offset to give stats some margin to mirror - int voxelPacketsToProcess = octreePacketProcessor.packetsToProcessCount(); - // Onscreen text about position, servers, etc - Stats::getInstance()->display(WHITE_TEXT, STATS_HORIZONTAL_OFFSET, application->getFps(), - bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond(), - bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond(), - bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond(), - bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond(), - voxelPacketsToProcess); - } + Stats::getInstance()->updateStats(); // Show on-screen msec timer if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) { @@ -412,16 +389,26 @@ void ApplicationOverlay::renderStatsAndLogs(gpu::Batch& batch) { drawText(canvasSize.x - 100, canvasSize.y - timerBottom, 0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT); } + + glPointSize(1.0f); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + NodeBounds& nodeBoundsDisplay = qApp->getNodeBoundsDisplay(); nodeBoundsDisplay.drawOverlay(); - */ + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); } -void ApplicationOverlay::renderDomainConnectionStatusBorder(gpu::Batch& batch) { +void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderArgs) { auto geometryCache = DependencyManager::get(); std::once_flag once; std::call_once(once, [&] { QVector points; - static const float B = 0.99; + static const float B = 0.99f; points.push_back(vec2(-B)); points.push_back(vec2(B, -B)); points.push_back(vec2(B)); @@ -430,9 +417,13 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(gpu::Batch& batch) { geometryCache->updateVertices(_domainStatusBorder, points, CONNECTION_STATUS_BORDER_COLOR); }); auto nodeList = DependencyManager::get(); - - if (nodeList && !nodeList->getDomainHandler().isConnected()) { + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + batch._glDisable(GL_DEPTH); + batch._glDisable(GL_LIGHTING); + batch._glEnable(GL_BLEND); batch.setProjectionTransform(mat4()); batch.setModelTransform(mat4()); batch.setUniformTexture(0, DependencyManager::get()->getWhiteTexture()); @@ -445,6 +436,8 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(gpu::Batch& batch) { //batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount))); geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder); + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); } } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 9076d61b18..efdec01fb5 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -29,13 +29,13 @@ public: private: - void renderAudioMeter(gpu::Batch& batch); - void renderCameraToggle(gpu::Batch& batch); - void renderStatsAndLogs(gpu::Batch& batch); - void renderDomainConnectionStatusBorder(gpu::Batch& batch); - void renderRearView(gpu::Batch& batch); - void renderQmlUi(gpu::Batch& batch); - void renderOverlays(gpu::Batch& batch, RenderArgs* renderArgs); + void renderAudioMeter(RenderArgs* renderArgs); + void renderCameraToggle(RenderArgs* renderArgs); + void renderStatsAndLogs(RenderArgs* renderArgs); + void renderDomainConnectionStatusBorder(RenderArgs* renderArgs); + void renderRearView(RenderArgs* renderArgs); + void renderQmlUi(RenderArgs* renderArgs); + void renderOverlays(RenderArgs* renderArgs); void buildFramebufferObject(); float _alpha{ 1.0f }; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 8359480b03..fc9ceb8a67 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -9,9 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include -#include +#include "Stats.h" #include #include @@ -25,147 +25,30 @@ #include #include -#include "Stats.h" #include "BandwidthRecorder.h" #include "InterfaceConfig.h" #include "Menu.h" #include "Util.h" #include "SequenceNumberStats.h" +HIFI_QML_DEF(Stats) + using namespace std; -const int STATS_PELS_PER_LINE = 16; -const int STATS_PELS_INITIALOFFSET = 12; - -const int STATS_GENERAL_MIN_WIDTH = 165; -const int STATS_PING_MIN_WIDTH = 190; -const int STATS_GEO_MIN_WIDTH = 240; -const int STATS_OCTREE_MIN_WIDTH = 410; +static Stats* INSTANCE{ nullptr }; Stats* Stats::getInstance() { - static Stats stats; - return &stats; + if (!INSTANCE) { + Stats::registerType(); + Stats::show(); + //Stats::toggle(); + Q_ASSERT(INSTANCE); + } + return INSTANCE; } -Stats::Stats(): - _expanded(false), - _recentMaxPackets(0), - _resetRecentMaxPacketsSoon(true), - _generalStatsWidth(STATS_GENERAL_MIN_WIDTH), - _pingStatsWidth(STATS_PING_MIN_WIDTH), - _geoStatsWidth(STATS_GEO_MIN_WIDTH), - _octreeStatsWidth(STATS_OCTREE_MIN_WIDTH), - _lastHorizontalOffset(0) -{ - auto canvasSize = Application::getInstance()->getCanvasSize(); - resetWidth(canvasSize.x, 0); -} - -void Stats::toggleExpanded() { - _expanded = !_expanded; -} - -// called on mouse click release -// check for clicks over stats in order to expand or contract them -void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - auto canvasSize = Application::getInstance()->getCanvasSize(); - - if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { - // not worried about dragging on stats - return; - } - - int statsHeight = 0, - statsWidth = 0, - statsX = 0, - statsY = 0, - lines = 0; - - statsX = horizontalOffset; - - // top-left stats click - lines = _expanded ? 5 : 3; - statsHeight = lines * STATS_PELS_PER_LINE + 10; - if (mouseX > statsX && mouseX < statsX + _generalStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { - toggleExpanded(); - return; - } - statsX += _generalStatsWidth; - - // ping stats click - if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { - lines = _expanded ? 4 : 3; - statsHeight = lines * STATS_PELS_PER_LINE + 10; - if (mouseX > statsX && mouseX < statsX + _pingStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { - toggleExpanded(); - return; - } - statsX += _pingStatsWidth; - } - - // geo stats panel click - lines = _expanded ? 4 : 3; - statsHeight = lines * STATS_PELS_PER_LINE + 10; - if (mouseX > statsX && mouseX < statsX + _geoStatsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { - toggleExpanded(); - return; - } - statsX += _geoStatsWidth; - - // top-right stats click - lines = _expanded ? 11 : 3; - statsHeight = lines * STATS_PELS_PER_LINE + 10; - statsWidth = canvasSize.x - statsX; - if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { - toggleExpanded(); - return; - } -} - -void Stats::resetWidth(int width, int horizontalOffset) { - auto canvasSize = Application::getInstance()->getCanvasSize(); - int extraSpace = canvasSize.x - horizontalOffset - 2 - - STATS_GENERAL_MIN_WIDTH - - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) - - STATS_GEO_MIN_WIDTH - - STATS_OCTREE_MIN_WIDTH; - - int panels = 4; - - _generalStatsWidth = STATS_GENERAL_MIN_WIDTH; - if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { - _pingStatsWidth = STATS_PING_MIN_WIDTH; - } else { - _pingStatsWidth = 0; - panels = 3; - } - _geoStatsWidth = STATS_GEO_MIN_WIDTH; - _octreeStatsWidth = STATS_OCTREE_MIN_WIDTH; - - if (extraSpace > panels) { - _generalStatsWidth += (int) extraSpace / panels; - if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { - _pingStatsWidth += (int) extraSpace / panels; - } - _geoStatsWidth += (int) extraSpace / panels; - _octreeStatsWidth += canvasSize.x - - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); - } -} - - -// translucent background box that makes stats more readable -void Stats::drawBackground(unsigned int rgba, int x, int y, int width, int height) { - glm::vec4 color(((rgba >> 24) & 0xff) / 255.0f, - ((rgba >> 16) & 0xff) / 255.0f, - ((rgba >> 8) & 0xff) / 255.0f, - (rgba & 0xff) / 255.0f); - - // FIX ME: is this correct? It seems to work to fix textures bleeding into us... - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - - DependencyManager::get()->renderQuad(x, y, width, height, color); +Stats::Stats(QQuickItem* parent) : QQuickItem(parent) { + INSTANCE = this; } bool Stats::includeTimingRecord(const QString& name) { @@ -190,161 +73,63 @@ bool Stats::includeTimingRecord(const QString& name) { return false; } -// display expanded or contracted stats -void Stats::display( - const float* color, - int horizontalOffset, - float fps, - int inPacketsPerSecond, - int outPacketsPerSecond, - int inKbitsPerSecond, - int outKbitsPerSecond, - int voxelPacketsToProcess) -{ - auto canvasSize = Application::getInstance()->getCanvasSize(); - - unsigned int backgroundColor = 0x33333399; - int verticalOffset = 0, lines = 0; - float scale = 0.10f; - float rotation = 0.0f; - int font = 2; - - QLocale locale(QLocale::English); - std::stringstream octreeStats; - - QSharedPointer bandwidthRecorder = DependencyManager::get(); - - if (_lastHorizontalOffset != horizontalOffset) { - resetWidth(canvasSize.x, horizontalOffset); - _lastHorizontalOffset = horizontalOffset; +#define STAT_UPDATE(name, src) \ + { \ + auto val = src; \ + if (_##name != val) { \ + _##name = val; \ + emit name##Changed(); \ + } \ } - glPointSize(1.0f); +#define STAT_UPDATE_FLOAT(name, src, epsilon) \ + { \ + float val = src; \ + if (abs(_##name - val) >= epsilon) { \ + _##name = val; \ + emit name##Changed(); \ + } \ + } + +void Stats::updateStats() { + if (!Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + if (isVisible()) { + setVisible(false); + } + return; + } else { + if (!isVisible()) { + setVisible(true); + } + } + + auto nodeList = DependencyManager::get(); + auto avatarManager = DependencyManager::get(); // we need to take one avatar out so we don't include ourselves - int totalAvatars = DependencyManager::get()->size() - 1; - int totalServers = DependencyManager::get()->size(); + STAT_UPDATE(avatarCount, avatarManager->size() - 1); + STAT_UPDATE(serverCount, nodeList->size()); + STAT_UPDATE(framerate, (int)qApp->getFps()); - lines = 5; - int columnOneWidth = _generalStatsWidth; - - bool performanceTimerIsActive = PerformanceTimer::isActive(); - bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); - if (displayPerf && performanceTimerIsActive) { - PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up - - columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide... - // we will also include room for 1 line per timing record and a header of 4 lines - lines += 4; - - const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); - QMapIterator i(allRecords); - bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); - int statsLines = 0; - while (i.hasNext()) { - i.next(); - if (includeTimingRecord(i.key())) { - lines++; - statsLines++; - if (onlyDisplayTopTen && statsLines == 10) { - break; - } - } - } - } - - drawBackground(backgroundColor, horizontalOffset, 0, columnOneWidth, (lines + 1) * STATS_PELS_PER_LINE); - horizontalOffset += 5; - - int columnOneHorizontalOffset = horizontalOffset; - - QString serverNodes = QString("Servers: %1").arg(totalServers); - QString avatarNodes = QString("Avatars: %1").arg(totalAvatars); - QString framesPerSecond = QString("Framerate: %1 FPS").arg(fps, 3, 'f', 0); - - verticalOffset = STATS_PELS_INITIALOFFSET; // first one is offset by less than a line - drawText(horizontalOffset, verticalOffset, scale, rotation, font, serverNodes.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarNodes.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, framesPerSecond.toUtf8().constData(), color); - - QString packetsPerSecondString = QString("Packets In/Out: %1/%2").arg(inPacketsPerSecond).arg(outPacketsPerSecond); - QString averageMegabitsPerSecond = QString("Mbps In/Out: %1/%2"). - arg((float)inKbitsPerSecond * 1.0f / 1000.0f). - arg((float)outKbitsPerSecond * 1.0f / 1000.0f); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, packetsPerSecondString.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, averageMegabitsPerSecond.toUtf8().constData(), color); - - - // TODO: the display of these timing details should all be moved to JavaScript - if (displayPerf && performanceTimerIsActive) { - bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); - // Timing details... - verticalOffset += STATS_PELS_PER_LINE * 4; // skip 3 lines to be under the other columns - drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, - "-------------------------------------------------------- Function " - "------------------------------------------------------- --msecs- -calls--", color); - - // First iterate all the records, and for the ones that should be included, insert them into - // a new Map sorted by average time... - QMap sortedRecords; - const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); - QMapIterator i(allRecords); - - while (i.hasNext()) { - i.next(); - if (includeTimingRecord(i.key())) { - float averageTime = (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC; - sortedRecords.insertMulti(averageTime, i.key()); - } - } - - int linesDisplayed = 0; - QMapIterator j(sortedRecords); - j.toBack(); - while (j.hasPrevious()) { - j.previous(); - QChar noBreakingSpace = QChar::Nbsp; - QString functionName = j.value(); - const PerformanceTimerRecord& record = allRecords.value(functionName); - - QString perfLine = QString("%1: %2 [%3]"). - arg(QString(qPrintable(functionName)), 120, noBreakingSpace). - arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace). - arg((int)record.getCount(), 6, 10, noBreakingSpace); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, perfLine.toUtf8().constData(), color); - linesDisplayed++; - if (onlyDisplayTopTen && linesDisplayed == 10) { - break; - } - } - } - - - verticalOffset = STATS_PELS_INITIALOFFSET; - horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + 1; + auto bandwidthRecorder = DependencyManager::get(); + STAT_UPDATE(packetInCount, bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond()); + STAT_UPDATE(packetOutCount, bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond()); + STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond() / 1000.0f, 0.01f); + STAT_UPDATE_FLOAT(mbpsOut, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f); + // Second column: ping if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { - int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingOctreeMax = -1; - - auto nodeList = DependencyManager::get(); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); + STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); + STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); - pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : -1; - pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : -1; - - // Now handle voxel servers, since there could be more than one, we average their ping times + //// Now handle voxel servers, since there could be more than one, we average their ping times unsigned long totalPingOctree = 0; int octreeServerCount = 0; - - nodeList->eachNode([&totalPingOctree, &pingOctreeMax, &octreeServerCount](const SharedNodePointer& node){ + int pingOctreeMax = 0; + int pingVoxel; + nodeList->eachNode([&](const SharedNodePointer& node) { // TODO: this should also support entities if (node->getType() == NodeType::EntityServer) { totalPingOctree += node->getPingMs(); @@ -359,146 +144,101 @@ void Stats::display( pingVoxel = totalPingOctree / octreeServerCount; } - lines = _expanded ? 4 : 3; - - // only draw our background if column one didn't draw a wide background - if (columnOneWidth == _generalStatsWidth) { - drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, (lines + 1) * STATS_PELS_PER_LINE); - } - horizontalOffset += 5; - - - QString audioPing; - if (pingAudio >= 0) { - audioPing = QString("Audio ping: %1").arg(pingAudio); - } else { - audioPing = QString("Audio ping: --"); - } - - QString avatarPing; - if (pingAvatar >= 0) { - avatarPing = QString("Avatar ping: %1").arg(pingAvatar); - } else { - avatarPing = QString("Avatar ping: --"); - } - - QString voxelAvgPing; - if (pingVoxel >= 0) { - voxelAvgPing = QString("Entities avg ping: %1").arg(pingVoxel); - } else { - voxelAvgPing = QString("Entities avg ping: --"); - } - - drawText(horizontalOffset, verticalOffset, scale, rotation, font, audioPing.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarPing.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelAvgPing.toUtf8().constData(), color); - - if (_expanded) { - QString voxelMaxPing; - if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid. - voxelMaxPing = QString("Voxel max ping: %1").arg(pingOctreeMax); - } else { - voxelMaxPing = QString("Voxel max ping: --"); - } - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing.toUtf8().constData(), color); - } - - verticalOffset = STATS_PELS_INITIALOFFSET; - horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + 2; + STAT_UPDATE(entitiesPing, pingVoxel); + //if (_expanded) { + // QString voxelMaxPing; + // if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid. + // voxelMaxPing = QString("Voxel max ping: %1").arg(pingOctreeMax); + // } else { + // voxelMaxPing = QString("Voxel max ping: --"); + // } + } else { + // -2 causes the QML to hide the ping column + STAT_UPDATE(audioPing, -2); } - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + + // Third column, avatar stats + MyAvatar* myAvatar = avatarManager->getMyAvatar(); glm::vec3 avatarPos = myAvatar->getPosition(); - - lines = _expanded ? 7 : 3; - - if (columnOneWidth == _generalStatsWidth) { - drawBackground(backgroundColor, horizontalOffset, 0, _geoStatsWidth, (lines + 1) * STATS_PELS_PER_LINE); - } - horizontalOffset += 5; - - QString avatarPosition = QString("Position: %1, %2, %3"). - arg(avatarPos.x, -1, 'f', 1). - arg(avatarPos.y, -1, 'f', 1). - arg(avatarPos.z, -1, 'f', 1); - QString avatarVelocity = QString("Velocity: %1").arg(glm::length(myAvatar->getVelocity()), -1, 'f', 1); - QString avatarBodyYaw = QString("Yaw: %1").arg(myAvatar->getBodyYaw(), -1, 'f', 1); - QString avatarMixerStats; - - drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarPosition.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarVelocity.toUtf8().constData(), color); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarBodyYaw.toUtf8().constData(), color); - + STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); + STAT_UPDATE_FLOAT(velocity, glm::length(myAvatar->getVelocity()), 0.1f); + STAT_UPDATE_FLOAT(yaw, myAvatar->getBodyYaw(), 0.1f); if (_expanded) { - SharedNodePointer avatarMixer = DependencyManager::get()->soloNodeOfType(NodeType::AvatarMixer); + SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer); if (avatarMixer) { - avatarMixerStats = QString("Avatar Mixer: %1 kbps, %2 pps"). - arg(roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) + - bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))). - arg(roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) + - bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); + STAT_UPDATE(avatarMixerKbps, roundf( + bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer) + + bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerPps, roundf( + bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer) + + bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer))); } else { - avatarMixerStats = QString("No Avatar Mixer"); + STAT_UPDATE(avatarMixerKbps, -1); + STAT_UPDATE(avatarMixerPps, -1); + } + SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); + if (audioMixerNode) { + STAT_UPDATE(audioMixerKbps, roundf( + bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) + + bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))); + STAT_UPDATE(audioMixerPps, roundf( + bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) + + bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); + } else { + STAT_UPDATE(audioMixerKbps, -1); + STAT_UPDATE(audioMixerPps, -1); } - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarMixerStats.toUtf8().constData(), color); - - stringstream downloads; - downloads << "Downloads: "; - foreach (Resource* resource, ResourceCache::getLoadingRequests()) { - downloads << (int)(resource->getProgress() * 100.0f) << "% "; - } - downloads << "(" << ResourceCache::getPendingRequestCount() << " pending)"; - - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, downloads.str().c_str(), color); - } + STAT_UPDATE(downloads, ResourceCache::getLoadingRequests().size()); + STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount()); + // TODO fix to match original behavior + //stringstream downloads; + //downloads << "Downloads: "; + //foreach(Resource* resource, ) { + // downloads << (int)(resource->getProgress() * 100.0f) << "% "; + //} + //downloads << "(" << << " pending)"; + } // expanded avatar column - verticalOffset = STATS_PELS_INITIALOFFSET; - horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3; - - lines = _expanded ? 10 : 3; - - drawBackground(backgroundColor, horizontalOffset, 0, canvasSize.x - horizontalOffset, - (lines + 1) * STATS_PELS_PER_LINE); - horizontalOffset += 5; - - // Model/Entity render details - octreeStats.str(""); - octreeStats << "Triangles: " << _renderDetails._trianglesRendered - << " / Quads:" << _renderDetails._quadsRendered - << " / Material Switches:" << _renderDetails._materialSwitches; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); + // Fourth column, octree stats +} +void Stats::setRenderDetails(const RenderDetails& details) { + //STATS_PROPERTY(int, triangles, 0) + //STATS_PROPERTY(int, quads, 0) + //STATS_PROPERTY(int, materialSwitches, 0) + //STATS_PROPERTY(int, meshOpaque, 0) + //STATS_PROPERTY(int, meshTranslucent, 0) + //STATS_PROPERTY(int, opaqueConsidered, 0) + //STATS_PROPERTY(int, opaqueOutOfView, 0) + //STATS_PROPERTY(int, opaqueTooSmall, 0) + //STATS_PROPERTY(int, translucentConsidered, 0) + //STATS_PROPERTY(int, translucentOutOfView, 0) + //STATS_PROPERTY(int, translucentTooSmall, 0) + //STATS_PROPERTY(int, octreeElementsServer, 0) + //STATS_PROPERTY(int, octreeElementsLocal, 0) + STAT_UPDATE(triangles, details._trianglesRendered); + STAT_UPDATE(quads, details._quadsRendered); + STAT_UPDATE(materialSwitches, details._materialSwitches); if (_expanded) { - octreeStats.str(""); - octreeStats << " Mesh Parts Rendered Opaque: " << _renderDetails._opaque._rendered - << " / Translucent:" << _renderDetails._translucent._rendered; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - - octreeStats.str(""); - octreeStats << " Opaque considered: " << _renderDetails._opaque._considered - << " / Out of view:" << _renderDetails._opaque._outOfView - << " / Too small:" << _renderDetails._opaque._tooSmall; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - - octreeStats.str(""); - octreeStats << " Translucent considered: " << _renderDetails._translucent._considered - << " / Out of view:" << _renderDetails._translucent._outOfView - << " / Too small:" << _renderDetails._translucent._tooSmall; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); + STAT_UPDATE(meshOpaque, details._opaque._rendered); + STAT_UPDATE(meshTranslucent, details._opaque._rendered); + STAT_UPDATE(opaqueConsidered, details._opaque._considered); + STAT_UPDATE(opaqueOutOfView, details._opaque._outOfView); + STAT_UPDATE(opaqueTooSmall, details._opaque._tooSmall); + STAT_UPDATE(translucentConsidered, details._translucent._considered); + STAT_UPDATE(translucentOutOfView, details._translucent._outOfView); + STAT_UPDATE(translucentTooSmall, details._translucent._tooSmall); } +} + +/* +// display expanded or contracted stats +void Stats::display( + int voxelPacketsToProcess) +{ // iterate all the current voxel stats, and list their sending modes, and total voxel counts std::stringstream sendingMode(""); sendingMode << "Octree Sending Mode: ["; @@ -619,3 +359,81 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } + +//// Performance timer + + + bool performanceTimerIsActive = PerformanceTimer::isActive(); + bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); + if (displayPerf && performanceTimerIsActive) { + PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up + columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide... + // we will also include room for 1 line per timing record and a header of 4 lines + lines += 4; + + const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); + QMapIterator i(allRecords); + bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); + int statsLines = 0; + while (i.hasNext()) { + i.next(); + if (includeTimingRecord(i.key())) { + lines++; + statsLines++; + if (onlyDisplayTopTen && statsLines == 10) { + break; + } + } + } + } + + + // TODO: the display of these timing details should all be moved to JavaScript + if (displayPerf && performanceTimerIsActive) { + bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); + // Timing details... + verticalOffset += STATS_PELS_PER_LINE * 4; // skip 3 lines to be under the other columns + drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, + "-------------------------------------------------------- Function " + "------------------------------------------------------- --msecs- -calls--", color); + + // First iterate all the records, and for the ones that should be included, insert them into + // a new Map sorted by average time... + QMap sortedRecords; + const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); + QMapIterator i(allRecords); + + while (i.hasNext()) { + i.next(); + if (includeTimingRecord(i.key())) { + float averageTime = (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC; + sortedRecords.insertMulti(averageTime, i.key()); + } + } + + int linesDisplayed = 0; + QMapIterator j(sortedRecords); + j.toBack(); + while (j.hasPrevious()) { + j.previous(); + QChar noBreakingSpace = QChar::Nbsp; + QString functionName = j.value(); + const PerformanceTimerRecord& record = allRecords.value(functionName); + + QString perfLine = QString("%1: %2 [%3]"). + arg(QString(qPrintable(functionName)), 120, noBreakingSpace). + arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace). + arg((int)record.getCount(), 6, 10, noBreakingSpace); + + verticalOffset += STATS_PELS_PER_LINE; + drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, perfLine.toUtf8().constData(), color); + linesDisplayed++; + if (onlyDisplayTopTen && linesDisplayed == 10) { + break; + } + } + } + + + +*/ \ No newline at end of file diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 4c6d6ede4e..553b54d04b 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -13,47 +13,113 @@ #define hifi_Stats_h #include +#include +#include +#include #include -class Stats: public QObject { +#define STATS_PROPERTY(type, name, initialValue) \ + Q_PROPERTY(type name READ name NOTIFY name##Changed) \ +public: \ + type name() { return _##name; }; \ +private: \ + type _##name{ initialValue }; + + +class Stats : public QQuickItem { Q_OBJECT + HIFI_QML_DECL + Q_PROPERTY(bool expanded READ isExpanded NOTIFY expandedChanged) + STATS_PROPERTY(int, serverCount, 0) + STATS_PROPERTY(int, framerate, 0) + STATS_PROPERTY(int, avatarCount, 0) + STATS_PROPERTY(int, packetInCount, 0) + STATS_PROPERTY(int, packetOutCount, 0) + STATS_PROPERTY(float, mbpsIn, 0) + STATS_PROPERTY(float, mbpsOut, 0) + STATS_PROPERTY(int, audioPing, 0) + STATS_PROPERTY(int, avatarPing, 0) + STATS_PROPERTY(int, entitiesPing, 0) + STATS_PROPERTY(QVector3D, position, QVector3D(0, 0, 0) ) + STATS_PROPERTY(float, velocity, 0) + STATS_PROPERTY(float, yaw, 0) + STATS_PROPERTY(int, avatarMixerKbps, 0) + STATS_PROPERTY(int, avatarMixerPps, 0) + STATS_PROPERTY(int, audioMixerKbps, 0) + STATS_PROPERTY(int, audioMixerPps, 0) + STATS_PROPERTY(int, downloads, 0) + STATS_PROPERTY(int, downloadsPending, 0) + STATS_PROPERTY(int, triangles, 0) + STATS_PROPERTY(int, quads, 0) + STATS_PROPERTY(int, materialSwitches, 0) + STATS_PROPERTY(int, meshOpaque, 0) + STATS_PROPERTY(int, meshTranslucent, 0) + STATS_PROPERTY(int, opaqueConsidered, 0) + STATS_PROPERTY(int, opaqueOutOfView, 0) + STATS_PROPERTY(int, opaqueTooSmall, 0) + STATS_PROPERTY(int, translucentConsidered, 0) + STATS_PROPERTY(int, translucentOutOfView, 0) + STATS_PROPERTY(int, translucentTooSmall, 0) + STATS_PROPERTY(int, octreeElementsServer, 0) + STATS_PROPERTY(int, octreeElementsLocal, 0) public: static Stats* getInstance(); - Stats(); - - static void drawBackground(unsigned int rgba, int x, int y, int width, int height); - - void toggleExpanded(); - bool isExpanded() { return _expanded; } - - void checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset); - void resetWidth(int width, int horizontalOffset); - void display(const float* color, int horizontalOffset, float fps, int inPacketsPerSecond, int outPacketsPerSecond, - int inKbitsPerSecond, int outKbitsPerSecond, int voxelPacketsToProcess); + Stats(QQuickItem* parent = nullptr); bool includeTimingRecord(const QString& name); - - void setRenderDetails(const RenderDetails& details) { _renderDetails = details; } - + void setRenderDetails(const RenderDetails& details); + + void updateStats(); + + bool isExpanded() { return _expanded; } + + void setExpanded(bool expanded) { + if (expanded != _expanded) { + _expanded = expanded; + } + } + +signals: + void expandedChanged(); + void serverCountChanged(); + void framerateChanged(); + void avatarCountChanged(); + void packetInCountChanged(); + void packetOutCountChanged(); + void mbpsInChanged(); + void mbpsOutChanged(); + void audioPingChanged(); + void avatarPingChanged(); + void entitiesPingChanged(); + void positionChanged(); + void velocityChanged(); + void yawChanged(); + void avatarMixerKbpsChanged(); + void avatarMixerPpsChanged(); + void audioMixerKbpsChanged(); + void audioMixerPpsChanged(); + void downloadsChanged(); + void downloadsPendingChanged(); + void trianglesChanged(); + void quadsChanged(); + void materialSwitchesChanged(); + void meshOpaqueChanged(); + void meshTranslucentChanged(); + void opaqueConsideredChanged(); + void opaqueOutOfViewChanged(); + void opaqueTooSmallChanged(); + void translucentConsideredChanged(); + void translucentOutOfViewChanged(); + void translucentTooSmallChanged(); + void octreeElementsServerChanged(); + void octreeElementsLocalChanged(); + private: - static Stats* _sharedInstance; - - bool _expanded; - - int _recentMaxPackets; // recent max incoming voxel packets to process - bool _resetRecentMaxPacketsSoon; - - int _generalStatsWidth; - int _bandwidthStatsWidth; - int _pingStatsWidth; - int _geoStatsWidth; - int _octreeStatsWidth; - - int _lastHorizontalOffset; - - RenderDetails _renderDetails; + int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process + bool _resetRecentMaxPacketsSoon{ true }; + bool _expanded{ false }; }; #endif // hifi_Stats_h diff --git a/libraries/render-utils/src/OffscreenQmlSurface.cpp b/libraries/render-utils/src/OffscreenQmlSurface.cpp index 9b497964e7..07a887be2c 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.cpp +++ b/libraries/render-utils/src/OffscreenQmlSurface.cpp @@ -91,6 +91,7 @@ void OffscreenQmlSurface::resize(const QSize& newSize) { // Qt bug in 5.4 forces this check of pixel ratio, // even though we're rendering offscreen. qreal pixelRatio = 1.0; + _qmlEngine->rootContext()->setContextProperty("surfaceSize", newSize); if (_renderControl && _renderControl->_renderWindow) { pixelRatio = _renderControl->_renderWindow->devicePixelRatio(); } else { @@ -111,7 +112,6 @@ void OffscreenQmlSurface::resize(const QSize& newSize) { _quickWindow->contentItem()->setSize(newSize); } - // Update our members if (_rootItem) { _rootItem->setSize(newSize); @@ -376,4 +376,4 @@ void OffscreenQmlSurface::setProxyWindow(QWindow* window) { QQuickWindow* OffscreenQmlSurface::getWindow() { return _quickWindow; -} \ No newline at end of file +} diff --git a/libraries/ui/src/Tooltip.cpp b/libraries/ui/src/Tooltip.cpp new file mode 100644 index 0000000000..35b17b74a2 --- /dev/null +++ b/libraries/ui/src/Tooltip.cpp @@ -0,0 +1,51 @@ +// +// Tooltip.cpp +// +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Tooltip.h" +#include + +HIFI_QML_DEF(Tooltip) + +Tooltip::Tooltip(QQuickItem* parent) : QQuickItem(parent) { +} + +Tooltip::~Tooltip() { +} + +QString Tooltip::text() const { + return _text; +} + +void Tooltip::setText(const QString& arg) { + if (arg != _text) { + _text = arg; + emit textChanged(); + } +} + +void Tooltip::setVisible(bool visible) { + QQuickItem::setVisible(visible); +} + +QString Tooltip::showTip(const QString& text) { + const QString newTipId = QUuid().createUuid().toString(); + Tooltip::show([&](QQmlContext*, QObject* object) { + object->setObjectName(newTipId); + object->setProperty("text", text); + }); + return newTipId; +} + +void Tooltip::closeTip(const QString& tipId) { + auto rootItem = DependencyManager::get()->getRootItem(); + QQuickItem* that = rootItem->findChild(tipId); + if (that) { + that->deleteLater(); + } +} \ No newline at end of file diff --git a/libraries/ui/src/Tooltip.h b/libraries/ui/src/Tooltip.h new file mode 100644 index 0000000000..7292fe9399 --- /dev/null +++ b/libraries/ui/src/Tooltip.h @@ -0,0 +1,45 @@ +// +// Tooltip.h +// +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_Tooltip_h +#define hifi_Tooltip_h + +#include "OffscreenQmlDialog.h" + +class Tooltip : public QQuickItem +{ + Q_OBJECT + HIFI_QML_DECL + +private: + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + +public: + Tooltip(QQuickItem* parent = 0); + virtual ~Tooltip(); + + QString text() const; + + static QString showTip(const QString& text); + static void closeTip(const QString& tipId); + +public slots: + virtual void setVisible(bool v); + void setText(const QString& arg); + +signals: + void textChanged(); + +private: + QString _text; +}; + +#endif // hifi_Tooltip_h From 2bf53b625e4b2cc7f6e210aae456cac633fa0a77 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 17 Jun 2015 02:00:13 -0700 Subject: [PATCH 008/121] Working on overlays and stats --- interface/resources/qml/Stats.qml | 164 +++++++-- interface/src/Application.cpp | 3 +- interface/src/ui/ApplicationOverlay.cpp | 12 +- interface/src/ui/Stats.cpp | 345 +++++++----------- interface/src/ui/Stats.h | 29 +- .../render-utils/src/OffscreenQmlSurface.cpp | 4 + 6 files changed, 306 insertions(+), 251 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 6173b8517d..89961aeb9c 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -11,19 +11,22 @@ Hifi.Stats { readonly property int sTATS_PING_MIN_WIDTH: 190 readonly property int sTATS_GEO_MIN_WIDTH: 240 readonly property int sTATS_OCTREE_MIN_WIDTH: 410 + readonly property int fontSize: 12 + readonly property string fontColor: "white" + readonly property string bgColor: "#99333333" onParentChanged: { root.x = parent.width - root.width; } + Row { - z: 100 id: row spacing: 8 Rectangle { width: generalCol.width + 8; height: generalCol.height + 8; - color: "#99333333"; + color: root.bgColor; MouseArea { anchors.fill: parent @@ -34,18 +37,38 @@ Hifi.Stats { id: generalCol spacing: 4; x: 4; y: 4; width: sTATS_GENERAL_MIN_WIDTH - Text { color: "white"; text: "Servers: " + root.serverCount } - Text { color: "white"; text: "Avatars: " + root.avatarCount } - Text { color: "white"; text: "Framerate: " + root.framerate } - Text { color: "white"; text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount } - Text { color: "white"; text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2) } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Servers: " + root.serverCount + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Avatars: " + root.avatarCount + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Framerate: " + root.framerate + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2) + } } } Rectangle { width: pingCol.width + 8 height: pingCol.height + 8 - color: "#99333333" + color: root.bgColor; visible: root.audioPing != -2 MouseArea { anchors.fill: parent @@ -55,45 +78,68 @@ Hifi.Stats { id: pingCol spacing: 4; x: 4; y: 4; width: sTATS_PING_MIN_WIDTH - Text { color: "white"; text: "Audio ping: " + root.audioPing } - Text { color: "white"; text: "Avatar ping: " + root.avatarPing } - Text { color: "white"; text: "Entities avg ping: " + root.entitiesPing } - Text { color: "white"; text: "Voxel max ping: " + 0; visible: root.expanded; } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + text: "Audio ping: " + root.audioPing + } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + text: "Avatar ping: " + root.avatarPing + } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + text: "Entities avg ping: " + root.entitiesPing + } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + visible: root.expanded; + text: "Voxel max ping: " + 0 + } } } + Rectangle { - width: geoCol.width - height: geoCol.height - color: "#99333333" + width: geoCol.width + 8 + height: geoCol.height + 8 + color: root.bgColor; MouseArea { anchors.fill: parent onClicked: { root.expanded = !root.expanded; } } Column { - spacing: 4 id: geoCol + spacing: 4; x: 4; y: 4; width: sTATS_GEO_MIN_WIDTH Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize text: "Position: " + root.position.x.toFixed(1) + ", " + root.position.y.toFixed(1) + ", " + root.position.z.toFixed(1) } Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize text: "Velocity: " + root.velocity.toFixed(1) } Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize text: "Yaw: " + root.yaw.toFixed(1) } Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize visible: root.expanded; text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " + root.avatarMixerPps + "pps"; } Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize visible: root.expanded; text: "Downloads: "; } @@ -102,7 +148,7 @@ Hifi.Stats { Rectangle { width: octreeCol.width + 8 height: octreeCol.height + 8 - color: "#99333333" + color: root.bgColor; MouseArea { anchors.fill: parent onClicked: { root.expanded = !root.expanded; } @@ -112,31 +158,93 @@ Hifi.Stats { spacing: 4; x: 4; y: 4; width: sTATS_OCTREE_MIN_WIDTH Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize text: "Triangles: " + root.triangles + " / Quads: " + root.quads + " / Material Switches: " + root.materialSwitches } Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize visible: root.expanded; text: "\tMesh Parts Rendered Opaque: " + root.meshOpaque + " / Translucent: " + root.meshTranslucent; } Text { - color: "white"; - visible: root.expanded; + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; text: "\tOpaque considered: " + root.opaqueConsidered + " / Out of view: " + root.opaqueOutOfView + " / Too small: " + root.opaqueTooSmall; } Text { - color: "white"; + color: root.fontColor; + font.pixelSize: root.fontSize visible: !root.expanded - text: "Octree Elements Server: "; + text: "Octree Elements Server: " + root.serverElements + + " Local: " + root.localElements; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "Octree Sending Mode: " + root.sendingMode; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "Octree Packets to Process: " + root.packetStats; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "Octree Elements - "; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "\tServer: " + root.serverElements + + " Internal: " + root.serverInternal + + " Leaves: " + root.serverLeaves; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "\tLocal: " + root.localElements + + " Internal: " + root.localInternal + + " Leaves: " + root.localLeaves; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "LOD: " + root.lodStatus; } } } } + Rectangle { + y: 250 + width: perfText.width + 8 + height: perfText.height + 8 + color: root.bgColor; + anchors.top: row.bottom + 16 + Text { + x: 4; y: 4 + id: perfText + color: root.fontColor + font.family: "Lucida Console" + text: "-------------------------------------------------------- Function " + + "------------------------------------------------------- --msecs- -calls--\n" + + root.timingStats; + } + } + Connections { target: root.parent onWidthChanged: { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 52aa9e97b3..d7e72e6541 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1817,6 +1817,7 @@ void Application::idle() { targetFramePeriod = 1000.0 / targetFramerate; } double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; + //if (true) { if (timeSinceLastUpdate > targetFramePeriod) { _lastTimeUpdated.start(); { @@ -1843,7 +1844,7 @@ void Application::idle() { } // After finishing all of the above work, restart the idle timer, allowing 2ms to process events. - idleTimer->start(2); + idleTimer->start(0); } } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 86f06ba7fa..ba0cdf3be0 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -87,7 +87,6 @@ ApplicationOverlay::~ApplicationOverlay() { void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - Stats::getInstance()->updateStats(); glm::vec2 size = qApp->getCanvasSize(); // TODO Handle fading and deactivation/activation of UI @@ -104,8 +103,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { //renderOverlays(renderArgs); //renderAudioMeter(renderArgs); //renderCameraToggle(renderArgs); - //renderStatsAndLogs(renderArgs); - + renderStatsAndLogs(renderArgs); renderDomainConnectionStatusBorder(renderArgs); renderQmlUi(renderArgs); @@ -370,14 +368,9 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { // Display stats and log text onscreen // Determine whether to compute timing details - bool shouldDisplayTimingDetail = Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && - Menu::getInstance()->isOptionChecked(MenuOption::Stats); //&& - // Stats::getInstance()->isExpanded(); - if (shouldDisplayTimingDetail != PerformanceTimer::isActive()) { - PerformanceTimer::setActive(shouldDisplayTimingDetail); - } Stats::getInstance()->updateStats(); + /* // Show on-screen msec timer if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) { auto canvasSize = qApp->getCanvasSize(); @@ -401,6 +394,7 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { glEnable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + */ } void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderArgs) { diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index fc9ceb8a67..ca91e3a919 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -13,6 +13,8 @@ #include "Stats.h" +#include + #include #include #include @@ -41,7 +43,6 @@ Stats* Stats::getInstance() { if (!INSTANCE) { Stats::registerType(); Stats::show(); - //Stats::toggle(); Q_ASSERT(INSTANCE); } return INSTANCE; @@ -104,6 +105,13 @@ void Stats::updateStats() { } } + bool shouldDisplayTimingDetail = Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && + Menu::getInstance()->isOptionChecked(MenuOption::Stats) && isExpanded(); + if (shouldDisplayTimingDetail != PerformanceTimer::isActive()) { + PerformanceTimer::setActive(shouldDisplayTimingDetail); + } + + auto nodeList = DependencyManager::get(); auto avatarManager = DependencyManager::get(); // we need to take one avatar out so we don't include ourselves @@ -144,7 +152,7 @@ void Stats::updateStats() { pingVoxel = totalPingOctree / octreeServerCount; } - STAT_UPDATE(entitiesPing, pingVoxel); + //STAT_UPDATE(entitiesPing, pingVoxel); //if (_expanded) { // QString voxelMaxPing; // if (pingVoxel >= 0) { // Average is only meaningful if pingVoxel is valid. @@ -202,22 +210,137 @@ void Stats::updateStats() { } // expanded avatar column // Fourth column, octree stats + int serverCount = 0; + int movingServerCount = 0; + unsigned long totalNodes = 0; + unsigned long totalInternal = 0; + unsigned long totalLeaves = 0; + std::stringstream sendingModeStream(""); + sendingModeStream << "["; + NodeToOctreeSceneStats* octreeServerSceneStats = Application::getInstance()->getOcteeSceneStats(); + for (NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) { + //const QUuid& uuid = i->first; + OctreeSceneStats& stats = i->second; + serverCount++; + if (_expanded) { + if (serverCount > 1) { + sendingModeStream << ","; + } + if (stats.isMoving()) { + sendingModeStream << "M"; + movingServerCount++; + } else { + sendingModeStream << "S"; + } + } + + // calculate server node totals + totalNodes += stats.getTotalElements(); + if (_expanded) { + totalInternal += stats.getTotalInternal(); + totalLeaves += stats.getTotalLeaves(); + } + } + if (_expanded) { + if (serverCount == 0) { + sendingModeStream << "---"; + } + sendingModeStream << "] " << serverCount << " servers"; + if (movingServerCount > 0) { + sendingModeStream << " "; + } else { + sendingModeStream << " "; + } + QString sendingModeResult = sendingModeStream.str().c_str(); + STAT_UPDATE(sendingMode, sendingModeResult); + } + + // Incoming packets + QLocale locale(QLocale::English); + auto voxelPacketsToProcess = qApp->getOctreePacketProcessor().packetsToProcessCount(); + if (_expanded) { + std::stringstream octreeStats; + QString packetsString = locale.toString((int)voxelPacketsToProcess); + QString maxString = locale.toString((int)_recentMaxPackets); + octreeStats << "Octree Packets to Process: " << qPrintable(packetsString) + << " [Recent Max: " << qPrintable(maxString) << "]"; + QString str = octreeStats.str().c_str(); + STAT_UPDATE(packetStats, str); + // drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); + } + + if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) { + _recentMaxPackets = 0; + _resetRecentMaxPacketsSoon = false; + } + if (voxelPacketsToProcess == 0) { + _resetRecentMaxPacketsSoon = true; + } else if (voxelPacketsToProcess > _recentMaxPackets) { + _recentMaxPackets = voxelPacketsToProcess; + } + + // Server Octree Elements + STAT_UPDATE(serverElements, totalNodes); + STAT_UPDATE(localElements, OctreeElement::getNodeCount()); + + if (_expanded) { + STAT_UPDATE(serverInternal, totalInternal); + STAT_UPDATE(serverLeaves, totalLeaves); + // Local Voxels + STAT_UPDATE(localInternal, OctreeElement::getInternalNodeCount()); + STAT_UPDATE(localLeaves, OctreeElement::getLeafNodeCount()); + // LOD Details + STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get()->getLODFeedbackText()); + } + + bool performanceTimerIsActive = PerformanceTimer::isActive(); + bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); + if (displayPerf && performanceTimerIsActive) { + PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up + + // we will also include room for 1 line per timing record and a header of 4 lines + // Timing details... + + // First iterate all the records, and for the ones that should be included, insert them into + // a new Map sorted by average time... + bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); + QMap sortedRecords; + const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); + QMapIterator i(allRecords); + + while (i.hasNext()) { + i.next(); + if (includeTimingRecord(i.key())) { + float averageTime = (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC; + sortedRecords.insertMulti(averageTime, i.key()); + } + } + + int linesDisplayed = 0; + QMapIterator j(sortedRecords); + j.toBack(); + QString perfLines; + while (j.hasPrevious()) { + j.previous(); + static const QChar noBreakingSpace = QChar::Nbsp; + QString functionName = j.value(); + const PerformanceTimerRecord& record = allRecords.value(functionName); + perfLines += QString("%1: %2 [%3]\n"). + arg(QString(qPrintable(functionName)), 120, noBreakingSpace). + arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace). + arg((int)record.getCount(), 6, 10, noBreakingSpace); + linesDisplayed++; + if (onlyDisplayTopTen && linesDisplayed == 10) { + break; + } + } + _timingStats = perfLines; + emit timingStatsChanged(); + } + } void Stats::setRenderDetails(const RenderDetails& details) { - //STATS_PROPERTY(int, triangles, 0) - //STATS_PROPERTY(int, quads, 0) - //STATS_PROPERTY(int, materialSwitches, 0) - //STATS_PROPERTY(int, meshOpaque, 0) - //STATS_PROPERTY(int, meshTranslucent, 0) - //STATS_PROPERTY(int, opaqueConsidered, 0) - //STATS_PROPERTY(int, opaqueOutOfView, 0) - //STATS_PROPERTY(int, opaqueTooSmall, 0) - //STATS_PROPERTY(int, translucentConsidered, 0) - //STATS_PROPERTY(int, translucentOutOfView, 0) - //STATS_PROPERTY(int, translucentTooSmall, 0) - //STATS_PROPERTY(int, octreeElementsServer, 0) - //STATS_PROPERTY(int, octreeElementsLocal, 0) STAT_UPDATE(triangles, details._trianglesRendered); STAT_UPDATE(quads, details._quadsRendered); STAT_UPDATE(materialSwitches, details._materialSwitches); @@ -240,200 +363,8 @@ void Stats::display( int voxelPacketsToProcess) { // iterate all the current voxel stats, and list their sending modes, and total voxel counts - std::stringstream sendingMode(""); - sendingMode << "Octree Sending Mode: ["; - int serverCount = 0; - int movingServerCount = 0; - unsigned long totalNodes = 0; - unsigned long totalInternal = 0; - unsigned long totalLeaves = 0; - NodeToOctreeSceneStats* octreeServerSceneStats = Application::getInstance()->getOcteeSceneStats(); - for(NodeToOctreeSceneStatsIterator i = octreeServerSceneStats->begin(); i != octreeServerSceneStats->end(); i++) { - //const QUuid& uuid = i->first; - OctreeSceneStats& stats = i->second; - serverCount++; - if (_expanded) { - if (serverCount > 1) { - sendingMode << ","; - } - if (stats.isMoving()) { - sendingMode << "M"; - movingServerCount++; - } else { - sendingMode << "S"; - } - } - // calculate server node totals - totalNodes += stats.getTotalElements(); - if (_expanded) { - totalInternal += stats.getTotalInternal(); - totalLeaves += stats.getTotalLeaves(); - } - } - if (_expanded) { - if (serverCount == 0) { - sendingMode << "---"; - } - sendingMode << "] " << serverCount << " servers"; - if (movingServerCount > 0) { - sendingMode << " "; - } else { - sendingMode << " "; - } - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)sendingMode.str().c_str(), color); - } - - // Incoming packets - if (_expanded) { - octreeStats.str(""); - QString packetsString = locale.toString((int)voxelPacketsToProcess); - QString maxString = locale.toString((int)_recentMaxPackets); - octreeStats << "Octree Packets to Process: " << qPrintable(packetsString) - << " [Recent Max: " << qPrintable(maxString) << "]"; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - } - - if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) { - _recentMaxPackets = 0; - _resetRecentMaxPacketsSoon = false; - } - if (voxelPacketsToProcess == 0) { - _resetRecentMaxPacketsSoon = true; - } else { - if (voxelPacketsToProcess > _recentMaxPackets) { - _recentMaxPackets = voxelPacketsToProcess; - } - } - - QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' '); - unsigned long localTotal = OctreeElement::getNodeCount(); - QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' '); - - // Server Octree Elements - if (!_expanded) { - octreeStats.str(""); - octreeStats << "Octree Elements Server: " << qPrintable(serversTotalString) - << " Local:" << qPrintable(localTotalString); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - } - - if (_expanded) { - octreeStats.str(""); - octreeStats << "Octree Elements -"; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - - QString serversInternalString = locale.toString((uint)totalInternal); - QString serversLeavesString = locale.toString((uint)totalLeaves); - - octreeStats.str(""); - octreeStats << " Server: " << qPrintable(serversTotalString) << - " Internal: " << qPrintable(serversInternalString) << - " Leaves: " << qPrintable(serversLeavesString); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - - // Local Voxels - unsigned long localInternal = OctreeElement::getInternalNodeCount(); - unsigned long localLeaves = OctreeElement::getLeafNodeCount(); - QString localInternalString = locale.toString((uint)localInternal); - QString localLeavesString = locale.toString((uint)localLeaves); - - octreeStats.str(""); - octreeStats << " Local: " << qPrintable(serversTotalString) << - " Internal: " << qPrintable(localInternalString) << - " Leaves: " << qPrintable(localLeavesString) << ""; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - } - - // LOD Details - octreeStats.str(""); - QString displayLODDetails = DependencyManager::get()->getLODFeedbackText(); - octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } -//// Performance timer - - - bool performanceTimerIsActive = PerformanceTimer::isActive(); - bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); - if (displayPerf && performanceTimerIsActive) { - PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up - columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide... - // we will also include room for 1 line per timing record and a header of 4 lines - lines += 4; - - const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); - QMapIterator i(allRecords); - bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); - int statsLines = 0; - while (i.hasNext()) { - i.next(); - if (includeTimingRecord(i.key())) { - lines++; - statsLines++; - if (onlyDisplayTopTen && statsLines == 10) { - break; - } - } - } - } - - - // TODO: the display of these timing details should all be moved to JavaScript - if (displayPerf && performanceTimerIsActive) { - bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); - // Timing details... - verticalOffset += STATS_PELS_PER_LINE * 4; // skip 3 lines to be under the other columns - drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, - "-------------------------------------------------------- Function " - "------------------------------------------------------- --msecs- -calls--", color); - - // First iterate all the records, and for the ones that should be included, insert them into - // a new Map sorted by average time... - QMap sortedRecords; - const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); - QMapIterator i(allRecords); - - while (i.hasNext()) { - i.next(); - if (includeTimingRecord(i.key())) { - float averageTime = (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC; - sortedRecords.insertMulti(averageTime, i.key()); - } - } - - int linesDisplayed = 0; - QMapIterator j(sortedRecords); - j.toBack(); - while (j.hasPrevious()) { - j.previous(); - QChar noBreakingSpace = QChar::Nbsp; - QString functionName = j.value(); - const PerformanceTimerRecord& record = allRecords.value(functionName); - - QString perfLine = QString("%1: %2 [%3]"). - arg(QString(qPrintable(functionName)), 120, noBreakingSpace). - arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace). - arg((int)record.getCount(), 6, 10, noBreakingSpace); - - verticalOffset += STATS_PELS_PER_LINE; - drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, perfLine.toUtf8().constData(), color); - linesDisplayed++; - if (onlyDisplayTopTen && linesDisplayed == 10) { - break; - } - } - } - - - */ \ No newline at end of file diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 553b54d04b..01179ad353 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -30,7 +30,7 @@ private: \ class Stats : public QQuickItem { Q_OBJECT HIFI_QML_DECL - Q_PROPERTY(bool expanded READ isExpanded NOTIFY expandedChanged) + Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, framerate, 0) STATS_PROPERTY(int, avatarCount, 0) @@ -61,8 +61,16 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, translucentConsidered, 0) STATS_PROPERTY(int, translucentOutOfView, 0) STATS_PROPERTY(int, translucentTooSmall, 0) - STATS_PROPERTY(int, octreeElementsServer, 0) - STATS_PROPERTY(int, octreeElementsLocal, 0) + STATS_PROPERTY(QString, sendingMode, QString()) + STATS_PROPERTY(QString, packetStats, QString()) + STATS_PROPERTY(QString, lodStatus, QString()) + STATS_PROPERTY(QString, timingStats, QString()) + STATS_PROPERTY(int, serverElements, 0) + STATS_PROPERTY(int, serverInternal, 0) + STATS_PROPERTY(int, serverLeaves, 0) + STATS_PROPERTY(int, localElements, 0) + STATS_PROPERTY(int, localInternal, 0) + STATS_PROPERTY(int, localLeaves, 0) public: static Stats* getInstance(); @@ -76,8 +84,9 @@ public: bool isExpanded() { return _expanded; } void setExpanded(bool expanded) { - if (expanded != _expanded) { + if (_expanded != expanded) { _expanded = expanded; + emit expandedChanged(); } } @@ -113,8 +122,16 @@ signals: void translucentConsideredChanged(); void translucentOutOfViewChanged(); void translucentTooSmallChanged(); - void octreeElementsServerChanged(); - void octreeElementsLocalChanged(); + void sendingModeChanged(); + void packetStatsChanged(); + void lodStatusChanged(); + void serverElementsChanged(); + void serverInternalChanged(); + void serverLeavesChanged(); + void localElementsChanged(); + void localInternalChanged(); + void localLeavesChanged(); + void timingStatsChanged(); private: int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process diff --git a/libraries/render-utils/src/OffscreenQmlSurface.cpp b/libraries/render-utils/src/OffscreenQmlSurface.cpp index 07a887be2c..b6bc6b721e 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.cpp +++ b/libraries/render-utils/src/OffscreenQmlSurface.cpp @@ -11,6 +11,9 @@ #include #include #include + +#include + #include "AbstractViewStateInterface.h" Q_DECLARE_LOGGING_CATEGORY(offscreenFocus) @@ -212,6 +215,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function Date: Wed, 17 Jun 2015 11:35:30 -0700 Subject: [PATCH 009/121] Working on overlays still, mirror rendering and overlay order --- interface/resources/qml/Stats.qml | 1 + interface/src/Application.cpp | 9 +- interface/src/ui/ApplicationOverlay.cpp | 157 ++++++++++++++---------- interface/src/ui/ApplicationOverlay.h | 3 +- interface/src/ui/Stats.cpp | 8 +- interface/src/ui/Stats.h | 4 + 6 files changed, 112 insertions(+), 70 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 89961aeb9c..c77ab8ec27 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -230,6 +230,7 @@ Hifi.Stats { Rectangle { y: 250 + visible: root.timingExpanded width: perfText.width + 8 height: perfText.height + 8 color: root.bgColor; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8e3c4e416d..058f809249 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -874,6 +874,11 @@ void Application::paintGL() { OculusManager::beginFrameTiming(); } + { + PerformanceTimer perfTimer("renderOverlay"); + _applicationOverlay.renderOverlay(&renderArgs); + } + PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); @@ -974,10 +979,6 @@ void Application::paintGL() { glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(&renderArgs); - } if (!OculusManager::isConnected() || OculusManager::allowSwap()) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ba0cdf3be0..d3c433339b 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -87,16 +87,16 @@ ApplicationOverlay::~ApplicationOverlay() { void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - glm::vec2 size = qApp->getCanvasSize(); - // TODO Handle fading and deactivation/activation of UI + buildFramebufferObject(); - // TODO First render the mirror to the mirror FBO + // First render the mirror to the mirror FBO + renderRearViewToFbo(renderArgs); // Execute the batch into our framebuffer - buildFramebufferObject(); _overlayFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glm::vec2 size = qApp->getCanvasSize(); glViewport(0, 0, size.x, size.y); // Now render the overlay components together into a single texture @@ -104,6 +104,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { //renderAudioMeter(renderArgs); //renderCameraToggle(renderArgs); renderStatsAndLogs(renderArgs); + renderRearView(renderArgs); renderDomainConnectionStatusBorder(renderArgs); renderQmlUi(renderArgs); @@ -284,73 +285,77 @@ void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { } } -void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { - // // Grab current viewport to reset it at the end - // int viewport[4]; - // glGetIntegerv(GL_VIEWPORT, viewport); - // float aspect = (float)region.width() / region.height(); - // float fov = MIRROR_FIELD_OF_VIEW; +void fboViewport(QOpenGLFramebufferObject* fbo) { + auto size = fbo->size(); + glViewport(0, 0, size.width(), size.height()); +} - // // bool eyeRelativeCamera = false; - // if (billboard) { - // fov = BILLBOARD_FIELD_OF_VIEW; // degees - // _mirrorCamera.setPosition(_myAvatar->getPosition() + - // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); +void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { + // Grab current viewport to reset it at the end + auto mirrorSize = _mirrorFramebuffer->size(); + float aspect = (float)mirrorSize.width() / mirrorSize.height(); + float fov = MIRROR_FIELD_OF_VIEW; + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + // bool eyeRelativeCamera = false; + bool billboard = false; + if (billboard) { + fov = BILLBOARD_FIELD_OF_VIEW; // degees + _mirrorCamera.setPosition(myAvatar->getPosition() + + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * myAvatar->getScale()); - // } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { - // _mirrorCamera.setPosition(_myAvatar->getChestPosition() + - // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); + } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { + _mirrorCamera.setPosition(myAvatar->getChestPosition() + + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale()); - // } else { // HEAD zoom level - // // FIXME note that the positioing of the camera relative to the avatar can suffer limited - // // precision as the user's position moves further away from the origin. Thus at - // // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways - // // wildly as you rotate your avatar because the floating point values are becoming - // // larger, squeezing out the available digits of precision you have available at the - // // human scale for camera positioning. + } else { // HEAD zoom level + // FIXME note that the positioing of the camera relative to the avatar can suffer limited + // precision as the user's position moves further away from the origin. Thus at + // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways + // wildly as you rotate your avatar because the floating point values are becoming + // larger, squeezing out the available digits of precision you have available at the + // human scale for camera positioning. - // // Previously there was a hack to correct this using the mechanism of repositioning - // // the avatar at the origin of the world for the purposes of rendering the mirror, - // // but it resulted in failing to render the avatar's head model in the mirror view - // // when in first person mode. Presumably this was because of some missed culling logic - // // that was not accounted for in the hack. + // Previously there was a hack to correct this using the mechanism of repositioning + // the avatar at the origin of the world for the purposes of rendering the mirror, + // but it resulted in failing to render the avatar's head model in the mirror view + // when in first person mode. Presumably this was because of some missed culling logic + // that was not accounted for in the hack. - // // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further - // // investigated in order to adapt the technique while fixing the head rendering issue, - // // but the complexity of the hack suggests that a better approach - // _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + - // _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); - // } - // _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); - // _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); + // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further + // investigated in order to adapt the technique while fixing the head rendering issue, + // but the complexity of the hack suggests that a better approach + _mirrorCamera.setPosition(myAvatar->getHead()->getEyePosition() + + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * myAvatar->getScale()); + } + _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); + _mirrorCamera.setRotation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); - // // set the bounds of rear mirror view - // if (billboard) { - // QSize size = DependencyManager::get()->getFrameBufferSize(); - // glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - // glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - // } else { - // // if not rendering the billboard, the region is in device independent coordinates; must convert to device - // QSize size = DependencyManager::get()->getFrameBufferSize(); - // float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); - // int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; - // glViewport(x, size.height() - y - height, width, height); - // glScissor(x, size.height() - y - height, width, height); - // } - // bool updateViewFrustum = false; - // updateProjectionMatrix(_mirrorCamera, updateViewFrustum); - // glEnable(GL_SCISSOR_TEST); - // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // set the bounds of rear mirror view + if (billboard) { + //QSize size = DependencyManager::get()->getFrameBufferSize(); + //glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + //glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + } else { + auto mirrorSize = _mirrorFramebuffer->size(); + fboViewport(_mirrorFramebuffer); + } - // // render rear mirror view - // glMatrixMode(GL_MODELVIEW); - // glPushMatrix(); - // glLoadIdentity(); - // glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); - // renderArgs->_context->syncCache(); - // displaySide(renderArgs, _mirrorCamera, true, billboard); - // glMatrixMode(GL_MODELVIEW); - // glPopMatrix(); + _mirrorFramebuffer->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + { + auto projection = _mirrorCamera.getProjection(); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(glm::value_ptr(projection)); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); + renderArgs->_context->syncCache(); + qApp->displaySide(renderArgs, _mirrorCamera, true, billboard); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + _mirrorFramebuffer->release(); // if (!billboard) { // _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); @@ -363,6 +368,30 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { //} } +void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { + if (_mirrorFramebuffer && _mirrorFramebuffer->texture()) { + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + batch._glDisable(GL_DEPTH_TEST); + batch._glDisable(GL_LIGHTING); + batch._glEnable(GL_BLEND); + batch.setProjectionTransform(mat4()); + batch.setModelTransform(mat4()); + auto textureCache = DependencyManager::get(); + batch.setUniformTexture(0, textureCache->getBlueTexture()); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + batch._glBindTexture(GL_TEXTURE_2D, _mirrorFramebuffer->texture()); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + renderArgs->_context->syncCache(); + auto overlaySize = _overlayFramebuffer->size(); + glViewport(MIRROR_VIEW_LEFT_PADDING, overlaySize.height() - MIRROR_VIEW_TOP_PADDING - MIRROR_VIEW_HEIGHT, + MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT); + renderArgs->_context->render(batch); + fboViewport(_overlayFramebuffer); + } +} + void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { // Display stats and log text onscreen diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index efdec01fb5..ab242e592b 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -33,6 +33,7 @@ private: void renderCameraToggle(RenderArgs* renderArgs); void renderStatsAndLogs(RenderArgs* renderArgs); void renderDomainConnectionStatusBorder(RenderArgs* renderArgs); + void renderRearViewToFbo(RenderArgs* renderArgs); void renderRearView(RenderArgs* renderArgs); void renderQmlUi(RenderArgs* renderArgs); void renderOverlays(RenderArgs* renderArgs); @@ -52,7 +53,7 @@ private: float _rotateMirror{ 0.0f }; float _raiseMirror{ 0.0f }; - + Camera _mirrorCamera; ivec2 _previousBorderSize{ -1 }; QRect _mirrorViewRect; QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr }; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ca91e3a919..f541357486 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -296,6 +296,10 @@ void Stats::updateStats() { bool performanceTimerIsActive = PerformanceTimer::isActive(); bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); if (displayPerf && performanceTimerIsActive) { + if (!_timingExpanded) { + _timingExpanded = true; + emit timingExpandedChanged(); + } PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up // we will also include room for 1 line per timing record and a header of 4 lines @@ -336,8 +340,10 @@ void Stats::updateStats() { } _timingStats = perfLines; emit timingStatsChanged(); + } else if (_timingExpanded) { + _timingExpanded = false; + emit timingExpandedChanged(); } - } void Stats::setRenderDetails(const RenderDetails& details) { diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 01179ad353..efe340ed18 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -31,6 +31,7 @@ class Stats : public QQuickItem { Q_OBJECT HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) + Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, framerate, 0) STATS_PROPERTY(int, avatarCount, 0) @@ -82,6 +83,7 @@ public: void updateStats(); bool isExpanded() { return _expanded; } + bool isTimingExpanded() { return _timingExpanded; } void setExpanded(bool expanded) { if (_expanded != expanded) { @@ -92,6 +94,7 @@ public: signals: void expandedChanged(); + void timingExpandedChanged(); void serverCountChanged(); void framerateChanged(); void avatarCountChanged(); @@ -137,6 +140,7 @@ private: int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process bool _resetRecentMaxPacketsSoon{ true }; bool _expanded{ false }; + bool _timingExpanded{ false }; }; #endif // hifi_Stats_h From 4282c044ef4d4e0b82b84a33c0391003214f214a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 17 Jun 2015 12:01:39 -0700 Subject: [PATCH 010/121] Working on mirror and overlay --- interface/src/Application.cpp | 79 +------------------------ interface/src/ui/ApplicationOverlay.cpp | 37 ++++++------ libraries/gpu/src/gpu/Context.cpp | 4 ++ libraries/gpu/src/gpu/Context.h | 4 ++ libraries/gpu/src/gpu/GLBackend.cpp | 4 +- libraries/gpu/src/gpu/GLBackend.h | 2 + 6 files changed, 34 insertions(+), 96 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 058f809249..994a09d65f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -877,6 +877,7 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); _applicationOverlay.renderOverlay(&renderArgs); + renderArgs._context->resetState(); } PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); @@ -3640,84 +3641,6 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { return screenPoint; } -//void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { -// // Grab current viewport to reset it at the end -// int viewport[4]; -// glGetIntegerv(GL_VIEWPORT, viewport); -// float aspect = (float)region.width() / region.height(); -// float fov = MIRROR_FIELD_OF_VIEW; -// -// // bool eyeRelativeCamera = false; -// if (billboard) { -// fov = BILLBOARD_FIELD_OF_VIEW; // degees -// _mirrorCamera.setPosition(_myAvatar->getPosition() + -// _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); -// -// } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { -// _mirrorCamera.setPosition(_myAvatar->getChestPosition() + -// _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); -// -// } else { // HEAD zoom level -// // FIXME note that the positioing of the camera relative to the avatar can suffer limited -// // precision as the user's position moves further away from the origin. Thus at -// // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways -// // wildly as you rotate your avatar because the floating point values are becoming -// // larger, squeezing out the available digits of precision you have available at the -// // human scale for camera positioning. -// -// // Previously there was a hack to correct this using the mechanism of repositioning -// // the avatar at the origin of the world for the purposes of rendering the mirror, -// // but it resulted in failing to render the avatar's head model in the mirror view -// // when in first person mode. Presumably this was because of some missed culling logic -// // that was not accounted for in the hack. -// -// // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further -// // investigated in order to adapt the technique while fixing the head rendering issue, -// // but the complexity of the hack suggests that a better approach -// _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + -// _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); -// } -// _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); -// _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); -// -// // set the bounds of rear mirror view -// if (billboard) { -// QSize size = DependencyManager::get()->getFrameBufferSize(); -// glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); -// glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); -// } else { -// // if not rendering the billboard, the region is in device independent coordinates; must convert to device -// QSize size = DependencyManager::get()->getFrameBufferSize(); -// float ratio = QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); -// int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; -// glViewport(x, size.height() - y - height, width, height); -// glScissor(x, size.height() - y - height, width, height); -// } -// bool updateViewFrustum = false; -// updateProjectionMatrix(_mirrorCamera, updateViewFrustum); -// glEnable(GL_SCISSOR_TEST); -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -// -// // render rear mirror view -// glMatrixMode(GL_MODELVIEW); -// glPushMatrix(); -// glLoadIdentity(); -// glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); -// renderArgs->_context->syncCache(); -// displaySide(renderArgs, _mirrorCamera, true, billboard); -// glMatrixMode(GL_MODELVIEW); -// glPopMatrix(); -// -// if (!billboard) { -// _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); -// } -// -// // reset Viewport and projection matrix -// glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); -// glDisable(GL_SCISSOR_TEST); -// updateProjectionMatrix(_myCamera, updateViewFrustum); -//} - void Application::resetSensors() { DependencyManager::get()->reset(); DependencyManager::get()->reset(); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index d3c433339b..a35cdce58b 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -53,6 +53,13 @@ static const float MIRROR_FIELD_OF_VIEW = 30.0f; static const float ORTHO_NEAR_CLIP = -10000; static const float ORTHO_FAR_CLIP = 10000; +// TODO move somewhere useful +static void fboViewport(QOpenGLFramebufferObject* fbo) { + auto size = fbo->size(); + glViewport(0, 0, size.width(), size.height()); +} + + ApplicationOverlay::ApplicationOverlay() : _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)) @@ -94,10 +101,8 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // Execute the batch into our framebuffer _overlayFramebuffer->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glm::vec2 size = qApp->getCanvasSize(); - glViewport(0, 0, size.x, size.y); + fboViewport(_overlayFramebuffer); // Now render the overlay components together into a single texture //renderOverlays(renderArgs); @@ -285,11 +290,6 @@ void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { } } -void fboViewport(QOpenGLFramebufferObject* fbo) { - auto size = fbo->size(); - glViewport(0, 0, size.width(), size.height()); -} - void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { // Grab current viewport to reset it at the end auto mirrorSize = _mirrorFramebuffer->size(); @@ -342,19 +342,22 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { _mirrorFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glLoadMatrixf(glm::value_ptr(_mirrorCamera.getProjection())); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); { - auto projection = _mirrorCamera.getProjection(); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(glm::value_ptr(projection)); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); renderArgs->_context->syncCache(); qApp->displaySide(renderArgs, _mirrorCamera, true, billboard); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); _mirrorFramebuffer->release(); // if (!billboard) { diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 9cc6bb3cd7..48bb94a89c 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -38,4 +38,8 @@ void Context::render(Batch& batch) { void Context::syncCache() { _backend->syncCache(); +} + +void Context::resetState() { + _backend->resetState(); } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 98ddc7fb64..db88040aa9 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -28,6 +28,7 @@ public: virtual~ Backend() {}; virtual void render(Batch& batch) = 0; virtual void syncCache() = 0; + virtual void resetState() = 0; class TransformObject { public: @@ -112,6 +113,9 @@ public: void syncCache(); + // TODO remove, make all apps set all the state they need + void resetState(); + protected: Context(const Context& context); diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 20a6b60901..b935796ec6 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -656,4 +656,6 @@ void GLBackend::fetchMatrix(GLenum target, glm::mat4 & m) { glGetFloatv(target, glm::value_ptr(m)); } - +void GLBackend::resetState() { + resetPipelineState(0); +} diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index c87394869c..10fffdf97b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -36,6 +36,8 @@ public: // Let's try to avoid to do that as much as possible! virtual void syncCache(); + virtual void resetState(); + // Render Batch create a local Context and execute the batch with it // WARNING: // if syncCache is true, then the gpu::GLBackend will synchornize From 11fff7c6e503866d803e78c917ffb53afe1351f2 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 17 Jun 2015 13:49:42 -0700 Subject: [PATCH 011/121] debugging stack on OSX --- interface/src/Application.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 994a09d65f..f1ba413fed 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -821,6 +821,23 @@ void Application::initializeGL() { InfoView::show(INFO_HELP_PATH, true); } +template +void with_stable_stack_check(F f) { + + GLint mvDepth, prDepth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepth); + glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepth); + + f(); + + GLint mvDepthFinal, prDepthFinal; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepthFinal); + glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepthFinal); + Q_ASSERT(mvDepth == mvDepthFinal); + Q_ASSERT(prDepth == prDepthFinal); + +} + void Application::initializeUi() { AddressBarDialog::registerType(); ErrorDialog::registerType(); @@ -955,12 +972,14 @@ void Application::paintGL() { QSize size = DependencyManager::get()->getFrameBufferSize(); glViewport(0, 0, size.width(), size.height()); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - displaySide(&renderArgs, _myCamera); - _compositor.displayOverlayTexture(&renderArgs); - glPopMatrix(); + with_stable_stack_check([&]{ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + displaySide(&renderArgs, _myCamera); + _compositor.displayOverlayTexture(&renderArgs); + glPopMatrix(); + }); //renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; //if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { From 8a1b51907138d8c09cac0f0182c20dc4c81b692a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 17 Jun 2015 16:06:06 -0700 Subject: [PATCH 012/121] Working on overlays --- interface/src/Application.cpp | 7 +++-- interface/src/devices/OculusManager.cpp | 2 +- interface/src/ui/ApplicationCompositor.cpp | 31 +++++++++++++++------- interface/src/ui/ApplicationOverlay.cpp | 1 - 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ed417ca458..b0fd376586 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -151,6 +151,7 @@ #include "ui/AddressBarDialog.h" #include "ui/UpdateDialog.h" +static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU #if defined(Q_OS_WIN) @@ -932,13 +933,15 @@ void Application::paintGL() { } } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { -#if 0 + // TODO put the mirror modifiers somewhere both the app and the overlay can access it + float _rotateMirror = 0.0f; + float _raiseMirror = 0.0f; + float _scaleMirror = 1.0f; _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); -#endif } // Update camera position diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 98597c4a05..53bacfacbf 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -610,7 +610,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); renderArgs->_renderSide = RenderArgs::MONO; - qApp->displaySide(renderArgs, *_camera, false); + qApp->displaySide(renderArgs, *_camera); //qApp->getApplicationCompositor().displayOverlayTexture(renderArgs); qApp->getApplicationCompositor().displayOverlayTextureHmd(renderArgs, eye); }); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index b0c21cf77d..d78d79b1ab 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -191,6 +191,11 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { return; } + GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); + if (!texture) { + return; + } + updateTooltips(); vec2 canvasSize = qApp->getCanvasSize(); @@ -198,10 +203,6 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { //Handle fading and deactivation/activation of UI gpu::Batch batch; - GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); - if (!texture) { - return; - } renderArgs->_context->syncCache(); auto geometryCache = DependencyManager::get(); @@ -262,28 +263,38 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int return; } + updateTooltips(); + vec2 canvasSize = qApp->getCanvasSize(); _textureAspectRatio = aspect(canvasSize); - updateTooltips(); - renderArgs->_context->syncCache(); auto geometryCache = DependencyManager::get(); gpu::Batch batch; - DependencyManager::get()->useSimpleDrawPipeline(batch); + geometryCache->useSimpleDrawPipeline(batch); batch._glDisable(GL_DEPTH_TEST); batch._glDisable(GL_CULL_FACE); batch._glBindTexture(GL_TEXTURE_2D, texture); batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - batch.setViewTransform(Transform()); batch.setProjectionTransform(qApp->getEyeProjection(eye)); + mat4 eyePose = qApp->getEyePose(eye); glm::mat4 overlayXfm = glm::inverse(eyePose); - batch.setModelTransform(overlayXfm); - drawSphereSection(batch); + +#ifdef DEBUG_OVERLAY + { + batch.setModelTransform(glm::translate(mat4(), vec3(0, 0, -2))); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + } +#else + { + batch.setModelTransform(overlayXfm); + drawSphereSection(batch); + } +#endif // Doesn't actually render renderPointers(batch); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index a35cdce58b..46264730c2 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -46,7 +46,6 @@ static const int MIRROR_VIEW_LEFT_PADDING = 10; static const int MIRROR_VIEW_WIDTH = 265; static const int MIRROR_VIEW_HEIGHT = 215; static const int STATS_HORIZONTAL_OFFSET = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; -static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; static const float MIRROR_REARVIEW_DISTANCE = 0.722f; static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; From 1705eb8f80bfdc5902d4c353552307ecd44b9a49 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 17 Jun 2015 14:49:44 -0700 Subject: [PATCH 013/121] Reverting some changes, putting overlay rendering in its own state manager --- interface/src/Application.cpp | 24 +++++++++----------- libraries/gpu/src/gpu/Context.cpp | 4 ---- libraries/gpu/src/gpu/Context.h | 4 ---- libraries/gpu/src/gpu/GLBackend.cpp | 4 +--- libraries/gpu/src/gpu/GLBackend.h | 2 -- libraries/render-utils/src/GeometryCache.cpp | 1 - 6 files changed, 12 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b0fd376586..f6d4c4afd7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -880,6 +880,16 @@ void Application::paintGL() { _glWidget->makeCurrent(); auto lodManager = DependencyManager::get(); + + { + PerformanceTimer perfTimer("renderOverlay"); + gpu::Context context(new gpu::GLBackend()); + RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), + lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); + _applicationOverlay.renderOverlay(&renderArgs); + } + gpu::Context context(new gpu::GLBackend()); RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, @@ -891,12 +901,7 @@ void Application::paintGL() { OculusManager::beginFrameTiming(); } - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(&renderArgs); - renderArgs._context->resetState(); - } - + PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); @@ -1004,7 +1009,6 @@ void Application::paintGL() { } - if (!OculusManager::isConnected() || OculusManager::allowSwap()) { _glWidget->swapBuffers(); } @@ -1079,12 +1083,6 @@ void Application::resizeGL() { offscreenUi->resize(_glWidget->size()); _glWidget->makeCurrent(); -#if 0 - // update Stats width - // let's set horizontal offset to give stats some margin to mirror - int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; - Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset); -#endif } void Application::updateProjectionMatrix() { diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 48bb94a89c..9cc6bb3cd7 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -38,8 +38,4 @@ void Context::render(Batch& batch) { void Context::syncCache() { _backend->syncCache(); -} - -void Context::resetState() { - _backend->resetState(); } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index db88040aa9..98ddc7fb64 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -28,7 +28,6 @@ public: virtual~ Backend() {}; virtual void render(Batch& batch) = 0; virtual void syncCache() = 0; - virtual void resetState() = 0; class TransformObject { public: @@ -113,9 +112,6 @@ public: void syncCache(); - // TODO remove, make all apps set all the state they need - void resetState(); - protected: Context(const Context& context); diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index b935796ec6..20a6b60901 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -656,6 +656,4 @@ void GLBackend::fetchMatrix(GLenum target, glm::mat4 & m) { glGetFloatv(target, glm::value_ptr(m)); } -void GLBackend::resetState() { - resetPipelineState(0); -} + diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 10fffdf97b..c87394869c 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -36,8 +36,6 @@ public: // Let's try to avoid to do that as much as possible! virtual void syncCache(); - virtual void resetState(); - // Render Batch create a local Context and execute the batch with it // WARNING: // if syncCache is true, then the gpu::GLBackend will synchornize diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 98067e1b81..7a2bbc81f4 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -2405,4 +2405,3 @@ int NetworkMesh::getTranslucentPartCount(const FBXMesh& fbxMesh) const { } return count; } - From a8d3dc721880f9d58f5620174b4a666b8096e438 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 17 Jun 2015 23:50:38 -0700 Subject: [PATCH 014/121] Updating oglplus version --- cmake/externals/oglplus/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt index 23ba0d515e..6556f5a61b 100644 --- a/cmake/externals/oglplus/CMakeLists.txt +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -4,8 +4,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - GIT_REPOSITORY https://github.com/jherico/oglplus.git - GIT_TAG 470d8e56fd6bf3913ceec03d82f42d3bafab2cbe + GIT_REPOSITORY https://github.com/matus-chochlik/oglplus.git + GIT_TAG a2681383928b1166f176512cbe0f95e96fe68d08 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 84c3dab3d8919135b69e8cbf0f63228aec7cc3c9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 00:23:40 -0700 Subject: [PATCH 015/121] Fixing error in stats qml parsing --- interface/resources/qml/Stats.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index c77ab8ec27..0a05bc18a1 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -234,7 +234,6 @@ Hifi.Stats { width: perfText.width + 8 height: perfText.height + 8 color: root.bgColor; - anchors.top: row.bottom + 16 Text { x: 4; y: 4 id: perfText From acdf7c48d9b588771163b7971ceb2e6f2f63c31f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 00:53:19 -0700 Subject: [PATCH 016/121] Adding more explicit error checking --- interface/src/ui/ApplicationOverlay.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 46264730c2..5ca03d8f0a 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -89,8 +90,10 @@ ApplicationOverlay::ApplicationOverlay() : ApplicationOverlay::~ApplicationOverlay() { } + // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { + CHECK_GL_ERROR(); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); buildFramebufferObject(); @@ -102,18 +105,24 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { _overlayFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); fboViewport(_overlayFramebuffer); + CHECK_GL_ERROR(); // Now render the overlay components together into a single texture //renderOverlays(renderArgs); //renderAudioMeter(renderArgs); //renderCameraToggle(renderArgs); renderStatsAndLogs(renderArgs); + CHECK_GL_ERROR(); renderRearView(renderArgs); + CHECK_GL_ERROR(); renderDomainConnectionStatusBorder(renderArgs); + CHECK_GL_ERROR(); renderQmlUi(renderArgs); + CHECK_GL_ERROR(); _overlayFramebuffer->release(); + CHECK_GL_ERROR(); } void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { @@ -446,7 +455,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr gpu::Batch batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); - batch._glDisable(GL_DEPTH); + batch._glDisable(GL_DEPTH_TEST); batch._glDisable(GL_LIGHTING); batch._glEnable(GL_BLEND); batch.setProjectionTransform(mat4()); From dfea571e629dac633c10d7031fccb7dca008ea18 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 00:54:35 -0700 Subject: [PATCH 017/121] Removing a 'using namespace' from a header and tweaking error checking code --- libraries/gpu/src/gpu/GLBackend.cpp | 10 ++++++++++ libraries/gpu/src/gpu/GLBackend.h | 3 +++ libraries/gpu/src/gpu/GLBackendOutput.cpp | 1 + libraries/gpu/src/gpu/GLBackendShared.h | 14 +++++--------- libraries/gpu/src/gpu/GLBackendTexture.cpp | 1 + 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 20a6b60901..1e61c0e6aa 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -12,6 +12,8 @@ #include "GLBackendShared.h" #include +using namespace gpu; + GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = { (&::gpu::GLBackend::do_draw), @@ -141,6 +143,14 @@ bool GLBackend::checkGLError(const char* name) { } } +bool GLBackend::checkGLErrorDebug(const char* name) { +#ifdef DEBUG + checkGLError(name); +#else + Q_UNUSED(name); + return false; +#endif +} void GLBackend::syncCache() { syncTransformStateCache(); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index c87394869c..394c394a3a 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -47,6 +47,9 @@ public: static bool checkGLError(const char* name = nullptr); + // Only checks in debug builds + static bool checkGLErrorDebug(const char* name = nullptr); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index b0dee550d9..903c97f45b 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -11,6 +11,7 @@ #include "GPULogging.h" #include "GLBackendShared.h" +using namespace gpu; GLBackend::GLFramebuffer::GLFramebuffer() {} diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index 92e06e1d11..9f5c93278b 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -17,9 +17,7 @@ #include "Batch.h" -using namespace gpu; - -static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = { +static const GLenum _primitiveToGLmode[gpu::NUM_PRIMITIVES] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, @@ -30,7 +28,7 @@ static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = { GL_QUAD_STRIP, }; -static const GLenum _elementTypeToGLType[NUM_TYPES]= { +static const GLenum _elementTypeToGLType[gpu::NUM_TYPES] = { GL_FLOAT, GL_INT, GL_UNSIGNED_INT, @@ -49,10 +47,8 @@ static const GLenum _elementTypeToGLType[NUM_TYPES]= { GL_UNSIGNED_BYTE }; -#if _DEBUG -#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError(__FUNCTION__) -#else -#define CHECK_GL_ERROR() false -#endif +// Stupid preprocessor trick to turn the line macro into a string +#define CHECK_GL_ERROR_HELPER(x) #x +#define CHECK_GL_ERROR() gpu::GLBackend::checkGLErrorDebug(__FUNCTION__ ":" CHECK_GL_ERROR_HELPER(__LINE__)) #endif diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 999173e5b7..b8f98590ff 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -11,6 +11,7 @@ #include "GPULogging.h" #include "GLBackendShared.h" +using namespace gpu; GLBackend::GLTexture::GLTexture() : _storageStamp(0), From f752534f7c166e3dcf4e453764165674771b1500 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 09:52:36 -0700 Subject: [PATCH 018/121] actionEvent signal, captureActions, began work on hmdControls.js --- examples/hmdControls.js | 87 +++++++++++++++++++ interface/src/Application.cpp | 22 ++--- .../ControllerScriptingInterface.cpp | 1 + .../scripting/ControllerScriptingInterface.h | 7 ++ interface/src/ui/UserInputMapper.cpp | 8 +- .../AbstractControllerScriptingInterface.h | 5 ++ 6 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 examples/hmdControls.js diff --git a/examples/hmdControls.js b/examples/hmdControls.js new file mode 100644 index 0000000000..3e73decaec --- /dev/null +++ b/examples/hmdControls.js @@ -0,0 +1,87 @@ +// +// hmdControls.js +// examples +// +// Created by Sam Gondelman on 6/17/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var MOVE_DISTANCE = 0.5; +var PITCH_INCREMENT = Math.PI / 8; +var YAW_INCREMENT = Math.PI / 8; +var BOOM_SPEED = 0.5; +var THRESHOLD = 0.2; + +var hmdControls = (function () { + + function onActionEvent(action, state) { + if (state < THRESHOLD) { + return; + } + switch (action) { + case 0: // backward + var direction = Quat.getFront(Camera.getOrientation()); + direction = Vec3.multiply(-1, direction); + direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + break; + case 1: // forward + var direction = Quat.getFront(Camera.getOrientation()); + direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + break; + case 2: // left + var direction = Quat.getRight(Camera.getOrientation()); + direction = Vec3.multiply(-1, direction); + direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + break; + case 3: // right + var direction = Quat.getRight(Camera.getOrientation()); + direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + break; + case 4: // down + var direction = Quat.getUp(Camera.getOrientation()); + direction = Vec3.multiply(-1, direction); + direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + break; + case 5: // up + var direction = Quat.getUp(Camera.getOrientation()); + direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + break; + case 6: // yaw left + MyAvatar.bodyYaw = MyAvatar.bodyYaw + YAW_INCREMENT; + break; + case 7: // yaw right + MyAvatar.bodyYaw = MyAvatar.bodyYaw - YAW_INCREMENT; + break; + case 8: // pitch down + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - PITCH_INCREMENT)); + break; + case 9: // pitch up + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + PITCH_INCREMENT)); + break; + default: + break; + } + } + + function setUp() { + Controller.captureActionEvents(); + + Controller.actionEvent.connect(onActionEvent); + } + + function tearDown() { + Controller.releaseActionEvents(); + } + + setUp(); + Script.scriptEnding.connect(tearDown); +}()); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 651e343087..ba6c86cafb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2505,16 +2505,18 @@ void Application::update(float deltaTime) { // Transfer the user inputs to the driveKeys _myAvatar->clearDriveKeys(); - _myAvatar->setDriveKeys(FWD, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_FORWARD)); - _myAvatar->setDriveKeys(BACK, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_BACKWARD)); - _myAvatar->setDriveKeys(UP, _userInputMapper.getActionState(UserInputMapper::VERTICAL_UP)); - _myAvatar->setDriveKeys(DOWN, _userInputMapper.getActionState(UserInputMapper::VERTICAL_DOWN)); - _myAvatar->setDriveKeys(LEFT, _userInputMapper.getActionState(UserInputMapper::LATERAL_LEFT)); - _myAvatar->setDriveKeys(RIGHT, _userInputMapper.getActionState(UserInputMapper::LATERAL_RIGHT)); - _myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP)); - _myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN)); - _myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT)); - _myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT)); + if (!_controllerScriptingInterface.areActionsCaptured()) { + _myAvatar->setDriveKeys(FWD, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_FORWARD)); + _myAvatar->setDriveKeys(BACK, _userInputMapper.getActionState(UserInputMapper::LONGITUDINAL_BACKWARD)); + _myAvatar->setDriveKeys(UP, _userInputMapper.getActionState(UserInputMapper::VERTICAL_UP)); + _myAvatar->setDriveKeys(DOWN, _userInputMapper.getActionState(UserInputMapper::VERTICAL_DOWN)); + _myAvatar->setDriveKeys(LEFT, _userInputMapper.getActionState(UserInputMapper::LATERAL_LEFT)); + _myAvatar->setDriveKeys(RIGHT, _userInputMapper.getActionState(UserInputMapper::LATERAL_RIGHT)); + _myAvatar->setDriveKeys(ROT_UP, _userInputMapper.getActionState(UserInputMapper::PITCH_UP)); + _myAvatar->setDriveKeys(ROT_DOWN, _userInputMapper.getActionState(UserInputMapper::PITCH_DOWN)); + _myAvatar->setDriveKeys(ROT_LEFT, _userInputMapper.getActionState(UserInputMapper::YAW_LEFT)); + _myAvatar->setDriveKeys(ROT_RIGHT, _userInputMapper.getActionState(UserInputMapper::YAW_RIGHT)); + } _myAvatar->setDriveKeys(BOOM_IN, _userInputMapper.getActionState(UserInputMapper::BOOM_IN)); _myAvatar->setDriveKeys(BOOM_OUT, _userInputMapper.getActionState(UserInputMapper::BOOM_OUT)); diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 5bee51c9b9..0d9cf38705 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -28,6 +28,7 @@ ControllerScriptingInterface::ControllerScriptingInterface() : { } + static int actionMetaTypeId = qRegisterMetaType(); static int inputChannelMetaTypeId = qRegisterMetaType(); static int inputMetaTypeId = qRegisterMetaType(); diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 3a54826195..44b59beded 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -72,12 +72,15 @@ public: void emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); } void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } + + void emitActionEvents(); bool isKeyCaptured(QKeyEvent* event) const; bool isKeyCaptured(const KeyEvent& event) const; bool isMouseCaptured() const { return _mouseCaptured; } bool isTouchCaptured() const { return _touchCaptured; } bool isWheelCaptured() const { return _wheelCaptured; } + bool areActionsCaptured() const { return _actionsCaptured; } bool isJoystickCaptured(int joystickIndex) const; void updateInputControllers(); @@ -122,6 +125,9 @@ public slots: virtual void captureWheelEvents() { _wheelCaptured = true; } virtual void releaseWheelEvents() { _wheelCaptured = false; } + + virtual void captureActionEvents() { _actionsCaptured = true; } + virtual void releaseActionEvents() { _actionsCaptured = false; } virtual void captureJoystick(int joystickIndex); virtual void releaseJoystick(int joystickIndex); @@ -142,6 +148,7 @@ private: bool _mouseCaptured; bool _touchCaptured; bool _wheelCaptured; + bool _actionsCaptured; QMultiMap _capturedKeys; QSet _capturedJoysticks; diff --git a/interface/src/ui/UserInputMapper.cpp b/interface/src/ui/UserInputMapper.cpp index 127aead761..985353e31e 100755 --- a/interface/src/ui/UserInputMapper.cpp +++ b/interface/src/ui/UserInputMapper.cpp @@ -8,9 +8,12 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "UserInputMapper.h" #include +#include "Application.h" + +#include "UserInputMapper.h" + // UserInputMapper Class @@ -207,6 +210,9 @@ void UserInputMapper::update(float deltaTime) { // Scale all the channel step with the scale for (auto i = 0; i < NUM_ACTIONS; i++) { _actionStates[i] *= _actionScales[i]; + if (_actionStates[i] > 0) { + emit Application::getInstance()->getControllerScriptingInterface()->actionEvent(i, _actionStates[i]); + } } } diff --git a/libraries/script-engine/src/AbstractControllerScriptingInterface.h b/libraries/script-engine/src/AbstractControllerScriptingInterface.h index 43076039a9..52c18bc8cf 100644 --- a/libraries/script-engine/src/AbstractControllerScriptingInterface.h +++ b/libraries/script-engine/src/AbstractControllerScriptingInterface.h @@ -83,6 +83,9 @@ public slots: virtual void captureWheelEvents() = 0; virtual void releaseWheelEvents() = 0; + + virtual void captureActionEvents() = 0; + virtual void releaseActionEvents() = 0; virtual void captureJoystick(int joystickIndex) = 0; virtual void releaseJoystick(int joystickIndex) = 0; @@ -111,6 +114,8 @@ signals: void touchUpdateEvent(const TouchEvent& event); void wheelEvent(const WheelEvent& event); + + void actionEvent(int action, float state); }; From 0c7c5f6301186cc9dd2917307be916308e898d6d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 28 May 2015 08:38:27 -0700 Subject: [PATCH 019/121] Limit the speed of eye saccades --- interface/src/avatar/Head.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 0982a33826..5298530a5f 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -128,14 +128,21 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { const float AVERAGE_SACCADE_INTERVAL = 4.0f; const float MICROSACCADE_MAGNITUDE = 0.002f; const float SACCADE_MAGNITUDE = 0.04f; - + const float MAXIMUM_SACCADE_SPEED = 0.8f; + if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) { _saccadeTarget = MICROSACCADE_MAGNITUDE * randVector(); } else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) { _saccadeTarget = SACCADE_MAGNITUDE * randVector(); } - _saccade += (_saccadeTarget - _saccade) * 0.50f; - + + glm::vec3 saccadeDelta = (_saccadeTarget - _saccade) * 0.5f; + float speed = glm::length(saccadeDelta) / deltaTime; + if (speed > MAXIMUM_SACCADE_SPEED) { + saccadeDelta = saccadeDelta * MAXIMUM_SACCADE_SPEED / speed; + } + _saccade += saccadeDelta; + // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; const float TALKING_LOUDNESS = 100.0f; From fdf5860c4f68540a024ab4c6bcc0fa185285293c Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 18 Jun 2015 10:39:58 -0700 Subject: [PATCH 020/121] 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 c88ba2c6d1f4b6b0862a8548c2c6b191d7e5195c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Jun 2015 10:41:51 -0700 Subject: [PATCH 021/121] Increase the saccade interval --- interface/src/avatar/Head.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 5298530a5f..69f7754703 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -124,8 +124,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { if (!(_isFaceTrackerConnected || billboard)) { // Update eye saccades - const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; - const float AVERAGE_SACCADE_INTERVAL = 4.0f; + const float AVERAGE_MICROSACCADE_INTERVAL = 1.0f; + const float AVERAGE_SACCADE_INTERVAL = 6.0f; const float MICROSACCADE_MAGNITUDE = 0.002f; const float SACCADE_MAGNITUDE = 0.04f; const float MAXIMUM_SACCADE_SPEED = 0.8f; From 440491700303d67a925bc48707c7cd7e926f7fb1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 11:16:25 -0700 Subject: [PATCH 022/121] Fix HMD projection post-merge --- interface/src/devices/OculusManager.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 8032fb7065..3686143bdc 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -212,8 +212,6 @@ bool OculusManager::_eyePerFrameMode = false; ovrEyeType OculusManager::_lastEyeRendered = ovrEye_Count; ovrSizei OculusManager::_recommendedTexSize = { 0, 0 }; float OculusManager::_offscreenRenderScale = 1.0; - -static glm::mat4 _eyeProjections[ovrEye_Count]; static glm::mat4 _combinedProjection; static ovrPosef _eyeRenderPoses[ovrEye_Count]; ovrRecti OculusManager::_eyeViewports[ovrEye_Count]; @@ -266,7 +264,13 @@ void OculusManager::connect(QOpenGLContext* shareContext) { for_each_eye([&](ovrEyeType eye) { _eyeFov[eye] = _ovrHmd->DefaultEyeFov[eye]; + _eyeProjection[eye] = toGlm(ovrMatrix4f_Projection(_eyeFov[eye], + DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded)); }); + ovrFovPort combinedFov = _ovrHmd->MaxEyeFov[0]; + combinedFov.RightTan = _ovrHmd->MaxEyeFov[1].RightTan; + _combinedProjection = toGlm(ovrMatrix4f_Projection(combinedFov, + DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded)); _recommendedTexSize = ovrHmd_GetFovTextureSize(_ovrHmd, ovrEye_Left, _eyeFov[ovrEye_Left], 1.0f); _renderTargetSize = { _recommendedTexSize.w * 2, _recommendedTexSize.h }; @@ -523,18 +527,12 @@ void OculusManager::endFrameTiming() { //Sets the camera FoV and aspect ratio void OculusManager::configureCamera(Camera& camera) { - ovrFovPort fov; if (_activeEye == ovrEye_Count) { // When not rendering, provide a FOV encompasing both eyes - fov = _eyeFov[0]; - fov.RightTan = _eyeFov[1].RightTan; - } else { - // When rendering, provide the exact FOV - fov = _eyeFov[_activeEye]; - } - // Convert the FOV to the correct projection matrix - glm::mat4 projection = toGlm(ovrMatrix4f_Projection(fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded)); - camera.setProjection(projection); + camera.setProjection(_combinedProjection); + return; + } + camera.setProjection(_eyeProjection[_activeEye]); } //Displays everything for the oculus, frame timing must be active @@ -812,7 +810,7 @@ int OculusManager::getHMDScreen() { } mat4 OculusManager::getEyeProjection(int eye) { - return _eyeProjections[eye]; + return _eyeProjection[eye]; } mat4 OculusManager::getEyePose(int eye) { From 1047703718f444d1b929d331b82b0289d2ed153f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Jun 2015 11:18:56 -0700 Subject: [PATCH 023/121] 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 0cdee2d6ec9c092db92bddd9ae20a777e2c3ed8a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 12:14:55 -0700 Subject: [PATCH 024/121] preprocessor error on Linux/Mac --- libraries/gpu/src/gpu/GLBackendShared.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index 9f5c93278b..27f58fcbe3 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -49,6 +49,8 @@ static const GLenum _elementTypeToGLType[gpu::NUM_TYPES] = { // Stupid preprocessor trick to turn the line macro into a string #define CHECK_GL_ERROR_HELPER(x) #x -#define CHECK_GL_ERROR() gpu::GLBackend::checkGLErrorDebug(__FUNCTION__ ":" CHECK_GL_ERROR_HELPER(__LINE__)) +// FIXME doesn't build on Linux or Mac. Hmmmm +// #define CHECK_GL_ERROR() gpu::GLBackend::checkGLErrorDebug(__FUNCTION__ ":" CHECK_GL_ERROR_HELPER(__LINE__)) +#define CHECK_GL_ERROR() gpu::GLBackend::checkGLErrorDebug(__FUNCTION__) #endif From bffc1a38a7838fb96936cb926e5db07e63fc70e9 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 18 Jun 2015 12:33:05 -0700 Subject: [PATCH 025/121] 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 026/121] 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 1243c547671a9fa1ae5664fa1b75ffb56dc7a424 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 12:44:57 -0700 Subject: [PATCH 027/121] More merge bugs --- interface/src/devices/OculusManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 3686143bdc..84469f8b29 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -709,7 +709,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const }); // restore our normal viewport - ovrHmd_EndFrame(_ovrHmd, eyeRenderPose, _eyeTextures); + ovrHmd_EndFrame(_ovrHmd, _eyeRenderPoses, _eyeTextures); glCanvas->makeCurrent(); #endif From 7bbaf026f3d5ded6b039545bc0d2ae5649e2e574 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 18 Jun 2015 13:33:37 -0700 Subject: [PATCH 028/121] use a monospace font on all platforms --- interface/resources/qml/Stats.qml | 4 ++-- interface/src/ui/Stats.cpp | 3 +++ interface/src/ui/Stats.h | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index c77ab8ec27..e52c07dda3 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -239,8 +239,8 @@ Hifi.Stats { x: 4; y: 4 id: perfText color: root.fontColor - font.family: "Lucida Console" - text: "-------------------------------------------------------- Function " + + font.family: root.monospaceFont + text: "-------------------------------------------------------- Function " + "------------------------------------------------------- --msecs- -calls--\n" + root.timingStats; } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index f541357486..c1d77b5fc2 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -14,6 +14,7 @@ #include "Stats.h" #include +#include #include #include @@ -50,6 +51,8 @@ Stats* Stats::getInstance() { Stats::Stats(QQuickItem* parent) : QQuickItem(parent) { INSTANCE = this; + const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + _monospaceFont = font.family(); } bool Stats::includeTimingRecord(const QString& name) { diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index efe340ed18..58d920d9a5 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -32,6 +32,8 @@ class Stats : public QQuickItem { HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) + Q_PROPERTY(QString monospaceFont READ monospaceFont) + STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, framerate, 0) STATS_PROPERTY(int, avatarCount, 0) @@ -79,7 +81,9 @@ public: Stats(QQuickItem* parent = nullptr); bool includeTimingRecord(const QString& name); void setRenderDetails(const RenderDetails& details); - + const QString& monospaceFont() { + return _monospaceFont; + } void updateStats(); bool isExpanded() { return _expanded; } @@ -141,6 +145,7 @@ private: bool _resetRecentMaxPacketsSoon{ true }; bool _expanded{ false }; bool _timingExpanded{ false }; + QString _monospaceFont; }; #endif // hifi_Stats_h From 100f7acddc89e8e003c9dfc017b2a33692ca8bc6 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 18 Jun 2015 13:46:27 -0700 Subject: [PATCH 029/121] Working on tooltip placement --- 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 f1504317e2..0ad3efc5a5 100644 --- a/interface/resources/qml/Tooltip.qml +++ b/interface/resources/qml/Tooltip.qml @@ -6,8 +6,9 @@ import "styles" Hifi.Tooltip { id: root HifiConstants { id: hifi } - x: lastMousePosition.x - y: lastMousePosition.y + // FIXME adjust position based on the edges of the screen + x: lastMousePosition.x + 20 + y: lastMousePosition.y + 5 implicitWidth: border.implicitWidth implicitHeight: border.implicitHeight From fd0efd91ff60425b1d0c457c2734dabd5337f764 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 13:59:37 -0700 Subject: [PATCH 030/121] added shift action, added timers and fast mode to hmdControls.js --- examples/hmdControls.js | 82 ++++++++++++++++--- interface/src/devices/Joystick.cpp | 2 + interface/src/devices/KeyboardMouseDevice.cpp | 2 + interface/src/devices/SixenseManager.cpp | 4 + interface/src/ui/UserInputMapper.cpp | 2 + interface/src/ui/UserInputMapper.h | 2 + 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/examples/hmdControls.js b/examples/hmdControls.js index 3e73decaec..aa3990acf2 100644 --- a/examples/hmdControls.js +++ b/examples/hmdControls.js @@ -9,73 +9,129 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var MOVE_DISTANCE = 0.5; -var PITCH_INCREMENT = Math.PI / 8; -var YAW_INCREMENT = Math.PI / 8; +var MOVE_DISTANCE = 0.3; +var PITCH_INCREMENT = 0.5; // degrees +var VR_PITCH_INCREMENT = 15.0; // degrees +var YAW_INCREMENT = 0.5; // degrees +var VR_YAW_INCREMENT = 15.0; // degrees var BOOM_SPEED = 0.5; var THRESHOLD = 0.2; +var CAMERA_UPDATE_TIME = 0.5; +var pitchTimer = CAMERA_UPDATE_TIME; +var yawTimer = CAMERA_UPDATE_TIME; + +var shifted = false; +var SHIFT_UPDATE_TIME = 0.5; +var shiftTimer = SHIFT_UPDATE_TIME; +var SHIFT_MAG = 4.0; + var hmdControls = (function () { function onActionEvent(action, state) { if (state < THRESHOLD) { + if (action == 6 || action == 7) { + yawTimer = CAMERA_UPDATE_TIME; + } else if (action == 8 || action == 9) { + pitchTimer = CAMERA_UPDATE_TIME; + } return; } switch (action) { case 0: // backward var direction = Quat.getFront(Camera.getOrientation()); direction = Vec3.multiply(-1, direction); - direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); MyAvatar.position = Vec3.sum(MyAvatar.position, direction); break; case 1: // forward var direction = Quat.getFront(Camera.getOrientation()); - direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); MyAvatar.position = Vec3.sum(MyAvatar.position, direction); break; case 2: // left var direction = Quat.getRight(Camera.getOrientation()); direction = Vec3.multiply(-1, direction); - direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); MyAvatar.position = Vec3.sum(MyAvatar.position, direction); break; case 3: // right var direction = Quat.getRight(Camera.getOrientation()); - direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); MyAvatar.position = Vec3.sum(MyAvatar.position, direction); break; case 4: // down var direction = Quat.getUp(Camera.getOrientation()); direction = Vec3.multiply(-1, direction); - direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); MyAvatar.position = Vec3.sum(MyAvatar.position, direction); break; case 5: // up var direction = Quat.getUp(Camera.getOrientation()); - direction = Vec3.multiply(Vec3.normalize(direction), MOVE_DISTANCE); + direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); MyAvatar.position = Vec3.sum(MyAvatar.position, direction); break; case 6: // yaw left - MyAvatar.bodyYaw = MyAvatar.bodyYaw + YAW_INCREMENT; + if (yawTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.bodyYaw = MyAvatar.bodyYaw + (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); + yawTimer = CAMERA_UPDATE_TIME; + } else if (!Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.bodyYaw = MyAvatar.bodyYaw + (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); + } break; case 7: // yaw right - MyAvatar.bodyYaw = MyAvatar.bodyYaw - YAW_INCREMENT; + if (yawTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.bodyYaw = MyAvatar.bodyYaw - (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); + yawTimer = CAMERA_UPDATE_TIME; + } else if (!Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.bodyYaw = MyAvatar.bodyYaw - (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); + } break; case 8: // pitch down - MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - PITCH_INCREMENT)); + if (pitchTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - (shifted ? SHIFT_MAG * VR_PITCH_INCREMENT : VR_PITCH_INCREMENT))); + pitchTimer = CAMERA_UPDATE_TIME; + } else if (!Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); + } break; case 9: // pitch up - MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + PITCH_INCREMENT)); + if (pitchTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + (shifted ? SHIFT_MAG * VR_PITCH_INCREMENT : VR_PITCH_INCREMENT))); + pitchTimer = CAMERA_UPDATE_TIME; + } else if (!Menu.isOptionChecked("Enable VR Mode")) { + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); + } + break; + case 12: // shift + if (shiftTimer < 0.0) { + shifted = !shifted; + shiftTimer = SHIFT_UPDATE_TIME; + } break; default: break; } } + function update(dt) { + if (yawTimer >= 0.0) { + yawTimer = yawTimer - dt; + } + if (pitchTimer >= 0.0) { + pitchTimer = pitchTimer - dt; + } + if (shiftTimer >= 0.0) { + shiftTimer = shiftTimer - dt; + } + } + function setUp() { Controller.captureActionEvents(); Controller.actionEvent.connect(onActionEvent); + + Script.update.connect(update); } function tearDown() { diff --git a/interface/src/devices/Joystick.cpp b/interface/src/devices/Joystick.cpp index 07f3c4873c..fcfee85b75 100644 --- a/interface/src/devices/Joystick.cpp +++ b/interface/src/devices/Joystick.cpp @@ -210,6 +210,8 @@ void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { // Zoom mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(RIGHT_SHOULDER), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), BOOM_SPEED/2.0f); mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(LEFT_SHOULDER), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), BOOM_SPEED/2.0f); + + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(SDL_CONTROLLER_BUTTON_LEFTSHOULDER)); #endif } diff --git a/interface/src/devices/KeyboardMouseDevice.cpp b/interface/src/devices/KeyboardMouseDevice.cpp index 9fadf7be82..e070e002c2 100755 --- a/interface/src/devices/KeyboardMouseDevice.cpp +++ b/interface/src/devices/KeyboardMouseDevice.cpp @@ -276,6 +276,8 @@ void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) { mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(MOUSE_AXIS_WHEEL_X_POS), BUTTON_YAW_SPEED); #endif + + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(Qt::Key_Space)); } diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index c2a53508e3..c94dd52f4f 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -724,6 +724,10 @@ void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) { mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(BUTTON_3, 1), BUTTON_MOVE_SPEED); mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(BUTTON_1, 1), BUTTON_MOVE_SPEED); + + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_2, 0)); + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_2, 1)); + } float SixenseManager::getButton(int channel) const { diff --git a/interface/src/ui/UserInputMapper.cpp b/interface/src/ui/UserInputMapper.cpp index 985353e31e..b5fcbebda6 100755 --- a/interface/src/ui/UserInputMapper.cpp +++ b/interface/src/ui/UserInputMapper.cpp @@ -247,6 +247,7 @@ void UserInputMapper::assignDefaulActionScales() { _actionScales[PITCH_UP] = 1.0f; // 1 degree per unit _actionScales[BOOM_IN] = 1.0f; // 1m per unit _actionScales[BOOM_OUT] = 1.0f; // 1m per unit + _actionStates[SHIFT] = 1.0f; // on } // This is only necessary as long as the actions are hardcoded @@ -264,4 +265,5 @@ void UserInputMapper::createActionNames() { _actionNames[PITCH_UP] = "PITCH_UP"; _actionNames[BOOM_IN] = "BOOM_IN"; _actionNames[BOOM_OUT] = "BOOM_OUT"; + _actionNames[SHIFT] = "SHIFT"; } \ No newline at end of file diff --git a/interface/src/ui/UserInputMapper.h b/interface/src/ui/UserInputMapper.h index 91aa724ea6..0093c36eec 100755 --- a/interface/src/ui/UserInputMapper.h +++ b/interface/src/ui/UserInputMapper.h @@ -139,6 +139,8 @@ public: BOOM_IN, BOOM_OUT, + + SHIFT, NUM_ACTIONS, }; From 1bae1d6065ef96b67bfe07393c16257da2c476f7 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 18 Jun 2015 13:59:48 -0700 Subject: [PATCH 031/121] Changing font size for timings --- interface/resources/qml/Stats.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index e52c07dda3..eb1cb1d337 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -240,6 +240,7 @@ Hifi.Stats { id: perfText color: root.fontColor font.family: root.monospaceFont + font.pixelSize: 10 text: "-------------------------------------------------------- Function " + "------------------------------------------------------- --msecs- -calls--\n" + root.timingStats; From 96ac5070f67d1a3ac8a4f6d2eb9c8e6ad1a965c8 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 18 Jun 2015 14:00:17 -0700 Subject: [PATCH 032/121] Adding some more protection to the viewport --- interface/src/ui/ApplicationOverlay.cpp | 51 +++++++++---------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 46264730c2..e278820195 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -92,11 +92,14 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); + + // TODO move to Application::idle()? + Stats::getInstance()->updateStats(); buildFramebufferObject(); // First render the mirror to the mirror FBO - renderRearViewToFbo(renderArgs); + // renderRearViewToFbo(renderArgs); // Execute the batch into our framebuffer _overlayFramebuffer->bind(); @@ -104,12 +107,15 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { fboViewport(_overlayFramebuffer); // Now render the overlay components together into a single texture - //renderOverlays(renderArgs); + renderOverlays(renderArgs); + fboViewport(_overlayFramebuffer); //renderAudioMeter(renderArgs); //renderCameraToggle(renderArgs); + fboViewport(_overlayFramebuffer); renderStatsAndLogs(renderArgs); - renderRearView(renderArgs); - + fboViewport(_overlayFramebuffer); + // renderRearView(renderArgs); + // fboViewport(_overlayFramebuffer); renderDomainConnectionStatusBorder(renderArgs); renderQmlUi(renderArgs); @@ -153,6 +159,7 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); + fboViewport(_overlayFramebuffer); } void ApplicationOverlay::renderCameraToggle(RenderArgs* renderArgs) { @@ -171,6 +178,7 @@ void ApplicationOverlay::renderCameraToggle(RenderArgs* renderArgs) { } DependencyManager::get()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, boxed); + fboViewport(_overlayFramebuffer); } void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { @@ -287,6 +295,7 @@ void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { audioLevel, AUDIO_METER_HEIGHT, quadColor, _audioBlueQuad); } + fboViewport(_overlayFramebuffer); } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { @@ -296,16 +305,9 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { float fov = MIRROR_FIELD_OF_VIEW; MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); // bool eyeRelativeCamera = false; - bool billboard = false; - if (billboard) { - fov = BILLBOARD_FIELD_OF_VIEW; // degees - _mirrorCamera.setPosition(myAvatar->getPosition() + - myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * myAvatar->getScale()); - - } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { + if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { _mirrorCamera.setPosition(myAvatar->getChestPosition() + myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale()); - } else { // HEAD zoom level // FIXME note that the positioing of the camera relative to the avatar can suffer limited // precision as the user's position moves further away from the origin. Thus at @@ -330,14 +332,7 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { _mirrorCamera.setRotation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); // set the bounds of rear mirror view - if (billboard) { - //QSize size = DependencyManager::get()->getFrameBufferSize(); - //glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - //glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); - } else { - auto mirrorSize = _mirrorFramebuffer->size(); - fboViewport(_mirrorFramebuffer); - } + fboViewport(_mirrorFramebuffer); _mirrorFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -351,23 +346,14 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); { renderArgs->_context->syncCache(); - qApp->displaySide(renderArgs, _mirrorCamera, true, billboard); + qApp->displaySide(renderArgs, _mirrorCamera, true, false); } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); _mirrorFramebuffer->release(); - - // if (!billboard) { - // _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); - // } - - // // reset Viewport and projection matrix - // glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - // glDisable(GL_SCISSOR_TEST); - // updateProjectionMatrix(_myCamera, updateViewFrustum); - //} + fboViewport(_overlayFramebuffer); } void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { @@ -399,7 +385,7 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { // Display stats and log text onscreen // Determine whether to compute timing details - Stats::getInstance()->updateStats(); + /* // Show on-screen msec timer @@ -425,6 +411,7 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { glEnable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + fboViewport(_overlayFramebuffer); */ } From 68595ef5dc90fb2eab487ef050677c0195109f6d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 12:47:23 -0700 Subject: [PATCH 033/121] Delete sync object after use --- interface/src/devices/OculusManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 84469f8b29..be8e18c038 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -701,6 +701,7 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const // rendering to complete before it starts the distortion rendering, // but without triggering a CPU/GPU synchronization glWaitSync(syncObject, 0, GL_TIMEOUT_IGNORED); + glDeleteSync(syncObject); GLuint textureId = gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)); for_each_eye([&](ovrEyeType eye) { From 53bbd519a3da0246156c0888ae65e63fac4e3cb1 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 14:37:09 -0700 Subject: [PATCH 034/121] two new customizable actions for use in js --- interface/src/devices/Joystick.cpp | 11 +++++------ interface/src/devices/KeyboardMouseDevice.cpp | 3 ++- interface/src/devices/SixenseManager.cpp | 3 +++ interface/src/ui/UserInputMapper.cpp | 4 ++++ interface/src/ui/UserInputMapper.h | 3 +++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/interface/src/devices/Joystick.cpp b/interface/src/devices/Joystick.cpp index fcfee85b75..8418b39712 100644 --- a/interface/src/devices/Joystick.cpp +++ b/interface/src/devices/Joystick.cpp @@ -173,9 +173,7 @@ void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { // Button controls mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(SDL_CONTROLLER_BUTTON_Y), DPAD_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(SDL_CONTROLLER_BUTTON_A), DPAD_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(SDL_CONTROLLER_BUTTON_X), JOYSTICK_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(SDL_CONTROLLER_BUTTON_B), JOYSTICK_YAW_SPEED); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(SDL_CONTROLLER_BUTTON_X), DPAD_MOVE_SPEED); // Zoom mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(RIGHT_SHOULDER), BOOM_SPEED); @@ -203,15 +201,16 @@ void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { // Button controls mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(SDL_CONTROLLER_BUTTON_Y), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.0f); - mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(SDL_CONTROLLER_BUTTON_A), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.0f); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(SDL_CONTROLLER_BUTTON_X), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_YAW_SPEED/2.0f); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(SDL_CONTROLLER_BUTTON_B), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), JOYSTICK_YAW_SPEED/2.0f); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(SDL_CONTROLLER_BUTTON_X), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), DPAD_MOVE_SPEED/2.0f); // Zoom mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(RIGHT_SHOULDER), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), BOOM_SPEED/2.0f); mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(LEFT_SHOULDER), makeInput(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), BOOM_SPEED/2.0f); mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(SDL_CONTROLLER_BUTTON_LEFTSHOULDER)); + + mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(SDL_CONTROLLER_BUTTON_B)); + mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(SDL_CONTROLLER_BUTTON_A)); #endif } diff --git a/interface/src/devices/KeyboardMouseDevice.cpp b/interface/src/devices/KeyboardMouseDevice.cpp index e070e002c2..e04c27ae88 100755 --- a/interface/src/devices/KeyboardMouseDevice.cpp +++ b/interface/src/devices/KeyboardMouseDevice.cpp @@ -278,7 +278,8 @@ void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) { #endif mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(Qt::Key_Space)); - + mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(Qt::Key_R)); + mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(Qt::Key_T)); } float KeyboardMouseDevice::getButton(int channel) const { diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index c94dd52f4f..cfcc479172 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -727,6 +727,9 @@ void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) { mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_2, 0)); mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_2, 1)); + + mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(BUTTON_4, 0)); + mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(BUTTON_4, 1)); } diff --git a/interface/src/ui/UserInputMapper.cpp b/interface/src/ui/UserInputMapper.cpp index b5fcbebda6..af5c98c44b 100755 --- a/interface/src/ui/UserInputMapper.cpp +++ b/interface/src/ui/UserInputMapper.cpp @@ -248,6 +248,8 @@ void UserInputMapper::assignDefaulActionScales() { _actionScales[BOOM_IN] = 1.0f; // 1m per unit _actionScales[BOOM_OUT] = 1.0f; // 1m per unit _actionStates[SHIFT] = 1.0f; // on + _actionStates[ACTION1] = 1.0f; // default + _actionStates[ACTION2] = 1.0f; // default } // This is only necessary as long as the actions are hardcoded @@ -266,4 +268,6 @@ void UserInputMapper::createActionNames() { _actionNames[BOOM_IN] = "BOOM_IN"; _actionNames[BOOM_OUT] = "BOOM_OUT"; _actionNames[SHIFT] = "SHIFT"; + _actionNames[ACTION1] = "ACTION1"; + _actionNames[ACTION2] = "ACTION2"; } \ No newline at end of file diff --git a/interface/src/ui/UserInputMapper.h b/interface/src/ui/UserInputMapper.h index 0093c36eec..800f181dcb 100755 --- a/interface/src/ui/UserInputMapper.h +++ b/interface/src/ui/UserInputMapper.h @@ -141,6 +141,9 @@ public: BOOM_OUT, SHIFT, + + ACTION1, + ACTION2, NUM_ACTIONS, }; From edfb25bfe2290f4f1fbe66ec9b549bf7deaa891c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 15:05:32 -0700 Subject: [PATCH 035/121] Removing debug define for VR overlay --- interface/src/ui/ApplicationCompositor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 9ba69437e6..d78d79b1ab 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -284,7 +284,6 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int mat4 eyePose = qApp->getEyePose(eye); glm::mat4 overlayXfm = glm::inverse(eyePose); -#define DEBUG_OVERLAY #ifdef DEBUG_OVERLAY { batch.setModelTransform(glm::translate(mat4(), vec3(0, 0, -2))); From c84a6cbf28819dfca728bca6c301b8113fbe4930 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 16:05:58 -0700 Subject: [PATCH 036/121] added warping --- examples/hmdControls.js | 113 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 9 deletions(-) diff --git a/examples/hmdControls.js b/examples/hmdControls.js index aa3990acf2..6634c48491 100644 --- a/examples/hmdControls.js +++ b/examples/hmdControls.js @@ -11,7 +11,6 @@ var MOVE_DISTANCE = 0.3; var PITCH_INCREMENT = 0.5; // degrees -var VR_PITCH_INCREMENT = 15.0; // degrees var YAW_INCREMENT = 0.5; // degrees var VR_YAW_INCREMENT = 15.0; // degrees var BOOM_SPEED = 0.5; @@ -26,6 +25,32 @@ var SHIFT_UPDATE_TIME = 0.5; var shiftTimer = SHIFT_UPDATE_TIME; var SHIFT_MAG = 4.0; +var warpActive = false; +var WARP_UPDATE_TIME = .5; +var warpTimer = WARP_UPDATE_TIME; + +var warpPosition = { x: 0, y: 0, z: 0 }; + +var WARP_SPHERE_SIZE = 1; +var warpSphere = Overlays.addOverlay("sphere", { + position: { x: 0, y: 0, z: 0 }, + size: WARP_SPHERE_SIZE, + color: { red: 0, green: 255, blue: 0 }, + alpha: 1.0, + solid: true, + visible: false, +}); + +var WARP_LINE_HEIGHT = 10; +var warpLine = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z:0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 255, blue: 255}, + alpha: 1, + lineWidth: 5, + visible: false, +}); + var hmdControls = (function () { function onActionEvent(action, state) { @@ -88,18 +113,12 @@ var hmdControls = (function () { } break; case 8: // pitch down - if (pitchTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - (shifted ? SHIFT_MAG * VR_PITCH_INCREMENT : VR_PITCH_INCREMENT))); - pitchTimer = CAMERA_UPDATE_TIME; - } else if (!Menu.isOptionChecked("Enable VR Mode")) { + if (!Menu.isOptionChecked("Enable VR Mode")) { MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); } break; case 9: // pitch up - if (pitchTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + (shifted ? SHIFT_MAG * VR_PITCH_INCREMENT : VR_PITCH_INCREMENT))); - pitchTimer = CAMERA_UPDATE_TIME; - } else if (!Menu.isOptionChecked("Enable VR Mode")) { + if (!Menu.isOptionChecked("Enable VR Mode")) { MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); } break; @@ -109,6 +128,23 @@ var hmdControls = (function () { shiftTimer = SHIFT_UPDATE_TIME; } break; + case 13: // action1 = start/end warp + if (warpTimer < 0.0) { + warpActive = !warpActive; + if (!warpActive) { + finishWarp(); + } + warpTimer = WARP_UPDATE_TIME; + } + break; + case 14: // action2 = cancel warp + warpActive = false; + Overlays.editOverlay(warpSphere, { + visible: false, + }); + Overlays.editOverlay(warpLine, { + visible: false, + }); default: break; } @@ -124,6 +160,65 @@ var hmdControls = (function () { if (shiftTimer >= 0.0) { shiftTimer = shiftTimer - dt; } + if (warpTimer >= 0.0) { + warpTimer = warpTimer - dt; + } + + if (warpActive) { + updateWarp(); + } + } + + function updateWarp() { + var look = Quat.getFront(Camera.getOrientation()); + var pitch = Math.asin(look.y); + + // Get relative to looking straight down + pitch += Math.PI / 2; + + // Scale up + pitch *= 2; + var distance = pitch * pitch * pitch; + + var warpDirection = Vec3.normalize({ x: look.x, y: 0, z: look.z }); + warpPosition = Vec3.multiply(warpDirection, distance); + warpPosition = Vec3.sum(MyAvatar.position, warpPosition); + + // Commented out until ray picking can be fixed + // var pickRay = { + // origin: Vec3.sum(warpPosition, WARP_PICK_OFFSET), + // direction: { x: 0, y: -1, z: 0 } + // }; + + // var intersection = Entities.findRayIntersection(pickRay); + + // if (intersection.intersects && intersection.distance < WARP_PICK_MAX_DISTANCE) { + // // Warp 1 meter above the object - this is an approximation + // // TODO Get the actual offset to the Avatar's feet and plant them to + // // the object. + // warpPosition = Vec3.sum(intersection.intersection, { x: 0, y: 1, z:0 }); + // } + + // Adjust overlays to match warp position + Overlays.editOverlay(warpSphere, { + position: warpPosition, + visible: true, + }); + Overlays.editOverlay(warpLine, { + start: warpPosition, + end: Vec3.sum(warpPosition, { x: 0, y: WARP_LINE_HEIGHT, z: 0 }), + visible: true, + }); + } + + function finishWarp() { + Overlays.editOverlay(warpSphere, { + visible: false, + }); + Overlays.editOverlay(warpLine, { + visible: false, + }); + MyAvatar.position = warpPosition; } function setUp() { From 012a508eb2d286bbc793e89f24df07e3d82717f5 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 16:25:12 -0700 Subject: [PATCH 037/121] removed extraneous code --- examples/hmdControls.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/hmdControls.js b/examples/hmdControls.js index 6634c48491..9b8b0e8ea5 100644 --- a/examples/hmdControls.js +++ b/examples/hmdControls.js @@ -17,7 +17,6 @@ var BOOM_SPEED = 0.5; var THRESHOLD = 0.2; var CAMERA_UPDATE_TIME = 0.5; -var pitchTimer = CAMERA_UPDATE_TIME; var yawTimer = CAMERA_UPDATE_TIME; var shifted = false; @@ -154,9 +153,6 @@ var hmdControls = (function () { if (yawTimer >= 0.0) { yawTimer = yawTimer - dt; } - if (pitchTimer >= 0.0) { - pitchTimer = pitchTimer - dt; - } if (shiftTimer >= 0.0) { shiftTimer = shiftTimer - dt; } From 2b4146125f8da04fac811b2d996bc6f67b1a6521 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 16:27:06 -0700 Subject: [PATCH 038/121] 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 039/121] 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 040/121] 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 8e5da5acaa7a20f0fed165e9bab426e8c0a1ea2c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 17:05:49 -0700 Subject: [PATCH 041/121] Fix debug compile error --- libraries/gpu/src/gpu/GLBackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 1e61c0e6aa..a3bc90c219 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -145,7 +145,7 @@ bool GLBackend::checkGLError(const char* name) { bool GLBackend::checkGLErrorDebug(const char* name) { #ifdef DEBUG - checkGLError(name); + return checkGLError(name); #else Q_UNUSED(name); return false; From 709508857c36f88953de2f5f2cac8cb9182f89cc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 18 Jun 2015 17:39:31 -0700 Subject: [PATCH 042/121] 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 043/121] 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 044/121] 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 045/121] 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 decae5c1f1d50d67f2c39f76449ccfb7dd007982 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 18:43:47 -0700 Subject: [PATCH 046/121] finished hmdControls.js --- examples/hmdControls.js | 79 +++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/examples/hmdControls.js b/examples/hmdControls.js index 9b8b0e8ea5..803d00ef94 100644 --- a/examples/hmdControls.js +++ b/examples/hmdControls.js @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var MOVE_DISTANCE = 0.3; +var MOVE_DISTANCE = 10.0; var PITCH_INCREMENT = 0.5; // degrees var YAW_INCREMENT = 0.5; // degrees var VR_YAW_INCREMENT = 15.0; // degrees @@ -50,52 +50,63 @@ var warpLine = Overlays.addOverlay("line3d", { visible: false, }); +var velocity = { x: 0, y: 0, z: 0 }; +var VERY_LONG_TIME = 1000000.0; + var hmdControls = (function () { + function findAction(name) { + var actions = Controller.getAllActions(); + for (var i = 0; i < actions.length; i++) { + if (actions[i].actionName == name) { + return i; + } + } + // If the action isn't found, it will default to the first available action + return 0; + } + function onActionEvent(action, state) { if (state < THRESHOLD) { - if (action == 6 || action == 7) { + if (action == findAction("YAW_LEFT") || action == findAction("YAW_RIGHT")) { yawTimer = CAMERA_UPDATE_TIME; - } else if (action == 8 || action == 9) { + } else if (action == findAction("PITCH_UP") || action == findAction("PITCH_DOWN")) { pitchTimer = CAMERA_UPDATE_TIME; } return; } switch (action) { - case 0: // backward - var direction = Quat.getFront(Camera.getOrientation()); - direction = Vec3.multiply(-1, direction); + case findAction("LONGITUDINAL_BACKWARD"): + var direction = {x: 0.0, y: 0.0, z:1.0}; direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); - MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + velocity = Vec3.sum(velocity, direction); break; - case 1: // forward - var direction = Quat.getFront(Camera.getOrientation()); + case findAction("LONGITUDINAL_FORWARD"): + var direction = {x: 0.0, y: 0.0, z:-1.0}; direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); - MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + velocity = Vec3.sum(velocity, direction); break; - case 2: // left - var direction = Quat.getRight(Camera.getOrientation()); - direction = Vec3.multiply(-1, direction); + case findAction("LATERAL_LEFT"): + var direction = {x:-1.0, y: 0.0, z: 0.0} direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); - MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + velocity = Vec3.sum(velocity, direction); break; - case 3: // right - var direction = Quat.getRight(Camera.getOrientation()); + case findAction("LATERAL_RIGHT"): + var direction = {x:1.0, y: 0.0, z: 0.0}; direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); - MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + velocity = Vec3.sum(velocity, direction); break; - case 4: // down - var direction = Quat.getUp(Camera.getOrientation()); - direction = Vec3.multiply(-1, direction); + case findAction("VERTICAL_DOWN"): + var direction = {x: 0.0, y: -1.0, z: 0.0}; direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); - MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + velocity = Vec3.sum(velocity, direction); break; - case 5: // up - var direction = Quat.getUp(Camera.getOrientation()); + case findAction("VERTICAL_UP"): + var direction = {x: 0.0, y: 1.0, z: 0.0}; direction = Vec3.multiply(Vec3.normalize(direction), shifted ? SHIFT_MAG * MOVE_DISTANCE : MOVE_DISTANCE); - MyAvatar.position = Vec3.sum(MyAvatar.position, direction); + velocity = Vec3.sum(velocity, direction); break; - case 6: // yaw left + case findAction("YAW_LEFT"): if (yawTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { MyAvatar.bodyYaw = MyAvatar.bodyYaw + (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); yawTimer = CAMERA_UPDATE_TIME; @@ -103,7 +114,7 @@ var hmdControls = (function () { MyAvatar.bodyYaw = MyAvatar.bodyYaw + (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); } break; - case 7: // yaw right + case findAction("YAW_RIGHT"): if (yawTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { MyAvatar.bodyYaw = MyAvatar.bodyYaw - (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); yawTimer = CAMERA_UPDATE_TIME; @@ -111,23 +122,23 @@ var hmdControls = (function () { MyAvatar.bodyYaw = MyAvatar.bodyYaw - (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); } break; - case 8: // pitch down + case findAction("PITCH_DOWN"): if (!Menu.isOptionChecked("Enable VR Mode")) { MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); } break; - case 9: // pitch up + case findAction("PITCH_UP"): if (!Menu.isOptionChecked("Enable VR Mode")) { MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); } break; - case 12: // shift + case findAction("SHIFT"): // speed up if (shiftTimer < 0.0) { shifted = !shifted; shiftTimer = SHIFT_UPDATE_TIME; } break; - case 13: // action1 = start/end warp + case findAction("ACTION1"): // start/end warp if (warpTimer < 0.0) { warpActive = !warpActive; if (!warpActive) { @@ -136,7 +147,7 @@ var hmdControls = (function () { warpTimer = WARP_UPDATE_TIME; } break; - case 14: // action2 = cancel warp + case findAction("ACTION2"): // cancel warp warpActive = false; Overlays.editOverlay(warpSphere, { visible: false, @@ -163,6 +174,10 @@ var hmdControls = (function () { if (warpActive) { updateWarp(); } + + MyAvatar.motorVelocity = velocity; + MyAvatar.motorTimescale = 0.0; + velocity = { x: 0, y: 0, z: 0 }; } function updateWarp() { @@ -227,6 +242,8 @@ var hmdControls = (function () { function tearDown() { Controller.releaseActionEvents(); + MyAvatar.motorVelocity = {x:0.0, y:0.0, z:0.0} + MyAvatar.motorTimescale = VERY_LONG_TIME; } setUp(); From aab8161fa4a7c3b79ea89d5bde5d2d6e017a035d Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 18:57:04 -0700 Subject: [PATCH 047/121] remove unused function --- interface/src/scripting/ControllerScriptingInterface.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 44b59beded..083b5fbe1a 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -72,8 +72,6 @@ public: void emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); } void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } - - void emitActionEvents(); bool isKeyCaptured(QKeyEvent* event) const; bool isKeyCaptured(const KeyEvent& event) const; From 9cfe8ecc011f07b06bf4fdde0593c49ad8ba4232 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Thu, 18 Jun 2015 18:59:10 -0700 Subject: [PATCH 048/121] added hmdControls.js to hmdDefaults.js --- examples/hmdDefaults.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/hmdDefaults.js b/examples/hmdDefaults.js index 0096b11777..2b5f333644 100644 --- a/examples/hmdDefaults.js +++ b/examples/hmdDefaults.js @@ -13,4 +13,5 @@ Script.load("progress.js"); Script.load("lobby.js"); Script.load("notifications.js"); Script.load("controllers/oculus/goTo.js"); +Script.load("hmdControls.js"); //Script.load("scripts.js"); // Not created yet From d65e5882aa038baf1487ca609a6728bc7a966bdf Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 18 Jun 2015 17:42:45 -0700 Subject: [PATCH 049/121] Working on 64 bit builds --- cmake/externals/LibOVR/CMakeLists.txt | 6 +++++- cmake/externals/glew/CMakeLists.txt | 15 ++++++++++----- cmake/externals/tbb/CMakeLists.txt | 9 +++++++-- cmake/modules/FindFaceshift.cmake | 6 +++++- cmake/modules/FindNSIGHT.cmake | 22 ++++++++++++++++------ cmake/modules/FindSixense.cmake | 18 +++++++++++++----- cmake/modules/FindTBB.cmake | 2 +- interface/src/main.cpp | 2 +- 8 files changed, 58 insertions(+), 22 deletions(-) diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index d491434b5f..b7dbc8b598 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -21,7 +21,11 @@ if (WIN32) # FIXME need to account for different architectures set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/Win32/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL) + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/x64/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL) + else() + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/Win32/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL) + endif() elseif(APPLE) diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt index 0d80e7a789..bcf175432c 100644 --- a/cmake/externals/glew/CMakeLists.txt +++ b/cmake/externals/glew/CMakeLists.txt @@ -16,11 +16,16 @@ if (WIN32) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of glew include directories") - - set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) - + + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(_LIB_DIR ${SOURCE_DIR}/lib/Release/x64) + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/x64 CACHE FILEPATH "Location of GLEW DLL") + else() + set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") + endif() + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32.lib CACHE FILEPATH "Location of GLEW release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Location of GLEW debug library") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") + endif () \ No newline at end of file diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 8f327bd69f..365bd3cf14 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -73,9 +73,14 @@ if (APPLE) ) elseif (WIN32) - set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/intel64/vc12") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/intel64/vc12" CACHE PATH "Path to TBB DLLs") + else() + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE PATH "Path to TBB DLLs") + endif() set(_LIB_EXT "lib") - set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE PATH "Path to TBB DLLs") elseif (ANDROID) set(_TBB_LIB_DIR "${SOURCE_DIR}/lib") set(_LIB_PREFIX "lib") diff --git a/cmake/modules/FindFaceshift.cmake b/cmake/modules/FindFaceshift.cmake index 0dcbcbb7dd..1f8b7b19fe 100644 --- a/cmake/modules/FindFaceshift.cmake +++ b/cmake/modules/FindFaceshift.cmake @@ -28,7 +28,11 @@ if (APPLE) elseif (UNIX) set(ARCH_DIR "UNIX") elseif (WIN32) - set(ARCH_DIR "Win32") + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(ARCH_DIR "x64") + else() + set(ARCH_DIR "Win32") + endif() endif () find_library(FACESHIFT_LIBRARY_RELEASE NAME faceshift PATH_SUFFIXES lib/${ARCH_DIR} HINTS ${FACESHIFT_SEARCH_DIRS}) diff --git a/cmake/modules/FindNSIGHT.cmake b/cmake/modules/FindNSIGHT.cmake index 4df0686ebe..243c337adb 100644 --- a/cmake/modules/FindNSIGHT.cmake +++ b/cmake/modules/FindNSIGHT.cmake @@ -16,7 +16,16 @@ # if (WIN32) - + + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(ARCH_DIR "x64") + set(ARCH_NAME "64") + else() + set(ARCH_DIR "Win32") + set(ARCH_NAME "32") + endif() + + find_path(NSIGHT_INCLUDE_DIRS NAMES nvToolsExt.h @@ -25,17 +34,18 @@ if (WIN32) PATHS "C:/Program Files/NVIDIA Corporation/NvToolsExt") - find_library(NSIGHT_LIBRARY_RELEASE nvToolsExt32_1 + find_library(NSIGHT_LIBRARY_RELEASE "nvToolsExt${ARCH_NAME}_1" PATH_SUFFIXES - "lib/Win32" "lib" + "lib/${ARCH_DIR}" "lib" PATHS "C:/Program Files/NVIDIA Corporation/NvToolsExt") - find_library(NSIGHT_LIBRARY_DEBUG nvToolsExt32_1 + find_library(NSIGHT_LIBRARY_DEBUG "nvToolsExt${ARCH_NAME}_1" PATH_SUFFIXES - "lib/Win32" "lib" + "lib/${ARCH_DIR}" "lib" PATHS "C:/Program Files/NVIDIA Corporation/NvToolsExt") - + + add_paths_to_fixup_libs("C:/Program Files/NVIDIA Corporation/NvToolsExt/bin/${ARCH_DIR}") include(SelectLibraryConfigurations) select_library_configurations(NSIGHT) endif () diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index 0f4346c53d..98b37d5410 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -30,12 +30,20 @@ elseif (UNIX) find_library(SIXENSE_LIBRARY_RELEASE lib/linux_x64/release/libsixense_x64.so HINTS ${SIXENSE_SEARCH_DIRS}) # find_library(SIXENSE_LIBRARY_DEBUG lib/linux_x64/debug/libsixensed_x64.so HINTS ${SIXENSE_SEARCH_DIRS}) elseif (WIN32) - find_library(SIXENSE_LIBRARY_RELEASE lib/win32/release_dll/sixense.lib HINTS ${SIXENSE_SEARCH_DIRS}) - find_library(SIXENSE_LIBRARY_DEBUG lib/win32/debug_dll/sixensed.lib HINTS ${SIXENSE_SEARCH_DIRS}) + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(ARCH_DIR "x64") + set(ARCH_SUFFIX "_x64") + else() + set(ARCH_DIR "Win32") + set(ARCH_SUFFIX "") + endif() + + find_library(SIXENSE_LIBRARY_RELEASE "lib/${ARCH_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" HINTS ${SIXENSE_SEARCH_DIRS}) + find_library(SIXENSE_LIBRARY_DEBUG "lib/${ARCH_DIR}/debug_dll/sixensed.lib" HINTS ${SIXENSE_SEARCH_DIRS}) - find_path(SIXENSE_DEBUG_DLL_PATH sixensed.dll PATH_SUFFIXES bin/win32/debug_dll HINTS ${SIXENSE_SEARCH_DIRS}) - find_path(SIXENSE_RELEASE_DLL_PATH sixense.dll PATH_SUFFIXES bin/win32/release_dll HINTS ${SIXENSE_SEARCH_DIRS}) - find_path(SIXENSE_DEVICE_DLL_PATH DeviceDLL.dll PATH_SUFFIXES samples/win32/sixense_simple3d HINTS ${SIXENSE_SEARCH_DIRS}) + find_path(SIXENSE_DEBUG_DLL_PATH "sixensed${ARCH_SUFFIX}.dll" PATH_SUFFIXES bin/${ARCH_DIR}/debug_dll HINTS ${SIXENSE_SEARCH_DIRS}) + find_path(SIXENSE_RELEASE_DLL_PATH "sixense${ARCH_SUFFIX}.dll" PATH_SUFFIXES bin/${ARCH_DIR}/release_dll HINTS ${SIXENSE_SEARCH_DIRS}) + find_path(SIXENSE_DEVICE_DLL_PATH DeviceDLL.dll PATH_SUFFIXES samples/${ARCH_DIR}/sixense_simple3d HINTS ${SIXENSE_SEARCH_DIRS}) endif () include(SelectLibraryConfigurations) diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index 4d4b3ca504..1ccdcd792d 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -49,7 +49,7 @@ elseif (UNIX AND NOT ANDROID) endif () elseif (WIN32) - if (CMAKE_CL_64) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_TBB_ARCH_DIR "intel64") else() set(_TBB_ARCH_DIR "ia32") diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 13ca17355b..e591034fb5 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -23,7 +23,7 @@ #ifdef Q_OS_WIN static BOOL CALLBACK enumWindowsCallback(HWND hWnd, LPARAM lParam) { const UINT TIMEOUT = 200; // ms - DWORD response; + DWORD_PTR response; LRESULT result = SendMessageTimeout(hWnd, UWM_IDENTIFY_INSTANCES, 0, 0, SMTO_BLOCK | SMTO_ABORTIFHUNG, TIMEOUT, &response); if (result == 0) { // Timeout; continue search. return TRUE; From 9bef5f011bc1da1e06aadd1d2c7f09a48fc187e8 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 19 Jun 2015 00:03:46 -0700 Subject: [PATCH 050/121] Reverting mirror functionality --- interface/resources/qml/Stats.qml | 6 +- interface/src/Application.cpp | 251 ++++++++++++++---------- interface/src/Application.h | 18 +- interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/devices/OculusManager.cpp | 4 +- interface/src/ui/ApplicationOverlay.cpp | 101 +--------- interface/src/ui/ApplicationOverlay.h | 7 - interface/src/ui/Stats.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.cpp | 16 ++ libraries/gpu/src/gpu/GLBackend.h | 6 +- libraries/gpu/src/gpu/GLBackendShared.h | 2 + 11 files changed, 196 insertions(+), 221 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index eb5a389c61..8ddea6a355 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -239,9 +239,9 @@ Hifi.Stats { id: perfText color: root.fontColor font.family: root.monospaceFont - font.pixelSize: 10 - text: "-------------------------------------------------------- Function " + - "------------------------------------------------------- --msecs- -calls--\n" + + font.pixelSize: 12 + text: "------------------------------------------ Function " + + "--------------------------------------- --msecs- -calls--\n" + root.timingStats; } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6b7f42fe0b..dc0eb3d23f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -151,7 +151,6 @@ #include "ui/AddressBarDialog.h" #include "ui/UpdateDialog.h" -static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU #if defined(Q_OS_WIN) @@ -325,11 +324,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _viewFrustum(), _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), + _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _firstRun("firstRun", true), _previousScriptLocation("LastScriptLocation"), _scriptsLocationHandle("scriptsLocation"), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), _viewTransform(), + _scaleMirror(1.0f), + _rotateMirror(0.0f), + _raiseMirror(0.0f), _cursorVisible(true), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), @@ -821,23 +824,6 @@ void Application::initializeGL() { InfoView::show(INFO_HELP_PATH, true); } -template -void with_stable_stack_check(F f) { - - GLint mvDepth, prDepth; - glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepth); - glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepth); - - f(); - - GLint mvDepthFinal, prDepthFinal; - glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepthFinal); - glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepthFinal); - Q_ASSERT(mvDepth == mvDepthFinal); - Q_ASSERT(prDepth == prDepthFinal); - -} - void Application::initializeUi() { AddressBarDialog::registerType(); ErrorDialog::registerType(); @@ -875,12 +861,7 @@ void Application::initializeUi() { }); } -void Application::paintGL() { - PROFILE_RANGE(__FUNCTION__); - _glWidget->makeCurrent(); - - auto lodManager = DependencyManager::get(); - +/* { PerformanceTimer perfTimer("renderOverlay"); gpu::Context context(new gpu::GLBackend()); @@ -889,6 +870,13 @@ void Application::paintGL() { RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); _applicationOverlay.renderOverlay(&renderArgs); } +*/ + +void Application::paintGL() { + PROFILE_RANGE(__FUNCTION__); + _glWidget->makeCurrent(); + + auto lodManager = DependencyManager::get(); gpu::Context context(new gpu::GLBackend()); RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), @@ -943,10 +931,6 @@ void Application::paintGL() { } } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // TODO put the mirror modifiers somewhere both the app and the overlay can access it - float _rotateMirror = 0.0f; - float _raiseMirror = 0.0f; - float _scaleMirror = 1.0f; _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0) + @@ -986,31 +970,32 @@ void Application::paintGL() { QSize size = DependencyManager::get()->getFrameBufferSize(); glViewport(0, 0, size.width(), size.height()); - with_stable_stack_check([&]{ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - displaySide(&renderArgs, _myCamera); - _compositor.displayOverlayTexture(&renderArgs); - glPopMatrix(); - }); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + displaySide(&renderArgs, _myCamera); + glPopMatrix(); - //renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - //if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { - // _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); - //} else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - // renderRearViewMirror(&renderArgs, _mirrorViewRect); - //} - //renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; + if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { + _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); + } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + renderRearViewMirror(&renderArgs, _mirrorViewRect); + } + + renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; auto finalFbo = DependencyManager::get()->render(&renderArgs); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y, 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + _compositor.displayOverlayTexture(&renderArgs); } @@ -1071,21 +1056,24 @@ void Application::resizeGL() { } else { renderSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); } - if (_renderResolution == toGlm(renderSize)) { - return; + + if (_renderResolution != toGlm(renderSize)) { + _renderResolution = toGlm(renderSize); + DependencyManager::get()->setFrameBufferSize(renderSize); + resetCamerasOnResizeGL(_myCamera, _renderResolution); + + glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu??? + + updateProjectionMatrix(); + glLoadIdentity(); } - _renderResolution = toGlm(renderSize); - DependencyManager::get()->setFrameBufferSize(renderSize); - resetCamerasOnResizeGL(_myCamera, _renderResolution); - - glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu??? - - updateProjectionMatrix(); - glLoadIdentity(); - auto offscreenUi = DependencyManager::get(); - offscreenUi->resize(_glWidget->size()); + + auto canvasSize = _glWidget->size(); + if (canvasSize != offscreenUi->getWindow()->size()) { + offscreenUi->resize(canvasSize); + } _glWidget->makeCurrent(); } @@ -1303,37 +1291,37 @@ void Application::keyPressEvent(QKeyEvent* event) { Menu::getInstance()->triggerOption(MenuOption::Chat); break; - //case Qt::Key_Up: - // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // if (!isShifted) { - // _scaleMirror *= 0.95f; - // } else { - // _raiseMirror += 0.05f; - // } - // } - // break; + case Qt::Key_Up: + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + if (!isShifted) { + _scaleMirror *= 0.95f; + } else { + _raiseMirror += 0.05f; + } + } + break; - //case Qt::Key_Down: - // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // if (!isShifted) { - // _scaleMirror *= 1.05f; - // } else { - // _raiseMirror -= 0.05f; - // } - // } - // break; + case Qt::Key_Down: + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + if (!isShifted) { + _scaleMirror *= 1.05f; + } else { + _raiseMirror -= 0.05f; + } + } + break; - //case Qt::Key_Left: - // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // _rotateMirror += PI / 20.0f; - // } - // break; + case Qt::Key_Left: + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + _rotateMirror += PI / 20.0f; + } + break; - //case Qt::Key_Right: - // if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // _rotateMirror -= PI / 20.0f; - // } - // break; + case Qt::Key_Right: + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + _rotateMirror -= PI / 20.0f; + } + break; #if 0 case Qt::Key_I: @@ -1598,12 +1586,11 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { // stop propagation return; } -#if 0 + if (_rearMirrorTools->mousePressEvent(getMouseX(), getMouseY())) { // stop propagation return; } -#endif } // nobody handled this - make it an action event on the _window object @@ -1654,15 +1641,6 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { if (event->button() == Qt::LeftButton) { _mousePressed = false; -#if 0 - if (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && mouseOnScreen()) { - // let's set horizontal offset to give stats some margin to mirror - int horizontalOffset = MIRROR_VIEW_WIDTH; - Stats::getInstance()->checkClick(getMouseX(), getMouseY(), - getMouseDragStartedX(), getMouseDragStartedY(), horizontalOffset); - } -#endif - // fire an action end event HFActionEvent actionEvent(HFActionEvent::endType(), computePickRay(event->x(), event->y())); @@ -1847,7 +1825,6 @@ void Application::idle() { targetFramePeriod = 1000.0 / targetFramerate; } double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; - //if (true) { if (timeSinceLastUpdate > targetFramePeriod) { _lastTimeUpdated.start(); { @@ -1874,7 +1851,7 @@ void Application::idle() { } // After finishing all of the above work, restart the idle timer, allowing 2ms to process events. - idleTimer->start(0); + idleTimer->start(2); } } @@ -2181,9 +2158,7 @@ void Application::init() { DependencyManager::get()->init(); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); -#if 0 _mirrorCamera.setMode(CAMERA_MODE_MIRROR); -#endif TV3DManager::connect(); if (TV3DManager::isConnected()) { @@ -2248,13 +2223,12 @@ void Application::init() { _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); -#if 0 _rearMirrorTools = new RearMirrorTools(_mirrorViewRect); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); -#endif + // initialize the GlowEffect with our widget bool glow = Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect); @@ -3166,7 +3140,6 @@ PickRay Application::computePickRay(float x, float y) const { return result; } -#if 0 QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { auto primaryFramebuffer = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer)); @@ -3192,7 +3165,6 @@ QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) { glBindFramebuffer(GL_FRAMEBUFFER, 0); return image; } -#endif ViewFrustum* Application::getViewFrustum() { #ifdef DEBUG @@ -3410,7 +3382,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se viewTransform.setTranslation(theCamera.getPosition()); viewTransform.setRotation(rotation); if (theCamera.getMode() == CAMERA_MODE_MIRROR) { - //viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); +// viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); } if (renderArgs->_renderSide != RenderArgs::MONO) { glm::mat4 invView = glm::inverse(_untranslatedViewMatrix); @@ -3677,6 +3649,79 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { return screenPoint; } +void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { + // Grab current viewport to reset it at the end + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + float aspect = (float)region.width() / region.height(); + float fov = MIRROR_FIELD_OF_VIEW; + + // bool eyeRelativeCamera = false; + if (billboard) { + fov = BILLBOARD_FIELD_OF_VIEW; // degees + _mirrorCamera.setPosition(_myAvatar->getPosition() + + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); + + } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { + _mirrorCamera.setPosition(_myAvatar->getChestPosition() + + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); + + } else { // HEAD zoom level + // FIXME note that the positioing of the camera relative to the avatar can suffer limited + // precision as the user's position moves further away from the origin. Thus at + // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways + // wildly as you rotate your avatar because the floating point values are becoming + // larger, squeezing out the available digits of precision you have available at the + // human scale for camera positioning. + + // Previously there was a hack to correct this using the mechanism of repositioning + // the avatar at the origin of the world for the purposes of rendering the mirror, + // but it resulted in failing to render the avatar's head model in the mirror view + // when in first person mode. Presumably this was because of some missed culling logic + // that was not accounted for in the hack. + + // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further + // investigated in order to adapt the technique while fixing the head rendering issue, + // but the complexity of the hack suggests that a better approach + _mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() + + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); + } + _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); + _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); + + // set the bounds of rear mirror view + if (billboard) { + QSize size = DependencyManager::get()->getFrameBufferSize(); + glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height()); + } else { + // if not rendering the billboard, the region is in device independent coordinates; must convert to device + QSize size = DependencyManager::get()->getFrameBufferSize(); + float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale(); + int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio; + glViewport(x, size.height() - y - height, width, height); + glScissor(x, size.height() - y - height, width, height); + } + bool updateViewFrustum = false; + updateProjectionMatrix(_mirrorCamera, updateViewFrustum); + glEnable(GL_SCISSOR_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // render rear mirror view + glPushMatrix(); + displaySide(renderArgs, _mirrorCamera, true, billboard); + glPopMatrix(); + + if (!billboard) { + _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); + } + + // reset Viewport and projection matrix + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + glDisable(GL_SCISSOR_TEST); + updateProjectionMatrix(_myCamera, updateViewFrustum); +} + void Application::resetSensors() { DependencyManager::get()->reset(); DependencyManager::get()->reset(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 605c85f7f7..99834a13d2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -108,6 +108,15 @@ static const QString FST_EXTENSION = ".fst"; static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees static const float BILLBOARD_DISTANCE = 5.56f; // meters +static const int MIRROR_VIEW_TOP_PADDING = 5; +static const int MIRROR_VIEW_LEFT_PADDING = 10; +static const int MIRROR_VIEW_WIDTH = 265; +static const int MIRROR_VIEW_HEIGHT = 215; +static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; +static const float MIRROR_REARVIEW_DISTANCE = 0.722f; +static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f; +static const float MIRROR_FIELD_OF_VIEW = 30.0f; + static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS_PER_SECOND; static const QString INFO_HELP_PATH = "html/interface-welcome.html"; @@ -469,7 +478,6 @@ private slots: void faceTrackerMuteToggled(); void setCursorVisible(bool visible); - //void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false); private: void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size); @@ -504,6 +512,7 @@ private: glm::vec3 getSunDirection(); void updateShadowMap(RenderArgs* renderArgs); + void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false); void setMenuShortcutsEnabled(bool enabled); static void attachNewHeadToNode(Node *newNode); @@ -555,6 +564,9 @@ private: UserInputMapper _userInputMapper; // User input mapper allowing to mapp different real devices to the action channels that the application has to offer MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) Camera _myCamera; // My view onto the world + Camera _mirrorCamera; // Cammera for mirror view + QRect _mirrorViewRect; + RearMirrorTools* _rearMirrorTools; Setting::Handle _firstRun; Setting::Handle _previousScriptLocation; @@ -566,6 +578,10 @@ private: glm::vec3 _viewMatrixTranslation; glm::mat4 _projectionMatrix; + float _scaleMirror; + float _rotateMirror; + float _raiseMirror; + static const int CASCADED_SHADOW_MATRIX_COUNT = 4; glm::mat4 _shadowMatrices[CASCADED_SHADOW_MATRIX_COUNT]; glm::vec3 _shadowDistances; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6b0a398246..16cba72fcb 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1466,7 +1466,6 @@ void MyAvatar::maybeUpdateBillboard() { return; } } - /* gpu::Context context(new gpu::GLBackend()); RenderArgs renderArgs(&context); QImage image = qApp->renderAvatarBillboard(&renderArgs); @@ -1477,7 +1476,6 @@ void MyAvatar::maybeUpdateBillboard() { _billboardValid = true; sendBillboardPacket(); - */ } void MyAvatar::increaseSize() { @@ -1577,7 +1575,7 @@ glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) { glm::vec3 result; - const auto& compositor = Application::getInstance()->getApplicationCompositor(); + const auto& compositor = qApp->getApplicationCompositor(); if (compositor.calculateRayUICollisionPoint(position, direction, result)) { return result; } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 782d9dadba..53b3702cca 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -646,11 +646,12 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const renderArgs->_renderSide = RenderArgs::MONO; qApp->displaySide(renderArgs, *_camera); - //qApp->getApplicationCompositor().displayOverlayTexture(renderArgs); qApp->getApplicationCompositor().displayOverlayTextureHmd(renderArgs, eye); }); _activeEye = ovrEye_Count; + glPopMatrix(); + gpu::FramebufferPointer finalFbo; //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { @@ -661,7 +662,6 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const finalFbo = DependencyManager::get()->getPrimaryFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, 0); } - glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 08de5be0c8..b24054f8a8 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -42,14 +42,6 @@ const int AUDIO_METER_GAP = 5; const int MUTE_ICON_PADDING = 10; const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; -static const int MIRROR_VIEW_TOP_PADDING = 5; -static const int MIRROR_VIEW_LEFT_PADDING = 10; -static const int MIRROR_VIEW_WIDTH = 265; -static const int MIRROR_VIEW_HEIGHT = 215; -static const int STATS_HORIZONTAL_OFFSET = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; -static const float MIRROR_REARVIEW_DISTANCE = 0.722f; -static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.56f; -static const float MIRROR_FIELD_OF_VIEW = 30.0f; static const float ORTHO_NEAR_CLIP = -10000; static const float ORTHO_FAR_CLIP = 10000; @@ -59,8 +51,7 @@ static void fboViewport(QOpenGLFramebufferObject* fbo) { glViewport(0, 0, size.width(), size.height()); } -ApplicationOverlay::ApplicationOverlay() : - _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)) +ApplicationOverlay::ApplicationOverlay() { auto geometryCache = DependencyManager::get(); _audioRedQuad = geometryCache->allocateID(); @@ -295,94 +286,16 @@ void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { - // Grab current viewport to reset it at the end - auto mirrorSize = _mirrorFramebuffer->size(); - float aspect = (float)mirrorSize.width() / mirrorSize.height(); - float fov = MIRROR_FIELD_OF_VIEW; - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - // bool eyeRelativeCamera = false; - if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { - _mirrorCamera.setPosition(myAvatar->getChestPosition() + - myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * myAvatar->getScale()); - } else { // HEAD zoom level - // FIXME note that the positioing of the camera relative to the avatar can suffer limited - // precision as the user's position moves further away from the origin. Thus at - // /1e7,1e7,1e7 (well outside the buildable volume) the mirror camera veers and sways - // wildly as you rotate your avatar because the floating point values are becoming - // larger, squeezing out the available digits of precision you have available at the - // human scale for camera positioning. - - // Previously there was a hack to correct this using the mechanism of repositioning - // the avatar at the origin of the world for the purposes of rendering the mirror, - // but it resulted in failing to render the avatar's head model in the mirror view - // when in first person mode. Presumably this was because of some missed culling logic - // that was not accounted for in the hack. - - // This was removed in commit 71e59cfa88c6563749594e25494102fe01db38e9 but could be further - // investigated in order to adapt the technique while fixing the head rendering issue, - // but the complexity of the hack suggests that a better approach - _mirrorCamera.setPosition(myAvatar->getHead()->getEyePosition() + - myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * myAvatar->getScale()); - } - _mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); - _mirrorCamera.setRotation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); - - // set the bounds of rear mirror view - fboViewport(_mirrorFramebuffer); - - _mirrorFramebuffer->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glLoadMatrixf(glm::value_ptr(_mirrorCamera.getProjection())); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glLoadMatrixf(glm::value_ptr(glm::mat4_cast(_mirrorCamera.getOrientation()) * glm::translate(glm::mat4(), _mirrorCamera.getPosition()))); - { - renderArgs->_context->syncCache(); - qApp->displaySide(renderArgs, _mirrorCamera, true, false); - } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - _mirrorFramebuffer->release(); - fboViewport(_overlayFramebuffer); } void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { - if (_mirrorFramebuffer && _mirrorFramebuffer->texture()) { - gpu::Batch batch; - auto geometryCache = DependencyManager::get(); - geometryCache->useSimpleDrawPipeline(batch); - batch._glDisable(GL_DEPTH_TEST); - batch._glDisable(GL_LIGHTING); - batch._glEnable(GL_BLEND); - batch.setProjectionTransform(mat4()); - batch.setModelTransform(mat4()); - auto textureCache = DependencyManager::get(); - batch.setUniformTexture(0, textureCache->getBlueTexture()); - geometryCache->renderUnitQuad(batch, glm::vec4(1)); - batch._glBindTexture(GL_TEXTURE_2D, _mirrorFramebuffer->texture()); - geometryCache->renderUnitQuad(batch, glm::vec4(1)); - renderArgs->_context->syncCache(); - auto overlaySize = _overlayFramebuffer->size(); - glViewport(MIRROR_VIEW_LEFT_PADDING, overlaySize.height() - MIRROR_VIEW_TOP_PADDING - MIRROR_VIEW_HEIGHT, - MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT); - renderArgs->_context->render(batch); - fboViewport(_overlayFramebuffer); - } } void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { - // Display stats and log text onscreen // Determine whether to compute timing details - /* // Show on-screen msec timer if (Menu::getInstance()->isOptionChecked(MenuOption::FrameTimer)) { @@ -457,18 +370,6 @@ GLuint ApplicationOverlay::getOverlayTexture() { } void ApplicationOverlay::buildFramebufferObject() { - if (!_mirrorFramebuffer) { - _mirrorFramebuffer = new QOpenGLFramebufferObject(QSize(MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT), QOpenGLFramebufferObject::Depth); - glBindTexture(GL_TEXTURE_2D, _mirrorFramebuffer->texture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - glBindTexture(GL_TEXTURE_2D, 0); - } - auto canvasSize = qApp->getCanvasSize(); QSize fboSize = QSize(canvasSize.x, canvasSize.y); if (_overlayFramebuffer && fboSize == _overlayFramebuffer->size()) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index ab242e592b..e50622d122 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -49,15 +49,8 @@ private: int _domainStatusBorder; int _magnifierBorder; - float _scaleMirror{ 1.0f }; - float _rotateMirror{ 0.0f }; - float _raiseMirror{ 0.0f }; - - Camera _mirrorCamera; ivec2 _previousBorderSize{ -1 }; - QRect _mirrorViewRect; QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr }; - QOpenGLFramebufferObject* _mirrorFramebuffer{ nullptr }; }; #endif // hifi_ApplicationOverlay_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index c1d77b5fc2..acc9521c72 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -333,7 +333,7 @@ void Stats::updateStats() { QString functionName = j.value(); const PerformanceTimerRecord& record = allRecords.value(functionName); perfLines += QString("%1: %2 [%3]\n"). - arg(QString(qPrintable(functionName)), 120, noBreakingSpace). + arg(QString(qPrintable(functionName)), 90, noBreakingSpace). arg((float)record.getMovingAverage() / (float)USECS_PER_MSEC, 8, 'f', 3, noBreakingSpace). arg((int)record.getCount(), 6, 10, noBreakingSpace); linesDisplayed++; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 5103633761..cd57d13615 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -689,4 +689,20 @@ void GLBackend::fetchMatrix(GLenum target, glm::mat4 & m) { glGetFloatv(target, glm::value_ptr(m)); } +void GLBackend::checkGLStackStable(std::function f) { +#ifdef DEBUG + GLint mvDepth, prDepth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepth); + glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepth); +#endif + f(); + +#ifdef DEBUG + GLint mvDepthFinal, prDepthFinal; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepthFinal); + glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepthFinal); + Q_ASSERT(mvDepth == mvDepthFinal); + Q_ASSERT(prDepth == prDepthFinal); +#endif +} diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index b6a93d1ea3..28236c68c9 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -12,11 +12,13 @@ #define hifi_gpu_GLBackend_h #include +#include +#include + #include "GPUConfig.h" #include "Context.h" #include "Batch.h" -#include namespace gpu { @@ -50,6 +52,8 @@ public: // Only checks in debug builds static bool checkGLErrorDebug(const char* name = nullptr); + static void checkGLStackStable(std::function f); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index 27f58fcbe3..365934379f 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -53,4 +53,6 @@ static const GLenum _elementTypeToGLType[gpu::NUM_TYPES] = { // #define CHECK_GL_ERROR() gpu::GLBackend::checkGLErrorDebug(__FUNCTION__ ":" CHECK_GL_ERROR_HELPER(__LINE__)) #define CHECK_GL_ERROR() gpu::GLBackend::checkGLErrorDebug(__FUNCTION__) +#define CHECK_GL_STACK_STABLE(f) gpu::GLBackend::checkGLStackStable(f) + #endif From 690e2e38f20caadad4411daa16f78b138502aa19 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 09:45:13 -0700 Subject: [PATCH 051/121] Move circle3d and text overlays to batches --- interface/src/ui/overlays/Circle3DOverlay.cpp | 328 +++++----- interface/src/ui/overlays/Text3DOverlay.cpp | 66 +- interface/src/ui/overlays/Text3DOverlay.h | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 579 +++++++++--------- .../render-utils/src/RenderDeferredTask.h | 4 +- 5 files changed, 496 insertions(+), 485 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 77debf304f..e5461d3478 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -101,205 +101,207 @@ void Circle3DOverlay::render(RenderArgs* args) { bool colorChanged = colorX.red != _lastColor.red || colorX.green != _lastColor.green || colorX.blue != _lastColor.blue; _lastColor = colorX; - glDisable(GL_LIGHTING); - glm::vec3 position = getPosition(); glm::vec3 center = getCenter(); glm::vec2 dimensions = getDimensions(); glm::quat rotation = getRotation(); - float glowLevel = getGlowLevel(); - Glower* glower = NULL; - if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); - } + auto batch = args->_batch; - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x / 2.0f, dimensions.y / 2.0f, 1.0f); + if (batch) { + Transform transform; + transform.setTranslation(position); + transform.setRotation(rotation); + transform.setScale(glm::vec3(dimensions.x, dimensions.y, 1.0f) / 2.0f); - glLineWidth(_lineWidth); + batch->setModelTransform(transform); - auto geometryCache = DependencyManager::get(); + batch->_glLineWidth(_lineWidth); - // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise - // we just draw a line... - if (getIsSolid()) { - if (_quadVerticesID == GeometryCache::UNKNOWN_ID) { - _quadVerticesID = geometryCache->allocateID(); - } + auto geometryCache = DependencyManager::get(); - if (geometryChanged || colorChanged) { + // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise + // we just draw a line... + if (getIsSolid()) { + if (_quadVerticesID == GeometryCache::UNKNOWN_ID) { + _quadVerticesID = geometryCache->allocateID(); + } - QVector points; + if (geometryChanged || colorChanged) { - float angle = startAt; - float angleInRadians = glm::radians(angle); - glm::vec2 firstInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); - glm::vec2 firstOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); + QVector points; - points << firstInnerPoint << firstOuterPoint; + float angle = startAt; + float angleInRadians = glm::radians(angle); + glm::vec2 firstInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 firstOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); - while (angle < endAt) { - angleInRadians = glm::radians(angle); - glm::vec2 thisInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); - glm::vec2 thisOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); + points << firstInnerPoint << firstOuterPoint; - points << thisOuterPoint << thisInnerPoint; - - angle += SLICE_ANGLE; - } - - // get the last slice portion.... - angle = endAt; + while (angle < endAt) { angleInRadians = glm::radians(angle); - glm::vec2 lastInnerPoint(cosf(angleInRadians) * innerRadius, sinf(angleInRadians) * innerRadius); - glm::vec2 lastOuterPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); + glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); - points << lastOuterPoint << lastInnerPoint; + points << thisOuterPoint << thisInnerPoint; - geometryCache->updateVertices(_quadVerticesID, points, color); + angle += SLICE_ANGLE; } - geometryCache->renderVertices(gpu::QUAD_STRIP, _quadVerticesID); + // get the last slice portion.... + angle = endAt; + angleInRadians = glm::radians(angle); + glm::vec2 lastInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 lastOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + // Add quads for the back side + while (angle > startAt) { + angleInRadians = glm::radians(angle); + glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + + points << thisOuterPoint << thisInnerPoint; + + angle -= SLICE_ANGLE; + } + + // get the last slice portion.... + angle = startAt; + angleInRadians = glm::radians(angle); + lastInnerPoint = glm::vec2(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + lastOuterPoint = glm::vec2(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + + points << lastOuterPoint << lastInnerPoint; + + geometryCache->updateVertices(_quadVerticesID, points, color); + } + geometryCache->renderVertices(*batch, gpu::QUAD_STRIP, _quadVerticesID); + + } else { + if (_lineVerticesID == GeometryCache::UNKNOWN_ID) { + _lineVerticesID = geometryCache->allocateID(); + } + + if (geometryChanged || colorChanged) { + QVector points; + + float angle = startAt; + float angleInRadians = glm::radians(angle); + glm::vec2 firstPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + points << firstPoint; + + while (angle < endAt) { + angle += SLICE_ANGLE; + angleInRadians = glm::radians(angle); + glm::vec2 thisPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + points << thisPoint; + + if (getIsDashedLine()) { + angle += SLICE_ANGLE / 2.0f; // short gap + angleInRadians = glm::radians(angle); + glm::vec2 dashStartPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + points << dashStartPoint; + } + } + + // get the last slice portion.... + angle = endAt; + angleInRadians = glm::radians(angle); + glm::vec2 lastPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + points << lastPoint; + + geometryCache->updateVertices(_lineVerticesID, points, color); + } + + if (getIsDashedLine()) { + geometryCache->renderVertices(*batch, gpu::LINES, _lineVerticesID); } else { - if (_lineVerticesID == GeometryCache::UNKNOWN_ID) { - _lineVerticesID = geometryCache->allocateID(); - } + geometryCache->renderVertices(*batch, gpu::LINE_STRIP, _lineVerticesID); + } + } - if (geometryChanged || colorChanged) { - QVector points; + // draw our tick marks + // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise + // we just draw a line... + if (getHasTickMarks()) { - float angle = startAt; + if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) { + _majorTicksVerticesID = geometryCache->allocateID(); + } + if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) { + _minorTicksVerticesID = geometryCache->allocateID(); + } + + if (geometryChanged) { + QVector majorPoints; + QVector minorPoints; + + // draw our major tick marks + if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) { + + float tickMarkAngle = getMajorTickMarksAngle(); + float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; float angleInRadians = glm::radians(angle); - glm::vec2 firstPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - points << firstPoint; + float tickMarkLength = getMajorTickMarksLength(); + float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius; + float endRadius = startRadius + tickMarkLength; - while (angle < endAt) { - angle += SLICE_ANGLE; + while (angle <= endAt) { angleInRadians = glm::radians(angle); - glm::vec2 thisPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - points << thisPoint; - if (getIsDashedLine()) { - angle += SLICE_ANGLE / 2.0f; // short gap - angleInRadians = glm::radians(angle); - glm::vec2 dashStartPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - points << dashStartPoint; - } + glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius); + glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius); + + majorPoints << thisPointA << thisPointB; + + angle += tickMarkAngle; } - - // get the last slice portion.... - angle = endAt; - angleInRadians = glm::radians(angle); - glm::vec2 lastPoint(cosf(angleInRadians) * outerRadius, sinf(angleInRadians) * outerRadius); - points << lastPoint; - - geometryCache->updateVertices(_lineVerticesID, points, color); } - if (getIsDashedLine()) { - geometryCache->renderVertices(gpu::LINES, _lineVerticesID); - } else { - geometryCache->renderVertices(gpu::LINE_STRIP, _lineVerticesID); + // draw our minor tick marks + if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) { + + float tickMarkAngle = getMinorTickMarksAngle(); + float angle = startAt - fmod(startAt, tickMarkAngle) + tickMarkAngle; + float angleInRadians = glm::radians(angle); + float tickMarkLength = getMinorTickMarksLength(); + float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius; + float endRadius = startRadius + tickMarkLength; + + while (angle <= endAt) { + angleInRadians = glm::radians(angle); + + glm::vec2 thisPointA(cos(angleInRadians) * startRadius, sin(angleInRadians) * startRadius); + glm::vec2 thisPointB(cos(angleInRadians) * endRadius, sin(angleInRadians) * endRadius); + + minorPoints << thisPointA << thisPointB; + + angle += tickMarkAngle; + } } + + xColor majorColorX = getMajorTickMarksColor(); + glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha); + + geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor); + + xColor minorColorX = getMinorTickMarksColor(); + glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha); + + geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor); } - // draw our tick marks - // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise - // we just draw a line... - if (getHasTickMarks()) { + geometryCache->renderVertices(*batch, gpu::LINES, _majorTicksVerticesID); - if (_majorTicksVerticesID == GeometryCache::UNKNOWN_ID) { - _majorTicksVerticesID = geometryCache->allocateID(); - } - if (_minorTicksVerticesID == GeometryCache::UNKNOWN_ID) { - _minorTicksVerticesID = geometryCache->allocateID(); - } + geometryCache->renderVertices(*batch, gpu::LINES, _minorTicksVerticesID); + } - if (geometryChanged) { - QVector majorPoints; - QVector minorPoints; - - // draw our major tick marks - if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) { - - float tickMarkAngle = getMajorTickMarksAngle(); - float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle; - float angleInRadians = glm::radians(angle); - float tickMarkLength = getMajorTickMarksLength(); - float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius; - float endRadius = startRadius + tickMarkLength; - - while (angle <= endAt) { - angleInRadians = glm::radians(angle); - - glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius); - glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius); - - majorPoints << thisPointA << thisPointB; - - angle += tickMarkAngle; - } - } - - // draw our minor tick marks - if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) { - - float tickMarkAngle = getMinorTickMarksAngle(); - float angle = startAt - fmodf(startAt, tickMarkAngle) + tickMarkAngle; - float angleInRadians = glm::radians(angle); - float tickMarkLength = getMinorTickMarksLength(); - float startRadius = (tickMarkLength > 0.0f) ? innerRadius : outerRadius; - float endRadius = startRadius + tickMarkLength; - - while (angle <= endAt) { - angleInRadians = glm::radians(angle); - - glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius); - glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius); - - minorPoints << thisPointA << thisPointB; - - angle += tickMarkAngle; - } - } - - xColor majorColorX = getMajorTickMarksColor(); - glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha); - - geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor); - - xColor minorColorX = getMinorTickMarksColor(); - glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha); - - geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor); - } - - geometryCache->renderVertices(gpu::LINES, _majorTicksVerticesID); - - geometryCache->renderVertices(gpu::LINES, _minorTicksVerticesID); - } - - - glPopMatrix(); - glPopMatrix(); - - if (geometryChanged) { - _lastStartAt = startAt; - _lastEndAt = endAt; - _lastInnerRadius = innerRadius; - _lastOuterRadius = outerRadius; - } - - if (glower) { - delete glower; + if (geometryChanged) { + _lastStartAt = startAt; + _lastEndAt = endAt; + _lastInnerRadius = innerRadius; + _lastOuterRadius = outerRadius; + } } } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index fd8410b7e6..327c70d778 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -14,6 +14,8 @@ #include "Application.h" #include "Text3DOverlay.h" +#include + const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const float DEFAULT_BACKGROUND_ALPHA = 0.7f; const float DEFAULT_MARGIN = 0.1f; @@ -52,7 +54,7 @@ Text3DOverlay::~Text3DOverlay() { xColor Text3DOverlay::getBackgroundColor() { if (_colorPulse == 0.0f) { - return _backgroundColor; + return _backgroundColor; } float pulseLevel = updatePulse(); @@ -75,19 +77,23 @@ void Text3DOverlay::render(RenderArgs* args) { return; // do nothing if we're not visible } - glPushMatrix(); { - glTranslatef(_position.x, _position.y, _position.z); + auto batch = args->_batch; + + if (batch) { glm::quat rotation; - + if (_isFacingAvatar) { // rotate about vertical to face the camera rotation = Application::getInstance()->getCamera()->getRotation(); } else { rotation = getRotation(); } - - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + Transform transform; + transform.setTranslation(_position); + transform.setRotation(rotation); + + batch->setModelTransform(transform); const float MAX_COLOR = 255.0f; xColor backgroundColor = getBackgroundColor(); @@ -96,40 +102,42 @@ void Text3DOverlay::render(RenderArgs* args) { glm::vec2 dimensions = getDimensions(); glm::vec2 halfDimensions = dimensions * 0.5f; - + const float SLIGHTLY_BEHIND = -0.005f; glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - DependencyManager::get()->renderQuad(topLeft, bottomRight, quadColor); - + DependencyManager::get()->renderQuad(*batch, topLeft, bottomRight, quadColor); + // Same font properties as textSize() float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; - - float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; - glTranslatef(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f); + float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; glm::vec2 clipMinimum(0.0f, 0.0f); - glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, + glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); - glScalef(scaleFactor, -scaleFactor, scaleFactor); - enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); - enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); - enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); - enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); - - glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; - _textRenderer->draw(0, 0, _text, textColor); + transform.setScale(glm::vec3(scaleFactor, -scaleFactor, scaleFactor)); + transform.preTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f)); + batch->setModelTransform(transform); + + // enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); + // enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); + // enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); + // enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); + + glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; + _textRenderer->draw(*batch, 0, 0, _text, textColor); + + // glDisable(GL_CLIP_PLANE0); + // glDisable(GL_CLIP_PLANE1); + // glDisable(GL_CLIP_PLANE2); + // glDisable(GL_CLIP_PLANE3); + + batch->setPipeline(DrawOverlay3D::getOpaquePipeline()); + } - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); - - } glPopMatrix(); - } void Text3DOverlay::enableClipPlane(GLenum plane, float x, float y, float z, float w) { diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 77a5c23cb9..f2c71f8676 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -17,7 +17,7 @@ #include #include -#include +#include #include "Planar3DOverlay.h" @@ -62,7 +62,7 @@ public: private: void enableClipPlane(GLenum plane, float x, float y, float z, float w); - TextRenderer* _textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); + TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); QString _text; xColor _backgroundColor; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ce3c6769ca..b8ec2e0467 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -1,244 +1,245 @@ -// -// RenderDeferredTask.cpp -// render-utils/src/ -// -// Created by Sam Gateau on 5/29/15. -// Copyright 20154 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#include "RenderDeferredTask.h" - -#include "gpu/Batch.h" -#include "gpu/Context.h" -#include "DeferredLightingEffect.h" -#include "ViewFrustum.h" -#include "RenderArgs.h" -#include "TextureCache.h" - -#include - +// +// RenderDeferredTask.cpp +// render-utils/src/ +// +// Created by Sam Gateau on 5/29/15. +// Copyright 20154 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "RenderDeferredTask.h" + +#include "gpu/Batch.h" +#include "gpu/Context.h" +#include "DeferredLightingEffect.h" +#include "ViewFrustum.h" +#include "RenderArgs.h" +#include "TextureCache.h" + +#include + #include "overlay3D_vert.h" -#include "overlay3D_frag.h" - -using namespace render; - -template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("PrepareDeferred"); - DependencyManager::get()->prepare(); -} - -template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("RenderDeferred"); - DependencyManager::get()->render(); -// renderContext->args->_context->syncCache(); -} - -template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("ResolveDeferred"); - DependencyManager::get()->copyBack(renderContext->args); - renderContext->args->_context->syncCache(); - -} - - - -RenderDeferredTask::RenderDeferredTask() : Task() { - _jobs.push_back(Job(PrepareDeferred())); - _jobs.push_back(Job(DrawBackground())); - _jobs.push_back(Job(DrawOpaqueDeferred())); - _jobs.push_back(Job(DrawLight())); - _jobs.push_back(Job(ResetGLState())); - _jobs.push_back(Job(RenderDeferred())); - _jobs.push_back(Job(ResolveDeferred())); - _jobs.push_back(Job(DrawTransparentDeferred())); - _jobs.push_back(Job(DrawOverlay3D())); - _jobs.push_back(Job(ResetGLState())); -} - -RenderDeferredTask::~RenderDeferredTask() { -} - -void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - // sanity checks - assert(sceneContext); - if (!sceneContext->_scene) { - return; - } - - - // Is it possible that we render without a viewFrustum ? - if (!(renderContext->args && renderContext->args->_viewFrustum)) { - return; - } - - renderContext->args->_context->syncCache(); - - for (auto job : _jobs) { - job.run(sceneContext, renderContext); - } -}; - - - -template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("DrawOpaqueDeferred"); - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - // render opaques - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withoutLayered()); - auto& renderDetails = renderContext->args->_details; - - ItemIDsBounds inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.emplace_back(ItemIDAndBounds(id)); - } - ItemIDsBounds& renderedItems = inItems; - - renderContext->_numFeedOpaqueItems = renderedItems.size(); - - ItemIDsBounds culledItems; - culledItems.reserve(inItems.size()); - if (renderContext->_cullOpaque) { - renderDetails.pointTo(RenderDetails::OPAQUE_ITEM); - cullItems(sceneContext, renderContext, renderedItems, culledItems); - renderDetails.pointTo(RenderDetails::OTHER_ITEM); - renderedItems = culledItems; - } - - renderContext->_numDrawnOpaqueItems = renderedItems.size(); - - - ItemIDsBounds sortedItems; - sortedItems.reserve(culledItems.size()); - if (renderContext->_sortOpaque) { - depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items! - renderedItems = sortedItems; - } - - // ItemIDsBounds sortedItems; - /* ItemMaterialBucketMap stateSortedItems; - stateSortedItems.allocateStandardMaterialBuckets(); - if (true) { - for (auto& itemIDAndBound : renderedItems) { - stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey()); - } - } -*/ - - if (renderContext->_renderOpaque) { - RenderArgs* args = renderContext->args; - gpu::Batch batch; - args->_batch = &batch; - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - { - GLenum buffers[3]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - batch._glDrawBuffers(bufferCount, buffers); - } - - renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems); - - args->_context->render((*args->_batch)); - args->_batch = nullptr; - } -} - - -template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("DrawTransparentDeferred"); - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - // render transparents - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape().withoutLayered()); - auto& renderDetails = renderContext->args->_details; - - ItemIDsBounds inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.push_back(id); - } - ItemIDsBounds& renderedItems = inItems; - - renderContext->_numFeedTransparentItems = renderedItems.size(); - - ItemIDsBounds culledItems; - if (renderContext->_cullTransparent) { - renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM); - cullItems(sceneContext, renderContext, inItems, culledItems); - renderDetails.pointTo(RenderDetails::OTHER_ITEM); - renderedItems = culledItems; - } - - renderContext->_numDrawnTransparentItems = renderedItems.size(); - - ItemIDsBounds sortedItems; - if (renderContext->_sortTransparent) { - depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items! - renderedItems = sortedItems; - } - - if (renderContext->_renderTransparent) { - RenderArgs* args = renderContext->args; - gpu::Batch batch; - args->_batch = &batch; - - - - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; - - { - GLenum buffers[3]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - batch._glDrawBuffers(bufferCount, buffers); - args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; - } - - - renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems); - - // Before rendering the batch make sure we re in sync with gl state - args->_context->syncCache(); - args->_context->render((*args->_batch)); - args->_batch = nullptr; - - // reset blend function to standard... - // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - } -} - -const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const { +#include "overlay3D_frag.h" + +using namespace render; + +template <> void render::jobRun(const PrepareDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("PrepareDeferred"); + DependencyManager::get()->prepare(); +} + +template <> void render::jobRun(const RenderDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("RenderDeferred"); + DependencyManager::get()->render(); +// renderContext->args->_context->syncCache(); +} + +template <> void render::jobRun(const ResolveDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("ResolveDeferred"); + DependencyManager::get()->copyBack(renderContext->args); + renderContext->args->_context->syncCache(); + +} + + + +RenderDeferredTask::RenderDeferredTask() : Task() { + _jobs.push_back(Job(PrepareDeferred())); + _jobs.push_back(Job(DrawBackground())); + _jobs.push_back(Job(DrawOpaqueDeferred())); + _jobs.push_back(Job(DrawLight())); + _jobs.push_back(Job(ResetGLState())); + _jobs.push_back(Job(RenderDeferred())); + _jobs.push_back(Job(ResolveDeferred())); + _jobs.push_back(Job(DrawTransparentDeferred())); + _jobs.push_back(Job(DrawOverlay3D())); + _jobs.push_back(Job(ResetGLState())); +} + +RenderDeferredTask::~RenderDeferredTask() { +} + +void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + // sanity checks + assert(sceneContext); + if (!sceneContext->_scene) { + return; + } + + + // Is it possible that we render without a viewFrustum ? + if (!(renderContext->args && renderContext->args->_viewFrustum)) { + return; + } + + renderContext->args->_context->syncCache(); + + for (auto job : _jobs) { + job.run(sceneContext, renderContext); + } +}; + + + +template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("DrawOpaqueDeferred"); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render opaques + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withoutLayered()); + auto& renderDetails = renderContext->args->_details; + + ItemIDsBounds inItems; + inItems.reserve(items.size()); + for (auto id : items) { + inItems.emplace_back(ItemIDAndBounds(id)); + } + ItemIDsBounds& renderedItems = inItems; + + renderContext->_numFeedOpaqueItems = renderedItems.size(); + + ItemIDsBounds culledItems; + culledItems.reserve(inItems.size()); + if (renderContext->_cullOpaque) { + renderDetails.pointTo(RenderDetails::OPAQUE_ITEM); + cullItems(sceneContext, renderContext, renderedItems, culledItems); + renderDetails.pointTo(RenderDetails::OTHER_ITEM); + renderedItems = culledItems; + } + + renderContext->_numDrawnOpaqueItems = renderedItems.size(); + + + ItemIDsBounds sortedItems; + sortedItems.reserve(culledItems.size()); + if (renderContext->_sortOpaque) { + depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items! + renderedItems = sortedItems; + } + + // ItemIDsBounds sortedItems; + /* ItemMaterialBucketMap stateSortedItems; + stateSortedItems.allocateStandardMaterialBuckets(); + if (true) { + for (auto& itemIDAndBound : renderedItems) { + stateSortedItems.insert(itemIDAndBound.id, scene->getItem(itemIDAndBound.id).getMaterialKey()); + } + } +*/ + + if (renderContext->_renderOpaque) { + RenderArgs* args = renderContext->args; + gpu::Batch batch; + args->_batch = &batch; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + { + GLenum buffers[3]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + batch._glDrawBuffers(bufferCount, buffers); + } + + renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnOpaqueItems); + + args->_context->render((*args->_batch)); + args->_batch = nullptr; + } +} + + +template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("DrawTransparentDeferred"); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render transparents + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape().withoutLayered()); + auto& renderDetails = renderContext->args->_details; + + ItemIDsBounds inItems; + inItems.reserve(items.size()); + for (auto id : items) { + inItems.push_back(id); + } + ItemIDsBounds& renderedItems = inItems; + + renderContext->_numFeedTransparentItems = renderedItems.size(); + + ItemIDsBounds culledItems; + if (renderContext->_cullTransparent) { + renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM); + cullItems(sceneContext, renderContext, inItems, culledItems); + renderDetails.pointTo(RenderDetails::OTHER_ITEM); + renderedItems = culledItems; + } + + renderContext->_numDrawnTransparentItems = renderedItems.size(); + + ItemIDsBounds sortedItems; + if (renderContext->_sortTransparent) { + depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items! + renderedItems = sortedItems; + } + + if (renderContext->_renderTransparent) { + RenderArgs* args = renderContext->args; + gpu::Batch batch; + args->_batch = &batch; + + + + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; + + { + GLenum buffers[3]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + batch._glDrawBuffers(bufferCount, buffers); + args->_alphaThreshold = TRANSPARENT_ALPHA_THRESHOLD; + } + + + renderItems(sceneContext, renderContext, renderedItems, renderContext->_maxDrawnTransparentItems); + + // Before rendering the batch make sure we re in sync with gl state + args->_context->syncCache(); + args->_context->render((*args->_batch)); + args->_batch = nullptr; + + // reset blend function to standard... + // glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + } +} + +gpu::PipelinePointer DrawOverlay3D::_opaquePipeline; +const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() { if (!_opaquePipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(overlay3D_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(overlay3D_frag))); @@ -251,53 +252,53 @@ const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const { _opaquePipeline.reset(gpu::Pipeline::create(program, state)); } return _opaquePipeline; -} - -template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer("DrawOverlay3D"); - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - // render backgrounds - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered()); - - - ItemIDsBounds inItems; - inItems.reserve(items.size()); - for (auto id : items) { - auto& item = scene->getItem(id); - if (item.getKey().isVisible() && (item.getLayer() == 1)) { - inItems.emplace_back(id); - } - } - - RenderArgs* args = renderContext->args; - gpu::Batch batch; - args->_batch = &batch; - args->_whiteTexture = DependencyManager::get()->getWhiteTexture(); - - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); - } - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - batch.setPipeline(job.getOpaquePipeline()); - batch.setUniformTexture(0, args->_whiteTexture); - - if (!inItems.empty()) { +} + +template <> void render::jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer("DrawOverlay3D"); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + // render backgrounds + auto& scene = sceneContext->_scene; + auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered()); + + + ItemIDsBounds inItems; + inItems.reserve(items.size()); + for (auto id : items) { + auto& item = scene->getItem(id); + if (item.getKey().isVisible() && (item.getLayer() == 1)) { + inItems.emplace_back(id); + } + } + + RenderArgs* args = renderContext->args; + gpu::Batch batch; + args->_batch = &batch; + args->_whiteTexture = DependencyManager::get()->getWhiteTexture(); + + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setPipeline(job.getOpaquePipeline()); + batch.setUniformTexture(0, args->_whiteTexture); + + if (!inItems.empty()) { batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0); - renderItems(sceneContext, renderContext, inItems); - } - - // Before rendering the batch make sure we re in sync with gl state - args->_context->syncCache(); - args->_context->render((*args->_batch)); - args->_batch = nullptr; - args->_whiteTexture.reset(); -} + renderItems(sceneContext, renderContext, inItems); + } + + // Before rendering the batch make sure we re in sync with gl state + args->_context->syncCache(); + args->_context->render((*args->_batch)); + args->_batch = nullptr; + args->_whiteTexture.reset(); +} diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 3b0ffdfc9b..d05a0b6f24 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -53,9 +53,9 @@ template <> void jobRun(const DrawTransparentDeferred& job, const SceneContextPo } class DrawOverlay3D { - mutable gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable + static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable public: - const gpu::PipelinePointer& getOpaquePipeline() const; + static const gpu::PipelinePointer& getOpaquePipeline(); }; namespace render { template <> void jobRun(const DrawOverlay3D& job, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); From b9ecff02f993872813e511026955d11025cb8154 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 09:45:33 -0700 Subject: [PATCH 052/121] Disable edit.js rotation text overlay temporarily --- examples/libraries/entitySelectionTool.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index d5e2b24f36..f3f1a186e1 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1992,8 +1992,9 @@ SelectionDisplay = (function () { innerRadius: 0.9, }); + // TODO: re-enable when text overlays are fixed Overlays.editOverlay(rotationDegreesDisplay, { - visible: true, + visible: false, }); updateRotationDegreesOverlay(0, yawHandleRotation, yawCenter); @@ -2121,8 +2122,9 @@ SelectionDisplay = (function () { innerRadius: 0.9, }); + // TODO: re-enable when text overlays are fixed Overlays.editOverlay(rotationDegreesDisplay, { - visible: true, + visible: false, }); updateRotationDegreesOverlay(0, pitchHandleRotation, pitchCenter); @@ -2242,8 +2244,9 @@ SelectionDisplay = (function () { innerRadius: 0.9, }); + // TODO: re-enable when text overlays are fixed Overlays.editOverlay(rotationDegreesDisplay, { - visible: true, + visible: false, }); updateRotationDegreesOverlay(0, rollHandleRotation, rollCenter); From 1eaf5ae82a5202707c2f71bf32a5253214a35806 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 10:37:57 -0700 Subject: [PATCH 053/121] 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 35f9d49c065d31433590d85f8827cbdefd93e911 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 10:47:25 -0700 Subject: [PATCH 054/121] Fix DrawOverlay3D::getOpaquePipeline invalid signature --- libraries/render-utils/src/RenderDeferredTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index bcc765839d..e0c66eb604 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -174,8 +174,8 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); } -gpu::PipelinePointer DrawOverlay3D::_opaquePipeline; -const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() const { +gpu::PipelinePointer DrawOverlay3D::_opaquePipeline; +const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() { if (!_opaquePipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(overlay3D_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(overlay3D_frag))); From e78ce8055acfa74259da7abd4455f976f83ed1ab Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Fri, 19 Jun 2015 11:17:36 -0700 Subject: [PATCH 055/121] hmdControls turns on when you enter VR mode, turns off when you exit, can toggle with CTRL+G --- examples/defaultScripts.js | 1 + examples/hmdControls.js | 58 ++++++++++++++++++++++++------ interface/src/devices/Joystick.cpp | 2 +- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 601b5254df..7bd108f86c 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -19,4 +19,5 @@ Script.load("grab.js"); Script.load("pointer.js"); Script.load("directory.js"); Script.load("mouseLook.js"); +Script.load("hmdControls.js"); Script.load("dialTone.js"); diff --git a/examples/hmdControls.js b/examples/hmdControls.js index 803d00ef94..9efcbc9db9 100644 --- a/examples/hmdControls.js +++ b/examples/hmdControls.js @@ -11,8 +11,10 @@ var MOVE_DISTANCE = 10.0; var PITCH_INCREMENT = 0.5; // degrees +var pitchChange = 0; // degrees var YAW_INCREMENT = 0.5; // degrees var VR_YAW_INCREMENT = 15.0; // degrees +var yawChange = 0; var BOOM_SPEED = 0.5; var THRESHOLD = 0.2; @@ -53,8 +55,17 @@ var warpLine = Overlays.addOverlay("line3d", { var velocity = { x: 0, y: 0, z: 0 }; var VERY_LONG_TIME = 1000000.0; +var active = Menu.isOptionChecked("Enable VR Mode"); +var prevVRMode = Menu.isOptionChecked("Enable VR Mode"); + var hmdControls = (function () { + function onKeyPressEvent(event) { + if (event.text == 'g' && event.isMeta) { + active = !active; + } + } + function findAction(name) { var actions = Controller.getAllActions(); for (var i = 0; i < actions.length; i++) { @@ -67,6 +78,9 @@ var hmdControls = (function () { } function onActionEvent(action, state) { + if (!active) { + return; + } if (state < THRESHOLD) { if (action == findAction("YAW_LEFT") || action == findAction("YAW_RIGHT")) { yawTimer = CAMERA_UPDATE_TIME; @@ -108,28 +122,28 @@ var hmdControls = (function () { break; case findAction("YAW_LEFT"): if (yawTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.bodyYaw = MyAvatar.bodyYaw + (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); + yawChange = yawChange + (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); yawTimer = CAMERA_UPDATE_TIME; } else if (!Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.bodyYaw = MyAvatar.bodyYaw + (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); + yawChange = yawChange + (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); } break; case findAction("YAW_RIGHT"): if (yawTimer < 0.0 && Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.bodyYaw = MyAvatar.bodyYaw - (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); + yawChange = yawChange - (shifted ? SHIFT_MAG * VR_YAW_INCREMENT : VR_YAW_INCREMENT); yawTimer = CAMERA_UPDATE_TIME; } else if (!Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.bodyYaw = MyAvatar.bodyYaw - (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); + yawChange = yawChange - (shifted ? SHIFT_MAG * YAW_INCREMENT : YAW_INCREMENT); } break; case findAction("PITCH_DOWN"): if (!Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch - (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); + pitchChange = pitchChange - (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT); } break; case findAction("PITCH_UP"): if (!Menu.isOptionChecked("Enable VR Mode")) { - MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT))); + pitchChange = pitchChange + (shifted ? SHIFT_MAG * PITCH_INCREMENT : PITCH_INCREMENT); } break; case findAction("SHIFT"): // speed up @@ -161,6 +175,11 @@ var hmdControls = (function () { } function update(dt) { + if (prevVRMode != Menu.isOptionChecked("Enable VR Mode")) { + active = Menu.isOptionChecked("Enable VR Mode"); + prevVRMode = Menu.isOptionChecked("Enable VR Mode"); + } + if (yawTimer >= 0.0) { yawTimer = yawTimer - dt; } @@ -175,9 +194,28 @@ var hmdControls = (function () { updateWarp(); } - MyAvatar.motorVelocity = velocity; - MyAvatar.motorTimescale = 0.0; - velocity = { x: 0, y: 0, z: 0 }; + if (active) { + Controller.captureActionEvents(); + + print(yawChange); + print(pitchChange); + print(JSON.stringify(velocity)); + + MyAvatar.bodyYaw = MyAvatar.bodyYaw + yawChange; + MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + pitchChange)); + yawChange = 0; + pitchChange = 0; + + MyAvatar.motorVelocity = velocity; + MyAvatar.motorTimescale = 0.0; + velocity = { x: 0, y: 0, z: 0 }; + } else { + Controller.releaseActionEvents(); + yawChange = 0; + pitchChange = 0; + MyAvatar.motorVelocity = {x:0.0, y:0.0, z:0.0} + MyAvatar.motorTimescale = VERY_LONG_TIME; + } } function updateWarp() { @@ -233,7 +271,7 @@ var hmdControls = (function () { } function setUp() { - Controller.captureActionEvents(); + Controller.keyPressEvent.connect(onKeyPressEvent); Controller.actionEvent.connect(onActionEvent); diff --git a/interface/src/devices/Joystick.cpp b/interface/src/devices/Joystick.cpp index 8418b39712..91f3b98bac 100644 --- a/interface/src/devices/Joystick.cpp +++ b/interface/src/devices/Joystick.cpp @@ -17,7 +17,7 @@ #include "Joystick.h" -const float CONTROLLER_THRESHOLD = 0.25f; +const float CONTROLLER_THRESHOLD = 0.3f; #ifdef HAVE_SDL2 const float MAX_AXIS = 32768.0f; From dc10e15e965bd6aa6b9591d5c94e821903edd97f Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 19 Jun 2015 14:20:00 -0700 Subject: [PATCH 056/121] 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 057/121] 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 99c217184b20833933273855cf2135a2ef753962 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 19 Jun 2015 14:46:39 -0700 Subject: [PATCH 058/121] Fixing the mic/camera buttons and the mirror UI buttons --- interface/resources/qml/AvatarInputs.qml | 177 ++++++++ interface/resources/qml/Stats.qml | 462 +++++++++++---------- interface/src/Application.cpp | 83 +--- interface/src/Application.h | 2 - interface/src/audio/AudioToolBox.cpp | 114 ----- interface/src/audio/AudioToolBox.h | 36 -- interface/src/devices/CameraToolBox.cpp | 121 ------ interface/src/devices/CameraToolBox.h | 45 -- interface/src/ui/ApplicationCompositor.cpp | 15 - interface/src/ui/ApplicationOverlay.cpp | 146 +------ interface/src/ui/ApplicationOverlay.h | 4 +- interface/src/ui/AvatarInputs.cpp | 133 ++++++ interface/src/ui/AvatarInputs.h | 59 +++ interface/src/ui/RearMirrorTools.cpp | 134 ------ interface/src/ui/RearMirrorTools.h | 56 --- interface/src/ui/Stats.cpp | 7 +- interface/src/ui/Stats.h | 5 +- 17 files changed, 626 insertions(+), 973 deletions(-) create mode 100644 interface/resources/qml/AvatarInputs.qml delete mode 100644 interface/src/audio/AudioToolBox.cpp delete mode 100644 interface/src/audio/AudioToolBox.h delete mode 100644 interface/src/devices/CameraToolBox.cpp delete mode 100644 interface/src/devices/CameraToolBox.h create mode 100644 interface/src/ui/AvatarInputs.cpp create mode 100644 interface/src/ui/AvatarInputs.h delete mode 100644 interface/src/ui/RearMirrorTools.cpp delete mode 100644 interface/src/ui/RearMirrorTools.h diff --git a/interface/resources/qml/AvatarInputs.qml b/interface/resources/qml/AvatarInputs.qml new file mode 100644 index 0000000000..7888ffd967 --- /dev/null +++ b/interface/resources/qml/AvatarInputs.qml @@ -0,0 +1,177 @@ +// +// Created by Bradley Austin Davis on 2015/06/19 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import Hifi 1.0 as Hifi +import QtQuick 2.4 +import QtQuick.Controls 1.3 +import QtGraphicalEffects 1.0 + +Hifi.AvatarInputs { + id: root + objectName: "AvatarInputs" + anchors.fill: parent + +// width: 800 +// height: 600 +// color: "black" + readonly property int iconPadding: 5 + readonly property int mirrorHeight: 215 + readonly property int mirrorWidth: 265 + readonly property int mirrorTopPad: iconPadding + readonly property int mirrorLeftPad: 10 + readonly property int iconSize: 24 + + Item { + id: mirror + width: root.mirrorWidth + height: root.mirrorVisible ? root.mirrorHeight : 0 + visible: root.mirrorVisible + anchors.left: parent.left + anchors.leftMargin: root.mirrorLeftPad + anchors.top: parent.top + anchors.topMargin: root.mirrorTopPad + clip: true + + MouseArea { + id: hover + anchors.fill: parent + hoverEnabled: true + propagateComposedEvents: true + } + + Image { + id: closeMirror + visible: hover.containsMouse + width: root.iconSize + height: root.iconSize + anchors.top: parent.top + anchors.topMargin: root.iconPadding + anchors.left: parent.left + anchors.leftMargin: root.iconPadding + source: "../images/close.svg" + MouseArea { + anchors.fill: parent + onClicked: { + root.closeMirror(); + } + } + } + + Image { + id: zoomIn + visible: hover.containsMouse + width: root.iconSize + height: root.iconSize + anchors.bottom: parent.bottom + anchors.bottomMargin: root.iconPadding + anchors.left: parent.left + anchors.leftMargin: root.iconPadding + source: root.mirrorZoomed ? "../images/minus.svg" : "../images/plus.svg" + MouseArea { + anchors.fill: parent + onClicked: { + root.toggleZoom(); + } + } + } + } + + Item { + width: root.mirrorWidth + height: 44 + + x: root.mirrorLeftPad + y: root.mirrorVisible ? root.mirrorTopPad + root.mirrorHeight : 5 + + + + Rectangle { + anchors.fill: parent + color: root.mirrorVisible ? (root.audioClipping ? "red" : "#696969") : "#00000000" + + Image { + id: faceMute + width: root.iconSize + height: root.iconSize + visible: root.cameraEnabled + anchors.left: parent.left + anchors.leftMargin: root.iconPadding + anchors.verticalCenter: parent.verticalCenter + source: root.cameraMuted ? "../images/face-mute.svg" : "../images/face.svg" + MouseArea { + anchors.fill: parent + onClicked: { + root.toggleCameraMute() + } + onDoubleClicked: { + root.resetSensors(); + } + } + } + + Image { + id: micMute + width: root.iconSize + height: root.iconSize + anchors.left: root.cameraEnabled ? faceMute.right : parent.left + anchors.leftMargin: root.iconPadding + anchors.verticalCenter: parent.verticalCenter + source: root.audioMuted ? "../images/mic-mute.svg" : "../images/mic.svg" + MouseArea { + anchors.fill: parent + onClicked: { + root.toggleAudioMute() + } + } + } + + Item { + id: audioMeter + anchors.verticalCenter: parent.verticalCenter + anchors.left: micMute.right + anchors.leftMargin: root.iconPadding + anchors.right: parent.right + anchors.rightMargin: root.iconPadding + height: 8 + Rectangle { + id: blueRect + color: "blue" + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + width: parent.width / 4 + } + Rectangle { + id: greenRect + color: "green" + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: blueRect.right + anchors.right: redRect.left + } + Rectangle { + id: redRect + color: "red" + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + width: parent.width / 5 + } + Rectangle { + z: 100 + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + width: (1.0 - root.audioLevel) * parent.width + color: "black" + } + } + } + } +} + diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 8ddea6a355..128dbcd3a6 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -2,255 +2,257 @@ import Hifi 1.0 as Hifi import QtQuick 2.3 import QtQuick.Controls 1.2 -Hifi.Stats { - id: root - objectName: "Stats" - implicitHeight: row.height - implicitWidth: row.width - readonly property int sTATS_GENERAL_MIN_WIDTH: 165 - readonly property int sTATS_PING_MIN_WIDTH: 190 - readonly property int sTATS_GEO_MIN_WIDTH: 240 - readonly property int sTATS_OCTREE_MIN_WIDTH: 410 - readonly property int fontSize: 12 - readonly property string fontColor: "white" - readonly property string bgColor: "#99333333" +Item { + anchors.fill: parent + anchors.leftMargin: 300 + Hifi.Stats { + id: root + objectName: "Stats" + implicitHeight: row.height + implicitWidth: row.width - onParentChanged: { - root.x = parent.width - root.width; - } + anchors.horizontalCenter: parent.horizontalCenter + readonly property int sTATS_GENERAL_MIN_WIDTH: 165 + readonly property int sTATS_PING_MIN_WIDTH: 190 + readonly property int sTATS_GEO_MIN_WIDTH: 240 + readonly property int sTATS_OCTREE_MIN_WIDTH: 410 + readonly property int fontSize: 12 + readonly property string fontColor: "white" + readonly property string bgColor: "#99333333" - Row { - id: row - spacing: 8 - Rectangle { - width: generalCol.width + 8; - height: generalCol.height + 8; - color: root.bgColor; + Row { + id: row + spacing: 8 + Rectangle { + width: generalCol.width + 8; + height: generalCol.height + 8; + color: root.bgColor; - MouseArea { - anchors.fill: parent - onClicked: { root.expanded = !root.expanded; } - } - - Column { - id: generalCol - spacing: 4; x: 4; y: 4; - width: sTATS_GENERAL_MIN_WIDTH - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Servers: " + root.serverCount + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Avatars: " + root.avatarCount - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Framerate: " + root.framerate - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2) - } - } - } - - Rectangle { - width: pingCol.width + 8 - height: pingCol.height + 8 - color: root.bgColor; - visible: root.audioPing != -2 - MouseArea { - anchors.fill: parent - onClicked: { root.expanded = !root.expanded; } - } - Column { - id: pingCol - spacing: 4; x: 4; y: 4; - width: sTATS_PING_MIN_WIDTH - Text { - color: root.fontColor - font.pixelSize: root.fontSize - text: "Audio ping: " + root.audioPing - } - Text { - color: root.fontColor - font.pixelSize: root.fontSize - text: "Avatar ping: " + root.avatarPing - } - Text { - color: root.fontColor - font.pixelSize: root.fontSize - text: "Entities avg ping: " + root.entitiesPing - } - Text { - color: root.fontColor - font.pixelSize: root.fontSize - visible: root.expanded; - text: "Voxel max ping: " + 0 - } - } - } - Rectangle { - width: geoCol.width + 8 - height: geoCol.height + 8 - color: root.bgColor; - MouseArea { - anchors.fill: parent - onClicked: { root.expanded = !root.expanded; } + Column { + id: generalCol + spacing: 4; x: 4; y: 4; + width: sTATS_GENERAL_MIN_WIDTH + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Servers: " + root.serverCount + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Avatars: " + root.avatarCount + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Framerate: " + root.framerate + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Mbps In/Out: " + root.mbpsIn.toFixed(2) + "/" + root.mbpsOut.toFixed(2) + } + } } - Column { - id: geoCol - spacing: 4; x: 4; y: 4; - width: sTATS_GEO_MIN_WIDTH - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Position: " + root.position.x.toFixed(1) + ", " + - root.position.y.toFixed(1) + ", " + root.position.z.toFixed(1) + + Rectangle { + width: pingCol.width + 8 + height: pingCol.height + 8 + color: root.bgColor; + visible: root.audioPing != -2 + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Velocity: " + root.velocity.toFixed(1) + Column { + id: pingCol + spacing: 4; x: 4; y: 4; + width: sTATS_PING_MIN_WIDTH + Text { + color: root.fontColor + font.pixelSize: root.fontSize + text: "Audio ping: " + root.audioPing + } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + text: "Avatar ping: " + root.avatarPing + } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + text: "Entities avg ping: " + root.entitiesPing + } + Text { + color: root.fontColor + font.pixelSize: root.fontSize + visible: root.expanded; + text: "Voxel max ping: " + 0 + } } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Yaw: " + root.yaw.toFixed(1) + } + + Rectangle { + width: geoCol.width + 8 + height: geoCol.height + 8 + color: root.bgColor; + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded; - text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " + - root.avatarMixerPps + "pps"; + Column { + id: geoCol + spacing: 4; x: 4; y: 4; + width: sTATS_GEO_MIN_WIDTH + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Position: " + root.position.x.toFixed(1) + ", " + + root.position.y.toFixed(1) + ", " + root.position.z.toFixed(1) + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Velocity: " + root.velocity.toFixed(1) + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Yaw: " + root.yaw.toFixed(1) + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; + text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " + + root.avatarMixerPps + "pps"; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; + text: "Downloads: "; + } } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded; - text: "Downloads: "; + } + Rectangle { + width: octreeCol.width + 8 + height: octreeCol.height + 8 + color: root.bgColor; + MouseArea { + anchors.fill: parent + onClicked: { root.expanded = !root.expanded; } + } + Column { + id: octreeCol + spacing: 4; x: 4; y: 4; + width: sTATS_OCTREE_MIN_WIDTH + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Triangles: " + root.triangles + + " / Quads: " + root.quads + " / Material Switches: " + root.materialSwitches + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; + text: "\tMesh Parts Rendered Opaque: " + root.meshOpaque + + " / Translucent: " + root.meshTranslucent; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; + text: "\tOpaque considered: " + root.opaqueConsidered + + " / Out of view: " + root.opaqueOutOfView + " / Too small: " + root.opaqueTooSmall; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: !root.expanded + text: "Octree Elements Server: " + root.serverElements + + " Local: " + root.localElements; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "Octree Sending Mode: " + root.sendingMode; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "Octree Packets to Process: " + root.packetStats; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "Octree Elements - "; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "\tServer: " + root.serverElements + + " Internal: " + root.serverInternal + + " Leaves: " + root.serverLeaves; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "\tLocal: " + root.localElements + + " Internal: " + root.localInternal + + " Leaves: " + root.localLeaves; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded + text: "LOD: " + root.lodStatus; + } } } } + Rectangle { - width: octreeCol.width + 8 - height: octreeCol.height + 8 + y: 250 + visible: root.timingExpanded + width: perfText.width + 8 + height: perfText.height + 8 color: root.bgColor; - MouseArea { - anchors.fill: parent - onClicked: { root.expanded = !root.expanded; } + Text { + x: 4; y: 4 + id: perfText + color: root.fontColor + font.family: root.monospaceFont + font.pixelSize: 12 + text: "------------------------------------------ Function " + + "--------------------------------------- --msecs- -calls--\n" + + root.timingStats; } - Column { - id: octreeCol - spacing: 4; x: 4; y: 4; - width: sTATS_OCTREE_MIN_WIDTH - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - text: "Triangles: " + root.triangles + - " / Quads: " + root.quads + " / Material Switches: " + root.materialSwitches - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded; - text: "\tMesh Parts Rendered Opaque: " + root.meshOpaque + - " / Translucent: " + root.meshTranslucent; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded; - text: "\tOpaque considered: " + root.opaqueConsidered + - " / Out of view: " + root.opaqueOutOfView + " / Too small: " + root.opaqueTooSmall; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: !root.expanded - text: "Octree Elements Server: " + root.serverElements + - " Local: " + root.localElements; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded - text: "Octree Sending Mode: " + root.sendingMode; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded - text: "Octree Packets to Process: " + root.packetStats; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded - text: "Octree Elements - "; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded - text: "\tServer: " + root.serverElements + - " Internal: " + root.serverInternal + - " Leaves: " + root.serverLeaves; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded - text: "\tLocal: " + root.localElements + - " Internal: " + root.localInternal + - " Leaves: " + root.localLeaves; - } - Text { - color: root.fontColor; - font.pixelSize: root.fontSize - visible: root.expanded - text: "LOD: " + root.lodStatus; - } + } + + Connections { + target: root.parent + onWidthChanged: { + root.x = root.parent.width - root.width; } } } - Rectangle { - y: 250 - visible: root.timingExpanded - width: perfText.width + 8 - height: perfText.height + 8 - color: root.bgColor; - Text { - x: 4; y: 4 - id: perfText - color: root.fontColor - font.family: root.monospaceFont - font.pixelSize: 12 - text: "------------------------------------------ Function " + - "--------------------------------------- --msecs- -calls--\n" + - root.timingStats; - } - } - - Connections { - target: root.parent - onWidthChanged: { - root.x = root.parent.width - root.width; - } - } } - diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dc0eb3d23f..fafe339bd1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -66,6 +66,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -83,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -107,11 +111,9 @@ #include "avatar/AvatarManager.h" -#include "audio/AudioToolBox.h" #include "audio/AudioIOStatsRenderer.h" #include "audio/AudioScope.h" -#include "devices/CameraToolBox.h" #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/Leapmotion.h" @@ -121,12 +123,6 @@ #include "devices/OculusManager.h" #include "devices/TV3DManager.h" -#include "gpu/Batch.h" -#include "gpu/Context.h" -#include "gpu/GLBackend.h" - -#include "RenderDeferredTask.h" - #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" @@ -142,6 +138,7 @@ #include "SpeechRecognizer.h" #endif +#include "ui/AvatarInputs.h" #include "ui/DataWebDialog.h" #include "ui/DialogsManager.h" #include "ui/LoginDialog.h" @@ -282,8 +279,6 @@ bool setupEssentials(int& argc, char** argv) { auto animationCache = DependencyManager::set(); auto ddeFaceTracker = DependencyManager::set(); auto modelBlender = DependencyManager::set(); - auto audioToolBox = DependencyManager::set(); - auto cameraToolBox = DependencyManager::set(); auto avatarManager = DependencyManager::set(); auto lodManager = DependencyManager::set(); auto jsConsole = DependencyManager::set(); @@ -861,23 +856,11 @@ void Application::initializeUi() { }); } -/* - { - PerformanceTimer perfTimer("renderOverlay"); - gpu::Context context(new gpu::GLBackend()); - RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), - lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, - RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); - _applicationOverlay.renderOverlay(&renderArgs); - } -*/ - void Application::paintGL() { PROFILE_RANGE(__FUNCTION__); _glWidget->makeCurrent(); auto lodManager = DependencyManager::get(); - gpu::Context context(new gpu::GLBackend()); RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, @@ -895,6 +878,17 @@ void Application::paintGL() { PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); + { + PerformanceTimer perfTimer("renderOverlay"); + /* + gpu::Context context(new gpu::GLBackend()); + RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(), + lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); + */ + _applicationOverlay.renderOverlay(&renderArgs); + } + glEnable(GL_LINE_SMOOTH); Menu::getInstance()->setIsOptionChecked("First Person", _myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN); @@ -977,9 +971,7 @@ void Application::paintGL() { glPopMatrix(); renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { - _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { renderRearViewMirror(&renderArgs, _mirrorViewRect); } @@ -1576,23 +1568,6 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { _mouseDragStarted = getTrueMouse(); _mousePressed = true; - if (mouseOnScreen()) { - if (DependencyManager::get()->mousePressEvent(getMouseX(), getMouseY())) { - // stop propagation - return; - } - - if (DependencyManager::get()->mousePressEvent(getMouseX(), getMouseY())) { - // stop propagation - return; - } - - if (_rearMirrorTools->mousePressEvent(getMouseX(), getMouseY())) { - // stop propagation - return; - } - } - // nobody handled this - make it an action event on the _window object HFActionEvent actionEvent(HFActionEvent::startType(), computePickRay(event->x(), event->y())); @@ -1609,17 +1584,6 @@ void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceI if (_controllerScriptingInterface.isMouseCaptured()) { return; } - - if (activeWindow() == _window) { - if (event->button() == Qt::LeftButton) { - if (mouseOnScreen()) { - if (DependencyManager::get()->mouseDoublePressEvent(getMouseX(), getMouseY())) { - // stop propagation - return; - } - } - } - } } void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { @@ -2223,13 +2187,6 @@ void Application::init() { _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); - _rearMirrorTools = new RearMirrorTools(_mirrorViewRect); - connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); - connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); - connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); - connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); - - // initialize the GlowEffect with our widget bool glow = Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect); DependencyManager::get()->init(glow); @@ -3662,7 +3619,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi _mirrorCamera.setPosition(_myAvatar->getPosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale()); - } else if (RearMirrorTools::rearViewZoomLevel.get() == BODY) { + } else if (!AvatarInputs::getInstance()->mirrorZoomed()) { _mirrorCamera.setPosition(_myAvatar->getChestPosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); @@ -3712,10 +3669,6 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi displaySide(renderArgs, _mirrorCamera, true, billboard); glPopMatrix(); - if (!billboard) { - _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); - } - // reset Viewport and projection matrix glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); glDisable(GL_SCISSOR_TEST); diff --git a/interface/src/Application.h b/interface/src/Application.h index 99834a13d2..b126757621 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -62,7 +62,6 @@ #include "ui/ModelsBrowser.h" #include "ui/NodeBounds.h" #include "ui/OctreeStatsDialog.h" -#include "ui/RearMirrorTools.h" #include "ui/SnapshotShareDialog.h" #include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" @@ -566,7 +565,6 @@ private: Camera _myCamera; // My view onto the world Camera _mirrorCamera; // Cammera for mirror view QRect _mirrorViewRect; - RearMirrorTools* _rearMirrorTools; Setting::Handle _firstRun; Setting::Handle _previousScriptLocation; diff --git a/interface/src/audio/AudioToolBox.cpp b/interface/src/audio/AudioToolBox.cpp deleted file mode 100644 index 68328e151e..0000000000 --- a/interface/src/audio/AudioToolBox.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// AudioToolBox.cpp -// interface/src/audio -// -// Created by Stephen Birarda on 2014-12-16. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include - -#include "Application.h" -#include "AudioToolBox.h" - -// Mute icon configration -const int MUTE_ICON_SIZE = 24; - -AudioToolBox::AudioToolBox() : - _iconPulseTimeReference(usecTimestampNow()) -{ -} - -bool AudioToolBox::mousePressEvent(int x, int y) { - if (_iconBounds.contains(x, y)) { - DependencyManager::get()->toggleMute(); - return true; - } - return false; -} - -void AudioToolBox::render(int x, int y, int padding, bool boxed) { - glEnable(GL_TEXTURE_2D); - - if (!_micTexture) { - _micTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/mic.svg"); - } - if (!_muteTexture) { - _muteTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/mic-mute.svg"); - } - if (_boxTexture) { - _boxTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/audio-box.svg"); - } - - auto audioIO = DependencyManager::get(); - - if (boxed) { - bool isClipping = ((audioIO->getTimeSinceLastClip() > 0.0f) && (audioIO->getTimeSinceLastClip() < 1.0f)); - const int BOX_LEFT_PADDING = 5; - const int BOX_TOP_PADDING = 10; - const int BOX_WIDTH = 266; - const int BOX_HEIGHT = 44; - - QRect boxBounds = QRect(x - BOX_LEFT_PADDING, y - BOX_TOP_PADDING, BOX_WIDTH, BOX_HEIGHT); - glm::vec4 quadColor; - - if (isClipping) { - quadColor = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f); - } else { - quadColor = glm::vec4(0.41f, 0.41f, 0.41f, 1.0f); - } - glm::vec2 topLeft(boxBounds.left(), boxBounds.top()); - glm::vec2 bottomRight(boxBounds.right(), boxBounds.bottom()); - static const glm::vec2 texCoordTopLeft(1,1); - static const glm::vec2 texCoordBottomRight(0, 0); - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_boxTexture)); - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); - } - - float iconColor = 1.0f; - - _iconBounds = QRect(x + padding, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); - if (!audioIO->isMuted()) { - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_micTexture)); - iconColor = 1.0f; - } else { - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_muteTexture)); - - // Make muted icon pulsate - static const float PULSE_MIN = 0.4f; - static const float PULSE_MAX = 1.0f; - static const float PULSE_FREQUENCY = 1.0f; // in Hz - qint64 now = usecTimestampNow(); - if (now - _iconPulseTimeReference > (qint64)USECS_PER_SECOND) { - // Prevents t from getting too big, which would diminish glm::cos precision - _iconPulseTimeReference = now - ((now - _iconPulseTimeReference) % USECS_PER_SECOND); - } - float t = (float)(now - _iconPulseTimeReference) / (float)USECS_PER_SECOND; - float pulseFactor = (glm::cos(t * PULSE_FREQUENCY * 2.0f * PI) + 1.0f) / 2.0f; - iconColor = PULSE_MIN + (PULSE_MAX - PULSE_MIN) * pulseFactor; - } - - glm::vec4 quadColor(iconColor, iconColor, iconColor, 1.0f); - - glm::vec2 topLeft(_iconBounds.left(), _iconBounds.top()); - glm::vec2 bottomRight(_iconBounds.right(), _iconBounds.bottom()); - glm::vec2 texCoordTopLeft(1,1); - glm::vec2 texCoordBottomRight(0,0); - - if (_boxQuadID == GeometryCache::UNKNOWN_ID) { - _boxQuadID = DependencyManager::get()->allocateID(); - } - - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor, _boxQuadID); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); -} \ No newline at end of file diff --git a/interface/src/audio/AudioToolBox.h b/interface/src/audio/AudioToolBox.h deleted file mode 100644 index ea2ef9f96a..0000000000 --- a/interface/src/audio/AudioToolBox.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// AudioToolBox.h -// interface/src/audio -// -// Created by Stephen Birarda on 2014-12-16. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AudioToolBox_h -#define hifi_AudioToolBox_h - -#include -#include -#include - -class AudioToolBox : public Dependency { - SINGLETON_DEPENDENCY -public: - void render(int x, int y, int padding, bool boxed); - - bool mousePressEvent(int x, int y); -protected: - AudioToolBox(); -private: - gpu::TexturePointer _micTexture; - gpu::TexturePointer _muteTexture; - gpu::TexturePointer _boxTexture; - int _boxQuadID = GeometryCache::UNKNOWN_ID; - QRect _iconBounds; - qint64 _iconPulseTimeReference = 0; -}; - -#endif // hifi_AudioToolBox_h \ No newline at end of file diff --git a/interface/src/devices/CameraToolBox.cpp b/interface/src/devices/CameraToolBox.cpp deleted file mode 100644 index 27cee5185b..0000000000 --- a/interface/src/devices/CameraToolBox.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// CameraToolBox.cpp -// interface/src/devices -// -// Created by David Rowe on 30 Apr 2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "InterfaceConfig.h" - -#include -#include - -#include "gpu/GLBackend.h" -#include "Application.h" -#include "CameraToolBox.h" -#include "FaceTracker.h" - - -CameraToolBox::CameraToolBox() : - _iconPulseTimeReference(usecTimestampNow()), - _doubleClickTimer(NULL) -{ -} - -CameraToolBox::~CameraToolBox() { - if (_doubleClickTimer) { - _doubleClickTimer->stop(); - delete _doubleClickTimer; - } -} - -bool CameraToolBox::mousePressEvent(int x, int y) { - if (_iconBounds.contains(x, y)) { - if (!_doubleClickTimer) { - // Toggle mute after waiting to check that it's not a double-click. - const int DOUBLE_CLICK_WAIT = 200; // ms - _doubleClickTimer = new QTimer(this); - connect(_doubleClickTimer, SIGNAL(timeout()), this, SLOT(toggleMute())); - _doubleClickTimer->setSingleShot(true); - _doubleClickTimer->setInterval(DOUBLE_CLICK_WAIT); - _doubleClickTimer->start(); - } - return true; - } - return false; -} - -bool CameraToolBox::mouseDoublePressEvent(int x, int y) { - if (_iconBounds.contains(x, y)) { - if (_doubleClickTimer) { - _doubleClickTimer->stop(); - delete _doubleClickTimer; - _doubleClickTimer = NULL; - } - Application::getInstance()->resetSensors(); - return true; - } - return false; -} - -void CameraToolBox::toggleMute() { - delete _doubleClickTimer; - _doubleClickTimer = NULL; - - FaceTracker* faceTracker = Application::getInstance()->getSelectedFaceTracker(); - if (faceTracker) { - faceTracker->toggleMute(); - } -} - -void CameraToolBox::render(int x, int y, bool boxed) { - glEnable(GL_TEXTURE_2D); - - if (!_enabledTexture) { - _enabledTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/face.svg"); - } - if (!_mutedTexture) { - _mutedTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/face-mute.svg"); - } - - const int MUTE_ICON_SIZE = 24; - _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); - float iconColor = 1.0f; - if (!Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking)) { - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_enabledTexture)); - } else { - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_mutedTexture)); - - // Make muted icon pulsate - static const float PULSE_MIN = 0.4f; - static const float PULSE_MAX = 1.0f; - static const float PULSE_FREQUENCY = 1.0f; // in Hz - qint64 now = usecTimestampNow(); - if (now - _iconPulseTimeReference > (qint64)USECS_PER_SECOND) { - // Prevents t from getting too big, which would diminish glm::cos precision - _iconPulseTimeReference = now - ((now - _iconPulseTimeReference) % USECS_PER_SECOND); - } - float t = (float)(now - _iconPulseTimeReference) / (float)USECS_PER_SECOND; - float pulseFactor = (glm::cos(t * PULSE_FREQUENCY * 2.0f * PI) + 1.0f) / 2.0f; - iconColor = PULSE_MIN + (PULSE_MAX - PULSE_MIN) * pulseFactor; - } - - glm::vec4 quadColor(iconColor, iconColor, iconColor, 1.0f); - - glm::vec2 topLeft(_iconBounds.left(), _iconBounds.top()); - glm::vec2 bottomRight(_iconBounds.right(), _iconBounds.bottom()); - glm::vec2 texCoordTopLeft(1,1); - glm::vec2 texCoordBottomRight(0,0); - - if (_boxQuadID == GeometryCache::UNKNOWN_ID) { - _boxQuadID = DependencyManager::get()->allocateID(); - } - - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor, _boxQuadID); - - glDisable(GL_TEXTURE_2D); -} \ No newline at end of file diff --git a/interface/src/devices/CameraToolBox.h b/interface/src/devices/CameraToolBox.h deleted file mode 100644 index 89e0c6a8dc..0000000000 --- a/interface/src/devices/CameraToolBox.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// CameraToolBox.h -// interface/src/devices -// -// Created by David Rowe on 30 Apr 2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_CameraToolBox_h -#define hifi_CameraToolBox_h - -#include - -#include -#include - -class CameraToolBox : public QObject, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - -public: - void render(int x, int y, bool boxed); - bool mousePressEvent(int x, int y); - bool mouseDoublePressEvent(int x, int y); - -protected: - CameraToolBox(); - ~CameraToolBox(); - -private slots: - void toggleMute(); - -private: - gpu::TexturePointer _enabledTexture; - gpu::TexturePointer _mutedTexture; - int _boxQuadID = GeometryCache::UNKNOWN_ID; - QRect _iconBounds; - qint64 _iconPulseTimeReference = 0; - QTimer* _doubleClickTimer; -}; - -#endif // hifi_CameraToolBox_h \ No newline at end of file diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index c2d2d91216..8e8290f060 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -16,27 +16,12 @@ #include #include -#include #include -#include -#include #include -#include #include - -#include "AudioClient.h" -#include "audio/AudioIOStatsRenderer.h" -#include "audio/AudioScope.h" -#include "audio/AudioToolBox.h" #include "Application.h" -#include "devices/CameraToolBox.h" -#include "Util.h" -#include "ui/Stats.h" - -#include "../../libraries/render-utils/standardTransformPNTC_vert.h" -#include "../../libraries/render-utils/standardDrawTexture_frag.h" // Used to animate the magnification windows static const float MAG_SPEED = 0.08f; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index b24054f8a8..8e5bdca8c0 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -29,13 +29,12 @@ #include "AudioClient.h" #include "audio/AudioIOStatsRenderer.h" #include "audio/AudioScope.h" -#include "audio/AudioToolBox.h" #include "Application.h" #include "ApplicationOverlay.h" -#include "devices/CameraToolBox.h" #include "Util.h" #include "ui/Stats.h" +#include "ui/AvatarInputs.h" const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; const int AUDIO_METER_GAP = 5; @@ -86,12 +85,10 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // TODO move to Application::idle()? Stats::getInstance()->updateStats(); + AvatarInputs::getInstance()->update(); buildFramebufferObject(); - // First render the mirror to the mirror FBO - // renderRearViewToFbo(renderArgs); - // Execute the batch into our framebuffer _overlayFramebuffer->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -99,10 +96,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // Now render the overlay components together into a single texture renderOverlays(renderArgs); - //renderAudioMeter(renderArgs); - //renderCameraToggle(renderArgs); renderStatsAndLogs(renderArgs); - // renderRearView(renderArgs); renderDomainConnectionStatusBorder(renderArgs); renderQmlUi(renderArgs); _overlayFramebuffer->release(); @@ -149,142 +143,6 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { fboViewport(_overlayFramebuffer); } -void ApplicationOverlay::renderCameraToggle(RenderArgs* renderArgs) { - if (Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)) { - return; - } - - int audioMeterY; - bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !qApp->isHMDMode(); - bool boxed = smallMirrorVisible && - !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror); - if (boxed) { - audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING; - } else { - audioMeterY = AUDIO_METER_GAP + MUTE_ICON_PADDING; - } - - DependencyManager::get()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, boxed); - fboViewport(_overlayFramebuffer); -} - -void ApplicationOverlay::renderAudioMeter(RenderArgs* renderArgs) { - auto audio = DependencyManager::get(); - - // Audio VU Meter and Mute Icon - const int MUTE_ICON_SIZE = 24; - const int AUDIO_METER_HEIGHT = 8; - const int INTER_ICON_GAP = 2; - - int cameraSpace = 0; - int audioMeterWidth = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - MUTE_ICON_PADDING; - int audioMeterScaleWidth = audioMeterWidth - 2; - int audioMeterX = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_GAP; - if (!Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)) { - cameraSpace = MUTE_ICON_SIZE + INTER_ICON_GAP; - audioMeterWidth -= cameraSpace; - audioMeterScaleWidth -= cameraSpace; - audioMeterX += cameraSpace; - } - - int audioMeterY; - bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !qApp->isHMDMode(); - bool boxed = smallMirrorVisible && - !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror); - if (boxed) { - audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING; - } else { - audioMeterY = AUDIO_METER_GAP + MUTE_ICON_PADDING; - } - - const glm::vec4 AUDIO_METER_BLUE = { 0.0, 0.0, 1.0, 1.0 }; - const glm::vec4 AUDIO_METER_GREEN = { 0.0, 1.0, 0.0, 1.0 }; - const glm::vec4 AUDIO_METER_RED = { 1.0, 0.0, 0.0, 1.0 }; - const float CLIPPING_INDICATOR_TIME = 1.0f; - const float AUDIO_METER_AVERAGING = 0.5; - const float LOG2 = log(2.0f); - const float METER_LOUDNESS_SCALE = 2.8f / 5.0f; - const float LOG2_LOUDNESS_FLOOR = 11.0f; - float audioGreenStart = 0.25f * audioMeterScaleWidth; - float audioRedStart = 0.8f * audioMeterScaleWidth; - float audioLevel = 0.0f; - float loudness = audio->getLastInputLoudness() + 1.0f; - - _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.0f - AUDIO_METER_AVERAGING) * loudness; - float log2loudness = logf(_trailingAudioLoudness) / LOG2; - - if (log2loudness <= LOG2_LOUDNESS_FLOOR) { - audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE * audioMeterScaleWidth; - } else { - audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.0f)) * METER_LOUDNESS_SCALE * audioMeterScaleWidth; - } - if (audioLevel > audioMeterScaleWidth) { - audioLevel = audioMeterScaleWidth; - } - bool isClipping = ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); - - DependencyManager::get()->render(MIRROR_VIEW_LEFT_PADDING + AUDIO_METER_GAP, audioMeterY, cameraSpace, boxed); - - auto canvasSize = qApp->getCanvasSize(); - DependencyManager::get()->render(canvasSize.x, canvasSize.y); - DependencyManager::get()->render(WHITE_TEXT, canvasSize.x, canvasSize.y); - - audioMeterY += AUDIO_METER_HEIGHT; - - // Draw audio meter background Quad - DependencyManager::get()->renderQuad(audioMeterX, audioMeterY, audioMeterWidth, AUDIO_METER_HEIGHT, - glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - - if (audioLevel > audioRedStart) { - glm::vec4 quadColor; - if (!isClipping) { - quadColor = AUDIO_METER_RED; - } else { - quadColor = glm::vec4(1, 1, 1, 1); - } - // Draw Red Quad - DependencyManager::get()->renderQuad(audioMeterX + audioRedStart, - audioMeterY, - audioLevel - audioRedStart, - AUDIO_METER_HEIGHT, quadColor, - _audioRedQuad); - - audioLevel = audioRedStart; - } - - if (audioLevel > audioGreenStart) { - glm::vec4 quadColor; - if (!isClipping) { - quadColor = AUDIO_METER_GREEN; - } else { - quadColor = glm::vec4(1, 1, 1, 1); - } - // Draw Green Quad - DependencyManager::get()->renderQuad(audioMeterX + audioGreenStart, - audioMeterY, - audioLevel - audioGreenStart, - AUDIO_METER_HEIGHT, quadColor, - _audioGreenQuad); - - audioLevel = audioGreenStart; - } - - if (audioLevel >= 0) { - glm::vec4 quadColor; - if (!isClipping) { - quadColor = AUDIO_METER_BLUE; - } else { - quadColor = glm::vec4(1, 1, 1, 1); - } - // Draw Blue (low level) quad - DependencyManager::get()->renderQuad(audioMeterX, - audioMeterY, - audioLevel, AUDIO_METER_HEIGHT, quadColor, - _audioBlueQuad); - } - fboViewport(_overlayFramebuffer); -} - void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index e50622d122..e7b28d53ed 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -29,8 +29,8 @@ public: private: - void renderAudioMeter(RenderArgs* renderArgs); - void renderCameraToggle(RenderArgs* renderArgs); + //void renderAudioMeter(RenderArgs* renderArgs); + //void renderCameraToggle(RenderArgs* renderArgs); void renderStatsAndLogs(RenderArgs* renderArgs); void renderDomainConnectionStatusBorder(RenderArgs* renderArgs); void renderRearViewToFbo(RenderArgs* renderArgs); diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp new file mode 100644 index 0000000000..4066dab80c --- /dev/null +++ b/interface/src/ui/AvatarInputs.cpp @@ -0,0 +1,133 @@ +// +// Created by Bradley Austin Davis 2015/06/19 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#include "Application.h" +#include "AvatarInputs.h" + +#include + +#include "Menu.h" +#include "devices/FaceTracker.h" + +HIFI_QML_DEF(AvatarInputs) + + +static AvatarInputs* INSTANCE{ nullptr }; +static const char SETTINGS_GROUP_NAME[] = "Rear View Tools"; +static const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel"; + +static Setting::Handle rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS, 0); + +AvatarInputs* AvatarInputs::getInstance() { + if (!INSTANCE) { + AvatarInputs::registerType(); + AvatarInputs::show(); + Q_ASSERT(INSTANCE); + } + return INSTANCE; +} + +AvatarInputs::AvatarInputs(QQuickItem* parent) : QQuickItem(parent) { + INSTANCE = this; + _mirrorZoomed = rearViewZoomLevel.get() != 0; +} + +#define AI_UPDATE(name, src) \ + { \ + auto val = src; \ + if (_##name != val) { \ + _##name = val; \ + emit name##Changed(); \ + } \ + } + +#define AI_UPDATE_FLOAT(name, src, epsilon) \ + { \ + float val = src; \ + if (abs(_##name - val) >= epsilon) { \ + _##name = val; \ + emit name##Changed(); \ + } \ + } + +void AvatarInputs::update() { + if (!Menu::getInstance()) { + return; + } + AI_UPDATE(mirrorVisible, Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !qApp->isHMDMode() + && !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)); + AI_UPDATE(cameraEnabled, !Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)); + AI_UPDATE(cameraMuted, Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking)); + + auto audioIO = DependencyManager::get(); + const float CLIPPING_INDICATOR_TIME = 1.0f; + const float AUDIO_METER_AVERAGING = 0.5; + const float LOG2 = log(2.0f); + const float METER_LOUDNESS_SCALE = 2.8f / 5.0f; + const float LOG2_LOUDNESS_FLOOR = 11.0f; + float audioLevel = 0.0f; + auto audio = DependencyManager::get(); + float loudness = audio->getLastInputLoudness() + 1.0f; + + _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.0f - AUDIO_METER_AVERAGING) * loudness; + + float log2loudness = logf(_trailingAudioLoudness) / LOG2; + + if (log2loudness <= LOG2_LOUDNESS_FLOOR) { + audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE; + } else { + audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.0f)) * METER_LOUDNESS_SCALE; + } + if (audioLevel > 1.0) { + audioLevel = 1.0; + } + AI_UPDATE_FLOAT(audioLevel, audioLevel, 0.01); + AI_UPDATE(audioClipping, ((audioIO->getTimeSinceLastClip() > 0.0f) && (audioIO->getTimeSinceLastClip() < 1.0f))); + AI_UPDATE(audioMuted, audioIO->isMuted()); + + //// Make muted icon pulsate + //static const float PULSE_MIN = 0.4f; + //static const float PULSE_MAX = 1.0f; + //static const float PULSE_FREQUENCY = 1.0f; // in Hz + //qint64 now = usecTimestampNow(); + //if (now - _iconPulseTimeReference > (qint64)USECS_PER_SECOND) { + // // Prevents t from getting too big, which would diminish glm::cos precision + // _iconPulseTimeReference = now - ((now - _iconPulseTimeReference) % USECS_PER_SECOND); + //} + //float t = (float)(now - _iconPulseTimeReference) / (float)USECS_PER_SECOND; + //float pulseFactor = (glm::cos(t * PULSE_FREQUENCY * 2.0f * PI) + 1.0f) / 2.0f; + //iconColor = PULSE_MIN + (PULSE_MAX - PULSE_MIN) * pulseFactor; +} + +void AvatarInputs::toggleCameraMute() { + FaceTracker* faceTracker = Application::getInstance()->getSelectedFaceTracker(); + if (faceTracker) { + faceTracker->toggleMute(); + } +} + +void AvatarInputs::toggleAudioMute() { + DependencyManager::get()->toggleMute(); +} + +void AvatarInputs::resetSensors() { + qApp->resetSensors(); +} + +void AvatarInputs::toggleZoom() { + _mirrorZoomed = !_mirrorZoomed; + rearViewZoomLevel.set(_mirrorZoomed ? 0 : 1); + emit mirrorZoomedChanged(); +} + +void AvatarInputs::closeMirror() { + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + Menu::getInstance()->triggerOption(MenuOption::Mirror); + } +} diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h new file mode 100644 index 0000000000..8ed4e8f163 --- /dev/null +++ b/interface/src/ui/AvatarInputs.h @@ -0,0 +1,59 @@ +// +// Created by Bradley Austin Davis 2015/06/19 +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarInputs_h +#define hifi_AvatarInputs_h + +#include +#include + +#define AI_PROPERTY(type, name, initialValue) \ + Q_PROPERTY(type name READ name NOTIFY name##Changed) \ +public: \ + type name() { return _##name; }; \ +private: \ + type _##name{ initialValue }; + +class AvatarInputs : public QQuickItem { + Q_OBJECT + HIFI_QML_DECL + + AI_PROPERTY(bool, cameraEnabled, false) + AI_PROPERTY(bool, cameraMuted, false) + AI_PROPERTY(bool, audioMuted, false) + AI_PROPERTY(bool, audioClipping, false) + AI_PROPERTY(float, audioLevel, 0) + AI_PROPERTY(bool, mirrorVisible, false) + AI_PROPERTY(bool, mirrorZoomed, true) + +public: + static AvatarInputs* getInstance(); + AvatarInputs(QQuickItem* parent = nullptr); + void update(); + +signals: + void cameraEnabledChanged(); + void cameraMutedChanged(); + void audioMutedChanged(); + void audioClippingChanged(); + void audioLevelChanged(); + void mirrorVisibleChanged(); + void mirrorZoomedChanged(); + +protected: + Q_INVOKABLE void resetSensors(); + Q_INVOKABLE void toggleCameraMute(); + Q_INVOKABLE void toggleAudioMute(); + Q_INVOKABLE void toggleZoom(); + Q_INVOKABLE void closeMirror(); + +private: + float _trailingAudioLoudness{ 0 }; +}; + +#endif // hifi_AvatarInputs_h diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp deleted file mode 100644 index 33f3e1b487..0000000000 --- a/interface/src/ui/RearMirrorTools.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// -// RearMirrorTools.cpp -// interface/src/ui -// -// Created by Stojce Slavkovski on 10/23/2013. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "InterfaceConfig.h" - -#include - -#include -#include -#include - -#include "Application.h" -#include "RearMirrorTools.h" -#include "Util.h" - -const int ICON_SIZE = 24; -const int ICON_PADDING = 5; - -const char SETTINGS_GROUP_NAME[] = "Rear View Tools"; -const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel"; -Setting::Handle RearMirrorTools::rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS, - ZoomLevel::HEAD); - -RearMirrorTools::RearMirrorTools(QRect& bounds) : - _bounds(bounds), - _windowed(false), - _fullScreen(false) -{ - _closeTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/close.svg"); - - _zoomHeadTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/plus.svg"); - _zoomBodyTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/minus.svg"); - - _shrinkIconRect = QRect(ICON_PADDING, ICON_PADDING, ICON_SIZE, ICON_SIZE); - _closeIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); - _resetIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); - _bodyZoomIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE); - _headZoomIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE); -} - -void RearMirrorTools::render(RenderArgs* renderArgs, bool fullScreen, const QPoint & mousePosition) { - if (fullScreen) { - _fullScreen = true; - displayIcon(QRect(QPoint(), qApp->getDeviceSize()), _shrinkIconRect, _closeTexture); - } else { - // render rear view tools if mouse is in the bounds - _windowed = _bounds.contains(mousePosition); - if (_windowed) { - displayIcon(_bounds, _closeIconRect, _closeTexture); - - ZoomLevel zoomLevel = (ZoomLevel)rearViewZoomLevel.get(); - displayIcon(_bounds, _headZoomIconRect, _zoomHeadTexture, zoomLevel == HEAD); - displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTexture, zoomLevel == BODY); - } - } -} - -bool RearMirrorTools::mousePressEvent(int x, int y) { - if (_windowed) { - if (_closeIconRect.contains(x, y)) { - _windowed = false; - emit closeView(); - return true; - } - - if (_headZoomIconRect.contains(x, y)) { - rearViewZoomLevel.set(HEAD); - return true; - } - - if (_bodyZoomIconRect.contains(x, y)) { - rearViewZoomLevel.set(BODY); - return true; - } - - if (_bounds.contains(x, y)) { - _windowed = false; - emit restoreView(); - return true; - } - } - - if (_fullScreen) { - if (_shrinkIconRect.contains(x, y)) { - _fullScreen = false; - emit shrinkView(); - return true; - } - } - return false; -} - -void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, const gpu::TexturePointer& texture, bool selected) { - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glOrtho(bounds.left(), bounds.right(), bounds.bottom(), bounds.top(), -1.0, 1.0); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); - - glm::vec4 quadColor; - if (selected) { - quadColor = glm::vec4(.5f, .5f, .5f, 1.0f); - } else { - quadColor = glm::vec4(1, 1, 1, 1); - } - - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(texture)); - - glm::vec2 topLeft(iconBounds.left(), iconBounds.top()); - glm::vec2 bottomRight(iconBounds.right(), iconBounds.bottom()); - static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); - static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); - - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); - - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); -} diff --git a/interface/src/ui/RearMirrorTools.h b/interface/src/ui/RearMirrorTools.h deleted file mode 100644 index c633d72a49..0000000000 --- a/interface/src/ui/RearMirrorTools.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// RearMirrorTools.h -// interface/src/ui -// -// Created by Stojce Slavkovski on 10/23/2013. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_RearMirrorTools_h -#define hifi_RearMirrorTools_h - -#include -#include - -enum ZoomLevel { - HEAD = 0, - BODY = 1 -}; - -class RearMirrorTools : public QObject { - Q_OBJECT -public: - RearMirrorTools(QRect& bounds); - void render(RenderArgs* renderArgs, bool fullScreen, const QPoint & mousePos); - bool mousePressEvent(int x, int y); - - static Setting::Handle rearViewZoomLevel; - -signals: - void closeView(); - void shrinkView(); - void resetView(); - void restoreView(); - -private: - QRect _bounds; - gpu::TexturePointer _closeTexture; - gpu::TexturePointer _zoomBodyTexture; - gpu::TexturePointer _zoomHeadTexture; - - QRect _closeIconRect; - QRect _resetIconRect; - QRect _shrinkIconRect; - QRect _headZoomIconRect; - QRect _bodyZoomIconRect; - - bool _windowed; - bool _fullScreen; - - void displayIcon(QRect bounds, QRect iconBounds, const gpu::TexturePointer& texture, bool selected = false); -}; - -#endif // hifi_RearMirrorTools_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index acc9521c72..934f53ffc7 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -1,8 +1,5 @@ // -// Stats.cpp -// interface/src/ui -// -// Created by Lucas Crisman on 22/03/14. +// Created by Bradley Austin Davis 2015/06/17 // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -376,4 +373,4 @@ void Stats::display( } -*/ \ No newline at end of file +*/ diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 58d920d9a5..8582d436af 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -1,8 +1,5 @@ // -// Stats.h -// interface/src/ui -// -// Created by Lucas Crisman on 22/03/14. +// Created by Bradley Austin Davis 2015/06/17 // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From 1734d5e584a52b1bd2cf2baff2b09377bc36c39a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 15:05:55 -0700 Subject: [PATCH 059/121] 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 a0d4b7ec7c918066beb0ae70097640162c244705 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Fri, 19 Jun 2015 16:11:43 -0700 Subject: [PATCH 060/121] without script, doesn't limit you to constant degree turns --- examples/hmdControls.js | 4 ---- interface/src/avatar/MyAvatar.cpp | 26 +++----------------------- interface/src/avatar/MyAvatar.h | 1 - 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/examples/hmdControls.js b/examples/hmdControls.js index 9efcbc9db9..e14ddca3ef 100644 --- a/examples/hmdControls.js +++ b/examples/hmdControls.js @@ -197,10 +197,6 @@ var hmdControls = (function () { if (active) { Controller.captureActionEvents(); - print(yawChange); - print(pitchChange); - print(JSON.stringify(velocity)); - MyAvatar.bodyYaw = MyAvatar.bodyYaw + yawChange; MyAvatar.headPitch = Math.max(-180, Math.min(180, MyAvatar.headPitch + pitchChange)); yawChange = 0; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 586e7a1f56..148d9cc08c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -76,7 +76,6 @@ const float MyAvatar::ZOOM_DEFAULT = 1.5f; MyAvatar::MyAvatar() : Avatar(), - _turningKeyPressTime(0.0f), _gravity(0.0f, 0.0f, 0.0f), _wasPushing(false), _isPushing(false), @@ -1205,28 +1204,9 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& c } void MyAvatar::updateOrientation(float deltaTime) { - // Gather rotation information from keyboard - const float TIME_BETWEEN_HMD_TURNS = 0.5f; - const float HMD_TURN_DEGREES = 22.5f; - if (!qApp->isHMDMode()) { - // Smoothly rotate body with arrow keys if not in HMD - _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; - _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; - } else { - // Jump turns if in HMD - if (_driveKeys[ROT_RIGHT] || _driveKeys[ROT_LEFT]) { - if (_turningKeyPressTime == 0.0f) { - setOrientation(getOrientation() * - glm::quat(glm::radians(glm::vec3(0.f, _driveKeys[ROT_LEFT] ? HMD_TURN_DEGREES : -HMD_TURN_DEGREES, 0.0f)))); - } - _turningKeyPressTime += deltaTime; - if (_turningKeyPressTime > TIME_BETWEEN_HMD_TURNS) { - _turningKeyPressTime = 0.0f; - } - } else { - _turningKeyPressTime = 0.0f; - } - } + // Smoothly rotate body with arrow keys + _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; + _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); // update body orientation by movement inputs diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 7adaf908f4..c4a9362fef 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -210,7 +210,6 @@ private: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); - float _turningKeyPressTime; glm::vec3 _gravity; float _driveKeys[MAX_DRIVE_KEYS]; From 3ab8025b821afc46f5136914d33a2618da384e11 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 19 Jun 2015 16:14:05 -0700 Subject: [PATCH 061/121] Responding to Sam's comments --- interface/src/ui/ApplicationOverlay.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 8e5bdca8c0..cae62ef61f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -108,9 +108,6 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { gpu::Batch batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); - batch._glDisable(GL_DEPTH_TEST); - batch._glDisable(GL_LIGHTING); - batch._glEnable(GL_BLEND); batch.setProjectionTransform(mat4()); batch.setModelTransform(mat4()); batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); @@ -122,6 +119,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { glm::vec2 size = qApp->getCanvasSize(); + mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -140,6 +138,8 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); + + renderArgs->_context->syncCache(); fboViewport(_overlayFramebuffer); } @@ -184,7 +184,7 @@ void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) { void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderArgs) { auto geometryCache = DependencyManager::get(); - std::once_flag once; + static std::once_flag once; std::call_once(once, [&] { QVector points; static const float B = 0.99f; @@ -200,9 +200,6 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr gpu::Batch batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); - batch._glDisable(GL_DEPTH_TEST); - batch._glDisable(GL_LIGHTING); - batch._glEnable(GL_BLEND); batch.setProjectionTransform(mat4()); batch.setModelTransform(mat4()); batch.setUniformTexture(0, DependencyManager::get()->getWhiteTexture()); From bdcf87a3c6ddbc36b08b717eef13c3c9fe535fef Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 19 Jun 2015 16:28:45 -0700 Subject: [PATCH 062/121] Improve legibility of entities editor Increased font sizes. Improved contrast between values and backgrounds. --- examples/html/style.css | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/examples/html/style.css b/examples/html/style.css index dd2e96ab43..4b7d4c825f 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -8,7 +8,7 @@ body { background-color: rgb(76, 76, 76); color: rgb(204, 204, 204); font-family: Arial; - font-size: 8.25pt; + font-size: 9.0pt; -webkit-touch-callout: none; -webkit-user-select: none; @@ -58,6 +58,7 @@ body { .multi-property-section { } + .property-section { display: block; margin: 10 10; @@ -132,7 +133,7 @@ input.no-spin::-webkit-inner-spin-button { table#entity-table { border-collapse: collapse; font-family: Sans-Serif; - font-size: 7.5pt; + font-size: 9pt; width: 100%; } @@ -156,7 +157,7 @@ table#entity-table { } #entity-table td { - font-size: 8.25pt; + font-size: 9.0pt; border: 0pt black solid; word-wrap: nowrap; white-space: nowrap; @@ -176,14 +177,14 @@ th#entity-type { div.input-area { display: inline-block; - font-size: 7.5pt; + font-size: 9pt; } input { } #type { - font-size: 10.5pt; + font-size: 9.0pt; } #type label { @@ -191,14 +192,14 @@ input { } input, textarea { - background-color: rgb(102, 102, 102); - color: rgb(204, 204, 204); + background-color: rgb(63, 63, 63); + color: rgb(255, 255, 255); border: none; - font-size: 7.5pt; + font-size: 9pt; } input:disabled, textarea:disabled { - background-color: rgb(102, 102, 102); + background-color: rgb(63, 63, 63); color: rgb(160, 160, 160); } @@ -224,7 +225,7 @@ input:disabled, textarea:disabled { #properties-list .property { padding: 4pt; border-bottom: 0.75pt solid rgb(63, 63, 63); - min-height: 1em; + min-height: 12pt; } @@ -245,7 +246,6 @@ table#properties-list { font-weight: bold; overflow: hidden; text-overflow: ellipsis; - vertical-align: middle; height: 1.2em; } @@ -270,9 +270,7 @@ div.inner { } td { - - - vertical-align: top; + vertical-align: top; } #no-entities { From a7f291154b0a39ad59be65013aadf900605609be Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Jun 2015 16:28:58 -0700 Subject: [PATCH 063/121] 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 064/121] 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 065/121] 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 066/121] 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 067/121] 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 068/121] 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 5bbfb97c37351cc3259a418856b386e8aa7b3525 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 21 Jun 2015 13:31:18 -0700 Subject: [PATCH 069/121] Fixing blurry UI on retina displays --- interface/src/ui/ApplicationOverlay.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index cae62ef61f..c236164957 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -225,8 +225,7 @@ GLuint ApplicationOverlay::getOverlayTexture() { } void ApplicationOverlay::buildFramebufferObject() { - auto canvasSize = qApp->getCanvasSize(); - QSize fboSize = QSize(canvasSize.x, canvasSize.y); + QSize fboSize = qApp->getDeviceSize(); if (_overlayFramebuffer && fboSize == _overlayFramebuffer->size()) { // Already built return; From 012b0973b980c186cc4352da9050c3ffa9638ba5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 21 Jun 2015 13:41:21 -0700 Subject: [PATCH 070/121] removing cruft --- interface/src/ui/ApplicationOverlay.cpp | 3 --- interface/src/ui/ApplicationOverlay.h | 8 +------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c236164957..63f68b86ce 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -53,9 +53,6 @@ static void fboViewport(QOpenGLFramebufferObject* fbo) { ApplicationOverlay::ApplicationOverlay() { auto geometryCache = DependencyManager::get(); - _audioRedQuad = geometryCache->allocateID(); - _audioGreenQuad = geometryCache->allocateID(); - _audioBlueQuad = geometryCache->allocateID(); _domainStatusBorder = geometryCache->allocateID(); _magnifierBorder = geometryCache->allocateID(); diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index e7b28d53ed..2f434ed7e1 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -28,9 +28,6 @@ public: GLuint getOverlayTexture(); private: - - //void renderAudioMeter(RenderArgs* renderArgs); - //void renderCameraToggle(RenderArgs* renderArgs); void renderStatsAndLogs(RenderArgs* renderArgs); void renderDomainConnectionStatusBorder(RenderArgs* renderArgs); void renderRearViewToFbo(RenderArgs* renderArgs); @@ -42,10 +39,7 @@ private: float _alpha{ 1.0f }; float _trailingAudioLoudness{ 0.0f }; GLuint _uiTexture{ 0 }; - - int _audioRedQuad; - int _audioGreenQuad; - int _audioBlueQuad; + int _domainStatusBorder; int _magnifierBorder; From 4ccdc78866d61b398adc1360519dd5f1a0644ed3 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 21 Jun 2015 15:53:24 -0700 Subject: [PATCH 071/121] Fixing frustum perspective bug --- libraries/octree/src/ViewFrustum.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 815376a456..974b1066a8 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -65,9 +65,10 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { _farClip = -_corners[BOTTOM_LEFT_FAR].z; _aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) / (_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y); - glm::vec3 right = glm::normalize(glm::vec3(_corners[TOP_RIGHT_NEAR])); - glm::vec3 left = glm::normalize(glm::vec3(_corners[TOP_LEFT_NEAR])); - _fieldOfView = abs(glm::degrees(glm::angle(right, left))); + vec4 top = _inverseProjection * vec4(0, 1, -1, 1); + top /= top.w; + static const vec3 center(0, 0, -1); + _fieldOfView = glm::degrees(2.0f * abs(glm::angle(center, glm::normalize(vec3(top))))); } // ViewFrustum::calculateViewFrustum() From 02510790c38b66f3d4b6cf05f24da2118493f33f Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 21 Jun 2015 17:16:30 -0700 Subject: [PATCH 072/121] Fixing projection during star rendering --- interface/src/starfield/renderer/Renderer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/src/starfield/renderer/Renderer.cpp b/interface/src/starfield/renderer/Renderer.cpp index 1ebb4245e2..5fc858d952 100644 --- a/interface/src/starfield/renderer/Renderer.cpp +++ b/interface/src/starfield/renderer/Renderer.cpp @@ -11,6 +11,7 @@ // #include "starfield/renderer/Renderer.h" +#include "Application.h" using namespace starfield; @@ -52,6 +53,10 @@ void Renderer::render(float perspective, float aspect, mat4 const& orientation, matrix[3][1] = 0.0f; matrix[3][2] = 0.0f; + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(glm::value_ptr(qApp->getDisplayViewFrustum()->getProjection())); + glMatrixMode(GL_MODELVIEW); // extract local z vector vec3 ahead = vec3(matrix[2]); @@ -74,6 +79,10 @@ void Renderer::render(float perspective, float aspect, mat4 const& orientation, floodFill(cursor, TileSelection(*this, _tileArray, _tileArray + _tiling.getTileCount(), (TileSelection::Cursor*) _batchCountArray)); this->glBatch(glm::value_ptr(matrix), prepareBatch((unsigned*) _batchOffs, _outIndexPos), alpha); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } // renderer construction From 1b44c220a729093141cb029ad0bb223b1af2dd03 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Jun 2015 09:42:21 -0700 Subject: [PATCH 073/121] Prep work for procedural stars & stuff --- libraries/octree/src/ViewFrustum.cpp | 8 +- libraries/render-utils/src/GeometryCache.cpp | 5 ++ libraries/render-utils/src/GeometryCache.h | 1 + .../src/standardTransformPNTC.slv | 2 + libraries/render-utils/src/stars.slf | 76 +++++++++++++++++++ 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 libraries/render-utils/src/stars.slf diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 974b1066a8..820ab32b67 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -65,10 +65,10 @@ void ViewFrustum::setProjection(const glm::mat4& projection) { _farClip = -_corners[BOTTOM_LEFT_FAR].z; _aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) / (_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y); - vec4 top = _inverseProjection * vec4(0, 1, -1, 1); - top /= top.w; - static const vec3 center(0, 0, -1); - _fieldOfView = glm::degrees(2.0f * abs(glm::angle(center, glm::normalize(vec3(top))))); + + glm::vec4 top = _inverseProjection * vec4(0, 1, -1, 1); + top /= top.w; + _fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0, 0, -1), glm::normalize(vec3(top)))))); } // ViewFrustum::calculateViewFrustum() diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 6ebe4dd46c..3e7e9a0adf 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1185,6 +1185,11 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co batch.draw(gpu::QUADS, 4, 0); } +void GeometryCache::renderUnitCube(gpu::Batch& batch) { + static const glm::vec4 color(1); + renderSolidCube(batch, 1, color); +} + void GeometryCache::renderUnitQuad(const glm::vec4& color, int id) { gpu::Batch batch; renderUnitQuad(batch, color, id); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 2155586f4b..f97ab8a773 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -155,6 +155,7 @@ public: void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); + void renderUnitCube(gpu::Batch& batch); void renderUnitQuad(const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID); void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID); diff --git a/libraries/render-utils/src/standardTransformPNTC.slv b/libraries/render-utils/src/standardTransformPNTC.slv index fd2c28049f..93abea267c 100644 --- a/libraries/render-utils/src/standardTransformPNTC.slv +++ b/libraries/render-utils/src/standardTransformPNTC.slv @@ -16,6 +16,7 @@ <$declareStandardTransform()$> +varying vec3 varPosition; varying vec3 varNormal; varying vec2 varTexcoord; varying vec4 varColor; @@ -30,4 +31,5 @@ void main(void) { <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> <$transformModelToEyeDir(cam, obj, gl_Normal, varNormal)$> varNormal = normalize(varNormal); + varPosition = gl_Vertex.xyz; } \ No newline at end of file diff --git a/libraries/render-utils/src/stars.slf b/libraries/render-utils/src/stars.slf new file mode 100644 index 0000000000..f0f81cb5f4 --- /dev/null +++ b/libraries/render-utils/src/stars.slf @@ -0,0 +1,76 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// stars.frag +// fragment shader +// +// Created by Bradley Austin Davis on 2015/06/19 + +varying vec2 varTexcoord; +varying vec3 varNomral; +varying vec3 varPosition; + + +const int star_iterations = 14; +const float time_scale = 0.2; +const vec3 col_star = vec3( 1.0, 0.7, 0.5 ); + +float hash( float n ) { return fract(sin(n)*123.456789); } + +vec2 rotate( in vec2 uv, float a) +{ + float c = cos( a ); + float s = sin( a ); + return vec2( c * uv.x - s * uv.y, s * uv.x + c * uv.y ); +} + +float noise( in vec3 p ) +{ + vec3 fl = floor( p ); + vec3 fr = fract( p ); + fr = fr * fr * ( 3.0 - 2.0 * fr ); + + float n = fl.x + fl.y * 157.0 + 113.0 * fl.z; + return mix( mix( mix( hash( n + 0.0), hash( n + 1.0 ), fr.x ), + mix( hash( n + 157.0), hash( n + 158.0 ), fr.x ), fr.y ), + mix( mix( hash( n + 113.0), hash( n + 114.0 ), fr.x ), + mix( hash( n + 270.0), hash( n + 271.0 ), fr.x ), fr.y ), fr.z ); +} + +float fbm( in vec2 p, float t ) +{ + float f; + f = 0.5000 * noise( vec3( p, t ) ); p *= 2.1; + f += 0.2500 * noise( vec3( p, t ) ); p *= 2.2; + f += 0.1250 * noise( vec3( p, t ) ); p *= 2.3; + f += 0.0625 * noise( vec3( p, t ) ); + return f; +} + +vec3 doBackgroundStars( in vec3 dir ) +{ + vec3 n = abs( dir ); + vec2 uv = ( n.x > n.y && n.x > n.z ) ? dir.yz / dir.x: + ( n.y > n.x && n.y > n.z ) ? dir.zx / dir.y: + dir.xy / dir.z; + + float f = 0.0; + + for( int i = 0 ; i < star_iterations; ++i ) + { + uv = rotate( 1.07 * uv + vec2( 0.7 ), 0.5 ); + + float t = 10. * uv.x * uv.y; + vec2 u = cos( 100. * uv ) * fbm( 10. * uv, 0.0 ); + f += smoothstep( 0.5, 0.55, u.x * u.y ) * ( 0.25 * sin( t ) + 0.75 ); + } + + return f * col_star; +} + +void main(void) { + vec3 c = doBackgroundStars( normalize(varPosition) ); + c = pow( c, vec3( 0.4545 ) ); + gl_FragColor = vec4( c, 1.0 ); +} + From 362d9a24817577ddae17d51147eb64717eb449c5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 10:35:00 -0700 Subject: [PATCH 074/121] 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 075/121] 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 076/121] 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 077/121] 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 078/121] 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 079/121] 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 080/121] 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 081/121] 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 082/121] 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 083/121] 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 084/121] 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 085/121] 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 086/121] 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 e1f6dd3b3bba7b32870e780f15c9902e5d3b8fbe Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 22 Jun 2015 16:56:42 -0700 Subject: [PATCH 087/121] Improve entity properties list in edit script. Add headers to break up logical sections, and reorder/relabel a few properties. --- examples/html/entityProperties.html | 86 ++++++++++++++++++++++------- examples/html/style.css | 6 +- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 27a2929d1c..c0737a1880 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -932,6 +932,7 @@ +
@@ -939,9 +940,12 @@
-
+
+ +
- +
@@ -976,6 +980,18 @@
+
+
User Data
+
+ +
+
+ + +
+ +
+
Position
@@ -1043,6 +1059,11 @@
+ +
+ +
+
Linear Velocity
@@ -1109,6 +1130,21 @@
+
+
Color
+
+
+
R
+
G
+
B
+
+
+ + +
+ +
+
Ignore For Collisions @@ -1144,22 +1180,9 @@
-
-
User Data
-
- -
-
- -
-
Color
-
-
-
R
-
G
-
B
-
+
+
@@ -1169,6 +1192,11 @@
+ +
+ +
+
Max Particles
@@ -1214,6 +1242,11 @@
+ +
+ +
+
Model URL
@@ -1280,8 +1313,13 @@
+ +
+ +
+
-
Text
+
Text Content
@@ -1311,6 +1349,11 @@
+ +
+ +
+
Spot Light @@ -1345,6 +1388,11 @@
+ +
+ +
+
Stage Sun Model Enabled @@ -1495,8 +1543,6 @@
- - diff --git a/examples/html/style.css b/examples/html/style.css index 4b7d4c825f..ff07411aaf 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -50,10 +50,12 @@ body { background-color: #333333; color: #999; padding: 3pt; + padding-top: 6pt; } .section-header label { font-weight: bold; + font-size: 11pt; } .multi-property-section { @@ -183,11 +185,11 @@ div.input-area { input { } -#type { +#type, #id { font-size: 9.0pt; } -#type label { +#type label, #id label { color: rgb(150, 150, 150); } From f833121032d0f8309ca5e0ce25d0b0c43b9ba3c5 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Mon, 22 Jun 2015 19:55:52 -0700 Subject: [PATCH 088/121] 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 62af30761e4cdfc498768a13f09e14cf50e8343e Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Mon, 22 Jun 2015 20:07:51 -0700 Subject: [PATCH 089/121] Fixing inverted mirror zoom setting --- interface/src/ui/AvatarInputs.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index 4066dab80c..e781037c0d 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -35,7 +35,8 @@ AvatarInputs* AvatarInputs::getInstance() { AvatarInputs::AvatarInputs(QQuickItem* parent) : QQuickItem(parent) { INSTANCE = this; - _mirrorZoomed = rearViewZoomLevel.get() != 0; + int zoomSetting = rearViewZoomLevel.get(); + _mirrorZoomed = zoomSetting == 0; } #define AI_UPDATE(name, src) \ From 07dce3856a0d68af636c3e6702f63eeee7c9350e Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Mon, 22 Jun 2015 20:10:21 -0700 Subject: [PATCH 090/121] Fixing some math functions --- interface/src/ui/AvatarInputs.cpp | 2 +- interface/src/ui/Stats.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index e781037c0d..11f744aaca 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -51,7 +51,7 @@ AvatarInputs::AvatarInputs(QQuickItem* parent) : QQuickItem(parent) { #define AI_UPDATE_FLOAT(name, src, epsilon) \ { \ float val = src; \ - if (abs(_##name - val) >= epsilon) { \ + if (fabs(_##name - val) >= epsilon) { \ _##name = val; \ emit name##Changed(); \ } \ diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 934f53ffc7..d6c61a33bd 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -86,7 +86,7 @@ bool Stats::includeTimingRecord(const QString& name) { #define STAT_UPDATE_FLOAT(name, src, epsilon) \ { \ float val = src; \ - if (abs(_##name - val) >= epsilon) { \ + if (fabs(_##name - val) >= epsilon) { \ _##name = val; \ emit name##Changed(); \ } \ From f7cd756796bb9e08ab73c00c8b840699511f064b Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 22 Jun 2015 16:56:42 -0700 Subject: [PATCH 091/121] Improve entity properties list in edit script. Add headers to break up logical sections, and reorder/relabel a few properties. --- examples/html/entityProperties.html | 86 ++++++++++++++++++++++------- examples/html/style.css | 6 +- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 27a2929d1c..c0737a1880 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -932,6 +932,7 @@ +
@@ -939,9 +940,12 @@
-
+
+ +
- +
@@ -976,6 +980,18 @@
+
+
User Data
+
+ +
+
+ + +
+ +
+
Position
@@ -1043,6 +1059,11 @@
+ +
+ +
+
Linear Velocity
@@ -1109,6 +1130,21 @@
+
+
Color
+
+
+
R
+
G
+
B
+
+
+ + +
+ +
+
Ignore For Collisions @@ -1144,22 +1180,9 @@
-
-
User Data
-
- -
-
- -
-
Color
-
-
-
R
-
G
-
B
-
+
+
@@ -1169,6 +1192,11 @@
+ +
+ +
+
Max Particles
@@ -1214,6 +1242,11 @@
+ +
+ +
+
Model URL
@@ -1280,8 +1313,13 @@
+ +
+ +
+
-
Text
+
Text Content
@@ -1311,6 +1349,11 @@
+ +
+ +
+
Spot Light @@ -1345,6 +1388,11 @@
+ +
+ +
+
Stage Sun Model Enabled @@ -1495,8 +1543,6 @@
- - diff --git a/examples/html/style.css b/examples/html/style.css index 4b7d4c825f..ff07411aaf 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -50,10 +50,12 @@ body { background-color: #333333; color: #999; padding: 3pt; + padding-top: 6pt; } .section-header label { font-weight: bold; + font-size: 11pt; } .multi-property-section { @@ -183,11 +185,11 @@ div.input-area { input { } -#type { +#type, #id { font-size: 9.0pt; } -#type label { +#type label, #id label { color: rgb(150, 150, 150); } From cf579ab275b192683b1c449b592686738e6bbf58 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 23 Jun 2015 09:52:29 -0700 Subject: [PATCH 092/121] 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 3e576fea92016f06d7199dbd23bda6063aaec561 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 23 Jun 2015 10:27:01 -0700 Subject: [PATCH 093/121] Remove vertical scaling from Text3DOverlay --- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 327c70d778..5ba6e35aea 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -118,7 +118,7 @@ void Text3DOverlay::render(RenderArgs* args) { glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); - transform.setScale(glm::vec3(scaleFactor, -scaleFactor, scaleFactor)); + transform.setScale(scaleFactor); transform.preTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f)); batch->setModelTransform(transform); From c1fdbeb3b42061c3e0d81e8a4487ebef5d8c78be Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Tue, 23 Jun 2015 10:52:44 -0700 Subject: [PATCH 094/121] hydra dead zone to prevent drifting --- interface/src/devices/SixenseManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index c7be89a121..c16611d2e8 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -36,6 +36,8 @@ const float NECK_X = 0.25f; // meters const float NECK_Y = 0.3f; // meters const float NECK_Z = 0.3f; // meters +const float CONTROLLER_THRESHOLD = 0.35f; + #ifdef __APPLE__ typedef int (*SixenseBaseFunction)(); typedef int (*SixenseTakeIntFunction)(int); @@ -326,6 +328,12 @@ void SixenseManager::update(float deltaTime) { } _controllersAtBase = (numControllersAtBase == 2); } + + for (auto axisState : _axisStateMap) { + if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) { + _axisStateMap[axisState.first] = 0.0f; + } + } #endif // HAVE_SIXENSE } From da031b039cf381f3599b56f769a3c354fc4a8529 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 23 Jun 2015 10:58:52 -0700 Subject: [PATCH 095/121] Removing qml wanrings --- interface/resources/qml/Stats.qml | 9 --------- interface/src/ui/Stats.h | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 128dbcd3a6..996f9f02ef 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -12,11 +12,6 @@ Item { implicitWidth: row.width anchors.horizontalCenter: parent.horizontalCenter - - readonly property int sTATS_GENERAL_MIN_WIDTH: 165 - readonly property int sTATS_PING_MIN_WIDTH: 190 - readonly property int sTATS_GEO_MIN_WIDTH: 240 - readonly property int sTATS_OCTREE_MIN_WIDTH: 410 readonly property int fontSize: 12 readonly property string fontColor: "white" readonly property string bgColor: "#99333333" @@ -37,7 +32,6 @@ Item { Column { id: generalCol spacing: 4; x: 4; y: 4; - width: sTATS_GENERAL_MIN_WIDTH Text { color: root.fontColor; font.pixelSize: root.fontSize @@ -78,7 +72,6 @@ Item { Column { id: pingCol spacing: 4; x: 4; y: 4; - width: sTATS_PING_MIN_WIDTH Text { color: root.fontColor font.pixelSize: root.fontSize @@ -114,7 +107,6 @@ Item { Column { id: geoCol spacing: 4; x: 4; y: 4; - width: sTATS_GEO_MIN_WIDTH Text { color: root.fontColor; font.pixelSize: root.fontSize @@ -157,7 +149,6 @@ Item { Column { id: octreeCol spacing: 4; x: 4; y: 4; - width: sTATS_OCTREE_MIN_WIDTH Text { color: root.fontColor; font.pixelSize: root.fontSize diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 8582d436af..a897e0422e 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -29,7 +29,7 @@ class Stats : public QQuickItem { HIFI_QML_DECL Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) Q_PROPERTY(bool timingExpanded READ isTimingExpanded NOTIFY timingExpandedChanged) - Q_PROPERTY(QString monospaceFont READ monospaceFont) + Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, framerate, 0) From 5114f82dca915e697a303bb06b05dc7cd35b8ca4 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 23 Jun 2015 12:07:01 -0700 Subject: [PATCH 096/121] Fix https://app.asana.com/0/32622044445063/38213714069516 --- examples/controllers/hydra/gun.js | 14 ++++---- examples/dice.js | 14 ++++---- examples/edit.js | 42 ++++-------------------- examples/libraries/toolBars.js | 53 +++++++++++++++++++++++++++---- examples/pointer.js | 12 ++----- 5 files changed, 69 insertions(+), 66 deletions(-) diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index 26eee029af..a90960a330 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -100,12 +100,12 @@ var NUM_BUTTONS = 3; var screenSize = Controller.getViewportDimensions(); var startX = screenSize.x / 2 - (NUM_BUTTONS * (BUTTON_SIZE + PADDING)) / 2; Script.include(["../../libraries/toolBars.js"]); -const persistKey = "highfidelity.gun.toolbar.position"; -var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); -toolBar.save = function () { - Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); -}; -var old = JSON.parse(Settings.getValue(persistKey) || '0'); +var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.gun.toolbar", function (screenSize) { + return { + x: startX, + y: (screenSize.y - (BUTTON_SIZE + PADDING)), + }; +}); var reticle = Overlays.addOverlay("image", { x: screenSize.x / 2 - (BUTTON_SIZE / 2), y: screenSize.y / 2 - (BUTTON_SIZE / 2), @@ -116,8 +116,6 @@ var reticle = Overlays.addOverlay("image", { }); var offButton = toolBar.addOverlay("image", { - x: old ? old[0] : startX, - y: old ? old[1] : (screenSize.y - (BUTTON_SIZE + PADDING)), width: BUTTON_SIZE, height: BUTTON_SIZE, imageURL: HIFI_PUBLIC_BUCKET + "images/gun/close.svg", diff --git a/examples/dice.js b/examples/dice.js index ac5d1b7426..ee88984b75 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -33,15 +33,13 @@ var BUTTON_SIZE = 32; var PADDING = 3; Script.include(["libraries/toolBars.js"]); -var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); -const persistKey = "highfidelity.dice.toolbar.position"; -toolBar.save = function () { - Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); -}; -var old = JSON.parse(Settings.getValue(persistKey) || '0'); +var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.dice.toolbar", function (screenSize) { + return { + x: (screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING), + y: (screenSize.y - (BUTTON_SIZE + PADDING)) + }; +}); var offButton = toolBar.addOverlay("image", { - x: old ? old[0] : (screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING), - y: old ? old[1] : (screenSize.y - (BUTTON_SIZE + PADDING)), width: BUTTON_SIZE, height: BUTTON_SIZE, imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", diff --git a/examples/edit.js b/examples/edit.js index 2974397cde..92e4737f29 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -49,7 +49,6 @@ selectionManager.addEventListener(function() { lightOverlayManager.updatePositions(); }); -var windowDimensions = Controller.getViewportDimensions(); var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; var toolHeight = 50; var toolWidth = 50; @@ -143,7 +142,12 @@ var toolBar = (function () { browseMarketplaceButton; function initialize() { - toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); + toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function (windowDimensions, toolbar) { + return { + x: windowDimensions.x - 8 - toolbar.width, + y: (windowDimensions.y - toolbar.height) / 2 + }; + }); browseMarketplaceButton = toolBar.addTool({ imageURL: toolIconUrl + "marketplace.svg", @@ -321,38 +325,6 @@ var toolBar = (function () { } } - const persistKey = "highfidelity.edit.toolbar.position"; - that.move = function () { - var newViewPort, - toolsX, - toolsY; - - newViewPort = Controller.getViewportDimensions(); - - if (toolBar === undefined) { - initialize(); - - toolBar.save = function () { - Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); - }; - var old = JSON.parse(Settings.getValue(persistKey) || '0'); - if (old) { - windowDimensions = newViewPort; - toolBar.move(old[0], old[1]); - return; - } - } else if (windowDimensions.x === newViewPort.x && - windowDimensions.y === newViewPort.y) { - return; - } - - windowDimensions = newViewPort; - toolsX = windowDimensions.x - 8 - toolBar.width; - toolsY = (windowDimensions.y - toolBar.height) / 2; - - toolBar.move(toolsX, toolsY); - }; - var newModelButtonDown = false; var browseMarketplaceButtonDown = false; that.mousePressEvent = function (event) { @@ -552,6 +524,7 @@ var toolBar = (function () { toolBar.cleanup(); }; + initialize(); return that; }()); @@ -931,7 +904,6 @@ var lastPosition = null; // Do some stuff regularly, like check for placement of various overlays Script.update.connect(function (deltaTime) { - toolBar.move(); progressDialog.move(); selectionDisplay.checkMove(); var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index 6e72795ea5..e420b668e7 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -126,7 +126,7 @@ Tool.prototype = new Overlay2D; Tool.IMAGE_HEIGHT = 50; Tool.IMAGE_WIDTH = 50; -ToolBar = function(x, y, direction) { +ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPositionFunction) { this.tools = new Array(); this.x = x; this.y = y; @@ -336,7 +336,7 @@ ToolBar = function(x, y, direction) { return (that.x <= x) && (x <= (that.x + that.width)) && (that.y <= y) && (y <= (that.y + that.height)); } - that.hover = function (enable) { + that.hover = function (enable) { // Can be overriden or extended by clients. that.isHovering = enable; if (that.back) { if (enable) { @@ -348,6 +348,26 @@ ToolBar = function(x, y, direction) { }); } }; + that.windowDimensions = Controller.getViewportDimensions(); + // Maybe fixme: Keeping the same percent of the window size isn't always the right thing. + // For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen". + // If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below. + that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients. + var fractionX = that.x / that.windowDimensions.x; + var fractionY = that.y / that.windowDimensions.y; + that.windowDimensions = newSize || Controller.getViewportDimensions(); + that.move(fractionX * that.windowDimensions.x, fractionY * that.windowDimensions.y); + }; + if (optionalPersistenceKey) { + this.fractionKey = optionalPersistenceKey + '.fraction'; + this.save = function () { + var screenSize = Controller.getViewportDimensions(); + var fraction = {x: that.x / screenSize.x, y: that.y / screenSize.y}; + Settings.setValue(this.fractionKey, JSON.stringify(fraction)); + } + } else { + this.save = function () { }; // Called on move. Can be overriden or extended by clients. + } // These are currently only doing that which is necessary for toolbar hover and toolbar drag. // They have not yet been extended to tool hover/click/release, etc. this.mousePressEvent = function (event) { @@ -375,15 +395,19 @@ ToolBar = function(x, y, direction) { } that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y); }; + that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport. + var currentWindowSize = Controller.getViewportDimensions(); + if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) { + that.onResizeViewport(currentWindowSize); + } + }; Controller.mousePressEvent.connect(this.mousePressEvent); Controller.mouseMoveEvent.connect(this.mouseMove); - // Called on move. A different approach would be to have all this on the prototype, - // and let apps extend where needed. Ex. app defines its toolbar.move() to call this.__proto__.move and then save. - this.save = function () { }; + Script.update.connect(that.checkResize); // This compatability hack breaks the model, but makes converting existing scripts easier: this.addOverlay = function (ignored, oldSchoolProperties) { var properties = JSON.parse(JSON.stringify(oldSchoolProperties)); // a copy - if (that.numberOfTools() === 0) { + if ((that.numberOfTools() === 0) && (properties.x != undefined) && (properties.y != undefined)) { that.move(properties.x, properties.y); } delete properties.x; @@ -392,6 +416,23 @@ ToolBar = function(x, y, direction) { var id = that.tools[index].overlay(); return id; } + if (this.fractionKey || optionalInitialPositionFunction) { + var savedFraction = JSON.parse(Settings.getValue(this.fractionKey) || '0'); // getValue can answer empty string + var screenSize = Controller.getViewportDimensions(); + if (savedFraction) { + // If we have saved data, keep the toolbar at the same proportion of the screen width/height. + that.move(savedFraction.x * screenSize.x, savedFraction.y * screenSize.y); + } else if (!optionalInitialPositionFunction) { + print("No initPosition(screenSize, intializedToolbar) specified for ToolBar"); + } else { + // Call the optionalInitialPositionFunctinon() AFTER the client has had a chance to set up. + var that = this; + Script.setTimeout(function () { + var position = optionalInitialPositionFunction(screenSize, that); + that.move(position.x, position.y); + }, 0); + } + } } ToolBar.SPACING = 4; ToolBar.VERTICAL = 0; diff --git a/examples/pointer.js b/examples/pointer.js index ea6b0c233f..83e2cbf776 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -29,19 +29,13 @@ var buttonOnColor = { }; HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -var screenSize = Controller.getViewportDimensions(); var userCanPoint = false; Script.include(["libraries/toolBars.js"]); -const persistKey = "highfidelity.pointer.toolbar.position"; -var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); -toolBar.save = function () { - Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); -}; -var old = JSON.parse(Settings.getValue(persistKey) || '0'); +var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.pointer.toolbar", function (screenSize) { + return {x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, y: screenSize.y - (BUTTON_SIZE + PADDING)}, +}); var pointerButton = toolBar.addOverlay("image", { - x: old ? old[0] : screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, - y: old ? old[1] : screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, height: BUTTON_SIZE, imageURL: HIFI_PUBLIC_BUCKET + "images/laser.png", From b1190bee6e75772032ff4881cabebbf2759e976c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 23 Jun 2015 14:13:13 -0700 Subject: [PATCH 097/121] 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__) */ From 8a1f446f05152e96d7b1fffa1af1505a5c59477d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 23 Jun 2015 14:43:41 -0700 Subject: [PATCH 098/121] Fix textoverlay3d text position --- interface/src/ui/overlays/Text3DOverlay.cpp | 23 ++++----------------- interface/src/ui/overlays/Text3DOverlay.h | 2 -- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 5ba6e35aea..5acd10eb45 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -19,7 +19,7 @@ const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const float DEFAULT_BACKGROUND_ALPHA = 0.7f; const float DEFAULT_MARGIN = 0.1f; -const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation +const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 80.0f; // this is a ratio determined through experimentation const float LINE_SCALE_RATIO = 1.2f; Text3DOverlay::Text3DOverlay() : @@ -118,37 +118,22 @@ void Text3DOverlay::render(RenderArgs* args) { glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); + transform.setTranslation(_position); + transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f)); transform.setScale(scaleFactor); - transform.preTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f)); batch->setModelTransform(transform); - // enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); - // enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); - // enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); - // enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); - glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; _textRenderer->draw(*batch, 0, 0, _text, textColor); - // glDisable(GL_CLIP_PLANE0); - // glDisable(GL_CLIP_PLANE1); - // glDisable(GL_CLIP_PLANE2); - // glDisable(GL_CLIP_PLANE3); - batch->setPipeline(DrawOverlay3D::getOpaquePipeline()); } } -void Text3DOverlay::enableClipPlane(GLenum plane, float x, float y, float z, float w) { - GLdouble coefficients[] = { x, y, z, w }; - glClipPlane(plane, coefficients); - glEnable(plane); -} - void Text3DOverlay::setProperties(const QScriptValue& properties) { Planar3DOverlay::setProperties(properties); - + QScriptValue text = properties.property("text"); if (text.isValid()) { setText(text.toVariant().toString()); diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index f2c71f8676..a30a720414 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -60,8 +60,6 @@ public: virtual Text3DOverlay* createClone() const; private: - void enableClipPlane(GLenum plane, float x, float y, float z, float w); - TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); QString _text; From 694a0517244aa732ccf6f808dda3ea91cf810a45 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 23 Jun 2015 15:32:24 -0700 Subject: [PATCH 099/121] Add titlebars to toolBars.js --- examples/libraries/toolBars.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index 6e72795ea5..88c48e668f 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -135,9 +135,9 @@ ToolBar = function(x, y, direction) { this.back = this.back = Overlays.addOverlay("text", { backgroundColor: { red: 255, green: 255, blue: 255 }, x: this.x, - y: this.y, + y: this.y - ToolBar.TITLE_BAR_HEIGHT, width: this.width, - height: this.height, + height: this.height + ToolBar.TITLE_BAR_HEIGHT, alpha: 1.0, backgroundAlpha: 1.0, visible: false @@ -161,7 +161,7 @@ ToolBar = function(x, y, direction) { Overlays.editOverlay(this.back, { width: this.width + ((direction == ToolBar.HORIZONTAL) ? 1 : 2) * ToolBar.SPACING, - height: this.height + + height: this.height + ToolBar.TITLE_BAR_HEIGHT + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, }); } @@ -201,7 +201,7 @@ ToolBar = function(x, y, direction) { Overlays.editOverlay(this.back, { width: this.width + ((direction == ToolBar.HORIZONTAL) ? 1 : 2) * ToolBar.SPACING, - height: this.height + + height: this.height + ToolBar.TITLE_BAR_HEIGHT + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, }); } @@ -218,7 +218,7 @@ ToolBar = function(x, y, direction) { if (this.back != null) { Overlays.editOverlay(this.back, { width: this.width + 2 * ToolBar.SPACING, - height: this.height + 2 * ToolBar.SPACING + height: this.height + ToolBar.TITLE_BAR_HEIGHT + 2 * ToolBar.SPACING }); } } @@ -234,7 +234,7 @@ ToolBar = function(x, y, direction) { if (this.back != null) { Overlays.editOverlay(this.back, { x: x - ToolBar.SPACING, - y: y - ToolBar.SPACING + y: y - ToolBar.TITLE_BAR_HEIGHT - ToolBar.SPACING }); } this.save(); @@ -265,7 +265,7 @@ ToolBar = function(x, y, direction) { Overlays.editOverlay(this.back, { width: this.width + ((direction == ToolBar.HORIZONTAL) ? 1 : 2) * ToolBar.SPACING, - height: this.height + + height: this.height + ToolBar.TITLE_BAR_HEIGHT + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, visible: true, backgroundColor: color, @@ -333,8 +333,9 @@ ToolBar = function(x, y, direction) { this.contains = function (xOrPoint, optionalY) { var x = (optionalY === undefined) ? xOrPoint.x : xOrPoint, y = (optionalY === undefined) ? xOrPoint.y : optionalY; + y += ToolBar.TITLE_BAR_HEIGHT; return (that.x <= x) && (x <= (that.x + that.width)) && - (that.y <= y) && (y <= (that.y + that.height)); + (that.y <= y) && (y <= (that.y + that.height + ToolBar.TITLE_BAR_HEIGHT)); } that.hover = function (enable) { that.isHovering = enable; @@ -351,13 +352,13 @@ ToolBar = function(x, y, direction) { // These are currently only doing that which is necessary for toolbar hover and toolbar drag. // They have not yet been extended to tool hover/click/release, etc. this.mousePressEvent = function (event) { - if (!that.contains(event)) { + if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) == that.back) { + that.mightBeDragging = true; + that.dragOffsetX = that.x - event.x; + that.dragOffsetY = that.y - event.y; + } else { that.mightBeDragging = false; - return; } - that.mightBeDragging = true; - that.dragOffsetX = that.x - event.x; - that.dragOffsetY = that.y - event.y; }; this.mouseMove = function (event) { if (!that.mightBeDragging || !event.isLeftButton) { @@ -396,3 +397,4 @@ ToolBar = function(x, y, direction) { ToolBar.SPACING = 4; ToolBar.VERTICAL = 0; ToolBar.HORIZONTAL = 1; +ToolBar.TITLE_BAR_HEIGHT = 10; From fb2fb0637185f78e8fdf51df9fafb72fbc3f0826 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 23 Jun 2015 15:42:32 -0700 Subject: [PATCH 100/121] Fixing misplaced UI on scale resolution, PC edition --- interface/src/Application.cpp | 2 +- interface/src/ui/ApplicationCompositor.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b0d91f8619..4fd702102f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -984,7 +984,7 @@ void Application::paintGL() { glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y, 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); + GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); _compositor.displayOverlayTexture(&renderArgs); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 26ea9cefa0..7b55de6dd8 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -182,7 +182,8 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { updateTooltips(); - vec2 canvasSize = qApp->getCanvasSize(); + auto deviceSize = qApp->getDeviceSize(); + glViewport(0, 0, deviceSize.width(), deviceSize.height()); //Handle fading and deactivation/activation of UI gpu::Batch batch; @@ -204,6 +205,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { //draw the mouse pointer // Get the mouse coordinates and convert to NDC [-1, 1] + vec2 canvasSize = qApp->getCanvasSize(); vec2 mousePosition = toNormalizedDeviceScale(vec2(qApp->getMouse()), canvasSize); // Invert the Y axis mousePosition.y *= -1.0f; From 05b668484c94c3780ae30916f43d644023192777 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 23 Jun 2015 16:41:15 -0700 Subject: [PATCH 101/121] Change address bar back/forward button color. --- .../resources/images/left-arrow-disabled.svg | 50 +++++++++++++++++++ interface/resources/images/redarrow.svg | 11 ---- .../resources/images/redarrow_reversed.svg | 11 ---- .../resources/images/right-arrow-disabled.svg | 11 ++++ interface/resources/qml/AddressBarDialog.qml | 4 +- 5 files changed, 63 insertions(+), 24 deletions(-) create mode 100644 interface/resources/images/left-arrow-disabled.svg delete mode 100644 interface/resources/images/redarrow.svg delete mode 100644 interface/resources/images/redarrow_reversed.svg create mode 100644 interface/resources/images/right-arrow-disabled.svg diff --git a/interface/resources/images/left-arrow-disabled.svg b/interface/resources/images/left-arrow-disabled.svg new file mode 100644 index 0000000000..a25123675e --- /dev/null +++ b/interface/resources/images/left-arrow-disabled.svg @@ -0,0 +1,50 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/images/redarrow.svg b/interface/resources/images/redarrow.svg deleted file mode 100644 index 156f4baa45..0000000000 --- a/interface/resources/images/redarrow.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/interface/resources/images/redarrow_reversed.svg b/interface/resources/images/redarrow_reversed.svg deleted file mode 100644 index 99c72cadb0..0000000000 --- a/interface/resources/images/redarrow_reversed.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - diff --git a/interface/resources/images/right-arrow-disabled.svg b/interface/resources/images/right-arrow-disabled.svg new file mode 100644 index 0000000000..b0c22afe19 --- /dev/null +++ b/interface/resources/images/right-arrow-disabled.svg @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 00e2d0b20b..3852ea3819 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -79,7 +79,7 @@ DialogContainer { Image { id: backArrow - source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/redarrow_reversed.svg" + source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/left-arrow-disabled.svg" anchors { fill: parent @@ -101,7 +101,7 @@ DialogContainer { Image { id: forwardArrow - source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/redarrow.svg" + source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/right-arrow-disabled.svg" anchors { fill: parent From 8c77fd369bc7cb5ce9bf3900a14cf5ba88e4ab4d Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 23 Jun 2015 17:40:25 -0700 Subject: [PATCH 102/121] Add subsections to the edit.js properties list. --- examples/html/entityProperties.html | 184 +++++++++++++++------------- examples/html/style.css | 12 +- 2 files changed, 112 insertions(+), 84 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index c0737a1880..56eee899f9 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -955,17 +955,6 @@ -
-
Hyperlink
-
Href
-
- -
-
Description
- -
-
-
Locked @@ -988,6 +977,24 @@
+
+ +
+ +
+
Href
+
+ +
+
+
+
Description
+
+ +
+
+ +
@@ -1181,6 +1188,78 @@ +
+ +
+ +
+
Model URL
+
+ +
+
+ +
+
Shape Type
+
+ +
+
+
+
Compound Shape URL
+
+ +
+
+
+
Animation URL
+
+ +
+
+
+ Animation Playing + + + +
+
+
Animation FPS
+
+ +
+
+
+
Animation Frame
+
+ +
+
+
+
Animation Settings
+
+ +
+
+
+
Textures
+
+ +
+
+
+
Original Textures
+
+ +
+
+ +
@@ -1243,77 +1322,6 @@ -
- -
- -
-
Model URL
-
- -
-
-
-
Shape Type
-
- -
-
-
-
Compound Shape URL
-
- -
-
-
-
Animation URL
-
- -
-
-
- Animation Playing - - - -
-
-
Animation FPS
-
- -
-
-
-
Animation Frame
-
- -
-
-
-
Animation Settings
-
- -
-
-
-
Textures
-
- -
-
-
-
Original Textures
-
- -
-
- -
@@ -1479,6 +1487,12 @@ + + +
+ +
+
Skybox Color
@@ -1494,6 +1508,12 @@
+ + +
+ +
+
Atmosphere Center
diff --git a/examples/html/style.css b/examples/html/style.css index ff07411aaf..f12cfb6dd0 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -44,7 +44,7 @@ body { border: 1.5pt solid black; } -.section-header { +.section-header, .sub-section-header { background: #AAA; border-bottom: 0.75pt solid #CCC; background-color: #333333; @@ -53,11 +53,19 @@ body { padding-top: 6pt; } -.section-header label { +.section-header label, .sub-section-header label { font-weight: bold; font-size: 11pt; } +.sub-section-header { + padding-top: 4px; +} + +.sub-section-header label { + font-size: 9pt; +} + .multi-property-section { } From 3b8a46b87d70568f390754c77bb2491c3f9f2f92 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 23 Jun 2015 21:01:34 -0700 Subject: [PATCH 103/121] Allow scripted audio injectors to have options set. --- libraries/audio/src/AudioInjector.cpp | 1 - libraries/script-engine/src/ScriptAudioInjector.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 480f13c54a..36b0345d34 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -93,7 +93,6 @@ void AudioInjector::injectAudio() { } void AudioInjector::restart() { - qCDebug(audio) << "Restarting an AudioInjector by stopping and starting over."; connect(this, &AudioInjector::finished, this, &AudioInjector::restartPortionAfterFinished); if (!_isStarted || _isFinished) { emit finished(); diff --git a/libraries/script-engine/src/ScriptAudioInjector.h b/libraries/script-engine/src/ScriptAudioInjector.h index b89a274af1..92bc5d31da 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.h +++ b/libraries/script-engine/src/ScriptAudioInjector.h @@ -28,7 +28,7 @@ public slots: void restart() { _injector->restart(); } void stop() { _injector->stop(); } - void setOptions(AudioInjectorOptions& options) { _injector->setOptions(options); } + void setOptions(const AudioInjectorOptions& options) { _injector->setOptions(options); } float getLoudness() const { return _injector->getLoudness(); } bool isPlaying() const { return _injector->isPlaying(); } From 666eaa81fe62d76e2a586ce7c627443a12a11a1c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 24 Jun 2015 14:02:06 -0700 Subject: [PATCH 104/121] Cleanup implementation of toolbar titlebar --- examples/libraries/toolBars.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index 88c48e668f..f3b68abf1e 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -131,13 +131,13 @@ ToolBar = function(x, y, direction) { this.x = x; this.y = y; this.width = 0; - this.height = 0; + this.height = ToolBar.TITLE_BAR_HEIGHT; this.back = this.back = Overlays.addOverlay("text", { backgroundColor: { red: 255, green: 255, blue: 255 }, x: this.x, y: this.y - ToolBar.TITLE_BAR_HEIGHT, width: this.width, - height: this.height + ToolBar.TITLE_BAR_HEIGHT, + height: this.height, alpha: 1.0, backgroundAlpha: 1.0, visible: false @@ -161,7 +161,7 @@ ToolBar = function(x, y, direction) { Overlays.editOverlay(this.back, { width: this.width + ((direction == ToolBar.HORIZONTAL) ? 1 : 2) * ToolBar.SPACING, - height: this.height + ToolBar.TITLE_BAR_HEIGHT + + height: this.height + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, }); } @@ -201,7 +201,7 @@ ToolBar = function(x, y, direction) { Overlays.editOverlay(this.back, { width: this.width + ((direction == ToolBar.HORIZONTAL) ? 1 : 2) * ToolBar.SPACING, - height: this.height + ToolBar.TITLE_BAR_HEIGHT + + height: this.height + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, }); } @@ -218,7 +218,7 @@ ToolBar = function(x, y, direction) { if (this.back != null) { Overlays.editOverlay(this.back, { width: this.width + 2 * ToolBar.SPACING, - height: this.height + ToolBar.TITLE_BAR_HEIGHT + 2 * ToolBar.SPACING + height: this.height + 2 * ToolBar.SPACING }); } } @@ -234,7 +234,7 @@ ToolBar = function(x, y, direction) { if (this.back != null) { Overlays.editOverlay(this.back, { x: x - ToolBar.SPACING, - y: y - ToolBar.TITLE_BAR_HEIGHT - ToolBar.SPACING + y: y - ToolBar.SPACING }); } this.save(); @@ -265,7 +265,7 @@ ToolBar = function(x, y, direction) { Overlays.editOverlay(this.back, { width: this.width + ((direction == ToolBar.HORIZONTAL) ? 1 : 2) * ToolBar.SPACING, - height: this.height + ToolBar.TITLE_BAR_HEIGHT + + height: this.height + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, visible: true, backgroundColor: color, @@ -333,9 +333,8 @@ ToolBar = function(x, y, direction) { this.contains = function (xOrPoint, optionalY) { var x = (optionalY === undefined) ? xOrPoint.x : xOrPoint, y = (optionalY === undefined) ? xOrPoint.y : optionalY; - y += ToolBar.TITLE_BAR_HEIGHT; return (that.x <= x) && (x <= (that.x + that.width)) && - (that.y <= y) && (y <= (that.y + that.height + ToolBar.TITLE_BAR_HEIGHT)); + (that.y <= y) && (y <= (that.y + that.height)); } that.hover = function (enable) { that.isHovering = enable; From 54ee869d9b9071e622f82cd70866353d1e0a2616 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 24 Jun 2015 14:04:53 -0700 Subject: [PATCH 105/121] Fix y position of toolbar --- examples/libraries/toolBars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index f3b68abf1e..5aad179fbc 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -135,7 +135,7 @@ ToolBar = function(x, y, direction) { this.back = this.back = Overlays.addOverlay("text", { backgroundColor: { red: 255, green: 255, blue: 255 }, x: this.x, - y: this.y - ToolBar.TITLE_BAR_HEIGHT, + y: this.y, width: this.width, height: this.height, alpha: 1.0, From 1ccd72d01ea3f0cde32c0a3af661a2378afdd5cb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 24 Jun 2015 15:32:32 -0700 Subject: [PATCH 106/121] Revert "Disable edit.js rotation text overlay temporarily" This reverts commit b9ecff02f993872813e511026955d11025cb8154. --- examples/libraries/entitySelectionTool.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index f3f1a186e1..d5e2b24f36 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1992,9 +1992,8 @@ SelectionDisplay = (function () { innerRadius: 0.9, }); - // TODO: re-enable when text overlays are fixed Overlays.editOverlay(rotationDegreesDisplay, { - visible: false, + visible: true, }); updateRotationDegreesOverlay(0, yawHandleRotation, yawCenter); @@ -2122,9 +2121,8 @@ SelectionDisplay = (function () { innerRadius: 0.9, }); - // TODO: re-enable when text overlays are fixed Overlays.editOverlay(rotationDegreesDisplay, { - visible: false, + visible: true, }); updateRotationDegreesOverlay(0, pitchHandleRotation, pitchCenter); @@ -2244,9 +2242,8 @@ SelectionDisplay = (function () { innerRadius: 0.9, }); - // TODO: re-enable when text overlays are fixed Overlays.editOverlay(rotationDegreesDisplay, { - visible: false, + visible: true, }); updateRotationDegreesOverlay(0, rollHandleRotation, rollCenter); From 6bb21b7a486608f4e7ad04f0ef0e23688e3c17f5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Jun 2015 15:07:43 -0700 Subject: [PATCH 107/121] Use dynamic_pointer_cast instead of static_cast --- interface/src/ui/overlays/OverlaysPayload.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index bcfba67313..4f94d9f34b 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -35,8 +35,8 @@ namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { - if (overlay->is3D() && !static_cast(overlay.get())->getDrawOnHUD()) { - if (static_cast(overlay.get())->getDrawInFront()) { + if (overlay->is3D() && !std::dynamic_pointer_cast(overlay)->getDrawOnHUD()) { + if (std::dynamic_pointer_cast(overlay)->getDrawInFront()) { return ItemKey::Builder().withTypeShape().withLayered().build(); } else { return ItemKey::Builder::opaqueShape(); @@ -47,9 +47,9 @@ namespace render { } template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { if (overlay->is3D()) { - return static_cast(overlay.get())->getBounds(); + return std::dynamic_pointer_cast(overlay)->getBounds(); } else { - QRect bounds = static_cast(overlay.get())->getBounds(); + QRect bounds = std::dynamic_pointer_cast(overlay)->getBounds(); return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f)); } } @@ -59,7 +59,7 @@ namespace render { const int LAYER_3D_FRONT = 1; const int LAYER_3D = 0; if (overlay->is3D()) { - return (static_cast(overlay.get())->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D); + return (std::dynamic_pointer_cast(overlay)->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D); } else { return LAYER_2D; } From e8da8e374cf17f4d603df7026d6426fead4691ad Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Jun 2015 15:10:48 -0700 Subject: [PATCH 108/121] Simplify Overlays payloadGetBounds --- interface/src/ui/overlays/Overlay.h | 2 ++ interface/src/ui/overlays/OverlaysPayload.cpp | 7 +------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 0264c6e3c0..c2f94050ec 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -47,6 +47,8 @@ public: void init(QScriptEngine* scriptEngine); virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; + + virtual AABox getBounds() const = 0; virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 4f94d9f34b..b7cacef80c 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -46,12 +46,7 @@ namespace render { } } template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { - if (overlay->is3D()) { - return std::dynamic_pointer_cast(overlay)->getBounds(); - } else { - QRect bounds = std::dynamic_pointer_cast(overlay)->getBounds(); - return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f)); - } + return overlay->getBounds(); } template <> int payloadGetLayer(const Overlay::Pointer& overlay) { // MAgic number while we are defining the layering mechanism: From c22f1aa7e100033c9ac578137bd5ff845ddeb2b2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Jun 2015 15:24:54 -0700 Subject: [PATCH 109/121] Overlay2D return correct getBounds --- interface/src/ui/overlays/Overlay2D.cpp | 7 ++++++- interface/src/ui/overlays/Overlay2D.h | 6 ++++-- interface/src/ui/overlays/Overlays.cpp | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index f60d44a472..10131ab7a6 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -28,6 +28,11 @@ Overlay2D::Overlay2D(const Overlay2D* overlay2D) : Overlay2D::~Overlay2D() { } +AABox Overlay2D::getBounds() const { + return AABox(glm::vec3(_bounds.x(), _bounds.y(), 0.0f), + glm::vec3(_bounds.width(), _bounds.height(), 0.01f)); +} + void Overlay2D::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); @@ -40,7 +45,7 @@ void Overlay2D::setProperties(const QScriptValue& properties) { boundsRect.setHeight(bounds.property("height").toVariant().toInt()); setBounds(boundsRect); } else { - QRect oldBounds = getBounds(); + QRect oldBounds = _bounds; QRect newBounds = oldBounds; if (properties.property("x").isValid()) { diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 20641206c2..51781ea468 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -30,6 +30,8 @@ public: Overlay2D(const Overlay2D* overlay2D); ~Overlay2D(); + virtual AABox getBounds() const; + virtual bool is3D() const { return false; } // getters @@ -37,8 +39,8 @@ public: int getY() const { return _bounds.y(); } int getWidth() const { return _bounds.width(); } int getHeight() const { return _bounds.height(); } - const QRect& getBounds() const { return _bounds; } - + const QRect& getBoundingRect() const { return _bounds; } + // setters void setX(int x) { _bounds.setX(x); } void setY(int y) { _bounds.setY(y); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 1bb81319e4..b86f7fa8e6 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -284,7 +284,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { } else { Overlay2D* thisOverlay = static_cast(i.value().get()); if (thisOverlay->getVisible() && thisOverlay->isLoaded() && - thisOverlay->getBounds().contains(pointCopy.x, pointCopy.y, false)) { + thisOverlay->getBoundingRect().contains(pointCopy.x, pointCopy.y, false)) { return thisID; } } From 31a98c5b40cf36ec9b7fe5d711e375750836805a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Jun 2015 15:35:49 -0700 Subject: [PATCH 110/121] Replace pos/rot by a transform in Base3DOverlay Also keep getBounds a pure virtual methods --- interface/src/ui/overlays/Base3DOverlay.cpp | 18 +++-------------- interface/src/ui/overlays/Base3DOverlay.h | 22 ++++++++++++--------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index db252d8a04..06e26e0781 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -16,15 +16,12 @@ #include "Application.h" #include "Base3DOverlay.h" -const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f); const float DEFAULT_LINE_WIDTH = 1.0f; const bool DEFAULT_IS_SOLID = false; const bool DEFAULT_IS_DASHED_LINE = false; Base3DOverlay::Base3DOverlay() : - _position(DEFAULT_POSITION), _lineWidth(DEFAULT_LINE_WIDTH), - _rotation(), _isSolid(DEFAULT_IS_SOLID), _isDashedLine(DEFAULT_IS_DASHED_LINE), _ignoreRayIntersection(false), @@ -35,9 +32,8 @@ Base3DOverlay::Base3DOverlay() : Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : Overlay(base3DOverlay), - _position(base3DOverlay->_position), + _transform(base3DOverlay->_transform), _lineWidth(base3DOverlay->_lineWidth), - _rotation(base3DOverlay->_rotation), _isSolid(base3DOverlay->_isSolid), _isDashedLine(base3DOverlay->_isDashedLine), _ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection), @@ -46,14 +42,6 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : { } -Base3DOverlay::~Base3DOverlay() { -} - -// TODO: Implement accurate getBounds() implementations -AABox Base3DOverlay::getBounds() const { - return AABox(_position, glm::vec3(1.0f)); -} - void Base3DOverlay::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); @@ -151,13 +139,13 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { QScriptValue Base3DOverlay::getProperty(const QString& property) { if (property == "position" || property == "start" || property == "p1" || property == "point") { - return vec3toScriptValue(_scriptEngine, _position); + return vec3toScriptValue(_scriptEngine, getPosition()); } if (property == "lineWidth") { return _lineWidth; } if (property == "rotation") { - return quatToScriptValue(_scriptEngine, _rotation); + return quatToScriptValue(_scriptEngine, getRotation()); } if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") { return _isSolid; diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index b24908a0cc..99126346bf 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -15,6 +15,7 @@ #include #include +#include #include "Overlay.h" @@ -24,32 +25,35 @@ class Base3DOverlay : public Overlay { public: Base3DOverlay(); Base3DOverlay(const Base3DOverlay* base3DOverlay); - ~Base3DOverlay(); // getters virtual bool is3D() const { return true; } - const glm::vec3& getPosition() const { return _position; } - const glm::vec3& getCenter() const { return _position; } // TODO: consider implementing registration points in this class + const glm::vec3& getPosition() const { return _transform.getTranslation(); } + const glm::quat& getRotation() const { return _transform.getRotation(); } + + // TODO: consider implementing registration points in this class + const glm::vec3& getCenter() const { return getPosition(); } + float getLineWidth() const { return _lineWidth; } bool getIsSolid() const { return _isSolid; } bool getIsDashedLine() const { return _isDashedLine; } bool getIsSolidLine() const { return !_isDashedLine; } - const glm::quat& getRotation() const { return _rotation; } bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; } bool getDrawInFront() const { return _drawInFront; } bool getDrawOnHUD() const { return _drawOnHUD; } // setters - void setPosition(const glm::vec3& position) { _position = position; } + void setPosition(const glm::vec3& value) { _transform.setTranslation(value); } + void setRotation(const glm::quat& value) { _transform.setRotation(value); } + void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } void setIsSolid(bool isSolid) { _isSolid = isSolid; } void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } - void setRotation(const glm::quat& value) { _rotation = value; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } void setDrawInFront(bool value) { _drawInFront = value; } void setDrawOnHUD(bool value) { _drawOnHUD = value; } - virtual AABox getBounds() const; + virtual AABox getBounds() const = 0; virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); @@ -62,9 +66,9 @@ public: } protected: - glm::vec3 _position; + Transform _transform; + float _lineWidth; - glm::quat _rotation; bool _isSolid; bool _isDashedLine; bool _ignoreRayIntersection; From 233d92c315d2efdedb8a583478a083833cbce1d7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Jun 2015 11:46:22 -0700 Subject: [PATCH 111/121] Some code cleanup --- interface/src/ui/overlays/Base3DOverlay.h | 4 ---- interface/src/ui/overlays/Overlay.cpp | 7 ++++--- interface/src/ui/overlays/Overlay.h | 15 ++------------- interface/src/ui/overlays/Overlay2D.cpp | 12 +----------- interface/src/ui/overlays/Overlay2D.h | 10 +--------- interface/src/ui/overlays/Overlays.cpp | 10 ++-------- interface/src/ui/overlays/Overlays.h | 8 +++++--- 7 files changed, 15 insertions(+), 51 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 99126346bf..542b786ae2 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -11,10 +11,6 @@ #ifndef hifi_Base3DOverlay_h #define hifi_Base3DOverlay_h -#include -#include - -#include #include #include "Overlay.h" diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 745c2b4a10..17e4ae74e1 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -8,12 +8,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - #include "Overlay.h" #include +#include + +static const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 }; +static const float DEFAULT_ALPHA = 0.7f; Overlay::Overlay() : _renderItemID(render::Item::INVALID_ITEM_ID), diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index c2f94050ec..a96631bbcf 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -11,21 +11,11 @@ #ifndef hifi_Overlay_h #define hifi_Overlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include - -#include #include // for xColor -#include -#include #include -const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 }; -const float DEFAULT_ALPHA = 0.7f; +class QScriptEngine; +class QScriptValue; class Overlay : public QObject { Q_OBJECT @@ -37,7 +27,6 @@ public: }; typedef std::shared_ptr Pointer; - typedef render::Payload Payload; typedef std::shared_ptr PayloadPointer; diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index 10131ab7a6..e37e70700c 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -8,16 +8,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include - #include "Overlay2D.h" - -Overlay2D::Overlay2D() { -} +#include Overlay2D::Overlay2D(const Overlay2D* overlay2D) : Overlay(overlay2D), @@ -25,9 +18,6 @@ Overlay2D::Overlay2D(const Overlay2D* overlay2D) : { } -Overlay2D::~Overlay2D() { -} - AABox Overlay2D::getBounds() const { return AABox(glm::vec3(_bounds.x(), _bounds.y(), 0.0f), glm::vec3(_bounds.width(), _bounds.height(), 0.01f)); diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 51781ea468..382105c047 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -11,14 +11,7 @@ #ifndef hifi_Overlay2D_h #define hifi_Overlay2D_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - #include -#include -#include - -#include // for xColor #include "Overlay.h" @@ -26,9 +19,8 @@ class Overlay2D : public Overlay { Q_OBJECT public: - Overlay2D(); + Overlay2D() {} Overlay2D(const Overlay2D* overlay2D); - ~Overlay2D(); virtual AABox getBounds() const; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index b86f7fa8e6..dc49478f38 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -8,14 +8,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Overlays.h" + #include #include -#include #include -#include -#include #include #include "BillboardOverlay.h" @@ -25,7 +24,6 @@ #include "Line3DOverlay.h" #include "LocalModelsOverlay.h" #include "ModelOverlay.h" -#include "Overlays.h" #include "Rectangle3DOverlay.h" #include "Sphere3DOverlay.h" #include "Grid3DOverlay.h" @@ -37,7 +35,6 @@ Overlays::Overlays() : _nextOverlayID(1) { } Overlays::~Overlays() { - { QWriteLocker lock(&_lock); QWriteLocker deleteLock(&_deleteLock); @@ -99,9 +96,6 @@ void Overlays::cleanupOverlaysToDelete() { void Overlays::renderHUD(RenderArgs* renderArgs) { QReadLocker lock(&_lock); - - auto lodManager = DependencyManager::get(); - foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { if (thisOverlay->is3D()) { glEnable(GL_DEPTH_TEST); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 57d8ccd509..cd5b0f1d10 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -11,13 +11,13 @@ #ifndef hifi_Overlays_h #define hifi_Overlays_h -#include +#include #include -#include -#include "Base3DOverlay.h" #include "Overlay.h" +class PickRay; + class OverlayPropertyResult { public: OverlayPropertyResult(); @@ -48,9 +48,11 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R class Overlays : public QObject { Q_OBJECT + public: Overlays(); ~Overlays(); + void init(); void update(float deltatime); void renderHUD(RenderArgs* renderArgs); From 85b2771c4a3ec73a3bd6ac969524bd2f3c37d8df Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Jun 2015 16:36:57 -0700 Subject: [PATCH 112/121] Extend Extents --- libraries/shared/src/Extents.cpp | 11 ++++++++++- libraries/shared/src/Extents.h | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/Extents.cpp b/libraries/shared/src/Extents.cpp index f48ba3c99f..ad00683cf2 100644 --- a/libraries/shared/src/Extents.cpp +++ b/libraries/shared/src/Extents.cpp @@ -10,12 +10,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Extents.h" + #include #include #include #include "AABox.h" -#include "Extents.h" +#include "Transform.h" void Extents::reset() { minimum = glm::vec3(FLT_MAX); @@ -78,3 +80,10 @@ void Extents::rotate(const glm::quat& rotation) { glm::max(topRightNearRotated, glm::max(topLeftFarRotated,topRightFarRotated))))))); } + + +void Extents::transform(const Transform& transform) { + scale(transform.getScale()); + rotate(transform.getRotation()); + shiftBy(transform.getTranslation()); +} diff --git a/libraries/shared/src/Extents.h b/libraries/shared/src/Extents.h index 647f33699a..3d5a2dbcec 100644 --- a/libraries/shared/src/Extents.h +++ b/libraries/shared/src/Extents.h @@ -20,6 +20,7 @@ #include "StreamUtils.h" class AABox; +class Transform; class Extents { public: @@ -56,6 +57,13 @@ public: /// rotate the extents around orign by rotation void rotate(const glm::quat& rotation); + + /// scale the extents around orign by scale + void scale(float scale) { minimum *= scale; maximum *= scale; } + void scale(const glm::vec3& scale) { minimum *= scale; maximum *= scale; } + + // Transform the extents with transform + void transform(const Transform& transform); glm::vec3 size() const { return maximum - minimum; } float largestDimension() const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); } From 99a03bac21950c7b1861711f1602a08a3e6a7a7e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 17 Jun 2015 18:36:48 -0700 Subject: [PATCH 113/121] Render a different model when in first person view. Currently this model is identical to the third person model, except that the head bones have been 'cauterized' by applying a zero scale transform. This allows us to set the near clip back to a reasonable value. --- interface/src/Application.cpp | 3 ++ interface/src/avatar/Avatar.cpp | 7 +-- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 62 ++++++++++++++++++----- interface/src/avatar/MyAvatar.h | 10 +++- interface/src/avatar/SkeletonModel.cpp | 65 ++++++++++++++++++++++++- interface/src/avatar/SkeletonModel.h | 14 +++++- libraries/octree/src/ViewFrustum.h | 2 +- libraries/render-utils/src/JointState.h | 3 ++ libraries/render-utils/src/Model.cpp | 52 +++++++++++++++++++- libraries/render-utils/src/Model.h | 8 +++ 11 files changed, 205 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bde557c430..461633460c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3306,6 +3306,9 @@ namespace render { void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) { + + _myAvatar->preRender(renderArgs); + activeRenderingThread = QThread::currentThread(); PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("display"); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0213afb675..d0778481a6 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -445,10 +445,10 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, boo _skeletonModel.renderJointCollisionShapes(0.7f); } - if (renderHead && shouldRenderHead(renderArgs, cameraPosition)) { + if (renderHead && shouldRenderHead(renderArgs)) { getHead()->getFaceModel().renderJointCollisionShapes(0.7f); } - if (renderBounding && shouldRenderHead(renderArgs, cameraPosition)) { + if (renderBounding && shouldRenderHead(renderArgs)) { _skeletonModel.renderBoundingCollisionShapes(0.7f); } @@ -533,6 +533,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { } void Avatar::fixupModelsInScene() { + // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = Application::getInstance()->getMain3DScene(); @@ -581,7 +582,7 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting); } -bool Avatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const { +bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const { return true; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ecb16f6010..236b04864b 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -237,7 +237,7 @@ protected: Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize) const; void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum) const; virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f); - virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const; + virtual bool shouldRenderHead(const RenderArgs* renderArgs) const; virtual void fixupModelsInScene(); void simulateAttachments(float deltaTime); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6904a1f975..61bff58d89 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -96,8 +97,12 @@ MyAvatar::MyAvatar() : _feetTouchFloor(true), _isLookingAtLeftEye(true), _realWorldFieldOfView("realWorldFieldOfView", - DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES) + DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), + _currentSkeletonModel(nullptr), + _firstPersonSkeletonModel(this) { + _firstPersonSkeletonModel.setIsFirstPerson(true); + ShapeCollider::initDispatchTable(); for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = 0.0f; @@ -131,6 +136,7 @@ QByteArray MyAvatar::toByteArray() { void MyAvatar::reset() { _skeletonModel.reset(); + _firstPersonSkeletonModel.reset(); getHead()->reset(); _targetVelocity = glm::vec3(0.0f); @@ -189,6 +195,7 @@ void MyAvatar::simulate(float deltaTime) { { PerformanceTimer perfTimer("skeleton"); _skeletonModel.simulate(deltaTime); + _firstPersonSkeletonModel.simulate(deltaTime); } if (!_skeletonModel.hasSkeleton()) { @@ -993,6 +1000,11 @@ void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); _billboardValid = false; + + if (_useFullAvatar) { + const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst"); + _firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); + } } void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { @@ -1176,18 +1188,12 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) { - if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { - return; // wait until both models are loaded + if (!(_skeletonModel.isRenderable() && _firstPersonSkeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { + return; // wait until all models are loaded } - // check to see if when we added our models to the scene they were ready, if they were not ready, then - // fix them up in the scene - fixupModelsInScene(); - - const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); - // Render head so long as the camera isn't inside it - if (shouldRenderHead(renderArgs, cameraPos)) { + if (shouldRenderHead(renderArgs)) { getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting); } if (postLighting) { @@ -1195,12 +1201,42 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo } } +void MyAvatar::setCurrentSkeletonModel(SkeletonModel* skeletonModel) { + if (_currentSkeletonModel != skeletonModel && skeletonModel->isActive() && skeletonModel->isRenderable()) { + + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + + if (_currentSkeletonModel) { + _currentSkeletonModel->setVisibleInScene(false, scene); + } + skeletonModel->setVisibleInScene(true, scene); + _currentSkeletonModel = skeletonModel; + } +} + +void MyAvatar::preRender(RenderArgs* renderArgs) { + + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + + _skeletonModel.initWhenReady(scene); + _firstPersonSkeletonModel.initWhenReady(scene); + + // set visiblity on each model + if (shouldRenderHead(renderArgs)) { + setCurrentSkeletonModel(&_skeletonModel); + } else { + setCurrentSkeletonModel(&_firstPersonSkeletonModel); + } +} + const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; -bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const { +bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { + const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); const Head* head = getHead(); - return (renderArgs->_renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) || - (glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale); + return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) || + (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) || + (glm::length(cameraPos - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale)); } void MyAvatar::updateOrientation(float deltaTime) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 948cec9eb1..9dda29a918 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -35,11 +35,12 @@ public: void reset(); void update(float deltaTime); void simulate(float deltaTime); + void preRender(RenderArgs* renderArgs); void updateFromTrackers(float deltaTime); virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting = false) override; virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f) override; - virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const override; + virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override; void renderDebugBodyPoints(); // setters @@ -210,6 +211,9 @@ private: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + void setCurrentSkeletonModel(SkeletonModel* skeletonModel); + void initModelWhenReady(Model* model); + glm::vec3 _gravity; float _driveKeys[MAX_DRIVE_KEYS]; @@ -265,6 +269,10 @@ private: QString _headModelName; QString _bodyModelName; QString _fullAvatarModelName; + + // used for rendering when in first person view or when in an HMD. + SkeletonModel* _currentSkeletonModel; + SkeletonModel _firstPersonSkeletonModel; }; #endif // hifi_MyAvatar_h diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 2aa08d36f3..2f66e84b50 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -21,6 +21,7 @@ #include "Menu.h" #include "SkeletonModel.h" #include "Util.h" +#include "InterfaceLogging.h" enum StandingFootState { LEFT_FOOT, @@ -38,7 +39,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _standingFoot(NO_FOOT), _standingOffset(0.0f), _clampedFootPosition(0.0f), - _headClipDistance(DEFAULT_NEAR_CLIP) + _headClipDistance(DEFAULT_NEAR_CLIP), + _isFirstPerson(false) { assert(_owningAvatar); _enableShapes = true; @@ -98,7 +100,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { setRotation(_owningAvatar->getOrientation() * refOrientation); setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale()); setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients()); - + Model::simulate(deltaTime, fullUpdate); if (!isActive() || !_owningAvatar->isMyAvatar()) { @@ -140,6 +142,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); } + if (_isFirstPerson) { + cauterizeHead(); + updateClusterMatrices(); + } + _boundingShape.setTranslation(_translation + _rotation * _boundingShapeLocalOffset); _boundingShape.setRotation(_rotation); } @@ -806,3 +813,57 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { bool SkeletonModel::hasSkeleton() { return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false; } + +void SkeletonModel::initHeadBones() { + _headBones.clear(); + const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry(); + const int neckJointIndex = fbxGeometry.neckJointIndex; + std::queue q; + q.push(neckJointIndex); + _headBones.push_back(neckJointIndex); + + // fbxJoints only hold links to parents not children, so we have to do a bit of extra work here. + while (q.size() > 0) { + int jointIndex = q.front(); + for (int i = 0; i < fbxGeometry.joints.size(); i++) { + const FBXJoint& fbxJoint = fbxGeometry.joints[i]; + if (jointIndex == fbxJoint.parentIndex) { + _headBones.push_back(i); + q.push(i); + } + } + q.pop(); + } +} + +void SkeletonModel::invalidateHeadBones() { + _headBones.clear(); +} + +void SkeletonModel::cauterizeHead() { + if (isActive()) { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const int neckJointIndex = geometry.neckJointIndex; + if (neckJointIndex > 0 && neckJointIndex < _jointStates.size()) { + + // lazy init of headBones + if (_headBones.size() == 0) { + initHeadBones(); + } + + // preserve the translation for the neck + glm::vec4 trans = _jointStates[neckJointIndex].getTransform()[3]; + glm::vec4 zero(0, 0, 0, 0); + for (const int &i : _headBones) { + JointState& joint = _jointStates[i]; + glm::mat4 newXform(zero, zero, zero, trans); + joint.setTransform(newXform); + joint.setVisibleTransform(newXform); + } + } + } +} + +void SkeletonModel::onInvalidate() { + invalidateHeadBones(); +} diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index e28988326a..bffdc58659 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -112,6 +112,11 @@ public: float getHeadClipDistance() const { return _headClipDistance; } + void setIsFirstPerson(bool value) { _isFirstPerson = value; } + bool getIsFirstPerson() const { return _isFirstPerson; } + + virtual void onInvalidate() override; + signals: void skeletonLoaded(); @@ -132,7 +137,11 @@ protected: void maybeUpdateLeanRotation(const JointState& parentState, JointState& state); void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state); void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state); - + + void cauterizeHead(); + void initHeadBones(); + void invalidateHeadBones(); + private: void renderJointConstraints(int jointIndex); @@ -164,6 +173,9 @@ private: glm::vec3 _clampedFootPosition; float _headClipDistance; // Near clip distance to use if no separate head model + + bool _isFirstPerson; + std::vector _headBones; }; #endif // hifi_SkeletonModel_h diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index cd1e010818..6c279585e2 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -31,7 +31,7 @@ const float DEFAULT_KEYHOLE_RADIUS = 3.0f; const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f; const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f; //const float DEFAULT_NEAR_CLIP = 0.08f; -const float DEFAULT_NEAR_CLIP = 0.25f; +const float DEFAULT_NEAR_CLIP = 0.1f; const float DEFAULT_FAR_CLIP = (float)TREE_SCALE; class ViewFrustum { diff --git a/libraries/render-utils/src/JointState.h b/libraries/render-utils/src/JointState.h index fbe2e9c986..0ef84e50c4 100644 --- a/libraries/render-utils/src/JointState.h +++ b/libraries/render-utils/src/JointState.h @@ -106,6 +106,9 @@ public: glm::quat computeParentRotation() const; glm::quat computeVisibleParentRotation() const; + void setTransform(const glm::mat4& transform) { _transform = transform; } + void setVisibleTransform(const glm::mat4& transform) { _visibleTransform = transform; } + private: void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation); /// debug helper function diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 1397512f4a..d6fe5cea1a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1102,9 +1102,11 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo _readyWhenAdded = false; // reset out render items. _needsReload = true; invalidCalculatedMeshBoxes(); - + _url = url; + onInvalidate(); + // if so instructed, keep the current geometry until the new one is loaded _nextBaseGeometry = _nextGeometry = DependencyManager::get()->getGeometry(url, fallback, delayLoad); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; @@ -1380,6 +1382,26 @@ void Model::simulate(float deltaTime, bool fullUpdate) { } } +void Model::updateClusterMatrices() { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + glm::mat4 modelToWorld = glm::mat4_cast(_rotation); + for (int i = 0; i < _meshStates.size(); i++) { + MeshState& state = _meshStates[i]; + const FBXMesh& mesh = geometry.meshes.at(i); + if (_showTrueJointTransforms) { + for (int j = 0; j < mesh.clusters.size(); j++) { + const FBXCluster& cluster = mesh.clusters.at(j); + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix; + } + } else { + for (int j = 0; j < mesh.clusters.size(); j++) { + const FBXCluster& cluster = mesh.clusters.at(j); + state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix; + } + } + } +} + void Model::simulateInternal(float deltaTime) { // update the world space transforms for all joints @@ -2120,6 +2142,34 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } } +bool Model::initWhenReady(render::ScenePointer scene) { + if (isActive() && isRenderable() && !_meshGroupsKnown && isLoadedWithTextures()) { + segregateMeshGroups(); + + render::PendingChanges pendingChanges; + + foreach (auto renderItem, _transparentRenderItems) { + auto item = scene->allocateID(); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); + _renderItems.insert(item, renderPayload); + pendingChanges.resetItem(item, renderPayload); + } + + foreach (auto renderItem, _opaqueRenderItems) { + auto item = scene->allocateID(); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); + _renderItems.insert(item, renderPayload); + pendingChanges.resetItem(item, renderPayload); + } + scene->enqueuePendingChanges(pendingChanges); + + _readyWhenAdded = true; + return true; + } + return false; +} ModelBlender::ModelBlender() : _pendingBlenders(0) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 6dfe223581..3748403b97 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -240,6 +240,8 @@ public: AABox getPartBounds(int meshIndex, int partIndex); void renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent); + bool initWhenReady(render::ScenePointer scene); + protected: QSharedPointer _geometry; @@ -312,6 +314,12 @@ protected: _calculatedMeshTrianglesValid = false; } + // rebuild the clusterMatrices from the current jointStates + void updateClusterMatrices(); + + // hook for derived classes to be notified when setUrl invalidates the current model. + virtual void onInvalidate() {}; + private: friend class AnimationHandle; From 8f03ead74ebcb8ef478294166f09d16bd09465fa Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 19 Jun 2015 16:41:31 -0700 Subject: [PATCH 114/121] Bug fix for two piece avatars. The head was not rendering --- interface/src/avatar/MyAvatar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 61bff58d89..762855e039 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1188,10 +1188,12 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) { - if (!(_skeletonModel.isRenderable() && _firstPersonSkeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { + if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until all models are loaded } + fixupModelsInScene(); + // Render head so long as the camera isn't inside it if (shouldRenderHead(renderArgs)) { getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting); From b88d7c2e05e1877872bf55c2a1a4cb94174e99ed Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 22 Jun 2015 08:55:39 -0700 Subject: [PATCH 115/121] Added FIXME comment to preRender --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 461633460c..c4985be15f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3307,6 +3307,8 @@ namespace render { void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) { + // FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering. + // Then we can move this logic into the Avatar::simulate call. _myAvatar->preRender(renderArgs); activeRenderingThread = QThread::currentThread(); From 3853395298777b39de5ad661eccbb72df68fb433 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 22 Jun 2015 18:19:17 -0700 Subject: [PATCH 116/121] Bug fixes for switching between head/body and full body avatars The head model visibility is now updated in preRender() Moved the near clip plane in a bit more Invalidate head bone vector on LOD switching. Removed _currentSkeletonModel pointer, instead use _prevShouldDrawHead to detect when we should flip the visibility bit. --- interface/src/avatar/MyAvatar.cpp | 43 ++++++++++++++++------------ interface/src/avatar/MyAvatar.h | 5 ++-- libraries/octree/src/ViewFrustum.h | 3 +- libraries/render-utils/src/Model.cpp | 1 + 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 762855e039..0b9d770de0 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -98,8 +98,8 @@ MyAvatar::MyAvatar() : _isLookingAtLeftEye(true), _realWorldFieldOfView("realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), - _currentSkeletonModel(nullptr), - _firstPersonSkeletonModel(this) + _firstPersonSkeletonModel(this), + _prevShouldDrawHead(true) { _firstPersonSkeletonModel.setIsFirstPerson(true); @@ -1203,16 +1203,9 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo } } -void MyAvatar::setCurrentSkeletonModel(SkeletonModel* skeletonModel) { - if (_currentSkeletonModel != skeletonModel && skeletonModel->isActive() && skeletonModel->isRenderable()) { - - render::ScenePointer scene = Application::getInstance()->getMain3DScene(); - - if (_currentSkeletonModel) { - _currentSkeletonModel->setVisibleInScene(false, scene); - } - skeletonModel->setVisibleInScene(true, scene); - _currentSkeletonModel = skeletonModel; +void MyAvatar::setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visible) { + if (model->isActive() && model->isRenderable()) { + model->setVisibleInScene(visible, scene); } } @@ -1221,14 +1214,26 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { render::ScenePointer scene = Application::getInstance()->getMain3DScene(); _skeletonModel.initWhenReady(scene); - _firstPersonSkeletonModel.initWhenReady(scene); - - // set visiblity on each model - if (shouldRenderHead(renderArgs)) { - setCurrentSkeletonModel(&_skeletonModel); - } else { - setCurrentSkeletonModel(&_firstPersonSkeletonModel); + if (_useFullAvatar) { + _firstPersonSkeletonModel.initWhenReady(scene); } + + bool shouldDrawHead = shouldRenderHead(renderArgs); + if (shouldDrawHead != _prevShouldDrawHead) { + if (_useFullAvatar) { + if (shouldDrawHead) { + _skeletonModel.setVisibleInScene(true, scene); + _firstPersonSkeletonModel.setVisibleInScene(false, scene); + } else { + _skeletonModel.setVisibleInScene(false, scene); + _firstPersonSkeletonModel.setVisibleInScene(true, scene); + } + } else { + getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene); + } + + } + _prevShouldDrawHead = shouldDrawHead; } const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9dda29a918..8543382445 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -211,8 +211,7 @@ private: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); - void setCurrentSkeletonModel(SkeletonModel* skeletonModel); - void initModelWhenReady(Model* model); + void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity); glm::vec3 _gravity; @@ -271,8 +270,8 @@ private: QString _fullAvatarModelName; // used for rendering when in first person view or when in an HMD. - SkeletonModel* _currentSkeletonModel; SkeletonModel _firstPersonSkeletonModel; + bool _prevShouldDrawHead; }; #endif // hifi_MyAvatar_h diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 6c279585e2..3e41b58bb6 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -30,8 +30,7 @@ const float DEFAULT_KEYHOLE_RADIUS = 3.0f; const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f; const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f; -//const float DEFAULT_NEAR_CLIP = 0.08f; -const float DEFAULT_NEAR_CLIP = 0.1f; +const float DEFAULT_NEAR_CLIP = 0.08f; const float DEFAULT_FAR_CLIP = (float)TREE_SCALE; class ViewFrustum { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d6fe5cea1a..93f3f345f0 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1370,6 +1370,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { // because ray picking needs valid boxes to work _calculatedMeshBoxesValid = false; _calculatedMeshTrianglesValid = false; + onInvalidate(); // check for scale to fit if (_scaleToFit && !_scaledToFit) { From 71639a7466f01f218219d47de8ce3980e15b6fb2 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 23 Jun 2015 11:24:40 -0700 Subject: [PATCH 117/121] Fix for switching avatars while mirror is not enabled. When the avatar is changed via set*URL, we need to set the associated model visibility appropriately. This way when it gets added to the scene later in preRender, initWhenReady, it will render with the correct visibility settings. --- interface/src/avatar/MyAvatar.cpp | 17 +++++++++++++---- interface/src/avatar/MyAvatar.h | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0b9d770de0..4704fc3413 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -994,16 +994,21 @@ QString MyAvatar::getModelDescription() const { void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { Avatar::setFaceModelURL(faceModelURL); + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene); _billboardValid = false; } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + _skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene); _billboardValid = false; if (_useFullAvatar) { const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst"); _firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); + _firstPersonSkeletonModel.setVisibleInScene(!_prevShouldDrawHead, scene); } } @@ -1212,13 +1217,13 @@ void MyAvatar::setVisibleInSceneIfReady(Model* model, render::ScenePointer scene void MyAvatar::preRender(RenderArgs* renderArgs) { render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + const bool shouldDrawHead = shouldRenderHead(renderArgs); _skeletonModel.initWhenReady(scene); if (_useFullAvatar) { _firstPersonSkeletonModel.initWhenReady(scene); } - bool shouldDrawHead = shouldRenderHead(renderArgs); if (shouldDrawHead != _prevShouldDrawHead) { if (_useFullAvatar) { if (shouldDrawHead) { @@ -1238,12 +1243,16 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; -bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { - const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); +bool MyAvatar::cameraInsideHead() const { const Head* head = getHead(); + const glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); + return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * _scale); +} + +bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) || - (glm::length(cameraPos - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale)); + !cameraInsideHead()); } void MyAvatar::updateOrientation(float deltaTime) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8543382445..2fea09ee27 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -207,6 +207,8 @@ signals: private: + bool cameraInsideHead() const; + // These are made private for MyAvatar so that you will use the "use" methods instead virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); From e3d22ef94bbcb20d07843a0eb0ecb0d00cf3a612 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Jun 2015 16:43:27 -0700 Subject: [PATCH 118/121] Fix overlays getBounds + code cleanup --- interface/src/ui/overlays/Base3DOverlay.h | 3 + .../src/ui/overlays/BillboardOverlay.cpp | 52 +++------ interface/src/ui/overlays/BillboardOverlay.h | 11 +- interface/src/ui/overlays/Circle3DOverlay.cpp | 29 ++--- interface/src/ui/overlays/Circle3DOverlay.h | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 6 - interface/src/ui/overlays/Cube3DOverlay.h | 4 +- interface/src/ui/overlays/Grid3DOverlay.cpp | 25 ++-- interface/src/ui/overlays/Grid3DOverlay.h | 8 +- interface/src/ui/overlays/ImageOverlay.cpp | 10 +- interface/src/ui/overlays/ImageOverlay.h | 11 +- interface/src/ui/overlays/Line3DOverlay.cpp | 23 ++-- interface/src/ui/overlays/Line3DOverlay.h | 2 +- .../src/ui/overlays/LocalModelsOverlay.cpp | 6 +- .../src/ui/overlays/LocalModelsOverlay.h | 1 - interface/src/ui/overlays/ModelOverlay.cpp | 83 ++++--------- interface/src/ui/overlays/ModelOverlay.h | 7 +- interface/src/ui/overlays/Planar3DOverlay.cpp | 34 +++--- interface/src/ui/overlays/Planar3DOverlay.h | 27 ++--- .../src/ui/overlays/Rectangle3DOverlay.cpp | 4 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 12 +- interface/src/ui/overlays/Sphere3DOverlay.h | 4 +- interface/src/ui/overlays/Text3DOverlay.cpp | 109 +++++++++--------- interface/src/ui/overlays/Text3DOverlay.h | 10 +- interface/src/ui/overlays/TextOverlay.cpp | 5 +- interface/src/ui/overlays/TextOverlay.h | 9 +- interface/src/ui/overlays/Volume3DOverlay.cpp | 70 +++++------ interface/src/ui/overlays/Volume3DOverlay.h | 30 ++--- 28 files changed, 220 insertions(+), 377 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 542b786ae2..3cb4d27021 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -26,6 +26,7 @@ public: virtual bool is3D() const { return true; } const glm::vec3& getPosition() const { return _transform.getTranslation(); } const glm::quat& getRotation() const { return _transform.getRotation(); } + const glm::vec3& getScale() const { return _transform.getScale(); } // TODO: consider implementing registration points in this class const glm::vec3& getCenter() const { return getPosition(); } @@ -41,6 +42,8 @@ public: // setters void setPosition(const glm::vec3& value) { _transform.setTranslation(value); } void setRotation(const glm::quat& value) { _transform.setRotation(value); } + void setScale(float value) { _transform.setScale(value); } + void setScale(const glm::vec3& value) { _transform.setScale(value); } void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } void setIsSolid(bool isSolid) { _isSolid = isSolid; } diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index e7b043f44f..288a950bbb 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -9,26 +9,20 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Application.h" -#include "GeometryUtil.h" -#include "PlaneShape.h" - #include "BillboardOverlay.h" -BillboardOverlay::BillboardOverlay() : - _fromImage(), - _scale(1.0f), - _isFacingAvatar(true) -{ +#include "Application.h" +#include "GeometryUtil.h" + +BillboardOverlay::BillboardOverlay() { _isLoaded = false; } BillboardOverlay::BillboardOverlay(const BillboardOverlay* billboardOverlay) : - Base3DOverlay(billboardOverlay), + Planar3DOverlay(billboardOverlay), _url(billboardOverlay->_url), _texture(billboardOverlay->_texture), _fromImage(billboardOverlay->_fromImage), - _scale(billboardOverlay->_scale), _isFacingAvatar(billboardOverlay->_isFacingAvatar) { } @@ -46,8 +40,8 @@ void BillboardOverlay::render(RenderArgs* args) { glm::quat rotation; if (_isFacingAvatar) { // rotate about vertical to face the camera - rotation = Application::getInstance()->getCamera()->getRotation(); - rotation *= glm::angleAxis(glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); + rotation = args->_viewFrustum->getOrientation(); + rotation *= glm::angleAxis(glm::pi(), IDENTITY_UP); rotation *= getRotation(); } else { rotation = getRotation(); @@ -89,11 +83,9 @@ void BillboardOverlay::render(RenderArgs* args) { auto batch = args->_batch; if (batch) { - Transform transform; - transform.setTranslation(_position); - transform.setRotation(rotation); - transform.setScale(_scale); - + Transform transform = _transform; + transform.postScale(glm::vec3(getDimensions(), 1.0f)); + batch->setModelTransform(transform); batch->setUniformTexture(0, _texture->getGPUTexture()); @@ -111,10 +103,10 @@ void BillboardOverlay::render(RenderArgs* args) { glBindTexture(GL_TEXTURE_2D, _texture->getID()); glPushMatrix(); { - glTranslatef(_position.x, _position.y, _position.z); + glTranslatef(getPosition().x, getPosition().y, getPosition().z); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glScalef(_scale, _scale, _scale); + glScalef(_dimensions.x, _dimensions.y, 1.0f); DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)); @@ -130,7 +122,7 @@ void BillboardOverlay::render(RenderArgs* args) { } void BillboardOverlay::setProperties(const QScriptValue &properties) { - Base3DOverlay::setProperties(properties); + Planar3DOverlay::setProperties(properties); QScriptValue urlValue = properties.property("url"); if (urlValue.isValid()) { @@ -171,11 +163,6 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) { } } - QScriptValue scaleValue = properties.property("scale"); - if (scaleValue.isValid()) { - _scale = scaleValue.toVariant().toFloat(); - } - QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar"); if (isFacingAvatarValue.isValid()) { _isFacingAvatar = isFacingAvatarValue.toVariant().toBool(); @@ -189,14 +176,11 @@ QScriptValue BillboardOverlay::getProperty(const QString& property) { if (property == "subImage") { return qRectToScriptValue(_scriptEngine, _fromImage); } - if (property == "scale") { - return _scale; - } if (property == "isFacingAvatar") { return _isFacingAvatar; } - return Base3DOverlay::getProperty(property); + return Planar3DOverlay::getProperty(property); } void BillboardOverlay::setURL(const QString& url) { @@ -212,13 +196,11 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float& distance, BoxFace& face) { if (_texture) { - glm::quat rotation; + glm::quat rotation = getRotation(); if (_isFacingAvatar) { // rotate about vertical to face the camera rotation = Application::getInstance()->getCamera()->getRotation(); rotation *= glm::angleAxis(glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); - } else { - rotation = _rotation; } // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. @@ -226,9 +208,9 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float width = isNull ? _texture->getWidth() : _fromImage.width(); float height = isNull ? _texture->getHeight() : _fromImage.height(); float maxSize = glm::max(width, height); - glm::vec2 dimensions = _scale * glm::vec2(width / maxSize, height / maxSize); + glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize); - return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions, distance); + return findRayRectangleIntersection(origin, direction, rotation, getPosition(), dimensions, distance); } return false; diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index a09c0c7528..15be0419a9 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -12,14 +12,11 @@ #ifndef hifi_BillboardOverlay_h #define hifi_BillboardOverlay_h -#include -#include - #include -#include "Base3DOverlay.h" +#include "Planar3DOverlay.h" -class BillboardOverlay : public Base3DOverlay { +class BillboardOverlay : public Planar3DOverlay { Q_OBJECT public: BillboardOverlay(); @@ -29,7 +26,6 @@ public: // setters void setURL(const QString& url); - void setScale(float scale) { _scale = scale; } void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } virtual void setProperties(const QScriptValue& properties); @@ -48,8 +44,7 @@ private: QRect _fromImage; // where from in the image to sample - float _scale; - bool _isFacingAvatar; + bool _isFacingAvatar = true; }; #endif // hifi_BillboardOverlay_h diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 55cb7ac9d2..53f1b4ce21 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -8,16 +8,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" +#include "Circle3DOverlay.h" #include #include -#include -#include -#include +#include -#include "Circle3DOverlay.h" Circle3DOverlay::Circle3DOverlay() : _startAt(0.0f), @@ -66,9 +62,6 @@ Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) : { } -Circle3DOverlay::~Circle3DOverlay() { -} - void Circle3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible @@ -103,15 +96,13 @@ void Circle3DOverlay::render(RenderArgs* args) { _lastColor = colorX; auto geometryCache = DependencyManager::get(); - - Transform transform; - transform.setTranslation(getCenter()); - transform.setRotation(getRotation()); - transform.setScale(glm::vec3(getDimensions(), 0.01f) / 2.0f); - + Q_ASSERT(args->_batch); auto& batch = *args->_batch; batch._glLineWidth(_lineWidth); + + auto transform = _transform; + transform.postScale(glm::vec3(getDimensions(), 1.0f)); batch.setModelTransform(transform); DependencyManager::get()->bindSimpleProgram(batch, false, false); @@ -402,12 +393,12 @@ bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, if (intersects) { glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position); - localHitPosition.y = localHitPosition.y * _dimensions.x / _dimensions.y; // Scale to make circular + glm::vec3 localHitPosition = glm::inverse(getRotation()) * (hitPosition - getPosition()); + localHitPosition.y = localHitPosition.y * getDimensions().x / getDimensions().y; // Scale to make circular float distanceToHit = glm::length(localHitPosition); - float innerRadius = _dimensions.x / 2.0f * _innerRadius; - float outerRadius = _dimensions.x / 2.0f * _outerRadius; + float innerRadius = getDimensions().x / 2.0f * _innerRadius; + float outerRadius = getDimensions().x / 2.0f * _outerRadius; intersects = innerRadius <= distanceToHit && distanceToHit <= outerRadius; } diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index fa9ecd0f25..c2f25c711d 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -19,7 +19,7 @@ class Circle3DOverlay : public Planar3DOverlay { public: Circle3DOverlay(); Circle3DOverlay(const Circle3DOverlay* circle3DOverlay); - ~Circle3DOverlay(); + virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 37b30a5bcb..7eb9a5b414 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -19,17 +19,11 @@ #include "Application.h" #include "Cube3DOverlay.h" -Cube3DOverlay::Cube3DOverlay() : _borderSize(0) { -} - Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) : Volume3DOverlay(cube3DOverlay) { } -Cube3DOverlay::~Cube3DOverlay() { -} - void Cube3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h index 16705a9c71..397ad77a9e 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.h +++ b/interface/src/ui/overlays/Cube3DOverlay.h @@ -17,9 +17,9 @@ class Cube3DOverlay : public Volume3DOverlay { Q_OBJECT public: - Cube3DOverlay(); + Cube3DOverlay() {} Cube3DOverlay(const Cube3DOverlay* cube3DOverlay); - ~Cube3DOverlay(); + virtual void render(RenderArgs* args); virtual Cube3DOverlay* createClone() const; diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index e68e5b47f2..6316c8cd77 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -9,28 +9,29 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include "Grid3DOverlay.h" + #include #include "Application.h" -#include "Grid3DOverlay.h" ProgramObject Grid3DOverlay::_gridProgram; -Grid3DOverlay::Grid3DOverlay() : Base3DOverlay(), +Grid3DOverlay::Grid3DOverlay() : _minorGridWidth(1.0), _majorGridEvery(5) { } Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) : - Base3DOverlay(grid3DOverlay), + Planar3DOverlay(grid3DOverlay), _minorGridWidth(grid3DOverlay->_minorGridWidth), _majorGridEvery(grid3DOverlay->_majorGridEvery) { } -Grid3DOverlay::~Grid3DOverlay() { -} - void Grid3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible @@ -41,7 +42,7 @@ void Grid3DOverlay::render(RenderArgs* args) { const float MAX_COLOR = 255.0f; // center the grid around the camera position on the plane - glm::vec3 rotated = glm::inverse(_rotation) * Application::getInstance()->getCamera()->getPosition(); + glm::vec3 rotated = glm::inverse(getRotation()) * Application::getInstance()->getCamera()->getPosition(); float spacing = _minorGridWidth; @@ -53,7 +54,7 @@ void Grid3DOverlay::render(RenderArgs* args) { if (batch) { Transform transform; - transform.setRotation(_rotation); + transform.setRotation(getRotation()); // Minor grid @@ -61,7 +62,7 @@ void Grid3DOverlay::render(RenderArgs* args) { batch->_glLineWidth(1.0f); auto position = glm::vec3(_minorGridWidth * (floorf(rotated.x / spacing) - MINOR_GRID_DIVISIONS / 2), spacing * (floorf(rotated.y / spacing) - MINOR_GRID_DIVISIONS / 2), - _position.z); + getPosition().z); float scale = MINOR_GRID_DIVISIONS * spacing; transform.setTranslation(position); @@ -78,7 +79,7 @@ void Grid3DOverlay::render(RenderArgs* args) { spacing *= _majorGridEvery; auto position = glm::vec3(spacing * (floorf(rotated.x / spacing) - MAJOR_GRID_DIVISIONS / 2), spacing * (floorf(rotated.y / spacing) - MAJOR_GRID_DIVISIONS / 2), - _position.z); + getPosition().z); float scale = MAJOR_GRID_DIVISIONS * spacing; transform.setTranslation(position); @@ -161,7 +162,7 @@ void Grid3DOverlay::render(RenderArgs* args) { } void Grid3DOverlay::setProperties(const QScriptValue& properties) { - Base3DOverlay::setProperties(properties); + Planar3DOverlay::setProperties(properties); if (properties.property("minorGridWidth").isValid()) { _minorGridWidth = properties.property("minorGridWidth").toVariant().toFloat(); @@ -180,7 +181,7 @@ QScriptValue Grid3DOverlay::getProperty(const QString& property) { return _majorGridEvery; } - return Base3DOverlay::getProperty(property); + return Planar3DOverlay::getProperty(property); } Grid3DOverlay* Grid3DOverlay::createClone() const { diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h index 451ce0a498..ac0f2834fe 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.h +++ b/interface/src/ui/overlays/Grid3DOverlay.h @@ -15,20 +15,16 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include - #include -#include -#include "Base3DOverlay.h" +#include "Planar3DOverlay.h" -class Grid3DOverlay : public Base3DOverlay { +class Grid3DOverlay : public Planar3DOverlay { Q_OBJECT public: Grid3DOverlay(); Grid3DOverlay(const Grid3DOverlay* grid3DOverlay); - ~Grid3DOverlay(); virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 72e47b5e3d..e84b60cc43 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -11,14 +11,11 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include -#include +#include "ImageOverlay.h" #include #include -#include - -#include "ImageOverlay.h" +#include ImageOverlay::ImageOverlay() : _imageURL(), @@ -38,9 +35,6 @@ ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) : { } -ImageOverlay::~ImageOverlay() { -} - // TODO: handle setting image multiple times, how do we manage releasing the bound texture? void ImageOverlay::setImageURL(const QUrl& url) { _imageURL = url; diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index 31c6031102..e818469643 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -11,21 +11,12 @@ #ifndef hifi_ImageOverlay_h #define hifi_ImageOverlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - #include -#include #include -#include -#include #include -#include -#include #include -#include "Overlay.h" #include "Overlay2D.h" class ImageOverlay : public Overlay2D { @@ -34,7 +25,7 @@ class ImageOverlay : public Overlay2D { public: ImageOverlay(); ImageOverlay(const ImageOverlay* imageOverlay); - ~ImageOverlay(); + virtual void render(RenderArgs* args); // getters diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 44c6ec7ef6..0bb32b9d6e 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "Line3DOverlay.h" @@ -33,13 +34,12 @@ Line3DOverlay::~Line3DOverlay() { } AABox Line3DOverlay::getBounds() const { - auto start = _position + _start; - auto end = _position + _end; - - auto min = glm::min(start, end); - auto max = glm::max(start, end); - - return AABox(min, max - min); + auto extents = Extents{}; + extents.addPoint(_start); + extents.addPoint(_end); + extents.transform(_transform); + + return AABox(extents); } void Line3DOverlay::render(RenderArgs* args) { @@ -55,14 +55,11 @@ void Line3DOverlay::render(RenderArgs* args) { auto batch = args->_batch; if (batch) { - Transform transform; - transform.setTranslation(_position); - transform.setRotation(_rotation); - batch->setModelTransform(transform); + batch->setModelTransform(_transform); if (getIsDashedLine()) { // TODO: add support for color to renderDashedLine() - DependencyManager::get()->renderDashedLine(*batch, _position, _end, colorv4, _geometryCacheID); + DependencyManager::get()->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID); } else { DependencyManager::get()->renderLine(*batch, _start, _end, colorv4, _geometryCacheID); } @@ -87,7 +84,7 @@ void Line3DOverlay::render(RenderArgs* args) { if (getIsDashedLine()) { // TODO: add support for color to renderDashedLine() - DependencyManager::get()->renderDashedLine(_position, _end, colorv4, _geometryCacheID); + DependencyManager::get()->renderDashedLine(_start, _end, colorv4, _geometryCacheID); } else { DependencyManager::get()->renderLine(_start, _end, colorv4, _geometryCacheID); } diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index ac5f18d8ed..4a4d8f4d90 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -21,7 +21,7 @@ public: Line3DOverlay(const Line3DOverlay* line3DOverlay); ~Line3DOverlay(); virtual void render(RenderArgs* args); - virtual AABox getBounds() const override; + virtual AABox getBounds() const; // getters const glm::vec3& getStart() const { return _start; } diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index b9ce245128..912196041f 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -24,10 +24,6 @@ LocalModelsOverlay::LocalModelsOverlay(const LocalModelsOverlay* localModelsOver Volume3DOverlay(localModelsOverlay), _entityTreeRenderer(localModelsOverlay->_entityTreeRenderer) { - -} - -LocalModelsOverlay::~LocalModelsOverlay() { } void LocalModelsOverlay::update(float deltatime) { @@ -46,7 +42,7 @@ void LocalModelsOverlay::render(RenderArgs* args) { glPushMatrix(); { Application* app = Application::getInstance(); glm::vec3 oldTranslation = app->getViewMatrixTranslation(); - app->setViewMatrixTranslation(oldTranslation + _position); + app->setViewMatrixTranslation(oldTranslation + getPosition()); _entityTreeRenderer->render(args); Application::getInstance()->setViewMatrixTranslation(oldTranslation); } glPopMatrix(); diff --git a/interface/src/ui/overlays/LocalModelsOverlay.h b/interface/src/ui/overlays/LocalModelsOverlay.h index a82943a4a0..c311b2bc1b 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.h +++ b/interface/src/ui/overlays/LocalModelsOverlay.h @@ -21,7 +21,6 @@ class LocalModelsOverlay : public Volume3DOverlay { public: LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer); LocalModelsOverlay(const LocalModelsOverlay* localModelsOverlay); - ~LocalModelsOverlay(); virtual void update(float deltatime); virtual void render(RenderArgs* args); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 822fff9808..4476518efe 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -9,15 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelOverlay.h" + #include #include -#include "ModelOverlay.h" ModelOverlay::ModelOverlay() : _model(), _modelTextures(QVariantMap()), - _scale(1.0f), _updateModel(false) { _model.init(); @@ -25,12 +25,10 @@ ModelOverlay::ModelOverlay() } ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) : - Base3DOverlay(modelOverlay), + Volume3DOverlay(modelOverlay), _model(), _modelTextures(QVariantMap()), _url(modelOverlay->_url), - _rotation(modelOverlay->_rotation), - _scale(modelOverlay->_scale), _updateModel(false) { _model.init(); @@ -45,8 +43,9 @@ void ModelOverlay::update(float deltatime) { _updateModel = false; _model.setSnapModelToCenter(true); - _model.setRotation(_rotation); - _model.setTranslation(_position); + _model.setScale(getScale()); + _model.setRotation(getRotation()); + _model.setTranslation(getPosition()); _model.setURL(_url); _model.simulate(deltatime, true); } else { @@ -56,13 +55,13 @@ void ModelOverlay::update(float deltatime) { } bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - Base3DOverlay::addToScene(overlay, scene, pendingChanges); + Volume3DOverlay::addToScene(overlay, scene, pendingChanges); _model.addToScene(scene, pendingChanges); return true; } void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - Base3DOverlay::removeFromScene(overlay, scene, pendingChanges); + Volume3DOverlay::removeFromScene(overlay, scene, pendingChanges); _model.removeFromScene(scene, pendingChanges); } @@ -100,54 +99,26 @@ void ModelOverlay::render(RenderArgs* args) { } void ModelOverlay::setProperties(const QScriptValue &properties) { - Base3DOverlay::setProperties(properties); + auto position = getPosition(); + auto rotation = getRotation(); + auto scale = getDimensions(); + + Volume3DOverlay::setProperties(properties); + + if (position != getPosition() || rotation != getRotation() || scale != getDimensions()) { + _model.setScaleToFit(true, getScale()); + _updateModel = true; + } QScriptValue urlValue = properties.property("url"); - if (urlValue.isValid()) { - _url = urlValue.toVariant().toString(); + if (urlValue.isValid() && urlValue.isString()) { + _url = urlValue.toString(); _updateModel = true; _isLoaded = false; } - QScriptValue scaleValue = properties.property("scale"); - if (scaleValue.isValid()) { - _scale = scaleValue.toVariant().toFloat(); - _model.setScaleToFit(true, _scale); - _updateModel = true; - } - - QScriptValue rotationValue = properties.property("rotation"); - if (rotationValue.isValid()) { - QScriptValue x = rotationValue.property("x"); - QScriptValue y = rotationValue.property("y"); - QScriptValue z = rotationValue.property("z"); - QScriptValue w = rotationValue.property("w"); - if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { - _rotation.x = x.toVariant().toFloat(); - _rotation.y = y.toVariant().toFloat(); - _rotation.z = z.toVariant().toFloat(); - _rotation.w = w.toVariant().toFloat(); - } - _updateModel = true; - } - - QScriptValue dimensionsValue = properties.property("dimensions"); - if (dimensionsValue.isValid()) { - QScriptValue x = dimensionsValue.property("x"); - QScriptValue y = dimensionsValue.property("y"); - QScriptValue z = dimensionsValue.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - glm::vec3 dimensions; - dimensions.x = x.toVariant().toFloat(); - dimensions.y = y.toVariant().toFloat(); - dimensions.z = z.toVariant().toFloat(); - _model.setScaleToFit(true, dimensions); - } - _updateModel = true; - } - QScriptValue texturesValue = properties.property("textures"); - if (texturesValue.isValid()) { + if (texturesValue.isValid() && texturesValue.toVariant().canConvert(QVariant::Map)) { QVariantMap textureMap = texturesValue.toVariant().toMap(); foreach(const QString& key, textureMap.keys()) { @@ -161,22 +132,12 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { _modelTextures[key] = newTextureURL; // Keep local track of textures for getProperty() } } - - if (properties.property("position").isValid()) { - _updateModel = true; - } } QScriptValue ModelOverlay::getProperty(const QString& property) { if (property == "url") { return _url.toString(); } - if (property == "scale") { - return _scale; - } - if (property == "rotation") { - return quatToScriptValue(_scriptEngine, _rotation); - } if (property == "dimensions") { return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions()); } @@ -192,7 +153,7 @@ QScriptValue ModelOverlay::getProperty(const QString& property) { } } - return Base3DOverlay::getProperty(property); + return Volume3DOverlay::getProperty(property); } bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index a81cae530a..1c43f42909 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -14,9 +14,9 @@ #include -#include "Base3DOverlay.h" +#include "Volume3DOverlay.h" -class ModelOverlay : public Base3DOverlay { +class ModelOverlay : public Volume3DOverlay { Q_OBJECT public: ModelOverlay(); @@ -41,9 +41,6 @@ private: QVariantMap _modelTextures; QUrl _url; - glm::quat _rotation; - float _scale; - bool _updateModel; }; diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 7ed7332f19..0ca092ba23 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -8,32 +8,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include -#include - -#include "GeometryUtil.h" - #include "Planar3DOverlay.h" -const float DEFAULT_SIZE = 1.0f; - -Planar3DOverlay::Planar3DOverlay() : - _dimensions(glm::vec2(DEFAULT_SIZE, DEFAULT_SIZE)) -{ -} +#include +#include +#include Planar3DOverlay::Planar3DOverlay(const Planar3DOverlay* planar3DOverlay) : - Base3DOverlay(planar3DOverlay), - _dimensions(planar3DOverlay->_dimensions) + Base3DOverlay(planar3DOverlay) { } -Planar3DOverlay::~Planar3DOverlay() { +AABox Planar3DOverlay::getBounds() const { + auto halfDimensions = glm::vec3{_dimensions / 2.0f, 0.01f}; + + auto extents = Extents{-halfDimensions, halfDimensions}; + extents.transform(_transform); + + return AABox(extents); } void Planar3DOverlay::setProperties(const QScriptValue& properties) { @@ -86,7 +78,7 @@ void Planar3DOverlay::setProperties(const QScriptValue& properties) { QScriptValue Planar3DOverlay::getProperty(const QString& property) { if (property == "dimensions" || property == "scale" || property == "size") { - return vec2toScriptValue(_scriptEngine, _dimensions); + return vec2toScriptValue(_scriptEngine, getDimensions()); } return Base3DOverlay::getProperty(property); @@ -94,5 +86,5 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { - return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions, distance); + return findRayRectangleIntersection(origin, direction, getRotation(), getPosition(), getDimensions(), distance); } diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index 8a02b35bd2..fe8c513efd 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -11,37 +11,28 @@ #ifndef hifi_Planar3DOverlay_h #define hifi_Planar3DOverlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include - -#include - #include "Base3DOverlay.h" class Planar3DOverlay : public Base3DOverlay { Q_OBJECT public: - Planar3DOverlay(); + Planar3DOverlay() {} Planar3DOverlay(const Planar3DOverlay* planar3DOverlay); - ~Planar3DOverlay(); - - // getters - const glm::vec2& getDimensions() const { return _dimensions; } - - // setters - void setSize(float size) { _dimensions = glm::vec2(size, size); } + + AABox getBounds() const; + + glm::vec2 getDimensions() const { return _dimensions; } + void setDimensions(float value) { _dimensions = glm::vec2(value); } void setDimensions(const glm::vec2& value) { _dimensions = value; } - + virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); - + protected: - glm::vec2 _dimensions; + glm::vec2 _dimensions{1.0f, 1.0f}; }; diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index dc5fdeabb2..74bbd1bca8 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -11,12 +11,12 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" +#include "Rectangle3DOverlay.h" + #include #include #include -#include "Rectangle3DOverlay.h" - Rectangle3DOverlay::Rectangle3DOverlay() : _geometryCacheID(DependencyManager::get()->allocateID()) { diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index f5fba0ed05..e129954db9 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -17,17 +17,12 @@ #include "Sphere3DOverlay.h" #include "Application.h" -Sphere3DOverlay::Sphere3DOverlay() { -} Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) : Volume3DOverlay(Sphere3DOverlay) { } -Sphere3DOverlay::~Sphere3DOverlay() { -} - void Sphere3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible @@ -42,11 +37,8 @@ void Sphere3DOverlay::render(RenderArgs* args) { auto batch = args->_batch; if (batch) { - Transform transform; - transform.setTranslation(_position); - transform.setRotation(_rotation); - transform.setScale(_dimensions); - + Transform transform = _transform; + transform.postScale(getDimensions()); batch->setModelTransform(transform); DependencyManager::get()->renderSphere(*batch, 1.0f, SLICES, SLICES, sphereColor, _isSolid); } else { diff --git a/interface/src/ui/overlays/Sphere3DOverlay.h b/interface/src/ui/overlays/Sphere3DOverlay.h index 3b881e5ba6..b82dc548f1 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.h +++ b/interface/src/ui/overlays/Sphere3DOverlay.h @@ -17,9 +17,9 @@ class Sphere3DOverlay : public Volume3DOverlay { Q_OBJECT public: - Sphere3DOverlay(); + Sphere3DOverlay() {} Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay); - ~Sphere3DOverlay(); + virtual void render(RenderArgs* args); virtual Sphere3DOverlay* createClone() const; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 5acd10eb45..37774094de 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -11,14 +11,17 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include "Application.h" #include "Text3DOverlay.h" #include +#include + +#include "Application.h" const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const float DEFAULT_BACKGROUND_ALPHA = 0.7f; const float DEFAULT_MARGIN = 0.1f; +const int FIXED_FONT_POINT_SIZE = 40; const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 80.0f; // this is a ratio determined through experimentation const float LINE_SCALE_RATIO = 1.2f; @@ -32,6 +35,7 @@ Text3DOverlay::Text3DOverlay() : _bottomMargin(DEFAULT_MARGIN), _isFacingAvatar(false) { + _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); } Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : @@ -46,6 +50,7 @@ Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : _bottomMargin(text3DOverlay->_bottomMargin), _isFacingAvatar(text3DOverlay->_isFacingAvatar) { + _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); } Text3DOverlay::~Text3DOverlay() { @@ -77,58 +82,58 @@ void Text3DOverlay::render(RenderArgs* args) { return; // do nothing if we're not visible } - auto batch = args->_batch; - - if (batch) { - glm::quat rotation; - - if (_isFacingAvatar) { - // rotate about vertical to face the camera - rotation = Application::getInstance()->getCamera()->getRotation(); - } else { - rotation = getRotation(); - } - - Transform transform; - transform.setTranslation(_position); - transform.setRotation(rotation); - - batch->setModelTransform(transform); - - const float MAX_COLOR = 255.0f; - xColor backgroundColor = getBackgroundColor(); - glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, - getBackgroundAlpha()); - - glm::vec2 dimensions = getDimensions(); - glm::vec2 halfDimensions = dimensions * 0.5f; - - const float SLIGHTLY_BEHIND = -0.005f; - - glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); - glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - DependencyManager::get()->renderQuad(*batch, topLeft, bottomRight, quadColor); - - // Same font properties as textSize() - float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; - - float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; - - glm::vec2 clipMinimum(0.0f, 0.0f); - glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, - (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); - - transform.setTranslation(_position); - transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f)); - transform.setScale(scaleFactor); - batch->setModelTransform(transform); - - glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; - _textRenderer->draw(*batch, 0, 0, _text, textColor); - - batch->setPipeline(DrawOverlay3D::getOpaquePipeline()); + + Q_ASSERT(args->_batch); + auto& batch = *args->_batch; + + glm::quat rotation; + + if (_isFacingAvatar) { + // rotate about vertical to face the camera + rotation = args->_viewFrustum->getOrientation(); + } else { + rotation = getRotation(); } - + + Transform transform; + transform.setTranslation(getPosition()); + transform.setRotation(rotation); + transform.setScale(getScale()); + + batch.setModelTransform(transform); + + const float MAX_COLOR = 255.0f; + xColor backgroundColor = getBackgroundColor(); + glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, + getBackgroundAlpha()); + + glm::vec2 dimensions = getDimensions(); + glm::vec2 halfDimensions = dimensions * 0.5f; + + const float SLIGHTLY_BEHIND = -0.005f; + + glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); + glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, quadColor); + + // Same font properties as textSize() + float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; + + float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; + + glm::vec2 clipMinimum(0.0f, 0.0f); + glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, + (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); + + transform.setTranslation(getPosition()); + transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin) , halfDimensions.y - _topMargin, 0.01f)); + transform.setScale(scaleFactor); + batch.setModelTransform(transform); + + glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, getAlpha() }; + _textRenderer->draw(batch, 0, 0, _text, textColor); + + batch.setPipeline(DrawOverlay3D::getOpaquePipeline()); } void Text3DOverlay::setProperties(const QScriptValue& properties) { diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index a30a720414..666b43d8b1 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -11,17 +11,11 @@ #ifndef hifi_Text3DOverlay_h #define hifi_Text3DOverlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - #include -#include -#include - #include "Planar3DOverlay.h" -const int FIXED_FONT_POINT_SIZE = 40; +class TextRenderer3D; class Text3DOverlay : public Planar3DOverlay { Q_OBJECT @@ -60,7 +54,7 @@ public: virtual Text3DOverlay* createClone() const; private: - TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); + TextRenderer3D* _textRenderer = nullptr; QString _text; xColor _backgroundColor; diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 1a8b74dea8..ccad3bd295 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -11,11 +11,14 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" +#include "TextOverlay.h" + #include #include +#include #include +#include -#include "TextOverlay.h" TextOverlay::TextOverlay() : _backgroundColor(DEFAULT_BACKGROUND_COLOR), diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 5a715ebfdf..b5d5dba11b 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -11,17 +11,10 @@ #ifndef hifi_TextOverlay_h #define hifi_TextOverlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include #include #include -#include -#include "Overlay.h" #include "Overlay2D.h" const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; @@ -30,6 +23,8 @@ const int DEFAULT_MARGIN = 10; const int DEFAULT_FONTSIZE = 11; const int DEFAULT_FONT_WEIGHT = 50; +class TextRenderer; + class TextOverlay : public Overlay2D { Q_OBJECT diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index b0310f8155..a7c9835f5d 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -8,32 +8,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include - #include "Volume3DOverlay.h" -const float DEFAULT_SIZE = 1.0f; - -Volume3DOverlay::Volume3DOverlay() : - _dimensions(glm::vec3(DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE)) -{ -} +#include +#include Volume3DOverlay::Volume3DOverlay(const Volume3DOverlay* volume3DOverlay) : - Base3DOverlay(volume3DOverlay), - _dimensions(volume3DOverlay->_dimensions) + Base3DOverlay(volume3DOverlay) { } -Volume3DOverlay::~Volume3DOverlay() { +AABox Volume3DOverlay::getBounds() const { + auto extents = Extents{_localBoundingBox}; + extents.rotate(getRotation()); + extents.shiftBy(getPosition()); + + return AABox(extents); } void Volume3DOverlay::setProperties(const QScriptValue& properties) { @@ -58,26 +48,30 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) { QScriptValue z = dimensions.property("z"); - if (x.isValid() && y.isValid() && z.isValid()) { - newDimensions.x = x.toVariant().toFloat(); - newDimensions.y = y.toVariant().toFloat(); - newDimensions.z = z.toVariant().toFloat(); + if (x.isValid() && x.isNumber() && + y.isValid() && y.isNumber() && + z.isValid() && z.isNumber()) { + newDimensions.x = x.toNumber(); + newDimensions.y = y.toNumber(); + newDimensions.z = z.toNumber(); validDimensions = true; } else { QScriptValue width = dimensions.property("width"); QScriptValue height = dimensions.property("height"); QScriptValue depth = dimensions.property("depth"); - if (width.isValid() && height.isValid() && depth.isValid()) { - newDimensions.x = width.toVariant().toFloat(); - newDimensions.y = height.toVariant().toFloat(); - newDimensions.z = depth.toVariant().toFloat(); + if (width.isValid() && width.isNumber() && + height.isValid() && height.isNumber() && + depth.isValid() && depth.isNumber()) { + newDimensions.x = width.toNumber(); + newDimensions.y = height.toNumber(); + newDimensions.z = depth.toNumber(); validDimensions = true; } } // size, scale, dimensions is special, it might just be a single scalar, check that here if (!validDimensions && dimensions.isNumber()) { - float size = dimensions.toVariant().toFloat(); + float size = dimensions.toNumber(); newDimensions.x = size; newDimensions.y = size; newDimensions.z = size; @@ -92,7 +86,7 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) { QScriptValue Volume3DOverlay::getProperty(const QString& property) { if (property == "dimensions" || property == "scale" || property == "size") { - return vec3toScriptValue(_scriptEngine, _dimensions); + return vec3toScriptValue(_scriptEngine, getDimensions()); } return Base3DOverlay::getProperty(property); @@ -100,24 +94,14 @@ QScriptValue Volume3DOverlay::getProperty(const QString& property) { bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { - // extents is the entity relative, scaled, centered extents of the entity - glm::vec3 position = getPosition(); - glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(position); - glm::mat4 entityToWorldMatrix = translation * rotation; - glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - - glm::vec3 dimensions = _dimensions; - glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference - AABox overlayFrameBox(corner, dimensions); + glm::mat4 worldToEntityMatrix; + _transform.getInverseMatrix(worldToEntityMatrix); + glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); // we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame // and testing intersection there. - if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) { - return true; - } - return false; + return _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face); } diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index b7c59b2ace..ada485a663 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -11,39 +11,29 @@ #ifndef hifi_Volume3DOverlay_h #define hifi_Volume3DOverlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include - -#include - #include "Base3DOverlay.h" class Volume3DOverlay : public Base3DOverlay { Q_OBJECT public: - Volume3DOverlay(); + Volume3DOverlay() {} Volume3DOverlay(const Volume3DOverlay* volume3DOverlay); - ~Volume3DOverlay(); - - // getters - const glm::vec3& getCenter() const { return _position; } // TODO: consider adding registration point!! - glm::vec3 getCorner() const { return _position - (_dimensions * 0.5f); } // TODO: consider adding registration point!! - const glm::vec3& getDimensions() const { return _dimensions; } - - // setters - void setSize(float size) { _dimensions = glm::vec3(size, size, size); } - void setDimensions(const glm::vec3& value) { _dimensions = value; } + + virtual AABox getBounds() const; + + const glm::vec3& getDimensions() const { return _localBoundingBox.getDimensions(); } + void setDimensions(float value) { _localBoundingBox.setBox(glm::vec3(-value / 2.0f), value); } + void setDimensions(const glm::vec3& value) { _localBoundingBox.setBox(-value / 2.0f, value); } virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face); - + protected: - glm::vec3 _dimensions; + // Centered local bounding box + AABox _localBoundingBox; }; From 55c490043fb177fb155f6c964366799897862bac Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 24 Jun 2015 14:35:03 -0700 Subject: [PATCH 119/121] Restore InterfaceConfig.h includes --- interface/src/ui/overlays/Circle3DOverlay.h | 3 +++ interface/src/ui/overlays/ImageOverlay.cpp | 3 --- interface/src/ui/overlays/ImageOverlay.h | 3 +++ interface/src/ui/overlays/Overlay.h | 3 +++ interface/src/ui/overlays/Overlay2D.h | 3 +++ interface/src/ui/overlays/Planar3DOverlay.h | 3 +++ interface/src/ui/overlays/Text3DOverlay.h | 3 +++ interface/src/ui/overlays/TextOverlay.h | 3 +++ interface/src/ui/overlays/Volume3DOverlay.h | 3 +++ 9 files changed, 24 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index c2f25c711d..0a2352148a 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -11,6 +11,9 @@ #ifndef hifi_Circle3DOverlay_h #define hifi_Circle3DOverlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include "Planar3DOverlay.h" class Circle3DOverlay : public Planar3DOverlay { diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index e84b60cc43..399e8a459a 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -8,9 +8,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - #include "ImageOverlay.h" #include diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index e818469643..b7924bdb71 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -11,6 +11,9 @@ #ifndef hifi_ImageOverlay_h #define hifi_ImageOverlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include #include #include diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index a96631bbcf..375a1c3bb9 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -11,6 +11,9 @@ #ifndef hifi_Overlay_h #define hifi_Overlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include // for xColor #include diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 382105c047..d91a20b070 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -11,6 +11,9 @@ #ifndef hifi_Overlay2D_h #define hifi_Overlay2D_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include #include "Overlay.h" diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index fe8c513efd..9683cb3357 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -11,6 +11,9 @@ #ifndef hifi_Planar3DOverlay_h #define hifi_Planar3DOverlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include "Base3DOverlay.h" class Planar3DOverlay : public Base3DOverlay { diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 666b43d8b1..93d4106708 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -11,6 +11,9 @@ #ifndef hifi_Text3DOverlay_h #define hifi_Text3DOverlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include #include "Planar3DOverlay.h" diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index b5d5dba11b..db89f0b73d 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -11,6 +11,9 @@ #ifndef hifi_TextOverlay_h #define hifi_TextOverlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include #include diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index ada485a663..51f63dc580 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -11,6 +11,9 @@ #ifndef hifi_Volume3DOverlay_h #define hifi_Volume3DOverlay_h +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + #include "Base3DOverlay.h" class Volume3DOverlay : public Base3DOverlay { From bc1abbe9b200893e339aabf308ad51af268f8146 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 24 Jun 2015 16:45:38 -0700 Subject: [PATCH 120/121] Update scripts --- examples/acScripts/rain.js | 2 +- examples/libraries/entitySelectionTool.js | 52 ++++++++++++----------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/examples/acScripts/rain.js b/examples/acScripts/rain.js index ee8a1e19a6..3f38b8d36a 100644 --- a/examples/acScripts/rain.js +++ b/examples/acScripts/rain.js @@ -123,7 +123,7 @@ var RainSquall = function (properties) { function setUp() { if (debug) { squallCircle = Overlays.addOverlay("circle3d", { - size: { x: 2 * squallRadius, y: 2 * squallRadius }, + size: { x: squallRadius, y: squallRadius }, color: SQUALL_CIRCLE_COLOR, alpha: SQUALL_CIRCLE_ALPHA, solid: true, diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index d5e2b24f36..98a71e3b12 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -392,7 +392,8 @@ SelectionDisplay = (function () { var grabberSpotLightCircle = Overlays.addOverlay("circle3d", { color: lightOverlayColor, - isSolid: false + isSolid: false, + visible: false }); var grabberSpotLightLineT = Overlays.addOverlay("line3d", spotLightLineProperties); var grabberSpotLightLineB = Overlays.addOverlay("line3d", spotLightLineProperties); @@ -409,17 +410,20 @@ SelectionDisplay = (function () { var grabberPointLightCircleX = Overlays.addOverlay("circle3d", { rotation: Quat.fromPitchYawRollDegrees(0, 90, 0), color: lightOverlayColor, - isSolid: false + isSolid: false, + visible: false }); var grabberPointLightCircleY = Overlays.addOverlay("circle3d", { rotation: Quat.fromPitchYawRollDegrees(90, 0, 0), color: lightOverlayColor, - isSolid: false + isSolid: false, + visible: false }); var grabberPointLightCircleZ = Overlays.addOverlay("circle3d", { rotation: Quat.fromPitchYawRollDegrees(0, 0, 0), color: lightOverlayColor, - isSolid: false + isSolid: false, + visible: false }); var grabberPointLightT = Overlays.addOverlay("cube", grabberPropertiesEdge); var grabberPointLightB = Overlays.addOverlay("cube", grabberPropertiesEdge); @@ -546,7 +550,7 @@ SelectionDisplay = (function () { var rotateOverlayTarget = Overlays.addOverlay("circle3d", { position: { x:0, y: 0, z: 0}, - size: rotateOverlayTargetSize * 2, + size: rotateOverlayTargetSize, color: { red: 0, green: 0, blue: 0 }, alpha: 0.0, solid: true, @@ -1186,7 +1190,7 @@ SelectionDisplay = (function () { }); Overlays.editOverlay(grabberSpotLightCircle, { position: NEAR, - dimensions: { x: distance * 2, y: distance * 2, z: 1 }, + dimensions: { x: distance, y: distance, z: 1 }, lineWidth: 1.5, rotation: rotation, visible: true, @@ -1258,19 +1262,19 @@ SelectionDisplay = (function () { Overlays.editOverlay(grabberPointLightCircleX, { position: position, rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(0, 90, 0)), - dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 }, + dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 }, visible: true, }); Overlays.editOverlay(grabberPointLightCircleY, { position: position, rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(90, 0, 0)), - dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 }, + dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 }, visible: true, }); Overlays.editOverlay(grabberPointLightCircleZ, { position: position, rotation: rotation, - dimensions: { x: properties.dimensions.z, y: properties.dimensions.z, z: 1 }, + dimensions: { x: properties.dimensions.z / 2.0, y: properties.dimensions.z / 2.0, z: 1 }, visible: true, }); @@ -1966,7 +1970,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, - size: innerRadius * 2, + size: innerRadius, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -1976,7 +1980,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayOuter, { visible: true, - size: outerRadius * 2, + size: outerRadius, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -1986,7 +1990,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, - size: outerRadius * 2, + size: outerRadius, startAt: 0, endAt: 0, innerRadius: 0.9, @@ -2064,13 +2068,13 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } @@ -2095,7 +2099,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, - size: innerRadius * 2, + size: innerRadius, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -2105,7 +2109,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayOuter, { visible: true, - size: outerRadius * 2, + size: outerRadius, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -2115,7 +2119,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, - size: outerRadius * 2, + size: outerRadius, startAt: 0, endAt: 0, innerRadius: 0.9, @@ -2186,13 +2190,13 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } @@ -2216,7 +2220,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, - size: innerRadius * 2, + size: innerRadius, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -2226,7 +2230,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayOuter, { visible: true, - size: outerRadius * 2, + size: outerRadius, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -2236,7 +2240,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, - size: outerRadius * 2, + size: outerRadius, startAt: 0, endAt: 0, innerRadius: 0.9, @@ -2306,13 +2310,13 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } From c480c85f85a07eabac035e5f039677ff111bc103 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 24 Jun 2015 17:35:23 -0700 Subject: [PATCH 121/121] Fixes for switching between fullAvatar and head & body avatars while in first person. Need to always add _skeletonModel to the main scene when switching to head/body avatar. Need to always remove _firstPersonSkeletonModel from main scene when switching to head/body avatar. --- interface/src/avatar/MyAvatar.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4704fc3413..4b140e0569 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -993,6 +993,7 @@ QString MyAvatar::getModelDescription() const { } void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { + Avatar::setFaceModelURL(faceModelURL); render::ScenePointer scene = Application::getInstance()->getMain3DScene(); getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene); @@ -1000,19 +1001,27 @@ void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + Avatar::setSkeletonModelURL(skeletonModelURL); render::ScenePointer scene = Application::getInstance()->getMain3DScene(); - _skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene); _billboardValid = false; if (_useFullAvatar) { + _skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene); + const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst"); _firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); _firstPersonSkeletonModel.setVisibleInScene(!_prevShouldDrawHead, scene); + } else { + _skeletonModel.setVisibleInScene(true, scene); + + _firstPersonSkeletonModel.setVisibleInScene(false, scene); + _firstPersonSkeletonModel.reset(); } } void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) { + if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection, Q_ARG(const QUrl&, fullAvatarURL),