1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "scatterpointbufferhelper_p.h"
5#include <QtGui/QVector2D>
6
7QT_BEGIN_NAMESPACE
8
9const QVector3D hiddenPos(-1000.0f, -1000.0f, -1000.0f);
10
11ScatterPointBufferHelper::ScatterPointBufferHelper()
12 : m_pointbuffer(0),
13 m_oldRemoveIndex(-1)
14{
15}
16
17ScatterPointBufferHelper::~ScatterPointBufferHelper()
18{
19 if (QOpenGLContext::currentContext())
20 glDeleteBuffers(n: 1, buffers: &m_pointbuffer);
21}
22
23GLuint ScatterPointBufferHelper::pointBuf()
24{
25 if (!m_meshDataLoaded)
26 qFatal(msg: "No loaded object");
27 return m_pointbuffer;
28}
29
30void ScatterPointBufferHelper::pushPoint(uint pointIndex)
31{
32 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
33
34 // Pop the previous point if it is still pushed
35 if (m_oldRemoveIndex >= 0) {
36 glBufferSubData(GL_ARRAY_BUFFER, offset: m_oldRemoveIndex * sizeof(QVector3D),
37 size: sizeof(QVector3D), data: &m_bufferedPoints.at(i: m_oldRemoveIndex));
38 }
39
40 glBufferSubData(GL_ARRAY_BUFFER, offset: pointIndex * sizeof(QVector3D),
41 size: sizeof(QVector3D),
42 data: &hiddenPos);
43
44 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
45
46 m_oldRemoveIndex = pointIndex;
47}
48
49void ScatterPointBufferHelper::popPoint()
50{
51 if (m_oldRemoveIndex >= 0) {
52 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
53 glBufferSubData(GL_ARRAY_BUFFER, offset: m_oldRemoveIndex * sizeof(QVector3D),
54 size: sizeof(QVector3D), data: &m_bufferedPoints.at(i: m_oldRemoveIndex));
55 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
56 }
57
58 m_oldRemoveIndex = -1;
59}
60
61void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache)
62{
63 ScatterRenderItemArray &renderArray = cache->renderArray();
64 const int renderArraySize = renderArray.size();
65 m_indexCount = 0;
66
67 if (m_meshDataLoaded) {
68 // Delete old data
69 glDeleteBuffers(n: 1, buffers: &m_pointbuffer);
70 glDeleteBuffers(n: 1, buffers: &m_uvbuffer);
71 m_bufferedPoints.clear();
72 m_pointbuffer = 0;
73 m_uvbuffer = 0;
74 m_meshDataLoaded = false;
75 }
76
77 bool itemsVisible = false;
78 m_bufferedPoints.resize(size: renderArraySize);
79 for (int i = 0; i < renderArraySize; i++) {
80 const ScatterRenderItem &item = renderArray.at(i);
81 if (!item.isVisible()) {
82 m_bufferedPoints[i] = hiddenPos;
83 } else {
84 itemsVisible = true;
85 m_bufferedPoints[i] = item.translation();
86 }
87 }
88
89 QList<QVector2D> buffered_uvs;
90 if (itemsVisible)
91 m_indexCount = renderArraySize;
92
93 if (m_indexCount > 0) {
94 if (cache->colorStyle() == Q3DTheme::ColorStyleRangeGradient)
95 createRangeGradientUVs(cache, buffered_uvs);
96
97 glGenBuffers(n: 1, buffers: &m_pointbuffer);
98 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
99 glBufferData(GL_ARRAY_BUFFER, size: m_bufferedPoints.size() * sizeof(QVector3D),
100 data: &m_bufferedPoints.at(i: 0),
101 GL_DYNAMIC_DRAW);
102
103 if (buffered_uvs.size()) {
104 glGenBuffers(n: 1, buffers: &m_uvbuffer);
105 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvbuffer);
106 glBufferData(GL_ARRAY_BUFFER, size: buffered_uvs.size() * sizeof(QVector2D),
107 data: &buffered_uvs.at(i: 0), GL_STATIC_DRAW);
108 }
109
110 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
111
112 m_meshDataLoaded = true;
113 }
114}
115
116void ScatterPointBufferHelper::update(ScatterSeriesRenderCache *cache)
117{
118 // It may be that the buffer hasn't yet been initialized, in case the entire series was
119 // hidden items. No need to update in that case.
120 if (m_indexCount > 0) {
121 const ScatterRenderItemArray &renderArray = cache->renderArray();
122 const int updateSize = cache->updateIndices().size();
123
124 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
125 for (int i = 0; i < updateSize; i++) {
126 int index = cache->updateIndices().at(i);
127 const ScatterRenderItem &item = renderArray.at(i: index);
128 if (!item.isVisible())
129 m_bufferedPoints[index] = hiddenPos;
130 else
131 m_bufferedPoints[index] = item.translation();
132
133 if (index != m_oldRemoveIndex) {
134 glBufferSubData(GL_ARRAY_BUFFER, offset: index * sizeof(QVector3D),
135 size: sizeof(QVector3D), data: &m_bufferedPoints.at(i: index));
136 }
137 }
138 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
139 }
140}
141
142void ScatterPointBufferHelper::updateUVs(ScatterSeriesRenderCache *cache)
143{
144 // It may be that the buffer hasn't yet been initialized, in case the entire series was
145 // hidden items. No need to update in that case.
146 if (m_indexCount > 0) {
147 QList<QVector2D> buffered_uvs;
148 createRangeGradientUVs(cache, buffered_uvs);
149
150 if (buffered_uvs.size()) {
151 if (!m_uvbuffer)
152 glGenBuffers(n: 1, buffers: &m_uvbuffer);
153
154 int updateSize = cache->updateIndices().size();
155 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvbuffer);
156 if (updateSize) {
157 for (int i = 0; i < updateSize; i++) {
158 int index = cache->updateIndices().at(i);
159 glBufferSubData(GL_ARRAY_BUFFER, offset: index * sizeof(QVector2D),
160 size: sizeof(QVector2D), data: &buffered_uvs.at(i));
161
162 }
163 } else {
164 glBufferData(GL_ARRAY_BUFFER, size: buffered_uvs.size() * sizeof(QVector2D),
165 data: &buffered_uvs.at(i: 0), GL_STATIC_DRAW);
166 }
167
168 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
169 }
170 }
171}
172
173void ScatterPointBufferHelper::createRangeGradientUVs(ScatterSeriesRenderCache *cache,
174 QList<QVector2D> &buffered_uvs)
175{
176 const ScatterRenderItemArray &renderArray = cache->renderArray();
177 const bool updateAll = (cache->updateIndices().size() == 0);
178 const int updateSize = updateAll ? renderArray.size() : cache->updateIndices().size();
179 buffered_uvs.resize(size: updateSize);
180
181 QVector2D uv;
182 uv.setX(0.0f);
183 for (int i = 0; i < updateSize; i++) {
184 int index = updateAll ? i : cache->updateIndices().at(i);
185 const ScatterRenderItem &item = renderArray.at(i: index);
186
187 float y = ((item.translation().y() + m_scaleY) * 0.5f) / m_scaleY;
188 uv.setY(y);
189 buffered_uvs[i] = uv;
190 }
191}
192
193QT_END_NAMESPACE
194

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