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

Side by Side Diff: third_party/WebKit/ManualTests/compositor-worker/physics/physics.js

Issue 1547893003: WIP - compositor worker mega patch. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 11 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
OLDNEW
(Empty)
1 (function(scope) {
2 "use strict";
3
4 scope.isMain = function() {
5 return scope.window;
6 };
7
8 var spheres = [];
9 var foils = [];
10 var gravity = 0.022;
11 var numBlurElements = 1;
12 var epsilon = 0.01;
13 var viewportHeight = 0;
14 var logo = null;
15 var janking = false;
16 var logoAngle = 0;
17 var logoSpeed = 5;
18
19 function lerp(a, b, t) {
20 return (1 - t) * a + t * b;
21 }
22
23 function setPosition(sphere, dt) {
24 var dx = sphere.dx + (sphere.vx * dt);
25 var dy = sphere.dy + (sphere.vy * dt);
26 for (var i = 0; i < numBlurElements; ++i) {
27 var t = i / (numBlurElements - 1 || 1);
28 var lx = lerp(sphere.dx, dx, 1 - t);
29 var ly = lerp(sphere.dy, dy, 1 - t);
30 if (isMain()) {
31 sphere.blurElements[i].style.transform =
32 "translate3d(" + lx + "px, " + ly + "px, 0px)";
33 } else {
34 var transform = sphere.blurElements[i].transform;
35 transform.m41 = lx;
36 transform.m42 = ly;
37 sphere.blurElements[i].transform = transform;
38 }
39 }
40 sphere.dx = dx;
41 sphere.dy = dy;
42 }
43
44 function updatePositions(dt) {
45 for (var i = 0; i < spheres.length; ++i)
46 setPosition(spheres[i], dt);
47 }
48
49 function applyGravity(dt) {
50 for (var i = 0; i < spheres.length; ++i)
51 spheres[i].vy += gravity * dt;
52 }
53
54 var re = /matrix\(.*, ([0-9\.]+)\)/;
55 function getAnimatedPosition(foil) {
56 if (isMain()) {
57 var match = window.getComputedStyle(foil.actor, null).webkitTransform.matc h(re);
58 return match ? parseFloat(match[1]) : 0;
59 } else {
60 return foil.actor.transform.m42;
61 }
62 }
63
64 function signedDistanceToLine(x1, y1, nx, ny, cx, cy) {
65 return (cx - x1) * nx + (cy - y1) * ny;
66 }
67
68 function normalizeBinormalComponent(component) {
69 if (component < epsilon && component > -epsilon)
70 return 0;
71 if (component < 0)
72 return -1;
73 return 1;
74 }
75
76 function doAABBoxesIntersect(x1, y1, w1, h1, x2, y2, w2, h2) {
77 if (x1 > x2 + w2)
78 return false;
79
80 if (x2 > x1 + w1)
81 return false;
82
83 if (y1 > y2 + h2)
84 return false;
85
86 if (y2 > y1 + h1)
87 return false;
88
89 return true;
90 }
91
92 function collideWithLine(x1, y1, x2, y2, nx, ny, vx, vy, sphere) {
93 var cx = sphere.dx + sphere.radius;
94 var cy = sphere.dy + sphere.radius;
95
96 var normalDotVelocity = nx * sphere.vx + ny * sphere.vy;
97 if (normalDotVelocity > 0)
98 return false;
99
100 var distanceToLine = signedDistanceToLine(x1, y1, nx, ny, cx, cy);
101 if (Math.abs(distanceToLine) > sphere.radius)
102 return false;
103
104 var binormX = normalizeBinormalComponent(x2 - x1);
105 var binormY = normalizeBinormalComponent(y2 - y1);
106
107 var distanceToBoundary1 = signedDistanceToLine(x1, y1, binormX, binormY, cx, cy);
108 if (distanceToBoundary1 < 0)
109 return false;
110
111 var distanceToBoundary2 = signedDistanceToLine(x2, y2, -binormX, -binormY, c x, cy);
112 if (distanceToBoundary2 < 0)
113 return false;
114
115 // We may have passed through the line. Let's fix that now.
116 var correction = sphere.radius - distanceToLine;
117 sphere.dx += correction * nx;
118 sphere.dy += correction * ny;
119
120 // Update velocity.
121 if (Math.abs(nx) > epsilon)
122 sphere.vx = vx - sphere.vx;
123
124 if (Math.abs(ny) > epsilon)
125 sphere.vy = vy - sphere.vy;
126
127 return true;
128 }
129
130 function collideWithSphere(a, b) {
131 if (!doAABBoxesIntersect(
132 a.dx, a.dy, a.radius * 2, a.radius * 2,
133 b.dx, b.dy, b.radius * 2, b.radius * 2))
134 return false;
135
136 var cax = a.dx + a.radius;
137 var cay = a.dy + a.radius;
138 var cbx = b.dx + b.radius;
139 var cby = b.dy + b.radius;
140
141 var deltaX = cax - cbx;
142 var deltaY = cay - cby;
143 var distance2 = deltaX * deltaX + deltaY * deltaY;
144
145 var minDistance2 = a.radius + b.radius;
146 minDistance2 = minDistance2 * minDistance2;
147 if (distance2 > minDistance2)
148 return false;
149
150 var futureDeltaX = (cax + a.vx * epsilon) - (cbx + b.vx * epsilon);
151 var futureDeltaY = (cay + a.vy * epsilon) - (cby + b.vy * epsilon);
152 var futureDistance2 = futureDeltaX * futureDeltaX + futureDeltaY * futureDel taY;
153
154 // If we're not getting closer, bail.
155 if (futureDistance2 > distance2)
156 return false;
157
158 var distance = Math.sqrt(distance2);
159 deltaX /= distance;
160 deltaY /= distance;
161
162 var p = 2 * (a.vx * deltaX + a.vy * deltaY - b.vx * deltaX - b.vy * deltaY);
163 p /= (a.mass + b.mass);
164
165 a.vx = a.vx - p * b.mass * deltaX;
166 a.vy = a.vy - p * b.mass * deltaY;
167 b.vx = b.vx + p * a.mass * deltaX;
168 b.vy = b.vy + p * a.mass * deltaY;
169
170 // Now we may be intersecting. Let's fix that.
171 var deltaDistance = Math.sqrt(minDistance2) - distance;
172 var correction = deltaDistance * 0.5;
173 a.dx += correction * deltaX;
174 a.dy += correction * deltaY;
175 b.dx -= correction * deltaX;
176 b.dy -= correction * deltaY;
177
178 return true;
179 }
180
181 function collideWithFoil(sphere, foil) {
182 if (!doAABBoxesIntersect(
183 sphere.dx, sphere.dy, sphere.radius * 2, sphere.radius * 2,
184 foil.dx, foil.dy, foil.width, foil.height))
185 return;
186
187 var corners = [
188 [ foil.dx, foil.dy ],
189 [ foil.dx + foil.width, foil.dy ],
190 [ foil.dx + foil.width, foil.dy + foil.height ],
191 [ foil.dx, foil.dy + foil.height ]
192 ];
193
194 for (var i = 0; i < corners.length; ++i) {
195 var corner0 = corners[i];
196 var corner1 = corners[(i + 1) % corners.length];
197 var corner2 = corners[(i + 2) % corners.length];
198
199 var nx = normalizeBinormalComponent(corner1[0] - corner2[0]);
200 var ny = normalizeBinormalComponent(corner1[1] - corner2[1]);
201
202 if (collideWithLine(corner0[0], corner0[1], corner1[0], corner1[1], nx, ny , foil.vx, foil.vy, sphere))
203 return;
204 }
205
206 var corner = Object();
207 corner.radius = 0.1;
208 corner.mass = 50000; // really big.
209
210 for (var i = 0; i < corners.length; ++i) {
211 corner.dx = corners[i][0];
212 corner.dy = corners[i][1];
213 corner.vx = foil.vx;
214 corner.vy = foil.vy;
215 if (collideWithSphere(sphere, corner))
216 return;
217 }
218 }
219
220 function updateFoilProperties(foil) {
221 var dy = getAnimatedPosition(foil) + foil.top;
222 foil.vy = dy - foil.dy;
223 foil.dy = dy;
224 }
225
226 function processCollisions() {
227 for (var i = 0; i < foils.length; ++i)
228 updateFoilProperties(foils[i]);
229 for (var i = 0; i < spheres.length; ++i) {
230 for (var j = 0; j < foils.length; ++j)
231 collideWithFoil(spheres[i], foils[j]);
232 for (var j = i + 1; j < spheres.length; ++j)
233 collideWithSphere(spheres[i], spheres[j]);
234 }
235 }
236
237 function resetSpheres() {
238 for (var i = 0; i < spheres.length; ++i) {
239 var sphere = spheres[i];
240 var padding = 400;
241 if (sphere.dy > viewportHeight + padding) {
242 sphere.dx = sphere.initialX;
243 sphere.dy = sphere.initialY - 0.5 * viewportHeight;
244 sphere.vy = 0;
245 sphere.vx *= epsilon;
246 if (Math.abs(sphere.vx) > 100)
247 sphere.vx = 0;
248 }
249 }
250 }
251
252 function updateLogo() {
253 logoAngle += logoSpeed;
254 while (logoAngle > 360)
255 logoAngle -= 360;
256
257 logo.style.webkitTransform = "translateZ(0) rotate(" + logoAngle + "deg)";
258 }
259
260 scope.tick = function(timestamp) {
261 var dt = 1.0;
262 console.log("tick: " + timestamp);
263 if (scope.lastTimestamp) {
264 dt = (timestamp - scope.lastTimestamp) * 60;
265 }
266 scope.lastTimestamp = timestamp;
267
268 if (isMain()) {
269 updateLogo();
270 } else {
271 updatePositions(dt);
272 processCollisions();
273 updatePositions(dt);
274 applyGravity(dt);
275 resetSpheres();
276 }
277 scope.requestAnimationFrame(tick);
278 }
279
280 function createFoil(dx, dy, width, height, delay) {
281 var foilActor = document.createElement("div");
282 foilActor.className = "foil";
283 foilActor.style.left = dx + "px";
284 foilActor.style.top = dy + "px";
285 foilActor.style.width = width;
286 foilActor.style.height = height;
287 foilActor.style.webkitAnimation = "foil-motion 1s " + delay + "ms infinite a lternate";
288 document.body.appendChild(foilActor);
289
290 var foil = new Object();
291 foil.actor = foilActor;
292 foil.left = dx;
293 foil.top = dy;
294 foil.width = width;
295 foil.height = height;
296 foil.dx = foil.left;
297 foil.dy = foil.top;
298 foil.vx = 0;
299 foil.vy = 0;
300
301 return foil;
302 }
303
304 function busySleep(duration) {
305 var start = new Date();
306 while ((new Date()).getTime() - start.getTime() < duration);
307 }
308
309 function doJank() {
310 busySleep(500);
311 if (janking)
312 window.setTimeout(doJank, 500);
313 }
314
315 function startJank() {
316 var startButton = document.getElementById("startJank");
317 startButton.style.webkitAnimation = "flip-hide 1s 1 forwards";
318
319 var stopButton = document.getElementById("stopJank");
320 stopButton.style.webkitAnimation = "flip-show 1s 1 forwards";
321
322 janking = true;
323
324 window.setTimeout(doJank, 16);
325 }
326
327 function stopJank() {
328 var startButton = document.getElementById("startJank");
329 startButton.style.webkitAnimation = "flip-show 1s 1 forwards";
330
331 var stopButton = document.getElementById("stopJank");
332 stopButton.style.webkitAnimation = "flip-hide 1s 1 forwards";
333
334 janking = false;
335 }
336
337 function toggle() {
338 if (janking)
339 stopJank();
340 else
341 startJank();
342 }
343
344 function createSphere(radius, topColor, bottomColor, dx, dy) {
345 var blurElements = [];
346 for (var i = 0; i < numBlurElements; ++i) {
347 var blurElement = document.createElement("div");
348 blurElement.className = "actor";
349 blurElement.style.background = "-webkit-gradient(linear, left top,"
350 + "left bottom, color-stop(0%," + topColor + "), color-stop(100%,"
351 + bottomColor + "))";
352 blurElement.style.width = (radius * 2) + "px";
353 blurElement.style.height = (radius * 2) + "px";
354 blurElement.style.borderRadius = radius + "px";
355 document.body.appendChild(blurElement);
356 var t = i / (numBlurElements - 1 || 1);
357 blurElement.style.opacity = lerp(0.4, 0.1, t);
358 blurElements.push(blurElement);
359 }
360
361 var sphere = new Object();
362 sphere.blurElements = blurElements;
363 sphere.radius = radius;
364 sphere.vx = 0;
365 sphere.vy = 0;
366 sphere.dx = sphere.initialX = dx;
367 sphere.dy = sphere.initialY = dy;
368 sphere.mass = radius * radius * Math.PI;
369
370 setPosition(sphere, dx, dy);
371
372 spheres.push(sphere);
373 }
374
375 function setupSpheres() {
376 var widths = [ 50, 10, 12, 30, 25, 10, 40, 10, 15, 10 ];
377 var colors = [
378 [ "rgba(53,53,255,1)", "rgba(28,41,127,1)" ],
379 [ "rgba(255,53,53,1)", "rgba(181,41,41,1)" ],
380 [ "rgba(8,160,0,1)", "rgba(24,102,23,1)" ],
381 [ "rgba(219,219,0,1)", "rgba(178,173,41,1)" ]
382 ];
383 var top = 100;
384 var left = 200;
385
386 var numSpheres = 80;
387 for (var i = 0; i < numSpheres; ++i) {
388 var radius = widths[i % widths.length];
389 var colorPair = colors[i % colors.length];
390 var noise = i % 2 == 0 ? -5 : 5;
391 var dx = left - radius + noise;
392 var dy = top - radius * 2;
393
394 createSphere(radius, colorPair[0], colorPair[1], dx, dy);
395
396 top -= (widths[i % widths.length] * 2) + 30;
397 if (i == Math.floor(numSpheres/3)) {
398 top = 500;
399 left = 650;
400 } else if (i == Math.floor((numSpheres*2)/3)) {
401 top = 200;
402 left = 950;
403 }
404 }
405 }
406
407 function setupFoils() {
408 var dxs = [ 50, 500, 700 ];
409 var dys = [ 150, 600, 300 ];
410 var delays = [ 0, 500, 250 ];
411 for (var i = 0; i < 3; ++i)
412 foils.push(createFoil(dxs[i], dys[i], 300, 30, delays[i]));
413 }
414
415 function setupScene() {
416 logo = document.getElementById("logo");
417 viewportHeight = document.documentElement.clientHeight;
418
419 var container = document.querySelector(".container");
420 container.addEventListener("mousedown", function(e) { e.preventDefault(); }) ;
421 container.addEventListener("click", toggle);
422
423 setupFoils();
424 setupSpheres();
425 }
426
427 scope.initWorker = function() {
428 self.onmessage = function(e) {
429 spheres = e.data.spheres;
430 foils = e.data.foils;
431 viewportHeight = e.data.viewportHeight;
432 requestAnimationFrame(tick);
433 }
434 };
435
436 scope.initMain = function() {
437 setupScene();
438 scope.worker = new CompositorWorker("physics.js");
439
440 var message = {
441 'spheres': [],
442 'foils': [],
443 'viewportHeight': viewportHeight
444 };
445
446 for (var i = 0; i < spheres.length; ++i) {
447 var sphere = spheres[i];
448 var sphereProxy = {
449 radius: sphere.radius,
450 vx: sphere.vx,
451 vy: sphere.vy,
452 dx: sphere.dx,
453 dy: sphere.dy,
454 initialX: sphere.initialX,
455 initialY: sphere.initialY,
456 mass:sphere.mass,
457 blurElements: []
458 };
459 for (var j = 0; j < sphere.blurElements.length; ++j)
460 sphereProxy.blurElements.push(new CompositorProxy(sphere.blurElements[j] , ['transform']));
461 message.spheres.push(sphereProxy);
462 }
463
464 for (var i = 0; i < foils.length; ++i) {
465 var foil = foils[i];
466 var foilProxy = {
467 left: foil.left,
468 top: foil.top,
469 width:foil.width,
470 height:foil.height,
471 dx:foil.dx,
472 dy:foil.dy,
473 vx:foil.vx,
474 vy:foil.vy,
475 actor:new CompositorProxy(foil.actor, ['transform'])
476 }
477 message.foils.push(foilProxy);
478 }
479
480 worker.postMessage(message);
481 requestAnimationFrame(tick);
482 };
483
484 if (isMain())
485 initMain();
486 else
487 initWorker();
488 })(self);
489
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698