Skip to content
Open
32 changes: 32 additions & 0 deletions RBBAnimation.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
objects = {

/* Begin PBXBuildFile section */
5409356419052226007565F7 /* RBBDampedHarmonicOscillaton.m in Sources */ = {isa = PBXBuildFile; fileRef = 5466A9B418F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.m */; };
540935651905223A007565F7 /* RBBDampedHarmonicOscillaton.h in Headers */ = {isa = PBXBuildFile; fileRef = 5466A9B318F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.h */; };
540935661905223D007565F7 /* RBBRubberbandAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 545FEFD418F177B000900B78 /* RBBRubberbandAnimation.h */; };
5409356719052241007565F7 /* RBBRubberbandAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 545FEFD518F177B000900B78 /* RBBRubberbandAnimation.m */; };
540935681905224C007565F7 /* RBBDampedHarmonicOscillatonSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 549ECA8518F7010400D968C7 /* RBBDampedHarmonicOscillatonSpec.m */; };
5409356919052251007565F7 /* RBBRubberbandAnimationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 549ECA8718F7028E00D968C7 /* RBBRubberbandAnimationSpec.m */; };
540F65A318F81DC9005A6BB8 /* Pods-RBBAnimationTest.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 540F65A218F81DC9005A6BB8 /* Pods-RBBAnimationTest.xcconfig */; };
540F65A718F82347005A6BB8 /* NSValue+PlatformIndependence.h in Headers */ = {isa = PBXBuildFile; fileRef = 540F65A518F82347005A6BB8 /* NSValue+PlatformIndependence.h */; settings = {ATTRIBUTES = (Private, ); }; };
540F65A818F82347005A6BB8 /* NSValue+PlatformIndependence.m in Sources */ = {isa = PBXBuildFile; fileRef = 540F65A618F82347005A6BB8 /* NSValue+PlatformIndependence.m */; };
Expand All @@ -24,6 +30,8 @@
545D5ABF180B2D3F00FC94AB /* RBBCubicBezier.m in Sources */ = {isa = PBXBuildFile; fileRef = 545D5ABE180B2D3F00FC94AB /* RBBCubicBezier.m */; };
545D5AC2180B5E8400FC94AB /* RBBEasingFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 545D5AC1180B5E8400FC94AB /* RBBEasingFunction.m */; };
545D5AC5180C138D00FC94AB /* RBBSpringAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 545D5AC4180C138D00FC94AB /* RBBSpringAnimation.m */; };
545FEFD618F177B000900B78 /* RBBRubberbandAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 545FEFD518F177B000900B78 /* RBBRubberbandAnimation.m */; };
5466A9B518F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.m in Sources */ = {isa = PBXBuildFile; fileRef = 5466A9B418F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.m */; };
5466C56118082BEB00652BDC /* RBBBlockBasedArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 5466C56018082BEB00652BDC /* RBBBlockBasedArray.m */; };
5466C56318082D4200652BDC /* RBBBlockBasedArraySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5466C56218082D4200652BDC /* RBBBlockBasedArraySpec.m */; };
5466C569180849D100652BDC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54F3AE2D1807394800E1E688 /* Foundation.framework */; };
Expand All @@ -37,6 +45,8 @@
5466C59818084BA200652BDC /* RBBAnimationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5466C59718084BA200652BDC /* RBBAnimationViewController.m */; };
5479BEA4181D8008009811FD /* RBBCustomAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5479BEA3181D8008009811FD /* RBBCustomAnimation.m */; };
549ECA8418F6ECFC00D968C7 /* RBBSpringAnimationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 549ECA8318F6ECFC00D968C7 /* RBBSpringAnimationSpec.m */; };
549ECA8618F7010400D968C7 /* RBBDampedHarmonicOscillatonSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 549ECA8518F7010400D968C7 /* RBBDampedHarmonicOscillatonSpec.m */; };
549ECA8818F7028E00D968C7 /* RBBRubberbandAnimationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 549ECA8718F7028E00D968C7 /* RBBRubberbandAnimationSpec.m */; };
549ECA9618F814A000D968C7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549ECA9518F814A000D968C7 /* Cocoa.framework */; };
549ECAAA18F814A000D968C7 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54F3AE3B1807394800E1E688 /* XCTest.framework */; };
549ECAAB18F814A000D968C7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549ECA9518F814A000D968C7 /* Cocoa.framework */; };
Expand Down Expand Up @@ -133,6 +143,10 @@
545D5AC1180B5E8400FC94AB /* RBBEasingFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBEasingFunction.m; sourceTree = "<group>"; };
545D5AC3180C138D00FC94AB /* RBBSpringAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBBSpringAnimation.h; sourceTree = "<group>"; };
545D5AC4180C138D00FC94AB /* RBBSpringAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBSpringAnimation.m; sourceTree = "<group>"; };
545FEFD418F177B000900B78 /* RBBRubberbandAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBBRubberbandAnimation.h; sourceTree = "<group>"; };
545FEFD518F177B000900B78 /* RBBRubberbandAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBRubberbandAnimation.m; sourceTree = "<group>"; };
5466A9B318F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBBDampedHarmonicOscillaton.h; sourceTree = "<group>"; };
5466A9B418F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBDampedHarmonicOscillaton.m; sourceTree = "<group>"; };
5466C55F18082BEB00652BDC /* RBBBlockBasedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBBBlockBasedArray.h; sourceTree = "<group>"; };
5466C56018082BEB00652BDC /* RBBBlockBasedArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBBlockBasedArray.m; sourceTree = "<group>"; };
5466C56218082D4200652BDC /* RBBBlockBasedArraySpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBBlockBasedArraySpec.m; sourceTree = "<group>"; };
Expand All @@ -150,6 +164,8 @@
5479BEA2181D8008009811FD /* RBBCustomAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RBBCustomAnimation.h; sourceTree = "<group>"; };
5479BEA3181D8008009811FD /* RBBCustomAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBCustomAnimation.m; sourceTree = "<group>"; };
549ECA8318F6ECFC00D968C7 /* RBBSpringAnimationSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBSpringAnimationSpec.m; sourceTree = "<group>"; };
549ECA8518F7010400D968C7 /* RBBDampedHarmonicOscillatonSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBDampedHarmonicOscillatonSpec.m; sourceTree = "<group>"; };
549ECA8718F7028E00D968C7 /* RBBRubberbandAnimationSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RBBRubberbandAnimationSpec.m; sourceTree = "<group>"; };
549ECA9418F814A000D968C7 /* RBBAnimation Mac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "RBBAnimation Mac.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
549ECA9518F814A000D968C7 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; };
549ECA9818F814A000D968C7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -326,6 +342,10 @@
545D5AB9180B1FAE00FC94AB /* RBBTweenAnimation.m */,
545D5AC3180C138D00FC94AB /* RBBSpringAnimation.h */,
545D5AC4180C138D00FC94AB /* RBBSpringAnimation.m */,
545FEFD418F177B000900B78 /* RBBRubberbandAnimation.h */,
545FEFD518F177B000900B78 /* RBBRubberbandAnimation.m */,
5466A9B318F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.h */,
5466A9B418F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.m */,
54D5EA87181AE8620014896C /* RBBLinearInterpolation.h */,
54D5EA88181AE8620014896C /* RBBLinearInterpolation.m */,
545D5AC0180B5E8400FC94AB /* RBBEasingFunction.h */,
Expand Down Expand Up @@ -358,8 +378,10 @@
isa = PBXGroup;
children = (
5466C56218082D4200652BDC /* RBBBlockBasedArraySpec.m */,
549ECA8518F7010400D968C7 /* RBBDampedHarmonicOscillatonSpec.m */,
540F65AA18F82B3E005A6BB8 /* RBBLinearInterpolationSpec.m */,
549ECA8318F6ECFC00D968C7 /* RBBSpringAnimationSpec.m */,
549ECA8718F7028E00D968C7 /* RBBRubberbandAnimationSpec.m */,
54F3AE441807394800E1E688 /* Supporting Files */,
);
path = Specs;
Expand All @@ -386,6 +408,8 @@
549ECAC418F8157200D968C7 /* RBBSpringAnimation.h in Headers */,
549ECACA18F8157200D968C7 /* RBBCubicBezier.h in Headers */,
549ECAC018F8157200D968C7 /* RBBCustomAnimation.h in Headers */,
540935651905223A007565F7 /* RBBDampedHarmonicOscillaton.h in Headers */,
540935661905223D007565F7 /* RBBRubberbandAnimation.h in Headers */,
549ECAC618F8157200D968C7 /* RBBLinearInterpolation.h in Headers */,
540F65A718F82347005A6BB8 /* NSValue+PlatformIndependence.h in Headers */,
540F65AF18F83EB3005A6BB8 /* NSColor+PlatformIndependence.h in Headers */,
Expand Down Expand Up @@ -695,6 +719,8 @@
549ECAC718F8157200D968C7 /* RBBLinearInterpolation.m in Sources */,
549ECABF18F8157200D968C7 /* RBBAnimation.m in Sources */,
549ECACD18F8157200D968C7 /* RBBBlockBasedArray.m in Sources */,
5409356719052241007565F7 /* RBBRubberbandAnimation.m in Sources */,
5409356419052226007565F7 /* RBBDampedHarmonicOscillaton.m in Sources */,
549ECACB18F8157200D968C7 /* RBBCubicBezier.m in Sources */,
540F65A918F82347005A6BB8 /* NSValue+PlatformIndependence.m in Sources */,
);
Expand All @@ -707,6 +733,8 @@
549ECABD18F8155800D968C7 /* RBBBlockBasedArraySpec.m in Sources */,
549ECABE18F8155B00D968C7 /* RBBSpringAnimationSpec.m in Sources */,
540F65AC18F82C67005A6BB8 /* RBBLinearInterpolationSpec.m in Sources */,
5409356919052251007565F7 /* RBBRubberbandAnimationSpec.m in Sources */,
540935681905224C007565F7 /* RBBDampedHarmonicOscillatonSpec.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -720,6 +748,8 @@
54D5EA89181AE8620014896C /* RBBLinearInterpolation.m in Sources */,
545D5AC2180B5E8400FC94AB /* RBBEasingFunction.m in Sources */,
5466C56118082BEB00652BDC /* RBBBlockBasedArray.m in Sources */,
545FEFD618F177B000900B78 /* RBBRubberbandAnimation.m in Sources */,
5466A9B518F6C2260090E3E6 /* RBBDampedHarmonicOscillaton.m in Sources */,
545D5ABA180B1FAE00FC94AB /* RBBTweenAnimation.m in Sources */,
545D5AC5180C138D00FC94AB /* RBBSpringAnimation.m in Sources */,
54F3AE351807394800E1E688 /* RBBAnimation.m in Sources */,
Expand All @@ -733,6 +763,8 @@
files = (
5466C56318082D4200652BDC /* RBBBlockBasedArraySpec.m in Sources */,
549ECA8418F6ECFC00D968C7 /* RBBSpringAnimationSpec.m in Sources */,
549ECA8618F7010400D968C7 /* RBBDampedHarmonicOscillatonSpec.m in Sources */,
549ECA8818F7028E00D968C7 /* RBBRubberbandAnimationSpec.m in Sources */,
540F65AB18F82B3E005A6BB8 /* RBBLinearInterpolationSpec.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
4 changes: 4 additions & 0 deletions RBBAnimation/NSValue+PlatformIndependence.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
//

#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
#import <UIKit/UIKit.h>
#endif

#import <Foundation/Foundation.h>

@interface NSValue (PlatformIndependence)
Expand Down
4 changes: 0 additions & 4 deletions RBBAnimation/NSValue+PlatformIndependence.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
//

#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
#import <UIKit/UIKit.h>
#endif

#import "NSValue+PlatformIndependence.h"

@implementation NSValue (PlatformIndependence)
Expand Down
13 changes: 13 additions & 0 deletions RBBAnimation/RBBDampedHarmonicOscillaton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// RBBDampedHarmonicOscillaton.h
// RBBAnimation
//
// Created by Robert Böhnke on 10/04/14.
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
//

#import <QuartzCore/QuartzCore.h>

typedef CGFloat (^RBBOsciallation)(CGFloat t);

RBBOsciallation RBBDampedHarmonicOscillation(CGFloat x0, CGFloat damping, CGFloat mass, CGFloat stiffness, CGFloat velocity, BOOL allowsOverdamping);
45 changes: 45 additions & 0 deletions RBBAnimation/RBBDampedHarmonicOscillaton.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// RBBDampedHarmonicOscillaton.m
// RBBAnimation
//
// Created by Robert Böhnke on 10/04/14.
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
//

#import "RBBDampedHarmonicOscillaton.h"

RBBOsciallation RBBDampedHarmonicOscillation(CGFloat x0, CGFloat b, CGFloat m, CGFloat k, CGFloat v0, BOOL allowsOverdamping) {
NSCAssert(m > 0, @"mass must be greater than zero.");
NSCAssert(k > 0, @"stiffness must be greater than zero.");
NSCAssert(b > 0, @"damping must be greater than zero.");

CGFloat beta = b / (2 * m);
CGFloat omega0 = sqrtf(k / m);
CGFloat omega1 = sqrtf((omega0 * omega0) - (beta * beta));
CGFloat omega2 = sqrtf((beta * beta) - (omega0 * omega0));

if (!allowsOverdamping && beta > omega0) beta = omega0;

if (beta < omega0) {
// Underdamped
return ^(CGFloat t) {
CGFloat envelope = expf(-beta * t);

return envelope * (x0 * cosf(omega1 * t) + ((beta * x0 + v0) / omega1) * sinf(omega1 * t));
};
} else if (beta == omega0) {
// Critically damped
return ^(CGFloat t) {
CGFloat envelope = expf(-beta * t);

return envelope * (x0 + (beta * x0 + v0) * t);
};
} else {
// Overdamped
return ^(CGFloat t) {
CGFloat envelope = expf(-beta * t);

return envelope * (x0 * coshf(omega2 * t) + ((beta * x0 + v0) / omega2) * sinhf(omega2 * t));
};
}
}
27 changes: 27 additions & 0 deletions RBBAnimation/RBBRubberbandAnimation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// RBBRubberbandAnimation.h
// RBBAnimation
//
// Created by Robert Böhnke on 06/04/14.
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
//

#import <QuartzCore/QuartzCore.h>

#import "RBBAnimation.h"

@interface RBBRubberbandAnimation : RBBAnimation

@property (readwrite, nonatomic, assign) CGFloat damping;
@property (readwrite, nonatomic, assign) CGFloat mass;
@property (readwrite, nonatomic, assign) CGFloat stiffness;
@property (readwrite, nonatomic, assign) CGPoint velocity;

@property (readwrite, nonatomic, assign) CGPoint from;
@property (readwrite, nonatomic, assign) CGPoint to;

@property (readwrite, nonatomic, assign) BOOL allowsOverdamping;

- (CFTimeInterval)durationForEpsilon:(double)epsilon;

@end
95 changes: 95 additions & 0 deletions RBBAnimation/RBBRubberbandAnimation.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//
// RBBRubberbandAnimation.m
// RBBAnimation
//
// Created by Robert Böhnke on 06/04/14.
// Copyright (c) 2014 Robert Böhnke. All rights reserved.
//

#import "NSValue+PlatformIndependence.h"

#import "RBBDampedHarmonicOscillaton.h"

#import "RBBRubberbandAnimation.h"

@implementation RBBRubberbandAnimation

#pragma mark - Lifecycle

- (id)init {
self = [super init];
if (self == nil) return nil;

self.damping = 10;
self.mass = 1;
self.stiffness = 100;

return self;
}

#pragma mark - KVO

+ (NSSet *)keyPathsForValuesAffectingAnimationBlock {
return [NSSet setWithArray:@[
@"damping",
@"mass",
@"stiffness",
@"velocity",
@"from",
@"to",
@"allowsOverdamping"
]];
}

#pragma mark - RBBSpringAnimation

- (CFTimeInterval)durationForEpsilon:(double)epsilon {
CGFloat beta = self.damping / (2 * self.mass);

CFTimeInterval duration = 0;
while (expf(-beta * duration) >= epsilon) {
duration += 0.1;
}

return duration;
}

#pragma mark - RBBAnimation

- (RBBAnimationBlock)animationBlock {
CGFloat deltaX = self.from.x - self.to.x;
CGFloat deltaY = self.from.y - self.to.y;

RBBOsciallation oscillationX = RBBDampedHarmonicOscillation(deltaX, self.damping, self.mass, self.stiffness, self.velocity.x, self.allowsOverdamping);
RBBOsciallation oscillationY = RBBDampedHarmonicOscillation(deltaY, self.damping, self.mass, self.stiffness, self.velocity.y, self.allowsOverdamping);

CGFloat x0 = self.to.x;
CGFloat y0 = self.to.y;

return ^(CGFloat t, CGFloat _) {
CGPoint p = { .x = x0 + oscillationX(t), .y = y0 + oscillationY(t) };

return [NSValue rbb_valueWithCGPoint:p];
};
}

#pragma mark - NSObject

- (id)copyWithZone:(NSZone *)zone {
RBBRubberbandAnimation *copy = [super copyWithZone:zone];
if (copy == nil) return nil;

copy->_damping = _damping;
copy->_mass = _mass;
copy->_stiffness = _stiffness;
copy->_velocity = _velocity;

copy->_from = _from;
copy->_to = _to;

copy->_allowsOverdamping = _allowsOverdamping;

return copy;
}

@end
45 changes: 3 additions & 42 deletions RBBAnimation/RBBSpringAnimation.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import "RBBBlockBasedArray.h"
#import "RBBDampedHarmonicOscillaton.h"
#import "RBBLinearInterpolation.h"

#import "RBBSpringAnimation.h"
Expand Down Expand Up @@ -58,51 +59,11 @@ - (CFTimeInterval)durationForEpsilon:(double)epsilon {
#pragma mark - RBBAnimation

- (RBBAnimationBlock)animationBlock {
CGFloat b = self.damping;
CGFloat m = self.mass;
CGFloat k = self.stiffness;
CGFloat v0 = self.velocity;

NSParameterAssert(m > 0);
NSParameterAssert(k > 0);
NSParameterAssert(b > 0);

CGFloat beta = b / (2 * m);
CGFloat omega0 = sqrtf(k / m);
CGFloat omega1 = sqrtf((omega0 * omega0) - (beta * beta));
CGFloat omega2 = sqrtf((beta * beta) - (omega0 * omega0));

CGFloat x0 = -1;

if (!self.allowsOverdamping && beta > omega0) beta = omega0;

CGFloat (^oscillation)(CGFloat);
if (beta < omega0) {
// Underdamped
oscillation = ^(CGFloat t) {
CGFloat envelope = expf(-beta * t);

return -x0 + envelope * (x0 * cosf(omega1 * t) + ((beta * x0 + v0) / omega1) * sinf(omega1 * t));
};
} else if (beta == omega0) {
// Critically damped
oscillation = ^(CGFloat t) {
CGFloat envelope = expf(-beta * t);

return -x0 + envelope * (x0 + (beta * x0 + v0) * t);
};
} else {
// Overdamped
oscillation = ^(CGFloat t) {
CGFloat envelope = expf(-beta * t);

return -x0 + envelope * (x0 * coshf(omega2 * t) + ((beta * x0 + v0) / omega2) * sinhf(omega2 * t));
};
}
CGFloat (^oscillation)(CGFloat) = RBBDampedHarmonicOscillation(-1, self.damping, self.mass, self.stiffness, self.velocity, self.allowsOverdamping);

RBBLinearInterpolation lerp = RBBInterpolate(self.fromValue, self.toValue);
return ^(CGFloat t, CGFloat _) {
return lerp(oscillation(t));
return lerp(1 + oscillation(t));
};
}

Expand Down
Loading