2
Copyright (c) 2008-2009 NetAllied Systems GmbH
4
This file is part of COLLADAMaya.
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.
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
16
#include "COLLADAMayaStableHeaders.h"
17
#include "COLLADAMayaControllerExporter.h"
18
#include "COLLADAMayaDagHelper.h"
19
#include "COLLADAMayaShaderHelper.h"
20
#include "COLLADAMayaSceneGraph.h"
21
#include "COLLADAMayaSyntax.h"
22
#include "COLLADAMayaExportOptions.h"
23
#include "COLLADAMayaGeometryExporter.h"
24
#include "COLLADAMayaConversion.h"
25
#include "COLLADAMayaAnimationTools.h"
26
#include "COLLADAMayaAnimationExporter.h"
27
#include "COLLADAMayaVisualSceneExporter.h"
31
#include "Math/COLLADABUMathUtils.h"
33
#include "COLLADASWBaseInputElement.h"
34
#include "COLLADASWExtra.h"
36
#include <maya/MItDependencyGraph.h>
37
#include <maya/MFnDagNode.h>
38
#include <maya/MFnTransform.h>
39
#include <maya/MFnSkinCluster.h>
40
#include <maya/MItGeometry.h>
41
#include <maya/MFnWeightGeometryFilter.h>
42
#include <maya/MFnPointArrayData.h>
43
#include <maya/MFnBlendShapeDeformer.h>
44
#include <maya/MFnComponentListData.h>
50
const String ControllerExporter::PARAM_TYPE_TRANSFORM = "TRANSFORM";
51
const String ControllerExporter::PARAM_TYPE_JOINT = "JOINT";
52
const String ControllerExporter::PARAM_TYPE_MORPH_TARGET = "MORPH_TARGET";
53
const String ControllerExporter::PARAM_TYPE_MORPH_WEIGHT = "MORPH_WEIGHT";
54
const String ControllerExporter::PARAM_TYPE_WEIGHT = "WEIGHT";
56
//------------------------------------------------------
57
ControllerExporter::ControllerExporter ( COLLADASW::StreamWriter* streamWriter,
58
DocumentExporter* documentExporter )
59
: COLLADASW::LibraryControllers ( streamWriter )
60
, mDocumentExporter ( documentExporter )
61
, mExportedControllers ( NULL )
64
//------------------------------------------------------
65
ControllerExporter::~ControllerExporter()
69
//------------------------------------------------------
70
void ControllerExporter::exportControllers()
72
// Get the list with the transform nodes.
73
SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
74
SceneElementsList* exportNodesTree = sceneGraph->getExportNodesTree();
76
// Export all/selected DAG nodes
77
size_t length = exportNodesTree->size();
78
for ( size_t i=0; i<length; ++i )
80
SceneElement* sceneElement = ( *exportNodesTree ) [i];
81
exportControllers ( sceneElement );
87
//------------------------------------------------------
88
void ControllerExporter::exportControllers( SceneElement* sceneElement )
90
// If we have a external reference, we don't need to export the data here.
91
if ( !sceneElement->getIsLocal() ) return;
92
if ( !sceneElement->getIsExportNode () ) return;
94
// Check if it is a mesh and an export node
95
SceneElement::Type sceneElementType = sceneElement->getType();
96
if ( sceneElementType == SceneElement::MESH )
98
// Get the current dag path
99
MDagPath dagPath = sceneElement->getPath();
100
String pathName = dagPath.fullPathName ().asChar ();
102
// Check if the current scene element isn't already exported.
103
if ( findExportedContollerSceneElement ( sceneElement ) ) return;
105
// Check if the current element is an instance.
106
// We don't need to export instances, because we export the original instanced element.
107
bool isInstance = ( dagPath.isInstanced() && dagPath.instanceNumber() > 0 );
109
// If the original instanced element isn't already exported, we have to export it now.
112
// Get the original instanced element.
113
MDagPath instancedPath;
114
dagPath.getPath ( instancedPath, 0 );
115
SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
116
SceneElement* instancedSceneElement = sceneGraph->findElement ( instancedPath );
118
// Check if the controller of the original instanced element is already exported.
119
std::vector<SceneElement*>::const_iterator controllerIter;
120
controllerIter = find ( mExportedControllerSceneElements.begin (), mExportedControllerSceneElements.end (), instancedSceneElement );
121
if ( controllerIter == mExportedControllerSceneElements.end () )
123
// Create a skin/morph transform object and export the controller for the
124
// the original instanced element.
125
if ( exportController ( instancedSceneElement ) )
127
// Push the scene element in the list of exported controller elements.
128
mExportedControllerSceneElements.push_back ( instancedSceneElement );
134
// Create a skin/morph transform object and export the controller.
135
if ( exportController ( sceneElement ) )
137
// Push the scene element in the list of exported controller elements.
138
mExportedControllerSceneElements.push_back ( sceneElement );
143
// Recursive call for all the child elements
144
for ( uint i=0; i<sceneElement->getChildCount(); ++i )
146
SceneElement* childElement = sceneElement->getChild ( i );
147
exportControllers ( childElement );
151
//------------------------------------------------------
152
bool ControllerExporter::exportController( SceneElement* sceneElement )
154
// Get the current dag path
155
MDagPath dagPath = sceneElement->getPath();
157
// Get the current mesh node.
158
MObject meshNode = dagPath.node();
160
// The stacks of the controllers for the affected nodes.
161
ControllerStack stack;
162
ControllerMeshStack meshStack;
164
// Iterate upstream finding all the nodes which affect the mesh.
165
if ( !findAffectedNodes ( meshNode, stack, meshStack ) )
170
// Disable any effects on the nodes.
171
setControllerNodeStatesToNoEffect ( stack );
172
// Set all meshes as visible and not intermediate.
173
setValidMeshParameters ( meshStack );
175
// Exports all the mesh affected nodes in the controller stack.
176
exportControllerStack ( sceneElement, stack );
178
// Reset the intermediate and visibility mesh parameters.
179
resetMeshParameters ( meshStack );
180
// Reset the controller node states.
181
resetControllerNodeStates ( stack );
182
// Delete the controller stack items and clear the stack.
183
deleteControllerStackItems ( stack );
188
//------------------------------------------------------
189
void ControllerExporter::exportControllerStack(
190
SceneElement *sceneElement,
191
const ControllerStack &stack )
193
// Get the current path and the mesh node.
194
MDagPath dagPath = sceneElement->getPath();
195
MObject meshNode = dagPath.node();
197
// We cannot express more than one skin per geometry instance...
198
bool alreadyHasSkin = false;
200
// Export the controller stack
201
for ( intptr_t i=stack.size()-1; i>=0; --i )
203
ControllerStackItem* item = stack[i];
206
if ( ExportOptions::exportJointsAndSkin() && !alreadyHasSkin )
208
// Correctly avoid chained joint-clusters: only export the first
209
// joint cluster which exports the subsequent joint-clusters with it.
210
MObject skinControllerNode = item->skinControllerNode;
211
if ( !skinControllerNode.hasFn ( MFn::kJointCluster ) ||
213
!stack[i-1]->isSkin ||
214
!stack[i-1]->skinControllerNode.hasFn ( MFn::kJointCluster ) )
216
exportSkinController ( sceneElement, skinControllerNode, MDagPath::getAPathTo( meshNode ) );
217
alreadyHasSkin = true;
223
exportMorphController( sceneElement, item->morphControllerNodes );
228
//------------------------------------------------------
229
void ControllerExporter::exportMorphController(
230
SceneElement* sceneElement,
231
MObjectArray& controllerNodes )
233
// Count the blendShape nodes.
234
uint controllerNodeCount = controllerNodes.length();
235
if ( controllerNodeCount == 0 ) return;
237
// Get the maya controller name
238
String mayaControllerId = sceneElement->getNodeName() +
239
COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX;
241
MObject blendShapeNode = controllerNodes[0];
242
// String mayaControllerId = MFnDependencyNode( blendShapeNode ).name().asChar();
244
// Check if the controller isn't already exported
245
if ( !findColladaControllerId ( mayaControllerId ).empty () ) return;
247
// Generate a COLLADA id for the new object
248
String colladaControllerId;
250
// Check if there is an extra attribute "colladaId" and use this as export id.
251
MString attributeValue;
252
DagHelper::getPlugValue ( blendShapeNode, COLLADA_ID_ATTRIBUTE_NAME, attributeValue );
253
if ( attributeValue != EMPTY_CSTRING )
255
// Generate a valid collada name, if necessary.
256
colladaControllerId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false );
260
// colladaControllerId = mDocumentExporter->dagPathToColladaId ( sceneElement->getPath () ) +
261
// COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX;
262
colladaControllerId = sceneElement->getNodeName() +
263
COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX;
267
// Make the id unique and store it in a map.
268
colladaControllerId = mControllerIdList.addId ( colladaControllerId );
269
mMayaIdColladaIdMap [ mayaControllerId ] = colladaControllerId;
271
// Create a morph controller to hold the data
272
MorphController morphController( colladaControllerId, mayaControllerId );
274
MorphControllerTargets& blendTargets = morphController.getMorphControllerTargets();
275
std::vector<float>& blendWeights = morphController.getMorphControllerWeights();
276
std::vector<MPlug> weightPlugs;
278
// Retrieve the target informations of the blend shape
279
for (uint i = 0; i < controllerNodeCount; ++i)
281
MObject controllerNode = controllerNodes[i];
282
MFnDependencyNode controllerFn ( controllerNode );
284
MPlug inputTargetArrayPlug = controllerFn.findPlug( ATTR_INPUT_TARGET ); // "inputTarget"
285
if ( inputTargetArrayPlug.attribute().isNull() ) continue;
287
MPlug weightArrayPlug = controllerFn.findPlug( ATTR_WEIGHT ); // "weight"
290
uint inputTargetCount = inputTargetArrayPlug.numElements();
291
for (uint j = 0; j < inputTargetCount; ++j)
293
MPlug inputTargetPlug = inputTargetArrayPlug.elementByPhysicalIndex(j);
294
if ( inputTargetPlug.attribute().isNull() ) continue;
296
MPlug inputTargetGroupArrayPlug = DagHelper::getChildPlug( inputTargetPlug, ATTR_INPUT_TARGET_GROUP ); // "inputTargetGroup"
297
if ( inputTargetGroupArrayPlug.attribute().isNull() ) continue;
299
uint inputTargetGroupCount = inputTargetGroupArrayPlug.numElements();
300
for (uint k = 0; k < inputTargetGroupCount; ++k)
302
MPlug inputTargetGroupPlug = inputTargetGroupArrayPlug.elementByPhysicalIndex( k );
303
if (inputTargetGroupPlug.attribute().isNull()) continue;
305
MPlug inputTargetInputArrayPlug = DagHelper::getChildPlug( inputTargetGroupPlug, ATTR_INPUT_TARGET_INPUT ); // "inputTargetInput"
306
if ( inputTargetInputArrayPlug.attribute().isNull() ) continue;
308
uint inputTargetInputCount = inputTargetInputArrayPlug.numElements();
309
for (uint m = 0; m < inputTargetInputCount; ++m)
311
MPlug inputTargetInput = inputTargetInputArrayPlug.elementByPhysicalIndex(m);
312
if (inputTargetInput.attribute().isNull()) continue;
314
MPlug inputTargetGeometryPlug = DagHelper::getChildPlug( inputTargetInput, ATTR_INPUT_GEOM_TARGET ); // "inputGeomTarget"
315
if (inputTargetGeometryPlug.attribute().isNull()) continue;
317
// We now have a valid Maya blend shape target.
318
uint currentIndex = nextIndex++;
319
String blendShapeTargetId;
320
bool isInstanced = DagHelper::hasConnection( inputTargetGeometryPlug, false, true );
323
// Find the first attached mesh DAG node.
324
MItDependencyGraph itDG(
325
inputTargetGeometryPlug,
327
MItDependencyGraph::kUpstream,
328
MItDependencyGraph::kDepthFirst,
329
MItDependencyGraph::kNodeLevel);
330
MObject targetObj = itDG.thisNode();
331
if (targetObj.isNull()) continue;
333
// This mesh is our morph target.
334
MDagPath targetPath = MDagPath::getAPathTo ( targetObj );
335
SceneGraph* sceneGraph = mDocumentExporter->getSceneGraph();
336
if ( sceneGraph->findExportedElement( targetPath ) == NULL )
338
SceneElement* targetSceneElement = sceneGraph->findElement( targetPath );
339
// We have to export the geometry
340
targetSceneElement->setIsForced ( true );
341
if ( !targetSceneElement->getNodeId().empty() )
342
blendShapeTargetId = targetSceneElement->getNodeId();
343
else blendShapeTargetId = targetSceneElement->getNodeName();
348
// TODO What the hell is this?
349
MPlug targetVertexListPlug = DagHelper::getChildPlug( inputTargetInput, ATTR_INPUT_POINTS_TARGET ); // "inputPointsTarget"
350
if (inputTargetInput.attribute().isNull()) continue;
352
MPlug targetComponentListPlug = DagHelper::getChildPlug( inputTargetInput, ATTR_INPUT_COMPONENT_TARGET ); // "inputComponentTarget"
353
if (inputTargetInput.attribute().isNull()) continue;
355
std::cerr << "'exportMorphTarget' not implemented!" << std::endl;
357
// We have a dangling geometry: create a FCDGeometry and fill it with the vertex positions.
358
// blendShapeTargetId = exportMorphTarget(targetVertexListPlug, targetComponentListPlug, currentIndex, baseMesh);
361
if ( !blendShapeTargetId.empty() )
363
MPlug weightPlug = weightArrayPlug.elementByLogicalIndex ( currentIndex );
364
if (weightPlug.attribute().isNull()) continue;
366
blendTargets.push_back( blendShapeTargetId );
367
weightPlugs.push_back( weightPlug );
374
size_t targetCount = blendTargets.size();
375
if (targetCount == 0) return ;
377
// Set the weights and export the morph target weight animations
378
for ( size_t j=0; j<targetCount; ++j )
380
MPlug& weightPlug = weightPlugs[j];
381
MPlug enveloppePlug = MFnDependencyNode( weightPlug.node() ).findPlug( ATTR_ENVELOPE );
382
float envelope=1.0f, weight;
383
if ( !enveloppePlug.attribute().isNull() )
384
enveloppePlug.getValue ( envelope );
385
weightPlug.getValue( weight );
386
blendWeights.push_back( envelope * weight );
388
String subId = colladaControllerId + MORPH_WEIGHTS_SOURCE_ID_SUFFIX;
389
AnimationExporter* animExport = mDocumentExporter->getAnimationExporter();
390
animExport->addPlugAnimation( weightPlug, subId, kSingle, XY_PARAMETERS, false, ( int ) j );
393
// Write the controller data into the COLLADA document
394
writeMorphController ( sceneElement->getNodeName(), morphController );
397
//------------------------------------------------------
398
void ControllerExporter::exportMorphTarget(
399
MPlug& targetVertexListPlug,
400
MPlug& targetComponentListPlug,
405
// Retrieve the data objects for the vertex list.
406
MObject pointArrayData, componentListData;
407
CHECK_STAT ( targetVertexListPlug.getValue ( pointArrayData ) );
408
if ( pointArrayData.isNull() ) return ;
410
CHECK_STAT ( targetComponentListPlug.getValue ( componentListData ) );
411
if ( componentListData.isNull() ) return ;
413
MFnPointArrayData vlistFn ( pointArrayData, &status ); CHECK_STAT ( status );
414
uint relativePointCount = vlistFn.length(&status); CHECK_STAT ( status );
415
if ( relativePointCount == 0 ) return ;
417
MFnComponentListData componentListFn ( componentListData, &status ); CHECK_STAT ( status );
418
uint componentCount = componentListFn.length ( &status ); CHECK_STAT ( status );
419
if ( componentCount == 0 ) return ;
422
//------------------------------------------------------
423
void ControllerExporter::exportSkinController(
424
SceneElement* sceneElement,
425
const MObject controllerNode,
426
MDagPath outputShape )
428
// Get the current path.
429
MDagPath targetDagPath = sceneElement->getPath();
431
// Figure out which type of skin controller we currently have: mesh-centric or joint-centric
432
bool isJointCluster = controllerNode.hasFn(MFn::kJointCluster);
433
bool isSkinCluster = controllerNode.hasFn(MFn::kSkinClusterFilter);
434
if (!isJointCluster && !isSkinCluster) return;
436
// Retrieve the instance information for this skinned character
437
MFnGeometryFilter clusterFn(controllerNode);
438
uint clusterIndex = retrieveInstanceInformation ( clusterFn, outputShape );
440
// Create the controller name
441
// MString mayaControllerName = ( isSkinCluster ) ? clusterFn.name() : outputShape.partialPathName();
442
// String mayaControllerId = mayaControllerName.asChar();
443
bool morphController = hasMorphController( targetDagPath.node() );
444
String controllerIdSuffix;
445
if ( morphController )
446
controllerIdSuffix = COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX +
447
COLLADASW::LibraryControllers::SKIN_CONTROLLER_ID_SUFFIX;
448
else controllerIdSuffix = COLLADASW::LibraryControllers::SKIN_CONTROLLER_ID_SUFFIX;
449
String mayaControllerId = sceneElement->getNodeName() + controllerIdSuffix;
451
// Generate a COLLADA id for the new object
452
String colladaControllerId;
454
// Check if there is an extra attribute "colladaId" and use this as export id.
455
MString attributeValue;
456
DagHelper::getPlugValue ( controllerNode, COLLADA_ID_ATTRIBUTE_NAME, attributeValue );
457
if ( attributeValue != EMPTY_CSTRING )
459
// Generate a valid collada name, if necessary.
460
colladaControllerId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false );
464
//colladaControllerId = mDocumentExporter->dagPathToColladaId ( sceneElement->getPath () ) + controllerIdSuffix;
465
colladaControllerId = sceneElement->getNodeName() + controllerIdSuffix;
468
// Make the id unique and store it in a map.
469
colladaControllerId = mControllerIdList.addId ( colladaControllerId );
470
mMayaIdColladaIdMap [ mayaControllerId ] = colladaControllerId;
472
// TODO Get the unique skin target id.
473
// If the output shape has a morph controller, the target
474
// is not the shape's geometry, but the morph controller.
475
MObject outputNode = outputShape.node ();
476
MFnDependencyNode fn ( outputNode );
478
String skinTarget = DocumentExporter::mayaNameToColladaName ( fn.name() );
479
if ( hasMorphController ( outputShape.node() ) )
481
// TODO Get the original collada id from the blend shape.
482
skinTarget += COLLADASW::LibraryControllers::MORPH_CONTROLLER_ID_SUFFIX;
486
// Attach a function set to the mesh node.
487
// We access all of the meshes data through the function set
489
MFnMesh fnMesh ( outputNode, &status );
490
if ( status != MStatus::kSuccess ) return;
492
// Get the scene element by the dag path.
493
MDagPath meshDagPath = fnMesh.dagPath ();
495
// TODO Get the skin controller connected geometry to get the skin target.
498
// TODO Get the original collada id from the geometry.
499
GeometryExporter* geometryExporter = mDocumentExporter->getGeometryExporter ();
500
skinTarget = geometryExporter->generateColladaMeshId ( outputShape );
503
// Create an skin controller to hold the data
504
SkinController skinController ( colladaControllerId, mayaControllerId );
506
// Get the transform matrix for the shape.
507
getBindShapeTransform ( &skinController, clusterFn, isJointCluster, clusterIndex, sceneElement );
509
// The weight filters to fill in.
510
MObjectArray weightFilters;
512
// Gather the list of joints and write them as the influences in the target controller object.
513
gatherJoints ( &skinController, controllerNode, weightFilters, clusterIndex );
515
// Set the joint entry into the other scene element, which use this joints.
516
MDagPathArray influences = skinController.getInfluences();
517
unsigned int numInfluences = influences.length();
518
for ( unsigned int i=0; i<numInfluences; ++i )
520
// Get the scene element.
521
MDagPath skeletonPath = influences [i];
522
SceneElement* sceneElement = mDocumentExporter->getSceneGraph ()->findElement ( skeletonPath );
524
// Get the collada id.
525
VisualSceneExporter* visualSceneExporter = mDocumentExporter->getVisualSceneExporter ();
526
String colladaNodeId = visualSceneExporter->getColladaNodeId ( skeletonPath );
528
// Get the uri of the current scene
529
COLLADASW::URI skeletonUri ( visualSceneExporter->getSceneElementURI ( sceneElement, colladaNodeId ) );
530
sceneElement->addSkeletonURI ( skeletonUri );
532
// Set the id on the other instanced nodes.
533
bool isInstanced = targetDagPath.isInstanced ();
534
uint instanceNumber = targetDagPath.instanceNumber ();
535
MDagPathArray pathes;
536
MDagPath::getAllPathsTo( targetDagPath.node(), pathes );
537
for (uint i=0; i<pathes.length(); ++i)
539
SceneElement* foundElement = mDocumentExporter->getSceneGraph()->findElement ( pathes[i] );
540
if ( foundElement != NULL )
541
foundElement->addSkeletonURI ( skeletonUri );
545
// Gather the bind matrices and write them as the bind poses in the target controller object.
546
gatherBindMatrices ( &skinController, controllerNode );
548
// Collect the vertex weights into the collada skin controller.
549
collectVertexWeights ( &skinController, controllerNode, outputShape, weightFilters, clusterIndex, numInfluences );
552
createJoints ( &skinController );
554
// Write the data into the collada document.
555
writeSkinController ( skinTarget, skinController );
559
//------------------------------------------------------
560
void ControllerExporter::collectVertexWeights (
561
SkinController* skinController,
562
const MObject &controllerNode,
563
const MDagPath &outputShape,
564
const MObjectArray &weightFilters,
565
const uint clusterIndex,
568
// Attach a function set to the output shape.
569
MFnMesh meshFn( outputShape );
571
// Collect all the weights
572
uint numVertices = meshFn.numVertices();
573
SkinControllerVertices& colladaInfluences = skinController->getVertexInfluences();
574
colladaInfluences.resize(numVertices);
576
if (controllerNode.apiType() == MFn::kSkinClusterFilter)
578
collectSkinClusterFilterVertexWeights(
579
colladaInfluences, controllerNode, outputShape, numInfluences);
581
else if (controllerNode.apiType() == MFn::kJointCluster)
583
collectJointClusterVertexWeights(
584
colladaInfluences, weightFilters, outputShape, clusterIndex );
588
//------------------------------------------------------
589
void ControllerExporter::collectSkinClusterFilterVertexWeights (
590
SkinControllerVertices& colladaInfluences,
591
const MObject& controllerNode,
592
const MDagPath& outputShape,
595
MFnSkinCluster skinClusterFn(controllerNode);
596
for (MItGeometry componentIt(outputShape); !componentIt.isDone(); componentIt.next())
598
int index = componentIt.index();
599
SkinControllerVertex& vertex = colladaInfluences[index];
602
MObject component = componentIt.component();
603
if (skinClusterFn.getWeights(outputShape, component, weights, numInfluences) != MS::kSuccess)
608
uint weightCount = weights.length();
609
for (uint i = 0; i < weightCount; ++i)
611
Weight weight = weights[i];
612
if (!COLLADABU::Math::Utils::equals(weight, Weight(0), getTolerance ()))
614
vertex[i] = (float)weight;
620
//------------------------------------------------------
621
void ControllerExporter::collectJointClusterVertexWeights (
622
SkinControllerVertices& colladaInfluences,
623
const MObjectArray &weightFilters,
624
const MDagPath &outputShape,
625
const uint clusterIndex )
627
// Get the weight for each of the clusters
628
uint weightFilterCount = weightFilters.length();
629
for (uint i = 0; i < weightFilterCount; ++i)
631
MFnWeightGeometryFilter filterFn(weightFilters[i]);
632
MObject deformSet = filterFn.deformerSet();
633
MFnSet setFn(deformSet);
635
// Get all the components affected by this joint cluster
636
MSelectionList clusterSetList;
637
setFn.getMembers(clusterSetList, true);
641
uint setListCount = clusterSetList.length();
642
for (uint s = 0; s < setListCount; ++s)
644
clusterSetList.getDagPath(s, shapePath, components);
645
if (shapePath.node() == outputShape.node()) break;
649
filterFn.getWeights(clusterIndex, components, weights);
652
for ( MItGeometry componentIt(shapePath, components);
653
!componentIt.isDone() && counter < weights.length();
656
// append the weight at its correct position: i
657
float weight = weights[counter++];
658
if ( COLLADABU::Math::Utils::equalsZero ( weight, getTolerance () ) )
660
SkinControllerVertex& vertex = colladaInfluences[componentIt.index()];
667
//------------------------------------------------------
668
void ControllerExporter::gatherJoints (
669
SkinController* skinController,
670
const MObject &controllerNode,
671
MObjectArray &weightFilters,
672
const uint clusterIndex )
674
// Gather the list of joints
675
MDagPathArray& influences = skinController->getInfluences();
676
if (controllerNode.apiType() == MFn::kSkinClusterFilter)
679
MFnSkinCluster skinClusterFn( controllerNode );
680
skinClusterFn.influenceObjects(influences, &status);
682
else if (controllerNode.apiType() == MFn::kJointCluster)
684
// Support for joint clusters pipeline
685
getJointClusterInfluences(controllerNode, influences, weightFilters, clusterIndex);
689
//------------------------------------------------------
690
void ControllerExporter::gatherBindMatrices(
691
SkinController* skinController,
692
const MObject& controllerNode )
694
// The list of joints
695
MDagPathArray& influences = skinController->getInfluences();
697
// Request a change in capacity
698
uint numInfluences = influences.length();
699
std::vector<MMatrix>& bindPoses = skinController->getBindPoses();
700
bindPoses.reserve(numInfluences);
702
// Gather the bind matrices
703
for (uint i = 0; i < numInfluences; ++i)
705
MObject influence = influences[i].node();
706
MMatrix mayaBindPoseMatrix = DagHelper::getBindPoseInverse(controllerNode, influence);
707
bindPoses.push_back( mayaBindPoseMatrix );
711
//------------------------------------------------------
712
void ControllerExporter::createJoints(
713
SkinController* skinController )
715
// Gather the list of joints
716
const MDagPathArray& influences = skinController->getInfluences();
718
// Create the joints with their ids.
719
SkinControllerJoints& joints = skinController->getJoints();
720
uint numInfluences = influences.length();
721
joints.resize( numInfluences );
723
for (uint i=0; i<numInfluences; ++i)
725
MDagPath dagPath = influences[i];
727
SkinControllerJoint &joint = joints[i];
728
joint.first = mDocumentExporter->dagPathToColladaId ( dagPath );
729
joint.second = skinController->getBindPoses()[i];
733
//------------------------------------------------------
734
void ControllerExporter::getJointClusterInfluences(
735
const MObject &controllerNode,
736
MDagPathArray &influences,
737
MObjectArray &weightFilters,
738
const uint clusterIndex )
740
MObject cluster( controllerNode );
741
while ( cluster.apiType() == MFn::kJointCluster )
743
weightFilters.append(cluster);
745
MObject joint = DagHelper::getNodeConnectedTo( cluster, ATTR_MATRIX );
746
MDagPath jointPath = MDagPath::getAPathTo( joint );
747
influences.append(jointPath);
750
MPlug plug = ShaderHelper::findPlug(MFnDependencyNode(cluster), ATTR_INPUt, &status);
751
if (status != MStatus::kSuccess)
752
{ MGlobal::displayError("Unable to get joint cluster input plug."); return; }
754
plug = plug.elementByLogicalIndex(clusterIndex, &status);
755
if (status != MStatus::kSuccess)
756
{ MGlobal::displayError("Unable to get joint cluster input plug first element."); return; }
758
plug = DagHelper::getChildPlug(plug, ATTR_INPUT_GEOMETRY, &status); // "inputGeometry"
759
if (status != MStatus::kSuccess)
760
{ MGlobal::displayError("Unable to get joint cluster input geometry plug."); return; }
762
cluster = DagHelper::getSourceNodeConnectedTo(plug);
766
//------------------------------------------------------
767
void ControllerExporter::getBindShapeTransform(
768
SkinController* skinController,
769
const MFnGeometryFilter &clusterFn,
770
const bool isJointCluster,
772
SceneElement* sceneElement )
774
// Add the bind-shape bind matrix
775
MMatrix mayaBindShapeMatrix;
776
MPlug bindShapeMatrixPlug = clusterFn.findPlug ( ATTR_GEOM_MATRIX );
778
if ( isJointCluster )
779
bindShapeMatrixPlug = bindShapeMatrixPlug.elementByLogicalIndex ( index );
781
DagHelper::getPlugValue ( bindShapeMatrixPlug, mayaBindShapeMatrix );
783
// Store the bindShapeMatrix of every element in a list.
784
// We need it again for the transformation of the skin controller elements.
785
sceneElement->setBindShapeMatrix ( mayaBindShapeMatrix );
787
// Set the bindShapeMatrix in the skin controller.
788
skinController->setBindShapeTransform ( mayaBindShapeMatrix );
791
//------------------------------------------------------
792
bool ControllerExporter::hasController ( const MObject& node )
794
return hasSkinController ( node ) || hasMorphController ( node );
797
//------------------------------------------------------
798
bool ControllerExporter::hasSkinController ( const MObject& node )
801
MPlug plug = MFnDependencyNode ( node ).findPlug ( ATTR_IN_MESH, &status );
803
if ( !status || !plug.isConnected() ) return false;
805
MItDependencyGraph dgIt ( plug,
807
MItDependencyGraph::kUpstream,
808
MItDependencyGraph::kBreadthFirst,
809
MItDependencyGraph::kNodeLevel,
811
if ( status != MS::kSuccess ) return false;
813
dgIt.disablePruningOnFilter();
815
while ( !dgIt.isDone() )
817
MObject thisNode = dgIt.thisNode();
818
if ( thisNode.hasFn ( MFn::kSkinClusterFilter ) || thisNode.hasFn ( MFn::kJointCluster ) )
829
//------------------------------------------------------
830
bool ControllerExporter::hasMorphController ( const MObject& node )
832
MPlug plug = MFnDependencyNode ( node ).findPlug ( ATTR_IN_MESH );
833
if ( plug.isConnected() )
835
MItDependencyGraph dgIt ( plug,
837
MItDependencyGraph::kUpstream,
838
MItDependencyGraph::kDepthFirst,
839
MItDependencyGraph::kPlugLevel );
840
dgIt.disablePruningOnFilter();
842
for ( ; ! dgIt.isDone(); dgIt.next() )
844
MObject thisNode = dgIt.thisNode();
845
if ( thisNode.hasFn ( MFn::kBlendShape ) ) return true;
852
//------------------------------------------------------
853
void ControllerExporter::disableBlendShape ( ControllerStack &stack )
855
// Disable the blend shape
856
for ( size_t i=0; i<stack.size(); ++i )
858
ControllerStackItem* item = stack[i];
860
// Disable the blend shape node
861
if ( item->skinControllerNode.hasFn ( MFn::kBlendShape ) )
863
// Attach the function set
864
MFnBlendShapeDeformer fn ( item->skinControllerNode );
866
// get the envelope attribute plug
867
MPlug plug = fn.findPlug ( ATTR_ENVELOPE );
871
MStatus status = plug.getValue ( envelope );
872
if ( status != MStatus::kSuccess ) return ;
873
item->envelope = envelope;
875
// set to 0 to disable FFD effect
876
plug.setValue (0.0f) ;
881
//------------------------------------------------------
882
void ControllerExporter::enableBlendShape ( ControllerStack &stack )
884
// Enable the blend shape
885
for ( size_t i=0; i<stack.size(); ++i )
887
ControllerStackItem* item = stack[i];
889
// Disable the blend shape node
890
if ( item->skinControllerNode.hasFn ( MFn::kBlendShape ) )
892
// Attach the function set
893
MFnBlendShapeDeformer fn ( item->skinControllerNode );
895
// get the envelope attribute plug
896
MPlug plug = fn.findPlug ( ATTR_ENVELOPE );
898
// set to 0 to disable FFD effect
899
plug.setValue ( item->envelope );
904
//------------------------------------------------------
905
uint ControllerExporter::retrieveInstanceInformation(
906
const MFnGeometryFilter &clusterFn,
907
MDagPath &outputShape )
911
// Attach a function set to the controller node.
912
MFnMesh fnMesh ( outputShape, &status );
915
uint idx = clusterFn.indexForOutputShape(outputShape.node());
918
// Alternate method for retrieving the index?
919
MPlug meshConnection = fnMesh.findPlug( ATTR_IN_MESH );
920
MItDependencyGraph dgIt(
923
MItDependencyGraph::kUpstream,
924
MItDependencyGraph::kBreadthFirst,
925
MItDependencyGraph::kNodeLevel,
927
CHECK_STATUS_AND_RETURN(status, NULL);
928
dgIt.disablePruningOnFilter();
930
for (; ! dgIt.isDone(); dgIt.next())
932
MObject thisNode = dgIt.thisNode();
933
idx = clusterFn.indexForOutputShape(thisNode);
936
outputShape = MDagPath::getAPathTo(thisNode);
944
//------------------------------------------------------
945
void ControllerExporter::writeSkinJointSource( const SkinController &skinController )
947
COLLADASW::NameSource jointSource( mDocumentExporter->getStreamWriter() );
948
String controllerId = skinController.getControllerId();
949
jointSource.setId ( controllerId + JOINTS_SOURCE_ID_SUFFIX );
950
jointSource.setNodeName ( controllerId + JOINTS_SOURCE_ID_SUFFIX );
951
jointSource.setArrayId ( controllerId + JOINTS_SOURCE_ID_SUFFIX + ARRAY_ID_SUFFIX );
952
jointSource.setAccessorStride ( 1 );
954
// Retrieves the vertex positions.
955
const MDagPathArray& influences = skinController.getInfluences();
956
uint numInfluences = influences.length();
957
jointSource.setAccessorCount ( numInfluences );
959
jointSource.getParameterNameList().push_back ( PARAM_TYPE_JOINT );
960
jointSource.prepareToAppendValues();
962
const SkinControllerJoints& joints = skinController.getJoints();
963
SkinControllerJoints::const_iterator it = joints.begin();
964
for (; it<joints.end(); ++it)
966
String boneId = (*it).first;
967
jointSource.appendValues ( boneId );
969
jointSource.finish();
972
//------------------------------------------------------
973
void ControllerExporter::writeMorphTargetSource( const MorphController &morphController )
975
COLLADASW::IdRefSource targetSource( mDocumentExporter->getStreamWriter() );
976
String controllerId = morphController.getControllerId();
977
targetSource.setId ( controllerId + TARGETS_SOURCE_ID_SUFFIX );
978
targetSource.setNodeName ( controllerId + TARGETS_SOURCE_ID_SUFFIX );
979
targetSource.setArrayId ( controllerId + TARGETS_SOURCE_ID_SUFFIX + ARRAY_ID_SUFFIX );
980
targetSource.setAccessorStride ( 1 );
982
// Retrieve the morph controller targets.
983
const MorphControllerTargets& morphControllerTargets = morphController.getMorphControllerTargets();
984
size_t numTargets = morphControllerTargets.size();
985
targetSource.setAccessorCount ( ( unsigned long ) numTargets );
986
targetSource.getParameterNameList().push_back ( PARAM_TYPE_MORPH_TARGET );
987
targetSource.prepareToAppendValues();
988
targetSource.appendValues ( morphControllerTargets );
989
targetSource.finish();
992
//------------------------------------------------------
993
void ControllerExporter::writeSkinBindPosesSource( const SkinController &skinController )
995
COLLADASW::Float4x4Source bindPosesSource( mDocumentExporter->getStreamWriter() );
996
String controllerId = skinController.getControllerId();
997
bindPosesSource.setId ( controllerId + BIND_POSES_SOURCE_ID_SUFFIX );
998
bindPosesSource.setNodeName ( controllerId + BIND_POSES_SOURCE_ID_SUFFIX );
999
bindPosesSource.setArrayId ( controllerId + BIND_POSES_SOURCE_ID_SUFFIX + ARRAY_ID_SUFFIX );
1000
bindPosesSource.setAccessorStride ( 16 );
1002
// Retrieves the vertex positions.
1003
const MDagPathArray& influences = skinController.getInfluences();
1004
uint numInfluences = influences.length();
1005
bindPosesSource.setAccessorCount ( numInfluences );
1007
bindPosesSource.getParameterNameList().push_back ( PARAM_TYPE_TRANSFORM );
1008
bindPosesSource.prepareToAppendValues();
1010
const std::vector<MMatrix>& bindPosesVec = skinController.getBindPoses();
1011
size_t numBindPoses = bindPosesVec.size();
1012
for (size_t i=0; i<bindPosesVec.size(); ++i)
1014
MMatrix mayaBindPoses = bindPosesVec[i];
1015
double bindPoses[4][4];
1016
convertMayaMatrixToTransposedDouble4x4 ( bindPoses, mayaBindPoses, getTolerance () );
1018
// Convert the maya internal unit type of the transform part of the
1019
// matrix from centimeters into the working units of the current scene!
1020
for ( uint i=0; i<3; ++i)
1021
bindPoses [i][3] = MDistance::internalToUI ( bindPoses [i][3] );
1023
bindPosesSource.appendValues ( bindPoses );
1025
bindPosesSource.finish();
1028
//------------------------------------------------------
1029
void ControllerExporter::writeSkinWeightSource( const SkinController &skinController )
1031
String controllerId = skinController.getControllerId();
1032
COLLADASW::FloatSourceF weightSource( mDocumentExporter->getStreamWriter() );
1033
weightSource.setId ( controllerId + WEIGHTS_SOURCE_ID_SUFFIX );
1034
weightSource.setNodeName ( controllerId + WEIGHTS_SOURCE_ID_SUFFIX );
1035
weightSource.setArrayId ( controllerId + WEIGHTS_SOURCE_ID_SUFFIX + ARRAY_ID_SUFFIX );
1036
weightSource.setAccessorStride ( 1 );
1038
// Create the vertex list
1039
std::vector<float> vertexVec;
1041
// Push a single one weight in front of the list. The vertex_weights array
1042
// can always reference to it, if we have a one weight.
1043
vertexVec.push_back(1.0f);
1044
uint numVertexPoints = 1;
1046
const SkinControllerVertices& vertexes = skinController.getVertexInfluences();
1047
for (uint i=0; i<vertexes.size(); ++i)
1049
SkinControllerVertex vertex = vertexes[i];
1050
for (uint j=0; j<vertex.size(); ++j)
1052
// We don't need to write the zero weight, cause then there is no
1053
// influence. We don't write the one weights, cause we have written
1054
// (see below) a one weight in front of the vertex_weights array and
1055
// always reference to it from the vertex_weights array.
1056
if ( !COLLADABU::Math::Utils::equalsZero ( vertex[j], getTolerance () ) &&
1057
!COLLADABU::Math::Utils::equals ( vertex[j], 1.0f, (float)getTolerance () ) )
1059
vertexVec.push_back ( vertex[j] );
1064
weightSource.setAccessorCount ( numVertexPoints );
1066
weightSource.getParameterNameList().push_back ( PARAM_TYPE_WEIGHT );
1067
weightSource.prepareToAppendValues();
1068
weightSource.appendValues ( vertexVec );
1069
weightSource.finish();
1072
//------------------------------------------------------
1073
void ControllerExporter::writeMorphWeightSource( const MorphController &morphController )
1075
String controllerId = morphController.getControllerId();
1076
COLLADASW::FloatSourceF weightSource( mDocumentExporter->getStreamWriter() );
1077
weightSource.setId ( controllerId + MORPH_WEIGHTS_SOURCE_ID_SUFFIX );
1078
weightSource.setNodeName ( controllerId + MORPH_WEIGHTS_SOURCE_ID_SUFFIX );
1079
weightSource.setArrayId ( controllerId + MORPH_WEIGHTS_SOURCE_ID_SUFFIX + ARRAY_ID_SUFFIX );
1080
weightSource.setAccessorStride ( 1 );
1082
// Get the morph weights
1083
const std::vector<float> morphWeights = morphController.getMorphControllerWeights ();
1084
weightSource.setAccessorCount ( ( unsigned long ) morphWeights.size() );
1085
weightSource.getParameterNameList().push_back ( PARAM_TYPE_MORPH_WEIGHT );
1086
weightSource.prepareToAppendValues();
1087
weightSource.appendValues ( morphWeights );
1088
weightSource.finish();
1091
//------------------------------------------------------
1092
void ControllerExporter::writeSkinBindShapeTransform ( const SkinController &skinController )
1094
// Write the bind shape transform matrix in the collada document.
1095
const MMatrix& mayaBindShapeMatrix = skinController.getBindShapeTransform();
1096
double bindShapeMatrix[4][4] ;
1097
convertMayaMatrixToTransposedDouble4x4 ( bindShapeMatrix, mayaBindShapeMatrix, getTolerance () );
1099
// Convert the maya internal unit type of the transform part of the
1100
// matrix from centimeters into the working units of the current scene!
1101
for ( uint i=0; i<3; ++i)
1102
bindShapeMatrix [i][3] = MDistance::internalToUI ( bindShapeMatrix [i][3] );
1104
addBindShapeTransform ( bindShapeMatrix );
1107
//------------------------------------------------------
1108
void ControllerExporter::writeSkinController(
1109
const String skinTarget,
1110
const SkinController &skinController )
1112
// Get the unique id and the name of the current controller.
1113
String controllerId = skinController.getControllerId();
1114
String controllerName = skinController.getControllerName();
1116
// Opens the skin tag in the collada document.
1117
openSkin ( controllerId , controllerName, COLLADASW::URI ( EMPTY_STRING, skinTarget ) );
1119
writeSkinBindShapeTransform( skinController );
1120
writeSkinJointSource( skinController );
1121
writeSkinBindPosesSource( skinController );
1122
writeSkinWeightSource( skinController );
1123
writeSkinElementJoints( skinController );
1124
writeSkinElementVertexWeights( skinController );
1126
// Export the original maya name.
1127
COLLADASW::Extra extraSource ( mSW );
1128
extraSource.openExtra();
1129
COLLADASW::Technique techniqueSource ( mSW );
1130
techniqueSource.openTechnique ( PROFILE_MAYA );
1131
techniqueSource.addParameter ( PARAMETER_MAYA_ID, controllerName );
1132
techniqueSource.closeTechnique();
1133
extraSource.closeExtra();
1135
// Close the opened skin tag.
1138
// Close the opened controller tag.
1142
//------------------------------------------------------
1143
void ControllerExporter::writeMorphController (
1144
const String morphTarget,
1145
const MorphController &morphController )
1147
// Get the unique id and the name of the current controller.
1148
String controllerId = morphController.getControllerId();
1149
String controllerName = morphController.getControllerName();
1151
// Opens the skin tag in the collada document.
1152
openMorph ( controllerId , controllerName, COLLADASW::URI ( EMPTY_STRING, morphTarget ) );
1154
writeMorphTargetSource( morphController );
1155
writeMorphWeightSource ( morphController );
1156
writeMorphElementTargets ( morphController );
1158
// Export the original maya name.
1159
COLLADASW::Extra extraSource ( mSW );
1160
extraSource.openExtra();
1161
COLLADASW::Technique techniqueSource ( mSW );
1162
techniqueSource.openTechnique ( PROFILE_MAYA );
1163
techniqueSource.addParameter ( PARAMETER_MAYA_ID, controllerName );
1164
techniqueSource.closeTechnique();
1165
extraSource.closeExtra();
1167
// Close the opened morph tag.
1170
// Close the opened controller tag.
1175
//------------------------------------------------------
1176
void ControllerExporter::writeSkinElementVertexWeights( const SkinController &skinController )
1178
String controllerId = skinController.getControllerId();
1179
String jointSourceId = controllerId + JOINTS_SOURCE_ID_SUFFIX;
1180
String weightSourceId = controllerId + WEIGHTS_SOURCE_ID_SUFFIX;
1183
COLLADASW::VertexWeightsElement vertexWeightsElement( mDocumentExporter->getStreamWriter() );
1184
COLLADASW::InputList &inputList = vertexWeightsElement.getInputList();
1185
inputList.push_back ( COLLADASW::Input ( COLLADASW::InputSemantic::JOINT, COLLADASW::URI (EMPTY_STRING, jointSourceId ), offset++ ) ); inputList.push_back ( COLLADASW::Input ( COLLADASW::InputSemantic::WEIGHT, COLLADASW::URI (EMPTY_STRING, weightSourceId ), offset++ ) );
1186
// The list for the vertex values.
1187
std::vector<unsigned long> vertexMatches;
1190
const SkinControllerVertices& vertexes = skinController.getVertexInfluences();
1192
// Counter for the influence counts
1193
size_t influenceCount = vertexes.size();
1194
vertexWeightsElement.setCount( ( unsigned long ) influenceCount );
1196
// Generate the vertex count and match value strings and export the <v> and <vcount> elements
1197
uint weightOffset = 1;
1198
for (size_t j=0; j<influenceCount; ++j)
1200
SkinControllerVertex vertex = vertexes[j];
1201
vertexWeightsElement.getVCountList().push_back( ( unsigned long ) vertex.size() );
1203
std::map<int, float>::const_iterator it = vertex.begin();
1204
for (; it!=vertex.end(); ++it)
1206
vertexMatches.push_back( (*it).first );
1208
if ( !COLLADABU::Math::Utils::equals( (*it).second, 1.0f, (float)getTolerance () ) )
1209
vertexMatches.push_back( weightOffset++ );
1211
// There is a one in the first position of the weight source array.
1212
// We will always reference to this element, if the weight is a one.
1213
vertexMatches.push_back ( 0 );
1216
// TODO In FCollada, the last element was erased?!?
1217
// if (!vertexMatches.empty()) vertexMatches.pop_back();
1219
vertexWeightsElement.prepareToAppendValues();
1220
vertexWeightsElement.appendValues( vertexMatches );
1221
vertexWeightsElement.finish();
1224
//------------------------------------------------------
1225
void ControllerExporter::writeSkinElementJoints( const SkinController &skinController )
1227
String controllerId = skinController.getControllerId();
1228
String jointSourceId = controllerId + JOINTS_SOURCE_ID_SUFFIX;
1229
String jointBindSourceId = controllerId + BIND_POSES_SOURCE_ID_SUFFIX;
1231
COLLADASW::JointsElement jointsElement( mDocumentExporter->getStreamWriter() );
1232
COLLADASW::InputList &jointsInputList = jointsElement.getInputList();
1233
jointsInputList.push_back ( COLLADASW::Input ( COLLADASW::InputSemantic::JOINT, COLLADASW::URI ( EMPTY_STRING, jointSourceId ) ) );
1234
jointsInputList.push_back ( COLLADASW::Input ( COLLADASW::InputSemantic::BINDMATRIX, COLLADASW::URI ( EMPTY_STRING, jointBindSourceId ) ) );
1235
jointsElement.add();
1238
//------------------------------------------------------
1239
void ControllerExporter::writeMorphElementTargets( const MorphController &morphController )
1241
String controllerId = morphController.getControllerId();
1242
String targetSourceId = controllerId + TARGETS_SOURCE_ID_SUFFIX;
1243
String morphWeightsSourceId = controllerId + MORPH_WEIGHTS_SOURCE_ID_SUFFIX;
1245
COLLADASW::TargetsElement targetsElement( mDocumentExporter->getStreamWriter() );
1246
COLLADASW::InputList &targetsInputList = targetsElement.getInputList();
1247
targetsInputList.push_back ( COLLADASW::Input ( COLLADASW::InputSemantic::MORPH_TARGET, COLLADASW::URI ( EMPTY_STRING, targetSourceId ) ) );
1248
targetsInputList.push_back ( COLLADASW::Input ( COLLADASW::InputSemantic::MORPH_WEIGHT, COLLADASW::URI ( EMPTY_STRING, morphWeightsSourceId ) ) );
1249
targetsElement.add();
1252
//------------------------------------------------------
1253
bool ControllerExporter::findAffectedNodes(
1254
const MObject& node,
1255
ControllerStack& stack,
1256
ControllerMeshStack& meshStack )
1258
MPlug plug = MFnDependencyNode ( node ).findPlug ( ATTR_IN_MESH );
1260
if ( plug.isConnected() )
1263
MItDependencyGraph dgIt ( plug,
1265
MItDependencyGraph::kUpstream,
1266
MItDependencyGraph::kBreadthFirst,
1267
MItDependencyGraph::kNodeLevel,
1269
if ( MS::kSuccess != status ) return false;
1271
dgIt.disablePruningOnFilter();
1272
for ( ; ! dgIt.isDone(); dgIt.next() )
1274
MObject thisNode = dgIt.thisNode();
1276
MFnDependencyNode fn( thisNode );
1277
String nodeName = fn.name().asChar();
1279
if ( thisNode.hasFn ( MFn::kSkinClusterFilter ) || thisNode.hasFn ( MFn::kJointCluster ) )
1281
// Append the skin controller node.
1282
ControllerStackItem* item = new ControllerStackItem();
1283
item->isSkin = true;
1284
item->skinControllerNode = thisNode;
1285
stack.push_back ( item );
1287
else if ( thisNode.hasFn ( MFn::kBlendShape ) )
1289
// Check for subsequent, multiple blend shape deformers.
1290
if ( stack.size() > 0 && !stack.back()->isSkin )
1292
stack.back()->morphControllerNodes.append ( thisNode );
1296
ControllerStackItem* item = new ControllerStackItem();
1297
item->isSkin = false;
1298
item->morphControllerNodes.append ( thisNode );
1299
stack.push_back ( item );
1302
else if ( thisNode.hasFn ( MFn::kMesh ) )
1304
// Queue up this mesh.
1305
ControllerMeshItem item;
1306
item.mesh = thisNode;
1307
meshStack.push_back ( item );
1317
//------------------------------------------------------
1318
void ControllerExporter::setControllerNodeStatesToNoEffect( ControllerStack &stack )
1320
// Set the controller node states
1321
for ( size_t i=0; i<stack.size(); ++i )
1323
ControllerStackItem* item = stack[i];
1325
// Disable the skin controller node
1329
DagHelper::getPlugValue ( item->skinControllerNode, ATTR_NODE_STATE, nodeState );
1330
DagHelper::setPlugValue ( item->skinControllerNode, ATTR_NODE_STATE, 1 ); // pass-through.
1331
item->nodeStates.push_back ( nodeState );
1334
// Disable the morph controllers
1335
for ( uint j=0; j<item->morphControllerNodes.length(); ++j )
1338
DagHelper::getPlugValue ( item->morphControllerNodes[j], ATTR_NODE_STATE, nodeState );
1339
DagHelper::setPlugValue ( item->morphControllerNodes[j], ATTR_NODE_STATE, 1 ); // pass-through.
1340
item->nodeStates.push_back( nodeState );
1345
//------------------------------------------------------
1346
void ControllerExporter::resetControllerNodeStates( ControllerStack &stack )
1348
// Reset all the controller node states
1349
for ( size_t i=0; i<stack.size(); ++i )
1351
ControllerStackItem* item = stack[i];
1354
// Reset the skin controller node state.
1355
size_t nodeStateSize = item->nodeStates.size();
1356
COLLADABU_ASSERT ( nodeStateSize >= 1 );
1357
int nodeState = item->nodeStates.front();
1358
DagHelper::setPlugValue ( item->skinControllerNode, ATTR_NODE_STATE, nodeState );
1360
// Maybe there are some morph controllers to reset.
1361
for ( uint i=0; i<item->morphControllerNodes.length(); ++i )
1363
COLLADABU_ASSERT ( nodeStateSize < i+1 );
1364
nodeState = item->nodeStates[i+1];
1365
DagHelper::setPlugValue ( item->morphControllerNodes[i], ATTR_NODE_STATE, nodeState );
1370
// Reset the morph controller node states.
1371
size_t nodeStateSize = item->nodeStates.size();
1372
for ( uint j=0; j<item->morphControllerNodes.length(); ++j )
1374
COLLADABU_ASSERT ( nodeStateSize >= j );
1375
int nodeState = item->nodeStates[j];
1376
DagHelper::setPlugValue ( item->morphControllerNodes[j], ATTR_NODE_STATE, nodeState );
1382
//------------------------------------------------------
1383
void ControllerExporter::setValidMeshParameters( ControllerMeshStack &meshStack )
1385
// Set valid mesh parameters (visible and not intermediate).
1386
for ( size_t i=0; i<meshStack.size(); ++i )
1388
ControllerMeshItem& item = meshStack[i];
1390
DagHelper::getPlugValue ( item.mesh, ATTR_INTERMEDIATE_OBJECT, item.isIntermediate );
1391
DagHelper::getPlugValue ( item.mesh, ATTR_VISIBILITY, item.isVisible );
1392
DagHelper::setPlugValue ( item.mesh, ATTR_INTERMEDIATE_OBJECT, false );
1393
DagHelper::setPlugValue ( item.mesh, ATTR_VISIBILITY, true );
1397
//------------------------------------------------------
1398
void ControllerExporter::resetMeshParameters( ControllerMeshStack &meshStack )
1400
// Reset all the intermediate and visibility mesh parameters.
1401
while ( !meshStack.empty() )
1403
ControllerMeshItem& item = meshStack.back();
1405
DagHelper::setPlugValue ( item.mesh, ATTR_INTERMEDIATE_OBJECT, item.isIntermediate );
1406
DagHelper::setPlugValue ( item.mesh, ATTR_VISIBILITY, item.isVisible );
1408
meshStack.pop_back();
1412
//------------------------------------------------------
1413
void ControllerExporter::deleteControllerStackItems( ControllerStack &stack )
1415
// Delete the controllerStack items
1416
for ( size_t i=0; i<stack.size(); ++i )
1418
ControllerStackItem* item = stack[i];
1425
//------------------------------------------------------
1426
bool ControllerExporter::findExportedContollerSceneElement ( const SceneElement* sceneElement )
1428
std::vector<SceneElement*>::const_iterator it = mExportedControllerSceneElements.begin ();
1429
while ( it != mExportedControllerSceneElements.end () )
1431
if ( *it == sceneElement )
1438
// ------------------------------------
1439
const String ControllerExporter::findColladaControllerId ( const String& mayaControllerId )
1441
const StringToStringMap::const_iterator it = mMayaIdColladaIdMap.find ( mayaControllerId );
1442
if ( it != mMayaIdColladaIdMap.end () )
1446
return EMPTY_STRING;