summaryrefslogtreecommitdiffstats
path: root/src/datavis3d/utils
diff options
context:
space:
mode:
authorHeikkinen Miikka <miikka.heikkinen@digia.com>2013-05-17 12:21:40 +0300
committerTomi Korpipää <tomi.korpipaa@digia.com>2013-05-17 12:37:26 +0300
commit3dafad59b97532e8e68c0b7abca796f3a9527a6e (patch)
tree6dcb5bf6edc5aee39490b35db11202a20929d858 /src/datavis3d/utils
parent5963d52c1923cf2468c1fa4738e04a175196cc7d (diff)
Added datavis3d back under src
Change-Id: I209e8b3228b2ce0085c897db6fb2ea78e93afa67 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src/datavis3d/utils')
-rw-r--r--src/datavis3d/utils/camerahelper.cpp281
-rw-r--r--src/datavis3d/utils/camerahelper_p.h93
-rw-r--r--src/datavis3d/utils/meshloader.cpp148
-rw-r--r--src/datavis3d/utils/meshloader_p.h74
-rw-r--r--src/datavis3d/utils/objecthelper.cpp165
-rw-r--r--src/datavis3d/utils/objecthelper_p.h91
-rw-r--r--src/datavis3d/utils/shaderhelper.cpp252
-rw-r--r--src/datavis3d/utils/shaderhelper_p.h133
-rw-r--r--src/datavis3d/utils/texturehelper.cpp358
-rw-r--r--src/datavis3d/utils/texturehelper_p.h90
-rw-r--r--src/datavis3d/utils/utils.cpp226
-rw-r--r--src/datavis3d/utils/utils.pri15
-rw-r--r--src/datavis3d/utils/utils_p.h84
-rw-r--r--src/datavis3d/utils/vertexindexer.cpp176
-rw-r--r--src/datavis3d/utils/vertexindexer_p.h111
15 files changed, 2297 insertions, 0 deletions
diff --git a/src/datavis3d/utils/camerahelper.cpp b/src/datavis3d/utils/camerahelper.cpp
new file mode 100644
index 00000000..2e868cac
--- /dev/null
+++ b/src/datavis3d/utils/camerahelper.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camerahelper_p.h"
+
+#include <qmath.h>
+#include <QMatrix4x4>
+#include <QVector3D>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+// Initial camera position
+QVector3D m_position = QVector3D(0, 0.25, 3);
+QVector3D m_target = QVector3D(0, 0, 0);
+QVector3D m_up = QVector3D(0, 1, 0);
+
+QPoint m_previousMousePos(0, 0);
+
+GLfloat m_xRotation = 0;
+GLfloat m_yRotation = 0;
+GLfloat m_defaultXRotation = 0;
+GLfloat m_defaultYRotation = 0;
+
+GLfloat m_rotationSpeed = 100;
+
+// FUNCTIONS
+void CameraHelper::setRotationSpeed(int speed)
+{
+ // increase for faster rotation
+ m_rotationSpeed = speed;
+}
+
+void CameraHelper::setCameraRotation(const QPointF &rotation)
+{
+ m_xRotation = rotation.x();
+ m_defaultXRotation = m_xRotation;
+ m_yRotation = rotation.y();
+ m_defaultYRotation = m_yRotation;
+}
+
+void CameraHelper::setDefaultCameraOrientation(const QVector3D &defaultPosition,
+ const QVector3D &defaultTarget,
+ const QVector3D &defaultUp)
+{
+ m_position = defaultPosition;
+ m_target = defaultTarget;
+ m_up = defaultUp;
+}
+
+QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom,
+ int screenWidth, int screenHeight)
+{
+ QMatrix4x4 viewMatrix;
+
+ // Calculate mouse movement since last frame
+ GLfloat mouseMoveX = GLfloat(m_previousMousePos.x() - mousePos.x())
+ / (screenWidth / m_rotationSpeed);
+ GLfloat mouseMoveY = GLfloat(m_previousMousePos.y() - mousePos.y())
+ / (screenHeight / m_rotationSpeed);
+ // Apply to rotations
+ m_xRotation -= mouseMoveX;
+ m_yRotation -= mouseMoveY;
+ // Reset at 360 in x and limit to 0...90 in y
+ if (qFabs(m_xRotation) >= 360)
+ m_xRotation = 0;
+ if (m_yRotation >= 90)
+ m_yRotation = 90;
+ else if (m_yRotation <= 0)
+ m_yRotation = 0;
+
+ // Apply to view matrix
+ viewMatrix.lookAt(m_position, m_target, m_up);
+ // Compensate for translation (if m_target is off origin)
+ viewMatrix.translate(m_target.x(), m_target.y(), m_target.z());
+ // Apply rotations
+ // Handle x and z rotation when y -angle is other than 0
+ viewMatrix.rotate(m_xRotation, 0, cos(m_yRotation * m_pi / 180.0f),
+ sin(m_yRotation * m_pi / 180.0f));
+ // y rotation is always "clean"
+ viewMatrix.rotate(m_yRotation, 1.0f, 0.0f, 0.0f);
+ // handle zoom by scaling
+ viewMatrix.scale((GLfloat)zoom / 100.0f);
+ // Compensate for translation (if m_target is off origin)
+ viewMatrix.translate(-m_target.x(), -m_target.y(), -m_target.z());
+ //qDebug() << m_xRotation << m_yRotation;
+
+ //qDebug() << "sin(m_yRotation)" << sin(m_yRotation*m_pi/180);
+ //qDebug() << "asin(m_yRotation)" << asin(m_yRotation*m_pi/180);
+ //qDebug() << "cos(m_yRotation)" << cos(m_yRotation*m_pi/180);
+ //qDebug() << "tan(m_yRotation)" << tan(m_yRotation*m_pi/180);
+
+ m_previousMousePos = mousePos;
+ return viewMatrix;
+}
+
+QVector3D CameraHelper::calculateLightPosition(const QVector3D &lightPosition,
+ GLfloat fixedRotation, GLfloat distanceModifier)
+{
+ // Move light with camera
+ QVector3D newLightPosition;
+ GLfloat radiusFactor = lightPosition.z() * (1.5f + distanceModifier); // for making sure light is outside the scene at its lowest point
+ GLfloat xAngle;
+ GLfloat yAngle;
+ if (!fixedRotation) {
+ xAngle = m_xRotation * m_pi / 180.0f;
+ yAngle = m_yRotation * m_pi / 180.0f;
+ } else {
+ xAngle = fixedRotation * m_pi / 180.0f;
+ yAngle = 0;
+ }
+ GLfloat radius = (radiusFactor + lightPosition.y()); // set radius to match the highest height of the light
+ GLfloat zPos = radius * cos(xAngle) * cos(yAngle);
+ GLfloat xPos = radius * sin(xAngle) * cos(yAngle);
+ GLfloat yPos = (radiusFactor + lightPosition.y()) * sin(yAngle);
+ // Keep light in the set position in relation to camera
+ // TODO: Does not work perfectly yet; Light seems wrong when viewing scene from sides (or isometrically)
+ newLightPosition = QVector3D(-xPos + lightPosition.x(),
+ yPos + lightPosition.y(),
+ zPos + lightPosition.z());
+ //qDebug() << newLightPosition << xAngle << yAngle << fixedRotation;
+ return newLightPosition;
+}
+
+void CameraHelper::updateMousePos(const QPoint &mousePos)
+{
+ m_previousMousePos = mousePos;
+ // if mouse position is set to (0, 0), reset rotations
+ if (QPoint(0, 0) == mousePos) {
+ m_xRotation = m_defaultXRotation;
+ m_yRotation = m_defaultYRotation;
+ }
+}
+
+QPointF CameraHelper::getCameraRotations()
+{
+ QPointF rotations(m_xRotation, m_yRotation);
+ return rotations;
+}
+
+void CameraHelper::setCameraPreset(CameraPreset preset)
+{
+ switch (preset) {
+ case PresetFrontLow: {
+ qDebug("PresetFrontLow");
+ CameraHelper::setCameraRotation(QPointF(0.0f, 0.0f));
+ break;
+ }
+ case PresetFront: {
+ qDebug("PresetFront");
+ CameraHelper::setCameraRotation(QPointF(0.0f, 22.5f));
+ break;
+ }
+ case PresetFrontHigh: {
+ qDebug("PresetFrontHigh");
+ CameraHelper::setCameraRotation(QPointF(0.0f, 45.0f));
+ break;
+ }
+ case PresetLeftLow: {
+ qDebug("PresetLeftLow");
+ CameraHelper::setCameraRotation(QPointF(90.0f, 0.0f));
+ break;
+ }
+ case PresetLeft: {
+ qDebug("PresetLeft");
+ CameraHelper::setCameraRotation(QPointF(90.0f, 22.5f));
+ break;
+ }
+ case PresetLeftHigh: {
+ qDebug("PresetLeftHigh");
+ CameraHelper::setCameraRotation(QPointF(90.0f, 45.0f));
+ break;
+ }
+ case PresetRightLow: {
+ qDebug("PresetRightLow");
+ CameraHelper::setCameraRotation(QPointF(-90.0f, 0.0f));
+ break;
+ }
+ case PresetRight: {
+ qDebug("PresetRight");
+ CameraHelper::setCameraRotation(QPointF(-90.0f, 22.5f));
+ break;
+ }
+ case PresetRightHigh: {
+ qDebug("PresetRightHigh");
+ CameraHelper::setCameraRotation(QPointF(-90.0f, 45.0f));
+ break;
+ }
+ case PresetBehindLow: {
+ qDebug("PresetBehindLow");
+ CameraHelper::setCameraRotation(QPointF(180.0f, 0.0f));
+ break;
+ }
+ case PresetBehind: {
+ qDebug("PresetBehind");
+ CameraHelper::setCameraRotation(QPointF(180.0f, 22.5f));
+ break;
+ }
+ case PresetBehindHigh: {
+ qDebug("PresetBehindHigh");
+ CameraHelper::setCameraRotation(QPointF(180.0f, 45.0f));
+ break;
+ }
+ case PresetIsometricLeft: {
+ qDebug("PresetIsometricLeft");
+ CameraHelper::setCameraRotation(QPointF(45.0f, 22.5f));
+ break;
+ }
+ case PresetIsometricLeftHigh: {
+ qDebug("PresetIsometricLeftHigh");
+ CameraHelper::setCameraRotation(QPointF(45.0f, 45.0f));
+ break;
+ }
+ case PresetIsometricRight: {
+ qDebug("PresetIsometricRight");
+ CameraHelper::setCameraRotation(QPointF(-45.0f, 22.5f));
+ break;
+ }
+ case PresetIsometricRightHigh: {
+ qDebug("PresetIsometricRightHigh");
+ CameraHelper::setCameraRotation(QPointF(-45.0f, 45.0f));
+ break;
+ }
+ case PresetDirectlyAbove: {
+ qDebug("PresetDirectlyAbove");
+ CameraHelper::setCameraRotation(QPointF(0.0f, 90.0f));
+ break;
+ }
+ case PresetDirectlyAboveCW45: {
+ qDebug("PresetDirectlyAboveCW45");
+ CameraHelper::setCameraRotation(QPointF(-45.0f, 90.0f));
+ break;
+ }
+ case PresetDirectlyAboveCCW45: {
+ qDebug("PresetDirectlyAboveCCW45");
+ CameraHelper::setCameraRotation(QPointF(45.0f, 90.0f));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/camerahelper_p.h b/src/datavis3d/utils/camerahelper_p.h
new file mode 100644
index 00000000..68e7e5a2
--- /dev/null
+++ b/src/datavis3d/utils/camerahelper_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef CAMERAPOSITIONER_P_H
+#define CAMERAPOSITIONER_P_H
+
+#include "qdatavis3dglobal.h"
+#include "qdatavis3namespace.h"
+#include "q3dbars.h"
+
+class QMatrix4x4;
+class QVector3D;
+class QPoint;
+class QPointF;
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class CameraHelper
+{
+ public:
+ // How fast camera rotates when mouse is dragged. Default is 100.
+ static void setRotationSpeed(int speed);
+ // Set camera rotation in degrees
+ static void setCameraRotation(const QPointF &rotation);
+ // Get camera rotations
+ static QPointF getCameraRotations();
+ // Set default camera orientation. Position's x and y should be 0.
+ static void setDefaultCameraOrientation(const QVector3D &defaultPosition,
+ const QVector3D &defaultTarget,
+ const QVector3D &defaultUp);
+ // Calculate view matrix based on rotation and zoom
+ static QMatrix4x4 calculateViewMatrix(const QPoint &mousePos, int zoom,
+ int screenWidth, int screenHeight);
+ // Calcluate light position based on rotation. Call after calling calculateViewMatrix to get
+ // up-to-date position
+ static QVector3D calculateLightPosition(const QVector3D &lightPosition,
+ GLfloat fixedRotation = 0.0f,
+ GLfloat distanceModifier = 0.0f);
+ static void updateMousePos(const QPoint &mousePos);
+ static void setCameraPreset(CameraPreset preset);
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/meshloader.cpp b/src/datavis3d/utils/meshloader.cpp
new file mode 100644
index 00000000..0e818a92
--- /dev/null
+++ b/src/datavis3d/utils/meshloader.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "meshloader_p.h"
+
+#include <QFile>
+#include <QStringList>
+#include <QVector>
+#include <QVector2D>
+#include <QVector3D>
+
+#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+QString slashTag = QStringLiteral("/");
+
+bool MeshLoader::loadOBJ(const QString &path,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals)
+{
+ //qDebug() << "Loading OBJ file" << path;
+
+ QVector<unsigned int> vertexIndices, uvIndices, normalIndices;
+ QVector<QVector3D> temp_vertices;
+ QVector<QVector2D> temp_uvs;
+ QVector<QVector3D> temp_normals;
+
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("Cannot open the file");
+ return false;
+ }
+
+ QTextStream textIn(&file);
+ while (!textIn.atEnd()) {
+ QString line = textIn.readLine();
+ QStringList lineContents = line.split(QStringLiteral(" "));
+ if (!lineContents.at(0).compare(QStringLiteral("v"))) {
+ QVector3D vertex;
+ vertex.setX(lineContents.at(1).toFloat());
+ vertex.setY(lineContents.at(2).toFloat());
+ vertex.setZ(lineContents.at(3).toFloat());
+ temp_vertices.append(vertex);
+ }
+ else if (!lineContents.at(0).compare(QStringLiteral("vt"))) {
+ QVector2D uv;
+ uv.setX(lineContents.at(1).toFloat());
+ uv.setY(lineContents.at(2).toFloat()); // invert this if using DDS textures
+ temp_uvs.append(uv);
+ }
+ else if (!lineContents.at(0).compare(QStringLiteral("vn"))) {
+ QVector3D normal;
+ normal.setX(lineContents.at(1).toFloat());
+ normal.setY(lineContents.at(2).toFloat());
+ normal.setZ(lineContents.at(3).toFloat());
+ temp_normals.append(normal);
+ }
+ else if (!lineContents.at(0).compare(QStringLiteral("f"))) {
+ unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
+ QStringList set1 = lineContents.at(1).split(slashTag);
+ QStringList set2 = lineContents.at(2).split(slashTag);
+ QStringList set3 = lineContents.at(3).split(slashTag);
+ vertexIndex[0] = set1.at(0).toUInt();
+ vertexIndex[1] = set2.at(0).toUInt();
+ vertexIndex[2] = set3.at(0).toUInt();
+ uvIndex[0] = set1.at(1).toUInt();
+ uvIndex[1] = set2.at(1).toUInt();
+ uvIndex[2] = set3.at(1).toUInt();
+ normalIndex[0] = set1.at(2).toUInt();
+ normalIndex[1] = set2.at(2).toUInt();
+ normalIndex[2] = set3.at(2).toUInt();
+ vertexIndices.append(vertexIndex[0]);
+ vertexIndices.append(vertexIndex[1]);
+ vertexIndices.append(vertexIndex[2]);
+ uvIndices.append(uvIndex[0]);
+ uvIndices.append(uvIndex[1]);
+ uvIndices.append(uvIndex[2]);
+ normalIndices.append(normalIndex[0]);
+ normalIndices.append(normalIndex[1]);
+ normalIndices.append(normalIndex[2]);
+ }
+ else {
+ //qWarning("Line did not contain usable data");
+ }
+ }
+
+ // For each vertex of each triangle
+ for (int i = 0; i < vertexIndices.size(); i++) {
+ // Get the indices of its attributes
+ unsigned int vertexIndex = vertexIndices[i];
+ unsigned int uvIndex = uvIndices[i];
+ unsigned int normalIndex = normalIndices[i];
+
+ // Get the attributes thanks to the index
+ QVector3D vertex = temp_vertices[vertexIndex - 1];
+ QVector2D uv = temp_uvs[uvIndex - 1];
+ QVector3D normal = temp_normals[normalIndex - 1];
+
+ // Put the attributes in buffers
+ out_vertices.append(vertex);
+ out_uvs.append(uv);
+ out_normals.append(normal);
+ }
+
+ return true;
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/meshloader_p.h b/src/datavis3d/utils/meshloader_p.h
new file mode 100644
index 00000000..514ae5c6
--- /dev/null
+++ b/src/datavis3d/utils/meshloader_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef MESHLOADER_P_H
+#define MESHLOADER_P_H
+
+#include "qdatavis3dglobal.h"
+
+class QVector2D;
+class QVector3D;
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class MeshLoader
+{
+ public:
+ static bool loadOBJ(const QString &path,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals);
+ // TODO: add loaders for other formats?
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/objecthelper.cpp b/src/datavis3d/utils/objecthelper.cpp
new file mode 100644
index 00000000..6659a187
--- /dev/null
+++ b/src/datavis3d/utils/objecthelper.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "meshloader_p.h"
+#include "vertexindexer_p.h"
+#include "objecthelper_p.h"
+
+#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+ObjectHelper::ObjectHelper(const QString &objectFile)
+ : m_objectFile(objectFile),
+ m_vertexbuffer(0),
+ m_normalbuffer(0),
+ m_uvbuffer(0),
+ m_elementbuffer(0),
+ m_indexCount(0),
+ m_meshDataLoaded(false)
+{
+ initializeOpenGLFunctions();
+}
+
+ObjectHelper::~ObjectHelper()
+{
+ glDeleteBuffers(1, &m_vertexbuffer);
+ glDeleteBuffers(1, &m_uvbuffer);
+ glDeleteBuffers(1, &m_normalbuffer);
+ glDeleteBuffers(1, &m_elementbuffer);
+}
+
+void ObjectHelper::setObjectFile(const QString &objectFile)
+{
+ m_objectFile = objectFile;
+}
+
+void ObjectHelper::load()
+{
+ if (m_meshDataLoaded) {
+ // Delete old data
+ glDeleteBuffers(1, &m_vertexbuffer);
+ glDeleteBuffers(1, &m_uvbuffer);
+ glDeleteBuffers(1, &m_normalbuffer);
+ glDeleteBuffers(1, &m_elementbuffer);
+ }
+ QVector<QVector3D> vertices;
+ QVector<QVector2D> uvs;
+ QVector<QVector3D> normals;
+ bool loadOk = MeshLoader::loadOBJ(m_objectFile, vertices, uvs, normals);
+ if (!loadOk)
+ qFatal("loading failed");
+
+ //qDebug() << "vertex count" << vertices.size();;
+
+ // Index vertices
+ QVector<unsigned short> indices;
+ QVector<QVector3D> indexed_vertices;
+ QVector<QVector2D> indexed_uvs;
+ QVector<QVector3D> indexed_normals;
+ VertexIndexer::indexVBO(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs,
+ indexed_normals);
+
+ m_indexCount = indices.size();
+ //qDebug() << "index count" << m_indexCount;
+
+ glGenBuffers(1, &m_vertexbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
+ glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(QVector3D),
+ &indexed_vertices.at(0),
+ GL_STATIC_DRAW);
+
+ glGenBuffers(1, &m_normalbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer);
+ glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(QVector3D),
+ &indexed_normals.at(0),
+ GL_STATIC_DRAW);
+
+ glGenBuffers(1, &m_uvbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
+ glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(QVector2D),
+ &indexed_uvs.at(0), GL_STATIC_DRAW);
+
+ glGenBuffers(1, &m_elementbuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short),
+ &indices.at(0), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ m_meshDataLoaded = true;
+}
+
+GLuint ObjectHelper::vertexBuf()
+{
+ if (!m_meshDataLoaded)
+ qFatal("No loaded object");
+ return m_vertexbuffer;
+}
+
+GLuint ObjectHelper::normalBuf()
+{
+ if (!m_meshDataLoaded)
+ qFatal("No loaded object");
+ return m_normalbuffer;
+}
+
+GLuint ObjectHelper::uvBuf()
+{
+ if (!m_meshDataLoaded)
+ qFatal("No loaded object");
+ return m_uvbuffer;
+}
+
+GLuint ObjectHelper::elementBuf()
+{
+ if (!m_meshDataLoaded)
+ qFatal("No loaded object");
+ return m_elementbuffer;
+}
+
+GLuint ObjectHelper::indexCount()
+{
+ return m_indexCount;
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/objecthelper_p.h b/src/datavis3d/utils/objecthelper_p.h
new file mode 100644
index 00000000..f3e342ba
--- /dev/null
+++ b/src/datavis3d/utils/objecthelper_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef OBJECTHELPER_P_H
+#define OBJECTHELPER_P_H
+
+#include "qdatavis3dglobal.h"
+#include <QOpenGLFunctions>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class ObjectHelper: protected QOpenGLFunctions
+{
+ public:
+ ObjectHelper(const QString &objectFile = QString());
+ ~ObjectHelper();
+
+ void setObjectFile(const QString &objectFile);
+
+ void load();
+
+ GLuint vertexBuf();
+ GLuint normalBuf();
+ GLuint uvBuf();
+ GLuint elementBuf();
+ GLuint indexCount();
+
+ private:
+ QString m_objectFile;
+
+ GLuint m_vertexbuffer;
+ GLuint m_normalbuffer;
+ GLuint m_uvbuffer;
+ GLuint m_elementbuffer;
+
+ GLuint m_indexCount;
+
+ GLboolean m_meshDataLoaded;
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/shaderhelper.cpp b/src/datavis3d/utils/shaderhelper.cpp
new file mode 100644
index 00000000..a66b6a00
--- /dev/null
+++ b/src/datavis3d/utils/shaderhelper.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shaderhelper_p.h"
+
+#include <QOpenGLShader>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+ShaderHelper::ShaderHelper(QObject *parent,
+ const QString &vertexShader,
+ const QString &fragmentShader,
+ const QString &texture,
+ const QString &depthTexture)
+ : m_caller(parent),
+ m_program(0),
+ m_vertexShaderFile(vertexShader),
+ m_fragmentShaderFile(fragmentShader),
+ m_textureFile(texture),
+ m_depthTextureFile(depthTexture)
+{
+}
+
+ShaderHelper::~ShaderHelper()
+{
+ delete m_program;
+}
+
+void ShaderHelper::setShaders(const QString &vertexShader,
+ const QString &fragmentShader)
+{
+ m_vertexShaderFile = vertexShader;
+ m_fragmentShaderFile = fragmentShader;
+}
+
+void ShaderHelper::setTextures(const QString &texture,
+ const QString &depthTexture)
+{
+ m_textureFile = texture;
+ m_depthTextureFile = depthTexture;
+}
+
+void ShaderHelper::initialize()
+{
+ if (m_program)
+ delete m_program;
+ m_program = new QOpenGLShaderProgram(m_caller);
+ if (!m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, m_vertexShaderFile))
+ qFatal("Compiling Vertex shader failed");
+ if (!m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, m_fragmentShaderFile))
+ qFatal("Compiling Fragment shader failed");
+ m_program->link();
+
+ m_positionAttr = m_program->attributeLocation("vertexPosition_mdl");
+ m_normalAttr = m_program->attributeLocation("vertexNormal_mdl");
+ m_uvAttr = m_program->attributeLocation("vertexUV");
+
+ m_mvpMatrixUniform = m_program->uniformLocation("MVP");
+ m_viewMatrixUniform = m_program->uniformLocation("V");
+ m_modelMatrixUniform = m_program->uniformLocation("M");
+ m_invTransModelMatrixUniform = m_program->uniformLocation("itM");
+ m_depthMatrixUniform = m_program->uniformLocation("depthMVP");
+ m_lightPositionUniform = m_program->uniformLocation("lightPosition_wrld");
+ m_lightStrengthUniform = m_program->uniformLocation("lightStrength");
+ m_ambientStrengthUniform = m_program->uniformLocation("ambientStrength");
+ m_shadowQualityUniform = m_program->uniformLocation("shadowQuality");
+ m_colorUniform = m_program->uniformLocation("color_mdl");
+ m_textureUniform = m_program->uniformLocation("textureSampler");
+ m_shadowUniform = m_program->uniformLocation("shadowMap");
+
+ m_initialized = true;
+}
+
+void ShaderHelper::bind()
+{
+ m_program->bind();
+}
+
+void ShaderHelper::release()
+{
+ m_program->release();
+}
+
+void ShaderHelper::setUniformValue(GLuint uniform, const QVector3D &value)
+{
+ m_program->setUniformValue(uniform, value);
+}
+
+void ShaderHelper::setUniformValue(GLuint uniform, const QVector4D &value)
+{
+ m_program->setUniformValue(uniform, value);
+}
+
+void ShaderHelper::setUniformValue(GLuint uniform, const QMatrix4x4 &value)
+{
+ m_program->setUniformValue(uniform, value);
+}
+
+void ShaderHelper::setUniformValue(GLuint uniform, GLfloat value)
+{
+ m_program->setUniformValue(uniform, value);
+}
+
+void ShaderHelper::setUniformValue(GLuint uniform, GLint value)
+{
+ m_program->setUniformValue(uniform, value);
+}
+
+GLuint ShaderHelper::MVP()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_mvpMatrixUniform;
+}
+
+GLuint ShaderHelper::view()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_viewMatrixUniform;
+}
+
+GLuint ShaderHelper::model()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_modelMatrixUniform;
+}
+
+GLuint ShaderHelper::nModel()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_invTransModelMatrixUniform;
+}
+
+GLuint ShaderHelper::depth()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_depthMatrixUniform;
+}
+
+GLuint ShaderHelper::lightP()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_lightPositionUniform;
+}
+
+GLuint ShaderHelper::lightS()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_lightStrengthUniform;
+}
+
+GLuint ShaderHelper::ambientS()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_ambientStrengthUniform;
+}
+
+GLuint ShaderHelper::shadowQ()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_shadowQualityUniform;
+}
+
+GLuint ShaderHelper::color()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_colorUniform;
+}
+
+GLuint ShaderHelper::texture()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_textureUniform;
+}
+
+GLuint ShaderHelper::shadow()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_shadowUniform;
+}
+
+GLuint ShaderHelper::posAtt()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_positionAttr;
+}
+
+GLuint ShaderHelper::uvAtt()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_uvAttr;
+}
+
+GLuint ShaderHelper::normalAtt()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_normalAttr;
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/shaderhelper_p.h b/src/datavis3d/utils/shaderhelper_p.h
new file mode 100644
index 00000000..83e8b981
--- /dev/null
+++ b/src/datavis3d/utils/shaderhelper_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef SHADERHELPER_P_H
+#define SHADERHELPER_P_H
+
+#include "qdatavis3dglobal.h"
+#include <QOpenGLFunctions>
+
+class QOpenGLShaderProgram;
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class ShaderHelper
+{
+ public:
+ ShaderHelper(QObject *parent,
+ const QString &vertexShader = QString(),
+ const QString &fragmentShader = QString(),
+ const QString &texture = QString(),
+ const QString &depthTexture = QString());
+ ~ShaderHelper();
+
+ void setShaders(const QString &vertexShader, const QString &fragmentShader);
+ void setTextures(const QString &texture, const QString &depthTexture);
+
+ void initialize();
+ void bind();
+ void release();
+ void setUniformValue(GLuint uniform, const QVector3D &value);
+ void setUniformValue(GLuint uniform, const QVector4D &value);
+ void setUniformValue(GLuint uniform, const QMatrix4x4 &value);
+ void setUniformValue(GLuint uniform, GLfloat value);
+ void setUniformValue(GLuint uniform, GLint value);
+
+ GLuint MVP();
+ GLuint view();
+ GLuint model();
+ GLuint nModel();
+ GLuint depth();
+ GLuint lightP();
+ GLuint lightS();
+ GLuint ambientS();
+ GLuint shadowQ();
+ GLuint color();
+ GLuint texture();
+ GLuint shadow();
+
+ GLuint posAtt();
+ GLuint uvAtt();
+ GLuint normalAtt();
+
+ private:
+ QObject *m_caller;
+ QOpenGLShaderProgram *m_program;
+
+ QString m_vertexShaderFile;
+ QString m_fragmentShaderFile;
+
+ QString m_textureFile;
+ QString m_depthTextureFile;
+
+ GLuint m_positionAttr;
+ GLuint m_uvAttr;
+ GLuint m_normalAttr;
+
+ GLuint m_colorUniform;
+ GLuint m_viewMatrixUniform;
+ GLuint m_modelMatrixUniform;
+ GLuint m_invTransModelMatrixUniform;
+ GLuint m_depthMatrixUniform;
+ GLuint m_mvpMatrixUniform;
+ GLuint m_lightPositionUniform;
+ GLuint m_lightStrengthUniform;
+ GLuint m_ambientStrengthUniform;
+ GLuint m_shadowQualityUniform;
+ GLuint m_textureUniform;
+ GLuint m_shadowUniform;
+
+ GLboolean m_initialized;
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavis3d/utils/texturehelper.cpp
new file mode 100644
index 00000000..c0083b15
--- /dev/null
+++ b/src/datavis3d/utils/texturehelper.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "texturehelper_p.h"
+
+#include <QImage>
+
+#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+TextureHelper::TextureHelper()
+{
+ initializeOpenGLFunctions();
+}
+
+TextureHelper::~TextureHelper()
+{
+}
+
+GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFiltering, bool convert)
+{
+ if (image.isNull())
+ return 0;
+
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ if (convert) {
+ QImage glTexture = convertToGLFormat(image);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glTexture.width(), glTexture.height(),
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, glTexture.bits());
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(),
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
+ }
+ if (useTrilinearFiltering) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return textureId;
+}
+
+GLuint TextureHelper::createCubeMapTexture(const QImage &image, bool useTrilinearFiltering)
+{
+ if (image.isNull())
+ return 0;
+
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);
+ QImage glTexture = convertToGLFormat(image);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP, 0, GL_RGBA, glTexture.width(), glTexture.height(),
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, glTexture.bits());
+ if (useTrilinearFiltering) {
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ } else {
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return textureId;
+}
+
+GLuint TextureHelper::createSelectionBuffer(const QSize &size, GLuint &texture,
+ GLuint &depthTexture)
+{
+ GLuint framebuffer;
+
+ // Create frame buffer
+ glGenFramebuffers(1, &framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+ // Create texture for the selection buffer
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB,
+ GL_UNSIGNED_BYTE, NULL);
+
+ // Create texture object for the depth buffer
+ glGenTextures(1, &depthTexture);
+ glBindTexture(GL_TEXTURE_2D, depthTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width(), size.height(),
+ 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Attach texture to color attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+ // Attach texture to depth attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
+
+ // Verify that the frame buffer is complete
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Frame buffer creation failed" << status;
+ return 0;
+ }
+
+ // Restore the default framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return framebuffer;
+}
+
+GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuffer,
+ GLuint &depthBuffer)
+{
+ GLuint textureid;
+
+ // Create texture for the selection buffer
+ glGenTextures(1, &textureid);
+ glBindTexture(GL_TEXTURE_2D, textureid);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB,
+ GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Create render buffer
+ glGenRenderbuffers(1, &depthBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height());
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ // Create frame buffer
+ glGenFramebuffers(1, &frameBuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+
+ // Attach texture to color attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureid, 0);
+ // Attach renderbuffer to depth attachment
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
+
+ // Verify that the frame buffer is complete
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Frame buffer creation failed" << status;
+ return 0;
+ }
+
+ // Restore the default framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return textureid;
+}
+
+GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer, GLuint textureSize)
+{
+ GLuint depthtextureid;
+
+ // Create depth texture for the shadow mapping
+ glGenTextures(1, &depthtextureid);
+ glBindTexture(GL_TEXTURE_2D, depthtextureid);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ // Use the following line if using shader's version 2 of shadowing, comment out if not
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size.width() * textureSize,
+ size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Create frame buffer
+ glGenFramebuffers(1, &frameBuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+
+ // Attach texture to depth attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthtextureid, 0);
+
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+
+ // Verify that the frame buffer is complete
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Frame buffer creation failed" << status;
+ return 0;
+ }
+
+ // Restore the default framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return depthtextureid;
+}
+
+void TextureHelper::deleteTexture(const GLuint *texture)
+{
+ glDeleteTextures(1, texture);
+}
+
+QImage TextureHelper::convertToGLFormat(const QImage &srcImage)
+{
+ QImage res(srcImage.size(), QImage::Format_ARGB32);
+ convertToGLFormatHelper(res, srcImage.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
+ return res;
+}
+
+void TextureHelper::convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage,
+ GLenum texture_format)
+{
+ Q_ASSERT(dstImage.depth() == 32);
+ Q_ASSERT(srcImage.depth() == 32);
+
+ if (dstImage.size() != srcImage.size()) {
+ int target_width = dstImage.width();
+ int target_height = dstImage.height();
+ qreal sx = target_width / qreal(srcImage.width());
+ qreal sy = target_height / qreal(srcImage.height());
+
+ quint32 *dest = (quint32 *) dstImage.scanLine(0); // NB! avoid detach here
+ uchar *srcPixels = (uchar *) srcImage.scanLine(srcImage.height() - 1);
+ int sbpl = srcImage.bytesPerLine();
+ int dbpl = dstImage.bytesPerLine();
+
+ int ix = int(0x00010000 / sx);
+ int iy = int(0x00010000 / sy);
+
+ quint32 basex = int(0.5 * ix);
+ quint32 srcy = int(0.5 * iy);
+
+ // scale, swizzle and mirror in one loop
+ while (target_height--) {
+ const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
+ int srcx = basex;
+ for (int x=0; x<target_width; ++x) {
+ dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
+ srcx += ix;
+ }
+ dest = (quint32 *)(((uchar *) dest) + dbpl);
+ srcy += iy;
+ }
+ } else {
+ const int width = srcImage.width();
+ const int height = srcImage.height();
+ const uint *p = (const uint*) srcImage.scanLine(srcImage.height() - 1);
+ uint *q = (uint*) dstImage.scanLine(0);
+
+ if (texture_format == GL_BGRA) {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ // mirror + swizzle
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = ((*p << 24) & 0xff000000)
+ | ((*p >> 24) & 0x000000ff)
+ | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ } else {
+ const uint bytesPerLine = srcImage.bytesPerLine();
+ for (int i=0; i < height; ++i) {
+ memcpy(q, p, bytesPerLine);
+ q += width;
+ p -= width;
+ }
+ }
+ } else {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = (*p << 8) | ((*p >> 24) & 0xff);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ } else {
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ }
+ }
+ }
+}
+
+QRgb TextureHelper::qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
+{
+ if (texture_format == GL_BGRA) {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return ((src_pixel << 24) & 0xff000000)
+ | ((src_pixel >> 24) & 0x000000ff)
+ | ((src_pixel << 8) & 0x00ff0000)
+ | ((src_pixel >> 8) & 0x0000ff00);
+ } else {
+ return src_pixel;
+ }
+ } else { // GL_RGBA
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
+ } else {
+ return ((src_pixel << 16) & 0xff0000)
+ | ((src_pixel >> 16) & 0xff)
+ | (src_pixel & 0xff00ff00);
+ }
+ }
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/texturehelper_p.h b/src/datavis3d/utils/texturehelper_p.h
new file mode 100644
index 00000000..4b420fa4
--- /dev/null
+++ b/src/datavis3d/utils/texturehelper_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef TEXTUREHELPER_P_H
+#define TEXTUREHELPER_P_H
+
+#include "qdatavis3dglobal.h"
+#include <QOpenGLFunctions>
+#include <QRgb>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class TextureHelper : protected QOpenGLFunctions
+{
+ public:
+ TextureHelper();
+ ~TextureHelper();
+
+ // Ownership of created texture is transferred to caller
+ GLuint create2DTexture(const QImage &image, bool useTrilinearFiltering = false,
+ bool convert = true);
+ GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
+ // Returns selection framebuffer and inserts generated texture id to texture parameters
+ GLuint createSelectionBuffer(const QSize &size, GLuint &texture, GLuint &depthTexture);
+ // Returns selection texture and inserts generated framebuffers to framebuffer parameters
+ GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer);
+ // Returns depth texture and inserts generated framebuffer to parameter
+ GLuint createDepthTexture(const QSize &size, GLuint &frameBuffer, GLuint textureSize = 1);
+ void deleteTexture(const GLuint *texture);
+
+ private:
+ QImage convertToGLFormat(const QImage &srcImage);
+ void convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage, GLenum texture_format);
+ QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format);
+
+ friend class Q3DBarsPrivate;
+ friend class Q3DMapsPrivate;
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/utils.cpp b/src/datavis3d/utils/utils.cpp
new file mode 100644
index 00000000..7b4cb6f6
--- /dev/null
+++ b/src/datavis3d/utils/utils.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "utils_p.h"
+
+#include <QVector3D>
+#include <QColor>
+#include <QPainter>
+#include <QPoint>
+#include <QImage>
+
+#include <qmath.h>
+
+#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+QVector3D Utils::vectorFromColor(const QColor &color)
+{
+ return QVector3D(color.redF(), color.greenF(), color.blueF());
+}
+
+void Utils::printText(QPainter *painter, const QString &text, const QSize &position,
+ bool absoluteCoords, qreal rotation, qreal scale)
+{
+ painter->save();
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ painter->setPen(Qt::black); // TODO: Use black, as nothing works
+ QFont bgrFont = QFont(QStringLiteral("Arial"), 17);
+ QFont valueFont = QFont(QStringLiteral("Arial"), 11);
+ valueFont.setBold(true);
+ painter->setFont(bgrFont);
+ QFontMetrics valueFM(valueFont);
+ QFontMetrics bgrFM(bgrFont);
+ int valueStrLen = valueFM.width(text);
+ int bgrStrLen = 0;
+ int bgrHeight = valueFM.height() + 8;
+ QString bgrStr = QString();
+ do {
+ bgrStr.append(QStringLiteral("I"));
+ bgrStrLen = bgrFM.width(bgrStr);
+ } while (bgrStrLen <= (valueStrLen + 8));
+#if 0
+ // Hack solution, as drawRect doesn't work
+ painter->drawText(position.width() - (bgrStrLen / 2),
+ position.height() - bgrHeight,
+ bgrStrLen, bgrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ bgrStr);
+ //painter->setPen(d_ptr->m_textColor);
+ painter->setPen(Qt::lightGray); // TODO: Use lightGray, as nothing works
+ painter->setFont(valueFont);
+ painter->drawText(position.width() - (valueStrLen / 2),
+ position.height() - bgrHeight,
+ valueStrLen, bgrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+#else
+ //qDebug() << painter->window() << painter->viewport();
+ painter->scale(scale, scale);
+ if (absoluteCoords) {
+ // This assumes absolute screen coordinates
+ painter->translate(position.width() - (((float)bgrStrLen / 2.0f)
+ * cos(rotation * m_pi / 180.0f))
+ + (((float)bgrHeight / 2.0f) * sin(rotation * m_pi / 180.0f)),
+ position.height()
+ - ((((float)bgrHeight / 2.0f) * cos(rotation * m_pi / 180.0f))
+ + (((float)bgrStrLen / 2.0f) * sin(rotation * m_pi / 180.0f))));
+ } else {
+ // This calculates y as a distance from screen bottom
+ painter->translate(position.width() - (((float)bgrStrLen / 2.0f)
+ * cos(rotation * m_pi / 180.0f))
+ + (((float)bgrHeight / 2.0f) * sin(rotation * m_pi / 180.0f)),
+ painter->window().height() - position.height()
+ - ((((float)bgrHeight / 2.0f) * cos(rotation * m_pi / 180.0f))
+ + (((float)bgrStrLen / 2.0f) * sin(rotation * m_pi / 180.0f))));
+ }
+ //qDebug() << painter->window().height() - position.height()
+ // - ((((float)bgrHeight / 2.0f) * cos(rotation * m_pi / 180.0f))
+ // + (((float)bgrStrLen / 2.0f) * sin(rotation * m_pi / 180.0f)));
+ painter->rotate(rotation);
+ painter->drawText(0, 0,
+ bgrStrLen, bgrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ bgrStr);
+ painter->setPen(Qt::lightGray); // TODO: Use lightGray, as nothing works
+ painter->setFont(valueFont);
+ painter->drawText(6, 0,
+ valueStrLen, bgrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+ painter->resetTransform();
+#endif
+ painter->restore();
+}
+
+QImage Utils::printTextToImage(const QFont &font, const QString &text, const QColor &bgrColor,
+ const QColor &txtColor, LabelTransparency transparency)
+{
+ // Calculate text dimensions
+ QFont valueFont = font;
+ valueFont.setPointSize(30);
+ QFontMetrics valueFM(valueFont);
+ int valueStrWidth = valueFM.width(text);
+ int valueStrHeight = valueFM.height();
+ QSize labelSize;
+ if (TransparencyNoBackground == transparency)
+ labelSize = QSize(valueStrWidth, valueStrHeight);
+ else
+ labelSize = QSize(valueStrWidth + 30, valueStrHeight + 30);
+
+ // Create image
+ QImage image = QImage(labelSize, QImage::Format_ARGB32);
+ image.fill(Qt::transparent);
+
+ // Init painter
+ QPainter painter(&image);
+ // Paint text
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ switch (transparency) {
+ case TransparencyNoBackground: {
+ painter.setFont(valueFont);
+ painter.setPen(txtColor);
+ painter.drawText(0, 0,
+ valueStrWidth, valueStrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+ break;
+ }
+ case TransparencyFromTheme: {
+ painter.setBrush(QBrush(bgrColor));
+ painter.setPen(bgrColor);
+ painter.drawRoundedRect(0, 0, labelSize.width(), labelSize.height(), 10.0, 10.0f);
+ painter.setFont(valueFont);
+ painter.setPen(txtColor);
+ painter.drawText(15, 15,
+ valueStrWidth, valueStrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+ break;
+ }
+ case TransparencyNone: {
+ painter.setBrush(QBrush(bgrColor));
+ painter.setPen(bgrColor);
+ painter.drawRect(0, 0, labelSize.width(), labelSize.height());
+ painter.setFont(valueFont);
+ painter.setPen(txtColor);
+ painter.drawText(15, 15,
+ valueStrWidth, valueStrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+ break;
+ }
+ }
+ return image;
+}
+
+QVector3D Utils::getSelection(QPoint mousepos, int height)
+{
+ QVector3D selectedColor;
+
+ // This is the only one that works with ANGLE (ES 2.0)
+ // Item count will be limited to 256*256*256
+ GLubyte pixel[4];
+ glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1,
+ GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel);
+
+ // These work with desktop OpenGL
+ // They offer a lot higher possible object count and a possibility to use object id's
+ //GLuint pixel2[3];
+ //glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1,
+ // GL_RGB, GL_UNSIGNED_INT, (void *)pixel2);
+
+ //GLfloat pixel3[3];
+ //glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1,
+ // GL_RGB, GL_FLOAT, (void *)pixel3);
+
+ //qDebug() << "rgba" << pixel[0] << pixel[1] << pixel[2];// << pixel[3];
+ //qDebug() << "rgba2" << pixel2[0] << pixel2[1] << pixel2[2];
+ //qDebug() << "rgba3" << pixel3[0] << pixel3[1] << pixel3[2];
+ selectedColor = QVector3D(pixel[0], pixel[1], pixel[2]);
+ //qDebug() << selectedColor;
+
+ return selectedColor;
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/utils.pri b/src/datavis3d/utils/utils.pri
new file mode 100644
index 00000000..566af55f
--- /dev/null
+++ b/src/datavis3d/utils/utils.pri
@@ -0,0 +1,15 @@
+HEADERS += $$PWD/meshloader_p.h \
+ $$PWD/vertexindexer_p.h \
+ $$PWD/camerahelper_p.h \
+ $$PWD/shaderhelper_p.h \
+ $$PWD/objecthelper_p.h \
+ $$PWD/texturehelper_p.h \
+ $$PWD/utils_p.h
+
+SOURCES += $$PWD/meshloader.cpp \
+ $$PWD/vertexindexer.cpp \
+ $$PWD/camerahelper.cpp \
+ $$PWD/shaderhelper.cpp \
+ $$PWD/objecthelper.cpp \
+ $$PWD/texturehelper.cpp \
+ $$PWD/utils.cpp
diff --git a/src/datavis3d/utils/utils_p.h b/src/datavis3d/utils/utils_p.h
new file mode 100644
index 00000000..1668ac40
--- /dev/null
+++ b/src/datavis3d/utils/utils_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef UTILS_P_H
+#define UTILS_P_H
+
+#include "qdatavis3dglobal.h"
+#include "qdatavis3namespace.h"
+#include "q3dbars.h"
+
+class QVector3D;
+class QColor;
+class QPainter;
+class QString;
+class QPoint;
+class QImage;
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class Utils
+{
+ public:
+ static QVector3D vectorFromColor(const QColor &color);
+ static void printText(QPainter *painter, const QString &text, const QSize &position,
+ bool absoluteCoords = true, qreal rotation = 0, qreal scale = 1.0f);
+ static QImage printTextToImage(const QFont &font,
+ const QString &text,
+ const QColor &bgrColor,
+ const QColor &txtColor,
+ LabelTransparency transparency);
+ static QVector3D getSelection(QPoint mousepos, int height);
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif
diff --git a/src/datavis3d/utils/vertexindexer.cpp b/src/datavis3d/utils/vertexindexer.cpp
new file mode 100644
index 00000000..7e5a863f
--- /dev/null
+++ b/src/datavis3d/utils/vertexindexer.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "vertexindexer_p.h"
+
+#include <string.h> // for memcmp
+#include <qmath.h>
+
+#include <QDebug>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+int unique_vertices = 0;
+
+// Returns true if v1 can be considered equal to v2
+bool VertexIndexer::is_near(float v1, float v2)
+{
+ return qFabs(v1 - v2) < 0.01f;
+}
+
+// Searches through all already-exported vertices
+// for a similar one.
+// Similar = same position + same UVs + same normal
+bool VertexIndexer::getSimilarVertexIndex(const QVector3D &in_vertex,
+ const QVector2D &in_uv,
+ const QVector3D &in_normal,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals,
+ unsigned short &result)
+{
+ // Lame linear search
+ for (int i = 0; i < out_vertices.size(); i++) {
+ if (is_near(in_vertex.x() , out_vertices[i].x())
+ && is_near(in_vertex.y() , out_vertices[i].y())
+ && is_near(in_vertex.z() , out_vertices[i].z())
+ && is_near(in_uv.x() , out_uvs [i].x())
+ && is_near(in_uv.y() , out_uvs [i].y())
+ && is_near(in_normal.x() , out_normals [i].x())
+ && is_near(in_normal.y() , out_normals [i].y())
+ && is_near(in_normal.z() , out_normals [i].z())) {
+ result = i;
+ return true;
+ }
+ }
+ // No other vertex could be used instead.
+ // Looks like we'll have to add it to the VBO.
+ return false;
+}
+
+bool VertexIndexer::getSimilarVertexIndex_fast(const PackedVertex &packed,
+ QMap<PackedVertex, unsigned short> &VertexToOutIndex,
+ unsigned short &result)
+{
+ QMap<PackedVertex, unsigned short>::iterator it = VertexToOutIndex.find(packed);
+ if (it == VertexToOutIndex.end()) {
+ return false;
+ } else {
+ result = it.value();
+ return true;
+ }
+}
+
+void VertexIndexer::indexVBO(const QVector<QVector3D> &in_vertices,
+ const QVector<QVector2D> &in_uvs,
+ const QVector<QVector3D> &in_normals,
+ QVector<unsigned short> &out_indices,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals)
+{
+ unique_vertices = 0;
+ QMap<PackedVertex, unsigned short> VertexToOutIndex;
+
+ // For each input vertex
+ for (int i = 0; i < in_vertices.size(); i++) {
+ PackedVertex packed = {in_vertices[i], in_uvs[i], in_normals[i]};
+
+ // Try to find a similar vertex in out_XXXX
+ unsigned short index;
+ bool found = getSimilarVertexIndex_fast(packed, VertexToOutIndex, index);
+
+ if (found) {
+ out_indices.append(index);
+ } else {
+ unique_vertices++;
+ out_vertices.append(in_vertices[i]);
+ out_uvs.append(in_uvs[i]);
+ out_normals.append(in_normals[i]);
+ unsigned short newindex = (unsigned short)out_vertices.size() - 1;
+ out_indices.append(newindex);
+ VertexToOutIndex[packed] = newindex;
+ }
+ }
+ //qDebug() << "unique vertices" << unique_vertices;
+}
+
+void VertexIndexer::indexVBO_TBN(const QVector<QVector3D> &in_vertices,
+ const QVector<QVector2D> &in_uvs,
+ const QVector<QVector3D> &in_normals,
+ const QVector<QVector3D> &in_tangents,
+ const QVector<QVector3D> &in_bitangents,
+ QVector<unsigned short> &out_indices,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals,
+ QVector<QVector3D> &out_tangents,
+ QVector<QVector3D> &out_bitangents)
+{
+ unique_vertices = 0;
+ // For each input vertex
+ for (int i = 0; i < in_vertices.size(); i++) {
+
+ // Try to find a similar vertex in out_XXXX
+ unsigned short index;
+ bool found = getSimilarVertexIndex(in_vertices[i], in_uvs[i], in_normals[i],
+ out_vertices, out_uvs, out_normals, index);
+
+ if (found) {
+ out_indices.append(index);
+
+ // Average the tangents and the bitangents
+ out_tangents[index] += in_tangents[i];
+ out_bitangents[index] += in_bitangents[i];
+ } else {
+ unique_vertices++;
+ out_vertices.append(in_vertices[i]);
+ out_uvs.append(in_uvs[i]);
+ out_normals.append(in_normals[i]);
+ out_tangents.append(in_tangents[i]);
+ out_bitangents.append(in_bitangents[i]);
+ out_indices.append((unsigned short)out_vertices.size() - 1);
+ }
+ }
+ //qDebug() << "unique vertices" << unique_vertices;
+}
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
diff --git a/src/datavis3d/utils/vertexindexer_p.h b/src/datavis3d/utils/vertexindexer_p.h
new file mode 100644
index 00000000..3ee908af
--- /dev/null
+++ b/src/datavis3d/utils/vertexindexer_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtDataVis3D module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef VERTEXINDEXER_P_H
+#define VERTEXINDEXER_P_H
+
+#include "qdatavis3dglobal.h"
+
+#include <QVector>
+#include <QVector2D>
+#include <QVector3D>
+
+QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
+
+class VertexIndexer
+{
+ public:
+ struct PackedVertex {
+ QVector3D position;
+ QVector2D uv;
+ QVector3D normal;
+ bool operator<(const PackedVertex that) const {
+ return memcmp((void*)this, (void*)&that, sizeof(PackedVertex)) > 0;
+ }
+ };
+
+ static void indexVBO(const QVector<QVector3D> &in_vertices,
+ const QVector<QVector2D> &in_uvs,
+ const QVector<QVector3D> &in_normals,
+ QVector<unsigned short> &out_indices,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals);
+
+ static void indexVBO_TBN(const QVector<QVector3D> &in_vertices,
+ const QVector<QVector2D> &in_uvs,
+ const QVector<QVector3D> &in_normals,
+ const QVector<QVector3D> &in_tangents,
+ const QVector<QVector3D> &in_bitangents,
+ QVector<unsigned short> &out_indices,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals,
+ QVector<QVector3D> &out_tangents,
+ QVector<QVector3D> &out_bitangents);
+
+ private:
+ static bool is_near(float v1, float v2);
+ static bool getSimilarVertexIndex(const QVector3D &in_vertex,
+ const QVector2D &in_uv,
+ const QVector3D &in_normal,
+ QVector<QVector3D> &out_vertices,
+ QVector<QVector2D> &out_uvs,
+ QVector<QVector3D> &out_normals,
+ unsigned short &result);
+ static bool getSimilarVertexIndex_fast(const PackedVertex &packed,
+ QMap<PackedVertex, unsigned short> &VertexToOutIndex,
+ unsigned short &result);
+};
+
+QTCOMMERCIALDATAVIS3D_END_NAMESPACE
+
+#endif