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 "COLLADAMayaExportOptions.h"
18
#include "COLLADAMayaAnimationSampleCache.h"
19
#include "COLLADAMayaAnimationHelper.h"
20
#include "COLLADAMayaDagHelper.h"
21
#include "COLLADAMayaSyntax.h"
23
#include <maya/MFnTransform.h>
24
#include <maya/MFnAnimCurve.h>
25
#include <maya/MPlugArray.h>
26
#include <maya/MFnIkHandle.h>
27
#include <maya/MFnMatrixData.h>
28
#include <maya/MGlobal.h>
29
#include <maya/MItDependencyGraph.h>
34
// --------------------------------------------
35
AnimationSampleCache::AnimationSampleCache() : mNodeSearch ( NULL ) {}
37
// --------------------------------------------
38
AnimationSampleCache::~AnimationSampleCache()
42
CacheNodeMap::iterator it = mNodes.begin();
43
for ( ; it!=mNodes.end(); ++it )
45
CacheNode* node = ( *it ).second;
52
// --------------------------------------------
53
void AnimationSampleCache::cacheTransformNode ( const MObject& node )
55
if ( node.hasFn ( MFn::kTransform ) )
57
MFnDagNode nodeFn ( node );
60
#define ADD_PLUG(name, mx) p = nodeFn.findPlug(name); cachePlug(p, mx);
61
ADD_PLUG ( ATTR_ROTATE, false );
62
ADD_PLUG ( ATTR_ROTATE_X, false );
63
ADD_PLUG ( ATTR_TRANSLATE, false );
64
ADD_PLUG ( ATTR_SCALE, false );
65
ADD_PLUG ( ATTR_MATRIX, true );
70
std::cerr << "Unsupported sampling type: " << node.apiTypeStr() << std::endl;
74
// --------------------------------------------
75
bool AnimationSampleCache::findCacheNode ( const MObject& node )
78
MFnDependencyNode fn ( node );
79
String nodeName = fn.name().asChar();
81
CacheNodeMap::iterator it = mNodes.find ( nodeName );
82
if ( it != mNodes.end() )
84
mNodeSearch = ( *it ).second;
92
// --------------------------------------------
93
bool AnimationSampleCache::findCachePlug ( const MPlug& plug,
94
std::vector<float>*& inputs,
95
std::vector<float>*& outputs )
100
if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
101
if ( mNodeSearch == NULL ) return false;
103
for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end(); ++it )
105
if ( ( *it ).plug == plug && ( *it ).plug.logicalIndex() == plug.logicalIndex() )
107
if ( ( *it ).isAnimated )
109
inputs = &AnimationHelper::mSamplingTimes;
110
outputs = & ( *it ).values;
120
// --------------------------------------------
121
bool AnimationSampleCache::findCachePlug ( const MPlug& plug, bool& isAnimated )
123
if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
124
if ( mNodeSearch == NULL ) return false;
126
for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end(); ++it )
128
if ( ( *it ).plug == plug && ( *it ).plug.logicalIndex() == plug.logicalIndex() )
130
isAnimated = ( *it ).isAnimated;
138
// --------------------------------------------
139
bool AnimationSampleCache::markPlugWanted ( const MPlug& plug )
141
if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
142
if ( mNodeSearch == NULL ) return false;
144
bool isSampling = false;
145
uint childCount = plug.numChildren();
146
std::vector<MPlug> marks ( 1 + childCount );
147
marks[childCount] = plug;
149
for ( uint i = 0; i < childCount; ++i ) marks[i] = plug.child ( i );
150
for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end(); ++it )
152
for ( uint i = 0; i < childCount + 1; ++i )
154
if ( ( *it ).plug == marks[i] && ( *it ).plug.logicalIndex() == marks[i].logicalIndex() )
156
isSampling = ( *it ).isWanted = true;
165
// --------------------------------------------
166
void AnimationSampleCache::cachePlug ( const MPlug& plug, bool isMatrix )
168
if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
169
if ( mNodeSearch == NULL )
171
mNodeSearch = new CacheNode ( plug.node() );
173
MFnDependencyNode fn ( plug.node() );
174
String nodeName = fn.name().asChar();
175
mNodes.insert ( std::pair<String, CacheNode*> ( nodeName, mNodeSearch ) );
178
std::vector<MPlug> marks;
179
uint childCount = plug.numChildren();
180
if ( childCount == 0 || isMatrix )
182
marks.push_back ( plug );
187
marks.resize ( childCount );
188
for ( uint i = 0; i < childCount; ++i ) marks[i] = plug.child ( i );
191
for ( uint i = 0; i < childCount; ++i )
196
for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end() && !found; ++it )
198
found = ( *it ).plug == p && ( *it ).plug.logicalIndex() == p.logicalIndex();
202
mNodeSearch->parts.push_back ( CacheNode::Part ( p ) );
203
mNodeSearch->parts.back().isMatrix = isMatrix;
208
// --------------------------------------------
209
void AnimationSampleCache::sampleExpression ( const MObject& object )
212
MFnDependencyNode depNode ( object );
213
MPlug plug = depNode.findPlug ( ATTR_OUTPUT );
215
uint elementCount = plug.numElements();
217
for ( uint e = 0; e < elementCount; e++ )
219
MPlug elementPlug = plug.elementByPhysicalIndex ( e );
221
MPlugArray connections;
222
elementPlug.connectedTo ( connections, false, true, &status );
224
uint connectionCount = connections.length();
226
for ( uint c = 0; c < connectionCount; ++c )
228
MPlug sampledPlug = connections[c];
229
MObject connectedNode = connections[c].node();
231
// By-pass any unit conversion nodes
232
while ( connectedNode.hasFn ( MFn::kUnitConversion ) )
234
bool hasConnection = DagHelper::getPlugConnectedTo ( connectedNode, ATTR_OUTPUT, sampledPlug );
235
connectedNode = ( hasConnection ) ? sampledPlug.node() : MObject::kNullObj;
238
// Add the corresponding plug to the sampling list
239
cachePlug ( sampledPlug, false );
244
// --------------------------------------------
245
void AnimationSampleCache::sampleConstraint ( const MDagPath& dagPath )
247
// Find all the transforms below this node.
248
MObject temp = dagPath.node();
249
MItDependencyGraph itDG ( temp, MFn::kTransform, MItDependencyGraph::kDownstream, MItDependencyGraph::kBreadthFirst, MItDependencyGraph::kNodeLevel );
251
for ( ; !itDG.isDone(); itDG.next() )
253
cacheTransformNode ( itDG.thisNode() );
257
// --------------------------------------------
258
void AnimationSampleCache::sampleIKHandle ( const MDagPath& dagPath )
261
MFnIkHandle ikHandle ( dagPath, &status );
263
if ( status == MStatus::kSuccess )
265
// Make sure this IK handle seems valid (represents a valid chain
266
// between two dag paths).
267
MDagPath joint, effector;
269
if ( ikHandle.getStartJoint ( joint ) != MStatus::kSuccess ) return;
270
if ( ikHandle.getEffector ( effector ) != MStatus::kSuccess ) return;
271
if ( effector.length() <= joint.length() ) return;
273
effector.pop ( effector.length() - joint.length() );
274
if ( ! ( effector == joint ) ) return;
276
// OK, I guess it's good. Now add all nodes affected by this IK
277
// handle to a list of IK affected nodes. We will mark all these
278
// as needing to be sampled...
279
ikHandle.getEffector ( effector );
280
for ( effector.pop ( 1 ); effector.length() >=joint.length(); effector.pop ( 1 ) )
282
MFnDagNode effectorNode ( effector );
283
MObject _enobj = effectorNode.object();
284
cacheTransformNode ( _enobj );
289
// --------------------------------------------
290
void AnimationSampleCache::samplePlugs()
292
if ( mNodes.empty() ) return;
295
MFnMatrixData matrixData;
297
AnimationHelper::getCurrentTime ( originalTime );
299
std::vector<float>& times = AnimationHelper::mSamplingTimes;
300
uint sampleCount = ( uint ) times.size();
302
// Allocate the necessary memory in all the plug timing buffers
303
for ( CacheNodeMap::iterator it = mNodes.begin(); it != mNodes.end(); ++it )
305
CacheNode* c = ( *it ).second;
306
for ( CachePartList::iterator it2 = c->parts.begin(); it2 != c->parts.end(); ++it2 )
308
CacheNode::Part& part = ( *it2 );
311
part.values.resize ( ( !part.isMatrix ) ? sampleCount : 16 * sampleCount );
316
// Sample all the wanted plugs
317
for ( uint i = 0; i < sampleCount; ++i )
319
MTime t ( times[i], MTime::kSeconds );
320
AnimationHelper::setCurrentTime ( t );
322
for ( CacheNodeMap::iterator it = mNodes.begin(); it != mNodes.end(); ++it )
324
CacheNode* c = ( *it ).second;
326
for ( CachePartList::iterator it2 = c->parts.begin(); it2 != c->parts.end(); ++it2 )
328
CacheNode::Part& part = ( *it2 );
331
if ( !part.isMatrix )
333
part.plug.getValue ( part.values[i] );
335
if ( i > 0 && part.values[i-1] != part.values[i] ) part.isAnimated = true;
340
part.plug.getValue ( val );
342
stat = matrixData.setObject ( val );
343
if ( stat != MStatus::kSuccess ) MGlobal::displayWarning ( "Unable to set matrixData on sampled transform." );
345
MMatrix matrix = matrixData.matrix ( &stat );
346
if ( stat != MStatus::kSuccess ) MGlobal::displayWarning ( "Unable to retrieve sampled matrixData." );
348
#define PV(a,b,c) part.values[16*i+a] = (float) matrix[b][c]
367
#define PD(a) part.values[16*i+a] != part.values[16*(i-1)+a]
368
if ( i > 0 && ( PD ( 0 ) || PD ( 1 ) || PD ( 2 ) || PD ( 3 ) || PD ( 4 )
369
|| PD ( 5 ) || PD ( 6 ) || PD ( 7 ) || PD ( 8 ) || PD ( 9 ) || PD ( 10 )
370
|| PD ( 11 ) || PD ( 12 ) || PD ( 13 ) || PD ( 14 ) || PD ( 15 ) ) )
371
part.isAnimated = true;
378
AnimationHelper::setCurrentTime ( originalTime );
b'\\ No newline at end of file'