Wed, 05 Feb 2014 06:07:05 +0200
Merge ../ldforge into gl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/GLCompiler.cc Wed Feb 05 06:07:05 2014 +0200 @@ -0,0 +1,340 @@ +#define GL_GLEXT_PROTOTYPES +#include <GL/glu.h> +#include <GL/glext.h> +#include "GLCompiler.h" +#include "LDObject.h" +#include "Colors.h" +#include "Document.h" +#include "Misc.h" +#include "GLRenderer.h" +#include "Dialogs.h" + +static const struct +{ + GLenum value; + QString text; +} +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" }, +}; + +#define DEBUG_PRINT(...) fprint (stdout, __VA_ARGS__) + +extern_cfg (Bool, gl_blackedges); +static QList<short> g_warnedColors; + +static const QColor g_BFCFrontColor(40, 192, 0); +static const QColor g_BFCBackColor(224, 0, 0); + +// ============================================================================= +// +void checkGLError_private (const char* file, int line) +{ + GLenum errnum = glGetError(); + + if (errnum == GL_NO_ERROR) + return; + + QString errmsg; + + for (const auto& it : g_GLErrors) + { + if (it.value == errnum) + { + errmsg = it.text; + break; + } + } + + log ("GL ERROR: %1:%2: %3", file, line, errmsg); +} + +// ============================================================================= +// +GLCompiler::GLCompiler() : + m_Document (null) +{ + needMerge(); +} + +// ============================================================================= +// +void GLCompiler::initialize() +{ + glGenBuffers (VBO_NumArrays, &m_mainVBOs[0]); + checkGLError(); +} + +GLCompiler::~GLCompiler() +{ + glDeleteBuffers (VBO_NumArrays, &m_mainVBOs[0]); + checkGLError(); +} + +// ============================================================================= +// +uint32 GLCompiler::getColorRGB (const QColor& color) +{ + return + (color.red() & 0xFF) << 0x00 | + (color.green() & 0xFF) << 0x08 | + (color.blue() & 0xFF) << 0x10 | + (color.alpha() & 0xFF) << 0x18; +} + +// ============================================================================= +// +QColor GLCompiler::getObjectColor (LDObject* obj, GLCompiler::E_ColorType colortype) const +{ + QColor qcol; + + if (!obj->isColored()) + return QColor(); + + if (colortype == E_PickColor) + { + // Make the color by the object's ID if we're picking, so we can make the + // ID again from the color we get from the picking results. Be sure to use + // the top level parent's index since we want a subfile's children point + // to the subfile itself. + long i = obj->topLevelParent()->getID(); + + // Calculate a color based from this index. This method caters for + // 16777216 objects. I don't think that'll be exceeded anytime soon. :) + // ATM biggest is 53588.dat with 12600 lines. + int r = (i / 0x10000) % 0x100, + g = (i / 0x100) % 0x100, + b = i % 0x100; + + return QColor (r, g, b); + } + + if (obj->getColor() == maincolor) + qcol = GLRenderer::getMainColor(); + else + { + LDColor* col = getColor (obj->getColor()); + + if (col) + qcol = col->faceColor; + } + + if (obj->getColor() == edgecolor) + { + qcol = QColor (32, 32, 32); // luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black; + LDColor* col; + + if (!gl_blackedges && obj->getParent() && (col = getColor (obj->getParent()->getColor()))) + qcol = col->edgeColor; + } + + if (qcol.isValid() == false) + { + // The color was unknown. Use main color to make the object at least + // not appear pitch-black. + if (obj->getColor() != edgecolor) + qcol = GLRenderer::getMainColor(); + else + qcol = Qt::black; + + // Warn about the unknown color, but only once. + for (short i : g_warnedColors) + if (obj->getColor() == i) + return qcol; + + log ("%1: Unknown color %2!\n", __func__, obj->getColor()); + g_warnedColors << obj->getColor(); + return qcol; + } + + if (obj->topLevelParent()->isSelected()) + { + // Brighten it up if selected. + const int add = 51; + + qcol.setRed (min (qcol.red() + add, 255)); + qcol.setGreen (min (qcol.green() + add, 255)); + qcol.setBlue (min (qcol.blue() + add, 255)); + } + + return qcol; +} + +// ============================================================================= +// +void GLCompiler::needMerge() +{ + // Set all of m_changed to true + // memset (m_changed, 0xFF, sizeof m_changed); + for (int i = 0; i < VBO_NumArrays; ++i) + m_changed[i] = true; +} + +// ============================================================================= +// +void GLCompiler::stageForCompilation (LDObject* obj) +{ + m_staged << obj; + removeDuplicates (m_staged); +} + +// ============================================================================= +// +void GLCompiler::compileDocument() +{ + for (LDObject* obj : getDocument()->getObjects()) + compileObject (obj); +} + +// ============================================================================= +// +void GLCompiler::compileStaged() +{ + for (LDObject* obj : m_staged) + compileObject (obj); + + m_staged.clear(); +} + +// ============================================================================= +// +void GLCompiler::prepareVBOArray (E_VBOArray type) +{ + // Compile anything that still awaits it + compileStaged(); + + if (!m_changed[type]) + return; + + m_mainVBOData[type].clear(); + + for (auto it = m_objArrays.begin(); it != m_objArrays.end(); ++it) + m_mainVBOData[type] += (*it)[type]; + + glBindBuffer (GL_ARRAY_BUFFER, m_mainVBOs[type]); + checkGLError(); + glBufferData (GL_ARRAY_BUFFER, m_mainVBOData[type].size() * sizeof(float), + m_mainVBOData[type].constData(), GL_DYNAMIC_DRAW); + checkGLError(); + glBindBuffer (GL_ARRAY_BUFFER, 0); + checkGLError(); + m_changed[type] = false; + log ("VBO array %1 prepared: %2 coordinates", (int) type, m_mainVBOData[type].size()); +} + +// ============================================================================= +// +void GLCompiler::forgetObject (LDObject* obj) +{ + auto it = m_objArrays.find (obj); + + if (it != m_objArrays.end()) + { + delete *it; + m_objArrays.erase (it); + } +} + +// ============================================================================= +// +void GLCompiler::compileObject (LDObject* obj) +{ + // Ensure we have valid arrays to write to. + if (m_objArrays.find (obj) == m_objArrays.end()) + m_objArrays[obj] = new QVector<GLfloat>[VBO_NumArrays]; + else + { + // Arrays exist already, clear them. + for (int i = 0; i < VBO_NumArrays; ++i) + m_objArrays[obj][i].clear(); + } + + compileSubObject (obj, obj); + QList<int> data; + + for (int i = 0; i < VBO_NumArrays; ++i) + data << m_objArrays[obj][i].size(); + + dlog ("Compiled #%1: %2 coordinates", obj->getID(), data); + needMerge(); +} + +// ============================================================================= +// +void GLCompiler::compileSubObject (LDObject* obj, LDObject* topobj) +{ + switch (obj->getType()) + { + // Note: We cannot split the quad into triangles here, it would + // mess up the wireframe view. Quads must go into a separate array. + case LDObject::ETriangle: + case LDObject::EQuad: + case LDObject::ELine: + case LDObject::ECondLine: + { + E_VBOArray arraynum; + int verts; + + switch (obj->getType()) + { + case LDObject::ETriangle: arraynum = VBO_Triangles; verts = 3; break; + case LDObject::EQuad: arraynum = VBO_Quads; verts = 4; break; + case LDObject::ELine: arraynum = VBO_Lines; verts = 2; break; + case LDObject::ECondLine: arraynum = VBO_CondLines; verts = 2; break; + default: break; + } + + QVector<GLfloat>* ap = m_objArrays[topobj]; + QColor normalColor = getObjectColor (obj, E_NormalColor); + QColor pickColor = getObjectColor (topobj, E_PickColor); + + for (int i = 0; i < verts; ++i) + { + // Write coordinates + ap[arraynum] + << obj->getVertex (i).x() + << -obj->getVertex (i).y() + << -obj->getVertex (i).z(); + + // Colors + writeColor (ap[VBO_NormalColors], normalColor); + writeColor (ap[VBO_PickColors], pickColor); + writeColor (ap[VBO_BFCFrontColors], g_BFCFrontColor); + writeColor (ap[VBO_BFCBackColors], g_BFCBackColor); + } + } break; + + case LDObject::ESubfile: + { + LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDObjectList subobjs = ref->inlineContents (LDSubfile::DeepCacheInline | LDSubfile::RendererInline); + + for (LDObject* subobj : subobjs) + { + compileSubObject (subobj, topobj); + subobj->deleteSelf(); + } + } break; + + default: + break; + } +} + +// ============================================================================= +// +void GLCompiler::writeColor (QVector<GLfloat>& array, const QColor& color) +{ + array << color.red() + << color.green() + << color.blue() + << color.alpha(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/GLCompiler.h Wed Feb 05 06:07:05 2014 +0200 @@ -0,0 +1,105 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013, 2014 Santeri 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/>. + */ + +#ifndef LDFORGE_GLCOMPILER_H +#define LDFORGE_GLCOMPILER_H + +#include "Main.h" +#include "GLRenderer.h" +#include "GLShared.h" +#include <QMap> + +// ============================================================================= +// GLCompiler +// +// This class manages vertex arrays for the GL renderer, compiling vertices into +// VAO-readable triangles which can be requested with getMergedBuffer. +// +// There are 6 main array types: +// - the normal polygon array, for triangles +// - edge line array, for lines +// - conditional line array, for conditional lines. Kept separate so that they +// can be drawn as dashed liness +// - BFC array, this is the same as the normal polygon array except that the +// polygons are listed twice, once normally and green and once reversed +// and red, this allows BFC red/green view. +// - Picking array, this is the same as the normal polygon array except the +// polygons are compiled with their index color, this way the picking +// method is capable of determining which object was selected by pixel +// color. +// - Edge line picking array, the pick array version of the edge line array. +// Conditional lines are grouped with normal edgelines here. +// +// There are also these same 5 arrays for every LDObject compiled. The main +// arrays are generated on demand from the ones in the current file's +// LDObjects and stored in cache for faster renmm dering. +// +// The nested Array class contains a vector-like buffer of the Vertex structs, +// these structs are the VAOs that get passed to the renderer. +// +class GLCompiler +{ + PROPERTY (public, LDDocumentPointer, Document, NO_OPS, STOCK_WRITE) + + public: + enum E_ColorType + { + E_NormalColor, + E_PickColor, + }; + + GLCompiler(); + ~GLCompiler(); + void compileDocument(); + void forgetObject (LDObject* obj); + void initObject (LDObject* obj); + QColor getObjectColor (LDObject* obj, E_ColorType colortype) const; + void needMerge(); + void prepareVBOArray (E_VBOArray type); + void stageForCompilation (LDObject* obj); + + static uint32 getColorRGB (const QColor& color); + + inline GLuint getVBOIndex (E_VBOArray array) const + { + return m_mainVBOs[array]; + } + + inline int getVBOCount (E_VBOArray array) const + { + return m_mainVBOData[array].size() / 3; + } + void initialize(); + + private: + void compileStaged(); + void compileObject (LDObject* obj); + void compileSubObject (LDObject* obj, LDObject* topobj); + void writeColor (QVector< float >& array, const QColor& color); + + QMap<LDObject*, QVector<GLfloat>*> m_objArrays; + QVector<GLfloat> m_mainVBOData[VBO_NumArrays]; + GLuint m_mainVBOs[VBO_NumArrays]; + bool m_changed[VBO_NumArrays]; + LDObjectList m_staged; // Objects that need to be compiled +}; + +#define checkGLError() { checkGLError_private (__FILE__, __LINE__); } +void checkGLError_private (const char* file, int line); + +#endif // LDFORGE_GLCOMPILER_H
--- a/src/GLRenderer.cc Wed Feb 05 06:06:23 2014 +0200 +++ b/src/GLRenderer.cc Wed Feb 05 06:07:05 2014 +0200 @@ -16,6 +16,9 @@ * 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 <QGLWidget> #include <QWheelEvent> #include <QMouseEvent> @@ -23,8 +26,6 @@ #include <QInputDialog> #include <QToolTip> #include <QTimer> -#include <GL/glu.h> - #include "Main.h" #include "Configuration.h" #include "Document.h" @@ -36,6 +37,7 @@ #include "Dialogs.h" #include "AddObjectDialog.h" #include "MessageLog.h" +#include "GLCompiler.h" #include "Primitives.h" #include "misc/RingFinder.h" #include "moc_GLRenderer.cpp" @@ -97,20 +99,21 @@ GL::EFreeCamera }; -// Definitions for visual axes, drawn on the screen -const struct LDGLAxis +struct LDGLAxis { const QColor col; const Vertex vert; -} g_GLAxes[3] = +}; + +// Definitions for visual axes, drawn on the screen +static const LDGLAxis g_GLAxes[3] = { { QColor (255, 0, 0), Vertex (10000, 0, 0) }, // X { QColor (80, 192, 0), Vertex (0, 10000, 0) }, // Y { QColor (0, 160, 192), Vertex (0, 0, 10000) }, // Z }; -static bool g_glInvert = false; -static QList<int> g_warnedColors; +static GLuint g_GLAxes_VBO; // ============================================================================= // @@ -127,6 +130,7 @@ setMessageLog (null); m_width = m_height = -1; m_hoverpos = g_origin; + m_compiler = new GLCompiler; m_toolTipTimer = new QTimer (this); m_toolTipTimer->setSingleShot (true); @@ -158,6 +162,8 @@ for (CameraIcon& info : m_cameraIcons) delete info.img; + + delete m_compiler; } // ============================================================================= @@ -245,11 +251,46 @@ setBackground(); glLineWidth (gl_linethickness); + glLineStipple (1, 0x6666); setAutoFillBackground (false); setMouseTracking (true); setFocusPolicy (Qt::WheelFocus); - compileAllObjects(); + + m_compiler->initialize(); + m_compiler->compileDocument(); + + initializeAxes(); +} + +// ============================================================================= +// +void GLRenderer::initializeAxes() +{ + float axesdata[18]; + memset (axesdata, 0, sizeof axesdata); + float colordata[18]; + + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + axesdata[(i * 6) + j] = g_GLAxes[i].vert.getCoordinate (j); + axesdata[(i * 6) + 3 + j] = -g_GLAxes[i].vert.getCoordinate (j); + } + + for (int j = 0; j < 2; ++j) + { + colordata[(i * 6) + (j * 3) + 0] = g_GLAxes[i].col.red(); + colordata[(i * 6) + (j * 3) + 1] = g_GLAxes[i].col.green(); + colordata[(i * 6) + (j * 3) + 2] = g_GLAxes[i].col.blue(); + } + } + + glGenBuffers (1, &g_GLAxes_VBO); + glBindBuffer (GL_ARRAY_BUFFER, g_GLAxes_VBO); + glBufferData (GL_ARRAY_BUFFER, sizeof axesdata, axesdata, GL_STATIC_DRAW); + glBindBuffer (GL_ARRAY_BUFFER, 0); } // ============================================================================= @@ -282,105 +323,7 @@ } // ============================================================================= -// -void GLRenderer::setObjectColor (LDObject* obj, const ListType list) -{ - QColor qcol; - - if (!obj->isColored()) - return; - - if (list == GL::PickList) - { - // Make the color by the object's ID if we're picking, so we can make the - // ID again from the color we get from the picking results. Be sure to use - // the top level parent's index since we want a subfile's children point - // to the subfile itself. - long i = obj->topLevelParent()->getID(); - - // Calculate a color based from this index. This method caters for - // 16777216 objects. I don't think that'll be exceeded anytime soon. :) - // ATM biggest is 53588.dat with 12600 lines. - double r = (i / 0x10000) % 0x100, - g = (i / 0x100) % 0x100, - b = i % 0x100; - - qglColor (QColor (r, g, b)); - return; - } - - if ((list == BFCFrontList || list == BFCBackList) && - obj->getType() != LDObject::ELine && - obj->getType() != LDObject::ECondLine) - { - if (list == GL::BFCFrontList) - qcol = QColor (40, 192, 0); - else - qcol = QColor (224, 0, 0); - } - else - { - if (obj->getColor() == maincolor) - qcol = getMainColor(); - else - { - LDColor* col = getColor (obj->getColor()); - - if (col) - qcol = col->faceColor; - } - - if (obj->getColor() == edgecolor) - { - LDColor* col; - - if (!gl_blackedges && obj->getParent() && (col = getColor (obj->getParent()->getColor()))) - qcol = col->edgeColor; - else - qcol = (m_darkbg == false) ? Qt::black : Qt::white; - } - - if (qcol.isValid() == false) - { - // The color was unknown. Use main color to make the object at least - // not appear pitch-black. - if (obj->getColor() != edgecolor) - qcol = getMainColor(); - - // Warn about the unknown colors, but only once. - for (int i : g_warnedColors) - if (obj->getColor() == i) - return; - - log ("%1: Unknown color %2!\n", __func__, obj->getColor()); - g_warnedColors << obj->getColor(); - return; - } - } - - int r = qcol.red(), - g = qcol.green(), - b = qcol.blue(), - a = qcol.alpha(); - - if (obj->topLevelParent()->isSelected()) - { - // Brighten it up for the select list. - QColor selcolor (gl_selectcolor); - r = (r + selcolor.red()) / 2; - g = (g + selcolor.green()) / 2; - b = (b + selcolor.blue()) / 2; - } - - glColor4f ( - ((double) r) / 255.0f, - ((double) g) / 255.0f, - ((double) b) / 255.0f, - ((double) a) / 255.0f); -} - -// ============================================================================= -// +// ----------------------------------------------------------------------------- void GLRenderer::refresh() { update(); @@ -388,10 +331,10 @@ } // ============================================================================= -// +// ----------------------------------------------------------------------------- void GLRenderer::hardRefresh() { - compileAllObjects(); + m_compiler->compileDocument(); refresh(); glLineWidth (gl_linethickness); @@ -462,47 +405,54 @@ glRotatef (rot (Z), 0.0f, 0.0f, 1.0f); } - const GL::ListType list = (!isDrawOnly() && isPicking()) ? PickList : NormalList; - - if (gl_colorbfc && !isPicking() && !isDrawOnly()) - { - glEnable (GL_CULL_FACE); - - for (LDObject* obj : getFile()->getObjects()) - { - if (obj->isHidden()) - continue; - - glCullFace (GL_BACK); - glCallList (obj->glLists[BFCFrontList]); + glEnableClientState (GL_VERTEX_ARRAY); - glCullFace (GL_FRONT); - glCallList (obj->glLists[BFCBackList]); - } - - glDisable (GL_CULL_FACE); - } - else + if (gl_axes) { - for (LDObject* obj : getFile()->getObjects()) - { - if (obj->isHidden()) - continue; - - glCallList (obj->glLists[list]); - } + glBindBuffer (GL_ARRAY_BUFFER, g_GLAxes_VBO); + checkGLError(); + glVertexPointer (3, GL_FLOAT, 0, NULL); + checkGLError(); + glDrawArrays (GL_LINES, 0, 6); + checkGLError(); } - if (gl_axes && !isPicking() && !isDrawOnly()) - glCallList (m_axeslist); + drawVBOs (VBO_Triangles, GL_TRIANGLES); + drawVBOs (VBO_Quads, GL_QUADS); + drawVBOs (VBO_Lines, GL_LINES); + drawVBOs (VBO_CondLines, GL_LINES); glPopMatrix(); + glBindBuffer (GL_ARRAY_BUFFER, 0); + glDisableClientState (GL_VERTEX_ARRAY); + checkGLError(); + glDisable (GL_CULL_FACE); glMatrixMode (GL_MODELVIEW); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); } // ============================================================================= // +void GLRenderer::drawVBOs (E_VBOArray arrayType, GLenum type) +{ + m_compiler->prepareVBOArray (arrayType); + GLuint idx = m_compiler->getVBOIndex (arrayType); + GLsizei count = m_compiler->getVBOCount (arrayType); + + if (count > 0) + { + glBindBuffer (GL_ARRAY_BUFFER, idx); + checkGLError(); + glVertexPointer (3, GL_FLOAT, 0, null); + checkGLError(); + // glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (GLCompiler::VAO), &array->data()[0].color); + // glVertexAttribPointer (idx, 3, GL_FLOAT, GL_FALSE, 0, null); + glDrawArrays (type, 0, count); + checkGLError(); + } +} + +// ============================================================================= // This converts a 2D point on the screen to a 3D point in the model. If 'snap' // is true, the 3D point will snap to the current grid. // @@ -897,127 +847,7 @@ // void GLRenderer::compileAllObjects() { - if (!getFile()) - return; - - // Compiling all is a big job, use a busy cursor - setCursor (Qt::BusyCursor); - - m_knownVerts.clear(); - - for (LDObject* obj : getFile()->getObjects()) - compileObject (obj); - - // Compile axes - glDeleteLists (m_axeslist, 1); - m_axeslist = glGenLists (1); - glNewList (m_axeslist, GL_COMPILE); - glBegin (GL_LINES); - - for (const LDGLAxis& ax : g_GLAxes) - { - qglColor (ax.col); - compileVertex (ax.vert); - compileVertex (-ax.vert); - } - - glEnd(); - glEndList(); - - setCursor (Qt::ArrowCursor); -} - -// ============================================================================= -// -void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) -{ - glBegin (gltype); - - const int numverts = (obj->getType() != LDObject::ECondLine) ? obj->vertices() : 2; - - if (g_glInvert == false) - for (int i = 0; i < numverts; ++i) - compileVertex (obj->getVertex (i)); - else - for (int i = numverts - 1; i >= 0; --i) - compileVertex (obj->getVertex (i)); - - glEnd(); -} - -// ============================================================================= -// -void GLRenderer::compileList (LDObject* obj, const GLRenderer::ListType list) -{ - setObjectColor (obj, list); - - switch (obj->getType()) - { - case LDObject::ELine: - { - compileSubObject (obj, GL_LINES); - } break; - - case LDObject::ECondLine: - { - // Draw conditional lines with a dash pattern - however, use a full - // line when drawing a pick list to make selecting them easier. - if (list != GL::PickList) - { - glLineStipple (1, 0x6666); - glEnable (GL_LINE_STIPPLE); - } - - compileSubObject (obj, GL_LINES); - - glDisable (GL_LINE_STIPPLE); - } break; - - case LDObject::ETriangle: - { - compileSubObject (obj, GL_TRIANGLES); - } break; - - case LDObject::EQuad: - { - compileSubObject (obj, GL_QUADS); - } break; - - case LDObject::ESubfile: - { - LDSubfile* ref = static_cast<LDSubfile*> (obj); - LDObjectList objs; - - objs = ref->inlineContents (LDSubfile::DeepCacheInline | LDSubfile::RendererInline); - bool oldinvert = g_glInvert; - - if (ref->getTransform().getDeterminant() < 0) - g_glInvert = !g_glInvert; - - LDObject* prev = ref->prev(); - - if (prev && prev->getType() == LDObject::EBFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext) - g_glInvert = !g_glInvert; - - for (LDObject* obj : objs) - { - compileList (obj, list); - obj->deleteSelf(); - } - - g_glInvert = oldinvert; - } break; - - default: - break; - } -} - -// ============================================================================= -// -void GLRenderer::compileVertex (const Vertex& vrt) -{ - glVertex3d (vrt[X], -vrt[Y], -vrt[Z]); + m_compiler->compileDocument(); } // ============================================================================= @@ -1376,8 +1206,8 @@ { qint32 idx = (*(pixelptr + 0) * 0x10000) + - (*(pixelptr + 1) * 0x00100) + - (*(pixelptr + 2) * 0x00001); + (*(pixelptr + 1) * 0x100) + + *(pixelptr + 2); pixelptr += 4; if (idx == 0xFFFFFF) @@ -1473,6 +1303,7 @@ void GLRenderer::setFile (LDDocument* const& a) { m_File = a; + m_compiler->setDocument (a); if (a != null) { @@ -1746,21 +1577,7 @@ // void GLRenderer::compileObject (LDObject* obj) { - deleteLists (obj); - - for (const GL::ListType listType : g_glListTypes) - { - if (isDrawOnly() && listType != GL::NormalList) - continue; - - GLuint list = glGenLists (1); - glNewList (list, GL_COMPILE); - - obj->glLists[listType] = list; - compileList (obj, listType); - - glEndList(); - } + m_compiler->stageForCompilation (obj); // Mark in known vertices of this object QList<Vertex> verts = getVertices (obj); @@ -1795,7 +1612,7 @@ // We come here if the cursor has stayed in one place for longer than a // a second. Check if we're holding it over a camera icon - if so, draw // a tooltip. -for (CameraIcon & icon : m_cameraIcons) + for (CameraIcon & icon : m_cameraIcons) { if (icon.destRect.contains (m_pos)) {
--- a/src/GLRenderer.h Wed Feb 05 06:06:23 2014 +0200 +++ b/src/GLRenderer.h Wed Feb 05 06:07:05 2014 +0200 @@ -23,7 +23,9 @@ #include "Main.h" #include "LDObject.h" #include "Document.h" +#include "GLShared.h" +class GLCompiler; class MessageManager; class QDialogButtonBox; class RadioGroup; @@ -152,7 +154,6 @@ Axis getCameraAxis (bool y, EFixedCamera camid = (EFixedCamera) - 1); const char* getCameraName() const; double getDepthValue() const; - QColor getMainColor(); LDGLOverlay& getOverlay (int newcam); uchar* getScreencap (int& w, int& h); void hardRefresh(); @@ -171,6 +172,7 @@ void zoomAllToFit(); static void deleteLists (LDObject* obj); + static QColor getMainColor(); protected: void contextMenuEvent (QContextMenuEvent* ev); @@ -216,6 +218,7 @@ Vertex m_rectverts[4]; QColor m_bgcolor; QList<Vertex> m_knownVerts; + GLCompiler* m_compiler; void addDrawnVertex (Vertex m_hoverpos); LDOverlay* findOverlayObject (EFixedCamera cam); @@ -245,6 +248,12 @@ // Convert a 2D point to a 3D point Vertex coordconv2_3 (const QPoint& pos2d, bool snap) const; + // Draw a VBO array + void drawVBOs (E_VBOArray arrayType, GLenum type); + + // Determine which color to draw text with + QColor getTextPen() const; + // Convert a 3D point to a 2D point QPoint coordconv3_2 (const Vertex& pos3d) const; @@ -290,6 +299,7 @@ private slots: void slot_toolTipTimer(); + void initializeAxes(); }; // Alias for short namespaces
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/GLShared.h Wed Feb 05 06:07:05 2014 +0200 @@ -0,0 +1,35 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013, 2014 Santeri 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/>. + */ + +#ifndef LDFORGE_GLSHARED_H +#define LDFORGE_GLSHARED_H + +enum E_VBOArray +{ + VBO_Quads, + VBO_Triangles, + VBO_Lines, + VBO_CondLines, + VBO_NormalColors, + VBO_BFCFrontColors, + VBO_BFCBackColors, + VBO_PickColors, + VBO_NumArrays +}; + +#endif // LDFORGE_GLSHARED_H \ No newline at end of file
--- a/src/LDObject.cc Wed Feb 05 06:06:23 2014 +0200 +++ b/src/LDObject.cc Wed Feb 05 06:07:05 2014 +0200 @@ -24,6 +24,7 @@ #include "EditHistory.h" #include "GLRenderer.h" #include "Colors.h" +#include "GLCompiler.h" cfg (String, ld_defaultname, ""); cfg (String, ld_defaultuser, "");
--- a/src/Main.cc Wed Feb 05 06:06:23 2014 +0200 +++ b/src/Main.cc Wed Feb 05 06:07:05 2014 +0200 @@ -22,6 +22,7 @@ #include <QFile> #include <QTextStream> #include <QDir> +#include <QDate> #include "MainWindow.h" #include "Document.h" #include "Misc.h" @@ -70,6 +71,30 @@ newFile(); win->show(); + /* + LDDocument* box = getDocument ("box.dat"); + LDSubfile* ref = new LDSubfile; + ref->setFileInfo (box); + ref->setPosition (g_origin); + ref->setTransform (g_identity); + ref->setColor (maincolor); + assert (box != null); + + for (int i = 0; i < 500; ++i) + { + QTime t0 = QTime::currentTime(); + LDObjectList objs = ref->inlineContents (LDSubfile::DeepCacheInline | LDSubfile::RendererInline); + LDObject::Type type = static_cast<LDObject*> (ref)->getType(); + dlog ("%1: %2ms (%3 objs)\n", i, t0.msecsTo (QTime::currentTime()), objs.size()); + + for (LDObject* obj : objs) + obj->deleteSelf(); + } + + ref->deleteSelf(); + delete box; + */ + // If this is the first start, get the user to configuration. Especially point // them to the profile tab, it's the most important form to fill in. if (firststart)
--- a/src/Types.h Wed Feb 05 06:06:23 2014 +0200 +++ b/src/Types.h Wed Feb 05 06:07:05 2014 +0200 @@ -23,6 +23,7 @@ #include <QObject> #include <QStringList> #include <QMetaType> +#include <QVector> #include "PropertyMacro.h" class LDObject; @@ -231,11 +232,11 @@ m_val.sprintf ("%p", a); } - template<class T> StringFormatArg (const QList<T>& a) + template<class T, class R> void initFromList (const T& a) { m_val = "{ "; - for (const T& it : a) + for (const R& it : a) { if (&it != &a.first()) m_val += ", "; @@ -250,6 +251,16 @@ m_val += "}"; } + template<class T> StringFormatArg (const QList<T>& a) + { + initFromList<QList<T>, T> (a); + } + + template<class T> StringFormatArg (const QVector<T>& a) + { + initFromList<QVector<T>, T> (a); + } + inline QString value() const { return m_val;