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
14#include <QOpenGLFramebufferObject>14#include <QOpenGLFramebufferObject>
15#include <QOpenGLTexture>15#include <QOpenGLTexture>
16 16
17#include <glm/gtc/type_ptr.hpp>
18
19#include <avatar/AvatarManager.h>17#include <avatar/AvatarManager.h>
20#include <DeferredLightingEffect.h>
21#include <GLMHelpers.h>18#include <GLMHelpers.h>
19#include <PathUtils.h>
22#include <gpu/GLBackend.h>20#include <gpu/GLBackend.h>
23#include <GLMHelpers.h>21#include <GLMHelpers.h>
24#include <OffscreenUi.h>
25#include <CursorManager.h>
26#include <PerfStat.h>22#include <PerfStat.h>
23#include <OffscreenUi.h>
27 24
28#include "AudioClient.h"25#include "AudioClient.h"
29#include "audio/AudioIOStatsRenderer.h"26#include "audio/AudioIOStatsRenderer.h"
@@ -36,9 +33,6 @@ · 6 unmodified lines
36#include "Util.h"33#include "Util.h"
37#include "ui/Stats.h"34#include "ui/Stats.h"
38 35
39#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
40#include "../../libraries/render-utils/standardDrawTexture_frag.h"
41
42// Used to animate the magnification windows36// Used to animate the magnification windows
43const float MAG_SPEED = 0.08f;37const float MAG_SPEED = 0.08f;
44 38
@@ -120,6 +114,27 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, · 75 unmodified lines
120 }114 }
121}115}
122 116
117void 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
123ApplicationOverlay::ApplicationOverlay() :138ApplicationOverlay::ApplicationOverlay() :
124 _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)),139 _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)),
125 _textureAspectRatio(1.0f),140 _textureAspectRatio(1.0f),
@@ -133,8 +148,7 @@ ApplicationOverlay::ApplicationOverlay() : · 7 unmodified lines
133 _previousMagnifierBottomLeft(),148 _previousMagnifierBottomLeft(),
134 _previousMagnifierBottomRight(),149 _previousMagnifierBottomRight(),
135 _previousMagnifierTopLeft(),150 _previousMagnifierTopLeft(),
136 _previousMagnifierTopRight(),151 _previousMagnifierTopRight()
137 _framebufferObject(nullptr)
138{152{
139 memset(_reticleActive, 0, sizeof(_reticleActive));153 memset(_reticleActive, 0, sizeof(_reticleActive));
140 memset(_magActive, 0, sizeof(_reticleActive));154 memset(_magActive, 0, sizeof(_reticleActive));
@@ -181,17 +195,16 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { · 40 unmodified lines
181 //Handle fading and deactivation/activation of UI195 //Handle fading and deactivation/activation of UI
182 196
183 // Render 2D overlay197 // Render 2D overlay
198 glMatrixMode(GL_PROJECTION);
184 glDisable(GL_DEPTH_TEST);199 glDisable(GL_DEPTH_TEST);
185 glDisable(GL_LIGHTING);200 glDisable(GL_LIGHTING);
186 glEnable(GL_BLEND);201 glEnable(GL_BLEND);
187 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);202 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
188 buildFramebufferObject();203 _overlays.buildFramebufferObject();
189 204 _overlays.bind();
190 _framebufferObject->bind();
191 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
192 glViewport(0, 0, size.x, size.y);206 glViewport(0, 0, size.x, size.y);
193 207
194 glMatrixMode(GL_PROJECTION);
195 glPushMatrix(); {208 glPushMatrix(); {
196 const float NEAR_CLIP = -10000;209 const float NEAR_CLIP = -10000;
197 const float FAR_CLIP = 10000;210 const float FAR_CLIP = 10000;
@@ -213,22 +226,6 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { · 15 unmodified lines
213 renderPointers();226 renderPointers();
214 227
215 renderDomainConnectionStatusBorder();228 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
232 229
233 glMatrixMode(GL_PROJECTION);230 glMatrixMode(GL_PROJECTION);
234 } glPopMatrix();231 } glPopMatrix();
@@ -238,160 +235,258 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { · 3 unmodified lines
238 glEnable(GL_LIGHTING);235 glEnable(GL_LIGHTING);
239 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);236 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
240 237
241 _framebufferObject->release();238 _overlays.release();
242}239}
243 240
244gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() {241// A quick and dirty solution for compositing the old overlay
245 if (!_standardDrawPipeline) {242// texture with the new one
246 auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)));243template <typename F>
247 auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag)));244void with_each_texture(GLuint firstPassTexture, GLuint secondPassTexture, F f) {
248 auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));245 glEnable(GL_TEXTURE_2D);
249 gpu::Shader::makeProgram((*program));246 glActiveTexture(GL_TEXTURE0);
250 247 if (firstPassTexture) {
251 auto state = gpu::StatePointer(new gpu::State());248 glBindTexture(GL_TEXTURE_2D, firstPassTexture);
252 249 f();
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));
257 }250 }
258 251 if (secondPassTexture) {
259 return _standardDrawPipeline;252 glBindTexture(GL_TEXTURE_2D, secondPassTexture);
260}253 f();
261
262void 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);
270 }254 }
271 batch.setUniformTexture(0, _cursors[iconId]);255 glBindTexture(GL_TEXTURE_2D, 0);
256 glDisable(GL_TEXTURE_2D);
272}257}
273 258
274#define CURSOR_PIXEL_SIZE 32.0f
275
276// Draws the FBO texture for the screen259// Draws the FBO texture for the screen
277void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) {260void ApplicationOverlay::displayOverlayTexture() {
278 if (_alpha == 0.0f) {261 if (_alpha == 0.0f) {
279 return;262 return;
280 }263 }
281 264 glMatrixMode(GL_PROJECTION);
282 renderArgs->_context->syncCache();265 glPushMatrix(); {
283 266 glLoadIdentity();
284 gpu::Batch batch;267 glDisable(GL_DEPTH_TEST);
285 Transform model;268 glDisable(GL_LIGHTING);
286 //DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true);269 glEnable(GL_BLEND);
287 batch.setPipeline(getDrawPipeline());270 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
288 batch.setModelTransform(Transform());271 glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height());
289 batch.setProjectionTransform(mat4());272
290 batch.setViewTransform(model);273 static const glm::vec2 topLeft(-1, 1);
291 batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());274 static const glm::vec2 bottomRight(1, -1);
292 batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);275 static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
293 batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);276 static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
294 DependencyManager::get<GeometryCache>()->renderUnitQuad(batch, vec4(vec3(1), _alpha));277 with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
295 278 DependencyManager::get<GeometryCache>()->renderQuad(
296 //draw the mouse pointer279 topLeft, bottomRight,
297 glm::vec2 canvasSize = qApp->getCanvasSize();280 texCoordTopLeft, texCoordBottomRight,
298 281 glm::vec4(1.0f, 1.0f, 1.0f, _alpha));
299 // Get the mouse coordinates and convert to NDC [-1, 1]282 });
300 vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY());283
301 mousePosition /= canvasSize;284 if (!_crosshairTexture) {
302 mousePosition *= 2.0f;285 _crosshairTexture = DependencyManager::get<TextureCache>()->
303 mousePosition -= 1.0f;286 getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
304 mousePosition.y *= -1.0f;287 }
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
316static gpu::BufferPointer _hemiVertices;
317static gpu::BufferPointer _hemiIndices;
318static int _hemiIndexCount{ 0 };
319 288
320glm::vec2 getPolarCoordinates(const PalmData& palm) {289 //draw the mouse pointer
321 MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();290 glm::vec2 canvasSize = qApp->getCanvasSize();
322 auto avatarOrientation = myAvatar->getOrientation();291 glm::vec2 mouseSize = 32.0f / canvasSize;
323 auto eyePos = myAvatar->getDefaultEyePosition();292 auto mouseTopLeft = topLeft * mouseSize;
324 glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);293 auto mouseBottomRight = bottomRight * mouseSize;
325 // Direction of the tip relative to the eye294 vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY());
326 glm::vec3 tipDirection = tip - eyePos;295 mousePosition /= canvasSize;
327 // orient into avatar space296 mousePosition *= 2.0f;
328 tipDirection = glm::inverse(avatarOrientation) * tipDirection;297 mousePosition -= 1.0f;
329 // Normalize for trig functions298 mousePosition.y *= -1.0f;
330 tipDirection = glm::normalize(tipDirection);299
331 // Convert to polar coordinates300 glEnable(GL_TEXTURE_2D);
332 glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y));301 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
333 return polar;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();
334}311}
335 312
336// Draws the FBO texture for Oculus rift.313// Draws the FBO texture for Oculus rift.
337void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) {314void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) {
338 if (_alpha == 0.0f) {315 if (_alpha == 0.0f) {
339 return;316 return;
340 }317 }
341 318
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);
343 326
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());
353 327
328 //Update and draw the magnifiers
354 MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();329 MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
355 const quat& avatarOrientation = myAvatar->getOrientation();330 const glm::quat& orientation = myAvatar->getOrientation();
356 quat hmdOrientation = qApp->getCamera()->getHmdRotation();331 // Always display the HMD overlay relative to the camera position but
357 vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition();332 // remove the HMD pose offset. This results in an overlay that sticks with you
358 mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition);333 // even in third person mode, but isn't drawn at a fixed distance.
359 batch.setModelTransform(Transform(overlayXfm));334 glm::vec3 position = whichCamera.getPosition();
360 drawSphereSection(batch);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 }
361 380
381 with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
382 _overlays.render();
383 });
362 384
363 bindCursorTexture(batch);385 if (!Application::getInstance()->isMouseHidden()) {
364 auto geometryCache = DependencyManager::get<GeometryCache>();386 renderPointersOculus();
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);
378 }387 }
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.
397void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) {
398 if (_alpha == 0.0f) {
399 return;
379 }400 }
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);
380 441
381 //Mouse Pointer442 with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
382 if (_reticleActive[MOUSE]) {443 DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x, y + quadHeight, -distance),
383 glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(),444 glm::vec3(x + quadWidth, y + quadHeight, -distance),
384 _reticlePosition[MOUSE].y()));445 glm::vec3(x + quadWidth, y, -distance),
385 mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));446 glm::vec3(x, y, -distance),
386 mat4 reticleXfm = overlayXfm * pointerXfm;447 glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f),
387 reticleXfm = glm::scale(reticleXfm, reticleScale);448 glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f),
388 batch.setModelTransform(reticleXfm);449 overlayColor);
389 geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);450 });
451
452 if (!_crosshairTexture) {
453 _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() +
454 "images/sixense-reticle.png");
390 }455 }
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 };
391 470
392 renderArgs->_context->render(batch);471 DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance),
393}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);
394 478
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}
395 490
396void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const {491void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const {
397 cursorPos *= qApp->getCanvasSize();492 cursorPos *= qApp->getCanvasSize();
@@ -421,6 +516,22 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi · 23 unmodified lines
421 direction = glm::normalize(intersectionWithUi - origin);516 direction = glm::normalize(intersectionWithUi - origin);
422}517}
423 518
519glm::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
424//Caculate the click location using one of the sixense controllers. Scale is not applied535//Caculate the click location using one of the sixense controllers. Scale is not applied
425QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {536QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
426 QPoint rv;537 QPoint rv;
@@ -471,9 +582,13 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, · 44 unmodified lines
471 582
472//Renders optional pointers583//Renders optional pointers
473void ApplicationOverlay::renderPointers() {584void ApplicationOverlay::renderPointers() {
474 //glEnable(GL_TEXTURE_2D);585 //lazily load crosshair texture
475 //glEnable(GL_BLEND);586 if (_crosshairTexture == 0) {
476 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);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);
477 592
478 //glActiveTexture(GL_TEXTURE0);593 //glActiveTexture(GL_TEXTURE0);
479 //bindCursorTexture();594 //bindCursorTexture();
@@ -635,6 +750,43 @@ void ApplicationOverlay::renderControllerPointers() { · 155 unmodified lines
635 }750 }
636}751}
637 752
753void 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
638//Renders a small magnification of the currently bound texture at the coordinates790//Renders a small magnification of the currently bound texture at the coordinates
639void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {791void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
640 if (!_magnifier) {792 if (!_magnifier) {
@@ -915,109 +1067,119 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { · 274 unmodified lines
915 }1067 }
916}1068}
917 1069
1070ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() :
1071 _vertices(0),
1072 _indices(0),
1073 _framebufferObject(NULL),
1074 _vbo(0, 0) {
1075}
918 1076
919void ApplicationOverlay::buildHemiVertices(1077ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() {
920 const float fov, const float aspectRatio, const int slices, const int stacks) {1078 cleanupVBO();
921 static float textureFOV = 0.0f, textureAspectRatio = 1.0f;1079 if (_framebufferObject != NULL) {
922 if (textureFOV == fov && textureAspectRatio == aspectRatio) {1080 delete _framebufferObject;
923 return;
924 }1081 }
1082}
925 1083
926 textureFOV = fov;1084void ApplicationOverlay::TexturedHemisphere::bind() {
927 textureAspectRatio = aspectRatio;1085 _framebufferObject->bind();
928 1086}
929 auto geometryCache = DependencyManager::get<GeometryCache>();
930
931 _hemiVertices = gpu::BufferPointer(new gpu::Buffer());
932 _hemiIndices = gpu::BufferPointer(new gpu::Buffer());
933 1087
1088void ApplicationOverlay::TexturedHemisphere::release() {
1089 _framebufferObject->release();
1090}
934 1091
1092void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov,
1093 const float aspectRatio,
1094 const int slices,
1095 const int stacks) {
935 if (fov >= PI) {1096 if (fov >= PI) {
936 qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues";1097 qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues";
937 }1098 }
938 1099 // Cleanup old VBO if necessary
1100 cleanupVBO();
1101
939 //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm1102 //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
940 1103
941 vec3 pos; 1104 // Compute number of vertices needed
942 vec2 uv;1105 _vertices = slices * stacks;
1106
943 // Compute vertices positions and texture UV coordinate1107 // Compute vertices positions and texture UV coordinate
944 // Create and write to buffer1108 TextureVertex* vertexData = new TextureVertex[_vertices];
1109 TextureVertex* vertexPtr = &vertexData[0];
945 for (int i = 0; i < stacks; i++) {1110 for (int i = 0; i < stacks; i++) {
946 uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f1111 float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f
947 // abs(theta) <= fov / 2.0f1112 // abs(theta) <= fov / 2.0f
948 float pitch = -fov * (uv.y - 0.5f);1113 float pitch = -fov * (stacksRatio - 0.5f);
1114
949 for (int j = 0; j < slices; j++) {1115 for (int j = 0; j < slices; j++) {
950 uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f1116 float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f
951 // abs(phi) <= fov * aspectRatio / 2.0f1117 // abs(phi) <= fov * aspectRatio / 2.0f
952 float yaw = -fov * aspectRatio * (uv.x - 0.5f);1118 float yaw = -fov * aspectRatio * (slicesRatio - 0.5f);
953 pos = getPoint(yaw, pitch);1119
954 static const vec4 color(1);1120 vertexPtr->position = getPoint(yaw, pitch);
955 _hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos);1121 vertexPtr->uv.x = slicesRatio;
956 _hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv);1122 vertexPtr->uv.y = stacksRatio;
957 _hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color);1123 vertexPtr++;
958 }1124 }
959 }1125 }
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
960 1133
961 // Compute number of indices needed1134 // Compute number of indices needed
962 static const int VERTEX_PER_TRANGLE = 3;1135 static const int VERTEX_PER_TRANGLE = 3;
963 static const int TRIANGLE_PER_RECTANGLE = 2;1136 static const int TRIANGLE_PER_RECTANGLE = 2;
964 int numberOfRectangles = (slices - 1) * (stacks - 1);1137 int numberOfRectangles = (slices - 1) * (stacks - 1);
965 _hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;1138 _indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
966 1139
967 // Compute indices order1140 // Compute indices order
968 std::vector<GLushort> indices;1141 GLushort* indexData = new GLushort[_indices];
1142 GLushort* indexPtr = indexData;
969 for (int i = 0; i < stacks - 1; i++) {1143 for (int i = 0; i < stacks - 1; i++) {
970 for (int j = 0; j < slices - 1; j++) {1144 for (int j = 0; j < slices - 1; j++) {
971 GLushort bottomLeftIndex = i * slices + j;1145 GLushort bottomLeftIndex = i * slices + j;
972 GLushort bottomRightIndex = bottomLeftIndex + 1;1146 GLushort bottomRightIndex = bottomLeftIndex + 1;
973 GLushort topLeftIndex = bottomLeftIndex + slices;1147 GLushort topLeftIndex = bottomLeftIndex + slices;
974 GLushort topRightIndex = topLeftIndex + 1;1148 GLushort topRightIndex = topLeftIndex + 1;
975 // FIXME make a z-order curve for better vertex cache locality1149
976 indices.push_back(topLeftIndex);1150 *(indexPtr++) = topLeftIndex;
977 indices.push_back(bottomLeftIndex);1151 *(indexPtr++) = bottomLeftIndex;
978 indices.push_back(topRightIndex);1152 *(indexPtr++) = topRightIndex;
979 1153
980 indices.push_back(topRightIndex);1154 *(indexPtr++) = topRightIndex;
981 indices.push_back(bottomLeftIndex);1155 *(indexPtr++) = bottomLeftIndex;
982 indices.push_back(bottomRightIndex);1156 *(indexPtr++) = bottomRightIndex;
983 }1157 }
984 }1158 }
985 _hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]);1159 // Create and write to buffer
986}1160 glGenBuffers(1, &_vbo.second);
987 1161 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
988 1162 static const int BYTES_PER_INDEX = sizeof(GLushort);
989void ApplicationOverlay::drawSphereSection(gpu::Batch& batch) {1163 glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
990 buildHemiVertices(_textureFov, _textureAspectRatio, 80, 80);1164 delete[] indexData;
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);
1009}1165}
1010 1166
1011 1167void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
1012GLuint ApplicationOverlay::getOverlayTexture() {1168 if (_vbo.first != 0) {
1013 return _framebufferObject->texture();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 }
1014}1176}
1015 1177
1016void ApplicationOverlay::buildFramebufferObject() {1178void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
1017 auto canvasSize = qApp->getCanvasSize();1179 auto canvasSize = qApp->getCanvasSize();
1018 QSize fboSize = QSize(canvasSize.x, canvasSize.y);1180 QSize fboSize = QSize(canvasSize.x, canvasSize.y);
1019 if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) {1181 if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) {
1020 // Already built1182 // Already build
1021 return;1183 return;
1022 }1184 }
1023 1185
@@ -1026,7 +1188,7 @@ void ApplicationOverlay::buildFramebufferObject() { · 2 unmodified lines
1026 }1188 }
1027 1189
1028 _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);1190 _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);
1029 glBindTexture(GL_TEXTURE_2D, getOverlayTexture());1191 glBindTexture(GL_TEXTURE_2D, getTexture());
1030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1031 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1193 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1032 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);1194 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
@@ -1036,6 +1198,38 @@ void ApplicationOverlay::buildFramebufferObject() { · 3 unmodified lines
1036 glBindTexture(GL_TEXTURE_2D, 0);1198 glBindTexture(GL_TEXTURE_2D, 0);
1037}1199}
1038 1200
1201//Renders a hemisphere with texture coordinates.
1202void 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
1229GLuint ApplicationOverlay::TexturedHemisphere::getTexture() {
1230 return _framebufferObject->texture();
1231}
1232
1039glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) {1233glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) {
1040 glm::vec2 result;1234 glm::vec2 result;
1041 // Compute yaw1235 // Compute yaw