From 839401edb787ed1f822d053c2e62da1d7c98fb53 Mon Sep 17 00:00:00 2001 From: kazu Date: Thu, 8 Feb 2018 21:38:51 +0100 Subject: [PATCH] refactoring wireframe display worked on 3d-model display --- IndoorMap.pro | 3 +- MainController.cpp | 6 +- mapview/2D/MV2DElementFloorObstacleDoor.cpp | 138 ++++++++++++++++++++ mapview/2D/MV2DElementFloorObstacleDoor.h | 125 ++---------------- mapview/2D/MV2DElementFloorOutlinePolygon.h | 2 +- mapview/2D/MapViewElementHelper.h | 2 +- mapview/3D/MapView3D.cpp | 20 ++- mapview/3D/MapView3D.h | 1 + mapview/3D/floorplan/FloorplanRenderer.h | 39 ++++-- mapview/3D/floorplan/RenderTriangle.h | 109 ++++++++++++---- mapview/model/IHasParams.h | 10 ++ mapview/model/MMFloorObstacleDoor.h | 5 +- params/ElementParamWidget.cpp | 44 ++++--- res.qrc | 1 + res/icons/mesh.svg | 72 ++-------- res/icons/wireframe.svg | 54 ++++++++ 16 files changed, 395 insertions(+), 236 deletions(-) create mode 100644 mapview/2D/MV2DElementFloorObstacleDoor.cpp create mode 100644 res/icons/wireframe.svg diff --git a/IndoorMap.pro b/IndoorMap.pro index bff8d55..baf8d75 100644 --- a/IndoorMap.pro +++ b/IndoorMap.pro @@ -48,7 +48,8 @@ SOURCES += \ mapview/3D/misc/Outline.cpp \ mapview/3D/misc/Handrail.cpp \ mapview/3D/navMesh/QNavMeshSettings.cpp \ - params/ToolBoxWidget.cpp + params/ToolBoxWidget.cpp \ + mapview/2D/MV2DElementFloorObstacleDoor.cpp HEADERS += MainWindow.h \ diff --git a/MainController.cpp b/MainController.cpp index b445da5..bfe0710 100644 --- a/MainController.cpp +++ b/MainController.cpp @@ -108,10 +108,12 @@ MainController::MainController() { //mapModel->load("/apps/map24b.xml"); //mapModel->load("/apps/SHL41.xml"); - //mapModel->load("/mnt/vm/paper/diss/data/maps/SHL41_nm.xml"); + //mapModel->load("/mnt/vm/paper/diss/data/maps/test_in_out_overlap.xml"); + + mapModel->load("/mnt/vm/paper/diss/data/maps/SHL42_nm.xml"); //mapModel->load("/apps/paper/diss/data/maps/SHL41_nm.xml"); - mapModel->load("/mnt/sdcard/SHL41_nm.xml"); + //mapModel->load("/mnt/sdcard/SHL41_nm.xml"); //mapModel->load("/apps/paper/diss/data/maps/map_elevator2.xml"); diff --git a/mapview/2D/MV2DElementFloorObstacleDoor.cpp b/mapview/2D/MV2DElementFloorObstacleDoor.cpp new file mode 100644 index 0000000..c7a0f1b --- /dev/null +++ b/mapview/2D/MV2DElementFloorObstacleDoor.cpp @@ -0,0 +1,138 @@ +#include "MV2DElementFloorObstacleDoor.h" + +#include "MV2DElement.h" +#include "MapViewElementHelper.h" +#include "HasMoveableNodes.h" +#include +#include + +MV2DElementFloorObstacleDoor::MV2DElementFloorObstacleDoor(Floorplan::FloorObstacleDoor* fo) : fo(fo) { + ; +} + +BBox2 MV2DElementFloorObstacleDoor::getBoundingBox() const { + BBox2 bbox; + bbox.add(fo->from); + bbox.add(fo->to); + return bbox; +} + +ClickDist MV2DElementFloorObstacleDoor::getMinDistanceXY(const Point2 p) const { + return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p) * 0.95; +} + +void MV2DElementFloorObstacleDoor::paint(Painter& p) { + + // selected endpoints? + if (hasFocus()) { + p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR); + if (selectedUserIdx == 0) {p.drawCircle(fo->from);} + if (selectedUserIdx == 1) {p.drawCircle(fo->to);} + } + + QPen pen; + pen.setColor(QColor(0.5,0.5,0.5)); + pen.setStyle(Qt::PenStyle::DotLine); + p.setPenBrush(pen, Qt::NoBrush); + + if (Floorplan::DoorType::SWING == fo->type) { + + // opening indicator + const float open = (fo->swap) ? (-M_PI * 0.5) : (+M_PI * 0.5); + const float len = (fo->to - fo->from).length(); + const float angle1 = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x); + const float angle2 = angle1 + open; + const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + fo->from; + + pen.setWidth(2); p.setPen(pen); + p.drawLine(fo->from, fo->to); + + pen.setWidth(1); p.setPen(pen); + p.drawLine(fo->from, pOpen); + p.drawArc(fo->from, len, angle1, open); + + } else if (Floorplan::DoorType::REVOLVING == fo->type) { + + const float angle_rad = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x); + + // arcs + const Point2 cen = (fo->from + fo->to) / 2; + const float rad = (fo->to - fo->from).length() / 2; + p.drawArc(cen, rad, (40-90)/180.0f*M_PI+angle_rad, 100/180.0f*M_PI); + p.drawArc(cen, rad, (180+40-90)/180.0f*M_PI+angle_rad, 100/180.0f*M_PI); + + const int funAngle = (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() / 50) % 360; + + // inner spinner + int numDoors = 3; + for (int i = 0; i < numDoors; ++i) { + const int deg = 360 * i / numDoors + angle_rad*180.0f/M_PI + funAngle; + const float sx = std::cos(deg / 180.0f * M_PI); + const float sy = std::sin(deg / 180.0f * M_PI); + const Point2 dst = cen + Point2(sx,sy) * rad; + p.drawLine(cen, dst); + } + + } + + + // available endpoints + if (hasFocus()) { + p.setPenBrush(Qt::black, Qt::NoBrush); + p.drawCircle(fo->from); + p.drawCircle(fo->to); + } + + // obstacle length + if (hasFocus()) { + p.setPenBrush(Qt::black, Qt::NoBrush); + p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to)); + } + +} + + +void MV2DElementFloorObstacleDoor::onFocus() { + ; +} + +void MV2DElementFloorObstacleDoor::onUnfocus() { + selectedUserIdx = -1; // clear selection +} + +void MV2DElementFloorObstacleDoor::mousePressed(MapView2D* v, const Point2 p) { + (void) v; + (void) p; +} + +void MV2DElementFloorObstacleDoor::mouseMove(MapView2D* v, const Point2 p) { + (void) v; + (void) p; +} + +void MV2DElementFloorObstacleDoor::mouseReleased(MapView2D* v, const Point2 p) { + (void) v; + (void) p; +} + +std::vector MV2DElementFloorObstacleDoor::getMoveableNodes() const { + std::vector nodes = { + MoveableNode(0, fo->from), + MoveableNode(1, fo->to) + }; + return nodes; +} + +void MV2DElementFloorObstacleDoor::onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) { + switch (userIdx) { + case 0: fo->from = newPos; break; + case 1: fo->to = newPos; break; + } + emit v->onElementChange(this); +} + +bool MV2DElementFloorObstacleDoor::keyPressEvent(MapView2D* v, QKeyEvent *e) { + (void) v; + (void) e; + return false; +} diff --git a/mapview/2D/MV2DElementFloorObstacleDoor.h b/mapview/2D/MV2DElementFloorObstacleDoor.h index 63d2880..ba60924 100644 --- a/mapview/2D/MV2DElementFloorObstacleDoor.h +++ b/mapview/2D/MV2DElementFloorObstacleDoor.h @@ -2,7 +2,6 @@ #define MV2DELEMENTFLOOROBSTACLEDOOR_H #include "MV2DElement.h" -#include "MapViewElementHelper.h" #include "HasMoveableNodes.h" #include @@ -16,136 +15,36 @@ private: public: /** ctor */ - MV2DElementFloorObstacleDoor(Floorplan::FloorObstacleDoor* fo) : fo(fo) {;} + MV2DElementFloorObstacleDoor(Floorplan::FloorObstacleDoor* fo); /** get the element's 3D bounding box */ - BBox2 getBoundingBox() const override { - BBox2 bbox; - bbox.add(fo->from); - bbox.add(fo->to); - return bbox; - } + BBox2 getBoundingBox() const override; /** get the element's minimal distance (nearest whatsoever) to the given point */ - ClickDist getMinDistanceXY(const Point2 p) const override { - return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); - } + ClickDist getMinDistanceXY(const Point2 p) const override; /** repaint me */ - void paint(Painter& p) override { + void paint(Painter& p) override; - // selected endpoints? - if (hasFocus()) { - p.setPenBrush(Qt::NoPen, CFG::SEL_COLOR); - if (selectedUserIdx == 0) {p.drawCircle(fo->from);} - if (selectedUserIdx == 1) {p.drawCircle(fo->to);} - } + virtual void onFocus() override; - QPen pen; - pen.setColor(QColor(0.5,0.5,0.5)); - pen.setStyle(Qt::PenStyle::DotLine); - p.setPenBrush(pen, Qt::NoBrush); + virtual void onUnfocus() override; - // opening indicator - const float open = (fo->swap) ? (-M_PI * 0.5) : (+M_PI * 0.5); - const float len = (fo->to - fo->from).length(); - const float angle1 = std::atan2(fo->to.y-fo->from.y, fo->to.x-fo->from.x); - const float angle2 = angle1 + open; - const Point2 pOpen = Point2( std::cos(angle2) * len, std::sin(angle2) * len ) + fo->from; + virtual void mousePressed(MapView2D* v, const Point2 p) override; - pen.setWidth(2); p.setPen(pen); - p.drawLine(fo->from, fo->to); + virtual void mouseMove(MapView2D* v, const Point2 p) override; - pen.setWidth(1); p.setPen(pen); - p.drawLine(fo->from, pOpen); - p.drawArc(fo->from, len, angle1, open); - - // available endpoints - if (hasFocus()) { - p.setPenBrush(Qt::black, Qt::NoBrush); - p.drawCircle(fo->from); - p.drawCircle(fo->to); - } - - // obstacle length - if (hasFocus()) { - p.setPenBrush(Qt::black, Qt::NoBrush); - p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to)); - } - - } - - - virtual void onFocus() override { - ; - } - - virtual void onUnfocus() override { - selectedUserIdx = -1; // clear selection - } - - virtual void mousePressed(MapView2D* v, const Point2 p) override { - (void) v; - (void) p; - } - - virtual void mouseMove(MapView2D* v, const Point2 p) override { - (void) v; - (void) p; - } - - virtual void mouseReleased(MapView2D* v, const Point2 p) override { - (void) v; - (void) p; - } - - /** mouse moved to the given point */ -// virtual void mouseMove(MapView2D* v, const Point2 _p) override { -// (void) v; -// if (selPoint == -1) {return;} -// const Point2 p = v->getScaler().snap(_p); -// if (selPoint == 0) {fo->from.x = p.x; fo->from.y = p.y;} -// if (selPoint == 1) {fo->to.x = p.x; fo->to.y = p.y;} -// emit v->onElementChange(this); -// } - - /** mouse released */ -// virtual void mouseReleased(MapView2D* v, const Point2 _p) override { -// // select a new point on mouse-release (more robust than on mouse-press) -// const float t = v->getScaler().sm(CFG::SEL_THRESHOLD_SIZE_PX); -// const float l1 = _p.getDistance(fo->from); -// const float l2 = _p.getDistance(fo->to); -// if (l1 < l2 && l1 <= t) {selPoint = 0;} -// else if (l2 < l1 && l2 <= t) {selPoint = 1;} -// else {selPoint = -1;} - -// } + virtual void mouseReleased(MapView2D* v, const Point2 p) override; /** get a list of all nodes that are selectable / moveable */ - virtual std::vector getMoveableNodes() const override { - std::vector nodes = { - MoveableNode(0, fo->from), - MoveableNode(1, fo->to) - }; - return nodes; - } + virtual std::vector getMoveableNodes() const override; /** the given node was moved */ - virtual void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override { - switch (userIdx) { - case 0: fo->from = newPos; break; - case 1: fo->to = newPos; break; - } - emit v->onElementChange(this); - } + virtual void onNodeMove(MapView2D* v, const int userIdx, const Point2 newPos) override; - virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override { - (void) v; - (void) e; - return false; - } + virtual bool keyPressEvent(MapView2D* v, QKeyEvent *e) override; }; diff --git a/mapview/2D/MV2DElementFloorOutlinePolygon.h b/mapview/2D/MV2DElementFloorOutlinePolygon.h index 9970eb0..9211d55 100644 --- a/mapview/2D/MV2DElementFloorOutlinePolygon.h +++ b/mapview/2D/MV2DElementFloorOutlinePolygon.h @@ -34,7 +34,7 @@ public: const ClickDist dst = MapElementHelper::getLineDistanceXY(p1, p2, p); if (dst < min) {min = dst;} } - return min; + return min * 1.1; // penalty.. outlines are everywhere.. reduce priority } virtual void onFocus() override { diff --git a/mapview/2D/MapViewElementHelper.h b/mapview/2D/MapViewElementHelper.h index c521736..40a00f0 100644 --- a/mapview/2D/MapViewElementHelper.h +++ b/mapview/2D/MapViewElementHelper.h @@ -56,7 +56,7 @@ public: } - // distance from endpoints + // (direct) distance from endpoints const ClickDist d1(p1.getDistance(dst), ClickDistType::DIRECT); const ClickDist d2(p2.getDistance(dst), ClickDistType::DIRECT); diff --git a/mapview/3D/MapView3D.cpp b/mapview/3D/MapView3D.cpp index 70b5444..7a90f03 100644 --- a/mapview/3D/MapView3D.cpp +++ b/mapview/3D/MapView3D.cpp @@ -56,6 +56,15 @@ MapView3D::MapView3D(QWidget *parent) : QOpenGLWidget(parent) { emit update(); }); + QPushButton* btnWireframe = new QPushButton(UIHelper::getIcon("wireframe"), "", this); + btnWireframe->setCheckable(true); + btnWireframe->setStyleSheet(style); + btnWireframe->setGeometry(16, 16+8+32+8+32, 32, 32); + connect(btnWireframe, &QPushButton::clicked, [this] () { + useWireframe = !useWireframe; + emit update(); + }); + QPushButton* btnGrid = new QPushButton(UIHelper::getIcon("grid"), "", this); btnGrid->setCheckable(true); btnGrid->setChecked(false); @@ -74,6 +83,7 @@ MapView3D::MapView3D(QWidget *parent) : QOpenGLWidget(parent) { emit onShow3DNavMesh(btnNavMesh->isChecked()); }); + // android setAttribute(Qt::WA_AcceptTouchEvents, true); grabGesture(Qt::PanGesture); @@ -81,7 +91,7 @@ MapView3D::MapView3D(QWidget *parent) : QOpenGLWidget(parent) { auto format = QSurfaceFormat(); //format.setVersion(4,3); - format.setSamples(4); + format.setSamples(2); //format.setProfile(QSurfaceFormat::CoreProfile); setFormat(format); @@ -298,8 +308,8 @@ void MapView3D::draw() { rs.shader->setViewMatrix(V); rs.shader->setProjectionMatrix(P); - if (floorplanRenderer && floorplanRendererModel) { - floorplanRenderer->renderSolid(rs, floorplanRendererModel->getTriaSolid() ); + if (showFloorplan && floorplanRendererModel) { + floorplanRenderer->renderSolid(rs, floorplanRendererModel->getTriaSolid(), useWireframe ); } // // solid floorplan parts @@ -330,8 +340,8 @@ void MapView3D::draw() { // } - if (floorplanRenderer && floorplanRendererModel) { - floorplanRenderer->renderTransp(rs, floorplanRendererModel->getTriaTransp() ); + if (showFloorplan && floorplanRendererModel) { + floorplanRenderer->renderTransp(rs, floorplanRendererModel->getTriaTransp(), useWireframe); } diff --git a/mapview/3D/MapView3D.h b/mapview/3D/MapView3D.h index 0d1de3c..f421026 100644 --- a/mapview/3D/MapView3D.h +++ b/mapview/3D/MapView3D.h @@ -21,6 +21,7 @@ class MapView3D : public QOpenGLWidget { Q_OBJECT bool usePerspectiveProjection = false; + bool useWireframe = false; public: diff --git a/mapview/3D/floorplan/FloorplanRenderer.h b/mapview/3D/floorplan/FloorplanRenderer.h index 284f0ac..7460ada 100644 --- a/mapview/3D/floorplan/FloorplanRenderer.h +++ b/mapview/3D/floorplan/FloorplanRenderer.h @@ -27,25 +27,34 @@ public: } /** render the given grid using GL commands */ - void renderSolid(const RenderSettings& rs, const RenderTriangle& rt) { + void renderSolid(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe) { rs.shader->bind(); rs.shader->setModelMatrix(QMatrix4x4()); - rs.shader->setVertices(rt.getVertices().data()); - rs.shader->setNormals(rt.getNormals().data()); - rs.shader->setVertexColor(rt.getRGBA().data()); - glDrawArrays(GL_TRIANGLES, 0, rt.getVertices().size()/3); + rs.shader->setVertices(rt.getVertices()); + rs.shader->setNormals(rt.getNormals()); + rs.shader->setVertexColor(rt.getRGBA()); + glDrawArrays(GL_TRIANGLES, 0, rt.count()); rs.shader->unsetVertices(); rs.shader->unsetNormals(); rs.shader->unsetVertexColor(); + if (wireframe) { + RenderTriangle rt2 = rt.toWireframe(false); + rs.shader->setColor(0,0,0,128); + rs.shader->setVertices(rt2.getVertices()); + //rs.shader->setVertexColor(rt2.getRGBA()); + glDrawArrays(GL_LINES, 0, rt2.count()); + rs.shader->unsetVertices(); + //rs.shader->unsetVertexColor(); + } rs.shader->release(); } /** render the given grid using GL commands */ - void renderTransp(const RenderSettings& rs, const RenderTriangle& rt) { + void renderTransp(const RenderSettings& rs, const RenderTriangle& rt, bool wireframe) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -53,14 +62,24 @@ public: rs.shader->bind(); rs.shader->setModelMatrix(QMatrix4x4()); - rs.shader->setVertices(rt.getVertices().data()); - rs.shader->setNormals(rt.getNormals().data()); - rs.shader->setVertexColor(rt.getRGBA().data()); - glDrawArrays(GL_TRIANGLES, 0, rt.getVertices().size()/3); + rs.shader->setVertices(rt.getVertices()); + rs.shader->setNormals(rt.getNormals()); + rs.shader->setVertexColor(rt.getRGBA()); + glDrawArrays(GL_TRIANGLES, 0, rt.count()); rs.shader->unsetVertices(); rs.shader->unsetNormals(); rs.shader->unsetVertexColor(); + if (wireframe) { + RenderTriangle rt2 = rt.toWireframe(false); + rs.shader->setColor(0,0,0,128); + rs.shader->setVertices(rt2.getVertices()); + //rs.shader->setVertexColor(rt2.getRGBA()); + glDrawArrays(GL_LINES, 0, rt2.count()); + rs.shader->unsetVertices(); + //rs.shader->unsetVertexColor(); + } + rs.shader->release(); glDisable(GL_BLEND); diff --git a/mapview/3D/floorplan/RenderTriangle.h b/mapview/3D/floorplan/RenderTriangle.h index d91afa6..36fe82f 100644 --- a/mapview/3D/floorplan/RenderTriangle.h +++ b/mapview/3D/floorplan/RenderTriangle.h @@ -7,56 +7,71 @@ class RenderTriangle { - std::vector vertices; - std::vector normals; - std::vector rgba; + struct Vertex{ + float x,y,z; + Vertex(const float x, const float y, const float z) : x(x), y(y), z(z) {;} + } __attribute__((packed)); + + struct Normal { + float x,y,z; + Normal(const float x, const float y, const float z) : x(x), y(y), z(z) {;} + } __attribute__((packed)); + + struct RGBA { + float r,g,b,a; + RGBA(const float r, const float g, const float b, const float a) : r(r), g(g), b(b), a(a) {;} + } __attribute__((packed)); + + std::vector vertices; + std::vector normals; + std::vector rgba; public: void addTriangle(Point3 p1, Point3 p2, Point3 p3) { - vertices.insert(vertices.end(), {p1.x, p1.y, p1.z}); - vertices.insert(vertices.end(), {p2.x, p2.y, p2.z}); - vertices.insert(vertices.end(), {p3.x, p3.y, p3.z}); + vertices.push_back(Vertex(p1.x, p1.y, p1.z)); + vertices.push_back(Vertex(p2.x, p2.y, p2.z)); + vertices.push_back(Vertex(p3.x, p3.y, p3.z)); } void addTriangle(Point3 p1, Point3 p2, Point3 p3, const Point3 n) { - vertices.insert(vertices.end(), {p1.x, p1.y, p1.z}); - vertices.insert(vertices.end(), {p2.x, p2.y, p2.z}); - vertices.insert(vertices.end(), {p3.x, p3.y, p3.z}); + vertices.push_back(Vertex(p1.x, p1.y, p1.z)); + vertices.push_back(Vertex(p2.x, p2.y, p2.z)); + vertices.push_back(Vertex(p3.x, p3.y, p3.z)); - normals.insert(normals.end(), {n.x, n.y, n.z}); - normals.insert(normals.end(), {n.x, n.y, n.z}); - normals.insert(normals.end(), {n.x, n.y, n.z}); + normals.push_back(Normal(n.x, n.y, n.z)); + normals.push_back(Normal(n.x, n.y, n.z)); + normals.push_back(Normal(n.x, n.y, n.z)); } void addTriangle(Point3 p1, Point3 p2, Point3 p3, const Point3 n, const float r, const float g, const float b, const float a) { - vertices.insert(vertices.end(), {p1.x, p1.y, p1.z}); - vertices.insert(vertices.end(), {p2.x, p2.y, p2.z}); - vertices.insert(vertices.end(), {p3.x, p3.y, p3.z}); + vertices.push_back(Vertex(p1.x, p1.y, p1.z)); + vertices.push_back(Vertex(p2.x, p2.y, p2.z)); + vertices.push_back(Vertex(p3.x, p3.y, p3.z)); - normals.insert(normals.end(), {n.x, n.y, n.z}); - normals.insert(normals.end(), {n.x, n.y, n.z}); - normals.insert(normals.end(), {n.x, n.y, n.z}); + normals.push_back(Normal(n.x, n.y, n.z)); + normals.push_back(Normal(n.x, n.y, n.z)); + normals.push_back(Normal(n.x, n.y, n.z)); - rgba.insert(rgba.end(), {r,g,b,a}); - rgba.insert(rgba.end(), {r,g,b,a}); - rgba.insert(rgba.end(), {r,g,b,a}); + rgba.push_back(RGBA(r,g,b,a)); + rgba.push_back(RGBA(r,g,b,a)); + rgba.push_back(RGBA(r,g,b,a)); } void addLine(Point3 p1, Point3 p2, const float r, const float g, const float b, const float a) { - vertices.insert(vertices.end(), {p1.x, p1.y, p1.z}); - vertices.insert(vertices.end(), {p2.x, p2.y, p2.z}); + vertices.push_back( Vertex(p1.x, p1.y, p1.z)); + vertices.push_back(Vertex(p2.x, p2.y, p2.z)); - rgba.insert(rgba.end(), {r,g,b,a}); - rgba.insert(rgba.end(), {r,g,b,a}); + rgba.push_back( RGBA(r,g,b,a)); + rgba.push_back(RGBA(r,g,b,a)); } @@ -66,11 +81,49 @@ public: rgba.clear(); } - const std::vector& getVertices() const {return vertices;} + const float* getVertices() const {return (float*) vertices.data();} - const std::vector& getNormals() const {return normals;} + const float* getNormals() const {return (float*) normals.data();} - const std::vector& getRGBA() const {return rgba;} + const float* getRGBA() const {return (float*) rgba.data();} + + size_t count() const {return vertices.size();} + + RenderTriangle toWireframe(const bool withVertexColors) const { + + RenderTriangle res; + + for (size_t i = 0; i < vertices.size(); i += 3) { + + res.vertices.push_back(vertices[i+0]); + res.vertices.push_back(vertices[i+1]); + + res.vertices.push_back(vertices[i+1]); + res.vertices.push_back(vertices[i+2]); + + res.vertices.push_back(vertices[i+2]); + res.vertices.push_back(vertices[i+0]); + + } + + if (withVertexColors) { + for (size_t i = 0; i < rgba.size(); i += 3) { + + res.rgba.push_back(rgba[i+0]); + res.rgba.push_back(rgba[i+1]); + + res.rgba.push_back(rgba[i+1]); + res.rgba.push_back(rgba[i+2]); + + res.rgba.push_back(rgba[i+2]); + res.rgba.push_back(rgba[i+0]); + + } + } + + return res; + + } }; diff --git a/mapview/model/IHasParams.h b/mapview/model/IHasParams.h index f266cab..5a637fb 100644 --- a/mapview/model/IHasParams.h +++ b/mapview/model/IHasParams.h @@ -15,6 +15,7 @@ enum class ParamType { FILE, POINT2, POINT3, + ENUM, }; class ParamValue { @@ -85,13 +86,22 @@ struct Param { /** read-only parameter? */ bool readOnly; + std::vector enumValues; + /** ctor */ Param(const std::string& name, const ParamType type, const bool readOnly = false) : name(name), type(type), readOnly(readOnly) {;} + /** ctor */ + Param(const std::string& name, const ParamType type, const std::vector& enumValues) : name(name), type(type), readOnly(false), enumValues(enumValues) {;} + + /** special parameter */ static Param getNA() { return Param("", ParamType::NOT_AVAILABLE); } + /** get all supported enum values */ + const std::vector& getEnumValues() const {return enumValues;} + }; /** free parameters */ diff --git a/mapview/model/MMFloorObstacleDoor.h b/mapview/model/MMFloorObstacleDoor.h index 1efb4da..af42c29 100644 --- a/mapview/model/MMFloorObstacleDoor.h +++ b/mapview/model/MMFloorObstacleDoor.h @@ -46,7 +46,7 @@ public: /** get the number of parameters */ int getNumParams() const override { - return 3; + return 4; } /** get the description of the idx-th parameter */ @@ -55,6 +55,7 @@ public: case 0: return Param("width", ParamType::FLOAT, true); case 1: return Param("height", ParamType::FLOAT); case 2: return Param("swap", ParamType::BOOL); + case 3: return Param("type", ParamType::ENUM, {"unknown", "swing", "double swing", "slide", "double slide", "revolving"}); default: throw Exception("out of bounds"); } } @@ -65,6 +66,7 @@ public: case 0: return fo->getSize(); case 1: return fo->height; case 2: return fo->swap; + case 3: return (int) fo->type; default: throw Exception("out of bounds"); } } @@ -75,6 +77,7 @@ public: case 0: break; case 1: fo->height = val.toFloat(); break; case 2: fo->swap = val.toBool(); break; + case 3: fo->type = (Floorplan::DoorType) val.toInt(); break; default: throw Exception("out of bounds"); } } diff --git a/params/ElementParamWidget.cpp b/params/ElementParamWidget.cpp index d1c624e..80c04a0 100644 --- a/params/ElementParamWidget.cpp +++ b/params/ElementParamWidget.cpp @@ -65,8 +65,6 @@ QComboBox* getOutlineMethods() { return cmb; } - - ElementParamWidget::ElementParamWidget(QWidget *parent) : QWidget(parent) { this->lay = new QGridLayout(this); @@ -148,7 +146,6 @@ void ElementParamWidget::refresh() { } } - { // does the element have "parameters" ? IHasParams* elem = dynamic_cast(el); if (elem) { @@ -168,6 +165,21 @@ void ElementParamWidget::refresh() { case ParamType::NOT_AVAILABLE: break; + case ParamType::ENUM: { + QComboBox* cmb = new QComboBox(); + int idx = 0; + for (const std::string& str : param.getEnumValues()) {cmb->addItem(str.c_str(), idx++);} + cmb->setCurrentIndex(value.toInt()); + connect(cmb, static_cast(&QComboBox::currentIndexChanged), [i, elem, cmb] (int idx) { + (void) idx; + elem->setParamValue(i, cmb->currentData().toInt() ); + }); + lay->addWidget(cmb,r,1); + break; + } + + + case ParamType::BOOL: { QCheckBox* chk = new QCheckBox( ); chk->setChecked(value.toBool()); @@ -197,20 +209,20 @@ void ElementParamWidget::refresh() { break; } - case ParamType::DOUBLE: { - const std::string str = std::to_string(value.toDouble()); - if (param.readOnly) { - lay->addWidget(new QLabel(str.c_str()),r,1); - } else { - QLineEdit* le = new QLineEdit( str.c_str() ); - connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) { - const double val = str.toDouble(); - elem->setParamValue(i, ParamValue(val)); - }); - lay->addWidget(le,r,1); + case ParamType::DOUBLE: { + const std::string str = std::to_string(value.toDouble()); + if (param.readOnly) { + lay->addWidget(new QLabel(str.c_str()),r,1); + } else { + QLineEdit* le = new QLineEdit( str.c_str() ); + connect(le, &QLineEdit::textChanged, [i,elem] (const QString& str) { + const double val = str.toDouble(); + elem->setParamValue(i, ParamValue(val)); + }); + lay->addWidget(le,r,1); + } + break; } - break; - } case ParamType::INT: { const std::string str = std::to_string(value.toInt()); diff --git a/res.qrc b/res.qrc index 4a98ea4..2371e34 100644 --- a/res.qrc +++ b/res.qrc @@ -24,5 +24,6 @@ res/icons/perspective.svg res/icons/floorplan.svg res/icons/grid.svg + res/icons/wireframe.svg diff --git a/res/icons/mesh.svg b/res/icons/mesh.svg index d799ae7..8afd46b 100644 --- a/res/icons/mesh.svg +++ b/res/icons/mesh.svg @@ -1,65 +1,21 @@ - + + + width="177.778px" height="177.778px" viewBox="0 0 177.778 177.778" style="enable-background:new 0 0 177.778 177.778;" + xml:space="preserve"> - + + + + + + + + + + diff --git a/res/icons/wireframe.svg b/res/icons/wireframe.svg new file mode 100644 index 0000000..0e11a92 --- /dev/null +++ b/res/icons/wireframe.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +