/src/away3d/animators/skeleton/SkeletonPose.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 196 lines · 129 code · 21 blank · 46 comment · 12 complexity · 5806a3b48d3a07de7441a6bd9d78d4bb MD5 · raw file

  1. package away3d.animators.skeleton
  2. {
  3. import away3d.core.math.Quaternion;
  4. import away3d.library.assets.AssetType;
  5. import away3d.library.assets.IAsset;
  6. import away3d.library.assets.NamedAssetBase;
  7. import flash.geom.Vector3D;
  8. /**
  9. * A SkeletonPose is a collection of JointPose objects, determining the pose for an entire skeleton.
  10. * A SkeletonPose and JointPose combination corresponds to a Skeleton and Joint combination. However, there is no
  11. * reference to a Skeleton instance, since several skeletons could be influenced by the same pose (fe: animation
  12. * sequences that can apply to any target with a valid skeleton)
  13. */
  14. public class SkeletonPose extends NamedAssetBase implements IAsset
  15. {
  16. /**
  17. * The joint poses for the skeleton. The JointPoses indices correspond to the target skeleton's joints.
  18. */
  19. public var jointPoses : Vector.<JointPose>;
  20. /**
  21. * Creates a new SkeletonPose object.
  22. * @param numJoints The number of joints in the target skeleton.
  23. */
  24. public function SkeletonPose()
  25. {
  26. jointPoses = new Vector.<JointPose>();
  27. }
  28. public function get assetType() : String
  29. {
  30. return AssetType.SKELETON_POSE;
  31. }
  32. /**
  33. * Returns the JointPose, given the joint name.
  34. * @param jointName is the name of the JointPose to be found.
  35. * @return JointPose
  36. */
  37. public function jointPoseFromName(jointName : String) : JointPose
  38. {
  39. var jointPoseIndex : int = jointPoseIndexFromName(jointName);
  40. if (jointPoseIndex != -1) {
  41. return jointPoses[jointPoseIndex];
  42. }
  43. else {
  44. return null;
  45. }
  46. }
  47. /**
  48. * Returns the joint index, given the joint name. -1 is returned if joint name not found.
  49. * @param jointName is the name of the JointPose to be found.
  50. * @return jointIndex
  51. */
  52. public function jointPoseIndexFromName(jointName : String) : int
  53. {
  54. // this function is implemented as a linear search, rather than a possibly
  55. // more optimal method (Dictionary lookup, for example) because:
  56. // a) it is assumed that it will be called once for each joint
  57. // b) it is assumed that it will be called only during load, and not during main loop
  58. // c) maintaining a dictionary (for safety) would dictate an interface to access JointPoses,
  59. // rather than direct array access. this would be sub-optimal.
  60. var jointPoseIndex : int;
  61. for each (var jointPose : JointPose in jointPoses) {
  62. if (jointPose.name == jointName) {
  63. return jointPoseIndex;
  64. }
  65. jointPoseIndex++;
  66. }
  67. return -1;
  68. }
  69. /**
  70. * The amount of joints in the Skeleton
  71. */
  72. public function get numJointPoses() : uint
  73. {
  74. return jointPoses.length;
  75. }
  76. /**
  77. * Clones this SkeletonPose, with all of its component jointPoses.
  78. * @return SkeletonPose
  79. */
  80. public function clone() : SkeletonPose
  81. {
  82. var clone : SkeletonPose = new SkeletonPose();
  83. var numJointPoses : uint = this.jointPoses.length;
  84. for (var i : uint = 0; i < numJointPoses; i++) {
  85. var cloneJointPose : JointPose = new JointPose();
  86. var thisJointPose : JointPose = this.jointPoses[i];
  87. cloneJointPose.name = thisJointPose.name;
  88. cloneJointPose.copyFrom(thisJointPose);
  89. clone.jointPoses[i] = cloneJointPose;
  90. }
  91. return clone;
  92. }
  93. /**
  94. * Converts a local hierarchical skeleton pose to a global pose
  95. * @param targetPose The SkeletonPose object that will contain the global pose.
  96. * @param skeleton The skeleton containing the joints, and as such, the hierarchical data to transform to global poses.
  97. */
  98. public function toGlobalPose(targetPose : SkeletonPose, skeleton : Skeleton) : void
  99. {
  100. var globalPoses : Vector.<JointPose> = targetPose.jointPoses;
  101. var globalJointPose : JointPose;
  102. var joints : Vector.<SkeletonJoint> = skeleton.joints;
  103. var len : uint = numJointPoses;
  104. var parentIndex : int;
  105. var joint : SkeletonJoint;
  106. var parentPose : JointPose;
  107. var pose : JointPose;
  108. var or : Quaternion;
  109. var tr : Vector3D;
  110. var t : Vector3D;
  111. var q : Quaternion;
  112. var x1 : Number, y1 : Number, z1 : Number, w1 : Number;
  113. var x2 : Number, y2 : Number, z2 : Number, w2 : Number;
  114. var x3 : Number, y3 : Number, z3 : Number;
  115. // :s
  116. if (globalPoses.length != len) globalPoses.length = len;
  117. for (var i : uint = 0; i < len; ++i) {
  118. globalJointPose = globalPoses[i] ||= new JointPose();
  119. joint = joints[i];
  120. parentIndex = joint.parentIndex;
  121. pose = jointPoses[i];
  122. q = globalJointPose.orientation;
  123. t = globalJointPose.translation;
  124. if (parentIndex < 0) {
  125. tr = pose.translation;
  126. or = pose.orientation;
  127. q.x = or.x;
  128. q.y = or.y;
  129. q.z = or.z;
  130. q.w = or.w;
  131. t.x = tr.x;
  132. t.y = tr.y;
  133. t.z = tr.z;
  134. }
  135. else {
  136. // append parent pose
  137. parentPose = globalPoses[parentIndex];
  138. // rotate point
  139. or = parentPose.orientation;
  140. tr = pose.translation;
  141. x2 = or.x;
  142. y2 = or.y;
  143. z2 = or.z;
  144. w2 = or.w;
  145. x3 = tr.x;
  146. y3 = tr.y;
  147. z3 = tr.z;
  148. w1 = -x2 * x3 - y2 * y3 - z2 * z3;
  149. x1 = w2 * x3 + y2 * z3 - z2 * y3;
  150. y1 = w2 * y3 - x2 * z3 + z2 * x3;
  151. z1 = w2 * z3 + x2 * y3 - y2 * x3;
  152. // append parent translation
  153. tr = parentPose.translation;
  154. t.x = -w1 * x2 + x1 * w2 - y1 * z2 + z1 * y2 + tr.x;
  155. t.y = -w1 * y2 + x1 * z2 + y1 * w2 - z1 * x2 + tr.y;
  156. t.z = -w1 * z2 - x1 * y2 + y1 * x2 + z1 * w2 + tr.z;
  157. // append parent orientation
  158. x1 = or.x;
  159. y1 = or.y;
  160. z1 = or.z;
  161. w1 = or.w;
  162. or = pose.orientation;
  163. x2 = or.x;
  164. y2 = or.y;
  165. z2 = or.z;
  166. w2 = or.w;
  167. q.w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2;
  168. q.x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2;
  169. q.y = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2;
  170. q.z = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2;
  171. }
  172. }
  173. }
  174. }
  175. }