summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/utils/scatterobjectbufferhelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/utils/scatterobjectbufferhelper.cpp')
-rw-r--r--src/datavisualization/utils/scatterobjectbufferhelper.cpp237
1 files changed, 192 insertions, 45 deletions
diff --git a/src/datavisualization/utils/scatterobjectbufferhelper.cpp b/src/datavisualization/utils/scatterobjectbufferhelper.cpp
index d68b9df4..44c84ae0 100644
--- a/src/datavisualization/utils/scatterobjectbufferhelper.cpp
+++ b/src/datavisualization/utils/scatterobjectbufferhelper.cpp
@@ -20,12 +20,14 @@
#include "objecthelper_p.h"
#include <QtGui/QVector2D>
#include <QtGui/QMatrix4x4>
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
const GLfloat itemScaler = 3.0f;
ScatterObjectBufferHelper::ScatterObjectBufferHelper()
+ : m_scaleY(0.0f)
{
m_indicesType = GL_UNSIGNED_INT;
}
@@ -36,34 +38,40 @@ ScatterObjectBufferHelper::~ScatterObjectBufferHelper()
void ScatterObjectBufferHelper::fullLoad(ScatterSeriesRenderCache *cache, qreal dotScale)
{
- initializeOpenGLFunctions();
-
m_meshDataLoaded = false;
m_indexCount = 0;
ObjectHelper *dotObj = cache->object();
- ScatterRenderItemArray &renderArray = cache->renderArray();
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
const uint renderArraySize = renderArray.size();
+
if (renderArraySize == 0)
return; // No use to go forward
- uint itemCount = renderArraySize;
+
+ uint itemCount = 0;
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);
+ m_vertexbuffer = 0;
+ m_uvbuffer = 0;
+ m_normalbuffer = 0;
+ m_elementbuffer = 0;
}
+
// 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();
+ const int indicesCount = indices.count();
+ const int verticeCount = indexed_vertices.count();
+ const int uvsCount = indexed_uvs.count();
+ const int normalsCount = indexed_normals.count();
float itemSize = cache->itemSize() / itemScaler;
if (itemSize == 0.0f)
@@ -89,47 +97,58 @@ void ScatterObjectBufferHelper::fullLoad(ScatterSeriesRenderCache *cache, qreal
buffered_indices.resize(indicesCount * renderArraySize);
buffered_vertices.resize(verticeCount * renderArraySize);
- buffered_uvs.resize(uvsCount * renderArraySize);
buffered_normals.resize(normalsCount * renderArraySize);
- uint pos = 0;
+ buffered_uvs.resize(uvsCount * renderArraySize);
+
+ if (cache->colorStyle() == Q3DTheme::ColorStyleRangeGradient)
+ createRangeGradientUVs(cache, buffered_uvs);
+ else if (cache->colorStyle() == Q3DTheme::ColorStyleObjectGradient)
+ createObjectGradientUVs(cache, buffered_uvs, indexed_vertices);
+
+ QVector2D dummyUV(0.0f, 0.0f);
+
+ cache->bufferIndices().resize(renderArraySize);
for (uint i = 0; i < renderArraySize; i++) {
- ScatterRenderItem &item = renderArray[i];
- if (!item.isVisible()) {
- itemCount--;
+ const ScatterRenderItem &item = renderArray.at(i);
+ if (!item.isVisible())
continue;
- }
+ else
+ cache->bufferIndices()[i] = itemCount;
- int offset = pos * verticeCount;
+ int offset = itemCount * verticeCount;
if (item.rotation().isIdentity()) {
- for (int j = 0; j < verticeCount; j++)
+ for (int j = 0; j < verticeCount; j++) {
buffered_vertices[j + offset] = scaled_vertices[j] + item.translation();
+ buffered_normals[j + offset] = indexed_normals[j];
+ }
} else {
QMatrix4x4 matrix;
- matrix.rotate(seriesRotation * item.rotation());
- modelMatrix = matrix.transposed();
- modelMatrix.scale(modelScaler);
+ QQuaternion totalRotation = seriesRotation * item.rotation();
+ matrix.rotate(totalRotation);
+ matrix.scale(modelScaler);
+ QMatrix4x4 itModelMatrix = matrix.inverted();
+ modelMatrix = matrix.transposed(); // Because of row-column major difference
- for (int j = 0; j < verticeCount; j++)
+ for (int j = 0; j < verticeCount; j++) {
buffered_vertices[j + offset] = indexed_vertices[j] * modelMatrix
+ item.translation();
+ buffered_normals[j + offset] = indexed_normals[j] * itModelMatrix;
+ }
}
- 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];
+ if (cache->colorStyle() == Q3DTheme::ColorStyleUniform) {
+ offset = itemCount * uvsCount;
+ for (int j = 0; j < uvsCount; j++)
+ buffered_uvs[j + offset] = dummyUV;
+ }
- int offsetVertice = i * verticeCount;
- offset = pos * indicesCount;
- for (int j = 0; j < indicesCount; j++) {
+ int offsetVertice = itemCount * verticeCount;
+ offset = itemCount * indicesCount;
+ for (int j = 0; j < indicesCount; j++)
buffered_indices[j + offset] = GLuint(indices[j] + offsetVertice);
- }
- pos++;
+ itemCount++;
}
m_indexCount = indicesCount * itemCount;
@@ -164,15 +183,128 @@ void ScatterObjectBufferHelper::fullLoad(ScatterSeriesRenderCache *cache, qreal
}
}
-void ScatterObjectBufferHelper::update(ScatterSeriesRenderCache *cache, qreal dotScale)
+void ScatterObjectBufferHelper::updateUVs(ScatterSeriesRenderCache *cache)
+{
+ ObjectHelper *dotObj = cache->object();
+ const int uvsCount = dotObj->indexedUVs().count();
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const bool updateAll = (cache->updateIndices().size() == 0);
+ const int updateSize = updateAll ? renderArray.size() : cache->updateIndices().size();
+
+ if (!updateSize)
+ return;
+
+ QVector<QVector2D> buffered_uvs;
+ buffered_uvs.resize(uvsCount * updateSize);
+
+ uint itemCount = 0;
+ if (cache->colorStyle() == Q3DTheme::ColorStyleRangeGradient) {
+ itemCount = createRangeGradientUVs(cache, buffered_uvs);
+ } else if (cache->colorStyle() == Q3DTheme::ColorStyleObjectGradient) {
+ const QVector<QVector3D> indexed_vertices = dotObj->indexedvertices();
+ itemCount = createObjectGradientUVs(cache, buffered_uvs, indexed_vertices);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
+ int itemSize = uvsCount * sizeof(QVector2D);
+ if (cache->updateIndices().size()) {
+ int pos = 0;
+ for (int i = 0; i < updateSize; i++) {
+ int index = cache->updateIndices().at(i);
+ if (renderArray.at(index).isVisible()) {
+ int dataPos = cache->bufferIndices().at(index);
+ glBufferSubData(GL_ARRAY_BUFFER, itemSize * dataPos, itemSize,
+ &buffered_uvs.at(uvsCount * pos++));
+ }
+ }
+ } else {
+ glBufferData(GL_ARRAY_BUFFER, itemSize * itemCount, &buffered_uvs.at(0), GL_STATIC_DRAW);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+uint ScatterObjectBufferHelper::createRangeGradientUVs(ScatterSeriesRenderCache *cache,
+ QVector<QVector2D> &buffered_uvs)
{
- initializeOpenGLFunctions();
+ ObjectHelper *dotObj = cache->object();
+ const int uvsCount = dotObj->indexedUVs().count();
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const bool updateAll = (cache->updateIndices().size() == 0);
+ const int updateSize = updateAll ? renderArray.size() : cache->updateIndices().size();
+ const float yAdjustment = 0.1f;
+ const float flippedYAdjustment = 0.9f;
+
+ QVector2D uv;
+ uv.setX(0.0f);
+ uint pos = 0;
+ for (int i = 0; i < updateSize; i++) {
+ int index = updateAll ? i : cache->updateIndices().at(i);
+ const ScatterRenderItem &item = renderArray.at(index);
+ if (!item.isVisible())
+ continue;
+
+ float y = ((item.translation().y() + m_scaleY) * 0.5f) / m_scaleY;
+ // Avoid values near gradient texel boundary, as this causes artifacts
+ // with some graphics cards.
+ const float floorY = float(qFloor(y * gradientTextureHeight));
+ const float diff = (y * gradientTextureHeight) - floorY;
+ if (diff < yAdjustment)
+ y += yAdjustment / gradientTextureHeight;
+ else if (diff > flippedYAdjustment)
+ y -= yAdjustment / gradientTextureHeight;
+ uv.setY(y);
+
+ int offset = pos * uvsCount;
+ for (int j = 0; j < uvsCount; j++)
+ buffered_uvs[j + offset] = uv;
+
+ pos++;
+ }
+
+ return pos;
+}
+
+uint ScatterObjectBufferHelper::createObjectGradientUVs(ScatterSeriesRenderCache *cache,
+ QVector<QVector2D> &buffered_uvs,
+ const QVector<QVector3D> &indexed_vertices)
+{
ObjectHelper *dotObj = cache->object();
- ScatterRenderItemArray &renderArray = cache->renderArray();
- const int renderArraySize = renderArray.size();
+ const int uvsCount = dotObj->indexedUVs().count();
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const uint renderArraySize = renderArray.size();
+
+ QVector2D uv;
+ uv.setX(0.0f);
+ uint pos = 0;
+ for (uint i = 0; i < renderArraySize; i++) {
+ const ScatterRenderItem &item = renderArray.at(i);
+ if (!item.isVisible())
+ continue;
+
+ int offset = pos * uvsCount;
+ for (int j = 0; j < uvsCount; j++) {
+ uv.setY((indexed_vertices.at(j).y() + 1.0f) / 2.0f);
+ buffered_uvs[j + offset] = uv;
+ }
+
+ pos++;
+ }
+
+ return pos;
+}
+
+void ScatterObjectBufferHelper::update(ScatterSeriesRenderCache *cache, qreal dotScale)
+{
+ ObjectHelper *dotObj = cache->object();
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const bool updateAll = (cache->updateIndices().size() == 0);
+ const int updateSize = updateAll ? renderArray.size() : cache->updateIndices().size();
QQuaternion seriesRotation(cache->meshRotation());
+ if (!updateSize)
+ return;
+
// Index vertices
const QVector<QVector3D> indexed_vertices = dotObj->indexedvertices();
int verticeCount = indexed_vertices.count();
@@ -195,14 +327,16 @@ void ScatterObjectBufferHelper::update(ScatterSeriesRenderCache *cache, qreal do
scaled_vertices[i] = indexed_vertices[i] * modelMatrix;
QVector<QVector3D> buffered_vertices;
+ buffered_vertices.resize(verticeCount * updateSize);
- buffered_vertices.resize(verticeCount * renderArraySize);
- for (int i = 0; i < renderArraySize; i++) {
- ScatterRenderItem &item = renderArray[i];
+ int itemCount = 0;
+ for (int i = 0; i < updateSize; i++) {
+ int index = updateAll ? i : cache->updateIndices().at(i);
+ const ScatterRenderItem &item = renderArray.at(index);
if (!item.isVisible())
continue;
- const int offset = i * verticeCount;
+ const int offset = itemCount * verticeCount;
if (item.rotation().isIdentity()) {
for (int j = 0; j < verticeCount; j++)
buffered_vertices[j + offset] = scaled_vertices[j] + item.translation();
@@ -216,15 +350,28 @@ void ScatterObjectBufferHelper::update(ScatterSeriesRenderCache *cache, qreal do
buffered_vertices[j + offset] = indexed_vertices[j] * modelMatrix
+ item.translation();
}
+ itemCount++;
}
glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
- glBufferData(GL_ARRAY_BUFFER, buffered_vertices.size() * sizeof(QVector3D),
- &buffered_vertices.at(0),
- GL_DYNAMIC_DRAW);
-
+ int sizeOfItem = verticeCount * sizeof(QVector3D);
+ if (updateAll) {
+ if (itemCount) {
+ glBufferData(GL_ARRAY_BUFFER, itemCount * sizeOfItem,
+ &buffered_vertices.at(0), GL_STATIC_DRAW);
+ }
+ } else {
+ itemCount = 0;
+ for (int i = 0; i < updateSize; i++) {
+ int index = updateAll ? i : cache->updateIndices().at(i);
+ if (renderArray.at(index).isVisible()) {
+ glBufferSubData(GL_ARRAY_BUFFER, cache->bufferIndices().at(index) * sizeOfItem,
+ sizeOfItem, &buffered_vertices.at(itemCount * verticeCount));
+ itemCount++;
+ }
+ }
+ }
glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
m_meshDataLoaded = true;
}