--- a/src/glCompiler.cc Tue Mar 03 16:50:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,423 +0,0 @@ -/* - * LDForge: LDraw parts authoring CAD - * Copyright (C) 2013 - 2015 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/>. - */ - -#define GL_GLEXT_PROTOTYPES -#include <GL/glu.h> -#include <GL/glext.h> -#include "glCompiler.h" -#include "ldObject.h" -#include "colors.h" -#include "ldDocument.h" -#include "miscallenous.h" -#include "glRenderer.h" -#include "dialogs.h" - -struct GLErrorInfo -{ - GLenum value; - QString text; -}; - -static const GLErrorInfo g_GLErrors[] = -{ - { GL_NO_ERROR, "No error" }, - { GL_INVALID_ENUM, "Unacceptable enumerator passed" }, - { GL_INVALID_VALUE, "Numeric argument out of range" }, - { GL_INVALID_OPERATION, "The operation is not allowed to be done in this state" }, - { GL_INVALID_FRAMEBUFFER_OPERATION, "Framebuffer object is not complete"}, - { GL_OUT_OF_MEMORY, "Out of memory" }, - { GL_STACK_UNDERFLOW, "The operation would have caused an underflow" }, - { GL_STACK_OVERFLOW, "The operation would have caused an overflow" }, -}; - -CFGENTRY (String, SelectColorBlend, "#0080FF") -EXTERN_CFGENTRY (Bool, BlackEdges) -EXTERN_CFGENTRY (String, BackgroundColor) - -static QList<int> g_warnedColors; -static const QColor g_BFCFrontColor (64, 192, 80); -static const QColor g_BFCBackColor (208, 64, 64); - -// static QMap<LDObjectPtr, String> g_objectOrigins; - -// ============================================================================= -// -void CheckGLErrorImpl (const char* file, int line) -{ - QString errmsg; - GLenum errnum = glGetError(); - - if (errnum == GL_NO_ERROR) - return; - - for (const GLErrorInfo& err : g_GLErrors) - { - if (err.value == errnum) - { - errmsg = err.text; - break; - } - } - - print ("OpenGL ERROR: at %1:%2: %3", Basename (QString (file)), line, errmsg); -} - -// ============================================================================= -// -GLCompiler::GLCompiler (GLRenderer* renderer) : - m_renderer (renderer) -{ - needMerge(); - memset (m_vboSizes, 0, sizeof m_vboSizes); -} - -// ============================================================================= -// -void GLCompiler::initialize() -{ - initializeOpenGLFunctions(); - glGenBuffers (g_numVBOs, &m_vbo[0]); - CHECK_GL_ERROR(); -} - -// ============================================================================= -// -GLCompiler::~GLCompiler() -{ - glDeleteBuffers (g_numVBOs, &m_vbo[0]); - CHECK_GL_ERROR(); - - if (m_renderer != null) - m_renderer->setCompiler (null); -} - -// ============================================================================= -// -uint32 GLCompiler::colorToRGB (const QColor& color) -{ - return - (color.red() & 0xFF) << 0x00 | - (color.green() & 0xFF) << 0x08 | - (color.blue() & 0xFF) << 0x10 | - (color.alpha() & 0xFF) << 0x18; -} - -// ============================================================================= -// -QColor GLCompiler::indexColorForID (int id) const -{ - // Calculate a color based from this index. This method caters for - // 16777216 objects. I don't think that will be exceeded anytime soon. :) - int r = (id / 0x10000) % 0x100, - g = (id / 0x100) % 0x100, - b = id % 0x100; - - return QColor (r, g, b); -} - -// ============================================================================= -// -QColor GLCompiler::getColorForPolygon (LDPolygon& poly, LDObjectPtr topobj, - EVBOComplement complement) const -{ - QColor qcol; - - switch (complement) - { - case VBOCM_Surfaces: - case VBOCM_NumComplements: - return QColor(); - - case VBOCM_BFCFrontColors: - qcol = g_BFCFrontColor; - break; - - case VBOCM_BFCBackColors: - qcol = g_BFCBackColor; - break; - - case VBOCM_PickColors: - return indexColorForID (topobj->id()); - - case VBOCM_RandomColors: - qcol = topobj->randomColor(); - break; - - case VBOCM_NormalColors: - if (poly.color == MainColorIndex) - { - if (topobj->color() == MainColor()) - qcol = GLRenderer::getMainColor(); - else - qcol = topobj->color().faceColor(); - } - elif (poly.color == EdgeColorIndex) - { - qcol = Luma (QColor (cfg::BackgroundColor)) > 40 ? Qt::black : Qt::white; - } - else - { - LDColor col = LDColor::fromIndex (poly.color); - - if (col) - qcol = col.faceColor(); - } - break; - } - - if (not qcol.isValid()) - { - // The color was unknown. Use main color to make the polygon at least - // not appear pitch-black. - if (poly.num != 2 and poly.num != 5) - qcol = GLRenderer::getMainColor(); - else - qcol = Qt::black; - - // Warn about the unknown color, but only once. - if (not g_warnedColors.contains (poly.color)) - { - print ("Unknown color %1!\n", poly.color); - g_warnedColors << poly.color; - } - - return qcol; - } - - double blendAlpha = 0.0; - - if (topobj->isSelected()) - blendAlpha = 1.0; - elif (topobj == m_renderer->objectAtCursor()) - blendAlpha = 0.5; - - if (blendAlpha != 0.0) - { - QColor selcolor (cfg::SelectColorBlend); - double denom = blendAlpha + 1.0; - qcol.setRed ((qcol.red() + (selcolor.red() * blendAlpha)) / denom); - qcol.setGreen ((qcol.green() + (selcolor.green() * blendAlpha)) / denom); - qcol.setBlue ((qcol.blue() + (selcolor.blue() * blendAlpha)) / denom); - } - - return qcol; -} - -// ============================================================================= -// -void GLCompiler::needMerge() -{ - for (int i = 0; i < countof (m_vboChanged); ++i) - m_vboChanged[i] = true; -} - -// ============================================================================= -// -void GLCompiler::stageForCompilation (LDObjectPtr obj) -{ - /* - g_objectOrigins[obj] = format ("%1:%2 (%3)", - obj->document()->getDisplayName(), obj->lineNumber(), obj->typeName()); - */ - - m_staged << LDObjectWeakPtr (obj); -} - -// ============================================================================= -// -void GLCompiler::unstage (LDObjectPtr obj) -{ - m_staged.removeOne (LDObjectWeakPtr (obj)); -} - -// ============================================================================= -// -void GLCompiler::compileDocument (LDDocumentPtr doc) -{ - if (doc == null) - return; - - for (LDObjectPtr obj : doc->objects()) - compileObject (obj); -} - -// ============================================================================= -// -void GLCompiler::compileStaged() -{ - RemoveDuplicates (m_staged); - - for (auto it = m_staged.begin(); it != m_staged.end(); ++it) - { - if (*it == null) - continue; - - compileObject (*it); - } - - m_staged.clear(); -} - -// ============================================================================= -// -void GLCompiler::prepareVBO (int vbonum) -{ - // Compile anything that still awaits it - compileStaged(); - - if (not m_vboChanged[vbonum]) - return; - - QVector<GLfloat> vbodata; - - for (auto it = m_objectInfo.begin(); it != m_objectInfo.end();) - { - if (it.key() == null) - { - it = m_objectInfo.erase (it); - continue; - } - - if (it.key().toStrongRef()->document() == CurrentDocument() - and not it.key().toStrongRef()->isHidden()) - { - vbodata += it->data[vbonum]; - } - - ++it; - } - - glBindBuffer (GL_ARRAY_BUFFER, m_vbo[vbonum]); - glBufferData (GL_ARRAY_BUFFER, vbodata.size() * sizeof(GLfloat), vbodata.constData(), GL_STATIC_DRAW); - glBindBuffer (GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); - m_vboChanged[vbonum] = false; - m_vboSizes[vbonum] = vbodata.size(); -} - -// ============================================================================= -// -void GLCompiler::dropObject (LDObjectPtr obj) -{ - auto it = m_objectInfo.find (obj); - - if (it != m_objectInfo.end()) - { - m_objectInfo.erase (it); - needMerge(); - } - - unstage (obj); -} - -// ============================================================================= -// -void GLCompiler::compileObject (LDObjectPtr obj) -{ -// print ("Compile %1\n", g_objectOrigins[obj]); - - if (obj == null or obj->document() == null or obj->document().toStrongRef()->isImplicit()) - return; - - ObjectVBOInfo info; - info.isChanged = true; - dropObject (obj); - - switch (obj->type()) - { - // Note: We cannot split quads into triangles here, it would mess up the - // wireframe view. Quads must go into separate vbos. - case OBJ_Triangle: - case OBJ_Quad: - case OBJ_Line: - case OBJ_CondLine: - { - LDPolygon* poly = obj->getPolygon(); - poly->id = obj->id(); - compilePolygon (*poly, obj, &info); - delete poly; - break; - } - - case OBJ_Subfile: - { - LDSubfilePtr ref = obj.staticCast<LDSubfile>(); - auto data = ref->inlinePolygons(); - - for (LDPolygon& poly : data) - { - poly.id = obj->id(); - compilePolygon (poly, obj, &info); - } - break; - } - - default: - break; - } - - m_objectInfo[obj] = info; - needMerge(); -} - -// ============================================================================= -// -void GLCompiler::compilePolygon (LDPolygon& poly, LDObjectPtr topobj, ObjectVBOInfo* objinfo) -{ - EVBOSurface surface; - int numverts; - - switch (poly.num) - { - case 2: surface = VBOSF_Lines; numverts = 2; break; - case 3: surface = VBOSF_Triangles; numverts = 3; break; - case 4: surface = VBOSF_Quads; numverts = 4; break; - case 5: surface = VBOSF_CondLines; numverts = 2; break; - default: return; - } - - for (EVBOComplement complement = VBOCM_First; complement < VBOCM_NumComplements; ++complement) - { - const int vbonum = vboNumber (surface, complement); - QVector<GLfloat>& vbodata = objinfo->data[vbonum]; - const QColor color = getColorForPolygon (poly, topobj, complement); - - for (int vert = 0; vert < numverts; ++vert) - { - if (complement == VBOCM_Surfaces) - { - // Write coordinates. Apparently Z must be flipped too? - vbodata << poly.vertices[vert].x() - << -poly.vertices[vert].y() - << -poly.vertices[vert].z(); - } - else - { - vbodata << ((GLfloat) color.red()) / 255.0f - << ((GLfloat) color.green()) / 255.0f - << ((GLfloat) color.blue()) / 255.0f - << ((GLfloat) color.alpha()) / 255.0f; - } - } - } -} - -void GLCompiler::setRenderer (GLRenderer* renderer) -{ - m_renderer = renderer; -}