diff --git a/apps/sample-gui/CMakeLists.txt b/apps/sample-gui/CMakeLists.txt index 8692893..0f43d96 100644 --- a/apps/sample-gui/CMakeLists.txt +++ b/apps/sample-gui/CMakeLists.txt @@ -9,6 +9,9 @@ list(APPEND client_HEADERS image_editor/ImageViewWidget.h canvas/CanvasView.h canvas/CanvasController.h + mesh_viewer/MeshViewerView.h + mesh_viewer/MeshViewerController.h + mesh_viewer/MeshViewerCanvas.h web_client/WebClientView.h) @@ -20,6 +23,9 @@ list(APPEND client_LIB_INCLUDES audio_editor/AudioEditorView.cpp image_editor/ImageEditorView.cpp image_editor/ImageViewWidget.cpp + mesh_viewer/MeshViewerView.cpp + mesh_viewer/MeshViewerController.cpp + mesh_viewer/MeshViewerCanvas.cpp canvas/CanvasView.cpp canvas/CanvasController.cpp web_client/WebClientView.cpp @@ -42,6 +48,7 @@ target_include_directories(sample_gui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/image_editor" "${CMAKE_CURRENT_SOURCE_DIR}/web_client" "${CMAKE_CURRENT_SOURCE_DIR}/canvas" + "${CMAKE_CURRENT_SOURCE_DIR}/mesh_viewer" ) target_link_libraries(sample_gui PUBLIC client windows console core network database geometry audio web) set_property(TARGET sample_gui PROPERTY FOLDER apps) diff --git a/apps/sample-gui/MediaTool.cpp b/apps/sample-gui/MediaTool.cpp index 7f377a5..864ff79 100644 --- a/apps/sample-gui/MediaTool.cpp +++ b/apps/sample-gui/MediaTool.cpp @@ -5,6 +5,7 @@ #include "ImageEditorView.h" #include "WebClientView.h" #include "CanvasView.h" +#include "MeshViewerView.h" #include "TabbedPanelWidget.h" #include "TopBar.h" @@ -54,6 +55,10 @@ void MediaTool::initializeViews() canvas->setName("CanvasView"); tabbedPanel->addPanel(std::move(canvas), "Canvas"); + auto mesh = MeshViewerView::Create(); + mesh->setName("MeshViewer"); + tabbedPanel->addPanel(std::move(mesh), "Mesh Viewer"); + auto topBar = TopBar::Create(); auto statusBar = StatusBar::Create(); diff --git a/apps/sample-gui/canvas/CanvasView.cpp b/apps/sample-gui/canvas/CanvasView.cpp index c8fbc6e..239adb1 100644 --- a/apps/sample-gui/canvas/CanvasView.cpp +++ b/apps/sample-gui/canvas/CanvasView.cpp @@ -16,6 +16,7 @@ CanvasView::CanvasView() : mController(CanvasController::Create()) { + std::cout << "Creatin canvas" << std::endl; initialize(); } diff --git a/apps/sample-gui/image_editor/ImageViewWidget.cpp b/apps/sample-gui/image_editor/ImageViewWidget.cpp index 1bc24c8..d737064 100644 --- a/apps/sample-gui/image_editor/ImageViewWidget.cpp +++ b/apps/sample-gui/image_editor/ImageViewWidget.cpp @@ -7,6 +7,7 @@ ImageViewWidget::ImageViewWidget() { + std::cout << "Creating image view widget" << std::endl; mName = "ImageViewWidget"; } diff --git a/apps/sample-gui/mesh_viewer/MeshViewerCanvas.cpp b/apps/sample-gui/mesh_viewer/MeshViewerCanvas.cpp new file mode 100644 index 0000000..e69de29 diff --git a/apps/sample-gui/mesh_viewer/MeshViewerCanvas.h b/apps/sample-gui/mesh_viewer/MeshViewerCanvas.h new file mode 100644 index 0000000..e69de29 diff --git a/apps/sample-gui/mesh_viewer/MeshViewerController.cpp b/apps/sample-gui/mesh_viewer/MeshViewerController.cpp new file mode 100644 index 0000000..e69de29 diff --git a/apps/sample-gui/mesh_viewer/MeshViewerController.h b/apps/sample-gui/mesh_viewer/MeshViewerController.h new file mode 100644 index 0000000..e69de29 diff --git a/apps/sample-gui/mesh_viewer/MeshViewerView.cpp b/apps/sample-gui/mesh_viewer/MeshViewerView.cpp new file mode 100644 index 0000000..b82a70a --- /dev/null +++ b/apps/sample-gui/mesh_viewer/MeshViewerView.cpp @@ -0,0 +1,65 @@ +#include "MeshViewerView.h" + +#include "MeshNode.h" +#include "TransformNode.h" +#include "AbstractMesh.h" +#include "MeshPrimitives.h" + +#include + +std::unique_ptr MeshViewerView::Create() +{ + return std::make_unique(); +} + +MeshViewerView::~MeshViewerView() +{ + +} + +MeshViewerView::MeshViewerView() +{ + mName = "MeshViewerView"; + mBackgroundColor = {204, 204, 255}; +} + +void MeshViewerView::doPaint(const PaintEvent* event) +{ + if (!mVisible) + { + return; + } + + if (!mMeshNode) + { + mMeshNode = std::make_unique(mLocation); + mMeshNode->setName(mName + "_MeshNode"); + + mMeshNode->setWidth(mSize.mWidth); + mMeshNode->setHeight(mSize.mHeight); + + mMeshNode->setFillColor(mBackgroundColor); + + mRootNode->addChild(mMeshNode.get()); + } + + if (mTransformDirty) + { + mMeshNode->setLocation(mLocation); + mMeshNode->setWidth(mSize.mWidth); + mMeshNode->setHeight(mSize.mHeight); + } + + if (mMaterialDirty) + { + mMeshNode->setFillColor(mBackgroundColor); + } + + if (!mMesh) + { + auto mesh = MeshPrimitives::buildRectangleAsTriMesh(); + mMesh = std::move(mesh); + + mMeshNode->setMesh(mMesh.get()); + } +} diff --git a/apps/sample-gui/mesh_viewer/MeshViewerView.h b/apps/sample-gui/mesh_viewer/MeshViewerView.h new file mode 100644 index 0000000..5fbfce7 --- /dev/null +++ b/apps/sample-gui/mesh_viewer/MeshViewerView.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Widget.h" + +class MeshNode; +class AbstractMesh; + +class MeshViewerView : public Widget +{ +public: + MeshViewerView(); + ~MeshViewerView(); + static std::unique_ptr Create(); + void doPaint(const PaintEvent* event) override; +private: + + std::unique_ptr mMesh; + std::unique_ptr mMeshNode; +}; diff --git a/src/graphics/opengl/OpenGlMeshPainter.cpp b/src/graphics/opengl/OpenGlMeshPainter.cpp index 93833a2..68a7b3c 100644 --- a/src/graphics/opengl/OpenGlMeshPainter.cpp +++ b/src/graphics/opengl/OpenGlMeshPainter.cpp @@ -121,10 +121,16 @@ void OpenGlMeshPainter::paint(SceneModel* model, DrawingContext* context) else { indices = dynamic_cast(model->getMesh())->getFaceNodeIds(); - } + auto model_color = model->getColor().getAsVectorDouble(); std::vector color = {float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3])}; paint(vertices, indices, color, line_mesh); + + if (model->getShowOutline()) + { + auto edge_indices = dynamic_cast(model->getMesh())->getEdgeNodeIds(); + paint(vertices, edge_indices, {0, 0, 0, 1}, true); + } } diff --git a/src/mesh/AbstractMesh.h b/src/mesh/AbstractMesh.h index 975f55d..6a1cb10 100644 --- a/src/mesh/AbstractMesh.h +++ b/src/mesh/AbstractMesh.h @@ -58,6 +58,11 @@ public: void transform(const Transform& transform); + unsigned getNumNodes() const + { + return mNodes.size(); + } + protected: std::unordered_map > mVectorAttributes; VecNodes mNodes; diff --git a/src/mesh/FaceMesh.cpp b/src/mesh/FaceMesh.cpp index b08b77e..06c7fa0 100644 --- a/src/mesh/FaceMesh.cpp +++ b/src/mesh/FaceMesh.cpp @@ -4,6 +4,8 @@ #include "Edge.h" #include "AbstractFace.h" +#include + FaceMesh::~FaceMesh() { @@ -64,18 +66,21 @@ void FaceMesh::resetIds() for (auto& node : mNodes) { node->setIndex(count); + count++; } count = 0; for (auto& edge : mEdges) { edge->setIndex(count); + count++; } count = 0; for (auto& face : mFaces) { face->setIndex(count); + count++; } } @@ -132,6 +137,17 @@ void FaceMesh::replaceIfOverlapping(FaceMesh* mesh, Edge* target_edge) const } } +std::vector FaceMesh::getEdgeNodeIds() const +{ + std::vector ids(2*mEdges.size()); + for(std::size_t idx=0; idxgetNode0Id(); + ids[2*idx + 1] = mEdges[idx]->getNode1Id(); + } + return ids; +} + void FaceMesh::merge(std::unique_ptr mesh) { if (mesh->getType() != getType()) diff --git a/src/mesh/FaceMesh.h b/src/mesh/FaceMesh.h index 2596115..b0b61be 100644 --- a/src/mesh/FaceMesh.h +++ b/src/mesh/FaceMesh.h @@ -27,6 +27,8 @@ public: std::vector getFaceNodeIds() const; + std::vector getEdgeNodeIds() const; + void addConstantFaceVectorAttribute(const std::string& tag, const std::vector& values); std::vector > getFaceVectorAttributes(const std::string& tag); diff --git a/src/visual_elements/CMakeLists.txt b/src/visual_elements/CMakeLists.txt index c007595..dacad19 100644 --- a/src/visual_elements/CMakeLists.txt +++ b/src/visual_elements/CMakeLists.txt @@ -2,6 +2,7 @@ list(APPEND visual_elements_LIB_INCLUDES GeometryNode.cpp RectangleNode.cpp MaterialNode.cpp + MeshNode.cpp TextNode.cpp Scene.cpp SceneModel.cpp diff --git a/src/visual_elements/MeshNode.cpp b/src/visual_elements/MeshNode.cpp new file mode 100644 index 0000000..591f7b7 --- /dev/null +++ b/src/visual_elements/MeshNode.cpp @@ -0,0 +1,90 @@ +#include "MeshNode.h" + +#include + +MeshNode::MeshNode(const DiscretePoint& location) + : MaterialNode(location) +{ + +} + +void MeshNode::setWidth(unsigned width) +{ + if (mWidth != width) + { + mTransformIsDirty = true; + mWidth = width; + } +} + +void MeshNode::setHeight(unsigned height) +{ + if (mHeight != height) + { + mTransformIsDirty = true; + mHeight = height; + } +} + +void MeshNode::setMesh(AbstractMesh* mesh) +{ + mWorkingMesh = mesh; + mMeshIsDirty = true; +} + +SceneItem* MeshNode::getSceneItem(std::size_t idx) const +{ + return mModel.get(); +} + +unsigned MeshNode::getNumSceneItems() const +{ + if (mWorkingMesh) + { + return 1; + } + else + { + return 0; + } +} + +void MeshNode::update(FontsManager* fontsManager) +{ + if (!mModel || mMeshIsDirty) + { + if (!mModel) + { + mModel = std::make_unique(nullptr); + mModel->setName(mName + "_MeshModel"); + mModel->setShowOutline(true); + } + + if (mWorkingMesh) + { + mModel->updateMesh(mWorkingMesh); + mMeshIsDirty = false; + } + } + + if (mWorkingMesh && mMeshIsDirty) + { + std::cout << "Updating mesh with " << mWorkingMesh->getNumNodes() << std::endl; + mModel->updateMesh(mWorkingMesh); + mMeshIsDirty = false; + } + + if (mTransformIsDirty) + { + auto size = mHeight > mWidth ? mWidth : mHeight; + mModel->updateTransform({mLocation, static_cast(size), static_cast(size)}); + mTransformIsDirty = false; + } + + if (mMaterialIsDirty) + { + mModel->updateUniformColor(mFillColor); + mMaterialIsDirty = false; + } +} + diff --git a/src/visual_elements/MeshNode.h b/src/visual_elements/MeshNode.h new file mode 100644 index 0000000..bf6ee54 --- /dev/null +++ b/src/visual_elements/MeshNode.h @@ -0,0 +1,28 @@ +#pragma once + +#include "MaterialNode.h" + +class AbstractMesh; + +class MeshNode : public MaterialNode +{ +public: + MeshNode(const DiscretePoint& location); + void setMesh(AbstractMesh* mesh); + + SceneItem* getSceneItem(std::size_t idx) const override; + unsigned getNumSceneItems() const override; + + void setWidth(unsigned width); + void setHeight(unsigned height); + + void update(FontsManager* fontsManager) override; + +private: + bool mMeshIsDirty{true}; + AbstractMesh* mWorkingMesh{nullptr}; + + unsigned mWidth{1}; + unsigned mHeight{1}; + std::unique_ptr mModel; +}; diff --git a/src/visual_elements/SceneModel.cpp b/src/visual_elements/SceneModel.cpp index b8be841..03dc068 100644 --- a/src/visual_elements/SceneModel.cpp +++ b/src/visual_elements/SceneModel.cpp @@ -11,7 +11,14 @@ SceneModel::SceneModel(std::unique_ptr mesh) AbstractMesh* SceneModel::getMesh() const { - return mMesh.get(); + if (mMesh) + { + return mMesh.get(); + } + else + { + return mRawMesh; + } } void SceneModel::updateMesh(std::unique_ptr mesh) @@ -20,6 +27,12 @@ void SceneModel::updateMesh(std::unique_ptr mesh) mMeshIsDirty = true; } +void SceneModel::updateMesh(AbstractMesh* mesh) +{ + mRawMesh = mesh; + mMeshIsDirty = true; +} + SceneItem::Type SceneModel::getType() const { return SceneItem::Type::MODEL; diff --git a/src/visual_elements/SceneModel.h b/src/visual_elements/SceneModel.h index aebfbc0..3b5a42d 100644 --- a/src/visual_elements/SceneModel.h +++ b/src/visual_elements/SceneModel.h @@ -19,13 +19,27 @@ public: AbstractMesh* getMesh() const; void updateMesh(std::unique_ptr mesh); + void updateMesh(AbstractMesh* mesh); + + void setShowOutline(bool showOutline) + { + mShowOutline = showOutline; + } + + bool getShowOutline() const + { + return mShowOutline; + } Type getType() const override; private: + + AbstractMesh* mRawMesh{nullptr}; std::unique_ptr mMesh; std::unique_ptr mColorMap; bool mMeshIsDirty{true}; bool mColorMapIsDirty{true}; + bool mShowOutline{false}; };