diff --git a/IndoorMap.pro b/IndoorMap.pro index 0f01768..9545660 100644 --- a/IndoorMap.pro +++ b/IndoorMap.pro @@ -190,7 +190,8 @@ HEADERS += MainWindow.h \ mapview/2D/MV2DElementFloorObstacleObject.h \ mapview/model/MMFloorObstacleObject.h \ mapview/3D/MV3DElementFloorObstacleObject.h \ - mapview/2D/tools/ToolNewObject.h + mapview/2D/tools/ToolNewObject.h \ + mapview/2D/tools/ToolNewPillar.h FORMS += MainWindow.ui diff --git a/MainController.cpp b/MainController.cpp index b1e68ee..9d0572e 100644 --- a/MainController.cpp +++ b/MainController.cpp @@ -120,10 +120,10 @@ MainController::MainController() { //mapModel->load("/mnt/vm/paper/diss/data/maps/walkmodel_stairs3.xml"); - mapModel->load("/mnt/vm/paper/diss/data/maps/walkmodel_2D_1.xml"); + //mapModel->load("/mnt/vm/paper/diss/data/maps/walkmodel_2D_1.xml"); //mapModel->load("/mnt/vm/paper/diss/data/maps/walkmodel_stairs3.xml"); - //mapModel->load("/mnt/vm/paper/diss/data/maps/SHL42_nm.xml"); + mapModel->load("/mnt/vm/paper/diss/data/maps/SHL44_nm.xml"); //mapModel->load("/apps/paper/diss/data/maps/SHL41_nm.xml"); //mapModel->load("/mnt/sdcard/SHL41_nm.xml"); diff --git a/mapview/2D/MV2DElementFloorObstacleLine.h b/mapview/2D/MV2DElementFloorObstacleLine.h index 2ac327e..4f596d3 100644 --- a/mapview/2D/MV2DElementFloorObstacleLine.h +++ b/mapview/2D/MV2DElementFloorObstacleLine.h @@ -32,8 +32,6 @@ public: return MapElementHelper::getLineDistanceXY(fo->from, fo->to, p); } - - /** repaint me */ void paint(Painter& p) override { @@ -58,7 +56,6 @@ public: // reset the old pen p.setPen(pen); - // available endpoints if (hasFocus()) { @@ -76,38 +73,8 @@ public: p.drawCircle_px(fo->to, 3); } - - - } -// void paintDoor(Painter& p) { - -// QPen pen; -// pen.setColor(QColor(0.5,0.5,0.5)); -// pen.setStyle(Qt::PenStyle::DotLine); -// p.setPenBrush(pen, Qt::NoBrush); - - -// // opening indicator -// const float open = M_PI / 4; -// 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; - -// p.drawLine(fo->from, fo->to); -// p.drawLine(fo->from, pOpen); - -// p.drawArc(fo->from, len, angle1, open); -// //p.drawLine(fo->to, pOpen); - -// // obstacle length -// p.setPenBrush(Qt::black, Qt::NoBrush); -// p.drawLength(fo->from, fo->to, fo->from.getDistance(fo->to)); - -// } - void onFocus() override { ; } @@ -135,7 +102,6 @@ public: emit v->onElementChange(this); } - }; #endif // MV2DELEMENTFLOOROBSTACLELINE_H diff --git a/mapview/2D/MapViewElementHelper.h b/mapview/2D/MapViewElementHelper.h index f84daf0..ccb6b1e 100644 --- a/mapview/2D/MapViewElementHelper.h +++ b/mapview/2D/MapViewElementHelper.h @@ -77,12 +77,13 @@ public: pen.setCapStyle(Qt::FlatCap); if (focus) {pen.setColor(Qt::black);} - if (mat == Material::CONCRETE) {;} - if (mat == Material::GLASS) {pen.setStyle(Qt::PenStyle::DotLine);} - if (mat == Material::METAL) {pen.setColor(QColor(50, 50, 50));} - if (type == ObstacleType::HANDRAIL) {pen.setStyle(Qt::PenStyle::DashLine);} - if (type == ObstacleType::UNKNOWN) {pen.setColor(Qt::red);} - if (type == ObstacleType::PILLAR) {pen.setColor(Qt::red);} + if (mat == Material::CONCRETE) {;} + if (mat == Material::GLASS) {pen.setStyle(Qt::PenStyle::DotLine);} + if (mat == Material::METALLIZED_GLAS) {pen.setStyle(Qt::PenStyle::DotLine);} + if (mat == Material::METAL) {pen.setColor(QColor(50, 50, 50));} + if (type == ObstacleType::HANDRAIL) {pen.setStyle(Qt::PenStyle::DashLine);} + if (type == ObstacleType::UNKNOWN) {pen.setColor(Qt::red);} + if (type == ObstacleType::PILLAR) {pen.setColor(Qt::red);} return pen; } diff --git a/mapview/2D/tools/ToolNewPillar.h b/mapview/2D/tools/ToolNewPillar.h new file mode 100644 index 0000000..185e3b0 --- /dev/null +++ b/mapview/2D/tools/ToolNewPillar.h @@ -0,0 +1,47 @@ +#ifndef TOOLNEWPILLAR_H +#define TOOLNEWPILLAR_H + +#include "ToolNewElement.h" +#include "../../model/MMFloorObstacles.h" +#include "../../model/MMFloorObstacleCircle.h" + +class ToolNewPillar : public ToolNewElement { + +public: + + ToolNewPillar(Tools& tools, MapLayer* layer) : ToolNewElement(tools, layer) { + ; + } + + void becomesActive() override { + emit onHelpTextChange("left-click where to place a new pillar. right-click to end."); + } + + void becomesInactive() override { + ; + } + + const std::string getName() const override { + return "new Pillar"; + } + + void moving(const Point2 mapPoint) override { + (void) mapPoint; + } + + void leftMouse(const Point2 mapPoint) override { + const Floorplan::Material mat = Floorplan::Material::CONCRETE; // default material + foEL = new Floorplan::FloorObstacleCircle(mat, mapPoint.x, mapPoint.y, 0.2);//"", Point3(mapPoint.x, mapPoint.y, 0.0), Point3(0,0,0)); + MMFloorObstacles* obs = (MMFloorObstacles*)layer; + mmEL = obs->createCircle(foEL); + } + + void rightMouse(const Point2 mapPoint) override { + (void) mapPoint; + finalizeCurrent(); + disableMe(); + } + +}; + +#endif // TOOLNEWPILLAR_H diff --git a/mapview/3D/MapView3D.cpp b/mapview/3D/MapView3D.cpp index fd483b2..06268f0 100644 --- a/mapview/3D/MapView3D.cpp +++ b/mapview/3D/MapView3D.cpp @@ -113,12 +113,13 @@ MapView3D::MapView3D(QWidget *parent) : QOpenGLWidget(parent) { auto format = QSurfaceFormat(); format.setRenderableType(QSurfaceFormat::OpenGL); - format.setVersion(3, 4); + //format.setVersion(3, 4); + //format.setSamples(2); + //format.setProfile(QSurfaceFormat::CompatibilityProfile); + //format.setOption(QSurfaceFormat::DebugContext); format.setSamples(2); - format.setProfile(QSurfaceFormat::CompatibilityProfile); - format.setOption(QSurfaceFormat::DebugContext); - setFormat(format); + setFormat(format); auto ver = format.version(); std::cout << "OpenGL Context Version: " << ver.first << "." << ver.second << std::endl; diff --git a/mapview/3D/floorplan/FloorplanRendererModel.h b/mapview/3D/floorplan/FloorplanRendererModel.h index 08e04b0..cc41f43 100644 --- a/mapview/3D/floorplan/FloorplanRendererModel.h +++ b/mapview/3D/floorplan/FloorplanRendererModel.h @@ -38,11 +38,14 @@ private: Material(140,140,140,255), // door (wood) Material(128,128,128,255), // concrete - Material(200,200,255,96), // glass + Material(240,240,255,96), // glass + Material(170,170,255,96), // glass (metallized) Material(170,120,60,255), // wood Material(200,200,200,255), // drywall - Material(255,255,255,255), // default + Material(255,255,255,255), // object + + Material(235,235,235,255), // default }; @@ -52,16 +55,19 @@ private: if (o.type == Ray3D::Obstacle3D::Type::GROUND_INDOOR) {return 1;} if (o.type == Ray3D::Obstacle3D::Type::STAIR) {return 2;} if (o.type == Ray3D::Obstacle3D::Type::HANDRAIL) {return 3;} + if (o.type == Ray3D::Obstacle3D::Type::OBJECT) {return 11;} if (o.type == Ray3D::Obstacle3D::Type::DOOR && o.mat == Floorplan::Material::GLASS) {return 4;} if (o.type == Ray3D::Obstacle3D::Type::DOOR) {return 5;} if (o.mat == Floorplan::Material::CONCRETE) {return 6;} if (o.mat == Floorplan::Material::GLASS) {return 7;} - if (o.mat == Floorplan::Material::WOOD) {return 8;} - if (o.mat == Floorplan::Material::DRYWALL) {return 9;} + if (o.mat == Floorplan::Material::METALLIZED_GLAS) {return 8;} - return 10; + if (o.mat == Floorplan::Material::WOOD) {return 9;} + if (o.mat == Floorplan::Material::DRYWALL) {return 10;} + + return 12; } diff --git a/mapview/3D/navMesh/QNavMeshSettings.cpp b/mapview/3D/navMesh/QNavMeshSettings.cpp index ebbabe2..243e57a 100644 --- a/mapview/3D/navMesh/QNavMeshSettings.cpp +++ b/mapview/3D/navMesh/QNavMeshSettings.cpp @@ -83,7 +83,7 @@ QNavMeshSettings::QNavMeshSettings(NM::NavMeshSettings* settings, QWidget* paren lay->addWidget(new QLabel("min region size"), row, 0); QLabel* lblMinRegionSize = new QLabel(""); lay->addWidget(lblMinRegionSize, row, 2); - QSlider* sldRegionMinSize = new QSlider(Qt::Orientation::Horizontal); sldRegionMinSize->setMinimum(400); sldRegionMinSize->setMaximum(10000); + QSlider* sldRegionMinSize = new QSlider(Qt::Orientation::Horizontal); sldRegionMinSize->setMinimum(400); sldRegionMinSize->setMaximum(99900); connect(sldRegionMinSize, &QSlider::valueChanged, [settings, sldRegionMinSize, lblMinRegionSize] () { settings->regionMinSize = sldRegionMinSize->value() / 100.0f; lblMinRegionSize->setText(QString("%1 m").arg(settings->regionMinSize, 5, 'f', 2, 0)); diff --git a/mapview/model/MMFloorObstacleCircle.h b/mapview/model/MMFloorObstacleCircle.h index 313dfb6..497cc1b 100644 --- a/mapview/model/MMFloorObstacleCircle.h +++ b/mapview/model/MMFloorObstacleCircle.h @@ -8,12 +8,14 @@ #include "IHasMaterial.h" #include "IHasObstacleType.h" +#include "IHasParams.h" + #include "../2D/MV2DElementFloorObstacleCircle.h" #include -class MMFloorObstacleCircle : public MapModelElement, public IHasMaterial { +class MMFloorObstacleCircle : public MapModelElement, public IHasMaterial, public IHasParams { private: @@ -41,6 +43,38 @@ public: mf->obstacles.erase(std::remove(mf->obstacles.begin(), mf->obstacles.end(), c), mf->obstacles.end()); } + /** get the number of parameters */ + int getNumParams() const override { + return 2; + } + + /** get the description of the idx-th parameter */ + virtual Param getParamDesc(const int idx) const override { + switch (idx) { + case 0: return Param("radius", ParamType::FLOAT); + case 1: return Param("height", ParamType::FLOAT); + default: throw Exception("out of bounds"); + } + } + + /** get the idx-th param's value */ + virtual ParamValue getParamValue(const int idx) const override { + switch(idx) { + case 0: return c->radius; + case 1: return c->height; + default: throw Exception("out of bounds"); + } + } + + /** set the idx-th param's value */ + virtual void setParamValue(const int idx, const ParamValue& val) override { + switch (idx) { + case 0: c->radius = val.toFloat(); break; + case 1: c->height = val.toFloat(); break; + default: throw Exception("out of bounds"); + } + } + }; #endif // MAPMODELELEMENTFLOOROBSTACLECIRCLE_H diff --git a/mapview/model/MMFloorObstacles.h b/mapview/model/MMFloorObstacles.h index 14c192e..a210ac6 100644 --- a/mapview/model/MMFloorObstacles.h +++ b/mapview/model/MMFloorObstacles.h @@ -77,13 +77,15 @@ public: } //TODO: check - void createCircle(Floorplan::FloorObstacleCircle* obs) { + MMFloorObstacleCircle* createCircle(Floorplan::FloorObstacleCircle* obs) { // add to underlying model floor->obstacles.push_back(obs); // add to myself as element - addElement(new MMFloorObstacleCircle(this, floor, obs)); + MMFloorObstacleCircle* mm = new MMFloorObstacleCircle(this, floor, obs); + addElement(mm); + return mm; } diff --git a/params/ElementParamWidget.cpp b/params/ElementParamWidget.cpp index c5fb866..673664b 100644 --- a/params/ElementParamWidget.cpp +++ b/params/ElementParamWidget.cpp @@ -25,12 +25,13 @@ QComboBox* getMaterials() { QComboBox* cmbMaterial = new QComboBox(); for (int i = 0; i < (int)Material::_END; ++i) { switch ((Material)i) { - case Material::CONCRETE: cmbMaterial->addItem("Concrete", i); break; - case Material::UNKNOWN: cmbMaterial->addItem("Unknown ", i); break; - case Material::DRYWALL: cmbMaterial->addItem("Drywall", i); break; - case Material::WOOD: cmbMaterial->addItem("Wood", i); break; - case Material::GLASS: cmbMaterial->addItem("Glass", i); break; - case Material::METAL: cmbMaterial->addItem("Metal", i); break; + case Material::CONCRETE: cmbMaterial->addItem("Concrete", i); break; + case Material::UNKNOWN: cmbMaterial->addItem("Unknown ", i); break; + case Material::DRYWALL: cmbMaterial->addItem("Drywall", i); break; + case Material::WOOD: cmbMaterial->addItem("Wood", i); break; + case Material::GLASS: cmbMaterial->addItem("Glass", i); break; + case Material::METAL: cmbMaterial->addItem("Metal", i); break; + case Material::METALLIZED_GLAS: cmbMaterial->addItem("Glass (metallized)", i); break; case Material::_END: throw 1; } } diff --git a/params/ToolBoxWidget.cpp b/params/ToolBoxWidget.cpp index f10ffdb..61bb300 100644 --- a/params/ToolBoxWidget.cpp +++ b/params/ToolBoxWidget.cpp @@ -31,6 +31,7 @@ #include "../mapview/2D/tools/ToolNewBeacon.h" #include "../mapview/2D/tools/ToolNewPOI.h" #include "../mapview/2D/tools/ToolNewObject.h" +#include "../mapview/2D/tools/ToolNewPillar.h" #include "../UIHelper.h" @@ -188,6 +189,8 @@ void ToolBoxWidget::onMainToolChanged() { btnObject->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); btnElevator->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); btnStair->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); + btnPillar->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); + btnFingerprintLocation->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); btnGTP->setStyleSheet( dynamic_cast(t) ? styleSel : styleNor ); @@ -268,21 +271,7 @@ void ToolBoxWidget::onNewObject() { } void ToolBoxWidget::onNewPillar() { - - const Point2 center = view->getScaler().getCenter(); - float s = view->getScaler().sm(50); - - Floorplan::FloorObstacleCircle* pillar = new Floorplan::FloorObstacleCircle( - Floorplan::Material::DRYWALL, - Point2(center.x-s, center.y), - s - ); - - MMFloorObstacles* obs = (MMFloorObstacles*)curLayer; - obs->createCircle(pillar); - - //view->getModel()->reselect(); - + view->getTools().setMain(new ToolNewPillar(view->getTools(), curLayer)); } diff --git a/res/mdl/tree1.obj b/res/mdl/tree1.obj new file mode 100644 index 0000000..89a2860 --- /dev/null +++ b/res/mdl/tree1.obj @@ -0,0 +1,138 @@ +# Blender v2.79 (sub 0) OBJ File: 'tree1.blend' +# www.blender.org +o Cylinder_Cylinder.001 +v -0.754967 -0.000000 0.002184 +v -0.325113 -0.000000 1.512119 +v -0.233298 0.718017 0.002184 +v -0.100465 0.309201 1.512119 +v 0.610782 0.443759 0.002184 +v 0.263022 0.191096 1.512119 +v 0.610781 -0.443759 0.002184 +v 0.263022 -0.191096 1.512119 +v -0.233298 -0.718017 0.002184 +v -0.100465 -0.309201 1.512119 +v -0.238977 -0.000000 4.531989 +v -0.073848 0.227281 4.531989 +v 0.193337 0.140467 4.531989 +v 0.193337 -0.140467 4.531989 +v -0.073848 -0.227281 4.531989 +v -2.277415 0.000000 5.084848 +v -0.703760 2.165951 5.084848 +v 1.842468 1.338631 5.084848 +v 1.842468 -1.338631 5.084848 +v -0.703760 -2.165951 5.084848 +v -3.560853 0.000000 6.623765 +v -1.100364 3.386573 6.623765 +v 2.880791 2.093017 6.623765 +v 2.880791 -2.093018 6.623765 +v -1.100365 -3.386573 6.623765 +v -2.588514 0.000000 8.162680 +v -0.799895 2.461823 8.162680 +v 2.094152 1.521490 8.162680 +v 2.094152 -1.521491 8.162680 +v -0.799895 -2.461823 8.162680 +v -0.364874 0.000000 9.701597 +v -0.112752 0.347016 9.701597 +v 0.295190 0.214468 9.701597 +v 0.295190 -0.214468 9.701597 +v -0.112752 -0.347016 9.701597 +vn -0.7884 0.5728 0.2244 +vn 0.3011 0.9268 0.2244 +vn 0.9745 -0.0000 0.2244 +vn 0.3089 0.9508 0.0231 +vn 0.3011 -0.9268 0.2244 +vn -0.7884 -0.5728 0.2244 +vn -0.0000 0.0000 -1.0000 +vn -0.2572 -0.1868 -0.9481 +vn -0.8088 -0.5876 0.0231 +vn -0.8088 0.5876 0.0231 +vn 0.9997 0.0000 0.0231 +vn 0.3089 -0.9508 0.0231 +vn 0.2562 -0.7884 -0.5593 +vn 0.3179 0.0000 -0.9481 +vn -0.2571 0.1868 -0.9481 +vn 0.0982 -0.3023 -0.9481 +vn 0.0982 0.3023 -0.9481 +vn 0.2752 0.8468 0.4551 +vn 0.2562 0.7884 -0.5593 +vn -0.6706 -0.4873 -0.5593 +vn 0.8290 0.0000 -0.5593 +vn -0.6706 0.4873 -0.5593 +vn 0.2009 0.6182 0.7599 +vn -0.7204 -0.5234 0.4551 +vn 0.8904 0.0000 0.4551 +vn -0.7204 0.5234 0.4551 +vn 0.2752 -0.8468 0.4551 +vn 0.0000 0.0000 1.0000 +vn -0.5259 -0.3821 0.7599 +vn 0.6500 0.0000 0.7599 +vn -0.5259 0.3821 0.7599 +vn 0.2009 -0.6182 0.7599 +vn -0.2572 0.1868 -0.9481 +s off +f 2//1 3//1 1//1 +f 4//2 5//2 3//2 +f 6//3 7//3 5//3 +f 4//4 13//4 6//4 +f 8//5 9//5 7//5 +f 10//6 1//6 9//6 +f 3//7 7//7 9//7 +f 15//8 16//8 11//8 +f 10//9 11//9 2//9 +f 2//10 12//10 4//10 +f 6//11 14//11 8//11 +f 8//12 15//12 10//12 +f 19//13 25//13 20//13 +f 14//14 18//14 19//14 +f 11//15 17//15 12//15 +f 14//16 20//16 15//16 +f 12//17 18//17 13//17 +f 22//18 28//18 23//18 +f 17//19 23//19 18//19 +f 20//20 21//20 16//20 +f 18//21 24//21 19//21 +f 17//22 21//22 22//22 +f 27//23 33//23 28//23 +f 21//24 30//24 26//24 +f 23//25 29//25 24//25 +f 22//26 26//26 27//26 +f 25//27 29//27 30//27 +f 31//28 34//28 33//28 +f 26//29 35//29 31//29 +f 29//30 33//30 34//30 +f 27//31 31//31 32//31 +f 30//32 34//32 35//32 +f 2//1 4//1 3//1 +f 4//2 6//2 5//2 +f 6//3 8//3 7//3 +f 4//4 12//4 13//4 +f 8//5 10//5 9//5 +f 10//6 2//6 1//6 +f 9//7 1//7 3//7 +f 3//7 5//7 7//7 +f 15//8 20//8 16//8 +f 10//9 15//9 11//9 +f 2//10 11//10 12//10 +f 6//11 13//11 14//11 +f 8//12 14//12 15//12 +f 19//13 24//13 25//13 +f 14//14 13//14 18//14 +f 11//33 16//33 17//33 +f 14//16 19//16 20//16 +f 12//17 17//17 18//17 +f 22//18 27//18 28//18 +f 17//19 22//19 23//19 +f 20//20 25//20 21//20 +f 18//21 23//21 24//21 +f 17//22 16//22 21//22 +f 27//23 32//23 33//23 +f 21//24 25//24 30//24 +f 23//25 28//25 29//25 +f 22//26 21//26 26//26 +f 25//27 24//27 29//27 +f 33//28 32//28 31//28 +f 31//28 35//28 34//28 +f 26//29 30//29 35//29 +f 29//30 28//30 33//30 +f 27//31 26//31 31//31 +f 30//32 29//32 34//32 diff --git a/res/mdl/yardBench1.obj b/res/mdl/yardBench1.obj new file mode 100644 index 0000000..d6d1786 --- /dev/null +++ b/res/mdl/yardBench1.obj @@ -0,0 +1,89 @@ +# Blender v2.79 (sub 0) OBJ File: 'yardBench1.blend' +# www.blender.org +o Cube.001_Cube.002 +v 2.300000 -2.300000 0.520000 +v 2.300000 -2.300000 0.620000 +v -2.300000 -2.300000 0.520000 +v -2.300000 -2.300000 0.620000 +v 2.300000 2.300000 0.520000 +v 2.300000 2.300000 0.620000 +v -2.300000 2.300000 0.520000 +v -2.300000 2.300000 0.620000 +v 1.533333 -1.533333 0.620000 +v 1.533333 -1.533333 0.520000 +v 1.533333 1.533333 0.620000 +v 1.533333 1.533333 0.520000 +v -0.570202 -1.533333 0.620000 +v -1.533333 -1.533333 0.620000 +v -1.533333 -1.533333 0.520000 +v -1.533333 1.533333 0.620000 +v -1.533333 1.533333 0.520000 +vn 0.0000 -1.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 0.0000 1.0000 +s off +f 2//1 3//1 1//1 +f 4//2 7//2 3//2 +f 8//3 5//3 7//3 +f 6//4 1//4 5//4 +f 7//5 12//5 17//5 +f 8//6 4//6 16//6 +f 11//1 17//1 12//1 +f 17//4 14//4 15//4 +f 13//6 4//6 2//6 +f 13//3 9//3 10//3 +f 10//2 11//2 12//2 +f 10//5 5//5 1//5 +f 2//1 4//1 3//1 +f 4//2 8//2 7//2 +f 8//3 6//3 5//3 +f 6//4 2//4 1//4 +f 15//5 3//5 7//5 +f 7//5 5//5 12//5 +f 17//5 15//5 7//5 +f 4//6 13//6 14//6 +f 16//6 11//6 6//6 +f 4//6 14//6 16//6 +f 16//6 6//6 8//6 +f 11//1 16//1 17//1 +f 17//4 16//4 14//4 +f 2//6 6//6 9//6 +f 6//6 11//6 9//6 +f 9//6 13//6 2//6 +f 10//3 15//3 13//3 +f 15//3 14//3 13//3 +f 10//2 9//2 11//2 +f 3//5 15//5 10//5 +f 10//5 12//5 5//5 +f 1//5 3//5 10//5 +o Cube_Cube.001 +v 2.200000 -2.200000 0.000000 +v 2.200000 -2.200000 0.500000 +v -2.200000 -2.200000 0.000000 +v -2.200000 -2.200000 0.500000 +v 2.200000 2.200000 0.000000 +v 2.200000 2.200000 0.500000 +v -2.200000 2.200000 0.000000 +v -2.200000 2.200000 0.500000 +vn 0.0000 -1.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 0.0000 1.0000 +s off +f 19//7 20//7 18//7 +f 21//8 24//8 20//8 +f 25//9 22//9 24//9 +f 23//10 18//10 22//10 +f 24//11 18//11 20//11 +f 21//12 23//12 25//12 +f 19//7 21//7 20//7 +f 21//8 25//8 24//8 +f 25//9 23//9 22//9 +f 23//10 19//10 18//10 +f 24//11 22//11 18//11 +f 21//12 19//12 23//12