Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: samples/siteswap/animation.js

Issue 155005: Adding unfinished-but-working siteswap demo, copied from an ancient perforce changelist. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | samples/siteswap/math.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // @@REWRITE(insert js-copyright)
2 // @@REWRITE(delete-start)
3 // Copyright 2009 Google Inc. All Rights Reserved
4 // @@REWRITE(delete-end)
5
6 /**
7 * This file contains the animation-management code for the siteswap animator.
8 * This is encapsulated in the EventQueue and QueueEvent classes, the event
9 * handler, and startAnimation, the main external interface to the animation.
10 */
11
12 /**
13 * A record, held in the EventQueue, that describes the curve that should be
14 * given to a shape at a time.
15 * @constructor
16 * @param {!number} time base time at which the event occurs/the curve starts.
17 * @param {!o3d.Shape} shape the shape to be updated.
18 * @param {Curve} curve the path for the shape to follow.
19 */
20 function QueueEvent(time, shape, curve) {
21 this.time = time;
22 this.shape = shape;
23 this.curve = curve;
24 return this;
25 }
26
27 /**
28 * A circular queue of events that will happen during the course of an animation
29 * that's duration beats long. The queue is ordered by the time each curve
30 * starts. Note that a curve may start after it ends, since time loops
31 * endlessly. The nextEvent field is the index of the next event to occur; it
32 * keeps track of how far we've gotten in the queue.
33 * @constructor
34 * @param {!number} duration the length of the animation in beats.
35 */
36 function EventQueue(duration) {
37 this.events = [];
38 this.nextEvent = 0;
39 this.duration = duration;
40 this.timeCorrection = 0; // Corrects from queue entry time to real time.
41 return this;
42 }
43
44 /**
45 * Add an event to the queue, inserting into order by its time field.
46 * A heap-based priority queue would be faster, but likely overkill, as this
47 * won't ever contain that many items, and isn't likely to be speed-critical.
48 * @param {!QueueEvent} event the event to add.
49 */
50 EventQueue.prototype.addEvent = function(event) {
51 var i = 0;
52 while (i < this.events.length && event.time > this.events[i].time) {
53 ++i;
54 }
55 this.events.splice(i, 0, event);
56 };
57
58 /**
59 * Pull the next event off the queue.
60 * @return {!QueueEvent} the event.
61 */
62 EventQueue.prototype.shift = function() {
63 var e = this.events[this.nextEvent];
64 if (++this.nextEvent >= this.events.length) {
65 assert(this.nextEvent > 0);
66 this.nextEvent = 0;
67 this.timeCorrection += this.duration;
68 }
69 return e;
70 };
71
72 /**
73 * Process all current events, updating all animated objects with their new
74 * curves, until we find that the next event in the queue is in the future.
75 * @param {!number} time the current time in beats. This number is an absolute,
76 * not locked to the range of the duration of the pattern, so getNextTime()
77 * returns a doctored number to add in the offset from in-pattern time to real
78 * time.
79 * @return {!number} the time of the next future event.
80 */
81 EventQueue.prototype.processEvents = function(time) {
82 while (this.getNextTime() <= time) {
83 var e = this.shift();
84 setParamCurveInfo(e.curve, e.shape, time);
85 }
86 return this.getNextTime(); // In case you want to set a callback.
87 };
88
89 /**
90 * Look up the initial curve for a shape [the curve that it'll be starting or in
91 * the middle of at time 0].
92 * @param {!CurveSet} curveSet the complete set of curves for a Shape.
93 * @return {!Object} the curve and the time at which it would have started.
94 */
95 function getInitialCurveInfo(curveSet) {
96 var curve = curveSet.getCurveForUnsafeTime(0);
97 var curveBaseTime;
98 if (!curve.startTime) {
99 curveBaseTime = 0;
100 } else {
101 // If the curve isn't starting now, it must have wrapped around.
102 assert(curve.startTime + curve.duration > curveSet.duration);
103 // So subtract off one wrap so that its startTime is in the right space of
104 // numbers. We assume here that no curve duration is longer than the
105 // pattern, which must be guaranteed by the code that generates patterns.
106 assert(curve.duration <= curveSet.duration);
107 curveBaseTime = curve.startTime - curveSet.duration;
108 }
109 return { curve: curve, curveBaseTime: curveBaseTime };
110 }
111
112 /**
113 * Set up the event queue with a complete pattern starting at time 0.
114 * @param {!Array.CurveSet} curveSets the curve sets for all shapes.
115 * @param {!Array.o3d.Shape} shapes all the shapes to animate.
116 */
117 EventQueue.prototype.setUp = function(curveSets, shapes) {
118 assert(curveSets.length == shapes.length);
119 for (var i = 0; i < shapes.length; ++i) {
120 var curveSet = curveSets[i];
121 assert(this.duration % curveSet.duration == 0);
122 var shape = shapes[i];
123 var record = getInitialCurveInfo(curveSet);
124 var curveBaseTime = record.curveBaseTime;
125 var curve = record.curve;
126 setParamCurveInfo(curve, shape, curveBaseTime);
127 do {
128 curveBaseTime += curve.duration;
129 curve = curveSet.getCurveForTime(curveBaseTime);
130 var e = new QueueEvent(curveBaseTime % this.duration, shape, curve);
131 this.addEvent(e);
132 } while (curveBaseTime + curve.duration <= this.duration);
133 }
134 };
135
136 /**
137 * Return the time of the next future event.
138 * @return {!number} the time.
139 */
140 EventQueue.prototype.getNextTime = function() {
141 return this.events[this.nextEvent].time + this.timeCorrection;
142 };
143
144 /**
145 * This is the event handler that runs the whole animation. When triggered by
146 * the counter, it updates the curves on all objects whose curves have expired.
147 *
148 * The current time will be some time around when we wanted to be called. It
149 * might be exact, but it might be a bit off due to floating point error, or a
150 * lot off due to the system getting bogged down somewhere for a second or
151 * two. e.g. if we wanted to get a call at time 7, it's likely to be
152 * something like 7.04, but might even be 11. We then use 7, not 7.04, as the
153 * start time for each of the curves set, so as to remove clock drift. Since
154 * the time we wanted to be called is stored in the next item in the queue, we
155 * can just pull that out and use it. However, if we then find that we're
156 * setting our callback in the past, we repeat the process until our callback
157 * is set safely in the future. We may get some visual artifacts, but at
158 * least we won't drop any events [leading to stuff drifting endlessly off
159 * into the distance].
160 */
161 function handler() {
162 var eventTime = g.eventQueue.getNextTime();
163 var trueCurrentTime;
164 do {
165 g.counter.removeCallback(eventTime);
166 eventTime = g.eventQueue.processEvents(eventTime);
167 g.counter.addCallback(eventTime, handler);
168 trueCurrentTime = g.counter.count;
169 } while (eventTime < trueCurrentTime);
170 }
171
172 /**
173 * Given a precomputed juggling pattern, this sets up the O3D objects,
174 * EventQueue, and callback necessary to start an animation, then calls
175 * updateAnimating to kick it off if enabled.
176 *
177 * @param {!number} numBalls the number of balls in the animation.
178 * @param {!number} numHands the number of hands in the animation.
179 * @param {!number} duration the length of the full animation cycle in beats.
180 * @param {!Array.CurveSet} ballCurveSets one CurveSet per ball.
181 * @param {!Array.CurveSet} handCurveSets one CurveSet per hand.
182 */
183 function startAnimation(numBalls, numHands, duration, ballCurveSets,
184 handCurveSets) {
185 g.counter.running = false;
186 g.counter.reset();
187
188 setNumBalls(numBalls);
189 setNumHands(numHands);
190
191 g.eventQueue = new EventQueue(duration);
192 g.eventQueue.setUp(handCurveSets, g.handShapes);
193 g.eventQueue.setUp(ballCurveSets, g.ballShapes);
194 g.counter.addCallback(g.eventQueue.getNextTime(), handler);
195
196 updateAnimating();
197 }
198
OLDNEW
« no previous file with comments | « no previous file | samples/siteswap/math.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698