Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/3dsmaxExport/OgreExport/include/OgreMaxSkeletonXMLExport.h @ 24

Last change on this file since 24 was 6, checked in by anonymous, 17 years ago

=…

File size: 14.7 KB
Line 
1/*
2                        // if skeleton data is present, stream skeleton file
3                        if (m_config.getExportSkeleton()) {
4                                // open the skeleton.xml output file
5                                of.open((m_config.getExportPath() + "\\" + m_skeletonFilename).c_str(), std::ios::out);
6
7                                // stream the skeleton file
8                                streamSkeleton(of);
9                                of.close();
10                        }
11
12*/
13
14#ifdef 0
15
16        // *******************************************************************************
17        // Skeleton streaming functions
18        // *******************************************************************************
19
20        std::string MeshXMLExporter::removeSpaces(const std::string &src) {
21                std::string s(src);
22                std::string::size_type pos;
23                while ((pos=s.find_first_of(" \t\n")) != std::string::npos)
24                        s.replace(pos, 1, "_");
25
26                return s;
27        }
28
29        bool MeshXMLExporter::streamSkeleton(std::ostream &of) {
30
31                // go through and sort out the bone hierarchy (include all of the non-null bones that were not
32                // skinned, as those could still be needed in the application)
33                of << "<?xml version=\"1.0\"?>" << std::endl << "<skeleton>" << std::endl;
34                of << "\t<bones>" << std::endl;
35
36                // write out the bone rest pose data
37                std::map< std::string, int >::const_iterator it = m_boneIndexMap.begin();
38                while (it != m_boneIndexMap.end()) {
39
40                        INode *thisNode = m_i->GetINodeByName(it->first.c_str());
41
42                        of << "\t\t<bone id=\"" << it->second << "\" name=\"" << removeSpaces(it->first) << "\" >" << std::endl;
43
44                        // assume rest pose is at time zero
45                        TimeValue start = m_i->GetAnimRange().Start();
46                        ObjectState os = thisNode->EvalWorldState(start);
47                        Object *obj = os.obj;
48                        SClass_ID scid = obj->SuperClassID();
49
50                        // SKELOBJ_CLASS_ID = 0x9125 = 37157
51                        // BIPED_CLASS_ID = 0x9155 = 37205
52                        // BIPSLAVE_CONTROL_CLASS_ID = 0x9154 = 37204
53                        // BIPBODY_CONTROL_CLASS_ID = 0x9156 = 37206
54                        // FOOTPRINT_CLASS_ID = 0x3011 = 12305
55                        // DUMMY_CLASS_ID = 0x876234 = 8872500
56                        Matrix3 tm(thisNode->GetNodeTM(start));
57                        Matrix3 ptm(thisNode->GetParentTM(start));
58                        Control *tmc = thisNode->GetTMController();
59
60                        TCHAR *nm = thisNode->GetName();
61                        Class_ID cid = tmc->ClassID();
62
63                        if (cid == BIPBODY_CONTROL_CLASS_ID || cid == BIPED_CLASS_ID) {
64                                if (m_config.getInvertYZ()) {
65                                        Matrix3 m = RotateXMatrix(PI / 2.0f);
66                                        tm = tm * Inverse(m);
67                                }
68                        }
69                        else
70                                tm = tm * Inverse(ptm);
71
72                        Point3 pos = tm.GetTrans();
73                        AngAxis aa(tm);
74
75                        of << "\t\t\t<position x=\"" << pos.x << "\" y=\"" << pos.y << "\" z=\"" << pos.z << "\" />" << std::endl;
76
77                        // there is still a lingering Max/Ogre handed-ness issue even after rotating to get the axes correct
78                        // so we negate the angle of rotation here
79                        of << "\t\t\t<rotation angle=\"" << -aa.angle << "\">" << std::endl;
80                        of << "\t\t\t\t<axis x=\"" << aa.axis.x << "\" y=\"" << aa.axis.y << "\" z=\"" << aa.axis.z << "\" />" << std::endl;
81                        of << "\t\t\t</rotation>" << std::endl;
82                        of << "\t\t</bone>" << std::endl;
83
84                        it++;
85                }
86
87                of << "\t</bones>" << std::endl;
88
89                // write out the bone hierarchy
90                it = m_boneIndexMap.begin();
91                of << "\t<bonehierarchy>" << std::endl;
92                while (it != m_boneIndexMap.end()) {
93                        INode *thisNode = m_i->GetINodeByName(it->first.c_str());
94
95                        if (thisNode != 0) {
96                                INode *parentNode = thisNode->GetParentNode();
97
98                                if (parentNode != 0 && parentNode != m_i->GetRootNode())
99                                        of << "\t\t<boneparent bone=\"" << removeSpaces(it->first) << "\" parent=\"" << removeSpaces(std::string(parentNode->GetName())) << "\"/>" << std::endl;
100                        }
101
102                        it++;
103                }
104                of << "\t</bonehierarchy>" << std::endl;
105
106                // the fun bits....
107                // Animations are named by the user during export; Max has no concept of animation subset names,
108                // so we have to get the user to do that manually. If the user has entered anything for animations,
109                // spit it all out here.
110                std::list<NamedAnimation>::iterator anim = m_animations.begin();
111
112                if (anim != m_animations.end()) {
113                        of << "\t<animations>" << std::endl;
114
115                        while (anim != m_animations.end()) {
116
117                                NamedAnimation a = *anim;
118                                anim++;
119
120                                float fps = (float)GetFrameRate();
121                                float length = (a.end - a.start) / fps;
122
123                                of << "\t\t<animation name=\"" << removeSpaces(a.name) << "\" length=\"" << length << "\">" << std::endl;
124
125                                streamAnimTracks(of, a.start, a.end);
126
127                                of << "\t\t</animation>" << std::endl;
128                        }
129
130                        of << "\t</animations>" << std::endl;
131                }
132
133                of << "</skeleton>" << std::endl;
134
135                return true;
136        }
137
138        static int _compare_func(const void *a, const void *b) { return *(( int *)a) - *(( int *)b); }
139
140        bool MeshXMLExporter::streamAnimTracks(std::ostream &of, int startFrame, int endFrame) {
141
142                int start = startFrame * GetTicksPerFrame();
143                int end = endFrame * GetTicksPerFrame();
144
145                std::map< std::string, int >::const_iterator it = m_boneIndexMap.begin();
146
147                of << "\t\t\t<tracks>" << std::endl;
148
149                // need this for calculating keyframe values
150                Matrix3 initTM, bipedMasterTM0;
151                IBipMaster *bip = 0;
152                bipedMasterTM0.IdentityMatrix();
153
154                while (it != m_boneIndexMap.end()) {
155
156                        INode *thisNode = m_i->GetINodeByName(it->first.c_str());
157                        it++;
158
159                        Control *c = thisNode->GetTMController();
160                        Class_ID cid = c->ClassID(); 
161
162                        Tab<TimeValue> keyTimes;
163                        Interval interval(start, end);
164
165                        /*
166                        -- gets initial transform at frame 0f
167                        at time 0f (
168                                initTform = d.transform ;
169                                if (not isRootUniversal2 d) then (
170                                        mparent = d.parent.transform ;
171                                        initTform = initTform*inverse(mparent) ;
172                                )
173                                else if (flipYZ) then (
174                                        if (not g_MAX) then
175                                                format " - flipping root track..." ;
176                                        -- we add the bip Transform
177                                        --initTform = initTform * d.controller.rootNode.transform ;
178                                        initTform = flipYZTransform initTform ;
179                                )
180                        )
181                        */
182
183                        initTM = thisNode->GetNodeTM(0);
184
185                        // must have at least a frame at the start...
186                        keyTimes.Append(1, &start);
187
188                        TCHAR *tch = thisNode->GetName();
189
190                        // SKELOBJ_CLASS_ID = 0x9125 = 37157
191                        // BIPED_CLASS_ID = 0x9155 = 37205
192                        // BIPSLAVE_CONTROL_CLASS_ID = 0x9154 = 37204
193                        // BIPBODY_CONTROL_CLASS_ID = 0x9156 = 37206
194                        // FOOTPRINT_CLASS_ID = 0x3011 = 12305
195                        // DUMMY_CLASS_ID = 0x876234 = 8872500
196
197                        // three-part controller for Biped root -- taking this cue from the old MaxScript exporter code
198                        if (cid == BIPBODY_CONTROL_CLASS_ID) {
199
200                                // we deal with the initial transform as-is, except that it might need to
201                                // be rotated (since the root transform is in world coords)
202                                if (m_config.getInvertYZ())
203                                        initTM = initTM * Inverse(RotateXMatrix(PI/2.0f));
204
205                                if (cid == BIPBODY_CONTROL_CLASS_ID) {
206                                        // get the keys from the horiz, vert and turn controllers
207                                        bip = GetBipMasterInterface(c);
208                                        Control *biph = bip->GetHorizontalControl();
209                                        Control *bipv = bip->GetVerticalControl();
210                                        Control *bipr = bip->GetTurnControl();
211
212                                        biph->GetKeyTimes(keyTimes, interval, KEYAT_POSITION | KEYAT_ROTATION);
213                                        bipv->GetKeyTimes(keyTimes, interval, KEYAT_POSITION | KEYAT_ROTATION);
214                                        bipr->GetKeyTimes(keyTimes, interval, KEYAT_POSITION | KEYAT_ROTATION);
215                                }
216                        }
217                        else if (cid == BIPSLAVE_CONTROL_CLASS_ID) {
218                                // slaves just have keys, apparently
219                                c->GetKeyTimes(keyTimes, interval, KEYAT_POSITION | KEYAT_ROTATION);
220                       
221                                // put initial transform into local coordinates -- since this is relative to the
222                                // parent, we don't need to sweat that possible rotations here
223                                initTM = initTM * Inverse(thisNode->GetParentTM(0));
224                        }
225
226                        // ...and stick a frame at the end as well...it will get sorted out if it is redundant
227                        keyTimes.Append(1, &end);
228
229                        // skip redundant key times here
230                        keyTimes.Sort(_compare_func);
231
232        //              if (cid == BIPSLAVE_CONTROL_CLASS_ID || cid == BIPBODY_CONTROL_CLASS_ID || cid == FOOTPRINT_CLASS_ID) {
233        //             
234        //                      if (cid == BIPBODY_CONTROL_CLASS_ID) {
235        //                              initTM = thisNode->GetNodeTM(0);
236        //
237        //                              if (m_flipYZ)
238        //                                      initTM = initTM * RotateXMatrix(PI/2.0f);
239        //                              bipedMasterTM0 = initTM;
240        //                      }
241        //                      else
242        //                              initTM = bipedMasterTM0;
243        //
244        //                      streamBipedKeyframes(of, bip, thisNode, keyTimes, interval, initTM);
245        //              }
246        //              else
247                                streamKeyframes(of, thisNode, keyTimes, interval, initTM);
248                }
249
250                of << "\t\t\t</tracks>" << std::endl;
251
252                return true;
253        }
254
255        bool MeshXMLExporter::streamKeyframes(std::ostream &of, INode *thisNode, Tab<TimeValue> &keyTimes, Interval &interval, Matrix3 &initTM) {
256
257                of << "\t\t\t\t<track bone=\"" << removeSpaces(std::string(thisNode->GetName())) << "\">" << std::endl;
258                of << "\t\t\t\t\t<keyframes>" << std::endl;
259
260                int i;
261                int keyTime = -1;
262                int start = interval.Start();
263                int end = interval.End();
264
265                /*
266               
267                -- gets initial transform at frame 0f
268                at time 0f (
269                        initTform = d.transform ;
270                        if (not isRootUniversal2 d) then (
271                                mparent = d.parent.transform ;
272                                initTform = initTform*inverse(mparent) ;
273                        )
274                        else if (flipYZ) then (
275                                if (not g_MAX) then
276                                        format " - flipping root track..." ;
277                                -- we add the bip Transform
278                                --initTform = initTform * d.controller.rootNode.transform ;
279                                initTform = flipYZTransform initTform ;
280                        )
281                )
282                */
283                initTM = thisNode->GetNodeTM(0);
284
285                Control *c = thisNode->GetTMController();
286                Control *pc = thisNode->GetParentNode()->GetTMController();
287                bool isRoot = false;
288
289                if (c > 0)
290                        if (c->ClassID() == BIPBODY_CONTROL_CLASS_ID)
291                                isRoot = true;
292        //      if (pc > 0)
293        //              if (pc->ClassID() == BIPBODY_CONTROL_CLASS_ID || pc->ClassID() == FOOTPRINT_CLASS_ID)
294        //                      isRoot = true;
295
296                TCHAR *tc = thisNode->GetName();
297                if (!isRoot) {
298                        Matrix3 ptm = thisNode->GetParentTM(0);
299                        initTM = initTM * Inverse(ptm);
300                }
301                else if (m_config.getInvertYZ()) {
302                        initTM = initTM * Inverse(RotateXMatrix(PI/2.0f));
303                }
304
305                for (i=0; i<keyTimes.Count(); i++) {
306                               
307                        // only operate within the supplied keyframe time range
308                        if (keyTimes[i] < start)
309                                continue;
310                        if (keyTimes[i] > end)
311                                break;
312
313                        // ignore key times we've already processed
314                        if (keyTimes[i] != keyTime) {
315
316                                keyTime = keyTimes[i];
317                                float keyTimef = (float) (keyTimes[i] - start) / (float)GetTicksPerFrame() / (float)GetFrameRate();
318
319                                of << "\t\t\t\t\t\t<keyframe time=\"" << keyTimef << "\">" << std::endl;
320
321                                /*
322
323                                function flipYZTransform Tform = (
324                                        local axis1,axis2,axis3,t,m
325                                       
326                                        -- computes the matrix
327                                        axis1 = point3 1 0 0 ;
328                                        axis2 = point3 0 0 1 ;
329                                        axis3 = point3 0 -1 0 ;
330                                        t = point3 0 0 0 ;
331                                        m=matrix3 axis1 axis2 axis3 t ;
332                                       
333                                        -- multiplies by the inverse
334                                        Tform = Tform*inverse(m) ;
335
336                                        return Tform ;
337                                )
338
339
340                                -- First, rotation which depends on initial transformation
341                                Tform = d.transform ;
342                                */
343                                Matrix3 tm = thisNode->GetNodeTM(keyTime);
344
345                                /*
346                                -- if this is the pelvis
347                                if (isRootUniversal2 d) then (
348                                        mparent = matrix3 1 ;
349
350                                        if (flipYZ) then
351                                                Tform = flipYZTransform Tform ;
352                                )                       
353                                else
354                                        mparent = d.parent.transform ;
355                                */
356
357                                // if this node's parent's controller is the biped controller, then this is either Pelvis or Footsteps,
358                                // and both should be treated as root nodes
359
360                                Matrix3 ident;
361                                Matrix3 ptm;
362                                ident.IdentityMatrix();
363                                Control *tmc = thisNode->GetTMController();
364                                TCHAR *tc = thisNode->GetName();
365
366                                if (tmc->ClassID() == BIPBODY_CONTROL_CLASS_ID) {
367
368                                        ptm = ident;
369                                        if (m_config.getInvertYZ()) {
370                                                tm = tm * Inverse(RotateXMatrix(PI/2.0f));
371                                        }
372                                }
373                                else
374                                        ptm = thisNode->GetParentNode()->GetNodeTM(keyTime);
375
376                                /*
377
378
379                                -- computes rotation
380                                mref = initTform*mparent ;     
381                                Tform = Tform*inverse(mref) ;
382                                */
383
384                                Matrix3 mref = initTM * ptm;
385                                tm = tm * Inverse(mref);
386
387                                /*
388                               
389                                -- rotation part is saved.
390                                rot = toAngleAxis Tform.rotation ;
391                                axis = rot.axis;
392                                angle = - rot.angle;
393                                */
394
395                                AngAxis aa(tm);
396
397                                /*
398                                -- Then, position which depends on parent                       
399                                Tform=d.transform ;
400                                Tform=Tform*inverse(mparent) ;
401
402                                */
403
404                                tm = thisNode->GetNodeTM(keyTime) * Inverse(ptm);
405
406                                /*
407
408                                -- if this is the root bone and flipYZ == true
409                                if (isRootUniversal2 d and flipYZ) then (
410                                        Tform = flipYZTransform Tform ;
411                                )
412
413                                */
414
415                                if (m_config.getInvertYZ() && thisNode->GetParentNode()->GetParentTM(0).IsIdentity()) {
416                                        tm = tm * Inverse(RotateXMatrix(PI/2.0f));
417                                }
418
419                                /*
420                                -- substracts position of the initial transform
421                                Tform.pos -= initTform.pos ;
422                                Tform.pos = Tform.pos * scale ;
423                               
424                                pos = Tform.pos ;
425                                */
426                                Point3 trans = tm.GetTrans();
427                                trans -= initTM.GetTrans();
428
429                                of << "\t\t\t\t\t\t\t<translate x=\"" << trans.x << "\" y=\"" << trans.y << "\" z=\"" << trans.z << "\" />" << std::endl;
430                                of << "\t\t\t\t\t\t\t<rotate angle=\"" << -aa.angle << "\">" << std::endl;
431                                of << "\t\t\t\t\t\t\t\t<axis x=\"" << aa.axis.x << "\" y=\"" << aa.axis.y << "\" z=\"" << aa.axis.z << "\" />" << std::endl;
432                                of << "\t\t\t\t\t\t\t</rotate>" << std::endl;
433
434                                of << "\t\t\t\t\t\t</keyframe>" << std::endl;
435                        }
436                }
437
438                of << "\t\t\t\t\t</keyframes>" << std::endl;
439                of << "\t\t\t\t</track>" << std::endl;
440
441                return true;
442        }
443
444        bool MeshXMLExporter::streamBipedKeyframes(std::ostream &of, IBipMaster *bip, INode *thisNode, Tab<TimeValue> &keyTimes, Interval &interval, Matrix3 &initTM) {
445
446                of << "\t\t\t\t<track bone=\"" << removeSpaces(std::string(thisNode->GetName())) << "\">" << std::endl;
447                of << "\t\t\t\t\t<keyframes>" << std::endl;
448
449                int i;
450                int keyTime = -1;
451                int start = interval.Start();
452                int end = interval.End();
453                Matrix3 tm(thisNode->GetNodeTM(start));
454                Matrix3 ptm(thisNode->GetParentTM(start));
455
456                for (i=0; i<keyTimes.Count(); i++) {
457                               
458                        // only operate within the supplied keyframe time range
459                        if (keyTimes[i] < start)
460                                continue;
461                        if (keyTimes[i] > end)
462                                break;
463
464                        // ignore key times we've already processed
465                        if (keyTimes[i] != keyTime) {
466
467                                keyTime = keyTimes[i];
468                                float keyTimef = (float) (keyTimes[i] - start) / (float)GetTicksPerFrame() / (float)GetFrameRate();
469
470                                of << "\t\t\t\t\t\t<keyframe time=\"" << keyTimef << "\">" << std::endl;
471
472                                Control *tmc = thisNode->GetTMController();
473
474                                TCHAR *nm = thisNode->GetName();
475                                Class_ID cid = tmc->ClassID();
476
477                                if (cid == BIPBODY_CONTROL_CLASS_ID || cid == BIPED_CLASS_ID) {
478                                        if (m_config.getInvertYZ()) {
479                                                Matrix3 m = RotateXMatrix(PI / 2.0f);
480                                                tm = tm * Inverse(m);
481                                        }
482                                }
483                                else
484                                        tm = tm * Inverse(ptm);
485
486                                //Point3 trans = bip->GetBipedPos(keyTime, thisNode);
487                                //Quat q = bip->GetBipedRot(keyTime, thisNode);
488
489                                Point3 trans = tm.GetTrans();
490                                trans = trans * Inverse(initTM);
491                                trans -= initTM.GetTrans();
492
493                                //AngAxis aa(q);
494                                AngAxis aa(tm);
495                                float ang = aa.angle;
496                                Point3 axis = aa.axis;
497               
498                                of << "\t\t\t\t\t\t\t<translate x=\"" << trans.x << "\" y=\"" << trans.y << "\" z=\"" << trans.z << "\" />" << std::endl;
499                                of << "\t\t\t\t\t\t\t<rotate angle=\"" << -ang << "\">" << std::endl;
500                                of << "\t\t\t\t\t\t\t\t<axis x=\"" << axis.x << "\" y=\"" << axis.y << "\" z=\"" << axis.z << "\" />" << std::endl;
501                                of << "\t\t\t\t\t\t\t</rotate>" << std::endl;
502
503                                of << "\t\t\t\t\t\t</keyframe>" << std::endl;
504                        }
505                }
506
507                of << "\t\t\t\t\t</keyframes>" << std::endl;
508                of << "\t\t\t\t</track>" << std::endl;
509
510                return true;
511        }
512
513                       
514                       
515#endif
Note: See TracBrowser for help on using the repository browser.