Fri, 09 Aug 2013 03:09:08 +0300
BIG COMMIT -- Moving from display lists to VAOs.
src/gldata.cpp | file | annotate | diff | comparison | revisions | |
src/gldata.h | file | annotate | diff | comparison | revisions | |
src/gldraw.cpp | file | annotate | diff | comparison | revisions | |
src/gldraw.h | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gldata.cpp Fri Aug 09 03:09:08 2013 +0300 @@ -0,0 +1,341 @@ +#include "gldata.h" +#include "ldtypes.h" +#include "colors.h" +#include "file.h" +#include "misc.h" +#include "gldraw.h" + +cfg (bool, gl_blackedges, true); + +// ============================================================================= +// ----------------------------------------------------------------------------- +VertexCompiler::Array::Array() : + m_data (null) +{ + clear(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +VertexCompiler::Array::~Array() { + delete[] m_data; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::Array::clear() { + delete[] m_data; + + m_data = new DataType[64]; + m_size = 64; + m_ptr = &m_data[0]; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::Array::resizeToFit ( + VertexCompiler::Array::SizeType newSize +) { + if (allocatedSize() >= newSize) + return; + + int32 cachedWriteSize = writtenSize(); + + // Add some lee-way space to reduce the amount of resizing. + newSize += 256; + + const SizeType oldSize = allocatedSize(); + + // We need to back up the data first + DataType* copy = new DataType[oldSize]; + memcpy (copy, m_data, oldSize); + + // Re-create the buffer + delete[] m_data; + m_data = new DataType[newSize]; + m_size = newSize; + m_ptr = &m_data[cachedWriteSize / sizeof (DataType)]; + + // Copy the data back + memcpy (m_data, copy, oldSize); + delete[] copy; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +const VertexCompiler::Array::DataType* VertexCompiler::Array::data() const { + return m_data; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +const VertexCompiler::Array::SizeType& VertexCompiler::Array::allocatedSize() const { + return m_size; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +VertexCompiler::Array::SizeType VertexCompiler::Array::writtenSize() const { + return (m_ptr - m_data) * sizeof (DataType); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::Array::write ( + VertexCompiler::Array::DataType f +) { + // Ensure there's enoughspace for the new float + resizeToFit (writtenSize() + sizeof f); + + // Write the float in + *m_ptr++ = f; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::Array::merge ( + Array* other +) { + // Ensure there's room for both buffers + resizeToFit (writtenSize() + other->writtenSize()); + + memcpy (m_ptr, other->data(), other->writtenSize()); + m_ptr += other->writtenSize() / sizeof (DataType); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +VertexCompiler::VertexCompiler() : + m_file (null) +{ + for (int i = 0; i < NumArrays; ++i) { + m_mainArrays[i] = new Array; + m_changed[i] = false; + } +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +VertexCompiler::~VertexCompiler() { + for (Array* array : m_mainArrays) + delete array; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::compileVertex ( + vertex v, + QColor col, + Array* array +) { + VertexCompiler::Vertex glvertex; + glvertex.x = v.x(); + glvertex.y = v.y(); + glvertex.z = v.z(); + glvertex.color = + (col.red() & 0xFF) << 0x00 | + (col.green() & 0xFF) << 0x08 | + (col.blue() & 0xFF) << 0x10 | + (col.alpha() & 0xFF) << 0x18; + + array->write (glvertex); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::compilePolygon ( + LDObject* obj, + VertexCompiler::Array** arrays +) { + LDObject::Type objtype = obj->getType(); + bool isline = (objtype == LDObject::Line || objtype == LDObject::CondLine); + int verts = isline ? 2 : obj->vertices(); + + for (int i = 0; i < verts; ++i) { + compileVertex (obj->getVertex (i), getObjectColor (obj, Normal), + arrays[isline ? EdgeArray : MainArray]); + } + + // For non-lines, compile BFC data + if (!isline) { + QColor col = getObjectColor (obj, BFCFront); + for (int i = 0; i < verts; ++i) + compileVertex (obj->getVertex(i), col, arrays[BFCArray]); + + col = getObjectColor (obj, BFCBack); + for (int i = verts - 1; i >= 0; --i) + compileVertex (obj->getVertex(i), col, arrays[BFCArray]); + } +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::compileObject ( + LDObject* obj +) { + if (m_objArrays.find (obj) == m_objArrays.end()) { + m_objArrays[obj] = new Array*[NumArrays]; + + for (int i = 0; i < NumArrays; ++i) + m_objArrays[obj][i] = new Array; + } else { + for (int i = 0; i < NumArrays; ++i) + m_objArrays[obj][i]->clear(); + } + + switch (obj->getType()) { + case LDObject::Triangle: + compilePolygon (obj, m_objArrays[obj]); + m_changed[MainArray] = true; + break; + + case LDObject::Quad: + for (LDTriangleObject* triangle : static_cast<LDQuadObject*> (obj)->splitToTriangles()) + compilePolygon (triangle, m_objArrays[obj]); + m_changed[MainArray] = true; + break; + + case LDObject::Line: + compilePolygon (obj, m_objArrays[obj]); + break; + + default: + break; + } +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::compileFile() { + for (LDObject* obj : *m_file) + compileObject (obj); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::forgetObject ( + LDObject* obj +) { + for (int i = 0; i < NumArrays; ++i) + delete m_objArrays[obj][i]; + + delete m_objArrays[obj]; + m_objArrays.remove (obj); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void VertexCompiler::setFile ( + LDFile* file +) { + m_file = file; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +VertexCompiler::Array* VertexCompiler::getMergedBuffer ( + VertexCompiler::MergedArrayType type +) { + assert (type < NumArrays); + + if (m_changed) { + m_changed[type] = false; + m_mainArrays[type]->clear(); + + for (LDObject* obj : *m_file) { + auto it = m_objArrays.find (obj); + + if (it != m_objArrays.end()) + m_mainArrays[type]->merge ((*it)[type]); + } + } + + return m_mainArrays[type]; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +static List<short> g_warnedColors; +QColor VertexCompiler::getObjectColor ( + LDObject* obj, + ColorType colotype +) const { + QColor qcol; + + if (!obj->isColored()) + return QColor(); + +/* + 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()->id(); + + // 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 / (256 * 256)) % 256, + g = (i / 256) % 256, + b = i % 256; + + qglColor (QColor (r, g, b)); + return; + } +*/ + + if ((colotype == BFCFront || colotype == BFCBack) && + obj->getType() != LDObject::Line && + obj->getType() != LDObject::CondLine) { + + if (colotype == BFCFront) + qcol = QColor (40, 192, 0); + else + qcol = QColor (224, 0, 0); + } else { + if (obj->color() == maincolor) + qcol = GL::getMainColor(); + else { + LDColor* col = getColor (obj->color()); + + if (col) + qcol = col->faceColor; + } + + if (obj->color() == edgecolor) { + qcol = QColor (32, 32, 32); // luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black; + LDColor* col; + + if (!gl_blackedges && obj->parent() && (col = getColor (obj->parent()->color()))) + 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->color() != edgecolor) + qcol = GL::getMainColor(); + + // Warn about the unknown colors, but only once. + for (short i : g_warnedColors) + if (obj->color() == i) + return Qt::black; + + print ("%1: Unknown color %2!\n", __func__, obj->color()); + g_warnedColors << obj->color(); + return Qt::black; + } + } + + if (obj->topLevelParent()->selected()) { + // Brighten it up for the select list. + const uchar 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; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gldata.h Fri Aug 09 03:09:08 2013 +0300 @@ -0,0 +1,74 @@ +#ifndef LDFORGE_GLDATA_H +#define LDFORGE_GLDATA_H + +#include "types.h" +#include <QMap> + +class QColor; +class LDFile; + +class VertexCompiler { +public: + enum ColorType { + Normal, + BFCFront, + BFCBack, + }; + + enum MergedArrayType { + MainArray, + EdgeArray, + BFCArray, + NumArrays + }; + + struct Vertex { + float x, y, z; + uint32 color; + float pad[4]; + }; + + class Array { + public: + typedef int32 SizeType; + typedef Vertex DataType; + + Array(); + Array (const Array& other) = delete; + ~Array(); + + void clear(); + void merge (Array* other); + void resizeToFit (SizeType newSize); + const SizeType& allocatedSize() const; + SizeType writtenSize() const; + const DataType* data() const; + void write (DataType f); + Array& operator= (const Array& other) = delete; + + private: + DataType* m_data; + DataType* m_ptr; + SizeType m_size; + }; + + VertexCompiler(); + ~VertexCompiler(); + void setFile (LDFile* file); + void compileFile(); + void compileObject (LDObject* obj); + void forgetObject (LDObject* obj); + Array* getMergedBuffer (MergedArrayType type); + QColor getObjectColor (LDObject* obj, ColorType list) const; + +private: + void compilePolygon (LDObject* obj, Array** arrays); + void compileVertex (vertex v, QColor col, VertexCompiler::Array* array); + + QMap<LDObject*, Array**> m_objArrays; + Array* m_mainArrays[NumArrays]; + LDFile* m_file; + bool m_changed[NumArrays]; +}; + +#endif // LDFORGE_GLDATA_H \ No newline at end of file
--- a/src/gldraw.cpp Wed Aug 07 20:50:53 2013 +0300 +++ b/src/gldraw.cpp Fri Aug 09 03:09:08 2013 +0300 @@ -21,10 +21,9 @@ #include <QMouseEvent> #include <QContextMenuEvent> #include <QInputDialog> -#include <qtooltip.h> +#include <QToolTip> #include <QTimer> #include <GL/glu.h> - #include "common.h" #include "config.h" #include "file.h" @@ -36,6 +35,8 @@ #include "dialogs.h" #include "addObjectDialog.h" #include "messagelog.h" +#include "gldata.h" +#include "build/moc_gldraw.cpp" static const struct staticCameraMeta { const char glrotate[3]; @@ -56,19 +57,18 @@ cfg (int, gl_linethickness, 2); cfg (bool, gl_colorbfc, true); cfg (int, gl_camera, GLRenderer::Free); -cfg (bool, gl_blackedges, true); cfg (bool, gl_axes, false); cfg (bool, gl_wireframe, false); // argh const char* g_CameraNames[7] = { - QT_TRANSLATE_NOOP ("GLRenderer", "Top"), - QT_TRANSLATE_NOOP ("GLRenderer", "Front"), - QT_TRANSLATE_NOOP ("GLRenderer", "Left"), - QT_TRANSLATE_NOOP ("GLRenderer", "Bottom"), - QT_TRANSLATE_NOOP ("GLRenderer", "Back"), - QT_TRANSLATE_NOOP ("GLRenderer", "Right"), - QT_TRANSLATE_NOOP ("GLRenderer", "Free") + QT_TRANSLATE_NOOP ("GLRenderer", "Top"), + QT_TRANSLATE_NOOP ("GLRenderer", "Front"), + QT_TRANSLATE_NOOP ("GLRenderer", "Left"), + QT_TRANSLATE_NOOP ("GLRenderer", "Bottom"), + QT_TRANSLATE_NOOP ("GLRenderer", "Back"), + QT_TRANSLATE_NOOP ("GLRenderer", "Right"), + QT_TRANSLATE_NOOP ("GLRenderer", "Free") }; const GL::Camera g_Cameras[7] = { @@ -86,10 +86,13 @@ const vertex vert; } g_GLAxes[3] = { { QColor (255, 0, 0), vertex (10000, 0, 0) }, - { QColor (80, 192, 0), vertex (0, 10000, 0) }, + { QColor (80, 192, 0), vertex (0, 10000, 0) }, { QColor (0, 160, 192), vertex (0, 0, 10000) }, }; - + +#warning this should be a member +static VertexCompiler g_vertexCompiler; + // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= @@ -190,7 +193,8 @@ setAutoFillBackground (false); setMouseTracking (true); setFocusPolicy (Qt::WheelFocus); - compileAllObjects(); + + g_vertexCompiler.compileFile(); } // ============================================================================= @@ -223,98 +227,6 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -static List<short> g_warnedColors; -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()->id(); - - // 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 / (256 * 256)) % 256, - g = (i / 256) % 256, - b = i % 256; - - qglColor (QColor (r, g, b)); - return; - } - - if ((list == BFCFrontList || list == BFCBackList) && - obj->getType() != LDObject::Line && - obj->getType() != LDObject::CondLine) { - - if (list == GL::BFCFrontList) - qcol = QColor (40, 192, 0); - else - qcol = QColor (224, 0, 0); - } else { - if (obj->color() == maincolor) - qcol = getMainColor(); - else { - LDColor* col = getColor (obj->color()); - - if (col) - qcol = col->faceColor; - } - - if (obj->color() == edgecolor) { - qcol = luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black; - LDColor* col; - - if (!gl_blackedges && obj->parent() && (col = getColor (obj->parent()->color()))) - 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->color() != edgecolor) - qcol = getMainColor(); - - // Warn about the unknown colors, but only once. - for (short i : g_warnedColors) - if (obj->color() == i) - return; - - printf ("%s: Unknown color %d!\n", __func__, obj->color()); - g_warnedColors << obj->color(); - return; - } - } - - long r = qcol.red(), - g = qcol.green(), - b = qcol.blue(), - a = qcol.alpha(); - - if (obj->topLevelParent()->selected()) { - // Brighten it up for the select list. - const uchar add = 51; - - r = min (r + add, 255l); - g = min (g + add, 255l); - b = min (b + add, 255l); - } - - glColor4f ( - ((double) r) / 255.0f, - ((double) g) / 255.0f, - ((double) b) / 255.0f, - ((double) a) / 255.0f); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= void GLRenderer::refresh() { update(); swapBuffers(); @@ -322,7 +234,7 @@ // ============================================================================= void GLRenderer::hardRefresh() { - compileAllObjects(); + g_vertexCompiler.compileFile(); refresh(); glLineWidth (gl_linethickness); @@ -385,32 +297,28 @@ const GL::ListType list = (!drawOnly() && m_picking) ? PickList : NormalList; - if (gl_colorbfc && !m_picking && !drawOnly()) { + // Draw the polygons + glEnableClientState (GL_VERTEX_ARRAY); + glEnableClientState (GL_COLOR_ARRAY); + glDisableClientState (GL_NORMAL_ARRAY); + + if (gl_colorbfc) { glEnable (GL_CULL_FACE); - - for (LDObject* obj : file()->objs()) { - if (obj->hidden()) - continue; - - glCullFace (GL_BACK); - glCallList (obj->glLists[BFCFrontList]); - - glCullFace (GL_FRONT); - glCallList (obj->glLists[BFCBackList]); - } - + glCullFace (GL_CCW); + } else glDisable (GL_CULL_FACE); - } else { - for (LDObject* obj : file()->objs()) { - if (obj->hidden()) - continue; - - glCallList (obj->glLists[list]); - } - } - if (gl_axes && !m_picking && !drawOnly()) - glCallList (m_axeslist); + VertexCompiler::Array* array = g_vertexCompiler.getMergedBuffer ( + (gl_colorbfc) ? VertexCompiler::BFCArray : VertexCompiler::MainArray); + glVertexPointer (3, GL_FLOAT, sizeof (VertexCompiler::Vertex), &array->data()[0].x); + glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (VertexCompiler::Vertex), &array->data()[0].color); + glDrawArrays (GL_TRIANGLES, 0, array->writtenSize() / sizeof (VertexCompiler::Vertex)); + + // Draw edge lines + array = g_vertexCompiler.getMergedBuffer (VertexCompiler::EdgeArray); + glVertexPointer (3, GL_FLOAT, sizeof (VertexCompiler::Vertex), &array->data()[0].x); + glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (VertexCompiler::Vertex), &array->data()[0].color); + glDrawArrays (GL_LINES, 0, array->writtenSize() / sizeof (VertexCompiler::Vertex)); glPopMatrix(); glMatrixMode (GL_MODELVIEW); @@ -664,114 +572,7 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void GLRenderer::compileAllObjects() { - if (!file()) - return; - - m_knownVerts.clear(); - - for (LDObject* obj : file()->objs()) - compileObject (obj); - - // Compile axes - glDeleteLists (m_axeslist, 1); - m_axeslist = glGenLists (1); - glNewList (m_axeslist, GL_COMPILE); - glBegin (GL_LINES); - - for (const GLAxis& ax : g_GLAxes) { - qglColor (ax.col); - compileVertex (ax.vert); - compileVertex (-ax.vert); - } - - glEnd(); - glEndList(); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -static bool g_glInvert = false; - -void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) { - glBegin (gltype); - - const short numverts = (obj->getType() != LDObject::CondLine) ? obj->vertices() : 2; - - if (g_glInvert == false) - for (short i = 0; i < numverts; ++i) - compileVertex (obj->m_coords[i]); - else - for (short i = numverts - 1; i >= 0; --i) - compileVertex (obj->m_coords[i]); - - glEnd(); -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void GLRenderer::compileList (LDObject* obj, const GLRenderer::ListType list) { - setObjectColor (obj, list); - - switch (obj->getType()) { - case LDObject::Line: - compileSubObject (obj, GL_LINES); - break; - - case LDObject::CondLine: - // 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::Triangle: - compileSubObject (obj, GL_TRIANGLES); - break; - - case LDObject::Quad: - compileSubObject (obj, GL_QUADS); - break; - - case LDObject::Subfile: { - LDSubfileObject* ref = static_cast<LDSubfileObject*> (obj); - List<LDObject*> objs = ref->inlineContents (true, true); - - bool oldinvert = g_glInvert; - - if (ref->transform().determinant() < 0) - g_glInvert = !g_glInvert; - - LDObject* prev = ref->prev(); - if (prev && prev->getType() == LDObject::BFC && static_cast<LDBFCObject*> (prev)->type == LDBFCObject::InvertNext) - g_glInvert = !g_glInvert; - - for (LDObject* obj : objs) { - compileList (obj, list); - delete obj; - } - - g_glInvert = oldinvert; - } - break; - - default: - break; - } -} - -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= -void GLRenderer::compileVertex (const vertex& vrt) { - glVertex3d (vrt[X], -vrt[Y], -vrt[Z]); + g_vertexCompiler.compileFile(); } // ============================================================================= @@ -1184,6 +985,7 @@ SET_ACCESSOR (LDFile*, GLRenderer::setFile) { m_file = val; + g_vertexCompiler.setFile (val); if (val != null) overlaysFromObjects(); @@ -1270,26 +1072,7 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void GLRenderer::compileObject (LDObject* obj) { - deleteLists (obj); - - for (const GL::ListType listType : g_glListTypes) { - if (drawOnly() && listType != GL::NormalList) - continue; - - GLuint list = glGenLists (1); - glNewList (list, GL_COMPILE); - - obj->glLists[listType] = list; - compileList (obj, listType); - - glEndList(); - } - - // Mark in known vertices of this object - List<vertex> verts = getVertices (obj); - m_knownVerts << verts; - m_knownVerts.makeUnique(); - + g_vertexCompiler.compileObject (obj); obj->m_glinit = true; } @@ -1658,6 +1441,4 @@ if (g_win->R() == this) g_win->refresh(); -} - -#include "build/moc_gldraw.cpp" \ No newline at end of file +} \ No newline at end of file
--- a/src/gldraw.h Wed Aug 07 20:50:53 2013 +0300 +++ b/src/gldraw.h Fri Aug 09 03:09:08 2013 +0300 @@ -79,7 +79,7 @@ double depthValue() const; void drawGLScene(); void endDraw (bool accept); - QColor getMainColor(); + static QColor getMainColor(); overlayMeta& getOverlay (int newcam); void hardRefresh(); void initGLData(); @@ -145,15 +145,11 @@ void addDrawnVertex (vertex m_hoverpos); void calcCameraIcons(); // Compute geometry for camera icons void clampAngle (double& angle) const; // Clamps an angle to [0, 360] - void compileList (LDObject* obj, const ListType list); // Compile one of the lists of an object - void compileSubObject (LDObject* obj, const GLenum gltype); // Sub-routine for object compiling - void compileVertex (const vertex& vrt); // Compile a single vertex to a list vertex coordconv2_3 (const QPoint& pos2d, bool snap) const; // Convert a 2D point to a 3D point QPoint coordconv3_2 (const vertex& pos3d) const; // Convert a 3D point to a 2D point LDOverlayObject* findOverlayObject (Camera cam); void updateRectVerts(); void pick (uint mouseX, uint mouseY); // Perform object selection - void setObjectColor (LDObject* obj, const ListType list); // Set the color to an object list private slots: void slot_toolTipTimer();