Skip to content

Commit

Permalink
Merge pull request #43 from nytm/develop
Browse files Browse the repository at this point in the history
v 0.6.1
  • Loading branch information
jaredsinclair committed Aug 31, 2016
2 parents ae59ca4 + 333d3a8 commit 06c4f07
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 34 deletions.
2 changes: 1 addition & 1 deletion NYT360Video.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'NYT360Video'
s.version = '0.6.0'
s.version = '0.6.1'
s.summary = 'NYT360Video plays 360º video streamed from an AVPlayer.'

s.description = <<-DESC
Expand Down
2 changes: 1 addition & 1 deletion NYT360VideoExample/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.6.0</string>
<string>0.6.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
2 changes: 1 addition & 1 deletion NYT360VideoTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.6.0</string>
<string>0.6.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
70 changes: 45 additions & 25 deletions NYT360VideoTests/NYT360EulerAngleCalculationsTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -135,72 +135,92 @@ - (void)testItCalculatesTheOptimalYFovForAVarietyOfInputs {

- (void)testItCalculatesTheCorrectCompassAngleForAVarietyOfInputs {

// Unless the host application needs a non-zero reference angle (zero is the
// default), we want an input camera rotation of 0 to yield a compass angle
// of 0 where 0 is pointing "due north".
//
// The y component of the SCNVector3 is positive in the counter-clockwise
// direction, whereas UIKit rotation transforms are positive in the
// clockwise direction. Thus we want to map camera rotation values to
// compass angle values by mapping them to the equivalent rotation transform
// in the opposite direction.
//
// For example, a positive quarter turn of the camera is equivalent to a
// negative quarter turn of a rotation transform, or:
//
// 0.25 cam rotations -> -0.25 rotation transform rotations
//
// or in their raw radian values:
//
// 1.571 camera radians -> -1.571 rotation transform radians

SCNVector3 eulerAngles;
float pi = M_PI;
float oneRotation = pi * 2.0;
float compassAngle;
float referenceAngle;

referenceAngle = NYT360EulerAngleCalculationDefaultReferenceCompassAngle;

eulerAngles.y = 0;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = pi;
eulerAngles.y = oneRotation;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = -pi;
eulerAngles.y = -oneRotation;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = pi * 0.5;
eulerAngles.y = oneRotation * -0.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi * 1.5, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * 0.5, 0.001);

eulerAngles.y = pi * -0.5;
eulerAngles.y = oneRotation * 0.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi * 0.5, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * -0.5, 0.001);

eulerAngles.y = pi * 1.5;
eulerAngles.y = oneRotation * -1.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi * 0.5, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * 0.5, 0.001);

eulerAngles.y = pi * -1.5;
eulerAngles.y = oneRotation * 1.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi * -0.5, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * -0.5, 0.001);

eulerAngles.y = pi * 2.0;
eulerAngles.y = oneRotation * -2.0;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = pi * -2.0;
eulerAngles.y = oneRotation * 2.0;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, -pi, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = pi * 2.5;
eulerAngles.y = oneRotation * -2.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi * 1.5, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * 0.5, 0.001);

eulerAngles.y = pi * -2.5;
eulerAngles.y = oneRotation * 2.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi * -1.5, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * -0.5, 0.001);

eulerAngles.y = pi * 3.0;
eulerAngles.y = oneRotation * 3.0;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = pi * -3.0;
eulerAngles.y = oneRotation * -3.0;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, 0, 0.001);

eulerAngles.y = pi * 4.0;
eulerAngles.y = oneRotation * -3.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, pi, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * 0.5, 0.001);

eulerAngles.y = pi * -4.0;
eulerAngles.y = oneRotation * 3.5;
compassAngle = NYT360CompassAngleForEulerAngles(eulerAngles, referenceAngle);
XCTAssertEqualWithAccuracy(compassAngle, -pi, 0.001);
XCTAssertEqualWithAccuracy(compassAngle, oneRotation * -0.5, 0.001);
}

@end
2 changes: 1 addition & 1 deletion Sources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.6.0</string>
<string>0.6.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
15 changes: 15 additions & 0 deletions Sources/NYT360EulerAngleCalculations.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,19 @@ NYT360EulerAngleCalculationResult NYT360PanGestureChangeCalculation(CGPoint posi

CGFloat NYT360OptimalYFovForViewSize(CGSize viewSize);

/**
* Unless the host application needs a non-zero reference angle (zero is the default), we want an input camera rotation of 0 to yield a compass angle of 0 where 0 is pointing "due north".
*
* The y component of the SCNVector3 is positive in the counter-clockwise direction, whereas UIKit rotation transforms are positive in the clockwise direction. Thus we want to map camera rotation values to compass angle values by mapping them to the equivalent rotation transform in the opposite direction.
*
* For example, a positive quarter turn of the camera is equivalent to a negative quarter turn of a rotation transform, or:
*
* 0.25 cam rotations -> -0.25 rotation transform rotations
*
* or in their raw radian values:
*
* 1.571 camera radians -> -1.571 rotation transform radians
*
* Input values in excess of one rotation will be mapped to an equivalent value within the range of plus or minus one radian, such that output values will exceed one rotation. Input values equal (or very very close to equal) to a multiple of one radian (positive or negative) will be mapped to 0.
*/
float NYT360CompassAngleForEulerAngles(SCNVector3 eulerAngles, float referenceAngle);
4 changes: 2 additions & 2 deletions Sources/NYT360EulerAngleCalculations.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#pragma mark - Constants

CGFloat const NYT360EulerAngleCalculationNoiseThresholdDefault = 0.12;
float const NYT360EulerAngleCalculationDefaultReferenceCompassAngle = M_PI;
float const NYT360EulerAngleCalculationDefaultReferenceCompassAngle = 0;

#pragma mark - Inline Functions

Expand Down Expand Up @@ -156,5 +156,5 @@ CGFloat NYT360OptimalYFovForViewSize(CGSize viewSize) {
}

float NYT360CompassAngleForEulerAngles(SCNVector3 eulerAngles, float referenceAngle) {
return NYT360UnitRotationForCameraRotation(eulerAngles.y + referenceAngle);
return NYT360UnitRotationForCameraRotation((-1.0 * eulerAngles.y) + referenceAngle);
}
15 changes: 14 additions & 1 deletion Sources/NYT360PlayerScene.m
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,20 @@ - (void)pause {
else {
// Prior to iOS 10, SceneKit prefers to use `setPaused:` alone to toggle
// playback on a video node. Mimic this usage here to ensure consistency
// and avoid putting the player into an out-of-sync state.
// and avoid putting the player into an out-of-sync state. There is one
// caveat, however: when the host application is pausing playback as the
// app is entering the background (and if background audio is enabled in
// the host application), then if you do not also call `pause` directly
// on the AVPlayer, then the player's audio will continue playing in the
// background. Even though this bug workaround means that our `pause`
// implementation is identical between iOS 8/9 and iOS 10, it's worth
// keeping the above check for the OS version since the edge cases
// before and after iOS 10 are different enough that it's worth keeping
// the implementations separated, if only for clarity that can be added
// via OS specific documentation (and also the fact that iOS 10's
// behavior may change between the current beta and a future production
// release).
[self.player pause];
self.videoNode.paused = YES;
}

Expand Down
6 changes: 4 additions & 2 deletions Sources/NYT360ViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
* Called when the compass angle is updated.
*
* @param viewController The view controller that updated the angle.
* @param compassAngle The current compass angle.
* @param compassAngle The current compass angle. The value will be within the range of plus or minus one radian, non-inclusive, where a positive value is equivalent to a clockwise rotation.
*
* @note This method is called synchronously from SCNSceneRendererDelegate; its implementation should return quickly to avoid performance implications.
*/
Expand Down Expand Up @@ -62,7 +62,9 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Camera Movement

/**
Returns the current compass angle.
* Returns the current compass angle.
*
* The value will be within the range of plus or minus one radian, non-inclusive, where a positive value is equivalent to a clockwise rotation.
*/
@property (nonatomic, readonly) float compassAngle;

Expand Down
4 changes: 4 additions & 0 deletions Sources/NYT360ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ - (instancetype)initWithAVPlayer:(AVPlayer *)player motionManager:(id<NYT360Moti
typeof(self) __weak weakSelf = self;
_cameraController.compassAngleUpdateBlock = ^(float compassAngle) {
typeof(self) strongSelf = weakSelf;
if (!strongSelf) {
return;
}

[strongSelf.delegate nyt360ViewController:strongSelf didUpdateCompassAngle:strongSelf.compassAngle];
};

Expand Down

0 comments on commit 06c4f07

Please sign in to comment.