diff options
Diffstat (limited to 'src/datavisualization/utils/surfaceobject.cpp')
-rw-r--r-- | src/datavisualization/utils/surfaceobject.cpp | 211 |
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 |