src/vertexcompiler.cpp

changeset 1385
2f18c0da749d
equal deleted inserted replaced
1384:4c134708be05 1385:2f18c0da749d
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2018 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "vertexcompiler.h"
20 #include "vertexselection.h"
21 #include "model.h"
22
23 static const Vertex sphere[] = {
24 {1, 0, 0}, {0.7071, 0.7071, 0}, {0.7071, 0, 0.7071},
25 {0, 0.7071, 0.7071}, {0, 0, 1}, {0.7071, 0, 0.7071},
26 {0.7071, 0.7071, 0}, {0, 0.7071, 0.7071}, {0.7071, 0, 0.7071},
27 {0, 1, 0}, {0, 0.7071, 0.7071}, {0.7071, 0.7071, 0},
28 {0.7071, 0, -0.7071}, {0.7071, 0.7071, 0}, {1, 0, 0},
29 {0.7071, 0, -0.7071}, {0, 0, -1}, {0, 0.7071, -0.7071},
30 {0.7071, 0, -0.7071}, {0, 0.7071, -0.7071}, {0.7071, 0.7071, 0},
31 {0.7071, 0.7071, 0}, {0, 0.7071, -0.7071}, {0, 1, 0},
32 {-0.7071, 0, 0.7071}, {-0.7071, 0.7071, 0}, {-1, 0, 0},
33 {-0.7071, 0, 0.7071}, {0, 0, 1}, {0, 0.7071, 0.7071},
34 {-0.7071, 0, 0.7071}, {0, 0.7071, 0.7071}, {-0.7071, 0.7071, 0},
35 {-0.7071, 0.7071, 0}, {0, 0.7071, 0.7071}, {0, 1, 0},
36 {-1, 0, 0}, {-0.7071, 0.7071, 0}, {-0.7071, 0, -0.7071},
37 {0, 0.7071, -0.7071}, {0, 0, -1}, {-0.7071, 0, -0.7071},
38 {-0.7071, 0.7071, 0}, {0, 0.7071, -0.7071}, {-0.7071, 0, -0.7071},
39 {0, 1, 0}, {0, 0.7071, -0.7071}, {-0.7071, 0.7071, 0},
40 {-0.7071, 0, -0.7071}, {0, 0, -1}, {0, -0.7071, -0.7071},
41 {0, -1, 0}, {0, -0.7071, 0.7071}, {-0.7071, -0.7071, 0},
42 {0.7071, -0.7071, 0}, {0, -0.7071, -0.7071}, {0.7071, 0, -0.7071},
43 {-1, 0, 0}, {-0.7071, -0.7071, 0}, {-0.7071, 0, 0.7071},
44 {-0.7071, -0.7071, 0}, {0, -0.7071, -0.7071}, {0, -1, 0},
45 {0, -1, 0}, {0, -0.7071, -0.7071}, {0.7071, -0.7071, 0},
46 {0.7071, 0, 0.7071}, {0, -0.7071, 0.7071}, {0.7071, -0.7071, 0},
47 {-0.7071, 0, -0.7071}, {-0.7071, -0.7071, 0}, {-1, 0, 0},
48 {1, 0, 0}, {0.7071, -0.7071, 0}, {0.7071, 0, -0.7071},
49 {0.7071, 0, 0.7071}, {0, 0, 1}, {0, -0.7071, 0.7071},
50 {-0.7071, 0, -0.7071}, {0, -0.7071, -0.7071}, {-0.7071, -0.7071, 0},
51 {0.7071, -0.7071, 0}, {0, -0.7071, 0.7071}, {0, -1, 0},
52 {0.7071, 0, 0.7071}, {0.7071, -0.7071, 0}, {1, 0, 0},
53 {-0.7071, -0.7071, 0}, {0, -0.7071, 0.7071}, {-0.7071, 0, 0.7071},
54 {0, -0.7071, -0.7071}, {0, 0, -1}, {0.7071, 0, -0.7071},
55 {0, -0.7071, 0.7071}, {0, 0, 1}, {-0.7071, 0, 0.7071},
56 };
57
58 static const float sphereSize = 0.5;
59 static const QColor sphereColor {192, 192, 255};
60
61 VertexCompiler::VertexCompiler(Model* model, VertexSelection* selection, QObject* parent) :
62 QObject {parent},
63 model {model}
64 {
65 connect(model, &Model::objectAdded, this, &VertexCompiler::handleNewObject);
66 connect(model, &Model::aboutToRemoveObject, this, &VertexCompiler::handleRemovedObject);
67
68 if (selection != nullptr)
69 {
70 this->connect(
71 selection,
72 &VertexSelection::vertexSelected,
73 this,
74 &VertexCompiler::updateVertex
75 );
76 this->connect(
77 selection,
78 &VertexSelection::vertexDeselected,
79 this,
80 &VertexCompiler::updateVertex
81 );
82 }
83 }
84
85 VertexCompiler::~VertexCompiler()
86 {
87 if (this->initialized)
88 {
89 GLuint buffers[NumVbos];
90
91 for (int i = 0; i < countof(this->vbos); i += 1)
92 buffers[i] = this->vbos[i].buffer;
93
94 this->glDeleteBuffers(countof(buffers), &buffers[0]);
95 }
96 }
97
98 void VertexCompiler::handleNewObject(const QModelIndex &index)
99 {
100 LDObject* object = this->model->lookup(index);
101 this->addVerticesFromObject(object);
102 connect(object, &LDObject::aboutToBeModified, this, &VertexCompiler::handlePreModifiedObject);
103 connect(object, &LDObject::modified, this, &VertexCompiler::handleModifiedObject);
104 }
105
106 void VertexCompiler::handleRemovedObject(const QModelIndex &index)
107 {
108 LDObject* object = this->model->lookup(index);
109 this->removeVerticesFromObject(object);
110 }
111
112 void VertexCompiler::handlePreModifiedObject()
113 {
114 removeVerticesFromObject(qobject_cast<LDObject*>(this->sender()));
115 }
116
117 void VertexCompiler::handleModifiedObject()
118 {
119 addVerticesFromObject(qobject_cast<LDObject*>(this->sender()));
120 }
121
122 void VertexCompiler::initialize()
123 {
124 if (not this->initialized)
125 {
126 this->initializeOpenGLFunctions();
127 this->initialized = true;
128 GLuint buffers[NumVbos];
129 this->glGenBuffers(countof(buffers), &buffers[0]);
130
131 for (int i = 0; i < countof(this->vbos); i += 1)
132 this->vbos[i].buffer = buffers[i];
133 }
134 }
135
136 void VertexCompiler::addVerticesFromObject(LDObject* object)
137 {
138 for (int i = 0; i < object->numPolygonVertices(); i += 1)
139 this->addVertex(object->vertex(i));
140
141 this->needCompile = true;
142 }
143
144 void VertexCompiler::removeVerticesFromObject(LDObject* object)
145 {
146 for (int i = 0; i < object->numPolygonVertices(); i += 1)
147 this->removeVertex(object->vertex(i));
148
149 this->needCompile = true;
150 }
151
152 void VertexCompiler::addVertex(const Vertex& vertex)
153 {
154 auto iterator = this->vertices.find(vertex);
155
156 if (iterator == this->vertices.end())
157 this->vertices.insert(vertex, 1);
158 else
159 iterator.value() += 1;
160 }
161
162 void VertexCompiler::removeVertex(const Vertex& vertex)
163 {
164 auto iterator = this->vertices.find(vertex);
165
166 if (iterator != this->vertices.end())
167 {
168 if (iterator.value() > 1)
169 iterator.value() -= 1;
170 else
171 this->vertices.erase(iterator);
172 }
173 }
174
175 void VertexCompiler::updateVertex(const Vertex&)
176 {
177 this->needCompile = true;
178 }
179
180 /*
181 * Returns the GL buffer for the given vbo.
182 */
183 GLuint VertexCompiler::vbo(Vbo vboIndex)
184 {
185 if (this->needCompile)
186 {
187 this->compile();
188 this->upload();
189 this->needCompile = false;
190 }
191
192 return this->vbos[vboIndex].buffer;
193 }
194
195 /*
196 * Returns the size of the given vbo.
197 */
198 size_t VertexCompiler::vboSize(Vbo vboIndex) const
199 {
200 return this->vbos[vboIndex].data.size();
201 }
202
203 /*
204 * Clears the vertex scene.
205 */
206 void VertexCompiler::clear()
207 {
208 for (auto& vbo : this->vbos)
209 vbo.data.clear();
210 }
211
212 /*
213 * Builds the vertex scene
214 */
215 void VertexCompiler::compile()
216 {
217 this->clear();
218 QMapIterator<Vertex, unsigned int> iterator {this->vertices};
219
220 while (iterator.hasNext())
221 {
222 iterator.next();
223 this->compileVertex(iterator.key());
224 }
225 }
226
227 /*
228 * Adds a little sphere into the scene to represent the given vertex.
229 */
230 void VertexCompiler::compileVertex(const Vertex& vertex)
231 {
232 for (int i = 0; i < countof(::sphere); i += 1)
233 {
234 // Y and Z inverted like the rest of the scene
235 Vertex spherePoint = {
236 ::sphere[i][X] * ::sphereSize + vertex.x,
237 ::sphere[i][Y] * ::sphereSize - vertex.y,
238 ::sphere[i][Z] * ::sphereSize - vertex.z
239 };
240 this->vbos[Surfaces].data << spherePoint.x << spherePoint.y << spherePoint.z;
241 // The points of the sphere are position vectors, which in this case are also unit normals.
242 this->vbos[Normals].data << ::sphere[i][X] << ::sphere[i][Y] << ::sphere[i][Z];
243 this->vbos[Colors].data
244 << ::sphereColor.redF()
245 << ::sphereColor.greenF()
246 << ::sphereColor.blueF()
247 << ::sphereColor.alphaF();
248 }
249 }
250
251 /*
252 * Uploads VBO data to the graphics card.
253 */
254 void VertexCompiler::upload()
255 {
256 for (const auto& vbo : this->vbos)
257 {
258 glBindBuffer(GL_ARRAY_BUFFER, vbo.buffer);
259 glBufferData(
260 GL_ARRAY_BUFFER,
261 countof(vbo.data) * sizeof(GLfloat),
262 vbo.data.constData(),
263 GL_STATIC_DRAW
264 );
265 }
266 glBindBuffer(GL_ARRAY_BUFFER, 0);
267 }

mercurial