Browse Source

EMF export

Johannes Kreutz 2 years ago
parent
commit
2726c642e4

+ 2 - 0
trackpoint-app/include/OpenScadRenderer.hpp

@@ -2,6 +2,7 @@
 
 // Include modules
 #include "OptiTrackPoint.hpp"
+#include "EMFTrackPoint.hpp"
 #include "SteamVRTrackPoint.hpp"
 
 // Include dependencies
@@ -11,6 +12,7 @@ class OpenScadRenderer {
 public:
   static bool openScadAvailable();
   void renderOptiTrack(std::vector<OptiTrackPoint*> points);
+  void renderEMFTrack(std::vector<EMFTrackPoint*> points);
   void renderSteamVRTrack(std::vector<SteamVRTrackPoint*> points);
 
 private:

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

@@ -30,6 +30,8 @@ public:
   osg::ref_ptr<osg::Geode> getMesh();
 
 private:
+  osg::Matrix emfYFix(osg::Vec3 normal);
+  osg::Vec3 getRotation(osg::Vec3 normal);
   osg::ref_ptr<osg::Switch> _selectionSwitch;
   osg::ref_ptr<osg::MatrixTransform> _selectionTranslateGroup;
   osg::ref_ptr<osg::MatrixTransform> _selectionRotateGroup;

+ 21 - 0
trackpoint-app/src/OpenScadRenderer.cpp

@@ -21,6 +21,11 @@ const char* openScadBase =
   "module optiTrackPointBase(translation, rotation, length, radius) {\n"
   "translate(translation) rotate(rotation) cylinder(length, radius, radius, false);\n"
   "}\n"
+  "module emfTrackPointBase(translation, rotation, width, height, depth) {\n"
+  "translate(translation) rotate(rotation) {\n"
+  "translate([-(width / 2), -(height / 2), 0]) cube([width, height, depth]);"
+  "}\n"
+  "}\n"
   "module steamVrTrackPointBase(translation, rotation, length) {\n"
   "translate(translation) rotate(rotation) {\n"
   "cylinder(length, 3.5, 3.5, false);\n"
@@ -49,6 +54,22 @@ void OpenScadRenderer::renderOptiTrack(std::vector<OptiTrackPoint*> points) {
   system(command.c_str());
 }
 
+void OpenScadRenderer::renderEMFTrack(std::vector<EMFTrackPoint*> points) {
+  std::ofstream scadFile;
+  scadFile.open(std::filesystem::temp_directory_path().u8string() + fileDelimiter + "trackpointapp_export_emftrack.scad");
+  scadFile << openScadBase;
+  scadFile << "difference() {\nimport(\"trackpointapp_export.3mf\");\n";
+  for (EMFTrackPoint* point: points) {
+    osg::Vec3 translation = point->getTranslation();
+    osg::Vec3 rotation = point->getRotation();
+    scadFile << "emfTrackPointBase([" << translation.x() << "," << translation.y() << "," << translation.z() << "], [" << rotation.x() << "," << rotation.y() << "," << rotation.z() << "], " << point->getWidth() << ", " << point->getHeight() << ", " << point->getDepth() << ");\n";
+  }
+  scadFile << "}\n";
+  scadFile.close();
+  std::string command = openScadPath + " -o " + std::filesystem::temp_directory_path().u8string() + fileDelimiter + "trackpointapp_render_emftrack.3mf " + std::filesystem::temp_directory_path().u8string() + fileDelimiter + "trackpointapp_export_emftrack.scad";
+  system(command.c_str());
+}
+
 void OpenScadRenderer::renderSteamVRTrack(std::vector<SteamVRTrackPoint*> points) {
   enableSteamvrThread();
   std::ofstream scadFile;

+ 4 - 0
trackpoint-app/src/PickHandler.cpp

@@ -196,6 +196,10 @@ void PickHandler::rotateToNormalVector(osg::Vec3f normal) {
   MainWindow::getInstance()->getEditWiget()->updateNormals(normal);
   if (_shape) {
     osg::Vec3 modifier = MainWindow::getInstance()->getStore()->getNormalModifier();
+    ActiveTrackingSystem activeTrackingSystem = MainWindow::getInstance()->getEditWiget()->getSelectedTrackingSystem();
+    if (activeTrackingSystem == EMFTrack) {
+      normal = normal.operator*(-1.0f);
+    }
     _shape->rotateToNormalVector(normal);
     _shape->setNormalModifier(modifier);
   }

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

@@ -50,11 +50,15 @@ void PointShape::setNormalModifier(osg::Vec3f normalModifier) {
 void PointShape::rotateToNormalVector(osg::Vec3f normal) {
   osg::Matrix modifierRotation = osg::Matrix::rotate(_normalModifier.x() * M_PI / 180, osg::Vec3(1.0f, 0.0f, 0.0f), _normalModifier.y() * M_PI / 180, osg::Vec3(0.0f, 1.0f, 0.0f), _normalModifier.z() * M_PI / 180, osg::Vec3(0.0f, 0.0f, 1.0f));
   normal = modifierRotation.preMult(normal);
+  normal.normalize();
+  osg::Matrix rotationMatrix;
   if (_activeTrackingSystem == EMFTrack) {
-    normal = normal.operator*(-1.0f);
+    osg::Vec3 angles = getRotation(normal);
+    rotationMatrix = osg::Matrix::rotate(angles.x() * M_PI / 180, osg::Vec3(1.0f, 0.0f, 0.0f), angles.y() * M_PI / 180, osg::Vec3(0.0f, 1.0f, 0.0f), angles.z() * M_PI / 180, osg::Vec3(0.0f, 0.0f, 1.0f));
+  } else {
+    rotationMatrix = osg::Matrix::rotate(osg::Vec3f(0.0f, 0.0f, 1.0f), normal);
   }
-  normal.normalize();
-  _selectionRotateGroup->setMatrix(osg::Matrix::rotate(osg::Vec3f(0.0f, 0.0f, 1.0f), normal));
+  _selectionRotateGroup->setMatrix(rotationMatrix);
   if (_activeTrackingSystem == OptiTrack || _activeTrackingSystem == SteamVRTrack) {
     osg::Vec3f movementVector = normal.operator*(_optiTrackSteamVRLength / 2);
     _selectionMoveToEndGroup->setMatrix(osg::Matrix::translate(movementVector));
@@ -136,3 +140,37 @@ void PointShape::setupActionPoints() {
 osg::ref_ptr<osg::Geode> PointShape::getMesh() {
   return _geode;
 }
+
+osg::Matrix PointShape::emfYFix(osg::Vec3 normal) {
+  osg::Vec3 xyNormal = osg::Vec3(normal.x(), normal.y(), 0.0f);
+  xyNormal.normalize();
+  float deg = (90.0f * M_PI / 180) * normal.x() * -1;
+  return osg::Matrix::rotate(deg, normal);
+}
+
+osg::Vec3 PointShape::getRotation(osg::Vec3 normal) {
+  osg::Vec3 start = osg::Vec3(0.0f, 0.0f, 1.0f);
+  osg::Vec3 finalNormal = normal;
+
+  // From https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
+  osg::Quat quat = osg::Quat(0.0f, 0.0f, 0.0f, 0.0f);
+  quat.makeRotate(start, finalNormal);
+
+  float sinr_cosp = 2 * (quat.w() * quat.x() + quat.y() * quat.z());
+  float cosr_cosp = 1 - 2 * (quat.x() * quat.x() + quat.y() * quat.y());
+  float xRotation = std::atan2(sinr_cosp, cosr_cosp) * 180.0 / M_PI;
+
+  float sinp = 2 * (quat.w() * quat.y() - quat.z() * quat.x());
+  float yRotation;
+  if (std::abs(sinp) >= 1) {
+    yRotation = std::copysign(M_PI / 2, sinp) * 180.0 / M_PI;
+  } else {
+    yRotation = std::asin(sinp) * 180.0 / M_PI;
+  }
+
+  float siny_cosp = 2 * (quat.w() * quat.z() + quat.x() * quat.y());
+  float cosy_cosp = 1 - 2 * (quat.y() * quat.y() + quat.z() * quat.z());
+  float zRotation = std::atan2(siny_cosp, cosy_cosp) * 180.0 / M_PI;
+
+  return osg::Vec3(xRotation, yRotation, zRotation);
+}

+ 32 - 0
trackpoint-app/src/ProjectStore.cpp

@@ -134,7 +134,38 @@ bool ProjectStore::exportProject(std::string path, ExportSettings settings) {
     exportModel->AddBuildItem(exportMesh.get(), _wrapper->GetIdentityTransform());
   }
   if (settings.EMFTrack) {
+    renderer->renderEMFTrack(_emfTrackPoints);
+    Lib3MF::PModel emfTrackModel = _wrapper->CreateModel();
+    Lib3MF::PReader reader = emfTrackModel->QueryReader("3mf");
+    reader->ReadFromFile(std::filesystem::temp_directory_path().u8string() + fileDelimiter + "trackpointapp_render_emftrack.3mf");
+    Lib3MF::PMeshObjectIterator meshIterator = emfTrackModel->GetMeshObjects();
+    if (meshIterator->Count() != 1) {
+      return false;
+    }
+    meshIterator->MoveNext();
+    Lib3MF::PMeshObject renderedMesh = meshIterator->GetCurrentMeshObject();
+    Lib3MF::PMeshObject exportMesh = exportModel->AddMeshObject();
+    exportMesh->SetName("emftrack");
+    std::vector<Lib3MF::sPosition> verticesBuffer;
+    std::vector<Lib3MF::sTriangle> triangleBuffer;
+    renderedMesh->GetVertices(verticesBuffer);
+    renderedMesh->GetTriangleIndices(triangleBuffer);
+    exportMesh->SetGeometry(verticesBuffer, triangleBuffer);
+    json trackpointData = json::array();
+    for (EMFTrackPoint* point: _emfTrackPoints) {
+      osg::Vec3 moveToMid = point->getNormal().operator*(-(point->getDepth() / 2));
+      osg::Vec3 trackPoint = point->getTrackPoint().operator+(moveToMid);
+      osg::Vec3 trackNormal = point->getNormal();
+      json pointData = {
+        {"point", {trackPoint.x(), trackPoint.y(), trackPoint.z()}},
+        {"normal", {trackNormal.x(), trackNormal.y(), trackNormal.z()}}
+      };
+      trackpointData.push_back(pointData);
+    }
 
+    Lib3MF::PMetaDataGroup emfMetaData = exportMesh->GetMetaDataGroup();
+    emfMetaData->AddMetaData(META_NAMESPACE, "trackpoints-emftrack", trackpointData.dump(), "string", true);
+    exportModel->AddBuildItem(exportMesh.get(), _wrapper->GetIdentityTransform());
   }
   if (settings.SteamVRTrack) {
     renderer->renderSteamVRTrack(_steamVrTrackPoints);
@@ -228,6 +259,7 @@ void ProjectStore::addTrackPoint(osg::Vec3 point, osg::Vec3 normal, ActiveTracki
       break;
     }
     case EMFTrack: {
+      normal = normal.operator*(-1.0f);
       EMFTrackPoint* emfTrackPoint = new EMFTrackPoint(point, normal, _normalModifier, _emfTrackSettings.width, _emfTrackSettings.height, _emfTrackSettings.depth);
       _emfTrackPoints.push_back(emfTrackPoint);
       break;