This reverts commit 4d18bd7cec710b5188d1f6ad5c58010117d7a77d, reversing changes made to 24fda9a7336e4eff1d1310dd3359dd6cbbb6acb5.
Showing the changes to interface/src/ui/ApplicationOverlay.cpp (1 of 10 files). Show all
Unified · Split
| @@ -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 windows | 36 | // Used to animate the magnification windows |
| 43 | const float MAG_SPEED = 0.08f; | 37 | const 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 | ||
| 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 | |||
| 123 | ApplicationOverlay::ApplicationOverlay() : | 138 | ApplicationOverlay::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 UI | 195 | //Handle fading and deactivation/activation of UI |
| 182 | 196 | ||
| 183 | // Render 2D overlay | 197 | // 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 | ||
| 244 | gpu::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))); | 243 | template <typename F> |
| 247 | auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); | 244 | void 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 | |||
| 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); | ||
| 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 screen | 259 | // Draws the FBO texture for the screen |
| 277 | void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { | 260 | void 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 pointer | 279 | 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 | |||
| 316 | static gpu::BufferPointer _hemiVertices; | ||
| 317 | static gpu::BufferPointer _hemiIndices; | ||
| 318 | static int _hemiIndexCount{ 0 }; | ||
| 319 | 288 | ||
| 320 | glm::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 eye | 294 | vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); |
| 326 | glm::vec3 tipDirection = tip - eyePos; | 295 | mousePosition /= canvasSize; |
| 327 | // orient into avatar space | 296 | mousePosition *= 2.0f; |
| 328 | tipDirection = glm::inverse(avatarOrientation) * tipDirection; | 297 | mousePosition -= 1.0f; |
| 329 | // Normalize for trig functions | 298 | mousePosition.y *= -1.0f; |
| 330 | tipDirection = glm::normalize(tipDirection); | 299 | |
| 331 | // Convert to polar coordinates | 300 | 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. |
| 337 | void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { | 314 | void 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. | ||
| 397 | void 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 Pointer | 442 | 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 | ||
| 396 | void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { | 491 | void 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 | ||
| 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 | |||
| 424 | //Caculate the click location using one of the sixense controllers. Scale is not applied | 535 | //Caculate the click location using one of the sixense controllers. Scale is not applied |
| 425 | QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { | 536 | QPoint 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 pointers | 583 | //Renders optional pointers |
| 473 | void ApplicationOverlay::renderPointers() { | 584 | void 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 | ||
| 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 | |||
| 638 | //Renders a small magnification of the currently bound texture at the coordinates | 790 | //Renders a small magnification of the currently bound texture at the coordinates |
| 639 | void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) { | 791 | void 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 | ||
| 1070 | ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : | ||
| 1071 | _vertices(0), | ||
| 1072 | _indices(0), | ||
| 1073 | _framebufferObject(NULL), | ||
| 1074 | _vbo(0, 0) { | ||
| 1075 | } | ||
| 918 | 1076 | ||
| 919 | void ApplicationOverlay::buildHemiVertices( | 1077 | ApplicationOverlay::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; | 1084 | void 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 | ||
| 1088 | void ApplicationOverlay::TexturedHemisphere::release() { | ||
| 1089 | _framebufferObject->release(); | ||
| 1090 | } | ||
| 934 | 1091 | ||
| 1092 | void 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.htm | 1102 | //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 coordinate | 1107 | // Compute vertices positions and texture UV coordinate |
| 944 | // Create and write to buffer | 1108 | 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.0f | 1111 | float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f |
| 947 | // abs(theta) <= fov / 2.0f | 1112 | // 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.0f | 1116 | float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f |
| 951 | // abs(phi) <= fov * aspectRatio / 2.0f | 1117 | // 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 needed | 1134 | // 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 order | 1140 | // 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 locality | 1149 | |
| 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); | |
| 989 | void 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 | 1167 | void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { | |
| 1012 | GLuint 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 | ||
| 1016 | void ApplicationOverlay::buildFramebufferObject() { | 1178 | void 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 built | 1182 | // 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. | ||
| 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 | |||
| 1039 | glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { | 1233 | glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { |
| 1040 | glm::vec2 result; | 1234 | glm::vec2 result; |
| 1041 | // Compute yaw | 1235 | // Compute yaw |