~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to COLLADAMaya/src/COLLADAMayaAnimationSampleCache.cpp

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "COLLADAMayaExportOptions.h"
 
18
#include "COLLADAMayaAnimationSampleCache.h"
 
19
#include "COLLADAMayaAnimationHelper.h"
 
20
#include "COLLADAMayaDagHelper.h"
 
21
#include "COLLADAMayaSyntax.h"
 
22
 
 
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>
 
30
 
 
31
 
 
32
namespace COLLADAMaya
 
33
{
 
34
    // --------------------------------------------
 
35
    AnimationSampleCache::AnimationSampleCache() : mNodeSearch ( NULL ) {}
 
36
 
 
37
    // --------------------------------------------
 
38
    AnimationSampleCache::~AnimationSampleCache()
 
39
    {
 
40
        mNodeSearch = NULL;
 
41
 
 
42
        CacheNodeMap::iterator it = mNodes.begin();
 
43
        for ( ; it!=mNodes.end(); ++it )
 
44
        {
 
45
            CacheNode* node = ( *it ).second;
 
46
            delete node;
 
47
        }
 
48
 
 
49
        mNodes.clear();
 
50
    }
 
51
 
 
52
    // --------------------------------------------
 
53
    void AnimationSampleCache::cacheTransformNode ( const MObject& node )
 
54
    {
 
55
        if ( node.hasFn ( MFn::kTransform ) )
 
56
        {
 
57
            MFnDagNode nodeFn ( node );
 
58
            MPlug p;
 
59
 
 
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 );
 
66
#undef ADD_PLUG
 
67
        }
 
68
        else
 
69
        {
 
70
            std::cerr << "Unsupported sampling type: " << node.apiTypeStr() << std::endl;
 
71
        }
 
72
    }
 
73
 
 
74
    // --------------------------------------------
 
75
    bool AnimationSampleCache::findCacheNode ( const MObject& node )
 
76
    {
 
77
        // Get the node name
 
78
        MFnDependencyNode fn ( node );
 
79
        String nodeName = fn.name().asChar();
 
80
 
 
81
        CacheNodeMap::iterator it = mNodes.find ( nodeName );
 
82
        if ( it != mNodes.end() )
 
83
        {
 
84
            mNodeSearch = ( *it ).second;
 
85
            return true;
 
86
        }
 
87
 
 
88
        mNodeSearch = NULL;
 
89
        return false;
 
90
    }
 
91
 
 
92
    // --------------------------------------------
 
93
    bool AnimationSampleCache::findCachePlug ( const MPlug& plug,
 
94
            std::vector<float>*& inputs,
 
95
            std::vector<float>*& outputs )
 
96
    {
 
97
        inputs = NULL;
 
98
        outputs = NULL;
 
99
 
 
100
        if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
 
101
        if ( mNodeSearch == NULL ) return false;
 
102
 
 
103
        for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end(); ++it )
 
104
        {
 
105
            if ( ( *it ).plug == plug && ( *it ).plug.logicalIndex() == plug.logicalIndex() )
 
106
            {
 
107
                if ( ( *it ).isAnimated )
 
108
                {
 
109
                    inputs = &AnimationHelper::mSamplingTimes;
 
110
                    outputs = & ( *it ).values;
 
111
                }
 
112
 
 
113
                return true;
 
114
            }
 
115
        }
 
116
 
 
117
        return false;
 
118
    }
 
119
 
 
120
    // --------------------------------------------
 
121
    bool AnimationSampleCache::findCachePlug ( const MPlug& plug, bool& isAnimated )
 
122
    {
 
123
        if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
 
124
        if ( mNodeSearch == NULL ) return false;
 
125
 
 
126
        for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end(); ++it )
 
127
        {
 
128
            if ( ( *it ).plug == plug && ( *it ).plug.logicalIndex() == plug.logicalIndex() )
 
129
            {
 
130
                isAnimated = ( *it ).isAnimated;
 
131
                return true;
 
132
            }
 
133
        }
 
134
 
 
135
        return false;
 
136
    }
 
137
 
 
138
    // --------------------------------------------
 
139
    bool AnimationSampleCache::markPlugWanted ( const MPlug& plug )
 
140
    {
 
141
        if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
 
142
        if ( mNodeSearch == NULL ) return false;
 
143
 
 
144
        bool isSampling = false;
 
145
        uint childCount = plug.numChildren();
 
146
        std::vector<MPlug> marks ( 1 + childCount );
 
147
        marks[childCount] = plug;
 
148
 
 
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 )
 
151
        {
 
152
            for ( uint i = 0; i < childCount + 1; ++i )
 
153
            {
 
154
                if ( ( *it ).plug == marks[i] && ( *it ).plug.logicalIndex() == marks[i].logicalIndex() )
 
155
                {
 
156
                    isSampling = ( *it ).isWanted = true;
 
157
                    break;
 
158
                }
 
159
            }
 
160
        }
 
161
 
 
162
        return isSampling;
 
163
    }
 
164
 
 
165
    // --------------------------------------------
 
166
    void AnimationSampleCache::cachePlug ( const MPlug& plug, bool isMatrix )
 
167
    {
 
168
        if ( mNodeSearch == NULL || mNodeSearch->node != plug.node() ) findCacheNode ( plug.node() );
 
169
        if ( mNodeSearch == NULL )
 
170
        {
 
171
            mNodeSearch = new CacheNode ( plug.node() );
 
172
 
 
173
            MFnDependencyNode fn ( plug.node() );
 
174
            String nodeName = fn.name().asChar();
 
175
            mNodes.insert ( std::pair<String, CacheNode*> ( nodeName, mNodeSearch ) );
 
176
        }
 
177
 
 
178
        std::vector<MPlug> marks;
 
179
        uint childCount = plug.numChildren();
 
180
        if ( childCount == 0 || isMatrix )
 
181
        {
 
182
            marks.push_back ( plug );
 
183
            childCount = 1;
 
184
        }
 
185
        else
 
186
        {
 
187
            marks.resize ( childCount );
 
188
            for ( uint i = 0; i < childCount; ++i ) marks[i] = plug.child ( i );
 
189
        }
 
190
 
 
191
        for ( uint i = 0; i < childCount; ++i )
 
192
        {
 
193
            MPlug p = marks[i];
 
194
            bool found = false;
 
195
 
 
196
            for ( CachePartList::iterator it = mNodeSearch->parts.begin(); it != mNodeSearch->parts.end() && !found; ++it )
 
197
            {
 
198
                found = ( *it ).plug == p && ( *it ).plug.logicalIndex() == p.logicalIndex();
 
199
            }
 
200
            if ( !found )
 
201
            {
 
202
                mNodeSearch->parts.push_back ( CacheNode::Part ( p ) );
 
203
                mNodeSearch->parts.back().isMatrix = isMatrix;
 
204
            }
 
205
        }
 
206
    }
 
207
 
 
208
    // --------------------------------------------
 
209
    void AnimationSampleCache::sampleExpression ( const MObject& object )
 
210
    {
 
211
        MStatus status;
 
212
        MFnDependencyNode depNode ( object );
 
213
        MPlug plug = depNode.findPlug ( ATTR_OUTPUT );
 
214
 
 
215
        uint elementCount = plug.numElements();
 
216
 
 
217
        for ( uint e = 0; e < elementCount; e++ )
 
218
        {
 
219
            MPlug elementPlug = plug.elementByPhysicalIndex ( e );
 
220
 
 
221
            MPlugArray connections;
 
222
            elementPlug.connectedTo ( connections, false, true, &status );
 
223
 
 
224
            uint connectionCount = connections.length();
 
225
 
 
226
            for ( uint c = 0; c < connectionCount; ++c )
 
227
            {
 
228
                MPlug sampledPlug = connections[c];
 
229
                MObject connectedNode = connections[c].node();
 
230
 
 
231
                // By-pass any unit conversion nodes
 
232
                while ( connectedNode.hasFn ( MFn::kUnitConversion ) )
 
233
                {
 
234
                    bool hasConnection = DagHelper::getPlugConnectedTo ( connectedNode, ATTR_OUTPUT, sampledPlug );
 
235
                    connectedNode = ( hasConnection ) ? sampledPlug.node() : MObject::kNullObj;
 
236
                }
 
237
 
 
238
                // Add the corresponding plug to the sampling list
 
239
                cachePlug ( sampledPlug, false );
 
240
            }
 
241
        }
 
242
    }
 
243
 
 
244
    // --------------------------------------------
 
245
    void AnimationSampleCache::sampleConstraint ( const MDagPath& dagPath )
 
246
    {
 
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 );
 
250
 
 
251
        for ( ; !itDG.isDone(); itDG.next() )
 
252
        {
 
253
            cacheTransformNode ( itDG.thisNode() );
 
254
        }
 
255
    }
 
256
 
 
257
    // --------------------------------------------
 
258
    void AnimationSampleCache::sampleIKHandle ( const MDagPath& dagPath )
 
259
    {
 
260
        MStatus status;
 
261
        MFnIkHandle ikHandle ( dagPath, &status );
 
262
 
 
263
        if ( status == MStatus::kSuccess )
 
264
        {
 
265
            // Make sure this IK handle seems valid (represents a valid chain
 
266
            // between two dag paths).
 
267
            MDagPath joint, effector;
 
268
 
 
269
            if ( ikHandle.getStartJoint ( joint ) != MStatus::kSuccess ) return;
 
270
            if ( ikHandle.getEffector ( effector ) != MStatus::kSuccess ) return;
 
271
            if ( effector.length() <= joint.length() ) return;
 
272
 
 
273
            effector.pop ( effector.length() - joint.length() );
 
274
            if ( ! ( effector == joint ) ) return;
 
275
 
 
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 ) )
 
281
            {
 
282
                MFnDagNode effectorNode ( effector );
 
283
                MObject _enobj = effectorNode.object();
 
284
                cacheTransformNode ( _enobj );
 
285
            }
 
286
        }
 
287
    }
 
288
 
 
289
    // --------------------------------------------
 
290
    void AnimationSampleCache::samplePlugs()
 
291
    {
 
292
        if ( mNodes.empty() ) return;
 
293
 
 
294
        MTime originalTime;
 
295
        MFnMatrixData matrixData;
 
296
        MStatus stat;
 
297
        AnimationHelper::getCurrentTime ( originalTime );
 
298
 
 
299
        std::vector<float>& times = AnimationHelper::mSamplingTimes;
 
300
        uint sampleCount = ( uint ) times.size();
 
301
 
 
302
        // Allocate the necessary memory in all the plug timing buffers
 
303
        for ( CacheNodeMap::iterator it = mNodes.begin(); it != mNodes.end(); ++it )
 
304
        {
 
305
            CacheNode* c = ( *it ).second;
 
306
            for ( CachePartList::iterator it2 = c->parts.begin(); it2 != c->parts.end(); ++it2 )
 
307
            {
 
308
                CacheNode::Part& part = ( *it2 );
 
309
                if ( part.isWanted )
 
310
                {
 
311
                    part.values.resize ( ( !part.isMatrix ) ? sampleCount : 16 * sampleCount );
 
312
                }
 
313
            }
 
314
        }
 
315
 
 
316
        // Sample all the wanted plugs
 
317
        for ( uint i = 0; i < sampleCount; ++i )
 
318
        {
 
319
            MTime t ( times[i], MTime::kSeconds );
 
320
            AnimationHelper::setCurrentTime ( t );
 
321
 
 
322
            for ( CacheNodeMap::iterator it = mNodes.begin(); it != mNodes.end(); ++it )
 
323
            {
 
324
                CacheNode* c = ( *it ).second;
 
325
 
 
326
                for ( CachePartList::iterator it2 = c->parts.begin(); it2 != c->parts.end(); ++it2 )
 
327
                {
 
328
                    CacheNode::Part& part = ( *it2 );
 
329
                    if ( part.isWanted )
 
330
                    {
 
331
                        if ( !part.isMatrix )
 
332
                        {
 
333
                            part.plug.getValue ( part.values[i] );
 
334
 
 
335
                            if ( i > 0 && part.values[i-1] != part.values[i] ) part.isAnimated = true;
 
336
                        }
 
337
                        else
 
338
                        {
 
339
                            MObject val;
 
340
                            part.plug.getValue ( val );
 
341
 
 
342
                            stat = matrixData.setObject ( val );
 
343
                            if ( stat != MStatus::kSuccess ) MGlobal::displayWarning ( "Unable to set matrixData on sampled transform." );
 
344
 
 
345
                            MMatrix matrix = matrixData.matrix ( &stat );
 
346
                            if ( stat != MStatus::kSuccess ) MGlobal::displayWarning ( "Unable to retrieve sampled matrixData." );
 
347
 
 
348
#define PV(a,b,c) part.values[16*i+a] = (float) matrix[b][c]
 
349
                            PV ( 0, 0, 0 );
 
350
                            PV ( 1, 1, 0 );
 
351
                            PV ( 2, 2, 0 );
 
352
                            PV ( 3, 3, 0 );
 
353
                            PV ( 4, 0, 1 );
 
354
                            PV ( 5, 1, 1 );
 
355
                            PV ( 6, 2, 1 );
 
356
                            PV ( 7, 3, 1 );
 
357
                            PV ( 8, 0, 2 );
 
358
                            PV ( 9, 1, 2 );
 
359
                            PV ( 10,2, 2 );
 
360
                            PV ( 11,3, 2 );
 
361
                            PV ( 12,0, 3 );
 
362
                            PV ( 13,1, 3 );
 
363
                            PV ( 14,2, 3 );
 
364
                            PV ( 15,3, 3 );
 
365
#undef PV
 
366
 
 
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;
 
372
                        }
 
373
                    }
 
374
                }
 
375
            }
 
376
        }
 
377
 
 
378
        AnimationHelper::setCurrentTime ( originalTime );
 
379
    }
 
380
 
 
381
}
 
 
b'\\ No newline at end of file'