--- a/src/gldata.cpp Mon Jan 20 15:04:26 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,471 +0,0 @@ -#include "gldata.h" -#include "ldtypes.h" -#include "colors.h" -#include "file.h" -#include "misc.h" -#include "gldraw.h" -#include <QDate> - -#define DEBUG(...) fprint (stdout, __VA_ARGS__) - -cfg (Bool, gl_blackedges, false); -static QList<short> g_warnedColors; -VertexCompiler g_vertexCompiler; - -// ============================================================================= -// ----------------------------------------------------------------------------- -VertexCompiler::Array::Array() : - m_data (null) -{ - clear(); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -VertexCompiler::Array::~Array() -{ delete[] m_data; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::Array::clear() -{ delete[] m_data; - - m_data = new Vertex[64]; - m_size = 64; - m_ptr = &m_data[0]; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::Array::resizeToFit (Size newSize) -{ if (allocatedSize() >= newSize) - return; - - int32 cachedWriteSize = writtenSize(); - - // Add some lee-way space to reduce the amount of resizing. - newSize += 256; - - const Size oldSize = allocatedSize(); - - // We need to back up the data first - Vertex* copy = new Vertex[oldSize]; - memcpy (copy, m_data, oldSize); - - // Re-create the buffer - delete[] m_data; - m_data = new Vertex[newSize]; - m_size = newSize; - m_ptr = &m_data[cachedWriteSize / sizeof (Vertex)]; - - // Copy the data back - memcpy (m_data, copy, oldSize); - delete[] copy; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -const VertexCompiler::Vertex* VertexCompiler::Array::data() const -{ return m_data; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -const VertexCompiler::Array::Size& VertexCompiler::Array::allocatedSize() const -{ return m_size; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -VertexCompiler::Array::Size VertexCompiler::Array::writtenSize() const -{ return (m_ptr - m_data) * sizeof (Vertex); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::Array::write (const Vertex& f) -{ // Ensure there's enoughspace for the new vertex - 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 (Vertex); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -VertexCompiler::VertexCompiler() : - m_file (null) -{ needMerge(); -} - -VertexCompiler::~VertexCompiler() {} - -// ============================================================================= -// 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 VertexCompiler::compilePolygon (LDObject* drawobj, LDObject* trueobj, QList< VertexCompiler::CompiledTriangle >& data) -{ const QColor pickColor = getObjectColor (trueobj, PickColor); - LDObject::Type type = drawobj->getType(); - QList<LDObject*> objs; - - assert (type != LDObject::Subfile); - - if (type == LDObject::Quad) - { 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::Line || objtype == LDObject::CndLine); - const int verts = isline ? 2 : obj->vertices(); - QColor normalColor = getObjectColor (obj, Normal); - - assert (isline || objtype == LDObject::Triangle); - - CompiledTriangle a; - a.rgb = normalColor.rgb(); - a.pickrgb = pickColor.rgb(); - a.numVerts = verts; - a.obj = trueobj; - a.isCondLine = (objtype == LDObject::CndLine); - - 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 VertexCompiler::compileObject (LDObject* obj) -{ initObject (obj); - QList<CompiledTriangle> data; - QTime t0; - - for (int i = 0; i < GL::NumArrays; ++i) - m_objArrays[obj][i].clear(); - - t0 = QTime::currentTime(); - compileSubObject (obj, obj, data); - DEBUG ("COMPILATION: %1ms\n", t0.msecsTo (QTime::currentTime())); - - t0 = QTime::currentTime(); - - for (int i = 0; i < GL::NumArrays; ++i) - { GL::VAOType type = (GL::VAOType) i; - const bool islinearray = (type == GL::EdgeArray || type == GL::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. - if (type != GL::EdgePickArray && type != GL::CondEdgeArray) - continue; - } - else - { // Lines and only lines go to the line array and only to the line array. - if ( (poly.numVerts == 2) ^ islinearray) - continue; - - // Only conditional lines go into the conditional line array - if (type == GL::CondEdgeArray) - continue; - } - - Array* verts = postprocess (poly, type); - m_objArrays[obj][type].merge (verts); - delete verts; - } - } - - DEBUG ("POST-PROCESS: %1ms\n", t0.msecsTo (QTime::currentTime())); - - needMerge(); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::compileSubObject (LDObject* obj, LDObject* topobj, QList< VertexCompiler::CompiledTriangle >& data) -{ QList<LDObject*> objs; - - switch (obj->getType()) - { case LDObject::Triangle: - case LDObject::Line: - case LDObject::CndLine: - { compilePolygon (obj, topobj, data); - } break; - - case LDObject::Quad: - { for (LDTriangle * triangle : static_cast<LDQuad*> (obj)->splitToTriangles()) - compilePolygon (triangle, topobj, data); - } break; - - case LDObject::Subfile: - { QTime t0 = QTime::currentTime(); - objs = static_cast<LDSubfile*> (obj)->inlineContents (LDSubfile::RendererInline | LDSubfile::DeepCacheInline); - DEBUG ("\t- INLINE: %1ms\n", t0.msecsTo (QTime::currentTime())); - DEBUG ("\t- %1 objects\n", objs.size()); - - t0 = QTime::currentTime(); - - for (LDObject* obj : objs) - { compileSubObject (obj, topobj, data); - delete obj; - } - - DEBUG ("\t- SUB-COMPILATION: %1ms\n", t0.msecsTo (QTime::currentTime())); - } break; - - default: - {} break; - } -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::compileFile() -{ for (LDObject * obj : m_file->objects()) - compileObject (obj); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::forgetObject (LDObject* obj) -{ auto it = m_objArrays.find (obj); - - if (it != m_objArrays.end()) - delete *it; - - m_objArrays.remove (obj); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::setFile (LDFile* file) -{ m_file = file; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -const VertexCompiler::Array* VertexCompiler::getMergedBuffer (GL::VAOType 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 < GL::NumArrays); - - if (m_changed[type]) - { m_changed[type] = false; - m_mainArrays[type].clear(); - - for (LDObject* obj : m_file->objects()) - { if (!obj->isScemantic()) - continue; - - auto it = m_objArrays.find (obj); - - if (it != m_objArrays.end()) - m_mainArrays[type].merge (& (*it) [type]); - } - - DEBUG ("merged array %1: %2 bytes\n", (int) type, m_mainArrays[type].writtenSize()); - } - - return &m_mainArrays[type]; -} - -// ============================================================================= -// This turns a compiled triangle into usable VAO vertices -// ----------------------------------------------------------------------------- -VertexCompiler::Array* VertexCompiler::postprocess (const CompiledTriangle& triangle, GL::VAOType type) -{ Array* va = new Array; - QList<Vertex> verts; - - for (int i = 0; i < triangle.numVerts; ++i) - { alias v0 = triangle.verts[i]; - Vertex v; - v.x = v0.x(); - v.y = v0.y(); - v.z = v0.z(); - - switch (type) - { case GL::MainArray: - case GL::EdgeArray: - case GL::CondEdgeArray: - { v.color = triangle.rgb; - } break; - - case GL::PickArray: - case GL::EdgePickArray: - { v.color = triangle.pickrgb; - } break; - - case GL::BFCArray: - case GL::NumArrays: - break; // handled separately - } - - verts << v; - } - - if (type == GL::BFCArray) - { int32 rgb = getObjectColor (triangle.obj, BFCFront).rgb(); - - for (Vertex v : verts) - { v.color = rgb; - va->write (v); - } - - rgb = getObjectColor (triangle.obj, BFCBack).rgb(); - - for (int i = verts.size() - 1; i >= 0; --i) - { Vertex v = verts[i]; - v.color = rgb; - va->write (v); - } - } - else - { for (Vertex v : verts) - va->write (v); - } - - return va; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -uint32 VertexCompiler::getColorRGB (QColor& color) -{ return - (color.red() & 0xFF) << 0x00 | - (color.green() & 0xFF) << 0x08 | - (color.blue() & 0xFF) << 0x10 | - (color.alpha() & 0xFF) << 0x18; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -QColor VertexCompiler::getObjectColor (LDObject* obj, ColorType colotype) const -{ QColor qcol; - - if (!obj->isColored()) - return QColor(); - - if (colotype == PickColor) - { // Make the color by the object's ID if we're picking, so we can make the - // ID again from the color we get from the picking results. Be sure to use - // the top level parent's index since we want a subfile's children point - // to the subfile itself. - long i = obj->topLevelParent()->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. - int r = (i / (256 * 256)) % 256, - g = (i / 256) % 256, - b = i % 256; - - return QColor (r, g, b); - } - - if ((colotype == BFCFront || colotype == BFCBack) && - obj->getType() != LDObject::Line && - obj->getType() != LDObject::CndLine - ) - { 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(); - else - qcol = Qt::black; - - // Warn about the unknown color, but only once. - for (short i : g_warnedColors) - if (obj->color() == i) - return qcol; - - log ("%1: Unknown color %2!\n", __func__, obj->color()); - g_warnedColors << obj->color(); - return qcol; - } - } - - if (obj->topLevelParent()->selected()) - { // Brighten it up if selected. - const int add = 51; - - qcol.setRed (min (qcol.red() + add, 255)); - qcol.setGreen (min (qcol.green() + add, 255)); - qcol.setBlue (min (qcol.blue() + add, 255)); - } - - return qcol; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::needMerge() -{ // Set all of m_changed to true - memset (m_changed, 0xFF, sizeof m_changed); -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::initObject (LDObject* obj) -{ if (m_objArrays.find (obj) == m_objArrays.end()) - m_objArrays[obj] = new Array[GL::NumArrays]; -} - -// ============================================================================= -// ----------------------------------------------------------------------------- -void VertexCompiler::stageForCompilation (LDObject* obj) -{ m_staged << obj; - removeDuplicates (m_staged); -}