Sun, 07 Sep 2014 18:41:23 +0300
- commit work done on bfc support
src/basics.h | file | annotate | diff | comparison | revisions | |
src/glCompiler.cc | file | annotate | diff | comparison | revisions | |
src/glShared.h | file | annotate | diff | comparison | revisions | |
src/ldDocument.cc | file | annotate | diff | comparison | revisions | |
src/ldDocument.h | file | annotate | diff | comparison | revisions | |
src/ldObject.cc | file | annotate | diff | comparison | revisions | |
src/ldObject.h | file | annotate | diff | comparison | revisions |
--- a/src/basics.h Sun Sep 07 04:15:54 2014 +0300 +++ b/src/basics.h Sun Sep 07 18:41:23 2014 +0300 @@ -56,6 +56,21 @@ Z }; +enum class Winding +{ + CW, + CCW, + None +}; + +inline void invertWinding (Winding& winding) +{ + if (winding == Winding::CW) + winding = Winding::CCW; + elif (winding == Winding::CCW) + winding = Winding::CW; +} + // // Derivative of QVector3D: this class is used for the vertices. //
--- a/src/glCompiler.cc Sun Sep 07 04:15:54 2014 +0300 +++ b/src/glCompiler.cc Sun Sep 07 18:41:23 2014 +0300 @@ -49,10 +49,6 @@ 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; // ============================================================================= @@ -135,7 +131,12 @@ QColor GLCompiler::getColorForPolygon (LDPolygon& poly, LDObjectPtr topobj, EVBOComplement complement) const { + static const QColor bfcFrontColor (64, 192, 80); + static const QColor bfcBackColor (208, 64, 64); + static const QColor bfcDisabledColor (64, 64, 208); + static QList<int> warnedcolors; QColor qcol; + print ("Winding of %1 is %2", poly.id, (int) poly.winding); switch (complement) { @@ -144,11 +145,11 @@ return QColor(); case VBOCM_BFCFrontColors: - qcol = g_BFCFrontColor; + qcol = (poly.winding != Winding::None) ? bfcFrontColor : bfcDisabledColor; break; case VBOCM_BFCBackColors: - qcol = g_BFCBackColor; + qcol = (poly.winding != Winding::None) ? bfcBackColor : bfcDisabledColor; break; case VBOCM_PickColors: @@ -184,16 +185,13 @@ { // 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; + qcol = (poly.num != 2 and poly.num != 5) ? GLRenderer::getMainColor() : Qt::black; // Warn about the unknown color, but only once. - if (not g_warnedColors.contains (poly.color)) + if (not warnedcolors.contains (poly.color)) { print ("Unknown color %1!\n", poly.color); - g_warnedColors << poly.color; + warnedcolors << poly.color; } return qcol; @@ -389,7 +387,9 @@ QVector<GLfloat>& vbodata = objinfo->data[vbonum]; const QColor color = getColorForPolygon (poly, topobj, complement); - for (int vert = 0; vert < numverts; ++vert) + bool inverted = (poly.winding != Winding::CCW); + + auto func = [&](int vert) { if (complement == VBOCM_Surfaces) { @@ -405,6 +405,17 @@ << ((GLfloat) color.blue()) / 255.0f << ((GLfloat) color.alpha()) / 255.0f; } + }; + + if (not inverted) + { + for (int vert = 0; vert < numverts; ++vert) + func (vert); + } + else + { + for (int vert = numverts - 1; vert >= 0; --vert) + func (vert); } } }
--- a/src/glShared.h Sun Sep 07 04:15:54 2014 +0300 +++ b/src/glShared.h Sun Sep 07 18:41:23 2014 +0300 @@ -32,6 +32,7 @@ Vertex vertices[4]; int id; int color; + Winding winding; inline int numVertices() const {
--- a/src/ldDocument.cc Sun Sep 07 04:15:54 2014 +0300 +++ b/src/ldDocument.cc Sun Sep 07 18:41:23 2014 +0300 @@ -208,6 +208,12 @@ } } +LDObjectList const& LDDocument::objects() +{ + sweepBFC(); + return m_objects; +} + // ============================================================================= // QList<LDDocumentPtr> const& LDDocument::explicitDocuments() @@ -1142,6 +1148,7 @@ } // ============================================================================= +// Adds an object at the end of the file. // int LDDocument::addObject (LDObjectPtr obj) { @@ -1150,6 +1157,7 @@ addKnownVertices (obj); obj->setDocument (self()); g_win->R()->compileObject (obj); + requireBFCSweep(); return getObjectCount() - 1; } @@ -1162,6 +1170,8 @@ if (obj != null) addObject (obj); } + + requireBFCSweep(); } // ============================================================================= @@ -1172,8 +1182,8 @@ m_objects.insert (pos, obj); obj->setDocument (self()); g_win->R()->compileObject (obj); + requireBFCSweep(); - #ifdef DEBUG if (not isImplicit()) dprint ("Inserted object #%1 (%2) at %3\n", obj->id(), obj->typeName(), pos); @@ -1209,6 +1219,11 @@ m_objectVertices.remove (obj); } + // We only need a sweep if we got rid of a BFC object, no processing is required if a polygon + // just got removed. + if (obj->type() == OBJ_BFC) + requireBFCSweep(); + m_objects.removeAt (idx); obj->setDocument (LDDocumentPtr()); } @@ -1252,11 +1267,12 @@ // ============================================================================= // -LDObjectPtr LDDocument::getObject (int pos) const +LDObjectPtr LDDocument::getObject (int pos) { if (m_objects.size() <= pos) return LDObjectPtr(); + sweepBFC(); return m_objects[pos]; } @@ -1264,7 +1280,7 @@ // int LDDocument::getObjectCount() const { - return objects().size(); + return m_objects.size(); } // ============================================================================= @@ -1502,8 +1518,9 @@ // ============================================================================= // -const LDObjectList& LDDocument::getSelection() const +const LDObjectList& LDDocument::getSelection() { + sweepBFC(); return m_sel; } @@ -1517,6 +1534,7 @@ m_objects[b] = one; m_objects[a] = other; addToHistory (new SwapHistory (one->id(), other->id())); + requireBFCSweep(); } // ============================================================================= @@ -1549,3 +1567,72 @@ { m_needVertexMerge = true; } + +// +// Sweeps through the file and adjusts the block windings of all objects. +// +void LDDocument::sweepBFC() +{ + if (not m_needBFCSweep) + return; + + QTime t0 (QTime::currentTime()); + Winding winding (Winding::None); + Winding preclip (winding); + LDBFCPtr bfc; + bool invertnext (false); + + for (LDObjectPtr obj : m_objects) + { + if (obj->type() == OBJ_BFC) + { + switch (obj.staticCast<LDBFC>()->statement()) + { + case BFCStatement::CCW: + case BFCStatement::CertifyCCW: + winding = Winding::CCW; + break; + + case BFCStatement::CW: + case BFCStatement::CertifyCW: + winding = Winding::CW; + + case BFCStatement::NoCertify: + winding = Winding::None; + break; + + case BFCStatement::NoClip: + preclip = winding; + winding = Winding::None; + break; + + case BFCStatement::InvertNext: + invertnext = true; + break; + + case BFCStatement::Clip: + winding = preclip; + break; + + default: + break; + } + } + else + { + Winding objwinding (winding); + + if (invertnext) + { + invertWinding (objwinding); + invertnext = false; + } + + print ("%1: BFC sweep: set winding of %2 to %3", getDisplayName(), obj->id(), int (objwinding)); + obj->setBlockWinding (objwinding); + } + } + + print ("%1: BFC sweep done in %2ms", getDisplayName(), t0.msecsTo (QTime::currentTime())); + m_needBFCSweep = false; +}
--- a/src/ldDocument.h Sun Sep 07 04:15:54 2014 +0300 +++ b/src/ldDocument.h Sun Sep 07 18:41:23 2014 +0300 @@ -64,7 +64,6 @@ { public: PROPERTY (public, QString, name, setName, STOCK_WRITE) - PROPERTY (private, LDObjectList, objects, setObjects, STOCK_WRITE) PROPERTY (private, LDObjectList, cache, setCache, STOCK_WRITE) PROPERTY (private, History*, history, setHistory, STOCK_WRITE) PROPERTY (public, QString, fullPath, setFullPath, STOCK_WRITE) @@ -90,13 +89,13 @@ void clearSelection(); void forgetObject (LDObjectPtr obj); // Deletes the given object from the object chain. QString getDisplayName(); - const LDObjectList& getSelection() const; + const LDObjectList& getSelection(); bool hasUnsavedChanges() const; // Does this document have unsaved changes? void initializeCachedData(); LDObjectList inlineContents (bool deep, bool renderinline); void insertObj (int pos, LDObjectPtr obj); int getObjectCount() const; - LDObjectPtr getObject (int pos) const; + LDObjectPtr getObject (int pos); bool save (QString path = "", int64* sizeptr = null); // Saves this file to disk. void swapObjects (LDObjectPtr one, LDObjectPtr other); bool isSafeToClose(); // Perform safety checks. Do this before closing any files! @@ -109,6 +108,8 @@ void redoVertices(); void needVertexMerge(); void reloadAllSubfiles(); + void sweepBFC(); + LDObjectList const& objects(); inline LDDocument& operator<< (LDObjectPtr obj) { @@ -146,6 +147,11 @@ setImplicit (true); } + inline void requireBFCSweep() + { + m_needBFCSweep = true; + } + static LDDocumentPtr current(); static void setCurrent (LDDocumentPtr f); static void closeInitialFile(); @@ -170,12 +176,16 @@ friend class GLRenderer; private: + LDObjectList m_objects; LDObjectList m_sel; LDGLData* m_gldata; // If set to true, next polygon inline of this document discards the // stored polygon data and re-builds it. bool m_needsReCache; + + // If set to true, next object reference request causes BFC sweep. + bool m_needBFCSweep; }; inline LDDocumentPtr CurrentDocument()
--- a/src/ldObject.cc Sun Sep 07 04:15:54 2014 +0300 +++ b/src/ldObject.cc Sun Sep 07 18:41:23 2014 +0300 @@ -419,6 +419,7 @@ data->id = id(); data->num = num; data->color = color().index(); + data->winding = blockWinding(); for (int i = 0; i < data->numVertices(); ++i) data->vertices[i] = vertex (i); @@ -430,14 +431,29 @@ // QList<LDPolygon> LDSubfile::inlinePolygons() { + bool isInverted (false); + LDBFCPtr bfc (previous().dynamicCast<LDBFC>()); + + if ((bfc != null and bfc->statement() == BFCStatement::InvertNext) + or transform().getDeterminant() < 0) + { + isInverted = true; + } + + print ("inlining polygons of subfile-ref %1: inverted: %2", fileInfo()->name(), isInverted ? "true" : "false"); + QList<LDPolygon> data = fileInfo()->inlinePolygons(); for (LDPolygon& entry : data) { for (int i = 0; i < entry.numVertices(); ++i) entry.vertices[i].transform (transform(), position()); + + if (isInverted) + invertWinding (entry.winding); } + print ("Using winding: %1\n", (data[0].winding == Winding::CCW) ? "CCW" : (data[0].winding == Winding::CW) ? "CW" : "None"); return data; }
--- a/src/ldObject.h Sun Sep 07 04:15:54 2014 +0300 +++ b/src/ldObject.h Sun Sep 07 18:41:23 2014 +0300 @@ -101,6 +101,11 @@ PROPERTY (private, QColor, randomColor, setRandomColor, STOCK_WRITE) PROPERTY (private, LDObjectWeakPtr, self, setSelf, STOCK_WRITE) + // What winding the object is supposed to be wound in, depending on the BFC statements + // This is CW if the part is CW-certified at this object, and vice versa. Can also be + // Winding::None for NOCERTIFY parts. + PROPERTY (public, Winding, blockWinding, setBlockWinding, STOCK_WRITE) + public: LDObject (LDObjectPtr* selfptr);