Browse Source

Basic work: add SteamVRTrack and ActionPoints

Johannes Kreutz 2 years ago
parent
commit
ed56459771

BIN
testdata/testExport2.trackproj


+ 1 - 0
trackpoint-app/CMakeLists.txt

@@ -67,6 +67,7 @@ QT_ADD_EXECUTABLE(TrackpointApp
   src/PickHandler.cpp
   src/TrackPoint.cpp
   src/OptiTrackPoint.cpp
+  src/ActionPoint.cpp
   src/SteamVRTrackPoint.cpp
   src/OpenScadRenderer.cpp
   src/StringBasics.cpp

+ 118 - 6
trackpoint-app/gui/EditWidget.ui

@@ -402,7 +402,7 @@
        <item>
         <widget class="QTabWidget" name="tabWidget">
          <property name="sizePolicy">
-          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
            <horstretch>0</horstretch>
            <verstretch>0</verstretch>
           </sizepolicy>
@@ -440,7 +440,7 @@
              </property>
              <layout class="QVBoxLayout" name="verticalLayout_5">
               <item>
-               <layout class="QGridLayout" name="gridLayout">
+               <layout class="QGridLayout" name="optiTrackGrid">
                 <item row="0" column="1">
                  <widget class="QDoubleSpinBox" name="optiTrackLength">
                   <property name="minimum">
@@ -487,6 +487,19 @@
              </layout>
             </widget>
            </item>
+           <item>
+            <spacer name="optiTrackSpacer">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>0</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
           </layout>
          </widget>
          <widget class="QWidget" name="emfTrack">
@@ -501,9 +514,9 @@
             <number>3</number>
            </property>
            <item>
-            <widget class="QPushButton" name="emfTrackExport">
+            <widget class="QLabel" name="emfTrackCount">
              <property name="text">
-              <string>Export for use with EMF Tracking</string>
+              <string>TRACKPOINTS SET: 0</string>
              </property>
             </widget>
            </item>
@@ -521,12 +534,67 @@
             <number>3</number>
            </property>
            <item>
-            <widget class="QPushButton" name="pushButton_2">
+            <widget class="QLabel" name="steamVrTrackCount">
              <property name="text">
-              <string>Export for use with SteamVR Tracking</string>
+              <string>TRACKPOINTS SET: 0</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QGroupBox" name="steamVrProperties">
+             <property name="font">
+              <font>
+               <pointsize>13</pointsize>
+              </font>
              </property>
+             <property name="title">
+              <string>PROPERTIES</string>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_8">
+              <item>
+               <layout class="QGridLayout" name="steamVrTrackGrid">
+                <item row="1" column="0">
+                 <widget class="QLabel" name="steamVrTrackLengthLabel">
+                  <property name="text">
+                   <string>Length</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="1">
+                 <widget class="QDoubleSpinBox" name="steamVrTrackLength">
+                  <property name="maximum">
+                   <double>100.000000000000000</double>
+                  </property>
+                  <property name="value">
+                   <double>5.000000000000000</double>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </item>
+              <item>
+               <widget class="QPushButton" name="steamVrTrackLoadDefaults">
+                <property name="text">
+                 <string>Load defaults</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
             </widget>
            </item>
+           <item>
+            <spacer name="steamVrSpacer">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>0</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
           </layout>
          </widget>
          <widget class="QWidget" name="actionPoints">
@@ -540,6 +608,50 @@
            <property name="bottomMargin">
             <number>3</number>
            </property>
+           <item>
+            <widget class="QLabel" name="actionPointCount">
+             <property name="text">
+              <string>ACTION POINTS SET: 0</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLineEdit" name="actionPointIdentifier">
+             <property name="text">
+              <string>point0</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QLabel" name="actionPointDoubleIdentifier">
+             <property name="styleSheet">
+              <string notr="true">color: red;</string>
+             </property>
+             <property name="text">
+              <string>Identifier already in use! Not updated.</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="actionPointLoadDefaults">
+             <property name="text">
+              <string>Reset identifier</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="actionPointSpacer">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>0</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
           </layout>
          </widget>
         </widget>

+ 17 - 0
trackpoint-app/include/ActionPoint.hpp

@@ -0,0 +1,17 @@
+#pragma once
+
+// Include modules
+#include "defaults.hpp"
+#include "TrackPoint.hpp"
+#include "TrackSystemSettingsStructs.hpp"
+
+class ActionPoint: public TrackPoint {
+public:
+  ActionPoint(const osg::Vec3 point, const osg::Vec3 normal, const osg::Vec3 normalModifier, const std::string identifier = ACTIONPOINT_DEFAULT_IDENFIFIER);
+  std::string getIdentifier();
+  ActionPointSettings getActionPointSettings();
+  void updateActionPointSettings(ActionPointSettings settings);
+
+private:
+  std::string _identifier;
+};

+ 8 - 0
trackpoint-app/include/EditWidget.hpp

@@ -30,12 +30,20 @@ protected:
 
 private slots:
   void selectTool(Tool tool);
+  void resetAllSettings();
+  void tabChanged(int index);
   void updateNormalModifier();
   void resetNormalModifier();
   void setNormalModifier(osg::Vec3 normalModifier);
   void updateOptiTrackSettings();
   void resetOptiTrackSettings();
   void setOptiTrackSettings(double length, double radius);
+  void updateSteamVRTrackSettings();
+  void resetSteamVRTrackSettings();
+  void setSteamVRTrackSettings(double length);
+  void updateActionPointSettings(QString input);
+  void resetActionPointSettings();
+  void setActionPointSettings(std::string identifier);
   void deleteCurrentTrackPoint();
   void exportProject();
 

+ 1 - 4
trackpoint-app/include/PickHandler.hpp

@@ -17,10 +17,8 @@ public:
   void updateRenderer();
 
 private:
+  PointShape* _shape = nullptr;
   osg::ref_ptr<osg::Switch> _selectionSwitch;
-  osg::ref_ptr<osg::MatrixTransform> _selectionTranslateGroup;
-  osg::ref_ptr<osg::MatrixTransform> _selectionRotateGroup;
-  osg::ref_ptr<osg::MatrixTransform> _selectionMoveToEndGroup;
   bool _addNewPoints = true;
   bool _clickStartedOnElement = false;
   OSGWidget* _osgWidget;
@@ -28,7 +26,6 @@ private:
   int _selectedPoint = -1;
   void moveTo(osg::Vec3f position);
   void rotateToNormalVector(osg::Vec3f normal);
-  void removeAllShapes();
   void setVisibility(bool mode);
   void addPoint(osg::Vec3 point, osg::Vec3 normal);
   void invalidateTrackPointColors();

+ 3 - 0
trackpoint-app/include/PointShape.hpp

@@ -22,6 +22,8 @@ public:
   void setVisibility(bool mode);
   void setColor(osg::Vec4 color);
   void setupOptiTrack(OptiTrackSettings optiTrackSettings);
+  void setupSteamVRTrack(SteamVRTrackSettings steamVrTrackSettings);
+  void setupActionPoints();
   osg::ref_ptr<osg::Geode> getMesh();
 
 private:
@@ -29,6 +31,7 @@ private:
   osg::ref_ptr<osg::MatrixTransform> _selectionTranslateGroup;
   osg::ref_ptr<osg::MatrixTransform> _selectionRotateGroup;
   osg::ref_ptr<osg::MatrixTransform> _selectionMoveToEndGroup;
+  osg::ref_ptr<osg::MatrixTransform> _screwMove;
   osg::ref_ptr<osg::Group> _renderRoot;
   osg::ref_ptr<osg::ShapeDrawable> _shape;
   osg::ref_ptr<osg::Geode> _geode;

+ 10 - 2
trackpoint-app/include/ProjectStore.hpp

@@ -4,6 +4,7 @@
 #include "lib3mf_implicit.hpp"
 #include "OptiTrackPoint.hpp"
 #include "SteamVRTrackPoint.hpp"
+#include "ActionPoint.hpp"
 #include "TrackSystemSettingsStructs.hpp"
 #include "OpenScadRenderer.hpp"
 #include "enums.hpp"
@@ -60,7 +61,13 @@ public:
   SteamVRTrackSettings getSteamVRTrackSettings();
   // ACTION POINTS
   // Get all Action points
-  std::vector<TrackPoint*> getActionPoints();
+  std::vector<ActionPoint*> getActionPoints();
+  // Update actual Action point settings
+  void updateActionPointSettings(ActionPointSettings actionPointSettings);
+  // Return Action point settings
+  ActionPointSettings getActionPointSettings();
+  // Check if an identifier is already in use
+  bool actionPointIdentifierInUse(std::string candidate);
 
 private:
   bool _projectLoaded;
@@ -70,10 +77,11 @@ private:
   std::string _projectFile;
   std::vector<OptiTrackPoint*> _optiTrackPoints;
   std::vector<SteamVRTrackPoint*> _steamVrTrackPoints;
-  std::vector<TrackPoint*> _actionPoints;
+  std::vector<ActionPoint*> _actionPoints;
   OptiTrackSettings _optiTrackSettings = OptiTrackSettings {OPTITRACK_DEFAULT_LENGTH, OPTITRACK_DEFAULT_RADIUS};
   EMFTrackSettings _emfTrackSettings;
   SteamVRTrackSettings _steamVrTrackSettings = SteamVRTrackSettings {STEAMVR_DEFAULT_LENGTH};
+  ActionPointSettings _actionPointSettings = ActionPointSettings {ACTIONPOINT_DEFAULT_IDENFIFIER};
   osg::Vec3 _normalModifier = osg::Vec3(0.0f, 0.0f, 0.0f);
   void load3mfLib();
   void render3MFMesh();

+ 6 - 0
trackpoint-app/include/TrackSystemSettingsStructs.hpp

@@ -1,5 +1,7 @@
 #pragma once
 
+#include <string>
+
 typedef struct {
   bool OptiTrack;
   bool EMFTrack;
@@ -20,3 +22,7 @@ typedef struct {
 typedef struct {
   double length;
 } SteamVRTrackSettings;
+
+typedef struct {
+  std::string identifier;
+} ActionPointSettings;

+ 4 - 0
trackpoint-app/include/defaults.hpp

@@ -1,6 +1,10 @@
 #pragma once
 
+#include <string>
+
 #define OPTITRACK_DEFAULT_LENGTH 10.0
 #define OPTITRACK_DEFAULT_RADIUS 1.0
 
 #define STEAMVR_DEFAULT_LENGTH 10.0
+
+#define ACTIONPOINT_DEFAULT_IDENFIFIER "point0"

BIN
trackpoint-app/resources/steamvrthread.stl


+ 18 - 0
trackpoint-app/src/ActionPoint.cpp

@@ -0,0 +1,18 @@
+// Include own headers
+#include "ActionPoint.hpp"
+
+ActionPoint::ActionPoint(const osg::Vec3 point, const osg::Vec3 normal, const osg::Vec3 normalModifier, const std::string identifier): TrackPoint(point, normal, normalModifier) {
+  _identifier = identifier;
+}
+
+std::string ActionPoint::getIdentifier() {
+  return _identifier;
+}
+
+ActionPointSettings ActionPoint::getActionPointSettings() {
+  return ActionPointSettings {_identifier};
+}
+
+void ActionPoint::updateActionPointSettings(ActionPointSettings settings) {
+  _identifier = settings.identifier;
+}

+ 131 - 20
trackpoint-app/src/EditWidget.cpp

@@ -13,11 +13,13 @@
 
 EditWidget::EditWidget(QWidget* parent): QWidget(parent), ui(new Ui::EditWidget) {
   ui->setupUi(this);
+  ui->actionPointDoubleIdentifier->setVisible(false);
   ui->insertionToolButton->setCheckable(true);
   ui->insertionToolButton->setChecked(true);
   QObject::connect(ui->insertionToolButton, &QToolButton::clicked, this, [=](){ this->selectTool(InsertionTool); });
   ui->selectionToolButton->setCheckable(true);
   QObject::connect(ui->selectionToolButton, &QToolButton::clicked, this, [=](){ this->selectTool(SelectionTool); });
+  QObject::connect(ui->tabWidget, &QTabWidget::currentChanged, this, &EditWidget::tabChanged);
   // Modifiers
   QObject::connect(ui->normalModX, &QDoubleSpinBox::valueChanged, this, &EditWidget::updateNormalModifier);
   QObject::connect(ui->normalModY, &QDoubleSpinBox::valueChanged, this, &EditWidget::updateNormalModifier);
@@ -27,6 +29,12 @@ EditWidget::EditWidget(QWidget* parent): QWidget(parent), ui(new Ui::EditWidget)
   QObject::connect(ui->optiTrackLength, &QDoubleSpinBox::valueChanged, this, &EditWidget::updateOptiTrackSettings);
   QObject::connect(ui->optiTrackRadius, &QDoubleSpinBox::valueChanged, this, &EditWidget::updateOptiTrackSettings);
   QObject::connect(ui->optiTrackLoadDefaults, &QPushButton::clicked, this, &EditWidget::resetOptiTrackSettings);
+  // StramVRTrack settings
+  QObject::connect(ui->steamVrTrackLength, &QDoubleSpinBox::valueChanged, this, &EditWidget::updateSteamVRTrackSettings);
+  QObject::connect(ui->steamVrTrackLoadDefaults, &QPushButton::clicked, this, &EditWidget::resetSteamVRTrackSettings);
+  // Action point settings
+  QObject::connect(ui->actionPointIdentifier, &QLineEdit::textChanged, this, &EditWidget::updateActionPointSettings);
+  QObject::connect(ui->actionPointLoadDefaults, &QPushButton::clicked, this, &EditWidget::resetActionPointSettings);
   // Delete button
   QObject::connect(ui->deleteTrackPoint, &QPushButton::clicked, this, &EditWidget::deleteCurrentTrackPoint);
   // Export button
@@ -95,9 +103,19 @@ void EditWidget::setSelection(int id) {
       break;
     }
     case 2: {
+      SteamVRTrackPoint* point = MainWindow::getInstance()->getStore()->getSteamVRTrackPoints()[id];
+      updatePositions(point->getTranslation());
+      updateNormals(point->getNormal());
+      setNormalModifier(point->getNormalModifier());
+      setSteamVRTrackSettings(point->getLength());
       break;
     }
     default: {
+      ActionPoint* point = MainWindow::getInstance()->getStore()->getActionPoints()[id];
+      updatePositions(point->getTranslation());
+      updateNormals(point->getNormal());
+      setNormalModifier(point->getNormalModifier());
+      setActionPointSettings(point->getIdentifier());
       break;
     }
   }
@@ -108,30 +126,41 @@ int EditWidget::getSelectedPoint() {
 }
 
 void EditWidget::updateTrackpointCount() {
-  ActiveTrackingSystem activeTrackingSystem = getSelectedTrackingSystem();
-  int count = MainWindow::getInstance()->getStore()->getCount(activeTrackingSystem);
-  switch(activeTrackingSystem) {
-    case OptiTrack: {
-      QString countString("TRACKPOINTS SET: ");
-      countString.append(QString::number(count));
-      ui->optiTrackCount->setText(countString);
-      break;
-    }
-    case EMFTrack: {
-      break;
-    }
-    case SteamVRTrack: {
-      break;
-    }
-    case ActionPoints: {
-      break;
-    }
+  int count;
+  count = MainWindow::getInstance()->getStore()->getCount(OptiTrack);
+  {
+    QString countString("TRACKPOINTS SET: ");
+    countString.append(QString::number(count));
+    ui->optiTrackCount->setText(countString);
+  }
+
+  // TODO: EMF Track
+
+  count = MainWindow::getInstance()->getStore()->getCount(SteamVRTrack);
+  {
+    QString countString("TRACKPOINTS SET: ");
+    countString.append(QString::number(count));
+    ui->steamVrTrackCount->setText(countString);
+  }
+
+  count = MainWindow::getInstance()->getStore()->getCount(ActionPoints);
+  {
+    QString countString("ACTION POINTS SET: ");
+    countString.append(QString::number(count));
+    ui->actionPointCount->setText(countString);
   }
 }
 
 void EditWidget::showEvent(QShowEvent* event) {
   QWidget::showEvent(event);
+  resetAllSettings();
+}
+
+void EditWidget::resetAllSettings() {
+  resetNormalModifier();
   resetOptiTrackSettings();
+  resetSteamVRTrackSettings();
+  resetActionPointSettings();
 }
 
 void EditWidget::selectTool(Tool tool) {
@@ -141,8 +170,7 @@ void EditWidget::selectTool(Tool tool) {
       ui->selectionToolButton->setChecked(false);
       MainWindow::getInstance()->getOsgWidget()->getPicker()->setSelection(true);
       invalidatePositions();
-      resetNormalModifier();
-      resetOptiTrackSettings();
+      resetAllSettings();
       selectedPoint = -1;
       break;
     }
@@ -155,6 +183,15 @@ void EditWidget::selectTool(Tool tool) {
   }
 }
 
+void EditWidget::tabChanged(int index) {
+  if (selectedPoint < 0) {
+    MainWindow::getInstance()->getOsgWidget()->getPicker()->updateRenderer();
+  }
+  selectedPoint = -1;
+  ActiveTrackingSystem activeTrackingSystem = getSelectedTrackingSystem();
+  MainWindow::getInstance()->getOsgWidget()->getPointRenderer()->render(activeTrackingSystem);
+}
+
 void EditWidget::updateNormalModifier() {
   osg::Vec3 modifier = osg::Vec3(ui->normalModX->value(), ui->normalModY->value(), ui->normalModZ->value());
   if (selectedPoint < 0) {
@@ -217,6 +254,79 @@ void EditWidget::setOptiTrackSettings(double length, double radius) {
   ui->optiTrackRadius->setValue(radius);
 }
 
+void EditWidget::updateSteamVRTrackSettings() {
+  SteamVRTrackSettings settings = {ui->steamVrTrackLength->value()};
+  if (selectedPoint < 0) {
+    MainWindow::getInstance()->getStore()->updateSteamVRTrackSettings(settings);
+    MainWindow::getInstance()->getOsgWidget()->getPicker()->updateRenderer();
+  } else {
+    MainWindow::getInstance()->getStore()->getSteamVRTrackPoints()[selectedPoint]->updateSteamVRTrackSettings(settings);
+    MainWindow::getInstance()->getOsgWidget()->getPointRenderer()->render(SteamVRTrack);
+  }
+}
+
+void EditWidget::resetSteamVRTrackSettings() {
+  SteamVRTrackSettings settings = {STEAMVR_DEFAULT_LENGTH};
+  ui->steamVrTrackLength->setValue(STEAMVR_DEFAULT_LENGTH);
+  if (selectedPoint < 0) {
+    MainWindow::getInstance()->getStore()->updateSteamVRTrackSettings(settings);
+    MainWindow::getInstance()->getOsgWidget()->getPicker()->updateRenderer();
+  } else {
+    MainWindow::getInstance()->getStore()->getSteamVRTrackPoints()[selectedPoint]->updateSteamVRTrackSettings(settings);
+    MainWindow::getInstance()->getOsgWidget()->getPointRenderer()->render(SteamVRTrack);
+  }
+}
+
+void EditWidget::setSteamVRTrackSettings(double length) {
+  ui->steamVrTrackLength->setValue(length);
+}
+
+void EditWidget::updateActionPointSettings(QString qinput) {
+  std::string input = qinput.toUtf8().constData();
+  if (MainWindow::getInstance()->getStore()->actionPointIdentifierInUse(input)) {
+    ui->actionPointDoubleIdentifier->setVisible(true);
+  } else {
+    ui->actionPointDoubleIdentifier->setVisible(false);
+    QString qtext = ui->actionPointIdentifier->text();
+    ActionPointSettings settings = {qtext.toUtf8().constData()};
+    if (selectedPoint < 0) {
+      MainWindow::getInstance()->getStore()->updateActionPointSettings(settings);
+    } else {
+      MainWindow::getInstance()->getStore()->getActionPoints()[selectedPoint]->updateActionPointSettings(settings);
+    }
+  }
+}
+
+void EditWidget::resetActionPointSettings() {
+  int iterator = 0;
+  ActionPointSettings settings;
+  std::string candidate;
+  while (true) {
+    candidate = "point";
+    candidate += std::to_string(iterator);
+    bool result = MainWindow::getInstance()->getStore()->actionPointIdentifierInUse(candidate);
+    if (!result) {
+      settings = {candidate};
+      break;
+    }
+  }
+  ui->actionPointIdentifier->setText(QString::fromStdString(candidate));
+  if (selectedPoint < 0) {
+    MainWindow::getInstance()->getStore()->updateActionPointSettings(settings);
+  } else {
+    MainWindow::getInstance()->getStore()->getActionPoints()[selectedPoint]->updateActionPointSettings(settings);
+  }
+}
+
+void EditWidget::setActionPointSettings(std::string identifier) {
+  if (MainWindow::getInstance()->getStore()->actionPointIdentifierInUse(identifier)) {
+    ui->actionPointDoubleIdentifier->setVisible(true);
+  } else {
+    ui->actionPointDoubleIdentifier->setVisible(false);
+    ui->actionPointIdentifier->setText(QString::fromStdString(identifier));
+  }
+}
+
 void EditWidget::deleteCurrentTrackPoint() {
   ActiveTrackingSystem activeTrackingSystem = getSelectedTrackingSystem();
   MainWindow::getInstance()->getStore()->removeTrackPoint(selectedPoint, activeTrackingSystem);
@@ -230,6 +340,7 @@ void EditWidget::deleteCurrentTrackPoint() {
       break;
     }
     case SteamVRTrack: {
+      resetSteamVRTrackSettings();
       break;
     }
     case ActionPoints: {

+ 29 - 35
trackpoint-app/src/PickHandler.cpp

@@ -19,16 +19,8 @@
 PickHandler::PickHandler(OSGWidget* osgWidget, osg::ref_ptr<osg::Group> root) {
   _osgWidget = osgWidget;
 
-  _selectionRotateGroup = new osg::MatrixTransform;
-
-  _selectionMoveToEndGroup = new osg::MatrixTransform;
-  _selectionMoveToEndGroup->addChild(_selectionRotateGroup.get());
-
-  _selectionTranslateGroup = new osg::MatrixTransform;
-  _selectionTranslateGroup->addChild(_selectionMoveToEndGroup.get());
-
   _selectionSwitch = new osg::Switch;
-  _selectionSwitch->addChild(_selectionTranslateGroup.get());
+
 
   root->addChild(_selectionSwitch.get());
 }
@@ -159,51 +151,53 @@ void PickHandler::setSelection(bool addNewPoints) {
   updateRenderer();
 }
 
-void PickHandler::moveTo(osg::Vec3f position) {
-  _selectionTranslateGroup->setMatrix(osg::Matrix::translate(position));
-  MainWindow::getInstance()->getEditWiget()->updatePositions(position);
-}
-
-void PickHandler::rotateToNormalVector(osg::Vec3f normal) {
-  MainWindow::getInstance()->getEditWiget()->updateNormals(normal);
-  osg::Vec3 modifier = MainWindow::getInstance()->getStore()->getNormalModifier();
-  normal = normal.operator+(modifier);
-  normal.normalize();
-  _selectionRotateGroup->setMatrix(osg::Matrix::rotate(osg::Vec3f(0.0f, 0.0f, 1.0f), normal));
-  osg::Vec3f movementVector = normal.operator*(_optiTrackSteamVRLength / 2);
-  _selectionMoveToEndGroup->setMatrix(osg::Matrix::translate(movementVector));
-}
-
 void PickHandler::updateRenderer() {
-  removeAllShapes();
-  switch(MainWindow::getInstance()->getEditWiget()->getSelectedTrackingSystem()) {
+  delete _shape;
+  ActiveTrackingSystem activeTrackingSystem = MainWindow::getInstance()->getEditWiget()->getSelectedTrackingSystem();
+  switch(activeTrackingSystem) {
     case OptiTrack: {
       OptiTrackSettings settings = MainWindow::getInstance()->getStore()->getOptiTrackSettings();
       _optiTrackSteamVRLength = settings.length;
-      osg::ref_ptr<osg::Geode> geode = new osg::Geode;
-      osg::ref_ptr<osg::ShapeDrawable> cylinder = new osg::ShapeDrawable();
-      cylinder->setShape(new osg::Cylinder(osg::Vec3(0.0f, 0.0f, 0.0f), settings.radius, settings.length));
-      cylinder->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 0.2f));
-      geode->addDrawable(cylinder.get());
-      OSGWidget::fixMaterialState(geode);
-      _selectionRotateGroup->addChild(geode.get());
+      _shape = new PointShape(_selectionSwitch, activeTrackingSystem, osg::Vec3(0.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 0.0f));
+      _shape->setupOptiTrack(settings);
       break;
     }
     case EMFTrack: {
       break;
     }
     case SteamVRTrack: {
+      SteamVRTrackSettings settings = MainWindow::getInstance()->getStore()->getSteamVRTrackSettings();
+      _optiTrackSteamVRLength = settings.length;
+      _shape = new PointShape(_selectionSwitch, activeTrackingSystem, osg::Vec3(0.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 0.0f));
+      _shape->setupSteamVRTrack(settings);
       break;
     }
     case ActionPoints: {
+      _shape = new PointShape(_selectionSwitch, activeTrackingSystem, osg::Vec3(0.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, 0.0f));
+      _shape->setupActionPoints();
       break;
     }
   }
+  if (_shape) {
+    _shape->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 0.2f));
+  }
   setVisibility(_addNewPoints);
 }
 
-void PickHandler::removeAllShapes() {
-  _selectionRotateGroup->removeChildren(0, _selectionRotateGroup->getNumChildren());
+void PickHandler::moveTo(osg::Vec3f position) {
+  if (_shape) {
+    _shape->moveTo(position);
+    MainWindow::getInstance()->getEditWiget()->updatePositions(position);
+  }
+}
+
+void PickHandler::rotateToNormalVector(osg::Vec3f normal) {
+  MainWindow::getInstance()->getEditWiget()->updateNormals(normal);
+  if (_shape) {
+    osg::Vec3 modifier = MainWindow::getInstance()->getStore()->getNormalModifier();
+    _shape->rotateToNormalVector(normal);
+    _shape->setNormalModifier(modifier);
+  }
 }
 
 void PickHandler::setVisibility(bool mode) {

+ 41 - 2
trackpoint-app/src/PointShape.cpp

@@ -4,14 +4,20 @@
 // Include modules
 #include "OSGWidget.hpp"
 
+// Include dependencies
+#include <osgDB/ReadFile>
+
 PointShape::PointShape(const osg::ref_ptr<osg::Group> renderRoot, const ActiveTrackingSystem activeTrackingSystem, osg::Vec3f point, osg::Vec3f normal, osg::Vec3f normalModifier) {
   _renderRoot = renderRoot;
   _activeTrackingSystem = activeTrackingSystem;
 
   _selectionRotateGroup = new osg::MatrixTransform;
 
+  _screwMove = new osg::MatrixTransform;
+
   _selectionMoveToEndGroup = new osg::MatrixTransform;
   _selectionMoveToEndGroup->addChild(_selectionRotateGroup.get());
+  _selectionMoveToEndGroup->addChild(_screwMove.get());
 
   _selectionTranslateGroup = new osg::MatrixTransform;
   _selectionTranslateGroup->addChild(_selectionMoveToEndGroup.get());
@@ -42,8 +48,14 @@ void PointShape::rotateToNormalVector(osg::Vec3f normal) {
   normal = normal.operator+(_normalModifier);
   normal.normalize();
   _selectionRotateGroup->setMatrix(osg::Matrix::rotate(osg::Vec3f(0.0f, 0.0f, 1.0f), normal));
-  osg::Vec3f movementVector = normal.operator*(_optiTrackSteamVRLength / 2);
-  _selectionMoveToEndGroup->setMatrix(osg::Matrix::translate(movementVector));
+  if (_activeTrackingSystem == OptiTrack || _activeTrackingSystem == SteamVRTrack) {
+    osg::Vec3f movementVector = normal.operator*(_optiTrackSteamVRLength / 2);
+    _selectionMoveToEndGroup->setMatrix(osg::Matrix::translate(movementVector));
+  }
+  if (_activeTrackingSystem == SteamVRTrack) {
+    osg::Vec3f movementVector = normal.operator*(_optiTrackSteamVRLength);
+    _screwMove->setMatrix(osg::Matrix::translate(movementVector));
+  }
 }
 
 void PointShape::setVisibility(bool mode) {
@@ -67,6 +79,33 @@ void PointShape::setupOptiTrack(OptiTrackSettings optiTrackSettings) {
   }
 }
 
+void PointShape::setupSteamVRTrack(SteamVRTrackSettings steamVrTrackSettings) {
+  if (_activeTrackingSystem == SteamVRTrack) {
+    _optiTrackSteamVRLength = steamVrTrackSettings.length;
+    _geode = new osg::Geode;
+    _shape = new osg::ShapeDrawable();
+    _shape->setShape(new osg::Cylinder(osg::Vec3(0.0f, 0.0f, 0.0f), 1.0f, steamVrTrackSettings.length));
+    _shape->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 0.2f));
+    _geode->addDrawable(_shape.get());
+    osg::ref_ptr<osg::Node> screw = osgDB::readNodeFile("../resources/steamvrthread.stl");
+    _screwMove->addChild(screw.get());
+    OSGWidget::fixMaterialState(_geode);
+    _selectionRotateGroup->addChild(_geode.get());
+  }
+}
+
+void PointShape::setupActionPoints() {
+  if (_activeTrackingSystem == ActionPoints) {
+    _geode = new osg::Geode;
+    _shape = new osg::ShapeDrawable();
+    _shape->setShape(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 0.5f));
+    _shape->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 0.2f));
+    _geode->addDrawable(_shape.get());
+    OSGWidget::fixMaterialState(_geode);
+    _selectionRotateGroup->addChild(_geode.get());
+  }
+}
+
 osg::ref_ptr<osg::Geode> PointShape::getMesh() {
   return _geode;
 }

+ 94 - 15
trackpoint-app/src/ProjectStore.cpp

@@ -125,10 +125,10 @@ TrackPoint* ProjectStore::getTrackPointById(int id, ActiveTrackingSystem activeT
       break;
     };
     case SteamVRTrack: {
-      break;
+      return _steamVrTrackPoints[id];
     };
     case ActionPoints: {
-      break;
+      return _actionPoints[id];
     };
   }
 }
@@ -138,7 +138,6 @@ void ProjectStore::addTrackPoint(osg::Vec3 point, osg::Vec3 normal, ActiveTracki
     case OptiTrack: {
       OptiTrackPoint* optiTrackPoint = new OptiTrackPoint(point, normal, _normalModifier, _optiTrackSettings.length, _optiTrackSettings.radius);
       _optiTrackPoints.push_back(optiTrackPoint);
-      MainWindow::getInstance()->getEditWiget()->updateTrackpointCount();
       break;
     }
     case EMFTrack: {
@@ -147,13 +146,15 @@ void ProjectStore::addTrackPoint(osg::Vec3 point, osg::Vec3 normal, ActiveTracki
     case SteamVRTrack: {
       SteamVRTrackPoint* steamVrTrackPoint = new SteamVRTrackPoint(point, normal, _normalModifier, _steamVrTrackSettings.length);
       _steamVrTrackPoints.push_back(steamVrTrackPoint);
-      MainWindow::getInstance()->getEditWiget()->updateTrackpointCount();
       break;
     }
     case ActionPoints: {
+      ActionPoint* actionPoint = new ActionPoint(point, normal, _normalModifier, _actionPointSettings.identifier);
+      _actionPoints.push_back(actionPoint);
       break;
     }
   }
+  MainWindow::getInstance()->getEditWiget()->updateTrackpointCount();
 }
 
 int ProjectStore::getCount(ActiveTrackingSystem activeTrackingSystem) {
@@ -165,10 +166,10 @@ int ProjectStore::getCount(ActiveTrackingSystem activeTrackingSystem) {
       break;
     };
     case SteamVRTrack: {
-      break;
+      return _steamVrTrackPoints.size();
     };
     case ActionPoints: {
-      break;
+      return _actionPoints.size();
     };
   }
 }
@@ -183,9 +184,11 @@ void ProjectStore::removeTrackPoint(int id, ActiveTrackingSystem activeTrackingS
       break;
     }
     case SteamVRTrack: {
+      _steamVrTrackPoints.erase(_steamVrTrackPoints.begin() + id);
       break;
     }
     case ActionPoints: {
+      _actionPoints.erase(_actionPoints.begin() + id);
       break;
     }
   }
@@ -224,10 +227,27 @@ SteamVRTrackSettings ProjectStore::getSteamVRTrackSettings() {
   return _steamVrTrackSettings;
 }
 
-std::vector<TrackPoint*> ProjectStore::getActionPoints() {
+std::vector<ActionPoint*> ProjectStore::getActionPoints() {
   return _actionPoints;
 }
 
+void ProjectStore::updateActionPointSettings(ActionPointSettings actionPointSettings) {
+  _actionPointSettings = actionPointSettings;
+}
+
+ActionPointSettings ProjectStore::getActionPointSettings() {
+  return _actionPointSettings;
+}
+
+bool ProjectStore::actionPointIdentifierInUse(std::string candidate) {
+  for (ActionPoint* actionPoint: _actionPoints) {
+    if (candidate.compare(actionPoint->getIdentifier()) != 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void ProjectStore::load3mfLib() {
   _wrapper = Lib3MF::CWrapper::loadLibrary();
   _project = _wrapper->CreateModel();
@@ -300,6 +320,35 @@ void ProjectStore::updateMetaData() {
   } catch (Lib3MF::ELib3MFException &e) {
     metaData->AddMetaData(META_NAMESPACE, "optitrack", optiTrackData.dump(), "string", true);
   }
+  json steamVrTrackData = json::array();
+  for (SteamVRTrackPoint* steamVrTrackPoint: _steamVrTrackPoints) {
+    steamVrTrackData.push_back({
+      {"point", osgVecToStdVec(steamVrTrackPoint->getTranslation())},
+      {"normal", osgVecToStdVec(steamVrTrackPoint->getNormal())},
+      {"normalModifier", osgVecToStdVec(steamVrTrackPoint->getNormalModifier())},
+      {"length", steamVrTrackPoint->getLength()}
+    });
+  }
+  try {
+    Lib3MF::PMetaData steamVrTrackPoints = metaData->GetMetaDataByKey(META_NAMESPACE, "steamvrtrack");
+    steamVrTrackPoints->SetValue(steamVrTrackData.dump());
+  } catch (Lib3MF::ELib3MFException &e) {
+    metaData->AddMetaData(META_NAMESPACE, "steamvrtrack", steamVrTrackData.dump(), "string", true);
+  }
+  json actionPointData = json::array();
+  for (ActionPoint* actionPoint: _actionPoints) {
+    actionPointData.push_back({
+      {"point", osgVecToStdVec(actionPoint->getTranslation())},
+      {"normal", osgVecToStdVec(actionPoint->getNormal())},
+      {"normalModifier", osgVecToStdVec(actionPoint->getNormalModifier())}
+    });
+  }
+  try {
+    Lib3MF::PMetaData actionPoints = metaData->GetMetaDataByKey(META_NAMESPACE, "actionpoints");
+    actionPoints->SetValue(actionPointData.dump());
+  } catch (Lib3MF::ELib3MFException &e) {
+    metaData->AddMetaData(META_NAMESPACE, "actionpoints", actionPointData.dump(), "string", true);
+  }
 }
 
 void ProjectStore::loadMetaData() {
@@ -313,17 +362,47 @@ void ProjectStore::loadMetaData() {
   Lib3MF::PMetaData optiTrackString;
   try {
     optiTrackString = metaData->GetMetaDataByKey(META_NAMESPACE, "optitrack");
+    auto optiTrackData = json::parse(optiTrackString->GetValue());
+    _optiTrackPoints.clear();
+    for (const auto pointData: optiTrackData) {
+      osg::Vec3f point = osg::Vec3f(pointData["point"][0], pointData["point"][1], pointData["point"][2]);
+      osg::Vec3f normal = osg::Vec3f(pointData["normal"][0], pointData["normal"][1], pointData["normal"][2]);
+      osg::Vec3f normalModifier = osg::Vec3f(pointData["normalModifier"][0], pointData["normalModifier"][1], pointData["normalModifier"][2]);
+      OptiTrackPoint* optiTrackPoint = new OptiTrackPoint(point, normal, normalModifier, static_cast<double>(pointData["length"]), static_cast<double>(pointData["radius"]));
+      _optiTrackPoints.push_back(optiTrackPoint);
+    }
+  } catch (Lib3MF::ELib3MFException &e) {
+    // TODO: Something is wrong with the file
+  }
+  Lib3MF::PMetaData steamVrTrackString;
+  try {
+    steamVrTrackString = metaData->GetMetaDataByKey(META_NAMESPACE, "steamvrtrack");
+    auto steamVrData = json::parse(steamVrTrackString->GetValue());
+    _steamVrTrackPoints.clear();
+    for (const auto pointData: steamVrData) {
+      osg::Vec3f point = osg::Vec3f(pointData["point"][0], pointData["point"][1], pointData["point"][2]);
+      osg::Vec3f normal = osg::Vec3f(pointData["normal"][0], pointData["normal"][1], pointData["normal"][2]);
+      osg::Vec3f normalModifier = osg::Vec3f(pointData["normalModifier"][0], pointData["normalModifier"][1], pointData["normalModifier"][2]);
+      SteamVRTrackPoint* steamVrTrackPoint = new SteamVRTrackPoint(point, normal, normalModifier, static_cast<double>(pointData["length"]));
+      _steamVrTrackPoints.push_back(steamVrTrackPoint);
+    }
   } catch (Lib3MF::ELib3MFException &e) {
     // TODO: Something is wrong with the file
   }
-  auto optiTrackData = json::parse(optiTrackString->GetValue());
-  _optiTrackPoints.clear();
-  for (const auto pointData: optiTrackData) {
-    osg::Vec3f point = osg::Vec3f(pointData["point"][0], pointData["point"][1], pointData["point"][2]);
-    osg::Vec3f normal = osg::Vec3f(pointData["normal"][0], pointData["normal"][1], pointData["normal"][2]);
-    osg::Vec3f normalModifier = osg::Vec3f(pointData["normalModifier"][0], pointData["normalModifier"][1], pointData["normalModifier"][2]);
-    OptiTrackPoint* optiTrackPoint = new OptiTrackPoint(point, normal, normalModifier, static_cast<double>(pointData["length"]), static_cast<double>(pointData["radius"]));
-    _optiTrackPoints.push_back(optiTrackPoint);
+  Lib3MF::PMetaData actionPointString;
+  try {
+    actionPointString = metaData->GetMetaDataByKey(META_NAMESPACE, "actionpoints");
+    auto actionPointData = json::parse(actionPointString->GetValue());
+    _actionPoints.clear();
+    for (const auto pointData: actionPointData) {
+      osg::Vec3f point = osg::Vec3f(pointData["point"][0], pointData["point"][1], pointData["point"][2]);
+      osg::Vec3f normal = osg::Vec3f(pointData["normal"][0], pointData["normal"][1], pointData["normal"][2]);
+      osg::Vec3f normalModifier = osg::Vec3f(pointData["normalModifier"][0], pointData["normalModifier"][1], pointData["normalModifier"][2]);
+      ActionPoint* actionPoint = new ActionPoint(point, normal, normalModifier);
+      _actionPoints.push_back(actionPoint);
+    }
+  } catch (Lib3MF::ELib3MFException &e) {
+    // TODO: Something is wrong with the file
   }
   render3MFMesh();
   MainWindow::getInstance()->renderView(Edit);

+ 28 - 0
trackpoint-app/src/TrackPointRenderer.cpp

@@ -43,9 +43,37 @@ void TrackPointRenderer::render(ActiveTrackingSystem activeTrackingSystem) {
       break;
     }
     case SteamVRTrack: {
+      std::vector<SteamVRTrackPoint*> points = MainWindow::getInstance()->getStore()->getSteamVRTrackPoints();
+      int id = 0;
+      for (SteamVRTrackPoint* point: points) {
+        PointShape* newShape = new PointShape(_renderRoot, activeTrackingSystem, point->getTranslation(), point->getNormal(), point->getNormalModifier());
+        newShape->setupSteamVRTrack(point->getSteamVRTrackSettings());
+        if (id == MainWindow::getInstance()->getEditWiget()->getSelectedPoint()) {
+          newShape->setColor(osg::Vec4(0.0f, 0.0f, 1.0f, 0.2f));
+        } else {
+          newShape->setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 0.2f));
+        }
+        newShape->rotateToNormalVector(point->getNormal());
+        _shapes.push_back(newShape);
+        id++;
+      }
       break;
     }
     case ActionPoints: {
+      std::vector<ActionPoint*> points = MainWindow::getInstance()->getStore()->getActionPoints();
+      int id = 0;
+      for (ActionPoint* point: points) {
+        PointShape* newShape = new PointShape(_renderRoot, activeTrackingSystem, point->getTranslation(), point->getNormal(), point->getNormalModifier());
+        newShape->setupActionPoints();
+        if (id == MainWindow::getInstance()->getEditWiget()->getSelectedPoint()) {
+          newShape->setColor(osg::Vec4(0.0f, 0.0f, 1.0f, 0.2f));
+        } else {
+          newShape->setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 0.2f));
+        }
+        newShape->rotateToNormalVector(point->getNormal());
+        _shapes.push_back(newShape);
+        id++;
+      }
       break;
     }
   }