1// tSkeleton.cpp 
2// 
3// This file implements scene skeletons as a hierarchy of joints and poses that, well, pose a skeleton. 
4// 
5// Copyright (c) 2006, 2017 Tristan Grimmer. 
6// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
7// granted, provided that the above copyright notice and this permission notice appear in all copies. 
8// 
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
10// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
11// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
12// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
13// PERFORMANCE OF THIS SOFTWARE. 
14 
15#include <Math/tVector3.h> 
16#include <Math/tQuaternion.h> 
17#include "Scene/tSkeleton.h" 
18using namespace tMath; 
19namespace tScene 
20{ 
21 
22 
23void tJoint::Save(tChunkWriter& chunk) const 
24{ 
25 chunk.Begin(tChunkID::Scene_Joint); 
26 { 
27 tObject::Save(chunk); 
28 
29 chunk.Begin(tChunkID::Scene_JointTranslation); 
30 chunk.Write(Translation); 
31 chunk.End(); 
32 
33 chunk.Begin(tChunkID::Scene_JointOrientation); 
34 chunk.Write(Orientation); 
35 chunk.End(); 
36 
37 chunk.Begin(tChunkID::Scene_JointScale); 
38 chunk.Write(JointScale); 
39 chunk.End(); 
40 
41 chunk.Begin(tChunkID::Scene_JointParentID); 
42 chunk.Write(ParentID); 
43 chunk.End(); 
44 
45 chunk.Begin(tChunkID::Scene_JointNumChildren); 
46 chunk.Write(NumChildren); 
47 chunk.End(); 
48 
49 chunk.Begin(tChunkID::Scene_JointChildIDTable); 
50 chunk.Write(Children, NumChildren); 
51 chunk.End(); 
52 } 
53 chunk.End(); 
54} 
55 
56 
57void tJoint::Load(const tChunk& jointChunk) 
58{ 
59 tAssert(jointChunk.GetID() == tChunkID::Scene_Joint); 
60 Clear(); 
61 
62 for (tChunk chunk = jointChunk.First(); chunk.IsValid(); chunk = chunk.Next()) 
63 { 
64 switch (chunk.GetID()) 
65 { 
66 case tChunkID::Scene_Object: 
67 tObject::Load(chunk); 
68 break; 
69 
70 case tChunkID::Scene_JointTranslation: 
71 chunk.GetItem(Translation); 
72 break; 
73 
74 case tChunkID::Scene_JointOrientation: 
75 chunk.GetItem(Orientation); 
76 break; 
77 
78 case tChunkID::Scene_JointScale: 
79 chunk.GetItem(JointScale); 
80 break; 
81 
82 case tChunkID::Scene_JointParentID: 
83 chunk.GetItem(ParentID); 
84 break; 
85 
86 case tChunkID::Scene_JointNumChildren: 
87 chunk.GetItem(NumChildren); 
88 break; 
89 
90 case tChunkID::Scene_JointChildIDTable: 
91 { 
92 tAssert(NumChildren > 0); 
93 Children = new uint32[NumChildren]; 
94 chunk.GetItems(Children, NumChildren); 
95 break; 
96 } 
97 } 
98 } 
99} 
100 
101 
102void tJoint::AddChildID(uint32 id) 
103{ 
104 tAssert(NumChildren < MaxChildJoints); 
105 if (!Children) 
106 { 
107 Children = new uint32[MaxChildJoints]; 
108 for (int i = 0; i < MaxChildJoints; i++) 
109 Children[i] = 0; 
110 } 
111 
112 Children[NumChildren++] = id; 
113} 
114 
115 
116void tPose::Save(tChunkWriter& chunk) const 
117{ 
118 chunk.Begin(tChunkID::Scene_Pose); 
119 { 
120 chunk.Begin(tChunkID::Scene_PoseInfo); 
121 { 
122 chunk.Write(FrameNumber); 
123 chunk.Write(NumJoints); 
124 } 
125 chunk.End(); 
126 
127 chunk.Begin(tChunkID::Scene_QuaternionTable); 
128 { 
129 chunk.Write(Quaternions, NumJoints); 
130 } 
131 chunk.End(); 
132 
133 chunk.Begin(tChunkID::Scene_ScaleTable); 
134 { 
135 chunk.Write(Scales, NumJoints); 
136 } 
137 chunk.End(); 
138 } 
139 chunk.End(); 
140} 
141 
142 
143void tPose::Load(const tChunk& poseChunk) 
144{ 
145 tAssert(poseChunk.GetID() == tChunkID::Scene_Pose); 
146 
147 for (tChunk chunk = poseChunk.First(); chunk.IsValid(); chunk = chunk.Next()) 
148 { 
149 switch (chunk.GetID()) 
150 { 
151 case tChunkID::Scene_PoseInfo: 
152 chunk.GetItem(FrameNumber); 
153 chunk.GetItem(NumJoints); 
154 break; 
155 
156 case tChunkID::Scene_QuaternionTable: 
157 { 
158 tAssert((FrameNumber != -1) && (NumJoints > 0)); 
159 Quaternions = new tQuaternion[NumJoints]; 
160 chunk.GetItems(Quaternions, NumJoints); 
161 break; 
162 } 
163 
164 case tChunkID::Scene_ScaleTable: 
165 { 
166 tAssert((FrameNumber != -1) && (NumJoints > 0)); 
167 Scales = new tVector4[NumJoints]; 
168 chunk.GetItems(Scales, NumJoints); 
169 break; 
170 } 
171 } 
172 }  
173} 
174 
175 
176void tSkeleton::Save(tChunkWriter& chunk) const 
177{ 
178 chunk.Begin(tChunkID::Scene_Skeleton); 
179 { 
180 tObject::Save(chunk); 
181 
182 chunk.Begin(tChunkID::Scene_SkeletonInfo); 
183 { 
184 chunk.Write(NumJoints); 
185 chunk.Write(NumPoses); 
186 chunk.Write(FrameFrequency); 
187 } 
188 chunk.End(); 
189 
190 chunk.Begin(tChunkID::Scene_JointList); 
191 { 
192 for (tItList<tJoint>::Iter joint = Joints.First(); joint; joint.Next()) 
193 joint->Save(chunk); 
194 } 
195 chunk.End(); 
196 
197 chunk.Begin(tChunkID::Scene_PoseList); 
198 { 
199 for (tItList<tPose>::Iter pose = Poses.First(); pose; ++pose) 
200 pose->Save(chunk); 
201 } 
202 chunk.End(); 
203 } 
204} 
205 
206 
207void tSkeleton::Load(const tChunk& skelChunk) 
208{ 
209 tAssert(skelChunk.GetID() == tChunkID::Scene_Skeleton); 
210 Clear(); 
211 
212 for (tChunk chunk = skelChunk.First(); chunk.IsValid(); chunk = chunk.Next()) 
213 { 
214 switch (chunk.GetID()) 
215 { 
216 case tChunkID::Scene_Object: 
217 tObject::Load(chunk); 
218 break; 
219 
220 case tChunkID::Scene_SkeletonInfo: 
221 chunk.GetItem(NumJoints); 
222 chunk.GetItem(NumPoses); 
223 chunk.GetItem(FrameFrequency); 
224 break; 
225 
226 case tChunkID::Scene_JointList: 
227 { 
228 tAssert((chunk.GetID() == tChunkID::Scene_JointList) && (Joints.IsEmpty())); 
229 for (tChunk c = chunk.First(); c.IsValid(); c = c.Next()) 
230 { 
231 switch (c.GetID()) 
232 { 
233 case tChunkID::Scene_Joint: 
234 Joints.Append(new tJoint(c)); 
235 break; 
236 } 
237 } 
238 break; 
239 } 
240 
241 case tChunkID::Scene_PoseList: 
242 { 
243 tAssert((chunk.GetID() == tChunkID::Scene_PoseList) && (Poses.IsEmpty())); 
244 for (tChunk c = chunk.First(); c.IsValid(); c = c.Next()) 
245 { 
246 switch (c.GetID()) 
247 { 
248 case tChunkID::Scene_Pose: 
249 Poses.Append(new tPose(c)); 
250 break; 
251 } 
252 } 
253 break; 
254 } 
255 } 
256 } 
257} 
258 
259 
260void tSkeleton::Pose(int poseNum) 
261{ 
262 if (poseNum >= NumPoses) 
263 poseNum = NumPoses - 1; 
264 
265 tItList<tPose>::Iter pose = Poses.First(); 
266 while (poseNum) 
267 { 
268 ++pose; 
269 poseNum--; 
270 } 
271 
272 int jointNum = 0; 
273 for (tItList<tJoint>::Iter joint = Joints.First(); joint; ++joint) 
274 { 
275 joint->Orientation = pose->Quaternions[jointNum]; 
276 joint->JointScale = pose->Scales[jointNum]; 
277 jointNum++; 
278 } 
279} 
280 
281 
282} 
283