mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 08:33:12 +02:00
TexturedHemisphere class
This commit is contained in:
parent
3c5f33f0ac
commit
bf21376c90
2 changed files with 342 additions and 304 deletions
|
@ -27,20 +27,16 @@ const float MAG_SPEED = 0.08f;
|
|||
|
||||
const quint64 MSECS_TO_USECS = 1000ULL;
|
||||
|
||||
// Fast helper functions
|
||||
inline float max(float a, float b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f };
|
||||
const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f };
|
||||
|
||||
inline float min(float a, float b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f };
|
||||
const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f;
|
||||
|
||||
ApplicationOverlay::ApplicationOverlay() :
|
||||
_framebufferObject(NULL),
|
||||
_textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE),
|
||||
ApplicationOverlay::ApplicationOverlay() :
|
||||
_textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)),
|
||||
_alpha(1.0f),
|
||||
_oculusuiRadius(1.0f),
|
||||
_oculusUIRadius(1.0f),
|
||||
_crosshairTexture(0) {
|
||||
|
||||
memset(_reticleActive, 0, sizeof(_reticleActive));
|
||||
|
@ -49,23 +45,14 @@ ApplicationOverlay::ApplicationOverlay() :
|
|||
}
|
||||
|
||||
ApplicationOverlay::~ApplicationOverlay() {
|
||||
if (_framebufferObject != NULL) {
|
||||
delete _framebufferObject;
|
||||
}
|
||||
}
|
||||
|
||||
const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f };
|
||||
const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f };
|
||||
|
||||
const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f };
|
||||
const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f;
|
||||
|
||||
// Renders the overlays either to a texture or to the screen
|
||||
void ApplicationOverlay::renderOverlay(bool renderToTexture) {
|
||||
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
|
||||
|
||||
_textureFov = Menu::getInstance()->getOculusUIAngularSize() * RADIANS_PER_DEGREE;
|
||||
_textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize());
|
||||
|
||||
Application* application = Application::getInstance();
|
||||
|
||||
|
@ -86,42 +73,39 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) {
|
|||
}
|
||||
}
|
||||
|
||||
if (renderToTexture) {
|
||||
getFramebufferObject()->bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
// Render 2D overlay
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, glWidget->width(), glWidget->height(), 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
renderAudioMeter();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) {
|
||||
myAvatar->renderHeadMouse(glWidget->width(), glWidget->height());
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if (renderToTexture) {
|
||||
_overlays.bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
renderStatsAndLogs();
|
||||
|
||||
// give external parties a change to hook in
|
||||
emit application->renderingOverlay();
|
||||
|
||||
overlays.render2D();
|
||||
|
||||
renderPointers();
|
||||
|
||||
renderDomainConnectionStatusBorder();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
glPushMatrix(); {
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, glWidget->width(), glWidget->height(), 0);
|
||||
|
||||
renderAudioMeter();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) {
|
||||
myAvatar->renderHeadMouse(glWidget->width(), glWidget->height());
|
||||
}
|
||||
|
||||
renderStatsAndLogs();
|
||||
|
||||
// give external parties a change to hook in
|
||||
emit application->renderingOverlay();
|
||||
|
||||
overlays.render2D();
|
||||
|
||||
renderPointers();
|
||||
|
||||
renderDomainConnectionStatusBorder();
|
||||
} glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
@ -129,7 +113,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) {
|
|||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
|
||||
if (renderToTexture) {
|
||||
getFramebufferObject()->release();
|
||||
_overlays.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,7 +543,6 @@ void ApplicationOverlay::renderPointers() {
|
|||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderControllerPointers() {
|
||||
|
@ -844,118 +827,6 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
|
|||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
//Renders a small magnification of the currently bound texture at the coordinates
|
||||
void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const
|
||||
{
|
||||
Application* application = Application::getInstance();
|
||||
GLCanvas* glWidget = application->getGLWidget();
|
||||
|
||||
const int widgetWidth = glWidget->width();
|
||||
const int widgetHeight = glWidget->height();
|
||||
|
||||
const float magnifyWidth = MAGNIFY_WIDTH * sizeMult;
|
||||
const float magnifyHeight = MAGNIFY_HEIGHT * sizeMult;
|
||||
|
||||
mouseX -= magnifyWidth / 2;
|
||||
mouseY -= magnifyHeight / 2;
|
||||
|
||||
float newWidth = magnifyWidth * MAGNIFY_MULT;
|
||||
float newHeight = magnifyHeight * MAGNIFY_MULT;
|
||||
|
||||
// Magnification Texture Coordinates
|
||||
float magnifyULeft = mouseX / (float)widgetWidth;
|
||||
float magnifyURight = (mouseX + magnifyWidth) / (float)widgetWidth;
|
||||
float magnifyVBottom = 1.0f - mouseY / (float)widgetHeight;
|
||||
float magnifyVTop = 1.0f - (mouseY + magnifyHeight) / (float)widgetHeight;
|
||||
|
||||
// Coordinates of magnification overlay
|
||||
float newMouseX = (mouseX + magnifyWidth / 2) - newWidth / 2.0f;
|
||||
float newMouseY = (mouseY + magnifyHeight / 2) + newHeight / 2.0f;
|
||||
|
||||
// Get position on hemisphere using angle
|
||||
|
||||
//Get new UV coordinates from our magnification window
|
||||
float newULeft = newMouseX / widgetWidth;
|
||||
float newURight = (newMouseX + newWidth) / widgetWidth;
|
||||
float newVBottom = 1.0 - newMouseY / widgetHeight;
|
||||
float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight;
|
||||
|
||||
// Project our position onto the hemisphere using the UV coordinates
|
||||
float radius = _oculusuiRadius * application->getAvatar()->getScale();
|
||||
float radius2 = radius * radius;
|
||||
|
||||
float lX = radius * sin((newULeft - 0.5f) * _textureFov);
|
||||
float rX = radius * sin((newURight - 0.5f) * _textureFov);
|
||||
float bY = radius * sin((newVBottom - 0.5f) * _textureFov);
|
||||
float tY = radius * sin((newVTop - 0.5f) * _textureFov);
|
||||
|
||||
float blZ, tlZ, brZ, trZ;
|
||||
|
||||
float dist;
|
||||
float discriminant;
|
||||
|
||||
//Bottom Left
|
||||
dist = sqrt(lX * lX + bY * bY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
blZ = sqrt(discriminant);
|
||||
} else {
|
||||
blZ = 0;
|
||||
}
|
||||
//Top Left
|
||||
dist = sqrt(lX * lX + tY * tY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
tlZ = sqrt(discriminant);
|
||||
} else {
|
||||
tlZ = 0;
|
||||
}
|
||||
//Bottom Right
|
||||
dist = sqrt(rX * rX + bY * bY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
brZ = sqrt(discriminant);
|
||||
} else {
|
||||
brZ = 0;
|
||||
}
|
||||
//Top Right
|
||||
dist = sqrt(rX * rX + tY * tY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
trZ = sqrt(discriminant);
|
||||
} else {
|
||||
trZ = 0;
|
||||
}
|
||||
|
||||
if (showBorder) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glLineWidth(1.0f);
|
||||
//Outer Line
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, _alpha);
|
||||
|
||||
glVertex3f(lX, tY, -tlZ);
|
||||
glVertex3f(rX, tY, -trZ);
|
||||
glVertex3f(rX, bY, -brZ);
|
||||
glVertex3f(lX, bY, -blZ);
|
||||
glVertex3f(lX, tY, -tlZ);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
glColor4f(1.0f, 1.0f, 1.0f, _alpha);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(lX, tY, -tlZ);
|
||||
glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rX, tY, -trZ);
|
||||
glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rX, bY, -brZ);
|
||||
glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(lX, bY, -blZ);
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderAudioMeter() {
|
||||
|
||||
Application* application = Application::getInstance();
|
||||
|
@ -1129,120 +1000,6 @@ void ApplicationOverlay::renderStatsAndLogs() {
|
|||
nodeBoundsDisplay.drawOverlay();
|
||||
}
|
||||
|
||||
ApplicationOverlay::VerticesIndices* ApplicationOverlay::makeTexturedHemiphereVBO(float fov,
|
||||
float aspectRatio,
|
||||
int slices,
|
||||
int stacks) {
|
||||
if (fov >= PI) {
|
||||
qDebug() << "ApplicationOverlay::makeHemiphereVBO(): FOV greater or equal than Pi will create issues";
|
||||
}
|
||||
|
||||
//UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
|
||||
VerticesIndices* vbo = new VerticesIndices(0, 0);
|
||||
|
||||
// Compute number of vertices needed
|
||||
int vertices = slices * stacks;
|
||||
|
||||
// Compute vertices positions and texture UV coordinate
|
||||
TextureVertex* vertexData = new TextureVertex[vertices];
|
||||
TextureVertex* vertexPtr = &vertexData[0];
|
||||
for (int i = 0; i < stacks; i++) {
|
||||
float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f
|
||||
// abs(phi) <= fov / 2.0f
|
||||
float phi = fov * (stacksRatio - 0.5f);
|
||||
|
||||
for (int j = 0; j < slices; j++) {
|
||||
float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f
|
||||
// abs(theta) <= fov * aspectRatio / 2.0f
|
||||
float theta = fov * aspectRatio * (slicesRatio - 0.5f);
|
||||
|
||||
vertexPtr->position.x = -sinf(theta);
|
||||
vertexPtr->position.y = sinf(phi);
|
||||
vertexPtr->position.z = cosf(theta);
|
||||
vertexPtr->uv.x = slicesRatio;
|
||||
vertexPtr->uv.y = 1.0f - stacksRatio;
|
||||
vertexPtr++;
|
||||
}
|
||||
}
|
||||
// Create and write to buffer
|
||||
glGenBuffers(1, &vbo->first);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo->first);
|
||||
static const int BYTES_PER_VERTEX = sizeof(TextureVertex);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||
delete[] vertexData;
|
||||
|
||||
|
||||
// Compute number of indices needed
|
||||
static const int VERTEX_PER_TRANGLE = 3;
|
||||
static const int TRIANGLE_PER_RECTANGLE = 2;
|
||||
int numberOfRectangles = (slices - 1) * (stacks - 1);
|
||||
int indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
|
||||
|
||||
// Compute indices order
|
||||
GLushort* indexData = new GLushort[indices];
|
||||
GLushort* indexPtr = indexData;
|
||||
for (int i = 0; i < stacks - 1; i++) {
|
||||
for (int j = 0; j < slices - 1; j++) {
|
||||
GLushort bottomLeftIndex = i * slices + j;
|
||||
GLushort bottomRightIndex = bottomLeftIndex + 1;
|
||||
GLushort topLeftIndex = bottomLeftIndex + slices;
|
||||
GLushort topRightIndex = topLeftIndex + 1;
|
||||
|
||||
*(indexPtr++) = topLeftIndex;
|
||||
*(indexPtr++) = bottomLeftIndex;
|
||||
*(indexPtr++) = topRightIndex;
|
||||
|
||||
*(indexPtr++) = topRightIndex;
|
||||
*(indexPtr++) = bottomLeftIndex;
|
||||
*(indexPtr++) = bottomRightIndex;
|
||||
}
|
||||
}
|
||||
// Create and write to buffer
|
||||
glGenBuffers(1, &vbo->second);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->second);
|
||||
static const int BYTES_PER_INDEX = sizeof(GLushort);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||
delete[] indexData;
|
||||
|
||||
return vbo;
|
||||
}
|
||||
|
||||
//Renders a hemisphere with texture coordinates.
|
||||
void ApplicationOverlay::renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo->first);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->second);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
static const int STRIDE = sizeof(TextureVertex);
|
||||
static const void* VERTEX_POINTER = 0;
|
||||
static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3);
|
||||
glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER);
|
||||
glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER);
|
||||
|
||||
|
||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||
const glm::quat& orientation = myAvatar->getOrientation();
|
||||
const glm::vec3& position = myAvatar->getDefaultEyePosition();
|
||||
const float scale = _oculusuiRadius * myAvatar->getScale();
|
||||
|
||||
glPushMatrix(); {
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::mat4 rotation = glm::toMat4(orientation);
|
||||
glMultMatrixf(&rotation[0][0]);
|
||||
glScalef(scale, scale, scale);
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);
|
||||
} glPopMatrix();
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void ApplicationOverlay::renderDomainConnectionStatusBorder() {
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
|
@ -1267,22 +1024,281 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() {
|
|||
}
|
||||
}
|
||||
|
||||
QOpenGLFramebufferObject* ApplicationOverlay::getFramebufferObject() {
|
||||
QSize size = Application::getInstance()->getGLWidget()->getDeviceSize();
|
||||
if (!_framebufferObject || _framebufferObject->size() != size) {
|
||||
|
||||
delete _framebufferObject;
|
||||
|
||||
_framebufferObject = new QOpenGLFramebufferObject(size);
|
||||
glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
//Renders a small magnification of the currently bound texture at the coordinates
|
||||
void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const {
|
||||
Application* application = Application::getInstance();
|
||||
GLCanvas* glWidget = application->getGLWidget();
|
||||
|
||||
const int widgetWidth = glWidget->width();
|
||||
const int widgetHeight = glWidget->height();
|
||||
|
||||
const float magnifyWidth = MAGNIFY_WIDTH * sizeMult;
|
||||
const float magnifyHeight = MAGNIFY_HEIGHT * sizeMult;
|
||||
|
||||
mouseX -= magnifyWidth / 2;
|
||||
mouseY -= magnifyHeight / 2;
|
||||
|
||||
float newWidth = magnifyWidth * MAGNIFY_MULT;
|
||||
float newHeight = magnifyHeight * MAGNIFY_MULT;
|
||||
|
||||
// Magnification Texture Coordinates
|
||||
float magnifyULeft = mouseX / (float)widgetWidth;
|
||||
float magnifyURight = (mouseX + magnifyWidth) / (float)widgetWidth;
|
||||
float magnifyVBottom = 1.0f - mouseY / (float)widgetHeight;
|
||||
float magnifyVTop = 1.0f - (mouseY + magnifyHeight) / (float)widgetHeight;
|
||||
|
||||
// Coordinates of magnification overlay
|
||||
float newMouseX = (mouseX + magnifyWidth / 2) - newWidth / 2.0f;
|
||||
float newMouseY = (mouseY + magnifyHeight / 2) + newHeight / 2.0f;
|
||||
|
||||
// Get position on hemisphere using angle
|
||||
|
||||
//Get new UV coordinates from our magnification window
|
||||
float newULeft = newMouseX / widgetWidth;
|
||||
float newURight = (newMouseX + newWidth) / widgetWidth;
|
||||
float newVBottom = 1.0 - newMouseY / widgetHeight;
|
||||
float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight;
|
||||
|
||||
// Project our position onto the hemisphere using the UV coordinates
|
||||
float radius = _oculusuiRadius * application->getAvatar()->getScale();
|
||||
float radius2 = radius * radius;
|
||||
|
||||
float lX = radius * sin((newULeft - 0.5f) * _textureFov);
|
||||
float rX = radius * sin((newURight - 0.5f) * _textureFov);
|
||||
float bY = radius * sin((newVBottom - 0.5f) * _textureFov);
|
||||
float tY = radius * sin((newVTop - 0.5f) * _textureFov);
|
||||
|
||||
float blZ, tlZ, brZ, trZ;
|
||||
|
||||
float dist;
|
||||
float discriminant;
|
||||
|
||||
//Bottom Left
|
||||
dist = sqrt(lX * lX + bY * bY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
blZ = sqrt(discriminant);
|
||||
} else {
|
||||
blZ = 0;
|
||||
}
|
||||
return _framebufferObject;
|
||||
//Top Left
|
||||
dist = sqrt(lX * lX + tY * tY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
tlZ = sqrt(discriminant);
|
||||
} else {
|
||||
tlZ = 0;
|
||||
}
|
||||
//Bottom Right
|
||||
dist = sqrt(rX * rX + bY * bY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
brZ = sqrt(discriminant);
|
||||
} else {
|
||||
brZ = 0;
|
||||
}
|
||||
//Top Right
|
||||
dist = sqrt(rX * rX + tY * tY);
|
||||
discriminant = radius2 - dist * dist;
|
||||
if (discriminant > 0) {
|
||||
trZ = sqrt(discriminant);
|
||||
} else {
|
||||
trZ = 0;
|
||||
}
|
||||
|
||||
if (showBorder) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glLineWidth(1.0f);
|
||||
//Outer Line
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, _alpha);
|
||||
|
||||
glVertex3f(lX, tY, -tlZ);
|
||||
glVertex3f(rX, tY, -trZ);
|
||||
glVertex3f(rX, bY, -brZ);
|
||||
glVertex3f(lX, bY, -blZ);
|
||||
glVertex3f(lX, tY, -tlZ);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
glColor4f(1.0f, 1.0f, 1.0f, _alpha);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(lX, tY, -tlZ);
|
||||
glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(rX, tY, -trZ);
|
||||
glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(rX, bY, -brZ);
|
||||
glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(lX, bY, -blZ);
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() :
|
||||
_vertices(0),
|
||||
_indices(0),
|
||||
_framebufferObject(NULL),
|
||||
_vbo(0, 0) {
|
||||
}
|
||||
|
||||
ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() {
|
||||
cleanupVBO();
|
||||
if (_framebufferObject != NULL) {
|
||||
delete _framebufferObject;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationOverlay::TexturedHemisphere::bind() {
|
||||
if (_framebufferObject != NULL) {
|
||||
_framebufferObject->bind();
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationOverlay::TexturedHemisphere::release() {
|
||||
if (_framebufferObject != NULL) {
|
||||
_framebufferObject->release();
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov,
|
||||
const float aspectRatio,
|
||||
const int slices,
|
||||
const int stacks) {
|
||||
if (fov >= PI) {
|
||||
qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues";
|
||||
}
|
||||
// Cleanup old VBO if necessary
|
||||
cleanupVBO();
|
||||
|
||||
//UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
|
||||
|
||||
// Compute number of vertices needed
|
||||
_vertices = slices * stacks;
|
||||
|
||||
// Compute vertices positions and texture UV coordinate
|
||||
TextureVertex* vertexData = new TextureVertex[_vertices];
|
||||
TextureVertex* vertexPtr = &vertexData[0];
|
||||
for (int i = 0; i < stacks; i++) {
|
||||
float stacksRatio = (float)i / (float)stacks; // First stack is 0.0f, last stack is 1.0f
|
||||
// abs(phi) <= fov / 2.0f
|
||||
float phi = fov * (stacksRatio - 0.5f);
|
||||
|
||||
for (int j = 0; j < slices; j++) {
|
||||
float slicesRatio = (float)j / (float)slices; // First slice is 0.0f, last slice is 1.0f
|
||||
// abs(theta) <= fov * aspectRatio / 2.0f
|
||||
float theta = fov * aspectRatio * (slicesRatio - 0.5f);
|
||||
|
||||
vertexPtr->position.x = -sinf(theta);
|
||||
vertexPtr->position.y = sinf(phi);
|
||||
vertexPtr->position.z = cosf(theta);
|
||||
vertexPtr->uv.x = slicesRatio;
|
||||
vertexPtr->uv.y = 1.0f - stacksRatio;
|
||||
vertexPtr++;
|
||||
}
|
||||
}
|
||||
// Create and write to buffer
|
||||
glGenBuffers(1, &_vbo.first);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo.first);
|
||||
static const int BYTES_PER_VERTEX = sizeof(TextureVertex);
|
||||
glBufferData(GL_ARRAY_BUFFER, _vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||
delete[] vertexData;
|
||||
|
||||
|
||||
// Compute number of indices needed
|
||||
static const int VERTEX_PER_TRANGLE = 3;
|
||||
static const int TRIANGLE_PER_RECTANGLE = 2;
|
||||
int numberOfRectangles = (slices - 1) * (stacks - 1);
|
||||
_indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
|
||||
|
||||
// Compute indices order
|
||||
GLushort* indexData = new GLushort[_indices];
|
||||
GLushort* indexPtr = indexData;
|
||||
for (int i = 0; i < stacks - 1; i++) {
|
||||
for (int j = 0; j < slices - 1; j++) {
|
||||
GLushort bottomLeftIndex = i * slices + j;
|
||||
GLushort bottomRightIndex = bottomLeftIndex + 1;
|
||||
GLushort topLeftIndex = bottomLeftIndex + slices;
|
||||
GLushort topRightIndex = topLeftIndex + 1;
|
||||
|
||||
*(indexPtr++) = topLeftIndex;
|
||||
*(indexPtr++) = bottomLeftIndex;
|
||||
*(indexPtr++) = topRightIndex;
|
||||
|
||||
*(indexPtr++) = topRightIndex;
|
||||
*(indexPtr++) = bottomLeftIndex;
|
||||
*(indexPtr++) = bottomRightIndex;
|
||||
}
|
||||
}
|
||||
// Create and write to buffer
|
||||
glGenBuffers(1, &_vbo.second);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
|
||||
static const int BYTES_PER_INDEX = sizeof(GLushort);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||
delete[] indexData;
|
||||
}
|
||||
|
||||
void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
|
||||
if (_vbo.first != 0) {
|
||||
glDeleteBuffers(1, &_vbo.first);
|
||||
_vbo.first = 0;
|
||||
}
|
||||
if (_vbo.second != 0) {
|
||||
glDeleteBuffers(1, &_vbo.second);
|
||||
_vbo.second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject(const QSize& size) {
|
||||
if (_framebufferObject != NULL) {
|
||||
delete _framebufferObject;
|
||||
}
|
||||
|
||||
_framebufferObject = new QOpenGLFramebufferObject(size);
|
||||
glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
//Renders a hemisphere with texture coordinates.
|
||||
void ApplicationOverlay::TexturedHemisphere::render(const glm::quat& orientation, const glm::vec3& position, const float scale) {
|
||||
if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) {
|
||||
qDebug() << "TexturedHemisphere::render(): Incorrect initialisation";
|
||||
return;
|
||||
}
|
||||
|
||||
_framebufferObject->bind();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo.first);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
static const int STRIDE = sizeof(TextureVertex);
|
||||
static const void* VERTEX_POINTER = 0;
|
||||
static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3);
|
||||
glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER);
|
||||
glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER);
|
||||
|
||||
glPushMatrix(); {
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::mat4 rotation = glm::toMat4(orientation);
|
||||
glMultMatrixf(&rotation[0][0]);
|
||||
glScalef(scale, scale, scale);
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0);
|
||||
} glPopMatrix();
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
_framebufferObject->release();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ public:
|
|||
|
||||
|
||||
// Getters
|
||||
QOpenGLFramebufferObject* getFramebufferObject();
|
||||
float getAlpha() const { return _alpha; }
|
||||
|
||||
private:
|
||||
|
@ -48,7 +47,31 @@ private:
|
|||
};
|
||||
|
||||
typedef QPair<GLuint, GLuint> VerticesIndices;
|
||||
|
||||
class TexturedHemisphere {
|
||||
public:
|
||||
TexturedHemisphere();
|
||||
~TexturedHemisphere();
|
||||
|
||||
void bind();
|
||||
void release();
|
||||
|
||||
void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks);
|
||||
void buildFramebufferObject(const QSize& size);
|
||||
void render(const glm::quat& orientation, const glm::vec3& position, const float scale);
|
||||
|
||||
private:
|
||||
void cleanupVBO();
|
||||
|
||||
GLuint _vertices;
|
||||
GLuint _indices;
|
||||
QOpenGLFramebufferObject* _framebufferObject;
|
||||
VerticesIndices _vbo;
|
||||
};
|
||||
|
||||
VerticesIndices* makeTexturedHemiphereVBO(float fov, float aspectRatio, int slices, int stacks);
|
||||
void renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices);
|
||||
QOpenGLFramebufferObject* newFramebufferObject(QSize& size);
|
||||
|
||||
void renderPointers();
|
||||
void renderControllerPointers();
|
||||
void renderPointersOculus(const glm::vec3& eyePos);
|
||||
|
@ -56,15 +79,14 @@ private:
|
|||
void renderAudioMeter();
|
||||
void renderStatsAndLogs();
|
||||
void renderDomainConnectionStatusBorder();
|
||||
|
||||
VerticesIndices* makeTexturedHemiphereVBO(float fov, float aspectRatio, int slices, int stacks);
|
||||
void renderTexturedHemisphere(ApplicationOverlay::VerticesIndices* vbo, int vertices, int indices);
|
||||
|
||||
QOpenGLFramebufferObject* _framebufferObject;
|
||||
TexturedHemisphere _overlays;
|
||||
TexturedHemisphere _reticule;
|
||||
|
||||
float _trailingAudioLoudness;
|
||||
float _textureFov;
|
||||
|
||||
enum MagnifyDevices { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_MAGNIFIERS = RIGHT_CONTROLLER + 1 };
|
||||
enum MagnifyDevices { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_MAGNIFIERS };
|
||||
bool _reticleActive[NUMBER_OF_MAGNIFIERS];
|
||||
int _mouseX[NUMBER_OF_MAGNIFIERS];
|
||||
int _mouseY[NUMBER_OF_MAGNIFIERS];
|
||||
|
@ -74,7 +96,7 @@ private:
|
|||
float _magSizeMult[NUMBER_OF_MAGNIFIERS];
|
||||
|
||||
float _alpha;
|
||||
float _oculusuiRadius;
|
||||
float _oculusUIRadius;
|
||||
|
||||
GLuint _crosshairTexture;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue