1 //
2 // Copyright (c) 2008-2017 the Urho3D project.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 //
22
23 #include "../Precompiled.h"
24
25 #include "../Graphics/Skeleton.h"
26 #include "../IO/Log.h"
27
28 #include "../DebugNew.h"
29
30 namespace Urho3D
31 {
32
Skeleton()33 Skeleton::Skeleton() :
34 rootBoneIndex_(M_MAX_UNSIGNED)
35 {
36 }
37
~Skeleton()38 Skeleton::~Skeleton()
39 {
40 }
41
Load(Deserializer & source)42 bool Skeleton::Load(Deserializer& source)
43 {
44 ClearBones();
45
46 if (source.IsEof())
47 return false;
48
49 unsigned bones = source.ReadUInt();
50 bones_.Reserve(bones);
51
52 for (unsigned i = 0; i < bones; ++i)
53 {
54 Bone newBone;
55 newBone.name_ = source.ReadString();
56 newBone.nameHash_ = newBone.name_;
57 newBone.parentIndex_ = source.ReadUInt();
58 newBone.initialPosition_ = source.ReadVector3();
59 newBone.initialRotation_ = source.ReadQuaternion();
60 newBone.initialScale_ = source.ReadVector3();
61 source.Read(&newBone.offsetMatrix_.m00_, sizeof(Matrix3x4));
62
63 // Read bone collision data
64 newBone.collisionMask_ = source.ReadUByte();
65 if (newBone.collisionMask_ & BONECOLLISION_SPHERE)
66 newBone.radius_ = source.ReadFloat();
67 if (newBone.collisionMask_ & BONECOLLISION_BOX)
68 newBone.boundingBox_ = source.ReadBoundingBox();
69
70 if (newBone.parentIndex_ == i)
71 rootBoneIndex_ = i;
72
73 bones_.Push(newBone);
74 }
75
76 return true;
77 }
78
Save(Serializer & dest) const79 bool Skeleton::Save(Serializer& dest) const
80 {
81 if (!dest.WriteUInt(bones_.Size()))
82 return false;
83
84 for (unsigned i = 0; i < bones_.Size(); ++i)
85 {
86 const Bone& bone = bones_[i];
87 dest.WriteString(bone.name_);
88 dest.WriteUInt(bone.parentIndex_);
89 dest.WriteVector3(bone.initialPosition_);
90 dest.WriteQuaternion(bone.initialRotation_);
91 dest.WriteVector3(bone.initialScale_);
92 dest.Write(bone.offsetMatrix_.Data(), sizeof(Matrix3x4));
93
94 // Collision info
95 dest.WriteUByte(bone.collisionMask_);
96 if (bone.collisionMask_ & BONECOLLISION_SPHERE)
97 dest.WriteFloat(bone.radius_);
98 if (bone.collisionMask_ & BONECOLLISION_BOX)
99 dest.WriteBoundingBox(bone.boundingBox_);
100 }
101
102 return true;
103 }
104
Define(const Skeleton & src)105 void Skeleton::Define(const Skeleton& src)
106 {
107 ClearBones();
108
109 bones_ = src.bones_;
110 // Make sure we clear node references, if they exist
111 // (AnimatedModel will create new nodes on its own)
112 for (Vector<Bone>::Iterator i = bones_.Begin(); i != bones_.End(); ++i)
113 i->node_.Reset();
114 rootBoneIndex_ = src.rootBoneIndex_;
115 }
116
SetRootBoneIndex(unsigned index)117 void Skeleton::SetRootBoneIndex(unsigned index)
118 {
119 if (index < bones_.Size())
120 rootBoneIndex_ = index;
121 else
122 URHO3D_LOGERROR("Root bone index out of bounds");
123 }
124
ClearBones()125 void Skeleton::ClearBones()
126 {
127 bones_.Clear();
128 rootBoneIndex_ = M_MAX_UNSIGNED;
129 }
130
Reset()131 void Skeleton::Reset()
132 {
133 for (Vector<Bone>::Iterator i = bones_.Begin(); i != bones_.End(); ++i)
134 {
135 if (i->animated_ && i->node_)
136 i->node_->SetTransform(i->initialPosition_, i->initialRotation_, i->initialScale_);
137 }
138 }
139
ResetSilent()140 void Skeleton::ResetSilent()
141 {
142 for (Vector<Bone>::Iterator i = bones_.Begin(); i != bones_.End(); ++i)
143 {
144 if (i->animated_ && i->node_)
145 i->node_->SetTransformSilent(i->initialPosition_, i->initialRotation_, i->initialScale_);
146 }
147 }
148
149
GetRootBone()150 Bone* Skeleton::GetRootBone()
151 {
152 return GetBone(rootBoneIndex_);
153 }
154
GetBone(unsigned index)155 Bone* Skeleton::GetBone(unsigned index)
156 {
157 return index < bones_.Size() ? &bones_[index] : (Bone*)0;
158 }
159
GetBone(const String & name)160 Bone* Skeleton::GetBone(const String& name)
161 {
162 return GetBone(StringHash(name));
163 }
164
GetBone(const char * name)165 Bone* Skeleton::GetBone(const char* name)
166 {
167 return GetBone(StringHash(name));
168 }
169
GetBone(StringHash nameHash)170 Bone* Skeleton::GetBone(StringHash nameHash)
171 {
172 for (Vector<Bone>::Iterator i = bones_.Begin(); i != bones_.End(); ++i)
173 {
174 if (i->nameHash_ == nameHash)
175 return &(*i);
176 }
177
178 return 0;
179 }
180
181 }
182