VisualizationObject.cpp
Go to the documentation of this file.
1 #include "VisualizationObject.h"
2 
3 #include <SimoxUtility/algorithm/string/string_tools.h>
4 #include <VirtualRobot/Import/MeshImport/AssimpReader.h>
5 #include <VirtualRobot/ManipulationObject.h>
6 #include <VirtualRobot/SceneObject.h>
7 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualization.h>
8 #include <VirtualRobot/XML/ObjectIO.h>
9 #include <VirtualRobot/XML/RobotIO.h>
10 
14 
16 
17 #include <Inventor/SbColor.h>
18 #include <Inventor/nodes/SoMaterial.h>
19 
20 namespace armarx::viz::coin
21 {
22 
23  namespace
24  {
25  std::string
26  findObjectInArmarXObjects(const std::string& filename)
27  {
28  IceUtil::Time start = IceUtil::Time::now();
29  std::string objectName = std::filesystem::path(filename).filename().stem();
30  // ARMARX_INFO << "Trying to find object '" << objectName << "' in ArmarXObjects.";
31 
32  std::string fullFilename;
33  std::stringstream ss;
34 
35  armarx::ObjectFinder objectFinder;
36  if (std::optional<armarx::ObjectInfo> info = objectFinder.findObject("", objectName))
37  {
38  fullFilename = info->simoxXML().absolutePath;
39  ss << "Found '" << objectName << "' in ArmarXObjects as " << *info << " \nat '"
40  << fullFilename << "'.";
41  }
42  else
43  {
44  ss << "Did not find '" << objectName << "' in ArmarXObjects.";
45  }
46  ss << "\n(Lookup took " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
47  << " ms.)";
48  ARMARX_INFO << ss.str();
49 
50  return fullFilename;
51  }
52 
53  VirtualRobot::ManipulationObjectPtr
54  loadObject(std::string const& project, std::string const& filename)
55  {
56  VirtualRobot::ManipulationObjectPtr result;
57 
58  if (filename.empty())
59  {
60  ARMARX_INFO << deactivateSpam() << "No filename provided for object";
61  return result;
62  }
63 
64  bool checkArmarXObjects = true;
65 
66 
67  // This check cannot be done here!
68  // filename is a relative path in the project
69  // Also the code below does check whether the file is readable!
70  // std::ifstream fs(filename);
71  // if (!fs.good())
72  // {
73 
74  // ARMARX_WARNING << "unable to read from file " << VAROUT(filename);
75  // return result;
76  // }
77 
79  std::string fullFilename;
80  if (!ArmarXDataPath::SearchReadableFile(filename, fullFilename))
81  {
82  fullFilename = "";
83  if (checkArmarXObjects)
84  {
85  fullFilename = findObjectInArmarXObjects(filename);
86  }
87  if (fullFilename.empty())
88  {
89  ARMARX_INFO << deactivateSpam() << "Unable to find readable file for name "
90  << filename;
91  return result;
92  }
93  }
94 
95  try
96  {
97  ARMARX_INFO << "Loading object from " << fullFilename;
98 
99  std::filesystem::path path{fullFilename};
100  const std::string ext = simox::alg::to_lower(path.extension());
101 
102  if (ext == ".wrl" || ext == ".iv")
103  {
104  VirtualRobot::VisualizationFactoryPtr factory =
105  VirtualRobot::VisualizationFactory::fromName("inventor", nullptr);
106  VirtualRobot::VisualizationNodePtr vis =
107  factory->getVisualizationFromFile(fullFilename);
108  result = VirtualRobot::ManipulationObjectPtr(
109  new VirtualRobot::ManipulationObject(filename, vis));
110  }
111  else if (ext == ".xml" || ext == ".moxml")
112  {
113  result = VirtualRobot::ObjectIO::loadManipulationObject(fullFilename);
114  }
115  else if (VirtualRobot::AssimpReader::can_load(fullFilename))
116  {
117  const auto& tri = VirtualRobot::AssimpReader{}.readFileAsTriMesh(fullFilename);
118  result = VirtualRobot::ManipulationObjectPtr(
119  new VirtualRobot::ManipulationObject(filename, tri));
120  }
121  else
122  {
123  ARMARX_WARNING << "Could not load object from file: " << fullFilename
124  << "\nunknown extension '" << ext << "'";
125  }
126  }
127  catch (std::exception const& ex)
128  {
129  ARMARX_WARNING << "Could not load object from file: " << fullFilename
130  << "\nReason: " << ex.what();
131  }
132 
133  return result;
134  }
135 
136  static std::vector<LoadedObject> objectcache;
137 
138  LoadedObject
139  getObjectFromCache(std::string const& project, std::string const& filename)
140  {
141  // We can use a global variable, since this code is only executed in the GUI thread
142 
143  LoadedObject result;
144 
145  for (LoadedObject const& loaded : objectcache)
146  {
147  if (loaded.project == project && loaded.filename == filename)
148  {
149  result = loaded;
150  result.object = loaded.object;
151  return result;
152  }
153  }
154 
155  result.project = project;
156  result.filename = filename;
157  result.object = loadObject(project, filename);
158 
159 
160  objectcache.push_back(result);
161 
162  return result;
163  }
164  } // namespace
165 
166  bool
168  {
169  bool fileChanged = loaded.project != element.project || loaded.filename != element.filename;
170  if (fileChanged)
171  {
172  // The robot file changed, so reload the robot
173  loaded = getObjectFromCache(element.project, element.filename);
174  }
175  if (!loaded.object)
176  {
178  << "Object will not be visualized since it could not be loaded."
179  << "\nID: " << element.id << "\nProject: " << element.project
180  << "\nFilename: " << element.filename;
181  return true;
182  }
183 
184  bool drawStyleChanged = loadedDrawStyle != element.drawStyle;
185  if (fileChanged || drawStyleChanged)
186  {
187  recreateVisualizationNodes(element.drawStyle);
188  loadedDrawStyle = element.drawStyle;
189  }
190 
191  if (loadedDrawStyle & data::ModelDrawStyle::OVERRIDE_COLOR)
192  {
193  int numChildren = node->getNumChildren();
194  for (int i = 0; i < numChildren; i++)
195  {
196  SoSeparator* nodeSep = static_cast<SoSeparator*>(node->getChild(i));
197  // The first entry must be a SoMaterial (see recreateVisualizationNodes)
198  SoMaterial* m = dynamic_cast<SoMaterial*>(nodeSep->getChild(0));
199  if (!m)
200  {
201  ARMARX_WARNING << "Error at node with index: " << i;
202  continue;
203  }
204 
205  auto color = element.color;
206  const float conv = 1.0f / 255.0f;
207  float a = color.a * conv;
208  SbColor coinColor(conv * color.r, conv * color.g, conv * color.b);
209  m->diffuseColor = coinColor;
210  m->ambientColor = coinColor;
211  m->transparency = 1.0f - a;
212  m->setOverride(true);
213  }
214  }
215 
216  return true;
217  }
218 
219  void
221  {
222  VirtualRobot::SceneObject::VisualizationType visuType = VirtualRobot::SceneObject::Full;
223  if (drawStyle & data::ModelDrawStyle::COLLISION)
224  {
225  visuType = VirtualRobot::SceneObject::Collision;
226  }
227 
228  node->removeAllChildren();
229 
230  VirtualRobot::ManipulationObject& object = *loaded.object;
231 
232  SoSeparator* nodeSep = new SoSeparator;
233 
234  // This material is used to color the nodes individually
235  // We require it to be the first node in the separator for updates
236  SoMaterial* nodeMat = new SoMaterial;
237  nodeMat->setOverride(false);
238  nodeSep->addChild(nodeMat);
239 
241  object.getVisualization<VirtualRobot::CoinVisualization>(visuType);
242  if (nodeVisu)
243  {
244  SoNode* sepRobNode = nodeVisu->getCoinVisualization();
245 
246  if (sepRobNode)
247  {
248  nodeSep->addChild(sepRobNode);
249  }
250  }
251 
252  node->addChild(nodeSep);
253  }
254 
255  void
257  {
258  objectcache.clear();
259  }
260 } // namespace armarx::viz::coin
armarx::viz::coin::VisualizationObject::loaded
LoadedObject loaded
Definition: VisualizationObject.h:26
armarx::viz::coin::VisualizationObject::loadedDrawStyle
int loadedDrawStyle
Definition: VisualizationObject.h:27
armarx::viz::coin::VisualizationObject::ElementType
data::ElementObject ElementType
Definition: VisualizationObject.h:20
armarx::viz::coin::clearObjectCache
void clearObjectCache()
Definition: VisualizationObject.cpp:256
armarx::ArmarXDataPath::FindPackageAndAddDataPath
static bool FindPackageAndAddDataPath(const std::string &packageName)
Search for the package and add its data path if it was found.
Definition: ArmarXDataPath.cpp:824
project
std::string project
Definition: VisualizationRobot.cpp:85
armarx::viz::coin::LoadedObject::filename
std::string filename
Definition: VisualizationObject.h:14
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
armarx::ObjectFinder
Used to find objects in the ArmarX objects repository [1] (formerly [2]).
Definition: ObjectFinder.h:22
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
armarx::viz::coin::TypedElementVisualization< SoSeparator >::node
NodeType * node
Definition: ElementVisualizer.h:67
CoinVisualizationPtr
boost::shared_ptr< VirtualRobot::CoinVisualization > CoinVisualizationPtr
Definition: ManipulatorVisualization.h:56
armarx::viz::coin::VisualizationObject::recreateVisualizationNodes
void recreateVisualizationNodes(int drawStyle)
Definition: VisualizationObject.cpp:220
armarx::viz::coin::VisualizationObject::update
bool update(ElementType const &element)
Definition: VisualizationObject.cpp:167
armarx::viz::coin::LoadedObject::object
VirtualRobot::ManipulationObjectPtr object
Definition: VisualizationObject.h:15
filename
std::string filename
Definition: VisualizationRobot.cpp:86
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::ArmarXDataPath::SearchReadableFile
static bool SearchReadableFile(const std::string &querryFileName, std::string &resultFileName, bool verbose=true)
Definition: ArmarXDataPath.cpp:216
CMakePackageFinder.h
armarx::viz::coin::LoadedObject::project
std::string project
Definition: VisualizationObject.h:13
armarx::viz::coin
Definition: ElementVisualizer.cpp:11
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ObjectFinder::findObject
std::optional< ObjectInfo > findObject(const std::string &dataset, const std::string &name) const
Definition: ObjectFinder.cpp:64
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
ArmarXDataPath.h
ObjectFinder.h
VisualizationObject.h