summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/utils/surfaceobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/utils/surfaceobject.cpp')
-rw-r--r--src/datavisualization/utils/surfaceobject.cpp211
1 files changed, 117 insertions, 94 deletions
diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp
index 9bcdfee2..d999ba90 100644
--- a/src/datavisualization/utils/surfaceobject.cpp
+++ b/src/datavisualization/utils/surfaceobject.cpp
@@ -17,17 +17,21 @@
****************************************************************************/
#include "surfaceobject_p.h"
-#include "abstractobjecthelper_p.h"
+#include "surface3drenderer_p.h"
#include <QtGui/QVector2D>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-SurfaceObject::SurfaceObject()
+SurfaceObject::SurfaceObject(Surface3DRenderer *renderer)
: m_surfaceType(Undefined),
m_columns(0),
m_rows(0),
- m_gridIndexCount(0)
+ m_gridIndexCount(0),
+ m_axisCacheX(renderer->m_axisCacheX),
+ m_axisCacheY(renderer->m_axisCacheY),
+ m_axisCacheZ(renderer->m_axisCacheZ)
+
{
m_indicesType = GL_UNSIGNED_INT;
initializeOpenGLFunctions();
@@ -45,16 +49,11 @@ SurfaceObject::~SurfaceObject()
}
void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space,
- GLfloat yRange, GLfloat yMin, bool changeGeometry)
+ bool changeGeometry, bool flipXZ)
{
m_columns = space.width();
m_rows = space.height();
int totalSize = m_rows * m_columns;
- GLfloat xMin = dataArray.at(0)->at(0).x();
- GLfloat zMin = dataArray.at(0)->at(0).z();
- GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
- GLfloat yNormalizer = yRange / 2.0f;
- GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
@@ -68,21 +67,31 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
if (changeGeometry)
uvs.resize(totalSize);
int totalIndex = 0;
+
+ AxisRenderCache &xCache = flipXZ ? m_axisCacheZ : m_axisCacheX;
+ AxisRenderCache &zCache = flipXZ ? m_axisCacheX : m_axisCacheZ;
+
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 = ((data.x() - xMin) / xNormalizer);
- float normalizedY = ((data.y() - yMin) / yNormalizer);
- float normalizedZ = ((data.z() - zMin) / zNormalizer);
- m_vertices[totalIndex] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f,
- normalizedZ + 1.0f);
+ 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);
if (changeGeometry)
uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY);
totalIndex++;
}
}
+ if (flipXZ) {
+ for (int i = 0; i < m_vertices.size(); i++) {
+ m_vertices[i].setX(-m_vertices.at(i).x());
+ m_vertices[i].setZ(-m_vertices.at(i).z());
+ }
+ }
+
// Create normals
int rowLimit = m_rows - 1;
int colLimit = m_columns - 1;
@@ -92,25 +101,30 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
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));
+ 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));
+ 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));
+ m_vertices.at(j + 1),
+ flipNormal);
}
m_normals[totalIndex++] = normal(m_vertices.at(totalLimit),
m_vertices.at(totalLimit - 1),
- m_vertices.at(totalLimit - m_columns));
+ m_vertices.at(totalLimit - m_columns),
+ flipNormal);
// Create indices table
if (changeGeometry)
@@ -123,24 +137,18 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry);
}
-void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex,
- GLfloat yRange, GLfloat yMin)
+void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex)
{
- GLfloat xMin = dataArray.at(0)->at(0).x();
- GLfloat zMin = dataArray.at(0)->at(0).z();
- GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
- GLfloat yNormalizer = yRange / 2.0f;
- GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
-
// 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 = ((data.x() - xMin) / xNormalizer);
- float normalizedY = ((data.y() - yMin) / yNormalizer);
- float normalizedZ = ((data.z() - zMin) / zNormalizer);
- m_vertices[p++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+ 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);
}
// Create normals
@@ -153,18 +161,21 @@ void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowI
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));
+ 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));
+ m_vertices.at(p - 1),
+ flipNormal);
}
if (rowIndex == m_rows - 1) {
// Top most line, nothing above, must have different handling.
@@ -173,32 +184,26 @@ void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowI
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));
+ 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));
+ m_vertices.at(rowLimit - m_columns),
+ flipNormal);
}
}
-void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row,
- int column, GLfloat yRange, GLfloat yMin)
+void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column)
{
- GLfloat xMin = dataArray.at(0)->at(0).x();
- GLfloat zMin = dataArray.at(0)->at(0).z();
- GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
- GLfloat yNormalizer = yRange / 2.0f;
- GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
-
// Update a vertice
const QSurfaceDataItem &data = dataArray.at(row)->at(column);
- float normalizedX = ((data.x() - xMin) / xNormalizer);
- float normalizedY = ((data.y() - yMin) / yNormalizer);
- float normalizedZ = ((data.z() - zMin) / zNormalizer);
- m_vertices[row * m_columns + column] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f,
- normalizedZ + 1.0f);
+ 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);
// Create normals
int startRow = row;
@@ -210,6 +215,7 @@ void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row
int rightCol = m_columns - 1;
int topRow = m_rows - 1;
+ const bool flipNormal = checkFlipNormal(dataArray);
for (int i = startRow; i <= row; i++) {
for (int j = startCol; j <= column; j++) {
int p = i * m_columns + j;
@@ -218,12 +224,14 @@ void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row
// One right and one up
m_normals[p] = normal(m_vertices.at(p),
m_vertices.at(p + 1),
- m_vertices.at(p + m_columns));
+ 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));
+ m_vertices.at(p - 1),
+ flipNormal);
}
} else {
// Top most line, nothing above, must have different handling.
@@ -231,12 +239,14 @@ void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row
// 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));
+ 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));
+ m_vertices.at(p - m_columns),
+ flipNormal);
}
}
}
@@ -321,16 +331,11 @@ void SurfaceObject::createSmoothGridlineIndices(int x, int y, int endX, int endY
}
void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space,
- GLfloat yRange, GLfloat yMin, bool changeGeometry)
+ bool changeGeometry, bool flipXZ)
{
m_columns = space.width();
m_rows = space.height();
int totalSize = m_rows * m_columns * 2;
- GLfloat xMin = dataArray.at(0)->at(0).x();
- GLfloat zMin = dataArray.at(0)->at(0).z();
- GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
- GLfloat yNormalizer = yRange / 2.0f;
- GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
@@ -350,15 +355,17 @@ 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;
+
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 = ((data.x() - xMin) / xNormalizer);
- float normalizedY = ((data.y() - yMin) / yNormalizer);
- float normalizedZ = ((data.z() - zMin) / zNormalizer);
- m_vertices[totalIndex] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f,
- normalizedZ + 1.0f);
+ 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);
if (changeGeometry)
uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY);
@@ -373,6 +380,13 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
}
}
+ if (flipXZ) {
+ for (int i = 0; i < m_vertices.size(); i++) {
+ m_vertices[i].setX(-m_vertices.at(i).x());
+ m_vertices[i].setZ(-m_vertices.at(i).z());
+ }
+ }
+
// Create normals & indices table
GLint *indices = 0;
int p = 0;
@@ -384,6 +398,7 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
}
totalIndex = 0;
+ const bool flipNormal = checkFlipNormal(dataArray);
for (int row = 0, upperRow = doubleColumns;
row < rowColLimit;
row += doubleColumns, upperRow += doubleColumns) {
@@ -391,12 +406,14 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
// 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));
+ 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));
+ m_vertices.at(upperRow + j),
+ flipNormal);
if (changeGeometry) {
// Left triangle
@@ -421,26 +438,20 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
delete[] indices;
}
-void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex,
- GLfloat yRange, GLfloat yMin)
+void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex)
{
- GLfloat xMin = dataArray.at(0)->at(0).x();
- GLfloat zMin = dataArray.at(0)->at(0).z();
- GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
- GLfloat yNormalizer = yRange / 2.0f;
- GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
-
int colLimit = m_columns - 1;
int doubleColumns = m_columns * 2 - 2;
int p = rowIndex * doubleColumns;
const QSurfaceDataRow &dataRow = *dataArray.at(rowIndex);
+
for (int j = 0; j < m_columns; j++) {
const QSurfaceDataItem &data = dataRow.at(j);
- float normalizedX = ((data.x() - xMin) / xNormalizer);
- float normalizedY = ((data.y() - yMin) / yNormalizer);
- float normalizedZ = ((data.z() - zMin) / zNormalizer);
- m_vertices[p++] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+ 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);
if (j > 0 && j < colLimit) {
m_vertices[p] = m_vertices[p - 1];
@@ -455,6 +466,7 @@ 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) {
@@ -462,35 +474,30 @@ void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowI
// 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));
+ 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));
+ m_vertices.at(upperRow + j),
+ flipNormal);
}
}
}
-void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row,
- int column, GLfloat yRange, GLfloat yMin)
+void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column)
{
- GLfloat xMin = dataArray.at(0)->at(0).x();
- GLfloat zMin = dataArray.at(0)->at(0).z();
- GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f;
- GLfloat yNormalizer = yRange / 2.0f;
- GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f;
-
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 = ((data.x() - xMin) / xNormalizer);
- float normalizedY = ((data.y() - yMin) / yNormalizer);
- float normalizedZ = ((data.z() - zMin) / zNormalizer);
- m_vertices[p] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f);
+ 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++;
if (column > 0 && column < colLimit)
@@ -508,19 +515,22 @@ 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));
+ 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));
+ m_vertices.at(p + doubleColumns - 1),
+ flipNormal);
}
}
}
@@ -656,6 +666,13 @@ void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVec
m_meshDataLoaded = true;
}
+bool SurfaceObject::checkFlipNormal(const QSurfaceDataArray &array)
+{
+ 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;
+}
+
GLuint SurfaceObject::gridElementBuf()
{
if (!m_meshDataLoaded)
@@ -686,13 +703,19 @@ void SurfaceObject::clear()
m_gridIndexCount = 0;
m_indexCount = 0;
m_surfaceType = Undefined;
+ m_vertices.clear();
+ m_normals.clear();
}
-QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c)
+QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c,
+ bool flipNormal)
{
QVector3D v1 = b - a;
QVector3D v2 = c - a;
- return QVector3D::crossProduct(v1, v2);
+ QVector3D normal = QVector3D::crossProduct(v1, v2);
+ if (flipNormal)
+ normal *= -1;
+ return normal;
}
QT_END_NAMESPACE_DATAVISUALIZATION