From de3661089cb85701d7444bbf517711783df3aa49 Mon Sep 17 00:00:00 2001 From: Mika Salmela Date: Tue, 26 Nov 2013 15:48:51 +0200 Subject: Better proxy API for surface Part 1, row change. More is on the way. Change-Id: I4e152a5160275f2d629e7793d4d40b85082a2fc2 Reviewed-by: Miikka Heikkinen --- src/datavisualization/utils/surfaceobject.cpp | 361 +++++++++++++++++++++----- src/datavisualization/utils/surfaceobject_p.h | 10 +- 2 files changed, 304 insertions(+), 67 deletions(-) (limited to 'src/datavisualization/utils') diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index c4d8532e..81945900 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -105,58 +105,164 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR m_vertices.at(j - m_columns), m_vertices.at(j + 1)); } - int p = m_rows * colLimit; - m_normals[totalIndex++] = normal(m_vertices.at(p), - m_vertices.at(p - 1), - m_vertices.at(p - m_columns - 1)); + m_normals[totalIndex++] = normal(m_vertices.at(totalLimit), + m_vertices.at(totalLimit - 1), + m_vertices.at(totalLimit - m_columns)); // Create indices table - GLint *indices = 0; - if (changeGeometry) { - m_indexCount = 6 * colLimit * rowLimit; - indices = new GLint[m_indexCount]; - p = 0; - for (int row = 0; row < rowLimit * m_columns; row += m_columns) { - for (int j = 0; j < colLimit; j++) { - // Left triangle - indices[p++] = row + j + 1; - indices[p++] = row + m_columns + j; - indices[p++] = row + j; + if (changeGeometry) + createSmoothIndices(0, 0, colLimit, rowLimit); - // Right triangle - indices[p++] = row + m_columns + j + 1; - indices[p++] = row + m_columns + j; - indices[p++] = row + j + 1; - } + // Create line element indices + if (changeGeometry) + createSmoothGridlineIndices(0, 0, colLimit, rowLimit); + + createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry); +} + +void SurfaceObject::updateSmoothRows(const QSurfaceDataArray &dataArray, int startRow, + int endRow, GLfloat yRange, GLfloat yMin) +{ + 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 totalIndex = startRow * m_columns; + for (int i = startRow; i < endRow; 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); } } - // Create line element indices - GLint *gridIndices = 0; - if (changeGeometry) { - m_gridIndexCount = 2 * m_columns * rowLimit + 2 * m_rows * colLimit; - gridIndices = new GLint[m_gridIndexCount]; - p = 0; - for (int i = 0, row = 0; i < m_rows; i++, row += m_columns) { + // Create normals + int colLimit = m_columns - 1; + int rowColLimit = endRow * m_columns; + if (endRow == m_rows) + rowColLimit = (endRow - 1) * m_columns; + int totalLimit = endRow * m_columns - 1; + + totalIndex = startRow * m_columns; + if (startRow > 0) { + // Change the normals for the previous row also + totalIndex -= m_columns; + } + if (totalIndex < (m_rows - 1) * m_columns) { + for (int row = totalIndex; row < rowColLimit; row += m_columns) { for (int j = 0; j < colLimit; j++) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + 1; + // 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)); } + 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)); } - for (int i = 0, row = 0; i < rowLimit; i++, row += m_columns) { - for (int j = 0; j < m_columns; j++) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + m_columns; - } + } + if (endRow == m_rows) { + // Top most line, nothing above, must have different handling. + // Take from one down and one right. Read till second-to-last + 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)); + } + + // Top left corner. Take from one left and one down + m_normals[totalIndex++] = normal(m_vertices.at(totalLimit), + m_vertices.at(totalLimit - 1), + m_vertices.at(totalLimit - m_columns)); + } + + QVector uvs; // Empty dummy + createBuffers(m_vertices, uvs, m_normals, 0, false); +} + +void SurfaceObject::createSmoothIndices(int x, int y, int endX, int endY) +{ + if (endX >= m_columns) + endX = m_columns - 1; + if (endY >= m_rows) + endY = m_rows - 1; + if (x > endX) + x = endX - 1; + if (y > endY) + y = endY - 1; + + m_indexCount = 6 * (endX - x) * (endY - y); + GLint *indices = new GLint[m_indexCount]; + int p = 0; + 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; } } - createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry); + 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); delete[] indices; - delete[] gridIndices; } +void SurfaceObject::createSmoothGridlineIndices(int x, int y, int endX, int endY) +{ + if (endX >= m_columns) + endX = m_columns - 1; + if (endY >= m_rows) + endY = m_rows - 1; + if (x > endX) + x = endX - 1; + if (y > endY) + y = endY - 1; + + int nColumns = endX - x + 1; + int nRows = endY - y + 1; + m_gridIndexCount = 2 * nColumns * (nRows - 1) + 2 * nRows * (nColumns - 1); + GLint *gridIndices = new GLint[m_gridIndexCount]; + int p = 0; + for (int i = y, row = m_columns * y; i <= endY; i++, row += m_columns) { + for (int j = x; j < endX; j++) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + 1; + } + } + for (int i = y, row = m_columns * y; i < endY; i++, row += m_columns) { + for (int j = x; j <= endX; j++) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + m_columns; + } + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), + gridIndices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + delete[] gridIndices; +} void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, GLfloat yMin, bool changeGeometry) @@ -250,38 +356,164 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s } // Create grid line element indices - GLint *gridIndices = 0; - if (changeGeometry) { - m_gridIndexCount = 2 * m_columns * rowLimit + 2 * m_rows * colLimit; - gridIndices = new GLint[m_gridIndexCount]; - p = 0; - int fullRowLimit = m_rows * doubleColumns; - for (int row = 0; row < fullRowLimit; row += doubleColumns) { - for (int j = 0; j < doubleColumns; j += 2) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + 1; + if (changeGeometry) + createCoarseGridlineIndices(0, 0, colLimit, rowLimit); + + createBuffers(m_vertices, uvs, m_normals, indices, changeGeometry); + + delete[] indices; +} - if (row < rowColLimit) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + doubleColumns; - } +void SurfaceObject::updateCoarseRows(const QSurfaceDataArray &dataArray, int startRow, + int endRow, GLfloat yRange, GLfloat yMin) +{ + 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 totalIndex = startRow * doubleColumns; + + for (int i = startRow; i < endRow; 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); + + if (j > 0 && j < colLimit) { + m_vertices[totalIndex] = m_vertices[totalIndex - 1]; + totalIndex++; } } - for (int i = doubleColumns - 1; i < rowColLimit; i += doubleColumns) { - gridIndices[p++] = i; - gridIndices[p++] = i + doubleColumns; + } + + // Create normals + if (startRow > 0) + startRow--; + totalIndex = startRow * doubleColumns; + int rowColLimit = startRow * doubleColumns; + for (int row = totalIndex, upperRow = totalIndex + 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)); + + // 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)); + } + } + + QVector uvs; // Empty dummy + createBuffers(m_vertices, uvs, m_normals, 0, false); +} + +void SurfaceObject::createCoarseIndices(int x, int y, int columns, int rows) +{ + if (columns > m_columns) + columns = m_columns; + if (rows > m_rows) + rows = m_rows; + if (x > columns) + x = columns - 1; + if (y > rows) + y = rows - 1; + + int rowLimit = rows - 1; + int doubleColumns = m_columns * 2 - 2; + int doubleColumnsLimit = columns * 2 - 2; + int rowColLimit = rowLimit * doubleColumns; + m_indexCount = 6 * (columns - 1 - x) * (rowLimit - y); + + int p = 0; + GLint *indices = new GLint[m_indexCount]; + 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; } } - createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry); + 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); delete[] indices; +} + +void SurfaceObject::createCoarseGridlineIndices(int x, int y, int endX, int endY) +{ + if (endX >= m_columns) + endX = m_columns - 1; + if (endY >= m_rows) + endY = m_rows - 1; + if (x > endX) + x = endX - 1; + if (y > endY) + y = endY - 1; + + int nColumns = endX - x + 1; + int nRows = endY - y + 1; + int doubleEndX = endX * 2; + int doubleColumns = m_columns * 2 - 2; + int rowColLimit = endY * doubleColumns; + + m_gridIndexCount = 2 * nColumns * (nRows - 1) + 2 * nRows * (nColumns - 1); + GLint *gridIndices = new GLint[m_gridIndexCount]; + int p = 0; + + for (int row = y * doubleColumns; row <= rowColLimit; row += doubleColumns) { + for (int j = x * 2; j < doubleEndX; j += 2) { + // Horizontal line + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + 1; + + if (row < rowColLimit) { + // Vertical line + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + doubleColumns; + } + } + } + // The rightmost line separately, since there isn't double vertice + for (int i = y * doubleColumns + doubleEndX - 1; i < rowColLimit; i += doubleColumns) { + gridIndices[p++] = i; + gridIndices[p++] = i + doubleColumns; + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), + gridIndices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + delete[] gridIndices; } void SurfaceObject::createBuffers(const QVector &vertices, const QVector &uvs, const QVector &normals, const GLint *indices, - const GLint *gridIndices, bool changeGeometry) + bool changeGeometry) { // Move to buffers glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); @@ -293,18 +525,15 @@ void SurfaceObject::createBuffers(const QVector &vertices, const QVec &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); + 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, m_elementbuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint), - indices, GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), - gridIndices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h index 4f30f7c0..895fd3eb 100644 --- a/src/datavisualization/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -48,6 +48,14 @@ public: GLfloat yMin, bool changeGeometry); void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, GLfloat yMin, bool changeGeometry); + void updateCoarseRows(const QSurfaceDataArray &dataArray, int startRow, + int endRow, GLfloat yRange, GLfloat yMin); + void updateSmoothRows(const QSurfaceDataArray &dataArray, int startRow, + int endRow, GLfloat yRange, GLfloat yMin); + void createSmoothIndices(int x, int y, int endX, int endY); + void createCoarseIndices(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); GLuint gridElementBuf(); GLuint gridIndexCount(); QVector3D vertexAt(int column, int row); @@ -56,7 +64,7 @@ private: QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c); void createBuffers(const QVector &vertices, const QVector &uvs, const QVector &normals, const GLint *indices, - const GLint *gridIndices, bool changeGeometry); + bool changeGeometry); private: enum SurfaceType { -- cgit v1.2.3