History

Revert "Merge pull request #5106 from jherico/render_cursor"

This reverts commit 4d18bd7cec710b5188d1f6ad5c58010117d7a77d, reversing changes made to 24fda9a7336e4eff1d1310dd3359dd6cbbb6acb5.

ZappoMan committed 11 years ago

Commit 0cdc2b51 parent a5b286610 files · +467 −325Browse files

Showing the changes to interface/src/ui/ApplicationOverlay.cpp (1 of 10 files). Show all

Unified · Split

interface/src/ui/ApplicationOverlay.cpp+417−223
@@ -14,16 +14,13 @@ · 13 unmodified lines
1414 #include <QOpenGLFramebufferObject>
1515 #include <QOpenGLTexture>
1616
17−#include <glm/gtc/type_ptr.hpp>
18−
1917 #include <avatar/AvatarManager.h>
20−#include <DeferredLightingEffect.h>
2118 #include <GLMHelpers.h>
19+#include <PathUtils.h>
2220 #include <gpu/GLBackend.h>
2321 #include <GLMHelpers.h>
24−#include <OffscreenUi.h>
25−#include <CursorManager.h>
2622 #include <PerfStat.h>
23+#include <OffscreenUi.h>
2724
2825 #include "AudioClient.h"
2926 #include "audio/AudioIOStatsRenderer.h"
@@ -36,9 +33,6 @@ · 6 unmodified lines
3633 #include "Util.h"
3734 #include "ui/Stats.h"
3835
39−#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
40−#include "../../libraries/render-utils/standardDrawTexture_frag.h"
41−
4236 // Used to animate the magnification windows
4337 const float MAG_SPEED = 0.08f;
4438
@@ -120,6 +114,27 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, · 75 unmodified lines
120114 }
121115 }
122116
117+void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) {
118+ glPushMatrix(); {
119+ glm::vec3 axis = glm::axis(orientation);
120+ glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z);
121+ glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f);
122+ glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f);
123+ glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f);
124+ glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f);
125+
126+ // TODO: this version of renderQuad() needs to take a color
127+ glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha };
128+
129+
130+
131+ DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomLeft, bottomRight, topRight,
132+ glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f),
133+ glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f),
134+ reticleColor, _reticleQuad);
135+ } glPopMatrix();
136+}
137+
123138 ApplicationOverlay::ApplicationOverlay() :
124139 _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)),
125140 _textureAspectRatio(1.0f),
@@ -133,8 +148,7 @@ ApplicationOverlay::ApplicationOverlay() : · 7 unmodified lines
133148 _previousMagnifierBottomLeft(),
134149 _previousMagnifierBottomRight(),
135150 _previousMagnifierTopLeft(),
136− _previousMagnifierTopRight(),
137− _framebufferObject(nullptr)
151+ _previousMagnifierTopRight()
138152 {
139153 memset(_reticleActive, 0, sizeof(_reticleActive));
140154 memset(_magActive, 0, sizeof(_reticleActive));
@@ -181,17 +195,16 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { · 40 unmodified lines
181195 //Handle fading and deactivation/activation of UI
182196
183197 // Render 2D overlay
198+ glMatrixMode(GL_PROJECTION);
184199 glDisable(GL_DEPTH_TEST);
185200 glDisable(GL_LIGHTING);
186201 glEnable(GL_BLEND);
187202 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
188− buildFramebufferObject();
189−
190− _framebufferObject->bind();
203+ _overlays.buildFramebufferObject();
204+ _overlays.bind();
191205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
192206 glViewport(0, 0, size.x, size.y);
193207
194− glMatrixMode(GL_PROJECTION);
195208 glPushMatrix(); {
196209 const float NEAR_CLIP = -10000;
197210 const float FAR_CLIP = 10000;
@@ -213,22 +226,6 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { · 15 unmodified lines
213226 renderPointers();
214227
215228 renderDomainConnectionStatusBorder();
216− if (_newUiTexture) {
217− glMatrixMode(GL_PROJECTION);
218− glLoadIdentity();
219− glMatrixMode(GL_MODELVIEW);
220− glLoadIdentity();
221− glEnable(GL_TEXTURE_2D);
222− glEnable(GL_BLEND);
223− glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
224− glBindTexture(GL_TEXTURE_2D, _newUiTexture);
225− DependencyManager::get<GeometryCache>()->renderUnitQuad();
226− glBindTexture(GL_TEXTURE_2D, 0);
227− glDisable(GL_TEXTURE_2D);
228− glDisable(GL_BLEND);
229− }
230− glLoadIdentity();
231−
232229
233230 glMatrixMode(GL_PROJECTION);
234231 } glPopMatrix();
@@ -238,160 +235,258 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { · 3 unmodified lines
238235 glEnable(GL_LIGHTING);
239236 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
240237
241− _framebufferObject->release();
238+ _overlays.release();
242239 }
243240
244−gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() {
245− if (!_standardDrawPipeline) {
246− auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)));
247− auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag)));
248− auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
249− gpu::Shader::makeProgram((*program));
250−
251− auto state = gpu::StatePointer(new gpu::State());
252−
253− // enable decal blend
254− state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
255−
256− _standardDrawPipeline.reset(gpu::Pipeline::create(program, state));
241+// A quick and dirty solution for compositing the old overlay
242+// texture with the new one
243+template <typename F>
244+void with_each_texture(GLuint firstPassTexture, GLuint secondPassTexture, F f) {
245+ glEnable(GL_TEXTURE_2D);
246+ glActiveTexture(GL_TEXTURE0);
247+ if (firstPassTexture) {
248+ glBindTexture(GL_TEXTURE_2D, firstPassTexture);
249+ f();
257250 }
258−
259− return _standardDrawPipeline;
260−}
261−
262−void ApplicationOverlay::bindCursorTexture(gpu::Batch& batch, uint8_t cursorIndex) {
263− auto& cursorManager = Cursor::Manager::instance();
264− auto cursor = cursorManager.getCursor(cursorIndex);
265− auto iconId = cursor->getIcon();
266− if (!_cursors.count(iconId)) {
267− auto iconPath = cursorManager.getIconImage(cursor->getIcon());
268− _cursors[iconId] = DependencyManager::get<TextureCache>()->
269− getImageTexture(iconPath);
251+ if (secondPassTexture) {
252+ glBindTexture(GL_TEXTURE_2D, secondPassTexture);
253+ f();
270254 }
271− batch.setUniformTexture(0, _cursors[iconId]);
255+ glBindTexture(GL_TEXTURE_2D, 0);
256+ glDisable(GL_TEXTURE_2D);
272257 }
273258
274−#define CURSOR_PIXEL_SIZE 32.0f
275−
276259 // Draws the FBO texture for the screen
277−void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) {
260+void ApplicationOverlay::displayOverlayTexture() {
278261 if (_alpha == 0.0f) {
279262 return;
280263 }
281−
282− renderArgs->_context->syncCache();
283−
284− gpu::Batch batch;
285− Transform model;
286− //DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true);
287− batch.setPipeline(getDrawPipeline());
288− batch.setModelTransform(Transform());
289− batch.setProjectionTransform(mat4());
290− batch.setViewTransform(model);
291− batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());
292− batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
293− batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
294− DependencyManager::get<GeometryCache>()->renderUnitQuad(batch, vec4(vec3(1), _alpha));
295−
296− //draw the mouse pointer
297− glm::vec2 canvasSize = qApp->getCanvasSize();
298−
299− // Get the mouse coordinates and convert to NDC [-1, 1]
300− vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY());
301− mousePosition /= canvasSize;
302− mousePosition *= 2.0f;
303− mousePosition -= 1.0f;
304− mousePosition.y *= -1.0f;
305− model.setTranslation(vec3(mousePosition, 0));
306− glm::vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize;
307− model.setScale(vec3(mouseSize, 1.0f));
308− batch.setModelTransform(model);
309− bindCursorTexture(batch);
310− glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
311− DependencyManager::get<GeometryCache>()->renderUnitQuad(batch, vec4(1));
312− renderArgs->_context->render(batch);
313−}
314−
315−
316−static gpu::BufferPointer _hemiVertices;
317−static gpu::BufferPointer _hemiIndices;
318−static int _hemiIndexCount{ 0 };
264+ glMatrixMode(GL_PROJECTION);
265+ glPushMatrix(); {
266+ glLoadIdentity();
267+ glDisable(GL_DEPTH_TEST);
268+ glDisable(GL_LIGHTING);
269+ glEnable(GL_BLEND);
270+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
271+ glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height());
272+
273+ static const glm::vec2 topLeft(-1, 1);
274+ static const glm::vec2 bottomRight(1, -1);
275+ static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
276+ static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
277+ with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
278+ DependencyManager::get<GeometryCache>()->renderQuad(
279+ topLeft, bottomRight,
280+ texCoordTopLeft, texCoordBottomRight,
281+ glm::vec4(1.0f, 1.0f, 1.0f, _alpha));
282+ });
283+
284+ if (!_crosshairTexture) {
285+ _crosshairTexture = DependencyManager::get<TextureCache>()->
286+ getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
287+ }
319288
320−glm::vec2 getPolarCoordinates(const PalmData& palm) {
321− MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
322− auto avatarOrientation = myAvatar->getOrientation();
323− auto eyePos = myAvatar->getDefaultEyePosition();
324− glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);
325− // Direction of the tip relative to the eye
326− glm::vec3 tipDirection = tip - eyePos;
327− // orient into avatar space
328− tipDirection = glm::inverse(avatarOrientation) * tipDirection;
329− // Normalize for trig functions
330− tipDirection = glm::normalize(tipDirection);
331− // Convert to polar coordinates
332− glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y));
333− return polar;
289+ //draw the mouse pointer
290+ glm::vec2 canvasSize = qApp->getCanvasSize();
291+ glm::vec2 mouseSize = 32.0f / canvasSize;
292+ auto mouseTopLeft = topLeft * mouseSize;
293+ auto mouseBottomRight = bottomRight * mouseSize;
294+ vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY());
295+ mousePosition /= canvasSize;
296+ mousePosition *= 2.0f;
297+ mousePosition -= 1.0f;
298+ mousePosition.y *= -1.0f;
299+
300+ glEnable(GL_TEXTURE_2D);
301+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
302+ glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
303+ glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
304+ DependencyManager::get<GeometryCache>()->renderQuad(
305+ mouseTopLeft + mousePosition, mouseBottomRight + mousePosition,
306+ texCoordTopLeft, texCoordBottomRight,
307+ reticleColor);
308+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
309+ glDisable(GL_TEXTURE_2D);
310+ } glPopMatrix();
334311 }
335312
336313 // Draws the FBO texture for Oculus rift.
337−void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) {
314+void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) {
338315 if (_alpha == 0.0f) {
339316 return;
340317 }
341318
342− renderArgs->_context->syncCache();
319+ glEnable(GL_BLEND);
320+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
321+ glEnable(GL_DEPTH_TEST);
322+ glDepthMask(GL_TRUE);
323+ glDisable(GL_LIGHTING);
324+ glEnable(GL_ALPHA_TEST);
325+ glAlphaFunc(GL_GREATER, 0.01f);
343326
344− gpu::Batch batch;
345− batch.setPipeline(getDrawPipeline());
346− batch._glDisable(GL_DEPTH_TEST);
347− batch._glDisable(GL_CULL_FACE);
348− batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());
349− batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
350− batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
351− batch.setProjectionTransform(whichCamera.getProjection());
352− batch.setViewTransform(Transform());
353327
328+ //Update and draw the magnifiers
354329 MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
355− const quat& avatarOrientation = myAvatar->getOrientation();
356− quat hmdOrientation = qApp->getCamera()->getHmdRotation();
357− vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition();
358− mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition);
359− batch.setModelTransform(Transform(overlayXfm));
360− drawSphereSection(batch);
330+ const glm::quat& orientation = myAvatar->getOrientation();
331+ // Always display the HMD overlay relative to the camera position but
332+ // remove the HMD pose offset. This results in an overlay that sticks with you
333+ // even in third person mode, but isn't drawn at a fixed distance.
334+ glm::vec3 position = whichCamera.getPosition();
335+ position -= qApp->getCamera()->getHmdPosition();
336+ const float scale = myAvatar->getScale() * _oculusUIRadius;
337+
338+// glm::vec3 eyeOffset = setEyeOffsetPosition;
339+ glMatrixMode(GL_MODELVIEW);
340+ glPushMatrix(); {
341+ glTranslatef(position.x, position.y, position.z);
342+ glm::mat4 rotation = glm::toMat4(orientation);
343+ glMultMatrixf(&rotation[0][0]);
344+ glScalef(scale, scale, scale);
345+ for (int i = 0; i < NUMBER_OF_RETICLES; i++) {
346+
347+ if (_magActive[i]) {
348+ _magSizeMult[i] += MAG_SPEED;
349+ if (_magSizeMult[i] > 1.0f) {
350+ _magSizeMult[i] = 1.0f;
351+ }
352+ } else {
353+ _magSizeMult[i] -= MAG_SPEED;
354+ if (_magSizeMult[i] < 0.0f) {
355+ _magSizeMult[i] = 0.0f;
356+ }
357+ }
358+
359+ if (_magSizeMult[i] > 0.0f) {
360+ //Render magnifier, but dont show border for mouse magnifier
361+ glm::vec2 projection = screenToOverlay(glm::vec2(_reticlePosition[MOUSE].x(),
362+ _reticlePosition[MOUSE].y()));
363+ with_each_texture(_overlays.getTexture(), 0, [&] {
364+ renderMagnifier(projection, _magSizeMult[i], i != MOUSE);
365+ });
366+ }
367+ }
368+
369+ glDepthMask(GL_FALSE);
370+ glDisable(GL_ALPHA_TEST);
371+
372+ static float textureFOV = 0.0f, textureAspectRatio = 1.0f;
373+ if (textureFOV != _textureFov ||
374+ textureAspectRatio != _textureAspectRatio) {
375+ textureFOV = _textureFov;
376+ textureAspectRatio = _textureAspectRatio;
377+
378+ _overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80);
379+ }
361380
381+ with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
382+ _overlays.render();
383+ });
362384
363− bindCursorTexture(batch);
364− auto geometryCache = DependencyManager::get<GeometryCache>();
365− vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize);
366− //Controller Pointers
367− for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
368− PalmData& palm = myAvatar->getHand()->getPalms()[i];
369− if (palm.isActive()) {
370− glm::vec2 polar = getPolarCoordinates(palm);
371− // Convert to quaternion
372− mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));
373− mat4 reticleXfm = overlayXfm * pointerXfm;
374− reticleXfm = glm::scale(reticleXfm, reticleScale);
375− batch.setModelTransform(reticleXfm);
376− // Render reticle at location
377− geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
385+ if (!Application::getInstance()->isMouseHidden()) {
386+ renderPointersOculus();
378387 }
388+ glDepthMask(GL_TRUE);
389+ glDisable(GL_TEXTURE_2D);
390+
391+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
392+ glEnable(GL_LIGHTING);
393+ } glPopMatrix();
394+}
395+
396+// Draws the FBO texture for 3DTV.
397+void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) {
398+ if (_alpha == 0.0f) {
399+ return;
379400 }
401+
402+ MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
403+ const glm::vec3& viewMatrixTranslation = qApp->getViewMatrixTranslation();
404+
405+ glEnable(GL_BLEND);
406+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
407+ glEnable(GL_DEPTH_TEST);
408+ glDisable(GL_LIGHTING);
409+
410+ glMatrixMode(GL_MODELVIEW);
411+
412+ glPushMatrix();
413+ glLoadIdentity();
414+ // Transform to world space
415+ glm::quat rotation = whichCamera.getRotation();
416+ glm::vec3 axis2 = glm::axis(rotation);
417+ glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z);
418+ glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z);
419+
420+ // Translate to the front of the camera
421+ glm::vec3 pos = whichCamera.getPosition();
422+ glm::quat rot = myAvatar->getOrientation();
423+ glm::vec3 axis = glm::axis(rot);
424+
425+ glTranslatef(pos.x, pos.y, pos.z);
426+ glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z);
427+
428+ glm::vec4 overlayColor = {1.0f, 1.0f, 1.0f, _alpha};
429+
430+ //Render
431+ const GLfloat distance = 1.0f;
432+
433+ const GLfloat halfQuadHeight = distance * tan(fov);
434+ const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio;
435+ const GLfloat quadWidth = halfQuadWidth * 2.0f;
436+ const GLfloat quadHeight = halfQuadHeight * 2.0f;
437+
438+ GLfloat x = -halfQuadWidth;
439+ GLfloat y = -halfQuadHeight;
440+ glDisable(GL_DEPTH_TEST);
380441
381− //Mouse Pointer
382− if (_reticleActive[MOUSE]) {
383− glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(),
384− _reticlePosition[MOUSE].y()));
385− mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));
386− mat4 reticleXfm = overlayXfm * pointerXfm;
387− reticleXfm = glm::scale(reticleXfm, reticleScale);
388− batch.setModelTransform(reticleXfm);
389− geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
442+ with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
443+ DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x, y + quadHeight, -distance),
444+ glm::vec3(x + quadWidth, y + quadHeight, -distance),
445+ glm::vec3(x + quadWidth, y, -distance),
446+ glm::vec3(x, y, -distance),
447+ glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f),
448+ glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f),
449+ overlayColor);
450+ });
451+
452+ if (!_crosshairTexture) {
453+ _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() +
454+ "images/sixense-reticle.png");
390455 }
456+
457+ //draw the mouse pointer
458+ glEnable(GL_BLEND);
459+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
460+ glEnable(GL_TEXTURE_2D);
461+ glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
462+ glm::vec2 canvasSize = qApp->getCanvasSize();
463+ const float reticleSize = 40.0f / canvasSize.x * quadWidth;
464+ x -= reticleSize / 2.0f;
465+ y += reticleSize / 2.0f;
466+ const float mouseX = (qApp->getMouseX() / (float)canvasSize.x) * quadWidth;
467+ const float mouseY = (1.0 - (qApp->getMouseY() / (float)canvasSize.y)) * quadHeight;
468+
469+ glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
391470
392− renderArgs->_context->render(batch);
393−}
471+ DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance),
472+ glm::vec3(x + mouseX + reticleSize, y + mouseY, -distance),
473+ glm::vec3(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance),
474+ glm::vec3(x + mouseX, y + mouseY - reticleSize, -distance),
475+ glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f),
476+ glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f),
477+ reticleColor, _reticleQuad);
394478
479+ glEnable(GL_DEPTH_TEST);
480+
481+ glPopMatrix();
482+
483+ glDepthMask(GL_TRUE);
484+ glBindTexture(GL_TEXTURE_2D, 0);
485+ glDisable(GL_TEXTURE_2D);
486+
487+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
488+ glEnable(GL_LIGHTING);
489+}
395490
396491 void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const {
397492 cursorPos *= qApp->getCanvasSize();
@@ -421,6 +516,22 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi · 23 unmodified lines
421516 direction = glm::normalize(intersectionWithUi - origin);
422517 }
423518
519+glm::vec2 getPolarCoordinates(const PalmData& palm) {
520+ MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
521+ auto avatarOrientation = myAvatar->getOrientation();
522+ auto eyePos = myAvatar->getDefaultEyePosition();
523+ glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);
524+ // Direction of the tip relative to the eye
525+ glm::vec3 tipDirection = tip - eyePos;
526+ // orient into avatar space
527+ tipDirection = glm::inverse(avatarOrientation) * tipDirection;
528+ // Normalize for trig functions
529+ tipDirection = glm::normalize(tipDirection);
530+ // Convert to polar coordinates
531+ glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y));
532+ return polar;
533+}
534+
424535 //Caculate the click location using one of the sixense controllers. Scale is not applied
425536 QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
426537 QPoint rv;
@@ -471,9 +582,13 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, · 44 unmodified lines
471582
472583 //Renders optional pointers
473584 void ApplicationOverlay::renderPointers() {
474− //glEnable(GL_TEXTURE_2D);
475− //glEnable(GL_BLEND);
476− //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
585+ //lazily load crosshair texture
586+ if (_crosshairTexture == 0) {
587+ _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
588+ }
589+ glEnable(GL_TEXTURE_2D);
590+ glEnable(GL_BLEND);
591+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
477592
478593 //glActiveTexture(GL_TEXTURE0);
479594 //bindCursorTexture();
@@ -635,6 +750,43 @@ void ApplicationOverlay::renderControllerPointers() { · 155 unmodified lines
635750 }
636751 }
637752
753+void ApplicationOverlay::renderPointersOculus() {
754+
755+ glEnable(GL_BLEND);
756+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
757+ glEnable(GL_TEXTURE_2D);
758+
759+ glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
760+ glDisable(GL_DEPTH_TEST);
761+
762+ glMatrixMode(GL_MODELVIEW);
763+
764+ //Controller Pointers
765+ MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
766+ for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
767+ PalmData& palm = myAvatar->getHand()->getPalms()[i];
768+ if (palm.isActive()) {
769+ glm::vec2 polar = getPolarCoordinates(palm);
770+ // Convert to quaternion
771+ glm::quat orientation = glm::quat(glm::vec3(polar.y, -polar.x, 0.0f));
772+ // Render reticle at location
773+ renderReticle(orientation, _alpha);
774+ }
775+ }
776+
777+ //Mouse Pointer
778+ if (_reticleActive[MOUSE]) {
779+ glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(),
780+ _reticlePosition[MOUSE].y()));
781+ glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f));
782+ renderReticle(orientation, _alpha);
783+ }
784+
785+ glEnable(GL_DEPTH_TEST);
786+ glDisable(GL_TEXTURE_2D);
787+ glDisable(GL_BLEND);
788+}
789+
638790 //Renders a small magnification of the currently bound texture at the coordinates
639791 void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
640792 if (!_magnifier) {
@@ -915,109 +1067,119 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { · 274 unmodified lines
9151067 }
9161068 }
9171069
1070+ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() :
1071+ _vertices(0),
1072+ _indices(0),
1073+ _framebufferObject(NULL),
1074+ _vbo(0, 0) {
1075+}
9181076
919−void ApplicationOverlay::buildHemiVertices(
920− const float fov, const float aspectRatio, const int slices, const int stacks) {
921− static float textureFOV = 0.0f, textureAspectRatio = 1.0f;
922− if (textureFOV == fov && textureAspectRatio == aspectRatio) {
923− return;
1077+ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() {
1078+ cleanupVBO();
1079+ if (_framebufferObject != NULL) {
1080+ delete _framebufferObject;
9241081 }
1082+}
9251083
926− textureFOV = fov;
927− textureAspectRatio = aspectRatio;
928−
929− auto geometryCache = DependencyManager::get<GeometryCache>();
930−
931− _hemiVertices = gpu::BufferPointer(new gpu::Buffer());
932− _hemiIndices = gpu::BufferPointer(new gpu::Buffer());
1084+void ApplicationOverlay::TexturedHemisphere::bind() {
1085+ _framebufferObject->bind();
1086+}
9331087
1088+void ApplicationOverlay::TexturedHemisphere::release() {
1089+ _framebufferObject->release();
1090+}
9341091
1092+void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov,
1093+ const float aspectRatio,
1094+ const int slices,
1095+ const int stacks) {
9351096 if (fov >= PI) {
9361097 qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues";
9371098 }
938−
1099+ // Cleanup old VBO if necessary
1100+ cleanupVBO();
1101+
9391102 //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
9401103
941− vec3 pos;
942− vec2 uv;
1104+ // Compute number of vertices needed
1105+ _vertices = slices * stacks;
1106+
9431107 // Compute vertices positions and texture UV coordinate
944− // Create and write to buffer
1108+ TextureVertex* vertexData = new TextureVertex[_vertices];
1109+ TextureVertex* vertexPtr = &vertexData[0];
9451110 for (int i = 0; i < stacks; i++) {
946− uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f
1111+ float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f
9471112 // abs(theta) <= fov / 2.0f
948− float pitch = -fov * (uv.y - 0.5f);
1113+ float pitch = -fov * (stacksRatio - 0.5f);
1114+
9491115 for (int j = 0; j < slices; j++) {
950− uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f
1116+ float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f
9511117 // abs(phi) <= fov * aspectRatio / 2.0f
952− float yaw = -fov * aspectRatio * (uv.x - 0.5f);
953− pos = getPoint(yaw, pitch);
954− static const vec4 color(1);
955− _hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos);
956− _hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv);
957− _hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color);
1118+ float yaw = -fov * aspectRatio * (slicesRatio - 0.5f);
1119+
1120+ vertexPtr->position = getPoint(yaw, pitch);
1121+ vertexPtr->uv.x = slicesRatio;
1122+ vertexPtr->uv.y = stacksRatio;
1123+ vertexPtr++;
9581124 }
9591125 }
1126+ // Create and write to buffer
1127+ glGenBuffers(1, &_vbo.first);
1128+ glBindBuffer(GL_ARRAY_BUFFER, _vbo.first);
1129+ static const int BYTES_PER_VERTEX = sizeof(TextureVertex);
1130+ glBufferData(GL_ARRAY_BUFFER, _vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
1131+ delete[] vertexData;
1132+
9601133
9611134 // Compute number of indices needed
9621135 static const int VERTEX_PER_TRANGLE = 3;
9631136 static const int TRIANGLE_PER_RECTANGLE = 2;
9641137 int numberOfRectangles = (slices - 1) * (stacks - 1);
965− _hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
1138+ _indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
9661139
9671140 // Compute indices order
968− std::vector<GLushort> indices;
1141+ GLushort* indexData = new GLushort[_indices];
1142+ GLushort* indexPtr = indexData;
9691143 for (int i = 0; i < stacks - 1; i++) {
9701144 for (int j = 0; j < slices - 1; j++) {
9711145 GLushort bottomLeftIndex = i * slices + j;
9721146 GLushort bottomRightIndex = bottomLeftIndex + 1;
9731147 GLushort topLeftIndex = bottomLeftIndex + slices;
9741148 GLushort topRightIndex = topLeftIndex + 1;
975− // FIXME make a z-order curve for better vertex cache locality
976− indices.push_back(topLeftIndex);
977− indices.push_back(bottomLeftIndex);
978− indices.push_back(topRightIndex);
979−
980− indices.push_back(topRightIndex);
981− indices.push_back(bottomLeftIndex);
982− indices.push_back(bottomRightIndex);
1149+
1150+ *(indexPtr++) = topLeftIndex;
1151+ *(indexPtr++) = bottomLeftIndex;
1152+ *(indexPtr++) = topRightIndex;
1153+
1154+ *(indexPtr++) = topRightIndex;
1155+ *(indexPtr++) = bottomLeftIndex;
1156+ *(indexPtr++) = bottomRightIndex;
9831157 }
9841158 }
985− _hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]);
986−}
987−
988−
989−void ApplicationOverlay::drawSphereSection(gpu::Batch& batch) {
990− buildHemiVertices(_textureFov, _textureAspectRatio, 80, 80);
991− static const int VERTEX_DATA_SLOT = 0;
992− static const int TEXTURE_DATA_SLOT = 1;
993− static const int COLOR_DATA_SLOT = 2;
994− gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone
995− streamFormat->setAttribute(gpu::Stream::POSITION, VERTEX_DATA_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
996− streamFormat->setAttribute(gpu::Stream::TEXCOORD, TEXTURE_DATA_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
997− streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_DATA_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA));
998− batch.setInputFormat(streamFormat);
999−
1000− static const int VERTEX_STRIDE = sizeof(vec3) + sizeof(vec2) + sizeof(vec4);
1001− gpu::BufferView posView(_hemiVertices, 0, _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
1002− gpu::BufferView uvView(_hemiVertices, sizeof(vec3), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element);
1003− gpu::BufferView colView(_hemiVertices, sizeof(vec3) + sizeof(vec2), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
1004− batch.setInputBuffer(VERTEX_DATA_SLOT, posView);
1005− batch.setInputBuffer(TEXTURE_DATA_SLOT, uvView);
1006− batch.setInputBuffer(COLOR_DATA_SLOT, colView);
1007− batch.setIndexBuffer(gpu::UINT16, _hemiIndices, 0);
1008− batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount);
1159+ // Create and write to buffer
1160+ glGenBuffers(1, &_vbo.second);
1161+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
1162+ static const int BYTES_PER_INDEX = sizeof(GLushort);
1163+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
1164+ delete[] indexData;
10091165 }
10101166
1011−
1012−GLuint ApplicationOverlay::getOverlayTexture() {
1013− return _framebufferObject->texture();
1167+void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
1168+ if (_vbo.first != 0) {
1169+ glDeleteBuffers(1, &_vbo.first);
1170+ _vbo.first = 0;
1171+ }
1172+ if (_vbo.second != 0) {
1173+ glDeleteBuffers(1, &_vbo.second);
1174+ _vbo.second = 0;
1175+ }
10141176 }
10151177
1016−void ApplicationOverlay::buildFramebufferObject() {
1178+void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
10171179 auto canvasSize = qApp->getCanvasSize();
10181180 QSize fboSize = QSize(canvasSize.x, canvasSize.y);
10191181 if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) {
1020− // Already built
1182+ // Already build
10211183 return;
10221184 }
10231185
@@ -1026,7 +1188,7 @@ void ApplicationOverlay::buildFramebufferObject() { · 2 unmodified lines
10261188 }
10271189
10281190 _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);
1029− glBindTexture(GL_TEXTURE_2D, getOverlayTexture());
1191+ glBindTexture(GL_TEXTURE_2D, getTexture());
10301192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10311193 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
10321194 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
@@ -1036,6 +1198,38 @@ void ApplicationOverlay::buildFramebufferObject() { · 3 unmodified lines
10361198 glBindTexture(GL_TEXTURE_2D, 0);
10371199 }
10381200
1201+//Renders a hemisphere with texture coordinates.
1202+void ApplicationOverlay::TexturedHemisphere::render() {
1203+ if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) {
1204+ qDebug() << "TexturedHemisphere::render(): Incorrect initialisation";
1205+ return;
1206+ }
1207+
1208+ glBindBuffer(GL_ARRAY_BUFFER, _vbo.first);
1209+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
1210+
1211+ glEnableClientState(GL_VERTEX_ARRAY);
1212+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1213+
1214+ static const int STRIDE = sizeof(TextureVertex);
1215+ static const void* VERTEX_POINTER = 0;
1216+ static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3);
1217+ glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER);
1218+ glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER);
1219+
1220+ glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0);
1221+
1222+ glDisableClientState(GL_VERTEX_ARRAY);
1223+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1224+
1225+ glBindBuffer(GL_ARRAY_BUFFER, 0);
1226+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1227+}
1228+
1229+GLuint ApplicationOverlay::TexturedHemisphere::getTexture() {
1230+ return _framebufferObject->texture();
1231+}
1232+
10391233 glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) {
10401234 glm::vec2 result;
10411235 // Compute yaw