blob: d646429afee3e7ed76d2460e40d8c8b4afe601a4 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Data Visualization module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "selectionpointer_p.h"
#include "shaderhelper_p.h"
#include "objecthelper_p.h"
#include "texturehelper_p.h"
#include "q3dcamera_p.h"
#include "utils_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
const GLfloat sliceUnits = 2.5;
SelectionPointer::SelectionPointer(Drawer *drawer)
: QObject(0),
m_labelShader(0),
m_pointShader(0),
m_labelObj(0),
m_pointObj(0),
m_textureHelper(0),
m_cachedTheme(drawer->theme()),
m_labelBackground(false),
m_drawer(drawer),
m_cachedScene(0)
{
initializeOpenGL();
QObject::connect(m_drawer, &Drawer::drawerChanged,
this, &SelectionPointer::handleDrawerChange);
}
SelectionPointer::~SelectionPointer()
{
delete m_labelShader;
delete m_pointShader;
delete m_textureHelper;
}
void SelectionPointer::initializeOpenGL()
{
initializeOpenGLFunctions();
m_textureHelper = new TextureHelper();
m_drawer->initializeOpenGL();
initShaders();
}
void SelectionPointer::updateScene(Q3DScene *scene)
{
m_cachedScene = scene;
}
void SelectionPointer::renderSelectionPointer(GLuint defaultFboHandle, bool useOrtho)
{
Q_UNUSED(defaultFboHandle)
glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
m_mainViewPort.width(), m_mainViewPort.height());
Q3DCamera *camera = m_cachedScene->activeCamera();
QMatrix4x4 itModelMatrix;
// Get view matrix
QMatrix4x4 viewMatrix;
QMatrix4x4 projectionMatrix;
GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
if (m_cachedIsSlicingActivated) {
GLfloat sliceUnitsScaled = sliceUnits / m_autoScaleAdjustment;
viewMatrix.lookAt(QVector3D(0.0f, 0.0f, 1.0f), zeroVector, upVector);
projectionMatrix.ortho(-sliceUnitsScaled * viewPortRatio, sliceUnitsScaled * viewPortRatio,
-sliceUnitsScaled, sliceUnitsScaled,
-1.0f, 4.0f);
} else if (useOrtho) {
viewMatrix = camera->d_ptr->viewMatrix();
GLfloat orthoRatio = 2.0f;
projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
-orthoRatio, orthoRatio,
0.0f, 100.0f);
} else {
viewMatrix = camera->d_ptr->viewMatrix();
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
}
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
// Position the pointer ball
modelMatrix.translate(m_position);
if (!m_rotation.isIdentity()) {
modelMatrix.rotate(m_rotation);
itModelMatrix.rotate(m_rotation);
}
// Scale the point with fixed values (at this point)
QVector3D scaleVector(0.05f, 0.05f, 0.05f);
modelMatrix.scale(scaleVector);
itModelMatrix.scale(scaleVector);
MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
QVector3D lightPos = m_cachedScene->activeLight()->position();
//
// Draw the point
//
m_pointShader->bind();
m_pointShader->setUniformValue(m_pointShader->lightP(), lightPos);
m_pointShader->setUniformValue(m_pointShader->view(), viewMatrix);
m_pointShader->setUniformValue(m_pointShader->model(), modelMatrix);
m_pointShader->setUniformValue(m_pointShader->nModel(), itModelMatrix.inverted().transposed());
m_pointShader->setUniformValue(m_pointShader->color(), m_highlightColor);
m_pointShader->setUniformValue(m_pointShader->MVP(), MVPMatrix);
m_pointShader->setUniformValue(m_pointShader->ambientS(),
m_cachedTheme->ambientLightStrength());
m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme->lightStrength() * 2.0f);
m_pointShader->setUniformValue(m_pointShader->lightColor(),
Utils::vectorFromColor(m_cachedTheme->lightColor()));
m_drawer->drawObject(m_pointShader, m_pointObj);
}
void SelectionPointer::renderSelectionLabel(GLuint defaultFboHandle, bool useOrtho)
{
Q_UNUSED(defaultFboHandle)
glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
m_mainViewPort.width(), m_mainViewPort.height());
Q3DCamera *camera = m_cachedScene->activeCamera();
// Get view matrix
QMatrix4x4 viewMatrix;
QMatrix4x4 modelMatrixLabel;
QMatrix4x4 projectionMatrix;
GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
if (m_cachedIsSlicingActivated) {
GLfloat sliceUnitsScaled = sliceUnits / m_autoScaleAdjustment;
viewMatrix.lookAt(QVector3D(0.0f, 0.0f, 1.0f), zeroVector, upVector);
projectionMatrix.ortho(-sliceUnitsScaled * viewPortRatio, sliceUnitsScaled * viewPortRatio,
-sliceUnitsScaled, sliceUnitsScaled,
-1.0f, 4.0f);
} else if (useOrtho) {
viewMatrix = camera->d_ptr->viewMatrix();
GLfloat orthoRatio = 2.0f;
projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
-orthoRatio, orthoRatio,
0.0f, 100.0f);
} else {
viewMatrix = camera->d_ptr->viewMatrix();
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
}
QSize textureSize = m_labelItem.size();
// Calculate scale factor to get uniform font size
GLfloat scaledFontSize = 0.05f + m_drawer->font().pointSizeF() / 500.0f;
GLfloat scaleFactor = scaledFontSize / (GLfloat)textureSize.height();
// Position label
QVector3D labelAlign(0.0f, 1.0f * scaledFontSize + 0.05f, 0.0f);
modelMatrixLabel.translate(m_position + labelAlign);
// Position the label towards the camera
float camRotationsX = camera->xRotation();
float camRotationsY = camera->yRotation();
if (!m_cachedIsSlicingActivated) {
modelMatrixLabel.rotate(-camRotationsX, 0.0f, 1.0f, 0.0f);
modelMatrixLabel.rotate(-camRotationsY, 1.0f, 0.0f, 0.0f);
}
// Scale label based on text size
modelMatrixLabel.scale(QVector3D((GLfloat)textureSize.width() * scaleFactor,
scaledFontSize,
0.0f));
// Make label to be always on top
glDisable(GL_DEPTH_TEST);
// Make label transparent
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_labelShader->bind();
QMatrix4x4 MVPMatrix;
// Set shader bindings
MVPMatrix = projectionMatrix * viewMatrix * modelMatrixLabel;
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
// Draw the object
m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId());
// Release shader
glUseProgram(0);
// Disable transparency
glDisable(GL_BLEND);
// Depth test back to normal
glEnable(GL_DEPTH_TEST);
}
void SelectionPointer::setPosition(const QVector3D &position)
{
m_position = position;
}
void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment)
{
m_cachedIsSlicingActivated = sliceActivated;
m_autoScaleAdjustment = autoScaleAdjustment;
}
void SelectionPointer::setHighlightColor(const QVector4D &colorVector)
{
m_highlightColor = colorVector;
}
void SelectionPointer::setRotation(const QQuaternion &rotation)
{
m_rotation = rotation;
}
void SelectionPointer::setLabel(const QString &label, bool themeChange)
{
if (themeChange || m_label != label) {
m_label = label;
m_drawer->generateLabelItem(m_labelItem, m_label);
}
}
void SelectionPointer::setPointerObject(ObjectHelper *object)
{
m_pointObj = object;
}
void SelectionPointer::setLabelObject(ObjectHelper *object)
{
m_labelObj = object;
}
void SelectionPointer::handleDrawerChange()
{
m_cachedTheme = m_drawer->theme();
setLabel(m_label, true);
}
void SelectionPointer::updateBoundingRect(const QRect &rect)
{
m_mainViewPort = rect;
}
void SelectionPointer::initShaders()
{
// The shader for printing the text label
if (m_labelShader)
delete m_labelShader;
m_labelShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
m_labelShader->initialize();
// The shader for the small point ball
if (m_pointShader)
delete m_pointShader;
if (Utils::isOpenGLES()) {
m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentES2"));
} else {
m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
}
m_pointShader->initialize();
}
QT_END_NAMESPACE_DATAVISUALIZATION