| 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 | |