From 5a8aa6107ba01353126467e1bb524d5359a68aef Mon Sep 17 00:00:00 2001 From: anotheruserofgithub <96748782+anotheruserofgithub@users.noreply.github.com> Date: Thu, 30 Mar 2023 11:27:48 +0200 Subject: [PATCH] [OMEdit] Support OBJ & 3DS files as CAD shapes (#10377) * Support OBJ & 3DS files as CAD shapes * Clean up functions for CAD file checks * Add helper functions for CAD type checks --- OMEdit/OMEditLIB/Animation/AnimationUtil.h | 91 ++++++++++++++------ OMEdit/OMEditLIB/Animation/ViewerWidget.cpp | 12 +-- OMEdit/OMEditLIB/Animation/ViewerWidget.h | 1 + OMEdit/OMEditLIB/Animation/Visualization.cpp | 60 +++++++++---- OMEdit/OMEditLIB/Animation/Visualization.h | 1 + 5 files changed, 115 insertions(+), 50 deletions(-) diff --git a/OMEdit/OMEditLIB/Animation/AnimationUtil.h b/OMEdit/OMEditLIB/Animation/AnimationUtil.h index ee31379203e..4cbc26542c1 100644 --- a/OMEdit/OMEditLIB/Animation/AnimationUtil.h +++ b/OMEdit/OMEditLIB/Animation/AnimationUtil.h @@ -35,15 +35,10 @@ #ifndef ANIMATIONUTIL_H #define ANIMATIONUTIL_H -#include -#include #include +#include -#include // must be included before OSG headers - -#include #include -#include #include "MainWindow.h" #include "OMC/OMCProxy.h" @@ -125,40 +120,83 @@ inline bool checkForXMLFile(const std::string& modelFile, const std::string& pat return fileExists(xmlFileName); } -/*! \brief Checks if the type is a cad file +/*! + * \brief Gets the filename of the CAD file */ -inline bool isCADType(const std::string& typeName) +inline std::string extractCADFilename(const std::string& typeName) { - return ((typeName.size() >= 12 && std::string(typeName.begin(), typeName.begin() + 11) == "modelica://") - || (typeName.size() >= 8 && std::string(typeName.begin(), typeName.begin() + 7) == "file://")); + QString str(typeName.c_str()); + if (str.startsWith("modelica://")) { + const QString absoluteFileName = MainWindow::instance()->getOMCProxy()->uriToFilename(str); + return absoluteFileName.toStdString(); + } else { + const std::string fileKey = "file://"; + return typeName.substr(fileKey.length(), typeName.length()); + } } +/*! + * \brief Checks if the type is a CAD file + */ +inline bool isCADFile(const std::string& typeName) +{ + return ((typeName.size() >= 12 && std::string(typeName.begin(), typeName.begin() + 11) == "modelica://") || + (typeName.size() >= 8 && std::string(typeName.begin(), typeName.begin() + 7) == "file://")); +} -inline bool dxfFileType(const std::string& typeName) +inline bool isDXFFile(const std::string& fileName) { - return typeName.substr(typeName.size()-3) == std::string("dxf"); + return fileName.substr(fileName.size() - 3) == "dxf"; } +inline bool isSTLFile(const std::string& fileName) +{ + return fileName.substr(fileName.size() - 3) == "stl"; +} -inline bool stlFileType(const std::string& typeName) +inline bool isOBJFile(const std::string& fileName) { - return typeName.substr(typeName.size()-3) == std::string("stl"); + return fileName.substr(fileName.size() - 3) == "obj"; } +inline bool is3DSFile(const std::string& fileName) +{ + return fileName.substr(fileName.size() - 3) == "3ds"; +} -/*! \brief Get file name of the cad file - */ -inline std::string extractCADFilename(const std::string& s) +inline bool isDXFType(const std::string& type) { - QString str(s.c_str()); - if (str.startsWith("modelica://")) { - const QString absoluteFileName = MainWindow::instance()->getOMCProxy()->uriToFilename(str); - return absoluteFileName.toStdString(); - } else { - std::string fileKey = "file://"; - std::string s2 = s.substr(fileKey.length(), s.length()); - return s2; - } + return type == "DXF"; +} + +inline bool isSTLType(const std::string& type) +{ + return type == "STL"; +} + +inline bool isOBJType(const std::string& type) +{ + return type == "OBJ"; +} + +inline bool is3DSType(const std::string& type) +{ + return type == "3DS"; +} + +inline bool isCADType(const std::string& type) +{ + return isDXFType(type) || isSTLType(type) || isOBJType(type) || is3DSType(type); +} + +inline bool isSimpleCADType(const std::string& type) +{ + return isDXFType(type) || isSTLType(type); +} + +inline bool isAdvancedCADType(const std::string& type) +{ + return isOBJType(type) || is3DSType(type); } inline const char* boolToString(bool b) @@ -166,5 +204,4 @@ inline const char* boolToString(bool b) return b ? "true" : "false"; } - #endif //ANIMATIONUTIL_H diff --git a/OMEdit/OMEditLIB/Animation/ViewerWidget.cpp b/OMEdit/OMEditLIB/Animation/ViewerWidget.cpp index 33eee357652..c5ddd3c8765 100644 --- a/OMEdit/OMEditLIB/Animation/ViewerWidget.cpp +++ b/OMEdit/OMEditLIB/Animation/ViewerWidget.cpp @@ -403,8 +403,8 @@ void ViewerWidget::applyCheckerTexture() if (mpSelectedVisualizer) { if (mpSelectedVisualizer->isShape()) { ShapeObject* shape = mpSelectedVisualizer->asShape(); - if (shape->_type.compare("dxf") == 0 or shape->_type.compare("stl") == 0) { - QString msg = tr("Texture feature is not applicable for %1 files.").arg(shape->_type.compare("dxf") == 0 ? "DXF" : "STL"); + if (isSimpleCADType(shape->_type)) { + QString msg = tr("Texture feature is not applicable for %1 files.").arg(shape->_type.c_str()); MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, msg, Helper::scriptingKind, Helper::notificationLevel)); mpSelectedVisualizer = nullptr; @@ -426,8 +426,8 @@ void ViewerWidget::applyCustomTexture() if (mpSelectedVisualizer) { if (mpSelectedVisualizer->isShape()) { ShapeObject* shape = mpSelectedVisualizer->asShape(); - if (shape->_type.compare("dxf") == 0 or shape->_type.compare("stl") == 0) { - QString msg = tr("Texture feature is not applicable for %1 files.").arg(shape->_type.compare("dxf") == 0 ? "DXF" : "STL"); + if (isSimpleCADType(shape->_type)) { + QString msg = tr("Texture feature is not applicable for %1 files.").arg(shape->_type.c_str()); MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, msg, Helper::scriptingKind, Helper::notificationLevel)); mpSelectedVisualizer = nullptr; @@ -454,8 +454,8 @@ void ViewerWidget::removeTexture() if (mpSelectedVisualizer) { if (mpSelectedVisualizer->isShape()) { ShapeObject* shape = mpSelectedVisualizer->asShape(); - if (shape->_type.compare("dxf") == 0 or shape->_type.compare("stl") == 0) { - QString msg = tr("Texture feature is not applicable for %1 files.").arg(shape->_type.compare("dxf") == 0 ? "DXF" : "STL"); + if (isSimpleCADType(shape->_type)) { + QString msg = tr("Texture feature is not applicable for %1 files.").arg(shape->_type.c_str()); MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, msg, Helper::scriptingKind, Helper::notificationLevel)); mpSelectedVisualizer = nullptr; diff --git a/OMEdit/OMEditLIB/Animation/ViewerWidget.h b/OMEdit/OMEditLIB/Animation/ViewerWidget.h index 26c4e44213d..a6a3b38c669 100644 --- a/OMEdit/OMEditLIB/Animation/ViewerWidget.h +++ b/OMEdit/OMEditLIB/Animation/ViewerWidget.h @@ -47,6 +47,7 @@ #include #include "AbstractAnimationWindow.h" +#include "AnimationUtil.h" #include "Util/Helper.h" /*! diff --git a/OMEdit/OMEditLIB/Animation/Visualization.cpp b/OMEdit/OMEditLIB/Animation/Visualization.cpp index a4a1a3b14d9..c9ebda70b67 100644 --- a/OMEdit/OMEditLIB/Animation/Visualization.cpp +++ b/OMEdit/OMEditLIB/Animation/Visualization.cpp @@ -41,6 +41,7 @@ #include // must be included before OSG headers #include // for having direct access to glClear() +#include #include #include #include @@ -316,7 +317,7 @@ void OMVisualBase::initVisObjects() } shape._type = std::string(expNode->value()); - if (isCADType(shape._type)) + if (isCADFile(shape._type)) { shape._fileName = extractCADFilename(shape._type); if (!fileExists(shape._fileName)) { @@ -327,10 +328,14 @@ void OMVisualBase::initVisObjects() continue; } - if (dxfFileType(shape._fileName)) { - shape._type = "dxf"; - } else if (stlFileType(shape._fileName)) { - shape._type = "stl"; + if (isDXFFile(shape._fileName)) { + shape._type = "DXF"; + } else if (isSTLFile(shape._fileName)) { + shape._type = "STL"; + } else if (isOBJFile(shape._fileName)) { + shape._type = "OBJ"; + } else if (is3DSFile(shape._fileName)) { + shape._type = "3DS"; } } @@ -790,8 +795,8 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex* // Store the radius of relevant shapes for (ShapeObject& shape : relevantShapes) { - // Consider OpenSceneGraph shape drawables only - if (shape._type.compare("dxf") == 0 || shape._type.compare("stl") == 0) { + // Consider OSG shape drawables only + if (isCADType(shape._type)) { continue; } @@ -1281,8 +1286,19 @@ void OSGScene::setUpScene(std::vector& shapes) osg::ref_ptr transf = new osg::MatrixTransform(); transf->setName(shape._id); - if (shape._type.compare("stl") == 0) - { //cad node + if (isAdvancedCADType(shape._type)) + { //advanced cad node + //std::cout<<"It's an advanced cad and the filename is "< node = osgDB::readNodeFile(shape._fileName); + if (node.valid()) + { + osg::ref_ptr cad = new CADFile(node.get()); + + transf->addChild(cad.get()); + } + } + else if (isSTLType(shape._type)) + { //stl node //std::cout<<"It's a stl and the filename is "< options = new osgDB::Options("noTriStripPolygons"); @@ -1294,7 +1310,7 @@ void OSGScene::setUpScene(std::vector& shapes) transf->addChild(cad.get()); } } - else if (shape._type.compare("dxf") == 0) + else if (isDXFType(shape._type)) { //geode with dxf drawable //std::cout<<"It's a dxf and the filename is "< dxfDraw = new DXFile(shape._fileName); @@ -1412,7 +1428,7 @@ void UpdateVisitor::apply(osg::Geode& node) case VisualizerType::shape: { ShapeObject* shape = _visualizer->asShape(); - if (shape->_type.compare("dxf") == 0 or shape->_type.compare("stl") == 0) + if (isCADType(shape->_type)) { //it's a cad file so we have to rescale the underlying geometry vertices osg::ref_ptr transformNode = shape->getTransformNode(); @@ -1545,16 +1561,18 @@ void UpdateVisitor::apply(osg::Geode& node) if (changeMaterial || changeTexture) { osg::ref_ptr stateSet = nullptr; bool geometryColors = false; + bool is3DSShape = false; if (_visualizer->isShape()) { ShapeObject* shape = _visualizer->asShape(); - if (shape->_type.compare("dxf") == 0 or shape->_type.compare("stl") == 0) { + if (isCADType(shape->_type)) { osg::ref_ptr transformNode = shape->getTransformNode(); if (transformNode.valid() && transformNode->getNumChildren() > 0) { osg::ref_ptr cad = dynamic_cast(transformNode->getChild(0)); if (cad.valid()) { stateSet = cad->getOrCreateStateSet(); geometryColors = !shape->getVisualProperties()->getColor().custom(); + is3DSShape = is3DSType(shape->_type); } } } @@ -1576,9 +1594,14 @@ void UpdateVisitor::apply(osg::Geode& node) //set transparency changeTransparencyOfMaterial(ss, transparency); if (geometryColors) { - changeTransparencyOfGeometry(node, transparency); + if (is3DSShape) { + changeTransparencyOfGeometry(node, transparency); + } else { + changeTransparencyOfGeometry (node, transparency); + } } } + if (changeTexture) { //set texture applyTexture(ss, textureImagePath); @@ -1699,18 +1722,21 @@ void UpdateVisitor::changeTransparencyOfMaterial(osg::StateSet* ss, const float * \brief UpdateVisitor::changeTransparencyOfGeometry * changes transparency of a geode's geometry */ +template void UpdateVisitor::changeTransparencyOfGeometry(osg::Geode& geode, const float transparency) { - osg::Vec4::value_type opacity = 1.0 - transparency; + using Vec4 = typename Vec4Array::ElementDataType; + using type = typename Vec4::value_type; + type opacity = (1.0 - transparency) * scale; unsigned int num = geode.getNumDrawables(); for (unsigned int i = 0; i < num; i++) { osg::Drawable* drawable = geode.getDrawable(i); if (drawable) { osg::Geometry* geometry = drawable->asGeometry(); if (geometry) { - osg::Vec4Array* colors = dynamic_cast(geometry->getColorArray()); + Vec4Array* colors = dynamic_cast(geometry->getColorArray()); if (colors) { - for (osg::Vec4& color : colors->asVector()) { + for (Vec4& color : colors->asVector()) { color.a() = opacity; } colors->dirty(); @@ -1861,7 +1887,7 @@ rAndT rotateModelica2OSG(osg::Matrix3 T, osg::Vec3f r, osg::Vec3f r_shape, osg:: //std::cout << "hDir " << hDir[0] << ", " << hDir[1] << ", " << hDir[2] << std::endl; osg::Matrix3 T0; - if (type == "stl" || type == "dxf") + if (isCADType(type)) { T0 = osg::Matrix3(dirs._lDir[0], dirs._lDir[1], dirs._lDir[2], dirs._wDir[0], dirs._wDir[1], dirs._wDir[2], diff --git a/OMEdit/OMEditLIB/Animation/Visualization.h b/OMEdit/OMEditLIB/Animation/Visualization.h index 5ce81d45511..5aec8fdec82 100644 --- a/OMEdit/OMEditLIB/Animation/Visualization.h +++ b/OMEdit/OMEditLIB/Animation/Visualization.h @@ -99,6 +99,7 @@ class UpdateVisitor : public osg::NodeVisitor void applyTexture(osg::StateSet* ss, const std::string& imagePath); void changeColorOfMaterial(osg::StateSet* ss, const osg::Material::ColorMode mode, const QColor color, const float specular); void changeTransparencyOfMaterial(osg::StateSet* ss, const float transparency); + template void changeTransparencyOfGeometry(osg::Geode& geode, const float transparency); public: AbstractVisualizerObject* _visualizer;