summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/utils')
-rw-r--r--src/datavisualization/utils/abstractobjecthelper.cpp1
-rw-r--r--src/datavisualization/utils/abstractobjecthelper_p.h4
-rw-r--r--src/datavisualization/utils/objecthelper.cpp5
-rw-r--r--src/datavisualization/utils/objecthelper_p.h2
-rw-r--r--src/datavisualization/utils/qutils.h12
-rw-r--r--src/datavisualization/utils/scatterobjectbufferhelper.cpp237
-rw-r--r--src/datavisualization/utils/scatterobjectbufferhelper_p.h13
-rw-r--r--src/datavisualization/utils/scatterpointbufferhelper.cpp109
-rw-r--r--src/datavisualization/utils/scatterpointbufferhelper_p.h13
-rw-r--r--src/datavisualization/utils/shaderhelper.cpp177
-rw-r--r--src/datavisualization/utils/shaderhelper_p.h112
-rw-r--r--src/datavisualization/utils/surfaceobject.cpp745
-rw-r--r--src/datavisualization/utils/surfaceobject_p.h52
-rw-r--r--src/datavisualization/utils/texturehelper.cpp244
-rw-r--r--src/datavisualization/utils/texturehelper_p.h14
-rw-r--r--src/datavisualization/utils/utils.cpp252
-rw-r--r--src/datavisualization/utils/utils.pri2
-rw-r--r--src/datavisualization/utils/utils_p.h15
18 files changed, 1465 insertions, 544 deletions
diff --git a/src/datavisualization/utils/abstractobjecthelper.cpp b/src/datavisualization/utils/abstractobjecthelper.cpp
index c350d096..40b3a45e 100644
--- a/src/datavisualization/utils/abstractobjecthelper.cpp
+++ b/src/datavisualization/utils/abstractobjecthelper.cpp
@@ -28,6 +28,7 @@ AbstractObjectHelper::AbstractObjectHelper()
m_indexCount(0),
m_meshDataLoaded(false)
{
+ initializeOpenGLFunctions();
}
AbstractObjectHelper::~AbstractObjectHelper()
diff --git a/src/datavisualization/utils/abstractobjecthelper_p.h b/src/datavisualization/utils/abstractobjecthelper_p.h
index c1618909..99f85dab 100644
--- a/src/datavisualization/utils/abstractobjecthelper_p.h
+++ b/src/datavisualization/utils/abstractobjecthelper_p.h
@@ -38,11 +38,11 @@ class AbstractObjectHelper: protected QOpenGLFunctions
protected:
AbstractObjectHelper();
public:
- ~AbstractObjectHelper();
+ virtual ~AbstractObjectHelper();
GLuint vertexBuf();
GLuint normalBuf();
- GLuint uvBuf();
+ virtual GLuint uvBuf();
GLuint elementBuf();
GLuint indexCount();
GLuint indicesType();
diff --git a/src/datavisualization/utils/objecthelper.cpp b/src/datavisualization/utils/objecthelper.cpp
index a66e0f7e..4240d6f5 100644
--- a/src/datavisualization/utils/objecthelper.cpp
+++ b/src/datavisualization/utils/objecthelper.cpp
@@ -111,7 +111,6 @@ ObjectHelper *ObjectHelper::getObjectHelper(const Abstract3DRenderer *cacheId,
void ObjectHelper::load()
{
- initializeOpenGLFunctions();
if (m_meshDataLoaded) {
// Delete old data
glDeleteBuffers(1, &m_vertexbuffer);
@@ -122,6 +121,10 @@ void ObjectHelper::load()
m_indexedVertices.clear();
m_indexedUVs.clear();
m_indexedNormals.clear();
+ m_vertexbuffer = 0;
+ m_uvbuffer = 0;
+ m_normalbuffer = 0;
+ m_elementbuffer = 0;
}
QVector<QVector3D> vertices;
QVector<QVector2D> uvs;
diff --git a/src/datavisualization/utils/objecthelper_p.h b/src/datavisualization/utils/objecthelper_p.h
index c84f53bd..b00e5d8d 100644
--- a/src/datavisualization/utils/objecthelper_p.h
+++ b/src/datavisualization/utils/objecthelper_p.h
@@ -41,7 +41,7 @@ class ObjectHelper : public AbstractObjectHelper
private:
ObjectHelper(const QString &objectFile);
public:
- ~ObjectHelper();
+ virtual ~ObjectHelper();
static void resetObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj,
const QString &meshFile);
diff --git a/src/datavisualization/utils/qutils.h b/src/datavisualization/utils/qutils.h
index 43375a9c..d4acfc99 100644
--- a/src/datavisualization/utils/qutils.h
+++ b/src/datavisualization/utils/qutils.h
@@ -28,17 +28,21 @@ inline static QSurfaceFormat qDefaultSurfaceFormat(bool antialias = true)
QSurfaceFormat surfaceFormat;
surfaceFormat.setDepthBufferSize(24);
+ surfaceFormat.setStencilBufferSize(8);
surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
-#if !defined(QT_OPENGL_ES_2)
- surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
-#else
+ surfaceFormat.setRenderableType(QSurfaceFormat::DefaultRenderableType);
+#if defined(QT_OPENGL_ES_2)
// Antialias not supported for ES
antialias = false;
- surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+ surfaceFormat.setRedBufferSize(8);
+ surfaceFormat.setBlueBufferSize(8);
+ surfaceFormat.setGreenBufferSize(8);
#endif
if (antialias)
surfaceFormat.setSamples(8);
+ else
+ surfaceFormat.setSamples(0);
return surfaceFormat;
}
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;
}
diff --git a/src/datavisualization/utils/scatterobjectbufferhelper_p.h b/src/datavisualization/utils/scatterobjectbufferhelper_p.h
index 952c3d7d..08a42900 100644
--- a/src/datavisualization/utils/scatterobjectbufferhelper_p.h
+++ b/src/datavisualization/utils/scatterobjectbufferhelper_p.h
@@ -39,10 +39,21 @@ class ScatterObjectBufferHelper : public AbstractObjectHelper
{
public:
ScatterObjectBufferHelper();
- ~ScatterObjectBufferHelper();
+ virtual ~ScatterObjectBufferHelper();
void fullLoad(ScatterSeriesRenderCache *cache, qreal dotScale);
void update(ScatterSeriesRenderCache *cache, qreal dotScale);
+ void updateUVs(ScatterSeriesRenderCache *cache);
+ void setScaleY(float scale) { m_scaleY = scale; }
+
+private:
+ uint createRangeGradientUVs(ScatterSeriesRenderCache *cache,
+ QVector<QVector2D> &buffered_uvs);
+ uint createObjectGradientUVs(ScatterSeriesRenderCache *cache,
+ QVector<QVector2D> &buffered_uvs,
+ const QVector<QVector3D> &indexed_vertices);
+
+ float m_scaleY;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/scatterpointbufferhelper.cpp b/src/datavisualization/utils/scatterpointbufferhelper.cpp
index b14d84ad..22e76f92 100644
--- a/src/datavisualization/utils/scatterpointbufferhelper.cpp
+++ b/src/datavisualization/utils/scatterpointbufferhelper.cpp
@@ -17,6 +17,7 @@
****************************************************************************/
#include "scatterpointbufferhelper_p.h"
+#include <QtGui/QVector2D>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -24,8 +25,7 @@ const QVector3D hiddenPos(-1000.0f, -1000.0f, -1000.0f);
ScatterPointBufferHelper::ScatterPointBufferHelper()
: m_pointbuffer(0),
- m_oldRemoveIndex(0),
- m_oldRemove(false)
+ m_oldRemoveIndex(-1)
{
m_indicesType = GL_UNSIGNED_INT;
}
@@ -47,7 +47,8 @@ void ScatterPointBufferHelper::pushPoint(uint pointIndex)
{
glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer);
- if (m_oldRemove && m_oldRemoveIndex < pointIndex) {
+ // Pop the previous point if it is still pushed
+ if (m_oldRemoveIndex >= 0) {
glBufferSubData(GL_ARRAY_BUFFER, m_oldRemoveIndex * sizeof(QVector3D),
sizeof(QVector3D), &m_bufferedPoints.at(m_oldRemoveIndex));
}
@@ -59,26 +60,22 @@ void ScatterPointBufferHelper::pushPoint(uint pointIndex)
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_oldRemoveIndex = pointIndex;
- m_oldRemove = true;
}
void ScatterPointBufferHelper::popPoint()
{
- if (m_oldRemove) {
+ if (m_oldRemoveIndex >= 0) {
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;
+ m_oldRemoveIndex = -1;
}
void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache)
{
- initializeOpenGLFunctions();
-
ScatterRenderItemArray &renderArray = cache->renderArray();
const int renderArraySize = renderArray.size();
m_indexCount = 0;
@@ -86,13 +83,16 @@ void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache)
if (m_meshDataLoaded) {
// Delete old data
glDeleteBuffers(1, &m_pointbuffer);
+ glDeleteBuffers(1, &m_uvbuffer);
m_bufferedPoints.clear();
+ m_pointbuffer = 0;
+ m_uvbuffer = 0;
}
bool itemsVisible = false;
m_bufferedPoints.resize(renderArraySize);
for (int i = 0; i < renderArraySize; i++) {
- ScatterRenderItem &item = renderArray[i];
+ const ScatterRenderItem &item = renderArray.at(i);
if (!item.isVisible()) {
m_bufferedPoints[i] = hiddenPos;
} else {
@@ -101,19 +101,108 @@ void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache)
}
}
+ QVector<QVector2D> buffered_uvs;
if (itemsVisible)
m_indexCount = renderArraySize;
if (m_indexCount > 0) {
+ if (cache->colorStyle() == Q3DTheme::ColorStyleRangeGradient)
+ createRangeGradientUVs(cache, buffered_uvs);
+
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);
+
+ if (buffered_uvs.size()) {
+ glGenBuffers(1, &m_uvbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
+ glBufferData(GL_ARRAY_BUFFER, buffered_uvs.size() * sizeof(QVector2D),
+ &buffered_uvs.at(0), GL_STATIC_DRAW);
+ }
+
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_meshDataLoaded = true;
}
}
+void ScatterPointBufferHelper::update(ScatterSeriesRenderCache *cache)
+{
+ // It may be that the buffer hasn't yet been initialized, in case the entire series was
+ // hidden items. No need to update in that case.
+ if (m_indexCount > 0) {
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const int updateSize = cache->updateIndices().size();
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer);
+ for (int i = 0; i < updateSize; i++) {
+ int index = cache->updateIndices().at(i);
+ const ScatterRenderItem &item = renderArray.at(index);
+ if (!item.isVisible())
+ m_bufferedPoints[index] = hiddenPos;
+ else
+ m_bufferedPoints[index] = item.translation();
+
+ if (index != m_oldRemoveIndex) {
+ glBufferSubData(GL_ARRAY_BUFFER, index * sizeof(QVector3D),
+ sizeof(QVector3D), &m_bufferedPoints.at(index));
+ }
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+}
+
+void ScatterPointBufferHelper::updateUVs(ScatterSeriesRenderCache *cache)
+{
+ // It may be that the buffer hasn't yet been initialized, in case the entire series was
+ // hidden items. No need to update in that case.
+ if (m_indexCount > 0) {
+ QVector<QVector2D> buffered_uvs;
+ createRangeGradientUVs(cache, buffered_uvs);
+
+ if (buffered_uvs.size()) {
+ if (!m_uvbuffer)
+ glGenBuffers(1, &m_uvbuffer);
+
+ int updateSize = cache->updateIndices().size();
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
+ if (updateSize) {
+ for (int i = 0; i < updateSize; i++) {
+ int index = cache->updateIndices().at(i);
+ glBufferSubData(GL_ARRAY_BUFFER, index * sizeof(QVector2D),
+ sizeof(QVector2D), &buffered_uvs.at(i));
+
+ }
+ } else {
+ glBufferData(GL_ARRAY_BUFFER, buffered_uvs.size() * sizeof(QVector2D),
+ &buffered_uvs.at(0), GL_STATIC_DRAW);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ }
+}
+
+void ScatterPointBufferHelper::createRangeGradientUVs(ScatterSeriesRenderCache *cache,
+ QVector<QVector2D> &buffered_uvs)
+{
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const bool updateAll = (cache->updateIndices().size() == 0);
+ const int updateSize = updateAll ? renderArray.size() : cache->updateIndices().size();
+ buffered_uvs.resize(updateSize);
+
+ QVector2D uv;
+ uv.setX(0.0f);
+ for (int i = 0; i < updateSize; i++) {
+ int index = updateAll ? i : cache->updateIndices().at(i);
+ const ScatterRenderItem &item = renderArray.at(index);
+
+ float y = ((item.translation().y() + m_scaleY) * 0.5f) / m_scaleY;
+ uv.setY(y);
+ buffered_uvs[i] = uv;
+ }
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/scatterpointbufferhelper_p.h b/src/datavisualization/utils/scatterpointbufferhelper_p.h
index b3adcfa8..8b34542d 100644
--- a/src/datavisualization/utils/scatterpointbufferhelper_p.h
+++ b/src/datavisualization/utils/scatterpointbufferhelper_p.h
@@ -39,21 +39,28 @@ class ScatterPointBufferHelper : public AbstractObjectHelper
{
public:
ScatterPointBufferHelper();
- ~ScatterPointBufferHelper();
+ virtual ~ScatterPointBufferHelper();
GLuint pointBuf();
void pushPoint(uint pointIndex);
void popPoint();
void load(ScatterSeriesRenderCache *cache);
+ void update(ScatterSeriesRenderCache *cache);
+ void setScaleY(float scale) { m_scaleY = scale; }
+ void updateUVs(ScatterSeriesRenderCache *cache);
public:
GLuint m_pointbuffer;
private:
+ void createRangeGradientUVs(ScatterSeriesRenderCache *cache,
+ QVector<QVector2D> &buffered_uvs);
+
+private:
QVector<QVector3D> m_bufferedPoints;
- uint m_oldRemoveIndex;
- bool m_oldRemove;
+ int m_oldRemoveIndex;
+ float m_scaleY;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/shaderhelper.cpp b/src/datavisualization/utils/shaderhelper.cpp
index 7fb237c6..bbd7fe0e 100644
--- a/src/datavisualization/utils/shaderhelper.cpp
+++ b/src/datavisualization/utils/shaderhelper.cpp
@@ -40,7 +40,37 @@ ShaderHelper::ShaderHelper(QObject *parent,
m_vertexShaderFile(vertexShader),
m_fragmentShaderFile(fragmentShader),
m_textureFile(texture),
- m_depthTextureFile(depthTexture)
+ m_depthTextureFile(depthTexture),
+ m_positionAttr(0),
+ m_uvAttr(0),
+ m_normalAttr(0),
+ m_colorUniform(0),
+ m_viewMatrixUniform(0),
+ m_modelMatrixUniform(0),
+ m_invTransModelMatrixUniform(0),
+ m_depthMatrixUniform(0),
+ m_mvpMatrixUniform(0),
+ m_lightPositionUniform(0),
+ m_lightStrengthUniform(0),
+ m_ambientStrengthUniform(0),
+ m_shadowQualityUniform(0),
+ m_textureUniform(0),
+ m_shadowUniform(0),
+ m_gradientMinUniform(0),
+ m_gradientHeightUniform(0),
+ m_lightColorUniform(0),
+ m_volumeSliceIndicesUniform(0),
+ m_colorIndexUniform(0),
+ m_cameraPositionRelativeToModelUniform(0),
+ m_color8BitUniform(0),
+ m_textureDimensionsUniform(0),
+ m_sampleCountUniform(0),
+ m_alphaMultiplierUniform(0),
+ m_preserveOpacityUniform(0),
+ m_minBoundsUniform(0),
+ m_maxBoundsUniform(0),
+ m_sliceFrameWidthUniform(0),
+ m_initialized(false)
{
}
@@ -93,6 +123,17 @@ void ShaderHelper::initialize()
m_gradientMinUniform = m_program->uniformLocation("gradMin");
m_gradientHeightUniform = m_program->uniformLocation("gradHeight");
m_lightColorUniform = m_program->uniformLocation("lightColor");
+ m_volumeSliceIndicesUniform = m_program->uniformLocation("volumeSliceIndices");
+ m_colorIndexUniform = m_program->uniformLocation("colorIndex");
+ m_cameraPositionRelativeToModelUniform = m_program->uniformLocation("cameraPositionRelativeToModel");
+ m_color8BitUniform = m_program->uniformLocation("color8Bit");
+ m_textureDimensionsUniform = m_program->uniformLocation("textureDimensions");
+ m_sampleCountUniform = m_program->uniformLocation("sampleCount");
+ m_alphaMultiplierUniform = m_program->uniformLocation("alphaMultiplier");
+ m_preserveOpacityUniform = m_program->uniformLocation("preserveOpacity");
+ m_minBoundsUniform = m_program->uniformLocation("minBounds");
+ m_maxBoundsUniform = m_program->uniformLocation("maxBounds");
+ m_sliceFrameWidthUniform = m_program->uniformLocation("sliceFrameWidth");
m_initialized = true;
}
@@ -125,151 +166,239 @@ void ShaderHelper::release()
m_program->release();
}
-void ShaderHelper::setUniformValue(GLuint uniform, const QVector3D &value)
+void ShaderHelper::setUniformValue(GLint uniform, const QVector2D &value)
{
m_program->setUniformValue(uniform, value);
}
-void ShaderHelper::setUniformValue(GLuint uniform, const QVector4D &value)
+void ShaderHelper::setUniformValue(GLint uniform, const QVector3D &value)
{
m_program->setUniformValue(uniform, value);
}
-void ShaderHelper::setUniformValue(GLuint uniform, const QMatrix4x4 &value)
+void ShaderHelper::setUniformValue(GLint uniform, const QVector4D &value)
{
m_program->setUniformValue(uniform, value);
}
-void ShaderHelper::setUniformValue(GLuint uniform, GLfloat value)
+void ShaderHelper::setUniformValue(GLint uniform, const QMatrix4x4 &value)
{
m_program->setUniformValue(uniform, value);
}
-void ShaderHelper::setUniformValue(GLuint uniform, GLint value)
+void ShaderHelper::setUniformValue(GLint uniform, GLfloat value)
{
m_program->setUniformValue(uniform, value);
}
-GLuint ShaderHelper::MVP()
+void ShaderHelper::setUniformValue(GLint uniform, GLint value)
+{
+ m_program->setUniformValue(uniform, value);
+}
+
+void ShaderHelper::setUniformValueArray(GLint uniform, const QVector4D *values, int count)
+{
+ m_program->setUniformValueArray(uniform, values, count);
+}
+
+GLint ShaderHelper::MVP()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_mvpMatrixUniform;
}
-GLuint ShaderHelper::view()
+GLint ShaderHelper::view()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_viewMatrixUniform;
}
-GLuint ShaderHelper::model()
+GLint ShaderHelper::model()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_modelMatrixUniform;
}
-GLuint ShaderHelper::nModel()
+GLint ShaderHelper::nModel()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_invTransModelMatrixUniform;
}
-GLuint ShaderHelper::depth()
+GLint ShaderHelper::depth()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_depthMatrixUniform;
}
-GLuint ShaderHelper::lightP()
+GLint ShaderHelper::lightP()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_lightPositionUniform;
}
-GLuint ShaderHelper::lightS()
+GLint ShaderHelper::lightS()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_lightStrengthUniform;
}
-GLuint ShaderHelper::ambientS()
+GLint ShaderHelper::ambientS()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_ambientStrengthUniform;
}
-GLuint ShaderHelper::shadowQ()
+GLint ShaderHelper::shadowQ()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_shadowQualityUniform;
}
-GLuint ShaderHelper::color()
+GLint ShaderHelper::color()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_colorUniform;
}
-GLuint ShaderHelper::texture()
+GLint ShaderHelper::texture()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_textureUniform;
}
-GLuint ShaderHelper::shadow()
+GLint ShaderHelper::shadow()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_shadowUniform;
}
-GLuint ShaderHelper::gradientMin()
+GLint ShaderHelper::gradientMin()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_gradientMinUniform;
}
-GLuint ShaderHelper::gradientHeight()
+GLint ShaderHelper::gradientHeight()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_gradientHeightUniform;
}
-GLuint ShaderHelper::lightColor()
+GLint ShaderHelper::lightColor()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_lightColorUniform;
}
-GLuint ShaderHelper::posAtt()
+GLint ShaderHelper::volumeSliceIndices()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_volumeSliceIndicesUniform;
+}
+
+GLint ShaderHelper::colorIndex()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_colorIndexUniform;
+}
+
+GLint ShaderHelper::cameraPositionRelativeToModel()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_cameraPositionRelativeToModelUniform;
+}
+
+GLint ShaderHelper::color8Bit()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_color8BitUniform;
+}
+
+GLint ShaderHelper::textureDimensions()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_textureDimensionsUniform;
+}
+
+GLint ShaderHelper::sampleCount()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_sampleCountUniform;
+}
+
+GLint ShaderHelper::alphaMultiplier()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_alphaMultiplierUniform;
+}
+
+GLint ShaderHelper::preserveOpacity()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_preserveOpacityUniform;
+}
+
+GLint ShaderHelper::maxBounds()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_maxBoundsUniform;
+}
+
+GLint ShaderHelper::minBounds()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_minBoundsUniform;
+}
+
+GLint ShaderHelper::sliceFrameWidth()
+{
+
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_sliceFrameWidthUniform;
+}
+
+GLint ShaderHelper::posAtt()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_positionAttr;
}
-GLuint ShaderHelper::uvAtt()
+GLint ShaderHelper::uvAtt()
{
if (!m_initialized)
qFatal("Shader not initialized");
return m_uvAttr;
}
-GLuint ShaderHelper::normalAtt()
+GLint ShaderHelper::normalAtt()
{
if (!m_initialized)
qFatal("Shader not initialized");
diff --git a/src/datavisualization/utils/shaderhelper_p.h b/src/datavisualization/utils/shaderhelper_p.h
index fdef0dff..812cba18 100644
--- a/src/datavisualization/utils/shaderhelper_p.h
+++ b/src/datavisualization/utils/shaderhelper_p.h
@@ -52,31 +52,44 @@ class ShaderHelper
bool testCompile();
void bind();
void release();
- void setUniformValue(GLuint uniform, const QVector3D &value);
- void setUniformValue(GLuint uniform, const QVector4D &value);
- void setUniformValue(GLuint uniform, const QMatrix4x4 &value);
- void setUniformValue(GLuint uniform, GLfloat value);
- void setUniformValue(GLuint uniform, GLint value);
-
- GLuint MVP();
- GLuint view();
- GLuint model();
- GLuint nModel();
- GLuint depth();
- GLuint lightP();
- GLuint lightS();
- GLuint ambientS();
- GLuint shadowQ();
- GLuint color();
- GLuint texture();
- GLuint shadow();
- GLuint gradientMin();
- GLuint gradientHeight();
- GLuint lightColor();
-
- GLuint posAtt();
- GLuint uvAtt();
- GLuint normalAtt();
+ void setUniformValue(GLint uniform, const QVector2D &value);
+ void setUniformValue(GLint uniform, const QVector3D &value);
+ void setUniformValue(GLint uniform, const QVector4D &value);
+ void setUniformValue(GLint uniform, const QMatrix4x4 &value);
+ void setUniformValue(GLint uniform, GLfloat value);
+ void setUniformValue(GLint uniform, GLint value);
+ void setUniformValueArray(GLint uniform, const QVector4D *values, int count);
+
+ GLint MVP();
+ GLint view();
+ GLint model();
+ GLint nModel();
+ GLint depth();
+ GLint lightP();
+ GLint lightS();
+ GLint ambientS();
+ GLint shadowQ();
+ GLint color();
+ GLint texture();
+ GLint shadow();
+ GLint gradientMin();
+ GLint gradientHeight();
+ GLint lightColor();
+ GLint volumeSliceIndices();
+ GLint colorIndex();
+ GLint cameraPositionRelativeToModel();
+ GLint color8Bit();
+ GLint textureDimensions();
+ GLint sampleCount();
+ GLint alphaMultiplier();
+ GLint preserveOpacity();
+ GLint maxBounds();
+ GLint minBounds();
+ GLint sliceFrameWidth();
+
+ GLint posAtt();
+ GLint uvAtt();
+ GLint normalAtt();
private:
QObject *m_caller;
@@ -88,25 +101,36 @@ class ShaderHelper
QString m_textureFile;
QString m_depthTextureFile;
- GLuint m_positionAttr;
- GLuint m_uvAttr;
- GLuint m_normalAttr;
-
- GLuint m_colorUniform;
- GLuint m_viewMatrixUniform;
- GLuint m_modelMatrixUniform;
- GLuint m_invTransModelMatrixUniform;
- GLuint m_depthMatrixUniform;
- GLuint m_mvpMatrixUniform;
- GLuint m_lightPositionUniform;
- GLuint m_lightStrengthUniform;
- GLuint m_ambientStrengthUniform;
- GLuint m_shadowQualityUniform;
- GLuint m_textureUniform;
- GLuint m_shadowUniform;
- GLuint m_gradientMinUniform;
- GLuint m_gradientHeightUniform;
- GLuint m_lightColorUniform;
+ GLint m_positionAttr;
+ GLint m_uvAttr;
+ GLint m_normalAttr;
+
+ GLint m_colorUniform;
+ GLint m_viewMatrixUniform;
+ GLint m_modelMatrixUniform;
+ GLint m_invTransModelMatrixUniform;
+ GLint m_depthMatrixUniform;
+ GLint m_mvpMatrixUniform;
+ GLint m_lightPositionUniform;
+ GLint m_lightStrengthUniform;
+ GLint m_ambientStrengthUniform;
+ GLint m_shadowQualityUniform;
+ GLint m_textureUniform;
+ GLint m_shadowUniform;
+ GLint m_gradientMinUniform;
+ GLint m_gradientHeightUniform;
+ GLint m_lightColorUniform;
+ GLint m_volumeSliceIndicesUniform;
+ GLint m_colorIndexUniform;
+ GLint m_cameraPositionRelativeToModelUniform;
+ GLint m_color8BitUniform;
+ GLint m_textureDimensionsUniform;
+ GLint m_sampleCountUniform;
+ GLint m_alphaMultiplierUniform;
+ GLint m_preserveOpacityUniform;
+ GLint m_minBoundsUniform;
+ GLint m_maxBoundsUniform;
+ GLint m_sliceFrameWidthUniform;
GLboolean m_initialized;
};
diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp
index d999ba90..b93030b1 100644
--- a/src/datavisualization/utils/surfaceobject.cpp
+++ b/src/datavisualization/utils/surfaceobject.cpp
@@ -30,26 +30,31 @@ SurfaceObject::SurfaceObject(Surface3DRenderer *renderer)
m_gridIndexCount(0),
m_axisCacheX(renderer->m_axisCacheX),
m_axisCacheY(renderer->m_axisCacheY),
- m_axisCacheZ(renderer->m_axisCacheZ)
-
+ m_axisCacheZ(renderer->m_axisCacheZ),
+ m_renderer(renderer),
+ m_returnTextureBuffer(false),
+ m_dataDimension(0),
+ m_oldDataDimension(-1)
{
m_indicesType = GL_UNSIGNED_INT;
- initializeOpenGLFunctions();
glGenBuffers(1, &m_vertexbuffer);
glGenBuffers(1, &m_normalbuffer);
glGenBuffers(1, &m_uvbuffer);
glGenBuffers(1, &m_elementbuffer);
glGenBuffers(1, &m_gridElementbuffer);
+ glGenBuffers(1, &m_uvTextureBuffer);
}
SurfaceObject::~SurfaceObject()
{
- if (QOpenGLContext::currentContext())
+ if (QOpenGLContext::currentContext()) {
glDeleteBuffers(1, &m_gridElementbuffer);
+ glDeleteBuffers(1, &m_uvTextureBuffer);
+ }
}
void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space,
- bool changeGeometry, bool flipXZ)
+ bool changeGeometry, bool polar, bool flipXZ)
{
m_columns = space.width();
m_rows = space.height();
@@ -59,6 +64,12 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
m_surfaceType = SurfaceSmooth;
+ checkDirections(dataArray);
+ bool indicesDirty = false;
+ if (m_dataDimension != m_oldDataDimension)
+ indicesDirty = true;
+ m_oldDataDimension = m_dataDimension;
+
// Create/populate vertix table
if (changeGeometry)
m_vertices.resize(totalSize);
@@ -68,17 +79,14 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
uvs.resize(totalSize);
int totalIndex = 0;
- AxisRenderCache &xCache = flipXZ ? m_axisCacheZ : m_axisCacheX;
- AxisRenderCache &zCache = flipXZ ? m_axisCacheX : m_axisCacheZ;
+ // Init min and max to ridiculous values
+ m_minY = 10000000.0;
+ m_maxY = -10000000.0f;
for (int i = 0; i < m_rows; i++) {
const QSurfaceDataRow &p = *dataArray.at(i);
for (int j = 0; j < m_columns; j++) {
- const QSurfaceDataItem &data = p.at(j);
- float normalizedX = xCache.positionAt(data.x());
- float normalizedY = m_axisCacheY.positionAt(data.y());
- float normalizedZ = zCache.positionAt(data.z());
- m_vertices[totalIndex] = QVector3D(normalizedX, normalizedY, normalizedZ);
+ getNormalizedVertex(p.at(j), m_vertices[totalIndex], polar, flipXZ);
if (changeGeometry)
uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY);
totalIndex++;
@@ -95,161 +103,305 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
// Create normals
int rowLimit = m_rows - 1;
int colLimit = m_columns - 1;
- int rowColLimit = rowLimit * m_columns;
- int totalLimit = totalSize - 1;
if (changeGeometry)
m_normals.resize(totalSize);
totalIndex = 0;
- const bool flipNormal = checkFlipNormal(dataArray);
- for (int row = 0; row < rowColLimit; row += m_columns) {
- for (int j = 0; j < colLimit; j++) {
- m_normals[totalIndex++] = normal(m_vertices.at(row + j),
- m_vertices.at(row + j + 1),
- m_vertices.at(row + m_columns + j),
- flipNormal);
- }
- int p = row + colLimit;
- m_normals[totalIndex++] = normal(m_vertices.at(p),
- m_vertices.at(p + m_columns),
- m_vertices.at(p - 1),
- flipNormal);
- }
- for (int j = rowColLimit; j < totalLimit; j++) {
- m_normals[totalIndex++] = normal(m_vertices.at(j),
- m_vertices.at(j - m_columns),
- m_vertices.at(j + 1),
- flipNormal);
+
+ if ((m_dataDimension == BothAscending) || (m_dataDimension == XDescending)) {
+ for (int row = 0; row < rowLimit; row++)
+ createSmoothNormalBodyLine(totalIndex, row * m_columns);
+ createSmoothNormalUpperLine(totalIndex);
+ } else { // BothDescending || ZDescending
+ createSmoothNormalUpperLine(totalIndex);
+ for (int row = 1; row < m_rows; row++)
+ createSmoothNormalBodyLine(totalIndex, row * m_columns);
}
- m_normals[totalIndex++] = normal(m_vertices.at(totalLimit),
- m_vertices.at(totalLimit - 1),
- m_vertices.at(totalLimit - m_columns),
- flipNormal);
// Create indices table
- if (changeGeometry)
+ if (changeGeometry || indicesDirty)
createSmoothIndices(0, 0, colLimit, rowLimit);
// Create line element indices
if (changeGeometry)
createSmoothGridlineIndices(0, 0, colLimit, rowLimit);
- createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry);
+ createBuffers(m_vertices, uvs, m_normals, 0);
}
-void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex)
+void SurfaceObject::createSmoothNormalBodyLine(int &totalIndex, int column)
+{
+ int colLimit = m_columns - 1;
+
+ if (m_dataDimension == BothAscending) {
+ int end = colLimit + column;
+ for (int j = column; j < end; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j + 1),
+ m_vertices.at(j + m_columns));
+ }
+ m_normals[totalIndex++] = normal(m_vertices.at(end),
+ m_vertices.at(end + m_columns),
+ m_vertices.at(end - 1));
+ } else if (m_dataDimension == XDescending) {
+ m_normals[totalIndex++] = normal(m_vertices.at(column),
+ m_vertices.at(column + m_columns),
+ m_vertices.at(column + 1));
+ int end = column + m_columns;
+ for (int j = column + 1; j < end; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j - 1),
+ m_vertices.at(j + m_columns));
+ }
+ } else if (m_dataDimension == ZDescending) {
+ int end = colLimit + column;
+ for (int j = column; j < end; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j + 1),
+ m_vertices.at(j - m_columns));
+ }
+ m_normals[totalIndex++] = normal(m_vertices.at(end),
+ m_vertices.at(end - m_columns),
+ m_vertices.at(end - 1));
+ } else { // BothDescending
+ m_normals[totalIndex++] = normal(m_vertices.at(column),
+ m_vertices.at(column - m_columns),
+ m_vertices.at(column + 1));
+ int end = column + m_columns;
+ for (int j = column + 1; j < end; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j - 1),
+ m_vertices.at(j - m_columns));
+ }
+ }
+}
+
+void SurfaceObject::createSmoothNormalUpperLine(int &totalIndex)
+{
+ if (m_dataDimension == BothAscending) {
+ int lineEnd = m_rows * m_columns - 1;
+ for (int j = (m_rows - 1) * m_columns; j < lineEnd; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j - m_columns),
+ m_vertices.at(j + 1));
+ }
+ m_normals[totalIndex++] = normal(m_vertices.at(lineEnd),
+ m_vertices.at(lineEnd - 1),
+ m_vertices.at(lineEnd - m_columns));
+ } else if (m_dataDimension == XDescending) {
+ int lineStart = (m_rows - 1) * m_columns;
+ int lineEnd = m_rows * m_columns;
+ m_normals[totalIndex++] = normal(m_vertices.at(lineStart),
+ m_vertices.at(lineStart + 1),
+ m_vertices.at(lineStart - m_columns));
+ for (int j = lineStart + 1; j < lineEnd; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j - m_columns),
+ m_vertices.at(j - 1));
+ }
+ } else if (m_dataDimension == ZDescending) {
+ int colLimit = m_columns - 1;
+ for (int j = 0; j < colLimit; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j + m_columns),
+ m_vertices.at(j + 1));
+ }
+ m_normals[totalIndex++] = normal(m_vertices.at(colLimit),
+ m_vertices.at(colLimit - 1),
+ m_vertices.at(colLimit + m_columns));
+ } else { // BothDescending
+ m_normals[totalIndex++] = normal(m_vertices.at(0),
+ m_vertices.at(1),
+ m_vertices.at(m_columns));
+ for (int j = 1; j < m_columns; j++) {
+ m_normals[totalIndex++] = normal(m_vertices.at(j),
+ m_vertices.at(j + m_columns),
+ m_vertices.at(j - 1));
+ }
+ }
+}
+
+QVector3D SurfaceObject::createSmoothNormalBodyLineItem(int x, int y)
+{
+ int p = y * m_columns + x;
+ if (m_dataDimension == BothAscending) {
+ if (x < m_columns - 1) {
+ return normal(m_vertices.at(p), m_vertices.at(p + 1),
+ m_vertices.at(p + m_columns));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p + m_columns),
+ m_vertices.at(p - 1));
+ }
+ } else if (m_dataDimension == XDescending) {
+ if (x == 0) {
+ return normal(m_vertices.at(p), m_vertices.at(p + m_columns),
+ m_vertices.at(p + 1));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p - 1),
+ m_vertices.at(p + m_columns));
+ }
+ } else if (m_dataDimension == ZDescending) {
+ if (x < m_columns - 1) {
+ return normal(m_vertices.at(p), m_vertices.at(p + 1),
+ m_vertices.at(p - m_columns));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p - m_columns),
+ m_vertices.at(p - 1));
+ }
+ } else { // BothDescending
+ if (x == 0) {
+ return normal(m_vertices.at(p), m_vertices.at(p - m_columns),
+ m_vertices.at(p + 1));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p - 1),
+ m_vertices.at(p - m_columns));
+ }
+ }
+}
+
+QVector3D SurfaceObject::createSmoothNormalUpperLineItem(int x, int y)
+{
+ int p = y * m_columns + x;
+ if (m_dataDimension == BothAscending) {
+ if (x < m_columns - 1) {
+ return normal(m_vertices.at(p), m_vertices.at(p - m_columns),
+ m_vertices.at(p + 1));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p - 1),
+ m_vertices.at(p - m_columns));
+ }
+ } else if (m_dataDimension == XDescending) {
+ if (x == 0) {
+ return normal(m_vertices.at(p), m_vertices.at(p + 1),
+ m_vertices.at(p - m_columns));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p - m_columns),
+ m_vertices.at(p - 1));
+ }
+ } else if (m_dataDimension == ZDescending) {
+ if (x < m_columns - 1) {
+ return normal(m_vertices.at(p), m_vertices.at(p + m_columns),
+ m_vertices.at(p + 1));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p - 1),
+ m_vertices.at(p + m_columns));
+ }
+ } else { // BothDescending
+ if (x == 0) {
+ return normal(m_vertices.at(0), m_vertices.at(1),
+ m_vertices.at(m_columns));
+ } else {
+ return normal(m_vertices.at(p), m_vertices.at(p + m_columns),
+ m_vertices.at(p - 1));
+ }
+ }
+}
+
+void SurfaceObject::smoothUVs(const QSurfaceDataArray &dataArray,
+ const QSurfaceDataArray &modelArray)
+{
+ int columns = dataArray.at(0)->size();
+ int rows = dataArray.size();
+ float xRangeNormalizer = dataArray.at(0)->at(columns - 1).x() - dataArray.at(0)->at(0).x();
+ float zRangeNormalizer = dataArray.at(rows - 1)->at(0).z() - dataArray.at(0)->at(0).z();
+ float xMin = dataArray.at(0)->at(0).x();
+ float zMin = dataArray.at(0)->at(0).z();
+ const bool zDescending = m_dataDimension.testFlag(SurfaceObject::ZDescending);
+ const bool xDescending = m_dataDimension.testFlag(SurfaceObject::XDescending);
+
+ QVector<QVector2D> uvs;
+ uvs.resize(m_rows * m_columns);
+ int index = 0;
+ for (int i = 0; i < m_rows; i++) {
+ float y = (modelArray.at(i)->at(0).z() - zMin) / zRangeNormalizer;
+ if (zDescending)
+ y = 1.0f - y;
+ const QSurfaceDataRow &p = *modelArray.at(i);
+ for (int j = 0; j < m_columns; j++) {
+ float x = (p.at(j).x() - xMin) / xRangeNormalizer;
+ if (xDescending)
+ x = 1.0f - x;
+ uvs[index] = QVector2D(x, y);
+ index++;
+ }
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvTextureBuffer);
+ glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
+ &uvs.at(0), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_returnTextureBuffer = true;
+}
+
+void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar)
{
// Update vertices
int p = rowIndex * m_columns;
const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex);
- for (int j = 0; j < m_columns; j++) {
- const QSurfaceDataItem &data = dataRow.at(j);
- float normalizedX = m_axisCacheX.positionAt(data.x());
- float normalizedY = m_axisCacheY.positionAt(data.y());
- float normalizedZ = m_axisCacheZ.positionAt(data.z());
- m_vertices[p++] = QVector3D(normalizedX, normalizedY, normalizedZ);
- }
+ for (int j = 0; j < m_columns; j++)
+ getNormalizedVertex(dataRow.at(j), m_vertices[p++], polar, false);
// Create normals
- int colLimit = m_columns - 1;
+ bool upwards = (m_dataDimension == BothAscending) || (m_dataDimension == XDescending);
int startRow = rowIndex;
- if (startRow > 0)
+ if ((startRow > 0) && upwards)
startRow--;
+ int endRow = rowIndex;
+ if (!upwards && (rowIndex < m_rows - 1))
+ endRow++;
+ if ((endRow == m_rows - 1) && upwards)
+ endRow--;
int totalIndex = startRow * m_columns;
- int rowLimit = (rowIndex + 1) * m_columns;
- if (rowIndex == m_rows - 1)
- rowLimit = rowIndex * m_columns; // The rowIndex is top most row, special handling
- const bool flipNormal = checkFlipNormal(dataArray);
- for (int row = totalIndex; row < rowLimit; row += m_columns) {
- for (int j = 0; j < colLimit; j++) {
- // One right and one up
- m_normals[totalIndex++] = normal(m_vertices.at(row + j),
- m_vertices.at(row + j + 1),
- m_vertices.at(row + m_columns + j),
- flipNormal);
- }
- int p = row + colLimit;
- // One up and one left
- m_normals[totalIndex++] = normal(m_vertices.at(p),
- m_vertices.at(p + m_columns),
- m_vertices.at(p - 1),
- flipNormal);
+ if ((startRow == 0) && !upwards) {
+ createSmoothNormalUpperLine(totalIndex);
+ startRow++;
}
- if (rowIndex == m_rows - 1) {
- // Top most line, nothing above, must have different handling.
- // Take from one down and one right. Read till second-to-last
- rowLimit = (rowIndex + 1) * m_columns - 1;
- for (int j = rowIndex * m_columns; j < rowLimit; j++) {
- m_normals[totalIndex++] = normal(m_vertices.at(j),
- m_vertices.at(j - m_columns),
- m_vertices.at(j + 1),
- flipNormal);
- }
- // Top left corner. Take from one left and one down
- m_normals[totalIndex++] = normal(m_vertices.at(rowLimit),
- m_vertices.at(rowLimit - 1),
- m_vertices.at(rowLimit - m_columns),
- flipNormal);
- }
+ for (int row = startRow; row <= endRow; row++)
+ createSmoothNormalBodyLine(totalIndex, row * m_columns);
+
+ if ((rowIndex == m_rows - 1) && upwards)
+ createSmoothNormalUpperLine(totalIndex);
}
-void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column)
+void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column,
+ bool polar)
{
// Update a vertice
- const QSurfaceDataItem &data = dataArray.at(row)->at(column);
- float normalizedX = m_axisCacheX.positionAt(data.x());
- float normalizedY = m_axisCacheY.positionAt(data.y());
- float normalizedZ = m_axisCacheZ.positionAt(data.z());
- m_vertices[row * m_columns + column] = QVector3D(normalizedX, normalizedY, normalizedZ);
+ getNormalizedVertex(dataArray.at(row)->at(column),
+ m_vertices[row * m_columns + column], polar, false);
// Create normals
+ bool upwards = (m_dataDimension == BothAscending) || (m_dataDimension == XDescending);
+ bool rightwards = (m_dataDimension == BothAscending) || (m_dataDimension == ZDescending);
int startRow = row;
- if (startRow > 0)
- startRow--; // Change the normal for previous row also
+ if ((startRow > 0) && upwards)
+ startRow--;
+ int endRow = row;
+ if (!upwards && (row < m_rows - 1))
+ endRow++;
+ if ((endRow == m_rows - 1) && upwards)
+ endRow--;
int startCol = column;
- if (startCol > 0)
+ if ((startCol > 0) && rightwards)
startCol--;
- int rightCol = m_columns - 1;
- int topRow = m_rows - 1;
+ int endCol = column;
+ if ((endCol < m_columns - 1) && !rightwards)
+ endCol++;
- const bool flipNormal = checkFlipNormal(dataArray);
- for (int i = startRow; i <= row; i++) {
- for (int j = startCol; j <= column; j++) {
+ for (int i = startRow; i <= endRow; i++) {
+ for (int j = startCol; j <= endCol; j++) {
int p = i * m_columns + j;
- if (i < topRow) {
- if (j < rightCol) {
- // One right and one up
- m_normals[p] = normal(m_vertices.at(p),
- m_vertices.at(p + 1),
- m_vertices.at(p + m_columns),
- flipNormal);
- } else {
- // Last item, nothing on the right. One up and one left
- m_normals[p] = normal(m_vertices.at(p),
- m_vertices.at(p + m_columns),
- m_vertices.at(p - 1),
- flipNormal);
- }
- } else {
- // Top most line, nothing above, must have different handling.
- if (j < rightCol) {
- // Take from one down and one right. Read till second-to-last
- m_normals[p] = normal(m_vertices.at(p),
- m_vertices.at(p - m_columns),
- m_vertices.at(p + 1),
- flipNormal);
- } else {
- // Top left corner. Take from one left and one down
- m_normals[p] = normal(m_vertices.at(p),
- m_vertices.at(p - 1),
- m_vertices.at(p - m_columns),
- flipNormal);
- }
- }
- }
+ if ((i == 0) && !upwards)
+ m_normals[p] = createSmoothNormalUpperLineItem(j, i);
+ else if ((i == m_rows - 1) && upwards)
+ m_normals[p] = createSmoothNormalUpperLineItem(j, i);
+ else
+ m_normals[p] = createSmoothNormalBodyLineItem(j, i);
+ }
}
}
@@ -271,15 +423,38 @@ void SurfaceObject::createSmoothIndices(int x, int y, int endX, int endY)
int rowEnd = endY * m_columns;
for (int row = y * m_columns; row < rowEnd; row += m_columns) {
for (int j = x; j < endX; j++) {
- // Left triangle
- indices[p++] = row + j + 1;
- indices[p++] = row + m_columns + j;
- indices[p++] = row + j;
-
- // Right triangle
- indices[p++] = row + m_columns + j + 1;
- indices[p++] = row + m_columns + j;
- indices[p++] = row + j + 1;
+ if ((m_dataDimension == BothAscending) || (m_dataDimension == BothDescending)) {
+ // Left triangle
+ indices[p++] = row + j + 1;
+ indices[p++] = row + m_columns + j;
+ indices[p++] = row + j;
+
+ // Right triangle
+ indices[p++] = row + m_columns + j + 1;
+ indices[p++] = row + m_columns + j;
+ indices[p++] = row + j + 1;
+ } else if (m_dataDimension == XDescending) {
+ // Right triangle
+ indices[p++] = row + m_columns + j;
+ indices[p++] = row + m_columns + j + 1;
+ indices[p++] = row + j;
+
+ // Left triangle
+ indices[p++] = row + j;
+ indices[p++] = row + m_columns + j + 1;
+ indices[p++] = row + j + 1;
+ } else {
+ // Left triangle
+ indices[p++] = row + m_columns + j;
+ indices[p++] = row + m_columns + j + 1;
+ indices[p++] = row + j;
+
+ // Right triangle
+ indices[p++] = row + j;
+ indices[p++] = row + m_columns + j + 1;
+ indices[p++] = row + j + 1;
+
+ }
}
}
@@ -331,7 +506,7 @@ void SurfaceObject::createSmoothGridlineIndices(int x, int y, int endX, int endY
}
void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space,
- bool changeGeometry, bool flipXZ)
+ bool changeGeometry, bool polar, bool flipXZ)
{
m_columns = space.width();
m_rows = space.height();
@@ -339,6 +514,12 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
+ checkDirections(dataArray);
+ bool indicesDirty = false;
+ if (m_dataDimension != m_oldDataDimension)
+ indicesDirty = true;
+ m_oldDataDimension = m_dataDimension;
+
m_surfaceType = SurfaceFlat;
// Create vertix table
@@ -355,17 +536,14 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
int doubleColumns = m_columns * 2 - 2;
int rowColLimit = rowLimit * doubleColumns;
- AxisRenderCache &xCache = flipXZ ? m_axisCacheZ : m_axisCacheX;
- AxisRenderCache &zCache = flipXZ ? m_axisCacheX : m_axisCacheZ;
+ // Init min and max to ridiculous values
+ m_minY = 10000000.0;
+ m_maxY = -10000000.0f;
for (int i = 0; i < m_rows; i++) {
const QSurfaceDataRow &row = *dataArray.at(i);
for (int j = 0; j < m_columns; j++) {
- const QSurfaceDataItem &data = row.at(j);
- float normalizedX = xCache.positionAt(data.x());
- float normalizedY = m_axisCacheY.positionAt(data.y());
- float normalizedZ = zCache.positionAt(data.z());
- m_vertices[totalIndex] = QVector3D(normalizedX, normalizedY, normalizedZ);
+ getNormalizedVertex(row.at(j), m_vertices[totalIndex], polar, flipXZ);
if (changeGeometry)
uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY);
@@ -389,42 +567,23 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
// Create normals & indices table
GLint *indices = 0;
- int p = 0;
- if (changeGeometry) {
+ if (changeGeometry || indicesDirty) {
int normalCount = 2 * colLimit * rowLimit;
m_indexCount = 3 * normalCount;
indices = new GLint[m_indexCount];
m_normals.resize(normalCount);
}
+ int p = 0;
totalIndex = 0;
- const bool flipNormal = checkFlipNormal(dataArray);
for (int row = 0, upperRow = doubleColumns;
row < rowColLimit;
row += doubleColumns, upperRow += doubleColumns) {
for (int j = 0; j < doubleColumns; j += 2) {
- // Normal for the left triangle
- m_normals[totalIndex++] = normal(m_vertices.at(row + j),
- m_vertices.at(row + j + 1),
- m_vertices.at(upperRow + j),
- flipNormal);
-
- // Normal for the right triangle
- m_normals[totalIndex++] = normal(m_vertices.at(row + j + 1),
- m_vertices.at(upperRow + j + 1),
- m_vertices.at(upperRow + j),
- flipNormal);
-
- if (changeGeometry) {
- // Left triangle
- indices[p++] = row + j + 1;
- indices[p++] = upperRow + j;
- indices[p++] = row + j;
+ createNormals(totalIndex, row, upperRow, j);
- // Right triangle
- indices[p++] = upperRow + j + 1;
- indices[p++] = upperRow + j;
- indices[p++] = row + j + 1;
+ if (changeGeometry || indicesDirty) {
+ createCoarseIndices(indices, p, row, upperRow, j);
}
}
}
@@ -433,12 +592,54 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
if (changeGeometry)
createCoarseGridlineIndices(0, 0, colLimit, rowLimit);
- createBuffers(m_vertices, uvs, m_normals, indices, changeGeometry);
+ createBuffers(m_vertices, uvs, m_normals, indices);
delete[] indices;
}
-void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex)
+void SurfaceObject::coarseUVs(const QSurfaceDataArray &dataArray,
+ const QSurfaceDataArray &modelArray)
+{
+ int columns = dataArray.at(0)->size();
+ int rows = dataArray.size();
+ float xRangeNormalizer = dataArray.at(0)->at(columns - 1).x() - dataArray.at(0)->at(0).x();
+ float zRangeNormalizer = dataArray.at(rows - 1)->at(0).z() - dataArray.at(0)->at(0).z();
+ float xMin = dataArray.at(0)->at(0).x();
+ float zMin = dataArray.at(0)->at(0).z();
+ const bool zDescending = m_dataDimension.testFlag(SurfaceObject::ZDescending);
+ const bool xDescending = m_dataDimension.testFlag(SurfaceObject::XDescending);
+
+ QVector<QVector2D> uvs;
+ uvs.resize(m_rows * m_columns * 2);
+ int index = 0;
+ int colLimit = m_columns - 1;
+ for (int i = 0; i < m_rows; i++) {
+ float y = (modelArray.at(i)->at(0).z() - zMin) / zRangeNormalizer;
+ if (zDescending)
+ y = 1.0f - y;
+ const QSurfaceDataRow &p = *modelArray.at(i);
+ for (int j = 0; j < m_columns; j++) {
+ float x = (p.at(j).x() - xMin) / xRangeNormalizer;
+ if (xDescending)
+ x = 1.0f - x;
+ uvs[index] = QVector2D(x, y);
+ index++;
+ if (j > 0 && j < colLimit) {
+ uvs[index] = uvs[index - 1];
+ index++;
+ }
+ }
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvTextureBuffer);
+ glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
+ &uvs.at(0), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_returnTextureBuffer = true;
+}
+
+void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar)
{
int colLimit = m_columns - 1;
int doubleColumns = m_columns * 2 - 2;
@@ -447,12 +648,7 @@ void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowI
const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex);
for (int j = 0; j < m_columns; j++) {
- const QSurfaceDataItem &data = dataRow.at(j);
- float normalizedX = m_axisCacheX.positionAt(data.x());
- float normalizedY = m_axisCacheY.positionAt(data.y());
- float normalizedZ = m_axisCacheZ.positionAt(data.z());
- m_vertices[p++] = QVector3D(normalizedX, normalizedY, normalizedZ);
-
+ getNormalizedVertex(dataRow.at(j), m_vertices[p++], polar, false);
if (j > 0 && j < colLimit) {
m_vertices[p] = m_vertices[p - 1];
p++;
@@ -466,39 +662,23 @@ void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowI
int rowLimit = (rowIndex + 1) * doubleColumns;
if (rowIndex == m_rows - 1)
rowLimit = rowIndex * doubleColumns; //Topmost row, no normals
- const bool flipNormal = checkFlipNormal(dataArray);
for (int row = p, upperRow = p + doubleColumns;
row < rowLimit;
row += doubleColumns, upperRow += doubleColumns) {
- for (int j = 0; j < doubleColumns; j += 2) {
- // Normal for the left triangle
- m_normals[p++] = normal(m_vertices.at(row + j),
- m_vertices.at(row + j + 1),
- m_vertices.at(upperRow + j),
- flipNormal);
-
- // Normal for the right triangle
- m_normals[p++] = normal(m_vertices.at(row + j + 1),
- m_vertices.at(upperRow + j + 1),
- m_vertices.at(upperRow + j),
- flipNormal);
- }
+ for (int j = 0; j < doubleColumns; j += 2)
+ createNormals(p, row, upperRow, j);
}
}
-void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column)
+void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column,
+ bool polar)
{
int colLimit = m_columns - 1;
int doubleColumns = m_columns * 2 - 2;
// Update a vertice
int p = row * doubleColumns + column * 2 - (column > 0);
- const QSurfaceDataItem &data = dataArray.at(row)->at(column);
- float normalizedX = m_axisCacheX.positionAt(data.x());
- float normalizedY = m_axisCacheY.positionAt(data.y());
- float normalizedZ = m_axisCacheZ.positionAt(data.z());
- m_vertices[p] = QVector3D(normalizedX, normalizedY, normalizedZ);
- p++;
+ getNormalizedVertex(dataArray.at(row)->at(column), m_vertices[p++], polar, false);
if (column > 0 && column < colLimit)
m_vertices[p] = m_vertices[p - 1];
@@ -515,27 +695,15 @@ void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row
if (column == m_columns - 1)
column--;
- const bool flipNormal = checkFlipNormal(dataArray);
for (int i = startRow; i <= row; i++) {
for (int j = startCol; j <= column; j++) {
p = i * doubleColumns + j * 2;
- // Normal for the left triangle
- m_normals[p] = normal(m_vertices.at(p),
- m_vertices.at(p + 1),
- m_vertices.at(p + doubleColumns),
- flipNormal);
- p++;
-
- // Normal for the right triangle
- m_normals[p] = normal(m_vertices.at(p),
- m_vertices.at(p + doubleColumns),
- m_vertices.at(p + doubleColumns - 1),
- flipNormal);
+ createNormals(p, i * doubleColumns, (i + 1) * doubleColumns, j * 2);
}
}
}
-void SurfaceObject::createCoarseIndices(int x, int y, int columns, int rows)
+void SurfaceObject::createCoarseSubSection(int x, int y, int columns, int rows)
{
if (columns > m_columns)
columns = m_columns;
@@ -557,17 +725,8 @@ void SurfaceObject::createCoarseIndices(int x, int y, int columns, int rows)
for (int row = y * doubleColumns, upperRow = (y + 1) * doubleColumns;
row < rowColLimit;
row += doubleColumns, upperRow += doubleColumns) {
- for (int j = 2 * x; j < doubleColumnsLimit; j += 2) {
- // Left triangle
- indices[p++] = row + j + 1;
- indices[p++] = upperRow + j;
- indices[p++] = row + j;
-
- // Right triangle
- indices[p++] = upperRow + j + 1;
- indices[p++] = upperRow + j;
- indices[p++] = row + j + 1;
- }
+ for (int j = 2 * x; j < doubleColumnsLimit; j += 2)
+ createCoarseIndices(indices, p, row, upperRow, j);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
@@ -631,12 +790,11 @@ void SurfaceObject::createCoarseGridlineIndices(int x, int y, int endX, int endY
void SurfaceObject::uploadBuffers()
{
QVector<QVector2D> uvs; // Empty dummy
- createBuffers(m_vertices, uvs, m_normals, 0, false);
+ createBuffers(m_vertices, uvs, m_normals, 0);
}
void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs,
- const QVector<QVector3D> &normals, const GLint *indices,
- bool changeGeometry)
+ const QVector<QVector3D> &normals, const GLint *indices)
{
// Move to buffers
glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer);
@@ -647,30 +805,62 @@ void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVec
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(QVector3D),
&normals.at(0), GL_DYNAMIC_DRAW);
- if (changeGeometry) {
+ if (uvs.size()) {
glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
&uvs.at(0), GL_STATIC_DRAW);
+ }
- if (indices) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint),
- indices, GL_STATIC_DRAW);
- }
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ if (indices) {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint),
+ indices, GL_STATIC_DRAW);
}
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_meshDataLoaded = true;
}
-bool SurfaceObject::checkFlipNormal(const QSurfaceDataArray &array)
+void SurfaceObject::checkDirections(const QSurfaceDataArray &array)
+{
+ m_dataDimension = BothAscending;
+
+ if (array.at(0)->at(0).x() > array.at(0)->at(array.at(0)->size() - 1).x())
+ m_dataDimension |= XDescending;
+ if (m_axisCacheX.reversed())
+ m_dataDimension ^= XDescending;
+
+ if (array.at(0)->at(0).z() > array.at(array.size() - 1)->at(0).z())
+ m_dataDimension |= ZDescending;
+ if (m_axisCacheZ.reversed())
+ m_dataDimension ^= ZDescending;
+}
+
+void SurfaceObject::getNormalizedVertex(const QSurfaceDataItem &data, QVector3D &vertex,
+ bool polar, bool flipXZ)
{
- const bool ascendingX = array.at(0)->at(0).x() < array.at(0)->at(array.at(0)->size() - 1).x();
- const bool ascendingZ = array.at(0)->at(0).z() < array.at(array.size() - 1)->at(0).z();
- return ascendingX != ascendingZ;
+ float normalizedX;
+ float normalizedZ;
+ if (polar) {
+ // Slice don't use polar, so don't care about flip
+ m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ);
+ } else {
+ if (flipXZ) {
+ normalizedX = m_axisCacheZ.positionAt(data.x());
+ normalizedZ = m_axisCacheX.positionAt(data.z());
+ } else {
+ normalizedX = m_axisCacheX.positionAt(data.x());
+ normalizedZ = m_axisCacheZ.positionAt(data.z());
+ }
+ }
+ float normalizedY = m_axisCacheY.positionAt(data.y());
+ m_minY = qMin(normalizedY, m_minY);
+ m_maxY = qMax(normalizedY, m_maxY);
+ vertex.setX(normalizedX);
+ vertex.setY(normalizedY);
+ vertex.setZ(normalizedZ);
}
GLuint SurfaceObject::gridElementBuf()
@@ -680,6 +870,17 @@ GLuint SurfaceObject::gridElementBuf()
return m_gridElementbuffer;
}
+GLuint SurfaceObject::uvBuf()
+{
+ if (!m_meshDataLoaded)
+ qFatal("No loaded object");
+
+ if (m_returnTextureBuffer)
+ return m_uvTextureBuffer;
+ else
+ return m_uvbuffer;
+}
+
GLuint SurfaceObject::gridIndexCount()
{
return m_gridIndexCount;
@@ -707,14 +908,74 @@ void SurfaceObject::clear()
m_normals.clear();
}
-QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c,
- bool flipNormal)
+void SurfaceObject::createCoarseIndices(GLint *indices, int &p, int row, int upperRow, int j)
+{
+ if ((m_dataDimension == BothAscending) || (m_dataDimension == BothDescending)) {
+ // Left triangle
+ indices[p++] = row + j + 1;
+ indices[p++] = upperRow + j;
+ indices[p++] = row + j;
+
+ // Right triangle
+ indices[p++] = upperRow + j + 1;
+ indices[p++] = upperRow + j;
+ indices[p++] = row + j + 1;
+ } else if (m_dataDimension == XDescending) {
+ indices[p++] = upperRow + j;
+ indices[p++] = upperRow + j + 1;
+ indices[p++] = row + j;
+
+ indices[p++] = row + j;
+ indices[p++] = upperRow + j + 1;
+ indices[p++] = row + j + 1;
+ } else {
+ // Left triangle
+ indices[p++] = upperRow + j;
+ indices[p++] = upperRow + j + 1;
+ indices[p++] = row + j;
+
+ // Right triangle
+ indices[p++] = row + j;
+ indices[p++] = upperRow + j + 1;
+ indices[p++] = row + j + 1;
+ }
+}
+
+void SurfaceObject::createNormals(int &p, int row, int upperRow, int j)
+{
+ if ((m_dataDimension == BothAscending) || (m_dataDimension == BothDescending)) {
+ m_normals[p++] = normal(m_vertices.at(row + j),
+ m_vertices.at(row + j + 1),
+ m_vertices.at(upperRow + j));
+
+ m_normals[p++] = normal(m_vertices.at(row + j + 1),
+ m_vertices.at(upperRow + j + 1),
+ m_vertices.at(upperRow + j));
+ } else if (m_dataDimension == XDescending) {
+ m_normals[p++] = normal(m_vertices.at(row + j),
+ m_vertices.at(upperRow + j),
+ m_vertices.at(upperRow + j + 1));
+
+ m_normals[p++] = normal(m_vertices.at(row + j + 1),
+ m_vertices.at(row + j),
+ m_vertices.at(upperRow + j + 1));
+ } else {
+ m_normals[p++] = normal(m_vertices.at(row + j),
+ m_vertices.at(upperRow + j),
+ m_vertices.at(upperRow + j + 1));
+
+ m_normals[p++] = normal(m_vertices.at(row + j + 1),
+ m_vertices.at(row + j),
+ m_vertices.at(upperRow + j + 1));
+ }
+}
+
+QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c)
{
QVector3D v1 = b - a;
QVector3D v2 = c - a;
QVector3D normal = QVector3D::crossProduct(v1, v2);
- if (flipNormal)
- normal *= -1;
+
return normal;
}
diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h
index 9c18dcb2..e7b61310 100644
--- a/src/datavisualization/utils/surfaceobject_p.h
+++ b/src/datavisualization/utils/surfaceobject_p.h
@@ -49,34 +49,55 @@ public:
Undefined
};
+ enum DataDimension {
+ BothAscending = 0,
+ XDescending = 1,
+ ZDescending = 2,
+ BothDescending = XDescending | ZDescending
+ };
+ Q_DECLARE_FLAGS(DataDimensions, DataDimension)
+
public:
SurfaceObject(Surface3DRenderer *renderer);
- ~SurfaceObject();
+ virtual ~SurfaceObject();
void setUpData(const QSurfaceDataArray &dataArray, const QRect &space,
- bool changeGeometry, bool flipXZ = false);
+ bool changeGeometry, bool polar, bool flipXZ = false);
void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space,
- bool changeGeometry, bool flipXZ = false);
- void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex);
- void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow);
- void updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column);
- void updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column);
+ bool changeGeometry, bool polar, bool flipXZ = false);
+ void smoothUVs(const QSurfaceDataArray &dataArray, const QSurfaceDataArray &modelArray);
+ void coarseUVs(const QSurfaceDataArray &dataArray, const QSurfaceDataArray &modelArray);
+ void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar);
+ void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow, bool polar);
+ void updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column, bool polar);
+ void updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column, bool polar);
void createSmoothIndices(int x, int y, int endX, int endY);
- void createCoarseIndices(int x, int y, int columns, int rows);
+ void createCoarseSubSection(int x, int y, int columns, int rows);
void createSmoothGridlineIndices(int x, int y, int endX, int endY);
void createCoarseGridlineIndices(int x, int y, int endX, int endY);
void uploadBuffers();
GLuint gridElementBuf();
+ GLuint uvBuf();
GLuint gridIndexCount();
QVector3D vertexAt(int column, int row);
void clear();
+ float minYValue() const { return m_minY; }
+ float maxYValue() const { return m_maxY; }
+ inline void activateSurfaceTexture(bool value) { m_returnTextureBuffer = value; }
private:
- QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c, bool flipNormal);
+ void createCoarseIndices(GLint *indices, int &p, int row, int upperRow, int j);
+ void createNormals(int &p, int row, int upperRow, int j);
+ void createSmoothNormalBodyLine(int &totalIndex, int column);
+ void createSmoothNormalUpperLine(int &totalIndex);
+ QVector3D createSmoothNormalBodyLineItem(int x, int y);
+ QVector3D createSmoothNormalUpperLineItem(int x, int y);
+ QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c);
void createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs,
- const QVector<QVector3D> &normals, const GLint *indices,
- bool changeGeometry);
- bool checkFlipNormal(const QSurfaceDataArray &array);
+ const QVector<QVector3D> &normals, const GLint *indices);
+ void checkDirections(const QSurfaceDataArray &array);
+ inline void getNormalizedVertex(const QSurfaceDataItem &data, QVector3D &vertex, bool polar,
+ bool flipXZ);
private:
SurfaceType m_surfaceType;
@@ -90,6 +111,13 @@ private:
AxisRenderCache &m_axisCacheX;
AxisRenderCache &m_axisCacheY;
AxisRenderCache &m_axisCacheZ;
+ Surface3DRenderer *m_renderer;
+ float m_minY;
+ float m_maxY;
+ GLuint m_uvTextureBuffer;
+ bool m_returnTextureBuffer;
+ SurfaceObject::DataDimensions m_dataDimension;
+ SurfaceObject::DataDimensions m_oldDataDimension;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/texturehelper.cpp b/src/datavisualization/utils/texturehelper.cpp
index 2a2a89dd..3944fb0c 100644
--- a/src/datavisualization/utils/texturehelper.cpp
+++ b/src/datavisualization/utils/texturehelper.cpp
@@ -21,12 +21,29 @@
#include <QtGui/QImage>
#include <QtGui/QPainter>
+#include <QtCore/QTime>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+// Defined in shaderhelper.cpp
+extern void discardDebugMsgs(QtMsgType type, const QMessageLogContext &context, const QString &msg);
+
TextureHelper::TextureHelper()
{
initializeOpenGLFunctions();
+#if !defined(QT_OPENGL_ES_2)
+ if (!Utils::isOpenGLES()) {
+ // Discard warnings about deprecated functions
+ QtMessageHandler handler = qInstallMessageHandler(discardDebugMsgs);
+
+ m_openGlFunctions_2_1 =
+ QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_1>();
+ m_openGlFunctions_2_1->initializeOpenGLFunctions();
+
+ // Restore original message handler
+ qInstallMessageHandler(handler);
+ }
+#endif
}
TextureHelper::~TextureHelper()
@@ -41,17 +58,16 @@ GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFilt
QImage texImage = image;
-#if defined(QT_OPENGL_ES_2)
- GLuint temp;
- GLuint imageWidth = Utils::getNearestPowerOfTwo(image.width(), temp);
- GLuint imageHeight = Utils::getNearestPowerOfTwo(image.height(), temp);
- if (smoothScale) {
- texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation);
- } else {
- texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio);
+ if (!Utils::isOpenGLES()) {
+ GLuint imageWidth = Utils::getNearestPowerOfTwo(image.width());
+ GLuint imageHeight = Utils::getNearestPowerOfTwo(image.height());
+ if (smoothScale) {
+ texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio,
+ Qt::SmoothTransformation);
+ } else {
+ texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio);
+ }
}
-#endif
GLuint textureId;
glGenTextures(1, &textureId);
@@ -73,6 +89,53 @@ GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFilt
if (clampY)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
+
+ return textureId;
+}
+
+GLuint TextureHelper::create3DTexture(const QVector<uchar> *data, int width, int height, int depth,
+ QImage::Format dataFormat)
+{
+ if (Utils::isOpenGLES() || !width || !height || !depth)
+ return 0;
+
+ GLuint textureId = 0;
+#if defined(QT_OPENGL_ES_2)
+ Q_UNUSED(dataFormat)
+ Q_UNUSED(data)
+#else
+ glEnable(GL_TEXTURE_3D);
+
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_3D, textureId);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ GLenum status = glGetError();
+ // glGetError docs advise to call glGetError in loop to clear all error flags
+ while (status)
+ status = glGetError();
+
+ GLint internalFormat = 4;
+ GLint format = GL_BGRA;
+ if (dataFormat == QImage::Format_Indexed8) {
+ internalFormat = 1;
+ format = GL_RED;
+ // Align width to 32bits
+ width = width + width % 4;
+ }
+ m_openGlFunctions_2_1->glTexImage3D(GL_TEXTURE_3D, 0, internalFormat, width, height, depth, 0,
+ format, GL_UNSIGNED_BYTE, data->constData());
+ status = glGetError();
+ if (status)
+ qWarning() << __FUNCTION__ << "3D texture creation failed:" << status;
+
+ glBindTexture(GL_TEXTURE_3D, 0);
+ glDisable(GL_TEXTURE_3D);
+#endif
return textureId;
}
@@ -113,14 +176,27 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
glBindTexture(GL_TEXTURE_2D, 0);
// Create render buffer
- if (!depthBuffer)
- glGenRenderbuffers(1, &depthBuffer);
+ if (depthBuffer)
+ glDeleteRenderbuffers(1, &depthBuffer);
+
+ glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
-#if !defined(QT_OPENGL_ES_2)
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height());
-#else
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.width(), size.height());
-#endif
+ GLenum status = glGetError();
+ // glGetError docs advise to call glGetError in loop to clear all error flags
+ while (status)
+ status = glGetError();
+ if (Utils::isOpenGLES())
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.width(), size.height());
+ else
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height());
+
+ status = glGetError();
+ if (status) {
+ qCritical() << "Selection texture render buffer creation failed:" << status;
+ glDeleteTextures(1, &textureid);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ return 0;
+ }
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// Create frame buffer
@@ -134,10 +210,11 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
// Verify that the frame buffer is complete
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
- qCritical() << "Frame buffer creation failed" << status;
- return 0;
+ qCritical() << "Selection texture frame buffer creation failed:" << status;
+ glDeleteTextures(1, &textureid);
+ textureid = 0;
}
// Restore the default framebuffer
@@ -146,6 +223,31 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
return textureid;
}
+GLuint TextureHelper::createCursorPositionTexture(const QSize &size, GLuint &frameBuffer)
+{
+ GLuint textureid;
+ glGenTextures(1, &textureid);
+ glBindTexture(GL_TEXTURE_2D, textureid);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffers(1, &frameBuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ textureid, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Cursor position mapper frame buffer creation failed:" << status;
+ glDeleteTextures(1, &textureid);
+ textureid = 0;
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return textureid;
+}
+
GLuint TextureHelper::createUniformTexture(const QColor &color)
{
QImage image(QSize(int(uniformTextureWidth), int(uniformTextureHeight)),
@@ -170,76 +272,64 @@ GLuint TextureHelper::createGradientTexture(const QLinearGradient &gradient)
return create2DTexture(image, false, true, false, true);
}
-#if !defined(QT_OPENGL_ES_2)
GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint textureSize)
{
- GLuint depthtextureid;
-
- // Create depth texture for the shadow mapping
- glGenTextures(1, &depthtextureid);
- glBindTexture(GL_TEXTURE_2D, depthtextureid);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width() * textureSize,
- size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
- glBindTexture(GL_TEXTURE_2D, 0);
-
+ GLuint depthtextureid = 0;
+#if defined(QT_OPENGL_ES_2)
+ Q_UNUSED(size)
+ Q_UNUSED(textureSize)
+#else
+ if (!Utils::isOpenGLES()) {
+ // Create depth texture for the shadow mapping
+ glGenTextures(1, &depthtextureid);
+ glBindTexture(GL_TEXTURE_2D, depthtextureid);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width() * textureSize,
+ size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+#endif
return depthtextureid;
}
-#endif
-#if !defined(QT_OPENGL_ES_2)
GLuint TextureHelper::createDepthTextureFrameBuffer(const QSize &size, GLuint &frameBuffer,
GLuint textureSize)
{
GLuint depthtextureid = createDepthTexture(size, textureSize);
+#if defined(QT_OPENGL_ES_2)
+ Q_UNUSED(frameBuffer)
+#else
+ if (!Utils::isOpenGLES()) {
+ // Create frame buffer
+ if (!frameBuffer)
+ glGenFramebuffers(1, &frameBuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+
+ // Attach texture to depth attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthtextureid, 0);
+
+ m_openGlFunctions_2_1->glDrawBuffer(GL_NONE);
+ m_openGlFunctions_2_1->glReadBuffer(GL_NONE);
+
+ // Verify that the frame buffer is complete
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Depth texture frame buffer creation failed" << status;
+ glDeleteTextures(1, &depthtextureid);
+ depthtextureid = 0;
+ }
- // Create frame buffer
- if (!frameBuffer)
- glGenFramebuffers(1, &frameBuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
-
- // Attach texture to depth attachment
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthtextureid, 0);
-
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
-
- // Verify that the frame buffer is complete
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- qCritical() << "Frame buffer creation failed" << status;
- return 0;
+ // Restore the default framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-
- // Restore the default framebuffer
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- return depthtextureid;
-}
#endif
-
-#if !defined(QT_OPENGL_ES_2)
-void TextureHelper::fillDepthTexture(GLuint texture,const QSize &size, GLuint textureSize,
- GLfloat value)
-{
- int nItems = size.width() * textureSize * size.height() * textureSize;
- GLfloat *bits = new GLfloat[nItems];
- for (int i = 0; i < nItems; i++)
- bits[i] = value;
-
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width() * textureSize,
- size.height() * textureSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, bits);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- delete[] bits;
+ return depthtextureid;
}
-#endif
void TextureHelper::deleteTexture(GLuint *texture)
{
diff --git a/src/datavisualization/utils/texturehelper_p.h b/src/datavisualization/utils/texturehelper_p.h
index aec137a4..6c0aa3de 100644
--- a/src/datavisualization/utils/texturehelper_p.h
+++ b/src/datavisualization/utils/texturehelper_p.h
@@ -32,6 +32,10 @@
#include "datavisualizationglobal_p.h"
#include <QtGui/QRgb>
#include <QtGui/QLinearGradient>
+#if !defined(QT_OPENGL_ES_2)
+// 3D Textures are not supported by ES set
+# include <QtGui/QOpenGLFunctions_2_1>
+#endif
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -44,17 +48,17 @@ class TextureHelper : protected QOpenGLFunctions
// Ownership of created texture is transferred to caller
GLuint create2DTexture(const QImage &image, bool useTrilinearFiltering = false,
bool convert = true, bool smoothScale = true, bool clampY = false);
+ GLuint create3DTexture(const QVector<uchar> *data, int width, int height, int depth,
+ QImage::Format dataFormat);
GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
// Returns selection texture and inserts generated framebuffers to framebuffer parameters
GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer);
+ GLuint createCursorPositionTexture(const QSize &size, GLuint &frameBuffer);
GLuint createUniformTexture(const QColor &color);
GLuint createGradientTexture(const QLinearGradient &gradient);
-#if !defined(QT_OPENGL_ES_2)
GLuint createDepthTexture(const QSize &size, GLuint textureSize);
// Returns depth texture and inserts generated framebuffer to parameter
GLuint createDepthTextureFrameBuffer(const QSize &size, GLuint &frameBuffer, GLuint textureSize);
- void fillDepthTexture(GLuint texture, const QSize &size, GLuint textureSize, GLfloat value);
-#endif
void deleteTexture(GLuint *texture);
private:
@@ -62,9 +66,13 @@ class TextureHelper : protected QOpenGLFunctions
void convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage, GLenum texture_format);
QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format);
+#if !defined(QT_OPENGL_ES_2)
+ QOpenGLFunctions_2_1 *m_openGlFunctions_2_1; // Not owned
+#endif
friend class Bars3DRenderer;
friend class Surface3DRenderer;
friend class Scatter3DRenderer;
+ friend class Abstract3DRenderer;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/utils.cpp b/src/datavisualization/utils/utils.cpp
index 2368d86a..cb64eb8f 100644
--- a/src/datavisualization/utils/utils.cpp
+++ b/src/datavisualization/utils/utils.cpp
@@ -17,6 +17,7 @@
****************************************************************************/
#include "utils_p.h"
+#include "qutils.h"
#include <QtGui/QPainter>
@@ -25,11 +26,12 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
#define NUM_IN_POWER(y, x) for (;y<x;y<<=1)
#define MIN_POWER 2
-GLuint Utils::getNearestPowerOfTwo(GLuint value, GLuint &padding)
+static GLint maxTextureSize = 0; // Safe, as all instances have the same texture size
+
+GLuint Utils::getNearestPowerOfTwo(GLuint value)
{
GLuint powOfTwoValue = MIN_POWER;
NUM_IN_POWER(powOfTwoValue, value);
- padding = powOfTwoValue - value;
return powOfTwoValue;
}
@@ -54,35 +56,76 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
const QColor &txtColor, bool labelBackground,
bool borders, int maxLabelWidth)
{
+ if (maxTextureSize == 0) {
+ QOpenGLContext::currentContext()->functions()->glGetIntegerv(
+ GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+ }
GLuint paddingWidth = 20;
GLuint paddingHeight = 20;
+ GLuint prePadding = 20;
+ GLint targetWidth = maxTextureSize;
+
// Calculate text dimensions
QFont valueFont = font;
valueFont.setPointSize(textureFontSize);
QFontMetrics valueFM(valueFont);
int valueStrWidth = valueFM.width(text);
- if (maxLabelWidth && labelBackground)
+
+ // ES2 needs to use maxLabelWidth always (when given) because of the power of 2 -issue.
+ if (maxLabelWidth && (labelBackground || Utils::isOpenGLES()))
valueStrWidth = maxLabelWidth;
int valueStrHeight = valueFM.height();
valueStrWidth += paddingWidth / 2; // Fix clipping problem with skewed fonts (italic or italic-style)
QSize labelSize;
+ qreal fontRatio = 1.0;
-#if defined(QT_OPENGL_ES_2)
- // ES2 can't handle textures with dimensions not in power of 2. Resize labels accordingly.
- // Add some padding before converting to power of two to avoid too tight fit
- GLuint prePadding = 5;
- // ES2 needs to use this always (when given) because of the power of 2 -issue.
- if (maxLabelWidth)
- valueStrWidth = maxLabelWidth + paddingWidth / 2;
- labelSize = QSize(valueStrWidth + prePadding, valueStrHeight + prePadding);
- labelSize.setWidth(getNearestPowerOfTwo(labelSize.width(), paddingWidth));
- labelSize.setHeight(getNearestPowerOfTwo(labelSize.height(), paddingHeight));
-#else
- if (!labelBackground)
- labelSize = QSize(valueStrWidth, valueStrHeight);
- else
- labelSize = QSize(valueStrWidth + paddingWidth * 2, valueStrHeight + paddingHeight * 2);
-#endif
+ if (Utils::isOpenGLES()) {
+ // Test if text with slighly smaller font would fit into one step smaller texture
+ // ie. if the text is just exceeded the smaller texture boundary, it would
+ // make a label with large empty space
+ uint testWidth = getNearestPowerOfTwo(valueStrWidth + prePadding) >> 1;
+ int diffToFit = (valueStrWidth + prePadding) - testWidth;
+ int maxSqueeze = int((valueStrWidth + prePadding) * 0.1f);
+ if (diffToFit < maxSqueeze && maxTextureSize > GLint(testWidth))
+ targetWidth = testWidth;
+ }
+
+ bool sizeOk = false;
+ int currentFontSize = textureFontSize;
+ do {
+ if (Utils::isOpenGLES()) {
+ // ES2 can't handle textures with dimensions not in power of 2. Resize labels accordingly.
+ // Add some padding before converting to power of two to avoid too tight fit
+ labelSize = QSize(valueStrWidth + prePadding, valueStrHeight + prePadding);
+ labelSize.setWidth(getNearestPowerOfTwo(labelSize.width()));
+ labelSize.setHeight(getNearestPowerOfTwo(labelSize.height()));
+ } else {
+ if (!labelBackground)
+ labelSize = QSize(valueStrWidth, valueStrHeight);
+ else
+ labelSize = QSize(valueStrWidth + paddingWidth * 2, valueStrHeight + paddingHeight * 2);
+ }
+
+ if (!maxTextureSize || (labelSize.width() <= maxTextureSize
+ && (labelSize.width() <= targetWidth || !Utils::isOpenGLES()))) {
+ // Make sure the label is not too wide
+ sizeOk = true;
+ } else if (--currentFontSize == 4) {
+ qCritical() << "Label" << text << "is too long to be generated.";
+ return QImage();
+ } else {
+ fontRatio = (qreal)currentFontSize / (qreal)textureFontSize;
+ // Reduce font size and try again
+ valueFont.setPointSize(currentFontSize);
+ QFontMetrics currentValueFM(valueFont);
+ if (maxLabelWidth && (labelBackground || Utils::isOpenGLES()))
+ valueStrWidth = maxLabelWidth * fontRatio;
+ else
+ valueStrWidth = currentValueFM.width(text);
+ valueStrHeight = currentValueFM.height();
+ valueStrWidth += paddingWidth / 2;
+ }
+ } while (!sizeOk);
// Create image
QImage image = QImage(labelSize, QImage::Format_ARGB32);
@@ -96,27 +139,30 @@ QImage Utils::printTextToImage(const QFont &font, const QString &text, const QCo
painter.setFont(valueFont);
if (!labelBackground) {
painter.setPen(txtColor);
-#if defined(QT_OPENGL_ES_2)
- painter.drawText((labelSize.width() - valueStrWidth) / 2.0f,
- (labelSize.height() - valueStrHeight) / 2.0f,
- valueStrWidth, valueStrHeight,
- Qt::AlignCenter | Qt::AlignVCenter,
- text);
-#else
- painter.drawText(0, 0,
- valueStrWidth, valueStrHeight,
- Qt::AlignCenter | Qt::AlignVCenter,
- text);
-#endif
+ if (Utils::isOpenGLES()) {
+ painter.drawText((labelSize.width() - valueStrWidth) / 2.0f,
+ (labelSize.height() - valueStrHeight) / 2.0f,
+ valueStrWidth, valueStrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+ } else {
+ painter.drawText(0, 0,
+ valueStrWidth, valueStrHeight,
+ Qt::AlignCenter | Qt::AlignVCenter,
+ text);
+ }
} else {
painter.setBrush(QBrush(bgrColor));
+ qreal radius = 10.0 * fontRatio;
if (borders) {
- painter.setPen(QPen(QBrush(txtColor), 5, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
- painter.drawRoundedRect(5, 5, labelSize.width() - 10, labelSize.height() - 10,
- 10.0, 10.0);
+ painter.setPen(QPen(QBrush(txtColor), 5.0 * fontRatio,
+ Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
+ painter.drawRoundedRect(5, 5,
+ labelSize.width() - 10, labelSize.height() - 10,
+ radius, radius);
} else {
painter.setPen(bgrColor);
- painter.drawRoundedRect(0, 0, labelSize.width(), labelSize.height(), 10.0, 10.0);
+ painter.drawRoundedRect(0, 0, labelSize.width(), labelSize.height(), radius, radius);
}
painter.setPen(txtColor);
painter.drawText((labelSize.width() - valueStrWidth) / 2.0f,
@@ -133,62 +179,74 @@ QVector4D Utils::getSelection(QPoint mousepos, int height)
// This is the only one that works with OpenGL ES 2.0, so we're forced to use it
// Item count will be limited to 256*256*256
GLubyte pixel[4] = {255, 255, 255, 255};
- glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
- (void *)pixel);
+ QOpenGLContext::currentContext()->functions()->glReadPixels(mousepos.x(), height - mousepos.y(),
+ 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+ (void *)pixel);
QVector4D selectedColor(pixel[0], pixel[1], pixel[2], pixel[3]);
return selectedColor;
}
-QImage Utils::getGradientImage(const QLinearGradient &gradient)
+QImage Utils::getGradientImage(QLinearGradient &gradient)
{
- QImage image(QSize(1, 101), QImage::Format_RGB32);
+ QImage image(QSize(gradientTextureWidth, gradientTextureHeight), QImage::Format_RGB32);
+ gradient.setFinalStop(qreal(gradientTextureWidth), qreal(gradientTextureHeight));
+ gradient.setStart(0.0, 0.0);
+
QPainter pmp(&image);
pmp.setBrush(QBrush(gradient));
pmp.setPen(Qt::NoPen);
- pmp.drawRect(0, 0, 1, 101);
+ pmp.drawRect(0, 0, int(gradientTextureWidth), int(gradientTextureHeight));
return image;
}
-Utils::ParamType Utils::mapFormatCharToParamType(const QChar &formatChar)
+Utils::ParamType Utils::preParseFormat(const QString &format, QString &preStr, QString &postStr,
+ int &precision, char &formatSpec)
{
- ParamType retVal = ParamTypeUnknown;
- if (formatChar == QLatin1Char('d')
- || formatChar == QLatin1Char('i')
- || formatChar == QLatin1Char('c')) {
- retVal = ParamTypeInt;
- } else if (formatChar == QLatin1Char('u')
- || formatChar == QLatin1Char('o')
- || formatChar == QLatin1Char('x')
- || formatChar == QLatin1Char('X')) {
- retVal = ParamTypeUInt;
- } else if (formatChar == QLatin1Char('f')
- || formatChar == QLatin1Char('F')
- || formatChar == QLatin1Char('e')
- || formatChar == QLatin1Char('E')
- || formatChar == QLatin1Char('g')
- || formatChar == QLatin1Char('G')) {
- retVal = ParamTypeReal;
+ static QRegExp formatMatcher(QStringLiteral("^([^%]*)%([\\-\\+#\\s\\d\\.lhjztL]*)([dicuoxfegXFEG])(.*)$"));
+ static QRegExp precisionMatcher(QStringLiteral("\\.(\\d+)"));
+
+ Utils::ParamType retVal;
+
+ if (formatMatcher.indexIn(format, 0) != -1) {
+ preStr = formatMatcher.cap(1);
+ // Six and 'g' are defaults in Qt API
+ precision = 6;
+ if (!formatMatcher.cap(2).isEmpty()) {
+ if (precisionMatcher.indexIn(formatMatcher.cap(2), 0) != -1)
+ precision = precisionMatcher.cap(1).toInt();
+ }
+ if (formatMatcher.cap(3).isEmpty())
+ formatSpec = 'g';
+ else
+ formatSpec = formatMatcher.cap(3).at(0).toLatin1();
+ postStr = formatMatcher.cap(4);
+ retVal = mapFormatCharToParamType(formatSpec);
+ } else {
+ retVal = ParamTypeUnknown;
+ // The out parameters are irrelevant in unknown case
}
return retVal;
}
-Utils::ParamType Utils::findFormatParamType(const QString &format)
+Utils::ParamType Utils::mapFormatCharToParamType(char formatSpec)
{
- static QRegExp formatMatcher(QStringLiteral("%[\\-\\+#\\s\\d\\.lhjztL]*([dicuoxfegXFEG])"));
-
- if (formatMatcher.indexIn(format, 0) != -1) {
- QString capStr = formatMatcher.cap(1);
- if (capStr.isEmpty())
- return ParamTypeUnknown;
- else
- return mapFormatCharToParamType(capStr.at(0));
+ ParamType retVal = ParamTypeUnknown;
+ if (formatSpec == 'd' || formatSpec == 'i' || formatSpec == 'c') {
+ retVal = ParamTypeInt;
+ } else if (formatSpec == 'u' || formatSpec == 'o'
+ || formatSpec == 'x'|| formatSpec == 'X') {
+ retVal = ParamTypeUInt;
+ } else if (formatSpec == 'f' || formatSpec == 'F'
+ || formatSpec == 'e' || formatSpec == 'E'
+ || formatSpec == 'g' || formatSpec == 'G') {
+ retVal = ParamTypeReal;
}
- return ParamTypeUnknown;
+ return retVal;
}
-QString Utils::formatLabel(const QByteArray &format, ParamType paramType, qreal value)
+QString Utils::formatLabelSprintf(const QByteArray &format, Utils::ParamType paramType, qreal value)
{
switch (paramType) {
case ParamTypeInt:
@@ -198,7 +256,24 @@ QString Utils::formatLabel(const QByteArray &format, ParamType paramType, qreal
case ParamTypeReal:
return QString().sprintf(format, value);
default:
- return QString::fromUtf8(format); // To detect errors
+ // Return format string to detect errors. Bars selection label logic also depends on this.
+ return QString::fromUtf8(format);
+ }
+}
+
+QString Utils::formatLabelLocalized(Utils::ParamType paramType, qreal value,
+ const QLocale &locale, const QString &preStr, const QString &postStr,
+ int precision, char formatSpec, const QByteArray &format)
+{
+ switch (paramType) {
+ case ParamTypeInt:
+ case ParamTypeUInt:
+ return preStr + locale.toString(qint64(value)) + postStr;
+ case ParamTypeReal:
+ return preStr + locale.toString(value, formatSpec, precision) + postStr;
+ default:
+ // Return format string to detect errors. Bars selection label logic also depends on this.
+ return QString::fromUtf8(format);
}
}
@@ -238,4 +313,41 @@ QQuaternion Utils::calculateRotation(const QVector3D &xyzRotations)
return totalRotation;
}
+bool Utils::isOpenGLES()
+{
+#if defined(QT_OPENGL_ES_2)
+ return true;
+#elif (QT_VERSION < QT_VERSION_CHECK(5, 3, 0))
+ return false;
+#else
+ static bool resolved = false;
+ static bool isES = false;
+ if (!resolved) {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QWindow *dummySurface = 0;
+ if (!ctx) {
+ QSurfaceFormat surfaceFormat = qDefaultSurfaceFormat();
+ dummySurface = new QWindow();
+ dummySurface->setSurfaceType(QWindow::OpenGLSurface);
+ dummySurface->setFormat(surfaceFormat);
+ dummySurface->create();
+ ctx = new QOpenGLContext;
+ ctx->setFormat(surfaceFormat);
+ ctx->create();
+ ctx->makeCurrent(dummySurface);
+ }
+
+ isES = ctx->isOpenGLES();
+ resolved = true;
+
+ if (dummySurface) {
+ ctx->doneCurrent();
+ delete ctx;
+ delete dummySurface;
+ }
+ }
+ return isES;
+#endif
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/utils.pri b/src/datavisualization/utils/utils.pri
index 30bfb156..904407b8 100644
--- a/src/datavisualization/utils/utils.pri
+++ b/src/datavisualization/utils/utils.pri
@@ -22,3 +22,5 @@ SOURCES += $$PWD/meshloader.cpp \
$$PWD/surfaceobject.cpp \
$$PWD/scatterobjectbufferhelper.cpp \
$$PWD/scatterpointbufferhelper.cpp
+
+INCLUDEPATH += $$PWD
diff --git a/src/datavisualization/utils/utils_p.h b/src/datavisualization/utils/utils_p.h
index d7187c16..1a46c731 100644
--- a/src/datavisualization/utils/utils_p.h
+++ b/src/datavisualization/utils/utils_p.h
@@ -45,7 +45,7 @@ public:
ParamTypeReal
};
- static GLuint getNearestPowerOfTwo(GLuint value, GLuint &padding);
+ static GLuint getNearestPowerOfTwo(GLuint value);
static QVector4D vectorFromColor(const QColor &color);
static QColor colorFromVector(const QVector3D &colorVector);
static QColor colorFromVector(const QVector4D &colorVector);
@@ -57,17 +57,22 @@ public:
bool borders = false,
int maxLabelWidth = 0);
static QVector4D getSelection(QPoint mousepos, int height);
- static QImage getGradientImage(const QLinearGradient &gradient);
+ static QImage getGradientImage(QLinearGradient &gradient);
- static ParamType findFormatParamType(const QString &format);
- static QString formatLabel(const QByteArray &format, ParamType paramType, qreal value);
+ static ParamType preParseFormat(const QString &format, QString &preStr, QString &postStr,
+ int &precision, char &formatSpec);
+ static QString formatLabelSprintf(const QByteArray &format, ParamType paramType, qreal value);
+ static QString formatLabelLocalized(ParamType paramType, qreal value,
+ const QLocale &locale, const QString &preStr, const QString &postStr,
+ int precision, char formatSpec, const QByteArray &format);
static QString defaultLabelFormat();
static float wrapValue(float value, float min, float max);
static QQuaternion calculateRotation(const QVector3D &xyzRotations);
+ static bool isOpenGLES();
private:
- static ParamType mapFormatCharToParamType(const QChar &formatChar);
+ static ParamType mapFormatCharToParamType(char formatSpec);
};
QT_END_NAMESPACE_DATAVISUALIZATION