VisualizationObject.cpp
Go to the documentation of this file.
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
20namespace 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
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
240 VirtualRobot::CoinVisualizationPtr nodeVisu =
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
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
static bool SearchReadableFile(const std::string &querryFileName, std::string &resultFileName, bool verbose=true)
static bool FindPackageAndAddDataPath(const std::string &packageName)
Search for the package and add its data path if it was found.
std::optional< ObjectInfo > findObject(const std::string &dataset, const std::string &name) const
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
void project(pcl::PointCloud< pcl::PointXYZ > &cloud, wykobi::Polygon polygon)
bool update(ElementType const &element)