Thu, 06 Feb 2014 22:11:28 +0200
- work on improved rendering performance
src/Document.cc | file | annotate | diff | comparison | revisions | |
src/Document.h | file | annotate | diff | comparison | revisions | |
src/ExternalPrograms.cc | file | annotate | diff | comparison | revisions | |
src/GLCompiler.cc | file | annotate | diff | comparison | revisions | |
src/GLCompiler.h | file | annotate | diff | comparison | revisions | |
src/GLRenderer.cc | file | annotate | diff | comparison | revisions | |
src/GLRenderer.h | file | annotate | diff | comparison | revisions | |
src/GLShared.h | file | annotate | diff | comparison | revisions | |
src/LDObject.cc | file | annotate | diff | comparison | revisions | |
src/LDObject.h | file | annotate | diff | comparison | revisions | |
src/Types.cc | file | annotate | diff | comparison | revisions | |
src/actions/EditActions.cc | file | annotate | diff | comparison | revisions |
--- a/src/Document.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/Document.cc Thu Feb 06 22:11:28 2014 +0200 @@ -19,6 +19,7 @@ #include <QMessageBox> #include <QFileDialog> #include <QDir> +#include <QTime> #include <QApplication> #include "Main.h" #include "Configuration.h" @@ -145,10 +146,6 @@ for (LDObject* obj : getObjects()) obj->deleteSelf(); - // Clear the cache as well - for (LDObject* obj : getCache()) - obj->deleteSelf(); - delete m_History; delete m_gldata; @@ -1192,82 +1189,77 @@ } // ============================================================================= +// +void LDDocument::initializeGLData() +{ + log (getDisplayName() + ": Initializing GL data"); + LDObjectList objs = inlineContents (true, true); + + for (LDObject* obj : objs) + { + assert (obj->getType() != LDObject::ESubfile); + LDPolygon* data = obj->getPolygon(); + + if (data != null) + { + m_PolygonData << *data; + delete data; + } + + obj->deleteSelf(); + } + + m_needsGLReInit = false; +} + +// ============================================================================= +// +QList<LDPolygon> LDDocument::inlinePolygons() +{ + if (m_needsGLReInit == true) + initializeGLData(); + + return m_PolygonData; +} + +// ============================================================================= // ----------------------------------------------------------------------------- -LDObjectList LDDocument::inlineContents (LDSubfile::InlineFlags flags) +LDObjectList LDDocument::inlineContents (bool deep, bool renderinline) { // Possibly substitute with logoed studs: // stud.dat -> stud-logo.dat // stud2.dat -> stud-logo2.dat - if (gl_logostuds && (flags & LDSubfile::RendererInline)) + if (gl_logostuds && renderinline) { // Ensure logoed studs are loaded first loadLogoedStuds(); - if (getName() == "stud.dat" && g_logoedStud) - return g_logoedStud->inlineContents (flags); - elif (getName() == "stud2.dat" && g_logoedStud2) - return g_logoedStud2->inlineContents (flags); + if (getName() == "stud.dat" && g_logoedStud != null) + return g_logoedStud->inlineContents (deep, renderinline); + elif (getName() == "stud2.dat" && g_logoedStud2 != null) + return g_logoedStud2->inlineContents (deep, renderinline); } LDObjectList objs, objcache; - bool deep = flags & LDSubfile::DeepInline, - doCache = flags & LDSubfile::CacheInline; - - if (m_needsCache) - { - clearCache(); - doCache = true; - } - - // If we have this cached, just create a copy of that - if (deep && getCache().isEmpty() == false) + for (LDObject* obj : getObjects()) { - for (LDObject* obj : getCache()) - objs << obj->createCopy(); - } - else - { - if (!deep) - doCache = false; - - for (LDObject* obj : getObjects()) - { - // Skip those without scemantic meaning - if (!obj->isScemantic()) - continue; + // Skip those without scemantic meaning + if (!obj->isScemantic()) + continue; - // Got another sub-file reference, inline it if we're deep-inlining. If not, - // just add it into the objects normally. Also, we only cache immediate - // subfiles and this is not one. Yay, recursion! - if (deep && obj->getType() == LDObject::ESubfile) - { - LDSubfile* ref = static_cast<LDSubfile*> (obj); - - // We only want to cache immediate subfiles, so shed the caching - // flag when recursing deeper in hierarchy. - LDObjectList otherobjs = ref->inlineContents (flags & ~ (LDSubfile::CacheInline)); + // Got another sub-file reference, inline it if we're deep-inlining. If not, + // just add it into the objects normally. Yay, recursion! + if (deep == true && obj->getType() == LDObject::ESubfile) + { + LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDObjectList otherobjs = ref->inlineContents (deep, renderinline); - for (LDObject* otherobj : otherobjs) - { - // Cache this object, if desired - if (doCache) - objcache << otherobj->createCopy(); - - objs << otherobj; - } - } - else - { - if (doCache) - objcache << obj->createCopy(); - - objs << obj->createCopy(); - } + for (LDObject* otherobj : otherobjs) + objs << otherobj; } - - if (doCache) - setCache (objcache); + else + objs << obj->createCopy(); } return objs;
--- a/src/Document.h Wed Feb 05 06:07:05 2014 +0200 +++ b/src/Document.h Thu Feb 06 22:11:28 2014 +0200 @@ -23,6 +23,7 @@ #include "Main.h" #include "LDObject.h" #include "EditHistory.h" +#include "GLShared.h" class History; class OpenProgressDialog; @@ -65,7 +66,7 @@ PROPERTY (public, QString, FullPath, STR_OPS, STOCK_WRITE) PROPERTY (public, QString, DefaultName, STR_OPS, STOCK_WRITE) PROPERTY (public, bool, Implicit, BOOL_OPS, STOCK_WRITE) - PROPERTY (public, LDObjectList, Cache, LIST_OPS, STOCK_WRITE) + PROPERTY (public, QList<LDPolygon>, PolygonData, NO_OPS, STOCK_WRITE) PROPERTY (public, long, SavePosition, NUM_OPS, STOCK_WRITE) PROPERTY (public, QListWidgetItem*, ListItem, NO_OPS, STOCK_WRITE) @@ -80,7 +81,8 @@ QString getDisplayName(); const LDObjectList& getSelection() const; bool hasUnsavedChanges() const; // Does this Document.have unsaved changes? - LDObjectList inlineContents (LDSubfile::InlineFlags flags); + void initializeGLData(); + LDObjectList inlineContents (bool deep, bool renderinline); void insertObj (int pos, LDObject* obj); int getObjectCount() const; LDObject* getObject (int pos) const; @@ -90,6 +92,7 @@ void setObject (int idx, LDObject* obj); void addReference (LDDocumentPointer* ptr); void removeReference (LDDocumentPointer* ptr); + QList<LDPolygon> inlinePolygons(); inline LDDocument& operator<< (LDObject* obj) { @@ -147,9 +150,9 @@ LDObjectList m_sel; LDGLData* m_gldata; - // If set to true, next inline of this document discards the cache and - // re-builds it. - bool m_needsCache; + // If set to true, next polygon inline of this document discards the + // stored polygon data and re-builds it. + bool m_needsGLReInit; static LDDocument* m_curdoc; };
--- a/src/ExternalPrograms.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/ExternalPrograms.cc Thu Feb 06 22:11:28 2014 +0200 @@ -173,7 +173,7 @@ if (obj->getType() == LDObject::ESubfile) { LDSubfile* ref = static_cast<LDSubfile*> (obj); - LDObjectList objs = ref->inlineContents (LDSubfile::DeepInline); + LDObjectList objs = ref->inlineContents (true, false); writeObjects (objs, f);
--- a/src/GLCompiler.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/GLCompiler.cc Thu Feb 06 22:11:28 2014 +0200 @@ -9,12 +9,13 @@ #include "GLRenderer.h" #include "Dialogs.h" -static const struct +struct GLErrorInfo { GLenum value; QString text; -} -g_GLErrors[] = +}; + +static const GLErrorInfo g_GLErrors[] = { { GL_NO_ERROR, "No error" }, { GL_INVALID_ENUM, "Unacceptable enumerator passed" }, @@ -26,35 +27,47 @@ { GL_STACK_OVERFLOW, "The operation would have caused an overflow" }, }; +#include <QTime> + +#define CLOCK_INIT QTime t0; + +#define CLOCK_START \ +{ \ + t0 = QTime::currentTime(); \ +} + +#define CLOCK_TIME(A) \ +{ \ + fprint (stderr, A ": %1ms\n", t0.msecsTo (QTime::currentTime())); \ +} + #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); +static QList<short> gWarnedColors; +static const QColor gBFCFrontColor (40, 192, 40); +static const QColor gBFCBackColor (224, 40, 40); // ============================================================================= // void checkGLError_private (const char* file, int line) { + QString errmsg; GLenum errnum = glGetError(); if (errnum == GL_NO_ERROR) return; - QString errmsg; - - for (const auto& it : g_GLErrors) + for (const GLErrorInfo& err : g_GLErrors) { - if (it.value == errnum) + if (err.value == errnum) { - errmsg = it.text; + errmsg = err.text; break; } } - log ("GL ERROR: %1:%2: %3", file, line, errmsg); + log ("OpenGL ERROR: at %1:%2: %3", basename (QString (file)), line, errmsg); } // ============================================================================= @@ -69,13 +82,15 @@ // void GLCompiler::initialize() { - glGenBuffers (VBO_NumArrays, &m_mainVBOs[0]); + glGenBuffers (gNumVBOs, &mVBOs[0]); checkGLError(); } +// ============================================================================= +// GLCompiler::~GLCompiler() { - glDeleteBuffers (VBO_NumArrays, &m_mainVBOs[0]); + glDeleteBuffers (gNumVBOs, &mVBOs[0]); checkGLError(); } @@ -92,70 +107,64 @@ // ============================================================================= // -QColor GLCompiler::getObjectColor (LDObject* obj, GLCompiler::E_ColorType colortype) const +QColor GLCompiler::getIndexColor (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::getPolygonColor (LDPolygon& poly, LDObject* topobj) 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) + if (poly.color == maincolor) qcol = GLRenderer::getMainColor(); else { - LDColor* col = getColor (obj->getColor()); + LDColor* col = getColor (poly.color); if (col) qcol = col->faceColor; } - if (obj->getColor() == edgecolor) + if (poly.color == 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()))) + /* + if (!gl_blackedges && poly.obj->getParent() && (col = getColor (poly.obj->getParent()->getColor()))) qcol = col->edgeColor; + */ } if (qcol.isValid() == false) { - // The color was unknown. Use main color to make the object at least + // The color was unknown. Use main color to make the poly.object at least // not appear pitch-black. - if (obj->getColor() != edgecolor) + if (poly.color != 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) + for (short i : gWarnedColors) + if (poly.color == i) return qcol; - log ("%1: Unknown color %2!\n", __func__, obj->getColor()); - g_warnedColors << obj->getColor(); + log ("%1: Unknown color %2!\n", __func__, poly.color); + gWarnedColors << poly.color; return qcol; } - if (obj->topLevelParent()->isSelected()) + if (topobj->isSelected()) { // Brighten it up if selected. const int add = 51; @@ -172,24 +181,27 @@ // 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; + // Set all of mChanged to true + // memset (mChanged, 0xFF, sizeof mChanged); + for (int i = 0; i < ((int) (sizeof mChanged / sizeof *mChanged)); ++i) + mChanged[i] = true; } // ============================================================================= // void GLCompiler::stageForCompilation (LDObject* obj) { - m_staged << obj; - removeDuplicates (m_staged); + mStaged << obj; + removeDuplicates (mStaged); } // ============================================================================= // void GLCompiler::compileDocument() { + if (getDocument() == null) + return; + for (LDObject* obj : getDocument()->getObjects()) compileObject (obj); } @@ -198,131 +210,184 @@ // void GLCompiler::compileStaged() { - for (LDObject* obj : m_staged) + for (LDObject* obj : mStaged) compileObject (obj); - m_staged.clear(); + mStaged.clear(); } // ============================================================================= // -void GLCompiler::prepareVBOArray (E_VBOArray type) +void GLCompiler::prepareVBO (int vbonum) { // Compile anything that still awaits it compileStaged(); - if (!m_changed[type]) + if (mChanged[vbonum] == false) 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]); + glBindBuffer (GL_ARRAY_BUFFER, mVBOs[vbonum]); checkGLError(); - glBufferData (GL_ARRAY_BUFFER, m_mainVBOData[type].size() * sizeof(float), - m_mainVBOData[type].constData(), GL_DYNAMIC_DRAW); + glBufferData (GL_ARRAY_BUFFER, mVBOData[vbonum].size() * sizeof(float), + mVBOData[vbonum].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()); + mChanged[vbonum] = false; } // ============================================================================= // -void GLCompiler::forgetObject (LDObject* obj) +void GLCompiler::uncompileObject (LDObject* obj) { - auto it = m_objArrays.find (obj); + auto it = mObjectInfo.find (obj); + + if (it == mObjectInfo.end()) + return; + + ObjectVBOInfo* info = &(*it); - if (it != m_objArrays.end()) + for (int i = 0; i < gNumVBOs; ++i) { - delete *it; - m_objArrays.erase (it); + if (info->size[i] == 0) + continue; + + mVBOData[i].remove (info->offset[i], info->size[i]); + mChanged[i] = true; } + + mObjectInfo.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(); - } + ObjectVBOInfo info; + uncompileObject (obj); - compileSubObject (obj, obj); - QList<int> data; + for (int i = 0; i < gNumVBOs; ++i) + info.offset[i] = mVBOData[i].size(); - for (int i = 0; i < VBO_NumArrays; ++i) - data << m_objArrays[obj][i].size(); - - dlog ("Compiled #%1: %2 coordinates", obj->getID(), data); + memset (info.size, 0, sizeof info.size); + compileSubObject (obj, obj, &info); + mObjectInfo[obj] = info; needMerge(); } // ============================================================================= // -void GLCompiler::compileSubObject (LDObject* obj, LDObject* topobj) +void GLCompiler::compilePolygon (LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo) { + EVBOSurface surface; + int numverts; + + switch (poly.num) + { + case 3: surface = vboTriangles; numverts = 3; break; + case 4: surface = vboQuads; numverts = 4; break; + case 2: surface = vboLines; numverts = 2; break; + case 5: surface = vboCondLines; numverts = 2; break; + + default: + log ("OMGWTFBBQ weird polygon with number %1 (topobj: #%2, %3), origin: %4", + (int) poly.num, topobj->getID(), topobj->getTypeName(), poly.origin); + assert (false); + } + + for (int complement = 0; complement < vboNumComplements; ++complement) + { + const int vbonum = getVBONumber (surface, (EVBOComplement) complement); + QVector<GLfloat>& vbodata = mVBOData[vbonum]; + const QColor normalColor = getPolygonColor (poly, topobj); + const QColor pickColor = getIndexColor (topobj->getID()); + + for (int vert = 0; vert < numverts; ++vert) + { + objinfo->size[vbonum] += (complement == vboSurfaces) ? 3 : 4; + + switch ((EVBOComplement) complement) + { + case vboSurfaces: + { + // Write coordinates. Apparently Z must be flipped too? + vbodata << poly.vertices[vert].x() + << -poly.vertices[vert].y() + << -poly.vertices[vert].z(); + break; + } + + case vboNormalColors: + { + writeColor (vbodata, normalColor); + break; + } + + case vboPickColors: + { + writeColor (vbodata, pickColor); + break; + } + + case vboBFCFrontColors: + { + writeColor (vbodata, gBFCFrontColor); + break; + } + + case vboBFCBackColors: + { + writeColor (vbodata, gBFCBackColor); + break; + } + + case vboNumComplements: + break; + } + } + } +} + +// ============================================================================= +// +void GLCompiler::compileSubObject (LDObject* obj, LDObject* topobj, ObjectVBOInfo* objinfo) +{ + CLOCK_INIT + 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. + // Note: We cannot split quads into triangles here, it would mess up the + // wireframe view. Quads must go into separate vbos. 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; + LDPolygon* poly = obj->getPolygon(); + poly->id = topobj->getID(); + compilePolygon (*poly, topobj, objinfo); + delete poly; + break; + } case LDObject::ESubfile: { + CLOCK_INIT + CLOCK_START LDSubfile* ref = static_cast<LDSubfile*> (obj); - LDObjectList subobjs = ref->inlineContents (LDSubfile::DeepCacheInline | LDSubfile::RendererInline); + auto data = ref->inlinePolygons(); + CLOCK_TIME ("Inline") + CLOCK_START - for (LDObject* subobj : subobjs) + for (LDPolygon& poly : data) { - compileSubObject (subobj, topobj); - subobj->deleteSelf(); + poly.id = topobj->getID(); + compilePolygon (poly, topobj, objinfo); } - } break; + CLOCK_TIME ("Compile") + + break; + } default: break; @@ -333,8 +398,8 @@ // void GLCompiler::writeColor (QVector<GLfloat>& array, const QColor& color) { - array << color.red() - << color.green() - << color.blue() - << color.alpha(); + array << ((float) color.red()) / 255.0f + << ((float) color.green()) / 255.0f + << ((float) color.blue()) / 255.0f + << ((float) color.alpha()) / 255.0f; } \ No newline at end of file
--- a/src/GLCompiler.h Wed Feb 05 06:07:05 2014 +0200 +++ b/src/GLCompiler.h Thu Feb 06 22:11:28 2014 +0200 @@ -25,78 +25,58 @@ #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 + struct ObjectVBOInfo { - E_NormalColor, - E_PickColor, + int offset[gNumVBOs]; + int size[gNumVBOs]; }; 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); + void compileDocument(); + void uncompileObject (LDObject* obj); + void initialize(); + QColor getPolygonColor (LDPolygon& poly, LDObject* topobj) const; + QColor getIndexColor (int id) const; + void needMerge(); + void prepareVBO (int vbonum); + void stageForCompilation (LDObject* obj); - static uint32 getColorRGB (const QColor& color); + static uint32 getColorRGB (const QColor& color); - inline GLuint getVBOIndex (E_VBOArray array) const + static inline int getVBONumber (EVBOSurface surface, EVBOComplement complement) { - return m_mainVBOs[array]; + return (surface * vboNumComplements) + complement; } - inline int getVBOCount (E_VBOArray array) const + inline GLuint getVBO (int vbonum) const { - return m_mainVBOData[array].size() / 3; + return mVBOs[vbonum]; } - void initialize(); + + inline int getVBOCount (int vbonum) const + { + return mVBOData[vbonum].size() / 3; + } private: void compileStaged(); void compileObject (LDObject* obj); - void compileSubObject (LDObject* obj, LDObject* topobj); - void writeColor (QVector< float >& array, const QColor& color); + void compileSubObject (LDObject* obj, LDObject* topobj, GLCompiler::ObjectVBOInfo* objinfo); + void writeColor (QVector<float>& array, const QColor& color); + void compilePolygon (LDPolygon& poly, LDObject* topobj, GLCompiler::ObjectVBOInfo* objinfo); - 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 + QMap<LDObject*, ObjectVBOInfo> mObjectInfo; + QVector<GLfloat> mVBOData[gNumVBOs]; + GLuint mVBOs[gNumVBOs]; + bool mChanged[gNumVBOs]; + LDObjectList mStaged; // Objects that need to be compiled }; #define checkGLError() { checkGLError_private (__FILE__, __LINE__); }
--- a/src/GLRenderer.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/GLRenderer.cc Thu Feb 06 22:11:28 2014 +0200 @@ -125,12 +125,12 @@ m_EditMode = ESelectMode; m_rectdraw = false; m_panning = false; + m_compiler = new GLCompiler; setFile (null); setDrawOnly (false); setMessageLog (null); m_width = m_height = -1; m_hoverpos = g_origin; - m_compiler = new GLCompiler; m_toolTipTimer = new QTimer (this); m_toolTipTimer->setSingleShot (true); @@ -417,10 +417,10 @@ checkGLError(); } - drawVBOs (VBO_Triangles, GL_TRIANGLES); - drawVBOs (VBO_Quads, GL_QUADS); - drawVBOs (VBO_Lines, GL_LINES); - drawVBOs (VBO_CondLines, GL_LINES); + drawVBOs (vboTriangles, GL_TRIANGLES); + drawVBOs (vboQuads, GL_QUADS); + drawVBOs (vboLines, GL_LINES); + drawVBOs (vboCondLines, GL_LINES); glPopMatrix(); glBindBuffer (GL_ARRAY_BUFFER, 0); @@ -433,20 +433,25 @@ // ============================================================================= // -void GLRenderer::drawVBOs (E_VBOArray arrayType, GLenum type) +void GLRenderer::drawVBOs (EVBOSurface surface, GLenum type) { - m_compiler->prepareVBOArray (arrayType); - GLuint idx = m_compiler->getVBOIndex (arrayType); - GLsizei count = m_compiler->getVBOCount (arrayType); + int surfacenum = m_compiler->getVBONumber (surface, vboSurfaces); + int colornum = m_compiler->getVBONumber (surface, vboNormalColors); + + m_compiler->prepareVBO (surfacenum); + m_compiler->prepareVBO (colornum); + GLuint surfacevbo = m_compiler->getVBO (surfacenum); + GLuint colorvbo = m_compiler->getVBO (colornum); + GLsizei count = m_compiler->getVBOCount (surfacevbo); if (count > 0) { - glBindBuffer (GL_ARRAY_BUFFER, idx); - checkGLError(); + glBindBuffer (GL_ARRAY_BUFFER, surfacevbo); 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); + glBindBuffer (GL_ARRAY_BUFFER, colorvbo); + glColorPointer (4, GL_FLOAT, 0, null); + checkGLError(); glDrawArrays (type, 0, count); checkGLError(); } @@ -1558,10 +1563,11 @@ { for (int i = 0; i < obj->vertices(); ++i) verts << obj->getVertex (i); - } elif (obj->getType() == LDObject::ESubfile) + } + elif (obj->getType() == LDObject::ESubfile) { LDSubfile* ref = static_cast<LDSubfile*> (obj); - LDObjectList objs = ref->inlineContents (LDSubfile::DeepCacheInline); + LDObjectList objs = ref->inlineContents (true, false); for (LDObject* obj : objs) { @@ -1580,15 +1586,24 @@ m_compiler->stageForCompilation (obj); // Mark in known vertices of this object + /* QList<Vertex> verts = getVertices (obj); m_knownVerts << verts; removeDuplicates (m_knownVerts); + */ obj->setGLInit (true); } // ============================================================================= // +void GLRenderer::forgetObject (LDObject* obj) +{ + m_compiler->uncompileObject (obj); +} + +// ============================================================================= +// uchar* GLRenderer::getScreencap (int& w, int& h) { w = m_width; @@ -1626,20 +1641,6 @@ // ============================================================================= // -void GLRenderer::deleteLists (LDObject* obj) -{ - // Delete the lists but only if they have been initialized - if (!obj->isGLInit()) - return; - - for (const GL::ListType listType : g_glListTypes) - glDeleteLists (obj->glLists[listType], 1); - - obj->setGLInit (false); -} - -// ============================================================================= -// Axis GLRenderer::getCameraAxis (bool y, GLRenderer::EFixedCamera camid) { if (camid == (GL::EFixedCamera) - 1)
--- a/src/GLRenderer.h Wed Feb 05 06:07:05 2014 +0200 +++ b/src/GLRenderer.h Thu Feb 06 22:11:28 2014 +0200 @@ -151,6 +151,7 @@ void compileAllObjects(); void drawGLScene(); void endDraw (bool accept); + void forgetObject (LDObject* obj); Axis getCameraAxis (bool y, EFixedCamera camid = (EFixedCamera) - 1); const char* getCameraName() const; double getDepthValue() const; @@ -249,7 +250,7 @@ Vertex coordconv2_3 (const QPoint& pos2d, bool snap) const; // Draw a VBO array - void drawVBOs (E_VBOArray arrayType, GLenum type); + void drawVBOs (EVBOSurface surface, GLenum type); // Determine which color to draw text with QColor getTextPen() const;
--- a/src/GLShared.h Wed Feb 05 06:07:05 2014 +0200 +++ b/src/GLShared.h Thu Feb 06 22:11:28 2014 +0200 @@ -18,18 +18,53 @@ #ifndef LDFORGE_GLSHARED_H #define LDFORGE_GLSHARED_H +#include <QString> -enum E_VBOArray +class LDObject; + +struct LDPolygon { - VBO_Quads, - VBO_Triangles, - VBO_Lines, - VBO_CondLines, - VBO_NormalColors, - VBO_BFCFrontColors, - VBO_BFCBackColors, - VBO_PickColors, - VBO_NumArrays + char num; + Vertex vertices[4]; + int id; + int color; + QString origin; + + inline int numVertices() const + { + return (num == 5) ? 4 : num; + } }; +enum EVBOSurface +{ + vboLines, + vboTriangles, + vboQuads, + vboCondLines, + vboNumSurfaces +}; + +enum EVBOComplement +{ + vboSurfaces, + vboNormalColors, + vboPickColors, + vboBFCFrontColors, + vboBFCBackColors, + vboNumComplements +}; + +// KDevelop doesn't seem to understand some VBO stuff +#ifdef IN_IDE_PARSER +using GLenum = unsigned int; +using GLuint = unsigned int; +void glBindBuffer (GLenum, GLuint); +void glGenBuffers (GLuint, GLuint*); +void glDeleteBuffers (GLuint, GLuint*); +void glBufferData (GLuint, GLuint, void*, GLuint); +#endif + +static const int gNumVBOs = vboNumSurfaces * vboNumComplements; + #endif // LDFORGE_GLSHARED_H \ No newline at end of file
--- a/src/LDObject.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/LDObject.cc Thu Feb 06 22:11:28 2014 +0200 @@ -270,7 +270,7 @@ getFile()->forgetObject (this); // Delete the GL lists - GL::deleteLists (this); + g_win->R()->forgetObject (this); // Remove this object from the list of LDObjects g_LDObjects.removeOne (this); @@ -320,9 +320,9 @@ // ============================================================================= // ----------------------------------------------------------------------------- -LDObjectList LDSubfile::inlineContents (InlineFlags flags) +LDObjectList LDSubfile::inlineContents (bool deep, bool render) { - LDObjectList objs = getFileInfo()->inlineContents (flags); + LDObjectList objs = getFileInfo()->inlineContents (deep, render); // Transform the objects for (LDObject* obj : objs) @@ -336,6 +336,45 @@ } // ============================================================================= +// +LDPolygon* LDObject::getPolygon() +{ + Type ot = getType(); + int num = + (ot == LDObject::ELine) ? 2 : + (ot == LDObject::ETriangle) ? 3 : + (ot == LDObject::EQuad) ? 4 : + (ot == LDObject::ECondLine) ? 5 : + 0; + if (ot == 0) + return null; + + LDPolygon* data = new LDPolygon; + data->id = getID(); + data->num = num; + data->color = getColor(); + data->origin = getOrigin(); + + for (int i = 0; i < data->numVertices(); ++i) + data->vertices[i] = getVertex (i); + + return data; +} + +// ============================================================================= +// +QList<LDPolygon> LDSubfile::inlinePolygons() +{ + QList<LDPolygon> data = getFileInfo()->inlinePolygons(); + + for (LDPolygon& entry : data) + for (int i = 0; i < entry.numVertices(); ++i) + entry.vertices[i].transform (getTransform(), getPosition()); + + return data; +} + +// ============================================================================= // ----------------------------------------------------------------------------- long LDObject::getIndex() const { @@ -832,5 +871,28 @@ */ LDObject* copy = parseLine (raw()); + + if (getOrigin().isEmpty() == false) + copy->setOrigin (getOrigin()); + elif (getFile() != null) + copy->setOrigin (getFile()->getDisplayName() + ":" + QString::number (getIndex())); + return copy; -} \ No newline at end of file +} + +// ============================================================================= +// +void LDSubfile::setFileInfo (const LDDocumentPointer& a) +{ + m_FileInfo = a; + + // If it's an immediate subfile reference (i.e. this subfile belongs in an + // explicit file), we need to pre-compile the GL polygons for the document + // if they don't exist already. + if (a != null && + a->isImplicit() == false && + a->getPolygonData().isEmpty()) + { + a->initializeGLData(); + } +}; \ No newline at end of file
--- a/src/LDObject.h Wed Feb 05 06:07:05 2014 +0200 +++ b/src/LDObject.h Thu Feb 06 22:11:28 2014 +0200 @@ -22,6 +22,7 @@ #include "Main.h" #include "Types.h" #include "misc/DocumentPointer.h" +#include "GLShared.h" #define LDOBJ(T) \ protected: \ @@ -74,6 +75,7 @@ PROPERTY (private, int, ID, NUM_OPS, STOCK_WRITE) PROPERTY (public, int, Color, NUM_OPS, CUSTOM_WRITE) PROPERTY (public, bool, GLInit, BOOL_OPS, STOCK_WRITE) + PROPERTY (public, QString, Origin, NO_OPS, STOCK_WRITE) public: // Object type codes. @@ -174,6 +176,7 @@ // Get a description of a list of LDObjects static QString describeObjects (const LDObjectList& objs); static LDObject* fromID (int id); + LDPolygon* getPolygon(); // TODO: make these private! // OpenGL list for this object @@ -395,7 +398,7 @@ LDOBJ_COLORED LDOBJ_SCEMANTIC LDOBJ_HAS_MATRIX - PROPERTY (public, LDDocumentPointer, FileInfo, NO_OPS, STOCK_WRITE) + PROPERTY (public, LDDocumentPointer, FileInfo, NO_OPS, CUSTOM_WRITE) public: enum InlineFlag @@ -416,7 +419,8 @@ // Inlines this subfile. Note that return type is an array of heap-allocated // LDObject copies, they must be deleted manually. - LDObjectList inlineContents (InlineFlags flags); + LDObjectList inlineContents (bool deep, bool render); + QList<LDPolygon> inlinePolygons(); protected: ~LDSubfile();
--- a/src/Types.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/Types.cc Thu Feb 06 22:11:28 2014 +0200 @@ -329,7 +329,7 @@ case LDObject::ESubfile: { LDSubfile* ref = static_cast<LDSubfile*> (obj); - LDObjectList objs = ref->inlineContents (LDSubfile::DeepCacheInline); + LDObjectList objs = ref->inlineContents (true, false); for (LDObject * obj : objs) {
--- a/src/actions/EditActions.cc Wed Feb 05 06:07:05 2014 +0200 +++ b/src/actions/EditActions.cc Thu Feb 06 22:11:28 2014 +0200 @@ -123,19 +123,10 @@ // inlined contents. long idx = obj->getIndex(); - if (idx == -1) + if (idx == -1 || obj->getType() != LDObject::ESubfile) continue; - LDObjectList objs; - - if (obj->getType() == LDObject::ESubfile) - objs = static_cast<LDSubfile*> (obj)->inlineContents ( - (LDSubfile::InlineFlags) - ( (deep) ? LDSubfile::DeepInline : 0) | - LDSubfile::CacheInline - ); - else - continue; + LDObjectList objs = static_cast<LDSubfile*> (obj)->inlineContents (deep, false); // Merge in the inlined objects for (LDObject * inlineobj : objs) @@ -394,11 +385,13 @@ vect[Y] *= *currentGrid().confs[Grid::Y]; vect[Z] *= *currentGrid().confs[Grid::Z]; + QTime t0 = QTime::currentTime(); for (LDObject* obj : selection()) { obj->move (vect); g_win->R()->compileObject (obj); } + fprint (stderr, "Move: %1ms\n", t0.msecsTo (QTime::currentTime())); g_win->refresh(); }