- converted to VBO

Fri, 24 Jan 2014 18:29:11 +0200

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Fri, 24 Jan 2014 18:29:11 +0200
changeset 676
f7f965742fd5
parent 675
450827da2376
child 677
b3c32a2741be

- converted to VBO

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/Main.cc file | annotate | diff | comparison | revisions
src/Types.h file | annotate | diff | comparison | revisions
--- a/src/GLCompiler.cc	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/GLCompiler.cc	Fri Jan 24 18:29:11 2014 +0200
@@ -1,309 +1,36 @@
+#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 <QDate>
 
-#define DE_BUG_PRINT(...) fprint (stdout, __VA_ARGS__)
+#define DEBUG_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()));
-}
+static const QColor g_BFCFrontColor(40, 192, 0);
+static const QColor g_BFCBackColor(224, 0, 0);
 
 // =============================================================================
 //
-void GLCompiler::compileSubObject (LDObject* obj, LDObject* topobj, GLCompiler::PolygonList& data)
+GLCompiler::GLCompiler() :
+	m_Document (null)
 {
-	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;
+	glGenBuffers (VBO_NumArrays, &m_mainVBOIndices[0]);
+	for (int i = 0; i < 8; ++i)
+		printf ("%d. %u\n", i, m_mainVBOIndices[i]);
+	needMerge();
 }
 
-// =============================================================================
-//
-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)
+GLCompiler::~GLCompiler()
 {
-	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;
+	glDeleteBuffers (VBO_NumArrays, &m_mainVBOIndices[0]);
 }
 
 // =============================================================================
@@ -344,54 +71,42 @@
 		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);
-	}
+	if (obj->getColor() == maincolor)
+		qcol = GLRenderer::getMainColor();
 	else
 	{
-		if (obj->getColor() == maincolor)
+		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
-		{
-			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;
-		}
+			qcol = Qt::black;
 
-		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;
 
-			// 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;
-		}
+		log ("%1: Unknown color %2!\n", __func__, obj->getColor());
+		g_warnedColors << obj->getColor();
+		return qcol;
 	}
 
 	if (obj->topLevelParent()->isSelected())
@@ -412,15 +127,9 @@
 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];
+	// memset (m_changed, 0xFF, sizeof m_changed);
+	for (int i = 0; i < VBO_NumArrays; ++i)
+		m_changed[i] = true;
 }
 
 // =============================================================================
@@ -431,3 +140,150 @@
 	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_mainArrays[type].clear();
+
+	for (auto it = m_objArrays.begin(); it != m_objArrays.end(); ++it)
+		m_mainArrays[type] += (*it)[type];
+
+	glBindBuffer (GL_ARRAY_BUFFER, m_mainVBOIndices[type]);
+	glBufferData (GL_ARRAY_BUFFER, m_mainArrays[type].size() * sizeof(float),
+		m_mainArrays[type].constData(), GL_DYNAMIC_DRAW);
+	glBindBuffer (GL_ARRAY_BUFFER, m_mainVBOIndices[type]);
+	m_changed[type] = false;
+	log ("VBO array %1 prepared: %2 coordinates", (int) type, m_mainArrays[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<float>[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<float>* 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
+				for (int j = 0; j < 3; ++j)
+					ap[arraynum] << obj->getVertex (i).getCoordinate (j);
+
+				// 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<float>& array, const QColor& color)
+{
+	array	<< color.red()
+			<< color.green()
+			<< color.blue()
+			<< color.alpha();
+}
\ No newline at end of file
--- a/src/GLCompiler.h	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/GLCompiler.h	Fri Jan 24 18:29:11 2014 +0200
@@ -54,58 +54,47 @@
 //
 class GLCompiler
 {
+	PROPERTY (public,	LDDocumentPointer,	Document,	NO_OPS,	STOCK_WRITE)
+
 	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);
+		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);
 
-		static uint32 getColorRGB (const QColor& color);
+		inline GLuint	getVBOIndex (E_VBOArray array) const
+		{
+			return m_mainVBOIndices[array];
+		}
+
+		inline int		getVBOCount (E_VBOArray array) const
+		{
+			return m_mainArrays[array].size() / 3;
+		}
 
 	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);
+		void			compileStaged();
+		void			compileObject (LDObject* obj);
+		void			compileSubObject (LDObject* obj, LDObject* topobj);
+		void			writeColor (QVector< float >& array, const QColor& color);
 
-		QMap<LDObject*, VertexArray*>				m_objArrays;
-		VertexArray								m_mainArrays[E_NumVertexArrays];
-		LDDocument*							m_file;
-		bool								m_changed[E_NumVertexArrays];
+		QMap<LDObject*, QVector<float>*>	m_objArrays;
+		QVector<float>						m_mainArrays[VBO_NumArrays];
+		GLuint								m_mainVBOIndices[VBO_NumArrays];
+		bool								m_changed[VBO_NumArrays];
 		LDObjectList						m_staged; // Objects that need to be compiled
 };
 
--- a/src/GLRenderer.cc	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/GLRenderer.cc	Fri Jan 24 18:29:11 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"
@@ -98,18 +99,22 @@
 	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 GLuint g_GLAxes_VBO;
+
 // =============================================================================
 //
 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent)
@@ -144,6 +149,32 @@
 		info->cam = cam;
 	}
 
+	// Init VBO for axes
+	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, g_GLAxes_VBO);
+
 	calcCameraIcons();
 }
 
@@ -364,31 +395,22 @@
 		glRotatef (rot (Z), 0.0f, 0.0f, 1.0f);
 	}
 
-	// Draw the VAOs now
 	glEnableClientState (GL_VERTEX_ARRAY);
-	glEnableClientState (GL_COLOR_ARRAY);
-	glDisableClientState (GL_NORMAL_ARRAY);
-
-	if (gl_colorbfc) {
-		glEnable (GL_CULL_FACE);
-		glCullFace (GL_CCW);
-	} else
-		glDisable (GL_CULL_FACE);
 
-	drawVAOs ((isPicking() ? E_PickArray : gl_colorbfc ? E_BFCArray : E_SurfaceArray), GL_TRIANGLES);
-	drawVAOs ((isPicking() ? E_EdgePickArray : E_EdgeArray), GL_LINES);
-
-	// 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())
+	if (gl_axes)
 	{
-		glEnable (GL_LINE_STIPPLE);
-		drawVAOs (E_CondEdgeArray, GL_LINES);
-		glDisable (GL_LINE_STIPPLE);
+		glBindBuffer (GL_ARRAY_BUFFER, g_GLAxes_VBO);
+		glVertexPointer (3, GL_FLOAT, 0, NULL);
+		glDrawArrays (GL_LINES, 0, 6);
 	}
 
+	drawVBOs (VBO_Triangles, GL_TRIANGLES);
+	drawVBOs (VBO_Quads, GL_QUADS);
+	drawVBOs (VBO_Lines, GL_LINES);
+	drawVBOs (VBO_CondLines, GL_LINES);
+
 	glPopMatrix();
+	glDisableClientState (GL_VERTEX_ARRAY);
 	glDisable (GL_CULL_FACE);
 	glMatrixMode (GL_MODELVIEW);
 	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
@@ -396,12 +418,20 @@
 
 // =============================================================================
 //
-void GLRenderer::drawVAOs (E_VertexArrayType arrayType, GLenum type)
+void GLRenderer::drawVBOs (E_VBOArray 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());
+	g_vertexCompiler.prepareVBOArray (arrayType);
+	GLuint idx = g_vertexCompiler.getVBOIndex (arrayType);
+	GLsizei count = g_vertexCompiler.getVBOCount (arrayType);
+
+	if (count > 0)
+	{
+		glBindBuffer (GL_ARRAY_BUFFER, idx);
+		glVertexPointer (3, GL_FLOAT, 0, null);
+		// 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);
+	}
 }
 
 // =============================================================================
@@ -1255,7 +1285,7 @@
 void GLRenderer::setFile (LDDocument* const& a)
 {
 	m_File = a;
-	g_vertexCompiler.setFile (a);
+	g_vertexCompiler.setDocument (a);
 
 	if (a != null)
 	{
@@ -1526,7 +1556,7 @@
 }
 
 // =============================================================================
-// -----------------------------------------------------------------------------
+//
 void GLRenderer::compileObject (LDObject* obj)
 {
 	g_vertexCompiler.stageForCompilation (obj);
@@ -1564,7 +1594,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	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/GLRenderer.h	Fri Jan 24 18:29:11 2014 +0200
@@ -246,8 +246,8 @@
 		// 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);
+		// Draw a VBO array
+		void           drawVBOs (E_VBOArray arrayType, GLenum type);
 
 		// Determine which color to draw text with
 		QColor         getTextPen() const;
--- a/src/GLShared.h	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/GLShared.h	Fri Jan 24 18:29:11 2014 +0200
@@ -19,15 +19,17 @@
 #ifndef LDFORGE_GLSHARED_H
 #define LDFORGE_GLSHARED_H
 
-enum E_VertexArrayType
+enum E_VBOArray
 {
-	E_SurfaceArray,
-	E_EdgeArray,
-	E_CondEdgeArray,
-	E_BFCArray,
-	E_PickArray,
-	E_EdgePickArray,
-	E_NumVertexArrays
+	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/Main.cc	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/Main.cc	Fri Jan 24 18:29:11 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	Tue Jan 21 02:09:14 2014 +0200
+++ b/src/Types.h	Fri Jan 24 18:29:11 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;

mercurial