1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "surfaceobject_p.h"
5#include "surface3drenderer_p.h"
6
7#include <QtGui/QVector2D>
8
9QT_BEGIN_NAMESPACE
10
11SurfaceObject::SurfaceObject(Surface3DRenderer *renderer)
12 : m_axisCacheX(renderer->m_axisCacheX),
13 m_axisCacheY(renderer->m_axisCacheY),
14 m_axisCacheZ(renderer->m_axisCacheZ),
15 m_renderer(renderer)
16{
17 glGenBuffers(n: 1, buffers: &m_vertexbuffer);
18 glGenBuffers(n: 1, buffers: &m_normalbuffer);
19 glGenBuffers(n: 1, buffers: &m_uvbuffer);
20 glGenBuffers(n: 1, buffers: &m_elementbuffer);
21 glGenBuffers(n: 1, buffers: &m_gridElementbuffer);
22 glGenBuffers(n: 1, buffers: &m_uvTextureBuffer);
23}
24
25SurfaceObject::~SurfaceObject()
26{
27 if (QOpenGLContext::currentContext()) {
28 glDeleteBuffers(n: 1, buffers: &m_gridElementbuffer);
29 glDeleteBuffers(n: 1, buffers: &m_uvTextureBuffer);
30 }
31}
32
33void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space,
34 bool changeGeometry, bool polar, bool flipXZ)
35{
36 m_columns = space.width();
37 m_rows = space.height();
38 int totalSize = m_rows * m_columns;
39 GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
40 GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
41
42 m_surfaceType = SurfaceSmooth;
43
44 checkDirections(array: dataArray);
45 bool indicesDirty = false;
46 if (m_dataDimension != m_oldDataDimension)
47 indicesDirty = true;
48 m_oldDataDimension = m_dataDimension;
49
50 // Create/populate vertix table
51 if (changeGeometry)
52 m_vertices.resize(size: totalSize);
53
54 QList<QVector2D> uvs;
55 if (changeGeometry)
56 uvs.resize(size: totalSize);
57 int totalIndex = 0;
58
59 // Init min and max to ridiculous values
60 m_minY = 10000000.0;
61 m_maxY = -10000000.0f;
62
63 for (int i = 0; i < m_rows; i++) {
64 const QSurfaceDataRow &p = *dataArray.at(i);
65 for (int j = 0; j < m_columns; j++) {
66 getNormalizedVertex(data: p.at(i: j), vertex&: m_vertices[totalIndex], polar, flipXZ);
67 if (changeGeometry)
68 uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY);
69 totalIndex++;
70 }
71 }
72
73 if (flipXZ) {
74 for (int i = 0; i < m_vertices.size(); i++) {
75 m_vertices[i].setX(-m_vertices.at(i).x());
76 m_vertices[i].setZ(-m_vertices.at(i).z());
77 }
78 }
79
80 // Create normals
81 int rowLimit = m_rows - 1;
82 int colLimit = m_columns - 1;
83 if (changeGeometry)
84 m_normals.resize(size: totalSize);
85
86 totalIndex = 0;
87
88 if ((m_dataDimension == BothAscending) || (m_dataDimension == XDescending)) {
89 for (int row = 0; row < rowLimit; row++)
90 createSmoothNormalBodyLine(totalIndex, column: row * m_columns);
91 createSmoothNormalUpperLine(totalIndex);
92 } else { // BothDescending || ZDescending
93 createSmoothNormalUpperLine(totalIndex);
94 for (int row = 1; row < m_rows; row++)
95 createSmoothNormalBodyLine(totalIndex, column: row * m_columns);
96 }
97
98 // Create indices table
99 if (changeGeometry || indicesDirty)
100 createSmoothIndices(x: 0, y: 0, endX: colLimit, endY: rowLimit);
101
102 // Create line element indices
103 if (changeGeometry)
104 createSmoothGridlineIndices(x: 0, y: 0, endX: colLimit, endY: rowLimit);
105
106 createBuffers(vertices: m_vertices, uvs, normals: m_normals, indices: 0);
107}
108
109void SurfaceObject::createSmoothNormalBodyLine(int &totalIndex, int column)
110{
111 int colLimit = m_columns - 1;
112
113 if (m_dataDimension == BothAscending) {
114 int end = colLimit + column;
115 for (int j = column; j < end; j++) {
116 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
117 b: m_vertices.at(i: j + 1),
118 c: m_vertices.at(i: j + m_columns));
119 }
120 m_normals[totalIndex++] = normal(a: m_vertices.at(i: end),
121 b: m_vertices.at(i: end + m_columns),
122 c: m_vertices.at(i: end - 1));
123 } else if (m_dataDimension == XDescending) {
124 m_normals[totalIndex++] = normal(a: m_vertices.at(i: column),
125 b: m_vertices.at(i: column + m_columns),
126 c: m_vertices.at(i: column + 1));
127 int end = column + m_columns;
128 for (int j = column + 1; j < end; j++) {
129 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
130 b: m_vertices.at(i: j - 1),
131 c: m_vertices.at(i: j + m_columns));
132 }
133 } else if (m_dataDimension == ZDescending) {
134 int end = colLimit + column;
135 for (int j = column; j < end; j++) {
136 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
137 b: m_vertices.at(i: j + 1),
138 c: m_vertices.at(i: j - m_columns));
139 }
140 m_normals[totalIndex++] = normal(a: m_vertices.at(i: end),
141 b: m_vertices.at(i: end - m_columns),
142 c: m_vertices.at(i: end - 1));
143 } else { // BothDescending
144 m_normals[totalIndex++] = normal(a: m_vertices.at(i: column),
145 b: m_vertices.at(i: column - m_columns),
146 c: m_vertices.at(i: column + 1));
147 int end = column + m_columns;
148 for (int j = column + 1; j < end; j++) {
149 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
150 b: m_vertices.at(i: j - 1),
151 c: m_vertices.at(i: j - m_columns));
152 }
153 }
154}
155
156void SurfaceObject::createSmoothNormalUpperLine(int &totalIndex)
157{
158 if (m_dataDimension == BothAscending) {
159 int lineEnd = m_rows * m_columns - 1;
160 for (int j = (m_rows - 1) * m_columns; j < lineEnd; j++) {
161 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
162 b: m_vertices.at(i: j - m_columns),
163 c: m_vertices.at(i: j + 1));
164 }
165 m_normals[totalIndex++] = normal(a: m_vertices.at(i: lineEnd),
166 b: m_vertices.at(i: lineEnd - 1),
167 c: m_vertices.at(i: lineEnd - m_columns));
168 } else if (m_dataDimension == XDescending) {
169 int lineStart = (m_rows - 1) * m_columns;
170 int lineEnd = m_rows * m_columns;
171 m_normals[totalIndex++] = normal(a: m_vertices.at(i: lineStart),
172 b: m_vertices.at(i: lineStart + 1),
173 c: m_vertices.at(i: lineStart - m_columns));
174 for (int j = lineStart + 1; j < lineEnd; j++) {
175 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
176 b: m_vertices.at(i: j - m_columns),
177 c: m_vertices.at(i: j - 1));
178 }
179 } else if (m_dataDimension == ZDescending) {
180 int colLimit = m_columns - 1;
181 for (int j = 0; j < colLimit; j++) {
182 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
183 b: m_vertices.at(i: j + m_columns),
184 c: m_vertices.at(i: j + 1));
185 }
186 m_normals[totalIndex++] = normal(a: m_vertices.at(i: colLimit),
187 b: m_vertices.at(i: colLimit - 1),
188 c: m_vertices.at(i: colLimit + m_columns));
189 } else { // BothDescending
190 m_normals[totalIndex++] = normal(a: m_vertices.at(i: 0),
191 b: m_vertices.at(i: 1),
192 c: m_vertices.at(i: m_columns));
193 for (int j = 1; j < m_columns; j++) {
194 m_normals[totalIndex++] = normal(a: m_vertices.at(i: j),
195 b: m_vertices.at(i: j + m_columns),
196 c: m_vertices.at(i: j - 1));
197 }
198 }
199}
200
201QVector3D SurfaceObject::createSmoothNormalBodyLineItem(int x, int y)
202{
203 int p = y * m_columns + x;
204 if (m_dataDimension == BothAscending) {
205 if (x < m_columns - 1) {
206 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + 1),
207 c: m_vertices.at(i: p + m_columns));
208 } else {
209 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + m_columns),
210 c: m_vertices.at(i: p - 1));
211 }
212 } else if (m_dataDimension == XDescending) {
213 if (x == 0) {
214 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + m_columns),
215 c: m_vertices.at(i: p + 1));
216 } else {
217 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - 1),
218 c: m_vertices.at(i: p + m_columns));
219 }
220 } else if (m_dataDimension == ZDescending) {
221 if (x < m_columns - 1) {
222 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + 1),
223 c: m_vertices.at(i: p - m_columns));
224 } else {
225 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - m_columns),
226 c: m_vertices.at(i: p - 1));
227 }
228 } else { // BothDescending
229 if (x == 0) {
230 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - m_columns),
231 c: m_vertices.at(i: p + 1));
232 } else {
233 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - 1),
234 c: m_vertices.at(i: p - m_columns));
235 }
236 }
237}
238
239QVector3D SurfaceObject::createSmoothNormalUpperLineItem(int x, int y)
240{
241 int p = y * m_columns + x;
242 if (m_dataDimension == BothAscending) {
243 if (x < m_columns - 1) {
244 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - m_columns),
245 c: m_vertices.at(i: p + 1));
246 } else {
247 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - 1),
248 c: m_vertices.at(i: p - m_columns));
249 }
250 } else if (m_dataDimension == XDescending) {
251 if (x == 0) {
252 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + 1),
253 c: m_vertices.at(i: p - m_columns));
254 } else {
255 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - m_columns),
256 c: m_vertices.at(i: p - 1));
257 }
258 } else if (m_dataDimension == ZDescending) {
259 if (x < m_columns - 1) {
260 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + m_columns),
261 c: m_vertices.at(i: p + 1));
262 } else {
263 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p - 1),
264 c: m_vertices.at(i: p + m_columns));
265 }
266 } else { // BothDescending
267 if (x == 0) {
268 return normal(a: m_vertices.at(i: 0), b: m_vertices.at(i: 1),
269 c: m_vertices.at(i: m_columns));
270 } else {
271 return normal(a: m_vertices.at(i: p), b: m_vertices.at(i: p + m_columns),
272 c: m_vertices.at(i: p - 1));
273 }
274 }
275}
276
277void SurfaceObject::smoothUVs(const QSurfaceDataArray &dataArray,
278 const QSurfaceDataArray &modelArray)
279{
280 if (dataArray.size() == 0 || modelArray.size() == 0)
281 return;
282
283 int columns = dataArray.at(i: 0)->size();
284 int rows = dataArray.size();
285 float xRangeNormalizer = dataArray.at(i: 0)->at(i: columns - 1).x() - dataArray.at(i: 0)->at(i: 0).x();
286 float zRangeNormalizer = dataArray.at(i: rows - 1)->at(i: 0).z() - dataArray.at(i: 0)->at(i: 0).z();
287 float xMin = dataArray.at(i: 0)->at(i: 0).x();
288 float zMin = dataArray.at(i: 0)->at(i: 0).z();
289 const bool zDescending = m_dataDimension.testFlag(flag: SurfaceObject::ZDescending);
290 const bool xDescending = m_dataDimension.testFlag(flag: SurfaceObject::XDescending);
291
292 QList<QVector2D> uvs;
293 uvs.resize(size: m_rows * m_columns);
294 int index = 0;
295 for (int i = 0; i < m_rows; i++) {
296 float y = (modelArray.at(i)->at(i: 0).z() - zMin) / zRangeNormalizer;
297 if (zDescending)
298 y = 1.0f - y;
299 const QSurfaceDataRow &p = *modelArray.at(i);
300 for (int j = 0; j < m_columns; j++) {
301 float x = (p.at(i: j).x() - xMin) / xRangeNormalizer;
302 if (xDescending)
303 x = 1.0f - x;
304 uvs[index] = QVector2D(x, y);
305 index++;
306 }
307 }
308
309 if (uvs.size() > 0) {
310 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvTextureBuffer);
311 glBufferData(GL_ARRAY_BUFFER, size: uvs.size() * sizeof(QVector2D),
312 data: &uvs.at(i: 0), GL_STATIC_DRAW);
313 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
314
315 m_returnTextureBuffer = true;
316 }
317}
318
319void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar)
320{
321 // Update vertices
322 int p = rowIndex * m_columns;
323 const QSurfaceDataRow &dataRow = *dataArray.at(i: rowIndex);
324
325 for (int j = 0; j < m_columns; j++)
326 getNormalizedVertex(data: dataRow.at(i: j), vertex&: m_vertices[p++], polar, flipXZ: false);
327
328 // Create normals
329 bool upwards = (m_dataDimension == BothAscending) || (m_dataDimension == XDescending);
330 int startRow = rowIndex;
331 if ((startRow > 0) && upwards)
332 startRow--;
333 int endRow = rowIndex;
334 if (!upwards && (rowIndex < m_rows - 1))
335 endRow++;
336 if ((endRow == m_rows - 1) && upwards)
337 endRow--;
338 int totalIndex = startRow * m_columns;
339
340 if ((startRow == 0) && !upwards) {
341 createSmoothNormalUpperLine(totalIndex);
342 startRow++;
343 }
344
345 for (int row = startRow; row <= endRow; row++)
346 createSmoothNormalBodyLine(totalIndex, column: row * m_columns);
347
348 if ((rowIndex == m_rows - 1) && upwards)
349 createSmoothNormalUpperLine(totalIndex);
350}
351
352void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column,
353 bool polar)
354{
355 // Update a vertice
356 getNormalizedVertex(data: dataArray.at(i: row)->at(i: column),
357 vertex&: m_vertices[row * m_columns + column], polar, flipXZ: false);
358
359 // Create normals
360 bool upwards = (m_dataDimension == BothAscending) || (m_dataDimension == XDescending);
361 bool rightwards = (m_dataDimension == BothAscending) || (m_dataDimension == ZDescending);
362 int startRow = row;
363 if ((startRow > 0) && upwards)
364 startRow--;
365 int endRow = row;
366 if (!upwards && (row < m_rows - 1))
367 endRow++;
368 if ((endRow == m_rows - 1) && upwards)
369 endRow--;
370 int startCol = column;
371 if ((startCol > 0) && rightwards)
372 startCol--;
373 int endCol = column;
374 if ((endCol < m_columns - 1) && !rightwards)
375 endCol++;
376
377 for (int i = startRow; i <= endRow; i++) {
378 for (int j = startCol; j <= endCol; j++) {
379 int p = i * m_columns + j;
380 if ((i == 0) && !upwards)
381 m_normals[p] = createSmoothNormalUpperLineItem(x: j, y: i);
382 else if ((i == m_rows - 1) && upwards)
383 m_normals[p] = createSmoothNormalUpperLineItem(x: j, y: i);
384 else
385 m_normals[p] = createSmoothNormalBodyLineItem(x: j, y: i);
386 }
387 }
388}
389
390
391void SurfaceObject::createSmoothIndices(int x, int y, int endX, int endY)
392{
393 if (endX >= m_columns)
394 endX = m_columns - 1;
395 if (endY >= m_rows)
396 endY = m_rows - 1;
397 if (x > endX)
398 x = endX - 1;
399 if (y > endY)
400 y = endY - 1;
401
402 m_indexCount = 6 * (endX - x) * (endY - y);
403 GLint *indices = new GLint[m_indexCount];
404 int p = 0;
405 int rowEnd = endY * m_columns;
406 for (int row = y * m_columns; row < rowEnd; row += m_columns) {
407 for (int j = x; j < endX; j++) {
408 if ((m_dataDimension == BothAscending) || (m_dataDimension == BothDescending)) {
409 // Left triangle
410 indices[p++] = row + j + 1;
411 indices[p++] = row + m_columns + j;
412 indices[p++] = row + j;
413
414 // Right triangle
415 indices[p++] = row + m_columns + j + 1;
416 indices[p++] = row + m_columns + j;
417 indices[p++] = row + j + 1;
418 } else if (m_dataDimension == XDescending) {
419 // Right triangle
420 indices[p++] = row + m_columns + j;
421 indices[p++] = row + m_columns + j + 1;
422 indices[p++] = row + j;
423
424 // Left triangle
425 indices[p++] = row + j;
426 indices[p++] = row + m_columns + j + 1;
427 indices[p++] = row + j + 1;
428 } else {
429 // Left triangle
430 indices[p++] = row + m_columns + j;
431 indices[p++] = row + m_columns + j + 1;
432 indices[p++] = row + j;
433
434 // Right triangle
435 indices[p++] = row + j;
436 indices[p++] = row + m_columns + j + 1;
437 indices[p++] = row + j + 1;
438
439 }
440 }
441 }
442
443 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_elementbuffer);
444 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size: m_indexCount * sizeof(GLint),
445 data: indices, GL_STATIC_DRAW);
446
447 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: 0);
448
449 delete[] indices;
450}
451
452void SurfaceObject::createSmoothGridlineIndices(int x, int y, int endX, int endY)
453{
454 if (endX >= m_columns)
455 endX = m_columns - 1;
456 if (endY >= m_rows)
457 endY = m_rows - 1;
458 if (x > endX)
459 x = endX - 1;
460 if (y > endY)
461 y = endY - 1;
462
463 int nColumns = endX - x + 1;
464 int nRows = endY - y + 1;
465 m_gridIndexCount = 2 * nColumns * (nRows - 1) + 2 * nRows * (nColumns - 1);
466 GLint *gridIndices = new GLint[m_gridIndexCount];
467 int p = 0;
468 for (int i = y, row = m_columns * y; i <= endY; i++, row += m_columns) {
469 for (int j = x; j < endX; j++) {
470 gridIndices[p++] = row + j;
471 gridIndices[p++] = row + j + 1;
472 }
473 }
474 for (int i = y, row = m_columns * y; i < endY; i++, row += m_columns) {
475 for (int j = x; j <= endX; j++) {
476 gridIndices[p++] = row + j;
477 gridIndices[p++] = row + j + m_columns;
478 }
479 }
480
481 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_gridElementbuffer);
482 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size: m_gridIndexCount * sizeof(GLint),
483 data: gridIndices, GL_STATIC_DRAW);
484
485 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: 0);
486
487 delete[] gridIndices;
488}
489
490void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space,
491 bool changeGeometry, bool polar, bool flipXZ)
492{
493 m_columns = space.width();
494 m_rows = space.height();
495 int totalSize = m_rows * m_columns * 2;
496 GLfloat uvX = 1.0f / GLfloat(m_columns - 1);
497 GLfloat uvY = 1.0f / GLfloat(m_rows - 1);
498
499 checkDirections(array: dataArray);
500 bool indicesDirty = false;
501 if (m_dataDimension != m_oldDataDimension)
502 indicesDirty = true;
503 m_oldDataDimension = m_dataDimension;
504
505 m_surfaceType = SurfaceFlat;
506
507 // Create vertix table
508 if (changeGeometry)
509 m_vertices.resize(size: totalSize);
510
511 QList<QVector2D> uvs;
512 if (changeGeometry)
513 uvs.resize(size: totalSize);
514
515 int totalIndex = 0;
516 int rowLimit = m_rows - 1;
517 int colLimit = m_columns - 1;
518 int doubleColumns = m_columns * 2 - 2;
519 int rowColLimit = rowLimit * doubleColumns;
520
521 // Init min and max to ridiculous values
522 m_minY = 10000000.0;
523 m_maxY = -10000000.0f;
524
525 for (int i = 0; i < m_rows; i++) {
526 const QSurfaceDataRow &row = *dataArray.at(i);
527 for (int j = 0; j < m_columns; j++) {
528 getNormalizedVertex(data: row.at(i: j), vertex&: m_vertices[totalIndex], polar, flipXZ);
529 if (changeGeometry)
530 uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY);
531
532 totalIndex++;
533
534 if (j > 0 && j < colLimit) {
535 m_vertices[totalIndex] = m_vertices[totalIndex - 1];
536 if (changeGeometry)
537 uvs[totalIndex] = uvs[totalIndex - 1];
538 totalIndex++;
539 }
540 }
541 }
542
543 if (flipXZ) {
544 for (int i = 0; i < m_vertices.size(); i++) {
545 m_vertices[i].setX(-m_vertices.at(i).x());
546 m_vertices[i].setZ(-m_vertices.at(i).z());
547 }
548 }
549
550 // Create normals & indices table
551 GLint *indices = 0;
552 if (changeGeometry || indicesDirty) {
553 int normalCount = 2 * colLimit * rowLimit;
554 m_indexCount = 3 * normalCount;
555 indices = new GLint[m_indexCount];
556 m_normals.resize(size: normalCount);
557 }
558
559 int p = 0;
560 totalIndex = 0;
561 for (int row = 0, upperRow = doubleColumns;
562 row < rowColLimit;
563 row += doubleColumns, upperRow += doubleColumns) {
564 for (int j = 0; j < doubleColumns; j += 2) {
565 createNormals(p&: totalIndex, row, upperRow, j);
566
567 if (changeGeometry || indicesDirty) {
568 createCoarseIndices(indices, p, row, upperRow, j);
569 }
570 }
571 }
572
573 // Create grid line element indices
574 if (changeGeometry)
575 createCoarseGridlineIndices(x: 0, y: 0, endX: colLimit, endY: rowLimit);
576
577 createBuffers(vertices: m_vertices, uvs, normals: m_normals, indices);
578
579 delete[] indices;
580}
581
582void SurfaceObject::coarseUVs(const QSurfaceDataArray &dataArray,
583 const QSurfaceDataArray &modelArray)
584{
585 if (dataArray.size() == 0 || modelArray.size() == 0)
586 return;
587
588 int columns = dataArray.at(i: 0)->size();
589 int rows = dataArray.size();
590 float xRangeNormalizer = dataArray.at(i: 0)->at(i: columns - 1).x() - dataArray.at(i: 0)->at(i: 0).x();
591 float zRangeNormalizer = dataArray.at(i: rows - 1)->at(i: 0).z() - dataArray.at(i: 0)->at(i: 0).z();
592 float xMin = dataArray.at(i: 0)->at(i: 0).x();
593 float zMin = dataArray.at(i: 0)->at(i: 0).z();
594 const bool zDescending = m_dataDimension.testFlag(flag: SurfaceObject::ZDescending);
595 const bool xDescending = m_dataDimension.testFlag(flag: SurfaceObject::XDescending);
596
597 QList<QVector2D> uvs;
598 uvs.resize(size: m_rows * m_columns * 2);
599 int index = 0;
600 int colLimit = m_columns - 1;
601 for (int i = 0; i < m_rows; i++) {
602 float y = (modelArray.at(i)->at(i: 0).z() - zMin) / zRangeNormalizer;
603 if (zDescending)
604 y = 1.0f - y;
605 const QSurfaceDataRow &p = *modelArray.at(i);
606 for (int j = 0; j < m_columns; j++) {
607 float x = (p.at(i: j).x() - xMin) / xRangeNormalizer;
608 if (xDescending)
609 x = 1.0f - x;
610 uvs[index] = QVector2D(x, y);
611 index++;
612 if (j > 0 && j < colLimit) {
613 uvs[index] = uvs[index - 1];
614 index++;
615 }
616 }
617 }
618
619 if (uvs.size() > 0) {
620 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvTextureBuffer);
621 glBufferData(GL_ARRAY_BUFFER, size: uvs.size() * sizeof(QVector2D),
622 data: &uvs.at(i: 0), GL_STATIC_DRAW);
623 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
624
625 m_returnTextureBuffer = true;
626 }
627}
628
629void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar)
630{
631 int colLimit = m_columns - 1;
632 int doubleColumns = m_columns * 2 - 2;
633
634 int p = rowIndex * doubleColumns;
635 const QSurfaceDataRow &dataRow = *dataArray.at(i: rowIndex);
636
637 for (int j = 0; j < m_columns; j++) {
638 getNormalizedVertex(data: dataRow.at(i: j), vertex&: m_vertices[p++], polar, flipXZ: false);
639 if (j > 0 && j < colLimit) {
640 m_vertices[p] = m_vertices[p - 1];
641 p++;
642 }
643 }
644
645 // Create normals
646 p = rowIndex * doubleColumns;
647 if (p > 0)
648 p -= doubleColumns;
649 int rowLimit = (rowIndex + 1) * doubleColumns;
650 if (rowIndex == m_rows - 1)
651 rowLimit = rowIndex * doubleColumns; //Topmost row, no normals
652 for (int row = p, upperRow = p + doubleColumns;
653 row < rowLimit;
654 row += doubleColumns, upperRow += doubleColumns) {
655 for (int j = 0; j < doubleColumns; j += 2)
656 createNormals(p, row, upperRow, j);
657 }
658}
659
660void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column,
661 bool polar)
662{
663 int colLimit = m_columns - 1;
664 int doubleColumns = m_columns * 2 - 2;
665
666 // Update a vertice
667 int p = row * doubleColumns + column * 2 - (column > 0);
668 getNormalizedVertex(data: dataArray.at(i: row)->at(i: column), vertex&: m_vertices[p++], polar, flipXZ: false);
669
670 if (column > 0 && column < colLimit)
671 m_vertices[p] = m_vertices[p - 1];
672
673 // Create normals
674 int startRow = row;
675 if (startRow > 0)
676 startRow--; // Change the normal for previous row also
677 int startCol = column;
678 if (startCol > 0)
679 startCol--;
680 if (row == m_rows - 1)
681 row--;
682 if (column == m_columns - 1)
683 column--;
684
685 for (int i = startRow; i <= row; i++) {
686 for (int j = startCol; j <= column; j++) {
687 p = i * doubleColumns + j * 2;
688 createNormals(p, row: i * doubleColumns, upperRow: (i + 1) * doubleColumns, j: j * 2);
689 }
690 }
691}
692
693void SurfaceObject::createCoarseSubSection(int x, int y, int columns, int rows)
694{
695 if (columns > m_columns)
696 columns = m_columns;
697 if (rows > m_rows)
698 rows = m_rows;
699 if (x > columns)
700 x = columns - 1;
701 if (y > rows)
702 y = rows - 1;
703
704 int rowLimit = rows - 1;
705 int doubleColumns = m_columns * 2 - 2;
706 int doubleColumnsLimit = columns * 2 - 2;
707 int rowColLimit = rowLimit * doubleColumns;
708 m_indexCount = 6 * (columns - 1 - x) * (rowLimit - y);
709
710 int p = 0;
711 GLint *indices = new GLint[m_indexCount];
712 for (int row = y * doubleColumns, upperRow = (y + 1) * doubleColumns;
713 row < rowColLimit;
714 row += doubleColumns, upperRow += doubleColumns) {
715 for (int j = 2 * x; j < doubleColumnsLimit; j += 2)
716 createCoarseIndices(indices, p, row, upperRow, j);
717 }
718
719 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_elementbuffer);
720 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size: m_indexCount * sizeof(GLint),
721 data: indices, GL_STATIC_DRAW);
722
723 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: 0);
724
725 delete[] indices;
726}
727
728void SurfaceObject::createCoarseGridlineIndices(int x, int y, int endX, int endY)
729{
730 if (endX >= m_columns)
731 endX = m_columns - 1;
732 if (endY >= m_rows)
733 endY = m_rows - 1;
734 if (x > endX)
735 x = endX - 1;
736 if (y > endY)
737 y = endY - 1;
738
739 int nColumns = endX - x + 1;
740 int nRows = endY - y + 1;
741 int doubleEndX = endX * 2;
742 int doubleColumns = m_columns * 2 - 2;
743 int rowColLimit = endY * doubleColumns;
744
745 m_gridIndexCount = 2 * nColumns * (nRows - 1) + 2 * nRows * (nColumns - 1);
746 GLint *gridIndices = new GLint[m_gridIndexCount];
747 int p = 0;
748
749 for (int row = y * doubleColumns; row <= rowColLimit; row += doubleColumns) {
750 for (int j = x * 2; j < doubleEndX; j += 2) {
751 // Horizontal line
752 gridIndices[p++] = row + j;
753 gridIndices[p++] = row + j + 1;
754
755 if (row < rowColLimit) {
756 // Vertical line
757 gridIndices[p++] = row + j;
758 gridIndices[p++] = row + j + doubleColumns;
759 }
760 }
761 }
762 // The rightmost line separately, since there isn't double vertice
763 for (int i = y * doubleColumns + doubleEndX - 1; i < rowColLimit; i += doubleColumns) {
764 gridIndices[p++] = i;
765 gridIndices[p++] = i + doubleColumns;
766 }
767
768 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_gridElementbuffer);
769 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size: m_gridIndexCount * sizeof(GLint),
770 data: gridIndices, GL_STATIC_DRAW);
771
772 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: 0);
773
774 delete[] gridIndices;
775}
776
777void SurfaceObject::uploadBuffers()
778{
779 QList<QVector2D> uvs; // Empty dummy
780 createBuffers(vertices: m_vertices, uvs, normals: m_normals, indices: 0);
781}
782
783void SurfaceObject::createBuffers(const QList<QVector3D> &vertices, const QList<QVector2D> &uvs,
784 const QList<QVector3D> &normals, const GLint *indices)
785{
786 // Move to buffers
787 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_vertexbuffer);
788 glBufferData(GL_ARRAY_BUFFER, size: vertices.size() * sizeof(QVector3D),
789 data: &vertices.at(i: 0), GL_DYNAMIC_DRAW);
790
791 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_normalbuffer);
792 glBufferData(GL_ARRAY_BUFFER, size: normals.size() * sizeof(QVector3D),
793 data: &normals.at(i: 0), GL_DYNAMIC_DRAW);
794
795 if (uvs.size()) {
796 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvbuffer);
797 glBufferData(GL_ARRAY_BUFFER, size: uvs.size() * sizeof(QVector2D),
798 data: &uvs.at(i: 0), GL_STATIC_DRAW);
799 }
800
801 if (indices) {
802 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_elementbuffer);
803 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size: m_indexCount * sizeof(GLint),
804 data: indices, GL_STATIC_DRAW);
805 }
806
807 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: 0);
808 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
809
810 m_meshDataLoaded = true;
811}
812
813void SurfaceObject::checkDirections(const QSurfaceDataArray &array)
814{
815 m_dataDimension = BothAscending;
816
817 if (array.at(i: 0)->at(i: 0).x() > array.at(i: 0)->at(i: array.at(i: 0)->size() - 1).x())
818 m_dataDimension |= XDescending;
819 if (m_axisCacheX.reversed())
820 m_dataDimension ^= XDescending;
821
822 if (array.at(i: 0)->at(i: 0).z() > array.at(i: array.size() - 1)->at(i: 0).z())
823 m_dataDimension |= ZDescending;
824 if (m_axisCacheZ.reversed())
825 m_dataDimension ^= ZDescending;
826}
827
828void SurfaceObject::getNormalizedVertex(const QSurfaceDataItem &data, QVector3D &vertex,
829 bool polar, bool flipXZ)
830{
831 float normalizedX;
832 float normalizedZ;
833 if (polar) {
834 // Slice don't use polar, so don't care about flip
835 m_renderer->calculatePolarXZ(dataPos: data.position(), x&: normalizedX, z&: normalizedZ);
836 } else {
837 if (flipXZ) {
838 normalizedX = m_axisCacheZ.positionAt(value: data.x());
839 normalizedZ = m_axisCacheX.positionAt(value: data.z());
840 } else {
841 normalizedX = m_axisCacheX.positionAt(value: data.x());
842 normalizedZ = m_axisCacheZ.positionAt(value: data.z());
843 }
844 }
845 float normalizedY = m_axisCacheY.positionAt(value: data.y());
846 m_minY = qMin(a: normalizedY, b: m_minY);
847 if (!qIsNaN(f: normalizedY) && !qIsInf(f: normalizedY))
848 m_maxY = qMax(a: normalizedY, b: m_maxY);
849 vertex.setX(normalizedX);
850 vertex.setY(normalizedY);
851 vertex.setZ(normalizedZ);
852}
853
854GLuint SurfaceObject::gridElementBuf()
855{
856 if (!m_meshDataLoaded)
857 qFatal(msg: "No loaded object");
858 return m_gridElementbuffer;
859}
860
861GLuint SurfaceObject::uvBuf()
862{
863 if (!m_meshDataLoaded)
864 qFatal(msg: "No loaded object");
865
866 if (m_returnTextureBuffer)
867 return m_uvTextureBuffer;
868 else
869 return m_uvbuffer;
870}
871
872GLuint SurfaceObject::gridIndexCount()
873{
874 return m_gridIndexCount;
875}
876
877QVector3D SurfaceObject::vertexAt(int column, int row)
878{
879 int pos = 0;
880 if (m_surfaceType == Undefined || !m_vertices.size())
881 return zeroVector;
882
883 if (m_surfaceType == SurfaceFlat)
884 pos = row * (m_columns * 2 - 2) + column * 2 - (column > 0);
885 else
886 pos = row * m_columns + column;
887 return m_vertices.at(i: pos);
888}
889
890void SurfaceObject::clear()
891{
892 m_gridIndexCount = 0;
893 m_indexCount = 0;
894 m_surfaceType = Undefined;
895 m_vertices.clear();
896 m_normals.clear();
897}
898
899void SurfaceObject::createCoarseIndices(GLint *indices, int &p, int row, int upperRow, int j)
900{
901 if ((m_dataDimension == BothAscending) || (m_dataDimension == BothDescending)) {
902 // Left triangle
903 indices[p++] = row + j + 1;
904 indices[p++] = upperRow + j;
905 indices[p++] = row + j;
906
907 // Right triangle
908 indices[p++] = upperRow + j + 1;
909 indices[p++] = upperRow + j;
910 indices[p++] = row + j + 1;
911 } else if (m_dataDimension == XDescending) {
912 indices[p++] = upperRow + j;
913 indices[p++] = upperRow + j + 1;
914 indices[p++] = row + j;
915
916 indices[p++] = row + j;
917 indices[p++] = upperRow + j + 1;
918 indices[p++] = row + j + 1;
919 } else {
920 // Left triangle
921 indices[p++] = upperRow + j;
922 indices[p++] = upperRow + j + 1;
923 indices[p++] = row + j;
924
925 // Right triangle
926 indices[p++] = row + j;
927 indices[p++] = upperRow + j + 1;
928 indices[p++] = row + j + 1;
929 }
930}
931
932void SurfaceObject::createNormals(int &p, int row, int upperRow, int j)
933{
934 if ((m_dataDimension == BothAscending) || (m_dataDimension == BothDescending)) {
935 m_normals[p++] = normal(a: m_vertices.at(i: row + j),
936 b: m_vertices.at(i: row + j + 1),
937 c: m_vertices.at(i: upperRow + j));
938
939 m_normals[p++] = normal(a: m_vertices.at(i: row + j + 1),
940 b: m_vertices.at(i: upperRow + j + 1),
941 c: m_vertices.at(i: upperRow + j));
942 } else if (m_dataDimension == XDescending) {
943 m_normals[p++] = normal(a: m_vertices.at(i: row + j),
944 b: m_vertices.at(i: upperRow + j),
945 c: m_vertices.at(i: upperRow + j + 1));
946
947 m_normals[p++] = normal(a: m_vertices.at(i: row + j + 1),
948 b: m_vertices.at(i: row + j),
949 c: m_vertices.at(i: upperRow + j + 1));
950 } else {
951 m_normals[p++] = normal(a: m_vertices.at(i: row + j),
952 b: m_vertices.at(i: upperRow + j),
953 c: m_vertices.at(i: upperRow + j + 1));
954
955 m_normals[p++] = normal(a: m_vertices.at(i: row + j + 1),
956 b: m_vertices.at(i: row + j),
957 c: m_vertices.at(i: upperRow + j + 1));
958 }
959}
960
961QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c)
962{
963 QVector3D v1 = b - a;
964 QVector3D v2 = c - a;
965 QVector3D normal = QVector3D::crossProduct(v1, v2);
966
967 return normal;
968}
969
970QT_END_NAMESPACE
971

source code of qtdatavis3d/src/datavisualization/utils/surfaceobject.cpp