diff options
author | Mika Salmela <mika.salmela@digia.com> | 2014-06-05 10:32:24 +0300 |
---|---|---|
committer | Mika Salmela <mika.salmela@digia.com> | 2014-06-05 10:36:02 +0300 |
commit | 2299481acb0b36d76414ed9e0ae2b2d110ff13d8 (patch) | |
tree | c7e4412dcea928b428a2abb7116009b3a4fbce43 /src/datavisualization/utils | |
parent | f8e9d36ce868adaade5aaa6769ba681763d16874 (diff) |
Scatter perf improvement
Task-number: QTRD-3148
Change-Id: I2c9efa84184819aaac123ee29685bc3a9e35bfe6
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavisualization/utils')
-rw-r--r-- | src/datavisualization/utils/objecthelper.cpp | 30 | ||||
-rw-r--r-- | src/datavisualization/utils/objecthelper_p.h | 10 | ||||
-rw-r--r-- | src/datavisualization/utils/scatterobjectbufferhelper.cpp | 226 | ||||
-rw-r--r-- | src/datavisualization/utils/scatterobjectbufferhelper_p.h | 51 | ||||
-rw-r--r-- | src/datavisualization/utils/scatterpointbufferhelper.cpp | 113 | ||||
-rw-r--r-- | src/datavisualization/utils/scatterpointbufferhelper_p.h | 62 | ||||
-rw-r--r-- | src/datavisualization/utils/utils.pri | 8 |
7 files changed, 482 insertions, 18 deletions
diff --git a/src/datavisualization/utils/objecthelper.cpp b/src/datavisualization/utils/objecthelper.cpp index 30f119f2..a66e0f7e 100644 --- a/src/datavisualization/utils/objecthelper.cpp +++ b/src/datavisualization/utils/objecthelper.cpp @@ -118,6 +118,10 @@ void ObjectHelper::load() glDeleteBuffers(1, &m_uvbuffer); glDeleteBuffers(1, &m_normalbuffer); glDeleteBuffers(1, &m_elementbuffer); + m_indices.clear(); + m_indexedVertices.clear(); + m_indexedUVs.clear(); + m_indexedNormals.clear(); } QVector<QVector3D> vertices; QVector<QVector2D> uvs; @@ -127,36 +131,32 @@ void ObjectHelper::load() qFatal("loading failed"); // Index vertices - QVector<unsigned short> indices; - QVector<QVector3D> indexed_vertices; - QVector<QVector2D> indexed_uvs; - QVector<QVector3D> indexed_normals; - VertexIndexer::indexVBO(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, - indexed_normals); + VertexIndexer::indexVBO(vertices, uvs, normals, m_indices, m_indexedVertices, m_indexedUVs, + m_indexedNormals); - m_indexCount = indices.size(); + m_indexCount = m_indices.size(); glGenBuffers(1, &m_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); - glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(QVector3D), - &indexed_vertices.at(0), + glBufferData(GL_ARRAY_BUFFER, m_indexedVertices.size() * sizeof(QVector3D), + &m_indexedVertices.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_normalbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); - glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(QVector3D), - &indexed_normals.at(0), + glBufferData(GL_ARRAY_BUFFER, m_indexedNormals.size() * sizeof(QVector3D), + &m_indexedNormals.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_uvbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); - glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(QVector2D), - &indexed_uvs.at(0), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, m_indexedUVs.size() * sizeof(QVector2D), + &m_indexedUVs.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_elementbuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), - &indices.at(0), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(unsigned short), + &m_indices.at(0), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/datavisualization/utils/objecthelper_p.h b/src/datavisualization/utils/objecthelper_p.h index 1c3217b7..c84f53bd 100644 --- a/src/datavisualization/utils/objecthelper_p.h +++ b/src/datavisualization/utils/objecthelper_p.h @@ -46,15 +46,23 @@ public: static void resetObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj, const QString &meshFile); static void releaseObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj); - inline const QString &objectFile() { return m_objectFile; } + inline const QVector<unsigned short> &indices() const { return m_indices; } + inline const QVector<QVector3D> &indexedvertices() const { return m_indexedVertices; } + inline const QVector<QVector2D> &indexedUVs() const { return m_indexedUVs; } + inline const QVector<QVector3D> &indexedNormals() const { return m_indexedNormals; } + private: static ObjectHelper *getObjectHelper(const Abstract3DRenderer *cacheId, const QString &objectFile); void load(); QString m_objectFile; + QVector<unsigned short> m_indices; + QVector<QVector3D> m_indexedVertices; + QVector<QVector2D> m_indexedUVs; + QVector<QVector3D> m_indexedNormals; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/scatterobjectbufferhelper.cpp b/src/datavisualization/utils/scatterobjectbufferhelper.cpp new file mode 100644 index 00000000..123588f1 --- /dev/null +++ b/src/datavisualization/utils/scatterobjectbufferhelper.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatterobjectbufferhelper_p.h" +#include "objecthelper_p.h" +#include <QtGui/QVector2D> +#include <QtGui/QMatrix4x4> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +const GLfloat itemScaler = 3.0f; + +ScatterObjectBufferHelper::ScatterObjectBufferHelper() +{ + m_indicesType = GL_UNSIGNED_INT; +} + +ScatterObjectBufferHelper::~ScatterObjectBufferHelper() +{ +} + +void ScatterObjectBufferHelper::fullLoad(ScatterSeriesRenderCache *cache, qreal dotScale) +{ + initializeOpenGLFunctions(); + + ObjectHelper *dotObj = cache->object(); + ScatterRenderItemArray &renderArray = cache->renderArray(); + const uint renderArraySize = renderArray.size(); + uint itemCount = renderArraySize; + QQuaternion seriesRotation(cache->meshRotation()); + + if (m_meshDataLoaded) { + // Delete old data + glDeleteBuffers(1, &m_vertexbuffer); + glDeleteBuffers(1, &m_uvbuffer); + glDeleteBuffers(1, &m_normalbuffer); + glDeleteBuffers(1, &m_elementbuffer); + } + + // Index vertices + const QVector<unsigned short> indices = dotObj->indices(); + const QVector<QVector3D> indexed_vertices = dotObj->indexedvertices(); + const QVector<QVector2D> indexed_uvs = dotObj->indexedUVs(); + const QVector<QVector3D> indexed_normals = dotObj->indexedNormals(); + int indicesCount = indices.count(); + int verticeCount = indexed_vertices.count(); + int uvsCount = indexed_uvs.count(); + int normalsCount = indexed_normals.count(); + + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = dotScale; + QVector3D modelScaler(itemSize, itemSize, itemSize); + QMatrix4x4 modelMatrix; + if (!seriesRotation.isIdentity()) { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation); + modelMatrix = matrix.transposed(); + } + modelMatrix.scale(modelScaler); + + QVector<QVector3D> scaled_vertices; + scaled_vertices.resize(verticeCount); + for (int i = 0; i < verticeCount; i++) + scaled_vertices[i] = indexed_vertices[i] * modelMatrix; + + QVector<GLuint> buffered_indices; + QVector<QVector3D> buffered_vertices; + QVector<QVector2D> buffered_uvs; + QVector<QVector3D> buffered_normals; + + buffered_indices.resize(indicesCount * renderArraySize); + buffered_vertices.resize(verticeCount * renderArraySize); + buffered_uvs.resize(uvsCount * renderArraySize); + buffered_normals.resize(normalsCount * renderArraySize); + uint pos = 0; + for (uint i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) { + itemCount--; + continue; + } + + int offset = pos * verticeCount; + if (item.rotation().isIdentity()) { + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = scaled_vertices[j] + item.translation(); + } else { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation * item.rotation()); + modelMatrix = matrix.transposed(); + modelMatrix.scale(modelScaler); + + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = indexed_vertices[j] * modelMatrix + + item.translation(); + } + + offset = pos * normalsCount; + for (int j = 0; j < normalsCount; j++) + buffered_normals[j + offset] = indexed_normals[j]; + + offset = pos * uvsCount; + for (int j = 0; j < uvsCount; j++) + buffered_uvs[j + offset] = indexed_uvs[j]; + + int offsetVertice = i * verticeCount; + offset = pos * indicesCount; + for (int j = 0; j < indicesCount; j++) { + buffered_indices[j + offset] = GLuint(indices[j] + offsetVertice); + } + + pos++; + } + + m_indexCount = indicesCount * itemCount; + + glGenBuffers(1, &m_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, verticeCount * itemCount * sizeof(QVector3D), + &buffered_vertices.at(0), + GL_STATIC_DRAW); + + glGenBuffers(1, &m_normalbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); + glBufferData(GL_ARRAY_BUFFER, normalsCount * itemCount * sizeof(QVector3D), + &buffered_normals.at(0), + GL_STATIC_DRAW); + + glGenBuffers(1, &m_uvbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); + glBufferData(GL_ARRAY_BUFFER, uvsCount * itemCount * sizeof(QVector2D), + &buffered_uvs.at(0), GL_STATIC_DRAW); + + glGenBuffers(1, &m_elementbuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount * itemCount * sizeof(GLint), + &buffered_indices.at(0), GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +void ScatterObjectBufferHelper::update(ScatterSeriesRenderCache *cache, qreal dotScale) +{ + initializeOpenGLFunctions(); + + ObjectHelper *dotObj = cache->object(); + ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + QQuaternion seriesRotation(cache->meshRotation()); + + // Index vertices + const QVector<QVector3D> indexed_vertices = dotObj->indexedvertices(); + int verticeCount = indexed_vertices.count(); + + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = dotScale; + QVector3D modelScaler(itemSize, itemSize, itemSize); + QMatrix4x4 modelMatrix; + if (!seriesRotation.isIdentity()) { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation); + modelMatrix = matrix.transposed(); + } + modelMatrix.scale(modelScaler); + + QVector<QVector3D> scaled_vertices; + scaled_vertices.resize(verticeCount); + for (int i = 0; i < verticeCount; i++) + scaled_vertices[i] = indexed_vertices[i] * modelMatrix; + + QVector<QVector3D> buffered_vertices; + + buffered_vertices.resize(verticeCount * renderArraySize); + for (int i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) + continue; + + const int offset = i * verticeCount; + if (item.rotation().isIdentity()) { + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = scaled_vertices[j] + item.translation(); + } else { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation * item.rotation()); + modelMatrix = matrix.transposed(); + modelMatrix.scale(modelScaler); + + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = indexed_vertices[j] * modelMatrix + + item.translation(); + } + } + + glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, buffered_vertices.size() * sizeof(QVector3D), + &buffered_vertices.at(0), + GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/scatterobjectbufferhelper_p.h b/src/datavisualization/utils/scatterobjectbufferhelper_p.h new file mode 100644 index 00000000..0bba45f5 --- /dev/null +++ b/src/datavisualization/utils/scatterobjectbufferhelper_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization 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 SCATTEROBJECTBUFFERHELPER_P_H +#define SCATTEROBJECTBUFFERHELPER_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractobjecthelper_p.h" +#include "scatterseriesrendercache_p.h" +#include <QtGui/QOpenGLFunctions> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class ScatterObjectBufferHelper : public AbstractObjectHelper +{ +public: + ScatterObjectBufferHelper(); + ~ScatterObjectBufferHelper(); + + void fullLoad(ScatterSeriesRenderCache *cache, qreal dotScale); + void update(ScatterSeriesRenderCache *cache, qreal dotScale); +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/utils/scatterpointbufferhelper.cpp b/src/datavisualization/utils/scatterpointbufferhelper.cpp new file mode 100644 index 00000000..0f290aeb --- /dev/null +++ b/src/datavisualization/utils/scatterpointbufferhelper.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "scatterpointbufferhelper_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +const GLfloat itemScaler = 3.0f; +const QVector3D hiddenPos(-1000.0f, -1000.0f, -1000.0f); + +ScatterPointBufferHelper::ScatterPointBufferHelper() + : m_pointbuffer(0), + m_oldRemoveIndex(0), + m_oldRemove(false) +{ + m_indicesType = GL_UNSIGNED_INT; +} + +ScatterPointBufferHelper::~ScatterPointBufferHelper() +{ + if (QOpenGLContext::currentContext()) + glDeleteBuffers(1, &m_pointbuffer); +} + +GLuint ScatterPointBufferHelper::pointBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_pointbuffer; +} + +void ScatterPointBufferHelper::pushPoint(uint pointIndex) +{ + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + + if (m_oldRemove && m_oldRemoveIndex < pointIndex) { + glBufferSubData(GL_ARRAY_BUFFER, m_oldRemoveIndex * sizeof(QVector3D), + sizeof(QVector3D), &m_bufferedPoints.at(m_oldRemoveIndex)); + } + + glBufferSubData(GL_ARRAY_BUFFER, pointIndex * sizeof(QVector3D), + sizeof(QVector3D), + &hiddenPos); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_oldRemoveIndex = pointIndex; + m_oldRemove = true; +} + +void ScatterPointBufferHelper::popPoint() +{ + if (m_oldRemove) { + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + glBufferSubData(GL_ARRAY_BUFFER, m_oldRemoveIndex * sizeof(QVector3D), + sizeof(QVector3D), &m_bufferedPoints.at(m_oldRemoveIndex)); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + m_oldRemoveIndex = 0; + m_oldRemove = false; +} + +void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache) +{ + initializeOpenGLFunctions(); + + ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + + if (m_meshDataLoaded) { + // Delete old data + glDeleteBuffers(1, &m_pointbuffer); + m_bufferedPoints.clear(); + } + + m_bufferedPoints.resize(renderArraySize); + for (int i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) + m_bufferedPoints[i] = hiddenPos; + else + m_bufferedPoints[i] = item.translation(); + } + + m_indexCount = renderArraySize; + + glGenBuffers(1, &m_pointbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + glBufferData(GL_ARRAY_BUFFER, m_bufferedPoints.size() * sizeof(QVector3D), + &m_bufferedPoints.at(0), + GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/scatterpointbufferhelper_p.h b/src/datavisualization/utils/scatterpointbufferhelper_p.h new file mode 100644 index 00000000..39903b1a --- /dev/null +++ b/src/datavisualization/utils/scatterpointbufferhelper_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization 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 SCATTERPOINTBUFFERHELPER_P_H +#define SCATTERPOINTBUFFERHELPER_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractobjecthelper_p.h" +#include "scatterseriesrendercache_p.h" +#include <QtGui/QOpenGLFunctions> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class ScatterPointBufferHelper : public AbstractObjectHelper +{ +public: + ScatterPointBufferHelper(); + ~ScatterPointBufferHelper(); + + GLuint pointBuf(); + + void pushPoint(uint pointIndex); + void popPoint(); + void load(ScatterSeriesRenderCache *cache); + +public: + GLuint m_pointbuffer; + +private: + QVector<QVector3D> m_bufferedPoints; + uint m_oldRemoveIndex; + bool m_oldRemove; +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/utils/utils.pri b/src/datavisualization/utils/utils.pri index 8ce8794e..30bfb156 100644 --- a/src/datavisualization/utils/utils.pri +++ b/src/datavisualization/utils/utils.pri @@ -7,7 +7,9 @@ HEADERS += $$PWD/meshloader_p.h \ $$PWD/utils_p.h \ $$PWD/abstractobjecthelper_p.h \ $$PWD/surfaceobject_p.h \ - $$PWD/qutils.h + $$PWD/qutils.h \ + $$PWD/scatterobjectbufferhelper_p.h \ + $$PWD/scatterpointbufferhelper_p.h SOURCES += $$PWD/meshloader.cpp \ $$PWD/vertexindexer.cpp \ @@ -17,4 +19,6 @@ SOURCES += $$PWD/meshloader.cpp \ $$PWD/texturehelper.cpp \ $$PWD/utils.cpp \ $$PWD/abstractobjecthelper.cpp \ - $$PWD/surfaceobject.cpp + $$PWD/surfaceobject.cpp \ + $$PWD/scatterobjectbufferhelper.cpp \ + $$PWD/scatterpointbufferhelper.cpp |