PageRenderTime 63ms CodeModel.GetById 30ms app.highlight 15ms RepoModel.GetById 15ms app.codeStats 0ms

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