diff options
author | Mika Salmela <mika.salmela@digia.com> | 2014-10-03 16:47:44 +0300 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@digia.com> | 2014-10-06 11:34:27 +0300 |
commit | 90ac955006749ecf6ea021bc7cf736a6c21095af (patch) | |
tree | 690bf1af7e0bce7287ab2b240b857a66dbd33742 /src | |
parent | 2788e9f7412fa650f41b25fad1f4b02efb0e5e89 (diff) |
Fix surface normals on ascending/descending
Normals and triangles are generated according to data direction.
Task-number: QTRD-3160
Change-Id: Ia4286467682628930da3d82b204fd1ec078a396a
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/datavisualization/utils/surfaceobject.cpp | 555 | ||||
-rw-r--r-- | src/datavisualization/utils/surfaceobject_p.h | 24 |
2 files changed, 379 insertions, 200 deletions
diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index f8dae6f4..c91075e5 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -32,7 +32,9 @@ SurfaceObject::SurfaceObject(Surface3DRenderer *renderer) m_axisCacheY(renderer->m_axisCacheY), m_axisCacheZ(renderer->m_axisCacheZ), m_renderer(renderer), - m_returnTextureBuffer(false) + m_returnTextureBuffer(false), + m_dataDimension(0), + m_oldDataDimension(-1) { m_indicesType = GL_UNSIGNED_INT; initializeOpenGLFunctions(); @@ -63,6 +65,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); @@ -96,46 +104,198 @@ 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::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, @@ -179,48 +339,27 @@ void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowI 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, @@ -231,50 +370,33 @@ void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row 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); + } } } @@ -296,15 +418,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; + + } } } @@ -364,6 +509,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 @@ -411,42 +562,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); } } } @@ -455,7 +587,7 @@ 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; } @@ -519,23 +651,11 @@ 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); } } @@ -564,27 +684,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; @@ -606,17 +714,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); @@ -680,12 +779,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); @@ -696,30 +794,37 @@ 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) { - 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; + 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, @@ -792,14 +897,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 f373eb5d..39d10445 100644 --- a/src/datavisualization/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -49,6 +49,13 @@ public: Undefined }; + enum DataDimensions { + BothAscending = 0, + XDescending = 1, + ZDescending = 2, + BothDescending = XDescending | ZDescending + }; + public: SurfaceObject(Surface3DRenderer *renderer); virtual ~SurfaceObject(); @@ -64,7 +71,7 @@ public: 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(); @@ -78,11 +85,16 @@ public: 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); @@ -103,6 +115,8 @@ private: float m_maxY; GLuint m_uvTextureBuffer; bool m_returnTextureBuffer; + int m_dataDimension; + int m_oldDataDimension; }; QT_END_NAMESPACE_DATAVISUALIZATION |