Browse Source

Fix renderer, some cleanup

Johannes Kreutz 2 years ago
parent
commit
f85bdae897

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

@@ -33,5 +33,5 @@ private:
   OSGWidget* osgWidget;
   NoMeshWidget* noMeshWidget;
   EditWidget* editWidget;
-  ProjectStore projectStore;
+  ProjectStore* projectStore;
 };

+ 2 - 1
trackpoint-app/include/OSGWidget.hpp

@@ -31,7 +31,8 @@ class OSGWidget : public QOpenGLWidget {
 public:
   OSGWidget(QWidget* parent = nullptr);
   virtual ~OSGWidget();
-  void renderBaseMesh(const std::vector<Lib3MF::sPosition> &verticesBuffer, const std::vector<Lib3MF::sTriangle> &triangleBuffer);
+  void renderBaseMesh(const osg::ref_ptr<osg::Vec3Array> vertices, const osg::ref_ptr<osg::Vec3Array> normals);
+  static void fixMaterialState(osg::ref_ptr<osg::Node> node);
 
 protected:
   virtual void paintEvent(QPaintEvent* paintEvent);

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

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "lib3mf_implicit.hpp"
+
 #include <string>
 
 class ProjectStore {
@@ -15,7 +17,8 @@ public:
 
 private:
   bool projectLoaded;
-  //Lib3MF::PWrapper _wrapper;
-  //Lib3MF::PModel _project;
+  Lib3MF::PWrapper _wrapper;
+  Lib3MF::PModel _project;
   void load3mfLib();
+  void render3MFMesh(const std::vector<Lib3MF::sPosition> verticesBuffer, const std::vector<Lib3MF::sTriangle> triangleBuffer);
 };

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

@@ -20,9 +20,8 @@ MainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::MainWin
   ui->sceneWidget->layout()->addWidget(osgWidget);
 
   // TODO: Add option for opening a project via double click
-  //projectStore = new ProjectStore();
+  projectStore = new ProjectStore();
   renderView(NoMesh);
-  projectStore.loadMesh("/home/johannes/Documents/GitLab/bachelorthesis/testdata/testbutton.3mf");
 }
 
 MainWindow::~MainWindow() {
@@ -35,7 +34,7 @@ OSGWidget* MainWindow::getOsgWidget() {
 }
 
 ProjectStore* MainWindow::getStore() {
-  return &projectStore;
+  return projectStore;
 }
 
 void MainWindow::renderView(GuiView view) {

+ 17 - 34
trackpoint-app/src/OSGWidget.cpp

@@ -14,7 +14,7 @@
 #include <osgGA/TrackballManipulator>
 #include <osgUtil/LineSegmentIntersector>
 #include <osgUtil/IntersectionVisitor>
-#include <osgUtil/SmoothingVisitor>
+#include <osgUtil/MeshOptimizers>
 #include <osg/PolygonMode>
 
 #include <osgDB/WriteFile>
@@ -45,6 +45,16 @@ namespace osgWidget {
   }
 }
 
+void OSGWidget::fixMaterialState(osg::ref_ptr<osg::Node> node) {
+  osg::StateSet* stateSet = node->getOrCreateStateSet();
+  osg::Material* material = new osg::Material;
+
+  material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
+
+  stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
+  stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
+}
+
 OSGWidget::OSGWidget(QWidget* parent): QOpenGLWidget(parent),
   graphicsWindow_(new osgViewer::GraphicsWindowEmbedded(this->x(), this->y(), this->width(), this->height())),
   _viewer(new osgWidget::Viewer),
@@ -77,15 +87,7 @@ OSGWidget::OSGWidget(QWidget* parent): QOpenGLWidget(parent),
   zAxis->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
   _coordinateAxes->addDrawable(zAxis.get());
 
-  {
-    osg::StateSet* stateSet = _coordinateAxes->getOrCreateStateSet();
-    osg::Material* material = new osg::Material;
-
-    material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
-
-    stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
-    stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-  }
+  OSGWidget::fixMaterialState(_coordinateAxes);
 
   _root->addChild(_coordinateAxes);
 
@@ -124,36 +126,17 @@ OSGWidget::OSGWidget(QWidget* parent): QOpenGLWidget(parent),
 OSGWidget::~OSGWidget() {
 }
 
-void OSGWidget::renderBaseMesh(const std::vector<Lib3MF::sPosition> &verticesBuffer, const std::vector<Lib3MF::sTriangle> &triangleBuffer) {
+void OSGWidget::renderBaseMesh(const osg::ref_ptr<osg::Vec3Array> vertices, const osg::ref_ptr<osg::Vec3Array> normals) {
   _root->removeChild(_axesNode);
 
   osg::ref_ptr<osg::Geometry> meshGeometry = new osg::Geometry;
-  osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
-  for (const Lib3MF::sPosition vertex: verticesBuffer) {
-    vertices->push_back(osg::Vec3(vertex.m_Coordinates[0], vertex.m_Coordinates[1], vertex.m_Coordinates[2]));
-  }
   meshGeometry->setVertexArray(vertices.get());
-  osg::ref_ptr<osg::DrawElementsUInt> primitiveSet = new osg::DrawElementsUInt(GL_TRIANGLES);
-  for (const Lib3MF::sTriangle triangle: triangleBuffer) {
-    for (unsigned char i = 0; i < 3; i++) {
-      primitiveSet->push_back(triangle.m_Indices[i]);
-    }
-  }
-  meshGeometry->addPrimitiveSet(primitiveSet);
-  osgUtil::SmoothingVisitor::smooth(*meshGeometry);
+  meshGeometry->setNormalArray(normals.get(), osg::Array::BIND_PER_VERTEX);
+  meshGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertices->getNumElements()));
+  osgUtil::optimizeMesh(meshGeometry.get());
   _axesNode->addDrawable(meshGeometry.get());
 
-  // Set material for basic lighting and enable depth tests. Else, the sphere
-  // will suffer from rendering errors.
-  {
-    osg::StateSet* stateSet = _axesNode->getOrCreateStateSet();
-    osg::Material* material = new osg::Material;
-
-    material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
-
-    stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
-    stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-  }
+  OSGWidget::fixMaterialState(_axesNode);
 
   _root->addChild(_axesNode);
 }

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

@@ -1,6 +1,9 @@
 // Include own headers
 #include "PickHandler.hpp"
 
+// Include modules
+#include "OSGWidget.hpp"
+
 // Include dependencies
 #include <osg/io_utils>
 
@@ -28,15 +31,7 @@ osg::Node* PickHandler::getOrCreateSelectionCylinder() {
     cylinder->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 0.2f));
     geode->addDrawable(cylinder.get());
 
-    {
-      osg::StateSet* stateSet = geode->getOrCreateStateSet();
-      osg::Material* material = new osg::Material;
-
-      material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
-
-      stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
-      stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-    }
+    OSGWidget::fixMaterialState(geode);
 
     _selectionRotateGroup = new osg::MatrixTransform;
     _selectionRotateGroup->addChild(geode.get());

+ 45 - 41
trackpoint-app/src/ProjectStore.cpp

@@ -5,14 +5,12 @@
 #include "MainWindow.hpp"
 #include "StringBasics.hpp"
 
-#include "lib3mf_implicit.hpp"
-
 #include <typeinfo>
 #include <iostream>
 
 ProjectStore::ProjectStore() {
   projectLoaded = false;
-  //load3mfLib();
+  load3mfLib();
 }
 
 ProjectStore::ProjectStore(std::string projectFile) {
@@ -23,59 +21,65 @@ ProjectStore::~ProjectStore() {
 
 }
 
-void ProjectStore::load3mfLib() {
-  //_wrapper = Lib3MF::CWrapper::loadLibrary();
-}
-
 void ProjectStore::loadMesh(std::string meshFile) {
   if (StringBasics::endsWithCaseInsensitive(meshFile, ".STL")) {
     printf("Currently unsupported.\n");
   } else if (StringBasics::endsWithCaseInsensitive(meshFile, ".3MF")) {
-    Lib3MF::PWrapper _wrapper = Lib3MF::CWrapper::loadLibrary();
-    Lib3MF::PModel _project = _wrapper->CreateModel();
+    // Create new project model (because we don't have one if we load a mesh)
+    _project = _wrapper->CreateModel();
+    // 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) {
-      printf("Not 1 mesh: %d\n", meshIterator->Count());
+      // 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);
-
-    Lib3MF_uint64 vertex_count = mesh->GetVertexCount();
-    Lib3MF_uint64 triangle_count = mesh->GetTriangleCount();
-    for (Lib3MF_uint64 idx = 0; idx < triangle_count; ++idx) {
-			Lib3MF::sTriangle triangle = mesh->GetTriangle(idx);
-			Lib3MF::sPosition vertex1, vertex2, vertex3;
-
-			vertex1 = mesh->GetVertex(triangle.m_Indices[0]);
-			vertex2 = mesh->GetVertex(triangle.m_Indices[1]);
-			vertex3 = mesh->GetVertex(triangle.m_Indices[2]);
-
-			//p->append_poly();
-			//p->append_vertex(vertex1.m_Coordinates[0], vertex1.m_Coordinates[1], vertex1.m_Coordinates[2]);
-			//p->append_vertex(vertex2.m_Coordinates[0], vertex2.m_Coordinates[1], vertex2.m_Coordinates[2]);
-			//p->append_vertex(vertex3.m_Coordinates[0], vertex3.m_Coordinates[1], vertex3.m_Coordinates[2]);
-      printf("%f %f %f\n", vertex1.m_Coordinates[0], vertex1.m_Coordinates[1], vertex1.m_Coordinates[2]);
-      printf("%f %f %f\n", vertex2.m_Coordinates[0], vertex2.m_Coordinates[1], vertex2.m_Coordinates[2]);
-      printf("%f %f %f\n", vertex3.m_Coordinates[0], vertex3.m_Coordinates[1], vertex3.m_Coordinates[2]);
-		}
-
-
-    /*for (const Lib3MF::sPosition vertex: verticesBuffer) {
-      std::cout << typeid(vertex).name() << std::endl;
-      std::cout << typeid(vertex.m_Coordinates).name() << std::endl;
-      std::cout << typeid(vertex.m_Coordinates[0]).name() << std::endl;
-      printf("%f %f %f\n", (float)vertex.m_Coordinates[0], (float)vertex.m_Coordinates[1], (float)vertex.m_Coordinates[2]);
-    }*/
     std::vector<Lib3MF::sTriangle> triangleBuffer;
     mesh->GetTriangleIndices(triangleBuffer);
-    MainWindow* mainWindow = MainWindow::getInstance();
-    mainWindow->getOsgWidget()->renderBaseMesh(verticesBuffer, triangleBuffer);
-    printf("Done\n");
+    render3MFMesh(verticesBuffer, triangleBuffer);
   } else {
-    printf("Unsupported file type.\n"); // TODO: Show popup
+    // TODO: Show error popup
+    printf("Unsupported file type.\n");
+  }
+}
+
+void ProjectStore::load3mfLib() {
+  _wrapper = Lib3MF::CWrapper::loadLibrary();
+}
+
+void ProjectStore::render3MFMesh(const std::vector<Lib3MF::sPosition> verticesBuffer, const std::vector<Lib3MF::sTriangle> triangleBuffer) {
+  // Create osg style arrays
+  osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
+  osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
+  // Convert data to osg format and calculate vertex normals
+  for (const Lib3MF::sTriangle triangle: triangleBuffer) {
+    // Create osg vectors
+    osg::Vec3 vertex[3] = {};
+    for (char i = 0; i < 3; i++) {
+      vertex[i] = osg::Vec3(verticesBuffer[triangle.m_Indices[i]].m_Coordinates[0], verticesBuffer[triangle.m_Indices[i]].m_Coordinates[1], verticesBuffer[triangle.m_Indices[i]].m_Coordinates[2]);
+    }
+    // Calculate normal
+    osg::Vec3 edgeOne = vertex[1].operator-(vertex[0]);
+    osg::Vec3 edgeTwo = vertex[2].operator-(vertex[0]);
+    osg::Vec3 normal = edgeOne.operator^(edgeTwo);
+    normal.normalize();
+    // Store them
+    for (int i = 0; i < 3; i++) {
+      printf("%f %f %f\n", vertex[i].x(), vertex[i].y(), vertex[i].z());
+      vertices->push_back(vertex[i]);
+      normals->push_back(normal);
+    }
   }
+  // Call renderer
+  MainWindow* mainWindow = MainWindow::getInstance();
+  mainWindow->getOsgWidget()->renderBaseMesh(vertices, normals);
 }

+ 4 - 9
trackpoint-app/src/TrackPoint.cpp

@@ -1,6 +1,9 @@
 // Include own headers
 #include "TrackPoint.hpp"
 
+// Include modules
+#include "OSGWidget.hpp"
+
 // Include dependencies
 #include <osg/Geode>
 #include <osg/ShapeDrawable>
@@ -14,15 +17,7 @@ TrackPoint::TrackPoint(osg::Vec3 point, osg::Vec3 normal) {
   cylinder->setColor(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
   geode->addDrawable(cylinder.get());
 
-  {
-    osg::StateSet* stateSet = geode->getOrCreateStateSet();
-    osg::Material* material = new osg::Material;
-
-    material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
-
-    stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
-    stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-  }
+  OSGWidget::fixMaterialState(geode);
 
   _rotationGroup = new osg::MatrixTransform;
   _rotationGroup->addChild(geode.get());