Fri, 10 Feb 2017 23:06:24 +0200
Added the RingAdapter class and interfacing ring() function and simplified some math in GLCompiler with it
src/basics.h | file | annotate | diff | comparison | revisions | |
src/glCompiler.cpp | file | annotate | diff | comparison | revisions |
--- a/src/basics.h Thu Feb 09 23:51:42 2017 +0200 +++ b/src/basics.h Fri Feb 10 23:06:24 2017 +0200 @@ -217,6 +217,75 @@ double getRadialPoint(int segment, int divisions, double(*func)(double)); QVector<QLineF> makeCircle(int segments, int divisions, double radius); +/* + * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds. + * The maximum amount can be specified manually. + * + * Example: + * + * int A[] = {10,20,30,40}; + * ring(A)[0] == A[0 % 4] == A[0] + * ring(A)[5] == A[5 % 4] == A[1] + * ring(A)[-1] == ring(A)[-1 + 4] == A[3] + */ +template<typename T> +class RingAdapter +{ +private: + // The private section must come first because _collection is used in decltype() below. + T& _collection; + const int _count; + +public: + RingAdapter(T& collection, int count) : + _collection {collection}, + _count {count} {} + + template<typename IndexType> + decltype(_collection[IndexType()]) operator[](IndexType index) + { + if (_count == 0) + { + // Argh! ...let the collection deal with this case. + return _collection[0]; + } + else + { + index %= _count; + + // Fix negative modulus... + if (index < 0) + index += _count; + + return _collection[index]; + } + } + + int size() const + { + return _count; + } +}; + +/* + * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed + * to be the amount of elements in the collection. + */ +template<typename T> +RingAdapter<T> ring(T& collection) +{ + return RingAdapter<T> {collection, countof(collection)}; +} + +/* + * Version of ring() that allows manual specification of the count. + */ +template<typename T> +RingAdapter<T> ring(T& collection, int count) +{ + return RingAdapter<T> {collection, count}; +} + // // Get the amount of elements in something. // @@ -254,3 +323,9 @@ { return vector.size(); } + +template<typename T> +int countof(const RingAdapter<T>& ring) +{ + return ring.size(); +}
--- a/src/glCompiler.cpp Thu Feb 09 23:51:42 2017 +0200 +++ b/src/glCompiler.cpp Fri Feb 10 23:06:24 2017 +0200 @@ -334,24 +334,26 @@ void GLCompiler::compilePolygon (LDPolygon& poly, LDObject* topobj, ObjectVBOInfo* objinfo) { SurfaceVboType surface; - int numverts; + int vertexCount; switch (poly.num) { - case 2: surface = LinesVbo; numverts = 2; break; - case 3: surface = TrianglesVbo; numverts = 3; break; - case 4: surface = QuadsVbo; numverts = 4; break; - case 5: surface = ConditionalLinesVbo; numverts = 2; break; + case 2: surface = LinesVbo; vertexCount = 2; break; + case 3: surface = TrianglesVbo; vertexCount = 3; break; + case 4: surface = QuadsVbo; vertexCount = 4; break; + case 5: surface = ConditionalLinesVbo; vertexCount = 2; break; default: return; } // Determine the normals for the polygon. Vertex normals[4]; - for (int i = 0; i < numverts; ++i) + auto vertexRing = ring(poly.vertices, vertexCount); + + for (int i = 0; i < vertexCount; ++i) { - const Vertex& v1 = poly.vertices[(i - 1 + numverts) % numverts]; - const Vertex& v2 = poly.vertices[i]; - const Vertex& v3 = poly.vertices[(i + 1) % numverts]; + const Vertex& v1 = vertexRing[i - 1]; + const Vertex& v2 = vertexRing[i]; + const Vertex& v3 = vertexRing[i + 1]; normals[i] = Vertex::crossProduct(v3 - v2, v1 - v2).normalized(); } @@ -361,7 +363,7 @@ QVector<GLfloat>& vbodata = objinfo->data[vbonum]; const QColor color = getColorForPolygon (poly, topobj, complement); - for (int vert = 0; vert < numverts; ++vert) + for (int vert = 0; vert < vertexCount; ++vert) { if (complement == SurfacesVboComplement) {