Fri, 27 Apr 2018 16:27:14 +0300
added vertex rendering
/* * LDForge: LDraw parts authoring CAD * Copyright (C) 2013 - 2018 Teemu Piippo * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "vertexcompiler.h" #include "vertexselection.h" #include "model.h" static const Vertex sphere[] = { {1, 0, 0}, {0.7071, 0.7071, 0}, {0.7071, 0, 0.7071}, {0, 0.7071, 0.7071}, {0, 0, 1}, {0.7071, 0, 0.7071}, {0.7071, 0.7071, 0}, {0, 0.7071, 0.7071}, {0.7071, 0, 0.7071}, {0, 1, 0}, {0, 0.7071, 0.7071}, {0.7071, 0.7071, 0}, {0.7071, 0, -0.7071}, {0.7071, 0.7071, 0}, {1, 0, 0}, {0.7071, 0, -0.7071}, {0, 0, -1}, {0, 0.7071, -0.7071}, {0.7071, 0, -0.7071}, {0, 0.7071, -0.7071}, {0.7071, 0.7071, 0}, {0.7071, 0.7071, 0}, {0, 0.7071, -0.7071}, {0, 1, 0}, {-0.7071, 0, 0.7071}, {-0.7071, 0.7071, 0}, {-1, 0, 0}, {-0.7071, 0, 0.7071}, {0, 0, 1}, {0, 0.7071, 0.7071}, {-0.7071, 0, 0.7071}, {0, 0.7071, 0.7071}, {-0.7071, 0.7071, 0}, {-0.7071, 0.7071, 0}, {0, 0.7071, 0.7071}, {0, 1, 0}, {-1, 0, 0}, {-0.7071, 0.7071, 0}, {-0.7071, 0, -0.7071}, {0, 0.7071, -0.7071}, {0, 0, -1}, {-0.7071, 0, -0.7071}, {-0.7071, 0.7071, 0}, {0, 0.7071, -0.7071}, {-0.7071, 0, -0.7071}, {0, 1, 0}, {0, 0.7071, -0.7071}, {-0.7071, 0.7071, 0}, {-0.7071, 0, -0.7071}, {0, 0, -1}, {0, -0.7071, -0.7071}, {0, -1, 0}, {0, -0.7071, 0.7071}, {-0.7071, -0.7071, 0}, {0.7071, -0.7071, 0}, {0, -0.7071, -0.7071}, {0.7071, 0, -0.7071}, {-1, 0, 0}, {-0.7071, -0.7071, 0}, {-0.7071, 0, 0.7071}, {-0.7071, -0.7071, 0}, {0, -0.7071, -0.7071}, {0, -1, 0}, {0, -1, 0}, {0, -0.7071, -0.7071}, {0.7071, -0.7071, 0}, {0.7071, 0, 0.7071}, {0, -0.7071, 0.7071}, {0.7071, -0.7071, 0}, {-0.7071, 0, -0.7071}, {-0.7071, -0.7071, 0}, {-1, 0, 0}, {1, 0, 0}, {0.7071, -0.7071, 0}, {0.7071, 0, -0.7071}, {0.7071, 0, 0.7071}, {0, 0, 1}, {0, -0.7071, 0.7071}, {-0.7071, 0, -0.7071}, {0, -0.7071, -0.7071}, {-0.7071, -0.7071, 0}, {0.7071, -0.7071, 0}, {0, -0.7071, 0.7071}, {0, -1, 0}, {0.7071, 0, 0.7071}, {0.7071, -0.7071, 0}, {1, 0, 0}, {-0.7071, -0.7071, 0}, {0, -0.7071, 0.7071}, {-0.7071, 0, 0.7071}, {0, -0.7071, -0.7071}, {0, 0, -1}, {0.7071, 0, -0.7071}, {0, -0.7071, 0.7071}, {0, 0, 1}, {-0.7071, 0, 0.7071}, }; static const float sphereSize = 0.5; static const QColor sphereColor {192, 192, 255}; VertexCompiler::VertexCompiler(Model* model, VertexSelection* selection, QObject* parent) : QObject {parent}, model {model} { connect(model, &Model::objectAdded, this, &VertexCompiler::handleNewObject); connect(model, &Model::aboutToRemoveObject, this, &VertexCompiler::handleRemovedObject); if (selection != nullptr) { this->connect( selection, &VertexSelection::vertexSelected, this, &VertexCompiler::updateVertex ); this->connect( selection, &VertexSelection::vertexDeselected, this, &VertexCompiler::updateVertex ); } } VertexCompiler::~VertexCompiler() { if (this->initialized) { GLuint buffers[NumVbos]; for (int i = 0; i < countof(this->vbos); i += 1) buffers[i] = this->vbos[i].buffer; this->glDeleteBuffers(countof(buffers), &buffers[0]); } } void VertexCompiler::handleNewObject(const QModelIndex &index) { LDObject* object = this->model->lookup(index); this->addVerticesFromObject(object); connect(object, &LDObject::aboutToBeModified, this, &VertexCompiler::handlePreModifiedObject); connect(object, &LDObject::modified, this, &VertexCompiler::handleModifiedObject); } void VertexCompiler::handleRemovedObject(const QModelIndex &index) { LDObject* object = this->model->lookup(index); this->removeVerticesFromObject(object); } void VertexCompiler::handlePreModifiedObject() { removeVerticesFromObject(qobject_cast<LDObject*>(this->sender())); } void VertexCompiler::handleModifiedObject() { addVerticesFromObject(qobject_cast<LDObject*>(this->sender())); } void VertexCompiler::initialize() { if (not this->initialized) { this->initializeOpenGLFunctions(); this->initialized = true; GLuint buffers[NumVbos]; this->glGenBuffers(countof(buffers), &buffers[0]); for (int i = 0; i < countof(this->vbos); i += 1) this->vbos[i].buffer = buffers[i]; } } void VertexCompiler::addVerticesFromObject(LDObject* object) { for (int i = 0; i < object->numPolygonVertices(); i += 1) this->addVertex(object->vertex(i)); this->needCompile = true; } void VertexCompiler::removeVerticesFromObject(LDObject* object) { for (int i = 0; i < object->numPolygonVertices(); i += 1) this->removeVertex(object->vertex(i)); this->needCompile = true; } void VertexCompiler::addVertex(const Vertex& vertex) { auto iterator = this->vertices.find(vertex); if (iterator == this->vertices.end()) this->vertices.insert(vertex, 1); else iterator.value() += 1; } void VertexCompiler::removeVertex(const Vertex& vertex) { auto iterator = this->vertices.find(vertex); if (iterator != this->vertices.end()) { if (iterator.value() > 1) iterator.value() -= 1; else this->vertices.erase(iterator); } } void VertexCompiler::updateVertex(const Vertex&) { this->needCompile = true; } /* * Returns the GL buffer for the given vbo. */ GLuint VertexCompiler::vbo(Vbo vboIndex) { if (this->needCompile) { this->compile(); this->upload(); this->needCompile = false; } return this->vbos[vboIndex].buffer; } /* * Returns the size of the given vbo. */ size_t VertexCompiler::vboSize(Vbo vboIndex) const { return this->vbos[vboIndex].data.size(); } /* * Clears the vertex scene. */ void VertexCompiler::clear() { for (auto& vbo : this->vbos) vbo.data.clear(); } /* * Builds the vertex scene */ void VertexCompiler::compile() { this->clear(); QMapIterator<Vertex, unsigned int> iterator {this->vertices}; while (iterator.hasNext()) { iterator.next(); this->compileVertex(iterator.key()); } } /* * Adds a little sphere into the scene to represent the given vertex. */ void VertexCompiler::compileVertex(const Vertex& vertex) { for (int i = 0; i < countof(::sphere); i += 1) { // Y and Z inverted like the rest of the scene Vertex spherePoint = { ::sphere[i][X] * ::sphereSize + vertex.x, ::sphere[i][Y] * ::sphereSize - vertex.y, ::sphere[i][Z] * ::sphereSize - vertex.z }; this->vbos[Surfaces].data << spherePoint.x << spherePoint.y << spherePoint.z; // The points of the sphere are position vectors, which in this case are also unit normals. this->vbos[Normals].data << ::sphere[i][X] << ::sphere[i][Y] << ::sphere[i][Z]; this->vbos[Colors].data << ::sphereColor.redF() << ::sphereColor.greenF() << ::sphereColor.blueF() << ::sphereColor.alphaF(); } } /* * Uploads VBO data to the graphics card. */ void VertexCompiler::upload() { for (const auto& vbo : this->vbos) { glBindBuffer(GL_ARRAY_BUFFER, vbo.buffer); glBufferData( GL_ARRAY_BUFFER, countof(vbo.data) * sizeof(GLfloat), vbo.data.constData(), GL_STATIC_DRAW ); } glBindBuffer(GL_ARRAY_BUFFER, 0); }