Merge ../ldforge into gl

Tue, 21 Jan 2014 02:09:14 +0200

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Tue, 21 Jan 2014 02:09:14 +0200
changeset 675
450827da2376
parent 674
3d8ab0f89102 (diff)
parent 629
b75c6cce02e2 (current diff)
child 676
f7f965742fd5

Merge ../ldforge into gl

Conflicts:
src/GLRenderer.cc
src/GLRenderer.h
src/LDObject.cc

ldforge.pro 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/LDObject.cc file | annotate | diff | comparison | revisions
src/addObjectDialog.cc file | annotate | diff | comparison | revisions
src/addObjectDialog.h file | annotate | diff | comparison | revisions
src/colorSelectDialog.cc file | annotate | diff | comparison | revisions
src/colorSelectDialog.h file | annotate | diff | comparison | revisions
src/colors.cc file | annotate | diff | comparison | revisions
src/colors.h file | annotate | diff | comparison | revisions
src/config.cc file | annotate | diff | comparison | revisions
src/config.h file | annotate | diff | comparison | revisions
src/configDialog.cc file | annotate | diff | comparison | revisions
src/configDialog.h file | annotate | diff | comparison | revisions
src/crashcatcher.cc file | annotate | diff | comparison | revisions
src/crashcatcher.h file | annotate | diff | comparison | revisions
src/dialogs.cc file | annotate | diff | comparison | revisions
src/dialogs.h file | annotate | diff | comparison | revisions
src/docs.cc file | annotate | diff | comparison | revisions
src/docs.h file | annotate | diff | comparison | revisions
src/document.cc file | annotate | diff | comparison | revisions
src/document.h file | annotate | diff | comparison | revisions
src/download.cc file | annotate | diff | comparison | revisions
src/download.h file | annotate | diff | comparison | revisions
src/extprogs.cc file | annotate | diff | comparison | revisions
src/gldraw.cc file | annotate | diff | comparison | revisions
src/gldraw.h file | annotate | diff | comparison | revisions
src/gui.cc file | annotate | diff | comparison | revisions
src/gui.h file | annotate | diff | comparison | revisions
src/gui_actions.cc file | annotate | diff | comparison | revisions
src/gui_editactions.cc file | annotate | diff | comparison | revisions
src/history.cc file | annotate | diff | comparison | revisions
src/history.h file | annotate | diff | comparison | revisions
src/ldconfig.cc file | annotate | diff | comparison | revisions
src/ldconfig.h file | annotate | diff | comparison | revisions
src/ldtypes.cc file | annotate | diff | comparison | revisions
src/ldtypes.h file | annotate | diff | comparison | revisions
src/main.cc file | annotate | diff | comparison | revisions
src/main.h file | annotate | diff | comparison | revisions
src/messagelog.cc file | annotate | diff | comparison | revisions
src/messagelog.h file | annotate | diff | comparison | revisions
src/misc.cc file | annotate | diff | comparison | revisions
src/misc.h file | annotate | diff | comparison | revisions
src/misc/documentPointer.cc file | annotate | diff | comparison | revisions
src/misc/documentPointer.h file | annotate | diff | comparison | revisions
src/misc/invokationDeferer.cc file | annotate | diff | comparison | revisions
src/misc/invokationDeferer.h file | annotate | diff | comparison | revisions
src/misc/ringFinder.cc file | annotate | diff | comparison | revisions
src/misc/ringFinder.h file | annotate | diff | comparison | revisions
src/primitives.cc file | annotate | diff | comparison | revisions
src/primitives.h file | annotate | diff | comparison | revisions
src/property.h file | annotate | diff | comparison | revisions
src/types.cc file | annotate | diff | comparison | revisions
src/types.h file | annotate | diff | comparison | revisions
src/widgets.cc file | annotate | diff | comparison | revisions
src/widgets.h file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/GLCompiler.cc	Tue Jan 21 02:09:14 2014 +0200
@@ -0,0 +1,433 @@
+#include "GLCompiler.h"
+#include "LDObject.h"
+#include "Colors.h"
+#include "Document.h"
+#include "Misc.h"
+#include "GLRenderer.h"
+#include <QDate>
+
+#define DE_BUG_PRINT(...) fprint (stdout, __VA_ARGS__)
+
+extern_cfg (Bool, gl_blackedges);
+static QList<short> g_warnedColors;
+GLCompiler g_vertexCompiler;
+
+// =============================================================================
+//
+GLCompiler::GLCompiler() :
+	m_file (null)
+{
+	needMerge();
+}
+
+GLCompiler::~GLCompiler() {}
+
+// =============================================================================
+// Note: we use the top level object's color but the draw object's vertices.
+// This is so that the index color is generated correctly - it has to reference
+// the top level object's ID. This is crucial for picking to work.
+//
+void GLCompiler::compilePolygon (LDObject* drawobj, LDObject* trueobj, QList< GLCompiler::CompiledTriangle >& data)
+{
+	const QColor pickColor = getObjectColor (trueobj, E_PickColor);
+	LDObject::Type type = drawobj->getType();
+	LDObjectList objs;
+
+	assert (type != LDObject::ESubfile);
+
+	if (type == LDObject::EQuad)
+	{
+		for (LDTriangle* t : static_cast<LDQuad*> (drawobj)->splitToTriangles())
+			objs << t;
+	}
+	else
+		objs << drawobj;
+
+	for (LDObject* obj : objs)
+	{
+		const LDObject::Type objtype = obj->getType();
+		const bool isline = (objtype == LDObject::ELine || objtype == LDObject::ECondLine);
+		const int verts = isline ? 2 : obj->vertices();
+		QColor normalColor = getObjectColor (obj, E_NormalColor);
+
+		assert (isline || objtype == LDObject::ETriangle);
+
+		CompiledTriangle a;
+		a.rgb = getColorRGB (normalColor);
+		a.pickrgb = getColorRGB (pickColor);
+		a.numVerts = verts;
+		a.obj = trueobj;
+		a.isCondLine = (objtype == LDObject::ECondLine);
+
+		for (int i = 0; i < verts; ++i)
+		{
+			a.verts[i] = obj->getVertex (i);
+			a.verts[i].y() = -a.verts[i].y();
+			a.verts[i].z() = -a.verts[i].z();
+		}
+
+		data << a;
+	}
+}
+
+// =============================================================================
+//
+void GLCompiler::compileObject (LDObject* obj)
+{
+	initObject (obj);
+	QList<CompiledTriangle> data;
+	QTime t0;
+
+	t0 = QTime::currentTime();
+	for (int i = 0; i < E_NumVertexArrays; ++i)
+		m_objArrays[obj][i].clear();
+	DE_BUG_PRINT ("INIT: %1ms\n", t0.msecsTo (QTime::currentTime()));
+
+	t0 = QTime::currentTime();
+	compileSubObject (obj, obj, data);
+	DE_BUG_PRINT ("COMPILATION: %1ms\n", t0.msecsTo (QTime::currentTime()));
+
+	t0 = QTime::currentTime();
+
+	for (int i = 0; i < E_NumVertexArrays; ++i)
+	{
+		E_VertexArrayType type = (E_VertexArrayType) i;
+		const bool islinearray = (type == E_EdgeArray || type == E_EdgePickArray);
+
+		for (const CompiledTriangle& poly : data)
+		{
+			if (poly.isCondLine)
+			{
+				// Conditional lines go to the edge pick array and the array
+				// specifically designated for conditional lines and nowhere else.
+				// They are kept separate from the regular edge array so that
+				// they can be drawn as dashed lines.
+				//
+				// However we don't need nor desire that behavior for the pick
+				// scene, so they can be grouped with normal edgelines for that.
+				if (type != E_EdgePickArray && type != E_CondEdgeArray)
+					continue;
+			}
+			else
+			{
+				// Lines and only lines go to line arrays and only to line arrays.
+				if ((poly.numVerts == 2) ^ islinearray)
+					continue;
+
+				// Only conditional lines go into the conditional line array
+				if (type == E_CondEdgeArray)
+					continue;
+			}
+
+			// Postprocess the polygon into a VAO and add it in
+			VertexArray* verts = postprocess (poly, type);
+			m_objArrays[obj][type] += *verts;
+
+			// The array is changed, it needs a merge now.
+			m_changed[type] = true;
+			delete verts;
+		}
+	}
+
+	DE_BUG_PRINT ("POST-PROCE_SS: %1ms\n", t0.msecsTo (QTime::currentTime()));
+}
+
+// =============================================================================
+//
+void GLCompiler::compileSubObject (LDObject* obj, LDObject* topobj, GLCompiler::PolygonList& data)
+{
+	LDObjectList objs;
+
+	switch (obj->getType())
+	{
+		case LDObject::ETriangle:
+		case LDObject::ELine:
+		case LDObject::ECondLine:
+		{
+			compilePolygon (obj, topobj, data);
+		} break;
+
+		case LDObject::EQuad:
+		{
+			QTime t0 = QTime::currentTime();
+			for (LDTriangle* triangle : static_cast<LDQuad*> (obj)->splitToTriangles())
+				compilePolygon (triangle, topobj, data);
+			DE_BUG_PRINT ("\t- QUAD COMPILE: %1ms\n", t0.msecsTo (QTime::currentTime()));
+		} break;
+
+		case LDObject::ESubfile:
+		{
+			QTime t0 = QTime::currentTime();
+			objs = static_cast<LDSubfile*> (obj)->inlineContents (LDSubfile::RendererInline | LDSubfile::DeepCacheInline);
+			DE_BUG_PRINT ("\t- INLINE: %1ms\n", t0.msecsTo (QTime::currentTime()));
+			DE_BUG_PRINT ("\t- %1 objects\n", objs.size());
+
+			t0 = QTime::currentTime();
+
+			for (LDObject* obj : objs)
+			{
+				compileSubObject (obj, topobj, data);
+				obj->deleteSelf();
+			}
+
+			DE_BUG_PRINT ("\t- SUB-COMPILATION: %1ms\n", t0.msecsTo (QTime::currentTime()));
+		} break;
+
+		default:
+		{} break;
+	}
+}
+
+// =============================================================================
+//
+void GLCompiler::compileDocument()
+{
+	for (LDObject * obj : m_file->getObjects())
+		compileObject (obj);
+}
+
+// =============================================================================
+//
+void GLCompiler::forgetObject (LDObject* obj)
+{
+	auto it = m_objArrays.find (obj);
+
+	if (it != m_objArrays.end())
+		delete *it;
+
+	m_objArrays.remove (obj);
+}
+
+// =============================================================================
+//
+void GLCompiler::setFile (LDDocument* file)
+{
+	m_file = file;
+}
+
+// =============================================================================
+//
+const GLCompiler::VertexArray* GLCompiler::getMergedBuffer (E_VertexArrayType type)
+{
+	// If there are objects staged for compilation, compile them now.
+	if (m_staged.size() > 0)
+	{
+		for (LDObject * obj : m_staged)
+			compileObject (obj);
+
+		m_staged.clear();
+	}
+
+	assert (type < E_NumVertexArrays);
+
+	if (m_changed[type])
+	{
+		m_changed[type] = false;
+		m_mainArrays[type].clear();
+
+		for (LDObject* obj : m_file->getObjects())
+		{
+			if (!obj->isScemantic())
+				continue;
+
+			auto it = m_objArrays.find (obj);
+
+			if (it != m_objArrays.end())
+				m_mainArrays[type] += (*it)[type];
+		}
+
+		DE_BUG_PRINT ("merged array %1: %2 entries\n", (int) type, m_mainArrays[type].size());
+	}
+
+	return &m_mainArrays[type];
+}
+
+// =============================================================================
+// This turns a compiled triangle into usable VAO vertices
+//
+GLCompiler::VertexArray* GLCompiler::postprocess (const CompiledTriangle& poly, E_VertexArrayType type)
+{
+	VertexArray* va = new VertexArray;
+	VertexArray verts;
+
+	for (int i = 0; i < poly.numVerts; ++i)
+	{
+		VAO vao;
+		const auto& v0 = poly.verts[i];
+		vao.x = v0.x();
+		vao.y = v0.y();
+		vao.z = v0.z();
+
+		switch (type)
+		{
+			case E_SurfaceArray:
+			case E_EdgeArray:
+			case E_CondEdgeArray:
+			{
+				vao.color = poly.rgb;
+			} break;
+
+			case E_PickArray:
+			case E_EdgePickArray:
+			{
+				vao.color = poly.pickrgb;
+			} break;
+
+			case E_BFCArray:
+			case E_NumVertexArrays:
+				break;
+		}
+
+		verts << vao;
+	}
+
+	if (type == E_BFCArray)
+	{
+		int32 rgb = getColorRGB (getObjectColor (poly.obj, E_BFCFrontColor));
+
+		for (VAO vao : verts)
+		{
+			vao.color = rgb;
+			*va << vao;
+		}
+
+		rgb = getColorRGB (getObjectColor (poly.obj, E_BFCBackColor));
+
+		for (int i = verts.size() - 1; i >= 0; --i)
+		{
+			VAO vao = verts[i];
+			vao.color = rgb;
+			*va << vao;
+		}
+	}
+	else
+		*va = verts;
+
+	return va;
+}
+
+// =============================================================================
+//
+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 ((colortype == E_BFCFrontColor || colortype == E_BFCBackColor) &&
+		obj->getType() != LDObject::ELine &&
+		obj->getType() != LDObject::ECondLine)
+	{
+		if (colortype == E_BFCFrontColor)
+			qcol = QColor (40, 192, 0);
+		else
+			qcol = QColor (224, 0, 0);
+	}
+	else
+	{
+		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);
+}
+
+// =============================================================================
+//
+void GLCompiler::initObject (LDObject* obj)
+{
+	if (m_objArrays.find (obj) == m_objArrays.end())
+		m_objArrays[obj] = new VertexArray[E_NumVertexArrays];
+}
+
+// =============================================================================
+//
+void GLCompiler::stageForCompilation (LDObject* obj)
+{
+	m_staged << obj;
+	removeDuplicates (m_staged);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/GLCompiler.h	Tue Jan 21 02:09:14 2014 +0200
@@ -0,0 +1,114 @@
+/*
+ *  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
+{
+	public:
+		enum E_ColorType
+		{
+			E_NormalColor,
+			E_BFCFrontColor,
+			E_BFCBackColor,
+			E_PickColor,
+		};
+
+		struct CompiledTriangle
+		{
+			Vertex		verts[3];
+			uint8		numVerts;	// 2 if a line
+			uint32		rgb;		// Color of this poly normally
+			uint32		pickrgb;	// Color of this poly while picking
+			bool		isCondLine;	// Is this a conditional line?
+			LDObject*	obj;		// Pointer to the object this poly represents
+		};
+
+		struct VAO
+		{
+			float x, y, z;
+			uint32 color;
+			float pad[4];
+		};
+
+		using PolygonList = QList<CompiledTriangle>;
+		using VertexArray = QVector<VAO>;
+
+		GLCompiler();
+		~GLCompiler();
+		void setFile (LDDocument* file);
+		void compileDocument();
+		void forgetObject (LDObject* obj);
+		void initObject (LDObject* obj);
+		const VertexArray* getMergedBuffer (E_VertexArrayType type);
+		QColor getObjectColor (LDObject* obj, E_ColorType colortype) const;
+		void needMerge();
+		void stageForCompilation (LDObject* obj);
+
+		static uint32 getColorRGB (const QColor& color);
+
+	private:
+		void compilePolygon (LDObject* drawobj, LDObject* trueobj, PolygonList& data);
+		void compileObject (LDObject* obj);
+		void compileSubObject (LDObject* obj, LDObject* topobj, PolygonList& data);
+		VertexArray* postprocess (const CompiledTriangle& poly, E_VertexArrayType type);
+
+		QMap<LDObject*, VertexArray*>				m_objArrays;
+		VertexArray								m_mainArrays[E_NumVertexArrays];
+		LDDocument*							m_file;
+		bool								m_changed[E_NumVertexArrays];
+		LDObjectList						m_staged; // Objects that need to be compiled
+};
+
+extern GLCompiler g_vertexCompiler;
+
+#endif // LDFORGE_GLCOMPILER_H
--- a/src/GLRenderer.cc	Tue Jan 21 02:03:27 2014 +0200
+++ b/src/GLRenderer.cc	Tue Jan 21 02:09:14 2014 +0200
@@ -36,6 +36,7 @@
 #include "Dialogs.h"
 #include "AddObjectDialog.h"
 #include "MessageLog.h"
+#include "GLCompiler.h"
 #include "Primitives.h"
 #include "misc/RingFinder.h"
 #include "moc_GLRenderer.cpp"
@@ -109,9 +110,6 @@
 	{ QColor (0,   160, 192), Vertex (0, 0, 10000) }, // Z
 };
 
-static bool g_glInvert = false;
-static QList<int> g_warnedColors;
-
 // =============================================================================
 //
 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent)
@@ -245,11 +243,13 @@
 	setBackground();
 
 	glLineWidth (gl_linethickness);
+	glLineStipple (1, 0x6666);
 
 	setAutoFillBackground (false);
 	setMouseTracking (true);
 	setFocusPolicy (Qt::WheelFocus);
-	compileAllObjects();
+
+	g_vertexCompiler.compileDocument();
 }
 
 // =============================================================================
@@ -282,105 +282,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 +290,10 @@
 }
 
 // =============================================================================
-//
+// -----------------------------------------------------------------------------
 void GLRenderer::hardRefresh()
 {
-	compileAllObjects();
+	g_vertexCompiler.compileDocument();
 	refresh();
 
 	glLineWidth (gl_linethickness);
@@ -462,47 +364,47 @@
 		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);
+	// Draw the VAOs now
+	glEnableClientState (GL_VERTEX_ARRAY);
+	glEnableClientState (GL_COLOR_ARRAY);
+	glDisableClientState (GL_NORMAL_ARRAY);
 
-		for (LDObject* obj : getFile()->getObjects())
-		{
-			if (obj->isHidden())
-				continue;
-
-			glCullFace (GL_BACK);
-			glCallList (obj->glLists[BFCFrontList]);
+	if (gl_colorbfc) {
+		glEnable (GL_CULL_FACE);
+		glCullFace (GL_CCW);
+	} else
+		glDisable (GL_CULL_FACE);
 
-			glCullFace (GL_FRONT);
-			glCallList (obj->glLists[BFCBackList]);
-		}
+	drawVAOs ((isPicking() ? E_PickArray : gl_colorbfc ? E_BFCArray : E_SurfaceArray), GL_TRIANGLES);
+	drawVAOs ((isPicking() ? E_EdgePickArray : E_EdgeArray), GL_LINES);
 
-		glDisable (GL_CULL_FACE);
-	}
-	else
+	// Draw conditional lines. Note that conditional lines are drawn into
+	// EdgePickArray in the picking scene so we only draw this array when
+	// not using the pick scene.
+	if (!isPicking())
 	{
-		for (LDObject* obj : getFile()->getObjects())
-		{
-			if (obj->isHidden())
-				continue;
-
-			glCallList (obj->glLists[list]);
-		}
+		glEnable (GL_LINE_STIPPLE);
+		drawVAOs (E_CondEdgeArray, GL_LINES);
+		glDisable (GL_LINE_STIPPLE);
 	}
 
-	if (gl_axes && !isPicking() && !isDrawOnly())
-		glCallList (m_axeslist);
-
 	glPopMatrix();
+	glDisable (GL_CULL_FACE);
 	glMatrixMode (GL_MODELVIEW);
 	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 }
 
 // =============================================================================
 //
+void GLRenderer::drawVAOs (E_VertexArrayType arrayType, GLenum type)
+{
+	const GLCompiler::VertexArray* array = g_vertexCompiler.getMergedBuffer (arrayType);
+	glVertexPointer (3, GL_FLOAT, sizeof (GLCompiler::VAO), &array->data()[0].x);
+	glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (GLCompiler::VAO), &array->data()[0].color);
+	glDrawArrays (type, 0, array->size());
+}
+
+// =============================================================================
 // 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 +799,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]);
+	g_vertexCompiler.compileDocument();
 }
 
 // =============================================================================
@@ -1376,8 +1158,8 @@
 	{
 		qint32 idx =
 			(*(pixelptr + 0) * 0x10000) +
-			(*(pixelptr + 1) * 0x00100) +
-			(*(pixelptr + 2) * 0x00001);
+			(*(pixelptr + 1) * 0x100) +
+			*(pixelptr + 2);
 		pixelptr += 4;
 
 		if (idx == 0xFFFFFF)
@@ -1473,6 +1255,7 @@
 void GLRenderer::setFile (LDDocument* const& a)
 {
 	m_File = a;
+	g_vertexCompiler.setFile (a);
 
 	if (a != null)
 	{
@@ -1743,24 +1526,10 @@
 }
 
 // =============================================================================
-//
+// -----------------------------------------------------------------------------
 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();
-	}
+	g_vertexCompiler.stageForCompilation (obj);
 
 	// Mark in known vertices of this object
 	QList<Vertex> verts = getVertices (obj);
--- a/src/GLRenderer.h	Tue Jan 21 02:03:27 2014 +0200
+++ b/src/GLRenderer.h	Tue Jan 21 02:09:14 2014 +0200
@@ -23,6 +23,7 @@
 #include "Main.h"
 #include "LDObject.h"
 #include "Document.h"
+#include "GLShared.h"
 
 class MessageManager;
 class QDialogButtonBox;
@@ -152,7 +153,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 +171,7 @@
 		void           zoomAllToFit();
 
 		static void    deleteLists (LDObject* obj);
+		static QColor  getMainColor();
 
 	protected:
 		void           contextMenuEvent (QContextMenuEvent* ev);
@@ -245,6 +246,12 @@
 		// Convert a 2D point to a 3D point
 		Vertex         coordconv2_3 (const QPoint& pos2d, bool snap) const;
 
+		// Draw a VAO array
+		void           drawVAOs (E_VertexArrayType 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;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/GLShared.h	Tue Jan 21 02:09:14 2014 +0200
@@ -0,0 +1,33 @@
+/*
+ *  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_VertexArrayType
+{
+	E_SurfaceArray,
+	E_EdgeArray,
+	E_CondEdgeArray,
+	E_BFCArray,
+	E_PickArray,
+	E_EdgePickArray,
+	E_NumVertexArrays
+};
+
+#endif // LDFORGE_GLSHARED_H
\ No newline at end of file
--- a/src/LDObject.cc	Tue Jan 21 02:03:27 2014 +0200
+++ b/src/LDObject.cc	Tue Jan 21 02:09:14 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, "");

mercurial