1 /* 2 Copyright (c) 2008-2009 NetAllied Systems GmbH 3 4 This file is part of COLLADAMaya. 5 6 Portions of the code are: 7 Copyright (c) 2005-2007 Feeling Software Inc. 8 Copyright (c) 2005-2007 Sony Computer Entertainment America 9 Copyright (c) 2004-2005 Alias Systems Corp. 10 11 Licensed under the MIT Open Source License, 12 for details please see LICENSE file or the website 13 http://www.opensource.org/licenses/mit-license.php 14 */ 15 16 #include "COLLADAMayaStableHeaders.h" 17 #include "COLLADAMayaVisualSceneExporter.h" 18 #include "COLLADAMayaSceneGraph.h" 19 #include "COLLADAMayaGeometryExporter.h" 20 #include "COLLADAMayaDagHelper.h" 21 #include "COLLADAMayaConversion.h" 22 #include "COLLADAMayaExportOptions.h" 23 #include "COLLADAMayaAnimationExporter.h" 24 #include "COLLADAMayaSyntax.h" 25 #include "COLLADAMayaControllerExporter.h" 26 #include "COLLADAMayaRotateHelper.h" 27 #include "COLLADAMayaReferenceManager.h" 28 #include "COLLADAMayaMaterialExporter.h" 29 #include "COLLADAMayaLightExporter.h" 30 #include "COLLADAMayaLightProbeExporter.h" 31 #include "COLLADAMayaCameraExporter.h" 32 #include "COLLADAMayaEffectExporter.h" 33 #include "COLLADAMayaPhysicsExporter.h" 34 #include "COLLADAMayaShaderHelper.h" 35 #include "COLLADAMayaAttributeParser.h" 36 37 #include <maya/MFnIkHandle.h> 38 #include <maya/MFnSkinCluster.h> 39 #include <maya/MItDag.h> 40 #include <maya/MFnIkJoint.h> 41 #include <maya/MQuaternion.h> 42 #include <maya/MEulerRotation.h> 43 #include <maya/MDagPath.h> 44 #include <maya/MFnCamera.h> 45 #include <maya/MFileIO.h> 46 #include <maya/MFnAttribute.h> 47 48 #include "COLLADASWNode.h" 49 #include "COLLADASWInstanceGeometry.h" 50 #include "COLLADASWInstanceController.h" 51 #include "COLLADASWLibraryControllers.h" 52 #include "COLLADASWInstanceLight.h" 53 #include "COLLADASWInstanceCamera.h" 54 #include "COLLADASWInstanceNode.h" 55 #include "COLLADASWConstants.h" 56 #include "COLLADASWExtraTechnique.h" 57 58 #include "Math/COLLADABUMathUtils.h" 59 60 #include "assert.h" 61 62 63 namespace COLLADAMaya 64 { 65 66 //--------------------------------------------------------------- VisualSceneExporter(COLLADASW::StreamWriter * streamWriter,DocumentExporter * documentExporter,const String & sceneId)67 VisualSceneExporter::VisualSceneExporter ( 68 COLLADASW::StreamWriter* streamWriter, 69 DocumentExporter* documentExporter, 70 const String& sceneId ) 71 : COLLADASW::LibraryVisualScenes ( streamWriter ) 72 , mDocumentExporter ( documentExporter ) 73 , mSceneId ( sceneId ) 74 , mIsJoint ( false ) 75 , mIsFirstRotation ( true ) 76 , mVisualSceneAdded ( false ) 77 , mVisualSceneNode ( NULL ) 78 , mLODIndexCounter1(0) 79 , mLODIndexCounter2(0) 80 { 81 } 82 ~VisualSceneExporter()83 VisualSceneExporter::~VisualSceneExporter() 84 { 85 lodCounterMap.clear(); 86 } 87 88 89 // ------------------------------------------------------------ exportVisualScenes()90 bool VisualSceneExporter::exportVisualScenes() 91 { 92 // Get the list with the transform nodes. 93 SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph(); 94 SceneElementsList* exportNodesTree = sceneGraph->getExportNodesTree(); 95 96 // The flag, if a node was exported and the visual scene tags must to be closed 97 bool nodeExported = false; 98 99 // Export all/selected DAG nodes 100 size_t length = exportNodesTree->size(); 101 for ( size_t i = 0; i < length; ++i ) 102 { 103 // No instance node under the visual scene! 104 SceneElement* sceneElement = ( *exportNodesTree ) [i]; 105 106 // Exports all the nodes in a node and all its child nodes recursive 107 if ( exportVisualSceneNodes ( sceneElement ) ) nodeExported = true; 108 } 109 110 // Just if a node was exported, the visual scene tag 111 // in the collada document is open and should be closed. 112 if ( nodeExported ) closeVisualScene(); 113 114 closeLibrary(); 115 116 // TODO 117 // Setup the reference information 118 // GetReferenceManager()->Synchronize(); 119 120 return nodeExported; 121 } 122 123 // --------------------------------------------------------------- 124 // Exports all the nodes in a node and all its child nodes recursive exportVisualSceneNodes(SceneElement * sceneElement)125 bool VisualSceneExporter::exportVisualSceneNodes ( SceneElement* sceneElement ) 126 { 127 // Get the path of the current scene element. 128 const MDagPath dagPath = sceneElement->getPath(); 129 130 // Check if the element isn't already exported 131 SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph(); 132 SceneElement* instantiatedSceneElement = sceneGraph->findExportedElement ( dagPath ); 133 134 // If the element is a root element and it is instanced, we have to try to set 135 bool isInstance = dagPath.isInstanced (); 136 bool hasPreviousInstance = ( instantiatedSceneElement != NULL ); 137 if ( hasPreviousInstance ) 138 { 139 sceneElement->setInstantiatedSceneElement ( instantiatedSceneElement ); 140 } 141 142 // The transform node 143 MStatus status; 144 MObject transformNode = dagPath.transform ( &status ); 145 if ( ( status != MS::kSuccess ) && status.statusCode () == MStatus::kInvalidParameter ) return false; 146 MFnDagNode transform ( transformNode, &status ); 147 if ( !status ) 148 { 149 status.perror ( "MFnDagNode constructor" ); 150 return false; 151 } 152 153 bool isForced = sceneElement->getIsForced(); 154 bool isVisible = sceneElement->getIsVisible(); 155 bool isExportNode = sceneElement->getIsExportNode(); 156 bool isPhysicsNode = sceneElement->getIsPhysicsNode(); 157 158 // Check for a file reference 159 bool isLocal = sceneElement->getIsLocal(); 160 161 // If this is a DAG node (not a DAG shape) check to see whether we should enter 162 bool animationExport = true; 163 bool isSceneRoot = dagPath.length() == 0; 164 if ( !isSceneRoot ) 165 { 166 if ( !isExportNode ) 167 { 168 animationExport = false; 169 } 170 } 171 172 // The COLLADA Node 173 COLLADASW::Node* colladaSceneNode = NULL; 174 175 // Flag if the node was exported 176 bool nodeExported = false; 177 178 // Export the transform 179 SceneElement::Type sceneElementType = sceneElement->getType(); 180 bool isTransform = dagPath.hasFn ( MFn::kTransform ); 181 182 bool doExport = true; 183 184 // Do export LOD Group Node only during "NO_PASS" (in library_visual_scenes) 185 if ((mDocumentExporter->mExportPass != VISUAL_SCENE_PASS && sceneElementType == SceneElement::LOD)) 186 doExport = false; 187 188 mLODIndexCounter1 = 1; 189 190 if (sceneElement->getParentCount()) 191 { 192 SceneElement::Type sceneParentElementType = sceneElement->getParent()->getType(); 193 if ((mDocumentExporter->mExportPass == VISUAL_SCENE_PASS && sceneParentElementType == SceneElement::LOD)) 194 { 195 196 std::map<SceneElement*, int>::iterator iterator = lodCounterMap.find(sceneElement->getParent()); 197 if (iterator != lodCounterMap.end()) 198 mLODIndexCounter1 = ++iterator->second; 199 else 200 lodCounterMap.insert(std::make_pair(sceneElement->getParent(), mLODIndexCounter1)); 201 } 202 203 204 if (mDocumentExporter->mExportPass == SECOND_LOD_PASS && sceneParentElementType == SceneElement::LOD) 205 mLODIndexCounter2++; 206 } 207 208 bool ContinueExport = false; 209 210 // DO export only from second LOD Node during "LOD second Pass" (in library_nodes) 211 if (mDocumentExporter->mExportPass == SECOND_LOD_PASS && mLODIndexCounter2 > 1) 212 ContinueExport = true; 213 214 // Do export only first LOD Node during "NO_PASS" (in library_visual_scenes) 215 if ((ExportOptions::exportLOD() && (mDocumentExporter->mExportPass != SECOND_LOD_PASS && isTransform && doExport && mLODIndexCounter1 < 2)) || (!ExportOptions::exportLOD() && isTransform)) 216 ContinueExport = true; 217 218 if (ContinueExport) 219 { 220 // Taken out of unvisible transforms. 221 if ((!ExportOptions::exportInvisibleNodes() && !isVisible && !isExportNode) || (ExportOptions::exportPhysics() && isPhysicsNode)) return false; 222 223 // Export the scene graph node for all transform-derivatives 224 if ( dagPath.hasFn ( MFn::kJoint ) ) 225 { 226 sceneElement->setHasJoint(true); 227 if (ExportOptions::exportJoints()) 228 { 229 if ( animationExport ) 230 { 231 colladaSceneNode = new COLLADASW::Node ( mDocumentExporter->getStreamWriter(), hasPreviousInstance ); 232 nodeExported = exportJointVisualSceneNode ( colladaSceneNode, sceneElement ); 233 234 // Push it into the list of the exported elements 235 sceneGraph->addExportedElement ( sceneElement ); 236 } 237 else 238 { 239 isLocal = true; 240 } 241 } 242 else 243 { 244 isTransform = false; // we didn't do anything to this node 245 } 246 } 247 else 248 { 249 // Just local export 250 if (!isForced && !isLocal && !ExportOptions::exportXRefs()) return false; 251 252 if ( animationExport ) 253 { 254 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 255 colladaSceneNode = new COLLADASW::Node ( streamWriter, hasPreviousInstance ); 256 nodeExported = exportNodeVisualSceneNode ( colladaSceneNode, sceneElement ); 257 258 // push it into the list of the exported elements 259 sceneGraph->addExportedElement ( sceneElement ); 260 } 261 else 262 { 263 isLocal = true; 264 } 265 } 266 } 267 268 // Export type-specific information 269 MFn::Type type = dagPath.apiType(); 270 switch (type) 271 { 272 case MFn::kLookAt: 273 case MFn::kParentConstraint: 274 case MFn::kOrientConstraint: 275 case MFn::kConstraint: 276 case MFn::kAimConstraint: 277 case MFn::kPoleVectorConstraint: 278 case MFn::kPointConstraint: 279 case MFn::kNormalConstraint: 280 MGlobal::displayError ( "Export of constraints not supported: " 281 + MString ( sceneElement->getNodeName ().c_str () ) ); 282 break; 283 284 case MFn::kAmbientLight: 285 case MFn::kSpotLight: 286 case MFn::kPointLight: 287 case MFn::kDirectionalLight: 288 break; 289 290 case MFn::kMesh: 291 break; 292 293 case MFn::kIkHandle: 294 if (ExportOptions::exportJoints()) 295 { 296 MGlobal::displayError ( "Export of ik handles not supported: " 297 + MString ( sceneElement->getNodeName ().c_str () ) ); 298 } 299 break; 300 301 case MFn::kCamera: 302 break; 303 304 case MFn::kRigid: 305 //if ( ExportOptions::exportPhysics() ) 306 { 307 MGlobal::displayError ( "Export of physics not supported: " 308 + MString ( sceneElement->getNodeName ().c_str () ) ); 309 } 310 break; 311 312 case MFn::kNurbsCurve: 313 { 314 MGlobal::displayError ( "Export of spline not supported: " 315 + MString ( sceneElement->getNodeName ().c_str () ) ); 316 } 317 break; 318 case MFn::kNurbsSurface: 319 { 320 MGlobal::displayError ( "Export of nurbs not supported: " 321 + MString ( sceneElement->getNodeName ().c_str () ) ); 322 } 323 break; 324 case MFn::kEmitter: 325 { 326 MGlobal::displayError ( "Export of emitters not supported: " 327 + MString ( sceneElement->getNodeName ().c_str () ) ); 328 } 329 break; 330 case MFn::kAir: 331 case MFn::kDrag: 332 case MFn::kField: 333 case MFn::kGravity: 334 case MFn::kNewton: 335 case MFn::kRadial: 336 case MFn::kTurbulence: 337 case MFn::kUniform: 338 case MFn::kVortex: 339 case MFn::kVolumeAxis: 340 { 341 MGlobal::displayError ( "Could not export. Unknown node type: " 342 + MString ( sceneElement->getNodeName ().c_str () ) ); 343 } 344 break; 345 default: break; 346 } 347 348 // Check if the element is a local element and isn't already exported. 349 if ( isLocal && !hasPreviousInstance ) 350 { 351 // Recursive call for all the child elements 352 for ( uint i=0; i<sceneElement->getChildCount(); ++i ) 353 { 354 SceneElement* childElement = sceneElement->getChild ( i ); 355 exportVisualSceneNodes ( childElement ); 356 } 357 } 358 359 // Close the visual scene tag in the collada document 360 if ( colladaSceneNode != NULL ) 361 { 362 if ( nodeExported ) 363 { 364 // Close the current scene node 365 colladaSceneNode->end(); 366 } 367 delete ( colladaSceneNode ); 368 369 colladaSceneNode = NULL; 370 } 371 372 return nodeExported; 373 } 374 375 //------------------------------------------------------ exportJointVisualSceneNode(COLLADASW::Node * sceneNode,SceneElement * sceneElement)376 bool VisualSceneExporter::exportJointVisualSceneNode ( 377 COLLADASW::Node *sceneNode, 378 SceneElement* sceneElement ) 379 { 380 // Set the type of the node to a joint 381 sceneNode->setType ( COLLADASW::Node::JOINT ); 382 383 // Get the current dag path 384 MDagPath dagPath = sceneElement->getPath(); 385 MObject node = dagPath.node(); 386 387 // Generate a COLLADA sid for the new object 388 String nodeSid = mDocumentExporter->dagPathToColladaSid(dagPath); 389 sceneNode->setNodeSid( nodeSid ); 390 391 // // Export the segment-scale-compensate flag. 392 // bool segmentScaleCompensate; 393 // DagHelper::getPlugValue ( dagPath.transform(), 394 // ATTR_SEGMENT_SCALE_COMPENSATE, 395 // segmentScaleCompensate ); 396 // 397 // // Not animateable 398 // sceneNode->addExtraTechniqueParameter ( PROFILE_MAYA, 399 // MAYA_SEGMENTSCALECOMP_PARAMETER, 400 // segmentScaleCompensate ); 401 402 // Export the node 403 return exportVisualSceneNode ( sceneNode, sceneElement ); 404 } 405 406 //------------------------------------------------------ exportNodeVisualSceneNode(COLLADASW::Node * sceneNode,SceneElement * sceneElement)407 bool VisualSceneExporter::exportNodeVisualSceneNode ( 408 COLLADASW::Node *sceneNode, 409 SceneElement* sceneElement ) 410 { 411 // Set the type of the node 412 sceneNode->setType ( COLLADASW::Node::NODE ); 413 414 // Export the node 415 return exportVisualSceneNode ( sceneNode, sceneElement ); 416 } 417 418 //--------------------------------------------------------------- exportVisualSceneNode(COLLADASW::Node * sceneNode,SceneElement * sceneElement)419 bool VisualSceneExporter::exportVisualSceneNode ( 420 COLLADASW::Node* sceneNode, 421 SceneElement* sceneElement ) 422 { 423 // Set the visual scene node 424 mVisualSceneNode = sceneNode; 425 426 // Get the dagPath from the scene element 427 MDagPath dagPath = sceneElement->getPath(); 428 429 // Flag, if the node is already instantiated 430 bool isInstanceNode = mVisualSceneNode->getIsInstanceNode(); 431 432 // False, if the node has a external reference. 433 bool isLocal = sceneElement->getIsLocal(); 434 435 436 // Do all the stuff if we export a full node. 437 if (!isInstanceNode || mDocumentExporter->mExportPass == SECOND_LOD_PASS) 438 { 439 // Initialize the member variables 440 if ( !initializeTransform ( sceneElement ) ) 441 { 442 MString pathName = dagPath.fullPathName(); 443 MString message = "Could not initialize the transform object of the path " + pathName; 444 MGlobal::displayError( message ); 445 return false; 446 } 447 } 448 449 // Prepares the visual scene node 450 // (open the visual scene node o a node instance, if we need this). 451 if (!openVisualSceneNode(sceneElement)) 452 return false; 453 454 455 bool exportTransformation = false; 456 if (mDocumentExporter->mExportPass == VISUAL_SCENE_PASS) 457 { 458 if (!isLocal || !isInstanceNode) 459 exportTransformation = true; 460 } 461 else 462 { 463 if (sceneElement->getType() != SceneElement::LOD) 464 { 465 // Do export Transformation for LOD node only during 2nd Pass Library node 466 SceneElement::Type sceneParentElementType = sceneElement->getParent()->getType(); 467 if ((mDocumentExporter->mExportPass == SECOND_LOD_PASS && sceneParentElementType == SceneElement::LOD)) 468 exportTransformation = false; 469 else 470 exportTransformation = true; 471 } 472 } 473 474 if (exportTransformation) 475 { 476 // Export the transformation information 477 if (ExportOptions::bakeTransforms()) 478 { 479 exportMatrixTransform(); 480 } 481 else if (ExportOptions::exportCameraAsLookat() && dagPath.hasFn(MFn::kCamera)) 482 { 483 exportLookatTransform(); 484 } 485 else 486 { 487 exportDecomposedTransform(); 488 } 489 490 // Exports the visibility technique tag and the visibility animation. 491 exportVisibility(sceneNode); 492 } 493 494 495 if (!isLocal || mDocumentExporter->mExportPass == SECOND_LOD_PASS || 496 (mDocumentExporter->mExportPass == VISUAL_SCENE_PASS && (ExportOptions::exportLOD() && (sceneElement->getParentCount() > 0 && sceneElement->getParent()->getType() == SceneElement::LOD)))) 497 { 498 // Export the node external reference 499 exportInstanceNode ( sceneElement ); 500 } 501 else if ( !isInstanceNode ) 502 { 503 // Write the instance urls of the geometries, controllers 504 // and lights into the collada document. 505 exportInstanceChildNodes ( sceneElement ); 506 } 507 508 return true; 509 } 510 511 //--------------------------------------------------------------- exportInstanceMaterial(COLLADASW::InstanceMaterialList & instanceMaterialList,const MDagPath & dagPath)512 void VisualSceneExporter::exportInstanceMaterial ( 513 COLLADASW::InstanceMaterialList &instanceMaterialList, 514 const MDagPath &dagPath ) 515 { 516 MaterialExporter* materialExporter = mDocumentExporter->getMaterialExporter (); 517 EffectExporter* effectExporter = mDocumentExporter->getEffectExporter (); 518 519 // Find how many shaders are used by this instance of the mesh 520 const MObject& meshNode = dagPath.node(); 521 MFnMesh fnMesh ( meshNode ); 522 523 // Get the connected shaders of the main mesh instance (we will take always the zero). 524 // This is a COLLADA workaround to get the symbolic material name. 525 // This is used to share a pointer in the geometry, but to use different materials in the node. 526 MObjectArray shaders; 527 MIntArray shaderIndices; 528 fnMesh.getConnectedShaders ( 0, shaders, shaderIndices ); 529 530 uint realShaderCount = ( uint ) shaders.length(); 531 uint numShaders = ( uint ) std::max ( ( size_t ) 1, ( size_t ) shaders.length() ); 532 for ( uint shaderPosition = 0; shaderPosition < numShaders; ++shaderPosition ) 533 { 534 if ( shaderPosition < realShaderCount ) 535 { 536 // Add shader-specific parameters (TexCoords sets). 537 // Add symbolic name for the material used on this polygon set. 538 MObject shadingEngine = shaders[shaderPosition]; 539 MFnDependencyNode shadingEngineFn ( shadingEngine ); 540 String shadingEngineName = DocumentExporter::mayaNameToColladaName ( shadingEngineFn.name() ); 541 542 // Check if the current mesh has some polygons for the connected shader. 543 // If not, we don't need to write the current material instance. 544 if ( !meshContainsShaderPolygons ( meshNode, shaders, shaderIndices, shaderPosition ) ) continue; 545 546 // To get the right shader name, we have to take the correct mesh instance. 547 MStatus status; 548 uint instanceNumber = dagPath.instanceNumber( &status ); CHECK_STAT( status ); 549 if ( instanceNumber > 0 ) 550 { 551 MObjectArray instanceShaders; 552 MIntArray instanceShaderIndices; 553 fnMesh.getConnectedShaders ( instanceNumber, instanceShaders, instanceShaderIndices ); 554 shadingEngine = instanceShaders[shaderPosition]; 555 } 556 557 // This object contains a reference to a shader, or material, so we might call 558 // our own function to write that material to our own data structure for later export. 559 MObject shader = DagHelper::getSourceNodeConnectedTo ( shadingEngine, ATTR_SURFACE_SHADER ); 560 MFnDependencyNode shaderNode ( shader ); 561 String mayaMaterialId = DocumentExporter::mayaNameToColladaName ( shaderNode.name(), true ); 562 const String& colladaMaterialId = materialExporter->findColladaMaterialId ( mayaMaterialId ); 563 564 // Create the material instance object. 565 COLLADASW::InstanceMaterial materialInstance(shadingEngineName, COLLADASW::URI(EMPTY_STRING, colladaMaterialId)); 566 567 // Retrieve all the file textures with the blend modes, if exist. 568 MObjectArray fileTextures; 569 MIntArray blendModes; 570 effectExporter->getShaderTextures ( shader, ATTR_OUT_COLOR, fileTextures, blendModes ); 571 effectExporter->getShaderTextures ( shader, ATTR_INCANDESCENCE, fileTextures, blendModes ); 572 effectExporter->getShaderTextures ( shader, ATTR_AMBIENT_COLOR, fileTextures, blendModes ); 573 effectExporter->getShaderTextures ( shader, ATTR_COLOR, fileTextures, blendModes ); 574 effectExporter->getShaderTextures ( shader, ATTR_NORMAL_CAMERA, fileTextures, blendModes ); 575 effectExporter->getShaderTextures ( shader, ATTR_SPECULAR_COLOR, fileTextures, blendModes ); 576 effectExporter->getShaderTextures ( shader, ATTR_REFLECTED_COLOR, fileTextures, blendModes ); 577 effectExporter->getShaderTextures ( shader, ATTR_OUT_TRANSPARENCY, fileTextures, blendModes ); 578 effectExporter->getShaderTextures ( shader, ATTR_TRANSPARENCY, fileTextures, blendModes ); 579 uint fileTextureCount = fileTextures.length(); 580 581 // Check if the current material instance uses a texcoord binding. 582 MPlug uvSetMainPlug = MFnDependencyNode ( meshNode ).findPlug ( ATTR_UV_SET ); 583 for (uint i = 0; i < fileTextureCount; ++i) 584 { 585 // Get the current file texture. 586 const MObject& fileTexture = fileTextures[i]; 587 588 // Retrieve the UV set index for this texture 589 uint uvSetIndex = ShaderHelper::getAssociatedUVSet ( meshNode, fileTexture ); 590 591 // Retrieve the name for this UV set and match it with a DAE source. 592 MPlug uvSetPlug = uvSetMainPlug.elementByPhysicalIndex ( uvSetIndex, &status ); 593 if (status != MStatus::kSuccess) continue; 594 MPlug uvSetNamePlug = DagHelper::getChildPlug ( uvSetPlug, ATTR_UV_SET_NAME ); // "uvSetName" 595 MString uvSetName; uvSetNamePlug.getValue(uvSetName); 596 if (uvSetName.length() == 0) continue; 597 598 // Generate the name of the texture coordinates. 599 String texCoordName = EffectExporter::TEXCOORD_BASE + COLLADASW::Utils::toString ( i ); 600 COLLADASW::BindVertexInput bindVertexInput ( texCoordName, COLLADASW::CSWC::CSW_SEMANTIC_TEXCOORD, uvSetIndex ); 601 materialInstance.push_back ( bindVertexInput ); 602 } 603 604 instanceMaterialList.push_back ( materialInstance ); 605 } 606 } 607 } 608 609 //--------------------------------------------------------------- meshContainsShaderPolygons(const MObject & mesh,const MObjectArray & shaders,const MIntArray & shaderIndices,const uint shaderPosition)610 const bool VisualSceneExporter::meshContainsShaderPolygons ( 611 const MObject& mesh, 612 const MObjectArray& shaders, 613 const MIntArray& shaderIndices, 614 const uint shaderPosition ) 615 { 616 // Iterate through all polygons of the current mesh. 617 MItMeshPolygon meshPolygonsIter ( mesh ); 618 for ( meshPolygonsIter.reset(); !meshPolygonsIter.isDone(); meshPolygonsIter.next() ) 619 { 620 // Is this polygon shaded by this shader? 621 int polyIndex = meshPolygonsIter.index(); 622 uint realShaderCount = ( uint ) shaders.length(); 623 if ( shaderPosition < realShaderCount && 624 ( uint ) shaderIndices[polyIndex] != shaderPosition ) continue; 625 if ( shaderPosition >= realShaderCount && 626 ( shaderIndices[polyIndex] >= 0 && 627 shaderIndices[polyIndex] < ( int ) realShaderCount ) ) continue; 628 629 // Polygons for the current shader found. 630 return true; 631 } 632 633 // No polygons for the current shader. 634 return false; 635 } 636 GetThresholdPlugValue(const SceneElement * sceneElement,int indexLOD)637 static float GetThresholdPlugValue(const SceneElement* sceneElement, int indexLOD) 638 { 639 640 // Add Threshold value To switch to Next LOD Node 641 double threshold = -1; 642 MDagPath dagPath; 643 644 SceneElement::Type sceneElementType = sceneElement->getType(); 645 if (sceneElementType == SceneElement::LOD) 646 dagPath = sceneElement->getPath(); 647 else 648 dagPath = sceneElement->getParent()->getPath(); 649 650 MStatus status; 651 MObject transformNode = dagPath.transform(&status); 652 653 MPlug plugThreshold = MFnDependencyNode(transformNode).findPlug(ATTR_THRESHOLD, &status); 654 if (status == MStatus::kSuccess) 655 { 656 657 char indexLODString[50]; 658 sprintf(indexLODString, "%d", indexLOD); 659 660 MPlug plug = plugThreshold.elementByPhysicalIndex(indexLOD, &status); 661 662 String thresholdLOD = String(ATTR_THRESHOLD) + String("[") + String(indexLODString) + String("]"); 663 plug.getValue(threshold); 664 threshold = MDistance::internalToUI(threshold); 665 } 666 667 return (float)threshold; 668 } 669 670 //--------------------------------------------------------------- openVisualSceneNode(const SceneElement * sceneElement)671 bool VisualSceneExporter::openVisualSceneNode ( const SceneElement* sceneElement ) 672 { 673 // Get the dagPath from the scene element 674 const MDagPath dagPath = sceneElement->getPath(); 675 676 // Add the visual scene, if not done before 677 if (mDocumentExporter->mExportPass == VISUAL_SCENE_PASS) 678 { 679 if (!mVisualSceneAdded) 680 { 681 MString sceneName; 682 MGlobal::executeCommand(MString("file -q -ns"), sceneName); 683 if (sceneName.length() != 0) mSceneId = sceneName.asChar(); 684 685 // There is always just one visual scene. Give it a valid unique id. 686 String visualSceneName = COLLADABU::Utils::checkNCName(mSceneId); 687 openVisualScene(VISUAL_SCENE_NODE_ID, visualSceneName); 688 mVisualSceneAdded = true; 689 } 690 } 691 692 bool isInstanceNode = mVisualSceneNode->getIsInstanceNode(); 693 if ( isInstanceNode ) 694 { 695 String mayaNodeId; 696 697 // Get the URL of the instantiated visual scene node 698 SceneElement* instantiatedSceneElement = sceneElement->getInstantiatedSceneElement(); 699 if ( instantiatedSceneElement != 0 ) 700 { 701 MDagPath instantiatedDagPath = instantiatedSceneElement->getPath(); 702 mayaNodeId = mDocumentExporter->dagPathToColladaId ( instantiatedDagPath ); 703 } 704 else 705 { 706 // The maya node id. 707 mayaNodeId = mDocumentExporter->dagPathToColladaId ( dagPath ); 708 } 709 710 String colladaNodeId = findColladaNodeId ( mayaNodeId ); 711 if ( colladaNodeId.empty () ) 712 { 713 colladaNodeId = getColladaNodeId ( dagPath ); 714 } 715 716 mVisualSceneNode->setNodeURL ( COLLADASW::URI ( EMPTY_STRING, colladaNodeId ) ); 717 718 if (mDocumentExporter->mExportPass == SECOND_LOD_PASS) 719 { 720 // Get the dag node. 721 MFnDagNode node(dagPath.node()); 722 723 // The maya node id. 724 String mayaNodeId = mDocumentExporter->dagPathToColladaId(dagPath); 725 726 // Export the original maya name. 727 mVisualSceneNode->setNodeId(String("LOD__") + mayaNodeId); 728 mVisualSceneNode->setNodeName(mayaNodeId); 729 730 //mVisualSceneNode->addExtraTechniqueParameter(PROFILE_MAYA, PARAMETER_MAYA_ID, mayaNodeId); 731 } 732 } 733 else 734 { 735 // Get the dag node. 736 MFnDagNode node(dagPath.node()); 737 738 // The maya node id. 739 String mayaNodeId = mDocumentExporter->dagPathToColladaId(dagPath); 740 741 // Generate a COLLADA id for the new object. 742 String colladaNodeId = getColladaNodeId(dagPath); 743 744 // Make the id unique and store it in a map. 745 colladaNodeId = mNodeIdList.addId(colladaNodeId, mDocumentExporter->mExportPass == VISUAL_SCENE_PASS ? false : true); 746 747 mMayaIdColladaNodeId[mayaNodeId] = colladaNodeId; 748 749 // Set the node id and the name. 750 mVisualSceneNode->setNodeId(colladaNodeId); 751 String nodeName = mDocumentExporter->dagPathToColladaName(dagPath); 752 753 mVisualSceneNode->setNodeName(nodeName); 754 755 mVisualSceneNode->addExtraTechniqueParameter(PROFILE_MAYA, PARAMETER_MAYA_ID, nodeName); 756 } 757 758 exportExtraAttributes(sceneElement); 759 760 // TODO Export the imported extra tags, if there exist some. 761 762 763 // open the scene node 764 765 bool lodPass = false; 766 if (mDocumentExporter->mExportPass == SECOND_LOD_PASS || mDocumentExporter->mExportPass == FIRST_LOD_PASS) 767 lodPass = true; 768 769 if (mDocumentExporter->mExportPass == SECOND_LOD_PASS) 770 { 771 int indexLOD; 772 String proxy = findNextColladaNodeId(sceneElement, indexLOD); 773 if (proxy.compare(EMPTY_STRING) == 0) 774 return false; 775 776 } 777 778 mVisualSceneNode->start(lodPass); 779 return true; 780 } 781 782 //--------------------------------------------------------------- initializeTransform(SceneElement * sceneElement)783 bool VisualSceneExporter::initializeTransform ( SceneElement* sceneElement ) 784 { 785 // Get the dagPath from the scene element 786 MDagPath dagPath = sceneElement->getPath(); 787 mDagPath = dagPath; 788 789 MStatus status; 790 MObject transformNode = dagPath.transform ( &status ); 791 if ( ( status != MS::kSuccess ) && status.statusCode () == MStatus::kInvalidParameter ) return false; 792 793 mTransformObject = transformNode; 794 MFnDagNode transform ( transformNode, &status ); 795 if ( !status ) 796 { 797 status.perror ( "MFnDagNode constructor" ); 798 return false; 799 } 800 801 // Get the transforms local translation 802 MFnTransform fn ( transformNode ); 803 mTransformMatrix = fn.transformation(); 804 if ( fn.parentCount() > 0 ) 805 { 806 MFnTransform t ( fn.parent ( 0 ) ); 807 if ( t.hasObj ( MFn::kClusterFilter ) || t.hasObj ( MFn::kSkinClusterFilter ) ) 808 { 809 mTransformMatrix = MTransformationMatrix ( mTransformMatrix.asMatrix() * t.transformationMatrix() ); 810 } 811 } 812 813 // Skins being exported from maya need to have the bindpose matrix 814 // subtracted from the instance matrix. 815 bool oneSkinAlready = false; 816 817 // Check the child instances, which use this visual scene node. 818 size_t childCount = sceneElement->getChildCount(); 819 for ( size_t i=0; i<childCount && !oneSkinAlready; ++i ) 820 { 821 // Check if the child element is a mesh object and an export node 822 SceneElement* childElement = sceneElement->getChild ( i ); 823 if ( childElement->getType() == SceneElement::MESH && 824 childElement->getIsExportNode() ) 825 { 826 // Get the controller library 827 ControllerExporter* controller = mDocumentExporter->getControllerExporter(); 828 MObject childNode = childElement->getPath().node(); 829 bool hasSkinController = controller->hasSkinController ( childNode ); 830 if ( hasSkinController ) 831 { 832 // Skins being exported from maya need to have the bindpose matrix 833 // subtracted from the instance matrix. 834 MMatrix bindShapeMatrix = childElement->getBindShapeMatrix (); 835 MMatrix transformMatrix = mTransformMatrix.asMatrix (); 836 837 // Calculate the world transform of the node. 838 MMatrix transformMx = bindShapeMatrix.inverse () * transformMatrix; 839 840 // Set the new calculated transform matrix 841 mTransformMatrix = transformMx; 842 mTransformObject = MObject::kNullObj; 843 844 // Do it just once. 845 oneSkinAlready = true; 846 } 847 } 848 } 849 850 return true; 851 } 852 853 //--------------------------------------------------------------- exportDecomposedTransform()854 void VisualSceneExporter::exportDecomposedTransform() 855 { 856 MVector translation = mTransformMatrix.translation ( MSpace::kTransform ); 857 MPoint rotatePivotTranslation = mTransformMatrix.rotatePivotTranslation ( MSpace::kTransform ); 858 MPoint rotatePivot = mTransformMatrix.rotatePivot ( MSpace::kTransform, NULL ); 859 MVector scalePivotTranslation = mTransformMatrix.scalePivotTranslation ( MSpace::kTransform ); 860 MVector scalePivot = mTransformMatrix.scalePivot ( MSpace::kTransform ); 861 double shear[3] = {0, 0, 0}; 862 mTransformMatrix.getShear ( shear, MSpace::kTransform ); 863 864 MEulerRotation jointOrientation, rotation, rotationAxis; 865 if ( mTransformObject != MObject::kNullObj ) 866 { 867 mIsJoint = DagHelper::getPlugValue ( mTransformObject, ATTR_JOINT_ORIENT, jointOrientation ); 868 869 if ( !DagHelper::getPlugValue ( mTransformObject, ATTR_ROTATE, rotation ) ) rotation.setValue ( 0, 0, 0 ); 870 if ( !DagHelper::getPlugValue ( mTransformObject, ATTR_ROTATE_AXIS, rotationAxis ) ) rotationAxis.setValue ( 0, 0, 0 ); 871 872 rotation.order = ( MEulerRotation::RotationOrder ) ( ( int ) mTransformMatrix.rotationOrder() - MTransformationMatrix::kXYZ + MEulerRotation::kXYZ ); 873 rotationAxis.order = jointOrientation.order = MEulerRotation::kXYZ; 874 } 875 else 876 { 877 rotation = mTransformMatrix.eulerRotation(); 878 rotation.order = ( MEulerRotation::RotationOrder ) ( ( int ) mTransformMatrix.rotationOrder() - MTransformationMatrix::kXYZ + MEulerRotation::kXYZ ); 879 mIsJoint = false; 880 } 881 882 // This is the order of the transforms: 883 // 884 // matrix = [SP-1 * S * SH * SP * ST] * [RP-1 * RA * R * JO * RP * RT] * T 885 // [ scale ] * [ rotation ] * translation 886 // 887 // Where SP is scale pivot translation, S is scale, SH is shear, ST is scale pivot translation 888 // RP is rotation pivot, RA is rotation axis, R is rotation, RP is rotation pivot, 889 // RT is rotation pivot translation, T is translation, JO is joint orientation 890 // 891 // references: Maya documentation - transform node, Maya documentation - joint node 892 // NOTE: Left multiplying, column-order matrices 893 // 894 exportTranslation ( ATTR_TRANSLATE, translation, true ); 895 exportTranslation ( ATTR_ROTATE_PIVOT_TRANSLATION, rotatePivotTranslation, false ); 896 exportTranslation ( ATTR_ROTATE_PIVOT, rotatePivot, false ); 897 898 if ( mIsJoint ) exportRotation ( ATTR_JOINT_ORIENT, jointOrientation ); 899 exportRotation ( ATTR_ROTATE, rotation ); 900 if ( mIsJoint ) exportRotation ( ATTR_ROTATE_AXIS, rotationAxis ); 901 902 exportTranslation ( ATTR_ROTATE_PIVOT_INVERSE, rotatePivot * -1, false ); 903 exportTranslation ( ATTR_SCALE_PIVOT_TRANSLATION, scalePivotTranslation, false ); 904 exportTranslation ( ATTR_SCALE_PIVOT, scalePivot, false ); 905 906 exportSkew ( shear ); 907 908 // get the transforms scale 909 exportScale(); 910 911 exportTranslation ( ATTR_SCALE_PIVOT_INVERSE, scalePivot * -1, false ); 912 } 913 914 //--------------------------------------------------------------- exportSkew(double * shear)915 void VisualSceneExporter::exportSkew ( double* shear ) 916 { 917 // From my derivation, it is easier to split the shear into three. 918 // This forces the hard coded axises and the angle becomes simply: 919 // skewAngle = arctan(shearValue); 920 // 921 922 float xAxis[] = {1.0f, 0.0f, 0.0f}; 923 float yAxis[] = {0.0f, 1.0f, 0.0f}; 924 float zAxis[] = {0.0f, 0.0f, 1.0f}; 925 926 if ( !COLLADABU::Math::Utils::equalsZero ( shear[0], getTolerance () ) ) 927 { 928 double angle = COLLADABU::Math::Utils::radToDeg ( atan ( shear[0] ) ); 929 angle = COLLADABU::Math::Utils::equalsZero ( angle, getTolerance () ) ? 0 : angle; 930 float* rotateAxis ( xAxis ); 931 float* aroundAxis ( yAxis ); 932 933 mVisualSceneNode->addSkew ( SKEW_XY_SID, (float) angle, rotateAxis, aroundAxis ); 934 935 // // Set the animation, if the skew is animated. 936 // AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 937 // animationExporter->addNodeAnimation ( mTransformObject, ATTR_SKEW, ( SampleType ) ( kSingle | kQualifiedAngle ), XY_PARAMETER ); 938 } 939 940 if ( !COLLADABU::Math::Utils::equalsZero ( shear[1], getTolerance () ) ) 941 { 942 double angle = COLLADABU::Math::Utils::radToDeg ( atan ( shear[1] ) ); 943 angle = COLLADABU::Math::Utils::equalsZero( angle, getTolerance () ) ? 0 : angle; 944 float* rotateAxis ( xAxis ); 945 float* aroundAxis ( zAxis ); 946 947 mVisualSceneNode->addSkew ( SKEW_XZ_SID, (float) angle, rotateAxis, aroundAxis ); 948 949 // // Set the animation, if the skew is animated. 950 // AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 951 // animationExporter->addNodeAnimation ( mTransformObject, ATTR_SKEW, ( SampleType ) ( kSingle | kQualifiedAngle ), XZ_PARAMETER ); 952 } 953 954 if ( !COLLADABU::Math::Utils::equalsZero ( shear[2], getTolerance () ) ) 955 { 956 double angle = MAngle::internalToUI ( atan ( shear[2] ) ); 957 angle = COLLADABU::Math::Utils::equalsZero( angle, getTolerance () ) ? 0 : angle; 958 float* rotateAxis ( yAxis ); 959 float* aroundAxis ( zAxis ); 960 961 mVisualSceneNode->addSkew ( SKEW_YZ_SID, (float) angle, rotateAxis, aroundAxis ); 962 963 // // Set the animation, if the skew is animated. 964 // AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 965 // animationExporter->addNodeAnimation ( mTransformObject, ATTR_SKEW, ( SampleType ) ( kSingle | kQualifiedAngle ), YZ_PARAMETER ); 966 } 967 } 968 969 //--------------------------------------------------------------- exportScale()970 void VisualSceneExporter::exportScale() 971 { 972 // Get the scale. 973 double scale[3] = {1, 1, 1}; 974 mTransformMatrix.getScale ( scale, MSpace::kTransform ); 975 976 // Check if all fields in the std::vector are ones 977 bool isOneVector = true; 978 for ( int i=0; i<3 && isOneVector; ++i ) 979 { 980 if ( !COLLADABU::Math::Utils::equals( scale[i], 1.0, getTolerance () ) ) isOneVector = false; 981 } 982 983 // Check if the scale is animated. 984 AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 985 bool isAnimated = animationExporter->addNodeAnimation ( mTransformObject, ATTR_SCALE, kVector, XYZ_PARAMETERS ); 986 987 if ( mTransformObject != MObject::kNullObj || ( !isOneVector || isAnimated ) ) 988 { 989 mVisualSceneNode->addScale ( 990 ATTR_SCALE, 991 COLLADABU::Math::Utils::equalsZero ( scale[0], getTolerance () ) ? 0 : scale[0], 992 COLLADABU::Math::Utils::equalsZero ( scale[1], getTolerance () ) ? 0 : scale[1], 993 COLLADABU::Math::Utils::equalsZero ( scale[2], getTolerance () ) ? 0 : scale[2] ); 994 } 995 } 996 997 //--------------------------------------------------------------- exportTranslation(const String name,const MPoint & translation,bool animation)998 void VisualSceneExporter::exportTranslation ( 999 const String name, 1000 const MPoint& translation, 1001 bool animation ) 1002 { 1003 exportTranslation ( name, MVector ( translation ), animation ); 1004 } 1005 1006 //--------------------------------------------------------------- exportTranslation(const String name,const MVector & translation,bool animation)1007 void VisualSceneExporter::exportTranslation ( 1008 const String name, 1009 const MVector& translation, 1010 bool animation ) 1011 { 1012 bool isZero = true; 1013 for ( int i=0; i<3 && isZero; ++i ) 1014 { 1015 if ( translation[i] != 0 ) isZero = false; 1016 } 1017 1018 if ( animation || !isZero ) 1019 { 1020 // Convert the maya internal unit type from centimeters 1021 // into the working units of the current scene! 1022 mVisualSceneNode->addTranslate ( 1023 name, 1024 COLLADABU::Math::Utils::equalsZero( translation.x, getTolerance () ) ? 0 : MDistance::internalToUI ( translation.x ), 1025 COLLADABU::Math::Utils::equalsZero( translation.y, getTolerance () ) ? 0 : MDistance::internalToUI ( translation.y ), 1026 COLLADABU::Math::Utils::equalsZero( translation.z, getTolerance () ) ? 0 : MDistance::internalToUI ( translation.z ) ); 1027 1028 if ( animation ) 1029 { 1030 AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 1031 animationExporter->addNodeAnimation ( mDagPath.node(), ATTR_TRANSLATE, name, ( SampleType ) ( kVector | kLength ), XYZ_PARAMETERS, true ); 1032 } 1033 } 1034 } 1035 1036 //--------------------------------------------------------------- exportRotation(const String name,const MEulerRotation & rotation)1037 void VisualSceneExporter::exportRotation ( 1038 const String name, 1039 const MEulerRotation& rotation ) 1040 { 1041 RotateHelper rotateHelper ( rotation ); 1042 std::vector<std::vector<double> >& matrixRotate = rotateHelper.getRotationMatrix (); 1043 std::vector<String>& rotateParams = rotateHelper.getRotationParameters (); 1044 1045 // Set zero flags, where the rotation is zero. The order of rotation is ZYX. 1046 bool isZero[3] = { COLLADABU::Math::Utils::equalsZero ( matrixRotate[0][3], getTolerance () ), 1047 COLLADABU::Math::Utils::equalsZero ( matrixRotate[1][3], getTolerance () ), 1048 COLLADABU::Math::Utils::equalsZero ( matrixRotate[2][3], getTolerance () ) }; 1049 1050 // Get a pointer to the animation exporter. 1051 AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 1052 1053 // The array for the animations. 1054 bool isAnimated[3] = { false, false, false }; 1055 1056 // Go through the axes for the animations. 1057 for ( uint i=0; i<3; ++i ) 1058 { 1059 // Add the animation in the order XYZ 1060 isAnimated[i] = animationExporter->addNodeAnimation ( mTransformObject, name + rotateParams[i], ( SampleType ) ( kSingle | kQualifiedAngle ), ANGLE_PARAMETER ); 1061 } 1062 1063 // Go through the axes for the rotations. 1064 for ( uint i=0; i<3; ++i ) 1065 { 1066 bool rotationIsNecessary = false; 1067 1068 // Check, if we have to write the rotation. 1069 if ( mIsJoint && COLLADABU::Utils::equalsIgnoreCase ( name, ATTR_JOINT_ORIENT )) 1070 { 1071 // A joint must always have a rotation. 1072 rotationIsNecessary = true; 1073 } 1074 else 1075 { 1076 // You have to write the rotation, if the element is animated. 1077 rotationIsNecessary = ( isAnimated[i] || !( !mIsFirstRotation && isZero[i] )); 1078 } 1079 1080 if ( mTransformObject != MObject::kNullObj && rotationIsNecessary ) 1081 { 1082 // Add the rotation in the order ZYX 1083 mVisualSceneNode->addRotate ( 1084 name + rotateParams[i], 1085 COLLADABU::Math::Utils::equalsZero( matrixRotate[i][0], getTolerance () ) ? 0 : matrixRotate[i][0], 1086 COLLADABU::Math::Utils::equalsZero( matrixRotate[i][1], getTolerance () ) ? 0 : matrixRotate[i][1], 1087 COLLADABU::Math::Utils::equalsZero( matrixRotate[i][2], getTolerance () ) ? 0 : matrixRotate[i][2], 1088 COLLADABU::Math::Utils::equalsZero( matrixRotate[i][3], getTolerance () ) ? 0 : matrixRotate[i][3] ); 1089 } 1090 } 1091 1092 mIsFirstRotation = false; 1093 } 1094 1095 //--------------------------------------------------------------- exportMatrixTransform()1096 void VisualSceneExporter::exportMatrixTransform() 1097 { 1098 MMatrix mayaSceneMatrix = mTransformMatrix.asMatrix(); 1099 double sceneMatrix[4][4] ; 1100 convertMayaMatrixToTransposedDouble4x4 ( sceneMatrix, mayaSceneMatrix, getTolerance () ); 1101 1102 // Convert the maya internal unit type of the transform part of the 1103 // matrix from centimeters into the working units of the current scene! 1104 for ( uint i=0; i<3; ++i) 1105 sceneMatrix [i][3] = MDistance::internalToUI ( sceneMatrix [i][3] ); 1106 1107 mVisualSceneNode->addMatrix ( ATTR_TRANSFORM, sceneMatrix ); 1108 1109 // For animations, sampling is always enforced for baked transforms. 1110 MPlug plug = MFnDagNode ( mTransformObject ).findPlug ( ATTR_MATRIX ); 1111 mDocumentExporter->getAnimationCache()->cachePlug ( plug, true ); 1112 1113 MEulerRotation rotation; 1114 rotation.order = (MEulerRotation::RotationOrder) ((int)mTransformMatrix.rotationOrder() - MTransformationMatrix::kXYZ + MEulerRotation::kXYZ); 1115 1116 // Export the animations 1117 AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 1118 animationExporter->addPlugAnimation(plug, ATTR_TRANSFORM, kMatrix, rotation.order, TRANSFORM_PARAMETER, true ); 1119 } 1120 1121 //--------------------------------------------------------------- exportLookatTransform()1122 void VisualSceneExporter::exportLookatTransform() 1123 { 1124 // Compute local space parameters and export them. These parameters are: 1125 // - Eye position 1126 // - Interest point 1127 // - Up-axis direction 1128 // 1129 // TODO: camera animations for look-at transform are not implemented yet. 1130 // 1131 1132 // attach the function set to the object 1133 MFnTransform transformFunctionSet ( mTransformObject ); 1134 1135 // Locate the camera in the dagPath 1136 MObject cameraObject ( MObject::kNullObj ); 1137 uint pathChildCount = transformFunctionSet.childCount(); 1138 for ( uint i = 0; i < pathChildCount; ++i ) 1139 { 1140 MObject child = transformFunctionSet.child ( i ); 1141 if ( child.hasFn ( MFn::kCamera ) ) 1142 { 1143 cameraObject = child; 1144 break; 1145 } 1146 } 1147 1148 if ( cameraObject == MObject::kNullObj ) 1149 { 1150 // Revert to using decomposed transforms. 1151 exportDecomposedTransform(); 1152 } 1153 else 1154 { 1155 // Positioning and orienting a camera or object in the scene is often 1156 // complicated when using a matrix. A lookat transform is an intuitive 1157 // way to specify an eye position, interest point, and orientation. 1158 1159 // Get the camera matrix from which the other parameters are computed. 1160 MFnCamera camera ( cameraObject ); 1161 MMatrix matrix = transformFunctionSet.transformationMatrix(); 1162 matrix.homogenize(); 1163 1164 // Get the position of the camera in local space. 1165 MVector eye(matrix[3][0], matrix[3][1], matrix[3][2]); 1166 float eyePosition[3] = { 1167 COLLADABU::Math::Utils::equalsZero( matrix[3][0], getTolerance () ) ? 0.0f : (float) matrix[3][0], 1168 COLLADABU::Math::Utils::equalsZero( matrix[3][1], getTolerance () ) ? 0.0f : (float) matrix[3][1], 1169 COLLADABU::Math::Utils::equalsZero( matrix[3][2], getTolerance () ) ? 0.0f : (float) matrix[3][2] }; 1170 1171 // Compute center of interest. 1172 double centerOfInterestDistance = camera.centerOfInterestPoint ( MSpace::kObject ).z; 1173 MVector front ( matrix[2][0], matrix[2][1], matrix[2][2] ); 1174 MVector centerOfInterest = eye + ( front * centerOfInterestDistance ); 1175 float interestPosition[3] = { 1176 COLLADABU::Math::Utils::equalsZero( centerOfInterest.x, getTolerance () ) ? 0.0f : (float) centerOfInterest.x, 1177 COLLADABU::Math::Utils::equalsZero( centerOfInterest.y, getTolerance () ) ? 0.0f : (float) centerOfInterest.y, 1178 COLLADABU::Math::Utils::equalsZero( centerOfInterest.z, getTolerance () ) ? 0.0f : (float) centerOfInterest.z }; 1179 1180 // Extract the up direction, which corresponds to the second row. 1181 float upPosition[3] = { 1182 COLLADABU::Math::Utils::equalsZero( matrix[1][0], getTolerance () ) ? 0.0f : (float) matrix[1][0], 1183 COLLADABU::Math::Utils::equalsZero( matrix[1][1], getTolerance () ) ? 0.0f : (float) matrix[1][1], 1184 COLLADABU::Math::Utils::equalsZero( matrix[1][2], getTolerance () ) ? 0.0f : (float) matrix[1][2] }; 1185 1186 // Add the camera lookat 1187 mVisualSceneNode->addLookat ( eyePosition, interestPosition, upPosition ); 1188 } 1189 } 1190 1191 //--------------------------------------------------------------- exportVisibility(COLLADASW::Node * sceneNode)1192 void VisualSceneExporter::exportVisibility ( COLLADASW::Node* sceneNode ) 1193 { 1194 bool isVisible; 1195 1196 if ( mTransformObject != MObject::kNullObj ) 1197 { 1198 // Get the visibility value, if it exist 1199 if ( DagHelper::getPlugValue ( mTransformObject, ATTR_VISIBILITY, isVisible ) ) 1200 { 1201 AnimationSampleCache* animationCache = mDocumentExporter->getAnimationCache(); 1202 AnimationResult animationResult; 1203 animationResult = AnimationHelper::isAnimated( animationCache, mTransformObject, ATTR_VISIBILITY ); 1204 1205 // Write out the visibility of this node, if it is not visible or if it is animated. 1206 if ( !isVisible || animationResult != kISANIM_None ) 1207 { 1208 // Add an <extra> node with a visibility parameters that the animation can target 1209 sceneNode->addExtraTechniqueParameter ( PROFILE_MAYA, ATTR_VISIBILITY, isVisible ); 1210 1211 AnimationExporter* animationExporter = mDocumentExporter->getAnimationExporter(); 1212 animationExporter->addNodeAnimation ( mTransformObject, ATTR_VISIBILITY, kBoolean ); 1213 } 1214 } 1215 } 1216 } 1217 1218 //--------------------------------------------------------------- exportExtraAttributes(const SceneElement * sceneElement)1219 void VisualSceneExporter::exportExtraAttributes(const SceneElement* sceneElement) 1220 { 1221 class ExtraAttributeExporter : public AttributeParser 1222 { 1223 public: 1224 ExtraAttributeExporter(COLLADASW::Node & visualSceneNode) 1225 : mVisualSceneNode(visualSceneNode) 1226 {} 1227 1228 private: 1229 COLLADASW::Node & mVisualSceneNode; 1230 1231 protected: 1232 virtual bool onBeforePlug(MPlug & plug) override 1233 { 1234 MStatus status; 1235 1236 MObject attr = plug.attribute(&status); 1237 if (!status) return false; 1238 1239 MFnAttribute fnAttr(attr, &status); 1240 if (!status) return false; 1241 1242 MString attrName = fnAttr.name(&status); 1243 if (!status) return false; 1244 1245 bool isDynamic = fnAttr.isDynamic(&status); 1246 if (!status) return false; 1247 1248 if (!isDynamic) 1249 return false; 1250 1251 bool isHidden = fnAttr.isHidden(&status); 1252 if (!status) return false; 1253 1254 if (isHidden) 1255 return false; 1256 1257 return true; 1258 } 1259 1260 virtual void onBoolean(MPlug & plug, const MString & name, bool value) override 1261 { 1262 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1263 } 1264 1265 virtual void onInteger(MPlug & plug, const MString & name, int value) override 1266 { 1267 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1268 } 1269 1270 virtual void onInteger2(MPlug & plug, const MString & name, int value[2]) override 1271 { 1272 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1273 } 1274 1275 virtual void onInteger3(MPlug & plug, const MString & name, int value[3]) override 1276 { 1277 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1278 } 1279 1280 virtual void onFloat(MPlug & plug, const MString & name, float value) override 1281 { 1282 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1283 } 1284 1285 virtual void onFloat2(MPlug & plug, const MString & name, float value[2]) override 1286 { 1287 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1288 } 1289 1290 virtual void onFloat3(MPlug & plug, const MString & name, float value[3]) override 1291 { 1292 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1293 } 1294 1295 virtual void onDouble(MPlug & plug, const MString & name, double value) override 1296 { 1297 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value, "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1298 } 1299 1300 virtual void onDouble2(MPlug & plug, const MString & name, double value[2]) override 1301 { 1302 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1303 } 1304 1305 virtual void onDouble3(MPlug & plug, const MString & name, double value[3]) override 1306 { 1307 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1308 } 1309 1310 virtual void onDouble4(MPlug & plug, const MString & name, double value[4]) override 1311 { 1312 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), value[0], value[1], value[2], value[3], "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1313 } 1314 1315 virtual void onString(MPlug & plug, const MString & name, const MString & value) override 1316 { 1317 mVisualSceneNode.addExtraTechniqueParameter(PROFILE_MAYA, name.asChar(), COLLADABU::StringUtils::translateToXML(String(value.asChar())), "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1318 } 1319 1320 virtual void onEnum(MPlug & plug, const MString & name, int enumValue, const MString & enumName) override 1321 { 1322 // TODO export all possible enum values to be able to re-import them? 1323 mVisualSceneNode.addExtraTechniqueEnumParameter(PROFILE_MAYA, name.asChar(), COLLADABU::StringUtils::translateToXML(String(enumName.asChar())), "", COLLADASW::CSWC::CSW_ELEMENT_PARAM); 1324 } 1325 }; 1326 1327 MObject nodeObject = sceneElement->getNode(); 1328 1329 MStatus status; 1330 MFnDependencyNode fnNode(nodeObject, &status); 1331 if (!status) return; 1332 1333 ExtraAttributeExporter extraAttributeExporter(*mVisualSceneNode); 1334 AttributeParser::parseAttributes(fnNode, extraAttributeExporter); 1335 } 1336 1337 //--------------------------------------------------------------- exportInstanceController(SceneElement * sceneElement,const bool hasSkinController,const bool hasMorphController)1338 void VisualSceneExporter::exportInstanceController( 1339 SceneElement* sceneElement, 1340 const bool hasSkinController, 1341 const bool hasMorphController ) 1342 { 1343 MObject childNode = sceneElement->getPath().node(); 1344 1345 // Get the streamWriter from the export document 1346 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 1347 ControllerExporter* controllerExporter = mDocumentExporter->getControllerExporter (); 1348 1349 // Get the collada id. 1350 // MDagPath dagPath = sceneElement->getPath(); 1351 // String mayaControllerId = mDocumentExporter->dagPathToColladaId ( dagPath ); 1352 String mayaControllerId = sceneElement->getNodeName(); 1353 if ( hasMorphController ) 1354 mayaControllerId += COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX; 1355 if ( hasSkinController ) 1356 mayaControllerId += COLLADASW::LibraryControllers::SKIN_CONTROLLER_ID_SUFFIX; 1357 1358 String colladaId = controllerExporter->findColladaControllerId ( mayaControllerId ); 1359 1360 // TODO id preservation 1361 // Create the unique controller ID 1362 // String colladaId; 1363 // if ( !sceneElement->getNodeId().empty() ) 1364 // colladaId = sceneElement->getNodeId(); 1365 // else 1366 // colladaId = sceneElement->getNodeName(); 1367 // if ( hasMorphController ) 1368 // colladaId += COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX; 1369 // if ( hasSkinController ) 1370 // colladaId += COLLADASW::LibraryControllers::SKIN_CONTROLLER_ID_SUFFIX; 1371 1372 // Get the uri of the current scene 1373 COLLADASW::URI uri; 1374 if (!ExportOptions::exportSeparateFile() || (ExportOptions::exportSeparateFile() && !ExportOptions::exportAnimationsOnly())) 1375 uri = getSceneElementURI(sceneElement, colladaId); 1376 else 1377 { 1378 String daeName = ExportOptions::getDAEmodelName().asChar(); 1379 1380 MString exportedFile = mDocumentExporter->getFilename().c_str(); 1381 1382 // Make referenced file path relative to exported file directory 1383 COLLADASW::URI exportedFileURI = exportedFile.asChar(); 1384 COLLADASW::URI exportedFileDirURI = exportedFileURI.getPathDir(); 1385 exportedFileDirURI.setScheme(exportedFileURI.getScheme()); 1386 1387 COLLADASW::URI referencedFileURI = MString(daeName.c_str()).asChar(); 1388 referencedFileURI.makeRelativeTo(exportedFileDirURI); 1389 1390 if (ExportOptions::exportAnimationsOnly() && daeName.compare("") != 0) 1391 { 1392 uri = URI(referencedFileURI.getURIString() + String("#") + colladaId); 1393 } 1394 else 1395 { 1396 MGlobal::displayWarning(MString("Please provide Model DAE path to not lose association between animation and a specific model ")); 1397 return; 1398 } 1399 } 1400 1401 // Create the collada controller instance 1402 COLLADASW::InstanceController instanceController ( streamWriter ); 1403 instanceController.setUrl ( uri ); 1404 1405 // Set the skeletonId. It indicates where a skin controller is to start to search for the 1406 // joint nodes it needs. This element is meaningless for morph controllers. 1407 const std::set<URI>& skeletonURIs = sceneElement->getSkeletonURIs (); 1408 if ( skeletonURIs.size () > 0 ) 1409 { 1410 std::set<URI>::const_iterator it = skeletonURIs.begin (); 1411 while ( it != skeletonURIs.end () ) 1412 { 1413 instanceController.addSkeleton ( *it ); 1414 ++it; 1415 } 1416 } 1417 1418 // Write all materials 1419 COLLADASW::InstanceMaterialList& instanceMaterialList = 1420 instanceController.getBindMaterial().getInstanceMaterialList(); 1421 1422 // Export the materials 1423 exportInstanceMaterial ( instanceMaterialList, sceneElement->getPath() ); 1424 1425 instanceController.add(); 1426 } 1427 1428 //--------------------------------------------------------------- exportInstanceGeometry(SceneElement * sceneElement)1429 void VisualSceneExporter::exportInstanceGeometry ( SceneElement* sceneElement ) 1430 { 1431 // Get the current dag path 1432 MDagPath dagPath = sceneElement->getPath(); 1433 1434 // Get the collada mesh id. 1435 GeometryExporter* geometryExporter = mDocumentExporter->getGeometryExporter (); 1436 const String& colladaMeshId = geometryExporter->getColladaGeometryId ( dagPath ); 1437 if ( colladaMeshId.empty () ) return; 1438 1439 // Get the uri of the current scene 1440 COLLADASW::URI uri(getSceneElementURI(sceneElement, colladaMeshId)); 1441 1442 // Get the streamWriter from the export document 1443 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 1444 1445 // Write the geometry instance 1446 COLLADASW::InstanceGeometry instanceGeometry ( streamWriter ); 1447 instanceGeometry.setUrl ( uri ); 1448 1449 // Write all materials 1450 COLLADASW::InstanceMaterialList& instanceMaterialList = 1451 instanceGeometry.getBindMaterial().getInstanceMaterialList(); 1452 1453 // Export the materials 1454 exportInstanceMaterial ( instanceMaterialList, sceneElement->getPath() ); 1455 1456 instanceGeometry.add(); 1457 } 1458 1459 //--------------------------------------------------------------- exportInstanceLightProbe(const SceneElement * sceneElement)1460 void VisualSceneExporter::exportInstanceLightProbe(const SceneElement* sceneElement) 1461 { 1462 // Get the collada light probe id. 1463 MDagPath dagPath = sceneElement->getPath(); 1464 String mayaLightProbeId = mDocumentExporter->dagPathToColladaId ( dagPath ); 1465 LightProbeExporter* lightProbeExporter = mDocumentExporter->getLightProbeExporter (); 1466 String colladaLightProbeId = lightProbeExporter->findColladaLightProbeId ( mayaLightProbeId ); 1467 1468 // Get the uri of the current scene 1469 COLLADASW::URI uri(getSceneElementURI(sceneElement, colladaLightProbeId)); 1470 1471 // Create and write the light probe instance 1472 //COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 1473 //COLLADASW::InstanceLightProbe instanceLightProbe ( streamWriter, uri ); 1474 //instanceLightProbe.add(); 1475 1476 mVisualSceneNode->addExtraTechniqueElement(COLLADAMaya::PROFILE_MAYA, COLLADAMaya::CSW_ELEMENT_INSTANCE_LIGHT_PROBE, COLLADASW::CSWC::CSW_ATTRIBUTE_URL, uri.getURIString()); 1477 } 1478 1479 //--------------------------------------------------------------- exportInstanceLight(const SceneElement * sceneElement)1480 void VisualSceneExporter::exportInstanceLight( const SceneElement* sceneElement ) 1481 { 1482 // Get the collada light id. 1483 MDagPath dagPath = sceneElement->getPath(); 1484 String mayaLightId = mDocumentExporter->dagPathToColladaId ( dagPath ); 1485 LightExporter* lightExporter = mDocumentExporter->getLightExporter (); 1486 String colladaLightId = lightExporter->findColladaLightId ( mayaLightId ); 1487 1488 // Get the uri of the current scene 1489 COLLADASW::URI uri(getSceneElementURI(sceneElement, colladaLightId)); 1490 1491 // Create and write the light instance 1492 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 1493 COLLADASW::InstanceLight instanceLight ( streamWriter, uri ); 1494 instanceLight.add(); 1495 } 1496 1497 //--------------------------------------------------------------- exportInstanceCamera(const SceneElement * sceneElement)1498 void VisualSceneExporter::exportInstanceCamera( const SceneElement* sceneElement ) 1499 { 1500 // Get the collada id. 1501 MDagPath dagPath = sceneElement->getPath(); 1502 String mayaId = mDocumentExporter->dagPathToColladaId ( dagPath ); 1503 CameraExporter* cameraExporter = mDocumentExporter->getCameraExporter (); 1504 String colladaId = cameraExporter->findColladaCameraId ( mayaId ); 1505 1506 // Get the uri of the current scene 1507 COLLADASW::URI uri(getSceneElementURI(sceneElement, colladaId)); 1508 1509 // Create and write the camera instance 1510 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 1511 COLLADASW::InstanceCamera instanceCamera ( streamWriter, uri ); 1512 instanceCamera.add(); 1513 } 1514 1515 //--------------------------------------------------------------- exportInstanceNode(SceneElement * sceneElement)1516 void VisualSceneExporter::exportInstanceNode ( SceneElement* sceneElement ) 1517 { 1518 // Get the collada id. 1519 String mayaNodeId = sceneElement->getNodeId(); 1520 if (mayaNodeId.empty()) 1521 { 1522 mayaNodeId = mVisualSceneNode->getNodeId(); 1523 } 1524 if ( mayaNodeId.empty() ) 1525 mayaNodeId = sceneElement->getNodeName(); 1526 String colladaNodeId = findColladaNodeId ( mayaNodeId ); 1527 1528 // Get the uri of the current scene 1529 COLLADASW::URI uri ( getSceneElementURI ( sceneElement, colladaNodeId ) ); 1530 1531 // Create and write the camera instance 1532 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 1533 COLLADASW::InstanceNode instanceNode ( streamWriter, uri ); 1534 1535 // Add Proxy to Next LOD Node (during Library Node second Pass) 1536 // Or during Visual Scene Pass only for element inside LOD Group 1537 if ((mDocumentExporter->mExportPass == SECOND_LOD_PASS) || 1538 (ExportOptions::exportLOD() && mDocumentExporter->mExportPass == VISUAL_SCENE_PASS && (sceneElement->getParentCount()>0 && sceneElement->getParent()->getType() == SceneElement::LOD))) 1539 { 1540 int indexLOD; 1541 1542 SceneElement* element; 1543 1544 if (mDocumentExporter->mExportPass == VISUAL_SCENE_PASS) 1545 element = sceneElement->getParent(); 1546 else 1547 element = sceneElement; 1548 1549 String proxy = findNextColladaNodeId(element, indexLOD); 1550 if (proxy.compare(EMPTY_STRING) != 0) 1551 { 1552 String prefix = "LOD__"; 1553 SceneElement* parent = sceneElement->getParent(); 1554 1555 if (indexLOD == parent->getChildCount() - 2) 1556 prefix = ""; 1557 1558 1559 const String url = "#" + prefix + proxy; 1560 instanceNode.addExtraTechniqueParentElement(PROFILE_MAYA, PARAMETER_PROXY, "url", url); 1561 1562 const String threshold = String(ATTR_THRESHOLD); 1563 instanceNode.addExtraTechniqueChildElement(PROFILE_MAYA, PARAMETER_PROXY, threshold, GetThresholdPlugValue(element, indexLOD)); 1564 } 1565 1566 if (mDocumentExporter->mExportPass == VISUAL_SCENE_PASS) 1567 instanceNode.addExtraTechnique(); // Only Add Extra, Instance node has been added before 1568 else 1569 instanceNode.add(); // Add Instance Node with proxy if != EMPTY_STRING, Add extra too 1570 } 1571 else 1572 instanceNode.add(); 1573 } 1574 1575 //--------------------------------------------------------------- getSceneElementURI(const SceneElement * sceneElement,const String & elementId)1576 COLLADASW::URI VisualSceneExporter::getSceneElementURI ( 1577 const SceneElement* sceneElement, 1578 const String& elementId /** = EMPTY_STRING */) 1579 { 1580 return getSceneElementURI(sceneElement->getPath(), elementId); 1581 } 1582 1583 //--------------------------------------------------------------- getSceneElementURI(const MDagPath & dagPath,const String & id)1584 COLLADASW::URI VisualSceneExporter::getSceneElementURI(const MDagPath& dagPath, const String& id /*= EMPTY_STRING*/) 1585 { 1586 MFnDagNode dagFn(dagPath); 1587 bool isLocal = !dagFn.isFromReferencedFile(); 1588 if (ExportOptions::exportXRefs() && ExportOptions::dereferenceXRefs()) { 1589 isLocal = true; 1590 } 1591 1592 // Get the Uri of the element. 1593 if (!isLocal) 1594 { 1595 MObject referenceNode; 1596 MStatus status = ReferenceManager::getTopLevelReferenceNode(dagPath, referenceNode); 1597 if (status == MS::kFailure) { 1598 return COLLADASW::URI(); 1599 } 1600 1601 MString mayaReferenceFilename; 1602 status = ReferenceManager::getReferenceFilename(referenceNode, mayaReferenceFilename); 1603 1604 String referenceFilename = mayaReferenceFilename.asChar(); 1605 1606 // Replace .mb by .dae 1607 String::size_type dotPos = referenceFilename.rfind('.'); 1608 if (dotPos != String::npos) { 1609 referenceFilename.resize(dotPos); 1610 referenceFilename.append(".dae"); 1611 } 1612 MString exportedFile = MFileIO::currentFile(); 1613 1614 // Make referenced file path relative to exported file directory 1615 COLLADASW::URI exportedFileURI = exportedFile.asChar(); 1616 COLLADASW::URI exportedFileDirURI = exportedFileURI.getPathDir(); 1617 exportedFileDirURI.setScheme(exportedFileURI.getScheme()); 1618 COLLADASW::URI referencedFileURI = referenceFilename; 1619 if (ExportOptions::relativePaths()) 1620 { 1621 referencedFileURI.makeRelativeTo(exportedFileDirURI); 1622 } 1623 1624 COLLADASW::URI sceneElementURI(referencedFileURI); 1625 const bool removeFirstNamespace = true; 1626 String refNodeId = getColladaNodeId(dagPath, removeFirstNamespace); 1627 sceneElementURI.setFragment(refNodeId); 1628 return sceneElementURI; 1629 } 1630 else 1631 { 1632 // Get the id of the element 1633 if (!id.empty()) { 1634 return COLLADASW::URI(EMPTY_STRING, id); 1635 } 1636 else { 1637 return COLLADASW::URI(EMPTY_STRING, mDocumentExporter->dagPathToColladaId(dagPath)); 1638 } 1639 } 1640 } 1641 1642 //--------------------------------------------------------------- exportInstanceChildNodes(const SceneElement * sceneElement)1643 void VisualSceneExporter::exportInstanceChildNodes( const SceneElement* sceneElement ) 1644 { 1645 // Check the geometry instances, which use this visual scene 1646 size_t childCount = sceneElement->getChildCount(); 1647 for ( size_t i=0; i<childCount; ++i ) 1648 { 1649 SceneElement* childElement = sceneElement->getChild ( i ); 1650 1651 // Just export visible export nodes. 1652 if ( !childElement->getIsExportNode() ) continue; 1653 if ( !ExportOptions::exportInvisibleNodes () && !childElement->getIsVisible () ) continue; 1654 1655 bool exportGeometry = true; 1656 bool physicsExportNode = false; 1657 1658 const MObject& transformNode = sceneElement->getPath().transform(); 1659 DagHelper::getPlugValue(transformNode, ATTR_COLLISION_EXPORT_NODE, physicsExportNode); 1660 1661 int shape; 1662 if (DagHelper::getPlugValue(transformNode, ATTR_COLLISION_SHAPE, shape) && !physicsExportNode) 1663 { 1664 if (shape == PhysicsExporter::Box || 1665 shape == PhysicsExporter::Capsule) 1666 exportGeometry = false; 1667 } 1668 1669 // Check if the child element is a mesh object and an export node 1670 if ( childElement->getType() == SceneElement::MESH && exportGeometry) 1671 { 1672 // Get the controller library 1673 ControllerExporter* controller = mDocumentExporter->getControllerExporter(); 1674 MObject childNode = childElement->getPath().node(); 1675 1676 bool hasSkinController = controller->hasSkinController ( childNode ); 1677 bool hasMorphController = controller->hasMorphController ( childNode ); 1678 1679 // Check for controllers, otherwise instantiate the geometry. 1680 // Add the controller and/or geometry to our libraries 1681 if ((ExportOptions::exportJoints() && hasSkinController) || hasMorphController) 1682 { 1683 if (ExportOptions::exportSkin() || ExportOptions::exportSeparateFile()) 1684 exportInstanceController ( childElement, hasSkinController, hasMorphController ); 1685 } 1686 else 1687 { 1688 exportInstanceGeometry ( childElement ); 1689 } 1690 } 1691 else if (childElement->getType() == SceneElement::LIGHT_PROBE && 1692 childElement->getIsExportNode()) 1693 { 1694 exportInstanceLightProbe(childElement); 1695 } 1696 else if ( childElement->getType() == SceneElement::LIGHT && 1697 childElement->getIsExportNode() && 1698 ExportOptions::exportLights()) 1699 { 1700 exportInstanceLight ( childElement ); 1701 } 1702 else if ( childElement->getType() == SceneElement::CAMERA && 1703 childElement->getIsExportNode() && 1704 ExportOptions::exportCameras()) 1705 { 1706 exportInstanceCamera ( childElement ); 1707 } 1708 } 1709 } 1710 1711 // ------------------------------------ findColladaNodeId(const String & mayaNodeId)1712 const String VisualSceneExporter::findColladaNodeId ( const String& mayaNodeId ) 1713 { 1714 const StringToStringMap::const_iterator it = mMayaIdColladaNodeId.find ( mayaNodeId ); 1715 if ( it != mMayaIdColladaNodeId.end () ) 1716 { 1717 return it->second; 1718 } 1719 return EMPTY_STRING; 1720 } 1721 findNextColladaNodeId(const SceneElement * sceneElement,int & indexLOD)1722 const String VisualSceneExporter::findNextColladaNodeId(const SceneElement* sceneElement, int& indexLOD) 1723 { 1724 MDagPath dag; 1725 int index = 0; 1726 indexLOD = index; 1727 1728 if (mDocumentExporter->mExportPass == VISUAL_SCENE_PASS) 1729 dag = sceneElement->getChild(1)->getPath(); 1730 else 1731 { 1732 SceneElement* parent = sceneElement->getParent(); 1733 1734 bool found = false; 1735 for (index = 0; index < parent->getChildCount(); index++) 1736 { 1737 if (parent->getChild(index)->getPath() == sceneElement->getPath()) 1738 { 1739 found = true; 1740 break; 1741 } 1742 } 1743 1744 if (!found) 1745 return EMPTY_STRING; 1746 1747 if (index + 1 >= parent->getChildCount()) 1748 return EMPTY_STRING; 1749 else 1750 dag = parent->getChild(index + 1)->getPath(); 1751 } 1752 1753 indexLOD = index; 1754 1755 String mayaNodeId = mDocumentExporter->dagPathToColladaId(dag); 1756 1757 const StringToStringMap::iterator it = mMayaIdColladaNodeId.find(mayaNodeId); 1758 1759 if (it != mMayaIdColladaNodeId.end()) 1760 { 1761 return it->second; 1762 } 1763 return EMPTY_STRING; 1764 } 1765 1766 // ------------------------------------ getColladaNodeId(const MDagPath & dagPath,bool removeFirstNamespace)1767 COLLADAMaya::String VisualSceneExporter::getColladaNodeId ( 1768 const MDagPath &dagPath, 1769 bool removeFirstNamespace) 1770 { 1771 String colladaNodeId; 1772 1773 // Check if there is an extra attribute "colladaId" and use this as export id. 1774 MString attributeValue; 1775 DagHelper::getPlugValue ( dagPath.node (), COLLADA_ID_ATTRIBUTE_NAME, attributeValue ); 1776 if ( attributeValue != EMPTY_CSTRING ) 1777 { 1778 // Generate a valid collada name, if necessary. 1779 colladaNodeId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false, removeFirstNamespace ); 1780 } 1781 else 1782 { 1783 // Generate a COLLADA id for the new object 1784 //colladaNodeId = mDocumentExporter->mayaNameToColladaName ( node.name ().asChar () ); 1785 colladaNodeId = mDocumentExporter->dagPathToColladaId ( dagPath, removeFirstNamespace ); 1786 } 1787 1788 return colladaNodeId; 1789 } 1790 ResetLODCounter()1791 void VisualSceneExporter::ResetLODCounter() 1792 { 1793 mLODIndexCounter2 = 0; 1794 } 1795 } 1796