From 9219cee81ce0a163e4a37f854334a2ed95de3ed8 Mon Sep 17 00:00:00 2001 From: Tats Date: Sat, 11 Jan 2014 23:02:52 -0500 Subject: [PATCH] Add save/load of meshes --- MainWindow.cpp | 32 ++++++++++++++++++++++++++++ MainWindow.h | 11 ++++++++++ ProjectReader.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++----- ProjectReader.h | 1 + ProjectWriter.cpp | 29 ++++++++++++++++++------- Shape.cpp | 43 +++++++++++++++++++++++++++++++++++++ Shape.h | 12 +++++++++++ 7 files changed, 169 insertions(+), 13 deletions(-) diff --git a/MainWindow.cpp b/MainWindow.cpp index 2075426..8a3dd07 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -315,6 +315,38 @@ uid MainWindow::createImagePaint(uid paintId, QString uri, float x, float y) } } +uid MainWindow::createMeshTextureMapping(uid mappingId, + uid paintId, + int nColumns, int nRows, + const QList &src, const QList &dst) +{ + // Cannot create element with already existing id or element for which no paint exists. + if (Mapping::getUidAllocator().exists(mappingId) || + !Paint::getUidAllocator().exists(paintId) || + paintId == NULL_UID) + return NULL_UID; + + else + { + Paint::ptr paint = mappingManager->getPaintById(paintId); + int nVertices = nColumns * nRows; + qDebug() << nVertices << " vs " << nColumns << "x" << nRows << " vs " << src.size() << " " << dst.size() << endl; + Q_ASSERT(src.size() == nVertices && dst.size() == nVertices); + + Shape::ptr inputMesh( new Mesh(src, nColumns, nRows)); + Shape::ptr outputMesh(new Mesh(dst, nColumns, nRows)); + + // Add it to the manager. + Mapping::ptr mapping(new TextureMapping(paint, outputMesh, inputMesh, mappingId)); + uid id = mappingManager->addMapping(mapping); + + // Add it to the GUI. + addMappingItem(mappingId); + + // Return the id. + return id; + } +} uid MainWindow::createTriangleTextureMapping(uid mappingId, uid paintId, diff --git a/MainWindow.h b/MainWindow.h index f6c1a32..717cae2 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -86,10 +86,21 @@ private slots: void pollOscInterface(); public slots: + + // CRUD. /** * Create an image paint. */ uid createImagePaint(uid paintId, QString uri, float x, float y); + + /** + * Creates a textured mesh. + */ + uid createMeshTextureMapping(uid mappingId, + uid paintId, + int nColumns, int nRows, + const QList &src, const QList &dst); + /** * Creates a textured triangle. */ diff --git a/ProjectReader.cpp b/ProjectReader.cpp index b3d6af8..a9a71c5 100644 --- a/ProjectReader.cpp +++ b/ProjectReader.cpp @@ -130,6 +130,20 @@ void ProjectReader::parseMapping(const QDomElement& mapping) } else if (mappingAttrType == "mesh_texture") { + // Parse destination mesh. + int nColumns; + int nRows; + _parseMesh(dst, dstPoints, nColumns, nRows); + + // Get / parse source shape. + QDomElement src = mapping.firstChildElement("source"); + QList srcPoints; + _parseMesh(src, srcPoints, nColumns, nRows); + + uid id = _window->createMeshTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), nColumns, nRows, srcPoints, dstPoints); + + if (id == NULL_UID) + _xml.raiseError(QObject::tr("Cannot create mesh texture mapping")); } else @@ -147,14 +161,44 @@ void ProjectReader::_parseTriangle(const QDomElement& triangle, QList& points.clear(); // Add vertices. - QDomNodeList vertices = triangle.childNodes(); - if (vertices.size() != 3) - _xml.raiseError(QObject::tr("Shape has wrong number of vertices.")); + QDomElement vertex = triangle.firstChildElement("vertex"); + while (!vertex.isNull()) + { + points.push_back(_parseVertex(vertex)); + vertex = vertex.nextSiblingElement("vertex"); + } - for (int i=0; i<3; i++) - points.push_back(_parseVertex(vertices.at(i).toElement())); + if (points.size() != 3) + _xml.raiseError(QObject::tr("Shape has wrong number of vertices.")); } +void ProjectReader::_parseMesh(const QDomElement& mesh, QList& points, int& nColumns, int& nRows) +{ + // Check that the element is really a mash. + QString type = mesh.attribute("shape", ""); + if (type != "mesh") + _xml.raiseError(QObject::tr("Wrong shape type for destination: %1.").arg(type)); + + // Reset list of points. + points.clear(); + + // Check columns and rows. + nColumns = mesh.firstChildElement("dimensions").attribute("columns").toInt(); + nRows = mesh.firstChildElement("dimensions").attribute("rows").toInt(); + + // Add vertices. + QDomElement vertex = mesh.firstChildElement("vertex"); + while (!vertex.isNull()) + { + points.push_back(_parseVertex(vertex)); + vertex = vertex.nextSiblingElement("vertex"); + } + + if (points.size() != nColumns*nRows) + _xml.raiseError(QObject::tr("Shape has wrong number of vertices.")); +} + + QPointF ProjectReader::_parseVertex(const QDomElement& vertex) { return QPointF( diff --git a/ProjectReader.h b/ProjectReader.h index f2dc937..2983191 100644 --- a/ProjectReader.h +++ b/ProjectReader.h @@ -38,6 +38,7 @@ private: void parseMapping(const QDomElement& mapping); void _parseTriangle(const QDomElement& triangle, QList& points); + void _parseMesh(const QDomElement& mesh, QList& points, int& nColumns, int& nRows); QPointF _parseVertex(const QDomElement& vertex); // void readPaint(); //Paint *item); diff --git a/ProjectWriter.cpp b/ProjectWriter.cpp index 7faef74..a6ef499 100644 --- a/ProjectWriter.cpp +++ b/ProjectWriter.cpp @@ -84,6 +84,14 @@ void ProjectWriter::writeItem(Paint *item) void ProjectWriter::writeShapeVertices(Shape *shape) { + if (shape->getType() == "mesh") { + Mesh* mesh = (Mesh*) shape; + _xml.writeStartElement("dimensions"); + _xml.writeAttribute("columns", QString::number(mesh->nColumns())); + _xml.writeAttribute("rows", QString::number(mesh->nRows())); + _xml.writeEndElement(); // vertex + } + for (int i = 0; i < shape->nVertices(); i++) { Point *point = shape->getVertex(i); @@ -108,14 +116,19 @@ void ProjectWriter::writeItem(Mapping *item) writeShapeVertices(shape); _xml.writeEndElement(); // shape - // FIXME: check mapping type before casting to TextureMapping - TextureMapping *tex = (TextureMapping *) item; - shape = tex->getInputShape().get(); - _xml.writeStartElement("source"); - _xml.writeAttribute("shape", shape->getType()); - writeShapeVertices(shape); - _xml.writeEndElement(); // shape + if (item->getType().endsWith("_texture")) + { + TextureMapping *tex = (TextureMapping *) item; + shape = tex->getInputShape().get(); - _xml.writeEndElement(); // mapping + _xml.writeStartElement("source"); + _xml.writeAttribute("shape", shape->getType()); + writeShapeVertices(shape); + _xml.writeEndElement(); // shape + + _xml.writeEndElement(); // mapping + } + else + qDebug() << "Unknown type, cannot save: " << item->getType() << endl; } diff --git a/Shape.cpp b/Shape.cpp index af583b3..b571bfe 100644 --- a/Shape.cpp +++ b/Shape.cpp @@ -78,6 +78,26 @@ Mesh::Mesh(QPointF p1, QPointF p2, QPointF p3, QPointF p4, int nColumns, int nRo init(nColumns, nRows); } +Mesh::Mesh(const QList& points, int nColumns, int nRows) +: Quad(), _nColumns(nColumns), _nRows(nRows) +{ + Q_ASSERT(nColumns >= 2 && nRows >= 2); + Q_ASSERT(points.size() == nColumns * nRows); + + // Resize the vertices2d vector to appropriate dimensions. + resizeVertices2d(_vertices2d, _nColumns, _nRows); + + // Just build vertices2d in the standard order. + int k = 0; + for (int x=0; x<_nColumns; x++) + for (int y=0; y<_nRows; y++) + { + vertices.push_back( new Point(points[k].x(), points[k].y()) ); + _vertices2d[x][y] = k; + k++; + } +} + void Mesh::resizeVertices2d(std::vector< std::vector >& vertices2d, int nColumns, int nRows) { vertices2d.resize(nColumns); @@ -163,6 +183,9 @@ void Mesh::addColumn() // Increment number of columns. _nColumns++; + + // Reorder. + _reorderVertices(); } void Mesh::addRow() @@ -213,6 +236,9 @@ void Mesh::addRow() // Increment number of columns. _nRows++; + + // Reorder. + _reorderVertices(); } void Mesh::resize(int nColumns_, int nRows_) @@ -318,4 +344,21 @@ std::vector< std::vector > Mesh::getQuads2d() const return quads2d; } +void Mesh::_reorderVertices() +{ + // Populate new vertices vector. + std::vector newVertices(vertices.size()); + int k = 0; + for (int x=0; x& points, int nColumns, int nRows); virtual ~Mesh() {} virtual QString getType() const { return "mesh"; } @@ -216,6 +217,17 @@ protected: std::vector< std::vector > _vertices2d; // Maps a vertex id to the pair of vertex ids it "splits". std::map > _splitVertices; + + /** + * Reorder vertices in a standard order: + * + * 0----1----2----3 + * | | | | + * 4----5----6----7 + * | | | | + * 8----9---10----11 + */ + void _reorderVertices(); };