rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41 #include "AssimpPCH.h"
|
nuclear@0
|
42
|
nuclear@0
|
43 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "OgreImporter.hpp"
|
nuclear@0
|
46 #include "TinyFormatter.h"
|
nuclear@0
|
47
|
nuclear@0
|
48 using namespace std;
|
nuclear@0
|
49
|
nuclear@0
|
50 namespace Assimp
|
nuclear@0
|
51 {
|
nuclear@0
|
52 namespace Ogre
|
nuclear@0
|
53 {
|
nuclear@0
|
54
|
nuclear@0
|
55
|
nuclear@0
|
56
|
nuclear@0
|
57 void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vector<Animation> &Animations) const
|
nuclear@0
|
58 {
|
nuclear@0
|
59 const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
|
nuclear@0
|
60 (void)m_CurrentScene;
|
nuclear@0
|
61
|
nuclear@0
|
62
|
nuclear@0
|
63 //most likely the skeleton file will only end with .skeleton
|
nuclear@0
|
64 //But this is a xml reader, so we need: .skeleton.xml
|
nuclear@0
|
65 FileName+=".xml";
|
nuclear@0
|
66
|
nuclear@0
|
67 DefaultLogger::get()->debug(string("Loading Skeleton: ")+FileName);
|
nuclear@0
|
68
|
nuclear@0
|
69 //Open the File:
|
nuclear@0
|
70 boost::scoped_ptr<IOStream> File(m_CurrentIOHandler->Open(FileName));
|
nuclear@0
|
71 if(NULL==File.get())
|
nuclear@0
|
72 throw DeadlyImportError("Failed to open skeleton file "+FileName+".");
|
nuclear@0
|
73
|
nuclear@0
|
74 //Read the Mesh File:
|
nuclear@0
|
75 boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get()));
|
nuclear@0
|
76 XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get());
|
nuclear@0
|
77 if(!SkeletonFile)
|
nuclear@0
|
78 throw DeadlyImportError(string("Failed to create XML Reader for ")+FileName);
|
nuclear@0
|
79
|
nuclear@0
|
80 XmlRead(SkeletonFile);
|
nuclear@0
|
81 if(string("skeleton")!=SkeletonFile->getNodeName())
|
nuclear@0
|
82 throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+FileName);
|
nuclear@0
|
83
|
nuclear@0
|
84
|
nuclear@0
|
85
|
nuclear@0
|
86 //------------------------------------load bones-----------------------------------------
|
nuclear@0
|
87 XmlRead(SkeletonFile);
|
nuclear@0
|
88 if(string("bones")!=SkeletonFile->getNodeName())
|
nuclear@0
|
89 throw DeadlyImportError("No bones node in skeleton "+FileName);
|
nuclear@0
|
90
|
nuclear@0
|
91 XmlRead(SkeletonFile);
|
nuclear@0
|
92
|
nuclear@0
|
93 while(string("bone")==SkeletonFile->getNodeName())
|
nuclear@0
|
94 {
|
nuclear@0
|
95 //TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appear, so what....
|
nuclear@0
|
96
|
nuclear@0
|
97 //read a new bone:
|
nuclear@0
|
98 Bone NewBone;
|
nuclear@0
|
99 NewBone.Id=GetAttribute<int>(SkeletonFile, "id");
|
nuclear@0
|
100 NewBone.Name=GetAttribute<string>(SkeletonFile, "name");
|
nuclear@0
|
101
|
nuclear@0
|
102 //load the position:
|
nuclear@0
|
103 XmlRead(SkeletonFile);
|
nuclear@0
|
104 if(string("position")!=SkeletonFile->getNodeName())
|
nuclear@0
|
105 throw DeadlyImportError("Position is not first node in Bone!");
|
nuclear@0
|
106 NewBone.Position.x=GetAttribute<float>(SkeletonFile, "x");
|
nuclear@0
|
107 NewBone.Position.y=GetAttribute<float>(SkeletonFile, "y");
|
nuclear@0
|
108 NewBone.Position.z=GetAttribute<float>(SkeletonFile, "z");
|
nuclear@0
|
109
|
nuclear@0
|
110 //Rotation:
|
nuclear@0
|
111 XmlRead(SkeletonFile);
|
nuclear@0
|
112 if(string("rotation")!=SkeletonFile->getNodeName())
|
nuclear@0
|
113 throw DeadlyImportError("Rotation is not the second node in Bone!");
|
nuclear@0
|
114 NewBone.RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
|
nuclear@0
|
115 XmlRead(SkeletonFile);
|
nuclear@0
|
116 if(string("axis")!=SkeletonFile->getNodeName())
|
nuclear@0
|
117 throw DeadlyImportError("No axis specified for bone rotation!");
|
nuclear@0
|
118 NewBone.RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
|
nuclear@0
|
119 NewBone.RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
|
nuclear@0
|
120 NewBone.RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
|
nuclear@0
|
121
|
nuclear@0
|
122 //append the newly loaded bone to the bone list
|
nuclear@0
|
123 Bones.push_back(NewBone);
|
nuclear@0
|
124
|
nuclear@0
|
125 //Proceed to the next bone:
|
nuclear@0
|
126 XmlRead(SkeletonFile);
|
nuclear@0
|
127 }
|
nuclear@0
|
128 //The bones in the file a not neccesarly ordered by there id's so we do it now:
|
nuclear@0
|
129 std::sort(Bones.begin(), Bones.end());
|
nuclear@0
|
130
|
nuclear@0
|
131 //now the id of each bone should be equal to its position in the vector:
|
nuclear@0
|
132 //so we do a simple check:
|
nuclear@0
|
133 {
|
nuclear@0
|
134 bool IdsOk=true;
|
nuclear@0
|
135 for(int i=0; i<static_cast<signed int>(Bones.size()); ++i)//i is signed, because all Id's are also signed!
|
nuclear@0
|
136 {
|
nuclear@0
|
137 if(Bones[i].Id!=i)
|
nuclear@0
|
138 IdsOk=false;
|
nuclear@0
|
139 }
|
nuclear@0
|
140 if(!IdsOk)
|
nuclear@0
|
141 throw DeadlyImportError("Bone Ids are not valid!"+FileName);
|
nuclear@0
|
142 }
|
nuclear@0
|
143 DefaultLogger::get()->debug((Formatter::format(),"Number of bones: ",Bones.size()));
|
nuclear@0
|
144 //________________________________________________________________________________
|
nuclear@0
|
145
|
nuclear@0
|
146
|
nuclear@0
|
147
|
nuclear@0
|
148
|
nuclear@0
|
149
|
nuclear@0
|
150
|
nuclear@0
|
151 //----------------------------load bonehierarchy--------------------------------
|
nuclear@0
|
152 if(string("bonehierarchy")!=SkeletonFile->getNodeName())
|
nuclear@0
|
153 throw DeadlyImportError("no bonehierarchy node in "+FileName);
|
nuclear@0
|
154
|
nuclear@0
|
155 DefaultLogger::get()->debug("loading bonehierarchy...");
|
nuclear@0
|
156 XmlRead(SkeletonFile);
|
nuclear@0
|
157 while(string("boneparent")==SkeletonFile->getNodeName())
|
nuclear@0
|
158 {
|
nuclear@0
|
159 string Child, Parent;
|
nuclear@0
|
160 Child=GetAttribute<string>(SkeletonFile, "bone");
|
nuclear@0
|
161 Parent=GetAttribute<string>(SkeletonFile, "parent");
|
nuclear@0
|
162
|
nuclear@0
|
163 unsigned int ChildId, ParentId;
|
nuclear@0
|
164 ChildId=find(Bones.begin(), Bones.end(), Child)->Id;
|
nuclear@0
|
165 ParentId=find(Bones.begin(), Bones.end(), Parent)->Id;
|
nuclear@0
|
166
|
nuclear@0
|
167 Bones[ChildId].ParentId=ParentId;
|
nuclear@0
|
168 Bones[ParentId].Children.push_back(ChildId);
|
nuclear@0
|
169
|
nuclear@0
|
170 XmlRead(SkeletonFile);
|
nuclear@0
|
171 }
|
nuclear@0
|
172 //_____________________________________________________________________________
|
nuclear@0
|
173
|
nuclear@0
|
174
|
nuclear@0
|
175 //--------- Calculate the WorldToBoneSpace Matrix recursively for all bones: ------------------
|
nuclear@0
|
176 BOOST_FOREACH(Bone &theBone, Bones)
|
nuclear@0
|
177 {
|
nuclear@0
|
178 if(-1==theBone.ParentId) //the bone is a root bone
|
nuclear@0
|
179 {
|
nuclear@0
|
180 theBone.CalculateBoneToWorldSpaceMatrix(Bones);
|
nuclear@0
|
181 }
|
nuclear@0
|
182 }
|
nuclear@0
|
183 //_______________________________________________________________________
|
nuclear@0
|
184
|
nuclear@0
|
185
|
nuclear@0
|
186 //---------------------------load animations-----------------------------
|
nuclear@0
|
187 if(string("animations")==SkeletonFile->getNodeName())//animations are optional values
|
nuclear@0
|
188 {
|
nuclear@0
|
189 DefaultLogger::get()->debug("Loading Animations");
|
nuclear@0
|
190 XmlRead(SkeletonFile);
|
nuclear@0
|
191 while(string("animation")==SkeletonFile->getNodeName())
|
nuclear@0
|
192 {
|
nuclear@0
|
193 Animation NewAnimation;
|
nuclear@0
|
194 NewAnimation.Name=GetAttribute<string>(SkeletonFile, "name");
|
nuclear@0
|
195 NewAnimation.Length=GetAttribute<float>(SkeletonFile, "length");
|
nuclear@0
|
196
|
nuclear@0
|
197 //Load all Tracks
|
nuclear@0
|
198 XmlRead(SkeletonFile);
|
nuclear@0
|
199 if(string("tracks")!=SkeletonFile->getNodeName())
|
nuclear@0
|
200 throw DeadlyImportError("no tracks node in animation");
|
nuclear@0
|
201 XmlRead(SkeletonFile);
|
nuclear@0
|
202 while(string("track")==SkeletonFile->getNodeName())
|
nuclear@0
|
203 {
|
nuclear@0
|
204 Track NewTrack;
|
nuclear@0
|
205 NewTrack.BoneName=GetAttribute<string>(SkeletonFile, "bone");
|
nuclear@0
|
206
|
nuclear@0
|
207 //Load all keyframes;
|
nuclear@0
|
208 XmlRead(SkeletonFile);
|
nuclear@0
|
209 if(string("keyframes")!=SkeletonFile->getNodeName())
|
nuclear@0
|
210 throw DeadlyImportError("no keyframes node!");
|
nuclear@0
|
211 XmlRead(SkeletonFile);
|
nuclear@0
|
212 while(string("keyframe")==SkeletonFile->getNodeName())
|
nuclear@0
|
213 {
|
nuclear@0
|
214 Keyframe NewKeyframe;
|
nuclear@0
|
215 NewKeyframe.Time=GetAttribute<float>(SkeletonFile, "time");
|
nuclear@0
|
216
|
nuclear@0
|
217 //loop over the attributes:
|
nuclear@0
|
218
|
nuclear@0
|
219 while(true) //will quit, if a Node is not a animationkey
|
nuclear@0
|
220 {
|
nuclear@0
|
221 XmlRead(SkeletonFile);
|
nuclear@0
|
222
|
nuclear@0
|
223 //If any property doesn't show up, it will keep its initialization value
|
nuclear@0
|
224
|
nuclear@0
|
225 //Position:
|
nuclear@0
|
226 if(string("translate")==SkeletonFile->getNodeName())
|
nuclear@0
|
227 {
|
nuclear@0
|
228 NewKeyframe.Position.x=GetAttribute<float>(SkeletonFile, "x");
|
nuclear@0
|
229 NewKeyframe.Position.y=GetAttribute<float>(SkeletonFile, "y");
|
nuclear@0
|
230 NewKeyframe.Position.z=GetAttribute<float>(SkeletonFile, "z");
|
nuclear@0
|
231 }
|
nuclear@0
|
232
|
nuclear@0
|
233 //Rotation:
|
nuclear@0
|
234 else if(string("rotate")==SkeletonFile->getNodeName())
|
nuclear@0
|
235 {
|
nuclear@0
|
236 float RotationAngle=GetAttribute<float>(SkeletonFile, "angle");
|
nuclear@0
|
237 aiVector3D RotationAxis;
|
nuclear@0
|
238 XmlRead(SkeletonFile);
|
nuclear@0
|
239 if(string("axis")!=SkeletonFile->getNodeName())
|
nuclear@0
|
240 throw DeadlyImportError("No axis for keyframe rotation!");
|
nuclear@0
|
241 RotationAxis.x=GetAttribute<float>(SkeletonFile, "x");
|
nuclear@0
|
242 RotationAxis.y=GetAttribute<float>(SkeletonFile, "y");
|
nuclear@0
|
243 RotationAxis.z=GetAttribute<float>(SkeletonFile, "z");
|
nuclear@0
|
244
|
nuclear@0
|
245 if(0==RotationAxis.x && 0==RotationAxis.y && 0==RotationAxis.z)//we have an invalid rotation axis
|
nuclear@0
|
246 {
|
nuclear@0
|
247 RotationAxis.x=1.0f;
|
nuclear@0
|
248 if(0!=RotationAngle)//if we don't rotate at all, the axis does not matter
|
nuclear@0
|
249 {
|
nuclear@0
|
250 DefaultLogger::get()->warn("Invalid Rotation Axis in Keyframe!");
|
nuclear@0
|
251 }
|
nuclear@0
|
252 }
|
nuclear@0
|
253 NewKeyframe.Rotation=aiQuaternion(RotationAxis, RotationAngle);
|
nuclear@0
|
254 }
|
nuclear@0
|
255
|
nuclear@0
|
256 //Scaling:
|
nuclear@0
|
257 else if(string("scale")==SkeletonFile->getNodeName())
|
nuclear@0
|
258 {
|
nuclear@0
|
259 NewKeyframe.Scaling.x=GetAttribute<float>(SkeletonFile, "x");
|
nuclear@0
|
260 NewKeyframe.Scaling.y=GetAttribute<float>(SkeletonFile, "y");
|
nuclear@0
|
261 NewKeyframe.Scaling.z=GetAttribute<float>(SkeletonFile, "z");
|
nuclear@0
|
262 }
|
nuclear@0
|
263
|
nuclear@0
|
264 //we suppose, that we read all attributes and this is a new keyframe or the end of the animation
|
nuclear@0
|
265 else
|
nuclear@0
|
266 break;
|
nuclear@0
|
267 }
|
nuclear@0
|
268
|
nuclear@0
|
269 NewTrack.Keyframes.push_back(NewKeyframe);
|
nuclear@0
|
270 }
|
nuclear@0
|
271
|
nuclear@0
|
272 NewAnimation.Tracks.push_back(NewTrack);
|
nuclear@0
|
273 }
|
nuclear@0
|
274
|
nuclear@0
|
275 Animations.push_back(NewAnimation);
|
nuclear@0
|
276 }
|
nuclear@0
|
277 }
|
nuclear@0
|
278 //_____________________________________________________________________________
|
nuclear@0
|
279
|
nuclear@0
|
280 }
|
nuclear@0
|
281
|
nuclear@0
|
282
|
nuclear@0
|
283 void OgreImporter::CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &/*Animations*/)
|
nuclear@0
|
284 {
|
nuclear@0
|
285 if(!m_CurrentScene->mRootNode)
|
nuclear@0
|
286 throw DeadlyImportError("No root node exists!!");
|
nuclear@0
|
287 if(0!=m_CurrentScene->mRootNode->mNumChildren)
|
nuclear@0
|
288 throw DeadlyImportError("Root Node already has childnodes!");
|
nuclear@0
|
289
|
nuclear@0
|
290
|
nuclear@0
|
291 //Createt the assimp bone hierarchy
|
nuclear@0
|
292 vector<aiNode*> RootBoneNodes;
|
nuclear@0
|
293 BOOST_FOREACH(const Bone &theBone, Bones)
|
nuclear@0
|
294 {
|
nuclear@0
|
295 if(-1==theBone.ParentId) //the bone is a root bone
|
nuclear@0
|
296 {
|
nuclear@0
|
297 //which will recursily add all other nodes
|
nuclear@0
|
298 RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));
|
nuclear@0
|
299 }
|
nuclear@0
|
300 }
|
nuclear@0
|
301
|
nuclear@0
|
302 if(RootBoneNodes.size() > 0)
|
nuclear@0
|
303 {
|
nuclear@0
|
304 m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size();
|
nuclear@0
|
305 m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()];
|
nuclear@0
|
306 memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size());
|
nuclear@0
|
307 }
|
nuclear@0
|
308 }
|
nuclear@0
|
309
|
nuclear@0
|
310
|
nuclear@0
|
311 void OgreImporter::PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations)
|
nuclear@0
|
312 {
|
nuclear@0
|
313 //-----------------Create the Assimp Animations --------------------
|
nuclear@0
|
314 if(Animations.size()>0)//Maybe the model had only a skeleton and no animations. (If it also has no skeleton, this function would'nt have been called
|
nuclear@0
|
315 {
|
nuclear@0
|
316 m_CurrentScene->mNumAnimations=Animations.size();
|
nuclear@0
|
317 m_CurrentScene->mAnimations=new aiAnimation*[Animations.size()];
|
nuclear@0
|
318 for(unsigned int i=0; i<Animations.size(); ++i)//create all animations
|
nuclear@0
|
319 {
|
nuclear@0
|
320 aiAnimation* NewAnimation=new aiAnimation();
|
nuclear@0
|
321 NewAnimation->mName=Animations[i].Name;
|
nuclear@0
|
322 NewAnimation->mDuration=Animations[i].Length;
|
nuclear@0
|
323 NewAnimation->mTicksPerSecond=1.0f;
|
nuclear@0
|
324
|
nuclear@0
|
325 //Create all tracks in this animation
|
nuclear@0
|
326 NewAnimation->mNumChannels=Animations[i].Tracks.size();
|
nuclear@0
|
327 NewAnimation->mChannels=new aiNodeAnim*[Animations[i].Tracks.size()];
|
nuclear@0
|
328 for(unsigned int j=0; j<Animations[i].Tracks.size(); ++j)
|
nuclear@0
|
329 {
|
nuclear@0
|
330 aiNodeAnim* NewNodeAnim=new aiNodeAnim();
|
nuclear@0
|
331 NewNodeAnim->mNodeName=Animations[i].Tracks[j].BoneName;
|
nuclear@0
|
332
|
nuclear@0
|
333 //we need this, to acces the bones default pose, which we need to make keys absolute to the default bone pose
|
nuclear@0
|
334 vector<Bone>::const_iterator CurBone=find(Bones.begin(), Bones.end(), NewNodeAnim->mNodeName);
|
nuclear@0
|
335 aiMatrix4x4 t0, t1;
|
nuclear@0
|
336 aiMatrix4x4 DefBonePose=aiMatrix4x4::Translation(CurBone->Position, t1)
|
nuclear@0
|
337 * aiMatrix4x4::Rotation(CurBone->RotationAngle, CurBone->RotationAxis, t0);
|
nuclear@0
|
338
|
nuclear@0
|
339
|
nuclear@0
|
340 //Create the keyframe arrays...
|
nuclear@0
|
341 unsigned int KeyframeCount=Animations[i].Tracks[j].Keyframes.size();
|
nuclear@0
|
342 NewNodeAnim->mNumPositionKeys=KeyframeCount;
|
nuclear@0
|
343 NewNodeAnim->mNumRotationKeys=KeyframeCount;
|
nuclear@0
|
344 NewNodeAnim->mNumScalingKeys =KeyframeCount;
|
nuclear@0
|
345 NewNodeAnim->mPositionKeys=new aiVectorKey[KeyframeCount];
|
nuclear@0
|
346 NewNodeAnim->mRotationKeys=new aiQuatKey[KeyframeCount];
|
nuclear@0
|
347 NewNodeAnim->mScalingKeys =new aiVectorKey[KeyframeCount];
|
nuclear@0
|
348
|
nuclear@0
|
349 //...and fill them
|
nuclear@0
|
350 for(unsigned int k=0; k<KeyframeCount; ++k)
|
nuclear@0
|
351 {
|
nuclear@0
|
352 aiMatrix4x4 t2, t3;
|
nuclear@0
|
353
|
nuclear@0
|
354 //Create a matrix to transfrom a vector from the bones default pose to the bone bones in this animation key
|
nuclear@0
|
355 aiMatrix4x4 PoseToKey=
|
nuclear@0
|
356 aiMatrix4x4::Translation(Animations[i].Tracks[j].Keyframes[k].Position, t3) //pos
|
nuclear@0
|
357 * aiMatrix4x4(Animations[i].Tracks[j].Keyframes[k].Rotation.GetMatrix()) //rot
|
nuclear@0
|
358 * aiMatrix4x4::Scaling(Animations[i].Tracks[j].Keyframes[k].Scaling, t2); //scale
|
nuclear@0
|
359
|
nuclear@0
|
360
|
nuclear@0
|
361 //calculate the complete transformation from world space to bone space
|
nuclear@0
|
362 aiMatrix4x4 CompleteTransform=DefBonePose * PoseToKey;
|
nuclear@0
|
363
|
nuclear@0
|
364 aiVector3D Pos;
|
nuclear@0
|
365 aiQuaternion Rot;
|
nuclear@0
|
366 aiVector3D Scale;
|
nuclear@0
|
367
|
nuclear@0
|
368 CompleteTransform.Decompose(Scale, Rot, Pos);
|
nuclear@0
|
369
|
nuclear@0
|
370 double Time=Animations[i].Tracks[j].Keyframes[k].Time;
|
nuclear@0
|
371
|
nuclear@0
|
372 NewNodeAnim->mPositionKeys[k].mTime=Time;
|
nuclear@0
|
373 NewNodeAnim->mPositionKeys[k].mValue=Pos;
|
nuclear@0
|
374
|
nuclear@0
|
375 NewNodeAnim->mRotationKeys[k].mTime=Time;
|
nuclear@0
|
376 NewNodeAnim->mRotationKeys[k].mValue=Rot;
|
nuclear@0
|
377
|
nuclear@0
|
378 NewNodeAnim->mScalingKeys[k].mTime=Time;
|
nuclear@0
|
379 NewNodeAnim->mScalingKeys[k].mValue=Scale;
|
nuclear@0
|
380 }
|
nuclear@0
|
381
|
nuclear@0
|
382 NewAnimation->mChannels[j]=NewNodeAnim;
|
nuclear@0
|
383 }
|
nuclear@0
|
384
|
nuclear@0
|
385 m_CurrentScene->mAnimations[i]=NewAnimation;
|
nuclear@0
|
386 }
|
nuclear@0
|
387 }
|
nuclear@0
|
388 //TODO: Auf nicht vorhandene Animationskeys achten!
|
nuclear@0
|
389 //#pragma warning (s.o.)
|
nuclear@0
|
390 //__________________________________________________________________
|
nuclear@0
|
391 }
|
nuclear@0
|
392
|
nuclear@0
|
393
|
nuclear@0
|
394 aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode)
|
nuclear@0
|
395 {
|
nuclear@0
|
396 //----Create the node for this bone and set its values-----
|
nuclear@0
|
397 aiNode* NewNode=new aiNode(Bones[BoneId].Name);
|
nuclear@0
|
398 NewNode->mParent=ParentNode;
|
nuclear@0
|
399
|
nuclear@0
|
400 aiMatrix4x4 t0,t1;
|
nuclear@0
|
401 NewNode->mTransformation=
|
nuclear@0
|
402 aiMatrix4x4::Translation(Bones[BoneId].Position, t0)
|
nuclear@0
|
403 *aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, t1)
|
nuclear@0
|
404 ;
|
nuclear@0
|
405 //__________________________________________________________
|
nuclear@0
|
406
|
nuclear@0
|
407
|
nuclear@0
|
408 //---------- recursivly create all children Nodes: ----------
|
nuclear@0
|
409 NewNode->mNumChildren=Bones[BoneId].Children.size();
|
nuclear@0
|
410 NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()];
|
nuclear@0
|
411 for(unsigned int i=0; i<Bones[BoneId].Children.size(); ++i)
|
nuclear@0
|
412 {
|
nuclear@0
|
413 NewNode->mChildren[i]=CreateAiNodeFromBone(Bones[BoneId].Children[i], Bones, NewNode);
|
nuclear@0
|
414 }
|
nuclear@0
|
415 //____________________________________________________
|
nuclear@0
|
416
|
nuclear@0
|
417
|
nuclear@0
|
418 return NewNode;
|
nuclear@0
|
419 }
|
nuclear@0
|
420
|
nuclear@0
|
421
|
nuclear@0
|
422 void Bone::CalculateBoneToWorldSpaceMatrix(vector<Bone> &Bones)
|
nuclear@0
|
423 {
|
nuclear@0
|
424 //Calculate the matrix for this bone:
|
nuclear@0
|
425
|
nuclear@0
|
426 aiMatrix4x4 t0,t1;
|
nuclear@0
|
427 aiMatrix4x4 Transf= aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1)
|
nuclear@0
|
428 * aiMatrix4x4::Translation(-Position, t0);
|
nuclear@0
|
429
|
nuclear@0
|
430 if(-1==ParentId)
|
nuclear@0
|
431 {
|
nuclear@0
|
432 BoneToWorldSpace=Transf;
|
nuclear@0
|
433 }
|
nuclear@0
|
434 else
|
nuclear@0
|
435 {
|
nuclear@0
|
436 BoneToWorldSpace=Transf*Bones[ParentId].BoneToWorldSpace;
|
nuclear@0
|
437 }
|
nuclear@0
|
438
|
nuclear@0
|
439
|
nuclear@0
|
440 //and recursivly for all children:
|
nuclear@0
|
441 BOOST_FOREACH(int theChildren, Children)
|
nuclear@0
|
442 {
|
nuclear@0
|
443 Bones[theChildren].CalculateBoneToWorldSpaceMatrix(Bones);
|
nuclear@0
|
444 }
|
nuclear@0
|
445 }
|
nuclear@0
|
446
|
nuclear@0
|
447
|
nuclear@0
|
448 }//namespace Ogre
|
nuclear@0
|
449 }//namespace Assimp
|
nuclear@0
|
450
|
nuclear@0
|
451 #endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER
|