Sun, 24 Mar 2013 21:41:24 +0200
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