fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / FileIO / Ogre / OSGOgreSkeletonReader.cpp
blob4e35e4d87d47f786d60ced97a73930c346ba653a
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2010 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #include "OSGOgreSkeletonReader.h"
40 #include "OSGOgreLog.h"
42 #include "OSGAnimKeyFrameTemplate.h"
43 #include "OSGAnimTargetAttachment.h"
44 #include "OSGConceptPropertyChecks.h"
45 #include "OSGNameAttachment.h"
46 #include "OSGQuaternion.h"
47 #include "OSGSkeleton.h"
48 #include "OSGSkeletonOgreJoint.h"
49 #include "OSGVector.h"
52 OSG_BEGIN_NAMESPACE
54 const std::string OgreSkeletonReader::_versionString ("[Serializer_v1.10]");
55 const std::size_t OgreSkeletonReader::_boneLengthNoScale (_chunkHeaderSize + 1 * sizeof(UInt16) + 7 * sizeof(Real32));
56 const std::size_t OgreSkeletonReader::_keyFrameLengthNoScale(_chunkHeaderSize + 8 * sizeof(Real32));
58 /* explicit */
59 OgreSkeletonReader::OgreSkeletonReader( std::istream &is,
60 const OgreOptions &options)
61 : Inherited(is),
62 _options (options),
63 _skel (),
64 _globals ()
68 /* virtual */
69 OgreSkeletonReader::~OgreSkeletonReader(void)
73 void
74 OgreSkeletonReader::read(void)
76 OSG_OGRE_LOG(("OgreSkeletonReader::read\n"));
78 UInt16 headerId = readUInt16(_is);
80 if(_is)
82 if(headerId == CHUNK_HEADER)
84 std::string version = readString(_is);
86 if(version == _versionString)
88 readContent();
90 else
92 SWARNING << "OgreSkeletonReader::read: Unsupported version '"
93 << version << "'." << std::endl;
96 else
98 SWARNING << "OgreSkeletonReader::read: Unrecognized file header."
99 << std::endl;
102 else
104 SWARNING << "OgreSkeletonReader::read: Bad stream."
105 << std::endl;
109 Skeleton*
110 OgreSkeletonReader::getSkeleton(void)
112 return _skel;
115 GlobalsAttachment*
116 OgreSkeletonReader::getGlobals(void)
118 return _globals;
121 void
122 OgreSkeletonReader::readContent(void)
124 OSG_OGRE_LOG(("OgreSkeletonReader::readContent\n"));
126 JointNodeStore joints;
128 bool stop = false;
130 while(_is)
132 readChunkHeader(_is);
134 switch(_header.chunkId)
136 case CHUNK_BONE:
137 readBone(joints);
138 break;
140 case CHUNK_BONE_PARENT:
141 readBoneParent(joints);
142 break;
144 case CHUNK_ANIMATION:
145 readAnimation(joints);
146 break;
148 case CHUNK_ANIMATION_LINK:
149 readAnimationLink();
150 break;
152 default:
153 OSG_OGRE_LOG(("OgreSkeletonReader::readContent: Unknown chunkId '0x%x'\n",
154 _header.chunkId));
155 stop = true;
156 break;
159 if(stop == true)
161 skip(_is, -_chunkHeaderSize);
162 break;
166 calcInvBindMatrices(joints);
168 // construct skeleton
169 _skel = Skeleton::create();
171 JointNodeStore::const_iterator jIt = joints.begin();
172 JointNodeStore::const_iterator jEnd = joints.end ();
174 for(; jIt != jEnd; ++jIt)
176 if((*jIt) != NULL && (*jIt)->getParent() == NULL)
178 #ifndef OSG_OGRE_SILENT
179 SkeletonOgreJoint* joint =
180 dynamic_cast<SkeletonOgreJoint*>((*jIt)->getCore());
181 #endif
183 OSG_OGRE_LOG(("OgreSkeletonReader::readContent: "
184 "adding root joint id '%u'\n", joint->getJointId()));
186 _skel->editMFRoots()->push_back(*jIt);
191 void
192 OgreSkeletonReader::readBone(JointNodeStore &joints)
194 std::string boneName = readString(_is);
195 UInt16 boneId = readUInt16(_is);
196 Vec3f translate;
197 Quaternion rotate;
198 Vec3f scale(1.f, 1.f, 1.f);
200 translate[0] = readReal32(_is);
201 translate[1] = readReal32(_is);
202 translate[2] = readReal32(_is);
204 rotate[0] = readReal32(_is);
205 rotate[1] = readReal32(_is);
206 rotate[2] = readReal32(_is);
207 rotate[3] = readReal32(_is);
208 rotate.normalize();
210 if(_header.chunkSize > _boneLengthNoScale)
212 scale[0] = readReal32(_is);
213 scale[1] = readReal32(_is);
214 scale[2] = readReal32(_is);
217 Vec3f axis;
218 Real32 angle;
219 rotate.getValueAsAxisDeg(axis, angle);
221 OSG_OGRE_LOG(("OgreSkeletonReader::readBone: boneName '%s' "
222 "boneId '%u' translate '(%f %f %f)' rotate '(%f %f %f %f)' "
223 "scale '(%f %f %f)'\n",
224 boneName.c_str(), boneId, translate[0], translate[1], translate[2],
225 axis[0], axis[1], axis[2], angle, scale[0], scale[1], scale[2]));
227 SkeletonOgreJointUnrecPtr joint = SkeletonOgreJoint::create();
228 NodeUnrecPtr jointN = makeNodeFor(joint);
229 joint->setJointId(boneId);
230 joint->setTranslate(translate);
231 joint->setScale (scale);
232 joint->setRotate (rotate);
234 setTargetId(joint, boneName);
235 setName (jointN, boneName);
237 if(boneId >= joints.size())
238 joints.resize(boneId + 1, NULL);
240 joints[boneId] = jointN;
243 void
244 OgreSkeletonReader::readBoneParent(JointNodeStore &joints)
246 UInt16 boneId = readUInt16(_is);
247 UInt16 parentId = readUInt16(_is);
249 OSG_OGRE_LOG(("OgreSkeletonReader::readBoneParent: "
250 "boneId '%u' parentId '%u'\n", boneId, parentId));
252 joints[parentId]->addChild(joints[boneId]);
255 void
256 OgreSkeletonReader::readAnimation(JointNodeStore &joints)
258 if(_options.getLoadAnimations() == true)
260 std::string animName = readString(_is);
261 Real32 animLen = readReal32(_is);
263 osgSinkUnusedWarning(animLen);
265 OSG_OGRE_LOG(("OgreSkeletonReader::readAnimation: "
266 "animName '%s' animLen '%f'\n", animName.c_str(), animLen));
268 AnimTemplateUnrecPtr animTmpl = AnimKeyFrameTemplate::create();
269 animTmpl->setName(animName);
271 bool stop = false;
273 while(_is)
275 readChunkHeader(_is);
277 switch(_header.chunkId)
279 case CHUNK_ANIMATION_TRACK:
280 readAnimationTrack(joints, animTmpl);
281 break;
283 default:
284 stop = true;
285 break;
288 if(stop == true)
290 skip(_is, -_chunkHeaderSize);
291 break;
295 if(_globals == NULL)
296 _globals = GlobalsAttachment::create();
298 _globals->editMFElements()->push_back(animTmpl);
300 else
302 skip(_is, _header.chunkSize - _chunkHeaderSize);
306 void
307 OgreSkeletonReader::readAnimationTrack(JointNodeStore &joints,
308 AnimTemplate *animTmpl)
310 UInt16 boneId = readUInt16(_is);
312 std::string boneName;
313 getTargetId(joints[boneId]->getCore(), boneName);
315 // OSG_OGRE_LOG(("OgreSkeletonReader::readAnimationTrack: boneId '%u' boneName '%s'\n",
316 // boneId, boneName.c_str()));
318 AnimVec3fDataSourceUnrecPtr translateSrc = AnimVec3fDataSource ::create();
319 AnimVec3fDataSourceUnrecPtr scaleSrc = AnimVec3fDataSource ::create();
320 AnimQuaternionDataSourceUnrecPtr rotateSrc = AnimQuaternionDataSource::create();
322 translateSrc->editMFInterpolationModes()->push_back(AnimKeyFrameDataSource::IM_Linear);
323 scaleSrc ->editMFInterpolationModes()->push_back(AnimKeyFrameDataSource::IM_Linear);
324 rotateSrc ->editMFInterpolationModes()->push_back(AnimKeyFrameDataSource::IM_Linear);
326 bool stop = false;
328 while(_is)
330 readChunkHeader(_is);
332 switch(_header.chunkId)
334 case CHUNK_ANIMATION_TRACK_KEYFRAME:
335 readAnimationTrackKeyFrame(translateSrc, scaleSrc, rotateSrc);
336 break;
338 default:
339 stop = true;
340 break;
343 if(stop == true)
345 skip(_is, -_chunkHeaderSize);
346 break;
350 if(translateSrc->getMFInValues()->empty() == false)
352 animTmpl->editMFSources ()->push_back(translateSrc);
353 animTmpl->editMFTargetIds()->push_back(boneName + ".offsetTranslate");
356 if(scaleSrc->getMFInValues()->empty() == false)
358 animTmpl->editMFSources ()->push_back(scaleSrc);
359 animTmpl->editMFTargetIds()->push_back(boneName + ".offsetScale");
362 if(rotateSrc->getMFInValues()->empty() == false)
364 animTmpl->editMFSources ()->push_back(rotateSrc);
365 animTmpl->editMFTargetIds()->push_back(boneName + ".offsetRotate");
369 void
370 OgreSkeletonReader::readAnimationTrackKeyFrame(AnimVec3fDataSource *translateSrc,
371 AnimVec3fDataSource *scaleSrc,
372 AnimQuaternionDataSource *rotateSrc )
374 Real32 time = readReal32(_is);
375 Vec3f translate;
376 Quaternion rotate;
377 Vec3f scale(1.f, 1.f, 1.f);
378 bool hasScale = false;
380 rotate[0] = readReal32(_is);
381 rotate[1] = readReal32(_is);
382 rotate[2] = readReal32(_is);
383 rotate[3] = readReal32(_is);
384 rotate.normalize();
386 translate[0] = readReal32(_is);
387 translate[1] = readReal32(_is);
388 translate[2] = readReal32(_is);
390 if(_header.chunkSize > _keyFrameLengthNoScale)
392 hasScale = true;
394 scale[0] = readReal32(_is);
395 scale[1] = readReal32(_is);
396 scale[2] = readReal32(_is);
399 Vec3f axis;
400 Real32 angle;
401 rotate.getValueAsAxisDeg(axis, angle);
403 // OSG_OGRE_LOG(("OgreSkeletonReader::readAnimationTrackKeyFrame: "
404 // "time '%f' rotate '(%f %f %f %f)' translate '(%f %f %f)' "
405 // "scale '(%f %f %f)'\n",
406 // time, axis[0], axis[1], axis[2], angle,
407 // translate[0], translate[1], translate[2],
408 // scale[0], scale[1], scale[2]));
410 translateSrc->editMFInValues()->push_back(time);
411 translateSrc->editMFValues ()->push_back(translate);
413 if(hasScale == true)
415 scaleSrc ->editMFInValues()->push_back(time);
416 scaleSrc ->editMFValues ()->push_back(scale);
419 rotateSrc ->editMFInValues()->push_back(time);
420 rotateSrc ->editMFValues ()->push_back(rotate);
423 void
424 OgreSkeletonReader::readAnimationLink(void)
426 std::string skelName = readString(_is);
427 Real32 scale = readReal32(_is);
429 osgSinkUnusedWarning(skelName);
430 osgSinkUnusedWarning(scale);
432 OSG_OGRE_LOG(("OgreSkeletonReader::readAnimationLink "
433 "skelName '%s' scale '%f'\n", skelName.c_str(), scale));
436 void
437 OgreSkeletonReader::calcInvBindMatrices(JointNodeStore &joints)
439 OSG_OGRE_LOG(("OgreSkeletonReader::calcInvBindMatrices\n"));
441 JointNodeStore::iterator jIt = joints.begin();
442 JointNodeStore::iterator jEnd = joints.end ();
444 for(; jIt != jEnd; ++jIt)
446 if((*jIt) != NULL && (*jIt)->getParent() == NULL)
448 calcInvBindMatrix(*jIt, Vec3f(0.f, 0.f, 0.f),
449 Vec3f(1.f, 1.f, 1.f),
450 Quaternion::identity());
455 void
456 OgreSkeletonReader::calcInvBindMatrix(Node *node,
457 Vec3f parentTranslate,
458 Vec3f parentScale,
459 Quaternion parentRotate)
461 SkeletonOgreJoint *joint = dynamic_cast<SkeletonOgreJoint *>(node->getCore());
463 Quaternion rotate(parentRotate);
464 Vec3f scale (parentScale );
465 Vec3f translate;
467 if(joint != NULL)
469 rotate.mult(joint->getRotate());
471 scale[0] *= joint->getScale()[0];
472 scale[1] *= joint->getScale()[1];
473 scale[2] *= joint->getScale()[2];
475 translate = joint->getTranslate();
476 translate[0] *= parentScale[0];
477 translate[1] *= parentScale[1];
478 translate[2] *= parentScale[2];
480 parentRotate.multVec(translate, translate);
482 translate += parentTranslate;
484 joint->setInvBindTranslate(-translate);
485 joint->setInvBindScale (Vec3f(1.f/scale[0], 1.f/scale[1], 1.f/scale[2]));
486 joint->setInvBindRotate (rotate.inverse());
488 Vec3f axis;
489 Real32 angle;
490 joint->getInvBindRotate().getValueAsAxisDeg(axis, angle);
493 Node::MFChildrenType::const_iterator cIt = node->getMFChildren()->begin();
494 Node::MFChildrenType::const_iterator cEnd = node->getMFChildren()->end ();
496 for(; cIt != cEnd; ++cIt)
498 calcInvBindMatrix(*cIt, translate, scale, rotate);
502 OSG_END_NAMESPACE