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"  |
18 | using namespace tMath;  |
19 | namespace tScene  |
20 | {  |
21 |   |
22 |   |
23 | void 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 |   |
57 | void 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 |   |
102 | void 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 |   |
116 | void 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 |   |
143 | void 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 |   |
176 | void 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 |   |
207 | void 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 |   |
260 | void 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 | |