diff options
Diffstat (limited to 'src/datavis3d/engine')
57 files changed, 11052 insertions, 0 deletions
diff --git a/src/datavis3d/engine/drawer.cpp b/src/datavis3d/engine/drawer.cpp new file mode 100644 index 00000000..722a54b8 --- /dev/null +++ b/src/datavis3d/engine/drawer.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** 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 "qdatavis3namespace.h" +#include "drawer_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "camerahelper_p.h" +#include "qdataitem.h" +#include "qdataitem_p.h" +#include "utils_p.h" +#include "texturehelper_p.h" +#include <QMatrix4x4> +#include <qmath.h> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +Drawer::Drawer(const Theme &theme, const QFont &font, LabelTransparency transparency) + : m_theme(theme), + m_font(font), + m_transparency(transparency), + m_textureHelper(new TextureHelper()) +{ + initializeOpenGLFunctions(); +} + +Drawer::~Drawer() +{ + +} + +void Drawer::setTheme(const Theme &theme) +{ + m_theme = theme; + emit drawerChanged(); +} + +void Drawer::setFont(const QFont &font) +{ + m_font = font; + emit drawerChanged(); +} + +void Drawer::setTransparency(LabelTransparency transparency) +{ + m_transparency = transparency; + emit drawerChanged(); +} + +void Drawer::drawObject(ShaderHelper *shader, ObjectHelper *object, GLuint textureId, + GLuint depthTextureId) +{ + if (textureId) { + // Activate texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textureId); + shader->setUniformValue(shader->texture(), 0); + } + + if (depthTextureId) { + // Activate depth texture + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, depthTextureId); + shader->setUniformValue(shader->shadow(), 1); + } + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(shader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); + glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + // 2nd attribute buffer : normals + glEnableVertexAttribArray(shader->normalAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->normalBuf()); + glVertexAttribPointer(shader->normalAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + if (textureId || depthTextureId) { + // 3rd attribute buffer : UVs + glEnableVertexAttribArray(shader->uvAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->uvBuf()); + glVertexAttribPointer(shader->uvAtt(), 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + } + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, object->indexCount(), GL_UNSIGNED_SHORT, (void*)0); + + // Free buffers + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + if (textureId || depthTextureId) { + glBindTexture(GL_TEXTURE_2D, 0); + glDisableVertexAttribArray(shader->uvAtt()); + } + glDisableVertexAttribArray(shader->normalAtt()); + glDisableVertexAttribArray(shader->posAtt()); +} + +void Drawer::drawLabel(const QDataItem &item, const LabelItem &label, + const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, + const QVector3D &positionComp, const QVector3D &rotation, + GLfloat maxHeight, SelectionMode mode, + ShaderHelper *shader, ObjectHelper *object, bool useDepth, bool rotateAlong, + LabelPosition position, Qt::AlignmentFlag alignment) +{ + // Draw label + LabelItem labelItem = label; + if (!labelItem.textureId()) + return; // No texture, skip + + QSize textureSize = labelItem.size(); + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + GLfloat xPosition; + GLfloat yPosition; + GLfloat zPosition = positionComp.z(); + + switch (position) { + case LabelBelow: { + yPosition = -1.6f; // minus maximum negative height (+ some extra for label) + break; + } + case LabelLow: { + yPosition = -positionComp.y(); + break; + } + case LabelMid: { + // Use this for positioning with absolute item y position value + yPosition = item.d_ptr->translation().y(); + break; + } + case LabelHigh: { + // TODO: Fix this. Can't seem to get it right (if ok with positive-only bars, doesn't look good on +- and vice versa) + yPosition = item.d_ptr->translation().y() + (item.d_ptr->value() / maxHeight) / 2.0f; + break; + } + case LabelOver: { + float mod = 0.1f; + if (item.d_ptr->value() < 0) + mod = -0.1f; + yPosition = item.d_ptr->translation().y() - (positionComp.y() / 2.0f - 0.2f) + + (item.d_ptr->value() / maxHeight) + mod; + break; + } + case LabelBottom: { + yPosition = -1.95f; // TODO: Calculate from scene + xPosition = 0.0f; + break; + } + case LabelTop: { + yPosition = 1.95f; // TODO: Calculate from scene + xPosition = 0.0f; + break; + } + case LabelLeft: { + yPosition = 0.0f; + xPosition = -2.5f; // TODO: Calculate from scene + break; + } + case LabelRight: { + yPosition = 0.0f; + xPosition = 2.5f; // TODO: Calculate from scene + break; + } + } + + // Calculate scale factor to get uniform font size + GLfloat scaledFontSize = 0.05f + m_font.pointSizeF() / 500.0f; + GLfloat scaleFactor = scaledFontSize / (GLfloat)textureSize.height(); + + // Apply alignment + GLfloat xAlignment = 0.0f; + GLfloat zAlignment = 0.0f; + switch (alignment) { + case Qt::AlignLeft: { + xAlignment = (-(GLfloat)textureSize.width() * scaleFactor) + * qFabs(cos(rotation.y() * m_pi / 180.0f)); + zAlignment = ((GLfloat)textureSize.width() * scaleFactor) + * qFabs(sin(rotation.y() * m_pi / 180.0f)); + break; + } + case Qt::AlignRight: { + xAlignment = ((GLfloat)textureSize.width() * scaleFactor) + * qFabs(cos(rotation.y() * m_pi / 180.0f)); + zAlignment = (-(GLfloat)textureSize.width() * scaleFactor) + * qFabs(sin(rotation.y() * m_pi / 180.0f)); + break; + } + default: { + break; + } + } + + if (position < LabelBottom) { + xPosition = item.d_ptr->translation().x(); + if (useDepth) + zPosition = item.d_ptr->translation().z(); + else if (ModeZoomColumn == mode) + xPosition = -(item.d_ptr->translation().z()) + positionComp.z(); // flip first to left + } + + // Position label + modelMatrix.translate(xPosition + xAlignment, yPosition, zPosition + zAlignment); + + // Rotate + modelMatrix.rotate(rotation.z(), 0.0f, 0.0f, 1.0f); + modelMatrix.rotate(rotation.y(), 0.0f, 1.0f, 0.0f); + modelMatrix.rotate(rotation.x(), 1.0f, 0.0f, 0.0f); + + if (useDepth && !rotateAlong) { + // Apply negative camera rotations to keep labels facing camera + QPointF camRotations = CameraHelper::getCameraRotations(); + modelMatrix.rotate(-camRotations.x(), 0.0f, 1.0f, 0.0f); + modelMatrix.rotate(-camRotations.y(), 1.0f, 0.0f, 0.0f); + } + + // Scale label based on text size + modelMatrix.scale(QVector3D((GLfloat)textureSize.width() * scaleFactor, + scaledFontSize, + 0.0f)); + + MVPMatrix = projectionmatrix * viewmatrix * modelMatrix; + + // Set shader bindings + shader->setUniformValue(shader->MVP(), MVPMatrix); + + // Draw the object + drawObject(shader, object, labelItem.textureId()); +} + +void Drawer::generateLabelTexture(QDataItem *item) +{ + LabelItem labelItem = item->d_ptr->label(); + generateLabelItem(&labelItem, item->d_ptr->valueStr()); + item->d_ptr->setLabel(labelItem); +} + +void Drawer::generateLabelItem(LabelItem *item, const QString &text) +{ + // Delete previous texture, if there is one + GLuint labelTexture = item->textureId(); + if (labelTexture) + glDeleteTextures(1, &labelTexture); + + // Create labels + // Print label into a QImage using QPainter + QImage label = Utils::printTextToImage(m_font, + text, + m_theme.m_textBackgroundColor, + m_theme.m_textColor, + m_transparency); + + // Set label size + item->setSize(label.size()); + // Insert text texture into label + item->setTextureId(m_textureHelper->create2DTexture(label, true, true)); +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/drawer_p.h b/src/datavis3d/engine/drawer_p.h new file mode 100644 index 00000000..3b6a2c49 --- /dev/null +++ b/src/datavis3d/engine/drawer_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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 DRAWER_P_H +#define DRAWER_P_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include "QtDataVis3D/qdatavis3namespace.h" +#include "q3dbars.h" +#include "theme_p.h" +#include "labelitem_p.h" +#include <QFont> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataItem; +class ShaderHelper; +class ObjectHelper; +class TextureHelper; + +class Drawer : public QObject, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + explicit Drawer(const Theme &theme, const QFont &font, LabelTransparency transparency); + ~Drawer(); + + void setTheme(const Theme &theme); + void setFont(const QFont &font); + void setTransparency(LabelTransparency transparency); + + void drawObject(ShaderHelper *shader, ObjectHelper *object, GLuint textureId = 0, + GLuint depthTextureId = 0); + void drawLabel(const QDataItem &item, const LabelItem &label, + const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, + const QVector3D &positionComp, const QVector3D &rotation, GLfloat maxHeight, + SelectionMode mode, ShaderHelper *shader, ObjectHelper *object, + bool useDepth = false, bool rotateAlong = false, + LabelPosition position = LabelOver, + Qt::AlignmentFlag alignment = Qt::AlignCenter); + + void generateLabelTexture(QDataItem *item); + void generateLabelItem(LabelItem *item, const QString &text); + +Q_SIGNALS: + void drawerChanged(); + +private: + Theme m_theme; + QFont m_font; + LabelTransparency m_transparency; + TextureHelper *m_textureHelper; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/engine.pri b/src/datavis3d/engine/engine.pri new file mode 100644 index 00000000..ba063186 --- /dev/null +++ b/src/datavis3d/engine/engine.pri @@ -0,0 +1,27 @@ +SOURCES += $$PWD/q3dwindow.cpp \ + $$PWD/q3dbars.cpp \ + $$PWD/q3dmaps.cpp \ + $$PWD/qdataitem.cpp \ + $$PWD/qdatarow.cpp \ + $$PWD/qdataset.cpp \ + $$PWD/theme.cpp \ + $$PWD/drawer.cpp \ + $$PWD/labelitem.cpp + +HEADERS += $$PWD/q3dwindow_p.h \ + $$PWD/q3dwindow.h \ + $$PWD/q3dbars.h \ + $$PWD/q3dbars_p.h \ + $$PWD/q3dmaps.h \ + $$PWD/q3dmaps_p.h \ + $$PWD/qdataitem.h \ + $$PWD/qdataitem_p.h \ + $$PWD/qdatarow.h \ + $$PWD/qdatarow_p.h \ + $$PWD/qdataset.h \ + $$PWD/qdataset_p.h \ + $$PWD/theme_p.h \ + $$PWD/drawer_p.h \ + $$PWD/labelitem_p.h + +RESOURCES += engine/engine.qrc diff --git a/src/datavis3d/engine/engine.qrc b/src/datavis3d/engine/engine.qrc new file mode 100644 index 00000000..beff232d --- /dev/null +++ b/src/datavis3d/engine/engine.qrc @@ -0,0 +1,38 @@ +<RCC> + <qresource prefix="/defaultMeshes"> + <file alias="cone">meshes/coneFlat.obj</file> + <file alias="coneSmooth">meshes/coneSmooth.obj</file> + <file alias="pyramid">meshes/pyramidFlat.obj</file> + <file alias="pyramidSmooth">meshes/pyramidSmooth.obj</file> + <file alias="bar">meshes/cubeFlat.obj</file> + <file alias="barSmooth">meshes/cubeSmooth.obj</file> + <file alias="cylinder">meshes/cylinderFlat.obj</file> + <file alias="cylinderSmooth">meshes/cylinderSmooth.obj</file> + <file alias="background">meshes/backgroudFlat.obj</file> + <file alias="backgroundSmooth">meshes/backgroudSmooth.obj</file> + <file alias="label">meshes/plane.obj</file> + <file alias="sphere">meshes/sphere.obj</file> + <file alias="sphereSmooth">meshes/sphereSmooth.obj</file> + </qresource> + <qresource prefix="/shaders"> + <file alias="fragment">shaders/fragmentShader</file> + <file alias="vertex">shaders/vertexShader</file> + <file alias="fragmentAmbient">shaders/fragmentShaderAmbient</file> + <file alias="fragmentColorOnY">shaders/fragmentShaderColorOnY</file> + <file alias="fragmentSelection">shaders/fragmentShaderSelection</file> + <file alias="vertexSelection">shaders/vertexShaderSelection</file> + <file alias="fragmentTexture">shaders/fragmentShaderTexture</file> + <file alias="vertexTexture">shaders/vertexShaderTexture</file> + <file alias="fragmentLabel">shaders/fragmentShaderLabel</file> + <file alias="vertexLabel">shaders/vertexShaderLabel</file> + <file alias="fragmentDepth">shaders/fragmentShaderDepth</file> + <file alias="vertexDepth">shaders/vertexShaderDepth</file> + <file alias="testDepthFrag">shaders/fragmentDepthTest</file> + <file alias="testDepthVert">shaders/vertexDepthTest</file> + <file alias="fragmentShadow">shaders/fragmentShadow</file> + <file alias="vertexShadow">shaders/vertexShadow</file> + <file alias="fragmentShadowNoTex">shaders/fragmentShadowNoTex</file> + <file alias="fragmentShadowNoTexColorOnY">shaders/fragmentShadowNoTexColorOnY</file> + </qresource> + <qresource prefix="/textures"/> +</RCC> diff --git a/src/datavis3d/engine/labelitem.cpp b/src/datavis3d/engine/labelitem.cpp new file mode 100644 index 00000000..6ce0663c --- /dev/null +++ b/src/datavis3d/engine/labelitem.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 "labelitem_p.h" + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +LabelItem::LabelItem() + : m_size(QSize(0, 0)), + m_textureId(0) +{ +} + +LabelItem::~LabelItem() +{ +} + +void LabelItem::setSize(const QSize &size) +{ + m_size = size; +} + +QSize LabelItem::size() +{ + return m_size; +} + +void LabelItem::setTextureId(GLuint textureId) +{ + m_textureId = textureId; +} + +GLuint LabelItem::textureId() +{ + return m_textureId; +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/labelitem_p.h b/src/datavis3d/engine/labelitem_p.h new file mode 100644 index 00000000..49693631 --- /dev/null +++ b/src/datavis3d/engine/labelitem_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 LABELITEM_P_H +#define LABELITEM_P_H + +#include "qdatavis3dglobal.h" +#include <QOpenGLFunctions> +#include <QSize> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class LabelItem +{ +public: + explicit LabelItem(); + ~LabelItem(); + + void setSize(const QSize &size); + QSize size(); + void setTextureId(GLuint textureId); + GLuint textureId(); + +private: + QSize m_size; + GLuint m_textureId; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/meshes/backgroudFlat.obj b/src/datavis3d/engine/meshes/backgroudFlat.obj new file mode 100644 index 00000000..cf4d10a5 --- /dev/null +++ b/src/datavis3d/engine/meshes/backgroudFlat.obj @@ -0,0 +1,32 @@ +# Blender v2.66 (sub 0) OBJ File: 'backgroud.blend' +# www.blender.org +o Cube +v 1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v 0.999999 1.000000 1.000001 +v -1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +vt 0.000000 0.501529 +vt 0.001529 1.000000 +vt 0.500000 0.998471 +vt 0.501529 0.500000 +vt 1.000000 0.498471 +vt 0.998471 0.000000 +vt 0.500000 0.498471 +vt 0.498471 0.000000 +vt 0.000000 0.001529 +vt 0.498471 0.500000 +vt 0.500000 0.001529 +vt 0.001529 0.500000 +vn -0.000000 1.000000 0.000000 +vn 0.000000 -0.000000 -1.000000 +vn 1.000000 0.000000 0.000000 +s off +f 1/1/1 4/2/1 3/3/1 +f 2/4/2 3/5/2 6/6/2 +f 3/7/3 4/8/3 7/9/3 +f 2/10/1 1/1/1 3/3/1 +f 5/11/2 2/4/2 6/6/2 +f 6/12/3 3/7/3 7/9/3 diff --git a/src/datavis3d/engine/meshes/backgroudSmooth.obj b/src/datavis3d/engine/meshes/backgroudSmooth.obj new file mode 100644 index 00000000..ad16d904 --- /dev/null +++ b/src/datavis3d/engine/meshes/backgroudSmooth.obj @@ -0,0 +1,36 @@ +# Blender v2.66 (sub 0) OBJ File: 'backgroud.blend' +# www.blender.org +o Cube +v 1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v 0.999999 1.000000 1.000001 +v -1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +vt 0.000000 0.501529 +vt 0.001529 1.000000 +vt 0.500000 0.998471 +vt 0.501529 0.500000 +vt 1.000000 0.498471 +vt 0.998471 0.000000 +vt 0.500000 0.498471 +vt 0.498471 0.000000 +vt 0.000000 0.001529 +vt 0.498471 0.500000 +vt 0.500000 0.001529 +vt 0.001529 0.500000 +vn 0.000000 0.999969 0.000000 +vn 0.707083 0.707083 0.000000 +vn 0.577349 0.577349 -0.577349 +vn 0.000000 0.707083 -0.707083 +vn 0.707083 0.000000 -0.707083 +vn 0.999969 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +s 1 +f 1/1/1 4/2/2 3/3/3 +f 2/4/4 3/5/3 6/6/5 +f 3/7/3 4/8/2 7/9/6 +f 2/10/4 1/1/1 3/3/3 +f 5/11/7 2/4/4 6/6/5 +f 6/12/5 3/7/3 7/9/6 diff --git a/src/datavis3d/engine/meshes/coneFlat.obj b/src/datavis3d/engine/meshes/coneFlat.obj new file mode 100644 index 00000000..51c3821e --- /dev/null +++ b/src/datavis3d/engine/meshes/coneFlat.obj @@ -0,0 +1,89 @@ +# Blender v2.66 (sub 0) OBJ File: 'cone.blend' +# www.blender.org +o Cone_Cone.001 +v 0.000000 -1.000000 -1.000000 +v 0.309017 -1.000000 -0.951057 +v 0.587785 -1.000000 -0.809017 +v 0.809017 -1.000000 -0.587785 +v 0.951057 -1.000000 -0.309017 +v 1.000000 -1.000000 0.000000 +v 0.951056 -1.000000 0.309017 +v 0.809017 -1.000000 0.587785 +v 0.000000 1.000000 0.000000 +v 0.587785 -1.000000 0.809017 +v 0.309017 -1.000000 0.951057 +v -0.000000 -1.000000 1.000000 +v -0.309017 -1.000000 0.951056 +v -0.587786 -1.000000 0.809017 +v -0.809017 -1.000000 0.587785 +v -0.951057 -1.000000 0.309016 +v -1.000000 -1.000000 -0.000001 +v -0.951056 -1.000000 -0.309018 +v -0.809016 -1.000000 -0.587786 +v -0.587784 -1.000000 -0.809018 +v -0.309016 -1.000000 -0.951057 +vt 0.018984 0.308330 +vt 0.500000 0.482045 +vt 0.000000 0.410924 +vt 0.011213 0.505476 +vt 0.051524 0.582730 +vt 0.116989 0.635124 +vt 0.066306 0.207736 +vt 0.137334 0.118990 +vt 0.225115 0.050777 +vt 0.321057 0.009776 +vt 0.415768 0.000000 +vt 0.499978 0.022406 +vt 0.551525 0.582730 +vt 1.000000 0.482045 +vt 0.616989 0.635125 +vt 0.511213 0.505476 +vt 0.500000 0.410924 +vt 0.518984 0.308330 +vt 0.566306 0.207736 +vt 0.637334 0.118990 +vt 0.725115 0.050777 +vt 0.821057 0.009776 +vt 0.915768 0.000000 +vt 0.999978 0.022406 +vn -0.407058 0.442793 -0.798898 +vn 0.140263 0.442793 -0.885585 +vn -0.140262 0.442793 -0.885585 +vn 0.407059 0.442793 -0.798898 +vn -0.634008 0.442793 -0.634010 +vn -0.798897 0.442793 -0.407060 +vn -0.885585 0.442793 -0.140264 +vn -0.885585 0.442793 0.140262 +vn -0.798898 0.442793 0.407058 +vn -0.634009 0.442793 0.634009 +vn -0.407059 0.442793 0.798898 +vn -0.140263 0.442793 0.885585 +vn 0.140263 0.442793 0.885585 +vn 0.407059 0.442793 0.798898 +vn 0.634009 0.442793 0.634009 +vn 0.798898 0.442793 0.407059 +vn 0.885585 0.442793 0.140263 +vn 0.885585 0.442793 -0.140263 +vn 0.798898 0.442793 -0.407059 +vn 0.634009 0.442793 -0.634009 +s off +f 20/1/1 9/2/1 21/3/1 +f 1/4/2 9/2/2 2/5/2 +f 21/3/3 9/2/3 1/4/3 +f 2/5/4 9/2/4 3/6/4 +f 19/7/5 9/2/5 20/1/5 +f 18/8/6 9/2/6 19/7/6 +f 17/9/7 9/2/7 18/8/7 +f 16/10/8 9/2/8 17/9/8 +f 15/11/9 9/2/9 16/10/9 +f 14/12/10 9/2/10 15/11/10 +f 13/13/11 9/14/11 14/15/11 +f 12/16/12 9/14/12 13/13/12 +f 11/17/13 9/14/13 12/16/13 +f 10/18/14 9/14/14 11/17/14 +f 8/19/15 9/14/15 10/18/15 +f 7/20/16 9/14/16 8/19/16 +f 6/21/17 9/14/17 7/20/17 +f 5/22/18 9/14/18 6/21/18 +f 4/23/19 9/14/19 5/22/19 +f 3/24/20 9/14/20 4/23/20 diff --git a/src/datavis3d/engine/meshes/coneSmooth.obj b/src/datavis3d/engine/meshes/coneSmooth.obj new file mode 100644 index 00000000..48c48ba8 --- /dev/null +++ b/src/datavis3d/engine/meshes/coneSmooth.obj @@ -0,0 +1,90 @@ +# Blender v2.66 (sub 0) OBJ File: 'cone.blend' +# www.blender.org +o Cone_Cone.001 +v 0.000000 -1.000000 -1.000000 +v 0.309017 -1.000000 -0.951057 +v 0.587785 -1.000000 -0.809017 +v 0.809017 -1.000000 -0.587785 +v 0.951057 -1.000000 -0.309017 +v 1.000000 -1.000000 0.000000 +v 0.951056 -1.000000 0.309017 +v 0.809017 -1.000000 0.587785 +v 0.000000 1.000000 0.000000 +v 0.587785 -1.000000 0.809017 +v 0.309017 -1.000000 0.951057 +v -0.000000 -1.000000 1.000000 +v -0.309017 -1.000000 0.951056 +v -0.587786 -1.000000 0.809017 +v -0.809017 -1.000000 0.587785 +v -0.951057 -1.000000 0.309016 +v -1.000000 -1.000000 -0.000001 +v -0.951056 -1.000000 -0.309018 +v -0.809016 -1.000000 -0.587786 +v -0.587784 -1.000000 -0.809018 +v -0.309016 -1.000000 -0.951057 +vt 0.018984 0.308330 +vt 0.500000 0.482045 +vt 0.000000 0.410924 +vt 0.011213 0.505476 +vt 0.051524 0.582730 +vt 0.116989 0.635124 +vt 0.066306 0.207736 +vt 0.137334 0.118990 +vt 0.225115 0.050777 +vt 0.321057 0.009776 +vt 0.415768 0.000000 +vt 0.499978 0.022406 +vt 0.551525 0.582730 +vt 1.000000 0.482045 +vt 0.616989 0.635125 +vt 0.511213 0.505476 +vt 0.500000 0.410924 +vt 0.518984 0.308330 +vt 0.566306 0.207736 +vt 0.637334 0.118990 +vt 0.725115 0.050777 +vt 0.821057 0.009776 +vt 0.915768 0.000000 +vt 0.999978 0.022406 +vn -0.525712 0.447188 -0.723594 +vn 0.000000 1.000000 0.000000 +vn -0.276376 0.447188 -0.850642 +vn 0.000000 0.447188 -0.894406 +vn 0.276376 0.447188 -0.850642 +vn 0.525712 0.447188 -0.723594 +vn -0.723594 0.447188 -0.525712 +vn -0.850642 0.447188 -0.276376 +vn -0.894406 0.447188 0.000000 +vn -0.850642 0.447188 0.276376 +vn -0.723594 0.447188 0.525712 +vn -0.525712 0.447188 0.723594 +vn -0.276376 0.447188 0.850642 +vn 0.000000 0.447188 0.894406 +vn 0.276376 0.447188 0.850642 +vn 0.525712 0.447188 0.723594 +vn 0.723594 0.447188 0.525712 +vn 0.850642 0.447188 0.276376 +vn 0.894406 0.447188 0.000000 +vn 0.850642 0.447188 -0.276376 +vn 0.723594 0.447188 -0.525712 +s 1 +f 20/1/1 9/2/2 21/3/3 +f 1/4/4 9/2/2 2/5/5 +f 21/3/3 9/2/2 1/4/4 +f 2/5/5 9/2/2 3/6/6 +f 19/7/7 9/2/2 20/1/1 +f 18/8/8 9/2/2 19/7/7 +f 17/9/9 9/2/2 18/8/8 +f 16/10/10 9/2/2 17/9/9 +f 15/11/11 9/2/2 16/10/10 +f 14/12/12 9/2/2 15/11/11 +f 13/13/13 9/14/2 14/15/12 +f 12/16/14 9/14/2 13/13/13 +f 11/17/15 9/14/2 12/16/14 +f 10/18/16 9/14/2 11/17/15 +f 8/19/17 9/14/2 10/18/16 +f 7/20/18 9/14/2 8/19/17 +f 6/21/19 9/14/2 7/20/18 +f 5/22/20 9/14/2 6/21/19 +f 4/23/21 9/14/2 5/22/20 +f 3/24/6 9/14/2 4/23/21 diff --git a/src/datavis3d/engine/meshes/cubeFlat.obj b/src/datavis3d/engine/meshes/cubeFlat.obj new file mode 100644 index 00000000..3c8d6d0a --- /dev/null +++ b/src/datavis3d/engine/meshes/cubeFlat.obj @@ -0,0 +1,47 @@ +# Blender v2.66 (sub 0) OBJ File: 'cube.blend' +# www.blender.org +o Cube +v -1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v 1.000000 1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +vt 0.998999 0.334334 +vt 0.667668 0.334334 +vt 0.998999 0.665666 +vt 0.332332 0.001001 +vt 0.001001 0.001001 +vt 0.332332 0.332332 +vt 0.332332 0.334334 +vt 0.001001 0.334334 +vt 0.001001 0.665666 +vt 0.665666 0.001001 +vt 0.334334 0.001001 +vt 0.334334 0.332332 +vt 0.665666 0.334334 +vt 0.334334 0.334334 +vt 0.334334 0.665666 +vt 0.667668 0.665666 +vt 0.001001 0.332332 +vt 0.332332 0.665666 +vt 0.665666 0.332332 +vt 0.665666 0.665666 +vn -1.000000 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 1.000000 -0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 1.000000 0.000000 +s off +f 5/1/1 6/2/1 1/3/1 +f 6/4/2 7/5/2 2/6/2 +f 7/7/3 8/8/3 4/9/3 +f 8/10/4 5/11/4 1/12/4 +f 8/13/5 7/14/5 6/15/5 +f 6/2/1 2/16/1 1/3/1 +f 7/5/2 3/17/2 2/6/2 +f 3/18/3 7/7/3 4/9/3 +f 4/19/4 8/10/4 1/12/4 +f 5/20/5 8/13/5 6/15/5 diff --git a/src/datavis3d/engine/meshes/cubeSmooth.obj b/src/datavis3d/engine/meshes/cubeSmooth.obj new file mode 100644 index 00000000..9d147bfd --- /dev/null +++ b/src/datavis3d/engine/meshes/cubeSmooth.obj @@ -0,0 +1,50 @@ +# Blender v2.66 (sub 0) OBJ File: 'cube.blend' +# www.blender.org +o Cube +v -1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v 1.000000 1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +vt 0.998999 0.334334 +vt 0.667668 0.334334 +vt 0.998999 0.665666 +vt 0.332332 0.001001 +vt 0.001001 0.001001 +vt 0.332332 0.332332 +vt 0.332332 0.334334 +vt 0.001001 0.334334 +vt 0.001001 0.665666 +vt 0.665666 0.001001 +vt 0.334334 0.001001 +vt 0.334334 0.332332 +vt 0.665666 0.334334 +vt 0.334334 0.334334 +vt 0.334334 0.665666 +vt 0.667668 0.665666 +vt 0.001001 0.332332 +vt 0.332332 0.665666 +vt 0.665666 0.332332 +vt 0.665666 0.665666 +vn -0.577349 0.577349 0.577349 +vn -0.577349 0.577349 -0.577349 +vn -0.707083 0.000000 0.707083 +vn 0.577349 0.577349 -0.577349 +vn -0.707083 0.000000 -0.707083 +vn 0.577349 0.577349 0.577349 +vn 0.707083 0.000000 0.707083 +vn 0.707083 0.000000 -0.707083 +s 1 +f 5/1/1 6/2/2 1/3/3 +f 6/4/2 7/5/4 2/6/5 +f 7/7/4 8/8/6 4/9/7 +f 8/10/6 5/11/1 1/12/3 +f 8/13/6 7/14/4 6/15/2 +f 6/2/2 2/16/5 1/3/3 +f 7/5/4 3/17/8 2/6/5 +f 3/18/8 7/7/4 4/9/7 +f 4/19/7 8/10/6 1/12/3 +f 5/20/1 8/13/6 6/15/2 diff --git a/src/datavis3d/engine/meshes/cylinderFlat.obj b/src/datavis3d/engine/meshes/cylinderFlat.obj new file mode 100644 index 00000000..2b7e3e5e --- /dev/null +++ b/src/datavis3d/engine/meshes/cylinderFlat.obj @@ -0,0 +1,299 @@ +# Blender v2.66 (sub 0) OBJ File: 'cylinder.blend' +# www.blender.org +o Cylinder +v 0.000000 -1.000000 -1.000000 +v 0.000000 1.000000 -1.000000 +v 0.195090 -1.000000 -0.980785 +v 0.195090 1.000000 -0.980785 +v 0.382683 -1.000000 -0.923880 +v 0.382683 1.000000 -0.923880 +v 0.555570 -1.000000 -0.831470 +v 0.555570 1.000000 -0.831470 +v 0.707107 -1.000000 -0.707107 +v 0.707107 1.000000 -0.707107 +v 0.831470 -1.000000 -0.555570 +v 0.831470 1.000000 -0.555570 +v 0.923880 -1.000000 -0.382683 +v 0.923880 1.000000 -0.382683 +v 0.980785 -1.000000 -0.195090 +v 0.980785 1.000000 -0.195090 +v 1.000000 -1.000000 -0.000000 +v 1.000000 1.000000 -0.000000 +v 0.980785 -1.000000 0.195090 +v 0.980785 1.000000 0.195090 +v 0.923880 -1.000000 0.382683 +v 0.923880 1.000000 0.382683 +v 0.831470 -1.000000 0.555570 +v 0.831470 1.000000 0.555570 +v 0.707107 -1.000000 0.707107 +v 0.707107 1.000000 0.707107 +v 0.555570 -1.000000 0.831470 +v 0.555570 1.000000 0.831470 +v 0.382683 -1.000000 0.923880 +v 0.382683 1.000000 0.923880 +v 0.195090 -1.000000 0.980785 +v 0.195090 1.000000 0.980785 +v -0.000000 -1.000000 1.000000 +v -0.000000 1.000000 1.000000 +v -0.195091 -1.000000 0.980785 +v -0.195091 1.000000 0.980785 +v -0.382684 -1.000000 0.923879 +v -0.382684 1.000000 0.923879 +v -0.555571 -1.000000 0.831469 +v -0.555571 1.000000 0.831469 +v -0.707107 -1.000000 0.707106 +v -0.707107 1.000000 0.707106 +v -0.831470 -1.000000 0.555570 +v -0.831470 1.000000 0.555570 +v -0.923880 -1.000000 0.382683 +v -0.923880 1.000000 0.382683 +v -0.980785 -1.000000 0.195089 +v -0.980785 1.000000 0.195089 +v -1.000000 -1.000000 -0.000001 +v -1.000000 1.000000 -0.000001 +v -0.980785 -1.000000 -0.195091 +v -0.980785 1.000000 -0.195091 +v -0.923879 -1.000000 -0.382684 +v -0.923879 1.000000 -0.382684 +v -0.831469 -1.000000 -0.555571 +v -0.831469 1.000000 -0.555571 +v -0.707106 -1.000000 -0.707108 +v -0.707106 1.000000 -0.707108 +v -0.555569 -1.000000 -0.831470 +v -0.555569 1.000000 -0.831470 +v -0.382682 -1.000000 -0.923880 +v -0.382682 1.000000 -0.923880 +v -0.195089 -1.000000 -0.980786 +v -0.195089 1.000000 -0.980786 +vt 0.289718 0.879351 +vt 0.288367 0.438844 +vt 0.330714 0.438714 +vt 0.332066 0.879221 +vt 0.370605 0.438592 +vt 0.371956 0.879099 +vt 0.406505 0.438482 +vt 0.407857 0.878988 +vt 0.437036 0.438388 +vt 0.778904 0.000000 +vt 0.780256 0.440507 +vt 0.749725 0.440601 +vt 0.748373 0.000094 +vt 0.713824 0.440711 +vt 0.712473 0.000204 +vt 0.673934 0.440833 +vt 0.672582 0.000326 +vt 0.631586 0.440963 +vt 0.630235 0.000456 +vt 0.588409 0.441095 +vt 0.587057 0.000588 +vt 0.546061 0.441225 +vt 0.544710 0.000718 +vt 0.506171 0.441348 +vt 0.504819 0.000841 +vt 0.470270 0.441458 +vt 0.468919 0.000951 +vt 0.439739 0.441552 +vt 0.720545 0.882916 +vt 0.719194 0.442409 +vt 0.755094 0.442299 +vt 0.756446 0.882806 +vt 0.794985 0.442176 +vt 0.796336 0.882683 +vt 0.837333 0.442046 +vt 0.838684 0.882553 +vt 0.881861 0.882421 +vt 0.880510 0.441914 +vt 0.924209 0.882291 +vt 0.922857 0.441784 +vt 0.964099 0.882168 +vt 0.962748 0.441662 +vt 1.000000 0.882058 +vt 0.717842 0.441552 +vt 0.719194 0.882058 +vt 0.681942 0.441662 +vt 0.683293 0.882169 +vt 0.642051 0.441784 +vt 0.643403 0.882291 +vt 0.599704 0.441914 +vt 0.601055 0.882421 +vt 0.556526 0.442046 +vt 0.557878 0.882553 +vt 0.514179 0.442176 +vt 0.515530 0.882683 +vt 0.474288 0.442299 +vt 0.475640 0.882806 +vt 0.438388 0.442409 +vt 0.097872 0.879939 +vt 0.096520 0.439433 +vt 0.128403 0.879846 +vt 0.127051 0.439339 +vt 0.164303 0.879735 +vt 0.162952 0.439229 +vt 0.204194 0.879613 +vt 0.000000 0.197605 +vt 0.008423 0.155257 +vt 0.000000 0.240783 +vt 0.246541 0.879483 +vt 0.245190 0.438976 +vt 0.202842 0.439106 +vt 0.438388 0.878895 +vt 0.438388 0.001045 +vt 0.998649 0.441552 +vt 0.439739 0.882916 +vt 0.024947 0.115367 +vt 0.048935 0.079466 +vt 0.079466 0.048935 +vt 0.115366 0.024947 +vt 0.155257 0.008424 +vt 0.197605 0.000000 +vt 0.240782 0.000000 +vt 0.283130 0.008423 +vt 0.323021 0.024947 +vt 0.358922 0.048935 +vt 0.389453 0.079466 +vt 0.413441 0.115367 +vt 0.429964 0.155257 +vt 0.438388 0.197605 +vt 0.438388 0.240783 +vt 0.429964 0.283130 +vt 0.413441 0.323021 +vt 0.389453 0.358922 +vt 0.358922 0.389453 +vt 0.323021 0.413441 +vt 0.283130 0.429964 +vt 0.240783 0.438388 +vt 0.197605 0.438388 +vt 0.155257 0.429964 +vt 0.115367 0.413441 +vt 0.079466 0.389453 +vt 0.048935 0.358922 +vt 0.024947 0.323021 +vt 0.008423 0.283130 +vn 0.098017 0.000000 -0.995185 +vn 0.290285 0.000000 -0.956940 +vn 0.471397 0.000000 -0.881921 +vn 0.634393 0.000000 -0.773010 +vn 0.773010 0.000000 -0.634393 +vn 0.881921 0.000000 -0.471397 +vn 0.956940 0.000000 -0.290285 +vn 0.995185 0.000000 -0.098017 +vn 0.995185 0.000000 0.098017 +vn 0.956940 0.000000 0.290285 +vn 0.881921 0.000000 0.471396 +vn 0.773010 0.000000 0.634393 +vn 0.634393 0.000000 0.773010 +vn 0.471397 0.000000 0.881921 +vn 0.290284 0.000000 0.956940 +vn 0.098017 0.000000 0.995185 +vn -0.098018 0.000000 0.995185 +vn -0.290285 0.000000 0.956940 +vn -0.471397 0.000000 0.881921 +vn -0.634394 0.000000 0.773010 +vn -0.773011 0.000000 0.634393 +vn -0.881922 0.000000 0.471396 +vn -0.956941 0.000000 0.290284 +vn -0.995185 0.000000 0.098016 +vn -0.995185 -0.000000 -0.098018 +vn -0.956940 -0.000000 -0.290286 +vn -0.881921 -0.000000 -0.471398 +vn -0.773010 -0.000000 -0.634394 +vn -0.634392 -0.000000 -0.773011 +vn -0.471395 -0.000000 -0.881922 +vn -0.000000 1.000000 0.000000 +vn -0.098017 -0.000000 -0.995185 +vn -0.290283 -0.000000 -0.956941 +s off +f 1/1/1 2/2/1 4/3/1 +f 3/4/2 4/3/2 6/5/2 +f 5/6/3 6/5/3 8/7/3 +f 7/8/4 8/7/4 10/9/4 +f 9/10/5 10/11/5 12/12/5 +f 11/13/6 12/12/6 14/14/6 +f 13/15/7 14/14/7 16/16/7 +f 15/17/8 16/16/8 18/18/8 +f 17/19/9 18/18/9 20/20/9 +f 19/21/10 20/20/10 22/22/10 +f 21/23/11 22/22/11 24/24/11 +f 23/25/12 24/24/12 26/26/12 +f 25/27/13 26/26/13 28/28/13 +f 27/29/14 28/30/14 30/31/14 +f 29/32/15 30/31/15 32/33/15 +f 31/34/16 32/33/16 34/35/16 +f 33/36/17 34/35/17 35/37/17 +f 35/37/18 36/38/18 37/39/18 +f 37/39/19 38/40/19 39/41/19 +f 39/41/20 40/42/20 41/43/20 +f 41/44/21 42/45/21 43/46/21 +f 43/46/22 44/47/22 45/48/22 +f 45/48/23 46/49/23 47/50/23 +f 47/50/24 48/51/24 49/52/24 +f 49/52/25 50/53/25 51/54/25 +f 51/54/26 52/55/26 53/56/26 +f 53/56/27 54/57/27 55/58/27 +f 55/59/28 56/60/28 57/61/28 +f 57/61/29 58/62/29 59/63/29 +f 59/63/30 60/64/30 61/65/30 +f 4/66/31 2/67/31 6/68/31 +f 63/69/32 64/70/32 1/1/32 +f 61/65/33 62/71/33 63/69/33 +f 3/4/1 1/1/1 4/3/1 +f 5/6/2 3/4/2 6/5/2 +f 7/8/3 5/6/3 8/7/3 +f 9/72/4 7/8/4 10/9/4 +f 11/13/5 9/10/5 12/12/5 +f 13/15/6 11/13/6 14/14/6 +f 15/17/7 13/15/7 16/16/7 +f 17/19/8 15/17/8 18/18/8 +f 19/21/9 17/19/9 20/20/9 +f 21/23/10 19/21/10 22/22/10 +f 23/25/11 21/23/11 24/24/11 +f 25/27/12 23/25/12 26/26/12 +f 27/73/13 25/27/13 28/28/13 +f 29/32/14 27/29/14 30/31/14 +f 31/34/15 29/32/15 32/33/15 +f 33/36/16 31/34/16 34/35/16 +f 34/35/17 36/38/17 35/37/17 +f 36/38/18 38/40/18 37/39/18 +f 38/40/19 40/42/19 39/41/19 +f 40/42/20 42/74/20 41/43/20 +f 42/45/21 44/47/21 43/46/21 +f 44/47/22 46/49/22 45/48/22 +f 46/49/23 48/51/23 47/50/23 +f 48/51/24 50/53/24 49/52/24 +f 50/53/25 52/55/25 51/54/25 +f 52/55/26 54/57/26 53/56/26 +f 54/57/27 56/75/27 55/58/27 +f 56/60/28 58/62/28 57/61/28 +f 58/62/29 60/64/29 59/63/29 +f 60/64/30 62/71/30 61/65/30 +f 2/67/31 64/76/31 6/68/31 +f 64/76/31 62/77/31 6/68/31 +f 62/77/31 60/78/31 6/68/31 +f 60/78/31 58/79/31 6/68/31 +f 58/79/31 56/80/31 6/68/31 +f 56/80/31 54/81/31 6/68/31 +f 54/81/31 52/82/31 6/68/31 +f 52/82/31 50/83/31 6/68/31 +f 50/83/31 48/84/31 6/68/31 +f 48/84/31 46/85/31 6/68/31 +f 46/85/31 44/86/31 6/68/31 +f 44/86/31 42/87/31 6/68/31 +f 42/87/31 40/88/31 6/68/31 +f 40/88/31 38/89/31 6/68/31 +f 38/89/31 36/90/31 6/68/31 +f 36/90/31 34/91/31 6/68/31 +f 34/91/31 32/92/31 6/68/31 +f 32/92/31 30/93/31 6/68/31 +f 30/93/31 28/94/31 6/68/31 +f 28/94/31 26/95/31 6/68/31 +f 26/95/31 24/96/31 6/68/31 +f 24/96/31 22/97/31 6/68/31 +f 22/97/31 20/98/31 6/68/31 +f 20/98/31 18/99/31 6/68/31 +f 18/99/31 16/100/31 6/68/31 +f 16/100/31 14/101/31 6/68/31 +f 14/101/31 12/102/31 6/68/31 +f 12/102/31 10/103/31 8/104/31 +f 6/68/31 12/102/31 8/104/31 +f 64/70/32 2/2/32 1/1/32 +f 62/71/33 64/70/33 63/69/33 diff --git a/src/datavis3d/engine/meshes/cylinderSmooth.obj b/src/datavis3d/engine/meshes/cylinderSmooth.obj new file mode 100644 index 00000000..6ccbb286 --- /dev/null +++ b/src/datavis3d/engine/meshes/cylinderSmooth.obj @@ -0,0 +1,330 @@ +# Blender v2.66 (sub 0) OBJ File: 'cylinder.blend' +# www.blender.org +o Cylinder +v 0.000000 -1.000000 -1.000000 +v 0.000000 1.000000 -1.000000 +v 0.195090 -1.000000 -0.980785 +v 0.195090 1.000000 -0.980785 +v 0.382683 -1.000000 -0.923880 +v 0.382683 1.000000 -0.923880 +v 0.555570 -1.000000 -0.831470 +v 0.555570 1.000000 -0.831470 +v 0.707107 -1.000000 -0.707107 +v 0.707107 1.000000 -0.707107 +v 0.831470 -1.000000 -0.555570 +v 0.831470 1.000000 -0.555570 +v 0.923880 -1.000000 -0.382683 +v 0.923880 1.000000 -0.382683 +v 0.980785 -1.000000 -0.195090 +v 0.980785 1.000000 -0.195090 +v 1.000000 -1.000000 -0.000000 +v 1.000000 1.000000 -0.000000 +v 0.980785 -1.000000 0.195090 +v 0.980785 1.000000 0.195090 +v 0.923880 -1.000000 0.382683 +v 0.923880 1.000000 0.382683 +v 0.831470 -1.000000 0.555570 +v 0.831470 1.000000 0.555570 +v 0.707107 -1.000000 0.707107 +v 0.707107 1.000000 0.707107 +v 0.555570 -1.000000 0.831470 +v 0.555570 1.000000 0.831470 +v 0.382683 -1.000000 0.923880 +v 0.382683 1.000000 0.923880 +v 0.195090 -1.000000 0.980785 +v 0.195090 1.000000 0.980785 +v -0.000000 -1.000000 1.000000 +v -0.000000 1.000000 1.000000 +v -0.195091 -1.000000 0.980785 +v -0.195091 1.000000 0.980785 +v -0.382684 -1.000000 0.923879 +v -0.382684 1.000000 0.923879 +v -0.555571 -1.000000 0.831469 +v -0.555571 1.000000 0.831469 +v -0.707107 -1.000000 0.707106 +v -0.707107 1.000000 0.707106 +v -0.831470 -1.000000 0.555570 +v -0.831470 1.000000 0.555570 +v -0.923880 -1.000000 0.382683 +v -0.923880 1.000000 0.382683 +v -0.980785 -1.000000 0.195089 +v -0.980785 1.000000 0.195089 +v -1.000000 -1.000000 -0.000001 +v -1.000000 1.000000 -0.000001 +v -0.980785 -1.000000 -0.195091 +v -0.980785 1.000000 -0.195091 +v -0.923879 -1.000000 -0.382684 +v -0.923879 1.000000 -0.382684 +v -0.831469 -1.000000 -0.555571 +v -0.831469 1.000000 -0.555571 +v -0.707106 -1.000000 -0.707108 +v -0.707106 1.000000 -0.707108 +v -0.555569 -1.000000 -0.831470 +v -0.555569 1.000000 -0.831470 +v -0.382682 -1.000000 -0.923880 +v -0.382682 1.000000 -0.923880 +v -0.195089 -1.000000 -0.980786 +v -0.195089 1.000000 -0.980786 +vt 0.289718 0.879351 +vt 0.288367 0.438844 +vt 0.330714 0.438714 +vt 0.332066 0.879221 +vt 0.370605 0.438592 +vt 0.371956 0.879099 +vt 0.406505 0.438482 +vt 0.407857 0.878988 +vt 0.437036 0.438388 +vt 0.778904 0.000000 +vt 0.780256 0.440507 +vt 0.749725 0.440601 +vt 0.748373 0.000094 +vt 0.713824 0.440711 +vt 0.712473 0.000204 +vt 0.673934 0.440833 +vt 0.672582 0.000326 +vt 0.631586 0.440963 +vt 0.630235 0.000456 +vt 0.588409 0.441095 +vt 0.587057 0.000588 +vt 0.546061 0.441225 +vt 0.544710 0.000718 +vt 0.506171 0.441348 +vt 0.504819 0.000841 +vt 0.470270 0.441458 +vt 0.468919 0.000951 +vt 0.439739 0.441552 +vt 0.720545 0.882916 +vt 0.719194 0.442409 +vt 0.755094 0.442299 +vt 0.756446 0.882806 +vt 0.794985 0.442176 +vt 0.796336 0.882683 +vt 0.837333 0.442046 +vt 0.838684 0.882553 +vt 0.881861 0.882421 +vt 0.880510 0.441914 +vt 0.924209 0.882291 +vt 0.922857 0.441784 +vt 0.964099 0.882168 +vt 0.962748 0.441662 +vt 1.000000 0.882058 +vt 0.717842 0.441552 +vt 0.719194 0.882058 +vt 0.681942 0.441662 +vt 0.683293 0.882169 +vt 0.642051 0.441784 +vt 0.643403 0.882291 +vt 0.599704 0.441914 +vt 0.601055 0.882421 +vt 0.556526 0.442046 +vt 0.557878 0.882553 +vt 0.514179 0.442176 +vt 0.515530 0.882683 +vt 0.474288 0.442299 +vt 0.475640 0.882806 +vt 0.438388 0.442409 +vt 0.097872 0.879939 +vt 0.096520 0.439433 +vt 0.128403 0.879846 +vt 0.127051 0.439339 +vt 0.164303 0.879735 +vt 0.162952 0.439229 +vt 0.204194 0.879613 +vt 0.000000 0.197605 +vt 0.008423 0.155257 +vt 0.000000 0.240783 +vt 0.246541 0.879483 +vt 0.245190 0.438976 +vt 0.202842 0.439106 +vt 0.438388 0.878895 +vt 0.438388 0.001045 +vt 0.998649 0.441552 +vt 0.439739 0.882916 +vt 0.024947 0.115367 +vt 0.048935 0.079466 +vt 0.079466 0.048935 +vt 0.115366 0.024947 +vt 0.155257 0.008424 +vt 0.197605 0.000000 +vt 0.240782 0.000000 +vt 0.283130 0.008423 +vt 0.323021 0.024947 +vt 0.358922 0.048935 +vt 0.389453 0.079466 +vt 0.413441 0.115367 +vt 0.429964 0.155257 +vt 0.438388 0.197605 +vt 0.438388 0.240783 +vt 0.429964 0.283130 +vt 0.413441 0.323021 +vt 0.389453 0.358922 +vt 0.358922 0.389453 +vt 0.323021 0.413441 +vt 0.283130 0.429964 +vt 0.240783 0.438388 +vt 0.197605 0.438388 +vt 0.155257 0.429964 +vt 0.115367 0.413441 +vt 0.079466 0.389453 +vt 0.048935 0.358922 +vt 0.024947 0.323021 +vt 0.008423 0.283130 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.685690 -0.727866 +vn 0.142003 0.685690 -0.713889 +vn 0.195074 0.000000 -0.980773 +vn 0.278542 0.685690 -0.672475 +vn 0.382672 0.000000 -0.923856 +vn 0.404370 0.685690 -0.605213 +vn 0.555559 0.000000 -0.831446 +vn 0.514664 0.685690 -0.514664 +vn 0.707083 0.000000 -0.707083 +vn 0.605213 0.685690 -0.404370 +vn 0.831446 0.000000 -0.555559 +vn 0.672475 0.685690 -0.278542 +vn 0.923856 0.000000 -0.382672 +vn 0.713889 0.685690 -0.142003 +vn 0.980773 0.000000 -0.195074 +vn 0.727866 0.685690 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.713889 0.685690 0.142003 +vn 0.980773 0.000000 0.195074 +vn 0.672475 0.685690 0.278542 +vn 0.923856 0.000000 0.382672 +vn 0.605213 0.685690 0.404370 +vn 0.831446 0.000000 0.555559 +vn 0.514664 0.685690 0.514664 +vn 0.707083 0.000000 0.707083 +vn 0.404370 0.685690 0.605213 +vn 0.555559 0.000000 0.831446 +vn 0.278542 0.685690 0.672475 +vn 0.382672 0.000000 0.923856 +vn 0.142003 0.685690 0.713889 +vn 0.195074 0.000000 0.980773 +vn 0.000000 0.685690 0.727866 +vn 0.000000 0.000000 0.999969 +vn -0.195074 0.000000 0.980773 +vn -0.142003 0.685690 0.713889 +vn -0.382672 0.000000 0.923856 +vn -0.278542 0.685690 0.672475 +vn -0.555559 0.000000 0.831446 +vn -0.404370 0.685690 0.605213 +vn -0.707083 0.000000 0.707083 +vn -0.514664 0.685690 0.514664 +vn -0.831446 0.000000 0.555559 +vn -0.605213 0.685690 0.404370 +vn -0.923856 0.000000 0.382672 +vn -0.672475 0.685690 0.278542 +vn -0.980773 0.000000 0.195074 +vn -0.713889 0.685690 0.142003 +vn -1.000000 0.000000 0.000000 +vn -0.727866 0.685690 0.000000 +vn -0.980773 0.000000 -0.195074 +vn -0.713889 0.685690 -0.142003 +vn -0.923856 0.000000 -0.382672 +vn -0.672475 0.685690 -0.278542 +vn -0.831446 0.000000 -0.555559 +vn -0.605213 0.685690 -0.404370 +vn -0.707083 0.000000 -0.707083 +vn -0.514664 0.685690 -0.514695 +vn -0.555559 0.000000 -0.831446 +vn -0.404370 0.685690 -0.605213 +vn -0.382672 0.000000 -0.923856 +vn -0.195074 0.000000 -0.980773 +vn -0.142003 0.685690 -0.713889 +vn -0.278542 0.685690 -0.672475 +s 1 +f 1/1/1 2/2/2 4/3/3 +f 3/4/4 4/3/3 6/5/5 +f 5/6/6 6/5/5 8/7/7 +f 7/8/8 8/7/7 10/9/9 +f 9/10/10 10/11/9 12/12/11 +f 11/13/12 12/12/11 14/14/13 +f 13/15/14 14/14/13 16/16/15 +f 15/17/16 16/16/15 18/18/17 +f 17/19/18 18/18/17 20/20/19 +f 19/21/20 20/20/19 22/22/21 +f 21/23/22 22/22/21 24/24/23 +f 23/25/24 24/24/23 26/26/25 +f 25/27/26 26/26/25 28/28/27 +f 27/29/28 28/30/27 30/31/29 +f 29/32/30 30/31/29 32/33/31 +f 31/34/32 32/33/31 34/35/33 +f 33/36/34 34/35/33 35/37/35 +f 35/37/35 36/38/36 37/39/37 +f 37/39/37 38/40/38 39/41/39 +f 39/41/39 40/42/40 41/43/41 +f 41/44/41 42/45/42 43/46/43 +f 43/46/43 44/47/44 45/48/45 +f 45/48/45 46/49/46 47/50/47 +f 47/50/47 48/51/48 49/52/49 +f 49/52/49 50/53/50 51/54/51 +f 51/54/51 52/55/52 53/56/53 +f 53/56/53 54/57/54 55/58/55 +f 55/59/55 56/60/56 57/61/57 +f 57/61/57 58/62/58 59/63/59 +f 59/63/59 60/64/60 61/65/61 +f 4/66/3 2/67/2 6/68/5 +f 63/69/62 64/70/63 1/1/1 +f 61/65/61 62/71/64 63/69/62 +f 3/4/4 1/1/1 4/3/3 +f 5/6/6 3/4/4 6/5/5 +f 7/8/8 5/6/6 8/7/7 +f 9/72/10 7/8/8 10/9/9 +f 11/13/12 9/10/10 12/12/11 +f 13/15/14 11/13/12 14/14/13 +f 15/17/16 13/15/14 16/16/15 +f 17/19/18 15/17/16 18/18/17 +f 19/21/20 17/19/18 20/20/19 +f 21/23/22 19/21/20 22/22/21 +f 23/25/24 21/23/22 24/24/23 +f 25/27/26 23/25/24 26/26/25 +f 27/73/28 25/27/26 28/28/27 +f 29/32/30 27/29/28 30/31/29 +f 31/34/32 29/32/30 32/33/31 +f 33/36/34 31/34/32 34/35/33 +f 34/35/33 36/38/36 35/37/35 +f 36/38/36 38/40/38 37/39/37 +f 38/40/38 40/42/40 39/41/39 +f 40/42/40 42/74/42 41/43/41 +f 42/45/42 44/47/44 43/46/43 +f 44/47/44 46/49/46 45/48/45 +f 46/49/46 48/51/48 47/50/47 +f 48/51/48 50/53/50 49/52/49 +f 50/53/50 52/55/52 51/54/51 +f 52/55/52 54/57/54 53/56/53 +f 54/57/54 56/75/56 55/58/55 +f 56/60/56 58/62/58 57/61/57 +f 58/62/58 60/64/60 59/63/59 +f 60/64/60 62/71/64 61/65/61 +f 2/67/2 64/76/63 6/68/5 +f 64/76/63 62/77/64 6/68/5 +f 62/77/64 60/78/60 6/68/5 +f 60/78/60 58/79/58 6/68/5 +f 58/79/58 56/80/56 6/68/5 +f 56/80/56 54/81/54 6/68/5 +f 54/81/54 52/82/52 6/68/5 +f 52/82/52 50/83/50 6/68/5 +f 50/83/50 48/84/48 6/68/5 +f 48/84/48 46/85/46 6/68/5 +f 46/85/46 44/86/44 6/68/5 +f 44/86/44 42/87/42 6/68/5 +f 42/87/42 40/88/40 6/68/5 +f 40/88/40 38/89/38 6/68/5 +f 38/89/38 36/90/36 6/68/5 +f 36/90/36 34/91/33 6/68/5 +f 34/91/33 32/92/31 6/68/5 +f 32/92/31 30/93/29 6/68/5 +f 30/93/29 28/94/27 6/68/5 +f 28/94/27 26/95/25 6/68/5 +f 26/95/25 24/96/23 6/68/5 +f 24/96/23 22/97/21 6/68/5 +f 22/97/21 20/98/19 6/68/5 +f 20/98/19 18/99/17 6/68/5 +f 18/99/17 16/100/15 6/68/5 +f 16/100/15 14/101/13 6/68/5 +f 14/101/13 12/102/11 6/68/5 +f 12/102/11 10/103/9 8/104/7 +f 6/68/5 12/102/11 8/104/7 +f 64/70/63 2/2/2 1/1/1 +f 62/71/64 64/70/63 63/69/62 diff --git a/src/datavis3d/engine/meshes/plane.obj b/src/datavis3d/engine/meshes/plane.obj new file mode 100644 index 00000000..96ac0dd7 --- /dev/null +++ b/src/datavis3d/engine/meshes/plane.obj @@ -0,0 +1,15 @@ +# Blender v2.66 (sub 0) OBJ File: 'plane.blend' +# www.blender.org +o Plane +v -1.000000 -1.000000 -0.000001 +v -1.000000 1.000000 -0.000000 +v 1.000000 -1.000000 0.000000 +v 1.000000 1.000000 0.000001 +vt 0.003058 1.000000 +vt 0.000000 0.003058 +vt 1.000000 0.996942 +vt 0.996942 0.000000 +vn -0.000001 -0.000001 1.000000 +s off +f 2/1/1 1/2/1 4/3/1 +f 1/2/1 3/4/1 4/3/1 diff --git a/src/datavis3d/engine/meshes/pyramidFlat.obj b/src/datavis3d/engine/meshes/pyramidFlat.obj new file mode 100644 index 00000000..35edb477 --- /dev/null +++ b/src/datavis3d/engine/meshes/pyramidFlat.obj @@ -0,0 +1,22 @@ +# Blender v2.66 (sub 0) OBJ File: 'pyramid.blend' +# www.blender.org +o Cone_Cone.001 +v 1.000000 -1.000000 -0.999999 +v 0.999999 -1.000000 1.000000 +v -1.000000 -1.000000 0.999999 +v 0.000000 1.000000 0.000000 +v -0.999999 -1.000000 -1.000000 +vt 0.999900 0.000100 +vt 0.500000 0.500000 +vt 0.000100 0.000100 +vt 0.000100 0.999900 +vt 0.999900 0.999900 +vn -0.894427 0.447214 -0.000000 +vn 0.894427 0.447213 0.000000 +vn 0.000000 0.447214 -0.894427 +vn -0.000000 0.447214 0.894427 +s off +f 3/1/1 4/2/1 5/3/1 +f 1/4/2 4/2/2 2/5/2 +f 5/3/3 4/2/3 1/4/3 +f 2/5/4 4/2/4 3/1/4 diff --git a/src/datavis3d/engine/meshes/pyramidSmooth.obj b/src/datavis3d/engine/meshes/pyramidSmooth.obj new file mode 100644 index 00000000..b11c8750 --- /dev/null +++ b/src/datavis3d/engine/meshes/pyramidSmooth.obj @@ -0,0 +1,23 @@ +# Blender v2.66 (sub 0) OBJ File: 'pyramid.blend' +# www.blender.org +o Cone_Cone.001 +v 1.000000 -1.000000 -0.999999 +v 0.999999 -1.000000 1.000000 +v -1.000000 -1.000000 0.999999 +v 0.000000 1.000000 0.000000 +v -0.999999 -1.000000 -1.000000 +vt 0.999900 0.000100 +vt 0.500000 0.500000 +vt 0.000100 0.000100 +vt 0.000100 0.999900 +vt 0.999900 0.999900 +vn -0.577349 0.577349 0.577349 +vn 0.000000 1.000000 0.000000 +vn -0.577349 0.577349 -0.577349 +vn 0.577349 0.577349 -0.577349 +vn 0.577349 0.577349 0.577349 +s 1 +f 3/1/1 4/2/2 5/3/3 +f 1/4/4 4/2/2 2/5/5 +f 5/3/3 4/2/2 1/4/4 +f 2/5/5 4/2/2 3/1/1 diff --git a/src/datavis3d/engine/meshes/sphere.obj b/src/datavis3d/engine/meshes/sphere.obj new file mode 100644 index 00000000..671a7bcc --- /dev/null +++ b/src/datavis3d/engine/meshes/sphere.obj @@ -0,0 +1,1301 @@ +# Blender v2.66 (sub 0) OBJ File: 'sphere.blend' +# www.blender.org +o Sphere +v -0.195090 0.980785 0.000000 +v -0.382683 0.923880 0.000000 +v -0.555570 0.831470 0.000000 +v -0.707107 0.707107 0.000000 +v -0.831470 0.555570 0.000000 +v -0.923880 0.382683 0.000000 +v -0.980785 0.195090 0.000000 +v -1.000000 0.000000 0.000000 +v -0.980785 -0.195090 0.000000 +v -0.923880 -0.382683 0.000000 +v -0.831470 -0.555570 0.000000 +v -0.707107 -0.707107 0.000000 +v -0.555570 -0.831470 0.000000 +v -0.382683 -0.923880 0.000000 +v -0.195090 -0.980785 0.000000 +v -0.180240 0.980785 -0.074658 +v -0.353553 0.923880 -0.146447 +v -0.513280 0.831470 -0.212608 +v -0.653281 0.707107 -0.270598 +v -0.768178 0.555570 -0.318190 +v -0.853553 0.382683 -0.353553 +v -0.906127 0.195090 -0.375330 +v -0.923880 0.000000 -0.382684 +v -0.906127 -0.195090 -0.375330 +v -0.853553 -0.382683 -0.353554 +v -0.768178 -0.555570 -0.318190 +v -0.653281 -0.707107 -0.270598 +v -0.513280 -0.831470 -0.212608 +v -0.353553 -0.923880 -0.146447 +v -0.180240 -0.980785 -0.074658 +v 0.000000 -1.000000 0.000000 +v -0.137950 0.980785 -0.137950 +v -0.270598 0.923880 -0.270598 +v -0.392847 0.831470 -0.392848 +v -0.500000 0.707107 -0.500000 +v -0.587938 0.555570 -0.587938 +v -0.653281 0.382683 -0.653282 +v -0.693520 0.195090 -0.693520 +v -0.707107 0.000000 -0.707107 +v -0.693520 -0.195090 -0.693520 +v -0.653281 -0.382683 -0.653282 +v -0.587938 -0.555570 -0.587938 +v -0.500000 -0.707107 -0.500000 +v -0.392847 -0.831470 -0.392848 +v -0.270598 -0.923880 -0.270598 +v -0.137949 -0.980785 -0.137950 +v -0.074658 0.980785 -0.180240 +v -0.146446 0.923880 -0.353554 +v -0.212607 0.831470 -0.513280 +v -0.270598 0.707107 -0.653282 +v -0.318189 0.555570 -0.768178 +v -0.353553 0.382683 -0.853554 +v -0.375330 0.195090 -0.906128 +v -0.382683 0.000000 -0.923880 +v -0.375330 -0.195090 -0.906128 +v -0.353553 -0.382683 -0.853554 +v -0.318189 -0.555570 -0.768178 +v -0.270598 -0.707107 -0.653282 +v -0.212607 -0.831470 -0.513280 +v -0.146446 -0.923880 -0.353554 +v -0.074658 -0.980785 -0.180240 +v 0.000000 0.980785 -0.195091 +v 0.000000 0.923880 -0.382684 +v 0.000000 0.831470 -0.555570 +v 0.000000 0.707107 -0.707107 +v 0.000000 0.555570 -0.831470 +v 0.000000 0.382683 -0.923880 +v 0.000000 0.195090 -0.980785 +v 0.000000 0.000000 -1.000000 +v 0.000000 -0.195090 -0.980785 +v 0.000000 -0.382683 -0.923880 +v 0.000000 -0.555570 -0.831470 +v 0.000000 -0.707107 -0.707107 +v 0.000000 -0.831470 -0.555570 +v 0.000000 -0.923880 -0.382684 +v 0.000000 -0.980785 -0.195090 +v 0.074658 0.980785 -0.180240 +v 0.146447 0.923880 -0.353554 +v 0.212608 0.831470 -0.513280 +v 0.270598 0.707107 -0.653282 +v 0.318190 0.555570 -0.768178 +v 0.353554 0.382683 -0.853553 +v 0.375331 0.195090 -0.906128 +v 0.382684 0.000000 -0.923880 +v 0.375331 -0.195090 -0.906128 +v 0.353554 -0.382683 -0.853553 +v 0.318190 -0.555570 -0.768178 +v 0.270598 -0.707107 -0.653282 +v 0.212608 -0.831470 -0.513280 +v 0.146447 -0.923880 -0.353554 +v 0.074658 -0.980785 -0.180240 +v 0.137950 0.980785 -0.137950 +v 0.270599 0.923880 -0.270598 +v 0.392848 0.831470 -0.392848 +v 0.500000 0.707107 -0.500000 +v 0.587938 0.555570 -0.587938 +v 0.653282 0.382683 -0.653282 +v 0.693520 0.195090 -0.693520 +v 0.707107 0.000000 -0.707107 +v 0.693520 -0.195090 -0.693520 +v 0.653282 -0.382683 -0.653281 +v 0.587938 -0.555570 -0.587938 +v 0.500000 -0.707107 -0.500000 +v 0.392848 -0.831470 -0.392848 +v 0.270599 -0.923880 -0.270598 +v 0.137950 -0.980785 -0.137950 +v 0.180241 0.980785 -0.074658 +v 0.353554 0.923880 -0.146447 +v 0.513280 0.831470 -0.212608 +v 0.653282 0.707107 -0.270598 +v 0.768178 0.555570 -0.318190 +v 0.853554 0.382683 -0.353553 +v 0.906128 0.195090 -0.375330 +v 0.923880 0.000000 -0.382683 +v 0.906128 -0.195090 -0.375330 +v 0.853554 -0.382683 -0.353553 +v 0.768178 -0.555570 -0.318190 +v 0.653282 -0.707107 -0.270598 +v 0.513280 -0.831470 -0.212608 +v 0.353554 -0.923880 -0.146447 +v 0.180240 -0.980785 -0.074658 +v 0.195091 0.980785 0.000000 +v 0.382684 0.923880 0.000000 +v 0.555571 0.831470 0.000000 +v 0.707107 0.707107 0.000000 +v 0.831470 0.555570 0.000000 +v 0.923880 0.382683 0.000000 +v 0.980786 0.195090 0.000000 +v 1.000000 0.000000 0.000000 +v 0.980786 -0.195090 0.000000 +v 0.923880 -0.382683 0.000000 +v 0.831470 -0.555570 0.000000 +v 0.707107 -0.707107 0.000000 +v 0.555571 -0.831470 0.000000 +v 0.382684 -0.923880 0.000000 +v 0.195091 -0.980785 0.000000 +v 0.180241 0.980785 0.074658 +v 0.353554 0.923880 0.146447 +v 0.513280 0.831470 0.212608 +v 0.653282 0.707107 0.270598 +v 0.768178 0.555570 0.318190 +v 0.853554 0.382683 0.353553 +v 0.906128 0.195090 0.375330 +v 0.923880 0.000000 0.382684 +v 0.906128 -0.195090 0.375330 +v 0.853554 -0.382683 0.353553 +v 0.768178 -0.555570 0.318190 +v 0.653282 -0.707107 0.270598 +v 0.513280 -0.831470 0.212608 +v 0.353554 -0.923880 0.146447 +v 0.180240 -0.980785 0.074658 +v 0.137950 0.980785 0.137950 +v 0.270599 0.923880 0.270598 +v 0.392848 0.831470 0.392848 +v 0.500000 0.707107 0.500000 +v 0.587938 0.555570 0.587938 +v 0.653282 0.382683 0.653282 +v 0.693520 0.195090 0.693520 +v 0.707107 0.000000 0.707107 +v 0.693520 -0.195090 0.693520 +v 0.653282 -0.382683 0.653282 +v 0.587938 -0.555570 0.587938 +v 0.500000 -0.707107 0.500000 +v 0.392848 -0.831470 0.392848 +v 0.270599 -0.923880 0.270598 +v 0.137950 -0.980785 0.137950 +v 0.074658 0.980785 0.180240 +v 0.146447 0.923880 0.353554 +v 0.212608 0.831470 0.513280 +v 0.270598 0.707107 0.653282 +v 0.318190 0.555570 0.768178 +v 0.353554 0.382683 0.853553 +v 0.375331 0.195090 0.906128 +v 0.382684 0.000000 0.923880 +v 0.375331 -0.195090 0.906128 +v 0.353554 -0.382683 0.853553 +v 0.318190 -0.555570 0.768178 +v 0.270598 -0.707107 0.653282 +v 0.212608 -0.831470 0.513280 +v 0.146447 -0.923880 0.353554 +v 0.074658 -0.980785 0.180240 +v 0.000000 0.980785 0.195091 +v 0.000000 0.923880 0.382684 +v 0.000000 0.831470 0.555570 +v 0.000000 0.707107 0.707107 +v 0.000000 0.555570 0.831470 +v 0.000000 0.382683 0.923880 +v 0.000000 0.195090 0.980785 +v 0.000000 0.000000 1.000000 +v 0.000000 -0.195090 0.980785 +v 0.000000 -0.382683 0.923879 +v 0.000000 -0.555570 0.831470 +v 0.000000 -0.707107 0.707107 +v 0.000000 -0.831470 0.555570 +v 0.000000 -0.923880 0.382684 +v 0.000000 -0.980785 0.195090 +v -0.074658 0.980785 0.180240 +v -0.146446 0.923880 0.353554 +v -0.212607 0.831470 0.513280 +v -0.270598 0.707107 0.653282 +v -0.318189 0.555570 0.768178 +v -0.353553 0.382683 0.853553 +v -0.375330 0.195090 0.906128 +v -0.382683 0.000000 0.923880 +v -0.375330 -0.195090 0.906128 +v -0.353553 -0.382683 0.853553 +v -0.318189 -0.555570 0.768178 +v -0.270598 -0.707107 0.653282 +v -0.212607 -0.831470 0.513280 +v -0.146446 -0.923880 0.353554 +v -0.074658 -0.980785 0.180240 +v 0.000000 1.000000 0.000000 +v -0.137950 0.980785 0.137950 +v -0.270598 0.923880 0.270598 +v -0.392847 0.831470 0.392848 +v -0.500000 0.707107 0.500000 +v -0.587938 0.555570 0.587938 +v -0.653281 0.382683 0.653281 +v -0.693520 0.195090 0.693520 +v -0.707107 0.000000 0.707107 +v -0.693520 -0.195090 0.693520 +v -0.653281 -0.382683 0.653281 +v -0.587938 -0.555570 0.587938 +v -0.500000 -0.707107 0.500000 +v -0.392847 -0.831470 0.392848 +v -0.270598 -0.923880 0.270598 +v -0.137949 -0.980785 0.137950 +v -0.180240 0.980785 0.074658 +v -0.353553 0.923880 0.146447 +v -0.513280 0.831470 0.212608 +v -0.653281 0.707107 0.270598 +v -0.768177 0.555570 0.318190 +v -0.853553 0.382683 0.353553 +v -0.906127 0.195090 0.375330 +v -0.923879 0.000000 0.382683 +v -0.906127 -0.195090 0.375330 +v -0.853553 -0.382683 0.353553 +v -0.768177 -0.555570 0.318190 +v -0.653281 -0.707107 0.270598 +v -0.513280 -0.831470 0.212608 +v -0.353553 -0.923880 0.146447 +v -0.180240 -0.980785 0.074658 +vt 0.040867 0.325557 +vt 0.048386 0.386583 +vt 0.001015 0.334499 +vt 0.081872 0.692529 +vt 0.092315 0.752973 +vt 0.006404 0.709363 +vt 1.031336 0.264931 +vt 1.040867 0.325557 +vt 0.999822 0.272029 +vt 0.073887 0.631595 +vt 0.005301 0.646891 +vt 0.333915 0.937286 +vt 0.448527 0.905466 +vt 0.447682 0.976645 +vt 1.017784 0.205113 +vt 0.998129 0.209571 +vt 0.067156 0.570413 +vt 0.004397 0.584414 +vt 0.196016 0.918498 +vt 0.034176 0.958662 +vt 0.060989 0.509119 +vt 0.003585 0.521934 +vt 0.135028 0.869370 +vt 0.015221 0.896641 +vt 0.054891 0.447811 +vt 0.002796 0.459454 +vt 0.107782 0.812401 +vt 0.010297 0.834265 +vt 0.001965 0.396975 +vt 0.007907 0.771825 +vt 0.978319 0.207096 +vt 1.004397 0.584414 +vt 1.005301 0.646891 +vt 0.941200 0.576589 +vt 1.034176 0.958662 +vt 0.823807 0.933258 +vt 1.003585 0.521934 +vt 0.945911 0.514786 +vt 1.015221 0.896641 +vt 0.885287 0.880701 +vt 1.002796 0.459454 +vt 0.950535 0.452971 +vt 1.010297 0.834265 +vt 0.908873 0.821779 +vt 1.001965 0.396975 +vt 0.955439 0.391196 +vt 1.007907 0.771825 +vt 0.921503 0.761167 +vt 1.001015 0.334499 +vt 0.961079 0.329532 +vt 1.006404 0.709363 +vt 0.929787 0.699898 +vt 0.968202 0.268089 +vt 0.936013 0.638321 +vt 0.488610 0.915189 +vt 0.647808 0.950687 +vt 0.921611 0.311033 +vt 0.859136 0.666985 +vt 0.937209 0.253354 +vt 0.870446 0.607941 +vt 0.532175 0.909643 +vt 0.657607 0.903302 +vt 0.959449 0.197860 +vt 0.880347 0.548455 +vt 0.745300 0.879338 +vt 0.889690 0.488794 +vt 0.796385 0.834663 +vt 0.899158 0.429173 +vt 0.825891 0.781668 +vt 0.909472 0.369816 +vt 0.845097 0.725165 +vt 0.848920 0.390841 +vt 0.761226 0.728711 +vt 0.864196 0.334814 +vt 0.780693 0.674598 +vt 0.882867 0.280332 +vt 0.796418 0.618773 +vt 0.907539 0.228698 +vt 0.810089 0.562031 +vt 0.558962 0.891763 +vt 0.641452 0.857179 +vt 0.942759 0.182515 +vt 0.822818 0.504873 +vt 0.697492 0.824480 +vt 0.835477 0.447684 +vt 0.735147 0.779653 +vt 0.879896 0.195479 +vt 0.753309 0.508011 +vt 0.618082 0.815427 +vt 0.767315 0.452094 +vt 0.657173 0.773912 +vt 0.782092 0.396562 +vt 0.685241 0.725518 +vt 0.798714 0.341964 +vt 0.706593 0.673391 +vt 0.818709 0.289116 +vt 0.723996 0.619193 +vt 0.844487 0.239416 +vt 0.739178 0.563865 +vt 0.567268 0.868303 +vt 0.563300 0.844314 +vt 0.770454 0.236269 +vt 0.670392 0.566231 +vt 0.805029 0.190637 +vt 0.683774 0.509644 +vt 0.551952 0.822879 +vt 0.929896 0.162212 +vt 0.855308 0.155368 +vt 0.697011 0.452991 +vt 0.591182 0.780044 +vt 0.710973 0.396675 +vt 0.618699 0.730484 +vt 0.726705 0.341193 +vt 0.639317 0.677374 +vt 0.745717 0.287291 +vt 0.655961 0.622327 +vt 0.665037 0.288362 +vt 0.594131 0.638967 +vt 0.684737 0.232805 +vt 0.605914 0.580518 +vt 0.713639 0.180821 +vt 0.616615 0.521685 +vt 0.760428 0.136665 +vt 0.627046 0.462757 +vt 0.536166 0.805967 +vt 0.923407 0.138703 +vt 0.836350 0.110271 +vt 0.637946 0.403995 +vt 0.562017 0.752770 +vt 0.650183 0.345708 +vt 0.580132 0.696622 +vt 0.517784 0.794886 +vt 0.927547 0.114679 +vt 0.833915 0.062714 +vt 0.573887 0.368405 +vt 0.531336 0.735069 +vt 0.581872 0.307471 +vt 0.540867 0.674443 +vt 0.592315 0.247027 +vt 0.548386 0.613417 +vt 0.607782 0.187599 +vt 0.554891 0.552189 +vt 0.635028 0.130630 +vt 0.560989 0.490881 +vt 0.696016 0.081502 +vt 0.567156 0.429587 +vt 0.502796 0.540546 +vt 0.515221 0.103359 +vt 0.503585 0.478066 +vt 0.534176 0.041338 +vt 0.504397 0.415586 +vt 0.498129 0.790428 +vt 0.948527 0.094534 +vt 0.947682 0.023355 +vt 0.505301 0.353109 +vt 0.499822 0.727971 +vt 0.506404 0.290637 +vt 0.501015 0.665501 +vt 0.507907 0.228175 +vt 0.501965 0.603025 +vt 0.510297 0.165735 +vt 0.429787 0.300102 +vt 0.461079 0.670468 +vt 0.421503 0.238833 +vt 0.455439 0.608804 +vt 0.408873 0.178221 +vt 0.445911 0.485214 +vt 0.385287 0.119299 +vt 1.323807 0.066742 +vt 0.441200 0.423411 +vt 0.478319 0.792904 +vt 0.988610 0.084811 +vt 1.147808 0.049313 +vt 0.436013 0.361679 +vt 0.468202 0.731911 +vt 0.147808 0.049313 +vt 0.323807 0.066742 +vt 0.245300 0.120661 +vt 0.380347 0.451545 +vt 0.459449 0.802140 +vt 0.032175 0.090357 +vt 0.157607 0.096698 +vt 0.370446 0.392059 +vt 0.437209 0.746646 +vt 0.359136 0.333015 +vt 0.421611 0.688967 +vt 0.345097 0.274835 +vt 0.450536 0.547029 +vt 0.409472 0.630184 +vt 0.325892 0.218332 +vt 0.399158 0.570827 +vt 0.296385 0.165337 +vt 0.389690 0.511206 +vt 0.261226 0.271289 +vt 0.348920 0.609159 +vt 0.235147 0.220347 +vt 0.335478 0.552316 +vt 0.197492 0.175520 +vt 0.322818 0.495127 +vt 0.442759 0.817485 +vt 0.058962 0.108237 +vt 0.141452 0.142821 +vt 0.310089 0.437969 +vt 0.407539 0.771302 +vt 0.296418 0.381227 +vt 0.382867 0.719668 +vt 0.280693 0.325402 +vt 0.364196 0.665186 +vt 0.223996 0.380807 +vt 0.318709 0.710884 +vt 0.206593 0.326609 +vt 0.298714 0.658036 +vt 0.185241 0.274482 +vt 0.282092 0.603438 +vt 0.157173 0.226088 +vt 0.267315 0.547906 +vt 0.118082 0.184573 +vt 0.253309 0.491989 +vt 0.379896 0.804521 +vt 0.067268 0.131697 +vt 0.063300 0.155685 +vt 0.239178 0.436135 +vt 0.344487 0.760584 +vt 0.091182 0.219955 +vt 0.197011 0.547009 +vt 0.429896 0.837788 +vt 0.355308 0.844632 +vt 0.051952 0.177121 +vt 0.183774 0.490356 +vt 0.305029 0.809363 +vt 0.170392 0.433769 +vt 0.270454 0.763731 +vt 0.155961 0.377673 +vt 0.245717 0.712709 +vt 0.226706 0.658807 +vt 0.118699 0.269516 +vt 0.210973 0.603325 +vt 0.139317 0.322626 +vt 0.094131 0.361033 +vt 0.165037 0.711638 +vt 0.080132 0.303378 +vt 0.150183 0.654292 +vt 0.062017 0.247229 +vt 0.137946 0.596005 +vt 0.423407 0.861296 +vt 0.336350 0.889729 +vt 0.036166 0.194032 +vt 0.127046 0.537243 +vt 0.260428 0.863335 +vt 0.116615 0.478315 +vt 0.213639 0.819179 +vt 0.105914 0.419482 +vt 0.184737 0.767195 +vt 0.495265 0.852856 +vt 0.995265 0.147143 +vt 1.032175 0.090357 +vt 1.058962 0.108237 +vt 1.067268 0.131697 +vt 1.063300 0.155685 +vt 1.051952 0.177121 +vt 0.427547 0.885321 +vt 1.036166 0.194032 +vt 0.031336 0.264931 +vt 0.017784 0.205113 +vn -0.629402 -0.766928 -0.125196 +vn -0.940062 0.285165 -0.186990 +vn -0.469338 -0.878070 -0.093357 +vn -0.976241 0.096152 -0.194186 +vn -0.289802 0.955349 -0.057645 +vn -0.289802 -0.955349 -0.057645 +vn -0.976241 -0.096151 -0.194186 +vn -0.469338 0.878070 -0.093357 +vn -0.940062 -0.285165 -0.186990 +vn -0.629402 0.766928 -0.125196 +vn -0.868657 -0.464306 -0.172787 +vn -0.764031 0.627024 -0.151975 +vn -0.764031 -0.627024 -0.151975 +vn -0.868657 0.464306 -0.172787 +vn -0.245682 -0.955349 -0.164159 +vn -0.827617 -0.096152 -0.552996 +vn -0.397886 0.878069 -0.265859 +vn -0.796946 -0.285165 -0.532502 +vn -0.533581 0.766929 -0.356527 +vn -0.736412 -0.464306 -0.492055 +vn -0.647715 0.627024 -0.432789 +vn -0.647714 -0.627024 -0.432789 +vn -0.736412 0.464306 -0.492055 +vn -0.533581 -0.766928 -0.356528 +vn -0.796946 0.285165 -0.532502 +vn -0.397886 -0.878070 -0.265859 +vn -0.827617 0.096152 -0.552996 +vn -0.245682 0.955349 -0.164160 +vn -0.356527 -0.766928 -0.533581 +vn -0.532502 0.285165 -0.796946 +vn -0.265859 -0.878070 -0.397886 +vn -0.552996 0.096152 -0.827617 +vn -0.164160 0.955349 -0.245682 +vn -0.164159 -0.955349 -0.245682 +vn -0.552996 -0.096152 -0.827617 +vn -0.265859 0.878069 -0.397886 +vn -0.532502 -0.285165 -0.796946 +vn -0.356527 0.766929 -0.533581 +vn -0.492054 -0.464306 -0.736412 +vn -0.432789 0.627024 -0.647715 +vn -0.432789 -0.627024 -0.647715 +vn -0.492054 0.464306 -0.736412 +vn -0.172786 -0.464306 -0.868657 +vn -0.151975 0.627024 -0.764032 +vn -0.151975 -0.627024 -0.764032 +vn -0.172786 0.464306 -0.868657 +vn -0.125196 -0.766928 -0.629402 +vn -0.186990 0.285165 -0.940062 +vn -0.093357 -0.878070 -0.469338 +vn -0.194186 0.096152 -0.976241 +vn -0.057645 0.955349 -0.289802 +vn -0.057645 -0.955349 -0.289801 +vn -0.194186 -0.096152 -0.976241 +vn -0.093357 0.878069 -0.469338 +vn -0.186990 -0.285165 -0.940062 +vn -0.125196 0.766929 -0.629402 +vn 0.057645 -0.955349 -0.289801 +vn 0.194186 -0.096152 -0.976241 +vn 0.093357 0.878069 -0.469338 +vn 0.186990 -0.285165 -0.940062 +vn 0.125196 0.766929 -0.629402 +vn 0.172787 -0.464306 -0.868657 +vn 0.151975 0.627024 -0.764031 +vn 0.151975 -0.627024 -0.764031 +vn 0.172787 0.464306 -0.868657 +vn 0.125196 -0.766928 -0.629402 +vn 0.186990 0.285165 -0.940062 +vn 0.093357 -0.878070 -0.469338 +vn 0.194186 0.096152 -0.976241 +vn 0.057645 0.955349 -0.289802 +vn 0.356528 -0.766928 -0.533581 +vn 0.532502 0.285165 -0.796946 +vn 0.265859 -0.878070 -0.397886 +vn 0.552996 0.096152 -0.827617 +vn 0.164160 0.955349 -0.245682 +vn 0.164159 -0.955349 -0.245682 +vn 0.552996 -0.096152 -0.827617 +vn 0.265859 0.878069 -0.397886 +vn 0.532502 -0.285165 -0.796946 +vn 0.356527 0.766929 -0.533581 +vn 0.492055 -0.464306 -0.736412 +vn 0.432789 0.627024 -0.647715 +vn 0.432789 -0.627024 -0.647714 +vn 0.492055 0.464306 -0.736412 +vn 0.736412 -0.464306 -0.492055 +vn 0.647715 0.627024 -0.432789 +vn 0.647715 -0.627024 -0.432789 +vn 0.736412 0.464306 -0.492054 +vn 0.533581 -0.766928 -0.356528 +vn 0.796946 0.285165 -0.532502 +vn 0.397886 -0.878070 -0.265859 +vn 0.827617 0.096152 -0.552996 +vn 0.245682 0.955349 -0.164160 +vn 0.245682 -0.955349 -0.164159 +vn 0.827617 -0.096152 -0.552996 +vn 0.397886 0.878069 -0.265859 +vn 0.796946 -0.285165 -0.532502 +vn 0.533581 0.766929 -0.356527 +vn 0.289802 0.955349 -0.057645 +vn 0.289801 -0.955349 -0.057645 +vn 0.976241 -0.096152 -0.194186 +vn 0.469338 0.878069 -0.093357 +vn 0.940062 -0.285165 -0.186990 +vn 0.629402 0.766929 -0.125196 +vn 0.868657 -0.464306 -0.172786 +vn 0.764032 0.627024 -0.151975 +vn 0.764032 -0.627024 -0.151975 +vn 0.868657 0.464307 -0.172786 +vn 0.629402 -0.766928 -0.125196 +vn 0.940062 0.285165 -0.186990 +vn 0.469338 -0.878069 -0.093357 +vn 0.976241 0.096152 -0.194186 +vn 0.868657 0.464306 0.172787 +vn 0.629402 -0.766928 0.125196 +vn 0.940062 0.285165 0.186990 +vn 0.469338 -0.878069 0.093357 +vn 0.976241 0.096152 0.194186 +vn 0.289802 0.955349 0.057645 +vn 0.289801 -0.955349 0.057645 +vn 0.976241 -0.096152 0.194187 +vn 0.469338 0.878069 0.093357 +vn 0.940061 -0.285165 0.186990 +vn 0.629402 0.766929 0.125196 +vn 0.868657 -0.464306 0.172787 +vn 0.764032 0.627024 0.151975 +vn 0.764032 -0.627024 0.151976 +vn 0.796946 -0.285165 0.532502 +vn 0.533581 0.766929 0.356527 +vn 0.736412 -0.464306 0.492055 +vn 0.647715 0.627024 0.432789 +vn 0.647715 -0.627024 0.432789 +vn 0.736411 0.464307 0.492054 +vn 0.533581 -0.766928 0.356528 +vn 0.796946 0.285165 0.532502 +vn 0.397886 -0.878070 0.265859 +vn 0.827617 0.096151 0.552996 +vn 0.245682 0.955349 0.164160 +vn 0.245682 -0.955349 0.164159 +vn 0.827617 -0.096151 0.552996 +vn 0.397886 0.878070 0.265859 +vn 0.265859 -0.878070 0.397886 +vn 0.552996 0.096151 0.827617 +vn 0.164160 0.955349 0.245682 +vn 0.164159 -0.955349 0.245682 +vn 0.552996 -0.096151 0.827617 +vn 0.265859 0.878070 0.397886 +vn 0.532502 -0.285165 0.796946 +vn 0.356527 0.766929 0.533581 +vn 0.492054 -0.464306 0.736412 +vn 0.432789 0.627024 0.647715 +vn 0.432789 -0.627024 0.647715 +vn 0.492054 0.464307 0.736412 +vn 0.356528 -0.766928 0.533581 +vn 0.532502 0.285165 0.796946 +vn 0.151975 -0.627024 0.764032 +vn 0.172786 0.464307 0.868656 +vn 0.125196 -0.766928 0.629402 +vn 0.186990 0.285165 0.940062 +vn 0.093357 -0.878070 0.469338 +vn 0.194186 0.096151 0.976241 +vn 0.057645 0.955349 0.289802 +vn 0.057645 -0.955349 0.289801 +vn 0.194186 -0.096151 0.976241 +vn 0.093357 0.878070 0.469338 +vn 0.186990 -0.285166 0.940061 +vn 0.125196 0.766929 0.629402 +vn 0.172786 -0.464306 0.868657 +vn 0.151975 0.627023 0.764032 +vn -0.186990 -0.285166 0.940061 +vn -0.125196 0.766929 0.629402 +vn -0.172787 -0.464306 0.868657 +vn -0.151976 0.627023 0.764032 +vn -0.151975 -0.627024 0.764032 +vn -0.172787 0.464307 0.868656 +vn -0.125196 -0.766928 0.629402 +vn -0.186990 0.285165 0.940062 +vn -0.093357 -0.878069 0.469338 +vn -0.194186 0.096151 0.976241 +vn -0.057645 0.955349 0.289802 +vn -0.057645 -0.955349 0.289801 +vn -0.194186 -0.096151 0.976241 +vn -0.093357 0.878069 0.469338 +vn -0.265859 -0.878070 0.397886 +vn -0.552996 0.096151 0.827617 +vn -0.164160 0.955349 0.245682 +vn -0.164159 -0.955349 0.245682 +vn -0.552996 -0.096151 0.827617 +vn -0.265859 0.878070 0.397886 +vn -0.532502 -0.285166 0.796945 +vn -0.356527 0.766929 0.533581 +vn -0.492054 -0.464306 0.736412 +vn -0.432790 0.627023 0.647715 +vn -0.432789 -0.627024 0.647715 +vn -0.492054 0.464307 0.736411 +vn -0.356528 -0.766928 0.533581 +vn -0.532502 0.285165 0.796946 +vn -0.647715 -0.627024 0.432789 +vn -0.736411 0.464307 0.492054 +vn -0.533581 -0.766928 0.356528 +vn -0.796946 0.285165 0.532502 +vn -0.397886 -0.878070 0.265859 +vn -0.827617 0.096151 0.552996 +vn -0.245682 0.955349 0.164160 +vn -0.245682 -0.955349 0.164159 +vn -0.827617 -0.096151 0.552996 +vn -0.397886 0.878070 0.265859 +vn -0.796946 -0.285166 0.532502 +vn -0.533581 0.766929 0.356527 +vn -0.736412 -0.464306 0.492054 +vn -0.647715 0.627023 0.432789 +vn -0.097999 0.994996 -0.019493 +vn -0.097998 -0.994996 -0.019493 +vn -0.083079 -0.994996 -0.055512 +vn -0.083079 0.994996 -0.055512 +vn -0.055512 0.994996 -0.083079 +vn -0.055512 -0.994996 -0.083079 +vn -0.019493 0.994996 -0.097998 +vn -0.019493 -0.994996 -0.097998 +vn 0.019493 -0.994996 -0.097998 +vn 0.019493 0.994996 -0.097998 +vn 0.055512 0.994996 -0.083079 +vn 0.055512 -0.994996 -0.083079 +vn 0.083079 0.994996 -0.055512 +vn 0.083079 -0.994996 -0.055512 +vn 0.097998 -0.994996 -0.019493 +vn 0.097998 0.994996 -0.019493 +vn 0.097998 0.994996 0.019493 +vn 0.097998 -0.994996 0.019493 +vn 0.083079 0.994996 0.055512 +vn 0.083079 -0.994996 0.055512 +vn 0.055512 -0.994996 0.083079 +vn 0.055512 0.994996 0.083079 +vn 0.019493 0.994996 0.097999 +vn 0.019493 -0.994996 0.097998 +vn -0.019493 -0.994996 0.097998 +vn -0.019493 0.994996 0.097999 +vn -0.055512 -0.994996 0.083079 +vn -0.055512 0.994996 0.083079 +vn -0.083079 0.994996 0.055512 +vn -0.083079 -0.994996 0.055512 +vn -0.097998 -0.994996 0.019493 +vn -0.940061 -0.285166 0.186991 +vn -0.629402 0.766929 0.125196 +vn -0.868656 -0.464306 0.172788 +vn -0.764032 0.627023 0.151977 +vn -0.764032 -0.627024 0.151976 +vn -0.868656 0.464307 0.172787 +vn -0.629402 -0.766928 0.125196 +vn -0.940061 0.285165 0.186990 +vn -0.097999 0.994996 0.019493 +vn -0.469338 -0.878070 0.093357 +vn -0.976241 0.096151 0.194187 +vn -0.289802 0.955349 0.057646 +vn -0.289801 -0.955349 0.057645 +vn -0.976241 -0.096151 0.194187 +vn -0.469338 0.878070 0.093358 +vn -0.976241 -0.096152 -0.194186 +vn -0.469338 0.878069 -0.093357 +vn -0.629401 0.766929 -0.125196 +vn -0.764032 0.627024 -0.151975 +vn -0.736411 -0.464306 -0.492055 +vn -0.736411 0.464306 -0.492055 +vn -0.356528 -0.766928 -0.533581 +vn -0.151975 -0.627024 -0.764031 +vn -0.194186 -0.096151 -0.976241 +vn 0.186990 -0.285165 -0.940061 +vn 0.151975 0.627024 -0.764032 +vn 0.432789 -0.627024 -0.647715 +vn 0.492055 0.464306 -0.736411 +vn 0.736412 -0.464306 -0.492054 +vn 0.736411 0.464307 -0.492054 +vn 0.976241 -0.096151 -0.194186 +vn 0.940062 -0.285166 -0.186990 +vn 0.868657 -0.464306 -0.172787 +vn 0.868657 0.464306 -0.172786 +vn 0.940061 0.285165 -0.186990 +vn 0.868656 0.464307 0.172787 +vn 0.976241 0.096151 0.194187 +vn 0.976241 -0.096151 0.194186 +vn 0.469338 0.878070 0.093357 +vn 0.940061 -0.285166 0.186990 +vn 0.764032 0.627024 0.151976 +vn 0.764032 -0.627024 0.151975 +vn 0.796945 -0.285166 0.532502 +vn 0.647715 0.627023 0.432790 +vn 0.736411 0.464307 0.492055 +vn 0.532502 -0.285166 0.796946 +vn 0.432789 0.627023 0.647715 +vn 0.492054 0.464307 0.736411 +vn 0.151975 -0.627023 0.764032 +vn 0.186990 0.285165 0.940061 +vn 0.093357 0.878069 0.469338 +vn -0.151975 0.627023 0.764032 +vn -0.151976 -0.627023 0.764032 +vn -0.186990 0.285165 0.940061 +vn -0.093357 -0.878070 0.469338 +vn -0.093357 0.878070 0.469338 +vn -0.532502 -0.285166 0.796946 +vn -0.492055 -0.464306 0.736412 +vn -0.432789 -0.627023 0.647715 +vn -0.647715 -0.627023 0.432789 +vn -0.796945 -0.285166 0.532502 +vn -0.647715 0.627023 0.432790 +vn -0.940062 -0.285165 0.186990 +vn -0.629402 0.766928 0.125196 +vn -0.764031 0.627024 0.151975 +vn -0.764031 -0.627024 0.151976 +vn -0.868657 0.464306 0.172788 +vn -0.940062 0.285165 0.186991 +vn -0.976241 0.096152 0.194187 +vn -0.289802 -0.955349 0.057645 +s off +f 13/1/1 12/2/1 28/3/1 +f 7/4/2 6/5/2 22/6/2 +f 14/7/3 13/8/3 29/9/3 +f 8/10/4 7/4/4 23/11/4 +f 2/12/5 1/13/5 17/14/5 +f 15/15/6 14/7/6 30/16/6 +f 9/17/7 8/10/7 24/18/7 +f 3/19/8 2/12/8 18/20/8 +f 10/21/9 9/17/9 25/22/9 +f 4/23/10 3/19/10 19/24/10 +f 11/25/11 10/21/11 26/26/11 +f 5/27/12 4/23/12 20/28/12 +f 12/2/13 11/25/13 27/29/13 +f 6/5/14 5/27/14 21/30/14 +f 30/16/15 29/9/15 46/31/15 +f 24/32/16 23/33/16 40/34/16 +f 18/35/17 17/14/17 34/36/17 +f 25/37/18 24/32/18 41/38/18 +f 19/39/19 18/35/19 35/40/19 +f 26/41/20 25/37/20 42/42/20 +f 20/43/21 19/39/21 36/44/21 +f 27/45/22 26/41/22 43/46/22 +f 21/47/23 20/43/23 37/48/23 +f 28/49/24 27/45/24 44/50/24 +f 22/51/25 21/47/25 38/52/25 +f 29/9/26 28/49/26 45/53/26 +f 23/33/27 22/51/27 39/54/27 +f 17/14/28 16/55/28 33/56/28 +f 44/50/29 43/46/29 59/57/29 +f 38/52/30 37/48/30 53/58/30 +f 45/53/31 44/50/31 60/59/31 +f 39/54/32 38/52/32 54/60/32 +f 33/56/33 32/61/33 48/62/33 +f 46/31/34 45/53/34 61/63/34 +f 40/34/35 39/54/35 55/64/35 +f 34/36/36 33/56/36 49/65/36 +f 41/38/37 40/34/37 56/66/37 +f 35/40/38 34/36/38 50/67/38 +f 42/42/39 41/38/39 57/68/39 +f 36/44/40 35/40/40 51/69/40 +f 43/46/41 42/42/41 58/70/41 +f 37/48/42 36/44/42 52/71/42 +f 57/68/43 56/66/43 72/72/43 +f 51/69/44 50/67/44 66/73/44 +f 58/70/45 57/68/45 73/74/45 +f 52/71/46 51/69/46 67/75/46 +f 59/57/47 58/70/47 74/76/47 +f 53/58/48 52/71/48 68/77/48 +f 60/59/49 59/57/49 75/78/49 +f 54/60/50 53/58/50 69/79/50 +f 48/62/51 47/80/51 63/81/51 +f 61/63/52 60/59/52 76/82/52 +f 55/64/53 54/60/53 70/83/53 +f 49/65/54 48/62/54 64/84/54 +f 56/66/55 55/64/55 71/85/55 +f 50/67/56 49/65/56 65/86/56 +f 76/82/57 75/78/57 90/87/57 +f 70/83/58 69/79/58 84/88/58 +f 64/84/59 63/81/59 78/89/59 +f 71/85/60 70/83/60 85/90/60 +f 65/86/61 64/84/61 79/91/61 +f 72/72/62 71/85/62 86/92/62 +f 66/73/63 65/86/63 80/93/63 +f 73/74/64 72/72/64 87/94/64 +f 67/75/65 66/73/65 81/95/65 +f 74/76/66 73/74/66 88/96/66 +f 68/77/67 67/75/67 82/97/67 +f 75/78/68 74/76/68 89/98/68 +f 69/79/69 68/77/69 83/99/69 +f 63/81/70 62/100/70 77/101/70 +f 89/98/71 88/96/71 103/102/71 +f 83/99/72 82/97/72 97/103/72 +f 90/87/73 89/98/73 104/104/73 +f 84/88/74 83/99/74 98/105/74 +f 78/89/75 77/101/75 92/106/75 +f 91/107/76 90/87/76 105/108/76 +f 85/90/77 84/88/77 99/109/77 +f 79/91/78 78/89/78 93/110/78 +f 86/92/79 85/90/79 100/111/79 +f 80/93/80 79/91/80 94/112/80 +f 87/94/81 86/92/81 101/113/81 +f 81/95/82 80/93/82 95/114/82 +f 88/96/83 87/94/83 102/115/83 +f 82/97/84 81/95/84 96/116/84 +f 102/115/85 101/113/85 116/117/85 +f 96/116/86 95/114/86 110/118/86 +f 103/102/87 102/115/87 117/119/87 +f 97/103/88 96/116/88 111/120/88 +f 104/104/89 103/102/89 118/121/89 +f 98/105/90 97/103/90 112/122/90 +f 105/108/91 104/104/91 119/123/91 +f 99/109/92 98/105/92 113/124/92 +f 93/110/93 92/106/93 107/125/93 +f 106/126/94 105/108/94 120/127/94 +f 100/111/95 99/109/95 114/128/95 +f 94/112/96 93/110/96 108/129/96 +f 101/113/97 100/111/97 115/130/97 +f 95/114/98 94/112/98 109/131/98 +f 108/129/99 107/125/99 122/132/99 +f 121/133/100 120/127/100 135/134/100 +f 115/130/101 114/128/101 129/135/101 +f 109/131/102 108/129/102 123/136/102 +f 116/117/103 115/130/103 130/137/103 +f 110/118/104 109/131/104 124/138/104 +f 117/119/105 116/117/105 131/139/105 +f 111/120/106 110/118/106 125/140/106 +f 118/121/107 117/119/107 132/141/107 +f 112/122/108 111/120/108 126/142/108 +f 119/123/109 118/121/109 133/143/109 +f 113/124/110 112/122/110 127/144/110 +f 120/127/111 119/123/111 134/145/111 +f 114/128/112 113/124/112 128/146/112 +f 127/144/113 126/142/113 141/147/113 +f 134/145/114 133/143/114 148/148/114 +f 128/146/115 127/144/115 142/149/115 +f 135/134/116 134/145/116 149/150/116 +f 129/135/117 128/146/117 143/151/117 +f 123/136/118 122/132/118 137/152/118 +f 136/153/119 135/134/119 150/154/119 +f 130/137/120 129/135/120 144/155/120 +f 124/138/121 123/136/121 138/156/121 +f 131/139/122 130/137/122 145/157/122 +f 125/140/123 124/138/123 139/158/123 +f 132/141/124 131/139/124 146/159/124 +f 126/142/125 125/140/125 140/160/125 +f 133/143/126 132/141/126 147/161/126 +f 146/159/127 145/157/127 160/162/127 +f 140/160/128 139/158/128 154/163/128 +f 147/161/129 146/159/129 161/164/129 +f 141/147/130 140/160/130 155/165/130 +f 148/148/131 147/161/131 162/166/131 +f 142/149/132 141/147/132 157/167/132 +f 149/150/133 148/148/133 163/168/133 +f 143/151/134 142/149/134 157/167/134 +f 150/154/135 149/150/135 164/169/135 +f 144/155/136 143/151/136 158/170/136 +f 138/156/137 137/152/137 152/171/137 +f 151/172/138 150/154/138 165/173/138 +f 145/157/139 144/155/139 159/174/139 +f 139/158/140 138/156/140 153/175/140 +f 165/176/141 164/177/141 179/178/141 +f 159/174/142 158/170/142 173/179/142 +f 153/175/143 152/171/143 167/180/143 +f 166/181/144 165/176/144 180/182/144 +f 160/162/145 159/174/145 174/183/145 +f 154/163/146 153/175/146 168/184/146 +f 161/164/147 160/162/147 175/185/147 +f 155/165/148 154/163/148 169/186/148 +f 162/166/149 161/164/149 176/187/149 +f 156/188/150 155/165/150 170/189/150 +f 163/168/151 162/166/151 177/190/151 +f 157/167/152 156/188/152 171/191/152 +f 164/177/153 163/168/153 178/192/153 +f 158/170/154 157/167/154 172/193/154 +f 178/192/155 177/190/155 192/194/155 +f 172/193/156 171/191/156 186/195/156 +f 179/178/157 178/192/157 193/196/157 +f 173/179/158 172/193/158 187/197/158 +f 180/182/159 179/178/159 194/198/159 +f 174/183/160 173/179/160 188/199/160 +f 168/184/161 167/180/161 182/200/161 +f 181/201/162 180/182/162 195/202/162 +f 175/185/163 174/183/163 189/203/163 +f 169/186/164 168/184/164 183/204/164 +f 176/187/165 175/185/165 190/205/165 +f 170/189/166 169/186/166 184/206/166 +f 177/190/167 176/187/167 191/207/167 +f 171/191/168 170/189/168 185/208/168 +f 191/207/169 190/205/169 206/209/169 +f 185/208/170 184/206/170 200/210/170 +f 192/194/171 191/207/171 207/211/171 +f 186/195/172 185/208/172 201/212/172 +f 193/196/173 192/194/173 208/213/173 +f 187/197/174 186/195/174 202/214/174 +f 194/198/175 193/196/175 209/215/175 +f 188/199/176 187/197/176 203/216/176 +f 195/202/177 194/198/177 210/217/177 +f 189/203/178 188/199/178 204/218/178 +f 183/204/179 182/200/179 198/219/179 +f 196/220/180 195/202/180 211/221/180 +f 190/205/181 189/203/181 205/222/181 +f 184/206/182 183/204/182 199/223/182 +f 210/217/183 209/215/183 226/224/183 +f 204/218/184 203/216/184 220/225/184 +f 198/219/185 197/226/185 214/227/185 +f 211/221/186 210/217/186 227/228/186 +f 205/222/187 204/218/187 221/229/187 +f 199/223/188 198/219/188 215/230/188 +f 206/209/189 205/222/189 222/231/189 +f 200/210/190 199/223/190 216/232/190 +f 207/211/191 206/209/191 223/233/191 +f 201/212/192 200/210/192 217/234/192 +f 208/213/193 207/211/193 223/233/193 +f 202/214/194 201/212/194 218/235/194 +f 209/215/195 208/213/195 225/236/195 +f 203/216/196 202/214/196 219/237/196 +f 224/238/197 223/233/197 239/239/197 +f 218/235/198 217/234/198 233/240/198 +f 225/236/199 224/238/199 240/241/199 +f 219/237/200 218/235/200 234/242/200 +f 226/224/201 225/236/201 241/243/201 +f 220/225/202 219/237/202 235/244/202 +f 214/227/203 213/245/203 229/246/203 +f 227/228/204 226/224/204 242/247/204 +f 221/229/205 220/225/205 236/248/205 +f 215/230/206 214/227/206 230/249/206 +f 222/231/207 221/229/207 237/250/207 +f 216/232/208 215/230/208 231/251/208 +f 223/233/209 222/231/209 238/252/209 +f 217/234/210 216/232/210 232/253/210 +f 1/13/211 212/254/211 16/55/211 +f 31/255/212 15/15/212 30/16/212 +f 31/255/213 30/16/213 46/31/213 +f 16/55/214 212/254/214 32/61/214 +f 32/61/215 212/254/215 47/80/215 +f 31/255/216 46/31/216 61/63/216 +f 47/80/217 212/254/217 62/100/217 +f 31/255/218 61/63/218 76/82/218 +f 31/255/219 76/82/219 91/107/219 +f 62/100/220 212/254/220 77/101/220 +f 77/101/221 212/254/221 92/106/221 +f 31/255/222 91/107/222 106/126/222 +f 92/106/223 212/254/223 107/125/223 +f 31/255/224 106/126/224 121/133/224 +f 31/255/225 121/133/225 136/153/225 +f 107/125/226 212/254/226 122/132/226 +f 122/132/227 212/254/227 137/152/227 +f 31/255/228 136/153/228 151/172/228 +f 137/152/229 212/254/229 152/171/229 +f 31/255/230 151/172/230 166/256/230 +f 31/255/231 166/256/231 181/257/231 +f 152/171/232 212/254/232 167/180/232 +f 167/180/233 212/254/233 182/200/233 +f 31/255/234 181/257/234 196/258/234 +f 31/255/235 196/258/235 211/259/235 +f 182/200/236 212/254/236 197/226/236 +f 31/255/237 211/259/237 227/260/237 +f 197/226/238 212/254/238 213/245/238 +f 213/245/239 212/254/239 228/261/239 +f 31/255/240 227/260/240 242/262/240 +f 31/255/241 242/262/241 15/15/241 +f 237/250/242 236/248/242 10/21/242 +f 231/251/243 230/249/243 4/23/243 +f 238/252/244 237/250/244 10/21/244 +f 232/253/245 231/251/245 5/27/245 +f 239/239/246 238/252/246 11/25/246 +f 233/240/247 232/253/247 6/5/247 +f 240/241/248 239/239/248 13/1/248 +f 234/242/249 233/240/249 7/4/249 +f 228/261/250 212/254/250 1/13/250 +f 241/243/251 240/241/251 14/263/251 +f 235/244/252 234/242/252 8/10/252 +f 229/246/253 228/261/253 2/12/253 +f 242/247/254 241/243/254 15/264/254 +f 236/248/255 235/244/255 9/17/255 +f 230/249/256 229/246/256 3/19/256 +f 12/2/1 27/29/1 28/3/1 +f 6/5/2 21/30/2 22/6/2 +f 13/8/3 28/49/3 29/9/3 +f 7/4/4 22/6/4 23/11/4 +f 1/13/5 16/55/5 17/14/5 +f 14/7/6 29/9/6 30/16/6 +f 8/10/257 23/11/257 24/18/257 +f 2/12/258 17/14/258 18/20/258 +f 9/17/9 24/18/9 25/22/9 +f 3/19/259 18/20/259 19/24/259 +f 10/21/11 25/22/11 26/26/11 +f 4/23/260 19/24/260 20/28/260 +f 11/25/13 26/26/13 27/29/13 +f 5/27/14 20/28/14 21/30/14 +f 29/9/15 45/53/15 46/31/15 +f 23/33/16 39/54/16 40/34/16 +f 17/14/17 33/56/17 34/36/17 +f 24/32/18 40/34/18 41/38/18 +f 18/35/19 34/36/19 35/40/19 +f 25/37/261 41/38/261 42/42/261 +f 19/39/21 35/40/21 36/44/21 +f 26/41/22 42/42/22 43/46/22 +f 20/43/262 36/44/262 37/48/262 +f 27/45/24 43/46/24 44/50/24 +f 21/47/25 37/48/25 38/52/25 +f 28/49/26 44/50/26 45/53/26 +f 22/51/27 38/52/27 39/54/27 +f 16/55/28 32/61/28 33/56/28 +f 43/46/263 58/70/263 59/57/263 +f 37/48/30 52/71/30 53/58/30 +f 44/50/31 59/57/31 60/59/31 +f 38/52/32 53/58/32 54/60/32 +f 32/61/33 47/80/33 48/62/33 +f 45/53/34 60/59/34 61/63/34 +f 39/54/35 54/60/35 55/64/35 +f 33/56/36 48/62/36 49/65/36 +f 40/34/37 55/64/37 56/66/37 +f 34/36/38 49/65/38 50/67/38 +f 41/38/39 56/66/39 57/68/39 +f 35/40/40 50/67/40 51/69/40 +f 42/42/41 57/68/41 58/70/41 +f 36/44/42 51/69/42 52/71/42 +f 56/66/43 71/85/43 72/72/43 +f 50/67/44 65/86/44 66/73/44 +f 57/68/264 72/72/264 73/74/264 +f 51/69/46 66/73/46 67/75/46 +f 58/70/47 73/74/47 74/76/47 +f 52/71/48 67/75/48 68/77/48 +f 59/57/49 74/76/49 75/78/49 +f 53/58/50 68/77/50 69/79/50 +f 47/80/51 62/100/51 63/81/51 +f 60/59/52 75/78/52 76/82/52 +f 54/60/265 69/79/265 70/83/265 +f 48/62/54 63/81/54 64/84/54 +f 55/64/55 70/83/55 71/85/55 +f 49/65/56 64/84/56 65/86/56 +f 91/107/57 76/82/57 90/87/57 +f 85/90/58 70/83/58 84/88/58 +f 79/91/59 64/84/59 78/89/59 +f 86/92/266 71/85/266 85/90/266 +f 80/93/61 65/86/61 79/91/61 +f 87/94/62 72/72/62 86/92/62 +f 81/95/267 66/73/267 80/93/267 +f 88/96/64 73/74/64 87/94/64 +f 82/97/65 67/75/65 81/95/65 +f 89/98/66 74/76/66 88/96/66 +f 83/99/67 68/77/67 82/97/67 +f 90/87/68 75/78/68 89/98/68 +f 84/88/69 69/79/69 83/99/69 +f 78/89/70 63/81/70 77/101/70 +f 104/104/71 89/98/71 103/102/71 +f 98/105/72 83/99/72 97/103/72 +f 105/108/73 90/87/73 104/104/73 +f 99/109/74 84/88/74 98/105/74 +f 93/110/75 78/89/75 92/106/75 +f 106/126/76 91/107/76 105/108/76 +f 100/111/77 85/90/77 99/109/77 +f 94/112/78 79/91/78 93/110/78 +f 101/113/79 86/92/79 100/111/79 +f 95/114/80 80/93/80 94/112/80 +f 102/115/81 87/94/81 101/113/81 +f 96/116/82 81/95/82 95/114/82 +f 103/102/268 88/96/268 102/115/268 +f 97/103/269 82/97/269 96/116/269 +f 117/119/270 102/115/270 116/117/270 +f 111/120/86 96/116/86 110/118/86 +f 118/121/87 103/102/87 117/119/87 +f 112/122/271 97/103/271 111/120/271 +f 119/123/89 104/104/89 118/121/89 +f 113/124/90 98/105/90 112/122/90 +f 120/127/91 105/108/91 119/123/91 +f 114/128/92 99/109/92 113/124/92 +f 108/129/93 93/110/93 107/125/93 +f 121/133/94 106/126/94 120/127/94 +f 115/130/95 100/111/95 114/128/95 +f 109/131/96 94/112/96 108/129/96 +f 116/117/97 101/113/97 115/130/97 +f 110/118/98 95/114/98 109/131/98 +f 123/136/99 108/129/99 122/132/99 +f 136/153/100 121/133/100 135/134/100 +f 130/137/272 115/130/272 129/135/272 +f 124/138/102 109/131/102 123/136/102 +f 131/139/273 116/117/273 130/137/273 +f 125/140/104 110/118/104 124/138/104 +f 132/141/274 117/119/274 131/139/274 +f 126/142/106 111/120/106 125/140/106 +f 133/143/107 118/121/107 132/141/107 +f 127/144/275 112/122/275 126/142/275 +f 134/145/109 119/123/109 133/143/109 +f 128/146/276 113/124/276 127/144/276 +f 135/134/111 120/127/111 134/145/111 +f 129/135/112 114/128/112 128/146/112 +f 142/149/277 127/144/277 141/147/277 +f 149/150/114 134/145/114 148/148/114 +f 143/151/115 128/146/115 142/149/115 +f 150/154/116 135/134/116 149/150/116 +f 144/155/278 129/135/278 143/151/278 +f 138/156/118 123/136/118 137/152/118 +f 151/172/119 136/153/119 150/154/119 +f 145/157/279 130/137/279 144/155/279 +f 139/158/280 124/138/280 138/156/280 +f 146/159/281 131/139/281 145/157/281 +f 140/160/123 125/140/123 139/158/123 +f 147/161/124 132/141/124 146/159/124 +f 141/147/282 126/142/282 140/160/282 +f 148/148/283 133/143/283 147/161/283 +f 161/164/284 146/159/284 160/162/284 +f 155/165/128 140/160/128 154/163/128 +f 162/166/129 147/161/129 161/164/129 +f 156/188/285 141/147/285 155/165/285 +f 163/168/131 148/148/131 162/166/131 +f 141/147/286 156/188/286 157/167/286 +f 164/177/133 149/150/133 163/168/133 +f 158/170/134 143/151/134 157/167/134 +f 165/173/135 150/154/135 164/169/135 +f 159/174/136 144/155/136 158/170/136 +f 153/175/137 138/156/137 152/171/137 +f 166/256/138 151/172/138 165/173/138 +f 160/162/139 145/157/139 159/174/139 +f 154/163/140 139/158/140 153/175/140 +f 180/182/141 165/176/141 179/178/141 +f 174/183/142 159/174/142 173/179/142 +f 168/184/143 153/175/143 167/180/143 +f 181/201/144 166/181/144 180/182/144 +f 175/185/145 160/162/145 174/183/145 +f 169/186/146 154/163/146 168/184/146 +f 176/187/287 161/164/287 175/185/287 +f 170/189/148 155/165/148 169/186/148 +f 177/190/149 162/166/149 176/187/149 +f 171/191/288 156/188/288 170/189/288 +f 178/192/151 163/168/151 177/190/151 +f 172/193/289 157/167/289 171/191/289 +f 179/178/153 164/177/153 178/192/153 +f 173/179/154 158/170/154 172/193/154 +f 193/196/290 178/192/290 192/194/290 +f 187/197/156 172/193/156 186/195/156 +f 194/198/157 179/178/157 193/196/157 +f 188/199/291 173/179/291 187/197/291 +f 195/202/159 180/182/159 194/198/159 +f 189/203/160 174/183/160 188/199/160 +f 183/204/161 168/184/161 182/200/161 +f 196/220/162 181/201/162 195/202/162 +f 190/205/163 175/185/163 189/203/163 +f 184/206/292 169/186/292 183/204/292 +f 191/207/165 176/187/165 190/205/165 +f 185/208/166 170/189/166 184/206/166 +f 192/194/167 177/190/167 191/207/167 +f 186/195/168 171/191/168 185/208/168 +f 190/205/169 205/222/169 206/209/169 +f 184/206/170 199/223/170 200/210/170 +f 191/207/171 206/209/171 207/211/171 +f 185/208/293 200/210/293 201/212/293 +f 192/194/294 207/211/294 208/213/294 +f 186/195/174 201/212/174 202/214/174 +f 193/196/175 208/213/175 209/215/175 +f 187/197/295 202/214/295 203/216/295 +f 194/198/296 209/215/296 210/217/296 +f 188/199/178 203/216/178 204/218/178 +f 182/200/179 197/226/179 198/219/179 +f 195/202/180 210/217/180 211/221/180 +f 189/203/181 204/218/181 205/222/181 +f 183/204/297 198/219/297 199/223/297 +f 209/215/183 225/236/183 226/224/183 +f 203/216/184 219/237/184 220/225/184 +f 197/226/185 213/245/185 214/227/185 +f 210/217/186 226/224/186 227/228/186 +f 204/218/187 220/225/187 221/229/187 +f 198/219/188 214/227/188 215/230/188 +f 205/222/298 221/229/298 222/231/298 +f 199/223/190 215/230/190 216/232/190 +f 206/209/299 222/231/299 223/233/299 +f 200/210/192 216/232/192 217/234/192 +f 224/238/300 208/213/300 223/233/300 +f 201/212/194 217/234/194 218/235/194 +f 208/213/195 224/238/195 225/236/195 +f 202/214/196 218/235/196 219/237/196 +f 223/233/301 238/252/301 239/239/301 +f 217/234/198 232/253/198 233/240/198 +f 224/238/199 239/239/199 240/241/199 +f 218/235/200 233/240/200 234/242/200 +f 225/236/201 240/241/201 241/243/201 +f 219/237/202 234/242/202 235/244/202 +f 213/245/203 228/261/203 229/246/203 +f 226/224/204 241/243/204 242/247/204 +f 220/225/205 235/244/205 236/248/205 +f 214/227/206 229/246/206 230/249/206 +f 221/229/302 236/248/302 237/250/302 +f 215/230/208 230/249/208 231/251/208 +f 222/231/209 237/250/209 238/252/209 +f 216/232/303 231/251/303 232/253/303 +f 236/248/304 9/17/304 10/21/304 +f 230/249/305 3/19/305 4/23/305 +f 11/25/244 238/252/244 10/21/244 +f 231/251/306 4/23/306 5/27/306 +f 12/2/307 239/239/307 11/25/307 +f 232/253/308 5/27/308 6/5/308 +f 239/239/248 12/2/248 13/1/248 +f 233/240/309 6/5/309 7/4/309 +f 240/241/251 13/1/251 14/263/251 +f 234/242/310 7/4/310 8/10/310 +f 228/261/253 1/13/253 2/12/253 +f 241/243/311 14/263/311 15/264/311 +f 235/244/255 8/10/255 9/17/255 +f 229/246/256 2/12/256 3/19/256 diff --git a/src/datavis3d/engine/meshes/sphereSmooth.obj b/src/datavis3d/engine/meshes/sphereSmooth.obj new file mode 100644 index 00000000..3c5b1299 --- /dev/null +++ b/src/datavis3d/engine/meshes/sphereSmooth.obj @@ -0,0 +1,1232 @@ +# Blender v2.66 (sub 0) OBJ File: 'sphere.blend' +# www.blender.org +o Sphere +v -0.195090 0.980785 0.000000 +v -0.382683 0.923880 0.000000 +v -0.555570 0.831470 0.000000 +v -0.707107 0.707107 0.000000 +v -0.831470 0.555570 0.000000 +v -0.923880 0.382683 0.000000 +v -0.980785 0.195090 0.000000 +v -1.000000 0.000000 0.000000 +v -0.980785 -0.195090 0.000000 +v -0.923880 -0.382683 0.000000 +v -0.831470 -0.555570 0.000000 +v -0.707107 -0.707107 0.000000 +v -0.555570 -0.831470 0.000000 +v -0.382683 -0.923880 0.000000 +v -0.195090 -0.980785 0.000000 +v -0.180240 0.980785 -0.074658 +v -0.353553 0.923880 -0.146447 +v -0.513280 0.831470 -0.212608 +v -0.653281 0.707107 -0.270598 +v -0.768178 0.555570 -0.318190 +v -0.853553 0.382683 -0.353553 +v -0.906127 0.195090 -0.375330 +v -0.923880 0.000000 -0.382684 +v -0.906127 -0.195090 -0.375330 +v -0.853553 -0.382683 -0.353554 +v -0.768178 -0.555570 -0.318190 +v -0.653281 -0.707107 -0.270598 +v -0.513280 -0.831470 -0.212608 +v -0.353553 -0.923880 -0.146447 +v -0.180240 -0.980785 -0.074658 +v 0.000000 -1.000000 0.000000 +v -0.137950 0.980785 -0.137950 +v -0.270598 0.923880 -0.270598 +v -0.392847 0.831470 -0.392848 +v -0.500000 0.707107 -0.500000 +v -0.587938 0.555570 -0.587938 +v -0.653281 0.382683 -0.653282 +v -0.693520 0.195090 -0.693520 +v -0.707107 0.000000 -0.707107 +v -0.693520 -0.195090 -0.693520 +v -0.653281 -0.382683 -0.653282 +v -0.587938 -0.555570 -0.587938 +v -0.500000 -0.707107 -0.500000 +v -0.392847 -0.831470 -0.392848 +v -0.270598 -0.923880 -0.270598 +v -0.137949 -0.980785 -0.137950 +v -0.074658 0.980785 -0.180240 +v -0.146446 0.923880 -0.353554 +v -0.212607 0.831470 -0.513280 +v -0.270598 0.707107 -0.653282 +v -0.318189 0.555570 -0.768178 +v -0.353553 0.382683 -0.853554 +v -0.375330 0.195090 -0.906128 +v -0.382683 0.000000 -0.923880 +v -0.375330 -0.195090 -0.906128 +v -0.353553 -0.382683 -0.853554 +v -0.318189 -0.555570 -0.768178 +v -0.270598 -0.707107 -0.653282 +v -0.212607 -0.831470 -0.513280 +v -0.146446 -0.923880 -0.353554 +v -0.074658 -0.980785 -0.180240 +v 0.000000 0.980785 -0.195091 +v 0.000000 0.923880 -0.382684 +v 0.000000 0.831470 -0.555570 +v 0.000000 0.707107 -0.707107 +v 0.000000 0.555570 -0.831470 +v 0.000000 0.382683 -0.923880 +v 0.000000 0.195090 -0.980785 +v 0.000000 0.000000 -1.000000 +v 0.000000 -0.195090 -0.980785 +v 0.000000 -0.382683 -0.923880 +v 0.000000 -0.555570 -0.831470 +v 0.000000 -0.707107 -0.707107 +v 0.000000 -0.831470 -0.555570 +v 0.000000 -0.923880 -0.382684 +v 0.000000 -0.980785 -0.195090 +v 0.074658 0.980785 -0.180240 +v 0.146447 0.923880 -0.353554 +v 0.212608 0.831470 -0.513280 +v 0.270598 0.707107 -0.653282 +v 0.318190 0.555570 -0.768178 +v 0.353554 0.382683 -0.853553 +v 0.375331 0.195090 -0.906128 +v 0.382684 0.000000 -0.923880 +v 0.375331 -0.195090 -0.906128 +v 0.353554 -0.382683 -0.853553 +v 0.318190 -0.555570 -0.768178 +v 0.270598 -0.707107 -0.653282 +v 0.212608 -0.831470 -0.513280 +v 0.146447 -0.923880 -0.353554 +v 0.074658 -0.980785 -0.180240 +v 0.137950 0.980785 -0.137950 +v 0.270599 0.923880 -0.270598 +v 0.392848 0.831470 -0.392848 +v 0.500000 0.707107 -0.500000 +v 0.587938 0.555570 -0.587938 +v 0.653282 0.382683 -0.653282 +v 0.693520 0.195090 -0.693520 +v 0.707107 0.000000 -0.707107 +v 0.693520 -0.195090 -0.693520 +v 0.653282 -0.382683 -0.653281 +v 0.587938 -0.555570 -0.587938 +v 0.500000 -0.707107 -0.500000 +v 0.392848 -0.831470 -0.392848 +v 0.270599 -0.923880 -0.270598 +v 0.137950 -0.980785 -0.137950 +v 0.180241 0.980785 -0.074658 +v 0.353554 0.923880 -0.146447 +v 0.513280 0.831470 -0.212608 +v 0.653282 0.707107 -0.270598 +v 0.768178 0.555570 -0.318190 +v 0.853554 0.382683 -0.353553 +v 0.906128 0.195090 -0.375330 +v 0.923880 0.000000 -0.382683 +v 0.906128 -0.195090 -0.375330 +v 0.853554 -0.382683 -0.353553 +v 0.768178 -0.555570 -0.318190 +v 0.653282 -0.707107 -0.270598 +v 0.513280 -0.831470 -0.212608 +v 0.353554 -0.923880 -0.146447 +v 0.180240 -0.980785 -0.074658 +v 0.195091 0.980785 0.000000 +v 0.382684 0.923880 0.000000 +v 0.555571 0.831470 0.000000 +v 0.707107 0.707107 0.000000 +v 0.831470 0.555570 0.000000 +v 0.923880 0.382683 0.000000 +v 0.980786 0.195090 0.000000 +v 1.000000 0.000000 0.000000 +v 0.980786 -0.195090 0.000000 +v 0.923880 -0.382683 0.000000 +v 0.831470 -0.555570 0.000000 +v 0.707107 -0.707107 0.000000 +v 0.555571 -0.831470 0.000000 +v 0.382684 -0.923880 0.000000 +v 0.195091 -0.980785 0.000000 +v 0.180241 0.980785 0.074658 +v 0.353554 0.923880 0.146447 +v 0.513280 0.831470 0.212608 +v 0.653282 0.707107 0.270598 +v 0.768178 0.555570 0.318190 +v 0.853554 0.382683 0.353553 +v 0.906128 0.195090 0.375330 +v 0.923880 0.000000 0.382684 +v 0.906128 -0.195090 0.375330 +v 0.853554 -0.382683 0.353553 +v 0.768178 -0.555570 0.318190 +v 0.653282 -0.707107 0.270598 +v 0.513280 -0.831470 0.212608 +v 0.353554 -0.923880 0.146447 +v 0.180240 -0.980785 0.074658 +v 0.137950 0.980785 0.137950 +v 0.270599 0.923880 0.270598 +v 0.392848 0.831470 0.392848 +v 0.500000 0.707107 0.500000 +v 0.587938 0.555570 0.587938 +v 0.653282 0.382683 0.653282 +v 0.693520 0.195090 0.693520 +v 0.707107 0.000000 0.707107 +v 0.693520 -0.195090 0.693520 +v 0.653282 -0.382683 0.653282 +v 0.587938 -0.555570 0.587938 +v 0.500000 -0.707107 0.500000 +v 0.392848 -0.831470 0.392848 +v 0.270599 -0.923880 0.270598 +v 0.137950 -0.980785 0.137950 +v 0.074658 0.980785 0.180240 +v 0.146447 0.923880 0.353554 +v 0.212608 0.831470 0.513280 +v 0.270598 0.707107 0.653282 +v 0.318190 0.555570 0.768178 +v 0.353554 0.382683 0.853553 +v 0.375331 0.195090 0.906128 +v 0.382684 0.000000 0.923880 +v 0.375331 -0.195090 0.906128 +v 0.353554 -0.382683 0.853553 +v 0.318190 -0.555570 0.768178 +v 0.270598 -0.707107 0.653282 +v 0.212608 -0.831470 0.513280 +v 0.146447 -0.923880 0.353554 +v 0.074658 -0.980785 0.180240 +v 0.000000 0.980785 0.195091 +v 0.000000 0.923880 0.382684 +v 0.000000 0.831470 0.555570 +v 0.000000 0.707107 0.707107 +v 0.000000 0.555570 0.831470 +v 0.000000 0.382683 0.923880 +v 0.000000 0.195090 0.980785 +v 0.000000 0.000000 1.000000 +v 0.000000 -0.195090 0.980785 +v 0.000000 -0.382683 0.923879 +v 0.000000 -0.555570 0.831470 +v 0.000000 -0.707107 0.707107 +v 0.000000 -0.831470 0.555570 +v 0.000000 -0.923880 0.382684 +v 0.000000 -0.980785 0.195090 +v -0.074658 0.980785 0.180240 +v -0.146446 0.923880 0.353554 +v -0.212607 0.831470 0.513280 +v -0.270598 0.707107 0.653282 +v -0.318189 0.555570 0.768178 +v -0.353553 0.382683 0.853553 +v -0.375330 0.195090 0.906128 +v -0.382683 0.000000 0.923880 +v -0.375330 -0.195090 0.906128 +v -0.353553 -0.382683 0.853553 +v -0.318189 -0.555570 0.768178 +v -0.270598 -0.707107 0.653282 +v -0.212607 -0.831470 0.513280 +v -0.146446 -0.923880 0.353554 +v -0.074658 -0.980785 0.180240 +v 0.000000 1.000000 0.000000 +v -0.137950 0.980785 0.137950 +v -0.270598 0.923880 0.270598 +v -0.392847 0.831470 0.392848 +v -0.500000 0.707107 0.500000 +v -0.587938 0.555570 0.587938 +v -0.653281 0.382683 0.653281 +v -0.693520 0.195090 0.693520 +v -0.707107 0.000000 0.707107 +v -0.693520 -0.195090 0.693520 +v -0.653281 -0.382683 0.653281 +v -0.587938 -0.555570 0.587938 +v -0.500000 -0.707107 0.500000 +v -0.392847 -0.831470 0.392848 +v -0.270598 -0.923880 0.270598 +v -0.137949 -0.980785 0.137950 +v -0.180240 0.980785 0.074658 +v -0.353553 0.923880 0.146447 +v -0.513280 0.831470 0.212608 +v -0.653281 0.707107 0.270598 +v -0.768177 0.555570 0.318190 +v -0.853553 0.382683 0.353553 +v -0.906127 0.195090 0.375330 +v -0.923879 0.000000 0.382683 +v -0.906127 -0.195090 0.375330 +v -0.853553 -0.382683 0.353553 +v -0.768177 -0.555570 0.318190 +v -0.653281 -0.707107 0.270598 +v -0.513280 -0.831470 0.212608 +v -0.353553 -0.923880 0.146447 +v -0.180240 -0.980785 0.074658 +vt 0.040867 0.325557 +vt 0.048386 0.386583 +vt 0.001015 0.334499 +vt 0.081872 0.692529 +vt 0.092315 0.752973 +vt 0.006404 0.709363 +vt 1.031336 0.264931 +vt 1.040867 0.325557 +vt 0.999822 0.272029 +vt 0.073887 0.631595 +vt 0.005301 0.646891 +vt 0.333915 0.937286 +vt 0.448527 0.905466 +vt 0.447682 0.976645 +vt 1.017784 0.205113 +vt 0.998129 0.209571 +vt 0.067156 0.570413 +vt 0.004397 0.584414 +vt 0.196016 0.918498 +vt 0.034176 0.958662 +vt 0.060989 0.509119 +vt 0.003585 0.521934 +vt 0.135028 0.869370 +vt 0.015221 0.896641 +vt 0.054891 0.447811 +vt 0.002796 0.459454 +vt 0.107782 0.812401 +vt 0.010297 0.834265 +vt 0.001965 0.396975 +vt 0.007907 0.771825 +vt 0.978319 0.207096 +vt 1.004397 0.584414 +vt 1.005301 0.646891 +vt 0.941200 0.576589 +vt 1.034176 0.958662 +vt 0.823807 0.933258 +vt 1.003585 0.521934 +vt 0.945911 0.514786 +vt 1.015221 0.896641 +vt 0.885287 0.880701 +vt 1.002796 0.459454 +vt 0.950535 0.452971 +vt 1.010297 0.834265 +vt 0.908873 0.821779 +vt 1.001965 0.396975 +vt 0.955439 0.391196 +vt 1.007907 0.771825 +vt 0.921503 0.761167 +vt 1.001015 0.334499 +vt 0.961079 0.329532 +vt 1.006404 0.709363 +vt 0.929787 0.699898 +vt 0.968202 0.268089 +vt 0.936013 0.638321 +vt 0.488610 0.915189 +vt 0.647808 0.950687 +vt 0.921611 0.311033 +vt 0.859136 0.666985 +vt 0.937209 0.253354 +vt 0.870446 0.607941 +vt 0.532175 0.909643 +vt 0.657607 0.903302 +vt 0.959449 0.197860 +vt 0.880347 0.548455 +vt 0.745300 0.879338 +vt 0.889690 0.488794 +vt 0.796385 0.834663 +vt 0.899158 0.429173 +vt 0.825891 0.781668 +vt 0.909472 0.369816 +vt 0.845097 0.725165 +vt 0.848920 0.390841 +vt 0.761226 0.728711 +vt 0.864196 0.334814 +vt 0.780693 0.674598 +vt 0.882867 0.280332 +vt 0.796418 0.618773 +vt 0.907539 0.228698 +vt 0.810089 0.562031 +vt 0.558962 0.891763 +vt 0.641452 0.857179 +vt 0.942759 0.182515 +vt 0.822818 0.504873 +vt 0.697492 0.824480 +vt 0.835477 0.447684 +vt 0.735147 0.779653 +vt 0.879896 0.195479 +vt 0.753309 0.508011 +vt 0.618082 0.815427 +vt 0.767315 0.452094 +vt 0.657173 0.773912 +vt 0.782092 0.396562 +vt 0.685241 0.725518 +vt 0.798714 0.341964 +vt 0.706593 0.673391 +vt 0.818709 0.289116 +vt 0.723996 0.619193 +vt 0.844487 0.239416 +vt 0.739178 0.563865 +vt 0.567268 0.868303 +vt 0.563300 0.844314 +vt 0.770454 0.236269 +vt 0.670392 0.566231 +vt 0.805029 0.190637 +vt 0.683774 0.509644 +vt 0.551952 0.822879 +vt 0.929896 0.162212 +vt 0.855308 0.155368 +vt 0.697011 0.452991 +vt 0.591182 0.780044 +vt 0.710973 0.396675 +vt 0.618699 0.730484 +vt 0.726705 0.341193 +vt 0.639317 0.677374 +vt 0.745717 0.287291 +vt 0.655961 0.622327 +vt 0.665037 0.288362 +vt 0.594131 0.638967 +vt 0.684737 0.232805 +vt 0.605914 0.580518 +vt 0.713639 0.180821 +vt 0.616615 0.521685 +vt 0.760428 0.136665 +vt 0.627046 0.462757 +vt 0.536166 0.805967 +vt 0.923407 0.138703 +vt 0.836350 0.110271 +vt 0.637946 0.403995 +vt 0.562017 0.752770 +vt 0.650183 0.345708 +vt 0.580132 0.696622 +vt 0.517784 0.794886 +vt 0.927547 0.114679 +vt 0.833915 0.062714 +vt 0.573887 0.368405 +vt 0.531336 0.735069 +vt 0.581872 0.307471 +vt 0.540867 0.674443 +vt 0.592315 0.247027 +vt 0.548386 0.613417 +vt 0.607782 0.187599 +vt 0.554891 0.552189 +vt 0.635028 0.130630 +vt 0.560989 0.490881 +vt 0.696016 0.081502 +vt 0.567156 0.429587 +vt 0.502796 0.540546 +vt 0.515221 0.103359 +vt 0.503585 0.478066 +vt 0.534176 0.041338 +vt 0.504397 0.415586 +vt 0.498129 0.790428 +vt 0.948527 0.094534 +vt 0.947682 0.023355 +vt 0.505301 0.353109 +vt 0.499822 0.727971 +vt 0.506404 0.290637 +vt 0.501015 0.665501 +vt 0.507907 0.228175 +vt 0.501965 0.603025 +vt 0.510297 0.165735 +vt 0.429787 0.300102 +vt 0.461079 0.670468 +vt 0.421503 0.238833 +vt 0.455439 0.608804 +vt 0.408873 0.178221 +vt 0.445911 0.485214 +vt 0.385287 0.119299 +vt 1.323807 0.066742 +vt 0.441200 0.423411 +vt 0.478319 0.792904 +vt 0.988610 0.084811 +vt 1.147808 0.049313 +vt 0.436013 0.361679 +vt 0.468202 0.731911 +vt 0.147808 0.049313 +vt 0.323807 0.066742 +vt 0.245300 0.120661 +vt 0.380347 0.451545 +vt 0.459449 0.802140 +vt 0.032175 0.090357 +vt 0.157607 0.096698 +vt 0.370446 0.392059 +vt 0.437209 0.746646 +vt 0.359136 0.333015 +vt 0.421611 0.688967 +vt 0.345097 0.274835 +vt 0.450536 0.547029 +vt 0.409472 0.630184 +vt 0.325892 0.218332 +vt 0.399158 0.570827 +vt 0.296385 0.165337 +vt 0.389690 0.511206 +vt 0.261226 0.271289 +vt 0.348920 0.609159 +vt 0.235147 0.220347 +vt 0.335478 0.552316 +vt 0.197492 0.175520 +vt 0.322818 0.495127 +vt 0.442759 0.817485 +vt 0.058962 0.108237 +vt 0.141452 0.142821 +vt 0.310089 0.437969 +vt 0.407539 0.771302 +vt 0.296418 0.381227 +vt 0.382867 0.719668 +vt 0.280693 0.325402 +vt 0.364196 0.665186 +vt 0.223996 0.380807 +vt 0.318709 0.710884 +vt 0.206593 0.326609 +vt 0.298714 0.658036 +vt 0.185241 0.274482 +vt 0.282092 0.603438 +vt 0.157173 0.226088 +vt 0.267315 0.547906 +vt 0.118082 0.184573 +vt 0.253309 0.491989 +vt 0.379896 0.804521 +vt 0.067268 0.131697 +vt 0.063300 0.155685 +vt 0.239178 0.436135 +vt 0.344487 0.760584 +vt 0.091182 0.219955 +vt 0.197011 0.547009 +vt 0.429896 0.837788 +vt 0.355308 0.844632 +vt 0.051952 0.177121 +vt 0.183774 0.490356 +vt 0.305029 0.809363 +vt 0.170392 0.433769 +vt 0.270454 0.763731 +vt 0.155961 0.377673 +vt 0.245717 0.712709 +vt 0.226706 0.658807 +vt 0.118699 0.269516 +vt 0.210973 0.603325 +vt 0.139317 0.322626 +vt 0.094131 0.361033 +vt 0.165037 0.711638 +vt 0.080132 0.303378 +vt 0.150183 0.654292 +vt 0.062017 0.247229 +vt 0.137946 0.596005 +vt 0.423407 0.861296 +vt 0.336350 0.889729 +vt 0.036166 0.194032 +vt 0.127046 0.537243 +vt 0.260428 0.863335 +vt 0.116615 0.478315 +vt 0.213639 0.819179 +vt 0.105914 0.419482 +vt 0.184737 0.767195 +vt 0.495265 0.852856 +vt 0.995265 0.147143 +vt 1.032175 0.090357 +vt 1.058962 0.108237 +vt 1.067268 0.131697 +vt 1.063300 0.155685 +vt 1.051952 0.177121 +vt 0.427547 0.885321 +vt 1.036166 0.194032 +vt 0.031336 0.264931 +vt 0.017784 0.205113 +vn -0.563891 -0.825831 0.000000 +vn -0.713095 -0.701041 0.000000 +vn -0.520981 -0.825831 -0.215796 +vn -0.981231 0.192785 0.000000 +vn -0.925596 0.378430 0.000000 +vn -0.906522 0.192785 -0.375500 +vn -0.393017 -0.919523 0.000000 +vn -0.363109 -0.919523 -0.150395 +vn -1.000000 0.000000 0.000000 +vn -0.923856 0.000000 -0.382672 +vn -0.393017 0.919523 0.000000 +vn -0.206793 0.978362 0.000000 +vn -0.363109 0.919523 -0.150395 +vn -0.206793 -0.978362 0.000000 +vn -0.191046 -0.978362 -0.079134 +vn -0.981231 -0.192785 0.000000 +vn -0.906522 -0.192785 -0.375500 +vn -0.563891 0.825831 0.000000 +vn -0.520981 0.825831 -0.215796 +vn -0.925596 -0.378430 0.000000 +vn -0.855159 -0.378430 -0.354198 +vn -0.713095 0.701041 0.000000 +vn -0.658803 0.701041 -0.272866 +vn -0.835139 -0.550005 0.000000 +vn -0.771569 -0.550005 -0.319590 +vn -0.835139 0.550005 0.000000 +vn -0.771569 0.550005 -0.319590 +vn -0.658803 -0.701041 -0.272866 +vn -0.855159 0.378430 -0.354198 +vn -0.146214 -0.978362 -0.146214 +vn -0.693838 -0.192785 -0.693838 +vn -0.398724 0.825831 -0.398724 +vn -0.654500 -0.378430 -0.654500 +vn -0.504227 0.701041 -0.504227 +vn -0.590533 -0.550005 -0.590533 +vn -0.590533 0.550005 -0.590533 +vn -0.504227 -0.701041 -0.504227 +vn -0.654500 0.378430 -0.654500 +vn -0.398724 -0.825831 -0.398724 +vn -0.693838 0.192785 -0.693838 +vn -0.277902 -0.919523 -0.277902 +vn -0.707083 0.000000 -0.707083 +vn -0.191046 0.978362 -0.079134 +vn -0.277902 0.919523 -0.277902 +vn -0.215796 -0.825831 -0.520981 +vn -0.375500 0.192785 -0.906522 +vn -0.150395 -0.919523 -0.363109 +vn -0.382672 0.000000 -0.923856 +vn -0.146214 0.978362 -0.146214 +vn -0.150395 0.919523 -0.363109 +vn -0.079134 -0.978362 -0.191046 +vn -0.375500 -0.192785 -0.906522 +vn -0.215796 0.825831 -0.520981 +vn -0.354198 -0.378430 -0.855159 +vn -0.272866 0.701041 -0.658803 +vn -0.319590 -0.550005 -0.771569 +vn -0.319590 0.550005 -0.771569 +vn -0.272866 -0.701041 -0.658803 +vn -0.354198 0.378430 -0.855159 +vn 0.000000 -0.550005 -0.835139 +vn 0.000000 0.550005 -0.835139 +vn 0.000000 -0.701041 -0.713095 +vn 0.000000 0.378430 -0.925596 +vn 0.000000 -0.825831 -0.563891 +vn 0.000000 0.192785 -0.981231 +vn 0.000000 -0.919523 -0.393017 +vn 0.000000 0.000000 -1.000000 +vn -0.079134 0.978362 -0.191046 +vn 0.000000 0.919523 -0.393017 +vn 0.000000 -0.978362 -0.206793 +vn 0.000000 -0.192785 -0.981231 +vn 0.000000 0.825831 -0.563891 +vn 0.000000 -0.378430 -0.925596 +vn 0.000000 0.701041 -0.713095 +vn 0.150395 -0.919523 -0.363109 +vn 0.382672 0.000000 -0.923856 +vn 0.150395 0.919523 -0.363109 +vn 0.375500 -0.192785 -0.906522 +vn 0.215796 0.825831 -0.520981 +vn 0.354198 -0.378430 -0.855159 +vn 0.272866 0.701041 -0.658803 +vn 0.319590 -0.550005 -0.771569 +vn 0.319590 0.550005 -0.771569 +vn 0.272866 -0.701041 -0.658803 +vn 0.354198 0.378430 -0.855159 +vn 0.215796 -0.825831 -0.520981 +vn 0.375500 0.192785 -0.906522 +vn 0.000000 0.978362 -0.206793 +vn 0.079134 0.978362 -0.191046 +vn 0.504227 -0.701041 -0.504227 +vn 0.654500 0.378430 -0.654500 +vn 0.398724 -0.825831 -0.398724 +vn 0.693838 0.192785 -0.693838 +vn 0.146214 0.978362 -0.146214 +vn 0.079134 -0.978362 -0.191046 +vn 0.277902 -0.919523 -0.277902 +vn 0.707083 0.000000 -0.707083 +vn 0.277902 0.919523 -0.277902 +vn 0.693838 -0.192785 -0.693838 +vn 0.398724 0.825831 -0.398724 +vn 0.654500 -0.378430 -0.654500 +vn 0.504227 0.701041 -0.504227 +vn 0.590533 -0.550005 -0.590533 +vn 0.590533 0.550005 -0.590533 +vn 0.855159 -0.378430 -0.354198 +vn 0.658803 0.701041 -0.272866 +vn 0.771569 -0.550005 -0.319590 +vn 0.771569 0.550005 -0.319590 +vn 0.658803 -0.701041 -0.272866 +vn 0.855159 0.378430 -0.354198 +vn 0.520981 -0.825831 -0.215796 +vn 0.906522 0.192785 -0.375500 +vn 0.191046 0.978362 -0.079134 +vn 0.146214 -0.978362 -0.146214 +vn 0.363109 -0.919523 -0.150395 +vn 0.923856 0.000000 -0.382672 +vn 0.363109 0.919523 -0.150395 +vn 0.906522 -0.192785 -0.375500 +vn 0.520981 0.825831 -0.215796 +vn 0.206793 0.978362 0.000000 +vn 0.191046 -0.978362 -0.079134 +vn 0.393017 -0.919523 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.393017 0.919523 0.000000 +vn 0.981231 -0.192785 0.000000 +vn 0.563891 0.825831 0.000000 +vn 0.925596 -0.378430 0.000000 +vn 0.713095 0.701041 0.000000 +vn 0.835139 -0.550005 0.000000 +vn 0.835139 0.550005 0.000000 +vn 0.713095 -0.701041 0.000000 +vn 0.925596 0.378430 0.000000 +vn 0.563891 -0.825831 0.000000 +vn 0.981231 0.192785 0.000000 +vn 0.771569 0.550005 0.319590 +vn 0.658803 -0.701041 0.272866 +vn 0.855159 0.378430 0.354198 +vn 0.520981 -0.825831 0.215796 +vn 0.906522 0.192785 0.375500 +vn 0.191046 0.978362 0.079134 +vn 0.206793 -0.978362 0.000000 +vn 0.363109 -0.919523 0.150395 +vn 0.923856 0.000000 0.382672 +vn 0.363109 0.919523 0.150395 +vn 0.906522 -0.192785 0.375500 +vn 0.520981 0.825831 0.215796 +vn 0.855159 -0.378430 0.354198 +vn 0.658803 0.701041 0.272866 +vn 0.771569 -0.550005 0.319590 +vn 0.693838 -0.192785 0.693838 +vn 0.398724 0.825831 0.398724 +vn 0.654500 -0.378430 0.654500 +vn 0.504227 0.701041 0.504227 +vn 0.590533 -0.550005 0.590533 +vn 0.654500 0.378430 0.654500 +vn 0.504227 -0.701041 0.504227 +vn 0.398724 -0.825831 0.398724 +vn 0.693838 0.192785 0.693838 +vn 0.146214 0.978362 0.146214 +vn 0.191046 -0.978362 0.079134 +vn 0.277902 -0.919523 0.277902 +vn 0.707083 0.000000 0.707083 +vn 0.277902 0.919523 0.277902 +vn 0.215796 -0.825831 0.520981 +vn 0.375500 0.192785 0.906522 +vn 0.079134 0.978362 0.191046 +vn 0.146214 -0.978362 0.146214 +vn 0.150395 -0.919523 0.363109 +vn 0.382672 0.000000 0.923856 +vn 0.150395 0.919523 0.363109 +vn 0.375500 -0.192785 0.906522 +vn 0.215796 0.825831 0.520981 +vn 0.354198 -0.378430 0.855159 +vn 0.590533 0.550005 0.590533 +vn 0.272866 0.701041 0.658803 +vn 0.319590 -0.550005 0.771569 +vn 0.319590 0.550005 0.771569 +vn 0.272866 -0.701041 0.658803 +vn 0.354198 0.378430 0.855159 +vn 0.000000 -0.550005 0.835139 +vn 0.000000 0.550005 0.835139 +vn 0.000000 -0.701041 0.713095 +vn 0.000000 0.378430 0.925596 +vn 0.000000 -0.825831 0.563891 +vn 0.000000 0.192785 0.981231 +vn 0.000000 0.978362 0.206793 +vn 0.079134 -0.978362 0.191046 +vn 0.000000 -0.919523 0.393017 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.919523 0.393017 +vn 0.000000 -0.192785 0.981231 +vn 0.000000 0.825831 0.563891 +vn 0.000000 -0.378430 0.925596 +vn 0.000000 0.701041 0.713095 +vn -0.354198 -0.378430 0.855159 +vn -0.272866 0.701041 0.658803 +vn -0.319590 -0.550005 0.771569 +vn -0.319590 0.550005 0.771569 +vn -0.272866 -0.701041 0.658803 +vn -0.354198 0.378430 0.855159 +vn -0.215796 -0.825831 0.520981 +vn -0.375500 0.192785 0.906522 +vn -0.150395 -0.919523 0.363109 +vn -0.382672 0.000000 0.923856 +vn -0.150395 0.919523 0.363109 +vn 0.000000 -0.978362 0.206793 +vn -0.079134 -0.978362 0.191046 +vn -0.375500 -0.192785 0.906522 +vn -0.215796 0.825831 0.520981 +vn -0.277902 -0.919523 0.277902 +vn -0.707083 0.000000 0.707083 +vn -0.079134 0.978362 0.191046 +vn -0.277902 0.919523 0.277902 +vn -0.146214 -0.978362 0.146214 +vn -0.693838 -0.192785 0.693838 +vn -0.398724 0.825831 0.398724 +vn -0.654500 -0.378430 0.654500 +vn -0.504227 0.701041 0.504227 +vn -0.590533 -0.550005 0.590533 +vn -0.590533 0.550005 0.590533 +vn -0.654500 0.378430 0.654500 +vn -0.398724 -0.825831 0.398724 +vn -0.693838 0.192785 0.693838 +vn -0.504227 -0.701041 0.504227 +vn -0.658803 -0.701041 0.272866 +vn -0.855159 0.378430 0.354198 +vn -0.520981 -0.825831 0.215796 +vn -0.906522 0.192785 0.375500 +vn -0.363109 -0.919523 0.150395 +vn -0.923856 0.000000 0.382672 +vn -0.146214 0.978362 0.146214 +vn -0.363109 0.919523 0.150395 +vn -0.191046 -0.978362 0.079134 +vn -0.906522 -0.192785 0.375500 +vn -0.520981 0.825831 0.215796 +vn -0.855159 -0.378430 0.354198 +vn -0.658803 0.701041 0.272866 +vn -0.771569 -0.550005 0.319590 +vn -0.771569 0.550005 0.319590 +vn 0.000000 0.999969 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.191046 0.978362 0.079134 +s 1 +f 13/1/1 12/2/2 28/3/3 +f 7/4/4 6/5/5 22/6/6 +f 14/7/7 13/8/1 29/9/8 +f 8/10/9 7/4/4 23/11/10 +f 2/12/11 1/13/12 17/14/13 +f 15/15/14 14/7/7 30/16/15 +f 9/17/16 8/10/9 24/18/17 +f 3/19/18 2/12/11 18/20/19 +f 10/21/20 9/17/16 25/22/21 +f 4/23/22 3/19/18 19/24/23 +f 11/25/24 10/21/20 26/26/25 +f 5/27/26 4/23/22 20/28/27 +f 12/2/2 11/25/24 27/29/28 +f 6/5/5 5/27/26 21/30/29 +f 30/16/15 29/9/8 46/31/30 +f 24/32/17 23/33/10 40/34/31 +f 18/35/19 17/14/13 34/36/32 +f 25/37/21 24/32/17 41/38/33 +f 19/39/23 18/35/19 35/40/34 +f 26/41/25 25/37/21 42/42/35 +f 20/43/27 19/39/23 36/44/36 +f 27/45/28 26/41/25 43/46/37 +f 21/47/29 20/43/27 37/48/38 +f 28/49/3 27/45/28 44/50/39 +f 22/51/6 21/47/29 38/52/40 +f 29/9/8 28/49/3 45/53/41 +f 23/33/10 22/51/6 39/54/42 +f 17/14/13 16/55/43 33/56/44 +f 44/50/39 43/46/37 59/57/45 +f 38/52/40 37/48/38 53/58/46 +f 45/53/41 44/50/39 60/59/47 +f 39/54/42 38/52/40 54/60/48 +f 33/56/44 32/61/49 48/62/50 +f 46/31/30 45/53/41 61/63/51 +f 40/34/31 39/54/42 55/64/52 +f 34/36/32 33/56/44 49/65/53 +f 41/38/33 40/34/31 56/66/54 +f 35/40/34 34/36/32 50/67/55 +f 42/42/35 41/38/33 57/68/56 +f 36/44/36 35/40/34 51/69/57 +f 43/46/37 42/42/35 58/70/58 +f 37/48/38 36/44/36 52/71/59 +f 57/68/56 56/66/54 72/72/60 +f 51/69/57 50/67/55 66/73/61 +f 58/70/58 57/68/56 73/74/62 +f 52/71/59 51/69/57 67/75/63 +f 59/57/45 58/70/58 74/76/64 +f 53/58/46 52/71/59 68/77/65 +f 60/59/47 59/57/45 75/78/66 +f 54/60/48 53/58/46 69/79/67 +f 48/62/50 47/80/68 63/81/69 +f 61/63/51 60/59/47 76/82/70 +f 55/64/52 54/60/48 70/83/71 +f 49/65/53 48/62/50 64/84/72 +f 56/66/54 55/64/52 71/85/73 +f 50/67/55 49/65/53 65/86/74 +f 76/82/70 75/78/66 90/87/75 +f 70/83/71 69/79/67 84/88/76 +f 64/84/72 63/81/69 78/89/77 +f 71/85/73 70/83/71 85/90/78 +f 65/86/74 64/84/72 79/91/79 +f 72/72/60 71/85/73 86/92/80 +f 66/73/61 65/86/74 80/93/81 +f 73/74/62 72/72/60 87/94/82 +f 67/75/63 66/73/61 81/95/83 +f 74/76/64 73/74/62 88/96/84 +f 68/77/65 67/75/63 82/97/85 +f 75/78/66 74/76/64 89/98/86 +f 69/79/67 68/77/65 83/99/87 +f 63/81/69 62/100/88 77/101/89 +f 89/98/86 88/96/84 103/102/90 +f 83/99/87 82/97/85 97/103/91 +f 90/87/75 89/98/86 104/104/92 +f 84/88/76 83/99/87 98/105/93 +f 78/89/77 77/101/89 92/106/94 +f 91/107/95 90/87/75 105/108/96 +f 85/90/78 84/88/76 99/109/97 +f 79/91/79 78/89/77 93/110/98 +f 86/92/80 85/90/78 100/111/99 +f 80/93/81 79/91/79 94/112/100 +f 87/94/82 86/92/80 101/113/101 +f 81/95/83 80/93/81 95/114/102 +f 88/96/84 87/94/82 102/115/103 +f 82/97/85 81/95/83 96/116/104 +f 102/115/103 101/113/101 116/117/105 +f 96/116/104 95/114/102 110/118/106 +f 103/102/90 102/115/103 117/119/107 +f 97/103/91 96/116/104 111/120/108 +f 104/104/92 103/102/90 118/121/109 +f 98/105/93 97/103/91 112/122/110 +f 105/108/96 104/104/92 119/123/111 +f 99/109/97 98/105/93 113/124/112 +f 93/110/98 92/106/94 107/125/113 +f 106/126/114 105/108/96 120/127/115 +f 100/111/99 99/109/97 114/128/116 +f 94/112/100 93/110/98 108/129/117 +f 101/113/101 100/111/99 115/130/118 +f 95/114/102 94/112/100 109/131/119 +f 108/129/117 107/125/113 122/132/120 +f 121/133/121 120/127/115 135/134/122 +f 115/130/118 114/128/116 129/135/123 +f 109/131/119 108/129/117 123/136/124 +f 116/117/105 115/130/118 130/137/125 +f 110/118/106 109/131/119 124/138/126 +f 117/119/107 116/117/105 131/139/127 +f 111/120/108 110/118/106 125/140/128 +f 118/121/109 117/119/107 132/141/129 +f 112/122/110 111/120/108 126/142/130 +f 119/123/111 118/121/109 133/143/131 +f 113/124/112 112/122/110 127/144/132 +f 120/127/115 119/123/111 134/145/133 +f 114/128/116 113/124/112 128/146/134 +f 127/144/132 126/142/130 141/147/135 +f 134/145/133 133/143/131 148/148/136 +f 128/146/134 127/144/132 142/149/137 +f 135/134/122 134/145/133 149/150/138 +f 129/135/123 128/146/134 143/151/139 +f 123/136/124 122/132/120 137/152/140 +f 136/153/141 135/134/122 150/154/142 +f 130/137/125 129/135/123 144/155/143 +f 124/138/126 123/136/124 138/156/144 +f 131/139/127 130/137/125 145/157/145 +f 125/140/128 124/138/126 139/158/146 +f 132/141/129 131/139/127 146/159/147 +f 126/142/130 125/140/128 140/160/148 +f 133/143/131 132/141/129 147/161/149 +f 146/159/147 145/157/145 160/162/150 +f 140/160/148 139/158/146 154/163/151 +f 147/161/149 146/159/147 161/164/152 +f 141/147/135 140/160/148 155/165/153 +f 148/148/136 147/161/149 162/166/154 +f 142/149/137 141/147/135 157/167/155 +f 149/150/138 148/148/136 163/168/156 +f 143/151/139 142/149/137 157/167/155 +f 150/154/142 149/150/138 164/169/157 +f 144/155/143 143/151/139 158/170/158 +f 138/156/144 137/152/140 152/171/159 +f 151/172/160 150/154/142 165/173/161 +f 145/157/145 144/155/143 159/174/162 +f 139/158/146 138/156/144 153/175/163 +f 165/176/161 164/177/157 179/178/164 +f 159/174/162 158/170/158 173/179/165 +f 153/175/163 152/171/159 167/180/166 +f 166/181/167 165/176/161 180/182/168 +f 160/162/150 159/174/162 174/183/169 +f 154/163/151 153/175/163 168/184/170 +f 161/164/152 160/162/150 175/185/171 +f 155/165/153 154/163/151 169/186/172 +f 162/166/154 161/164/152 176/187/173 +f 156/188/174 155/165/153 170/189/175 +f 163/168/156 162/166/154 177/190/176 +f 157/167/155 156/188/174 171/191/177 +f 164/177/157 163/168/156 178/192/178 +f 158/170/158 157/167/155 172/193/179 +f 178/192/178 177/190/176 192/194/180 +f 172/193/179 171/191/177 186/195/181 +f 179/178/164 178/192/178 193/196/182 +f 173/179/165 172/193/179 187/197/183 +f 180/182/168 179/178/164 194/198/184 +f 174/183/169 173/179/165 188/199/185 +f 168/184/170 167/180/166 182/200/186 +f 181/201/187 180/182/168 195/202/188 +f 175/185/171 174/183/169 189/203/189 +f 169/186/172 168/184/170 183/204/190 +f 176/187/173 175/185/171 190/205/191 +f 170/189/175 169/186/172 184/206/192 +f 177/190/176 176/187/173 191/207/193 +f 171/191/177 170/189/175 185/208/194 +f 191/207/193 190/205/191 206/209/195 +f 185/208/194 184/206/192 200/210/196 +f 192/194/180 191/207/193 207/211/197 +f 186/195/181 185/208/194 201/212/198 +f 193/196/182 192/194/180 208/213/199 +f 187/197/183 186/195/181 202/214/200 +f 194/198/184 193/196/182 209/215/201 +f 188/199/185 187/197/183 203/216/202 +f 195/202/188 194/198/184 210/217/203 +f 189/203/189 188/199/185 204/218/204 +f 183/204/190 182/200/186 198/219/205 +f 196/220/206 195/202/188 211/221/207 +f 190/205/191 189/203/189 205/222/208 +f 184/206/192 183/204/190 199/223/209 +f 210/217/203 209/215/201 226/224/210 +f 204/218/204 203/216/202 220/225/211 +f 198/219/205 197/226/212 214/227/213 +f 211/221/207 210/217/203 227/228/214 +f 205/222/208 204/218/204 221/229/215 +f 199/223/209 198/219/205 215/230/216 +f 206/209/195 205/222/208 222/231/217 +f 200/210/196 199/223/209 216/232/218 +f 207/211/197 206/209/195 223/233/219 +f 201/212/198 200/210/196 217/234/220 +f 208/213/199 207/211/197 223/233/219 +f 202/214/200 201/212/198 218/235/221 +f 209/215/201 208/213/199 225/236/222 +f 203/216/202 202/214/200 219/237/223 +f 224/238/224 223/233/219 239/239/225 +f 218/235/221 217/234/220 233/240/226 +f 225/236/222 224/238/224 240/241/227 +f 219/237/223 218/235/221 234/242/228 +f 226/224/210 225/236/222 241/243/229 +f 220/225/211 219/237/223 235/244/230 +f 214/227/213 213/245/231 229/246/232 +f 227/228/214 226/224/210 242/247/233 +f 221/229/215 220/225/211 236/248/234 +f 215/230/216 214/227/213 230/249/235 +f 222/231/217 221/229/215 237/250/236 +f 216/232/218 215/230/216 231/251/237 +f 223/233/219 222/231/217 238/252/238 +f 217/234/220 216/232/218 232/253/239 +f 1/13/12 212/254/240 16/55/43 +f 31/255/241 15/15/14 30/16/15 +f 31/255/241 30/16/15 46/31/30 +f 16/55/43 212/254/240 32/61/49 +f 32/61/49 212/254/240 47/80/68 +f 31/255/241 46/31/30 61/63/51 +f 47/80/68 212/254/240 62/100/88 +f 31/255/241 61/63/51 76/82/70 +f 31/255/241 76/82/70 91/107/95 +f 62/100/88 212/254/240 77/101/89 +f 77/101/89 212/254/240 92/106/94 +f 31/255/241 91/107/95 106/126/114 +f 92/106/94 212/254/240 107/125/113 +f 31/255/241 106/126/114 121/133/121 +f 31/255/241 121/133/121 136/153/141 +f 107/125/113 212/254/240 122/132/120 +f 122/132/120 212/254/240 137/152/140 +f 31/255/241 136/153/141 151/172/160 +f 137/152/140 212/254/240 152/171/159 +f 31/255/241 151/172/160 166/256/167 +f 31/255/241 166/256/167 181/257/187 +f 152/171/159 212/254/240 167/180/166 +f 167/180/166 212/254/240 182/200/186 +f 31/255/241 181/257/187 196/258/206 +f 31/255/241 196/258/206 211/259/207 +f 182/200/186 212/254/240 197/226/212 +f 31/255/241 211/259/207 227/260/214 +f 197/226/212 212/254/240 213/245/231 +f 213/245/231 212/254/240 228/261/242 +f 31/255/241 227/260/214 242/262/233 +f 31/255/241 242/262/233 15/15/14 +f 237/250/236 236/248/234 10/21/20 +f 231/251/237 230/249/235 4/23/22 +f 238/252/238 237/250/236 10/21/20 +f 232/253/239 231/251/237 5/27/26 +f 239/239/225 238/252/238 11/25/24 +f 233/240/226 232/253/239 6/5/5 +f 240/241/227 239/239/225 13/1/1 +f 234/242/228 233/240/226 7/4/4 +f 228/261/242 212/254/240 1/13/12 +f 241/243/229 240/241/227 14/263/7 +f 235/244/230 234/242/228 8/10/9 +f 229/246/232 228/261/242 2/12/11 +f 242/247/233 241/243/229 15/264/14 +f 236/248/234 235/244/230 9/17/16 +f 230/249/235 229/246/232 3/19/18 +f 12/2/2 27/29/28 28/3/3 +f 6/5/5 21/30/29 22/6/6 +f 13/8/1 28/49/3 29/9/8 +f 7/4/4 22/6/6 23/11/10 +f 1/13/12 16/55/43 17/14/13 +f 14/7/7 29/9/8 30/16/15 +f 8/10/9 23/11/10 24/18/17 +f 2/12/11 17/14/13 18/20/19 +f 9/17/16 24/18/17 25/22/21 +f 3/19/18 18/20/19 19/24/23 +f 10/21/20 25/22/21 26/26/25 +f 4/23/22 19/24/23 20/28/27 +f 11/25/24 26/26/25 27/29/28 +f 5/27/26 20/28/27 21/30/29 +f 29/9/8 45/53/41 46/31/30 +f 23/33/10 39/54/42 40/34/31 +f 17/14/13 33/56/44 34/36/32 +f 24/32/17 40/34/31 41/38/33 +f 18/35/19 34/36/32 35/40/34 +f 25/37/21 41/38/33 42/42/35 +f 19/39/23 35/40/34 36/44/36 +f 26/41/25 42/42/35 43/46/37 +f 20/43/27 36/44/36 37/48/38 +f 27/45/28 43/46/37 44/50/39 +f 21/47/29 37/48/38 38/52/40 +f 28/49/3 44/50/39 45/53/41 +f 22/51/6 38/52/40 39/54/42 +f 16/55/43 32/61/49 33/56/44 +f 43/46/37 58/70/58 59/57/45 +f 37/48/38 52/71/59 53/58/46 +f 44/50/39 59/57/45 60/59/47 +f 38/52/40 53/58/46 54/60/48 +f 32/61/49 47/80/68 48/62/50 +f 45/53/41 60/59/47 61/63/51 +f 39/54/42 54/60/48 55/64/52 +f 33/56/44 48/62/50 49/65/53 +f 40/34/31 55/64/52 56/66/54 +f 34/36/32 49/65/53 50/67/55 +f 41/38/33 56/66/54 57/68/56 +f 35/40/34 50/67/55 51/69/57 +f 42/42/35 57/68/56 58/70/58 +f 36/44/36 51/69/57 52/71/59 +f 56/66/54 71/85/73 72/72/60 +f 50/67/55 65/86/74 66/73/61 +f 57/68/56 72/72/60 73/74/62 +f 51/69/57 66/73/61 67/75/63 +f 58/70/58 73/74/62 74/76/64 +f 52/71/59 67/75/63 68/77/65 +f 59/57/45 74/76/64 75/78/66 +f 53/58/46 68/77/65 69/79/67 +f 47/80/68 62/100/88 63/81/69 +f 60/59/47 75/78/66 76/82/70 +f 54/60/48 69/79/67 70/83/71 +f 48/62/50 63/81/69 64/84/72 +f 55/64/52 70/83/71 71/85/73 +f 49/65/53 64/84/72 65/86/74 +f 91/107/95 76/82/70 90/87/75 +f 85/90/78 70/83/71 84/88/76 +f 79/91/79 64/84/72 78/89/77 +f 86/92/80 71/85/73 85/90/78 +f 80/93/81 65/86/74 79/91/79 +f 87/94/82 72/72/60 86/92/80 +f 81/95/83 66/73/61 80/93/81 +f 88/96/84 73/74/62 87/94/82 +f 82/97/85 67/75/63 81/95/83 +f 89/98/86 74/76/64 88/96/84 +f 83/99/87 68/77/65 82/97/85 +f 90/87/75 75/78/66 89/98/86 +f 84/88/76 69/79/67 83/99/87 +f 78/89/77 63/81/69 77/101/89 +f 104/104/92 89/98/86 103/102/90 +f 98/105/93 83/99/87 97/103/91 +f 105/108/96 90/87/75 104/104/92 +f 99/109/97 84/88/76 98/105/93 +f 93/110/98 78/89/77 92/106/94 +f 106/126/114 91/107/95 105/108/96 +f 100/111/99 85/90/78 99/109/97 +f 94/112/100 79/91/79 93/110/98 +f 101/113/101 86/92/80 100/111/99 +f 95/114/102 80/93/81 94/112/100 +f 102/115/103 87/94/82 101/113/101 +f 96/116/104 81/95/83 95/114/102 +f 103/102/90 88/96/84 102/115/103 +f 97/103/91 82/97/85 96/116/104 +f 117/119/107 102/115/103 116/117/105 +f 111/120/108 96/116/104 110/118/106 +f 118/121/109 103/102/90 117/119/107 +f 112/122/110 97/103/91 111/120/108 +f 119/123/111 104/104/92 118/121/109 +f 113/124/112 98/105/93 112/122/110 +f 120/127/115 105/108/96 119/123/111 +f 114/128/116 99/109/97 113/124/112 +f 108/129/117 93/110/98 107/125/113 +f 121/133/121 106/126/114 120/127/115 +f 115/130/118 100/111/99 114/128/116 +f 109/131/119 94/112/100 108/129/117 +f 116/117/105 101/113/101 115/130/118 +f 110/118/106 95/114/102 109/131/119 +f 123/136/124 108/129/117 122/132/120 +f 136/153/141 121/133/121 135/134/122 +f 130/137/125 115/130/118 129/135/123 +f 124/138/126 109/131/119 123/136/124 +f 131/139/127 116/117/105 130/137/125 +f 125/140/128 110/118/106 124/138/126 +f 132/141/129 117/119/107 131/139/127 +f 126/142/130 111/120/108 125/140/128 +f 133/143/131 118/121/109 132/141/129 +f 127/144/132 112/122/110 126/142/130 +f 134/145/133 119/123/111 133/143/131 +f 128/146/134 113/124/112 127/144/132 +f 135/134/122 120/127/115 134/145/133 +f 129/135/123 114/128/116 128/146/134 +f 142/149/137 127/144/132 141/147/135 +f 149/150/138 134/145/133 148/148/136 +f 143/151/139 128/146/134 142/149/137 +f 150/154/142 135/134/122 149/150/138 +f 144/155/143 129/135/123 143/151/139 +f 138/156/144 123/136/124 137/152/140 +f 151/172/160 136/153/141 150/154/142 +f 145/157/145 130/137/125 144/155/143 +f 139/158/146 124/138/126 138/156/144 +f 146/159/147 131/139/127 145/157/145 +f 140/160/148 125/140/128 139/158/146 +f 147/161/149 132/141/129 146/159/147 +f 141/147/135 126/142/130 140/160/148 +f 148/148/136 133/143/131 147/161/149 +f 161/164/152 146/159/147 160/162/150 +f 155/165/153 140/160/148 154/163/151 +f 162/166/154 147/161/149 161/164/152 +f 156/188/174 141/147/135 155/165/153 +f 163/168/156 148/148/136 162/166/154 +f 141/147/135 156/188/174 157/167/155 +f 164/177/157 149/150/138 163/168/156 +f 158/170/158 143/151/139 157/167/155 +f 165/173/161 150/154/142 164/169/157 +f 159/174/162 144/155/143 158/170/158 +f 153/175/163 138/156/144 152/171/159 +f 166/256/167 151/172/160 165/173/161 +f 160/162/150 145/157/145 159/174/162 +f 154/163/151 139/158/146 153/175/163 +f 180/182/168 165/176/161 179/178/164 +f 174/183/169 159/174/162 173/179/165 +f 168/184/170 153/175/163 167/180/166 +f 181/201/187 166/181/167 180/182/168 +f 175/185/171 160/162/150 174/183/169 +f 169/186/172 154/163/151 168/184/170 +f 176/187/173 161/164/152 175/185/171 +f 170/189/175 155/165/153 169/186/172 +f 177/190/176 162/166/154 176/187/173 +f 171/191/177 156/188/174 170/189/175 +f 178/192/178 163/168/156 177/190/176 +f 172/193/179 157/167/155 171/191/177 +f 179/178/164 164/177/157 178/192/178 +f 173/179/165 158/170/158 172/193/179 +f 193/196/182 178/192/178 192/194/180 +f 187/197/183 172/193/179 186/195/181 +f 194/198/184 179/178/164 193/196/182 +f 188/199/185 173/179/165 187/197/183 +f 195/202/188 180/182/168 194/198/184 +f 189/203/189 174/183/169 188/199/185 +f 183/204/190 168/184/170 182/200/186 +f 196/220/206 181/201/187 195/202/188 +f 190/205/191 175/185/171 189/203/189 +f 184/206/192 169/186/172 183/204/190 +f 191/207/193 176/187/173 190/205/191 +f 185/208/194 170/189/175 184/206/192 +f 192/194/180 177/190/176 191/207/193 +f 186/195/181 171/191/177 185/208/194 +f 190/205/191 205/222/208 206/209/195 +f 184/206/192 199/223/209 200/210/196 +f 191/207/193 206/209/195 207/211/197 +f 185/208/194 200/210/196 201/212/198 +f 192/194/180 207/211/197 208/213/199 +f 186/195/181 201/212/198 202/214/200 +f 193/196/182 208/213/199 209/215/201 +f 187/197/183 202/214/200 203/216/202 +f 194/198/184 209/215/201 210/217/203 +f 188/199/185 203/216/202 204/218/204 +f 182/200/186 197/226/212 198/219/205 +f 195/202/188 210/217/203 211/221/207 +f 189/203/189 204/218/204 205/222/208 +f 183/204/190 198/219/205 199/223/209 +f 209/215/201 225/236/222 226/224/210 +f 203/216/202 219/237/223 220/225/211 +f 197/226/212 213/245/231 214/227/213 +f 210/217/203 226/224/210 227/228/214 +f 204/218/204 220/225/211 221/229/215 +f 198/219/205 214/227/213 215/230/216 +f 205/222/208 221/229/215 222/231/217 +f 199/223/209 215/230/216 216/232/218 +f 206/209/195 222/231/217 223/233/219 +f 200/210/196 216/232/218 217/234/220 +f 224/238/224 208/213/199 223/233/219 +f 201/212/198 217/234/220 218/235/221 +f 208/213/199 224/238/224 225/236/222 +f 202/214/200 218/235/221 219/237/223 +f 223/233/219 238/252/238 239/239/225 +f 217/234/220 232/253/239 233/240/226 +f 224/238/224 239/239/225 240/241/227 +f 218/235/221 233/240/226 234/242/228 +f 225/236/222 240/241/227 241/243/229 +f 219/237/223 234/242/228 235/244/230 +f 213/245/231 228/261/242 229/246/232 +f 226/224/210 241/243/229 242/247/233 +f 220/225/211 235/244/230 236/248/234 +f 214/227/213 229/246/232 230/249/235 +f 221/229/215 236/248/234 237/250/236 +f 215/230/216 230/249/235 231/251/237 +f 222/231/217 237/250/236 238/252/238 +f 216/232/218 231/251/237 232/253/239 +f 236/248/234 9/17/16 10/21/20 +f 230/249/235 3/19/18 4/23/22 +f 11/25/24 238/252/238 10/21/20 +f 231/251/237 4/23/22 5/27/26 +f 12/2/2 239/239/225 11/25/24 +f 232/253/239 5/27/26 6/5/5 +f 239/239/225 12/2/2 13/1/1 +f 233/240/226 6/5/5 7/4/4 +f 240/241/227 13/1/1 14/263/7 +f 234/242/228 7/4/4 8/10/9 +f 228/261/242 1/13/12 2/12/11 +f 241/243/229 14/263/7 15/264/14 +f 235/244/230 8/10/9 9/17/16 +f 229/246/232 2/12/11 3/19/18 diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp new file mode 100644 index 00000000..c991cd4b --- /dev/null +++ b/src/datavis3d/engine/q3dbars.cpp @@ -0,0 +1,2105 @@ +/**************************************************************************** +** +** 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 "q3dbars.h" +#include "q3dbars_p.h" +#include "camerahelper_p.h" +#include "qdataitem_p.h" +#include "qdatarow_p.h" +#include "qdataset_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" + +#include <QMatrix4x4> +#include <QOpenGLPaintDevice> +#include <QPainter> +#include <QScreen> +#include <QMouseEvent> + +#include <qmath.h> + +#include <QDebug> + +// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light +// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) +#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + +//#define DISPLAY_RENDER_SPEED + +#ifdef DISPLAY_RENDER_SPEED +#include <QTime> +#endif + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +//#define USE_HAX0R_SELECTION // keep this defined until the "real" method works +#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels + +const GLfloat gridLineWidth = 0.005f; + +Q3DBars::Q3DBars() + : d_ptr(new Q3DBarsPrivate(this)) +{ +} + +Q3DBars::~Q3DBars() +{ +} + +void Q3DBars::initialize() +{ + // Initialize shaders + if (d_ptr->m_shadowQuality > ShadowNone) { + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + // Init the depth buffer (for shadows) + d_ptr->initDepthBuffer(); + } else { + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + d_ptr->initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + + // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. + d_ptr->initDepthShader(); + + // Init selection shader + d_ptr->initSelectionShader(); + +#ifndef USE_HAX0R_SELECTION + // Init the selection buffer + d_ptr->initSelectionBuffer(); +#endif + + // Load default mesh + d_ptr->loadBarMesh(); + + // Load background mesh + d_ptr->loadBackgroundMesh(); + + // Load grid line mesh + d_ptr->loadGridLineMesh(); + + // Load label mesh + d_ptr->loadLabelMesh(); + + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + // Set initial camera position + // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later + CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // Set view port + glViewport(0, 0, width(), height()); + + // Set initialized -flag + d_ptr->m_isInitialized = true; +} + +void Q3DBars::render() +{ + if (!d_ptr->m_isInitialized) + return; + +#ifdef DISPLAY_RENDER_SPEED + // For speed computation + static bool firstRender = true; + static QTime lastTime; + static GLint nbFrames = 0; + if (firstRender) { + lastTime.start(); + firstRender = false; + } + + // Measure speed (as milliseconds per frame) + nbFrames++; + if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago + qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)"; + nbFrames = 0; + lastTime.restart(); + } +#endif + + // If zoom selection is on, draw zoom scene + drawZoomScene(); + // Draw bars scene + drawScene(); +} + +void Q3DBars::drawZoomScene() +{ + // Set clear color + QVector3D clearColor = Utils::vectorFromColor(d_ptr->m_theme->m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // If no zoom, return + if (!d_ptr->m_zoomActivated) + return; + + GLfloat barPosX = 0; + GLint startBar = 0; + GLint stopBar = d_ptr->m_zoomSelection->d_ptr->row().size(); + GLint stepBar = 1; + QVector3D lightPos; + + // Specify viewport + glViewport(d_ptr->m_zoomViewPort.x(), d_ptr->m_zoomViewPort.y(), + d_ptr->m_zoomViewPort.width(), d_ptr->m_zoomViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)d_ptr->m_zoomViewPort.width() + / (GLfloat)d_ptr->m_zoomViewPort.height(), 0.1f, 100.0f); + +#ifdef ROTATE_ZOOM_SELECTION + // Calculate view matrix + QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(d_ptr->m_mousePos, + d_ptr->m_zoomLevel + * d_ptr->m_zoomAdjustment, + d_ptr->m_zoomViewPort.width(), + d_ptr->m_zoomViewPort.height()); + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + lightPos = CameraHelper::calculateLightPosition(defaultLightPos); + + if (viewMatrix.row(0).z() <= 0) { + startBar = d_ptr->m_zoomSelection->d_ptr->row().size() - 1; + stopBar = -1; + stepBar = -1; + } +#else + // Set view matrix + QMatrix4x4 viewMatrix; + + viewMatrix.lookAt(QVector3D(0.0f, 0.0f, 5.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // Adjust scaling (zoom rate based on aspect ratio) + viewMatrix.scale(d_ptr->m_zoomAdjustment); + + // Set light position a bit above the camera (depends on do we have row or column zoom) + if (ModeZoomColumn == d_ptr->m_selectionMode) + lightPos = CameraHelper::calculateLightPosition(defaultLightPos, -85.0f); + else + lightPos = CameraHelper::calculateLightPosition(defaultLightPos, 5.0f); +#endif + + // Bind bar shader + d_ptr->m_barShader->bind(); + + // Draw bars + // Draw the selected row / column + for (int bar = startBar; bar != stopBar; bar += stepBar) { + QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + + if (barHeight < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + GLfloat barPosY = item->d_ptr->translation().y() - d_ptr->m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f + if (ModeZoomRow == d_ptr->m_selectionMode) + barPosX = item->d_ptr->translation().x(); + else + barPosX = -(item->d_ptr->translation().z() - zComp); // flip z; frontmost bar to the left + modelMatrix.translate(barPosX, barPosY, zComp); + modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ)); + itModelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor); + QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor) * barHeight; + + QVector3D barColor = baseColor + heightColor; + + GLfloat lightStrength = d_ptr->m_theme->m_lightStrength; + + if (barHeight != 0) { + // Set shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), lightStrength); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(), + d_ptr->m_theme->m_ambientStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj); + } + } + + // Release bar shader + d_ptr->m_barShader->release(); + + // Draw labels + d_ptr->m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glCullFace(GL_BACK); + if (d_ptr->m_labelTransparency > TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Draw labels for axes + QDataItem *dummyItem = NULL; + LabelItem x; + LabelItem z; + LabelItem y; + d_ptr->m_dataSet->d_ptr->axisLabelItems(&x, &z, &y); + LabelItem zoomSelectionLabel = d_ptr->m_zoomSelection->d_ptr->labelItem(); + if (ModeZoomRow == d_ptr->m_selectionMode) { + d_ptr->m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, false, false, LabelTop); + d_ptr->m_drawer->drawLabel(*dummyItem, z, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, false, false, LabelBottom); + } else { + d_ptr->m_drawer->drawLabel(*dummyItem, x, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, false, false, LabelBottom); + d_ptr->m_drawer->drawLabel(*dummyItem, zoomSelectionLabel, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, false, false, LabelTop); + } + d_ptr->m_drawer->drawLabel(*dummyItem, y, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 90.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, false, false, LabelLeft); + + // Draw labels for bars + for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) { + QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col); + // Draw values + d_ptr->m_drawer->drawLabel(*item, item->d_ptr->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj); + // Draw labels + LabelItem labelItem; + if (ModeZoomRow == d_ptr->m_selectionMode) { + if (d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > col) { + // If draw order of bars is flipped, label draw order should be too + if (d_ptr->m_xFlipped) { + labelItem = d_ptr->m_dataSet->d_ptr->columnLabelItems().at( + d_ptr->m_dataSet->d_ptr->columnLabelItems().size() - col - 1); + } else { + labelItem = d_ptr->m_dataSet->d_ptr->columnLabelItems().at(col); + } + } + } else { + if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > col) { + // If draw order of bars is flipped, label draw order should be too + if (d_ptr->m_zFlipped) { + labelItem = d_ptr->m_dataSet->d_ptr->rowLabelItems().at( + d_ptr->m_dataSet->d_ptr->rowLabelItems().size() - col - 1); + } else { + labelItem = d_ptr->m_dataSet->d_ptr->rowLabelItems().at(col); + } + } + } + d_ptr->m_drawer->drawLabel(*item, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, -45.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, false, false, LabelBelow); + } + + glDisable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + d_ptr->m_labelShader->release(); +} + +void Q3DBars::drawScene() +{ + GLint startBar = 0; + GLint stopBar = 0; + GLint stepBar = 0; + + GLint startRow = 0; + GLint stopRow = 0; + GLint stepRow = 0; + + GLfloat backgroundRotation = 0; + + GLfloat barPos = 0; + GLfloat rowPos = 0; + + static QVector3D selection = QVector3D(0, 0, 0); + + // Specify viewport + glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), + d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)d_ptr->m_sceneViewPort.width() + / (GLfloat)d_ptr->m_sceneViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(d_ptr->m_mousePos, + d_ptr->m_zoomLevel + * d_ptr->m_zoomAdjustment, + d_ptr->m_sceneViewPort.width(), + d_ptr->m_sceneViewPort.height()); + + // Calculate drawing order + // Draw order is reversed to optimize amount of drawing (ie. draw front objects first, depth test handles not needing to draw objects behind them) + if (viewMatrix.row(0).x() >= 0) { + startRow = 0; + stopRow = d_ptr->m_sampleCount.second; + stepRow = 1; + d_ptr->m_zFlipped = false; + } else { + startRow = d_ptr->m_sampleCount.second - 1; + stopRow = -1; + stepRow = -1; + d_ptr->m_zFlipped = true; + } + if (viewMatrix.row(0).z() <= 0) { + startBar = 0; + stopBar = d_ptr->m_sampleCount.first; + stepBar = 1; + d_ptr->m_xFlipped = false; + } else { + startBar = d_ptr->m_sampleCount.first - 1; + stopBar = -1; + stepBar = -1; + d_ptr->m_xFlipped = true; + } + + // calculate background rotation based on view matrix rotation + if (viewMatrix.row(0).x() >= 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 270.0f; + else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 180.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() >= 0) + backgroundRotation = 90.0f; + else if (viewMatrix.row(0).x() < 0 && viewMatrix.row(0).z() < 0) + backgroundRotation = 0.0f; + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos); + //lightPos = QVector3D(0.0f, 4.0f, zComp); // center of bars, 4.0f above - for testing + + // Skip depth rendering if we're in zoom mode + // TODO: Fix this, causes problems if depth rendering is off in zoom mode + // Introduce regardless of shadow quality to simplify logic + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + + if (d_ptr->m_shadowQuality > ShadowNone/*!d_ptr->m_zoomActivated*/) { + // Render scene into a depth texture for using with shadow mapping + // Bind depth shader + d_ptr->m_depthShader->bind(); + + // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. + glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), + d_ptr->m_sceneViewPort.width() * d_ptr->m_shadowQuality, + d_ptr->m_sceneViewPort.height() * d_ptr->m_shadowQuality); + + // Enable drawing to framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_depthFrameBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + // Set front face culling to reduce self-shadowing issues + glCullFace(GL_FRONT); + + // Get the depth view matrix + // It may be possible to hack lightPos here if we want to make some tweaks to shadow + depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, 1.0f - d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed + //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix +#ifdef USE_WIDER_SHADOWS + // Use this for a bit exaggerated shadows + depthProjectionMatrix.perspective(20.0f, (GLfloat)d_ptr->m_sceneViewPort.width() + / (GLfloat)d_ptr->m_sceneViewPort.height(), 3.0f, 100.0f); +#else + // Use these for normal shadows, with the light further away + depthProjectionMatrix = projectionMatrix; +#endif + // Draw bars to depth buffer + for (int row = startRow; row != stopRow; row += stepRow) { + for (int bar = startBar; bar != stopBar; bar += stepBar) { + if (!d_ptr->m_dataSet->d_ptr->getRow(row)) + continue; + QDataItem *item = d_ptr->m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + // skip shadows for barHeight < 0 (for now) + // skip shadows for 0 -height bars + if (barHeight <= 0) + continue; + + //if (barHeight < 0) + // glCullFace(GL_FRONT); + //else + // glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + barPos = (bar + 1) * (d_ptr->m_barSpacing.width()); + rowPos = (row + 1) * (d_ptr->m_barSpacing.height()); + + modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + barHeight - d_ptr->m_yAdjustment, + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + + zComp); + modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ)); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); + glVertexAttribPointer(d_ptr->m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt()); + } + } + + // Disable drawing to framebuffer (= enable drawing to screen) + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Release depth shader + d_ptr->m_depthShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) + d_ptr->m_labelShader->bind(); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix); + d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, + d_ptr->m_depthTexture); + glDisable(GL_TEXTURE_2D); + d_ptr->m_labelShader->release(); +#endif + // Reset culling to normal + glCullFace(GL_BACK); + + // Revert to original viewport + glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), + d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height()); + } + + // Skip selection mode drawing if we're zoomed or have no selection mode + if (!d_ptr->m_zoomActivated && d_ptr->m_selectionMode > ModeNone) { + // Bind selection shader + d_ptr->m_selectionShader->bind(); + + // Draw bars to selection buffer +#ifndef USE_HAX0R_SELECTION + glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer +#endif + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + for (int row = startRow; row != stopRow; row += stepRow) { + for (int bar = startBar; bar != stopBar; bar += stepBar) { + if (!d_ptr->m_dataSet->d_ptr->getRow(row)) + continue; + QDataItem *item = d_ptr->m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + + if (barHeight < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + barPos = (bar + 1) * (d_ptr->m_barSpacing.width()); + rowPos = (row + 1) * (d_ptr->m_barSpacing.height()); + + modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + barHeight - d_ptr->m_yAdjustment, + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + + zComp); + modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + // TODO: Save position to qdataitem, so that we don't need to calculate it each time? + + // add +2 to avoid black + QVector3D barColor = QVector3D((GLdouble)(row + 2) + / (GLdouble)(d_ptr->m_sampleCount.second + 2), + (GLdouble)(bar + 2) + / (GLdouble)(d_ptr->m_sampleCount.first + 2), + 0.0); + + d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->MVP(), + MVPMatrix); + d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->color(), + barColor); + +#ifdef USE_HAX0R_SELECTION + // 1st attribute buffer : vertices + glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); + glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), + 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), + GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); +#else + // 1st attribute buffer : vertices + glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); + glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), + 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); +#endif + } + } + glEnable(GL_DITHER); + + // Read color under cursor + if (Q3DBarsPrivate::MouseOnScene == d_ptr->m_mousePressed) + selection = Utils::getSelection(d_ptr->m_mousePos, height()); + +#ifndef USE_HAX0R_SELECTION + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + + // Release selection shader + d_ptr->m_selectionShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + glCullFace(GL_BACK); + d_ptr->m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix); + d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, true, + d_ptr->m_selectionTexture); + glDisable(GL_TEXTURE_2D); + d_ptr->m_labelShader->release(); +#endif + +#ifdef USE_HAX0R_SELECTION + // Set clear color + QVector3D clearColor = Utils::vectorFromColor(d_ptr->m_theme->m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + // Clear after selection + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#endif + } + + // Bind bar shader + d_ptr->m_barShader->bind(); + + // Enable texturing + glEnable(GL_TEXTURE_2D); + + // Draw bars + if (!d_ptr->m_zoomActivated && d_ptr->m_zoomSelection) + d_ptr->m_zoomSelection->d_ptr->clear(); + bool barSelectionFound = false; + for (int row = startRow; row != stopRow; row += stepRow) { + for (int bar = startBar; bar != stopBar; bar += stepBar) { + if (!d_ptr->m_dataSet->d_ptr->getRow(row)) + continue; + QDataItem *item = d_ptr->m_dataSet->d_ptr->getRow(row)->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + + if (barHeight < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); + + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + + barPos = (bar + 1) * (d_ptr->m_barSpacing.width()); + rowPos = (row + 1) * (d_ptr->m_barSpacing.height()); + modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + barHeight - d_ptr->m_yAdjustment, + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ)); + itModelMatrix.scale(QVector3D(d_ptr->m_scaleX, barHeight, d_ptr->m_scaleZ)); +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor); + QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor) + * barHeight; + QVector3D depthColor = Utils::vectorFromColor(d_ptr->m_theme->m_depthColor) + * (float(row) / GLfloat(d_ptr->m_sampleCount.second)); + + QVector3D barColor = baseColor + heightColor + depthColor; + + GLfloat lightStrength = d_ptr->m_theme->m_lightStrength; + if (d_ptr->m_selectionMode > ModeNone) { + Q3DBarsPrivate::SelectionType selectionType = d_ptr->isSelected(row, bar, + selection); + switch (selectionType) { + case Q3DBarsPrivate::SelectionBar: { + barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightBarColor); + lightStrength = d_ptr->m_theme->m_highlightLightStrength; + //if (d_ptr->m_mousePressed) { + // qDebug() << "selected object:" << barIndex << "( row:" << row + 1 << ", column:" << bar + 1 << ")"; + // qDebug() << "object position:" << modelMatrix.column(3).toVector3D(); + //} + // Insert data to QDataItem. We have no ownership, don't delete the previous one + if (!d_ptr->m_zoomActivated) { + d_ptr->m_selectedBar = item; + if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > row + && d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > bar) { + d_ptr->m_selectedBar->setPosition( + QPoint(d_ptr->m_dataSet->d_ptr->rowLabelItems().size() + - row - 1, + d_ptr->m_dataSet->d_ptr->columnLabelItems().size() + - bar - 1)); + } + item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); + barSelectionFound = true; + if (d_ptr->m_selectionMode >= ModeZoomRow) { + item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); + d_ptr->m_zoomSelection->addItem(item); + } + } + break; + } + case Q3DBarsPrivate::SelectionRow: { + // Current bar is on the same row as the selected bar + barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightRowColor); + lightStrength = d_ptr->m_theme->m_highlightLightStrength; + if (!d_ptr->m_zoomActivated && ModeZoomRow == d_ptr->m_selectionMode) { + item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); + d_ptr->m_zoomSelection->addItem(item); + if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > row) { + d_ptr->m_zoomSelection->d_ptr->setLabelItem( + d_ptr->m_dataSet->d_ptr->rowLabelItems().at( + d_ptr->m_dataSet->d_ptr->rowLabelItems().size() + - row - 1)); + } + } + break; + } + case Q3DBarsPrivate::SelectionColumn: { + // Current bar is on the same column as the selected bar + barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightColumnColor); + lightStrength = d_ptr->m_theme->m_highlightLightStrength; + if (!d_ptr->m_zoomActivated && ModeZoomColumn == d_ptr->m_selectionMode) { + item->d_ptr->setTranslation(modelMatrix.column(3).toVector3D()); + d_ptr->m_zoomSelection->addItem(item); + if (d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > bar) { + d_ptr->m_zoomSelection->d_ptr->setLabelItem( + d_ptr->m_dataSet->d_ptr->columnLabelItems().at( + d_ptr->m_dataSet->d_ptr->columnLabelItems().size() + - bar - 1)); + } + } + break; + } + case Q3DBarsPrivate::SelectionNone: { + // Current bar is not selected, nor on a row or column + // do nothing + break; + } + } + } + + if (barHeight != 0) { + // Set shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.transposed().inverted()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(), + d_ptr->m_theme->m_ambientStrength); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), + depthMVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj); + } + } + } + } + + // Release bar shader + d_ptr->m_barShader->release(); + + // Bind background shader + d_ptr->m_backgroundShader->bind(); + + glCullFace(GL_BACK); + + // Draw background + if (d_ptr->m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, 1.0f - d_ptr->m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, + 1.0f, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor)); + modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + itModelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, + 1.0f, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + + QVector3D backgroundColor = Utils::vectorFromColor(d_ptr->m_theme->m_backgroundColor); + + // Set shader bindings + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightP(), + lightPos); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->view(), + viewMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->model(), + modelMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(), + MVPMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->color(), + backgroundColor); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->ambientS(), + d_ptr->m_theme->m_ambientStrength); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->depth(), + depthMVPMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(), + d_ptr->m_theme->m_lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(), + d_ptr->m_theme->m_lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj); + } + } + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // Release background shader + d_ptr->m_backgroundShader->release(); + + // Draw grid lines + if (d_ptr->m_gridEnabled) { + // Bind bar shader + d_ptr->m_barShader->bind(); + + // Set unchanging shader bindings + QVector3D barColor = Utils::vectorFromColor(d_ptr->m_theme->m_gridLine); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(), + d_ptr->m_theme->m_ambientStrength); + + // Floor lines: rows + for (GLfloat row = 0.0f; row <= d_ptr->m_sampleCount.second; row++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + rowPos = (row + 0.5f) * (d_ptr->m_barSpacing.height()); + modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth, + gridLineWidth)); + itModelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth, + gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), + depthMVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj); + } + } + + // Floor lines: columns + for (GLfloat bar = 0.0f; bar <= d_ptr->m_sampleCount.first; bar++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + barPos = (bar + 0.5f) * (d_ptr->m_barSpacing.width()); + modelMatrix.translate((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + -d_ptr->m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), + depthMVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj); + } + } + + // Wall lines: back wall + GLfloat heightStep = d_ptr->m_heightNormalizer / 5.0f; // default to 5 lines + + if (d_ptr->m_tickCount > 0) + heightStep = d_ptr->m_tickStep; + + for (GLfloat lineHeight = heightStep; lineHeight <= d_ptr->m_heightNormalizer; + lineHeight += heightStep) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (d_ptr->m_zFlipped) { + modelMatrix.translate(0.0f, + 2.0f * lineHeight / d_ptr->m_heightNormalizer + - d_ptr->m_yAdjustment, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor + zComp); + } else { + modelMatrix.translate(0.0f, + 2.0f * lineHeight / d_ptr->m_heightNormalizer + - d_ptr->m_yAdjustment, + -d_ptr->m_columnDepth / d_ptr->m_scaleFactor + zComp); + } + modelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth, + gridLineWidth)); + itModelMatrix.scale(QVector3D(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, gridLineWidth, + gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), + depthMVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj); + } + } + + // Wall lines: side wall + for (GLfloat lineHeight = heightStep; lineHeight <= d_ptr->m_heightNormalizer; + lineHeight += heightStep) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (d_ptr->m_xFlipped) { + modelMatrix.translate(d_ptr->m_rowWidth / d_ptr->m_scaleFactor, + 2.0f * lineHeight / d_ptr->m_heightNormalizer + - d_ptr->m_yAdjustment, + zComp); + } else { + modelMatrix.translate(-d_ptr->m_rowWidth / d_ptr->m_scaleFactor, + 2.0f * lineHeight / d_ptr->m_heightNormalizer + - d_ptr->m_yAdjustment, + zComp); + } + modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor)); + itModelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, + d_ptr->m_columnDepth / d_ptr->m_scaleFactor)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), + depthMVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + d_ptr->m_theme->m_lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_gridLineObj); + } + } + + // Release bar shader + d_ptr->m_barShader->release(); + } + + // TODO: Draw y labels + + // Generate label textures for zoom selection if m_updateLabels is set + if (d_ptr->m_zoomActivated && d_ptr->m_updateLabels) { + // Create label textures + for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) { + QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col); + d_ptr->m_drawer->generateLabelTexture(item); + } + } + + // Handle zoom activation and label drawing + if (!barSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + d_ptr->m_selectedBar = NULL; + if (d_ptr->m_zoomActivated && Q3DBarsPrivate::MouseOnOverview == d_ptr->m_mousePressed) { + d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + d_ptr->m_zoomActivated = false; + } + } else if (d_ptr->m_selectionMode >= ModeZoomRow + && Q3DBarsPrivate::MouseOnScene == d_ptr->m_mousePressed) { + // Activate zoom mode + d_ptr->m_zoomActivated = true; + d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); + + // Create label textures + for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) { + QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col); + d_ptr->m_drawer->generateLabelTexture(item); + } + } else { + // Print value of selected bar + static QDataItem *prevItem = d_ptr->m_selectedBar; + d_ptr->m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +#ifndef DISPLAY_FULL_DATA_ON_SELECTION + // Draw just the value string of the selected bar + if (prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) { + d_ptr->m_drawer->generateLabelTexture(d_ptr->m_selectedBar); + prevItem = d_ptr->m_selectedBar; + } + + d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, d_ptr->m_selectedBar->d_ptr->label(), + viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true); +#else + static bool firstSelection = true; + // Draw the value string followed by row label and column label + LabelItem labelItem = d_ptr->m_selectedBar->d_ptr->selectionLabel(); + if (firstSelection || prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) { + QString labelText = d_ptr->m_selectedBar->d_ptr->valueStr(); + if ((d_ptr->m_dataSet->d_ptr->columnLabels().size() + > d_ptr->m_selectedBar->d_ptr->position().y()) + && (d_ptr->m_dataSet->d_ptr->rowLabels().size() + > d_ptr->m_selectedBar->d_ptr->position().x())) { + labelText.append(QStringLiteral(" (")); + labelText.append(d_ptr->m_dataSet->d_ptr->rowLabels().at( + d_ptr->m_selectedBar->d_ptr->position().x())); + labelText.append(QStringLiteral(", ")); + labelText.append(d_ptr->m_dataSet->d_ptr->columnLabels().at( + d_ptr->m_selectedBar->d_ptr->position().y())); + labelText.append(QStringLiteral(")")); + //qDebug() << labelText; + } + d_ptr->m_drawer->generateLabelItem(&labelItem, labelText); + d_ptr->m_selectedBar->d_ptr->setSelectionLabel(labelItem); + prevItem = d_ptr->m_selectedBar; + firstSelection = false; + } + + d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true, false); +#endif + glDisable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + d_ptr->m_labelShader->release(); + + // Reset label update flag; they should have been updated when we get here + d_ptr->m_updateLabels = false; + } + + // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. + // Bind label shader + d_ptr->m_labelShader->bind(); + + glEnable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) + for (int row = 0; row != d_ptr->m_sampleCount.second; row += 1) { + // Go through all rows and get position of max+1 or min-1 column, depending on x flip + // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems + rowPos = (row + 1) * (d_ptr->m_barSpacing.height()); + barPos = 0; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignRight; + if (d_ptr->m_zFlipped) + rotLabelY = 180.0f; + if (d_ptr->m_xFlipped) { + barPos = (d_ptr->m_sampleCount.first + 1) * (d_ptr->m_barSpacing.width()); + alignment = Qt::AlignLeft; + } + QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + + zComp); + + // TODO: Try it; draw the label here + + // Create a data item + QDataItem *label = new QDataItem(); + label->d_ptr->setTranslation(labelPos); + if (d_ptr->m_dataSet->d_ptr->rowLabelItems().size() > row) { + label->d_ptr->setLabel(d_ptr->m_dataSet->d_ptr->rowLabelItems().at( + d_ptr->m_dataSet->d_ptr->rowLabelItems().size() - row - 1)); + } + + //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->rowLabels().at(row); + + d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true, true, LabelMid, alignment); + + delete label; + } + for (int bar = 0; bar != d_ptr->m_sampleCount.first; bar += 1) { + // Go through all columns and get position of max+1 or min-1 row, depending on z flip + // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems + barPos = (bar + 1) * (d_ptr->m_barSpacing.width()); + rowPos = 0; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 90.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (d_ptr->m_xFlipped) + rotLabelY = -90.0f; + if (d_ptr->m_zFlipped) { + rowPos = (d_ptr->m_sampleCount.second + 1) * (d_ptr->m_barSpacing.height()); + alignment = Qt::AlignRight; + } + QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + + zComp); + + // TODO: Try it; draw the label here + + // Create a data item + QDataItem *label = new QDataItem(); + label->d_ptr->setTranslation(labelPos); + if (d_ptr->m_dataSet->d_ptr->columnLabelItems().size() > bar) { + label->d_ptr->setLabel(d_ptr->m_dataSet->d_ptr->columnLabelItems().at( + d_ptr->m_dataSet->d_ptr->columnLabelItems().size() + - bar - 1)); + } + + //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->columnLabels().at(bar); + + d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true, true, LabelMid, alignment); + + delete label; + } + glDisable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) + glDisable(GL_BLEND); + + // Release label shader + d_ptr->m_labelShader->release(); +} + +void Q3DBars::mousePressEvent(QMouseEvent *event) +{ + if (Qt::LeftButton == event->button()) { + if (d_ptr->m_zoomActivated) { + if (event->pos().x() <= d_ptr->m_sceneViewPort.width() + && event->pos().y() <= d_ptr->m_sceneViewPort.height()) { + d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnOverview; + //qDebug() << "Mouse pressed on overview"; + } else { + d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnZoom; + //qDebug() << "Mouse pressed on zoom"; + } + } else { + d_ptr->m_mousePressed = Q3DBarsPrivate::MouseOnScene; + // update mouse positions to prevent jumping when releasing or repressing a button + d_ptr->m_mousePos = event->pos(); + //qDebug() << "Mouse pressed on scene"; + } + } else if (Qt::MiddleButton == event->button()) { + // reset rotations + d_ptr->m_mousePos = QPoint(0, 0); + } else if (Qt::RightButton == event->button()) { + d_ptr->m_mousePressed = Q3DBarsPrivate::MouseRotating; + // update mouse positions to prevent jumping when releasing or repressing a button + d_ptr->m_mousePos = event->pos(); + } + CameraHelper::updateMousePos(d_ptr->m_mousePos); +} + +void Q3DBars::mouseReleaseEvent(QMouseEvent *event) +{ + if (Q3DBarsPrivate::MouseRotating == d_ptr->m_mousePressed) { + // update mouse positions to prevent jumping when releasing or repressing a button + d_ptr->m_mousePos = event->pos(); + CameraHelper::updateMousePos(event->pos()); + } + d_ptr->m_mousePressed = Q3DBarsPrivate::MouseNone; +} + +void Q3DBars::mouseMoveEvent(QMouseEvent *event) +{ + if (Q3DBarsPrivate::MouseRotating == d_ptr->m_mousePressed) + d_ptr->m_mousePos = event->pos(); +} + +void Q3DBars::wheelEvent(QWheelEvent *event) +{ + if (d_ptr->m_zoomLevel > 100) + d_ptr->m_zoomLevel += event->angleDelta().y() / 12; + else if (d_ptr->m_zoomLevel > 50) + d_ptr->m_zoomLevel += event->angleDelta().y() / 60; + else + d_ptr->m_zoomLevel += event->angleDelta().y() / 120; + if (d_ptr->m_zoomLevel > 500) + d_ptr->m_zoomLevel = 500; + else if (d_ptr->m_zoomLevel < 10) + d_ptr->m_zoomLevel = 10; +} + +void Q3DBars::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + // Set view port + if (d_ptr->m_zoomActivated) + d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); + else + d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + d_ptr->m_zoomViewPort = QRect(0, 0, width(), height()); + + // Calculate zoom level based on aspect ratio + GLfloat div; + GLfloat zoomAdjustment; + div = qMin(width(), height()); + zoomAdjustment = defaultRatio * ((width() / div) / (height() / div)); + //qDebug() << "zoom adjustment" << zoomAdjustment; + d_ptr->m_zoomAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f + + // Re-init selection buffer + d_ptr->initSelectionBuffer(); + + // Re-init depth buffer + d_ptr->initDepthBuffer(); +} + +void Q3DBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) +{ + d_ptr->m_barThickness = thickness; + if (relative) { + d_ptr->m_barSpacing.setWidth((thickness.width() * 2) * (spacing.width() + 1.0f)); + d_ptr->m_barSpacing.setHeight((thickness.height() * 2) * (spacing.height() + 1.0f)); + } else { + d_ptr->m_barSpacing = thickness * 2 + spacing * 2; + } + // Calculate here and at setting sample space + d_ptr->calculateSceneScalingFactors(); +} + +void Q3DBars::setBarType(BarStyle style, bool smooth) +{ + if (style == Bars) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/barSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bar"); + } else if (style == Pyramids) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramid"); + } else if (style == Cones) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cone"); + } else if (style == Cylinders) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinder"); + } + // Reload mesh data + if (d_ptr->m_isInitialized) + d_ptr->loadBarMesh(); +} + +void Q3DBars::setMeshFileName(const QString &objFileName) +{ + d_ptr->m_objFile = objFileName; +} + +void Q3DBars::setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow, + const QString &labelColumn, const QString &labelHeight) +{ + // Delete previous data set + delete d_ptr->m_dataSet; + d_ptr->m_dataSet = new QDataSet(); + d_ptr->m_sampleCount = qMakePair(samplesRow, samplesColumn); + d_ptr->m_dataSet->setLabels(labelRow, labelColumn, labelHeight); + // TODO: Invent "idiotproof" max scene size formula.. + // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) + d_ptr->m_maxSceneSize = 2 * qSqrt(samplesRow * samplesColumn); + //qDebug() << "maxSceneSize" << d_ptr->m_maxSceneSize; + // Calculate here and at setting bar specs + d_ptr->calculateSceneScalingFactors(); + d_ptr->m_axisLabelX = labelRow; + d_ptr->m_axisLabelZ = labelColumn; + d_ptr->m_axisLabelY = labelHeight; +} + +void Q3DBars::setCameraPreset(CameraPreset preset) +{ + CameraHelper::setCameraPreset(preset); +} + +void Q3DBars::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +{ + d_ptr->m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); + d_ptr->m_verticalRotation = qBound(0.0f, vertical, 90.0f); + d_ptr->m_zoomLevel = qBound(10, distance, 500); + CameraHelper::setCameraRotation(QPointF(d_ptr->m_horizontalRotation, + d_ptr->m_verticalRotation)); + //qDebug() << "camera rotation set to" << d_ptr->m_horizontalRotation << d_ptr->m_verticalRotation; +} + +void Q3DBars::setTheme(ColorTheme theme) +{ + d_ptr->m_theme->useTheme(theme); + d_ptr->m_drawer->setTheme(*d_ptr->m_theme); + // Re-initialize shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } +} + +void Q3DBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform) +{ + d_ptr->m_theme->m_baseColor = baseColor; + d_ptr->m_theme->m_heightColor = heightColor; + d_ptr->m_theme->m_depthColor = depthColor; + //qDebug() << "colors:" << d_ptr->m_baseColor << d_ptr->m_heightColor << d_ptr->m_depthColor; + if (d_ptr->m_theme->m_uniformColor != uniform) { + // Re-initialize shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + } + d_ptr->m_theme->m_uniformColor = uniform; +} + +void Q3DBars::setSelectionMode(SelectionMode mode) +{ + d_ptr->m_selectionMode = mode; + // Disable zoom if mode changes + d_ptr->m_zoomActivated = false; + d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + // Create zoom selection if there isn't one + if (mode >= ModeZoomRow && !d_ptr->m_zoomSelection) + d_ptr->m_zoomSelection = new QDataRow(); +} + +void Q3DBars::setWindowTitle(const QString &title) +{ + setTitle(title); +} + +void Q3DBars::setFontSize(float fontsize) +{ + d_ptr->m_font.setPointSizeF(fontsize); + d_ptr->m_drawer->setFont(d_ptr->m_font); +} + +void Q3DBars::setFont(const QFont &font) +{ + d_ptr->m_font = font; + d_ptr->m_drawer->setFont(font); +} + +void Q3DBars::setLabelTransparency(LabelTransparency transparency) +{ + d_ptr->m_labelTransparency = transparency; + d_ptr->m_drawer->setTransparency(transparency); +} + +void Q3DBars::setGridEnabled(bool enable) +{ + d_ptr->m_gridEnabled = enable; +} + +void Q3DBars::setTickCount(GLint tickCount, GLfloat step, GLfloat minimum) +{ + d_ptr->m_tickCount = tickCount; + d_ptr->m_tickStep = step; + if (tickCount > 0 && step > 0) { + d_ptr->m_heightNormalizer = tickCount * step; + d_ptr->calculateHeightAdjustment(QPair<float, float>(minimum, d_ptr->m_heightNormalizer)); + } +} + +void Q3DBars::setShadowQuality(ShadowQuality quality) +{ + d_ptr->m_shadowQuality = quality; + switch (quality) { + case ShadowLow: + d_ptr->m_shadowQualityToShader = 33.3f; + break; + case ShadowMedium: + d_ptr->m_shadowQualityToShader = 100.0f; + break; + case ShadowHigh: + d_ptr->m_shadowQualityToShader = 200.0f; + break; + default: + d_ptr->m_shadowQualityToShader = 0.0f; + break; + } + if (d_ptr->m_shadowQuality > ShadowNone) { + // Re-init depth buffer + d_ptr->initDepthBuffer(); + // Re-init shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } else { + // Re-init shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } +} + +void Q3DBars::addDataRow(const QVector<float> &dataRow, const QString &labelRow, + const QVector<QString> &labelsColumn) +{ + // Convert to QDataRow and add to QDataSet + QDataRow *row = new QDataRow(labelRow); + for (int i = 0; i < dataRow.size(); i++) + row->addItem(new QDataItem(dataRow.at(i))); + row->d_ptr->verifySize(d_ptr->m_sampleCount.first); + d_ptr->m_dataSet->addRow(row); + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_dataSet->d_ptr->limitValues(); + // Don't auto-adjust height if tick count is set + if (d_ptr->m_tickCount == 0) { + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + } + d_ptr->m_dataSet->setLabels(d_ptr->m_axisLabelX, d_ptr->m_axisLabelZ, d_ptr->m_axisLabelY, + QVector<QString>(), labelsColumn); + d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second); +} + +void Q3DBars::addDataRow(const QVector<QDataItem*> &dataRow, const QString &labelRow, + const QVector<QString> &labelsColumn) +{ + // Convert to QDataRow and add to QDataSet + QDataRow *row = new QDataRow(labelRow); + for (int i = 0; i < dataRow.size(); i++) + row->addItem(dataRow.at(i)); + row->d_ptr->verifySize(d_ptr->m_sampleCount.first); + d_ptr->m_dataSet->addRow(row); + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_dataSet->d_ptr->limitValues(); + // Don't auto-adjust height if tick count is set + if (d_ptr->m_tickCount == 0) { + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + } + d_ptr->m_dataSet->setLabels(d_ptr->m_axisLabelX, d_ptr->m_axisLabelZ, d_ptr->m_axisLabelY, + QVector<QString>(), labelsColumn); + d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second); +} + +void Q3DBars::addDataRow(QDataRow *dataRow) +{ + QDataRow *row = dataRow; + // Check that the input data fits into sample space, and resize if it doesn't + row->d_ptr->verifySize(d_ptr->m_sampleCount.first); + // With each new row, the previous data row must be moved back + // ie. we need as many vectors as we have rows in the sample space + d_ptr->m_dataSet->addRow(row); + // if the added data pushed us over sample space, remove the oldest data set + d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second); + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_dataSet->d_ptr->limitValues(); + // Don't auto-adjust height if tick count is set + if (d_ptr->m_tickCount == 0) { + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + } +} + +void Q3DBars::addDataSet(const QVector< QVector<float> > &data, const QVector<QString> &labelsRow, + const QVector<QString> &labelsColumn) +{ + // Copy axis labels + QString xAxis; + QString zAxis; + QString yAxis; + d_ptr->m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis); + // Delete old data set + delete d_ptr->m_dataSet; + d_ptr->m_dataSet = new QDataSet(); + // Give drawer to data set + d_ptr->m_dataSet->d_ptr->setDrawer(d_ptr->m_drawer); + // Convert to QDataRow and add to QDataSet + QDataRow *row; + for (int rowNr = 0; rowNr < data.size(); rowNr++) { + if (labelsRow.size() >= (rowNr + 1)) + row = new QDataRow(labelsRow.at(rowNr)); + else + row = new QDataRow(); + for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++) + row->addItem(new QDataItem(data.at(rowNr).at(colNr))); + row->d_ptr->verifySize(d_ptr->m_sampleCount.first); + d_ptr->m_dataSet->addRow(row); + row++; + } + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_dataSet->d_ptr->limitValues(); + // Don't auto-adjust height if tick count is set + if (d_ptr->m_tickCount == 0) { + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + } + d_ptr->m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn); + d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second); +} + +void Q3DBars::addDataSet(const QVector< QVector<QDataItem*> > &data, + const QVector<QString> &labelsRow, + const QVector<QString> &labelsColumn) +{ + // Copy axis labels + QString xAxis; + QString zAxis; + QString yAxis; + d_ptr->m_dataSet->d_ptr->axisLabels(&xAxis, &zAxis, &yAxis); + // Delete old data set + delete d_ptr->m_dataSet; + d_ptr->m_dataSet = new QDataSet(); + // Give drawer to data set + d_ptr->m_dataSet->d_ptr->setDrawer(d_ptr->m_drawer); + // Convert to QDataRow and add to QDataSet + QDataRow *row; + for (int rowNr = 0; rowNr < data.size(); rowNr++) { + if (labelsRow.size() >= (rowNr + 1)) + row = new QDataRow(labelsRow.at(rowNr)); + else + row = new QDataRow(); + for (int colNr = 0; colNr < data.at(rowNr).size(); colNr++) + row->addItem(data.at(rowNr).at(colNr)); + row->d_ptr->verifySize(d_ptr->m_sampleCount.first); + d_ptr->m_dataSet->addRow(row); + row++; + } + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_dataSet->d_ptr->limitValues(); + // Don't auto-adjust height if tick count is set + if (d_ptr->m_tickCount == 0) { + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + } + d_ptr->m_dataSet->setLabels(xAxis, zAxis, yAxis, labelsRow, labelsColumn); + d_ptr->m_dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second); +} + +void Q3DBars::addDataSet(QDataSet* dataSet) +{ + delete d_ptr->m_dataSet; + // Check sizes + dataSet->d_ptr->verifySize(d_ptr->m_sampleCount.second, d_ptr->m_sampleCount.first); + // Take ownership of given set + d_ptr->m_dataSet = dataSet; + // Find highest value + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_dataSet->d_ptr->limitValues(); + // Don't auto-adjust height if tick count is set + if (d_ptr->m_tickCount == 0) { + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + } + // Give drawer to data set + d_ptr->m_dataSet->d_ptr->setDrawer(d_ptr->m_drawer); +} + +Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q) + : q_ptr(q), + m_paintDevice(0), + m_barShader(0), + m_depthShader(0), + m_selectionShader(0), + m_backgroundShader(0), + m_labelShader(0), + m_barObj(0), + m_backgroundObj(0), + m_gridLineObj(0), + m_labelObj(0), + m_sampleCount(0, 0), + m_objFile(QStringLiteral(":/defaultMeshes/bar")), + m_mousePressed(MouseNone), + m_mousePos(QPoint(0, 0)), + m_zoomLevel(100), + m_zoomAdjustment(1.0f), + m_horizontalRotation(-45.0f), + m_verticalRotation(15.0f), + m_barThickness(QSizeF(0.75f, 0.75f)), + m_barSpacing(m_barThickness * 3.0f), + m_heightNormalizer(0.0f), + m_yAdjustment(0.0f), + m_rowWidth(0), + m_columnDepth(0), + m_maxDimension(0), + m_scaleX(0), + m_scaleZ(0), + m_scaleFactor(0), + m_maxSceneSize(40.0), + m_theme(new Theme()), + m_isInitialized(false), + m_selectionMode(ModeBar), + m_selectedBar(0), + m_zoomSelection(0), + m_dataSet(new QDataSet()), + m_axisLabelX(QStringLiteral("X")), + m_axisLabelZ(QStringLiteral("Z")), + m_axisLabelY(QStringLiteral("Y")), + m_sceneViewPort(0, 0, q->width(), q->height()), + m_zoomViewPort(0, 0, q->width(), q->height()), + m_zoomActivated(false), + m_textureHelper(new TextureHelper()), + m_labelTransparency(TransparencyNone), + m_font(QFont(QStringLiteral("Arial"))), + m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)), + m_xFlipped(false), + m_zFlipped(false), + m_bgrTexture(0), + m_depthTexture(0), + m_selectionTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_updateLabels(false), + m_gridEnabled(true), + m_shadowQuality(ShadowLow), + m_shadowQualityToShader(33.3f), + m_tickCount(0), + m_tickStep(0) +{ + m_dataSet->d_ptr->setDrawer(m_drawer); + QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Q3DBarsPrivate::updateTextures); +} + +Q3DBarsPrivate::~Q3DBarsPrivate() +{ + qDebug() << "Destroying Q3DBarsPrivate"; +#ifndef USE_HAX0R_SELECTION + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); +#endif + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->deleteTexture(&m_bgrTexture); + delete m_dataSet; + if (m_zoomSelection) { + m_zoomSelection->d_ptr->clear(); + delete m_zoomSelection; + } + delete m_barShader; + delete m_depthShader; + delete m_selectionShader; + delete m_backgroundShader; + delete m_barObj; + delete m_backgroundObj; + delete m_gridLineObj; + delete m_textureHelper; + delete m_drawer; +} + +void Q3DBarsPrivate::loadBarMesh() +{ + if (m_barObj) + delete m_barObj; + m_barObj = new ObjectHelper(m_objFile); + m_barObj->load(); +} + +void Q3DBarsPrivate::loadBackgroundMesh() +{ + if (m_backgroundObj) + delete m_backgroundObj; + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); + m_backgroundObj->load(); +} + +void Q3DBarsPrivate::loadGridLineMesh() +{ + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +void Q3DBarsPrivate::loadLabelMesh() +{ + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void Q3DBarsPrivate::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_barShader) + delete m_barShader; + m_barShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); + m_barShader->initialize(); +} + +void Q3DBarsPrivate::initSelectionShader() +{ + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexSelection"), + QStringLiteral(":/shaders/fragmentSelection")); + m_selectionShader->initialize(); +} + +void Q3DBarsPrivate::initDepthShader() +{ + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); +} + +void Q3DBarsPrivate::initSelectionBuffer() +{ +#ifndef USE_HAX0R_SELECTION + if (m_selectionTexture) { + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + } + m_selectionTexture = m_textureHelper->createSelectionTexture(q_ptr->size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +#endif +} + +void Q3DBarsPrivate::initDepthBuffer() +{ + if (m_depthTexture) { + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->deleteTexture(&m_depthTexture); + } + m_depthTexture = m_textureHelper->createDepthTexture(q_ptr->size(), m_depthFrameBuffer, + m_shadowQuality); +} + +void Q3DBarsPrivate::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Q3DBarsPrivate::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); + m_labelShader->initialize(); +} + +void Q3DBarsPrivate::updateTextures() +{ + // Drawer has changed; this flag needs to be checked when checking if we need to update labels + m_updateLabels = true; +} + +void Q3DBarsPrivate::calculateSceneScalingFactors() +{ + // Calculate scene scaling and translation factors + m_rowWidth = ((m_sampleCount.first + 1) * m_barSpacing.width()) / 2.0f; + m_columnDepth = ((m_sampleCount.second + 1) * m_barSpacing.height()) / 2.0f; + m_maxDimension = qMax(m_rowWidth, m_columnDepth); + m_scaleFactor = qMin((m_sampleCount.first * (m_maxDimension / m_maxSceneSize)), + (m_sampleCount.second * (m_maxDimension / m_maxSceneSize))); + m_scaleX = m_barThickness.width() / m_scaleFactor; + m_scaleZ = m_barThickness.height() / m_scaleFactor; + //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; + //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; + //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; +} + +void Q3DBarsPrivate::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) +{ + // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer + m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); + //qDebug() << m_yAdjustment; +} + +Q3DBarsPrivate::SelectionType Q3DBarsPrivate::isSelected(GLint row, GLint bar, + const QVector3D &selection) +{ + //static QVector3D prevSel = selection; // TODO: For debugging + SelectionType isSelectedType = SelectionNone; +#ifdef USE_HAX0R_SELECTION + if (selection == Utils::vectorFromColor(m_theme->m_windowColor)) +#else + if (selection == Utils::vectorFromColor(Qt::white)) +#endif + return isSelectedType; // skip window + QVector3D current = QVector3D((GLubyte)(((GLdouble)(row + 2) / (GLdouble)(m_sampleCount.second + 2)) + * 255.0 + 0.49), // +0.49 to fix rounding (there are conversions from unsigned short to GLdouble and back) + (GLubyte)(((GLdouble)(bar + 2) / (GLdouble)(m_sampleCount.first + 2)) + * 255.0 + 0.49), // +0.49 to fix rounding (there are conversions from unsigned short to GLdouble and back) + 0); + // TODO: For debugging + //if (selection != prevSel) { + // qDebug() << selection.x() << selection .y() << selection.z(); + // prevSel = selection; + //} + if (current == selection) + isSelectedType = SelectionBar; + else if (current.y() == selection.y() && (m_selectionMode == ModeBarAndColumn + || m_selectionMode == ModeBarRowAndColumn + || m_selectionMode == ModeZoomColumn)) + isSelectedType = SelectionColumn; + else if (current.x() == selection.x() && (m_selectionMode == ModeBarAndRow + || m_selectionMode == ModeBarRowAndColumn + || m_selectionMode == ModeZoomRow)) + isSelectedType = SelectionRow; + return isSelectedType; +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h new file mode 100644 index 00000000..3e490144 --- /dev/null +++ b/src/datavis3d/engine/q3dbars.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef Q3DBARS_H +#define Q3DBARS_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include "QtDataVis3D/qdatavis3namespace.h" +#include "q3dwindow.h" + +class QOpenGLShaderProgram; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Q3DBarsPrivate; +class QDataItem; +class QDataRow; +class QDataSet; +class LabelItem; + +class QTCOMMERCIALDATAVIS3D_EXPORT Q3DBars : public Q3DWindow +{ + Q_OBJECT +public: + explicit Q3DBars(); + ~Q3DBars(); + + void initialize(); + void render(); + + // Add a row of data. Each new row is added to the front of the sample space, moving previous + // rows back (if sample space is more than one row deep) + void addDataRow(const QVector<GLfloat> &dataRow, + const QString &labelRow = QString(), + const QVector<QString> &labelsColumn = QVector<QString>()); + // ownership of dataItems is transferred + void addDataRow(const QVector<QDataItem*> &dataRow, + const QString &labelRow = QString(), + const QVector<QString> &labelsColumn = QVector<QString>()); + // ownership of dataRow is transferred + void addDataRow(QDataRow *dataRow); + + // Add complete data set at a time, as a vector of data rows + void addDataSet(const QVector< QVector<GLfloat> > &data, + const QVector<QString> &labelsRow = QVector<QString>(), + const QVector<QString> &labelsColumn = QVector<QString>()); + + // ownership of dataItems is transferred + void addDataSet(const QVector< QVector<QDataItem*> > &data, + const QVector<QString> &labelsRow = QVector<QString>(), + const QVector<QString> &labelsColumn = QVector<QString>()); + // ownership of dataSet is transferred + void addDataSet(QDataSet* dataSet); + + // bar thickness, spacing between bars, and is spacing relative to thickness or absolute + // y -component sets the thickness/spacing of z -direction + // With relative 0.0f means side-to-side, 1.0f = one thickness in between + void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), + QSizeF spacing = QSizeF(1.0f, 1.0f), + bool relative = true); + + // bar type; bars (=cubes), pyramids, cones, cylinders, etc. + void setBarType(BarStyle style, bool smooth = false); + + // override bar type with own mesh + void setMeshFileName(const QString &objFileName); + + // how many samples per row and column, and names for axes + void setupSampleSpace(int samplesRow, int samplesColumn, const QString &labelRow = QString(), + const QString &labelColumn = QString(), + const QString &labelHeight = QString()); + + // Select preset camera placement + void setCameraPreset(CameraPreset preset); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (0...90) angles and distance in percentage (10...500)) + void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + + // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) + void setTheme(ColorTheme theme); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top + void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform = true); + + // TODO: valon siirto / asetus + // Change selection mode; single bar, bar and row, bar and column, or all + void setSelectionMode(SelectionMode mode); + + // Set window title + void setWindowTitle(const QString &title); + + // Font size adjustment (should it be in enum (smallest, smaller, small, normal, large, larger, largest), or just GLfloat? + void setFontSize(GLfloat fontsize); + + // Set font + void setFont(const QFont &font); + + // Label transparency adjustment + void setLabelTransparency(LabelTransparency transparency); + + // Enable or disable background grid + void setGridEnabled(bool enable); + + // Adjust shadow quality + void setShadowQuality(ShadowQuality quality); + + // Set tick count and step. Note; tickCount * step should be the maximum possible value of data set. + // Minimum is the absolute minimum possible value a bar can have. This is especially important to + // set if values can be negative. + void setTickCount(GLint tickCount, GLfloat step, GLfloat minimum = 0.0f); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + void drawZoomScene(); + void drawScene(); + QScopedPointer<Q3DBarsPrivate> d_ptr; + Q_DISABLE_COPY(Q3DBars) +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dbars_p.h b/src/datavis3d/engine/q3dbars_p.h new file mode 100644 index 00000000..30cdb6da --- /dev/null +++ b/src/datavis3d/engine/q3dbars_p.h @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** 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 Q3DBARS_p_H +#define Q3DBARS_p_H + +#include "qdatavis3dglobal.h" +#include "qdatavis3namespace.h" +#include <QOpenGLFunctions> +#include <QFont> + +class QOpenGLPaintDevice; + +class QPoint; +class QSizeF; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Q3DBars; +class QDataItem; +class QDataRow; +class QDataSet; +class ShaderHelper; +class ObjectHelper; +class TextureHelper; +class Theme; +class Drawer; + +class Q3DBarsPrivate : public QObject +{ +public: + enum SelectionType { + SelectionNone = 0, + SelectionBar, + SelectionRow, + SelectionColumn + }; + + enum MousePressType { + MouseNone = 0, + MouseOnScene, + MouseOnOverview, + MouseOnZoom, + MouseRotating + }; + +public: + Q3DBarsPrivate(Q3DBars *q); + ~Q3DBarsPrivate(); + + void loadBarMesh(); + void loadBackgroundMesh(); + void loadGridLineMesh(); + void loadLabelMesh(); + void initShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionShader(); + void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); + void initDepthShader(); + void initSelectionBuffer(); + void initDepthBuffer(); + void updateTextures(); + void calculateSceneScalingFactors(); + void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); + SelectionType isSelected(GLint row, GLint bar, const QVector3D &selection); + + Q3DBars *q_ptr; + + QOpenGLPaintDevice *m_paintDevice; + ShaderHelper *m_barShader; + ShaderHelper *m_depthShader; + ShaderHelper *m_selectionShader; + ShaderHelper *m_backgroundShader; + ShaderHelper *m_labelShader; + ObjectHelper *m_barObj; + ObjectHelper *m_backgroundObj; + ObjectHelper *m_gridLineObj; + ObjectHelper *m_labelObj; + QPair<int, int> m_sampleCount; + QString m_objFile; + MousePressType m_mousePressed; + QPoint m_mousePos; + GLint m_zoomLevel; + GLfloat m_zoomAdjustment; + GLfloat m_horizontalRotation; + GLfloat m_verticalRotation; + QSizeF m_barThickness; + QSizeF m_barSpacing; + GLfloat m_heightNormalizer; + GLfloat m_yAdjustment; + GLfloat m_rowWidth; + GLfloat m_columnDepth; + GLfloat m_maxDimension; + GLfloat m_scaleX; + GLfloat m_scaleZ; + GLfloat m_scaleFactor; + GLfloat m_maxSceneSize; + Theme *m_theme; + bool m_isInitialized; + SelectionMode m_selectionMode; + QDataItem *m_selectedBar; + QDataRow *m_zoomSelection; + QDataSet *m_dataSet; + QString m_axisLabelX; + QString m_axisLabelZ; + QString m_axisLabelY; + QRect m_sceneViewPort; + QRect m_zoomViewPort; + bool m_zoomActivated; + TextureHelper *m_textureHelper; + LabelTransparency m_labelTransparency; + QFont m_font; + Drawer *m_drawer; + bool m_xFlipped; + bool m_zFlipped; + GLuint m_bgrTexture; + GLuint m_depthTexture; + GLuint m_selectionTexture; + GLuint m_depthFrameBuffer; + GLuint m_selectionFrameBuffer; + GLuint m_selectionDepthBuffer; + bool m_updateLabels; + bool m_gridEnabled; + ShadowQuality m_shadowQuality; + GLfloat m_shadowQualityToShader; + GLint m_tickCount; + GLfloat m_tickStep; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp new file mode 100644 index 00000000..9ac43daa --- /dev/null +++ b/src/datavis3d/engine/q3dmaps.cpp @@ -0,0 +1,1525 @@ +/**************************************************************************** +** +** 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 "q3dmaps.h" +#include "q3dmaps_p.h" +#include "camerahelper_p.h" +#include "qdataitem_p.h" +#include "qdatarow_p.h" +#include "qdataset_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" + +#include <QMatrix4x4> +#include <QOpenGLPaintDevice> +#include <QPainter> +#include <QScreen> +#include <QMouseEvent> + +#include <qmath.h> + +#include <QDebug> + +//#define DISPLAY_RENDER_SPEED + +// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light +// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) +#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + +#ifdef DISPLAY_RENDER_SPEED +#include <QTime> +#endif + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels + +const GLfloat gridLineWidth = 0.005f; +GLfloat distanceMod = 0.0f; + +Q3DMaps::Q3DMaps() + : d_ptr(new Q3DMapsPrivate(this)) +{ +} + +Q3DMaps::~Q3DMaps() +{ +} + +void Q3DMaps::initialize() +{ + // Initialize shaders + if (d_ptr->m_shadowQuality > ShadowNone) { + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadow")); + // Init the depth buffer (for shadows) + d_ptr->initDepthBuffer(); + } else { + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), + QStringLiteral(":/shaders/fragmentTexture")); + } + d_ptr->initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + + // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. + d_ptr->initDepthShader(); + + // Init selection shader + d_ptr->initSelectionShader(); + + // Init the selection buffer + d_ptr->initSelectionBuffer(); + + // Load default mesh + d_ptr->loadBarMesh(); + + // Load background mesh + d_ptr->loadBackgroundMesh(); + + // Load grid line mesh + d_ptr->loadGridLineMesh(); + + // Load label mesh + d_ptr->loadLabelMesh(); + + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + // Set initial camera position + // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later + CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 1.0f + 2.9f * zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // Adjust to default rotation + setCameraPosition(d_ptr->m_horizontalRotation, d_ptr->m_verticalRotation, d_ptr->m_zoomLevel); + + // Set view port + glViewport(0, 0, width(), height()); + + // Set initialized -flag + d_ptr->m_isInitialized = true; + + // Update default light position +#ifndef USE_WIDER_SHADOWS + distanceMod = 1.0f; +#endif +} + +void Q3DMaps::render() +{ + if (!d_ptr->m_isInitialized) + return; + +#ifdef DISPLAY_RENDER_SPEED + // For speed computation + static bool firstRender = true; + static QTime lastTime; + static GLint nbFrames = 0; + if (firstRender) { + lastTime.start(); + firstRender = false; + } + + // Measure speed (as milliseconds per frame) + nbFrames++; + if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago + qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)"; + nbFrames = 0; + lastTime.restart(); + } +#endif + + // Draw scene + drawScene(); +} + +void Q3DMaps::drawScene() +{ + // Set clear color + QVector3D clearColor = Utils::vectorFromColor(d_ptr->m_theme->m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + static QVector3D selection = QVector3D(0, 0, 0); + + // Specify viewport + glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), + d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)d_ptr->m_sceneViewPort.width() + / (GLfloat)d_ptr->m_sceneViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = CameraHelper::calculateViewMatrix(d_ptr->m_mousePos, + d_ptr->m_zoomLevel + * d_ptr->m_zoomAdjustment, + d_ptr->m_sceneViewPort.width(), + d_ptr->m_sceneViewPort.height()); + + // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos, 0.0f, distanceMod); + + // Map adjustment direction to model matrix scaling + GLfloat heightMultiplier = 0.0f; + GLfloat widthMultiplier = 0.0f; + GLfloat depthMultiplier = 0.0f; + GLfloat heightScaler = 0.0f; + GLfloat widthScaler = 0.0f; + GLfloat depthScaler = 0.0f; + switch (d_ptr->m_adjustDirection) { + case AdjustHeight: + widthMultiplier = 0.0f; + heightMultiplier = 1.0f; + depthMultiplier = 0.0f; + widthScaler = d_ptr->m_barThickness.x() / d_ptr->m_scaleFactor; + heightScaler = 0.0f; + depthScaler = d_ptr->m_barThickness.z() / d_ptr->m_scaleFactor; + break; + case AdjustWidth: + widthMultiplier = 1.0f; + heightMultiplier = 0.0f; + depthMultiplier = 0.0f; + widthScaler = 0.0f; + heightScaler = d_ptr->m_barThickness.y() / d_ptr->m_scaleFactor; + depthScaler = d_ptr->m_barThickness.z() / d_ptr->m_scaleFactor; + break; + case AdjustDepth: + widthMultiplier = 0.0f; + heightMultiplier = 0.0f; + depthMultiplier = 1.0f; + widthScaler = d_ptr->m_barThickness.x() / d_ptr->m_scaleFactor; + heightScaler = d_ptr->m_barThickness.y() / d_ptr->m_scaleFactor; + depthScaler = 0.0f; + break; + case AdjustRadius: + widthMultiplier = 1.0f; + heightMultiplier = 0.0f; + depthMultiplier = 1.0f; + widthScaler = 0.0f; + heightScaler = d_ptr->m_barThickness.y() / d_ptr->m_scaleFactor; + depthScaler = 0.0f; + break; + case AdjustAll: + widthMultiplier = 1.0f; + heightMultiplier = 1.0f; + depthMultiplier = 1.0f; + widthScaler = 0.0f; + heightScaler = 0.0f; + depthScaler = 0.0f; + break; + } + + // Introduce regardless of shadow quality to simplify logic + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Render scene into a depth texture for using with shadow mapping + // Bind depth shader + d_ptr->m_depthShader->bind(); + + // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. + glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), + d_ptr->m_sceneViewPort.width() * d_ptr->m_shadowQuality, + d_ptr->m_sceneViewPort.height() * d_ptr->m_shadowQuality); + + // Enable drawing to framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_depthFrameBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + // Set front face culling to reduce self-shadowing issues + glCullFace(GL_FRONT); + + // Get the depth view matrix + // It may be possible to hack lightPos here if we want to make some tweaks to shadow + depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed + //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix +#ifdef USE_WIDER_SHADOWS + // Use this for a bit exaggerated shadows + depthProjectionMatrix.perspective(60.0f, (GLfloat)d_ptr->m_sceneViewPort.width() + / (GLfloat)d_ptr->m_sceneViewPort.height(), 3.0f, 100.0f); +#else + // Use these for normal shadows, with the light further away + depthProjectionMatrix = projectionMatrix; +#endif +#if 0 + // Draw background to depth buffer (You don't want to do this, except maybe for debugging purposes) + if (d_ptr->m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor, + 1.0f, + d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); + modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->vertexBuf()); + glVertexAttribPointer(d_ptr->m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_backgroundObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, d_ptr->m_backgroundObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt()); + } +#endif + // Draw bars to depth buffer + for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++) { + QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(item->d_ptr->translation().x(), + heightMultiplier * barHeight + heightScaler + - d_ptr->m_yAdjustment, + item->d_ptr->translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, + heightMultiplier * barHeight + heightScaler, + depthMultiplier * barHeight + depthScaler)); + + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); + glVertexAttribPointer(d_ptr->m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt()); + } + + // Disable drawing to framebuffer (= enable drawing to screen) + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset culling to normal + glCullFace(GL_BACK); + + // Release depth shader + d_ptr->m_depthShader->release(); + + // Revert to original viewport + glViewport(d_ptr->m_sceneViewPort.x(), d_ptr->m_sceneViewPort.y(), + d_ptr->m_sceneViewPort.width(), d_ptr->m_sceneViewPort.height()); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) + d_ptr->m_labelShader->bind(); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix); + d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, + d_ptr->m_depthTexture); + glDisable(GL_TEXTURE_2D); + d_ptr->m_labelShader->release(); +#endif + } +#if 1 + // Skip selection mode drawing if we're zoomed or have no selection mode + if (!d_ptr->m_zoomActivated && d_ptr->m_selectionMode > ModeNone) { + // Bind selection shader + d_ptr->m_selectionShader->bind(); + + // Draw bars to selection buffer + glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color to black + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++) { + QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(item->d_ptr->translation().x(), + heightMultiplier * barHeight + heightScaler + - d_ptr->m_yAdjustment, + item->d_ptr->translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, + heightMultiplier * barHeight + heightScaler, + depthMultiplier * barHeight + depthScaler)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + // add +2 to avoid black + QVector3D barColor = QVector3D((GLdouble)(bar + 2) + / (GLdouble)(d_ptr->m_data->d_ptr->row().size() + 2), + (GLdouble)(bar + 2) + / (GLdouble)(d_ptr->m_data->d_ptr->row().size() + 2), + 0.0); + + d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->MVP(), + MVPMatrix); + d_ptr->m_selectionShader->setUniformValue(d_ptr->m_selectionShader->color(), + barColor); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); + glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), + 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); + } + glEnable(GL_DITHER); + + // Read color under cursor + if (Q3DMapsPrivate::MouseOnScene == d_ptr->m_mousePressed) + selection = Utils::getSelection(d_ptr->m_mousePos, height()); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Release selection shader + d_ptr->m_selectionShader->release(); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + d_ptr->m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix); + d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, + d_ptr->m_selectionTexture); + glDisable(GL_TEXTURE_2D); + d_ptr->m_labelShader->release(); +#endif + } +#if 1 + // Bind bar shader + d_ptr->m_barShader->bind(); + + // Enable texture + glEnable(GL_TEXTURE_2D); + + // Draw bars + // TODO: Handle zoom by camera transformations + //if (!d_ptr->m_zoomActivated) + + bool barSelectionFound = false; + for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++) { + QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar); + if (!item) + continue; + + GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer; + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(item->d_ptr->translation().x(), + heightMultiplier * barHeight + heightScaler - d_ptr->m_yAdjustment, + item->d_ptr->translation().z()); + modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, + heightMultiplier * barHeight + heightScaler, + depthMultiplier * barHeight + depthScaler)); + itModelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler, + heightMultiplier * barHeight + heightScaler, + depthMultiplier * barHeight + depthScaler)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor); + QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor) + * barHeight; + + QVector3D barColor = baseColor + heightColor; + + GLfloat lightStrength = d_ptr->m_theme->m_lightStrength; + if (d_ptr->m_selectionMode > ModeNone) { + Q3DMapsPrivate::SelectionType selectionType = d_ptr->isSelected(bar, selection); + switch (selectionType) { + case Q3DMapsPrivate::SelectionBar: { + barColor = Utils::vectorFromColor(d_ptr->m_theme->m_highlightBarColor); + lightStrength = d_ptr->m_theme->m_highlightLightStrength; + // Insert data to QDataItem. We have no ownership, don't delete the previous one + if (!d_ptr->m_zoomActivated) { + d_ptr->m_selectedBar = item; + barSelectionFound = true; + } + break; + } + case Q3DMapsPrivate::SelectionNone: { + // Current bar is not selected, nor on a row or column + // do nothing + break; + } + default: { + // Unsupported selection mode + // do nothing + break; + } + } + } + + if (barHeight != 0) { + // Set shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightP(), lightPos); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->view(), viewMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->model(), modelMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->MVP(), MVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->color(), barColor); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->ambientS(), + d_ptr->m_theme->m_ambientStrength); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->depth(), + depthMVPMatrix); + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), + lightStrength / 10.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj, + 0, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_barShader->setUniformValue(d_ptr->m_barShader->lightS(), lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_barShader, d_ptr->m_barObj); + } + } + } + + // Release bar shader + d_ptr->m_barShader->release(); +#if 1 + // Bind background shader + d_ptr->m_backgroundShader->bind(); + + // Draw background + if (d_ptr->m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, zComp); + modelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor, + 1.0f, + d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); + modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); + itModelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor, + 1.0f, + d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set shader bindings + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightP(), lightPos); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->view(), viewMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->model(), modelMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(), MVPMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->ambientS(), + d_ptr->m_theme->m_ambientStrength * 3.0f); + + if (d_ptr->m_shadowQuality > ShadowNone) { + // Set shadow shader bindings + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->shadowQ(), + d_ptr->m_shadowQualityToShader); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->depth(), + depthMVPMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(), + d_ptr->m_theme->m_lightStrength / 25.0f); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, + d_ptr->m_bgrTexture, d_ptr->m_depthTexture); + } else { + // Set shadowless shader bindings + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(), + d_ptr->m_theme->m_lightStrength); + + // Draw the object + d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, + d_ptr->m_bgrTexture); + } + } + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // Release background shader + d_ptr->m_backgroundShader->release(); +#endif + + // Handle zoom activation and label drawing + if (!barSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + d_ptr->m_selectedBar = NULL; + //if (d_ptr->m_zoomActivated && Q3DMapsPrivate::MouseOnOverview == d_ptr->m_mousePressed) { + //d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + //d_ptr->m_zoomActivated = false; + //} + } /*else if (d_ptr->m_selectionMode >= ModeZoomRow + && Q3DMapsPrivate::MouseOnScene == d_ptr->m_mousePressed) { + // Activate zoom mode + d_ptr->m_zoomActivated = true; + d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); + + // Create label textures + for (int col = 0; col < d_ptr->m_zoomSelection->d_ptr->row().size(); col++) { + QDataItem *item = d_ptr->m_zoomSelection->d_ptr->getItem(col); + d_ptr->m_drawer->generateLabelTexture(item); + } + }*/ else { + // Print value of selected bar + static QDataItem *prevItem = d_ptr->m_selectedBar; + d_ptr->m_labelShader->bind(); + glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +#ifndef DISPLAY_FULL_DATA_ON_SELECTION + // Draw just the value string of the selected bar + if (prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) { + d_ptr->m_drawer->generateLabelTexture(d_ptr->m_selectedBar); + prevItem = d_ptr->m_selectedBar; + } + + d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, d_ptr->m_selectedBar->d_ptr->label(), + viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true); +#else + static bool firstSelection = true; + // Draw the value string followed by row label and column label + LabelItem labelItem = d_ptr->m_selectedBar->d_ptr->selectionLabel(); + if (firstSelection || prevItem != d_ptr->m_selectedBar || d_ptr->m_updateLabels) { + QString labelText = d_ptr->m_selectedBar->d_ptr->valueStr(); + // if ((d_ptr->m_data->d_ptr->columnLabels().size() + // > d_ptr->m_selectedBar->d_ptr->position().y()) + // && (d_ptr->m_data->d_ptr->rowLabels().size() + // > d_ptr->m_selectedBar->d_ptr->position().x())) { + // labelText.append(QStringLiteral(" (")); + // labelText.append(d_ptr->m_data->d_ptr->rowLabels().at( + // d_ptr->m_selectedBar->d_ptr->position().x())); + // labelText.append(QStringLiteral(", ")); + // labelText.append(d_ptr->m_data->d_ptr->columnLabels().at( + // d_ptr->m_selectedBar->d_ptr->position().y())); + // labelText.append(QStringLiteral(")")); + // //qDebug() << labelText; + // } + d_ptr->m_drawer->generateLabelItem(&labelItem, labelText); + d_ptr->m_selectedBar->d_ptr->setSelectionLabel(labelItem); + prevItem = d_ptr->m_selectedBar; + firstSelection = false; + } + + d_ptr->m_drawer->drawLabel(*d_ptr->m_selectedBar, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true, false); +#endif + glDisable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + // Release label shader + d_ptr->m_labelShader->release(); + + // Reset label update flag; they should have been updated when we get here + d_ptr->m_updateLabels = false; + } +#if 0 + // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. + // Bind label shader + d_ptr->m_labelShader->bind(); + + glEnable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) + for (int row = 0; row != d_ptr->m_sampleCount.second; row += 1) { + // Go through all rows and get position of max+1 or min-1 column, depending on x flip + // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems + rowPos = (row + 1) * (d_ptr->m_barSpacing.height()); + barPos = 0; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignRight; + if (d_ptr->m_zFlipped) + rotLabelY = 180.0f; + if (d_ptr->m_xFlipped) { + barPos = (d_ptr->m_sampleCount.first + 1) * (d_ptr->m_barSpacing.width()); + alignment = Qt::AlignLeft; + } + QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + + zComp); + + // TODO: Try it; draw the label here + + // Create a data item + QDataItem *label = new QDataItem(); + label->d_ptr->setTranslation(labelPos); + if (d_ptr->m_data->d_ptr->rowLabelItems().size() > row) { + label->d_ptr->setLabel(d_ptr->m_data->d_ptr->rowLabelItems().at( + d_ptr->m_data->d_ptr->rowLabelItems().size() - row - 1)); + } + + //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->rowLabels().at(row); + + d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true, true, LabelMid, alignment); + + delete label; + } + for (int bar = 0; bar != d_ptr->m_sampleCount.first; bar += 1) { + // Go through all columns and get position of max+1 or min-1 row, depending on z flip + // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems + barPos = (bar + 1) * (d_ptr->m_barSpacing.width()); + rowPos = 0; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 90.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (d_ptr->m_xFlipped) + rotLabelY = -90.0f; + if (d_ptr->m_zFlipped) { + rowPos = (d_ptr->m_sampleCount.second + 1) * (d_ptr->m_barSpacing.height()); + alignment = Qt::AlignRight; + } + QVector3D labelPos = QVector3D((d_ptr->m_rowWidth - barPos) / d_ptr->m_scaleFactor, + -d_ptr->m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" + (d_ptr->m_columnDepth - rowPos) / d_ptr->m_scaleFactor + + zComp); + + // TODO: Try it; draw the label here + + // Create a data item + QDataItem *label = new QDataItem(); + label->d_ptr->setTranslation(labelPos); + if (d_ptr->m_data->d_ptr->columnLabelItems().size() > bar) { + label->d_ptr->setLabel(d_ptr->m_data->d_ptr->columnLabelItems().at( + d_ptr->m_data->d_ptr->columnLabelItems().size() + - bar - 1)); + } + + //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << d_ptr->m_dataSet->d_ptr->columnLabels().at(bar); + + d_ptr->m_drawer->drawLabel(*label, label->d_ptr->label(), viewMatrix, projectionMatrix, + QVector3D(0.0f, d_ptr->m_yAdjustment, zComp), + QVector3D(rotLabelX, rotLabelY, 0.0f), d_ptr->m_heightNormalizer, + d_ptr->m_selectionMode, d_ptr->m_labelShader, + d_ptr->m_labelObj, true, true, LabelMid, alignment); + + delete label; + } + glDisable(GL_TEXTURE_2D); + if (d_ptr->m_labelTransparency > TransparencyNone) + glDisable(GL_BLEND); + + // Release label shader + d_ptr->m_labelShader->release(); +#endif +#endif +#endif +} + +void Q3DMaps::mousePressEvent(QMouseEvent *event) +{ + if (Qt::LeftButton == event->button()) { + if (d_ptr->m_zoomActivated) { + //qDebug() << event->pos().x() << event->pos().y() << d_ptr->m_sceneViewPort << d_ptr->m_zoomViewPort; + if (event->pos().x() <= d_ptr->m_sceneViewPort.width() + && event->pos().y() <= d_ptr->m_sceneViewPort.height()) { + d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnOverview; + //qDebug() << "Mouse pressed on overview"; + } else { + d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnZoom; + //qDebug() << "Mouse pressed on zoom"; + } + } else { + d_ptr->m_mousePressed = Q3DMapsPrivate::MouseOnScene; + // update mouse positions to prevent jumping when releasing or repressing a button + d_ptr->m_mousePos = event->pos(); + //qDebug() << "Mouse pressed on scene"; + } + } else if (Qt::MiddleButton == event->button()) { + // reset rotations + d_ptr->m_mousePos = QPoint(0, 0); + } else if (Qt::RightButton == event->button()) { + d_ptr->m_mousePressed = Q3DMapsPrivate::MouseRotating; + // update mouse positions to prevent jumping when releasing or repressing a button + d_ptr->m_mousePos = event->pos(); + } + CameraHelper::updateMousePos(d_ptr->m_mousePos); +} + +void Q3DMaps::mouseReleaseEvent(QMouseEvent *event) +{ + //qDebug() << "mouse button released" << event->button(); + if (Q3DMapsPrivate::MouseRotating == d_ptr->m_mousePressed) { + // update mouse positions to prevent jumping when releasing or repressing a button + d_ptr->m_mousePos = event->pos(); + CameraHelper::updateMousePos(event->pos()); + } + d_ptr->m_mousePressed = Q3DMapsPrivate::MouseNone; +} + +void Q3DMaps::mouseMoveEvent(QMouseEvent *event) +{ + if (Q3DMapsPrivate::MouseRotating == d_ptr->m_mousePressed) { + //qDebug() << "mouse moved while pressed" << event->pos(); + d_ptr->m_mousePos = event->pos(); + } +#if 0 + // TODO: Testi - laske kursorin sijainti scenessä + QPointF mouse3D((2.0f * event->pos().x() - width()) / height(), + 1.0f - (2.0f * event->pos().y()) / height()); + //qDebug() << "mouse position in scene" << mouse3D; + + // TODO: Testi laske focal point + GLfloat focalPoint = tan(45.0f / 2.0f); + + // TODO: Testi - laske viewmatriisin kerroin + QVector3D worldRay = QVector3D(0.0f, 0.0f, 0.0f) + - QVector3D(mouse3D.x(), mouse3D.y(), -focalPoint); + //qDebug() << "worldRay" << worldRay; + // multiply viewmatrix with this to get something? +#endif +} + +void Q3DMaps::wheelEvent(QWheelEvent *event) +{ + if (d_ptr->m_zoomLevel > 100) + d_ptr->m_zoomLevel += event->angleDelta().y() / 12; + else if (d_ptr->m_zoomLevel > 50) + d_ptr->m_zoomLevel += event->angleDelta().y() / 60; + else + d_ptr->m_zoomLevel += event->angleDelta().y() / 120; + if (d_ptr->m_zoomLevel > 500) + d_ptr->m_zoomLevel = 500; + else if (d_ptr->m_zoomLevel < 10) + d_ptr->m_zoomLevel = 10; +} + +void Q3DMaps::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + // Set view port + if (d_ptr->m_zoomActivated) + d_ptr->m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); + else + d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + d_ptr->m_zoomViewPort = QRect(0, 0, width(), height()); + + // Calculate zoom level based on aspect ratio + GLfloat div; + GLfloat zoomAdjustment; + div = qMin(width(), height()); + zoomAdjustment = defaultRatio * ((width() / div) / (height() / div)); + //qDebug() << "zoom adjustment" << zoomAdjustment; + d_ptr->m_zoomAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f + + // Re-init selection buffer + d_ptr->initSelectionBuffer(); + + // Re-init depth buffer + d_ptr->initDepthBuffer(); +} + +void Q3DMaps::setBarSpecs(const QVector3D &thickness, AdjustmentDirection direction) +{ + d_ptr->m_barThickness = thickness; + d_ptr->m_adjustDirection = direction; +} + +void Q3DMaps::setBarType(BarStyle style, bool smooth) +{ + if (style == Bars) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/barSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/bar"); + } else if (style == Pyramids) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/pyramid"); + } else if (style == Cones) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cone"); + } else if (style == Cylinders) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/cylinder"); + } else if (style == Spheres) { + if (smooth) + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); + else + d_ptr->m_objFile = QStringLiteral(":/defaultMeshes/sphere"); + } + // Reload mesh data + if (d_ptr->m_isInitialized) + d_ptr->loadBarMesh(); +} + +void Q3DMaps::setMeshFileName(const QString &objFileName) +{ + d_ptr->m_objFile = objFileName; +} + +void Q3DMaps::setCameraPreset(CameraPreset preset) +{ + CameraHelper::setCameraPreset(preset); +} + +void Q3DMaps::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +{ + d_ptr->m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); + d_ptr->m_verticalRotation = qBound(0.0f, vertical, 90.0f); + d_ptr->m_zoomLevel = qBound(10, distance, 500); + CameraHelper::setCameraRotation(QPointF(d_ptr->m_horizontalRotation, + d_ptr->m_verticalRotation)); + //qDebug() << "camera rotation set to" << d_ptr->m_horizontalRotation << d_ptr->m_verticalRotation; +} + +void Q3DMaps::setTheme(ColorTheme theme) +{ + d_ptr->m_theme->useTheme(theme); + d_ptr->m_drawer->setTheme(*d_ptr->m_theme); + // Re-initialize shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + d_ptr->m_updateLabels = true; +} + +void Q3DMaps::setBarColor(QColor baseColor, QColor heightColor, bool uniform) +{ + d_ptr->m_theme->m_baseColor = baseColor; + d_ptr->m_theme->m_heightColor = heightColor; + if (d_ptr->m_theme->m_uniformColor != uniform) { + // Re-initialize shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + } + d_ptr->m_theme->m_uniformColor = uniform; +} + +void Q3DMaps::setSelectionMode(SelectionMode mode) +{ + d_ptr->m_selectionMode = mode; + // Disable zoom if mode changes + //d_ptr->m_zoomActivated = false; + //d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); +} + +void Q3DMaps::setWindowTitle(const QString &title) +{ + setTitle(title); +} + +void Q3DMaps::setFontSize(float fontsize) +{ + d_ptr->m_font.setPointSizeF(fontsize); + d_ptr->m_drawer->setFont(d_ptr->m_font); + d_ptr->m_updateLabels = true; +} + +void Q3DMaps::setFont(const QFont &font) +{ + d_ptr->m_font = font; + d_ptr->m_drawer->setFont(font); + d_ptr->m_updateLabels = true; +} + +void Q3DMaps::setLabelTransparency(LabelTransparency transparency) +{ + d_ptr->m_labelTransparency = transparency; + d_ptr->m_drawer->setTransparency(transparency); + d_ptr->m_updateLabels = true; +} + +void Q3DMaps::setGridEnabled(bool enable) +{ + d_ptr->m_gridEnabled = enable; +} + +bool Q3DMaps::addDataItem(QDataItem* dataItem) +{ + // Check validity + if (!d_ptr->isValid(*dataItem)) + return false; + // Convert position to translation + d_ptr->calculateTranslation(dataItem); + // Add item + d_ptr->m_data->addItem(dataItem); + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + return true; +} + +bool Q3DMaps::addData(const QVector<QDataItem*> &data) +{ + // Convert to QDataRow + for (int i = 0; i < data.size(); i++) { + QDataItem *item = data.at(i); + // Check validity + if (!d_ptr->isValid(*item)) { + return false; + } else { + // Convert position to translation + d_ptr->calculateTranslation(item); + // Add item + d_ptr->m_data->addItem(item); + } + } + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + return true; +} + +bool Q3DMaps::addData(const QDataRow &dataRow) +{ + for (int itemIdx = 0; itemIdx < dataRow.d_ptr->row().size(); itemIdx++) { + QDataItem *item = dataRow.d_ptr->getItem(itemIdx); + // Check validity + if (!d_ptr->isValid(*item)) { + return false; + } else { + // Convert position to translation + d_ptr->calculateTranslation(item); + // Add item + d_ptr->m_data->addItem(item); + } + } + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + return true; +} + +bool Q3DMaps::setData(const QVector<QDataItem*> &dataRow) +{ + // Delete previous data + delete d_ptr->m_data; + // Convert to QDataRow + d_ptr->m_data = new QDataRow(); + for (int i = 0; i < dataRow.size(); i++) { + QDataItem *item = dataRow.at(i); + // Check validity + if (!d_ptr->isValid(*item)) { + return false; + } else { + // Convert position to translation + d_ptr->calculateTranslation(item); + // Add item + d_ptr->m_data->addItem(item); + } + } + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + return true; +} + +bool Q3DMaps::setData(QDataRow *dataRow) +{ + // Check validity + for (int i = 0; i < dataRow->d_ptr->row().size(); i++) { + if (!d_ptr->isValid(*dataRow->d_ptr->row().at(i))) + return false; + else + d_ptr->calculateTranslation(dataRow->d_ptr->row()[i]); + } + // Delete previous data + delete d_ptr->m_data; + // Set give data as new data + d_ptr->m_data = dataRow; + // Get the limits + QPair<GLfloat, GLfloat> limits = d_ptr->m_data->d_ptr->limitValues(); + d_ptr->m_heightNormalizer = (GLfloat)qMax(qFabs(limits.second), qFabs(limits.first)); + d_ptr->calculateHeightAdjustment(limits); + return true; +} + +void Q3DMaps::setAreaSpecs(const QRect &areaRect, const QImage &image) +{ + d_ptr->calculateSceneScalingFactors(areaRect); + setImage(image); +} + +void Q3DMaps::setImage(const QImage &image) +{ + if (d_ptr->m_bgrTexture) + glDeleteTextures(1, &d_ptr->m_bgrTexture); + d_ptr->m_bgrTexture = d_ptr->m_textureHelper->create2DTexture(image, true, true); +} + +void Q3DMaps::setShadowQuality(ShadowQuality quality) +{ + d_ptr->m_shadowQuality = quality; + switch (quality) { + case ShadowLow: + //qDebug() << "ShadowLow"; + d_ptr->m_shadowQualityToShader = 33.3f; + break; + case ShadowMedium: + //qDebug() << "ShadowMedium"; + d_ptr->m_shadowQualityToShader = 100.0f; + break; + case ShadowHigh: + //qDebug() << "ShadowHigh"; + d_ptr->m_shadowQualityToShader = 200.0f; + break; + default: + d_ptr->m_shadowQualityToShader = 0.0f; + break; + } + if (d_ptr->m_shadowQuality > ShadowNone) { + // Re-init depth buffer + d_ptr->initDepthBuffer(); + // Re-init shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadow")); + } else { + // Re-init shaders + if (!d_ptr->m_theme->m_uniformColor) { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + d_ptr->initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), + QStringLiteral(":/shaders/fragmentTexture")); + } +} + +Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q) + : q_ptr(q), + m_paintDevice(0), + m_barShader(0), + m_depthShader(0), + m_selectionShader(0), + m_backgroundShader(0), + m_labelShader(0), + m_barObj(0), + m_backgroundObj(0), + m_gridLineObj(0), + m_labelObj(0), + m_objFile(QStringLiteral(":/defaultMeshes/bar")), + m_mousePressed(MouseNone), + m_mousePos(QPoint(0, 0)), + m_zoomLevel(100), + m_zoomAdjustment(1.0f), + m_horizontalRotation(0.0f), + m_verticalRotation(45.0f), + m_barThickness(QVector3D(1.0f, 0.0f, 1.0f)), + m_heightNormalizer(0.0f), + m_yAdjustment(0.0f), + m_scaleFactor(1.0f), + m_theme(new Theme()), + m_isInitialized(false), + m_selectionMode(ModeBar), + m_selectedBar(0), + m_data(new QDataRow()), + m_axisLabelX(QStringLiteral("X")), + m_axisLabelZ(QStringLiteral("Z")), + m_axisLabelY(QStringLiteral("Y")), + m_sceneViewPort(0, 0, q->width(), q->height()), + m_zoomViewPort(0, 0, q->width(), q->height()), + m_zoomActivated(false), + m_textureHelper(new TextureHelper()), + m_labelTransparency(TransparencyNone), + m_font(QFont(QStringLiteral("Arial"))), + m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)), + m_bgrTexture(0), + m_depthTexture(0), + m_selectionTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_areaSize(QSizeF(1.0f, 1.0f)), + m_updateLabels(true), + m_gridEnabled(true), + m_shadowQuality(ShadowLow), + m_shadowQualityToShader(33.3f) +{ + //m_data->d_ptr->setDrawer(m_drawer); + //QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Q3DMapsPrivate::updateTextures); +} + +Q3DMapsPrivate::~Q3DMapsPrivate() +{ + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->deleteTexture(&m_bgrTexture); + delete m_data; + delete m_barShader; + delete m_selectionShader; + delete m_backgroundShader; + delete m_barObj; + delete m_backgroundObj; + delete m_gridLineObj; + delete m_textureHelper; + delete m_drawer; +} + +void Q3DMapsPrivate::loadBarMesh() +{ + if (m_barObj) + delete m_barObj; + m_barObj = new ObjectHelper(m_objFile); + m_barObj->load(); +} + +void Q3DMapsPrivate::loadBackgroundMesh() +{ + if (m_backgroundObj) + delete m_backgroundObj; + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_backgroundObj->load(); +} + +void Q3DMapsPrivate::loadGridLineMesh() +{ + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +void Q3DMapsPrivate::loadLabelMesh() +{ + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void Q3DMapsPrivate::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_barShader) + delete m_barShader; + m_barShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); + m_barShader->initialize(); +} + +void Q3DMapsPrivate::initSelectionShader() +{ + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexSelection"), + QStringLiteral(":/shaders/fragmentSelection")); + m_selectionShader->initialize(); +} + +void Q3DMapsPrivate::initDepthShader() +{ + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); +} + +void Q3DMapsPrivate::initSelectionBuffer() +{ + if (m_selectionTexture) { + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->deleteTexture(&m_selectionTexture); + } + m_selectionTexture = m_textureHelper->createSelectionTexture(q_ptr->size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +} + +void Q3DMapsPrivate::initDepthBuffer() +{ + if (m_depthTexture) { + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->deleteTexture(&m_depthTexture); + } + m_depthTexture = m_textureHelper->createDepthTexture(q_ptr->size(), m_depthFrameBuffer, + m_shadowQuality); +} + +void Q3DMapsPrivate::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Q3DMapsPrivate::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader); + // m_labelShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/testDepthVert"), + // QStringLiteral(":/shaders/testDepthFrag")); + m_labelShader->initialize(); +} + +void Q3DMapsPrivate::updateTextures() +{ + // Drawer has changed; this flag needs to be checked when checking if we need to update labels + m_updateLabels = true; +} + +void Q3DMapsPrivate::calculateSceneScalingFactors(const QRect &areaRect) +{ + m_areaSize = areaRect.size(); + // Calculate scaling factor so that we can be sure the whole area fits to positive z space + if (zComp > 1.0f) + m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()) / zComp; + else + m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); + //qDebug() << "scaleFactor" << m_scaleFactor; +} + +void Q3DMapsPrivate::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) +{ + // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer + m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); + //qDebug() << m_yAdjustment; +} + +void Q3DMapsPrivate::calculateTranslation(QDataItem *item) +{ + // We need to convert position (which is in coordinates), to translation (which has origin in the center and is scaled) + // -> move pos(center, center) to trans(0, 0) and pos(0, 0) to trans(left, top) + GLfloat xTrans = 2.0f * (item->d_ptr->position().x() - (m_areaSize.width() / 2.0f)) + / m_scaleFactor; + GLfloat zTrans = 2.0f * (item->d_ptr->position().y() - (m_areaSize.height() / 2.0f)) + / m_scaleFactor; + //qDebug() << "x, y" << item->d_ptr->position().x() << item->d_ptr->position().y(); + item->d_ptr->setTranslation(QVector3D(xTrans, 0.0f, zTrans + zComp)); + //qDebug() << item->d_ptr->translation(); +} + +Q3DMapsPrivate::SelectionType Q3DMapsPrivate::isSelected(GLint bar, const QVector3D &selection) +{ + //static QVector3D prevSel = selection; // TODO: For debugging + SelectionType isSelectedType = SelectionNone; + if (selection == Utils::vectorFromColor(Qt::black)) + return isSelectedType; // skip window + QVector3D current = QVector3D((GLubyte)((GLdouble)(bar + 2) + / (GLdouble)(m_data->d_ptr->row().size() + 2) + * 255.0 + 0.49), // +0.49 to fix rounding (there are conversions from unsigned short to GLdouble and back) + (GLubyte)(((GLdouble)(bar + 2) + / (GLdouble)(m_data->d_ptr->row().size() + 2)) + * 255.0 + 0.49), // +0.49 to fix rounding (there are conversions from unsigned short to GLdouble and back) + 0); + // TODO: For debugging + //if (selection != prevSel) { + // qDebug() << selection.x() << selection .y() << selection.z(); + // prevSel = selection; + //} + if (current == selection) + isSelectedType = SelectionBar; + return isSelectedType; +} + +bool Q3DMapsPrivate::isValid(const QDataItem &item) +{ + bool retval = true; + if (item.d_ptr->value() < 0) { + qCritical("Data item value out of range"); + retval = false; + } else if (item.d_ptr->position().x() < 0 || item.d_ptr->position().x() > m_areaSize.width()) { + qCritical("Data item x position out of range"); + retval = false; + } else if (item.d_ptr->position().y() < 0 || item.d_ptr->position().y() > m_areaSize.height()) { + qCritical("Data item y position out of range"); + retval = false; + } + return retval; +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dmaps.h b/src/datavis3d/engine/q3dmaps.h new file mode 100644 index 00000000..37bf08e7 --- /dev/null +++ b/src/datavis3d/engine/q3dmaps.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef Q3DMAPS_H +#define Q3DMAPS_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include "QtDataVis3D/qdatavis3namespace.h" +#include "q3dwindow.h" + +class QOpenGLShaderProgram; +class QImage; +class QRect; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Q3DMapsPrivate; +class QDataItem; +class QDataRow; +class QDataSet; +class LabelItem; + +class QTCOMMERCIALDATAVIS3D_EXPORT Q3DMaps : public Q3DWindow +{ + Q_OBJECT +public: + enum AdjustmentDirection { + AdjustHeight = 0, // map value to y + AdjustWidth, // map value to x + AdjustDepth, // map value to z + AdjustRadius, // map value to x and z + AdjustAll // map value to all (x, y, z) + }; + +public: + explicit Q3DMaps(); + ~Q3DMaps(); + + void initialize(); + void render(); + void render(QPainter *painter); + + // Add data item. New data item is appended to old data. + // ownership of data is transferred + bool addDataItem(QDataItem *dataItem); + + // Add data set. New data is appended to old data. + // ownership of data is transferred + bool addData(const QVector<QDataItem*> &data); + // ownership of data is transferred + bool addData(const QDataRow &data); + + // Add data set. Old data is deleted. + // ownership of data is transferred + bool setData(const QVector<QDataItem*> &data); + // ownership of data is transferred + bool setData(QDataRow *data); + + // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value + // TODO: Start using thickness also in adjustment direction; use it as a relative value. + // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to + // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. + void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), + AdjustmentDirection direction = AdjustHeight); + + // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. + void setBarType(BarStyle style, bool smooth = false); + + // override bar type with own mesh + void setMeshFileName(const QString &objFileName); + + // Select preset camera placement + void setCameraPreset(CameraPreset preset); + + // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and + // vertical (0...90) angles and distance in percentage (10...500)) + void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); + + // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) + void setTheme(ColorTheme theme); + + // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top + void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); + + // TODO: valon siirto / asetus + // Change selection mode; single bar, bar and row, bar and column, or all + void setSelectionMode(SelectionMode mode); + + // Set window title + void setWindowTitle(const QString &title); + + // Font size adjustment (should it be in enum (smallest, smaller, small, normal, large, larger, largest), or just GLfloat? + void setFontSize(GLfloat fontsize); + + // Set font + void setFont(const QFont &font); + + // Label transparency adjustment + void setLabelTransparency(LabelTransparency transparency); + + // Enable or disable background grid + void setGridEnabled(bool enable); + + // Set area specs + void setAreaSpecs(const QRect &areaRect, const QImage &image); + + // Set area image + void setImage(const QImage &image); + + // Adjust shadow quality + void setShadowQuality(ShadowQuality quality); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + void drawScene(); + QScopedPointer<Q3DMapsPrivate> d_ptr; + Q_DISABLE_COPY(Q3DMaps); +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dmaps_p.h b/src/datavis3d/engine/q3dmaps_p.h new file mode 100644 index 00000000..f02ebc36 --- /dev/null +++ b/src/datavis3d/engine/q3dmaps_p.h @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** 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 Q3DMAPS_P_H +#define Q3DMAPS_P_H + +#include "qdatavis3dglobal.h" +#include "qdatavis3namespace.h" +#include <QOpenGLFunctions> +#include <QFont> + +class QOpenGLPaintDevice; + +class QPoint; +class QSizeF; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Q3DMaps; +class QDataItem; +class QDataRow; +class QDataSet; +class ShaderHelper; +class ObjectHelper; +class TextureHelper; +class Theme; +class Drawer; + +class Q3DMapsPrivate : public QObject +{ +public: + enum SelectionType { + SelectionNone = 0, + SelectionBar, + SelectionRow, + SelectionColumn + }; + + enum MousePressType { + MouseNone = 0, + MouseOnScene, + MouseOnOverview, + MouseOnZoom, + MouseRotating + }; + +public: + Q3DMapsPrivate(Q3DMaps *q); + ~Q3DMapsPrivate(); + + void loadBarMesh(); + void loadBackgroundMesh(); + void loadGridLineMesh(); + void loadLabelMesh(); + void initShaders(const QString &vertexShader, const QString &fragmentShader); + void initSelectionShader(); + void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); + void initDepthShader(); + void initSelectionBuffer(); + void initDepthBuffer(); + void updateTextures(); + void calculateSceneScalingFactors(const QRect &areaRect); + void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); + void calculateTranslation(QDataItem *item); + SelectionType isSelected(GLint bar, const QVector3D &selection); + bool isValid(const QDataItem &item); + + Q3DMaps *q_ptr; + + QOpenGLPaintDevice *m_paintDevice; + ShaderHelper *m_barShader; + ShaderHelper *m_depthShader; + ShaderHelper *m_selectionShader; + ShaderHelper *m_backgroundShader; + ShaderHelper *m_labelShader; + ObjectHelper *m_barObj; + ObjectHelper *m_backgroundObj; + ObjectHelper *m_gridLineObj; + ObjectHelper *m_labelObj; + QString m_objFile; + MousePressType m_mousePressed; + QPoint m_mousePos; + GLint m_zoomLevel; + GLfloat m_zoomAdjustment; + GLfloat m_horizontalRotation; + GLfloat m_verticalRotation; + QVector3D m_barThickness; + GLfloat m_heightNormalizer; + GLfloat m_yAdjustment; + GLfloat m_scaleFactor; + Theme *m_theme; + bool m_isInitialized; + SelectionMode m_selectionMode; + QDataItem *m_selectedBar; + QDataRow *m_data; + QString m_axisLabelX; + QString m_axisLabelZ; + QString m_axisLabelY; + QRect m_sceneViewPort; + QRect m_zoomViewPort; + bool m_zoomActivated; + TextureHelper *m_textureHelper; + LabelTransparency m_labelTransparency; + QFont m_font; + Drawer *m_drawer; + QSizeF m_areaSize; + GLuint m_bgrTexture; + GLuint m_depthTexture; + GLuint m_selectionTexture; + GLuint m_depthFrameBuffer; + GLuint m_selectionFrameBuffer; + GLuint m_selectionDepthBuffer; + bool m_updateLabels; + bool m_gridEnabled; + Q3DMaps::AdjustmentDirection m_adjustDirection; + ShadowQuality m_shadowQuality; + GLfloat m_shadowQualityToShader; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dwindow.cpp b/src/datavis3d/engine/q3dwindow.cpp new file mode 100644 index 00000000..a172e7b6 --- /dev/null +++ b/src/datavis3d/engine/q3dwindow.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** 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 "q3dwindow.h" +#include "q3dwindow_p.h" + +#include <QGuiApplication> + +#include <QOpenGLContext> +#include <QOpenGLPaintDevice> +#include <QPainter> + +#include <QDebug> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +Q3DWindow::Q3DWindow(QWindow *parent) + : QWindow(parent), + d_ptr(new Q3DWindowPrivate(this)) +{ + setSurfaceType(QWindow::OpenGLSurface); + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(16); + surfaceFormat.setSamples(4); + surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + //surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); // OpenGL crashes with ANGLE, comment out or define OpenGLES + setFormat(surfaceFormat); + + create(); + + d_ptr->m_context->setFormat(requestedFormat()); + d_ptr->m_context->create(); +#if !defined(Q_OS_MAC) + // These are required here for windows (and linux?), but cause errors on mac + d_ptr->m_context->makeCurrent(this); + initializeOpenGLFunctions(); +#endif + initialize(); +} + +Q3DWindow::~Q3DWindow() +{ +} + +void Q3DWindow::initialize() +{ + qDebug() << "OpenGL version" << format().majorVersion() << format().minorVersion(); + qDebug() << "OpenGL renderer" << format().renderableType(); + //qDebug() << "OpenGL swapBehavior" << format().swapBehavior(); + setAnimating(true); +} + +void Q3DWindow::render() +{ +} + +void Q3DWindow::renderLater() +{ + if (!d_ptr->m_updatePending) { + d_ptr->m_updatePending = true; + QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); + } +} + +bool Q3DWindow::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::UpdateRequest: + renderNow(); + return true; + default: + return QWindow::event(event); + } +} + +void Q3DWindow::exposeEvent(QExposeEvent *event) +{ + Q_UNUSED(event); + + if (isExposed()) + renderNow(); +} + +void Q3DWindow::renderNow() +{ + if (!isExposed()) + return; + + static bool needsInit = true; + + d_ptr->m_updatePending = false; + + d_ptr->m_context->makeCurrent(this); + + if (needsInit) { +#if defined(Q_OS_MAC) + initializeOpenGLFunctions(); +#endif + initialize(); + needsInit = false; + } + + render(); + + d_ptr->m_context->swapBuffers(this); + + if (d_ptr->m_animating) + renderLater(); +} + +void Q3DWindow::setAnimating(bool animating) +{ + d_ptr->m_animating = animating; + + if (animating) + renderLater(); +} + +Q3DWindowPrivate::Q3DWindowPrivate(Q3DWindow *q) + : q_ptr(q), + m_updatePending(false), + m_animating(false), + m_context(new QOpenGLContext(q)) +{ +} + +Q3DWindowPrivate::~Q3DWindowPrivate() +{ +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dwindow.h b/src/datavis3d/engine/q3dwindow.h new file mode 100644 index 00000000..9958f7d9 --- /dev/null +++ b/src/datavis3d/engine/q3dwindow.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef Q3DWINDOW_H +#define Q3DWINDOW_H + +#include "QtDataVis3D/qdatavis3dglobal.h" + +#include <QWindow> +#include <QOpenGLFunctions> + +class QPainter; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Q3DWindowPrivate; + +class QTCOMMERCIALDATAVIS3D_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions +{ + Q_OBJECT +public: + explicit Q3DWindow(QWindow *parent = 0); + ~Q3DWindow(); + + virtual void render(); + + virtual void initialize(); + + void setAnimating(bool animating); + +public slots: + void renderLater(); + void renderNow(); + +protected: + bool event(QEvent *event); + void exposeEvent(QExposeEvent *event); + +private: + QScopedPointer<Q3DWindowPrivate> d_ptr; + + friend class Q3DBarsPrivate; + friend class Q3DBars; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dwindow_p.h b/src/datavis3d/engine/q3dwindow_p.h new file mode 100644 index 00000000..ef786fb3 --- /dev/null +++ b/src/datavis3d/engine/q3dwindow_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 Q3DWINDOW_p_H +#define Q3DWINDOW_p_H + +#include "qdatavis3dglobal.h" + +class QOpenGLContext; +class QOpenGLPaintDevice; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Q3DWindow; + +class Q3DWindowPrivate +{ +public: + Q3DWindowPrivate(Q3DWindow *q); + ~Q3DWindowPrivate(); + +public: + Q3DWindow *q_ptr; + + bool m_updatePending; + bool m_animating; + + QOpenGLContext *m_context; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/qdataitem.cpp b/src/datavis3d/engine/qdataitem.cpp new file mode 100644 index 00000000..14d6c85f --- /dev/null +++ b/src/datavis3d/engine/qdataitem.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** 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 "qdataitem.h" +#include "qdataitem_p.h" + +#include <QPoint> +#include <QString> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +QDataItem::QDataItem(float value, const QString &label) + : d_ptr(new QDataItemPrivate(this, value, label)) +{ + //qDebug("QDataItem"); +} + +QDataItem::~QDataItem() +{ + //qDebug("~QDataItem"); +} + +void QDataItem::setLabel(const QString &label, bool prepend) +{ + d_ptr->m_labelString = label; + d_ptr->m_prependLabel = prepend; +} + +void QDataItem::setValue(float value) +{ + d_ptr->m_value = value; +} + +void QDataItem::setValue(int value) +{ + d_ptr->m_value = (float)value; +} + +void QDataItem::setPosition(const QPointF &position) +{ + d_ptr->m_position = position; +} + +void QDataItem::setPosition(const QPoint &position) +{ + d_ptr->m_position = (QPointF)position; +} + +QDataItemPrivate::QDataItemPrivate(QDataItem *q, float value, const QString &label) + : q_ptr(q), + m_value(value), + m_labelString(label), + m_prependLabel(false), + m_translation(QVector3D(0, 0, 0)), + m_label(LabelItem()), + m_selectionLabel(LabelItem()) +{ +} + +QDataItemPrivate::~QDataItemPrivate() +{ +} + +void QDataItemPrivate::setTranslation(const QVector3D &translation) +{ + m_translation = translation; +} + +QVector3D QDataItemPrivate::translation() +{ + return m_translation; +} + +float QDataItemPrivate::value() +{ + return m_value; +} + +QString QDataItemPrivate::valueStr() +{ + QString strVal; + QString numStr; + numStr.setNum(m_value); + if (m_prependLabel) { + strVal.append(m_labelString); + strVal.append(QStringLiteral(" ")); + strVal.append(numStr); + } else { + strVal.append(numStr); + strVal.append(m_labelString); + } + return strVal; +} + +void QDataItemPrivate::setLabel(const LabelItem &label) +{ + m_label = label; +} + +LabelItem QDataItemPrivate::label() +{ + return m_label; +} + +void QDataItemPrivate::setSelectionLabel(const LabelItem &label) +{ + m_selectionLabel = label; +} + +LabelItem QDataItemPrivate::selectionLabel() +{ + return m_selectionLabel; +} + +QPointF QDataItemPrivate::position() +{ + return m_position; +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/qdataitem.h b/src/datavis3d/engine/qdataitem.h new file mode 100644 index 00000000..88d54faf --- /dev/null +++ b/src/datavis3d/engine/qdataitem.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QDATAITEM_H +#define QDATAITEM_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include <QScopedPointer> +#include <QString> + +class QPointF; +class QPoint; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataItemPrivate; + +class QTCOMMERCIALDATAVIS3D_EXPORT QDataItem +{ +public: + explicit QDataItem(float value = 0.0f, const QString &label = QString()); + ~QDataItem(); + + void setLabel(const QString &label, bool prepend = false); // label for value, unit for example + void setValue(float value); + void setValue(int value); + // Has no effect in Q3DBars + void setPosition(const QPointF &position); + void setPosition(const QPoint &position); + +private: + QScopedPointer<QDataItemPrivate> d_ptr; + friend class Q3DBars; + friend class Q3DBarsPrivate; + friend class Q3DMaps; + friend class Q3DMapsPrivate; + friend class QDataRowPrivate; + friend class Drawer; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/qdataitem_p.h b/src/datavis3d/engine/qdataitem_p.h new file mode 100644 index 00000000..f14fe175 --- /dev/null +++ b/src/datavis3d/engine/qdataitem_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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 QDATAITEM_P_H +#define QDATAITEM_P_H + +#include "qdatavis3dglobal.h" +#include "qdataitem.h" +#include "labelitem_p.h" +#include <QOpenGLFunctions> +#include <QSize> +#include <QString> +#include <QVector3D> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataItemPrivate +{ + public: + explicit QDataItemPrivate(QDataItem *q, float value = 0.0f, + const QString &label = QString()); + ~QDataItemPrivate(); + + // Position in 3D scene + void setTranslation(const QVector3D &translation); + QVector3D translation(); + // Value of bar + float value(); + // Value and label appended into a string. If label has prepend -flag set, append label and value + QString valueStr(); + // Label item (containing valueStr as texture) + void setLabel(const LabelItem &label); + LabelItem label(); + // Selection label item (containing specialar selection texture, if mode is activated) + void setSelectionLabel(const LabelItem &label); + LabelItem selectionLabel(); + QPointF position(); + + private: + QDataItem *q_ptr; + float m_value; + QString m_labelString; + bool m_prependLabel; + QVector3D m_translation; + LabelItem m_label; + LabelItem m_selectionLabel; + QPointF m_position; + friend class QDataItem; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/qdatarow.cpp b/src/datavis3d/engine/qdatarow.cpp new file mode 100644 index 00000000..f4a9e984 --- /dev/null +++ b/src/datavis3d/engine/qdatarow.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** 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 "qdatarow.h" +#include "qdatarow_p.h" +#include "qdataitem.h" +#include "qdataitem_p.h" + +#include <QString> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +QDataRow::QDataRow(const QString &label) + : d_ptr(new QDataRowPrivate(this, label)) +{ + //qDebug("QDataRow"); +} + +QDataRow::~QDataRow() +{ + //qDebug("~QDataRow"); +} + +void QDataRow::setLabel(const QString &label) +{ + d_ptr->m_label = label; +} + +void QDataRow::addItem(QDataItem *item) +{ + d_ptr->m_row.prepend(item); +} + +QDataRowPrivate::QDataRowPrivate(QDataRow *q, const QString &label) + : q_ptr(q), + m_label(label), + m_labelItem(LabelItem()) +{ +} + +QDataRowPrivate::~QDataRowPrivate() +{ + for (int itemCount = 0; itemCount < m_row.size(); itemCount++) + delete m_row.at(itemCount); + m_row.clear(); +} + +QVector<QDataItem*> QDataRowPrivate::row() +{ + return m_row; +} + +void QDataRowPrivate::clear() +{ + m_row.clear(); +} + +QDataItem *QDataRowPrivate::getItem(int itemIndex) +{ + QDataItem *item = NULL; + if (m_row.size() > itemIndex) + item = m_row.at(itemIndex); + return item; +} + +void QDataRowPrivate::verifySize(int size) +{ + if (size > m_row.size()) { + // QVector's resize doesn't delete data contained in it + // Delete contents of items to be removed + int nbrToBeRemoved = m_row.size() - size; + for (int itemCount = 0; itemCount < nbrToBeRemoved; itemCount++) { + int itemToBeRemoved = m_row.size() - itemCount - 1; // -1 to compensate index 0 + delete m_row.at(itemToBeRemoved); + } + // Resize vector + m_row.resize(size); + } else if (size < m_row.size()) { + qCritical("Check your sample space size! Your row is too short."); + } +} + +QPair<GLfloat, GLfloat> QDataRowPrivate::limitValues() +{ + QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); + for (int i = 0; i < m_row.size(); i++) { + QDataItem *item = m_row.at(i); + float itemValue = item->d_ptr->value(); + if (limits.second < itemValue) + limits.second = itemValue; + if (limits.first > itemValue) + limits.first = itemValue; + } + return limits; +} + +QString QDataRowPrivate::label() +{ + return m_label; +} + +void QDataRowPrivate::setLabelItem(const LabelItem &item) +{ + m_labelItem = item; +} + +LabelItem QDataRowPrivate::labelItem() +{ + return m_labelItem; +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/qdatarow.h b/src/datavis3d/engine/qdatarow.h new file mode 100644 index 00000000..766ae541 --- /dev/null +++ b/src/datavis3d/engine/qdatarow.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$ +** +****************************************************************************/ + +#ifndef QDATAROW_H +#define QDATAROW_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include <QScopedPointer> +#include <QString> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataRowPrivate; +class QDataItem; + +class QTCOMMERCIALDATAVIS3D_EXPORT QDataRow +{ +public: + explicit QDataRow(const QString &label = QString()); + ~QDataRow(); + + void setLabel(const QString &label); // label for value, unit for example + void addItem(QDataItem *item); + +private: + QScopedPointer<QDataRowPrivate> d_ptr; + friend class Q3DBars; + friend class Q3DBarsPrivate; + friend class Q3DMaps; + friend class Q3DMapsPrivate; + friend class QDataSetPrivate; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/qdatarow_p.h b/src/datavis3d/engine/qdatarow_p.h new file mode 100644 index 00000000..3a1adeee --- /dev/null +++ b/src/datavis3d/engine/qdatarow_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 QDATAROW_P_H +#define QDATAROW_P_H + +#include "qdatavis3dglobal.h" +#include "qdatarow.h" +#include "labelitem_p.h" +#include <QVector> +#include <QString> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataItem; + +class QDataRowPrivate +{ +public: + explicit QDataRowPrivate(QDataRow *q, const QString &label = QString()); + ~QDataRowPrivate(); + + QVector<QDataItem*> row(); + // Clears vector, doesn't delete items + void clear(); + QDataItem *getItem(int itemIndex); + void verifySize(int size); + QPair<GLfloat, GLfloat> limitValues(); + QString label(); + void setLabelItem(const LabelItem &item); + LabelItem labelItem(); + +private: + QDataRow *q_ptr; + QVector<QDataItem*> m_row; + QString m_label; + LabelItem m_labelItem; + friend class QDataRow; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/qdataset.cpp b/src/datavis3d/engine/qdataset.cpp new file mode 100644 index 00000000..5af920d2 --- /dev/null +++ b/src/datavis3d/engine/qdataset.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** 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 "qdataset.h" +#include "qdataset_p.h" +#include "qdatarow.h" +#include "qdatarow_p.h" + +#include <QPoint> +#include <QString> + +//#include <QDebug> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +const QString empty; + +QDataSet::QDataSet() + : d_ptr(new QDataSetPrivate(this)) +{ + //qDebug("QDataSet"); +} + +QDataSet::~QDataSet() +{ + //qDebug("~QDataSet"); +} + +void QDataSet::setLabels(const QString &xAxis, + const QString &zAxis, + const QString &yAxis, + const QVector<QString> &labelsRow, + const QVector<QString> &labelsColumn) +{ + // skip empty labels, keep the previous ones + if (xAxis != empty && d_ptr->m_xAxis != xAxis) { + d_ptr->m_xAxis = xAxis; + // Generate axis label texture + if (d_ptr->m_drawer) + d_ptr->m_drawer->generateLabelItem(&d_ptr->m_xAxisItem, xAxis); + } + if (zAxis != empty && d_ptr->m_zAxis != zAxis) { + d_ptr->m_zAxis = zAxis; + // Generate axis label texture + if (d_ptr->m_drawer) + d_ptr->m_drawer->generateLabelItem(&d_ptr->m_zAxisItem, zAxis); + } + if (yAxis != empty && d_ptr->m_yAxis != yAxis) { + d_ptr->m_yAxis = yAxis; + // Generate axis label texture + if (d_ptr->m_drawer) + d_ptr->m_drawer->generateLabelItem(&d_ptr->m_yAxisItem, yAxis); + } + d_ptr->m_labelsRow = labelsRow; + d_ptr->m_labelsColumn = labelsColumn; + // Generate row and column label textures + if (d_ptr->m_drawer) { + for (int itemCount = 0; itemCount < labelsColumn.size(); itemCount++) { + d_ptr->m_labelItemsColumn.append(LabelItem()); + d_ptr->m_drawer->generateLabelItem(&d_ptr->m_labelItemsColumn[itemCount], + labelsColumn.at(itemCount)); + } + for (int itemCount = 0; itemCount < labelsRow.size(); itemCount++) { + d_ptr->m_labelItemsRow.append(LabelItem()); + d_ptr->m_drawer->generateLabelItem(&d_ptr->m_labelItemsRow[itemCount], + labelsRow.at(itemCount)); + } + } +} + +void QDataSet::addRow(QDataRow *row) +{ + d_ptr->m_set.prepend(row); +} + +QDataSetPrivate::QDataSetPrivate(QDataSet *q) + : q_ptr(q), + m_set(QVector<QDataRow*>()), + m_xAxis(QString()), + m_zAxis(QString()), + m_yAxis(QString()), + m_labelsRow(QVector<QString>()), + m_labelsColumn(QVector<QString>()), + m_xAxisItem(LabelItem()), + m_zAxisItem(LabelItem()), + m_yAxisItem(LabelItem()), + m_labelItemsRow(QVector<LabelItem>()), + m_labelItemsColumn(QVector<LabelItem>()), + m_drawer(0) +{ +} + +QDataSetPrivate::~QDataSetPrivate() +{ + for (int itemCount = 0; itemCount < m_set.size(); itemCount++) + delete m_set.at(itemCount); + m_set.clear(); + // Delete axis textures + GLuint textureid = m_xAxisItem.textureId(); + if (textureid) + glDeleteTextures(1, &textureid); + textureid = m_zAxisItem.textureId(); + if (textureid) + glDeleteTextures(1, &textureid); + textureid = m_yAxisItem.textureId(); + if (textureid) + glDeleteTextures(1, &textureid); + // Delete row and column textures + for (int itemCount = 0; itemCount < m_labelItemsColumn.size(); itemCount++) { + LabelItem item = m_labelItemsColumn.at(itemCount); + textureid = item.textureId(); + if (textureid) + glDeleteTextures(1, &textureid); + } + for (int itemCount = 0; itemCount < m_labelItemsRow.size(); itemCount++) { + LabelItem item = m_labelItemsRow.at(itemCount); + textureid = item.textureId(); + if (textureid) + glDeleteTextures(1, &textureid); + } +} + +void QDataSetPrivate::setDrawer(Drawer *drawer) +{ + m_drawer = drawer; + connect(m_drawer, SIGNAL(drawerChanged()), this, SLOT(updateTextures())); + updateTextures(); +} + +QVector<QDataRow*> QDataSetPrivate::set() +{ + return m_set; +} + +QDataRow *QDataSetPrivate::getRow(int rowIndex) +{ + QDataRow *row = NULL; + if (m_set.size() > rowIndex) + row = m_set.at(rowIndex); + return row; +} + +QVector<QString> QDataSetPrivate::rowLabels() +{ + return m_labelsRow; +} + +QVector<QString> QDataSetPrivate::columnLabels() +{ + return m_labelsColumn; +} + +QVector<LabelItem> QDataSetPrivate::rowLabelItems() +{ + return m_labelItemsRow; +} + +QVector<LabelItem> QDataSetPrivate::columnLabelItems() +{ + return m_labelItemsColumn; +} + +void QDataSetPrivate::axisLabels(QString *xAxis, QString *zAxis, QString *yAxis) +{ + *xAxis = m_xAxis; + *zAxis = m_zAxis; + *yAxis = m_yAxis; +} + +void QDataSetPrivate::axisLabelItems(LabelItem *xAxisItem, LabelItem *zAxisItem, + LabelItem *yAxisItem) +{ + *xAxisItem = m_xAxisItem; + *zAxisItem = m_zAxisItem; + *yAxisItem = m_yAxisItem; +} + +void QDataSetPrivate::verifySize(int colSize, int rowSize) +{ + // First verify columns + // QVector's resize doesn't delete data contained in it + // Delete contents of rows to be removed + if (colSize < m_set.size()) { + int nbrToBeRemoved = m_set.size() - colSize; + for (int rowCount = 0; rowCount < nbrToBeRemoved; rowCount++) { + int rowToBeRemoved = m_set.size() - rowCount - 1; // -1 to compensate index 0 + delete m_set.at(rowToBeRemoved); + } + // Resize vector + m_set.resize(colSize); + } + // Then verify each row left + if (rowSize) { + for (int i = 0; i < m_set.size(); i++) + m_set.at(i)->d_ptr->verifySize(rowSize); + } +} + +QPair<GLfloat, GLfloat> QDataSetPrivate::limitValues() +{ + QPair<GLfloat, GLfloat> limits = qMakePair(100.0f, -100.0f); + QPair<GLfloat, GLfloat> rowLimits; + for (int i = 0; i < m_set.size(); i++) { + rowLimits = m_set.at(i)->d_ptr->limitValues(); + if (limits.second < rowLimits.second) + limits.second = rowLimits.second; + if (limits.first > rowLimits.first) + limits.first = rowLimits.first; + } + return limits; +} + +void QDataSetPrivate::updateTextures() +{ + if (m_xAxis != empty) + m_drawer->generateLabelItem(&m_xAxisItem, m_xAxis); + if (m_zAxis != empty) + m_drawer->generateLabelItem(&m_zAxisItem, m_zAxis); + if (m_yAxis != empty) + m_drawer->generateLabelItem(&m_yAxisItem, m_yAxis); + for (int itemCount = 0; itemCount < m_labelsColumn.size(); itemCount++) { + if (m_labelItemsColumn.size() < itemCount + 1) + m_labelItemsColumn.append(LabelItem()); + m_drawer->generateLabelItem(&m_labelItemsColumn[itemCount], m_labelsColumn.at(itemCount)); + } + for (int itemCount = 0; itemCount < m_labelsRow.size(); itemCount++) { + if (m_labelItemsRow.size() < itemCount + 1) + m_labelItemsRow.append(LabelItem()); + m_drawer->generateLabelItem(&m_labelItemsRow[itemCount], m_labelsRow.at(itemCount)); + } +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/qdataset.h b/src/datavis3d/engine/qdataset.h new file mode 100644 index 00000000..118d3df9 --- /dev/null +++ b/src/datavis3d/engine/qdataset.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QDATASET_H +#define QDATASET_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include "qdataitem.h" +#include "qdatarow.h" + +#include <QScopedPointer> +#include <QVector> +#include <QString> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataSetPrivate; + +class QTCOMMERCIALDATAVIS3D_EXPORT QDataSet +{ +public: + explicit QDataSet(); + ~QDataSet(); + + void setLabels(const QString &xAxis = QString(), + const QString &zAxis = QString(), + const QString &yAxis = QString(), + const QVector<QString> &labelsRow = QVector<QString>(), + const QVector<QString> &labelsColumn = QVector<QString>()); + void addRow(QDataRow *row); + +private: + QScopedPointer<QDataSetPrivate> d_ptr; + friend class Q3DBars; + friend class Q3DBarsPrivate; + friend class Q3DMaps; + friend class Q3DMapsPrivate; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/qdataset_p.h b/src/datavis3d/engine/qdataset_p.h new file mode 100644 index 00000000..90dc5329 --- /dev/null +++ b/src/datavis3d/engine/qdataset_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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 QDATASET_P_H +#define QDATASET_P_H + +#include "qdatavis3dglobal.h" +#include "qdataset.h" +#include "drawer_p.h" +#include "labelitem_p.h" +#include <QVector> +#include <QString> + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class QDataSetPrivate : public QObject +{ + Q_OBJECT + +public: + explicit QDataSetPrivate(QDataSet *q); + ~QDataSetPrivate(); + + void setDrawer(Drawer *drawer); + QVector<QDataRow*> set(); + QDataRow *getRow(int rowIndex); + QVector<QString> rowLabels(); + QVector<QString> columnLabels(); + QVector<LabelItem> rowLabelItems(); + QVector<LabelItem> columnLabelItems(); + void axisLabels(QString *xAxis, QString *zAxis, QString *yAxis); + void axisLabelItems(LabelItem *xAxisItem, LabelItem *zAxisItem, LabelItem *yAxisItem); + void verifySize(int colSize, int rowSize = 0); // If rowSize is 0, don't verify rows + // first = min, second = max + QPair<GLfloat, GLfloat> limitValues(); + +public Q_SLOTS: + void updateTextures(); + +private: + QDataSet *q_ptr; + QVector<QDataRow*> m_set; + QString m_xAxis; + QString m_zAxis; + QString m_yAxis; + QVector<QString> m_labelsRow; + QVector<QString> m_labelsColumn; + LabelItem m_xAxisItem; + LabelItem m_zAxisItem; + LabelItem m_yAxisItem; + QVector<LabelItem> m_labelItemsRow; + QVector<LabelItem> m_labelItemsColumn; + Drawer *m_drawer; + friend class QDataSet; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/shaders/fragmentDepthTest b/src/datavis3d/engine/shaders/fragmentDepthTest new file mode 100644 index 00000000..d6c502e1 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentDepthTest @@ -0,0 +1,7 @@ +uniform sampler2D textureSampler; + +varying highp vec2 UV; + +void main() { + gl_FragColor = texture2D(textureSampler, UV); +} diff --git a/src/datavis3d/engine/shaders/fragmentShader b/src/datavis3d/engine/shaders/fragmentShader new file mode 100644 index 00000000..5bf9c654 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShader @@ -0,0 +1,36 @@ +#version 120 + +varying highp vec2 UV; +varying highp vec2 coords_mdl; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform highp vec3 lightPosition_wrld; +uniform highp vec3 color_mdl; +uniform highp float lightStrength; +uniform highp float ambientStrength; + +void main() { + highp vec3 materialDiffuseColor = color_mdl.rgb; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + + materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; + gl_FragColor.a = 1.0; +} + diff --git a/src/datavis3d/engine/shaders/fragmentShaderAmbient b/src/datavis3d/engine/shaders/fragmentShaderAmbient new file mode 100644 index 00000000..88f850f3 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShaderAmbient @@ -0,0 +1,32 @@ +#version 120 + +uniform highp vec3 lightPosition_wrld; +uniform highp vec3 color_mdl; + +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +void main() { + highp vec3 lightColor = vec3(1.0, 1.0, 1.0); + highp float lightPower = 10.0; + highp vec3 materialAmbientColor = vec3(0.5, 0.5, 0.5) * color_mdl; + highp vec3 materialSpecularColor = vec3(0.3, 0.3, 0.3) * color_mdl; + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + gl_FragColor.rgb = + materialAmbientColor + + materialSpecularColor * lightColor * lightPower * pow(cosAlpha, 5) / (distance * distance); + gl_FragColor.a = 1.0; +} + diff --git a/src/datavis3d/engine/shaders/fragmentShaderColorOnY b/src/datavis3d/engine/shaders/fragmentShaderColorOnY new file mode 100644 index 00000000..ee57e8e5 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShaderColorOnY @@ -0,0 +1,33 @@ +#version 120 + +uniform highp vec3 lightPosition_wrld; +uniform highp vec3 color_mdl; +uniform highp float lightStrength; +uniform highp float ambientStrength; + +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec2 coords_mdl; + +void main() { + highp vec3 materialDiffuseColor = vec3(coords_mdl.y * color_mdl.x, coords_mdl.y * color_mdl.y, coords_mdl.y * color_mdl.z); + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp float distance = length(lightPosition_wrld - position_wrld); + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / (distance * distance) + + materialSpecularColor * lightStrength * pow(cosAlpha, 5) / (distance * distance); +} + diff --git a/src/datavis3d/engine/shaders/fragmentShaderDepth b/src/datavis3d/engine/shaders/fragmentShaderDepth new file mode 100644 index 00000000..5cfd4b10 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShaderDepth @@ -0,0 +1,3 @@ +void main() { + gl_FragDepth = gl_FragCoord.z; +} diff --git a/src/datavis3d/engine/shaders/fragmentShaderLabel b/src/datavis3d/engine/shaders/fragmentShaderLabel new file mode 100644 index 00000000..86021410 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShaderLabel @@ -0,0 +1,8 @@ +uniform sampler2D textureSampler; + +varying highp vec2 UV; + +void main() { + gl_FragColor = texture2D(textureSampler, UV); +} + diff --git a/src/datavis3d/engine/shaders/fragmentShaderSelection b/src/datavis3d/engine/shaders/fragmentShaderSelection new file mode 100644 index 00000000..66370224 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShaderSelection @@ -0,0 +1,7 @@ +uniform highp vec3 color_mdl; +//uniform highp vec4 color_mdl; +void main() { + gl_FragColor.rgb = color_mdl; + //gl_FragColor = color_mdl; +} + diff --git a/src/datavis3d/engine/shaders/fragmentShaderTexture b/src/datavis3d/engine/shaders/fragmentShaderTexture new file mode 100644 index 00000000..d271f985 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShaderTexture @@ -0,0 +1,35 @@ +#version 120 + +uniform highp vec3 lightPosition_wrld; +uniform highp vec3 color_mdl; +uniform highp float lightStrength; +uniform highp float ambientStrength; +uniform sampler2D textureSampler; + +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +void main() { + highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp float distance = length(lightPosition_wrld - position_wrld); + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance + + materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; + gl_FragColor.a = 1.0; +} + diff --git a/src/datavis3d/engine/shaders/fragmentShadow b/src/datavis3d/engine/shaders/fragmentShadow new file mode 100644 index 00000000..3a6ffc5a --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShadow @@ -0,0 +1,140 @@ +#version 120 +//#version 130 // use with version 1 + +uniform highp float lightStrength; +uniform highp float ambientStrength; +uniform highp float shadowQuality; +uniform highp sampler2D textureSampler; +uniform highp sampler2DShadow shadowMap; // use with version 2 +//uniform highp sampler2D shadowMap; // use with version 1 + +varying highp vec4 shadowCoord; +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790)); + +/*float random(vec3 seed, int i) { + vec4 seed4 = vec4(seed, i); + float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673)); + return fract(sin(dot_product) * 43758.5453); +}*/ + +// Version 1: Causes self-shadowing, but shadows are smooth +/*void main() { + float shadowFactor = 1.0; // default to '1' meaning "no shadow" + //float epsilon = 0.01; // increase value to remove little artifacts + vec4 shadCoordsPD = shadowCoord; + shadCoordsPD.z += 0.005; + shadCoordsPD /= shadowCoord.w; + if (shadowCoord.w <= 0.0) { // ignore negative projection + shadowFactor = 1.0; + } else if (shadCoordsPD.x < 0.0 || shadCoordsPD.y < 0.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else if (shadCoordsPD.x >= 1.0 || shadCoordsPD.y >= 1.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else { + // This does not work perfectly. It causes self-shadowing, which we should get rid of. + // Requires at least #version 130 + float shadow = 0.0; + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(0, 0)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(-1, 1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(1, 1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(-1, -1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(1, -1)); + shadow *= 0.2; + shadowFactor = shadow; + //float shadow = texture2D(shadowMap, shadCoordsPD.xy).x; + //if (shadow + epsilon < shadCoordsPD.z) { + // shadowFactor = 0.0; + //} + } + // shadow is dark gray, other parts light gray + //gl_FragColor = vec4(0.8, 0.8, 0.8, 1.0) * shadowFactor;// + vec4(0.2, 0.2, 0.2, 1.0); + // simple shadows with no effect from light + //gl_FragColor = texture2D(textureSampler, UV) * shadowFactor; + + // shadows including effects from light + highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(0.2, 0.2, 0.2); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + // Shadow strength can be adjusted by using pow(shadowFactor, strength), but it causes self-shadowing issues that need to be solved + gl_FragColor.rgb = + shadowFactor * (materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta + + materialSpecularColor * lightStrength * pow(cosAlpha, 10)); + gl_FragColor.a = 1.0; +}*/ + +// Version 2: Shadows are a bit rugged (may be fixed with poisson disk?) +void main() { + highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(0.2, 0.2, 0.2); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + highp float bias = 0.005 * tan(acos(cosTheta)); + bias = clamp(bias, 0.0, 0.01); + + vec4 shadCoords = shadowCoord; + shadCoords.z -= bias; + // adjust shadow strength by increasing the multiplier and lowering the addition (their sum must be 1) + // direct method; needs large shadow texture to look good + //highp float visibility = 0.75 * shadow2DProj(shadowMap, shadCoords).r + 0.25; + // poisson disk sampling; smoothes edges + highp float visibility = 0.2; + for (int i = 0; i < 15; i++) { + vec4 shadCoordsPD = shadCoords; + shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality; + shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality; + visibility += 0.05 * shadow2DProj(shadowMap, shadCoordsPD).r; + } + // stratified poisson; produces noise but hides pixel edges well + /*for (int i = 0; i < 15; i++) { + vec4 shadCoordsPD = shadCoords; + int index = int(16.0 * random(gl_FragCoord.xyy, i)); + shadCoordsPD.xy += poissonDisk[index] / 150.0; + visibility += 0.05 * shadow2DProj(shadowMap, shadCoordsPD).r; + } + */ + + gl_FragColor.rgb = + visibility * (materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta + + materialSpecularColor * lightStrength * pow(cosAlpha, 10)); + gl_FragColor.a = 1.0; +} diff --git a/src/datavis3d/engine/shaders/fragmentShadowNoTex b/src/datavis3d/engine/shaders/fragmentShadowNoTex new file mode 100644 index 00000000..a08b6b40 --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShadowNoTex @@ -0,0 +1,147 @@ +#version 120 +//#version 130 // use with version 1 + +uniform highp float lightStrength; +uniform highp float ambientStrength; +uniform highp float shadowQuality; +uniform highp vec3 color_mdl; +uniform highp sampler2DShadow shadowMap; // use with version 2 +//uniform highp sampler2D shadowMap; // use with version 1 + +varying highp vec4 shadowCoord; +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790)); + +/*const highp vec2 poissonDisk[16] = vec2[](vec2(-0.25, -0.25), + vec2(0.25, -0.25), + vec2(-0.25, 0.25), + vec2(0.25, 0.25), + vec2(-0.5, -0.5), + vec2(0.5, -0.5), + vec2(-0.5, 0.5), + vec2(0.5, 0.5), + vec2(-0.75, -0.75), + vec2(0.75, -0.75), + vec2(-0.75, 0.75), + vec2(0.75, 0.75), + vec2(-1.0, -1.0), + vec2(1.0, -1.0), + vec2(-1.0, 1.0), + vec2(1.0, 1.0));*/ + +/*float random(vec3 seed, int i) { + vec4 seed4 = vec4(seed, i); + float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673)); + return fract(sin(dot_product) * 43758.5453); +}*/ + +// Version 1: Causes self-shadowing, but shadows are smooth +/*void main() { + float shadowFactor = 1.0; // default to '1' meaning "no shadow" + vec4 shadCoordsPD = shadowCoord; + shadCoordsPD.z += 0.005; + shadCoordsPD /= shadowCoord.w; + if (shadowCoord.w <= 0.0) { // ignore negative projection + shadowFactor = 1.0; + } else if (shadCoordsPD.x < 0.0 || shadCoordsPD.y < 0.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else if (shadCoordsPD.x >= 1.0 || shadCoordsPD.y >= 1.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else { + // This does not work perfectly. It causes self-shadowing, which we should get rid of. + // Requires at least #version 130 + float shadow = 0.0; + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(0, 0)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(-1, 1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(1, 1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(-1, -1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(1, -1)); + shadow *= 0.2; + shadowFactor = shadow; + } + + highp vec3 materialDiffuseColor = color_mdl.rgb; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + // Shadow strength can be adjusted by using pow(shadowFactor, strength), but it causes self-shadowing issues that need to be solved + gl_FragColor.rgb = + shadowFactor * (materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta + + materialSpecularColor * lightStrength * pow(cosAlpha, 20)); + gl_FragColor.a = 1.0; +}*/ + +// Version 2: Shadows are a bit rugged (may be fixed with poisson disk?) +void main() { + highp vec3 materialDiffuseColor = color_mdl.rgb; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + highp float bias = 0.005 * tan(acos(cosTheta)); + bias = clamp(bias, 0.0, 0.01); + + vec4 shadCoords = shadowCoord; + shadCoords.z -= bias; + // adjust shadow strength by increasing the multiplier and lowering the addition (their sum must be 1) + // direct method; needs large shadow texture to look good + //highp float visibility = 0.75 * shadow2DProj(shadowMap, shadCoords).r + 0.25; + // poisson disk sampling; smoothes edges + highp float visibility = 0.2; + for (int i = 0; i < 15; i++) { + vec4 shadCoordsPD = shadCoords; + shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality; + shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality; + visibility += 0.05 * shadow2DProj(shadowMap, shadCoordsPD).r; + } + // stratified poisson; produces noise but hides pixel edges well + /*for (int i = 0; i < 15; i++) { + vec4 shadCoordsPD = shadCoords; + int index = int(16.0 * random(gl_FragCoord.xyy, i)); + shadCoordsPD.xy += poissonDisk[index] / 150.0; + visibility += 0.05 * shadow2DProj(shadowMap, shadCoordsPD).r; + } + */ + + gl_FragColor.rgb = + visibility * (materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta + + materialSpecularColor * lightStrength * pow(cosAlpha, 10)); + gl_FragColor.a = 1.0; +} diff --git a/src/datavis3d/engine/shaders/fragmentShadowNoTexColorOnY b/src/datavis3d/engine/shaders/fragmentShadowNoTexColorOnY new file mode 100644 index 00000000..d208c5fd --- /dev/null +++ b/src/datavis3d/engine/shaders/fragmentShadowNoTexColorOnY @@ -0,0 +1,128 @@ +#version 120 +//#version 130 // use with version 1 + +uniform highp float lightStrength; +uniform highp float ambientStrength; +uniform highp float shadowQuality; +uniform highp vec3 color_mdl; +uniform highp sampler2DShadow shadowMap; // use with version 2 +//uniform highp sampler2D shadowMap; // use with version 1 + +varying highp vec4 shadowCoord; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec2 coords_mdl; + +const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790)); + +/*float random(vec3 seed, int i) { + vec4 seed4 = vec4(seed, i); + float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673)); + return fract(sin(dot_product) * 43758.5453); +}*/ + +// Version 1: Causes self-shadowing, but shadows are smooth +/*void main() { + float shadowFactor = 1.0; // default to '1' meaning "no shadow" + vec4 shadCoordsPD = shadowCoord; + shadCoordsPD.z += 0.005; + shadCoordsPD /= shadowCoord.w; + if (shadowCoord.w <= 0.0) { // ignore negative projection + shadowFactor = 1.0; + } else if (shadCoordsPD.x < 0.0 || shadCoordsPD.y < 0.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else if (shadCoordsPD.x >= 1.0 || shadCoordsPD.y >= 1.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else { + // This does not work perfectly. It causes self-shadowing, which we should get rid of. + // Requires at least #version 130 + float shadow = 0.0; + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(0, 0)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(-1, 1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(1, 1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(-1, -1)); + shadow += textureProjOffset(shadowMap, shadCoordsPD, ivec2(1, -1)); + shadow *= 0.2; + shadowFactor = shadow; + } + + highp vec3 materialDiffuseColor = vec3(coords_mdl.y * color_mdl.x, coords_mdl.y * color_mdl.y, coords_mdl.y * color_mdl.z); + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + // Shadow strength can be adjusted by using pow(shadowFactor, strength), but it causes self-shadowing issues that need to be solved + gl_FragColor.rgb = + shadowFactor * (materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta + + materialSpecularColor * lightStrength * pow(cosAlpha, 20)); + gl_FragColor.a = 1.0; +}*/ + +// Version 2: Shadows are a bit rugged (may be fixed with poisson disk?) +void main() { + highp vec3 materialDiffuseColor = vec3(coords_mdl.y * color_mdl.x, coords_mdl.y * color_mdl.y, coords_mdl.y * color_mdl.z); + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = clamp(dot(n, l), 0.0, 1.0); + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); + + highp float bias = 0.005 * tan(acos(cosTheta)); + bias = clamp(bias, 0.0, 0.01); + + vec4 shadCoords = shadowCoord; + shadCoords.z -= bias; + // adjust shadow strength by increasing the multiplier and lowering the addition (their sum must be 1) + // direct method; needs large shadow texture to look good + //highp float visibility = 0.75 * shadow2DProj(shadowMap, shadCoords).r + 0.25; + // poisson disk sampling; smoothes edges + highp float visibility = 0.2; + for (int i = 0; i < 15; i++) { + vec4 shadCoordsPD = shadCoords; + shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality; + shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality; + visibility += 0.05 * shadow2DProj(shadowMap, shadCoordsPD).r; + } + /*for (int i = 0; i < 15; i++) { + vec4 shadCoordsPD = shadCoords; + int index = int(16.0 * random(gl_FragCoord.xyy, i)); + shadCoordsPD.xy += poissonDisk[index] / 150.0; + visibility += 0.05 * shadow2DProj(shadowMap, shadCoordsPD).r; + }*/ + + gl_FragColor.rgb = + visibility * (materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta + + materialSpecularColor * lightStrength * pow(cosAlpha, 10)); + gl_FragColor.a = 1.0; +} diff --git a/src/datavis3d/engine/shaders/vertexDepthTest b/src/datavis3d/engine/shaders/vertexDepthTest new file mode 100644 index 00000000..d62f1aa7 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexDepthTest @@ -0,0 +1,9 @@ +attribute highp vec3 vertexPosition_mdl; + +varying highp vec2 UV; + +void main() { + gl_Position = vec4(vertexPosition_mdl, 1.0); + UV = (vertexPosition_mdl.xy + vec2(1.0, 1.0)) / 2.0; +} + diff --git a/src/datavis3d/engine/shaders/vertexShader b/src/datavis3d/engine/shaders/vertexShader new file mode 100644 index 00000000..14f77773 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexShader @@ -0,0 +1,28 @@ +#version 120 + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; +attribute highp vec3 vertexNormal_mdl; + +uniform highp mat4 MVP; +uniform highp mat4 V; +uniform highp mat4 M; +uniform highp mat4 itM; +uniform highp vec3 lightPosition_wrld; + +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec2 coords_mdl; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + coords_mdl = vertexPosition_mdl.xy; + position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; + vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; + normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; +} diff --git a/src/datavis3d/engine/shaders/vertexShaderDepth b/src/datavis3d/engine/shaders/vertexShaderDepth new file mode 100644 index 00000000..9fe5a193 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexShaderDepth @@ -0,0 +1,8 @@ +uniform highp mat4 MVP; + +attribute highp vec3 vertexPosition_mdl; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); +} + diff --git a/src/datavis3d/engine/shaders/vertexShaderLabel b/src/datavis3d/engine/shaders/vertexShaderLabel new file mode 100644 index 00000000..b4debe53 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexShaderLabel @@ -0,0 +1,11 @@ +uniform highp mat4 MVP; + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; + +varying highp vec2 UV; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + UV = vertexUV; +} diff --git a/src/datavis3d/engine/shaders/vertexShaderSelection b/src/datavis3d/engine/shaders/vertexShaderSelection new file mode 100644 index 00000000..64d17e15 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexShaderSelection @@ -0,0 +1,7 @@ +uniform highp mat4 MVP; + +attribute highp vec3 vertexPosition_mdl; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); +} diff --git a/src/datavis3d/engine/shaders/vertexShaderTexture b/src/datavis3d/engine/shaders/vertexShaderTexture new file mode 100644 index 00000000..01f922e0 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexShaderTexture @@ -0,0 +1,26 @@ +uniform highp mat4 MVP; +uniform highp mat4 V; +uniform highp mat4 M; +uniform highp mat4 itM; +uniform highp vec3 lightPosition_wrld; + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; +attribute highp vec3 vertexNormal_mdl; + +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; + vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; + lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; + normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + UV = vertexUV; +} diff --git a/src/datavis3d/engine/shaders/vertexShadow b/src/datavis3d/engine/shaders/vertexShadow new file mode 100644 index 00000000..e29a8a30 --- /dev/null +++ b/src/datavis3d/engine/shaders/vertexShadow @@ -0,0 +1,37 @@ +#version 120 + +uniform highp mat4 MVP; +uniform highp mat4 V; +uniform highp mat4 M; +uniform highp mat4 itM; +uniform highp mat4 depthMVP; +uniform highp vec3 lightPosition_wrld; + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec3 vertexNormal_mdl; +attribute highp vec2 vertexUV; + +varying highp vec2 UV; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; +varying highp vec4 shadowCoord; +varying highp vec2 coords_mdl; + +const highp mat4 bias = mat4(0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0); + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + coords_mdl = vertexPosition_mdl.xy; + shadowCoord = bias * depthMVP * vec4(vertexPosition_mdl, 1.0); + position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; + vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; + eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; + lightDirection_cmr = (V * vec4(lightPosition_wrld, 0.0)).xyz; + normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; + UV = vertexUV; +} diff --git a/src/datavis3d/engine/theme.cpp b/src/datavis3d/engine/theme.cpp new file mode 100644 index 00000000..a9032e25 --- /dev/null +++ b/src/datavis3d/engine/theme.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** +** +** 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 "theme_p.h" + +#ifdef Q_OS_WIN +#include <windows.h> +#include <stdio.h> +#endif + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +Theme::Theme() + : m_baseColor(QColor(Qt::gray)), + m_heightColor(QColor(Qt::black)), + m_depthColor(QColor(Qt::black)), + m_backgroundColor(QColor(Qt::gray)), + m_windowColor(QColor(Qt::gray)), + m_textColor(QColor(Qt::white)), + m_textBackgroundColor(QColor(0x00, 0x00, 0x00, 0x80)), + m_gridLine(QColor(Qt::black)), + m_highlightBarColor(QColor(Qt::red)), + m_highlightRowColor(QColor(Qt::darkRed)), + m_highlightColumnColor(QColor(Qt::darkMagenta)), + m_lightStrength(4.0f), + m_ambientStrength(0.3f), + m_highlightLightStrength(8.0f), + m_uniformColor(true) +{ +} + +Theme::~Theme() +{ +} + +void Theme::useTheme(ColorTheme theme) +{ + switch (theme) { + case ThemeSystem: { +#ifdef Q_OS_WIN + DWORD colorHighlight; + colorHighlight = GetSysColor(COLOR_HIGHLIGHT); + m_baseColor = QColor(GetRValue(colorHighlight), + GetGValue(colorHighlight), + GetBValue(colorHighlight)); + DWORD colorWindowFrame; + colorWindowFrame = GetSysColor(COLOR_WINDOWFRAME); + m_heightColor = QColor(GetRValue(colorWindowFrame), + GetGValue(colorWindowFrame), + GetBValue(colorWindowFrame)); + m_depthColor = QColor(Qt::black); + DWORD colorWindow; + colorWindow = GetSysColor(COLOR_WINDOW); + m_backgroundColor = QColor(GetRValue(colorWindow), + GetGValue(colorWindow), + GetBValue(colorWindow)); + m_windowColor = QColor(GetRValue(colorWindow), + GetGValue(colorWindow), + GetBValue(colorWindow)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0xe2e2e2)); + m_highlightRowColor = QColor(QRgb(0xf2f2f2)); + m_highlightColumnColor = QColor(QRgb(0xf2f2f2)); + m_lightStrength = 4.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 6.0f; + m_uniformColor = true; +#elif defined(Q_OS_LINUX) + m_baseColor = QColor(QRgb(0x60a6e6)); + m_heightColor = QColor(QRgb(0xfc5751)); + m_depthColor = QColor(QRgb(0x92ca66)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0xeba85f)); + m_highlightRowColor = QColor(QRgb(0xfc5751)); + m_highlightColumnColor = QColor(QRgb(0xfc5751)); + m_lightStrength = 4.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 6.0f; + m_uniformColor = true; +#elif defined(Q_OS_MAC) + m_baseColor = QColor(QRgb(0x60a6e6)); + m_heightColor = QColor(QRgb(0xfc5751)); + m_depthColor = QColor(QRgb(0x92ca66)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0xeba85f)); + m_highlightRowColor = QColor(QRgb(0xfc5751)); + m_highlightColumnColor = QColor(QRgb(0xfc5751)); + m_lightStrength = 4.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 6.0f; + m_uniformColor = true; +#else + m_baseColor = QColor(QRgb(0x60a6e6)); + m_heightColor = QColor(QRgb(0xfc5751)); + m_depthColor = QColor(QRgb(0x92ca66)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0xeba85f)); + m_highlightRowColor = QColor(QRgb(0xfc5751)); + m_highlightColumnColor = QColor(QRgb(0xfc5751)); + m_lightStrength = 4.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 6.0f; + m_uniformColor = true; +#endif + qDebug("ThemeSystem"); + break; + } + case ThemeBlueCerulean: { + m_baseColor = QColor(QRgb(0xc7e85b)); + m_heightColor = QColor(QRgb(0xee7392)); + m_depthColor = QColor(QRgb(0x1cb54f)); + m_backgroundColor = QColor(QRgb(0x056189)); + m_windowColor = QColor(QRgb(0x101a31)); + m_textColor = QColor(QRgb(0xffffff)); + m_textBackgroundColor = QColor(0x05, 0x61, 0x89, 0x80); + m_gridLine = QColor(QRgb(0x84a2b0)); + m_highlightBarColor = QColor(QRgb(0x5cbf9b)); + m_highlightRowColor = QColor(QRgb(0x009fbf)); + m_highlightColumnColor = QColor(QRgb(0x009fbf)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.2f; + m_highlightLightStrength = 10.0f; + m_uniformColor = true; + qDebug("ThemeBlueCerulean"); + break; + } + case ThemeBlueIcy: { + m_baseColor = QRgb(0x3daeda); + m_heightColor = QRgb(0x2fa3b4); + m_depthColor = QColor(QRgb(0x2685bf)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0x0c2673)); + m_highlightRowColor = QColor(QRgb(0x5f3dba)); + m_highlightColumnColor = QColor(QRgb(0x5f3dba)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 8.0f; + m_uniformColor = true; + qDebug("ThemeBlueIcy"); + break; + } + case ThemeBlueNcs: { + m_baseColor = QColor(QRgb(0x1db0da)); + m_heightColor = QColor(QRgb(0x398ca3)); + m_depthColor = QColor(QRgb(0x1341a6)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0xff); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0x88d41e)); + m_highlightRowColor = QColor(QRgb(0xff8e1a)); + m_highlightColumnColor = QColor(QRgb(0xff8e1a)); + m_lightStrength = 4.0f; + m_ambientStrength = 0.2f; + m_highlightLightStrength = 6.0f; + m_uniformColor = true; + qDebug("ThemeBlueNcs"); + break; + } + case ThemeBrownSand: { + m_baseColor = QColor(QRgb(0xb39b72)); + m_heightColor = QColor(QRgb(0x494345)); + m_depthColor = QColor(QRgb(0xb3b376)); + m_backgroundColor = QColor(QRgb(0xf3ece0)); + m_windowColor = QColor(QRgb(0xf3ece0)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xb5, 0xb0, 0xa7, 0x80); + m_gridLine = QColor(QRgb(0xd4cec3)); + m_highlightBarColor = QColor(QRgb(0xc35660)); + m_highlightRowColor = QColor(QRgb(0x536780)); + m_highlightColumnColor = QColor(QRgb(0x536780)); + m_lightStrength = 6.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 8.0f; + m_uniformColor = false; + qDebug("ThemeBrownSand"); + break; + } + case ThemeDark: { + m_baseColor = QColor(QRgb(0x38ad6b)); // charts: series color 1 + m_heightColor = QColor(QRgb(0xbf593e)); // charts: series color 5 + m_depthColor = QColor(QRgb(0x3c84a7)); // charts: series color 2 + m_backgroundColor = QColor(QRgb(0x2e303a)); // charts: background color 1 + m_windowColor = QColor(QRgb(0x121218)); // charts: background color 2 + m_textColor = QColor(QRgb(0xffffff)); // charts: label color + m_textBackgroundColor = QColor(0x86, 0x87, 0x8c, 0x80); // charts: axis line pen OR background color 2 + m_gridLine = QColor(QRgb(0x86878c)); // charts: grid line color + m_highlightBarColor = QColor(QRgb(0xeb8817)); // charts: series color 3 + m_highlightRowColor = QColor(QRgb(0x7b7f8c)); // charts: series color 4 + m_highlightColumnColor = QColor(QRgb(0x7b7f8c)); // charts: series color 4 + m_lightStrength = 6.0f; + m_ambientStrength = 0.2f; + m_highlightLightStrength = 8.0f; + m_uniformColor = false; + qDebug("ThemeDark"); + break; + } + case ThemeHighContrast: { + m_baseColor = QColor(QRgb(0x202020)); + m_heightColor = QColor(QRgb(0xff4a41)); + m_depthColor = QColor(QRgb(0x596a74)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0x000000)); + m_textColor = QColor(QRgb(0x181818)); + m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80); + m_gridLine = QColor(QRgb(0x8c8c8c)); + m_highlightBarColor = QColor(QRgb(0xffab03)); + m_highlightRowColor = QColor(QRgb(0x038e9b)); + m_highlightColumnColor = QColor(QRgb(0x038e9b)); + m_lightStrength = 8.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 10.0f; + m_uniformColor = false; + qDebug("ThemeHighContrast"); + break; + } + case ThemeLight: { + m_baseColor = QColor(QRgb(0x209fdf)); + m_heightColor = QColor(QRgb(0xbf593e)); + m_depthColor = QColor(QRgb(0x99ca53)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x404044)); + m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); + m_gridLine = QColor(QRgb(0xe2e2e2)); + m_highlightBarColor = QColor(QRgb(0xf6a625)); + m_highlightRowColor = QColor(QRgb(0x6d5fd5)); + m_highlightColumnColor = QColor(QRgb(0x6d5fd5)); + m_lightStrength = 6.0f; + m_ambientStrength = 0.3f; + m_highlightLightStrength = 7.0f; + m_uniformColor = true; + qDebug("ThemeLight"); + break; + } + default: + break; + } +} + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/theme_p.h b/src/datavis3d/engine/theme_p.h new file mode 100644 index 00000000..d55e9a33 --- /dev/null +++ b/src/datavis3d/engine/theme_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 THEME_P_H +#define THEME_P_H + +#include "QtDataVis3D/qdatavis3dglobal.h" +#include "QtDataVis3D/qdatavis3namespace.h" +#include "q3dbars.h" + +class QColor; + +QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE + +class Theme +{ +public: + explicit Theme(); + ~Theme(); + + void useTheme(ColorTheme theme); + +private: + friend class Q3DBars; + friend class Q3DBarsPrivate; + friend class Q3DMaps; + friend class Q3DMapsPrivate; + friend class Drawer; + + QColor m_baseColor; + QColor m_heightColor; + QColor m_depthColor; + QColor m_backgroundColor; + QColor m_windowColor; + QColor m_textColor; + QColor m_textBackgroundColor; + QColor m_gridLine; + QColor m_highlightBarColor; + QColor m_highlightRowColor; + QColor m_highlightColumnColor; + float m_lightStrength; + float m_ambientStrength; + float m_highlightLightStrength; + bool m_uniformColor; +}; + +QTCOMMERCIALDATAVIS3D_END_NAMESPACE + +#endif |