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 "COLLADAMayaMaterialExporter.h" 18 #include "COLLADAMayaEffectExporter.h" 19 #include "COLLADAMayaSceneGraph.h" 20 #include "COLLADAMayaDagHelper.h" 21 #include "COLLADAMayaShaderHelper.h" 22 #include "COLLADAMayaSyntax.h" 23 #include "COLLADAMayaConversion.h" 24 #include "COLLADAMayaExportOptions.h" 25 #include "COLLADAMayaHwShaderExporter.h" 26 27 #include "COLLADASWNode.h" 28 #include "COLLADASWParamTemplate.h" 29 #include "COLLADASWConstants.h" 30 31 32 #include <maya/MItMeshPolygon.h> 33 #include <maya/MItDag.h> 34 #include <maya/MFnSet.h> 35 #include <maya/MFnMesh.h> 36 37 #if defined(WIN64) && MAYA_API_VERSION >= 201600 && !defined(WIN32) 38 /* define WIN32 to work around CFGX WIN64 compilation */ 39 #define WIN32 40 #endif 41 42 #include "cgfxShaderNode.h" 43 44 #include <cgfxFindImage.h> 45 46 namespace COLLADAMaya 47 { 48 49 MaterialExporter::SidSet MaterialExporter::mSurfaceSidList; 50 51 //--------------------------------------------------------------- MaterialExporter(COLLADASW::StreamWriter * streamWriter,DocumentExporter * documentExporter)52 MaterialExporter::MaterialExporter ( COLLADASW::StreamWriter* streamWriter, 53 DocumentExporter* documentExporter ) 54 : COLLADASW::LibraryMaterials ( streamWriter ), 55 mDocumentExporter ( documentExporter ), 56 mExportedMaterials ( NULL ), 57 mWriteMaterials ( false ), 58 materialMapInitialized ( false ) 59 {} 60 61 //--------------------------------------------------------------- exportMaterials(bool writeMaterials)62 MaterialMap* MaterialExporter::exportMaterials ( bool writeMaterials ) 63 { 64 mWriteMaterials = writeMaterials; 65 66 // Should we only export the selected elements? 67 bool exportSelectedOnly = mDocumentExporter->getExportSelectedOnly (); 68 69 // Should we only export the referenced (used) materials? 70 bool exportReferencedOnly = ExportOptions::exportReferencedMaterials (); 71 72 if ( !exportSelectedOnly && !exportReferencedOnly ) 73 { 74 // Get all shaders, which are in the default shader list. 75 // Unfortunately, you will not get the default initialShadingGroup elements, which are 76 // directly connected to an object, if no other material (shader) is connected to the object. 77 exportMaterialsByShaderPlug (); 78 } 79 80 // Now go through scene graph and find all shaders, connected to the meshes. 81 // So you can find the default shaders of an object. 82 exportMaterialsBySceneGraph (); 83 84 // Set the flag, that the material std::map is initialised 85 materialMapInitialized = true; 86 87 // Close the tags in the collada document 88 closeLibrary(); 89 90 // Return the material list 91 return &mMaterialMap; 92 } 93 94 //------------------------------------------------------ exportMaterialsByShaderPlug()95 void MaterialExporter::exportMaterialsByShaderPlug() 96 { 97 // Get all shaders, which are in the default shader list. 98 MObject defaultShaderList = DagHelper::getNode ( ATTR_DEFAULT_SHADER_LIST1 ); 99 MPlug defaultShadersPlug = MFnDependencyNode ( defaultShaderList ).findPlug ( ATTR_SHADERS ); 100 101 uint shaderCount = defaultShadersPlug.evaluateNumElements(); 102 for ( uint i = 0; i < shaderCount; ++i ) 103 { 104 MObject shader = DagHelper::getNodeConnectedTo ( defaultShadersPlug.elementByPhysicalIndex ( i ) ); 105 MFnDependencyNode shadingEngineFn ( shader ); 106 107 // Get the name of the current material (this is the maya material id) 108 String mayaMaterialId = DocumentExporter::mayaNameToColladaName ( shadingEngineFn.name(), true ); 109 110 bool doExportMaterial = true; 111 bool isFromReferencedFile = shadingEngineFn.isFromReferencedFile(); 112 // bool isDefaulNode = shadingEngineFn.isDefaultNode(); 113 // if ( isDefaulNode ) 114 // { 115 // doExportMaterial = false; 116 // } 117 // else if ( isFromReferencedFile ) 118 if ( isFromReferencedFile ) 119 { 120 if ( ExportOptions::exportXRefs() && ExportOptions::dereferenceXRefs() ) doExportMaterial = true; 121 else doExportMaterial = false; 122 } 123 124 if ( doExportMaterial ) 125 { 126 MObject shadingEngine = ShaderHelper::getShadingEngine ( shader ); 127 exportMaterial ( shadingEngine ); 128 } 129 } 130 } 131 132 //------------------------------------------------------ exportMaterialsBySceneGraph()133 void MaterialExporter::exportMaterialsBySceneGraph () 134 { 135 // Get the list with the transform nodes. 136 SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph(); 137 SceneElementsList* exportNodesTree = sceneGraph->getExportNodesTree(); 138 139 // Now go through scene graph and find all shaders, connected to the meshes. 140 // So you can find the default shaders of an object. 141 size_t length = exportNodesTree->size(); 142 for ( size_t i = 0; i < length; ++i ) 143 { 144 SceneElement* sceneElement = ( *exportNodesTree ) [i]; 145 if ( !sceneElement->getIsLocal() ) continue; 146 if ( !sceneElement->getIsExportNode () ) continue; 147 148 size_t childCount = sceneElement->getChildCount(); 149 for ( size_t i=0; i<childCount; ++i ) 150 { 151 SceneElement* childSceneElement = sceneElement->getChild ( i ); 152 153 exportConnectedMaterials ( childSceneElement ); 154 } 155 } 156 } 157 158 //------------------------------ exportConnectedMaterials(SceneElement * sceneElement)159 void MaterialExporter::exportConnectedMaterials ( SceneElement* sceneElement ) 160 { 161 // If we have a external reference, we don't need to export the data here. 162 if ( !sceneElement->getIsLocal() ) return; 163 if ( !sceneElement->getIsExportNode () ) return; 164 165 // Check if it is a mesh object and an export node 166 if ( sceneElement->getType() == SceneElement::MESH ) 167 { 168 MDagPath dagPath = sceneElement->getPath(); 169 170 // Attach a function set 171 MStatus status; 172 MFnMesh fnMesh ( dagPath.node(), &status ); 173 if ( status != MStatus::kSuccess ) return; 174 175 // Find how many shaders are used by this instance of the mesh 176 MObjectArray shaders; 177 MIntArray shaderIndices; 178 unsigned instanceNumber = dagPath.instanceNumber(); 179 fnMesh.getConnectedShaders ( instanceNumber, shaders, shaderIndices ); 180 181 // Find the polygons that correspond to each materials and export them 182 uint realShaderCount = ( uint ) shaders.length(); 183 uint numShaders = ( uint ) std::max ( ( size_t ) 1, ( size_t ) shaders.length() ); 184 for ( uint shaderPosition = 0; shaderPosition < numShaders; ++shaderPosition ) 185 { 186 if ( shaderPosition < realShaderCount ) 187 { 188 // Add shader-specific parameters (TexCoords sets). 189 // Add symbolic name for the material used on this polygon set. 190 MObject shadingEngine = shaders[shaderPosition]; 191 exportMaterial ( shadingEngine ); 192 } 193 } 194 } 195 196 // recursive call for all the child elements 197 for ( uint i=0; i<sceneElement->getChildCount(); ++i ) 198 { 199 SceneElement* childElement = sceneElement->getChild ( i ); 200 exportConnectedMaterials ( childElement ); 201 } 202 } 203 204 //-------------------------------- exportMaterial(MObject shadingEngine)205 void MaterialExporter::exportMaterial ( MObject shadingEngine ) 206 { 207 // Get the shader object. 208 MObject shader = DagHelper::getSourceNodeConnectedTo ( shadingEngine, ATTR_SURFACE_SHADER ); 209 210 // Find the actual shader node, since this function received shading sets as input 211 MStatus status; 212 MFnDependencyNode shaderNode ( shader, &status ); 213 if ( status != MStatus::kSuccess ) return; 214 215 // Get the name of the current material (this is the maya material id) 216 String mayaMaterialId = DocumentExporter::mayaNameToColladaName ( shaderNode.name(), true ); 217 218 // Have we seen this shader before, is it already exported? 219 MaterialMap::iterator materialMapIter; 220 materialMapIter = mMaterialMap.find ( mayaMaterialId ); 221 if ( materialMapIter != mMaterialMap.end() ) return; 222 223 // This is a new shading engine 224 mMaterialMap [mayaMaterialId] = shader; 225 226 // Generate a COLLADA id for the new object 227 String colladaMaterialId; 228 229 // Check if there is an extra attribute "colladaId" and use this as export id. 230 MString attributeValue; 231 DagHelper::getPlugValue ( shader, COLLADA_MATERIAL_ID_ATTRIBUTE_NAME, attributeValue ); 232 if ( attributeValue != EMPTY_CSTRING ) 233 { 234 // Generate a valid collada name, if necessary. 235 colladaMaterialId = DocumentExporter::mayaNameToColladaName ( attributeValue, false ); 236 } 237 else 238 { 239 // Generate a COLLADA id for the new object 240 colladaMaterialId = DocumentExporter::mayaNameToColladaName ( shaderNode.name(), true ); 241 } 242 // Make the id unique and store it. 243 colladaMaterialId = mMaterialIdList.addId ( colladaMaterialId ); 244 mMayaIdColladaMaterialIdMap [mayaMaterialId] = colladaMaterialId; 245 246 // MFnDependencyNode shadingEngineNode ( shadingEngine, &status ); 247 // if ( status != MStatus::kSuccess ) return; 248 // String shadingEngineNodeName = shadingEngineNode.name ().asChar (); // initialParticleSE 249 // String shaderNodeName = shaderNode.name ().asChar (); // lambert1 250 251 // Check if the material should be written 252 if ( mWriteMaterials ) 253 { 254 // Have we exported this shader already? 255 std::vector<String>::iterator exportedMaterialsIter; 256 exportedMaterialsIter = find ( mExportedMaterials.begin(), mExportedMaterials.end(), colladaMaterialId ); 257 258 if ( exportedMaterialsIter == mExportedMaterials.end() ) 259 { 260 // Open a tag for the current material in the collada document 261 openMaterial ( colladaMaterialId, mayaMaterialId ); 262 263 // Export the reference to the effect and the hardware shader components. 264 exportEffectInstance ( mayaMaterialId, colladaMaterialId, shader ); 265 266 // // TODO Export the user defined material extra data from import (extra preservation). 267 // mDocumentExporter->exportExtraData ( shader, COLLADAFW::ExtraKeys::MATERIAL ); 268 269 // Closes the current effect tag 270 closeMaterial(); 271 272 // Push the id of the exported material into the list for the exported materials 273 mExportedMaterials.push_back ( colladaMaterialId ); 274 } 275 } 276 } 277 278 //--------------------------------------- getExportedMaterialsMap()279 MaterialMap* MaterialExporter::getExportedMaterialsMap() 280 { 281 if ( !materialMapInitialized ) exportMaterials ( false ); 282 283 return &mMaterialMap; 284 } 285 286 //--------------------------------------- setSetParam(const cgfxShaderNode * shaderNodeCgfx,const cgfxAttrDef * attribute)287 void MaterialExporter::setSetParam ( const cgfxShaderNode* shaderNodeCgfx, const cgfxAttrDef* attribute ) 288 { 289 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 290 String attributeName = attribute->fName.asChar(); 291 292 cgfxAttrDef::cgfxAttrType attributeType = attribute->fType; 293 switch ( attributeType ) 294 { 295 case cgfxAttrDef::kAttrTypeBool: 296 { 297 if (attribute->fNumericDef) 298 { 299 COLLADASW::SetParamBool setParam ( streamWriter ); 300 setParam.openParam ( attributeName ); 301 setParam.appendValues ( attribute->fNumericDef[0] != 0.0 ); 302 setParam.closeParam (); 303 } 304 break; 305 } 306 case cgfxAttrDef::kAttrTypeInt: 307 { 308 if (attribute->fNumericDef) 309 { 310 COLLADASW::SetParamInt setParam(streamWriter); 311 setParam.openParam(attributeName); 312 setParam.appendValues(static_cast<int>(attribute->fNumericDef[0])); 313 setParam.closeParam(); 314 } 315 break; 316 } 317 case cgfxAttrDef::kAttrTypeString: 318 { 319 MGlobal::displayWarning(("CG String Parameter type: ") + MString(attributeName.c_str()) + MString(" not supported!") ); 320 321 /* 322 if (attribute->fStringDef.length() > 0) 323 { 324 COLLADASW::SetParamString setParam(streamWriter); 325 setParam.openParam(attributeName); 326 setParam.appendValues(String(attribute->fStringDef.asChar())); 327 setParam.closeParam(); 328 } 329 break; 330 */ 331 } 332 case cgfxAttrDef::kAttrTypeFloat: 333 { 334 if (attribute->fNumericDef) 335 { 336 COLLADASW::SetParamFloat setParam(streamWriter); 337 setParam.openParam(attributeName); 338 setParam.appendValues(attribute->fNumericDef[0]); 339 setParam.closeParam(); 340 } 341 break; 342 } 343 case cgfxAttrDef::kAttrTypeVector2: 344 { 345 if (attribute->fNumericDef) 346 { 347 COLLADASW::SetParamFloat2 setParam(streamWriter); 348 setParam.openParam(attributeName); 349 for (int i = 0; i < attribute->fSize; ++i) 350 { 351 setParam.appendValues(attribute->fNumericDef[i]); 352 } 353 setParam.closeParam(); 354 } 355 break; 356 } 357 case cgfxAttrDef::kAttrTypeVector3: 358 case cgfxAttrDef::kAttrTypeColor3: 359 { 360 if (attribute->fNumericDef) 361 { 362 COLLADASW::SetParamFloat3 setParam ( streamWriter ); 363 setParam.openParam ( attributeName ); 364 for ( int i=0; i<attribute->fSize; ++i ) 365 { 366 setParam.appendValues(attribute->fNumericDef[i]); 367 } 368 setParam.closeParam(); 369 } 370 break; 371 } 372 case cgfxAttrDef::kAttrTypeVector4: 373 case cgfxAttrDef::kAttrTypeColor4: 374 { 375 if (attribute->fNumericDef) 376 { 377 COLLADASW::SetParamFloat4 setParam(streamWriter); 378 setParam.openParam(attributeName); 379 for (int i = 0; i < attribute->fSize; ++i) 380 { 381 setParam.appendValues(attribute->fNumericDef[i]); 382 } 383 setParam.closeParam(); 384 } 385 break; 386 } 387 case cgfxAttrDef::kAttrTypeWorldDir: 388 case cgfxAttrDef::kAttrTypeWorldPos: 389 { 390 if (attribute->fNumericDef) 391 { 392 // Read the value 393 double tmp[4]; 394 for (int i = 0; i < attribute->fSize; ++i) 395 { 396 tmp[i] = attribute->fNumericDef[i]; 397 } 398 if (attribute->fSize == 3) tmp[3] = 1.0; 399 400 // Find the coordinate space, and whether it is a point or a vector 401 int base = cgfxAttrDef::kAttrTypeFirstPos; 402 if (attribute->fType <= cgfxAttrDef::kAttrTypeLastDir) 403 base = cgfxAttrDef::kAttrTypeFirstDir; 404 int space = attribute->fType - base; 405 406 // Compute the transform matrix 407 MMatrix mat; 408 switch (space) 409 { 410 /* case 0: object space, handled in view dependent method */ 411 case 1: /* world space - do nothing, identity */ break; 412 /* case 2: eye space, unsupported yet */ 413 /* case 3: clip space, unsupported yet */ 414 /* case 4: screen space, unsupported yet */ 415 } 416 417 if (base == cgfxAttrDef::kAttrTypeFirstPos) 418 { 419 MPoint point(tmp[0], tmp[1], tmp[2], tmp[3]); 420 point *= mat; 421 tmp[0] = point.x; 422 tmp[1] = point.y; 423 tmp[2] = point.z; 424 tmp[3] = point.w; 425 } 426 else 427 { 428 MVector vec(tmp[0], tmp[1], tmp[2]); 429 vec *= mat; 430 tmp[0] = vec.x; 431 tmp[1] = vec.y; 432 tmp[2] = vec.z; 433 tmp[3] = 1; 434 } 435 436 COLLADASW::SetParamFloat4 setParam(streamWriter); 437 setParam.openParam(attributeName); 438 setParam.appendValues(tmp[0], tmp[1], tmp[2], tmp[3]); 439 setParam.closeParam(); 440 } 441 break; 442 } 443 case cgfxAttrDef::kAttrTypeMatrix: 444 case cgfxAttrDef::kAttrTypeWorldMatrix: 445 case cgfxAttrDef::kAttrTypeViewMatrix: 446 case cgfxAttrDef::kAttrTypeProjectionMatrix: 447 case cgfxAttrDef::kAttrTypeWorldViewMatrix: 448 case cgfxAttrDef::kAttrTypeWorldViewProjectionMatrix: 449 { 450 if (attribute->fNumericDef) 451 { 452 COLLADASW::SetParamFloat4x4 setParam(streamWriter); 453 setParam.openParam(attributeName); 454 455 MMatrix mayaMatrix; 456 double* p = &mayaMatrix.matrix[0][0]; 457 for (int k = 0; k < attribute->fSize; ++k) 458 { 459 p[k] = attribute->fNumericDef[k]; 460 } 461 462 MMatrix wMatrix, vMatrix, pMatrix, sMatrix; 463 MMatrix wvMatrix, wvpMatrix, wvpsMatrix; 464 { 465 float tmp[4][4]; 466 467 wMatrix.setToIdentity(); 468 469 glGetFloatv(GL_MODELVIEW_MATRIX, &tmp[0][0]); 470 wvMatrix = MMatrix(tmp); 471 472 vMatrix = wMatrix.inverse() * wvMatrix; 473 474 glGetFloatv(GL_PROJECTION_MATRIX, &tmp[0][0]); 475 pMatrix = MMatrix(tmp); 476 477 wvpMatrix = wvMatrix * pMatrix; 478 479 float vpt[4]; 480 float depth[2]; 481 482 glGetFloatv(GL_VIEWPORT, vpt); 483 glGetFloatv(GL_DEPTH_RANGE, depth); 484 485 // Construct the NDC -> screen space matrix 486 // 487 float x0, y0, z0, w, h, d; 488 489 x0 = vpt[0]; 490 y0 = vpt[1]; 491 z0 = depth[0]; 492 w = vpt[2]; 493 h = vpt[3]; 494 d = depth[1] - z0; 495 496 // Make a reference to ease the typing 497 // 498 double* s = &sMatrix.matrix[0][0]; 499 500 s[0] = w / 2; s[1] = 0.0; s[2] = 0.0; s[3] = 0.0; 501 s[4] = 0.0; s[5] = h / 2; s[6] = 0.0; s[7] = 0.0; 502 s[8] = 0.0; s[9] = 0.0; s[10] = d / 2; s[11] = 0.0; 503 s[12] = x0 + w / 2; s[13] = y0 + h / 2; s[14] = z0 + d / 2; s[15] = 1.0; 504 505 wvpsMatrix = wvpMatrix * sMatrix; 506 } 507 508 switch (attribute->fType) 509 { 510 case cgfxAttrDef::kAttrTypeWorldMatrix: 511 mayaMatrix = wMatrix; break; 512 case cgfxAttrDef::kAttrTypeViewMatrix: 513 mayaMatrix = vMatrix; break; 514 case cgfxAttrDef::kAttrTypeProjectionMatrix: 515 mayaMatrix = pMatrix; break; 516 case cgfxAttrDef::kAttrTypeWorldViewMatrix: 517 mayaMatrix = wvMatrix; break; 518 case cgfxAttrDef::kAttrTypeWorldViewProjectionMatrix: 519 mayaMatrix = wvpMatrix; break; 520 default: 521 break; 522 } 523 524 if (attribute->fInvertMatrix) 525 mayaMatrix = mayaMatrix.inverse(); 526 527 if (!attribute->fTransposeMatrix) 528 mayaMatrix = mayaMatrix.transpose(); 529 530 double matrix[4][4]; 531 convertMayaMatrixToTransposedDouble4x4(matrix, mayaMatrix, getTolerance()); 532 setParam.appendValues(matrix); 533 setParam.closeParam(); 534 } 535 break; 536 } 537 case cgfxAttrDef::kAttrTypeColor1DTexture: 538 case cgfxAttrDef::kAttrTypeColor2DTexture: 539 case cgfxAttrDef::kAttrTypeColor3DTexture: 540 case cgfxAttrDef::kAttrTypeColor2DRectTexture: 541 case cgfxAttrDef::kAttrTypeNormalTexture: 542 case cgfxAttrDef::kAttrTypeBumpTexture: 543 case cgfxAttrDef::kAttrTypeCubeTexture: 544 case cgfxAttrDef::kAttrTypeEnvTexture: 545 case cgfxAttrDef::kAttrTypeNormalizationTexture: 546 { 547 CGparameter cgParameter = attribute->fParameterHandle; 548 HwShaderExporter hwShaderExporter ( mDocumentExporter ); 549 hwShaderExporter.setShaderFxFileUri ( getShaderFxFileUri () ); 550 551 MObject shaderNode = shaderNodeCgfx->thisMObject(); 552 hwShaderExporter.exportSampler ( shaderNode, cgParameter, false ); 553 554 555 // ------------------------------- 556 // String imageName = attribute->fStringDef.asChar(); 557 // 558 // MObject oNode = shaderNodeCgfx->thisMObject(); 559 // MFnDependencyNode oNodeFn ( oNode ); 560 // String oNodeName = oNodeFn.name().asChar(); // cgfxShader1 561 // 562 // MPlug plug; 563 // if ( DagHelper::getPlugConnectedTo( oNode, attributeName, plug ) ) 564 // { 565 // String plugName = plug.name().asChar(); // file1.outColor 566 // MObject textureNode = plug.node(); 567 // 568 // //COLLADASW::Surface::SurfaceType surfaceType; 569 // COLLADASW::Sampler::SamplerType samplerType; 570 // COLLADASW::ValueType::ColladaType samplerValueType; 571 // 572 // switch ( attributeType ) 573 // { 574 // case cgfxAttrDef::kAttrTypeColor1DTexture: 575 // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_1D; 576 // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_1D; 577 // samplerValueType = COLLADASW::ValueType::SAMPLER_1D; 578 // break; 579 // case cgfxAttrDef::kAttrTypeColor2DTexture: 580 // case cgfxAttrDef::kAttrTypeNormalTexture: 581 // case cgfxAttrDef::kAttrTypeBumpTexture: 582 // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_2D; 583 // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_2D; 584 // samplerValueType = COLLADASW::ValueType::SAMPLER_2D; 585 // break; 586 // case cgfxAttrDef::kAttrTypeColor3DTexture: 587 // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_3D; 588 // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_3D; 589 // samplerValueType = COLLADASW::ValueType::SAMPLER_3D; 590 // break; 591 // case cgfxAttrDef::kAttrTypeColor2DRectTexture: 592 // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_RECT; 593 // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_RECT; 594 // samplerValueType = COLLADASW::ValueType::SAMPLER_RECT; 595 // break; 596 // case cgfxAttrDef::kAttrTypeCubeTexture: 597 // case cgfxAttrDef::kAttrTypeEnvTexture: 598 // case cgfxAttrDef::kAttrTypeNormalizationTexture: 599 // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_CUBE; 600 // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_CUBE; 601 // samplerValueType = COLLADASW::ValueType::SAMPLER_CUBE; 602 // break; 603 // default: 604 // //surfaceType = COLLADASW::Surface::SURFACE_TYPE_UNTYPED; 605 // samplerType = COLLADASW::Sampler::SAMPLER_TYPE_UNSPECIFIED; 606 // samplerValueType = COLLADASW::ValueType::VALUE_TYPE_UNSPECIFIED; 607 // } 608 // 609 // // Write the params elements 610 // setSetParamTexture ( attribute, textureNode, samplerType, samplerValueType ); 611 // } 612 } 613 } 614 } 615 616 //--------------------------------------- setSetParamTexture(const cgfxAttrDef * attribute,MObject texture,COLLADASW::Sampler::SamplerType samplerType,COLLADASW::ValueType::ColladaType samplerValueType)617 void MaterialExporter::setSetParamTexture ( 618 const cgfxAttrDef* attribute, 619 MObject texture, 620 COLLADASW::Sampler::SamplerType samplerType, 621 COLLADASW::ValueType::ColladaType samplerValueType ) 622 { 623 // Get a pointer to the current stream writer. 624 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 625 626 // Get the image id 627 MFnDependencyNode textureNode ( texture ); 628 String plugName = textureNode.name().asChar(); // file1 629 630 // Get the file texture name 631 MPlug filenamePlug = textureNode.findPlug ( ATTR_FILE_TEXTURE_NAME ); 632 MString mayaFileName; 633 filenamePlug.getValue ( mayaFileName ); 634 if ( mayaFileName.length() == 0 ) return; 635 String fileName = mayaFileName.asChar (); 636 637 // Get the image path 638 // Take the filename for the unique image name 639 COLLADASW::URI sourceFileUri(COLLADASW::URI::nativePathToUri(fileName)); 640 if ( sourceFileUri.getScheme ().empty () ) 641 sourceFileUri.setScheme ( COLLADASW::URI::SCHEME_FILE ); 642 String mayaImageId = DocumentExporter::mayaNameToColladaName ( sourceFileUri.getPathFileBase().c_str () ); 643 644 // Get the image id of the maya image 645 EffectExporter* effectExporter = mDocumentExporter->getEffectExporter (); 646 String colladaImageId = effectExporter->findColladaImageId ( mayaImageId ); 647 if ( colladaImageId.empty () ) 648 { 649 // Check if there is an extra attribute "colladaId" and use this as export id. 650 MString attributeValue; 651 DagHelper::getPlugValue ( texture, COLLADA_ID_ATTRIBUTE_NAME, attributeValue ); 652 if ( attributeValue != EMPTY_CSTRING ) 653 { 654 // Generate a valid collada name, if necessary. 655 colladaImageId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false ); 656 } 657 else 658 { 659 // Generate a COLLADA id for the new light object 660 colladaImageId = DocumentExporter::mayaNameToColladaName ( textureNode.name() ); 661 } 662 // Make the id unique and store it in a map for refernences. 663 EffectTextureExporter* textureExporter = effectExporter->getTextureExporter (); 664 colladaImageId = textureExporter->getImageIdList ().addId ( colladaImageId ); 665 textureExporter->getMayaIdColladaImageId () [mayaImageId] = colladaImageId; 666 } 667 668 // Export the image 669 EffectTextureExporter* textureExporter = mDocumentExporter->getEffectExporter()->getTextureExporter(); 670 COLLADASW::Image* colladaImage = textureExporter->exportImage ( mayaImageId, colladaImageId, sourceFileUri ); 671 mayaImageId = colladaImage->getImageId(); 672 673 // Create the sampler and surface sid 674 String samplerSid = mayaImageId + COLLADASW::Sampler::SAMPLER_SID_SUFFIX; 675 String surfaceSid = mayaImageId + COLLADASW::Sampler::SURFACE_SID_SUFFIX; 676 677 // Avoid export of dublicate sampler params 678 if ( mSamplers.find ( samplerSid ) != mSamplers.end () ) return; 679 mSamplers.insert ( samplerSid ); 680 681 // Create the sampler and add the sampler <setparam> 682 COLLADASW::Sampler sampler ( samplerType, samplerSid, surfaceSid ); 683 sampler.setFormat ( EffectTextureExporter::FORMAT ); 684 sampler.setImageId ( colladaImage->getImageId() ); 685 sampler.addInSetParam ( streamWriter ); 686 } 687 688 //--------------------------------------- exportCustomHwShaderNode(COLLADASW::InstanceEffect & effectInstance,MObject shader)689 void MaterialExporter::exportCustomHwShaderNode( 690 COLLADASW::InstanceEffect &effectInstance, 691 MObject shader ) 692 { 693 MFnDependencyNode fnNode ( shader ); 694 if ( fnNode.typeId() == cgfxShaderNode::sId ) 695 { 696 // Add the technique hint and the effect attributes to the collada document. 697 exportCgfxShaderNode ( effectInstance, (cgfxShaderNode*) fnNode.userNode () ); 698 } 699 700 } 701 702 //--------------------------------------- exportCgfxShaderNode(COLLADASW::InstanceEffect & effectInstance,cgfxShaderNode * shaderNodeCgfx)703 void MaterialExporter::exportCgfxShaderNode ( 704 COLLADASW::InstanceEffect& effectInstance, 705 cgfxShaderNode* shaderNodeCgfx ) 706 { 707 // Get the filename of the current cgfx file 708 MString shaderFxFile = cgfxFindFile(shaderNodeCgfx->shaderFxFile()); 709 String shaderFxFileName = shaderFxFile.asChar(); // check3d.cgfx 710 setShaderFxFileUri ( COLLADASW::URI ( COLLADASW::URI::nativePathToUri ( shaderFxFileName ) ) ); 711 712 // Get the current technique name 713 String techniqueName = shaderNodeCgfx->getTechnique().asChar(); // techniqueName.asChar() 714 715 // Add the technique hint to the collada document. 716 effectInstance.addTechniqueHint ( techniqueName, COLLADASW::CSWC::CSW_PLATFORM_PC_OGL ); 717 718 // Clear the samplers setParam list. 719 mSamplers.clear (); 720 721 #if MAYA_API_VERSION < 201200 722 // Get the setParams attributes 723 CGeffect cgEffect = shaderNodeCgfx->effect(); 724 CGtechnique cgTechnique = cgGetNamedTechnique( cgEffect, techniqueName.c_str() ); 725 cgfxAttrDefList* effectAttributes = cgfxAttrDef::attrsFromEffect ( cgEffect, cgTechnique ); 726 MString sResult, sTemp; 727 cgfxAttrDefList::iterator effectIt; 728 for ( effectIt=effectAttributes->begin(); effectIt; ++effectIt ) 729 { 730 cgfxAttrDef* effectAttribute = *effectIt; 731 setSetParam ( shaderNodeCgfx, effectAttribute ); 732 } 733 #else // MAYA_API_VERSION < 201200 734 // Get the setParams attributes 735 const cgfxRCPtr<const cgfxEffect>& cgEffect = shaderNodeCgfx->effect(); 736 if( cgEffect.isNull() ) 737 { 738 MGlobal::displayError ( "cgEffect is null." ); 739 return; 740 } 741 742 cgfxRCPtr<cgfxAttrDefList> effectAttributes = cgEffect->attrsFromEffect(); 743 744 MString sResult, sTemp; 745 cgfxAttrDefList::iterator effectIt; 746 747 MaterialExporter::mSurfaceSidList.clear(); 748 749 for ( effectIt=effectAttributes->begin(); effectIt; ++effectIt ) 750 { 751 cgfxAttrDef* effectAttribute = *effectIt; 752 setSetParam ( shaderNodeCgfx, effectAttribute ); 753 } 754 #endif // MAYA_API_VERSION < 201200 755 } 756 757 // -------------------------------------- setShaderFxFileUri(const COLLADASW::URI & shaderFxFileName)758 void MaterialExporter::setShaderFxFileUri( const COLLADASW::URI& shaderFxFileName ) 759 { 760 mShaderFxFileUri = shaderFxFileName; 761 } 762 763 // -------------------------------------- getShaderFxFileUri() const764 const COLLADASW::URI& MaterialExporter::getShaderFxFileUri() const 765 { 766 return mShaderFxFileUri; 767 } 768 769 // -------------------------------------- exportEffectInstance(const String & mayaMaterialId,const String & colladaMaterialId,MObject & shader)770 void MaterialExporter::exportEffectInstance ( 771 const String& mayaMaterialId, 772 const String& colladaMaterialId, 773 MObject &shader ) 774 { 775 // Generate a COLLADA id for the new object 776 String colladaEffectId; 777 778 // Check if there is an extra attribute "colladaId" and use this as export id. 779 MString attributeValue; 780 DagHelper::getPlugValue ( shader, COLLADA_EFFECT_ID_ATTRIBUTE_NAME, attributeValue ); 781 if ( attributeValue != EMPTY_CSTRING ) 782 { 783 // Generate a valid collada name, if necessary. 784 colladaEffectId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false ); 785 } 786 else 787 { 788 // Generate a COLLADA id for the new object 789 colladaEffectId = colladaMaterialId + EffectExporter::EFFECT_ID_SUFFIX; 790 } 791 // Make the id unique and store it in a map. 792 colladaEffectId = mEffectIdList.addId ( colladaEffectId ); 793 mMayaIdColladaEffectIdMap [ mayaMaterialId ] = colladaEffectId; 794 795 // Create the effect instance 796 COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter(); 797 COLLADASW::InstanceEffect effectInstance ( streamWriter, COLLADASW::URI ( EMPTY_STRING, colladaEffectId ) ); 798 799 // Opens the current effect instance. 800 effectInstance.open(); 801 802 // Custom hardware shaders derived from MPxHardwareShader (the new stuff) 803 if ( shader.hasFn ( MFn::kPluginHwShaderNode ) ) 804 { 805 // Export the effect technique reference and the hardware shader parameters. 806 exportCustomHwShaderNode ( effectInstance, shader ); 807 } 808 809 // TODO 810 // // Export the user defined instance_effect extra data from import (extra preservation). 811 // mDocumentExporter->exportExtraData ( shader, COLLADAFW::ExtraKeys::INSTANCE_EFFECT ); 812 813 // Close the current effect element. 814 effectInstance.close(); 815 } 816 817 // -------------------------------------- findColladaEffectId(const String & mayaMaterialId)818 const String MaterialExporter::findColladaEffectId ( const String& mayaMaterialId ) 819 { 820 const StringToStringMap::const_iterator it = mMayaIdColladaEffectIdMap.find ( mayaMaterialId ); 821 if ( it != mMayaIdColladaEffectIdMap.end () ) 822 { 823 return it->second; 824 } 825 return EMPTY_STRING; 826 } 827 828 // -------------------------------------- findColladaMaterialId(const String & mayaMaterialId)829 const String MaterialExporter::findColladaMaterialId ( const String& mayaMaterialId ) 830 { 831 const StringToStringMap::const_iterator it = mMayaIdColladaMaterialIdMap.find ( mayaMaterialId ); 832 if ( it != mMayaIdColladaMaterialIdMap.end () ) 833 { 834 return it->second; 835 } 836 return EMPTY_STRING; 837 } 838 839 840 } 841