169 void gl::Compiler::initialize() |
169 void gl::Compiler::initialize() |
170 { |
170 { |
171 if (not this->initialized) |
171 if (not this->initialized) |
172 { |
172 { |
173 this->initializeOpenGLFunctions(); |
173 this->initializeOpenGLFunctions(); |
174 for (int i = 0; i < gl::NUM_ARRAY_CLASSES; i += 1) |
174 for (auto& object : this->glObjects) |
175 { |
175 { |
176 auto& object = this->glObjects[i]; |
|
177 object.program = new QOpenGLShaderProgram; |
176 object.program = new QOpenGLShaderProgram; |
178 gl::buildShaders(object.program, ::vertexShaderSource, ::fragmentShaderSource); |
177 gl::buildShaders(object.program, ::vertexShaderSource, ::fragmentShaderSource); |
179 object.program->bind(); |
178 object.program->bind(); |
180 object.buffer.create(); |
179 object.buffer.create(); |
181 object.buffer.bind(); |
180 object.buffer.bind(); |
184 object.vertexArray.bind(); |
183 object.vertexArray.bind(); |
185 for (int k : {0, 1, 2, 3, 4}) |
184 for (int k : {0, 1, 2, 3, 4}) |
186 { |
185 { |
187 object.program->enableAttributeArray(k); |
186 object.program->enableAttributeArray(k); |
188 } |
187 } |
189 constexpr int stride = sizeof(gl::Vertex); |
188 constexpr int stride = sizeof(Vertex); |
190 object.program->setAttributeBuffer(0, GL_FLOAT, offsetof(gl::Vertex, position), 3, stride); |
189 object.program->setAttributeBuffer(0, GL_FLOAT, offsetof(Vertex, position), 3, stride); |
191 object.program->setAttributeBuffer(1, GL_FLOAT, offsetof(gl::Vertex, color), 4, stride); |
190 object.program->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, color), 4, stride); |
192 object.program->setAttributeBuffer(2, GL_FLOAT, offsetof(gl::Vertex, normal), 3, stride); |
191 object.program->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, normal), 3, stride); |
193 glVertexAttribIPointer(3, 1, GL_INT, stride, reinterpret_cast<void*>(offsetof(gl::Vertex, id))); |
192 glVertexAttribIPointer(3, 1, GL_INT, stride, reinterpret_cast<void*>(offsetof(Vertex, id))); |
194 glVertexAttribIPointer(4, 1, GL_INT, stride, reinterpret_cast<void*>(offsetof(gl::Vertex, selected))); |
193 glVertexAttribIPointer(4, 1, GL_INT, stride, reinterpret_cast<void*>(offsetof(Vertex, selected))); |
195 object.vertexArray.release(); |
194 object.vertexArray.release(); |
196 object.buffer.release(); |
195 object.buffer.release(); |
197 object.program->release(); |
196 object.program->release(); |
198 } |
197 } |
199 this->initialized = true; |
198 this->initialized = true; |
201 } |
200 } |
202 |
201 |
203 void gl::Compiler::build(Model* model, DocumentManager* context, const gl::RenderPreferences& preferences) |
202 void gl::Compiler::build(Model* model, DocumentManager* context, const gl::RenderPreferences& preferences) |
204 { |
203 { |
205 this->boundingBox = {}; |
204 this->boundingBox = {}; |
206 std::vector<gl::Vertex> vboData[gl::NUM_ARRAY_CLASSES]; |
205 std::vector<Vertex> vboData[gl::NUM_POLYGON_TYPES]; |
207 const std::vector<gl::Polygon> polygons = model->getPolygons(context); |
206 const std::vector<gl::Polygon> polygons = model->getPolygons(context); |
208 for (const gl::Polygon& polygon : polygons) |
207 for (const gl::Polygon& polygon : polygons) |
209 { |
208 { |
210 this->buildPolygon(polygon, vboData, preferences); |
209 this->buildPolygon(polygon, vboData, preferences); |
211 } |
210 } |
212 for (int arrayId = 0; arrayId < gl::NUM_ARRAY_CLASSES; arrayId += 1) |
211 for (int arrayId = 0; arrayId < gl::NUM_POLYGON_TYPES; arrayId += 1) |
213 { |
212 { |
214 auto& buffer = this->glObjects[arrayId].buffer; |
213 auto& buffer = this->glObjects[arrayId].buffer; |
215 auto& vector = vboData[arrayId]; |
214 auto& vector = vboData[arrayId]; |
216 this->storedVertexCounts[arrayId] = vector.size(); |
215 this->storedVertexCounts[arrayId] = vector.size(); |
217 this->glObjects[arrayId].cachedData = vector; // todo: get rid of this copy |
216 this->glObjects[arrayId].cachedData = vector; // todo: get rid of this copy |
242 return {data[0] * std::int32_t{0x10000} + data[1] * std::int32_t{0x100} + data[2]}; |
241 return {data[0] * std::int32_t{0x10000} + data[1] * std::int32_t{0x100} + data[2]}; |
243 } |
242 } |
244 |
243 |
245 void gl::Compiler::buildPolygon( |
244 void gl::Compiler::buildPolygon( |
246 gl::Polygon polygon, |
245 gl::Polygon polygon, |
247 std::vector<gl::Vertex>* vboData, |
246 std::vector<Vertex>* vboData, |
248 const gl::RenderPreferences& preferences) |
247 const gl::RenderPreferences& preferences) |
249 { |
248 { |
250 const gl::ArrayClass vboClass = classifyPolygon(polygon); |
249 const gl::ArrayClass vboClass = classifyPolygon(polygon); |
251 std::vector<gl::Vertex>& vertexBuffer = vboData[static_cast<int>(vboClass)]; |
250 std::vector<Vertex>& vertexBuffer = vboData[static_cast<int>(vboClass)]; |
252 auto vertexRing = iter::ring(polygon.vertices, polygon.numPolygonVertices()); |
251 auto vertexRing = iter::ring(polygon.vertices, polygon.numPolygonVertices()); |
253 reserveMore(vertexBuffer, polygon.numPolygonVertices()); |
252 reserveMore(vertexBuffer, polygon.numPolygonVertices()); |
254 const QColor color = this->getColorForPolygon(polygon, preferences); |
253 const QColor color = this->getColorForPolygon(polygon, preferences); |
255 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
254 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
256 { |
255 { |
257 const glm::vec3& v1 = vertexRing[i - 1]; |
256 const glm::vec3& v1 = vertexRing[i - 1]; |
258 const glm::vec3& v2 = vertexRing[i]; |
257 const glm::vec3& v2 = vertexRing[i]; |
259 const glm::vec3& v3 = vertexRing[i + 1]; |
258 const glm::vec3& v3 = vertexRing[i + 1]; |
260 this->boundingBox.consider(polygon.vertices[i]); |
259 this->boundingBox.consider(polygon.vertices[i]); |
261 gl::Vertex& vertex = vertexBuffer.emplace_back(); |
260 Vertex& vertex = vertexBuffer.emplace_back(); |
262 vertex.position = polygon.vertices[i]; |
261 vertex.position = polygon.vertices[i]; |
263 vertex.normal = glm::normalize(glm::cross(v1 - v2, v3 - v2)); |
262 vertex.normal = glm::normalize(glm::cross(v1 - v2, v3 - v2)); |
264 vertex.color = glm::vec4{color.redF(), color.greenF(), color.blueF(), color.alphaF()}; |
263 vertex.color = glm::vec4{color.redF(), color.greenF(), color.blueF(), color.alphaF()}; |
265 vertex.id = polygon.id.value; |
264 vertex.id = polygon.id.value; |
266 } |
265 } |
311 object.vertexArray.release(); |
310 object.vertexArray.release(); |
312 } |
311 } |
313 |
312 |
314 void gl::Compiler::setSelectedObjects(const QSet<ldraw::id_t> ids) |
313 void gl::Compiler::setSelectedObjects(const QSet<ldraw::id_t> ids) |
315 { |
314 { |
316 for (int i = 0; i < gl::NUM_ARRAY_CLASSES; i += 1) |
315 for (auto& object : this->glObjects) |
317 { |
316 { |
318 auto& vector = this->glObjects[i].cachedData; |
317 std::vector<Vertex>& vector = object.cachedData; |
319 for (gl::Vertex& vertex : vector) |
318 for (Vertex& vertex : vector) |
320 { |
319 { |
321 vertex.selected = (ids.contains({vertex.id})) ? 1 : 0; |
320 vertex.selected = (ids.contains({vertex.id})) ? 1 : 0; |
322 } |
321 } |
323 const GLsizeiptr size = static_cast<int>(vector.size() * sizeof vector[0]); |
322 const GLsizeiptr size = static_cast<int>(vector.size() * sizeof vector[0]); |
324 this->glObjects[i].buffer.bind(); |
323 object.buffer.bind(); |
325 glBufferSubData(GL_ARRAY_BUFFER, 0, size, vector.data()); |
324 glBufferSubData(GL_ARRAY_BUFFER, 0, size, vector.data()); |
|
325 object.buffer.release(); |
326 } |
326 } |
327 } |
327 } |
328 |
328 |
329 std::size_t gl::Compiler::vertexCount(const gl::ArrayClass arrayClass) const |
329 std::size_t gl::Compiler::vertexCount(const gl::ArrayClass arrayClass) const |
330 { |
330 { |