diff --git a/apps/sample-gui/image_editor/ImageViewWidget.cpp b/apps/sample-gui/image_editor/ImageViewWidget.cpp index 87d081e..1bc24c8 100644 --- a/apps/sample-gui/image_editor/ImageViewWidget.cpp +++ b/apps/sample-gui/image_editor/ImageViewWidget.cpp @@ -19,7 +19,6 @@ void ImageViewWidget::doPaint(const PaintEvent* event) if (!mGridNode) { - std::cout << "Setting up grid node" << std::endl; mGridNode = std::make_unique(mLocation); mGridNode->setName(mName + "_GridNode"); mGridNode->setNumX(mNumX); @@ -27,6 +26,21 @@ void ImageViewWidget::doPaint(const PaintEvent* event) mGridNode->setWidth(mSize.mWidth); mGridNode->setHeight(mSize.mHeight); + + mGridNode->setStrokeColor(mBorderColor); + mRootNode->addChild(mGridNode.get()); } + + if (mTransformDirty) + { + mGridNode->setLocation(mLocation); + mGridNode->setWidth(mSize.mWidth); + mGridNode->setHeight(mSize.mHeight); + } + + if (mMaterialDirty) + { + mGridNode->setFillColor(mBorderColor); + } } diff --git a/src/geometry/CMakeLists.txt b/src/geometry/CMakeLists.txt index 216756d..4140dab 100644 --- a/src/geometry/CMakeLists.txt +++ b/src/geometry/CMakeLists.txt @@ -17,7 +17,8 @@ list(APPEND geometry_LIB_INCLUDES Rectangle.h Rectangle.cpp Triangle.h - Triangle.cpp) + Triangle.cpp + Transform.cpp) # add the library diff --git a/src/geometry/Point.h b/src/geometry/Point.h index ad4af1f..60bdb98 100644 --- a/src/geometry/Point.h +++ b/src/geometry/Point.h @@ -33,10 +33,18 @@ public: double getDeltaY(const Point& point) const; - void scale(double x, double y) + void scale(double x, double y, double z = 1.0) { mX = x*mX; mY = y*mY; + mZ = z*mZ; + } + + void translate(double x, double y, double z = 0.0) + { + mX += x; + mY += y; + mZ += z; } bool operator==(const Point& rhs) const diff --git a/src/visual_elements/Transform.cpp b/src/geometry/Transform.cpp similarity index 100% rename from src/visual_elements/Transform.cpp rename to src/geometry/Transform.cpp diff --git a/src/visual_elements/Transform.h b/src/geometry/Transform.h similarity index 100% rename from src/visual_elements/Transform.h rename to src/geometry/Transform.h diff --git a/src/graphics/opengl/OpenGlMeshPainter.cpp b/src/graphics/opengl/OpenGlMeshPainter.cpp index 9fde8a3..93833a2 100644 --- a/src/graphics/opengl/OpenGlMeshPainter.cpp +++ b/src/graphics/opengl/OpenGlMeshPainter.cpp @@ -3,7 +3,9 @@ #include "DrawingContext.h" #include "DrawingSurface.h" #include "SceneModel.h" + #include "TriMesh.h" +#include "LineMesh.h" #include "OpenGlShaderProgram.h" @@ -43,7 +45,7 @@ void OpenGlMeshPainter::initializeBuffers() glGenVertexArrays(1, &mVertexArray); } -void OpenGlMeshPainter::paint(const std::vector& verts, const std::vector& elements, const std::vector& color) +void OpenGlMeshPainter::paint(const std::vector& verts, const std::vector& elements, const std::vector& color, bool lines) { glBindVertexArray(mVertexArray); @@ -66,7 +68,15 @@ void OpenGlMeshPainter::paint(const std::vector& verts, const std::vector glUniform4f(vertexColorLocation, float(color[0]), float(color[1]), float(color[2]), float(color[3])); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + + if (lines) + { + glDrawElements(GL_LINES, elements.size(), GL_UNSIGNED_INT, 0); + } + else + { + glDrawElements( GL_TRIANGLES, elements.size(), GL_UNSIGNED_INT, 0); + } glBindVertexArray(0); } @@ -86,19 +96,14 @@ void OpenGlMeshPainter::paint(SceneModel* model, DrawingContext* context) const auto width = float(surface->getWidth()); const auto height = float(surface->getHeight()); - auto mesh = dynamic_cast(model->getMesh()); - std::cout << "Paint mesh for model " << model->getName() << std::endl; - auto transform = model->getTransform(); - - auto vertices = mesh->getVerticesFlat(); + auto vertices = model->getMesh()->getVerticesFlat(); for (std::size_t idx = 0; idxgetFaceNodeIds(); + std::vector indices; + const bool line_mesh = model->getMesh()->getType() == AbstractMesh::MeshType::LINE; + if (line_mesh) + { + indices = dynamic_cast(model->getMesh())->getEdgeNodeIds(); + } + else + { + indices = dynamic_cast(model->getMesh())->getFaceNodeIds(); + } auto model_color = model->getColor().getAsVectorDouble(); - std::cout << "Color is " << model_color[0] << "|" << model_color[0] << std::endl; std::vector color = {float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3])}; - paint(vertices, indices, color); + paint(vertices, indices, color, line_mesh); } diff --git a/src/graphics/opengl/OpenGlMeshPainter.h b/src/graphics/opengl/OpenGlMeshPainter.h index d3cf7d7..92521b3 100644 --- a/src/graphics/opengl/OpenGlMeshPainter.h +++ b/src/graphics/opengl/OpenGlMeshPainter.h @@ -18,7 +18,7 @@ private: void initializeShader(); void initializeBuffers(); - void paint(const std::vector& verts, const std::vector& elements, const std::vector& color); + void paint(const std::vector& verts, const std::vector& elements, const std::vector& color, bool lines = false); unsigned mVertexBuffer{0}; unsigned mElementBuffer{0}; diff --git a/src/mesh/AbstractMesh.cpp b/src/mesh/AbstractMesh.cpp index 30d2676..b9340f0 100644 --- a/src/mesh/AbstractMesh.cpp +++ b/src/mesh/AbstractMesh.cpp @@ -38,3 +38,26 @@ void AbstractMesh::scale(double scaleX, double scaleY) node->scale(scaleX, scaleY); } } + +void AbstractMesh::transform(const Transform& transform) +{ + auto scaleX = transform.getScaleX(); + auto scaleY = transform.getScaleY(); + + scale(scaleX, scaleY); + + translate(transform.getLocation()); +} + +void AbstractMesh::translate(double offsetX, double offsetY, double offsetZ) +{ + for (auto& node : mNodes) + { + node->translate(offsetX, offsetY, offsetZ); + } +} + +void AbstractMesh::translate(const Point& offset) +{ + translate(offset.getX(), offset.getY(), offset.getZ()); +} diff --git a/src/mesh/AbstractMesh.h b/src/mesh/AbstractMesh.h index 68f9d31..6acfe90 100644 --- a/src/mesh/AbstractMesh.h +++ b/src/mesh/AbstractMesh.h @@ -2,6 +2,7 @@ #include "Point.h" #include "Node.h" +#include "Transform.h" #include #include @@ -49,6 +50,12 @@ public: void scale(double scaleX, double scaleY); + void translate(const Point& offset); + + void translate(double offsetX, double offsetY, double offsetZ = 0.0); + + void transform(const Transform& transform); + protected: std::unordered_map > mVectorAttributes; VecNodes mNodes; diff --git a/src/mesh/CMakeLists.txt b/src/mesh/CMakeLists.txt index 0065cc9..e1b239b 100644 --- a/src/mesh/CMakeLists.txt +++ b/src/mesh/CMakeLists.txt @@ -7,6 +7,7 @@ list(APPEND mesh_LIB_INCLUDES Node.cpp QuadMesh.cpp TriMesh.cpp + LineMesh.cpp MeshPrimitives.cpp MeshBuilder.cpp) diff --git a/src/mesh/LineMesh.cpp b/src/mesh/LineMesh.cpp new file mode 100644 index 0000000..3823244 --- /dev/null +++ b/src/mesh/LineMesh.cpp @@ -0,0 +1,25 @@ +#include "LineMesh.h" + +#include "Edge.h" + +LineMesh::~LineMesh() +{ + +} + +void LineMesh::populate(VecNodes& nodes, VecEdges& edges) +{ + mNodes = std::move(nodes); + mEdges = std::move(edges); +} + +std::vector LineMesh::getEdgeNodeIds() const +{ + std::vector ids(2*mEdges.size()); + for(std::size_t idx=0; idxgetNode0Id(); + ids[2*idx + 1] = mEdges[idx]->getNode1Id(); + } + return ids; +} diff --git a/src/mesh/LineMesh.h b/src/mesh/LineMesh.h new file mode 100644 index 0000000..0116036 --- /dev/null +++ b/src/mesh/LineMesh.h @@ -0,0 +1,30 @@ +#pragma once + +#include "AbstractMesh.h" + +#include +#include + +class Edge; +using EdgePtr = std::unique_ptr; +using VecEdges = std::vector; + +class LineMesh : public AbstractMesh +{ +public: + LineMesh() = default; + + ~LineMesh(); + + void populate(VecNodes& nodes, VecEdges& edges); + + std::vector getEdgeNodeIds() const; + + MeshType getType() const override + { + return MeshType::LINE; + } + +private: + VecEdges mEdges; +}; diff --git a/src/mesh/MeshBuilder.cpp b/src/mesh/MeshBuilder.cpp index 1159431..8c448c3 100644 --- a/src/mesh/MeshBuilder.cpp +++ b/src/mesh/MeshBuilder.cpp @@ -33,3 +33,23 @@ std::unique_ptr MeshBuilder::buildTriMesh(const VecPoints& locations, c mesh->populate(nodes, edges, faces); return mesh; } + +std::unique_ptr MeshBuilder::buildLineMesh(const VecPoints& locations, const EdgeIds& edgeIds) +{ + auto mesh = std::make_unique(); + + VecNodes nodes(locations.size()); + for (std::size_t idx=0; idxpopulate(nodes, edges); + return mesh; +} diff --git a/src/mesh/MeshBuilder.h b/src/mesh/MeshBuilder.h index 596ab56..081f72e 100644 --- a/src/mesh/MeshBuilder.h +++ b/src/mesh/MeshBuilder.h @@ -1,8 +1,11 @@ #pragma once #include "TriMesh.h" +#include "LineMesh.h" #include "Point.h" +#include + using EdgeIds = std::vector >; using FaceIds = std::vector >; using VecPoints = std::vector; @@ -11,4 +14,6 @@ class MeshBuilder { public: static std::unique_ptr buildTriMesh(const VecPoints& locations, const EdgeIds& edgeIds, const FaceIds& faceIds); + + static std::unique_ptr buildLineMesh(const VecPoints& locations, const EdgeIds& edgeIds); }; diff --git a/src/mesh/MeshPrimitives.cpp b/src/mesh/MeshPrimitives.cpp index 13a65f6..066d3ae 100644 --- a/src/mesh/MeshPrimitives.cpp +++ b/src/mesh/MeshPrimitives.cpp @@ -1,18 +1,16 @@ #include "MeshPrimitives.h" +#include "MeshBuilder.h" + #include -std::unique_ptr MeshPrimitives::build(const Rectangle& rectangle) +std::unique_ptr MeshPrimitives::buildRectangleAsTriMesh() { - const auto bottom_left = rectangle.getLocation(); - const auto width = rectangle.getWidth(); - const auto height = rectangle.getHeight(); - VecPoints locations = { - bottom_left, - Point(bottom_left, width, 0), - Point(bottom_left, width, height), - Point(bottom_left, 0, height) + {0, 0}, + {1, 0}, + {1, 1}, + {0, 1} }; EdgeIds edge_ids = { @@ -31,14 +29,33 @@ std::unique_ptr MeshPrimitives::build(const Rectangle& rectangle) return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids); } -std::unique_ptr MeshPrimitives::buildExplodedGrid(unsigned numX, unsigned numY) +std::unique_ptr MeshPrimitives::buildRectangleAsLineMesh() +{ + VecPoints locations = { + {0, 0}, + {1, 0}, + {1, 1}, + {0, 1} + }; + + EdgeIds edge_ids = { + {0, 1}, + {1, 2}, + {2, 3}, + {3, 0} + }; + + return MeshBuilder::buildLineMesh(locations, edge_ids); +} + +std::unique_ptr MeshPrimitives::buildExplodedGridAsTriMesh(unsigned numX, unsigned numY) { double delta_x = 1.0/double(numX); double delta_y = 1.0/double(numY); VecPoints locations (4 * numX * numY); - double offset_x = delta_x; - double offset_y = delta_y; + double offset_x = delta_x/2.0; + double offset_y = delta_y/2.0; for (unsigned idx=0; idx MeshPrimitives::buildExplodedGrid(unsigned numX, unsign locations[id_offset + 1] = Point(locX1, locY0); locations[id_offset + 2] = Point(locX1, locY1); locations[id_offset + 3] = Point(locX0, locY1); + offset_x += delta_x; } - offset_x = delta_x; + offset_x = delta_x/2.0; offset_y += delta_y; } @@ -88,3 +106,49 @@ std::unique_ptr MeshPrimitives::buildExplodedGrid(unsigned numX, unsign return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids); } + +std::unique_ptr MeshPrimitives::buildExplodedGridAsLineMesh(unsigned numX, unsigned numY) +{ + double delta_x = 1.0/double(numX); + double delta_y = 1.0/double(numY); + + VecPoints locations (4 * numX * numY); + double offset_x = delta_x/2.0; + double offset_y = delta_y/2.0; + for (unsigned idx=0; idx +#include "LineMesh.h" class MeshPrimitives { public: - static std::unique_ptr build(const Rectangle& rectangle); + static std::unique_ptr buildRectangleAsTriMesh(); - static std::unique_ptr buildExplodedGrid(unsigned numX, unsigned numY); + static std::unique_ptr buildRectangleAsLineMesh(); + + static std::unique_ptr buildExplodedGridAsTriMesh(unsigned numX, unsigned numY); + + static std::unique_ptr buildExplodedGridAsLineMesh(unsigned numX, unsigned numY); }; diff --git a/src/mesh/Node.h b/src/mesh/Node.h index 1536f97..748dab1 100644 --- a/src/mesh/Node.h +++ b/src/mesh/Node.h @@ -34,6 +34,11 @@ public: mPoint.scale(x, y); } + void translate(double x, double y, double z = 0.0) + { + mPoint.translate(x, y, z); + } + private: std::unordered_map > mVectorAttributes; unsigned mIndex{0}; diff --git a/src/visual_elements/CMakeLists.txt b/src/visual_elements/CMakeLists.txt index 6d4be45..c007595 100644 --- a/src/visual_elements/CMakeLists.txt +++ b/src/visual_elements/CMakeLists.txt @@ -7,7 +7,6 @@ list(APPEND visual_elements_LIB_INCLUDES SceneModel.cpp SceneItem.cpp SceneText.cpp - Transform.cpp Texture.cpp GridNode.cpp AbstractVisualNode.cpp diff --git a/src/visual_elements/GridNode.cpp b/src/visual_elements/GridNode.cpp index c1c5602..2c0e148 100644 --- a/src/visual_elements/GridNode.cpp +++ b/src/visual_elements/GridNode.cpp @@ -67,56 +67,73 @@ SceneItem* GridNode::getSceneItem(std::size_t idx) const unsigned GridNode::getNumSceneItems() const { - return 1; + return 2; } void GridNode::update(FontsManager* fontsManager) { if (!mBackgroundModel || mDataDirty) { - auto mesh = MeshPrimitives::buildExplodedGrid(mNumberX, mNumberY); - - if (mHeight > mWidth) - { - mesh->scale(mWidth, mWidth); - } - else - { - mesh->scale(mHeight, mHeight); - } - + auto mesh = MeshPrimitives::buildExplodedGridAsTriMesh(mNumberX, mNumberY); if (!mBackgroundModel) { - std::cout << "Setting up background model for grid node " << std::endl; mBackgroundModel = std::make_unique(std::move(mesh)); - mBackgroundModel->setName(mName + "_Model"); - mBackgroundModel->updateUniformColor({200, 200, 200, 1.0}); + mBackgroundModel->setName(mName + "_BackgroundModel"); } else { mBackgroundModel.get()->updateMesh(std::move(mesh)); - mBackgroundModel->updateUniformColor({200, 200, 200, 1.0}); } } - /* - if (!mOutlineModel || mDataDirty) + if (mOutlineModel || mDataDirty) { - const auto rect = Rectangle(Point(), 1, 1); - auto mesh = MeshPrimitives::build(rect); + auto mesh = MeshPrimitives::buildExplodedGridAsLineMesh(mNumberX, mNumberY); if (!mOutlineModel) { mOutlineModel = std::make_unique(std::move(mesh)); - mOutlineModel->setName(mName + "_Model"); + mOutlineModel->setName(mName + "_OulineModel"); } else { mOutlineModel.get()->updateMesh(std::move(mesh)); } } - */ + + if (mDataDirty) + { + auto difference = mNumberX*mNumberY - mData.size(); + mData.resize(mNumberX*mNumberY, {}); + + auto node_data = std::vector >(4*mNumberX*mNumberY); + for (unsigned idx=0; idx< node_data.size(); idx++) + { + if (idx < mData.size()) + { + node_data[idx] = mData[idx].getAsVectorDouble(); + } + + } + //mBackgroundModel->getMesh()->addVectorAttribute("Color", mData); + + } + + if (mTransformIsDirty) + { + auto size = mHeight > mWidth ? mWidth : mHeight; + + mBackgroundModel->updateTransform({mLocation, static_cast(size), static_cast(size)}); + mOutlineModel->updateTransform({mLocation, static_cast(size), static_cast(size)}); + mTransformIsDirty = false; + } + + if (mMaterialIsDirty) + { + mOutlineModel->updateUniformColor(mStrokeColor); + mMaterialIsDirty = false; + } mDataDirty = false; } diff --git a/src/visual_elements/RectangleNode.cpp b/src/visual_elements/RectangleNode.cpp index 90d8a65..bfddd6d 100644 --- a/src/visual_elements/RectangleNode.cpp +++ b/src/visual_elements/RectangleNode.cpp @@ -73,8 +73,7 @@ void RectangleNode::update(FontsManager* fontsManager) { if (!mBackgroundItem || mGeometryIsDirty) { - const auto rect = Rectangle(Point(), 1, 1); - auto mesh = MeshPrimitives::build(rect); + auto mesh = MeshPrimitives::buildRectangleAsTriMesh(); if (!mBackgroundItem) {