- Timestamp:
- 01/31/10 13:55:29 (3 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.cpp
r9585 r11032 27 27 #include <Inventor/SoInteraction.h> 28 28 #include <Inventor/nodes/SoSeparator.h> 29 #include <Inventor/nodes/SoTransformSeparator.h> 29 30 #include <Inventor/nodes/SoShape.h> 30 31 #include <Inventor/nodes/SoVertexShape.h> … … 38 39 #include <Inventor/nodes/SoLOD.h> 39 40 #include <Inventor/nodes/SoTexture2.h> 41 #include <Inventor/nodes/SoEnvironment.h> 40 42 #include <Inventor/misc/SoChildList.h> 41 43 #include <Inventor/SoPrimitiveVertex.h> … … 43 45 #include <Inventor/nodes/SoTransform.h> 44 46 #include <Inventor/nodes/SoInfo.h> 47 #include <Inventor/actions/SoWriteAction.h> 48 #include <Inventor/elements/SoModelMatrixElement.h> 45 49 46 50 #ifdef __COIN__ … … 51 55 #endif 52 56 53 #include "GroupSoLOD.h" 57 #if defined(__COIN__) && (COIN_MAJOR_VERSION >= 3 || \ 58 (COIN_MAJOR_VERSION == 2 && COIN_MINOR_VERSION>=5)) 59 #define INVENTOR_SHADERS_AVAILABLE 60 #endif 61 62 #ifdef INVENTOR_SHADERS_AVAILABLE 63 #include <Inventor/nodes/SoShaderProgram.h> 64 #include <Inventor/nodes/SoVertexShader.h> 65 #include <Inventor/nodes/SoGeometryShader.h> 66 #include <Inventor/nodes/SoFragmentShader.h> 67 #endif 54 68 55 69 #include <map> … … 65 79 66 80 #define DEBUG_IV_PLUGIN 81 #define NOTIFY_HEADER "Inventor Plugin (reader): " 82 67 83 /////////////////////////////////////////// 68 84 ConvertFromInventor::ConvertFromInventor() … … 71 87 transformInfoName = ""; 72 88 appearanceName = ""; 73 inAppearanceWithNoTexture = false;74 lightGroup = NULL;75 89 } 76 90 /////////////////////////////////////////// … … 78 92 { 79 93 } 94 /////////////////////////////////////////////////////////////////// 95 static bool 96 nodePreservesState(const SoNode *node) 97 { 98 return node->isOfType(SoSeparator::getClassTypeId()) || 99 (node->getChildren() != NULL && node->affectsState() == FALSE); 100 } 101 //////////////////////////////////////////////////////////////////// 102 SoCallbackAction::Response 103 ConvertFromInventor::restructure(void* data, SoCallbackAction* action, 104 const SoNode* node) 105 { 106 #ifdef DEBUG_IV_PLUGIN 107 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "restructure() " 108 << node->getTypeId().getName().getString(); 109 #endif 110 111 int childrenTotal = 0; 112 int numModifiedChildren = 0; 113 int numRemovedNodes = 0; 114 std::vector<std::vector<int> > &stack = *((std::vector<std::vector<int> >*)data); 115 116 if (node->isOfType(SoGroup::getClassTypeId())) { 117 118 SoGroup *group = (SoGroup*)node; 119 SoGroup *affectedScene = NULL; 120 childrenTotal = group->getNumChildren(); 121 122 for (int i=0, c=group->getNumChildren(); i<c; i++) { 123 SoNode *child = group->getChild(i); 124 if (!child->isOfType(SoSeparator::getClassTypeId()) && 125 child->affectsState()) { 126 127 // Put the node bellow separator 128 SoSeparator *s = new SoSeparator; 129 s->addChild(group->getChild(i)); 130 group->replaceChild(i, s); 131 numModifiedChildren++; 132 133 // Create the scene that may be affected by the node 134 if (!affectedScene) { 135 136 // Create the graph of nodes that may be influenced 137 // by the node 138 const SoFullPath *path = (const SoFullPath*)action->getCurPath(); 139 assert(path->getLength() == 0 || 140 path->getNode(path->getLength()-1) == group && 141 "Group being restructured is not at the end of the path."); 142 int stackLevel = stack.size()-2; 143 for (int j=path->getLength()-2; j>=0; j--, stackLevel--) { 144 145 // Get the appropriate stack level of nodesToRemove 146 assert(stackLevel >=0); 147 std::vector<int> &nodesToRemove = stack[stackLevel]; 148 149 // Get parent and index of the current group 150 SoNode *parent = path->getNode(j); 151 int childIndex = path->getIndex(j+1); 152 const SoChildList *chl = parent->getChildren(); 153 assert(chl->operator[](childIndex) == path->getNode(j+1) && 154 "Wrong indexing."); 155 156 // Create affected scene graph 157 if (!affectedScene) 158 affectedScene = new SoGroup; 159 160 // Copy nodes to the graph 161 for (int k=childIndex+1, n=chl->getLength(); k<n; k++) { 162 affectedScene->addChild(chl->operator[](k)); 163 nodesToRemove.push_back(k); 164 numRemovedNodes++; 165 } 166 167 // Stop recursion if we reached separator 168 // or other state-preserving node. 169 if (nodePreservesState(parent)) 170 break; 171 } 172 } 173 174 // Append the affected graph to the separator 175 s->addChild(affectedScene); 176 } 177 } 178 } 179 180 #ifdef DEBUG_IV_PLUGIN 181 if (numModifiedChildren == 0) 182 osg::notify(osg::DEBUG_INFO) << ": no changes necessary" << std::endl; 183 else 184 osg::notify(osg::DEBUG_INFO) << ": " << numModifiedChildren << 185 " nodes of " << childrenTotal << " restruc., " << 186 numRemovedNodes << " removed" << std::endl; 187 #endif 188 189 return SoCallbackAction::CONTINUE; 190 } 80 191 /////////////////////////////////////////////////////////// 81 osg::Node* ConvertFromInventor::convert(SoNode* rootIVNode) 82 { 83 // Transformation matrix for converting Inventor coordinate system to OSG 192 SoCallbackAction::Response 193 ConvertFromInventor::restructurePreNode(void* data, SoCallbackAction* action, 194 const SoNode* node) 195 { 196 std::vector<std::vector<int> > &stack = *((std::vector<std::vector<int> >*)data); 197 198 stack.push_back(std::vector<int>()); 199 200 return SoCallbackAction::CONTINUE; 201 } 202 //////////////////////////////////////////////////////////////////// 203 SoCallbackAction::Response 204 ConvertFromInventor::restructurePostNode(void* data, SoCallbackAction* action, 205 const SoNode* node) 206 { 207 std::vector<std::vector<int> > &stack = *((std::vector<std::vector<int> >*)data); 208 209 assert(stack.size() > 0 && "Stack is empty"); 210 std::vector<int> &nodesToRemove = stack.back(); 211 212 if (nodesToRemove.size() > 0) { 213 214 #ifdef DEBUG_IV_PLUGIN 215 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postNode() " 216 << node->getTypeId().getName().getString() 217 << " (level " << stack.size() << ") removed " 218 << nodesToRemove.size() << " node(s)" << std::endl; 219 #endif 220 221 assert(node->getChildren()); 222 for (int i=nodesToRemove.size()-1; i>=0; i--) { 223 assert(i==0 || nodesToRemove[i-1] < nodesToRemove[i] && 224 "Children to remove are not in order."); 225 node->getChildren()->remove(nodesToRemove[i]); 226 } 227 } 228 229 stack.pop_back(); 230 231 return SoCallbackAction::CONTINUE; 232 } 233 /////////////////////////////////////////////////////////////////// 234 void 235 ConvertFromInventor::preprocess(SoNode* root) 236 { 237 #ifdef DEBUG_IV_PLUGIN 238 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "Preprocessing..." << std::endl; 239 #endif 240 241 SoCallbackAction action; 242 std::vector<std::vector<int> > stackOfNodesToRemove; 243 244 // Callbacks for troublesome nodes 245 action.addPreCallback(SoNode::getClassTypeId(), 246 restructurePreNode, &stackOfNodesToRemove); 247 action.addPostCallback(SoLOD::getClassTypeId(), 248 restructure, &stackOfNodesToRemove); 249 action.addPostCallback(SoNode::getClassTypeId(), 250 restructurePostNode, &stackOfNodesToRemove); 251 252 // Traverse the scene 253 action.apply(root); 254 255 #if 0 // For debugging purposes: Write preprocessed scene to the file 256 SoOutput out; 257 out.openFile("preprocess.iv"); 258 SoWriteAction wa(&out); 259 wa.apply(root); 260 #endif 261 } 262 /////////////////////////////////////////////////////////// 263 osg::Node* 264 ConvertFromInventor::convert(SoNode* ivRootNode) 265 { 266 #ifdef DEBUG_IV_PLUGIN 267 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "Converting..." << std::endl; 268 #endif 269 270 // Transformation matrix for converting Inventor coordinate system to OSG 84 271 // coordinate system 85 272 osg::Matrix ivToOSGMat(osg::Matrix(1.0, 0.0, 0.0, 0.0, … … 88 275 0.0, 0.0, 0.0, 1.0)); 89 276 90 // Create a root node and push it onto the stack 91 _root = new osg::MatrixTransform; 92 _root->setMatrix(ivToOSGMat); 93 groupStack.push(_root.get()); 94 95 // Push an empty list of light and push it onto the light stack 96 LightList lightList; 97 lightStack.push(lightList); 98 99 // Create callback actions for the inventor nodes 277 // Root of the scene 278 osg::ref_ptr<osg::Group> osgRootNode = new osg::MatrixTransform(ivToOSGMat); 279 280 // Initialize Inventor state stack 281 // (ivStateStack is used to track the state that is not accessible by 282 // SoCallbackAction functions) 283 ivStateStack.push(IvStateItem(ivRootNode, osgRootNode)); 284 285 // Create callback actions for the inventor nodes 100 286 // These callback functions perform the conversion 101 287 // note: if one class is derived from the other and both callbacks 102 288 // are registered, both functions will be called 103 289 SoCallbackAction cbAction; 290 291 // Node callbacks are used for detecting which node 292 // preserves state (like SoSeparator) and which not. 293 // There are few nodes that behave like SoSeparator although they 294 // are not derived from it. 295 // Note: postNode callback is moved down, because it must be 296 // called as the last callback. 297 cbAction.addPreCallback(SoNode::getClassTypeId(), preNode, this); 298 299 // SoTransformSeparator callbacks. Special handling of transformations. 300 cbAction.addPreCallback(SoTransformSeparator::getClassTypeId(), preTransformSeparator, this); 301 cbAction.addPostCallback(SoTransformSeparator::getClassTypeId(), postTransformSeparator, this); 302 303 // LOD (Level of Detail) callbacks. Handles SoLOD nodes. 304 // FIXME: SoLevelOfDetail needs to be implemented and tested. 305 cbAction.addPreCallback(SoLOD::getClassTypeId(), preLOD, this); 306 cbAction.addPostCallback(SoLOD::getClassTypeId(), postLOD, this); 307 308 // Shape callbacks collects all triangles and all the geometry data. 309 // Moreover, they handle transformations, ... 104 310 cbAction.addPreCallback(SoShape::getClassTypeId(), preShape, this); 105 311 cbAction.addPostCallback(SoShape::getClassTypeId(), postShape, this); 106 cbAction.addPreCallback(SoGroup::getClassTypeId(), preGroup, this); 107 cbAction.addPostCallback(SoGroup::getClassTypeId(), postGroup, this); 108 cbAction.addPreCallback(SoTexture2::getClassTypeId(), preTexture, this); 312 313 // Handling of textures 314 cbAction.addPostCallback(SoTexture2::getClassTypeId(), 315 postTexture, this); 109 316 #ifdef __COIN__ 110 cbAction.addPreCallback(SoVRMLImageTexture::getClassTypeId(), 111 preVRMLImageTexture, this); 112 cbAction.addPreCallback(SoVRMLAppearance::getClassTypeId(), 113 preVRMLAppearance, this); 317 cbAction.addPostCallback(SoVRMLImageTexture::getClassTypeId(), 318 postTexture, this); 319 cbAction.addPostCallback(SoVRMLAppearance::getClassTypeId(), 320 postTexture, this); 321 #endif 322 323 #ifdef __COIN__ 114 324 cbAction.addPreCallback(SoInfo::getClassTypeId(), preInfo, this); 115 325 #endif 326 327 // Lights 116 328 cbAction.addPreCallback(SoLight::getClassTypeId(), preLight, this); 329 330 // Environment (ambient light,...) 331 cbAction.addPreCallback(SoEnvironment::getClassTypeId(), preEnvironment, this); 332 333 // Shaders 334 #ifdef INVENTOR_SHADERS_AVAILABLE 335 cbAction.addPreCallback(SoShaderProgram::getClassTypeId(), preShaderProgram, this); 336 #endif 337 338 // Motion callbacks 117 339 cbAction.addPreCallback(SoRotor::getClassTypeId(), preRotor, this); 118 340 cbAction.addPreCallback(SoPendulum::getClassTypeId(), prePendulum, this); 119 341 cbAction.addPreCallback(SoShuttle::getClassTypeId(), preShuttle, this); 342 343 // Geometry callbacks 120 344 cbAction.addTriangleCallback(SoShape::getClassTypeId(), addTriangleCB, this); 121 345 cbAction.addLineSegmentCallback(SoShape::getClassTypeId(), addLineSegmentCB, … … 123 347 cbAction.addPointCallback(SoShape::getClassTypeId(), addPointCB, this); 124 348 349 // Post node callback 350 cbAction.addPostCallback(SoNode::getClassTypeId(), postNode, this); 351 125 352 // Traverse the inventor scene graph 126 cbAction.apply(rootIVNode); 127 128 // Pop all the groups that are Transforms 129 // Verify that the last transform is _root . 130 assert(groupStack.size() > 0 && "groupStack underflow."); 131 osg::ref_ptr<osg::Group> group = groupStack.top(); 132 while (strcmp(group->className(), "MatrixTransform") == 0) 133 { 134 groupStack.pop(); 135 if (groupStack.empty()) break; 136 group = groupStack.top(); 137 } 138 assert(group.get() == _root.get() && "groupStack error"); 139 assert(groupStack.size() == 0 && "groupStack is not empty after traversal."); 140 141 assert(soTexStack.size() == 0 && "soTexStack was left at inconsistent state."); 142 143 assert(lightStack.size() == 1 && "lightStack was left at inconsistent state."); 144 lightStack.pop(); 145 146 return _root.get(); 353 cbAction.apply(ivRootNode); 354 355 // Remove superfluous group 356 if (osgRootNode->getNumChildren() == 1) { 357 osg::ref_ptr<osg::Group> toRemove = osgRootNode->getChild(0)->asGroup(); 358 assert(toRemove.get() && 359 strcmp(toRemove->className(), "Group") == 0 && 360 "IvStateStack osg graph is expected to be " 361 "headed by osg::Group"); 362 osgRootNode->removeChild(0u); 363 for (int i=0, c=toRemove->getNumChildren(); i<c; i++) 364 osgRootNode->addChild(toRemove->getChild(i)); 365 } 366 367 return osgRootNode.get(); 147 368 } 148 369 /////////////////////////////////////////////////////////////////// 149 SoCallbackAction::Response 150 ConvertFromInventor::preShape(void* data, SoCallbackAction* action, 370 static void 371 notifyAboutMatrixContent(const osg::NotifySeverity level, const SbMatrix &m) 372 { 373 SbVec3f t,s; 374 SbRotation r,so; 375 m.getTransform(t, r, s, so); 376 SbVec3f axis; 377 float angle; 378 r.getValue(axis, angle); 379 osg::notify(level) << NOTIFY_HEADER << " Translation: " << 380 t[0] << "," << t[1] << "," << t[2] << std::endl; 381 osg::notify(level) << NOTIFY_HEADER << " Rotation: (" << 382 axis[0] << "," << axis[1] << "," << axis[2] << ")," << angle << std::endl; 383 } 384 /////////////////////////////////////////////////////////////////// 385 void 386 ConvertFromInventor::appendNode(osg::Node *n, const SoCallbackAction *action) 387 { 388 IvStateItem &ivState = ivStateStack.top(); 389 SbMatrix currentMatrix = action->getModelMatrix(); 390 SbMatrix inheritedMatrix = ivState.inheritedTransformation; 391 392 // Keep children order - this must be done for some nodes like 393 // SoSwitch, SoLOD,... 394 // We will append dummy nodes if the child is expected to be on 395 // higher index. 396 if (ivState.flags & IvStateItem::KEEP_CHILDREN_ORDER) { 397 398 // Determine child index 399 int childIndex = -1; 400 const SoFullPath *path = (const SoFullPath*)(((SoCallbackAction*)action)->getCurPath()); 401 for (int i=path->getLength()-2; i>=0; i--) 402 if (path->getNode(i) == ivState.keepChildrenOrderParent) { 403 childIndex = path->getIndex(i+1); 404 assert(ivState.keepChildrenOrderParent->getChildren()); 405 assert((ivState.keepChildrenOrderParent->getChildren()->operator[](childIndex) == path->getNode(i+1)) && "Indexing is wrong."); 406 break; 407 } 408 assert(childIndex != -1 && "Node did not found."); 409 410 // Append dummy nodes to keep children order 411 assert(int(ivState.osgStateRoot->getNumChildren()) <= childIndex && 412 "Number of children in ivState.osgStateRoot is too big."); 413 while (int(ivState.osgStateRoot->getNumChildren()) < childIndex) 414 ivState.osgStateRoot->addChild(new osg::Node); 415 } 416 417 #ifdef DEBUG_IV_PLUGIN 418 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "appendNode: " 419 << n->className(); 420 #endif 421 422 if (currentMatrix == inheritedMatrix) { 423 424 // just append node to the current group in osg scene graph 425 ivState.osgStateRoot->addChild(n); 426 ivState.lastUsedTransformation = inheritedMatrix; 427 428 #ifdef DEBUG_IV_PLUGIN 429 if (osg::isNotifyEnabled(osg::DEBUG_INFO)) 430 osg::notify(osg::DEBUG_INFO) << 431 " uses parent transformation" << std::endl; 432 #endif 433 434 } else { 435 436 if (!(ivState.flags & IvStateItem::KEEP_CHILDREN_ORDER) && 437 currentMatrix == ivState.lastUsedTransformation) { 438 439 // Previous node has the same transformation. Let's use it. 440 assert(ivState.osgStateRoot->getNumChildren() != 0 && 441 "This should never happen - there is no item on " 442 "osgShapeGraphs list while want to use last one."); 443 osg::Transform *t = ivState.osgStateRoot->getChild(ivState.osgStateRoot->getNumChildren()-1)->asTransform(); 444 assert(t && "This should never happen - want to use " 445 "transformation of previous scene geometry " 446 "and it does not have Transform node."); 447 t->addChild(n); 448 449 #ifdef DEBUG_IV_PLUGIN 450 if (osg::isNotifyEnabled(osg::DEBUG_INFO)) 451 osg::notify(osg::DEBUG_INFO) << 452 " reuses previous transformation" << std::endl; 453 #endif 454 455 } else { 456 457 // We need a new transformation node 458 osg::Matrix m(osg::Matrix(currentMatrix.operator float*())); 459 osg::Matrix m2; 460 m2.invert(osg::Matrix(inheritedMatrix.operator float*())); 461 m.postMult(m2); 462 osg::MatrixTransform *mt = new osg::MatrixTransform(m); 463 mt->addChild(n); 464 465 ivState.osgStateRoot->addChild(mt); 466 ivState.lastUsedTransformation = currentMatrix; 467 468 #ifdef DEBUG_IV_PLUGIN 469 if (osg::isNotifyEnabled(osg::DEBUG_INFO)) { 470 osg::notify(osg::DEBUG_INFO) << 471 " uses local transformation:" << std::endl; 472 notifyAboutMatrixContent(osg::DEBUG_INFO, 473 SbMatrix((SbMat&)(*osg::Matrixf(m).ptr()))); 474 } 475 #endif 476 } 477 } 478 } 479 /////////////////////////////////////////////////////////////////// 480 void 481 ConvertFromInventor::ivPushState(const SoCallbackAction *action, 482 const SoNode *initiator, const int flags, 483 osg::Group *root) 484 { 485 assert(ivStateStack.size() >= 1 && "There must be at least one " 486 "value in the ivStateStack to use ivPushState function."); 487 488 // APPEND_AT_PUSH 489 if (flags & IvStateItem::APPEND_AT_PUSH) 490 appendNode(root, action); 491 492 // Push state 493 ivStateStack.push(IvStateItem(ivStateStack.top(), action, initiator, flags, root)); 494 495 } 496 /////////////////////////////////////////////////////////////////// 497 void 498 ConvertFromInventor::ivPopState(const SoCallbackAction *action, 499 const SoNode *initiator) 500 { 501 bool multipop; 502 do { 503 assert(ivStateStack.size() >= 2 && "There must be at least two " 504 "values in the ivStateStack to use ivPopState function."); 505 506 // Get multipop value 507 IvStateItem ivState = ivStateStack.top(); 508 multipop = ivState.flags & IvStateItem::MULTI_POP; 509 assert(multipop || 510 ivState.pushInitiator == initiator && 511 "ivStateStack push was initiated by different node."); 512 513 // Get osgStateRoot (note: we HAVE TO reference it) 514 osg::Group *stateRoot = ivState.osgStateRoot; 515 osg::ref_ptr<osg::Group> r = stateRoot; 516 /* assert(strcmp(stateRoot->className(), "Group") == 0 && 517 "IvStateStack osg graph is expected to be " 518 "headed by osg::Group"); 519 if (stateRoot->getNumChildren() == 1) { 520 r = stateRoot->getChild(0)->asGroup(); 521 osg::notify(osg::FATAL) << stateRoot->className() << std::endl; 522 osg::notify(osg::FATAL) << stateRoot->getChild(0)->className() << std::endl; 523 exit(0); 524 assert(r != NULL && "Node must be group."); 525 }*/ 526 527 // Pop state 528 ivStateStack.pop(); 529 530 // Update state from already popped values 531 if ((ivState.flags & (IvStateItem::UPDATE_STATE | 532 IvStateItem::UPDATE_STATE_EXCEPT_TRANSFORM)) != 0) { 533 IvStateItem &newTop = ivStateStack.top(); 534 newTop.currentTexture = ivState.currentTexture; 535 newTop.currentLights = ivState.currentLights; 536 newTop.currentGLProgram = ivState.currentGLProgram; 537 } 538 539 // APPEND_AT_PUSH 540 if (!(ivState.flags & IvStateItem::APPEND_AT_PUSH)) 541 appendNode(r, action); 542 543 } while (multipop); 544 545 } 546 /////////////////////////////////////////////////////////////////// 547 SoCallbackAction::Response 548 ConvertFromInventor::preNode(void* data, SoCallbackAction* action, 549 const SoNode* node) 550 { 551 #ifdef DEBUG_IV_PLUGIN 552 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preNode() " 553 << node->getTypeId().getName().getString() << std::endl; 554 #endif 555 556 if (nodePreservesState(node)) { 557 558 // push state 559 ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 560 thisPtr->ivPushState(action, node); 561 #ifdef DEBUG_IV_PLUGIN 562 if (osg::isNotifyEnabled(osg::DEBUG_INFO)) { 563 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "push state, saved values: " << std::endl; 564 notifyAboutMatrixContent(osg::DEBUG_INFO, action->getModelMatrix()); 565 } 566 #endif 567 } 568 569 return SoCallbackAction::CONTINUE; 570 } 571 //////////////////////////////////////////////////////////////////// 572 SoCallbackAction::Response 573 ConvertFromInventor::postNode(void* data, SoCallbackAction* action, 151 574 const SoNode* node) 152 575 { 153 576 #ifdef DEBUG_IV_PLUGIN 154 osg::notify(osg:: INFO) << "preShape() "577 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postNode() " 155 578 << node->getTypeId().getName().getString() << std::endl; 156 579 #endif 157 580 581 if (nodePreservesState(node)) { 582 583 // pop state 584 ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 585 assert(thisPtr->ivStateStack.size() > 0 && "ivStackState underflow"); 586 thisPtr->ivPopState(action, node); 587 588 #ifdef DEBUG_IV_PLUGIN 589 if (osg::isNotifyEnabled(osg::DEBUG_INFO)) { 590 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << 591 "pop state, restored transformation: " << std::endl; 592 notifyAboutMatrixContent(osg::DEBUG_INFO, action->getModelMatrix()); 593 } 594 #endif 595 } 596 597 return SoCallbackAction::CONTINUE; 598 } 599 /////////////////////////////////////////////////////////////////// 600 SoCallbackAction::Response 601 ConvertFromInventor::preTransformSeparator(void* data, SoCallbackAction* action, 602 const SoNode* node) 603 { 604 #ifdef DEBUG_IV_PLUGIN 605 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preTransformSeparator() " 606 << node->getTypeId().getName().getString() << std::endl; 607 #endif 608 609 // push state 610 ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 611 thisPtr->ivPushState(action, node, IvStateItem::UPDATE_STATE_EXCEPT_TRANSFORM, 612 new osg::Group()); 613 614 return SoCallbackAction::CONTINUE; 615 } 616 //////////////////////////////////////////////////////////////////// 617 SoCallbackAction::Response 618 ConvertFromInventor::postTransformSeparator(void* data, SoCallbackAction* action, 619 const SoNode* node) 620 { 621 #ifdef DEBUG_IV_PLUGIN 622 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postTransformSeparator() " 623 << node->getTypeId().getName().getString() << std::endl; 624 #endif 625 626 // pop state 627 ConvertFromInventor *thisPtr = (ConvertFromInventor *) data; 628 assert(thisPtr->ivStateStack.size() > 0 && "ivStackState underflow"); 629 thisPtr->ivPopState(action, node); 630 631 return SoCallbackAction::CONTINUE; 632 } 633 /////////////////////////////////////////////////////////////////// 634 SoCallbackAction::Response 635 ConvertFromInventor::preLOD(void* data, SoCallbackAction* action, 636 const SoNode* node) 637 { 638 #ifdef DEBUG_IV_PLUGIN 639 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preLOD() " 640 << node->getTypeId().getName().getString() << std::endl; 641 #endif 642 643 // init values 644 ConvertFromInventor* thisPtr = (ConvertFromInventor*)data; 645 646 // SoLOD 647 // Note: It is not possible to convert SoLOD to osg:LOD 648 // in any non-complex algorithm, because SoLOD does not preserves 649 // traversal state (like SoSeparator). Thus, following example 650 // can not be easily converted: 651 // 652 // SoLOD { 653 // range [...] 654 // Complexity { value 0.1 } 655 // Complexity { value 0.2 } 656 // Complexity { value 0.3 } 657 // } 658 // Sphere {} 659 // 660 // It was decided that it is necessary to preprocess scene 661 // in a way to avoid any state to come out of SoLOD. For example: 662 // 663 // SoLOD { 664 // range [...] 665 // Separator { 666 // Complexity { value 0.1 } 667 // DEF mySphere Sphere {} 668 // } 669 // Separator { 670 // Complexity { value 0.2 } 671 // USE mySphere 672 // } 673 // Separator { 674 // Complexity { value 0.3 } 675 // USE mySphere 676 // } 677 // } 678 // 679 // Such scene can be converted easily to OSG. 680 if (node->isOfType(SoLOD::getClassTypeId())) { 681 682 thisPtr->ivPushState(action, node, IvStateItem::KEEP_CHILDREN_ORDER, 683 new osg::LOD); 684 thisPtr->ivStateStack.top().keepChildrenOrderParent = node; 685 686 return SoCallbackAction::CONTINUE; 687 } 688 689 return SoCallbackAction::CONTINUE; 690 } 691 ////////////////////////////////////////////////////////////// 692 SoCallbackAction::Response 693 ConvertFromInventor::postLOD(void* data, SoCallbackAction* action, 694 const SoNode* node) 695 { 696 #ifdef DEBUG_IV_PLUGIN 697 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postLOD() " 698 << node->getTypeId().getName().getString() << std::endl; 699 #endif 700 701 // SoGroup -> do nothing 702 if (node->getTypeId() == SoGroup::getClassTypeId()) 703 return SoCallbackAction::CONTINUE; 704 705 // init values 706 ConvertFromInventor* thisPtr = (ConvertFromInventor*)data; 707 IvStateItem &ivState = thisPtr->ivStateStack.top(); 708 709 // SoLOD 710 if (node->isOfType(SoLOD::getClassTypeId())) { 711 712 osg::LOD *lod = dynamic_cast<osg::LOD*>(ivState.osgStateRoot.get()); 713 SoLOD *ivLOD = (SoLOD*)node; 714 715 // LOD center 716 SbVec3f ivCenter = ivLOD->center.getValue(); 717 lod->setCenter(osg::Vec3(ivCenter[0], ivCenter[1], ivCenter[2])); 718 719 // Verify the number of children and range values 720 int num = lod->getNumChildren(); 721 if (ivLOD->range.getNum()+1 != num && 722 !(num == 0 && ivLOD->range.getNum() == 0)) { 723 osg::notify(osg::WARN) << NOTIFY_HEADER << 724 "Warning: SoLOD does not contain " 725 "correct data in range field." << std::endl; 726 if (ivLOD->range.getNum()+1 < num) { 727 lod->removeChildren(ivLOD->range.getNum() + 1, 728 num - ivLOD->range.getNum() - 1); 729 num = ivLOD->range.getNum() + 1; 730 } 731 } 732 733 // Get the ranges and set it 734 if (num > 0) { 735 if (num == 1) 736 lod->setRange(0, 0.0, FLT_MAX); 737 else { 738 lod->setRange(0, 0.0, ivLOD->range[0]); 739 for (int i = 1; i < num-1; i++) 740 lod->setRange(i, ivLOD->range[i-1], ivLOD->range[i]); 741 lod->setRange(num-1, ivLOD->range[num-2], FLT_MAX); 742 } 743 } 744 745 #ifdef DEBUG_IV_PLUGIN 746 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << 747 "Appending osg::LOD with " << num << " children." << std::endl; 748 #endif 749 750 assert(ivState.keepChildrenOrderParent == node && 751 "Current node is not the root of keepChildrenOrder graph."); 752 thisPtr->ivPopState(action, node); 753 754 return SoCallbackAction::CONTINUE; 755 } 756 757 return SoCallbackAction::CONTINUE; 758 } 759 /////////////////////////////////////////////////////////////////// 760 SoCallbackAction::Response 761 ConvertFromInventor::preShape(void* data, SoCallbackAction* action, 762 const SoNode* node) 763 { 764 #ifdef DEBUG_IV_PLUGIN 765 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preShape() " 766 << node->getTypeId().getName().getString() << std::endl; 767 #endif 768 158 769 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 159 770 160 771 // Normal and color binding map from Inventor to OSG 161 static std::map<SoNormalBinding::Binding, osg::Geometry::AttributeBinding> 772 static std::map<SoNormalBinding::Binding, osg::Geometry::AttributeBinding> 162 773 normBindingMap; 163 774 static std::map<SoMaterialBinding::Binding, osg::Geometry::AttributeBinding> … … 166 777 if (firstTime) 167 778 { 168 normBindingMap[SoNormalBinding::OVERALL] 779 normBindingMap[SoNormalBinding::OVERALL] 169 780 = osg::Geometry::BIND_OVERALL; 170 normBindingMap[SoNormalBinding::PER_PART] 781 normBindingMap[SoNormalBinding::PER_PART] 171 782 = osg::Geometry::BIND_PER_PRIMITIVE; 172 normBindingMap[SoNormalBinding::PER_PART_INDEXED] 783 normBindingMap[SoNormalBinding::PER_PART_INDEXED] 173 784 = osg::Geometry::BIND_PER_PRIMITIVE; 174 normBindingMap[SoNormalBinding::PER_FACE] 785 normBindingMap[SoNormalBinding::PER_FACE] 175 786 = osg::Geometry::BIND_PER_PRIMITIVE; 176 normBindingMap[SoNormalBinding::PER_FACE_INDEXED] 787 normBindingMap[SoNormalBinding::PER_FACE_INDEXED] 177 788 = osg::Geometry::BIND_PER_PRIMITIVE; 178 normBindingMap[SoNormalBinding::PER_VERTEX] 789 normBindingMap[SoNormalBinding::PER_VERTEX] 179 790 = osg::Geometry::BIND_PER_VERTEX; 180 normBindingMap[SoNormalBinding::PER_VERTEX_INDEXED] 791 normBindingMap[SoNormalBinding::PER_VERTEX_INDEXED] 181 792 = osg::Geometry::BIND_PER_VERTEX; 182 793 183 colBindingMap[SoMaterialBinding::OVERALL] 794 colBindingMap[SoMaterialBinding::OVERALL] 184 795 = osg::Geometry::BIND_OVERALL; 185 796 colBindingMap[SoMaterialBinding::PER_PART] 186 797 = osg::Geometry::BIND_PER_PRIMITIVE; 187 colBindingMap[SoMaterialBinding::PER_PART_INDEXED] 798 colBindingMap[SoMaterialBinding::PER_PART_INDEXED] 188 799 = osg::Geometry::BIND_PER_PRIMITIVE; 189 800 colBindingMap[SoMaterialBinding::PER_FACE] 190 801 = osg::Geometry::BIND_PER_PRIMITIVE; 191 colBindingMap[SoMaterialBinding::PER_FACE_INDEXED] 802 colBindingMap[SoMaterialBinding::PER_FACE_INDEXED] 192 803 = osg::Geometry::BIND_PER_PRIMITIVE; 193 colBindingMap[SoMaterialBinding::PER_VERTEX] 804 colBindingMap[SoMaterialBinding::PER_VERTEX] 194 805 = osg::Geometry::BIND_PER_VERTEX; 195 colBindingMap[SoMaterialBinding::PER_VERTEX_INDEXED] 806 colBindingMap[SoMaterialBinding::PER_VERTEX_INDEXED] 196 807 = osg::Geometry::BIND_PER_VERTEX; 197 808 … … 223 834 thisPtr->colors.clear(); 224 835 thisPtr->textureCoords.clear(); 225 836 226 837 return SoCallbackAction::CONTINUE; 227 838 } … … 230 841 //for matrices // 231 842 /////////////////////////////////////////////////////////// 232 void ConvertFromInventor::transposeMatrix(osg::Matrix& mat) 843 void 844 ConvertFromInventor::transposeMatrix(osg::Matrix& mat) 233 845 { 234 846 float tmp; 235 for (int j = 0; j < 4; j++) 236 { 237 for (int i = j + 1; i < 4; i++) 847 for (int j = 0; j < 4; j++) 848 { 849 for (int i = j + 1; i < 4; i++) 238 850 { 239 851 tmp = mat.operator()(j,i); … … 245 857 } 246 858 //////////////////////////////////////////////////////////////////// 247 SoCallbackAction::Response 248 ConvertFromInventor::postShape(void* data, SoCallbackAction* action, 859 SoCallbackAction::Response 860 ConvertFromInventor::postShape(void* data, SoCallbackAction* action, 249 861 const SoNode* node) 250 862 { 251 863 #ifdef DEBUG_IV_PLUGIN 252 osg::notify(osg:: INFO) << "postShape()"864 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postShape() " 253 865 << node->getTypeId().getName().getString() << std::endl; 254 866 #endif … … 291 903 SbColor ambient, diffuse, specular, emission; 292 904 float transparency, shininess; 293 action->getMaterial(ambient, diffuse, specular, emission, shininess, 905 action->getMaterial(ambient, diffuse, specular, emission, shininess, 294 906 transparency, 0); 295 907 (*cols)[0].set(diffuse[0], diffuse[1], diffuse[2], 1.0 - transparency); … … 306 918 307 919 if (thisPtr->textureCoords.empty()) 308 osg::notify(osg:: INFO)<<"tex coords not found"<<std::endl;920 osg::notify(osg::DEBUG_INFO)<<"tex coords not found"<<std::endl; 309 921 else { 310 922 311 923 // report texture coordinate conditions 312 924 if (action->getNumTextureCoordinates()>0) 313 osg::notify(osg:: INFO)<<"tex coords found"<<std::endl;925 osg::notify(osg::DEBUG_INFO)<<"tex coords found"<<std::endl; 314 926 else 315 osg::notify(osg:: INFO)<<"tex coords generated"<<std::endl;927 osg::notify(osg::DEBUG_INFO)<<"tex coords generated"<<std::endl; 316 928 317 929 // Get the texture transformation matrix … … 322 934 osg::Matrix identityMat; 323 935 identityMat.makeIdentity(); 324 osg::ref_ptr<osg::Vec2Array> texCoords 936 osg::ref_ptr<osg::Vec2Array> texCoords 325 937 = new osg::Vec2Array(thisPtr->textureCoords.size()); 326 938 if (textureMat == identityMat) … … 336 948 { 337 949 osg::Vec3 transVec = textureMat.preMult( 338 osg::Vec3(thisPtr->textureCoords[i][0], 950 osg::Vec3(thisPtr->textureCoords[i][0], 339 951 thisPtr->textureCoords[i][1], 340 952 0.0)); … … 345 957 geometry->setTexCoordArray(0, texCoords.get()); 346 958 } 347 959 348 960 // Set the parameters for the geometry 349 961 … … 353 965 osg::ref_ptr<osg::StateSet> stateSet = thisPtr->getStateSet(action); 354 966 geometry->setStateSet(stateSet.get()); 355 967 356 968 // Add the geoset to a geode 357 969 osg::ref_ptr<osg::Geode> geode = new osg::Geode; … … 363 975 geode->setName(name); 364 976 } 365 // Add geode to scenegraph 366 thisPtr->groupStack.top()->addChild(geode.get()); 977 978 // Transformation and scene graph building 979 thisPtr->appendNode(geode.get(), action); 367 980 368 981 return SoCallbackAction::CONTINUE; 369 982 } 370 983 /////////////////////////////////////////////////////////////// 371 SoCallbackAction::Response 372 ConvertFromInventor::preTexture(void* data, SoCallbackAction *, 373 const SoNode* node) 374 { 375 #ifdef DEBUG_IV_PLUGIN 376 osg::notify(osg::INFO) << "preTexture() " 377 << node->getTypeId().getName().getString() << std::endl; 378 #endif 379 984 SoCallbackAction::Response 985 ConvertFromInventor::postTexture(void* data, SoCallbackAction *, 986 const SoNode* node) 987 { 988 #ifdef DEBUG_IV_PLUGIN 989 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "postTexture() " 990 << node->getTypeId().getName().getString(); 991 if (node->isOfType(SoTexture2::getClassTypeId())) { 992 SoTexture2 *t = (SoTexture2*)node; 993 if (t->filename.getValue().getLength()) 994 osg::notify(osg::DEBUG_INFO) << " " << t->filename.getValue().getString(); 995 } 996 osg::notify(osg::DEBUG_INFO) << std::endl; 997 #endif 998 380 999 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 381 382 if (thisPtr->soTexStack.size()) 383 thisPtr->soTexStack.pop(); 384 thisPtr->soTexStack.push(node); 385 1000 bool texturingEnabled = false; 1001 1002 // Texture2 1003 if (node->isOfType(SoTexture2::getClassTypeId())) { 1004 1005 // Check whether texturing was enabled by the texture node 1006 SoTexture2 *t = (SoTexture2*)node; 1007 SbVec2s size; 1008 int nc; 1009 const unsigned char *data = t->image.getValue(size, nc); 1010 texturingEnabled = t->filename.getValue().getLength() || 1011 (data && size != SbVec2s(0,0)); 1012 } 1013 1014 #ifdef __COIN__ 1015 1016 // SoVRMLImageTexture 1017 if (node->isOfType(SoVRMLImageTexture::getClassTypeId())) { 1018 1019 // Check whether texturing was enabled by the texture node 1020 SoVRMLImageTexture *t = (SoVRMLImageTexture*)node; 1021 texturingEnabled = t->url.getNum() > 1 || (t->url.getNum() == 1 && t->url[0].getLength() > 0); 1022 } 1023 1024 // SoVRMLAppearance 1025 if (node->isOfType(SoVRMLAppearance::getClassTypeId())) { 1026 1027 // If SoVRMLAppearance is present and there is no texture 1028 // inside, disable texturing 1029 // FIXME: should SoVRMLAppearance really disable texturing 1030 // when not containing SoVRMLImageTexture? Coin is not doing that, 1031 // but it can be Coin bug. 1032 SoVRMLAppearance *a = (SoVRMLAppearance*)node; 1033 if (a->texture.getValue() == NULL) 1034 thisPtr->ivStateStack.top().currentTexture = NULL; 1035 1036 // Do not try to "optimize" this code by removing the return 1037 // and use the one at the end of the function. 1038 // It would break the case when there is texture inside 1039 // the appearance node. 1040 return SoCallbackAction::CONTINUE; 1041 } 1042 1043 #endif /* __COIN__ */ 1044 1045 // Set current texture 1046 if (texturingEnabled) 1047 thisPtr->ivStateStack.top().currentTexture = node; 1048 else 1049 thisPtr->ivStateStack.top().currentTexture = NULL; 1050 386 1051 return SoCallbackAction::CONTINUE; 387 1052 } 388 //////////////////////////////////////////////////////////////////////////////////389 SoCallbackAction::Response390 ConvertFromInventor::preVRMLAppearance(void* data, SoCallbackAction* action,391 const SoNode* node)392 {393 #ifdef DEBUG_IV_PLUGIN394 osg::notify(osg::INFO) << "preVRMLAppearance() "395 << node->getTypeId().getName().getString() << std::endl;396 #endif397 398 #ifdef __COIN__399 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);400 401 // If there is a VRML appearance node without a texture node, then402 // we push a NULL texture onto the stack403 bool foundTex = false;404 SoChildList *kids = node->getChildren();405 for (int i=0; i<kids->getLength(); i++) {406 SoNode* kid = (SoNode*)kids->get(i);407 if (kid->isOfType(SoVRMLMaterial::getClassTypeId())) {408 thisPtr->appearanceName = kid->getName();409 }410 if (kid->isOfType(SoVRMLTexture::getClassTypeId())) {411 foundTex = true;412 }413 }414 if (!foundTex) {415 thisPtr->soTexStack.push(NULL);416 thisPtr->inAppearanceWithNoTexture = true;417 }418 #endif419 return SoCallbackAction::CONTINUE;420 }421 422 //////////////////////////////////////////////////////////////////////////////////423 SoCallbackAction::Response424 ConvertFromInventor::preVRMLImageTexture(void* data, SoCallbackAction* action,425 const SoNode* node)426 {427 #ifdef DEBUG_IV_PLUGIN428 osg::notify(osg::INFO) << "preVRMLImageTexture() "429 << node->getTypeId().getName().getString() << std::endl;430 #endif431 432 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);433 434 if (thisPtr->soTexStack.size())435 thisPtr->soTexStack.pop();436 thisPtr->soTexStack.push(node);437 438 return SoCallbackAction::CONTINUE;439 }440 1053 ////////////////////////////////////////////////////////////////// 441 void ConvertFromInventor::transformLight(SoCallbackAction* action, 442 const SbVec3f& vec, 1054 void ConvertFromInventor::transformLight(SoCallbackAction* action, 1055 const SbVec3f& vec, 443 1056 osg::Vec3& transVec) 444 1057 { … … 450 1063 } 451 1064 /////////////////////////////////////////////////////////////////// 452 SoCallbackAction::Response 453 ConvertFromInventor::preLight(void* data, SoCallbackAction* action, 1065 SoCallbackAction::Response 1066 ConvertFromInventor::preLight(void* data, SoCallbackAction* action, 454 1067 const SoNode* node) 455 1068 { 456 1069 #ifdef DEBUG_IV_PLUGIN 457 osg::notify(osg:: INFO) << "preLight() "1070 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preLight() " 458 1071 << node->getTypeId().getName().getString() << std::endl; 459 1072 #endif 460 1073 461 1074 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 462 static int lightNum = 1; 463 1075 464 1076 // Return if the light is not on 465 1077 const SoLight* ivLight = (const SoLight*) node; … … 467 1079 return SoCallbackAction::CONTINUE; 468 1080 1081 // Create new OSG light 1082 IvStateItem &ivState = thisPtr->ivStateStack.top(); 469 1083 osg::ref_ptr<osg::Light> osgLight = new osg::Light; 470 osgLight->setLightNum(lightNum++); 471 1084 1085 // Light name 472 1086 const char* name = ivLight->getName().getString(); 473 1087 osgLight->setName(name); 474 1088 475 1089 // Get color and intensity 476 1090 SbVec3f lightColor = ivLight->color.getValue(); … … 478 1092 479 1093 // Set color and intensity 1094 osgLight->setAmbient(osg::Vec4(0.f, 0.f, 0.f, 1.f)); 480 1095 osgLight->setDiffuse(osg::Vec4(lightColor[0] * intensity, 481 1096 lightColor[1] * intensity, 482 1097 lightColor[2] * intensity, 1)); 483 1098 osgLight->setSpecular(osg::Vec4(lightColor[0] * intensity, 1099 lightColor[1] * intensity, 1100 lightColor[2] * intensity, 1)); 1101 1102 // Light type 484 1103 if (node->isOfType(SoDirectionalLight::getClassTypeId())) 485 1104 { 486 1105 SoDirectionalLight *dirLight = (SoDirectionalLight *) node; 487 1106 1107 #if 1 // Let's place the light to its place in scene graph instead of 1108 // old approach of global light group. 1109 SbVec3f l(dirLight->direction.getValue()); 1110 osgLight->setPosition(osg::Vec4(l[0], l[1], l[2] , 0.)); 1111 #else 488 1112 osg::Vec3 transVec; 489 1113 thisPtr->transformLight(action, dirLight->direction.getValue(), transVec); 490 osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 491 transVec.z(), 0)); 1114 osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 1115 transVec.z(), 0.)); 1116 #endif 492 1117 } 493 1118 else if (node->isOfType(SoPointLight::getClassTypeId())) … … 495 1120 SoPointLight* ptLight = (SoPointLight *) node; 496 1121 1122 #if 1 // Let's place the light to its place in scene graph instead of 1123 // old approach of global light group. 1124 SbVec3f l(ptLight->location.getValue()); 1125 osgLight->setPosition(osg::Vec4(l[0], l[1], l[2] , 1.)); 1126 #else 497 1127 osg::Vec3 transVec; 498 1128 thisPtr->transformLight(action, ptLight->location.getValue(), transVec); 499 osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 500 transVec.z(), 0)); 1129 osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 1130 transVec.z(), 1.)); 1131 #endif 501 1132 } 502 1133 else if (node->isOfType(SoSpotLight::getClassTypeId())) … … 507 1138 osgLight->setSpotCutoff(spotLight->cutOffAngle.getValue()*180.0/osg::PI); 508 1139 1140 #if 1 // Let's place the light to its place in scene graph instead of 1141 // old approach of global light group. 1142 SbVec3f l(spotLight->location.getValue()); 1143 osgLight->setPosition(osg::Vec4(l[0], l[1], l[2] , 1.)); 1144 l = spotLight->direction.getValue(); 1145 osgLight->setDirection(osg::Vec3(l[0], l[1], l[2])); 1146 #else 509 1147 osg::Vec3 transVec; 510 1148 thisPtr->transformLight(action, spotLight->location.getValue(), transVec); 511 osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 512 transVec.z(), 0));1149 osgLight->setPosition(osg::Vec4(transVec.x(), transVec.y(), 1150 transVec.z(), 1.)); 513 1151 514 1152 thisPtr->transformLight(action, spotLight->direction.getValue(),transVec); 515 osgLight->setDirection(osg::Vec3(transVec.x(), transVec.y(), 1153 osgLight->setDirection(osg::Vec3(transVec.x(), transVec.y(), 516 1154 transVec.z())); 517 } 518 519 // Add light to list in the current level 520 if (thisPtr->lightStack.size()) 521 { 522 LightList lightList; 523 lightList = thisPtr->lightStack.top(); 524 lightList.push_back(osgLight.get()); 525 thisPtr->lightStack.pop(); 526 thisPtr->lightStack.push(lightList); 527 } 528 529 // add a light source node to the scene graph 1155 #endif 1156 } 1157 1158 // Attenuation 1159 if (!node->isOfType(SoDirectionalLight::getClassTypeId())) { 1160 SbVec3f att = action->getLightAttenuation(); 1161 osgLight->setConstantAttenuation(att[2]); 1162 osgLight->setLinearAttenuation(att[1]); 1163 osgLight->setQuadraticAttenuation(att[0]); 1164 } else { 1165 // keep default light settings for directional light, e.g. 1166 // no attenuation 1167 } 1168 1169 // Append the light into the scene and onto the state stack 1170 osgLight->setLightNum(ivState.currentLights.size()); 1171 ivState.currentLights.push_back(osgLight); 1172 530 1173 osg::ref_ptr<osg::LightSource> ls = new osg::LightSource(); 531 1174 ls->setLight(osgLight.get()); 532 1175 ls->setName(ivLight->getName().getString()); 533 if (thisPtr->lightGroup == NULL) { 534 thisPtr->lightGroup = new osg::Group; 535 thisPtr->lightGroup->setName("IvLightGroup"); 536 thisPtr->_root->addChild(thisPtr->lightGroup.get()); 537 } 538 thisPtr->lightGroup->addChild(ls.get()); 1176 #if 1 // Let's place the light to its place in scene graph instead of 1177 // old approach of global light group. 1178 thisPtr->ivPushState(action, node, 1179 IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 1180 IvStateItem::APPEND_AT_PUSH, ls.get()); 1181 #else 1182 if (!(thisPtr->lightGroup.get())) 1183 thisPtr->lightGroup = new osg::Group(); 1184 thisPtr->lightGroup->addChild(ls); 1185 #endif 1186 1187 return SoCallbackAction::CONTINUE; 1188 } 1189 /////////////////////////////////////////////////////////////////// 1190 SoCallbackAction::Response 1191 ConvertFromInventor::preEnvironment(void* data, SoCallbackAction* action, 1192 const SoNode* node) 1193 { 1194 #ifdef DEBUG_IV_PLUGIN 1195 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preLight() " 1196 << node->getTypeId().getName().getString() << std::endl; 1197 #endif 1198 1199 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 1200 IvStateItem &ivState = thisPtr->ivStateStack.top(); 1201 1202 ivState.currentAmbientLight = ((SoEnvironment*)node)->ambientColor.getValue() * 1203 ((SoEnvironment*)node)->ambientIntensity.getValue(); 1204 1205 return SoCallbackAction::CONTINUE; 1206 } 1207 /////////////////////////////////////////////////////////////////// 1208 #ifdef INVENTOR_SHADERS_AVAILABLE 1209 static bool 1210 convertShader(osg::Shader::Type osgShaderType, 1211 const SoShaderObject *ivShader, 1212 osg::Program *osgProgram) 1213 { 1214 // NULL shader is not converted while returning success 1215 if (ivShader == NULL) 1216 return true; 1217 1218 // Create shader 1219 osg::ref_ptr<osg::Shader> osgShader = new osg::Shader(osgShaderType); 1220 if (ivShader->sourceType.getValue() == SoShaderObject::FILENAME) 1221 osgShader->loadShaderSourceFromFile(ivShader->sourceProgram.getValue().getString()); 1222 else 1223 if (ivShader->sourceType.getValue() == SoShaderObject::GLSL_PROGRAM) 1224 osgShader->setShaderSource(ivShader->sourceProgram.getValue().getString()); 1225 else { 1226 osg::notify(osg::WARN) << NOTIFY_HEADER << "Can not convert " 1227 << "shader. Unsupported shader language." << std::endl; 1228 return false; 1229 } 1230 1231 return osgProgram->addShader(osgShader); 1232 } 1233 #endif // INVENTOR_SHADERS_AVAILABLE 1234 /////////////////////////////////////////////////////////////////// 1235 SoCallbackAction::Response 1236 ConvertFromInventor::preShaderProgram(void* data, SoCallbackAction* action, 1237 const SoNode* node) 1238 { 1239 #ifdef DEBUG_IV_PLUGIN 1240 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preShaderProgram() " 1241 << node->getTypeId().getName().getString() << std::endl; 1242 #endif 1243 1244 #ifdef INVENTOR_SHADERS_AVAILABLE 1245 1246 ConvertFromInventor *thisPtr = (ConvertFromInventor*)data; 1247 IvStateItem &ivState = thisPtr->ivStateStack.top(); 1248 1249 // Get Inventor nodes 1250 // Note: Shaders are available since Coin 2.5 (including 1251 // geometry shader) 1252 const SoShaderProgram *ivProgram = (const SoShaderProgram*)node; 1253 const SoVertexShader *ivVertexShader = NULL; 1254 const SoGeometryShader *ivGeometryShader = NULL; 1255 const SoFragmentShader *ivFragmentShader = NULL; 1256 1257 for (int i=0, c=ivProgram->shaderObject.getNum(); i<c; i++) { 1258 1259 const SoShaderObject *shader = (const SoShaderObject*)ivProgram->shaderObject[i]; 1260 if (!shader->isOfType(SoShaderObject::getClassTypeId())) 1261 continue; 1262 if (shader->isActive.getValue() == FALSE) 1263 continue; 1264 1265 if (shader->isOfType(SoVertexShader::getClassTypeId())) 1266 ivVertexShader = (const SoVertexShader*)shader; 1267 if (shader->isOfType(SoGeometryShader::getClassTypeId())) 1268 ivGeometryShader = (const SoGeometryShader*)shader; 1269 if (shader->isOfType(SoFragmentShader::getClassTypeId())) 1270 ivFragmentShader = (const SoFragmentShader*)shader; 1271 } 1272 1273 // Create OSG shader 1274 osg::Program *osgProgram = new osg::Program(); 1275 if (!convertShader(osg::Shader::VERTEX, ivVertexShader, osgProgram)) 1276 osg::notify(osg::WARN) << NOTIFY_HEADER 1277 << "Failed to add vertex shader." << std::endl; 1278 if (!convertShader(osg::Shader::GEOMETRY, ivGeometryShader, osgProgram)) 1279 osg::notify(osg::WARN) << NOTIFY_HEADER 1280 << "Failed to add geometry shader." << std::endl; 1281 if (!convertShader(osg::Shader::FRAGMENT, ivFragmentShader, osgProgram)) 1282 osg::notify(osg::WARN) << NOTIFY_HEADER 1283 << "Failed to add fragment shader." << std::endl; 1284 1285 // Put shader to the state stack 1286 ivState.currentGLProgram = osgProgram; 1287 1288 #else 1289 1290 osg::notify(osg::WARN) << NOTIFY_HEADER << "Warning: The model " 1291 "contains shaders while your Inventor does not support " 1292 "them." << std::endl; 1293 #endif 539 1294 540 1295 return SoCallbackAction::CONTINUE; … … 545 1300 { 546 1301 osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet; 547 1302 548 1303 // Inherit modes from the global state 549 1304 stateSet->clear(); 550 1305 1306 // Inventor State Stack 1307 IvStateItem &ivState = ivStateStack.top(); 1308 551 1309 // Convert the IV texture to OSG texture if any 552 1310 osg::ref_ptr<osg::Texture2D> texture; 553 const SoNode *ivTexture = soTexStack.top();1311 const SoNode *ivTexture = ivState.currentTexture; 554 1312 if (ivTexture) 555 1313 { 556 osg::notify(osg::INFO)<<"Have texture"<<std::endl;557 558 1314 // Found a corresponding OSG texture object 559 1315 if (ivToOsgTexMap[ivTexture]) … … 567 1323 ivToOsgTexMap[ivTexture] = texture.get(); 568 1324 } 569 1325 570 1326 stateSet->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON); 571 1327 572 1328 // propogate name 573 1329 if(texture.valid()) … … 587 1343 texEnv->setMode(osg::TexEnv::DECAL); 588 1344 break; 589 case SoTexture2::BLEND: 1345 case SoTexture2::BLEND: { 590 1346 texEnv->setMode(osg::TexEnv::BLEND); 1347 SbColor c(action->getTextureBlendColor()); 1348 texEnv->setColor(osg::Vec4(c[0], c[1], c[2], 1.f)); 591 1349 break; 592 #if defined(__COIN__) && ((COIN_MAJOR_VERSION==2 && COIN_MINOR_VERSION>=2) || (COIN_MAJOR_VERSION>2)) 1350 } 593 1351 // SGI's Inventor does not have REPLACE mode, but the Coin 3D library does. 594 1352 // Coin supports REPLACE since 2.2 release, TGS Inventor from 4.0. 595 1353 // Let's convert to the TexEnv anyway. 596 case SoTexture2::REPLACE:1354 case 0x1E01: //SoTexture2::REPLACE: 597 1355 texEnv->setMode(osg::TexEnv::REPLACE); 598 1356 break; 599 #endif600 1357 default: 1358 osg::notify(osg::WARN) << "Unsupported TexEnv mode." << std::endl; 601 1359 break; 602 1360 … … 611 1369 action->getMaterial(ambient, diffuse, specular, emission, 612 1370 shininess, transparency, 0); 613 1371 614 1372 // Set transparency 615 1373 SbBool hasTextureTransparency = FALSE; 616 1374 if (ivTexture) { 617 1375 SbVec2s tmp; 618 int bpp ;1376 int bpp = 0; 619 1377 if (ivTexture->isOfType(SoTexture2::getClassTypeId())) 620 1378 ((SoTexture2*)ivTexture)->image.getValue(tmp, bpp); … … 624 1382 const SbImage *img = ((SoVRMLImageTexture*)ivTexture)->getImage(); 625 1383 if (img) img->getValue(tmp, bpp); 626 else bpp = 0;627 1384 } 628 1385 #endif … … 633 1390 { 634 1391 osg::ref_ptr<osg::BlendFunc> transparency = new osg::BlendFunc; 635 stateSet->setAttributeAndModes(transparency.get(), 1392 stateSet->setAttributeAndModes(transparency.get(), 636 1393 osg::StateAttribute::ON); 637 1394 638 1395 // Enable depth sorting for transparent objects 639 1396 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); 640 1397 } 641 1398 642 1399 // Set linewidth 643 1400 if (action->getLineWidth()) … … 655 1412 stateSet->setAttributeAndModes(point.get(), osg::StateAttribute::ON); 656 1413 } 657 658 // Set draw mode 1414 1415 // Set draw mode 659 1416 switch (action->getDrawStyle()) 660 1417 { … … 664 1421 // OSG defaults to filled draw style, so no need to set redundent state. 665 1422 osg::PolygonMode *polygonMode = new osg::PolygonMode; 666 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 1423 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 667 1424 osg::PolygonMode::FILL); 668 1425 stateSet->setAttributeAndModes(polygonMode, osg::StateAttribute::ON); … … 673 1430 { 674 1431 osg::ref_ptr<osg::PolygonMode> polygonMode = new osg::PolygonMode; 675 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 1432 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 676 1433 osg::PolygonMode::LINE); 677 1434 stateSet->setAttributeAndModes(polygonMode.get(), osg::StateAttribute::ON); … … 681 1438 { 682 1439 osg::ref_ptr<osg::PolygonMode> polygonMode = new osg::PolygonMode; 683 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 1440 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 684 1441 osg::PolygonMode::POINT); 685 1442 stateSet->setAttributeAndModes(polygonMode.get(), osg::StateAttribute::ON); … … 697 1454 cullFace->setMode(osg::CullFace::BACK); 698 1455 stateSet->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON); 699 } 1456 } 700 1457 701 1458 // Set lighting … … 707 1464 osg::ref_ptr<osg::Material> material = new osg::Material; 708 1465 709 material->setAmbient(osg::Material::FRONT_AND_BACK, 710 osg::Vec4(ambient[0], ambient[1], ambient[2], 1466 material->setAmbient(osg::Material::FRONT_AND_BACK, 1467 osg::Vec4(ambient[0], ambient[1], ambient[2], 711 1468 1.0 - transparency)); 712 material->setDiffuse(osg::Material::FRONT_AND_BACK, 713 osg::Vec4(diffuse[0], diffuse[1], diffuse[2], 1469 material->setDiffuse(osg::Material::FRONT_AND_BACK, 1470 osg::Vec4(diffuse[0], diffuse[1], diffuse[2], 714 1471 1.0 - transparency)); 715 material->setSpecular(osg::Material::FRONT_AND_BACK, 716 osg::Vec4(specular[0], specular[1], specular[2], 1472 material->setSpecular(osg::Material::FRONT_AND_BACK, 1473 osg::Vec4(specular[0], specular[1], specular[2], 717 1474 1.0 - transparency)); 718 material->setEmission(osg::Material::FRONT_AND_BACK, 719 osg::Vec4(emission[0], emission[1], emission[2], 1475 material->setEmission(osg::Material::FRONT_AND_BACK, 1476 osg::Vec4(emission[0], emission[1], emission[2], 720 1477 1.0 - transparency)); 721 1478 material->setTransparency(osg::Material::FRONT_AND_BACK, transparency); 722 1479 if (specular[0] || specular[1] || specular[2]) 723 material->setShininess(osg::Material::FRONT_AND_BACK, 1480 material->setShininess(osg::Material::FRONT_AND_BACK, 724 1481 shininess*128.0); 725 1482 else … … 732 1489 stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON); 733 1490 1491 // Set global ambient light 1492 // note on osg::LightModel default values: 1493 // colorControl: SINGLE_COLOR, localViewer: false, twoSided: false 1494 osg::LightModel *lightModel = new osg::LightModel(); 1495 const SbColor &c = ivState.currentAmbientLight; 1496 lightModel->setAmbientIntensity(osg::Vec4(c[0], c[1], c[2], 1.0)); 734 1497 #if 0 735 1498 // disable as two sided lighting causes problem under NVidia, and the above osg::Material settings are single sided anway.. 1499 update: The mentioned bug is probably just for very old NVidia drivers (commit time of the comment is 2005-03-18). 1500 The proper solution should be to set two sided lighting based on SoShapeHints node. Need to be developed. PCJohn-2010-01-20 736 1501 // Set two sided lighting 737 osg::LightModel* lightModel = new osg::LightModel;738 1502 lightModel->setTwoSided(true); 1503 #endif 739 1504 stateSet->setAttributeAndModes(lightModel, osg::StateAttribute::ON); 740 #endif 1505 741 1506 // Set lights 742 LightList lightList = lightStack.top(); 743 for (unsigned int i = 0; i < lightList.size(); i++) 744 stateSet->setAttributeAndModes(lightList[i], 1507 for (unsigned int i = 0; i < ivState.currentLights.size(); i++) 1508 stateSet->setAttributeAndModes(ivState.currentLights[i].get(), 745 1509 osg::StateAttribute::ON); 746 } 747 1510 1511 } 1512 1513 // Shader program setup 1514 if (ivState.currentGLProgram.get() != NULL) { 1515 stateSet->setAttributeAndModes(ivState.currentGLProgram.get(), 1516 osg::StateAttribute::ON); 1517 } 1518 1519 // Shader program uniforms 1520 if (ivState.currentGLProgram.get() != NULL) { 1521 for (int i=0, c=ivState.currentGLProgram->getNumShaders(); i<c; i++) { 1522 const std::string &shaderCode = ivState.currentGLProgram->getShader(i)->getShaderSource(); 1523 if (shaderCode.find("coin_texunit0_model") != std::string::npos) { 1524 int mode = (ivTexture!=NULL) ? action->getTextureModel() : 0; 1525 stateSet->addUniform(new osg::Uniform("coin_texunit0_model", mode)); 1526 break; 1527 } 1528 } 1529 } 1530 748 1531 return stateSet; 749 1532 } … … 753 1536 SoCallbackAction* action) 754 1537 { 755 osg::notify(osg::INFO)<<"convertIVTexToOSGTex of type "<< 756 soNode->getTypeId().getName().getString()<<std::endl; 1538 #ifdef DEBUG_IV_PLUGIN 1539 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER 1540 << "convertIVTexToOSGTex (" 1541 << soNode->getTypeId().getName().getString() 1542 << ")" << std::endl; 1543 #endif 757 1544 758 1545 SbVec2s soSize; … … 762 1549 const unsigned char* soImageData = action->getTextureImage(soSize, soNC); 763 1550 if (!soImageData) { 764 osg::notify(osg::WARN) << "IV import warning: Error while loading texture data." << std::endl; 1551 osg::notify(osg::WARN) << NOTIFY_HEADER 1552 << "Warning: Error while loading texture data." << std::endl; 765 1553 return NULL; 766 1554 } … … 782 1570 else 783 1571 if (soNode->isOfType(SoVRMLImageTexture::getClassTypeId())) 784 fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ? 1572 fileName = ((SoVRMLImageTexture*)soNode)->url.getNum() >= 1 ? 785 1573 ((SoVRMLImageTexture*)soNode)->url.getValues(0)[0].getString() : ""; 786 1574 #endif 787 1575 else 788 osg::notify(osg::WARN) << "IV import warning: Unsupported texture type: " 789 << soNode->getTypeId().getName().getString() << std::endl; 790 791 osg::notify(osg::INFO) << fileName << " -> "; 1576 osg::notify(osg::WARN) << NOTIFY_HEADER 1577 << " Warning: Unsupported texture type: " 1578 << soNode->getTypeId().getName().getString() << std::endl; 1579 1580 #ifdef DEBUG_IV_PLUGIN 1581 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER 1582 << " Converting file name: " << fileName << " -> "; 1583 #endif 792 1584 if (fileName[0]=='\"') fileName.erase(fileName.begin()); 793 if (fileName.size() > 0 && fileName[fileName.size()-1]=='\"') 1585 if (fileName.size() > 0 && fileName[fileName.size()-1]=='\"') 794 1586 fileName.erase(fileName.begin()+fileName.size()-1); 795 osg::notify(osg::INFO) << fileName << std::endl; 796 797 // Create the osg::Image 1587 #ifdef DEBUG_IV_PLUGIN 1588 osg::notify(osg::DEBUG_INFO) << fileName << std::endl; 1589 #endif 1590 1591 // Create the osg::Image 798 1592 osg::ref_ptr<osg::Image> osgImage = new osg::Image; 799 1593 osgImage->setFileName(fileName); … … 817 1611 firstTime = false; 818 1612 } 819 1613 820 1614 // Set texture wrap mode 821 1615 #ifdef __COIN__ … … 840 1634 } 841 1635 842 return osgTex; 1636 return osgTex; 843 1637 } 844 1638 /////////////////////////////////////////////////////////////////// 845 SoCallbackAction::Response 846 ConvertFromInventor::preInfo(void* data, SoCallbackAction* action, 847 const SoNode* node)848 { 849 #ifdef DEBUG_IV_PLUGIN 850 osg::notify(osg:: INFO) << "preInfo() "1639 SoCallbackAction::Response 1640 ConvertFromInventor::preInfo(void* data, SoCallbackAction* action, 1641 const SoNode* node) 1642 { 1643 #ifdef DEBUG_IV_PLUGIN 1644 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preInfo() " 851 1645 << node->getTypeId().getName().getString() << std::endl; 852 1646 #endif … … 857 1651 return SoCallbackAction::CONTINUE; 858 1652 } 859 860 ///////////////////////////////////////////////////////////////////861 SoCallbackAction::Response862 ConvertFromInventor::preGroup(void* data, SoCallbackAction* action,863 const SoNode* node)864 {865 #ifdef DEBUG_IV_PLUGIN866 osg::notify(osg::INFO) << "preGroup() "867 << node->getTypeId().getName().getString() << std::endl;868 #endif869 870 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);871 872 // Create a new Group or LOD and add it to the stack873 osg::ref_ptr<osg::Group> group;874 if (node->isOfType(SoLOD::getClassTypeId())) {875 group = new osg::LOD;876 }877 else {878 group = new osg::Group;879 }880 881 882 thisPtr->groupStack.top()->addChild(group.get());883 thisPtr->groupStack.push(group.get());884 885 // SoTransform nodes are not the parent of the nodes they apply to886 // But are in the same separator as them887 SoChildList *kids = node->getChildren();888 for (int i=0; i<kids->getLength(); i++) {889 SoNode* kid = (SoNode*)kids->get(i);890 if (kid->isOfType(SoTransform::getClassTypeId())) {891 SoTransform* t = (SoTransform*)kid;892 SbVec3f axis, center, trans, scale;893 float angle;894 895 center = t->center.getValue();896 t->rotation.getValue(axis, angle);897 trans = t->translation.getValue();898 scale = t->scaleFactor.getValue();899 std::string name = t->getName().getString();900 901 thisPtr->addMatrixTransform(name, axis, angle, center, trans, scale);902 }903 }904 #ifdef __COIN__905 if (node->isOfType(SoVRMLTransform::getClassTypeId())) {906 std::string name;907 if (thisPtr->transformInfoName != "") {908 name = std::string("INFO_");909 name += thisPtr->transformInfoName.getString();910 name += "_trans";911 }912 else {913 name = node->getName();914 }915 916 SoVRMLTransform* vt = (SoVRMLTransform*)node;917 SbVec3f axis, center, trans, scale;918 float angle;919 920 center = vt->center.getValue();921 vt->rotation.getValue(axis, angle);922 trans = vt->translation.getValue();923 scale = vt->scale.getValue();924 925 thisPtr->addMatrixTransform(name, axis, angle, center, trans, scale);926 }927 #endif928 if (node->isOfType(SoSeparator::getClassTypeId()))929 {930 if (thisPtr->soTexStack.size())931 thisPtr->soTexStack.push(thisPtr->soTexStack.top());932 else933 thisPtr->soTexStack.push(NULL);934 if (thisPtr->lightStack.size())935 {936 LightList lightList = thisPtr->lightStack.top();937 thisPtr->lightStack.push(lightList);938 }939 }940 941 return SoCallbackAction::CONTINUE;942 }943 //////////////////////////////////////////////////////////////944 SoCallbackAction::Response945 ConvertFromInventor::postGroup(void* data, SoCallbackAction* action,946 const SoNode* node)947 {948 // Handle SoLOD nodes specially949 if (node->isOfType(SoLOD::getClassTypeId()))950 return postLOD(data, action, node);951 952 #ifdef DEBUG_IV_PLUGIN953 osg::notify(osg::INFO) << "postGroup() "954 << node->getTypeId().getName().getString() << std::endl;955 #endif956 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);957 958 // Pop all the groups that are Transforms959 osg::ref_ptr<osg::Group> group = thisPtr->groupStack.top();960 while (strcmp(group->className(), "MatrixTransform") == 0)961 {962 thisPtr->groupStack.pop();963 group = thisPtr->groupStack.top();964 }965 966 // Pop the group from the stack967 thisPtr->groupStack.pop();968 969 // Pop the state if the group is a Separator970 if (node->isOfType(SoSeparator::getClassTypeId()))971 {972 thisPtr->soTexStack.pop();973 thisPtr->lightStack.pop();974 }975 976 return SoCallbackAction::CONTINUE;977 }978 ////////////////////////////////////////////////////////////979 SoCallbackAction::Response980 ConvertFromInventor::postLOD(void* data, SoCallbackAction *,981 const SoNode* node)982 {983 #ifdef DEBUG_IV_PLUGIN984 osg::notify(osg::INFO) << "postLOD() "985 << node->getTypeId().getName().getString() << std::endl;986 #endif987 988 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data);989 990 // Inventor and OSG LOD node991 SoLOD *ivLOD = (SoLOD *) node;992 osg::LOD *lod = dynamic_cast<osg::LOD*>(thisPtr->groupStack.top());993 994 // Get the center of LOD and set it995 SbVec3f ivCenter = ivLOD->center.getValue();996 lod->setCenter(osg::Vec3(ivCenter[0], ivCenter[1], ivCenter[2]));997 998 // Verify the number of children and range values999 int num = thisPtr->groupStack.top()->getNumChildren();1000 if (ivLOD->range.getNum()+1 != num && !(num == 0 && ivLOD->range.getNum() == 0)) {1001 osg::notify(osg::WARN) << "IV import warning: SoLOD does not "1002 << "contain correct data in range field." << std::endl;1003 if (ivLOD->range.getNum()+1 < num) {1004 thisPtr->groupStack.top()->removeChildren(ivLOD->range.getNum() + 1,1005 num - ivLOD->range.getNum() - 1);1006 num = ivLOD->range.getNum() + 1;1007 }1008 }1009 1010 // Get the ranges and set it1011 if (num > 0) {1012 if (num == 1)1013 lod->setRange(0, 0.0, FLT_MAX);1014 else {1015 lod->setRange(0, 0.0, ivLOD->range[0]);1016 for (int i = 1; i < num-2; i++)1017 lod->setRange(i, ivLOD->range[i-1], ivLOD->range[i]);1018 lod->setRange(num-1, ivLOD->range[num-2], FLT_MAX);1019 }1020 }1021 1022 // Pop the group from the stack1023 thisPtr->groupStack.pop();1024 1025 return SoCallbackAction::CONTINUE;1026 }1027 1653 ///////////////////////////////////////////////////////////// 1028 SoCallbackAction::Response 1029 ConvertFromInventor::preRotor(void * data, SoCallbackAction *,1030 const SoNode *node)1031 { 1032 #ifdef DEBUG_IV_PLUGIN 1033 osg::notify(osg:: INFO) << "preRotor() "1654 SoCallbackAction::Response 1655 ConvertFromInventor::preRotor(void *data, SoCallbackAction *action, 1656 const SoNode *node) 1657 { 1658 #ifdef DEBUG_IV_PLUGIN 1659 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preRotor() " 1034 1660 << node->getTypeId().getName().getString() << std::endl; 1035 1661 #endif … … 1045 1671 // Create a new osg::MatrixTransform 1046 1672 osg::ref_ptr<osg::MatrixTransform> rotorTransform = new osg::MatrixTransform; 1047 1673 1048 1674 // Create a Rotor Callback equivalent to the inventor Rotor 1049 1675 osg::Vec3 pivot(0, 0, 0); 1050 1676 osg::Vec3 axis(ivAxis[0], ivAxis[1], ivAxis[2]); 1051 osg::ref_ptr<osgUtil::TransformCallback> rotorCallback 1052 = new osgUtil::TransformCallback(pivot, axis, 1677 osg::ref_ptr<osgUtil::TransformCallback> rotorCallback 1678 = new osgUtil::TransformCallback(pivot, axis, 1053 1679 2 * osg::PI * ivRotor->speed.getValue()); 1054 1680 1055 1681 // Set the app callback 1056 1682 rotorTransform->setUpdateCallback(rotorCallback.get()); 1057 1058 // Push the rotor transform onto the group stack 1059 thisPtr->groupStack.top()->addChild(rotorTransform.get()); 1060 thisPtr->groupStack.push(rotorTransform.get()); 1061 1062 return SoCallbackAction::CONTINUE; 1683 1684 // Push the rotor onto the state stack 1685 thisPtr->ivPushState(action, node, 1686 IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 1687 IvStateItem::APPEND_AT_PUSH, rotorTransform.get()); 1688 1689 // Append initial rotation to the model matrix 1690 if (!ivRotor->rotation.isIgnored()) { 1691 SoModelMatrixElement::rotateBy(action->getState(), ivRotor, 1692 ivRotor->rotation.getValue()); 1693 } 1694 1695 // Don't do the traversal of the SoShuttle 1696 // since it was seen on Coin that is does not append just 1697 // initial shuttle position, but some interpolated one, 1698 // resulting in incorrect animation. 1699 return SoCallbackAction::PRUNE; 1063 1700 } 1064 1701 //////////////////////////////////////////////////////////////// 1065 SoCallbackAction::Response 1066 ConvertFromInventor::prePendulum(void* data, SoCallbackAction * ,1702 SoCallbackAction::Response 1703 ConvertFromInventor::prePendulum(void* data, SoCallbackAction *action, 1067 1704 const SoNode* node) 1068 1705 { 1069 1706 #ifdef DEBUG_IV_PLUGIN 1070 osg::notify(osg:: INFO) << "prePendulum() "1707 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "prePendulum() " 1071 1708 << node->getTypeId().getName().getString() << std::endl; 1072 1709 #endif … … 1080 1717 ivPendulum->rotation0.getValue(ivAxis0, startAngle); 1081 1718 ivPendulum->rotation1.getValue(ivAxis1, endAngle); 1719 ivAxis0.normalize(); 1720 ivAxis1.normalize(); 1721 1722 // Reverse axis and direction if required 1723 // Actually, this will produce correct results only when axis is 1724 // opposite to each other, and approximate results when nearly 1725 // opposite and garbage otherwise. 1726 if ((ivAxis0+ivAxis1).length() < 0.5 ) { 1727 ivAxis1 = -ivAxis1; 1728 endAngle = -endAngle; 1729 } 1082 1730 1083 1731 // Create a new osg::MatrixTransform 1084 1732 osg::ref_ptr<osg::MatrixTransform> pendulumTransform = new osg::MatrixTransform; 1085 1733 1086 1734 // Create a Pendulum Callback equivalent to the inventor Rotor 1087 osg::Vec3 axis(ivAxis0[0], ivAxis0[1], ivAxis0[2]); 1088 PendulumCallback* pendulumCallback 1735 // Use axis from of the bigger angle (to avoid lost axis when 1736 // angle is zero - see SbRotation and quaternion theory). 1737 osg::Vec3 axis; 1738 if (fabs(startAngle) > fabs(endAngle)) 1739 axis = osg::Vec3(ivAxis0[0], ivAxis0[1], ivAxis0[2]); 1740 else 1741 axis = osg::Vec3(ivAxis1[0], ivAxis1[1], ivAxis1[2]); 1742 PendulumCallback* pendulumCallback 1089 1743 = new PendulumCallback(axis, startAngle, endAngle, 1090 1744 ivPendulum->speed.getValue()); … … 1092 1746 // Set the app callback 1093 1747 pendulumTransform->setUpdateCallback(pendulumCallback); 1094 1095 // Push the pendulum transform onto the group stack 1096 thisPtr->groupStack.top()->addChild(pendulumTransform.get()); 1097 thisPtr->groupStack.push(pendulumTransform.get()); 1098 1099 return SoCallbackAction::CONTINUE; 1748 1749 // Push the pendulum onto the state stack 1750 thisPtr->ivPushState(action, node, 1751 IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 1752 IvStateItem::APPEND_AT_PUSH, pendulumTransform.get()); 1753 1754 // Don't do the traversal of the SoShuttle 1755 // since it was seen on Coin that is does not append just 1756 // initial shuttle position, but some interpolated one, 1757 // resulting in incorrect animation. 1758 return SoCallbackAction::PRUNE; 1100 1759 } 1101 1760 //////////////////////////////////////////////////////////////// 1102 SoCallbackAction::Response 1103 ConvertFromInventor::preShuttle(void* data, SoCallbackAction * ,1761 SoCallbackAction::Response 1762 ConvertFromInventor::preShuttle(void* data, SoCallbackAction *action, 1104 1763 const SoNode* node) 1105 1764 { 1106 1765 #ifdef DEBUG_IV_PLUGIN 1107 osg::notify(osg:: INFO) << "preShuttle() "1766 osg::notify(osg::DEBUG_INFO) << NOTIFY_HEADER << "preShuttle() " 1108 1767 << node->getTypeId().getName().getString() << std::endl; 1109 1768 #endif … … 1119 1778 // Create a new osg::MatrixTransform 1120 1779 osg::ref_ptr<osg::MatrixTransform> shuttleTransform = new osg::MatrixTransform; 1121 1780 1122 1781 // Create a shuttle Callback equivalent to the inventor Rotor 1123 1782 osg::Vec3 startPos(ivStartPos[0], ivStartPos[1], ivStartPos[2]); 1124 1783 osg::Vec3 endPos(ivEndPos[0], ivEndPos[1], ivEndPos[2]); 1125 ShuttleCallback* shuttleCallback 1784 ShuttleCallback* shuttleCallback 1126 1785 = new ShuttleCallback(startPos, endPos, ivShuttle->speed.getValue()); 1127 1786 1128 1787 // Set the app callback 1129 1788 shuttleTransform->setUpdateCallback(shuttleCallback); 1130 1131 // Push the shuttle transform onto the group stack 1132 thisPtr->groupStack.top()->addChild(shuttleTransform.get()); 1133 thisPtr->groupStack.push(shuttleTransform.get()); 1134 1135 return SoCallbackAction::CONTINUE; 1789 1790 // Push the shuttle onto the state stack 1791 thisPtr->ivPushState(action, node, 1792 IvStateItem::MULTI_POP | IvStateItem::UPDATE_STATE | 1793 IvStateItem::APPEND_AT_PUSH, shuttleTransform.get()); 1794 1795 // Don't do the traversal of the SoShuttle 1796 // since it was seen on Coin that is does not append just 1797 // initial shuttle position, but some interpolated one, 1798 // resulting in incorrect animation. 1799 return SoCallbackAction::PRUNE; 1136 1800 } 1137 1801 //////////////////////////////////////////////////////////// 1138 1802 void ConvertFromInventor::addVertex(SoCallbackAction* action, 1139 const SoPrimitiveVertex *v, 1803 const SoPrimitiveVertex *v, 1140 1804 int index) 1141 1805 { … … 1150 1814 (normalBinding == osg::Geometry::BIND_PER_PRIMITIVE && index == 0)) 1151 1815 { 1152 if (vertexOrder == CLOCKWISE) 1153 normals.push_back(osg::Vec3(-norm[0], -norm[1], -norm[2])); 1154 else 1816 // What is this? Why to invert normals at CLOCKWISE vertex ordering? 1817 // PCJohn 2009-12-13 1818 //if (vertexOrder == CLOCKWISE) 1819 // normals.push_back(osg::Vec3(-norm[0], -norm[1], -norm[2])); 1820 //else 1155 1821 normals.push_back(osg::Vec3(norm[0], norm[1], norm[2])); 1156 1822 } … … 1159 1825 colorBinding == osg::Geometry::BIND_PER_PRIMITIVE) 1160 1826 { 1161 // Get the material/color 1827 // Get the material/color 1162 1828 SbColor ambient, diffuse, specular, emission; 1163 1829 float transparency, shininess; 1164 action->getMaterial(ambient, diffuse, specular, emission, shininess, 1830 action->getMaterial(ambient, diffuse, specular, emission, shininess, 1165 1831 transparency, v->getMaterialIndex()); 1166 1832 if (colorBinding == osg::Geometry::BIND_PER_VERTEX) … … 1177 1843 } 1178 1844 //////////////////////////////////////////////////////////////////////////// 1179 void ConvertFromInventor::addMatrixTransform(const std::string& name, SbVec3f axis, float angle, SbVec3f center, SbVec3f trans, SbVec3f scale)1180 {1181 osg::Matrix mat;1182 if (trans.length() != 0.0 || name != "")1183 {1184 mat.makeIdentity();1185 mat.setTrans(trans[0], trans[1], trans[2]);1186 osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat);1187 if (name != "") {1188 std::string name2 = name;1189 name2 += "_t";1190 mt->setName(name2);1191 }1192 groupStack.top()->addChild(mt.get());1193 groupStack.push(mt.get());1194 }1195 1196 if (center.length() != 0.0) {1197 mat.makeIdentity();1198 mat.setTrans(center[0], center[1], center[2]);1199 osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat);1200 groupStack.top()->addChild(mt.get());1201 groupStack.push(mt.get());1202 }1203 1204 if (angle != 0.0 || name != "")1205 {1206 osg::Quat q(angle, osg::Vec3f(axis[0], axis[1], axis[2]));1207 mat.makeIdentity();1208 mat.setRotate(q);1209 osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat);1210 if (name != "") {1211 std::string name2 = name;1212 name2 += "_r";1213 mt->setName(name2);1214 }1215 groupStack.top()->addChild(mt.get());1216 groupStack.push(mt.get());1217 }1218 1219 if (center.length() != 0.0) {1220 center.negate();1221 mat.makeIdentity();1222 mat.setTrans(center[0], center[1], center[2]);1223 osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform(mat);1224 groupStack.top()->addChild(mt.get());1225 groupStack.push(mt.get());1226 }1227 1228 if (scale[0] != 1.0 || scale[1] != 1.0 || scale[2] != 1.0) {1229 mat.makeIdentity();1230 mat.makeScale(scale[0], scale[1], scale[2]);1231 osg::ref_ptr<osg::MatrixTransform> smt = new osg::MatrixTransform(mat);1232 groupStack.top()->addChild(smt.get());1233 groupStack.push(smt.get());1234 }1235 }1236 ////////////////////////////////////////////////////////////////////////////1237 1845 void ConvertFromInventor::addTriangleCB(void* data, SoCallbackAction* action, 1238 1846 const SoPrimitiveVertex* v0, … … 1241 1849 { 1242 1850 ConvertFromInventor* thisPtr = (ConvertFromInventor *) (data); 1243 1851 1244 1852 switch (thisPtr->vertexOrder) 1245 1853 {
