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

Side by Side Diff: sky/framework/animation/mechanics.dart

Issue 1132063007: Rationalize Dart mojo and sky package structure (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « sky/framework/animation/generators.dart ('k') | sky/framework/animation/scroll_behavior.dart » ('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 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 import 'dart:math' as math;
6
7 const double kGravity = -0.980; // m^s-2
8
9 abstract class System {
10 void update(double deltaT);
11 }
12
13 class Particle extends System {
14 final double mass;
15 double velocity;
16 double position;
17
18 Particle({this.mass: 1.0, this.velocity: 0.0, this.position: 0.0});
19
20 void applyImpulse(double impulse) {
21 velocity += impulse / mass;
22 }
23
24 void update(double deltaT) {
25 position += velocity * deltaT;
26 }
27
28 void setVelocityFromEnergy({double energy, double direction}) {
29 assert(direction == -1.0 || direction == 1.0);
30 assert(energy >= 0.0);
31 velocity = math.sqrt(2.0 * energy / mass) * direction;
32 }
33 }
34
35 abstract class Box {
36 void confine(Particle p);
37 }
38
39 class ClosedBox extends Box {
40 final double min; // m
41 final double max; // m
42
43 ClosedBox({this.min, this.max}) {
44 assert(min == null || max == null || min <= max);
45 }
46
47 void confine(Particle p) {
48 if (min != null) {
49 p.position = math.max(min, p.position);
50 if (p.position == min)
51 p.velocity = math.max(0.0, p.velocity);
52 }
53 if (max != null) {
54 p.position = math.min(max, p.position);
55 if (p.position == max)
56 p.velocity = math.min(0.0, p.velocity);
57 }
58 }
59 }
60
61 class GeofenceBox extends Box {
62 final double min; // m
63 final double max; // m
64
65 final Function onEscape;
66
67 GeofenceBox({this.min, this.max, this.onEscape}) {
68 assert(min == null || max == null || min <= max);
69 assert(onEscape != null);
70 }
71
72 void confine(Particle p) {
73 if (((min != null) && (p.position < min)) ||
74 ((max != null) && (p.position > max)))
75 onEscape();
76 }
77 }
78
79 class ParticleInBox extends System {
80 final Particle particle;
81 final Box box;
82
83 ParticleInBox({this.particle, this.box}) {
84 box.confine(particle);
85 }
86
87 void update(double deltaT) {
88 particle.update(deltaT);
89 box.confine(particle);
90 }
91 }
92
93 class ParticleInBoxWithFriction extends ParticleInBox {
94 final double friction; // unitless
95 final double _sign;
96
97 final Function onStop;
98
99 ParticleInBoxWithFriction({Particle particle, Box box, this.friction, this.onS top})
100 : super(particle: particle, box: box),
101 _sign = particle.velocity.sign;
102
103 void update(double deltaT) {
104 double force = -_sign * friction * particle.mass * -kGravity;
105 particle.applyImpulse(force * deltaT);
106 if (particle.velocity.sign != _sign) {
107 particle.velocity = 0.0;
108 }
109 super.update(deltaT);
110 if ((particle.velocity == 0.0) && (onStop != null))
111 onStop();
112 }
113 }
114
115 class Spring {
116 final double k;
117 double displacement;
118
119 Spring(this.k, {this.displacement: 0.0});
120
121 double get force => -k * displacement;
122 }
123
124 class ParticleAndSpringInBox extends System {
125 final Particle particle;
126 final Spring spring;
127 final Box box;
128
129 ParticleAndSpringInBox({this.particle, this.spring, this.box}) {
130 _applyInvariants();
131 }
132
133 void update(double deltaT) {
134 particle.applyImpulse(spring.force * deltaT);
135 particle.update(deltaT);
136 _applyInvariants();
137 }
138
139 void _applyInvariants() {
140 box.confine(particle);
141 spring.displacement = particle.position;
142 }
143 }
144
145 class ParticleClimbingRamp extends System {
146
147 // This is technically the same as ParticleInBoxWithFriction. The
148 // difference is in how the system is set up. Here, we configure the
149 // system so as to stop by a certain distance after having been
150 // given an initial impulse from rest, whereas
151 // ParticleInBoxWithFriction is set up to stop with a consistent
152 // decelerating force assuming an initial velocity. The angle theta
153 // (0 < theta < π/2) is used to configure how much energy the
154 // particle is to start with; lower angles result in a gentler kick
155 // while higher angles result in a faster conclusion.
156
157 final Particle particle;
158 final Box box;
159 final double theta;
160 final double _sinTheta;
161
162 ParticleClimbingRamp({
163 this.particle,
164 this.box,
165 double theta, // in radians
166 double targetPosition}) : this.theta = theta, this._sinTheta = math.sin(th eta) {
167 assert(theta > 0.0);
168 assert(theta < math.PI / 2.0);
169 double deltaPosition = targetPosition - particle.position;
170 double tanTheta = math.tan(theta);
171 // We need to give the particle exactly as much (kinetic) energy
172 // as it needs to get to the top of the slope and stop with
173 // energy=0. This is exactly the same amount of energy as the
174 // potential energy at the top of the slope, which is g*h*m.
175 // If the slope's horizontal component is delta P long, then
176 // the height is delta P times tan theta.
177 particle.setVelocityFromEnergy(
178 energy: (kGravity * (deltaPosition * tanTheta) * particle.mass).abs(),
179 direction: deltaPosition > 0.0 ? 1.0 : -1.0
180 );
181 box.confine(particle);
182 }
183
184 void update(double deltaT) {
185 particle.update(deltaT);
186 // Note that we apply the impulse from gravity after updating the particle's
187 // position so that we overestimate the distance traveled by the particle.
188 // That ensures that we actually hit the edge of the box and don't wind up
189 // reversing course.
190 particle.applyImpulse(particle.mass * kGravity * _sinTheta * deltaT);
191 box.confine(particle);
192 }
193 }
194
195 class Multisystem extends System {
196 final Particle particle;
197
198 System _currentSystem;
199
200 Multisystem({ this.particle, System system }) {
201 assert(system != null);
202 _currentSystem = system;
203 }
204
205 void update(double deltaT) {
206 _currentSystem.update(deltaT);
207 }
208
209 void transitionToSystem(System system) {
210 assert(system != null);
211 _currentSystem = system;
212 }
213 }
OLDNEW
« no previous file with comments | « sky/framework/animation/generators.dart ('k') | sky/framework/animation/scroll_behavior.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698