source: OGRE/trunk/ogrenew/Tools/MayaExport/shared/src/OgreMayaSkeleton.cpp @ 657

Revision 657, 16.8 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2============================================================================
3This source file is part of the Ogre-Maya Tools.
4Distributed as part of Ogre (Object-oriented Graphics Rendering Engine).
5Copyright (C) 2003 Fifty1 Software Inc., Bytelords
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; either version 2
10of the License, or (at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20or go to http://www.gnu.org/licenses/gpl.txt
21============================================================================
22*/
23#include "OgreMayaSkeleton.h"
24#include "OgreMayaOptions.h"
25
26#include <maya/MString.h>
27#include <maya/MArgList.h>
28#include <maya/MAnimControl.h>
29
30#include <maya/MFnMesh.h>
31#include <maya/MFnIkJoint.h>
32#include <maya/MFnDagNode.h>
33#include <maya/MFnSkinCluster.h>
34#include <maya/MFnMatrixData.h>
35#include <maya/MFnSet.h>
36#include <maya/MFnLambertShader.h>
37#include <maya/MFnBlinnShader.h>
38#include <maya/MFnPhongShader.h>
39
40#include <maya/MItGeometry.h>
41#include <maya/MItDag.h>
42#include <maya/MItDependencyGraph.h>
43#include <maya/MItDependencyNodes.h>
44#include <maya/MItMeshVertex.h>
45#include <maya/MItMeshPolygon.h>
46
47#include <maya/MPlug.h>
48#include <maya/MDagPathArray.h>
49#include <maya/MFloatPointArray.h>
50#include <maya/MFloatVectorArray.h>
51#include <maya/MFloatArray.h>
52#include <maya/MPointArray.h>
53#include <maya/MMatrix.h>
54#include <maya/MGlobal.h>
55#include <maya/MStatus.h>
56
57#include <iostream>
58
59namespace OgreMaya {
60       
61        using namespace std;
62
63    void printMMatrix(MMatrix const& m) {
64        cout.setf(ios::showpos | ios::fixed);
65        cout.precision(5);
66        cout << "("<<m(0,0)<<", "<<m(0,1)<<", "<<m(0,2)<<", "<<m(0,3)<<")" << '\n';
67        cout << "("<<m(1,0)<<", "<<m(1,1)<<", "<<m(1,2)<<", "<<m(1,3)<<")" << '\n';
68        cout << "("<<m(2,0)<<", "<<m(2,1)<<", "<<m(2,2)<<", "<<m(2,3)<<")" << '\n';
69        cout << "("<<m(3,0)<<", "<<m(3,1)<<", "<<m(3,2)<<", "<<m(3,3)<<")" << '\n';
70    }
71
72    void printMQuaternion(MQuaternion const& q) {
73        cout.setf(ios::showpos | ios::fixed);
74        cout.precision(5);
75        cout << "("<<q[0]<<", "<<q[1]<<", "<<q[2]<<", "<<q[3]<<")" << '\n';
76    }
77
78    void printMVector(MVector const& v) {
79        cout.setf(ios::showpos | ios::fixed);
80        cout.precision(5);
81        cout << "("<<v[0]<<", "<<v[1]<<", "<<v[2]<<")" << '\n';
82    }
83
84        //      --------------------------------------------------------------------------
85        /** Standard constructor. Creates Ogre Mesh and defines known options.
86        */     
87        //      --------------------------------------------------------------------------
88        SkeletonGenerator::SkeletonGenerator() {
89        }
90
91
92        //      --------------------------------------------------------------------------
93        /** Destructor.
94        */     
95        //      --------------------------------------------------------------------------
96        SkeletonGenerator::~SkeletonGenerator()
97        {
98        }
99
100
101        //      --------------------------------------------------------------------------
102        /** Find and export all joints
103
104                \return         True if exported ok, false otherwise
105        */     
106        //      --------------------------------------------------------------------------
107        bool SkeletonGenerator::exportAll()     {       
108
109        if(!_querySkeleton())
110            return false;
111
112        if(!_querySkeletonAnim())
113            return false;
114
115       
116        MGlobal::executeCommand("ikSystem -e -sol 0;");
117        MGlobal::selectByName(root->name.c_str());
118        MGlobal::executeCommand("dagPose -r -g -bp");
119        MGlobal::executeCommand("dagPose -r -g -bp");
120                //MGlobal::executeCommand("currentTime -edit 0");
121       
122       
123/*       
124        MGlobal::executeCommand("ikSystem -e -sol 0;");
125            MGlobal::executeCommand((string("select ")+root->name).c_str());
126            MGlobal::executeCommand("dagPose -r -g -bp");
127*/
128       
129        /////////////////////////////////////////////
130
131       
132        {
133            ofstream out(OPTIONS.outSkelFile.c_str());
134
135            out.precision(5);
136            out.setf(ios::fixed);
137
138            out << "<skeleton>\n";
139
140           
141            //
142            // BONES
143            //
144            out << "\t<bones>\n";
145
146
147            SkeletonJointList::iterator it, end;
148            MVector axis;
149            double angle;
150
151            for(it=jointList.begin(), end=jointList.end(); it!=end; ++it) {
152               
153                SkeletonJoint& j = **it;
154                               
155                /*
156                cout << "* worldMatrix:\n";
157                printMMatrix(j.worldMatrix);
158                cout << "* relPos:\n";
159                printMVector(j.relPos);
160                cout << "* relRot:\n";
161                printMQuaternion(j.relRot);
162                cout << "----------------------------\n";
163                */
164
165                j.relRot.getAxisAngle(axis, angle);
166
167                out << "\t\t<bone id=\""<<j.index<<"\" name=\""<<j.name<<"\">\n";
168                out << "\t\t\t<position x=\""<<j.relPos.x<<"\" y=\""<<j.relPos.y<<"\" z=\""<<j.relPos.z<<"\"/>\n";
169                out << "\t\t\t<rotation angle=\""<<((float)angle)<<"\">\n";
170                out << "\t\t\t\t<axis x=\""<<axis.x<<"\" y=\""<<axis.y<<"\" z=\""<<axis.z<<"\"/>\n";
171                out << "\t\t\t</rotation>\n";
172                out << "\t\t</bone>\n";
173
174            }
175
176            out << "\t</bones>\n";
177
178           
179            //
180            // HIERARCHY
181            //
182            out << "\t<bonehierarchy>\n";
183            for(it=jointList.begin(), end=jointList.end(); it!=end; ++it) {
184                SkeletonJoint& j = **it;
185                if(j.hasParent) {
186                    out << "\t\t<boneparent bone=\""<<j.name<<"\" parent=\""<<j.parentName<<"\"/>\n";
187                }
188            }
189
190            out << "\t</bonehierarchy>\n";
191           
192
193            //
194            // ANIMATIONS
195            //
196            out << "\t<animations>\n";
197            AnimationMap::iterator animIt = animations.begin();
198            AnimationMap::iterator animEnd = animations.end();
199            for(; animIt!=animEnd; ++animIt) {
200                string animName = (*animIt).first;
201                Animation& anim = (*animIt).second;
202
203                out << "\t\t<animation name=\""<<animName.c_str()<<"\" ";
204                out << "length=\""<<anim.time<<"\">\n";
205                out << "\t\t\t<tracks>\n";
206
207                KeyframesMap::iterator keyframesIt = anim.keyframes.begin();
208                KeyframesMap::iterator keyframesEnd = anim.keyframes.end();
209                for(; keyframesIt!=keyframesEnd; ++keyframesIt) {
210                    string boneName = (*keyframesIt).first;
211                    KeyframeList& l = (*keyframesIt).second;
212
213                    out << "\t\t\t\t<track bone=\""<<boneName.c_str()<<"\">\n";
214                    out << "\t\t\t\t\t<keyframes>\n";
215
216                    KeyframeList::iterator it  = l.begin();
217                    KeyframeList::iterator end = l.end();
218                    for(;it!=end; ++it) {
219                        Keyframe& k = *it;
220
221                        MVector axis;
222                        double angle;
223                        k.rot.getAxisAngle(axis, angle);
224
225                        out << "\t\t\t\t\t\t<keyframe time=\""<<k.time<<"\">\n";                       
226                        out << "\t\t\t\t\t\t\t<translate x=\""<<k.pos.x<<"\" y=\""<<k.pos.y<<"\" z=\""<<k.pos.z<<"\"/>\n";
227                        out << "\t\t\t\t\t\t\t<rotate angle=\""<<((float)angle)<<"\">\n";
228                        out << "\t\t\t\t\t\t\t\t<axis x=\""<<axis.x<<"\" y=\""<<axis.y<<"\" z=\""<<axis.z<<"\"/>\n";
229                        out << "\t\t\t\t\t\t\t</rotate>\n";
230                        out << "\t\t\t\t\t\t</keyframe>\n";
231                    }
232
233                    out << "\t\t\t\t\t</keyframes>\n";
234                    out << "\t\t\t\t</track>\n";
235                }                   
236
237                out << "\t\t\t</tracks>\n";
238                out << "\t\t</animation>\n";
239            }
240            out << "\t</animations>\n";
241
242
243            out << "</skeleton>\n";
244        }
245
246
247        deleteAll(jointList.begin(), jointList.end());
248
249        return true;
250    }
251       
252    //  --------------------------------------------------------------------------
253        /** Finds and exports all joints
254
255                \return         True if exported ok, false otherwise
256        */     
257        //      --------------------------------------------------------------------------
258
259        bool SkeletonGenerator::_querySkeleton() {
260
261        cout << "\nSkeletonGenerator::_querySkeleton\n";
262               
263        jointList.clear();
264
265
266            MItDag    kDagIt(MItDag::kDepthFirst, MFn::kJoint);
267            MDagPath  kRootPath;
268
269            MStatus   kStatus;
270
271        kDagIt.getPath(kRootPath);
272
273                // check if valid path
274                if(!kRootPath.isValid()) {
275                        cout << "\tcan not find parent joint\n";
276            return false;
277                }
278        else {
279            cout << "\tfound parent joint \""<<kRootPath.partialPathName().asChar()<<"\"\n";
280        }
281
282        /*
283        // is this really necessary?
284            // check for skeleton root joint
285            {
286                    MFnIkJoint    kJointFn( kRootPath.node() );
287
288                    MObject kParentObj = kJointFn.parent(0);
289
290                    // root joint can not have parent joint
291            if(!kParentObj.hasFn( MFn::kJoint)) {
292                            cout << "\tParent joint found: \"" << kJointFn.partialPathName().asChar() << "\"\n";
293                    }
294                    else {
295                MFnDagNode kDagNodeFn(kParentObj);
296                            cout << "\troot joint can not have joint as parent, PATH:\""<<kDagNodeFn.partialPathName().asChar()<<"\"\n";
297                            return 0;
298                    }
299            }
300        */
301
302            //Setup skeleton
303        cout << "\tsetup skeleton\n";
304            int uiNumJoints = 0;
305
306            for( ; !kDagIt.isDone(); kDagIt.next(), ++uiNumJoints ) {
307                    MDagPath kDagPath;
308
309                    kDagIt.getPath( kDagPath );
310                    MFnIkJoint kJointFn( kDagPath.node() );
311
312                    SkeletonJoint *pkJoint = new SkeletonJoint;
313
314                    jointList.push_back( pkJoint );
315
316            pkJoint->dagPath = kDagPath;
317                    pkJoint->name    = kJointFn.partialPathName().asChar();
318                    pkJoint->index   = uiNumJoints;                 
319
320                    unsigned int uiNumParents = kJointFn.parentCount();
321
322                    // can only have one parent
323                    if( uiNumParents != 1 ) {
324                            cout << "\t[ERROR] joint has " << uiNumParents << " parents (only 1 allowed)" << '\n';
325                            return 0;
326                    }
327
328                    MObject kParentObj = kJointFn.parent(0);
329                           
330                    if(kParentObj.hasFn(MFn::kJoint)) {
331                            MFnIkJoint kParentJointFn(kParentObj);
332
333                            pkJoint->parentName = kParentJointFn.partialPathName().asChar();
334                            pkJoint->hasParent  = true;                     
335                    }
336                    else {
337                // we've found root here -> mark
338                root = pkJoint;
339
340                pkJoint->parentName = "";
341                                pkJoint->hasParent  = false;               
342                    }
343
344
345                    //Get bindpose world matrix for joint
346
347                    MPlug   kBindMatrixPlug = kJointFn.findPlug("bindPose");
348                    MObject kBindMatrixObject;
349           
350                    kStatus = kBindMatrixPlug.getValue(kBindMatrixObject);
351
352                    if( kStatus != MStatus::kSuccess ) {
353                            cout << "\t[ERROR] unable to get bind matrix plug object\n";
354                            return 0;
355                    }
356
357                    MFnMatrixData kMatrixDataFn( kBindMatrixObject );
358                   
359                    MMatrix kBindMatrix = kMatrixDataFn.matrix( &kStatus );
360
361                    if( kStatus != MStatus::kSuccess ) {
362                            cout << "\t[ERROR] unable to get bind matrix data from plug object\n";
363                            return 0;
364                    }
365
366            pkJoint->worldMatrix    = kBindMatrix;
367            pkJoint->invWorldMatrix = kBindMatrix.inverse();
368            }
369
370
371        // if  numJoints == 0, we only have single root bone in skeleton
372        if(!uiNumJoints) {
373                    return true;           
374        }       
375
376
377            //Calculate relative position and rotation data
378        cout << "\tcalculate relative position and rotation data\n";
379           
380                SkeletonJointList::iterator jointIt  = jointList.begin();
381                SkeletonJointList::iterator jointEnd = jointList.end();
382                 
383        for(;jointIt!=jointEnd; ++jointIt) {
384
385            SkeletonJoint* j = *jointIt;
386
387            // search for parent node
388            if(j->hasParent) {
389                SkeletonJointList::iterator parentJointIt  = jointList.begin();
390                            SkeletonJointList::iterator parentJointEnd = jointList.end();
391                            for( ; parentJointIt != parentJointEnd; ++parentJointIt )
392                    if( (*parentJointIt)->name == (*jointIt)->parentName ) {
393                        (*jointIt)->parent = *parentJointIt;
394                                        break;
395                    }
396            }
397
398            if(j->hasParent)
399                j->localMatrix = j->worldMatrix * j->parent->invWorldMatrix;
400            else
401                j->localMatrix = j->worldMatrix;
402
403            j->invLocalMatrix = j->localMatrix.inverse();
404
405            j->relPos.x = j->localMatrix(3,0);
406            j->relPos.y = j->localMatrix(3,1);
407            j->relPos.z = j->localMatrix(3,2);
408           
409            j->relRot = j->localMatrix;       
410        }
411
412               
413                // ===== Done
414                return true;
415        }
416
417
418    bool SkeletonGenerator::_querySkeletonAnim() {
419
420        cout << "\nSkeletonGenerator::_querySkeletonAnim\n";
421
422        animations.clear();
423
424            MTime kTimeMin   = MAnimControl::minTime();
425            MTime kTimeMax   = MAnimControl::maxTime();
426            MTime kTimeTotal = kTimeMax - kTimeMin;
427            float fLength    = (float)kTimeTotal.as(MTime::kSeconds);
428            int iTimeMin     = (int)kTimeMin.value();
429            int iTimeMax     = (int)kTimeMax.value();
430            int iFrames      = (iTimeMax-iTimeMin)+1;
431        float secondsPerFrame = fLength / (float)iFrames;
432           
433            MAnimControl kAnimControl;
434
435            cout << "\tanimation start: " << iTimeMin << " end: " << iTimeMax << '\n';
436
437            if( iFrames <= 1 )
438                    return false;
439           
440
441        Options::KeyframeRangeMap& m = OPTIONS.animations;
442        Options::KeyframeRangeMap::iterator it  = m.begin();
443        Options::KeyframeRangeMap::iterator end = m.end();
444
445        for(;it!=end; ++it) {
446            string animationName = (*it).first;
447            int from    = (*it).second.from;
448            int to      = (*it).second.to;
449            int step    = (*it).second.step;
450            int frameCount = to - from + 1;
451           
452            if(from < iTimeMin || to > iTimeMax || !(frameCount>0)) {
453                cout << "\t[ERROR] Illegal Animation Range\n";
454                continue;
455            }
456
457            Animation& anim = animations[animationName];
458
459            anim.time = (float)(frameCount)*secondsPerFrame;           
460
461            SkeletonJointList::iterator ppkJoint = jointList.begin();
462            SkeletonJointList::iterator ppkJointEnd = jointList.end();             
463               
464                        for( ; ppkJoint != ppkJointEnd; ++ppkJoint ) {                         
465                MTime kFrame = kTimeMin + (from - 1);
466
467                    for(int iFrame=0; iFrame<frameCount; iFrame+=step, kFrame+=step) {
468                            kAnimControl.setCurrentTime( kFrame );
469
470                    MVector kTranslation;
471                                MQuaternion kRotation;
472                                       
473                                        MMatrix kIncMat    = (*ppkJoint)->dagPath.inclusiveMatrix();
474                                        MMatrix kExcMat    = (*ppkJoint)->dagPath.exclusiveMatrix();
475                                        MMatrix kExcInvMat = (*ppkJoint)->dagPath.exclusiveMatrixInverse();                                                                                                                                             
476                                       
477                                        if((*ppkJoint)->hasParent) {
478                                                MMatrix kLocalMat = kIncMat * kExcInvMat * (*ppkJoint)->invLocalMatrix;
479
480                                                kRotation = kLocalMat;
481
482                                                kTranslation.x = (float)kLocalMat(3, 0);
483                                                kTranslation.y = (float)kLocalMat(3, 1);
484                                                kTranslation.z = (float)kLocalMat(3, 2);
485                                        }
486                                        else {
487                                                // root has to be handled differently
488                                                // cause when exporting root bone to ogre
489                                                // we remove all maya parents
490                                                kRotation = kIncMat * (*ppkJoint)->invLocalMatrix;
491
492                                                kTranslation.x = (float)(kIncMat(3, 0) - kExcMat(3, 0));
493                                                kTranslation.y = (float)(kIncMat(3, 1) - kExcMat(3, 1));
494                                                kTranslation.z = (float)(kIncMat(3, 2) - kExcMat(3, 2));
495                                        }
496
497                    float timePos =
498                        (float)iFrame * secondsPerFrame;
499               
500                    anim.keyframes[(*ppkJoint)->name].push_back(
501                        Keyframe(timePos, kTranslation, kRotation)
502                    );
503                        }   
504            }
505        }
506
507            return true;
508    }
509
510} // namespace OgreMaya
Note: See TracBrowser for help on using the repository browser.