| Index: sky/framework/animation/mechanics.dart
|
| diff --git a/sky/framework/animation/mechanics.dart b/sky/framework/animation/mechanics.dart
|
| deleted file mode 100644
|
| index 6a6cc4cad46f7f8c744afe9cd8ac06757e5ba1a8..0000000000000000000000000000000000000000
|
| --- a/sky/framework/animation/mechanics.dart
|
| +++ /dev/null
|
| @@ -1,213 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -import 'dart:math' as math;
|
| -
|
| -const double kGravity = -0.980; // m^s-2
|
| -
|
| -abstract class System {
|
| - void update(double deltaT);
|
| -}
|
| -
|
| -class Particle extends System {
|
| - final double mass;
|
| - double velocity;
|
| - double position;
|
| -
|
| - Particle({this.mass: 1.0, this.velocity: 0.0, this.position: 0.0});
|
| -
|
| - void applyImpulse(double impulse) {
|
| - velocity += impulse / mass;
|
| - }
|
| -
|
| - void update(double deltaT) {
|
| - position += velocity * deltaT;
|
| - }
|
| -
|
| - void setVelocityFromEnergy({double energy, double direction}) {
|
| - assert(direction == -1.0 || direction == 1.0);
|
| - assert(energy >= 0.0);
|
| - velocity = math.sqrt(2.0 * energy / mass) * direction;
|
| - }
|
| -}
|
| -
|
| -abstract class Box {
|
| - void confine(Particle p);
|
| -}
|
| -
|
| -class ClosedBox extends Box {
|
| - final double min; // m
|
| - final double max; // m
|
| -
|
| - ClosedBox({this.min, this.max}) {
|
| - assert(min == null || max == null || min <= max);
|
| - }
|
| -
|
| - void confine(Particle p) {
|
| - if (min != null) {
|
| - p.position = math.max(min, p.position);
|
| - if (p.position == min)
|
| - p.velocity = math.max(0.0, p.velocity);
|
| - }
|
| - if (max != null) {
|
| - p.position = math.min(max, p.position);
|
| - if (p.position == max)
|
| - p.velocity = math.min(0.0, p.velocity);
|
| - }
|
| - }
|
| -}
|
| -
|
| -class GeofenceBox extends Box {
|
| - final double min; // m
|
| - final double max; // m
|
| -
|
| - final Function onEscape;
|
| -
|
| - GeofenceBox({this.min, this.max, this.onEscape}) {
|
| - assert(min == null || max == null || min <= max);
|
| - assert(onEscape != null);
|
| - }
|
| -
|
| - void confine(Particle p) {
|
| - if (((min != null) && (p.position < min)) ||
|
| - ((max != null) && (p.position > max)))
|
| - onEscape();
|
| - }
|
| -}
|
| -
|
| -class ParticleInBox extends System {
|
| - final Particle particle;
|
| - final Box box;
|
| -
|
| - ParticleInBox({this.particle, this.box}) {
|
| - box.confine(particle);
|
| - }
|
| -
|
| - void update(double deltaT) {
|
| - particle.update(deltaT);
|
| - box.confine(particle);
|
| - }
|
| -}
|
| -
|
| -class ParticleInBoxWithFriction extends ParticleInBox {
|
| - final double friction; // unitless
|
| - final double _sign;
|
| -
|
| - final Function onStop;
|
| -
|
| - ParticleInBoxWithFriction({Particle particle, Box box, this.friction, this.onStop})
|
| - : super(particle: particle, box: box),
|
| - _sign = particle.velocity.sign;
|
| -
|
| - void update(double deltaT) {
|
| - double force = -_sign * friction * particle.mass * -kGravity;
|
| - particle.applyImpulse(force * deltaT);
|
| - if (particle.velocity.sign != _sign) {
|
| - particle.velocity = 0.0;
|
| - }
|
| - super.update(deltaT);
|
| - if ((particle.velocity == 0.0) && (onStop != null))
|
| - onStop();
|
| - }
|
| -}
|
| -
|
| -class Spring {
|
| - final double k;
|
| - double displacement;
|
| -
|
| - Spring(this.k, {this.displacement: 0.0});
|
| -
|
| - double get force => -k * displacement;
|
| -}
|
| -
|
| -class ParticleAndSpringInBox extends System {
|
| - final Particle particle;
|
| - final Spring spring;
|
| - final Box box;
|
| -
|
| - ParticleAndSpringInBox({this.particle, this.spring, this.box}) {
|
| - _applyInvariants();
|
| - }
|
| -
|
| - void update(double deltaT) {
|
| - particle.applyImpulse(spring.force * deltaT);
|
| - particle.update(deltaT);
|
| - _applyInvariants();
|
| - }
|
| -
|
| - void _applyInvariants() {
|
| - box.confine(particle);
|
| - spring.displacement = particle.position;
|
| - }
|
| -}
|
| -
|
| -class ParticleClimbingRamp extends System {
|
| -
|
| - // This is technically the same as ParticleInBoxWithFriction. The
|
| - // difference is in how the system is set up. Here, we configure the
|
| - // system so as to stop by a certain distance after having been
|
| - // given an initial impulse from rest, whereas
|
| - // ParticleInBoxWithFriction is set up to stop with a consistent
|
| - // decelerating force assuming an initial velocity. The angle theta
|
| - // (0 < theta < π/2) is used to configure how much energy the
|
| - // particle is to start with; lower angles result in a gentler kick
|
| - // while higher angles result in a faster conclusion.
|
| -
|
| - final Particle particle;
|
| - final Box box;
|
| - final double theta;
|
| - final double _sinTheta;
|
| -
|
| - ParticleClimbingRamp({
|
| - this.particle,
|
| - this.box,
|
| - double theta, // in radians
|
| - double targetPosition}) : this.theta = theta, this._sinTheta = math.sin(theta) {
|
| - assert(theta > 0.0);
|
| - assert(theta < math.PI / 2.0);
|
| - double deltaPosition = targetPosition - particle.position;
|
| - double tanTheta = math.tan(theta);
|
| - // We need to give the particle exactly as much (kinetic) energy
|
| - // as it needs to get to the top of the slope and stop with
|
| - // energy=0. This is exactly the same amount of energy as the
|
| - // potential energy at the top of the slope, which is g*h*m.
|
| - // If the slope's horizontal component is delta P long, then
|
| - // the height is delta P times tan theta.
|
| - particle.setVelocityFromEnergy(
|
| - energy: (kGravity * (deltaPosition * tanTheta) * particle.mass).abs(),
|
| - direction: deltaPosition > 0.0 ? 1.0 : -1.0
|
| - );
|
| - box.confine(particle);
|
| - }
|
| -
|
| - void update(double deltaT) {
|
| - particle.update(deltaT);
|
| - // Note that we apply the impulse from gravity after updating the particle's
|
| - // position so that we overestimate the distance traveled by the particle.
|
| - // That ensures that we actually hit the edge of the box and don't wind up
|
| - // reversing course.
|
| - particle.applyImpulse(particle.mass * kGravity * _sinTheta * deltaT);
|
| - box.confine(particle);
|
| - }
|
| -}
|
| -
|
| -class Multisystem extends System {
|
| - final Particle particle;
|
| -
|
| - System _currentSystem;
|
| -
|
| - Multisystem({ this.particle, System system }) {
|
| - assert(system != null);
|
| - _currentSystem = system;
|
| - }
|
| -
|
| - void update(double deltaT) {
|
| - _currentSystem.update(deltaT);
|
| - }
|
| -
|
| - void transitionToSystem(System system) {
|
| - assert(system != null);
|
| - _currentSystem = system;
|
| - }
|
| -}
|
|
|