Considerably improved sub-file inlining. Use a matrix class instead of double[9], educated myself on what matrix multiplication actually is and fixed the algorithm up. Aside from I/O problems, 32551.dat is correctly rendered now.

Sun, 24 Mar 2013 21:41:24 +0200

author
Santeri Piippo <crimsondusk64@gmail.com>
date
Sun, 24 Mar 2013 21:41:24 +0200
changeset 64
ada4679d5bce
parent 63
aa40ce18f869
child 65
e4f25b44e240

Considerably improved sub-file inlining. Use a matrix class instead of double[9], educated myself on what matrix multiplication actually is and fixed the algorithm up. Aside from I/O problems, 32551.dat is correctly rendered now.

common.h file | annotate | diff | comparison | revisions
file.cpp file | annotate | diff | comparison | revisions
gldraw.cpp file | annotate | diff | comparison | revisions
gui.cpp file | annotate | diff | comparison | revisions
ldforge.pro file | annotate | diff | comparison | revisions
ldtypes.cpp file | annotate | diff | comparison | revisions
ldtypes.h file | annotate | diff | comparison | revisions
main.cpp file | annotate | diff | comparison | revisions
types.cpp file | annotate | diff | comparison | revisions
types.h file | annotate | diff | comparison | revisions
--- a/common.h	Sun Mar 24 18:03:33 2013 +0200
+++ b/common.h	Sun Mar 24 21:41:24 2013 +0200
@@ -40,6 +40,7 @@
 #include "stdarg.h"
 #include "str.h"
 #include "config.h"
+#include "types.h"
 
 #ifdef __GNUC__
  #define FORMAT_PRINTF(M,N) __attribute__ ((format (printf, M, N)))
@@ -66,33 +67,6 @@
 class QApplication;
 
 // =============================================================================
-// vertex (v)
-// 
-// Vertex class. Not to be confused with LDVertex, which is a vertex used in an
-// LDraw code file.
-//
-// Methods:
-// - midpoint (vertex&): returns a midpoint
-// =============================================================================
-class vertex {
-public:
-	double x, y, z;
-	
-	vertex () {}
-	vertex (double fX, double fY, double fZ) {
-		x = fX;
-		y = fY;
-		z = fZ;
-	}
-	
-	// =========================================================================
-	// Midpoint between this vertex and another vertex.
-	vertex midpoint (vertex& other);
-	str getStringRep (const bool bMangled);
-	void transform (double* matrix, vertex pos);
-};
-
-// =============================================================================
 // Plural expression
 #define PLURAL(n) ((n != 1) ? "s" : "")
 
--- a/file.cpp	Sun Mar 24 18:03:33 2013 +0200
+++ b/file.cpp	Sun Mar 24 21:41:24 2013 +0200
@@ -28,16 +28,10 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 OpenFile* findLoadedFile (str zName) {
-	printf ("finding %s in files\n", zName.chars());
-	
-	for (ulong i = 0; i < g_LoadedFiles.size(); i++) {
-		OpenFile* const file = g_LoadedFiles[i];
-		printf ("%s <-> %s\n", file->zFileName.chars(), zName.chars());
+	FOREACH (OpenFile, *, file, g_LoadedFiles)
 		if (file->zFileName == zName)
 			return file;
-	}
 	
-	printf ("failed to find given file\n");
 	return nullptr;
 }
 
@@ -299,7 +293,7 @@
 			obj->vPosition = parseVertex (tokens, 2); // 2 - 4
 			
 			for (short i = 0; i < 9; ++i)
-				obj->faMatrix[i] = atof (tokens[i + 5]); // 5 - 13
+				obj->mMatrix[i] = atof (tokens[i + 5]); // 5 - 13
 			
 			obj->zFileName = tokens[14];
 			obj->pFile = pFile;
--- a/gldraw.cpp	Sun Mar 24 18:03:33 2013 +0200
+++ b/gldraw.cpp	Sun Mar 24 21:41:24 2013 +0200
@@ -247,7 +247,7 @@
 		{
 			LDSubfile* ref = static_cast<LDSubfile*> (obj);
 			
-			vector<LDObject*> objs = ref->inlineContents (true, ref->faMatrix, ref->vPosition, true);
+			vector<LDObject*> objs = ref->inlineContents (true, ref->mMatrix, ref->vPosition, true);
 			
 			for (ulong i = 0; i < (ulong)objs.size(); ++i)
 				compileOneObject (objs[i], bBackSide);
--- a/gui.cpp	Sun Mar 24 18:03:33 2013 +0200
+++ b/gui.cpp	Sun Mar 24 21:41:24 2013 +0200
@@ -334,8 +334,8 @@
 	// Clear the clipboard. However, its contents are dynamically allocated
 	// clones of LDObjects (cannot use pointers to real objects because the
 	// cut operation deletes them!), so we have to delete said objects first.
-	for (std::size_t i = 0; i < g_Clipboard.size(); ++i)
-		delete g_Clipboard[i];
+	FOREACH (LDObject, *, obj, g_Clipboard)
+		delete obj;
 	
 	g_Clipboard.clear ();
 	
@@ -348,21 +348,6 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
-void ForgeWindow::deleteSelection () {
-	vector<LDObject*> objs = getSelectedObjects ();
-	
-	// Delete the objects that were being selected
-	for (ulong i = 0; i < (ulong)objs.size(); ++i) {
-		LDObject* obj = objs[i];
-		
-		g_CurrentFile->forgetObject (obj);
-		delete obj;
-	}
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
 void ForgeWindow::slot_cut () {
 	if (!copyToClipboard ())
 		return;
@@ -385,10 +370,8 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 void ForgeWindow::slot_paste () {
-	for (std::size_t i = 0; i < g_Clipboard.size(); ++i) {
-		LDObject* copy = g_Clipboard[i]->makeClone ();
-		g_CurrentFile->addObject (copy);
-	}
+	FOREACH (LDObject, *, obj, g_Clipboard)
+		g_CurrentFile->addObject (obj->makeClone ());
 	
 	refresh ();
 }
@@ -428,7 +411,7 @@
 		LDSubfile* ref = static_cast<LDSubfile*> (obj);
 		
 		// Get the inlined objects. These are clones of the subfile's contents.
-		vector<LDObject*> objs = ref->inlineContents (bDeep, ref->faMatrix,
+		vector<LDObject*> objs = ref->inlineContents (bDeep, ref->mMatrix,
 			ref->vPosition, true);
 		
 		// Merge in the inlined objects
@@ -457,11 +440,7 @@
 void ForgeWindow::slot_splitQuads () {
 	vector<LDObject*> objs = getSelectedObjects ();
 	
-	// Delete the objects that were being selected
-	for (ulong i = 0; i < (ulong)objs.size(); ++i) {
-		LDObject* obj = objs[i];
-		
-		// Don't even consider non-quads
+	FOREACH (LDObject, *, obj, objs) {
 		if (obj->getType() != OBJ_Quad)
 			continue;
 		
@@ -494,15 +473,14 @@
 	
 	std::vector<LDObject*> objs = getSelectedObjects ();
 	
-	// Try to get a consensus on the color used for use as a default.
-	for (ulong i = 0; i < objs.size(); ++i) {
-		LDObject* obj = objs[i];
-		
+	// If all selected objects have the same color, said color is our default
+	// value to the color selection dialog.
+	FOREACH (LDObject, *, obj, objs) {
 		if (obj->dColor == -1)
-			continue; // doesn't use colors
+			continue; // doesn't use color
 		
 		if (dDefault != -1 && obj->dColor != dDefault) {
-			// No unanimosity in object color, therefore we don't have a
+			// No consensus in object color, therefore we don't have a
 			// proper default value to use.
 			dDefault = -1;
 			break;
@@ -512,13 +490,11 @@
 			dDefault = obj->dColor;
 	}
 	
-	// Show the dialog to the user now and ask him for a color.
+	// Show the dialog to the user now and ask for a color.
 	if (ColorSelectDialog::staticDialog (dColor, dDefault, this)) {
-		for (ulong i = 0; i < objs.size(); ++i) {
-			LDObject* obj = objs[i];
+		FOREACH (LDObject, *, obj, objs)
 			if (obj->dColor != -1)
 				obj->dColor = dColor;
-		}
 		
 		refresh ();
 	}
@@ -531,9 +507,7 @@
 	vector<LDObject*> objs = getSelectedObjects ();
 	
 	// Delete the objects that were being selected
-	for (std::size_t i = 0; i < objs.size(); ++i) {
-		LDObject* obj = objs[i];
-		
+	FOREACH (LDObject, *, obj, objs) {
 		if (obj->getType() != OBJ_Quad && obj->getType() != OBJ_Triangle)
 			continue;
 		
@@ -569,6 +543,19 @@
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
+void ForgeWindow::deleteSelection () {
+	vector<LDObject*> objs = getSelectedObjects ();
+	
+	// Delete the objects that were being selected
+	FOREACH (LDObject, *, obj, objs) {
+		g_CurrentFile->forgetObject (obj);
+		delete obj;
+	}
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
 void ForgeWindow::buildObjList () {
 	if (!g_CurrentFile)
 		return;
@@ -652,7 +639,7 @@
 				
 				for (short i = 0; i < 9; ++i)
 					zText.appendformat ("%s%s",
-						ftoa (ref->faMatrix[i]).chars(),
+						ftoa (ref->mMatrix[i]).chars(),
 						(i != 8) ? " " : "");
 				
 				zText += ')';
--- a/ldforge.pro	Sun Mar 24 18:03:33 2013 +0200
+++ b/ldforge.pro	Sun Mar 24 21:41:24 2013 +0200
@@ -21,12 +21,15 @@
 	config.h \
 	cfgdef.h \
 	colors.h \
+	types.h \
 	zz_setContentsDialog.h \
 	zz_configDialog.h \
 	zz_addObjectDialog.h \
 	zz_colorSelectDialog.h \
 
 SOURCES += bbox.cpp \
+	config.cpp \
+	colors.cpp \
 	gldraw.cpp \
 	gui.cpp \
 	file.cpp \
@@ -34,8 +37,7 @@
 	main.cpp \
 	misc.cpp \
 	str.cpp \ 
-	config.cpp \
-	colors.cpp \
+	types.cpp \
 	zz_setContentsDialog.cpp \
 	zz_configDialog.cpp \
 	zz_addObjectDialog.cpp \
--- a/ldtypes.cpp	Sun Mar 24 18:03:33 2013 +0200
+++ b/ldtypes.cpp	Sun Mar 24 21:41:24 2013 +0200
@@ -127,14 +127,13 @@
 	return str::mkfmt ("0 %s", zText.chars ());
 }
 
+#define MATVAL(N) ftoa (mMatrix[N]).chars()
 str LDSubfile::getContents () {
-	str val = str::mkfmt ("1 %d %s ", dColor, vPosition.getStringRep (false).chars ());
-	
-	for (short i = 0; i < 9; ++i)
-		val.appendformat ("%s ", ftoa (faMatrix[i]).chars());
-	
-	val += zFileName;
-	return val;
+	return str::mkfmt ("1 %d %s %s %s %s %s %s %s %s %s %s %s",
+		dColor, vPosition.getStringRep (false).chars (),
+		MATVAL (0), MATVAL (1), MATVAL (2),
+		MATVAL (4), MATVAL (5), MATVAL (6),
+		MATVAL (8), MATVAL (9), MATVAL (10), zFileName.chars());
 }
 
 str LDLine::getContents () {
@@ -216,8 +215,6 @@
 	tri2->vaCoords[1] = vaCoords[2];
 	tri2->vaCoords[2] = vaCoords[3];
 	
-	printf ("triangles: %p %p\n", tri1, tri2);
-	
 	// The triangles also inherit the quad's color
 	tri1->dColor = tri2->dColor = dColor;
 	
@@ -267,7 +264,7 @@
 			{ \
 				LD##T* newobj = static_cast<LD##T*> (obj)->makeClone (); \
 				for (short i = 0; i < N; ++i) \
-					newobj->vaCoords[i].transform (matrix, pos); \
+					newobj->vaCoords[i].transform (mMatrix, pos); \
 				\
 				objs.push_back (newobj); \
 			} \
@@ -277,16 +274,14 @@
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 // =============================================================================
 static uint g_uTabs = 0;
-vector<LDObject*> LDSubfile::inlineContents (bool bDeepInline, double* matrix, vertex pos, bool bCache) {
+vector<LDObject*> LDSubfile::inlineContents (bool bDeepInline, matrix mMatrix, vertex pos, bool bCache) {
 	// If we have this cached, just return that.
 	if (bDeepInline && objCache.size ())
 		return objCache;
 	
 	vector<LDObject*> objs;
 	
-	for (ulong i = 0; i < pFile->objects.size(); ++i) {
-		LDObject* obj = pFile->objects[i];
-		
+	FOREACH (LDObject, *, obj, pFile->objects) {
 		switch (obj->getType()) {
 		case OBJ_Comment:
 		case OBJ_Empty:
@@ -307,27 +302,21 @@
 				// Got another sub-file reference, inline it if we're deep-inlining. If not,
 				// just add it into the objects normally.
 				if (bDeepInline) {
-					double faNewMatrix[9];
-					
-					for (short i = 0; i < 9; ++i)
-						faNewMatrix[i] = matrix[i] * ref->faMatrix[i];
-					
+					matrix mNewMatrix = mMatrix * ref->mMatrix;
 					vertex vNewPos = ref->vPosition;
-					vNewPos.transform (matrix, pos);
+					vNewPos.transform (mMatrix, pos);
 					
 					// Only cache immediate subfiles, this is not one. Yay recursion!
 					g_uTabs++;
-					vector<LDObject*> otherobjs = ref->inlineContents (true, faNewMatrix, vNewPos, false);
+					vector<LDObject*> otherobjs = ref->inlineContents (true, mNewMatrix, vNewPos, false);
 					g_uTabs--;
 					
 					for (ulong i = 0; i < otherobjs.size(); ++i)
 						objs.push_back (otherobjs[i]);
 				} else {
 					LDSubfile* clone = ref->makeClone ();
-					clone->vPosition.transform (matrix, pos);
-					
-					for (short i = 0; i < 9; ++i)
-						clone->faMatrix[i] *= matrix[i];
+					clone->vPosition.transform (mMatrix, pos);
+					clone->mMatrix *= mMatrix;
 					
 					objs.push_back (clone);
 				}
--- a/ldtypes.h	Sun Mar 24 18:03:33 2013 +0200
+++ b/ldtypes.h	Sun Mar 24 21:41:24 2013 +0200
@@ -20,6 +20,7 @@
 #define __LDTYPES_H__
 
 #include "common.h"
+#include "types.h"
 
 #define IMPLEMENT_LDTYPE(N) \
 	LD##N (); \
@@ -151,13 +152,13 @@
 	IMPLEMENT_LDTYPE (Subfile)
 	
 	vertex vPosition; // Position of the subpart
-	double faMatrix[9]; // Transformation matrix for the subpart
+	matrix mMatrix; // Transformation matrix for the subpart
 	str zFileName; // Filename of the subpart
 	OpenFile* pFile; // Pointer to opened file for this subfile. nullptr if unopened.
 	vector<LDObject*> objCache; // Cache of this file's contents, if desired
 	
 	// Gets the inlined contents of this subfile.
-	std::vector<LDObject*> inlineContents (bool bDeepInline, double* matrix,
+	std::vector<LDObject*> inlineContents (bool bDeepInline, matrix mMatrix,
 		vertex pos, bool bCache);
 };
 
--- a/main.cpp	Sun Mar 24 18:03:33 2013 +0200
+++ b/main.cpp	Sun Mar 24 21:41:24 2013 +0200
@@ -23,6 +23,7 @@
 #include "misc.h"
 #include "config.h"
 #include "colors.h"
+#include "types.h"
 
 vector<OpenFile*> g_LoadedFiles;
 OpenFile* g_CurrentFile = nullptr;
@@ -56,34 +57,6 @@
 	return app.exec ();
 }
 
-vertex vertex::midpoint (vertex& other) {
-	vertex mid;
-	mid.x = (x + other.x);
-	mid.y = (y + other.y);
-	mid.z = (z + other.z);
-	return mid;
-}
-
-str vertex::getStringRep (const bool bMangled) {
-	const char* sFormat = (bMangled) ? "(%s, %s, %s)" : "%s %s %s";
-	
-	return str::mkfmt (sFormat,
-		ftoa (x).chars(),
-		ftoa (y).chars(),
-		ftoa (z).chars());
-}
-
-void vertex::transform (double* matrix, vertex pos) {
-	double x2, y2, z2;
-	x2 = (matrix[0] * x) + (matrix[1] * y) + (matrix[2] * z) + pos.x;
-	y2 = (matrix[3] * x) + (matrix[4] * y) + (matrix[5] * z) + pos.y;
-	z2 = (matrix[6] * x) + (matrix[7] * y) + (matrix[8] * z) + pos.z;
-	
-	x = x2;
-	y = y2;
-	z = z2;
-}
-
 // =============================================================================
 // void logVA (logtype_e, const char*, va_list) [static]
 //
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types.cpp	Sun Mar 24 21:41:24 2013 +0200
@@ -0,0 +1,101 @@
+#include <assert.h>
+#include "common.h"
+#include "types.h"
+#include "misc.h"
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+vertex vertex::midpoint (vertex& other) {
+	vertex mid;
+	mid.x = (x + other.x);
+	mid.y = (y + other.y);
+	mid.z = (z + other.z);
+	return mid;
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+str vertex::getStringRep (const bool bMangled) {
+	const char* sFormat = (bMangled) ? "(%s, %s, %s)" : "%s %s %s";
+	
+	return str::mkfmt (sFormat,
+		ftoa (x).chars(),
+		ftoa (y).chars(),
+		ftoa (z).chars());
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+void vertex::transform (matrix mMatrix, vertex pos) {
+	double x2, y2, z2;
+	x2 = (mMatrix[0] * x) + (mMatrix[1] * y) + (mMatrix[2] * z) + pos.x;
+	y2 = (mMatrix[3] * x) + (mMatrix[4] * y) + (mMatrix[5] * z) + pos.y;
+	z2 = (mMatrix[6] * x) + (mMatrix[7] * y) + (mMatrix[8] * z) + pos.z;
+	
+	x = x2;
+	y = y2;
+	z = z2;
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+matrix::matrix (vector<double> vals) {
+	assert (vals.size() == (sizeof faValues / sizeof *faValues));
+	memcpy (&faValues[0], &(*vals.begin ()), sizeof faValues);
+}
+
+// -----------------------------------------------------------------------------
+matrix::matrix (double fVal) {
+	for (short i = 0; i < 9; ++i)
+		faValues[i] = fVal;
+}
+
+// -----------------------------------------------------------------------------
+matrix::matrix (double a, double b, double c, double d, double e, double f,
+	double g, double h, double i)
+{
+	faValues[0] = a; faValues[1] = b; faValues[2] = c;
+	faValues[3] = d; faValues[4] = e; faValues[5] = f;
+	faValues[6] = g; faValues[7] = h; faValues[8] = i;
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+void matrix::zero () {
+	memset (&faValues[0], 0, sizeof faValues);
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+matrix matrix::mult (matrix mOther) {
+	matrix mVal;
+	matrix& mThis = *this;
+	
+	mVal.zero ();
+	
+	// arrrrrrrrrrrgh
+	for (short i = 0; i < 3; ++i)
+	for (short j = 0; j < 3; ++j)
+	for (short k = 0; k < 3; ++k)
+		mVal[(i * 3) + j] += mThis[(i * 3) + k] * mOther[(k * 3) + j];
+	
+	return mVal;
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+void matrix::testOutput () {
+	for (short i = 0; i < 3; ++i) {
+		for (short j = 0; j < 3; ++j)
+			printf ("%*f\t", 10, faValues[(i * 3) + j]);
+		
+		printf ("\n");
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types.h	Sun Mar 24 21:41:24 2013 +0200
@@ -0,0 +1,77 @@
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include "types.h"
+#include "common.h"
+
+class matrix;
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+// vertex
+// 
+// Vertex class. Not to be confused with LDVertex, which is a vertex used in an
+// LDraw code file.
+// =============================================================================
+class vertex {
+public:
+	double x, y, z;
+	
+	vertex () {}
+	vertex (double fX, double fY, double fZ) {
+		x = fX;
+		y = fY;
+		z = fZ;
+	}
+	
+	// =========================================================================
+	// Midpoint between this vertex and another vertex.
+	vertex midpoint (vertex& other);
+	str getStringRep (const bool bMangled);
+	void transform (matrix mMatrix, vertex pos);
+};
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+// matrix
+// 
+// A mathematical 3x3 matrix
+// =============================================================================
+class matrix {
+public:
+	double faValues[9];
+	
+	// Constructors
+	matrix () {}
+	matrix (std::vector<double> vals);
+	matrix (double fVal);
+	matrix (double a, double b, double c,
+		double d, double e, double f,
+		double g, double h, double i);
+	
+	matrix mult (matrix mOther);
+	
+	matrix& operator= (matrix mOther) {
+		memcpy (&faValues[0], &mOther.faValues[0], sizeof faValues);
+		return *this;
+	}
+	
+	matrix operator* (matrix mOther) {
+		return mult (mOther);
+	}
+	
+	matrix& operator*= (matrix mOther) {
+		return operator= (mult (mOther));
+	}
+	
+	inline double& operator[] (const uint uIndex) {
+		return faValues[uIndex];
+	}
+	
+	void zero ();
+	void testOutput ();
+};
+
+#endif // __TYPES_H__
\ No newline at end of file

mercurial