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.cpp745
1 files changed, 503 insertions, 242 deletions
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;
}