PageRenderTime 405ms CodeModel.GetById 241ms app.highlight 17ms RepoModel.GetById 144ms app.codeStats 1ms

/src/away3d/animators/skeleton/SkeletonTimelineClipNode.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 204 lines | 159 code | 23 blank | 22 comment | 42 complexity | fe71692ddde9582d3538d1698e7ac852 MD5 | raw file
  1/**
  2 * Author: David Lenaerts
  3 */
  4package away3d.animators.skeleton
  5{
  6	import away3d.arcane;
  7
  8	import flash.geom.Vector3D;
  9
 10	use namespace arcane;
 11
 12	/**
 13	 * SkeletonTimelineClipNode represents a node in a skeleton tree containing a blending clip for which the keyframes
 14	 * are laid out on a timeline. As such, the pose is determined by the time property.
 15	 */
 16	public class SkeletonTimelineClipNode extends SkeletonClipNodeBase
 17	{
 18		private var _timeDir : Number;
 19		private var _frame1 : int;
 20		private var _frame2 : int;
 21		private var _blendWeight : Number = 0;
 22		private var _framesInvalid : Boolean;
 23		private var _resetTime : Boolean;
 24		private var _startTime : Number = 0;
 25		private var _lastFrame : int;
 26
 27		/**
 28		 * Creates a new SkeletonTimelineClipNode object.
 29		 * @param numJoints The amount of joints in the target skeleton.
 30		 */
 31		public function SkeletonTimelineClipNode()
 32		{
 33			super();
 34		}
 35
 36		public function reset() : void
 37		{
 38			if (!clip.looping)
 39				_resetTime = true;
 40		}
 41
 42		override public function set time(value : Number) : void
 43		{
 44			if (_resetTime) {
 45				_startTime = value;
 46				_resetTime = false;
 47			}
 48			if (_time == value) return;
 49			_framesInvalid = true;
 50			_timeDir = value - _time;
 51			super.time = value;
 52		}
 53
 54		/**
 55		 * @inheritDoc
 56		 */
 57		override public function updatePose(skeleton : Skeleton) : void
 58		{
 59			if (_clip.duration == 0) return;
 60			if (_framesInvalid) updateFrames(_time-_startTime);
 61
 62			var poses1 : Vector.<JointPose> = clip._frames[_frame1].jointPoses;
 63			var poses2 : Vector.<JointPose> = clip._frames[_frame2].jointPoses;
 64			var numJoints : uint = skeleton.numJoints;
 65			var p1 : Vector3D, p2 : Vector3D;
 66			var pose1 : JointPose, pose2 : JointPose;
 67			var endPoses : Vector.<JointPose> = skeletonPose.jointPoses;
 68			var endPose : JointPose;
 69			var tr : Vector3D;
 70
 71			// :s
 72			if (endPoses.length != numJoints) endPoses.length = numJoints;
 73
 74			if ((numJoints != poses1.length) || (numJoints != poses2.length))
 75				throw new Error("joint counts don't match!");
 76
 77			for (var i : uint = 0; i < numJoints; ++i) {
 78				endPose = endPoses[i] ||= new JointPose();
 79				pose1 = poses1[i];
 80				pose2 = poses2[i];
 81				p1 = pose1.translation; p2 = pose2.translation;
 82
 83				if (_highQuality)
 84					endPose.orientation.slerp(pose1.orientation, pose2.orientation, _blendWeight);
 85				else
 86					endPose.orientation.lerp(pose1.orientation, pose2.orientation, _blendWeight);
 87
 88				if (i > 0) {
 89					tr = endPose.translation;
 90					tr.x = p1.x + _blendWeight*(p2.x - p1.x);
 91					tr.y = p1.y + _blendWeight*(p2.y - p1.y);
 92					tr.z = p1.z + _blendWeight*(p2.z - p1.z);
 93				}
 94			}
 95		}
 96
 97		/**
 98		 * @inheritDoc
 99		 */
100		override public function updatePositionData() : void
101		{
102			if (_framesInvalid) updateFrames(_time-_startTime);
103
104			var p1 : Vector3D = clip._frames[_frame1].jointPoses[0].translation,
105				p2 : Vector3D = clip._frames[_frame2].jointPoses[0].translation;
106
107			if ((_timeDir > 0 && _frame2 > _lastFrame) || (_timeDir < 0 && _frame1 < _lastFrame)) {
108				var dx : Number = _rootPos.x;
109				var dy : Number = _rootPos.y;
110				var dz : Number = _rootPos.z;
111				_rootPos.x = p1.x + _blendWeight*(p2.x - p1.x);
112				_rootPos.y = p1.y + _blendWeight*(p2.y - p1.y);
113				_rootPos.z = p1.z + _blendWeight*(p2.z - p1.z);
114				rootDelta.x = _rootPos.x - dx;
115				rootDelta.y = _rootPos.y - dy;
116				rootDelta.z = _rootPos.z - dz;
117			}
118			// jumping back, need to reset position
119			else {
120				_rootPos.x = p1.x + _blendWeight*(p2.x - p1.x);
121				_rootPos.y = p1.y + _blendWeight*(p2.y - p1.y);
122				_rootPos.z = p1.z + _blendWeight*(p2.z - p1.z);
123				rootDelta.x = 0;
124				rootDelta.y = 0;
125				rootDelta.z = 0;
126			}
127			_lastFrame = _timeDir > 0? _frame1 : _frame2;
128		}
129
130		private function updateFrames(time : Number) : void
131		{
132			var lastFrame : uint;
133			var dur : uint, frameTime : uint;
134			var frames : Vector.<SkeletonPose> = _clip._frames;
135			var durations : Vector.<uint> = _clip._durations;
136			var duration : uint = _clip._totalDuration;
137			var looping : Boolean = _clip.looping;
138			var numFrames : uint = frames.length;
139
140			if (numFrames == 0) return;
141
142			lastFrame = numFrames - 1;
143			if (looping) {
144				if (time >= 1) time -= int(time);
145				if (time < 0) time -= int(time)-1;
146
147				if (_clip._fixedFrameRate) {
148					time *= lastFrame;
149					_frame1 = time;
150					_blendWeight = time - _frame1;
151					_frame2 = _frame1 + 1;
152				}
153				else {
154					do {
155						frameTime = dur;
156						dur += durations[_frame1];
157						_frame1 = _frame2;
158						if (++_frame2 == numFrames) {
159							_frame1 = 0;
160							_frame2 = 1;
161						}
162					} while (time > dur);
163
164					_blendWeight = (time - frameTime) / durations[_frame1];
165				}
166			}
167			else {
168				if (time >= 1) {
169					clip.notifyPlaybackComplete();
170					//if the animation has different frame count, set the frame to the lastframe return an error
171					_frame1 = lastFrame;
172					_frame2 = lastFrame;
173//					_frame1 = 0;
174//					_frame2 = 0;
175					_blendWeight = 0;
176				}
177				else if (_clip._fixedFrameRate) {
178					time *= lastFrame;
179					_frame1 = time;
180					_frame2 = _frame1 + 1;
181					if (_frame2 == numFrames) _frame2 = _frame1;
182					_blendWeight = time - _frame1;
183				}
184				else {
185					time *= duration - durations[lastFrame];
186					do {
187						frameTime = dur;
188						dur += durations[_frame1];
189						_frame1 = _frame2++;
190					} while (time > dur);
191
192					if (_frame2 == numFrames) {
193						_frame2 = _frame1;
194						_blendWeight = 0;
195					}
196					else
197						_blendWeight = (time - frameTime) / durations[_frame1];
198				}
199			}
200
201			_framesInvalid = false;
202		}
203	}
204}