[221] | 1 | /* -*-c++-*- osgVisual - Copyright (C) 2009-2011 Torben Dannhauer |
---|
[31] | 2 | * |
---|
| 3 | * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under |
---|
| 4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
---|
| 5 | * (at your option) any later version. The full license is in LICENSE file |
---|
| 6 | * included with this distribution, and on the openscenegraph.org website. |
---|
| 7 | * |
---|
| 8 | * osgVisual requires for some proprietary modules a license from the correspondig manufacturer. |
---|
| 9 | * You have to aquire licenses for all used proprietary modules. |
---|
| 10 | * |
---|
| 11 | * This library is distributed in the hope that it will be useful, |
---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 14 | * OpenSceneGraph Public License for more details. |
---|
| 15 | */ |
---|
| 16 | |
---|
| 17 | #include "visual_dataIO.h" |
---|
| 18 | |
---|
| 19 | using namespace osgVisual; |
---|
| 20 | |
---|
| 21 | visual_dataIO::visual_dataIO() |
---|
| 22 | { |
---|
| 23 | OSG_NOTIFY( osg::ALWAYS ) << "visual_dataIO constructed" << std::endl; |
---|
[88] | 24 | |
---|
[31] | 25 | initialized = false; |
---|
[157] | 26 | clusterMode = osgVisual::dataIO_cluster::STANDALONE; |
---|
| 27 | // Create Transport-Container: |
---|
| 28 | slotContainer = new osgVisual::dataIO_transportContainer(); |
---|
[31] | 29 | } |
---|
| 30 | |
---|
| 31 | visual_dataIO::~visual_dataIO() |
---|
| 32 | { |
---|
[121] | 33 | // Delete all slots: |
---|
| 34 | for(unsigned int i=0;i<dataSlots.size();i++) |
---|
| 35 | { |
---|
| 36 | delete dataSlots[i]; |
---|
| 37 | } |
---|
| 38 | dataSlots.clear(); |
---|
| 39 | |
---|
[31] | 40 | OSG_NOTIFY( osg::ALWAYS ) << "visual_dataIO destructed" << std::endl; |
---|
| 41 | } |
---|
| 42 | |
---|
| 43 | visual_dataIO* visual_dataIO::getInstance() |
---|
| 44 | { |
---|
| 45 | static visual_dataIO instance; |
---|
| 46 | return &instance; |
---|
| 47 | }; |
---|
| 48 | |
---|
[185] | 49 | void visual_dataIO::init(osgViewer::Viewer* viewer_, std::string configFileName) |
---|
[31] | 50 | { |
---|
[183] | 51 | OSG_NOTIFY( osg::ALWAYS ) << "visual_dataIO initialize.."; |
---|
[31] | 52 | |
---|
| 53 | // Init variables |
---|
| 54 | viewer = viewer_; |
---|
| 55 | |
---|
[186] | 56 | // Process XML configuration - all XML dependen initializations are performed in processXMLConfiguration() |
---|
[160] | 57 | this->configFileName = configFileName; |
---|
[186] | 58 | if(!processXMLConfiguration()) |
---|
[160] | 59 | OSG_FATAL << "ERROR: visual_dataIO::init() - Failed to initialize dataIO via XML configuration!"; |
---|
[157] | 60 | |
---|
[31] | 61 | // Install callbacks to perform DataIO activities every frame: |
---|
| 62 | //// EventCallback at the absolute beginning of the frame |
---|
| 63 | eventCallback = new dataIO_eventCallback(this); |
---|
| 64 | viewer->getCamera()->setEventCallback( eventCallback ); |
---|
| 65 | //// FinalDrawCallback at the end of event and update handling, but BEFORE rendering the frame |
---|
| 66 | finalDrawCallback = new dataIO_finalDrawCallback(this); |
---|
| 67 | viewer->getCamera()->setFinalDrawCallback( finalDrawCallback ); |
---|
| 68 | |
---|
| 69 | initialized = true; |
---|
| 70 | } |
---|
| 71 | |
---|
[186] | 72 | bool visual_dataIO::processXMLConfiguration() |
---|
[157] | 73 | { |
---|
[160] | 74 | // Init XML |
---|
| 75 | xmlDoc* tmpDoc; |
---|
| 76 | bool disabled; |
---|
| 77 | xmlNode* config = util::getModuleXMLConfig( configFileName, "dataio", tmpDoc, disabled ); |
---|
[186] | 78 | xmlNode* clusterConfig = NULL, *extLinkConfig = NULL; |
---|
[157] | 79 | |
---|
[160] | 80 | if( disabled) |
---|
| 81 | OSG_NOTIFY( osg::ALWAYS ) << "..disabled by XML configuration file. dataIO can't be disabled. Ignoring." << std::endl; |
---|
[183] | 82 | else |
---|
| 83 | OSG_NOTIFY( osg::ALWAYS ) << std::endl; |
---|
[160] | 84 | |
---|
| 85 | // extract configuration values |
---|
| 86 | if(config) |
---|
| 87 | { |
---|
| 88 | xmlNode* a_node = config->children; |
---|
| 89 | |
---|
| 90 | for (xmlNode *cur_node = a_node; cur_node; cur_node = cur_node->next) |
---|
| 91 | { |
---|
| 92 | std::string node_name=reinterpret_cast<const char*>(cur_node->name); |
---|
| 93 | //OSG_ALWAYS << "----visual_distortion::processXMLConfiguration() - node type="<< cur_node->type <<", name=" << cur_node->name << std::endl; |
---|
| 94 | |
---|
| 95 | // Check for dataio node |
---|
| 96 | if(cur_node->type == XML_ELEMENT_NODE && node_name == "dataio") |
---|
| 97 | { |
---|
| 98 | // Extract cluster role |
---|
| 99 | xmlAttr *attr = cur_node->properties; |
---|
| 100 | while ( attr ) |
---|
| 101 | { |
---|
| 102 | std::string attr_name=reinterpret_cast<const char*>(attr->name); |
---|
| 103 | std::string attr_value=reinterpret_cast<const char*>(attr->children->content); |
---|
| 104 | if( attr_name == "clusterrole" ) |
---|
| 105 | { |
---|
| 106 | if(attr_value == "master") |
---|
| 107 | { |
---|
| 108 | OSG_NOTIFY( osg::ALWAYS ) << "Configure osgVisual as MASTER" << std::endl; |
---|
| 109 | clusterMode = osgVisual::dataIO_cluster::MASTER; |
---|
| 110 | } |
---|
| 111 | else if(attr_value == "slave") |
---|
| 112 | { |
---|
| 113 | OSG_NOTIFY( osg::ALWAYS ) << "Configure osgVisual as SLAVE" << std::endl; |
---|
| 114 | clusterMode = osgVisual::dataIO_cluster::SLAVE; |
---|
| 115 | slotContainer = NULL; // Slave only recieves container, therefor set this Pointer NULL (created instance will be deleted because it is an auto pointer). |
---|
| 116 | } |
---|
| 117 | else if(attr_value == "standalone") |
---|
| 118 | { |
---|
| 119 | OSG_NOTIFY( osg::ALWAYS ) << "Configure osgVisual as STANDALONE" << std::endl; |
---|
| 120 | clusterMode = osgVisual::dataIO_cluster::STANDALONE; |
---|
| 121 | } |
---|
| 122 | } |
---|
| 123 | attr = attr->next; |
---|
| 124 | } // WHILE attrib END |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | // Check for cluster node |
---|
| 128 | if(cur_node->type == XML_ELEMENT_NODE && node_name == "cluster") |
---|
| 129 | { |
---|
[183] | 130 | // Pass cluster configuration to the used cluster implementation. |
---|
| 131 | // The implementation will use the configuration if it matches, otherwise falls back to dummy cluster |
---|
| 132 | clusterConfig = cur_node; |
---|
[160] | 133 | } |
---|
| 134 | |
---|
| 135 | // Check for extLink node |
---|
| 136 | if(cur_node->type == XML_ELEMENT_NODE && node_name == "extlink") |
---|
| 137 | { |
---|
[186] | 138 | // Pass extLink configuration to the used extLink implementation. |
---|
| 139 | // The implementation will use the configuration if it matches, otherwise falls back to dummy extLink |
---|
| 140 | extLinkConfig = cur_node; |
---|
[160] | 141 | } |
---|
| 142 | |
---|
| 143 | } // FOR all nodes END |
---|
| 144 | |
---|
[183] | 145 | |
---|
| 146 | // Create Cluster. |
---|
| 147 | #ifdef USE_CLUSTER_ASIO_TCP_IOSTREAM |
---|
| 148 | cluster = new dataIO_clusterAsioTcpIostream(); |
---|
| 149 | #endif |
---|
| 150 | #ifdef USE_CLUSTER_ENET |
---|
| 151 | cluster = new dataIO_clusterENet(); |
---|
| 152 | #endif |
---|
| 153 | if( !cluster.valid() || !clusterConfig || !cluster->init(clusterConfig, viewer, clusterMode, slotContainer, false) ) |
---|
| 154 | { |
---|
| 155 | cluster = new dataIO_clusterDummy(); |
---|
| 156 | cluster->init(clusterConfig, viewer, clusterMode, slotContainer, false); |
---|
| 157 | } |
---|
| 158 | |
---|
[186] | 159 | // Create extLink. |
---|
| 160 | #ifdef USE_EXTLINK_VCL |
---|
| 161 | extLink = new dataIO_extLinkVCL( dataSlots ); |
---|
| 162 | #endif |
---|
| 163 | if( !extLink.valid() || !extLinkConfig || !extLink->init(extLinkConfig) ) |
---|
| 164 | { |
---|
| 165 | extLink = new dataIO_extLinkDummy( dataSlots ); |
---|
| 166 | extLink->init(extLinkConfig); |
---|
| 167 | } |
---|
[183] | 168 | |
---|
| 169 | |
---|
[160] | 170 | // clean up |
---|
| 171 | xmlFreeDoc(tmpDoc); xmlCleanupParser(); |
---|
| 172 | return true; |
---|
| 173 | } // IF Config valid END |
---|
| 174 | else |
---|
| 175 | { |
---|
| 176 | OSG_WARN << "ERROR: visual_data::processXMLConfiguration() - Module configuration not found" << std::endl; |
---|
| 177 | return false; |
---|
| 178 | } |
---|
[157] | 179 | return true; |
---|
| 180 | } |
---|
| 181 | |
---|
[31] | 182 | void visual_dataIO::shutdown() |
---|
| 183 | { |
---|
| 184 | if(initialized) |
---|
| 185 | { |
---|
| 186 | OSG_NOTIFY( osg::ALWAYS ) << "Shutdown visual_dataIO..." << std::endl; |
---|
| 187 | |
---|
[70] | 188 | viewer->getCamera()->removeEventCallback( eventCallback ); |
---|
[31] | 189 | eventCallback = NULL; |
---|
| 190 | viewer->getCamera()->setFinalDrawCallback( NULL ); |
---|
| 191 | finalDrawCallback = NULL; |
---|
[70] | 192 | |
---|
[31] | 193 | viewer = NULL; |
---|
[70] | 194 | |
---|
[31] | 195 | |
---|
[65] | 196 | if(cluster.valid()) |
---|
| 197 | cluster->shutdown(); |
---|
| 198 | if(extLink.valid()) |
---|
[31] | 199 | extLink->shutdown(); |
---|
| 200 | } |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | void visual_dataIO::dataIO_eventCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) |
---|
| 204 | { |
---|
| 205 | // perform all actions for the eventDrawCallback. |
---|
| 206 | OSG_NOTIFY( osg::INFO ) << "---- Executing EventCallback.." << std::endl; |
---|
| 207 | |
---|
| 208 | switch( dataIO->clusterMode ) |
---|
| 209 | { |
---|
| 210 | case osgVisual::dataIO_cluster::MASTER : |
---|
| 211 | { |
---|
| 212 | dataIO->extLink->readTO_OBJvalues(); |
---|
[82] | 213 | dataIO->cluster->sendTO_OBJvaluesToSlaves(dataIO->calcViewMatrix()); |
---|
[31] | 214 | } |
---|
| 215 | break; |
---|
| 216 | case osgVisual::dataIO_cluster::SLAVE : |
---|
| 217 | { |
---|
| 218 | dataIO->cluster->readTO_OBJvaluesFromMaster(); |
---|
| 219 | } |
---|
| 220 | break; |
---|
| 221 | case osgVisual::dataIO_cluster::STANDALONE : |
---|
| 222 | { |
---|
| 223 | dataIO->extLink->readTO_OBJvalues(); |
---|
| 224 | } |
---|
| 225 | break; |
---|
| 226 | default: |
---|
| 227 | OSG_NOTIFY( osg::FATAL ) << "ERROR: Unkown clustermode!" << std::endl; |
---|
| 228 | break; |
---|
| 229 | }; |
---|
[73] | 230 | traverse(node, nv); |
---|
[31] | 231 | } |
---|
| 232 | |
---|
| 233 | void visual_dataIO::dataIO_finalDrawCallback::operator() (const osg::Camera& camera) const |
---|
| 234 | { |
---|
| 235 | // perform all actions for the initialDrawCallback. |
---|
| 236 | OSG_NOTIFY( osg::INFO ) << "---- Executing InitialDrawCallback.." << std::endl; |
---|
| 237 | |
---|
| 238 | switch( dataIO->clusterMode ) |
---|
| 239 | { |
---|
| 240 | case osgVisual::dataIO_cluster::MASTER : |
---|
| 241 | { |
---|
| 242 | dataIO->extLink->writebackFROM_OBJvalues(); |
---|
| 243 | dataIO->cluster->waitForAllReadyToSwap(); |
---|
| 244 | dataIO->cluster->sendSwapCommand(); |
---|
| 245 | } |
---|
| 246 | break; |
---|
| 247 | case osgVisual::dataIO_cluster::SLAVE : |
---|
| 248 | { |
---|
| 249 | dataIO->cluster->reportAsReadyToSwap(); |
---|
| 250 | dataIO->cluster->waitForSwap(); |
---|
| 251 | } |
---|
| 252 | break; |
---|
| 253 | case osgVisual::dataIO_cluster::STANDALONE : |
---|
| 254 | { |
---|
| 255 | dataIO->extLink->writebackFROM_OBJvalues(); |
---|
| 256 | } |
---|
| 257 | break; |
---|
| 258 | default: |
---|
| 259 | OSG_NOTIFY( osg::FATAL ) << "ERROR: visual_dataIO::dataIO_finalDrawCallback::operator() - Unkown clustermode!" << std::endl; |
---|
| 260 | break; |
---|
| 261 | }; |
---|
| 262 | } |
---|
| 263 | |
---|
| 264 | void* visual_dataIO::getSlotPointer(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_, osgVisual::dataIO_slot::varType variableTyp_ ) |
---|
| 265 | { |
---|
| 266 | // iterate through slotlist. If found, return pointer, else add slot to list and return pointer |
---|
| 267 | for (unsigned int i=0; i<dataSlots.size(); i++) |
---|
| 268 | { |
---|
| 269 | // Check if this variable name&-type already exists |
---|
[118] | 270 | if( dataSlots[i]->variableName == variableName_ && dataSlots[i]->direction == direction_ && dataSlots[i]->variableType == variableTyp_) |
---|
[31] | 271 | { |
---|
| 272 | //OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotPointer() - Slot found at position " << i << std::endl; |
---|
| 273 | // Return pointer to the value |
---|
[118] | 274 | return dataSlots[i]; |
---|
[31] | 275 | } |
---|
| 276 | } |
---|
| 277 | |
---|
| 278 | // Slot does not exist -> add it to slot list |
---|
| 279 | //OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotPointer() - Slot not found, will add as new slot " << std::endl; |
---|
[118] | 280 | dataIO_slot* newSlot = new dataIO_slot(); |
---|
| 281 | newSlot->variableName = variableName_; |
---|
| 282 | newSlot->variableType = variableTyp_; |
---|
| 283 | newSlot->value = 0; |
---|
| 284 | newSlot->sValue = ""; |
---|
[31] | 285 | dataSlots.push_back( newSlot ); |
---|
[118] | 286 | return dataSlots.back(); |
---|
[31] | 287 | } |
---|
| 288 | |
---|
| 289 | double visual_dataIO::getSlotDataAsDouble(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_ ) |
---|
| 290 | { |
---|
| 291 | // iterate through slotlist. If found, return value |
---|
| 292 | for (unsigned int i=0; i<dataSlots.size(); i++) |
---|
| 293 | { |
---|
| 294 | // Check if this variable name&-type already exists |
---|
[118] | 295 | if( dataSlots[i]->variableName == variableName_ && dataSlots[i]->direction == direction_ && dataSlots[i]->variableType == osgVisual::dataIO_slot::DOUBLE ) |
---|
[31] | 296 | { |
---|
| 297 | //OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotDataAsDouble() - Slot found at position " << i << std::endl; |
---|
[118] | 298 | return dataSlots[i]->value; |
---|
[31] | 299 | } |
---|
| 300 | } |
---|
| 301 | return 0; |
---|
| 302 | } |
---|
| 303 | |
---|
| 304 | std::string visual_dataIO::getSlotDataAsString(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_ ) |
---|
| 305 | { |
---|
| 306 | // iterate through slotlist. If found, return value |
---|
| 307 | for (unsigned int i=0; i<dataSlots.size(); i++) |
---|
| 308 | { |
---|
| 309 | // Check if this variable name&-type already exists |
---|
[118] | 310 | if( dataSlots[i]->variableName == variableName_ && dataSlots[i]->direction == direction_ && dataSlots[i]->variableType == osgVisual::dataIO_slot::STRING ) |
---|
[31] | 311 | { |
---|
| 312 | //OSG_NOTIFY( osg::INFO ) << "visual_dataIO::getSlotDataAsDouble() - Slot found at position " << i << std::endl; |
---|
[118] | 313 | return dataSlots[i]->sValue; |
---|
[31] | 314 | } |
---|
| 315 | } |
---|
| 316 | return ""; |
---|
| 317 | } |
---|
| 318 | |
---|
[116] | 319 | osgVisual::dataIO_slot* visual_dataIO::setSlotData(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_, std::string sValue_ ) |
---|
[31] | 320 | { |
---|
| 321 | bool slotFound = false; |
---|
| 322 | // iterate through slotlist. If found, return pointer, else add slot to list |
---|
| 323 | for (unsigned int i=0; i<dataSlots.size(); i++) |
---|
| 324 | { |
---|
| 325 | // Check if this variable name&-type already exists |
---|
[118] | 326 | if( dataSlots[i]->variableName == variableName_ && dataSlots[i]->direction == direction_ && dataSlots[i]->variableType == osgVisual::dataIO_slot::STRING) |
---|
[31] | 327 | { |
---|
| 328 | // Update value |
---|
[118] | 329 | dataSlots[i]->sValue = sValue_; |
---|
[31] | 330 | slotFound = true; |
---|
[118] | 331 | return dataSlots[i]; |
---|
[31] | 332 | } |
---|
| 333 | |
---|
| 334 | } |
---|
| 335 | |
---|
| 336 | if (!slotFound) |
---|
| 337 | { |
---|
| 338 | // Slot does not exist -> add it to slot list |
---|
[118] | 339 | dataIO_slot* newSlot = new dataIO_slot(); |
---|
| 340 | newSlot->variableName = variableName_; |
---|
| 341 | newSlot->direction = direction_; |
---|
| 342 | newSlot->variableType = osgVisual::dataIO_slot::STRING; |
---|
| 343 | newSlot->value = 0; |
---|
| 344 | newSlot->sValue = sValue_; |
---|
[31] | 345 | dataSlots.push_back( newSlot ); |
---|
[118] | 346 | return dataSlots.back(); |
---|
[31] | 347 | } |
---|
[116] | 348 | |
---|
| 349 | return NULL; |
---|
[31] | 350 | } |
---|
| 351 | |
---|
[116] | 352 | osgVisual::dataIO_slot* visual_dataIO::setSlotData(std::string variableName_, osgVisual::dataIO_slot::dataDirection direction_, double value_ ) |
---|
[31] | 353 | { |
---|
| 354 | // iterate through slotlist. If found, return pointer, else add slot to list |
---|
| 355 | bool slotFound = false; |
---|
| 356 | for (unsigned int i=0; i<dataSlots.size(); i++) |
---|
| 357 | { |
---|
| 358 | // Check if this variableName & -type already exists |
---|
[118] | 359 | if( dataSlots[i]->variableName == variableName_ && dataSlots[i]->direction == direction_ && dataSlots[i]->variableType == osgVisual::dataIO_slot::DOUBLE) |
---|
[31] | 360 | { |
---|
| 361 | // Update value |
---|
| 362 | //OSG_NOTIFY( osg::ALWAYS ) << "setSlotData: " << variableName_ << " - value: " << value_ << std::endl; |
---|
[118] | 363 | dataSlots[i]->value = value_; |
---|
[31] | 364 | slotFound = true; |
---|
[118] | 365 | return dataSlots[i]; |
---|
[31] | 366 | } |
---|
| 367 | } |
---|
| 368 | |
---|
| 369 | if (!slotFound) |
---|
| 370 | { |
---|
| 371 | // Slot does not exist -> add it to slot list |
---|
[118] | 372 | dataIO_slot* newSlot = new dataIO_slot(); |
---|
| 373 | newSlot->variableName = variableName_; |
---|
| 374 | newSlot->direction = direction_; |
---|
| 375 | newSlot->variableType = osgVisual::dataIO_slot::DOUBLE; |
---|
| 376 | newSlot->value = value_; |
---|
| 377 | newSlot->sValue = ""; |
---|
[31] | 378 | dataSlots.push_back( newSlot ); |
---|
[118] | 379 | return dataSlots.back(); |
---|
[31] | 380 | } |
---|
[116] | 381 | |
---|
| 382 | return NULL; |
---|
[82] | 383 | } |
---|
| 384 | |
---|
| 385 | osg::Matrixd visual_dataIO::calcViewMatrix() |
---|
| 386 | { |
---|
| 387 | return viewer->getCameraManipulator()->getInverseMatrix(); |
---|
[31] | 388 | } |
---|