1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "scatterpointbufferhelper_p.h"
31#include <QtGui/QVector2D>
32
33QT_BEGIN_NAMESPACE_DATAVISUALIZATION
34
35const QVector3D hiddenPos(-1000.0f, -1000.0f, -1000.0f);
36
37ScatterPointBufferHelper::ScatterPointBufferHelper()
38 : m_pointbuffer(0),
39 m_oldRemoveIndex(-1)
40{
41}
42
43ScatterPointBufferHelper::~ScatterPointBufferHelper()
44{
45 if (QOpenGLContext::currentContext())
46 glDeleteBuffers(n: 1, buffers: &m_pointbuffer);
47}
48
49GLuint ScatterPointBufferHelper::pointBuf()
50{
51 if (!m_meshDataLoaded)
52 qFatal(msg: "No loaded object");
53 return m_pointbuffer;
54}
55
56void ScatterPointBufferHelper::pushPoint(uint pointIndex)
57{
58 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
59
60 // Pop the previous point if it is still pushed
61 if (m_oldRemoveIndex >= 0) {
62 glBufferSubData(GL_ARRAY_BUFFER, offset: m_oldRemoveIndex * sizeof(QVector3D),
63 size: sizeof(QVector3D), data: &m_bufferedPoints.at(i: m_oldRemoveIndex));
64 }
65
66 glBufferSubData(GL_ARRAY_BUFFER, offset: pointIndex * sizeof(QVector3D),
67 size: sizeof(QVector3D),
68 data: &hiddenPos);
69
70 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
71
72 m_oldRemoveIndex = pointIndex;
73}
74
75void ScatterPointBufferHelper::popPoint()
76{
77 if (m_oldRemoveIndex >= 0) {
78 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
79 glBufferSubData(GL_ARRAY_BUFFER, offset: m_oldRemoveIndex * sizeof(QVector3D),
80 size: sizeof(QVector3D), data: &m_bufferedPoints.at(i: m_oldRemoveIndex));
81 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
82 }
83
84 m_oldRemoveIndex = -1;
85}
86
87void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache)
88{
89 ScatterRenderItemArray &renderArray = cache->renderArray();
90 const int renderArraySize = renderArray.size();
91 m_indexCount = 0;
92
93 if (m_meshDataLoaded) {
94 // Delete old data
95 glDeleteBuffers(n: 1, buffers: &m_pointbuffer);
96 glDeleteBuffers(n: 1, buffers: &m_uvbuffer);
97 m_bufferedPoints.clear();
98 m_pointbuffer = 0;
99 m_uvbuffer = 0;
100 m_meshDataLoaded = false;
101 }
102
103 bool itemsVisible = false;
104 m_bufferedPoints.resize(asize: renderArraySize);
105 for (int i = 0; i < renderArraySize; i++) {
106 const ScatterRenderItem &item = renderArray.at(i);
107 if (!item.isVisible()) {
108 m_bufferedPoints[i] = hiddenPos;
109 } else {
110 itemsVisible = true;
111 m_bufferedPoints[i] = item.translation();
112 }
113 }
114
115 QVector<QVector2D> buffered_uvs;
116 if (itemsVisible)
117 m_indexCount = renderArraySize;
118
119 if (m_indexCount > 0) {
120 if (cache->colorStyle() == Q3DTheme::ColorStyleRangeGradient)
121 createRangeGradientUVs(cache, buffered_uvs);
122
123 glGenBuffers(n: 1, buffers: &m_pointbuffer);
124 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
125 glBufferData(GL_ARRAY_BUFFER, size: m_bufferedPoints.size() * sizeof(QVector3D),
126 data: &m_bufferedPoints.at(i: 0),
127 GL_DYNAMIC_DRAW);
128
129 if (buffered_uvs.size()) {
130 glGenBuffers(n: 1, buffers: &m_uvbuffer);
131 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvbuffer);
132 glBufferData(GL_ARRAY_BUFFER, size: buffered_uvs.size() * sizeof(QVector2D),
133 data: &buffered_uvs.at(i: 0), GL_STATIC_DRAW);
134 }
135
136 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
137
138 m_meshDataLoaded = true;
139 }
140}
141
142void ScatterPointBufferHelper::update(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 const ScatterRenderItemArray &renderArray = cache->renderArray();
148 const int updateSize = cache->updateIndices().size();
149
150 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_pointbuffer);
151 for (int i = 0; i < updateSize; i++) {
152 int index = cache->updateIndices().at(i);
153 const ScatterRenderItem &item = renderArray.at(i: index);
154 if (!item.isVisible())
155 m_bufferedPoints[index] = hiddenPos;
156 else
157 m_bufferedPoints[index] = item.translation();
158
159 if (index != m_oldRemoveIndex) {
160 glBufferSubData(GL_ARRAY_BUFFER, offset: index * sizeof(QVector3D),
161 size: sizeof(QVector3D), data: &m_bufferedPoints.at(i: index));
162 }
163 }
164 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
165 }
166}
167
168void ScatterPointBufferHelper::updateUVs(ScatterSeriesRenderCache *cache)
169{
170 // It may be that the buffer hasn't yet been initialized, in case the entire series was
171 // hidden items. No need to update in that case.
172 if (m_indexCount > 0) {
173 QVector<QVector2D> buffered_uvs;
174 createRangeGradientUVs(cache, buffered_uvs);
175
176 if (buffered_uvs.size()) {
177 if (!m_uvbuffer)
178 glGenBuffers(n: 1, buffers: &m_uvbuffer);
179
180 int updateSize = cache->updateIndices().size();
181 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvbuffer);
182 if (updateSize) {
183 for (int i = 0; i < updateSize; i++) {
184 int index = cache->updateIndices().at(i);
185 glBufferSubData(GL_ARRAY_BUFFER, offset: index * sizeof(QVector2D),
186 size: sizeof(QVector2D), data: &buffered_uvs.at(i));
187
188 }
189 } else {
190 glBufferData(GL_ARRAY_BUFFER, size: buffered_uvs.size() * sizeof(QVector2D),
191 data: &buffered_uvs.at(i: 0), GL_STATIC_DRAW);
192 }
193
194 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
195 }
196 }
197}
198
199void ScatterPointBufferHelper::createRangeGradientUVs(ScatterSeriesRenderCache *cache,
200 QVector<QVector2D> &buffered_uvs)
201{
202 const ScatterRenderItemArray &renderArray = cache->renderArray();
203 const bool updateAll = (cache->updateIndices().size() == 0);
204 const int updateSize = updateAll ? renderArray.size() : cache->updateIndices().size();
205 buffered_uvs.resize(asize: updateSize);
206
207 QVector2D uv;
208 uv.setX(0.0f);
209 for (int i = 0; i < updateSize; i++) {
210 int index = updateAll ? i : cache->updateIndices().at(i);
211 const ScatterRenderItem &item = renderArray.at(i: index);
212
213 float y = ((item.translation().y() + m_scaleY) * 0.5f) / m_scaleY;
214 uv.setY(y);
215 buffered_uvs[i] = uv;
216 }
217}
218
219QT_END_NAMESPACE_DATAVISUALIZATION
220

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