Skip to content

Commit

Permalink
[OMEdit] Support OBJ & 3DS files as CAD shapes (#10377)
Browse files Browse the repository at this point in the history
* Support OBJ & 3DS files as CAD shapes

* Clean up functions for CAD file checks

* Add helper functions for CAD type checks
  • Loading branch information
anotheruserofgithub committed Mar 30, 2023
1 parent 7cad420 commit 5a8aa61
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 50 deletions.
91 changes: 64 additions & 27 deletions OMEdit/OMEditLIB/Animation/AnimationUtil.h
Expand Up @@ -35,15 +35,10 @@
#ifndef ANIMATIONUTIL_H
#define ANIMATIONUTIL_H

#include <QString>
#include <QRegExp>
#include <QFileInfo>
#include <QString>

#include <QOpenGLContext> // must be included before OSG headers

#include <sys/stat.h>
#include <string>
#include <osg/Vec3>

#include "MainWindow.h"
#include "OMC/OMCProxy.h"
Expand Down Expand Up @@ -125,46 +120,88 @@ 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)
{
return b ? "true" : "false";
}


#endif //ANIMATIONUTIL_H
12 changes: 6 additions & 6 deletions OMEdit/OMEditLIB/Animation/ViewerWidget.cpp
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions OMEdit/OMEditLIB/Animation/ViewerWidget.h
Expand Up @@ -47,6 +47,7 @@
#include <QMenu>

#include "AbstractAnimationWindow.h"
#include "AnimationUtil.h"
#include "Util/Helper.h"

/*!
Expand Down
60 changes: 43 additions & 17 deletions OMEdit/OMEditLIB/Animation/Visualization.cpp
Expand Up @@ -41,6 +41,7 @@
#include <QOpenGLContext> // must be included before OSG headers
#include <osg/GL> // for having direct access to glClear()

#include <osg/Array>
#include <osg/Drawable>
#include <osg/Shape>
#include <osg/ShapeDrawable>
Expand Down Expand Up @@ -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)) {
Expand All @@ -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";
}
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -1281,8 +1286,19 @@ void OSGScene::setUpScene(std::vector<ShapeObject>& shapes)
osg::ref_ptr<osg::MatrixTransform> 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 "<<shape._fileName<<std::endl;
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(shape._fileName);
if (node.valid())
{
osg::ref_ptr<CADFile> 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 "<<shape._fileName<<std::endl;
// Disable mesh optimization because it is too expensive (see OSG commit a082b57)
osg::ref_ptr<osgDB::Options> options = new osgDB::Options("noTriStripPolygons");
Expand All @@ -1294,7 +1310,7 @@ void OSGScene::setUpScene(std::vector<ShapeObject>& 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 "<<shape._fileName<<std::endl;
osg::ref_ptr<DXFile> dxfDraw = new DXFile(shape._fileName);
Expand Down Expand Up @@ -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<osg::Transform> transformNode = shape->getTransformNode();
Expand Down Expand Up @@ -1545,16 +1561,18 @@ void UpdateVisitor::apply(osg::Geode& node)
if (changeMaterial || changeTexture) {
osg::ref_ptr<osg::StateSet> 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<osg::Transform> transformNode = shape->getTransformNode();
if (transformNode.valid() && transformNode->getNumChildren() > 0) {
osg::ref_ptr<CADFile> cad = dynamic_cast<CADFile*>(transformNode->getChild(0));
if (cad.valid()) {
stateSet = cad->getOrCreateStateSet();
geometryColors = !shape->getVisualProperties()->getColor().custom();
is3DSShape = is3DSType(shape->_type);
}
}
}
Expand All @@ -1576,9 +1594,14 @@ void UpdateVisitor::apply(osg::Geode& node)
//set transparency
changeTransparencyOfMaterial(ss, transparency);
if (geometryColors) {
changeTransparencyOfGeometry(node, transparency);
if (is3DSShape) {
changeTransparencyOfGeometry<osg::Vec4ubArray, 255>(node, transparency);
} else {
changeTransparencyOfGeometry<osg::Vec4Array, 1> (node, transparency);
}
}
}

if (changeTexture) {
//set texture
applyTexture(ss, textureImagePath);
Expand Down Expand Up @@ -1699,18 +1722,21 @@ void UpdateVisitor::changeTransparencyOfMaterial(osg::StateSet* ss, const float
* \brief UpdateVisitor::changeTransparencyOfGeometry
* changes transparency of a geode's geometry
*/
template<typename Vec4Array, unsigned int scale>
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<osg::Vec4Array*>(geometry->getColorArray());
Vec4Array* colors = dynamic_cast<Vec4Array*>(geometry->getColorArray());
if (colors) {
for (osg::Vec4& color : colors->asVector()) {
for (Vec4& color : colors->asVector()) {
color.a() = opacity;
}
colors->dirty();
Expand Down Expand Up @@ -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],
Expand Down
1 change: 1 addition & 0 deletions OMEdit/OMEditLIB/Animation/Visualization.h
Expand Up @@ -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<typename Vec4Array, unsigned int scale>
void changeTransparencyOfGeometry(osg::Geode& geode, const float transparency);
public:
AbstractVisualizerObject* _visualizer;
Expand Down

0 comments on commit 5a8aa61

Please sign in to comment.