Browse Source

Implement project store and load

Johannes Kreutz 2 years ago
parent
commit
67805a49a5

+ 9 - 1
trackpoint-app/include/MainWindow.hpp

@@ -25,10 +25,18 @@ public:
   EditWidget* getEditWiget();
 
 private:
-  void openFile();
+  void load();
+  void save();
+  void saveAs();
   Ui::MainWindow* ui;
   OSGWidget* osgWidget;
   NoMeshWidget* noMeshWidget;
   EditWidget* editWidget;
   ProjectStore* projectStore;
+  QMenu* fileMenu;
+  QAction* newAct;
+  QAction* loadAct;
+  QAction* saveAct;
+  QAction* saveAsAct;
+  QAction* closeAct;
 };

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

@@ -7,6 +7,9 @@
 
 // Include dependencies
 #include <string>
+#include <nlohmann/json.hpp>
+
+using json = nlohmann::json;
 
 class ProjectStore {
 public:
@@ -42,7 +45,8 @@ public:
   OptiTrackSettings getOptiTrackSettings();
 
 private:
-  bool projectLoaded;
+  bool _projectLoaded;
+  bool _projectModified;
   Lib3MF::PWrapper _wrapper;
   Lib3MF::PModel _project;
   std::string _projectFile;
@@ -52,6 +56,9 @@ private:
   SteamVRTrackSettings _steamVrTrackSettings;
   osg::Vec3 _normalModifier = osg::Vec3(0.0f, 0.0f, 0.0f);
   void load3mfLib();
-  void render3MFMesh(const std::vector<Lib3MF::sPosition> verticesBuffer, const std::vector<Lib3MF::sTriangle> triangleBuffer);
-  void exportMetaData();
+  void render3MFMesh();
+  void updateMetaData();
+  void loadMetaData();
+  std::vector<float> osgVecToStdVec(osg::Vec3f input);
+  osg::Vec3f stdVecToOsgVec(std::vector<float> input);
 };

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

@@ -1,17 +0,0 @@
-#pragma once
-
-#include "TrackPoint.hpp"
-
-#include "lib3mf_implicit.hpp"
-#include <nlohmann/json.hpp>
-
-using json = nlohmann::json;
-
-class ThreeMFWriter {
-public:
-  ThreeMFWriter();
-  void writeTrackPoints(std::vector<TrackPoint*> points, std::string path);
-
-private:
-  Lib3MF::PWrapper _wrapper;
-};

+ 53 - 2
trackpoint-app/src/MainWindow.cpp

@@ -25,6 +25,41 @@ MainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::MainWin
   // TODO: Add option for opening a project via double click
   projectStore = new ProjectStore();
   renderView(NoMesh);
+
+  // Setup menu
+  newAct = new QAction(tr("&New project"), this);
+  newAct->setShortcuts(QKeySequence::New);
+  newAct->setStatusTip(tr("Create a new file"));
+  //connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
+
+  loadAct = new QAction(tr("&Load project"), this);
+  loadAct->setShortcuts(QKeySequence::Open);
+  loadAct->setStatusTip(tr("Load an existing project"));
+  connect(loadAct, &QAction::triggered, this, &MainWindow::load);
+
+  saveAct = new QAction(tr("&Save project"), this);
+  saveAct->setShortcuts(QKeySequence::Save);
+  saveAct->setStatusTip(tr("Update the project file"));
+  connect(saveAct, &QAction::triggered, this, &MainWindow::save);
+
+  saveAsAct = new QAction(tr("&Save project as"), this);
+  saveAsAct->setStatusTip(tr("Save the project in a new file"));
+  connect(saveAsAct, &QAction::triggered, this, &MainWindow::saveAs);
+
+  closeAct = new QAction(tr("&Close project"), this);
+  closeAct->setShortcuts(QKeySequence::Close);
+  closeAct->setStatusTip(tr("Closing the current project"));
+  //connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
+
+  fileMenu = menuBar()->addMenu(tr("&File"));
+  fileMenu->addAction(newAct);
+  fileMenu->addSeparator();
+  fileMenu->addAction(loadAct);
+  fileMenu->addSeparator();
+  fileMenu->addAction(saveAct);
+  fileMenu->addAction(saveAsAct);
+  fileMenu->addSeparator();
+  fileMenu->addAction(closeAct);
 }
 
 MainWindow::~MainWindow() {
@@ -59,6 +94,22 @@ void MainWindow::renderView(GuiView view) {
   }
 }
 
-void MainWindow::openFile() {
-  QString fileName = QFileDialog::getOpenFileName(this, tr("Open a TrackpointApp project or a 3D-Object"), "", tr("TrackpointApp Project (*.trackproj);;3MF File (*.3mf);;STL File (*.stl)"));
+void MainWindow::load() {
+  QString fileName = QFileDialog::getOpenFileName(this, tr("Open a TrackpointApp Project"), "", tr("TrackpointApp Projects (*.trackproj)"));
+  std::string projectFile = fileName.toUtf8().constData();
+  MainWindow::getInstance()->getStore()->loadProject(projectFile);
+}
+
+void MainWindow::save() {
+  if (!projectStore->saveProject()) {
+    saveAs();
+  }
+}
+
+void MainWindow::saveAs() {
+  QString fileName = QFileDialog::getSaveFileName(this, tr("Save your TrackpointApp Project"), "", tr("TrackpointApp Projects (*.trackproj)"));
+  std::string fileString = fileName.toUtf8().constData();
+  if (!projectStore->saveProject(fileString)) {
+    // TODO: Show error popup
+  }
 }

+ 2 - 2
trackpoint-app/src/NoMeshWidget.cpp

@@ -26,6 +26,6 @@ void NoMeshWidget::loadMeshFile() {
 
 void NoMeshWidget::loadProjectFile() {
   QString fileName = QFileDialog::getOpenFileName(this, tr("Open a TrackpointApp Project"), "", tr("TrackpointApp Projects (*.trackproj)"));
-  std::string meshFile = fileName.toUtf8().constData();
-  // TODO: Connect
+  std::string projectFile = fileName.toUtf8().constData();
+  MainWindow::getInstance()->getStore()->loadProject(projectFile);
 }

+ 95 - 27
trackpoint-app/src/ProjectStore.cpp

@@ -4,13 +4,17 @@
 // Include modules
 #include "MainWindow.hpp"
 #include "StringBasics.hpp"
+#include "TrackPointRenderer.hpp"
 
 // Include dependencies
 #include <typeinfo>
 #include <iostream>
 
+#define META_NAMESPACE "tk-ar-tracking"
+
 ProjectStore::ProjectStore() {
-  projectLoaded = false;
+  _projectLoaded = false;
+  _projectModified = false;
   load3mfLib();
 }
 
@@ -21,28 +25,12 @@ void ProjectStore::loadMesh(std::string meshFile) {
   if (StringBasics::endsWithCaseInsensitive(meshFile, ".STL")) {
     printf("Currently unsupported.\n");
   } else if (StringBasics::endsWithCaseInsensitive(meshFile, ".3MF")) {
-    projectLoaded = true;
+    _projectLoaded = true;
     // Read 3MF file
     Lib3MF::PReader reader = _project->QueryReader("3mf");
     reader->ReadFromFile(meshFile);
-    // Get meshes
-    Lib3MF::PMeshObjectIterator meshIterator = _project->GetMeshObjects();
-    // Our use case supports just a single mesh per project
-    if (meshIterator->Count() != 1) {
-      // TODO: Show error popup
-      printf("Not 1 mesh: %llu\n", meshIterator->Count());
-      return;
-    }
-    meshIterator->MoveNext();
-    Lib3MF::PMeshObject mesh = meshIterator->GetCurrentMeshObject();
-    // Load vertices and triangles and render them
-    std::vector<Lib3MF::sPosition> verticesBuffer;
-    mesh->GetVertices(verticesBuffer);
-    std::vector<Lib3MF::sTriangle> triangleBuffer;
-    mesh->GetTriangleIndices(triangleBuffer);
-    render3MFMesh(verticesBuffer, triangleBuffer);
-    MainWindow* mainWindow = MainWindow::getInstance();
-    mainWindow->renderView(Edit);
+    render3MFMesh();
+    MainWindow::getInstance()->renderView(Edit);
   } else {
     // TODO: Show error popup
     printf("Unsupported file type.\n");
@@ -50,10 +38,12 @@ void ProjectStore::loadMesh(std::string meshFile) {
 }
 
 bool ProjectStore::loadProject(std::string projectFile) {
-  if (!projectLoaded) {
+  if (!_projectLoaded) {
     Lib3MF::PReader reader = _project->QueryReader("3mf");
     reader->ReadFromFile(projectFile);
-    projectLoaded = true;
+    _projectLoaded = true;
+    _projectModified = false;
+    loadMetaData();
     return true;
   }
   return false;
@@ -61,16 +51,16 @@ bool ProjectStore::loadProject(std::string projectFile) {
 
 bool ProjectStore::saveProject() {
   if (_projectFile != "") {
-    Lib3MF::PWriter writer = _project->QueryWriter("3mf");
-    writer->WriteToFile(_projectFile);
-    return true;
+    return saveProject(_projectFile);
   }
   return false;
 }
 
 bool ProjectStore::saveProject(std::string path) {
+  updateMetaData();
   Lib3MF::PWriter writer = _project->QueryWriter("3mf");
   writer->WriteToFile(path);
+  _projectFile = path;
   return true;
 }
 
@@ -112,7 +102,23 @@ void ProjectStore::load3mfLib() {
   _project = _wrapper->CreateModel();
 }
 
-void ProjectStore::render3MFMesh(const std::vector<Lib3MF::sPosition> verticesBuffer, const std::vector<Lib3MF::sTriangle> triangleBuffer) {
+void ProjectStore::render3MFMesh() {
+  // Get meshes
+  Lib3MF::PMeshObjectIterator meshIterator = _project->GetMeshObjects();
+  // Our use case supports just a single mesh per project
+  if (meshIterator->Count() != 1) {
+    // TODO: Show error popup
+    printf("Not 1 mesh: %llu\n", meshIterator->Count());
+    return;
+  }
+  meshIterator->MoveNext();
+  Lib3MF::PMeshObject mesh = meshIterator->GetCurrentMeshObject();
+  // Load vertices and triangles and render them
+  std::vector<Lib3MF::sPosition> verticesBuffer;
+  mesh->GetVertices(verticesBuffer);
+  std::vector<Lib3MF::sTriangle> triangleBuffer;
+  mesh->GetTriangleIndices(triangleBuffer);
+
   // Create osg style arrays
   osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
   osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
@@ -139,6 +145,68 @@ void ProjectStore::render3MFMesh(const std::vector<Lib3MF::sPosition> verticesBu
   mainWindow->getOsgWidget()->renderBaseMesh(vertices, normals);
 }
 
-void ProjectStore::exportMetaData() {
+void ProjectStore::updateMetaData() {
+  Lib3MF::PMetaDataGroup metaData = _project->GetMetaDataGroup();
+  try {
+    Lib3MF::PMetaData versionInformation = metaData->GetMetaDataByKey(META_NAMESPACE, "format");
+  } catch (Lib3MF::ELib3MFException &e) {
+    metaData->AddMetaData(META_NAMESPACE, "format", "1.0.0", "string", true);
+  }
+
+  json optiTrackData = json::array();
+  for (OptiTrackPoint* optiTrackPoint: _optiTrackPoints) {
+    optiTrackData.push_back({
+      {"point", osgVecToStdVec(optiTrackPoint->getTranslation())},
+      {"normal", osgVecToStdVec(optiTrackPoint->getNormal())},
+      {"normalModifier", osgVecToStdVec(optiTrackPoint->getNormalModifier())},
+      {"length", optiTrackPoint->getLength()},
+      {"radius", optiTrackPoint->getRadius()}
+    });
+  }
+  try {
+    Lib3MF::PMetaData optiTrackPoints = metaData->GetMetaDataByKey(META_NAMESPACE, "optitrack");
+    optiTrackPoints->SetValue(optiTrackData.dump());
+  } catch (Lib3MF::ELib3MFException &e) {
+    metaData->AddMetaData(META_NAMESPACE, "optitrack", optiTrackData.dump(), "string", true);
+  }
+}
+
+void ProjectStore::loadMetaData() {
+  Lib3MF::PMetaDataGroup metaData = _project->GetMetaDataGroup();
+  try {
+    Lib3MF::PMetaData versionInformation = metaData->GetMetaDataByKey(META_NAMESPACE, "format");
+  } catch (Lib3MF::ELib3MFException &e) {
+    // TODO: Alert not a TrackpointApp poject
+  }
+
+  Lib3MF::PMetaData optiTrackString;
+  try {
+    optiTrackString = metaData->GetMetaDataByKey(META_NAMESPACE, "optitrack");
+  } 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);
+  }
+  render3MFMesh();
+  MainWindow::getInstance()->renderView(Edit);
+  MainWindow::getInstance()->getOsgWidget()->getPointRenderer()->render(MainWindow::getInstance()->getEditWiget()->getSelectedTrackingSystem());
+}
+
+std::vector<float> ProjectStore::osgVecToStdVec(osg::Vec3f input) {
+  std::vector<float> vector;
+  vector.push_back(input.x());
+  vector.push_back(input.y());
+  vector.push_back(input.z());
+  return vector;
+}
 
+osg::Vec3f ProjectStore::stdVecToOsgVec(std::vector<float> input) {
+  return osg::Vec3f(input[0], input[1], input[2]);
 }