From db959a83fa2108a6f830df9889dc6433d91dce00 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 22 Sep 2014 14:22:49 -0400 Subject: [PATCH 01/30] Removed clamp of Camera.tilt to [0, pi / 2]. --- CHANGES.md | 1 + Source/Scene/Camera.js | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e3a7f45ab713..c2c7d68a6c05 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Change Log a url to a glTF file. [#2078](https://github.com/AnalyticalGraphicsInc/cesium/issues/2078) * Added support for WKID 102113 (equivalent to 102100) to `ArcGisMapServerImageryProvider`. * Added `TerrainProvider.getTileDataAvailable` to improve tile loading performance when camera starts near globe. +* Removed clamp of Camera.tilt to [0, pi / 2]. ### 1.1 - 2014-09-02 diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 8cfdd5e8a973..07a384b3e2d4 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -733,9 +733,7 @@ define([ //>>includeEnd('debug'); if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - angle = CesiumMath.clamp(angle, 0.0, CesiumMath.PI_OVER_TWO); angle = angle - this.tilt; - this.look(this.right, angle); } } From 41e65419aeb4677f7b5e814f260ce099a2120658 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 29 Sep 2014 15:24:54 -0400 Subject: [PATCH 02/30] Clamp tilt to [-pi / 2, pi/ 2] and add Camera.roll. --- CHANGES.md | 3 ++- Source/Scene/Camera.js | 48 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ac4a1ac6bb72..103db6a5487d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,7 +12,8 @@ a url to a glTF file. [#2078](https://github.com/AnalyticalGraphicsInc/cesium/i * Added a constructor option to `Scene`, `CesiumWidget`, and `Viewer` to disable order independent translucency. * Added support for WKID 102113 (equivalent to 102100) to `ArcGisMapServerImageryProvider`. * Added `TerrainProvider.getTileDataAvailable` to improve tile loading performance when camera starts near globe. -* Removed clamp of Camera.tilt to [0, pi / 2]. +* Clamp of `Camera.tilt` to [-pi / 2, pi / 2] instead of [0, pi / 2]. +* Add `Camera.roll`. * Added `Globe.showWaterEffect` to enable/disable the water effect for supported terrain providers. ### 1.1 - 2014-09-02 diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 07a384b3e2d4..eb48c099e397 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -553,6 +553,21 @@ define([ return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(Cartesian3.dot(camera.direction, direction)); } + function getRoll3D(camera) { + var ellipsoid = camera._projection.ellipsoid; + var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid, scratchHeadingMatrix4); + var transform = Matrix4.getRotation(toFixedFrame, scratchHeadingMatrix3); + Matrix3.transpose(transform, transform); + + var up = Matrix3.multiplyByVector(transform, camera.up, scratchHeadingCartesian3); + if (CesiumMath.equalsEpsilon(Math.abs(up.z), 1.0, CesiumMath.EPSILON6)) { + return 0.0; + } + + var right = Matrix3.multiplyByVector(transform, camera.right, scratchHeadingCartesian3); + return Math.atan2(right.z, right.x); + } + defineProperties(Camera.prototype, { /** * Gets the inverse camera transform. @@ -708,7 +723,7 @@ define([ }, /** - * Gets or sets the camera tilt in radians + * Gets or sets the camera tilt in radians. * @memberof Camera.prototype * * @type {Number} @@ -733,10 +748,41 @@ define([ //>>includeEnd('debug'); if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + angle = CesiumMath.clamp(angle, -CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO); angle = angle - this.tilt; this.look(this.right, angle); } } + }, + + /** + * Gets or sets the camera roll in radians. + * @memberof Camera.prototype + * + * @type {Number} + */ + roll : { + get : function() { + if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + return getRoll3D(this); + } + + return undefined; + }, + //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 + set : function(angle) { + + //>>includeStart('debug', pragmas.debug); + if (!defined(angle)) { + throw new DeveloperError('angle is required.'); + } + //>>includeEnd('debug'); + + if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + angle = getRoll3D(this) - angle; + this.look(this.direction, angle); + } + } } }); From 0e36f299f1c16b96fc976a723252b0622dc5c95f Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 14 Oct 2014 16:18:04 -0400 Subject: [PATCH 03/30] Fix roll add tests. --- CHANGES.md | 4 +-- Source/Scene/Camera.js | 15 +++++++-- Specs/Scene/CameraSpec.js | 67 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2c40424c9501..4b9d97d7a47e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,8 @@ Change Log * Fixed a bug that caused non-base imagery layers with a limited `rectangle` to be stretched to the edges of imagery tiles. [#416](https://github.com/AnalyticalGraphicsInc/cesium/issues/416) * Added support to the `CesiumTerrainProvider` for handling terrain tiles that define more than 64k vertices. +* Clamp of `Camera.tilt` to [-pi / 2, pi / 2] instead of [0, pi / 2]. +* Add `Camera.roll`. ### 1.2 - 2014-10-01 @@ -22,8 +24,6 @@ Change Log * Added a constructor option to `Scene`, `CesiumWidget`, and `Viewer` to disable order independent translucency. * Added support for WKID 102113 (equivalent to 102100) to `ArcGisMapServerImageryProvider`. * Added `TerrainProvider.getTileDataAvailable` to improve tile loading performance when camera starts near globe. -* Clamp of `Camera.tilt` to [-pi / 2, pi / 2] instead of [0, pi / 2]. -* Add `Camera.roll`. * Added `Globe.showWaterEffect` to enable/disable the water effect for supported terrain providers. * Added `Globe.baseColor` to set the color of the globe when no imagery is available. * Changed default `GeoJSON` Point feature graphics to use `BillboardGraphics` with a blue map pin instead of color `PointGraphics`. diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index eb48c099e397..2da54151715c 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -553,6 +553,15 @@ define([ return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(Cartesian3.dot(camera.direction, direction)); } + function getRollCV(camera) { + if (CesiumMath.equalsEpsilon(Math.abs(camera.up.z), 1.0, CesiumMath.EPSILON6)) { + return 0.0; + } + + var right = camera.right; + return Math.atan2(right.z, right.x); + } + function getRoll3D(camera) { var ellipsoid = camera._projection.ellipsoid; var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid, scratchHeadingMatrix4); @@ -763,7 +772,9 @@ define([ */ roll : { get : function() { - if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + if (this._mode === SceneMode.COLUMBUS_VIEW) { + return getRollCV(this); + } else if (this._mode === SceneMode.SCENE3D) { return getRoll3D(this); } @@ -779,7 +790,7 @@ define([ //>>includeEnd('debug'); if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - angle = getRoll3D(this) - angle; + angle = angle - this.roll; this.look(this.direction, angle); } } diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index 100dd19c4a8f..858fde704558 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -250,6 +250,73 @@ defineSuite([ expect(camera.tilt).toEqualEpsilon(newTilt, CesiumMath.EPSILON14); }); + it('roll is undefined when not 3D or Columbus view', function() { + camera._mode = SceneMode.SCENE2D; + expect(camera.roll).not.toBeDefined(); + }); + + it('get roll in CV', function() { + camera._mode = SceneMode.COLUMBUS_VIEW; + + var roll = Math.atan2(right.z, right.x); + expect(camera.roll).toEqual(roll); + }); + + it('get roll in 3D', function() { + camera._mode = SceneMode.SCENE3D; + + var ellipsoid = Ellipsoid.WGS84; + var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid); + var transform = Matrix4.getRotation(toFixedFrame, new Matrix3()); + Matrix3.transpose(transform, transform); + + var right = Matrix3.multiplyByVector(transform, camera.right, new Cartesian3()); + var roll = Math.atan2(right.z, right.x); + + expect(camera.roll).toEqual(roll); + }); + + it('set roll throws without angle', function() { + expect(function() { + camera.roll = undefined; + }).toThrowDeveloperError(); + }); + + it('set roll in CV', function() { + camera._mode = SceneMode.COLUMBUS_VIEW; + + camera.position = new Cartesian3(100.0, 0.0, 100.0); + camera.direction = new Cartesian3(0.0, 1.0, -1.0); + Cartesian3.normalize(camera.direction, camera.direction); + camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); + + var roll = camera.roll; + var newRoll = CesiumMath.PI_OVER_TWO; + camera.roll = newRoll; + + expect(camera.roll).not.toEqual(roll); + expect(camera.roll).toEqualEpsilon(newRoll, CesiumMath.EPSILON12); + }); + + it('set roll in 3D', function() { + camera._mode = SceneMode.SCENE3D; + + camera.position = Cartesian3.clone(Cartesian3.UNIT_X); + Cartesian3.multiplyByScalar(camera.position, Ellipsoid.WGS84.maximumRadius + 100.0, camera.position); + camera.direction = new Cartesian3(-1.0, 0.0, 1.0); + Cartesian3.normalize(camera.direction, camera.direction); + camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); + + var roll = camera.roll; + var newRoll = CesiumMath.PI_OVER_TWO; + camera.roll = newRoll; + + expect(camera.roll).not.toEqual(roll); + expect(camera.roll).toEqualEpsilon(newRoll, CesiumMath.EPSILON14); + }); + it('update throws without mode', function() { expect(function() { camera.update(); From bcbac18519c904c8f39ebf7980036c467c57282c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 15 Oct 2014 14:00:04 -0400 Subject: [PATCH 04/30] Check direction alignment with local z. --- Source/Scene/Camera.js | 17 ++++++++++------- Specs/Scene/CameraSpec.js | 13 +++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 2da54151715c..4f42a8eb6e79 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -554,8 +554,8 @@ define([ } function getRollCV(camera) { - if (CesiumMath.equalsEpsilon(Math.abs(camera.up.z), 1.0, CesiumMath.EPSILON6)) { - return 0.0; + if (CesiumMath.equalsEpsilon(Math.abs(camera.direction.z), 1.0, CesiumMath.EPSILON6)) { + return undefined; } var right = camera.right; @@ -568,9 +568,9 @@ define([ var transform = Matrix4.getRotation(toFixedFrame, scratchHeadingMatrix3); Matrix3.transpose(transform, transform); - var up = Matrix3.multiplyByVector(transform, camera.up, scratchHeadingCartesian3); - if (CesiumMath.equalsEpsilon(Math.abs(up.z), 1.0, CesiumMath.EPSILON6)) { - return 0.0; + var direction = Matrix3.multiplyByVector(transform, camera.direction, scratchHeadingCartesian3); + if (CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)) { + return undefined; } var right = Matrix3.multiplyByVector(transform, camera.right, scratchHeadingCartesian3); @@ -790,8 +790,11 @@ define([ //>>includeEnd('debug'); if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - angle = angle - this.roll; - this.look(this.direction, angle); + var roll = this.roll; + if (defined(roll)) { + angle = angle - roll; + this.look(this.direction, angle); + } } } } diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index 858fde704558..55c97ca662e5 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -258,6 +258,12 @@ defineSuite([ it('get roll in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; + camera.position = new Cartesian3(100.0, 0.0, 100.0); + camera.direction = new Cartesian3(0.0, 1.0, -1.0); + Cartesian3.normalize(camera.direction, camera.direction); + camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); + var roll = Math.atan2(right.z, right.x); expect(camera.roll).toEqual(roll); }); @@ -266,6 +272,13 @@ defineSuite([ camera._mode = SceneMode.SCENE3D; var ellipsoid = Ellipsoid.WGS84; + camera.position = Cartesian3.clone(Cartesian3.UNIT_X); + Cartesian3.multiplyByScalar(camera.position, ellipsoid.maximumRadius + 100.0, camera.position); + camera.direction = new Cartesian3(-1.0, 0.0, 1.0); + Cartesian3.normalize(camera.direction, camera.direction); + camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); + var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid); var transform = Matrix4.getRotation(toFixedFrame, new Matrix3()); Matrix3.transpose(transform, transform); From 1db236f21c15ea8d5cbc4418083d8e014d53fd82 Mon Sep 17 00:00:00 2001 From: Ed Mackey Date: Tue, 21 Oct 2014 15:44:31 -0400 Subject: [PATCH 05/30] Added some hacking from a session with @bagnell. --- Source/Scene/Camera.js | 4 ++-- Specs/Scene/CameraSpec.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 4f42a8eb6e79..0016656dcde8 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -559,7 +559,7 @@ define([ } var right = camera.right; - return Math.atan2(right.z, right.x); + return CesiumMath.PI_OVER_TWO - Math.acos(right.z); } function getRoll3D(camera) { @@ -574,7 +574,7 @@ define([ } var right = Matrix3.multiplyByVector(transform, camera.right, scratchHeadingCartesian3); - return Math.atan2(right.z, right.x); + return CesiumMath.PI_OVER_TWO - Math.acos(right.z); } defineProperties(Camera.prototype, { diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index 55c97ca662e5..ce6621d00da8 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -262,6 +262,7 @@ defineSuite([ camera.direction = new Cartesian3(0.0, 1.0, -1.0); Cartesian3.normalize(camera.direction, camera.direction); camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + Cartesian3.normalize(camera.right, camera.right); camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); var roll = Math.atan2(right.z, right.x); @@ -277,6 +278,7 @@ defineSuite([ camera.direction = new Cartesian3(-1.0, 0.0, 1.0); Cartesian3.normalize(camera.direction, camera.direction); camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + Cartesian3.normalize(camera.right, camera.right); camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid); @@ -302,6 +304,7 @@ defineSuite([ camera.direction = new Cartesian3(0.0, 1.0, -1.0); Cartesian3.normalize(camera.direction, camera.direction); camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + Cartesian3.normalize(camera.right, camera.right); camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); var roll = camera.roll; @@ -320,6 +323,7 @@ defineSuite([ camera.direction = new Cartesian3(-1.0, 0.0, 1.0); Cartesian3.normalize(camera.direction, camera.direction); camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); + Cartesian3.normalize(camera.right, camera.right); camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); var roll = camera.roll; From a73b7acc29cf8ce0b296400e7370f68e3076e73a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 15:34:00 -0500 Subject: [PATCH 06/30] Update camera roll. --- Source/Scene/Camera.js | 81 ++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 0016656dcde8..6599cc523801 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -7,6 +7,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', + '../Core/deprecationWarning', '../Core/DeveloperError', '../Core/EasingFunction', '../Core/Ellipsoid', @@ -29,6 +30,7 @@ define([ defaultValue, defined, defineProperties, + deprecationWarning, DeveloperError, EasingFunction, Ellipsoid, @@ -507,7 +509,8 @@ define([ } function getHeading2D(camera) { - return Math.atan2(camera.right.y, camera.right.x); + var right = camera.right; + return Math.atan2(right.y, right.x); } var scratchHeadingMatrix4 = new Matrix4(); @@ -539,42 +542,37 @@ define([ camera.look(axis, angle); } - function getTiltCV(camera) { + function getPitchCV(camera) { // CesiumMath.acosClamped(dot(camera.direction, Cartesian3.negate(Cartesian3.UNIT_Z)) return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(-camera.direction.z); } - var scratchTiltCartesian3 = new Cartesian3(); + var scratchPitchCartesian3 = new Cartesian3(); - function getTilt3D(camera) { - var direction = Cartesian3.normalize(camera.position, scratchTiltCartesian3); + function getPitch3D(camera) { + var direction = Cartesian3.normalize(camera.position, scratchPitchCartesian3); Cartesian3.negate(direction, direction); return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(Cartesian3.dot(camera.direction, direction)); } function getRollCV(camera) { - if (CesiumMath.equalsEpsilon(Math.abs(camera.direction.z), 1.0, CesiumMath.EPSILON6)) { - return undefined; - } - var right = camera.right; - return CesiumMath.PI_OVER_TWO - Math.acos(right.z); + return Math.atan2(right.z, right.x); } + var scratchRollMatrix4 = new Matrix4(); + var scratchRollMatrix3 = new Matrix3(); + var scratchRollCartesian3 = new Cartesian3(); + function getRoll3D(camera) { var ellipsoid = camera._projection.ellipsoid; - var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid, scratchHeadingMatrix4); - var transform = Matrix4.getRotation(toFixedFrame, scratchHeadingMatrix3); + var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid, scratchRollMatrix4); + var transform = Matrix4.getRotation(toFixedFrame, scratchRollMatrix3); Matrix3.transpose(transform, transform); - var direction = Matrix3.multiplyByVector(transform, camera.direction, scratchHeadingCartesian3); - if (CesiumMath.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath.EPSILON3)) { - return undefined; - } - - var right = Matrix3.multiplyByVector(transform, camera.right, scratchHeadingCartesian3); - return CesiumMath.PI_OVER_TWO - Math.acos(right.z); + var right = Matrix3.multiplyByVector(transform, camera.right, scratchRollCartesian3); + return Math.atan2(right.z, right.x); } defineProperties(Camera.prototype, { @@ -716,7 +714,6 @@ define([ }, //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 set : function (angle) { - //>>includeStart('debug', pragmas.debug); if (!defined(angle)) { throw new DeveloperError('angle is required.'); @@ -732,24 +729,23 @@ define([ }, /** - * Gets or sets the camera tilt in radians. + * Gets or sets the camera pitch in radians. * @memberof Camera.prototype * * @type {Number} */ - tilt : { + pitch : { get : function() { if (this._mode === SceneMode.COLUMBUS_VIEW) { - return getTiltCV(this); + return getPitchCV(this); } else if (this._mode === SceneMode.SCENE3D) { - return getTilt3D(this); + return getPitch3D(this); } return undefined; }, //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 set : function(angle) { - //>>includeStart('debug', pragmas.debug); if (!defined(angle)) { throw new DeveloperError('angle is required.'); @@ -758,12 +754,31 @@ define([ if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { angle = CesiumMath.clamp(angle, -CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO); - angle = angle - this.tilt; + angle = angle - this.pitch; this.look(this.right, angle); } } }, + /** + * Gets or sets the camera tilt in radians. + * @memberof Camera.prototype + * + * @type {Number} + * + * @deprecated + */ + tilt : { + get : function() { + deprecationWarning('Camera.tilt', 'Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.8. Use Camera.pitch.'); + return this.pitch; + }, + set : function(angle) { + deprecationWarning('Camera.tilt', 'Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.8. Use Camera.pitch.'); + this.pitch = angle; + } + }, + /** * Gets or sets the camera roll in radians. * @memberof Camera.prototype @@ -782,20 +797,18 @@ define([ }, //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 set : function(angle) { - //>>includeStart('debug', pragmas.debug); if (!defined(angle)) { throw new DeveloperError('angle is required.'); } //>>includeEnd('debug'); - if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - var roll = this.roll; - if (defined(roll)) { - angle = angle - roll; - this.look(this.direction, angle); - } - } + var rollAngle; + + do { + rollAngle = CesiumMath.zeroToTwoPi(angle) - this.roll; + this.look(this.direction, rollAngle); + } while (!CesiumMath.equalsEpsilon(rollAngle, 0.0, CesiumMath.EPSILON4)); } } }); From 080dc31edc0d579dde2b4e59b9b1a0bf3740ee3b Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 15:42:20 -0500 Subject: [PATCH 07/30] Fix for negative angles. --- Source/Scene/Camera.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 6599cc523801..2b9bde84f7d5 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -806,7 +806,7 @@ define([ var rollAngle; do { - rollAngle = CesiumMath.zeroToTwoPi(angle) - this.roll; + rollAngle = CesiumMath.zeroToTwoPi(angle) - CesiumMath.zeroToTwoPi(this.roll); this.look(this.direction, rollAngle); } while (!CesiumMath.equalsEpsilon(rollAngle, 0.0, CesiumMath.EPSILON4)); } From 148d0625a06b950ead347e7c130a073483f55820 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 16:10:49 -0500 Subject: [PATCH 08/30] Revert computing roll angle. --- Source/Scene/Camera.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 2b9bde84f7d5..ea0041ae9c03 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -558,7 +558,7 @@ define([ function getRollCV(camera) { var right = camera.right; - return Math.atan2(right.z, right.x); + return CesiumMath.PI_OVER_TWO - Math.acos(right.z); } var scratchRollMatrix4 = new Matrix4(); @@ -572,7 +572,7 @@ define([ Matrix3.transpose(transform, transform); var right = Matrix3.multiplyByVector(transform, camera.right, scratchRollCartesian3); - return Math.atan2(right.z, right.x); + return CesiumMath.PI_OVER_TWO - Math.acos(right.z); } defineProperties(Camera.prototype, { From e6d3b77e4112a360042a13599f47aebb9a0096ad Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 17:33:07 -0500 Subject: [PATCH 09/30] Add Quaternion.fromHeadingPitchRoll and Transforms.headingPitchRollToFixedFrame. --- Source/Core/Quaternion.js | 32 ++++++++++++++++++++++++++++++++ Source/Core/Transforms.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/Source/Core/Quaternion.js b/Source/Core/Quaternion.js index f189bc96f8fd..1e79d2d96f0c 100644 --- a/Source/Core/Quaternion.js +++ b/Source/Core/Quaternion.js @@ -175,6 +175,38 @@ define([ return result; }; + var scratchHPRQuaternion = new Quaternion(); + + /** + * Computes a rotation from the given heading, pitch and roll angles. + * + * @param {Number} heading The heading angle in radians. + * @param {Number} pitch The pitch angle in radians. + * @param {Number} roll The roll angle in radians. + * @param {Quaternion} result The object onto which to store the result. + * @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided. + */ + Quaternion.fromHeadingPitchRoll = function(heading, pitch, roll, result) { + //>>includeStart('debug', pragmas.debug); + if (!defined(heading)) { + throw new DeveloperError('heading is required.'); + } + if (!defined(pitch)) { + throw new DeveloperError('pitch is required.'); + } + if (!defined(roll)) { + throw new DeveloperError('roll is required.'); + } + //>>includeEnd('debug'); + + var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, heading, result); + var tiltQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, scratchHPRQuaternion); + result = Quaternion.multiply(headingQuaternion, tiltQuaternion, headingQuaternion); + + var rollQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, roll, scratchHPRQuaternion); + return Quaternion.multiply(rollQuaternion, result, result); + }; + var sampledQuaternionAxis = new Cartesian3(); var sampledQuaternionRotation = new Cartesian3(); var sampledQuaternionTempQuaternion = new Quaternion(); diff --git a/Source/Core/Transforms.js b/Source/Core/Transforms.js index 6a0f52f1e6e9..9fedb4596126 100644 --- a/Source/Core/Transforms.js +++ b/Source/Core/Transforms.js @@ -16,6 +16,7 @@ define([ './Math', './Matrix3', './Matrix4', + './Quaternion', './TimeConstants' ], function( when, @@ -34,6 +35,7 @@ define([ CesiumMath, Matrix3, Matrix4, + Quaternion, TimeConstants) { "use strict"; @@ -344,6 +346,38 @@ define([ return result; }; + var scratchHPRQuaternion = new Quaternion(); + var scratchScale = new Cartesian3(1.0, 1.0, 1.0); + var scratchHPRMatrix4 = new Matrix4(); + + /** + * Computes a 4x4 transformation matrix from a reference frame with axes computed from the heading-pitch-roll angles + * centered at the provided origin to the provided ellipsoid's fixed reference frame. + * + * @param {Cartesian3} origin The center point of the local reference frame. + * @param {Number} heading The heading angle in radians. + * @param {Number} pitch The pitch angle in radians. + * @param {Number} roll The roll angle in radians. + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation. + * @param {Matrix4} [result] The object onto which to store the result. + * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided. + * + * @example + * // Get the transform from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame. + * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0); + * var heading = -Cesium.Math.PI_OVER_TWO; + * var pitch = Cesium.Math.PI_OVER_FOUR; + * var roll = 0.0; + * var transform = Cesium.Transforms.headingPitchRollToFixedFrame(center, heading, pitch, roll); + */ + Transforms.headingPitchRollToFixedFrame = function(origin, heading, pitch, roll, ellipsoid, result) { + // checks for required parameters happen in the called functions + var hprQuaternion = Quaternion.fromHeadingPitchRoll(heading, pitch, roll, scratchHPRQuaternion); + var hprMatrix = Matrix4.fromTranslationQuaternionRotationScale(Cartesian3.ZERO, hprQuaternion, scratchScale, scratchHPRMatrix4); + result = Transforms.eastNorthUpToFixedFrame(origin, ellipsoid, result); + return Matrix4.multiply(result, hprMatrix, result); + }; + var gmstConstant0 = 6 * 3600 + 41 * 60 + 50.54841; var gmstConstant1 = 8640184.812866; From b7474c1dd8b0e3a1b75181881dceae2d7b193834 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 20:10:56 -0500 Subject: [PATCH 10/30] Add tests for Quaternion.fromHeadingPitchRoll. --- Source/Core/Quaternion.js | 4 +-- Specs/Core/QuaternionSpec.js | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/Source/Core/Quaternion.js b/Source/Core/Quaternion.js index 1e79d2d96f0c..49d237f5ca19 100644 --- a/Source/Core/Quaternion.js +++ b/Source/Core/Quaternion.js @@ -200,8 +200,8 @@ define([ //>>includeEnd('debug'); var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, heading, result); - var tiltQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, scratchHPRQuaternion); - result = Quaternion.multiply(headingQuaternion, tiltQuaternion, headingQuaternion); + var pitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, scratchHPRQuaternion); + result = Quaternion.multiply(headingQuaternion, pitchQuaternion, headingQuaternion); var rollQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, roll, scratchHPRQuaternion); return Quaternion.multiply(rollQuaternion, result, result); diff --git a/Specs/Core/QuaternionSpec.js b/Specs/Core/QuaternionSpec.js index 17f91141e1ad..921a5693cca8 100644 --- a/Specs/Core/QuaternionSpec.js +++ b/Specs/Core/QuaternionSpec.js @@ -104,6 +104,42 @@ defineSuite([ expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(matrix, CesiumMath.EPSILON12); }); + it('fromHeadingPitchRoll with just heading', function() { + var angle = CesiumMath.toRadians(20.0); + var quaternion = Quaternion.fromHeadingPitchRoll(angle, 0.0, 0.0); + expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationZ(angle), CesiumMath.EPSILON11); + }); + + it('fromHeadingPitchRoll with just pitch', function() { + var angle = CesiumMath.toRadians(20.0); + var quaternion = Quaternion.fromHeadingPitchRoll(0.0, angle, 0.0); + expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationY(angle), CesiumMath.EPSILON11); + }); + + it('fromHeadingPitchRoll with just roll', function() { + var angle = CesiumMath.toRadians(20.0); + var quaternion = Quaternion.fromHeadingPitchRoll(0.0, 0.0, angle); + expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationX(angle), CesiumMath.EPSILON11); + }); + + it('fromHeadingPitchRoll with all angles', function() { + var angle = CesiumMath.toRadians(20.0); + var quaternion = Quaternion.fromHeadingPitchRoll(angle, angle, angle); + var expected = Matrix3.fromRotationY(angle); + Matrix3.multiply(Matrix3.fromRotationZ(angle), expected, expected); + Matrix3.multiply(Matrix3.fromRotationX(angle), expected, expected); + expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(expected, CesiumMath.EPSILON11); + }); + + it('fromHeadingPitchRoll works with result parameter', function() { + var angle = CesiumMath.toRadians(20.0); + var result = new Quaternion(); + var quaternion = Quaternion.fromHeadingPitchRoll(0.0, 0.0, angle, result); + var expected = Quaternion.fromRotationMatrix(Matrix3.fromRotationX(angle)); + expect(quaternion).toBe(result); + expect(quaternion).toEqualEpsilon(expected, CesiumMath.EPSILON11); + }); + it('clone without a result parameter', function() { var quaternion = new Quaternion(1.0, 2.0, 3.0, 4.0); var result = quaternion.clone(); @@ -608,6 +644,24 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('fromHeadingPitchRoll throws with undefined heading', function() { + expect(function() { + Quaternion.fromHeadingPitchRoll(undefined, 0.0, 0.0); + }).toThrowDeveloperError(); + }); + + it('fromHeadingPitchRoll throws with undefined pitch', function() { + expect(function() { + Quaternion.fromHeadingPitchRoll(0.0, undefined, 0.0); + }).toThrowDeveloperError(); + }); + + it('fromHeadingPitchRoll throws with undefined roll', function() { + expect(function() { + Quaternion.fromHeadingPitchRoll(0.0, 0.0, undefined); + }).toThrowDeveloperError(); + }); + it('clone returns undefined with no parameter', function() { expect(Quaternion.clone()).toBeUndefined(); }); From 5f3b256eb65f0161a800935f64634d55bd63f433 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 20:35:11 -0500 Subject: [PATCH 11/30] Add tests for Transforms.headingPitchRollToFixedFrame. --- Specs/Core/TransformsSpec.js | 80 ++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Specs/Core/TransformsSpec.js b/Specs/Core/TransformsSpec.js index 56bf147ade2d..e82c6170d102 100644 --- a/Specs/Core/TransformsSpec.js +++ b/Specs/Core/TransformsSpec.js @@ -186,6 +186,62 @@ defineSuite([ expect(Matrix4.getColumn(returnedResult, 3, new Cartesian4())).toEqual(expectedTranslation); // translation }); + it('headingPitchRollToFixedFrame works without a result parameter', function() { + var origin = new Cartesian3(1.0, 0.0, 0.0); + var heading = CesiumMath.toRadians(20.0); + var pitch = CesiumMath.toRadians(30.0); + var roll = CesiumMath.toRadians(40.0); + + var expectedRotation = Matrix3.fromQuaternion(Quaternion.fromHeadingPitchRoll(heading, pitch, roll)); + var expectedX = Matrix3.getColumn(expectedRotation, 0, new Cartesian3()); + var expectedY = Matrix3.getColumn(expectedRotation, 1, new Cartesian3()); + var expectedZ = Matrix3.getColumn(expectedRotation, 2, new Cartesian3()); + + Cartesian3.fromElements(expectedX.z, expectedX.x, expectedX.y, expectedX); + Cartesian3.fromElements(expectedY.z, expectedY.x, expectedY.y, expectedY); + Cartesian3.fromElements(expectedZ.z, expectedZ.x, expectedZ.y, expectedZ); + + var returnedResult = Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll, Ellipsoid.UNIT_SPHERE); + var actualX = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 0, new Cartesian4())); + var actualY = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 1, new Cartesian4())); + var actualZ = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 2, new Cartesian4())); + var actualTranslation = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 3, new Cartesian4())); + + expect(actualX).toEqual(expectedX); + expect(actualY).toEqual(expectedY); + expect(actualZ).toEqual(expectedZ); + expect(actualTranslation).toEqual(origin); + }); + + it('headingPitchRollToFixedFrame works with a result parameter', function() { + var origin = new Cartesian3(1.0, 0.0, 0.0); + var heading = CesiumMath.toRadians(20.0); + var pitch = CesiumMath.toRadians(30.0); + var roll = CesiumMath.toRadians(40.0); + + var expectedRotation = Matrix3.fromQuaternion(Quaternion.fromHeadingPitchRoll(heading, pitch, roll)); + var expectedX = Matrix3.getColumn(expectedRotation, 0, new Cartesian3()); + var expectedY = Matrix3.getColumn(expectedRotation, 1, new Cartesian3()); + var expectedZ = Matrix3.getColumn(expectedRotation, 2, new Cartesian3()); + + Cartesian3.fromElements(expectedX.z, expectedX.x, expectedX.y, expectedX); + Cartesian3.fromElements(expectedY.z, expectedY.x, expectedY.y, expectedY); + Cartesian3.fromElements(expectedZ.z, expectedZ.x, expectedZ.y, expectedZ); + + var result = new Matrix4(); + var returnedResult = Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll, Ellipsoid.UNIT_SPHERE, result); + var actualX = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 0, new Cartesian4())); + var actualY = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 1, new Cartesian4())); + var actualZ = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 2, new Cartesian4())); + var actualTranslation = Cartesian3.fromCartesian4(Matrix4.getColumn(returnedResult, 3, new Cartesian4())); + + expect(returnedResult).toBe(result); + expect(actualX).toEqual(expectedX); + expect(actualY).toEqual(expectedY); + expect(actualZ).toEqual(expectedZ); + expect(actualTranslation).toEqual(origin); + }); + it('computeTemeToPseudoFixedMatrix works before noon', function() { var time = JulianDate.now(); var secondsDiff = TimeConstants.SECONDS_PER_DAY - time.secondsOfDay; @@ -683,6 +739,30 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('headingPitchRollToFixedFrame throws without an origin', function() { + expect(function() { + Transforms.headingPitchRollToFixedFrame(undefined, 0.0, 0.0, 0.0); + }).toThrowDeveloperError(); + }); + + it('headingPitchRollToFixedFrame throws without an heading', function() { + expect(function() { + Transforms.headingPitchRollToFixedFrame(Cartesian3.ZERO, undefined, 0.0, 0.0); + }).toThrowDeveloperError(); + }); + + it('headingPitchRollToFixedFrame throws without an pitch', function() { + expect(function() { + Transforms.headingPitchRollToFixedFrame(Cartesian3.ZERO, 0.0, undefined, 0.0); + }).toThrowDeveloperError(); + }); + + it('headingPitchRollToFixedFrame throws without an roll', function() { + expect(function() { + Transforms.headingPitchRollToFixedFrame(Cartesian3.ZERO, 0.0, 0.0, undefined); + }).toThrowDeveloperError(); + }); + it('computeTemeToPseudoFixedMatrix throws without a date', function() { expect(function() { Transforms.computeTemeToPseudoFixedMatrix(undefined); From c2e6f80fb10f831b7708a16a73970e3173bc04ad Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 20:38:26 -0500 Subject: [PATCH 12/30] Update CHANGES.md. --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index d805bdb8690a..7782fd348967 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ Change Log * Deprecated * * Added `PolylineVolumeGraphics` and `Entity.polylineVolume` +* Added `Quaternion.fromHeadingPitchRoll` to create a rotation from heading, pitch, and roll angles. +* Added `Transforms.headingPitchRollToFixedFrame` to create a local from from a position and heading/pitch/roll angles. ### 1.5 - 2015-01-05 From 9e855388d119dbdc0b9c5036fc9be8dd48fc7d50 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 6 Jan 2015 20:41:44 -0500 Subject: [PATCH 13/30] Fix typo. --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 7782fd348967..2c00777449bc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,7 +11,7 @@ Change Log * * Added `PolylineVolumeGraphics` and `Entity.polylineVolume` * Added `Quaternion.fromHeadingPitchRoll` to create a rotation from heading, pitch, and roll angles. -* Added `Transforms.headingPitchRollToFixedFrame` to create a local from from a position and heading/pitch/roll angles. +* Added `Transforms.headingPitchRollToFixedFrame` to create a local frame from a position and heading/pitch/roll angles. ### 1.5 - 2015-01-05 From 21aaa4c14889dd81fc38fc51d9555e92b6ed8572 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Jan 2015 19:07:26 -0500 Subject: [PATCH 14/30] Deprecated camera tilt and heading setters. Deprecated tilt getter and replaced it with pitch. Added Camera.setView to set the camera position, heading, pitch, and roll. --- CHANGES.md | 3 +- Source/Scene/Camera.js | 236 ++++++++++++++++++++--------------------- 2 files changed, 119 insertions(+), 120 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4c1582c673d0..c0456b1c504a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,8 @@ Change Log * `Rectangle.isEmpty` was deprecated in Cesium 1.5. * The `sourceUri` parameter to `GeoJsonDatasource.load` was deprecated in Cesium 1.4 and has been removed. Use options.sourceUri instead. * Deprecated - * + * Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.pitch. + * Camera.heading and Camera.tilt were deprecated in Cesium 1.6. They will become read-only in Cesium 1.7. Use Camera.setView. * Improved performance of asynchronous geometry creation (as much as 20% faster in some use cases). [#2342](https://github.com/AnalyticalGraphicsInc/cesium/issues/2342) * Added `PolylineVolumeGraphics` and `Entity.polylineVolume` * Added `Camera.roll`. diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index ea0041ae9c03..209774301c43 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -505,74 +505,47 @@ define([ if (positionChanged || directionChanged || upChanged || rightChanged || transformChanged) { updateViewMatrix(camera); - } - } - - function getHeading2D(camera) { - var right = camera.right; - return Math.atan2(right.y, right.x); - } - - var scratchHeadingMatrix4 = new Matrix4(); - var scratchHeadingMatrix3 = new Matrix3(); - var scratchHeadingCartesian3 = new Cartesian3(); - - function getHeading3D(camera) { - var ellipsoid = camera._projection.ellipsoid; - var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid, scratchHeadingMatrix4); - var transform = Matrix4.getRotation(toFixedFrame, scratchHeadingMatrix3); - Matrix3.transpose(transform, transform); - - var right = Matrix3.multiplyByVector(transform, camera.right, scratchHeadingCartesian3); - return Math.atan2(right.y, right.x); - } - - function setHeading2D(camera, angle) { - var rightAngle = getHeading2D(camera); - angle = rightAngle - angle; - camera.look(Cartesian3.UNIT_Z, angle); - } - var scratchHeadingAxis = new Cartesian3(); - - function setHeading3D(camera, angle) { - var axis = Cartesian3.normalize(camera.position, scratchHeadingAxis); - var upAngle = getHeading3D(camera); - angle = upAngle - angle; - camera.look(axis, angle); - } - - function getPitchCV(camera) { - // CesiumMath.acosClamped(dot(camera.direction, Cartesian3.negate(Cartesian3.UNIT_Z)) - return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(-camera.direction.z); - } - - var scratchPitchCartesian3 = new Cartesian3(); - - function getPitch3D(camera) { - var direction = Cartesian3.normalize(camera.position, scratchPitchCartesian3); - Cartesian3.negate(direction, direction); - - return CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(Cartesian3.dot(camera.direction, direction)); - } - - function getRollCV(camera) { - var right = camera.right; - return CesiumMath.PI_OVER_TWO - Math.acos(right.z); - } - - var scratchRollMatrix4 = new Matrix4(); - var scratchRollMatrix3 = new Matrix3(); - var scratchRollCartesian3 = new Cartesian3(); - - function getRoll3D(camera) { - var ellipsoid = camera._projection.ellipsoid; - var toFixedFrame = Transforms.eastNorthUpToFixedFrame(camera.position, ellipsoid, scratchRollMatrix4); - var transform = Matrix4.getRotation(toFixedFrame, scratchRollMatrix3); - Matrix3.transpose(transform, transform); - - var right = Matrix3.multiplyByVector(transform, camera.right, scratchRollCartesian3); - return CesiumMath.PI_OVER_TWO - Math.acos(right.z); + var viewMatrix = camera._viewMatrix; + /* + viewMatrix[0] = r.x; + viewMatrix[1] = u.x; + viewMatrix[2] = -d.x; + viewMatrix[3] = 0.0; + viewMatrix[4] = r.y; + viewMatrix[5] = u.y; + viewMatrix[6] = -d.y; + viewMatrix[7] = 0.0; + viewMatrix[8] = r.z; + viewMatrix[9] = u.z; + viewMatrix[10] = -d.z; + viewMatrix[11] = 0.0; + viewMatrix[12] = -Cartesian3.dot(r, e); + viewMatrix[13] = -Cartesian3.dot(u, e); + viewMatrix[14] = Cartesian3.dot(d, e); + viewMatrix[15] = 1.0; + */ + + /* + var roll; + var pitch; + var heading = Math.asin(-viewMatrix[4]); + if (heading < CesiumMath.PI_OVER_TWO) { + if (heading > -CesiumMath.PI_OVER_TWO) { + roll = Math.atan2(viewMatrix[6], viewMatrix[5]); + pitch = Math.atan2(viewMatrix[8], viewMatrix[0]); + } else { + // not a unique solution (roll + pitch constant) + roll = Math.atan2(-viewMatrix[2], viewMatrix[10]); + pitch = 0.0; + } + } else { + // not a unique solution (roll - pitch constant) + roll = Math.atan2(viewMatrix[2], viewMatrix[10]); + pitch = 0.0; + } + */ + } } defineProperties(Camera.prototype, { @@ -697,66 +670,48 @@ define([ }, /** - * Gets or sets the camera heading in radians. + * Gets the camera heading in radians. * @memberof Camera.prototype * * @type {Number} */ heading : { get : function () { - if (this._mode === SceneMode.SCENE2D || this._mode === SceneMode.COLUMBUS_VIEW) { - return getHeading2D(this); - } else if (this._mode === SceneMode.SCENE3D) { - return getHeading3D(this); + if (this._mode !== SceneMode.MORPHING) { + return this._heading; } return undefined; }, - //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 set : function (angle) { + deprecationWarning('Camera.heading', 'Camera.heading was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.setView.'); + + //>>includeStart('debug', pragmas.debug); if (!defined(angle)) { throw new DeveloperError('angle is required.'); } //>>includeEnd('debug'); - if (this._mode === SceneMode.SCENE2D || this._mode === SceneMode.COLUMBUS_VIEW) { - setHeading2D(this, angle); - } else if (this._mode === SceneMode.SCENE3D) { - setHeading3D(this, angle); + if (this._mode !== SceneMode.MORPHING) { + this._heading = angle; } } }, /** - * Gets or sets the camera pitch in radians. + * Gets the camera pitch in radians. * @memberof Camera.prototype * * @type {Number} */ pitch : { get : function() { - if (this._mode === SceneMode.COLUMBUS_VIEW) { - return getPitchCV(this); - } else if (this._mode === SceneMode.SCENE3D) { - return getPitch3D(this); + if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + return this._pitch; } return undefined; - }, - //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 - set : function(angle) { - //>>includeStart('debug', pragmas.debug); - if (!defined(angle)) { - throw new DeveloperError('angle is required.'); - } - //>>includeEnd('debug'); - - if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - angle = CesiumMath.clamp(angle, -CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO); - angle = angle - this.pitch; - this.look(this.right, angle); - } } }, @@ -770,45 +725,37 @@ define([ */ tilt : { get : function() { - deprecationWarning('Camera.tilt', 'Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.8. Use Camera.pitch.'); + deprecationWarning('Camera.tilt', 'Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.pitch.'); return this.pitch; }, set : function(angle) { - deprecationWarning('Camera.tilt', 'Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.8. Use Camera.pitch.'); - this.pitch = angle; + deprecationWarning('Camera.tilt', 'Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.setView.'); + + //>>includeStart('debug', pragmas.debug); + if (!defined(angle)) { + throw new DeveloperError('angle is required.'); + } + //>>includeEnd('debug'); + + if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + this._pitch = angle; + } } }, /** - * Gets or sets the camera roll in radians. + * Gets the camera roll in radians. * @memberof Camera.prototype * * @type {Number} */ roll : { get : function() { - if (this._mode === SceneMode.COLUMBUS_VIEW) { - return getRollCV(this); - } else if (this._mode === SceneMode.SCENE3D) { - return getRoll3D(this); + if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { + return this._roll; } return undefined; - }, - //TODO See https://github.com/AnalyticalGraphicsInc/cesium/issues/832 - set : function(angle) { - //>>includeStart('debug', pragmas.debug); - if (!defined(angle)) { - throw new DeveloperError('angle is required.'); - } - //>>includeEnd('debug'); - - var rollAngle; - - do { - rollAngle = CesiumMath.zeroToTwoPi(angle) - CesiumMath.zeroToTwoPi(this.roll); - this.look(this.direction, rollAngle); - } while (!CesiumMath.equalsEpsilon(rollAngle, 0.0, CesiumMath.EPSILON4)); } } }); @@ -873,6 +820,57 @@ define([ Cartesian3.cross(this.direction, this.up, this.right); }; + var scratchSetViewCartesian = new Cartesian3(); + var scratchSetViewTransform1 = new Matrix4(); + var scratchSetViewTransform2 = new Matrix4(); + var scratchSetViewQuaternion = new Quaternion(); + var scratchSetViewMatrix3 = new Matrix3(); + + Camera.prototype.setView = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var heading = defaultValue(options.heading, 0.0); + var pitch = defaultValue(options.pitch, CesiumMath.PI_OVER_TWO); + var roll = defaultValue(options.roll, 0.0); + + var cartesian = options.cartesian; + var cartographic = options.cartographic; + + var ellipsoid = this._projection.ellipsoid; + + if (!defined(cartesian)) { + if (defined(cartographic)) { + cartesian = ellipsoid.cartographicToCartesian(cartographic, scratchSetViewCartesian); + } else { + cartesian = Cartesian3.clone(this.positionWC, scratchSetViewCartesian); + } + } + + var currentTransform = Matrix4.clone(this.transform, scratchSetViewTransform1); + var localTransform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, scratchSetViewTransform2); + this.setTransform(localTransform); + + Cartesian3.clone(Cartesian3.ZERO, this.position); + + var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, heading + CesiumMath.PI_OVER_TWO, new Quaternion()); + var pitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, new Quaternion()); + var rotQuat = Quaternion.multiply(headingQuaternion, pitchQuaternion, headingQuaternion); + + var rollQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, roll, new Quaternion()); + Quaternion.multiply(rollQuaternion, rotQuat, rotQuat); + var rotMat = Matrix3.fromQuaternion(rotQuat, scratchSetViewMatrix3); + + Matrix3.getColumn(rotMat, 0, this.direction); + Matrix3.getColumn(rotMat, 2, this.up); + Cartesian3.cross(this.direction, this.up, this.right); + + this.setTransform(currentTransform); + + this._heading = heading; + this._pitch = pitch; + this._roll = roll; + }; + /** * Transform a vector or point from world coordinates to the camera's reference frame. * From c17b48cf62ef190e9c64dea333f0f4e8b5cc29f3 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Jan 2015 19:24:34 -0500 Subject: [PATCH 15/30] Add 2D support to setView. --- Source/Scene/Camera.js | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 209774301c43..a96310a6d5a1 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -825,18 +825,26 @@ define([ var scratchSetViewTransform2 = new Matrix4(); var scratchSetViewQuaternion = new Quaternion(); var scratchSetViewMatrix3 = new Matrix3(); + var scratchSetViewCartographic = new Cartographic(); Camera.prototype.setView = function(options) { + if (this._mode === SceneMode.MORPHING) { + return; + } + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var scene2D = this._mode === SceneMode.SCENE2D; + var heading = defaultValue(options.heading, 0.0); - var pitch = defaultValue(options.pitch, CesiumMath.PI_OVER_TWO); - var roll = defaultValue(options.roll, 0.0); + var pitch = scene2D || !defined(options.pitch) ? CesiumMath.PI_OVER_TWO : options.pitch; + var roll = scene2D || !defined(options.pitch) ? 0.0 : options.roll; var cartesian = options.cartesian; var cartographic = options.cartographic; - var ellipsoid = this._projection.ellipsoid; + var projection = this._projection; + var ellipsoid = projection.ellipsoid; if (!defined(cartesian)) { if (defined(cartographic)) { @@ -850,7 +858,24 @@ define([ var localTransform = Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, scratchSetViewTransform2); this.setTransform(localTransform); - Cartesian3.clone(Cartesian3.ZERO, this.position); + if (scene2D) { + Cartesian2.clone(Cartesian3.ZERO, this.position); + + var cartographic2D = ellipsoid.cartesianToCartographic(cartesian, scratchSetViewCartographic); + var newLeft = -cartographic2D.height * 0.5; + var newRight = -newLeft; + + var frustum = this.frustum; + if (newRight > newLeft) { + var ratio = frustum.top / frustum.right; + frustum.right = newRight; + frustum.left = newLeft; + frustum.top = frustum.right * ratio; + frustum.bottom = -frustum.top; + } + } else { + Cartesian3.clone(Cartesian3.ZERO, this.position); + } var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, heading + CesiumMath.PI_OVER_TWO, new Quaternion()); var pitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, new Quaternion()); From eaf09d6658ea614a304ea9e5a6c750a4a7f2ce0a Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Jan 2015 19:28:58 -0500 Subject: [PATCH 16/30] Deprecated Camera.setPositionCartographic. Use Camera.setView. --- CHANGES.md | 5 ++-- Source/Scene/Camera.js | 53 ++++++------------------------------------ 2 files changed, 10 insertions(+), 48 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c0456b1c504a..b671019b53c5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,8 +8,9 @@ Change Log * `Rectangle.isEmpty` was deprecated in Cesium 1.5. * The `sourceUri` parameter to `GeoJsonDatasource.load` was deprecated in Cesium 1.4 and has been removed. Use options.sourceUri instead. * Deprecated - * Camera.tilt was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.pitch. - * Camera.heading and Camera.tilt were deprecated in Cesium 1.6. They will become read-only in Cesium 1.7. Use Camera.setView. + * `Camera.tilt` was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use `Camera.pitch`. + * `Camera.heading` and `Camera.tilt` were deprecated in Cesium 1.6. They will become read-only in Cesium 1.7. Use `Camera.setView`. + * `Camera.setPositionCartographic` was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use `Camera.setView`.; * Improved performance of asynchronous geometry creation (as much as 20% faster in some use cases). [#2342](https://github.com/AnalyticalGraphicsInc/cesium/issues/2342) * Added `PolylineVolumeGraphics` and `Entity.polylineVolume` * Added `Camera.roll`. diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index a96310a6d5a1..5c27acad48a6 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -1464,64 +1464,25 @@ define([ } }; - function setPositionCartographic2D(camera, cartographic) { - var newLeft = -cartographic.height * 0.5; - var newRight = -newLeft; - - var frustum = camera.frustum; - if (newRight > newLeft) { - var ratio = frustum.top / frustum.right; - frustum.right = newRight; - frustum.left = newLeft; - frustum.top = frustum.right * ratio; - frustum.bottom = -frustum.top; - } - - //We use Cartesian2 instead of 3 here because Z must be constant in 2D mode. - Cartesian2.clone(camera._projection.project(cartographic), camera.position); - Cartesian3.negate(Cartesian3.UNIT_Z, camera.direction); - Cartesian3.clone(Cartesian3.UNIT_Y, camera.up); - Cartesian3.clone(Cartesian3.UNIT_X, camera.right); - } - - function setPositionCartographicCV(camera, cartographic) { - var projection = camera._projection; - camera.position = projection.project(cartographic); - Cartesian3.negate(Cartesian3.UNIT_Z, camera.direction); - Cartesian3.clone(Cartesian3.UNIT_Y, camera.up); - Cartesian3.clone(Cartesian3.UNIT_X, camera.right); - } - - function setPositionCartographic3D(camera, cartographic) { - var ellipsoid = camera._projection.ellipsoid; - - ellipsoid.cartographicToCartesian(cartographic, camera.position); - Cartesian3.negate(camera.position, camera.direction); - Cartesian3.normalize(camera.direction, camera.direction); - Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, camera.right); - Cartesian3.cross(camera.right, camera.direction, camera.up); - Cartesian3.cross(camera.direction, camera.up, camera.right); - } - /** * Moves the camera to the provided cartographic position. * + * @deprecated + * * @param {Cartographic} cartographic The new camera position. */ Camera.prototype.setPositionCartographic = function(cartographic) { + deprecationWarning('Camera.setPositionCartographic', 'Camera.setPositionCartographic was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.setView.'); + //>>includeStart('debug', pragmas.debug); if (!defined(cartographic)) { throw new DeveloperError('cartographic is required.'); } //>>includeEnd('debug'); - if (this._mode === SceneMode.SCENE2D) { - setPositionCartographic2D(this, cartographic); - } else if (this._mode === SceneMode.COLUMBUS_VIEW) { - setPositionCartographicCV(this, cartographic); - } else if (this._mode === SceneMode.SCENE3D) { - setPositionCartographic3D(this, cartographic); - } + this.setView({ + cartographic : cartographic + }); }; /** From 0ba6ea64601d5be528f3f0557edc483a3b43ff58 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Thu, 8 Jan 2015 19:40:17 -0500 Subject: [PATCH 17/30] Fix default roll. --- Source/Scene/Camera.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 5c27acad48a6..848c54143c09 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -838,7 +838,7 @@ define([ var heading = defaultValue(options.heading, 0.0); var pitch = scene2D || !defined(options.pitch) ? CesiumMath.PI_OVER_TWO : options.pitch; - var roll = scene2D || !defined(options.pitch) ? 0.0 : options.roll; + var roll = scene2D || !defined(options.roll) ? 0.0 : options.roll; var cartesian = options.cartesian; var cartographic = options.cartographic; From 4b7ea2ebe1caa355e2eeeba5175a3abbb9629a04 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Jan 2015 18:17:09 -0500 Subject: [PATCH 18/30] Fix heading-pitch-roll property getters. --- Source/Scene/Camera.js | 105 +++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 848c54143c09..f4ff5e3be805 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -505,46 +505,6 @@ define([ if (positionChanged || directionChanged || upChanged || rightChanged || transformChanged) { updateViewMatrix(camera); - - var viewMatrix = camera._viewMatrix; - /* - viewMatrix[0] = r.x; - viewMatrix[1] = u.x; - viewMatrix[2] = -d.x; - viewMatrix[3] = 0.0; - viewMatrix[4] = r.y; - viewMatrix[5] = u.y; - viewMatrix[6] = -d.y; - viewMatrix[7] = 0.0; - viewMatrix[8] = r.z; - viewMatrix[9] = u.z; - viewMatrix[10] = -d.z; - viewMatrix[11] = 0.0; - viewMatrix[12] = -Cartesian3.dot(r, e); - viewMatrix[13] = -Cartesian3.dot(u, e); - viewMatrix[14] = Cartesian3.dot(d, e); - viewMatrix[15] = 1.0; - */ - - /* - var roll; - var pitch; - var heading = Math.asin(-viewMatrix[4]); - if (heading < CesiumMath.PI_OVER_TWO) { - if (heading > -CesiumMath.PI_OVER_TWO) { - roll = Math.atan2(viewMatrix[6], viewMatrix[5]); - pitch = Math.atan2(viewMatrix[8], viewMatrix[0]); - } else { - // not a unique solution (roll + pitch constant) - roll = Math.atan2(-viewMatrix[2], viewMatrix[10]); - pitch = 0.0; - } - } else { - // not a unique solution (roll - pitch constant) - roll = Math.atan2(viewMatrix[2], viewMatrix[10]); - pitch = 0.0; - } - */ } } @@ -678,7 +638,27 @@ define([ heading : { get : function () { if (this._mode !== SceneMode.MORPHING) { - return this._heading; + var origin = this.positionWC; + var ellipsoid = this._projection.ellipsoid; + + var oldTransform = Matrix4.clone(this.transform); + var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid); + this.setTransform(transform); + + + var right = this.right; + var direction = this.direction; + + var heading; + if (Math.abs(direction.z) < Math.abs(right.z)) { + heading = Math.atan2(direction.y, direction.x) - CesiumMath.PI_OVER_TWO; + } else { + heading = Math.atan2(right.y, right.x); + } + + this.setTransform(oldTransform); + + return CesiumMath.zeroToTwoPi(heading); } return undefined; @@ -686,7 +666,6 @@ define([ set : function (angle) { deprecationWarning('Camera.heading', 'Camera.heading was deprecated in Cesium 1.6. It will be removed in Cesium 1.7. Use Camera.setView.'); - //>>includeStart('debug', pragmas.debug); if (!defined(angle)) { throw new DeveloperError('angle is required.'); @@ -694,7 +673,7 @@ define([ //>>includeEnd('debug'); if (this._mode !== SceneMode.MORPHING) { - this._heading = angle; + this.setView({ heading : angle }); } } }, @@ -708,7 +687,18 @@ define([ pitch : { get : function() { if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - return this._pitch; + var origin = this.positionWC; + var ellipsoid = this._projection.ellipsoid; + + var oldTransform = Matrix4.clone(this.transform); + var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid); + this.setTransform(transform); + + var pitch = CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(-this.direction.z); + + this.setTransform(oldTransform); + + return pitch; } return undefined; @@ -738,7 +728,7 @@ define([ //>>includeEnd('debug'); if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - this._pitch = angle; + this.setView({ pitch : angle }); } } }, @@ -752,7 +742,26 @@ define([ roll : { get : function() { if (this._mode === SceneMode.COLUMBUS_VIEW || this._mode === SceneMode.SCENE3D) { - return this._roll; + var origin = this.positionWC; + var ellipsoid = this._projection.ellipsoid; + + var heading = this.heading; + + var oldTransform = Matrix4.clone(this.transform); + var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid); + this.setTransform(transform); + + var up = this.up; + var right = this.right; + + var roll = Math.acos(-right.z) - CesiumMath.PI_OVER_TWO; + if (up.z < 0.0) { + roll = CesiumMath.PI - roll; + } + + this.setTransform(oldTransform); + + return CesiumMath.zeroToTwoPi(roll); } return undefined; @@ -890,10 +899,6 @@ define([ Cartesian3.cross(this.direction, this.up, this.right); this.setTransform(currentTransform); - - this._heading = heading; - this._pitch = pitch; - this._roll = roll; }; /** From 3dae3f0a3272ad7a366470a03c5ee8460adc82a9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Jan 2015 18:21:25 -0500 Subject: [PATCH 19/30] Use scratch matrices when computing heading, pitch and roll. --- Source/Scene/Camera.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index f4ff5e3be805..00d23b91b67f 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -508,6 +508,9 @@ define([ } } + var scratchHPRMatrix1 = new Matrix4(); + var scratchHPRMatrix2 = new Matrix4(); + defineProperties(Camera.prototype, { /** * Gets the inverse camera transform. @@ -641,8 +644,8 @@ define([ var origin = this.positionWC; var ellipsoid = this._projection.ellipsoid; - var oldTransform = Matrix4.clone(this.transform); - var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid); + var oldTransform = Matrix4.clone(this.transform, scratchHPRMatrix1); + var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2); this.setTransform(transform); @@ -690,8 +693,8 @@ define([ var origin = this.positionWC; var ellipsoid = this._projection.ellipsoid; - var oldTransform = Matrix4.clone(this.transform); - var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid); + var oldTransform = Matrix4.clone(this.transform, scratchHPRMatrix1); + var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2); this.setTransform(transform); var pitch = CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(-this.direction.z); @@ -747,8 +750,8 @@ define([ var heading = this.heading; - var oldTransform = Matrix4.clone(this.transform); - var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid); + var oldTransform = Matrix4.clone(this.transform, scratchHPRMatrix1); + var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2); this.setTransform(transform); var up = this.up; From daaef966810ef78fc727dbe894714343888a982e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Jan 2015 18:33:24 -0500 Subject: [PATCH 20/30] Change setView defaults and add doc. --- Source/Scene/Camera.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 00d23b91b67f..d236809693d2 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -839,6 +839,19 @@ define([ var scratchSetViewMatrix3 = new Matrix3(); var scratchSetViewCartographic = new Cartographic(); + /** + * Sets the camera position and orientation with heading, pitch and roll angles. + * + * The position can be given as either a cartesian or a cartographic. If both are given, + * then the cartesian will be used. If neither is given, then the current camera position + * will be used. + * + * @param {Cartesian3} [options.cartesian] The cartesian position of the camera. + * @param {Cartographic} [options.cartographic] The cartographic position of the camera. + * @param {Number} [options.heading] The heading in radians or the current heading will be used if undefined. + * @param {Number} [options.pitch] The pitch in radians or the current pitch will be used if undefined. + * @param {Number} [options.roll] The roll in radians or the current roll will be used if undefined. + */ Camera.prototype.setView = function(options) { if (this._mode === SceneMode.MORPHING) { return; @@ -848,9 +861,9 @@ define([ var scene2D = this._mode === SceneMode.SCENE2D; - var heading = defaultValue(options.heading, 0.0); - var pitch = scene2D || !defined(options.pitch) ? CesiumMath.PI_OVER_TWO : options.pitch; - var roll = scene2D || !defined(options.roll) ? 0.0 : options.roll; + var heading = defaultValue(options.heading, this.heading); + var pitch = scene2D ? CesiumMath.PI_OVER_TWO : defaultValue(options.pitch, this.pitch); + var roll = scene2D ? 0.0 : defaultValue(options.roll, this.roll); var cartesian = options.cartesian; var cartographic = options.cartographic; @@ -1489,7 +1502,10 @@ define([ //>>includeEnd('debug'); this.setView({ - cartographic : cartographic + cartographic : cartographic, + heading : 0.0, + pitch : CesiumMath.PI_OVER_TWO, + roll : 0.0 }); }; From 3078afac9442c67e796bf3d78d24e9908251edd9 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 12 Jan 2015 21:45:39 -0500 Subject: [PATCH 21/30] Update camera tests. --- Source/Scene/Camera.js | 7 +- Specs/Scene/CameraSpec.js | 283 ++++++++++++++++++++------------------ 2 files changed, 152 insertions(+), 138 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index d236809693d2..fb3449634c94 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -748,8 +748,6 @@ define([ var origin = this.positionWC; var ellipsoid = this._projection.ellipsoid; - var heading = this.heading; - var oldTransform = Matrix4.clone(this.transform, scratchHPRMatrix1); var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2); this.setTransform(transform); @@ -860,11 +858,16 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var scene2D = this._mode === SceneMode.SCENE2D; + var scene3D = this._mode === SceneMode.SCENE3D; var heading = defaultValue(options.heading, this.heading); var pitch = scene2D ? CesiumMath.PI_OVER_TWO : defaultValue(options.pitch, this.pitch); var roll = scene2D ? 0.0 : defaultValue(options.roll, this.roll); + if (scene3D) { + roll = -roll; + } + var cartesian = options.cartesian; var cartographic = options.cartographic; diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index ce6621d00da8..1869d28c0690 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -146,23 +146,19 @@ defineSuite([ Matrix3.transpose(transform, transform); var right = Matrix3.multiplyByVector(transform, camera.right, new Cartesian3()); - var heading = Math.atan2(right.y, right.x); + var heading = CesiumMath.zeroToTwoPi(Math.atan2(right.y, right.x)); expect(camera.heading).toEqual(heading); }); - it('set heading throws without angle', function() { - expect(function() { - camera.heading = undefined; - }).toThrowDeveloperError(); - }); - it('set heading in 2D', function() { camera._mode = SceneMode.SCENE2D; var heading = camera.heading; var newHeading = CesiumMath.toRadians(45.0); - camera.heading = newHeading; + camera.setView({ + heading : newHeading + }); expect(camera.heading).not.toEqual(heading); expect(camera.heading).toEqualEpsilon(newHeading, CesiumMath.EPSILON14); @@ -171,9 +167,16 @@ defineSuite([ it('set heading in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; + camera.position = Cartesian3.fromDegrees(0.0, 0.0, 100000.0); + camera.direction = Cartesian3.negate(Cartesian3.normalize(camera.position, new Cartesian3()), new Cartesian3()); + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); + var heading = camera.heading; var newHeading = CesiumMath.toRadians(45.0); - camera.heading = newHeading; + camera.setView({ + heading : newHeading + }); expect(camera.heading).not.toEqual(heading); expect(camera.heading).toEqualEpsilon(newHeading, CesiumMath.EPSILON14); @@ -189,52 +192,60 @@ defineSuite([ var heading = camera.heading; var newHeading = CesiumMath.toRadians(45.0); - camera.heading = newHeading; + camera.setView({ + heading : newHeading + }); expect(camera.heading).not.toEqual(heading); expect(camera.heading).toEqualEpsilon(newHeading, CesiumMath.EPSILON14); }); - it('tilt is undefined when mode is not 3D or Columbus view', function() { + it('pitch is undefined when mode is not 3D or Columbus view', function() { camera._mode = SceneMode.MORPHING; - expect(camera.tilt).not.toBeDefined(); + expect(camera.pitch).not.toBeDefined(); }); - it('get tilt in CV', function() { + it('get pitch in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; - var tilt = CesiumMath.PI_OVER_TWO - Math.acos(-camera.direction.z); - expect(camera.tilt).toEqual(tilt); + camera.position = Cartesian3.fromDegrees(0.0, 0.0, 100000.0); + camera.direction = Cartesian3.negate(Cartesian3.normalize(camera.position, new Cartesian3()), new Cartesian3()); + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); + + var pitch = CesiumMath.PI_OVER_TWO - Math.acos(-camera.direction.z); + expect(camera.pitch).toEqualEpsilon(pitch, CesiumMath.EPSILON6); }); - it('get tilt in 3D', function() { + it('get pitch in 3D', function() { camera._mode = SceneMode.SCENE3D; var direction = Cartesian3.normalize(camera.position, new Cartesian3()); Cartesian3.negate(direction, direction); - var tilt = CesiumMath.PI_OVER_TWO - Math.acos(Cartesian3.dot(camera.direction, direction)); + var pitch = CesiumMath.PI_OVER_TWO - Math.acos(Cartesian3.dot(camera.direction, direction)); - expect(camera.tilt).toEqual(tilt); - }); - - it('set tilt throws without angle', function() { - expect(function() { - camera.tilt = undefined; - }).toThrowDeveloperError(); + expect(camera.pitch).toEqual(pitch); }); - it('set tilt in CV', function() { + it('set pitch in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; - var tilt = camera.tilt; - var newTilt = CesiumMath.toRadians(45.0); - camera.tilt = newTilt; + camera.position = Cartesian3.fromDegrees(0.0, 0.0, 100000.0); + camera.direction = Cartesian3.negate(Cartesian3.normalize(camera.position, new Cartesian3()), new Cartesian3()); + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); - expect(camera.tilt).not.toEqual(tilt); - expect(camera.tilt).toEqualEpsilon(newTilt, CesiumMath.EPSILON14); + var pitch = camera.pitch; + var newPitch = CesiumMath.toRadians(45.0); + camera.setView({ + pitch : newPitch + }); + + expect(camera.pitch).not.toEqual(pitch); + expect(camera.pitch).toEqualEpsilon(newPitch, CesiumMath.EPSILON6); }); - it('set tilt in 3D', function() { + it('set pitch in 3D', function() { camera._mode = SceneMode.SCENE3D; camera.position = Cartesian3.clone(Cartesian3.UNIT_X); @@ -242,12 +253,14 @@ defineSuite([ camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); - var tilt = camera.tilt; - var newTilt = CesiumMath.toRadians(45.0); - camera.tilt = newTilt; + var pitch = camera.pitch; + var newPitch = CesiumMath.toRadians(45.0); + camera.setView({ + pitch : newPitch + }); - expect(camera.tilt).not.toEqual(tilt); - expect(camera.tilt).toEqualEpsilon(newTilt, CesiumMath.EPSILON14); + expect(camera.pitch).not.toEqual(pitch); + expect(camera.pitch).toEqualEpsilon(newPitch, CesiumMath.EPSILON14); }); it('roll is undefined when not 3D or Columbus view', function() { @@ -258,15 +271,15 @@ defineSuite([ it('get roll in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; - camera.position = new Cartesian3(100.0, 0.0, 100.0); - camera.direction = new Cartesian3(0.0, 1.0, -1.0); - Cartesian3.normalize(camera.direction, camera.direction); - camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); - Cartesian3.normalize(camera.right, camera.right); - camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); + camera.position = Cartesian3.fromDegrees(0.0, 0.0, 100000.0); + camera.direction = Cartesian3.negate(Cartesian3.normalize(camera.position, new Cartesian3()), new Cartesian3()); + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); - var roll = Math.atan2(right.z, right.x); - expect(camera.roll).toEqual(roll); + camera.look(camera.direction, CesiumMath.toRadians(45.0)); + + var roll = Math.acos(-camera.right.z) - CesiumMath.PI_OVER_TWO; + expect(camera.roll).toEqualEpsilon(roll, CesiumMath.EPSILON6); }); it('get roll in 3D', function() { @@ -291,47 +304,35 @@ defineSuite([ expect(camera.roll).toEqual(roll); }); - it('set roll throws without angle', function() { - expect(function() { - camera.roll = undefined; - }).toThrowDeveloperError(); - }); - it('set roll in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; - camera.position = new Cartesian3(100.0, 0.0, 100.0); - camera.direction = new Cartesian3(0.0, 1.0, -1.0); - Cartesian3.normalize(camera.direction, camera.direction); - camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); - Cartesian3.normalize(camera.right, camera.right); - camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); + camera.position = Cartesian3.fromDegrees(0.0, 0.0, 100000.0); + camera.direction = Cartesian3.negate(Cartesian3.normalize(camera.position, new Cartesian3()), new Cartesian3()); + camera.up = Cartesian3.clone(Cartesian3.UNIT_Z); + camera.right = Cartesian3.cross(camera.direction, camera.up, new Cartesian3()); var roll = camera.roll; - var newRoll = CesiumMath.PI_OVER_TWO; - camera.roll = newRoll; + var newRoll = CesiumMath.PI_OVER_FOUR; + camera.setView({ + roll : newRoll + }); expect(camera.roll).not.toEqual(roll); - expect(camera.roll).toEqualEpsilon(newRoll, CesiumMath.EPSILON12); + expect(camera.roll).toEqualEpsilon(newRoll, CesiumMath.EPSILON6); }); it('set roll in 3D', function() { camera._mode = SceneMode.SCENE3D; - camera.position = Cartesian3.clone(Cartesian3.UNIT_X); - Cartesian3.multiplyByScalar(camera.position, Ellipsoid.WGS84.maximumRadius + 100.0, camera.position); - camera.direction = new Cartesian3(-1.0, 0.0, 1.0); - Cartesian3.normalize(camera.direction, camera.direction); - camera.right = Cartesian3.cross(camera.direction, Cartesian3.UNIT_Z, new Cartesian3()); - Cartesian3.normalize(camera.right, camera.right); - camera.up = Cartesian3.cross(camera.right, camera.direction, new Cartesian3()); - var roll = camera.roll; - var newRoll = CesiumMath.PI_OVER_TWO; - camera.roll = newRoll; + var newRoll = CesiumMath.PI_OVER_FOUR; + camera.setView({ + roll : newRoll + }); expect(camera.roll).not.toEqual(roll); - expect(camera.roll).toEqualEpsilon(newRoll, CesiumMath.EPSILON14); + expect(camera.roll).toEqualEpsilon(newRoll, CesiumMath.EPSILON6); }); it('update throws without mode', function() { @@ -362,6 +363,82 @@ defineSuite([ expect(camera.right).toEqualEpsilon(Cartesian3.UNIT_X, CesiumMath.EPSILON9); }); + it('setView with cartographic in 2D', function() { + var ellipsoid = Ellipsoid.WGS84; + var projection = new GeographicProjection(ellipsoid); + var maxRadii = ellipsoid.maximumRadius; + + camera._mode = SceneMode.SCENE2D; + camera._projection = projection; + + var frustum = new OrthographicFrustum(); + frustum.right = maxRadii * Math.PI; + frustum.left = -frustum.right; + frustum.top = frustum.right * (scene.drawingBufferHeight / scene.drawingBufferWidth); + frustum.bottom = -frustum.top; + frustum.near = 0.01 * maxRadii; + frustum.far = 60.0 * maxRadii; + camera.frustum = frustum; + + var ratio = frustum.top / frustum.right; + var cart = Cartographic.fromDegrees(-75.0, 42.0, 100.0); + camera.setView({ + heading : 0.0, + pitch : CesiumMath.PI_OVER_TWO, + roll : 0.0, + cartographic : cart + }); + + expect(Cartesian2.fromCartesian3(camera.position, new Cartesian2())).toEqualEpsilon(Cartesian2.fromCartesian3(projection.project(cart), new Cartesian2()), CesiumMath.EPSILON11); + expect(camera.direction).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), CesiumMath.EPSILON6); + expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_Y, CesiumMath.EPSILON6); + expect(camera.right).toEqualEpsilon(Cartesian3.UNIT_X, CesiumMath.EPSILON6); + expect(frustum.right - frustum.left).toEqualEpsilon(cart.height, CesiumMath.EPSILON6); + expect(frustum.top / frustum.right).toEqual(ratio); + }); + + it('setView with cartographic in Columbus View', function() { + var ellipsoid = Ellipsoid.WGS84; + var projection = new GeographicProjection(ellipsoid); + + camera._mode = SceneMode.COLUMBUS_VIEW; + camera._projection = projection; + + var cart = Cartographic.fromDegrees(-75.0, 42.0, 100.0); + camera.setView({ + heading : 0.0, + pitch : CesiumMath.PI_OVER_TWO, + roll : 0.0, + cartographic : cart + }); + + expect(camera.position).toEqualEpsilon(projection.project(cart), CesiumMath.EPSILON11); + expect(camera.direction).toEqualEpsilon(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()), CesiumMath.EPSILON6); + expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_Y, CesiumMath.EPSILON6); + expect(camera.right).toEqualEpsilon(Cartesian3.UNIT_X, CesiumMath.EPSILON6); + }); + + it('setView with cartographic in 3D', function() { + var ellipsoid = Ellipsoid.WGS84; + var projection = new GeographicProjection(ellipsoid); + + camera._mode = SceneMode.SCENE3D; + camera._projection = projection; + + var cart = new Cartographic(-75.0, 0.0, 100.0); + camera.setView({ + heading : 0.0, + pitch : CesiumMath.PI_OVER_TWO, + roll : 0.0, + cartographic : cart + }); + + expect(camera.position).toEqualEpsilon(ellipsoid.cartographicToCartesian(cart), CesiumMath.EPSILON6); + expect(camera.direction).toEqualEpsilon(Cartesian3.normalize(Cartesian3.negate(camera.position, new Cartesian3()), new Cartesian3()), CesiumMath.EPSILON6); + expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_Z, CesiumMath.EPSILON6); + expect(camera.right).toEqualEpsilon(Cartesian3.cross(camera.direction, camera.up, new Cartesian3()), CesiumMath.EPSILON6); + }); + it('worldToCameraCoordinates throws without cartesian', function() { expect(function() { camera.worldToCameraCoordinates(); @@ -1316,72 +1393,6 @@ defineSuite([ expect(p).toBeUndefined(); }); - it('set position cartographic throws without a cartographic', function() { - expect(function() { - camera.setPositionCartographic(); - }).toThrowDeveloperError(); - }); - - it('set position cartographic in 2D', function() { - var ellipsoid = Ellipsoid.WGS84; - var projection = new GeographicProjection(ellipsoid); - var maxRadii = ellipsoid.maximumRadius; - - camera._mode = SceneMode.SCENE2D; - camera._projection = projection; - - var frustum = new OrthographicFrustum(); - frustum.right = maxRadii * Math.PI; - frustum.left = -frustum.right; - frustum.top = frustum.right * (scene.drawingBufferHeight / scene.drawingBufferWidth); - frustum.bottom = -frustum.top; - frustum.near = 0.01 * maxRadii; - frustum.far = 60.0 * maxRadii; - camera.frustum = frustum; - - var ratio = frustum.top / frustum.right; - var cart = new Cartographic(-75.0, 42.0, 100.0); - camera.setPositionCartographic(cart); - - expect(Cartesian2.fromCartesian3(camera.position, new Cartesian2())).toEqual(Cartesian2.fromCartesian3(projection.project(cart), new Cartesian2())); - expect(camera.direction).toEqual(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3())); - expect(camera.up).toEqual(Cartesian3.UNIT_Y); - expect(camera.right).toEqual(Cartesian3.UNIT_X); - expect(frustum.right - frustum.left).toEqual(cart.height); - expect(frustum.top / frustum.right).toEqual(ratio); - }); - - it('set position cartographic in Columbus View', function() { - var ellipsoid = Ellipsoid.WGS84; - var projection = new GeographicProjection(ellipsoid); - - camera._mode = SceneMode.COLUMBUS_VIEW; - camera._projection = projection; - - var cart = new Cartographic(-75.0, 42.0, 100.0); - camera.setPositionCartographic(cart); - expect(camera.position).toEqual(projection.project(cart)); - expect(camera.direction).toEqual(Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3())); - expect(camera.up).toEqual(Cartesian3.UNIT_Y); - expect(camera.right).toEqual(Cartesian3.UNIT_X); - }); - - it('set position cartographic in 3D', function() { - var ellipsoid = Ellipsoid.WGS84; - var projection = new GeographicProjection(ellipsoid); - - camera._mode = SceneMode.SCENE3D; - camera._projection = projection; - - var cart = new Cartographic(-75.0, 0.0, 100.0); - camera.setPositionCartographic(cart); - - expect(camera.position).toEqual(ellipsoid.cartographicToCartesian(cart)); - expect(camera.direction).toEqual(Cartesian3.normalize(Cartesian3.negate(camera.position, new Cartesian3()), new Cartesian3())); - expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_Z, CesiumMath.EPSILON15); - expect(camera.right).toEqual(Cartesian3.cross(camera.direction, camera.up, new Cartesian3()), new Cartesian3()); - }); - it('get pick ray throws without a position', function() { expect(function () { camera.getPickRay(); From d5ead406970cfd667f3ebc8446e7e0df227f523e Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 13 Jan 2015 07:34:06 -0500 Subject: [PATCH 22/30] Fix whitespace --- Source/Scene/Camera.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index fb3449634c94..6b81b91a69af 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -648,7 +648,6 @@ define([ var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2); this.setTransform(transform); - var right = this.right; var direction = this.direction; From d2a3254645f1d8de19baf1e0b4a7c80e228d4a66 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 13 Jan 2015 12:00:37 -0500 Subject: [PATCH 23/30] Updates from review. --- Source/Scene/Camera.js | 8 ++++---- Specs/Scene/CameraSpec.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 6b81b91a69af..cf22ca68441e 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -843,8 +843,8 @@ define([ * then the cartesian will be used. If neither is given, then the current camera position * will be used. * - * @param {Cartesian3} [options.cartesian] The cartesian position of the camera. - * @param {Cartographic} [options.cartographic] The cartographic position of the camera. + * @param {Cartesian3} [options.position] The cartesian position of the camera. + * @param {Cartographic} [options.positionCartographic] The cartographic position of the camera. * @param {Number} [options.heading] The heading in radians or the current heading will be used if undefined. * @param {Number} [options.pitch] The pitch in radians or the current pitch will be used if undefined. * @param {Number} [options.roll] The roll in radians or the current roll will be used if undefined. @@ -867,8 +867,8 @@ define([ roll = -roll; } - var cartesian = options.cartesian; - var cartographic = options.cartographic; + var cartesian = options.position; + var cartographic = options.positionCartographic; var projection = this._projection; var ellipsoid = projection.ellipsoid; diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index 1869d28c0690..9c0667d25cfa 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -386,7 +386,7 @@ defineSuite([ heading : 0.0, pitch : CesiumMath.PI_OVER_TWO, roll : 0.0, - cartographic : cart + positionCartographic : cart }); expect(Cartesian2.fromCartesian3(camera.position, new Cartesian2())).toEqualEpsilon(Cartesian2.fromCartesian3(projection.project(cart), new Cartesian2()), CesiumMath.EPSILON11); @@ -409,7 +409,7 @@ defineSuite([ heading : 0.0, pitch : CesiumMath.PI_OVER_TWO, roll : 0.0, - cartographic : cart + positionCartographic : cart }); expect(camera.position).toEqualEpsilon(projection.project(cart), CesiumMath.EPSILON11); @@ -430,7 +430,7 @@ defineSuite([ heading : 0.0, pitch : CesiumMath.PI_OVER_TWO, roll : 0.0, - cartographic : cart + positionCartographic : cart }); expect(camera.position).toEqualEpsilon(ellipsoid.cartographicToCartesian(cart), CesiumMath.EPSILON6); From 855072d6988ef77544f6ffda997aaa8dc54140e8 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 13 Jan 2015 12:25:31 -0500 Subject: [PATCH 24/30] Add Transforms.headingPitchRollQuaternion based on review. --- Source/Core/Transforms.js | 30 ++++++++++++++++++++++++++++++ Specs/Core/TransformsSpec.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/Source/Core/Transforms.js b/Source/Core/Transforms.js index 9fedb4596126..6e1c44517298 100644 --- a/Source/Core/Transforms.js +++ b/Source/Core/Transforms.js @@ -378,6 +378,36 @@ define([ return Matrix4.multiply(result, hprMatrix, result); }; + var scratchENUMatrix4 = new Matrix4(); + var scratchHPRMatrix3 = new Matrix3(); + + /** + * Computes a quaternion from a reference frame with axes computed from the heading-pitch-roll angles + * centered at the provided origin. + * + * @param {Cartesian3} origin The center point of the local reference frame. + * @param {Number} heading The heading angle in radians. + * @param {Number} pitch The pitch angle in radians. + * @param {Number} roll The roll angle in radians. + * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation. + * @param {Quaternion} [result] The object onto which to store the result. + * @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided. + * + * @example + * // Get the quaternion from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame. + * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0); + * var heading = -Cesium.Math.PI_OVER_TWO; + * var pitch = Cesium.Math.PI_OVER_FOUR; + * var roll = 0.0; + * var quaternion = Cesium.Transforms.headingPitchRollQuaternion(center, heading, pitch, roll); + */ + Transforms.headingPitchRollQuaternion = function(origin, heading, pitch, roll, ellipsoid, result) { + // checks for required parameters happen in the called functions + var transform = Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll, ellipsoid, scratchENUMatrix4); + var rotation = Matrix4.getRotation(transform, scratchHPRMatrix3); + return Quaternion.fromRotationMatrix(rotation, result); + }; + var gmstConstant0 = 6 * 3600 + 41 * 60 + 50.54841; var gmstConstant1 = 8640184.812866; diff --git a/Specs/Core/TransformsSpec.js b/Specs/Core/TransformsSpec.js index e82c6170d102..86a21816d15b 100644 --- a/Specs/Core/TransformsSpec.js +++ b/Specs/Core/TransformsSpec.js @@ -242,6 +242,36 @@ defineSuite([ expect(actualTranslation).toEqual(origin); }); + it('headingPitchRollQuaternion works without a result parameter', function() { + var origin = new Cartesian3(1.0, 0.0, 0.0); + var heading = CesiumMath.toRadians(20.0); + var pitch = CesiumMath.toRadians(30.0); + var roll = CesiumMath.toRadians(40.0); + + var transform = Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll, Ellipsoid.UNIT_SPHERE); + var expected = Matrix4.getRotation(transform, new Matrix3()); + + var quaternion = Transforms.headingPitchRollQuaternion(origin, heading, pitch, roll, Ellipsoid.UNIT_SPHERE); + var actual = Matrix3.fromQuaternion(quaternion); + expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON11); + }); + + it('headingPitchRollQuaternion works with a result parameter', function() { + var origin = new Cartesian3(1.0, 0.0, 0.0); + var heading = CesiumMath.toRadians(20.0); + var pitch = CesiumMath.toRadians(30.0); + var roll = CesiumMath.toRadians(40.0); + + var transform = Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll, Ellipsoid.UNIT_SPHERE); + var expected = Matrix4.getRotation(transform, new Matrix3()); + + var result = new Quaternion(); + var quaternion = Transforms.headingPitchRollQuaternion(origin, heading, pitch, roll, Ellipsoid.UNIT_SPHERE, result); + var actual = Matrix3.fromQuaternion(quaternion); + expect(quaternion).toBe(result); + expect(actual).toEqualEpsilon(expected, CesiumMath.EPSILON11); + }); + it('computeTemeToPseudoFixedMatrix works before noon', function() { var time = JulianDate.now(); var secondsDiff = TimeConstants.SECONDS_PER_DAY - time.secondsOfDay; From 4f83b6e3a8a06d2715ee945329a8e5dbc672949e Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 13 Jan 2015 13:24:59 -0500 Subject: [PATCH 25/30] Update Sandcastle examples. --- Apps/Sandcastle/gallery/3D Models.html | 14 +++++++++++--- Apps/Sandcastle/gallery/Camera.html | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Models.html b/Apps/Sandcastle/gallery/3D Models.html index 6e1c379d9c54..3027fee2384c 100644 --- a/Apps/Sandcastle/gallery/3D Models.html +++ b/Apps/Sandcastle/gallery/3D Models.html @@ -30,10 +30,14 @@ var viewer = new Cesium.Viewer('cesiumContainer'); var scene = viewer.scene; -function createModel(url, height) { +function createModel(url, height, heading, pitch, roll) { height = Cesium.defaultValue(height, 0.0); + heading = Cesium.defaultValue(heading, 0.0); + pitch = Cesium.defaultValue(pitch, 0.0); + roll = Cesium.defaultValue(roll, 0.0); - var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height)); + var origin = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, height); + var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(origin, heading, pitch, roll); scene.primitives.removeAll(); // Remove previous model var model = scene.primitives.add(Cesium.Model.fromGltf({ @@ -75,7 +79,11 @@ var options = [{ text : 'Aircraft', onselect : function() { - createModel('../../SampleData/models/CesiumAir/Cesium_Air.gltf', 5000.0); + var height = 5000.0; + var heading = 0.0; + var pitch = Cesium.Math.toRadians(-10.0); + var roll = Cesium.Math.toRadians(-20.0); + createModel('../../SampleData/models/CesiumAir/Cesium_Air.gltf', height, heading, pitch, roll); } }, { text : 'Ground vehicle', diff --git a/Apps/Sandcastle/gallery/Camera.html b/Apps/Sandcastle/gallery/Camera.html index a28cdaafa4d7..307b07a3ee54 100644 --- a/Apps/Sandcastle/gallery/Camera.html +++ b/Apps/Sandcastle/gallery/Camera.html @@ -124,6 +124,18 @@ })); } +function setHeadingPitchRoll() { + Sandcastle.declare(setHeadingPitchRoll); + + var camera = viewer.camera; + camera.setView({ + position : Cesium.Cartesian3.fromDegrees(-75.5847, 40.0397, 1000.0), + heading : Cesium.Math.PI_OVER_TWO, + pitch : Cesium.Math.PI_OVER_FOUR, + roll : 0.0 + }) +} + function icrf(scene, time) { if (scene.mode !== Cesium.SceneMode.SCENE3D) { return; @@ -181,6 +193,12 @@ Sandcastle.highlight(setReferenceFrame); } }, { + text : 'Set camera with heading, pitch, and roll', + onselect : function() { + setHeadingPitchRoll(); + Sandcastle.highlight(setHeadingPitchRoll); + } +},{ text : 'View in ICRF', onselect : function() { viewInICRF(); From f871bcfe4eeeb13b45a5ab5a9501fd73007cceb5 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Tue, 13 Jan 2015 14:33:00 -0500 Subject: [PATCH 26/30] Fix jsHint error. --- Apps/Sandcastle/gallery/Camera.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/Sandcastle/gallery/Camera.html b/Apps/Sandcastle/gallery/Camera.html index 307b07a3ee54..ab1f8678b7cf 100644 --- a/Apps/Sandcastle/gallery/Camera.html +++ b/Apps/Sandcastle/gallery/Camera.html @@ -133,7 +133,7 @@ heading : Cesium.Math.PI_OVER_TWO, pitch : Cesium.Math.PI_OVER_FOUR, roll : 0.0 - }) + }); } function icrf(scene, time) { From 3be532b0dfa7816c3256fd54978e276e082ff9f8 Mon Sep 17 00:00:00 2001 From: Patrick Cozzi Date: Tue, 13 Jan 2015 17:36:48 -0500 Subject: [PATCH 27/30] Tweak README.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e3c4763d505e..41ced0bebc58 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,7 +15,7 @@ Change Log * `PolygonGraphics.positions` was deprecated and replaced with `PolygonGraphics.hierarchy`, whose value is a `PolygonHierarchy` instead of an array of positions. `PolygonGraphics.positions` will be removed in Cesium 1.8. * Improved performance of asynchronous geometry creation (as much as 20% faster in some use cases). [#2342](https://github.com/AnalyticalGraphicsInc/cesium/issues/2342) * Added `PolylineVolumeGraphics` and `Entity.polylineVolume` -* Added `Camera.roll`. +* Added `Camera.setView` (which use heading, pitch, and roll) and `Camera.roll`. * Added `Quaternion.fromHeadingPitchRoll` to create a rotation from heading, pitch, and roll angles. * Added `Transforms.headingPitchRollToFixedFrame` to create a local frame from a position and heading/pitch/roll angles. * Added `BillboardGraphics.imageSubRegion`, to enable custom texture atlas use for `Entity` instances. From 886eea4d8a9754c4a1e69aa010b6cc8696bc916c Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 14 Jan 2015 14:12:31 -0500 Subject: [PATCH 28/30] Change heading/pitch/roll convention. Heading is increasing moving eastward from north. Pitch is positive moving towards positive local z. --- Apps/Sandcastle/gallery/3D Models.html | 2 +- Apps/Sandcastle/gallery/Camera.html | 4 ++-- Source/Core/Quaternion.js | 4 ++-- Source/Scene/Camera.js | 21 ++++++++------------- Specs/Core/QuaternionSpec.js | 8 ++++---- Specs/Scene/CameraSpec.js | 18 +++++++++--------- 6 files changed, 26 insertions(+), 31 deletions(-) diff --git a/Apps/Sandcastle/gallery/3D Models.html b/Apps/Sandcastle/gallery/3D Models.html index 3027fee2384c..8ca9b39d04b9 100644 --- a/Apps/Sandcastle/gallery/3D Models.html +++ b/Apps/Sandcastle/gallery/3D Models.html @@ -81,7 +81,7 @@ onselect : function() { var height = 5000.0; var heading = 0.0; - var pitch = Cesium.Math.toRadians(-10.0); + var pitch = Cesium.Math.toRadians(10.0); var roll = Cesium.Math.toRadians(-20.0); createModel('../../SampleData/models/CesiumAir/Cesium_Air.gltf', height, heading, pitch, roll); } diff --git a/Apps/Sandcastle/gallery/Camera.html b/Apps/Sandcastle/gallery/Camera.html index ab1f8678b7cf..df8cd1afda12 100644 --- a/Apps/Sandcastle/gallery/Camera.html +++ b/Apps/Sandcastle/gallery/Camera.html @@ -130,8 +130,8 @@ var camera = viewer.camera; camera.setView({ position : Cesium.Cartesian3.fromDegrees(-75.5847, 40.0397, 1000.0), - heading : Cesium.Math.PI_OVER_TWO, - pitch : Cesium.Math.PI_OVER_FOUR, + heading : -Cesium.Math.PI_OVER_TWO, + pitch : -Cesium.Math.PI_OVER_FOUR, roll : 0.0 }); } diff --git a/Source/Core/Quaternion.js b/Source/Core/Quaternion.js index 49d237f5ca19..0d6c3bbd0cb6 100644 --- a/Source/Core/Quaternion.js +++ b/Source/Core/Quaternion.js @@ -199,8 +199,8 @@ define([ } //>>includeEnd('debug'); - var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, heading, result); - var pitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, scratchHPRQuaternion); + var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, -heading, result); + var pitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, -pitch, scratchHPRQuaternion); result = Quaternion.multiply(headingQuaternion, pitchQuaternion, headingQuaternion); var rollQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, roll, scratchHPRQuaternion); diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index cf22ca68441e..219fac82f38f 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -660,7 +660,7 @@ define([ this.setTransform(oldTransform); - return CesiumMath.zeroToTwoPi(heading); + return CesiumMath.TWO_PI - CesiumMath.zeroToTwoPi(heading); } return undefined; @@ -696,7 +696,7 @@ define([ var transform = Transforms.eastNorthUpToFixedFrame(this.positionWC, ellipsoid, scratchHPRMatrix2); this.setTransform(transform); - var pitch = CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(-this.direction.z); + var pitch = CesiumMath.PI_OVER_TWO - CesiumMath.acosClamped(this.direction.z); this.setTransform(oldTransform); @@ -761,7 +761,7 @@ define([ this.setTransform(oldTransform); - return CesiumMath.zeroToTwoPi(roll); + return CesiumMath.TWO_PI - CesiumMath.zeroToTwoPi(roll); } return undefined; @@ -857,13 +857,13 @@ define([ options = defaultValue(options, defaultValue.EMPTY_OBJECT); var scene2D = this._mode === SceneMode.SCENE2D; - var scene3D = this._mode === SceneMode.SCENE3D; + var sceneCV = this._mode === SceneMode.COLUMBUS_VIEW; var heading = defaultValue(options.heading, this.heading); - var pitch = scene2D ? CesiumMath.PI_OVER_TWO : defaultValue(options.pitch, this.pitch); + var pitch = scene2D ? -CesiumMath.PI_OVER_TWO : defaultValue(options.pitch, this.pitch); var roll = scene2D ? 0.0 : defaultValue(options.roll, this.roll); - if (scene3D) { + if (sceneCV) { roll = -roll; } @@ -904,12 +904,7 @@ define([ Cartesian3.clone(Cartesian3.ZERO, this.position); } - var headingQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, heading + CesiumMath.PI_OVER_TWO, new Quaternion()); - var pitchQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_Y, pitch, new Quaternion()); - var rotQuat = Quaternion.multiply(headingQuaternion, pitchQuaternion, headingQuaternion); - - var rollQuaternion = Quaternion.fromAxisAngle(Cartesian3.UNIT_X, roll, new Quaternion()); - Quaternion.multiply(rollQuaternion, rotQuat, rotQuat); + var rotQuat = Quaternion.fromHeadingPitchRoll(heading - CesiumMath.PI_OVER_TWO, pitch, roll, scratchSetViewQuaternion); var rotMat = Matrix3.fromQuaternion(rotQuat, scratchSetViewMatrix3); Matrix3.getColumn(rotMat, 0, this.direction); @@ -1506,7 +1501,7 @@ define([ this.setView({ cartographic : cartographic, heading : 0.0, - pitch : CesiumMath.PI_OVER_TWO, + pitch : -CesiumMath.PI_OVER_TWO, roll : 0.0 }); }; diff --git a/Specs/Core/QuaternionSpec.js b/Specs/Core/QuaternionSpec.js index 921a5693cca8..10ce2ddf5300 100644 --- a/Specs/Core/QuaternionSpec.js +++ b/Specs/Core/QuaternionSpec.js @@ -107,13 +107,13 @@ defineSuite([ it('fromHeadingPitchRoll with just heading', function() { var angle = CesiumMath.toRadians(20.0); var quaternion = Quaternion.fromHeadingPitchRoll(angle, 0.0, 0.0); - expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationZ(angle), CesiumMath.EPSILON11); + expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationZ(-angle), CesiumMath.EPSILON11); }); it('fromHeadingPitchRoll with just pitch', function() { var angle = CesiumMath.toRadians(20.0); var quaternion = Quaternion.fromHeadingPitchRoll(0.0, angle, 0.0); - expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationY(angle), CesiumMath.EPSILON11); + expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(Matrix3.fromRotationY(-angle), CesiumMath.EPSILON11); }); it('fromHeadingPitchRoll with just roll', function() { @@ -125,8 +125,8 @@ defineSuite([ it('fromHeadingPitchRoll with all angles', function() { var angle = CesiumMath.toRadians(20.0); var quaternion = Quaternion.fromHeadingPitchRoll(angle, angle, angle); - var expected = Matrix3.fromRotationY(angle); - Matrix3.multiply(Matrix3.fromRotationZ(angle), expected, expected); + var expected = Matrix3.fromRotationY(-angle); + Matrix3.multiply(Matrix3.fromRotationZ(-angle), expected, expected); Matrix3.multiply(Matrix3.fromRotationX(angle), expected, expected); expect(Matrix3.fromQuaternion(quaternion)).toEqualEpsilon(expected, CesiumMath.EPSILON11); }); diff --git a/Specs/Scene/CameraSpec.js b/Specs/Scene/CameraSpec.js index 9c0667d25cfa..505b02ae846d 100644 --- a/Specs/Scene/CameraSpec.js +++ b/Specs/Scene/CameraSpec.js @@ -126,14 +126,14 @@ defineSuite([ it('get heading in 2D', function() { camera._mode = SceneMode.SCENE2D; - var heading = Math.atan2(camera.right.y, camera.right.x); + var heading = CesiumMath.TWO_PI - Math.atan2(camera.right.y, camera.right.x); expect(camera.heading).toEqual(heading); }); it('get heading in CV', function() { camera._mode = SceneMode.COLUMBUS_VIEW; - var heading = Math.atan2(camera.right.y, camera.right.x); + var heading = CesiumMath.TWO_PI - Math.atan2(camera.right.y, camera.right.x); expect(camera.heading).toEqual(heading); }); @@ -146,7 +146,7 @@ defineSuite([ Matrix3.transpose(transform, transform); var right = Matrix3.multiplyByVector(transform, camera.right, new Cartesian3()); - var heading = CesiumMath.zeroToTwoPi(Math.atan2(right.y, right.x)); + var heading = CesiumMath.TWO_PI - CesiumMath.zeroToTwoPi(Math.atan2(right.y, right.x)); expect(camera.heading).toEqual(heading); }); @@ -222,7 +222,7 @@ defineSuite([ var direction = Cartesian3.normalize(camera.position, new Cartesian3()); Cartesian3.negate(direction, direction); - var pitch = CesiumMath.PI_OVER_TWO - Math.acos(Cartesian3.dot(camera.direction, direction)); + var pitch = CesiumMath.PI_OVER_TWO - Math.acos(-Cartesian3.dot(camera.direction, direction)); expect(camera.pitch).toEqual(pitch); }); @@ -278,7 +278,7 @@ defineSuite([ camera.look(camera.direction, CesiumMath.toRadians(45.0)); - var roll = Math.acos(-camera.right.z) - CesiumMath.PI_OVER_TWO; + var roll = CesiumMath.zeroToTwoPi(-CesiumMath.toRadians(45.0)); expect(camera.roll).toEqualEpsilon(roll, CesiumMath.EPSILON6); }); @@ -299,7 +299,7 @@ defineSuite([ Matrix3.transpose(transform, transform); var right = Matrix3.multiplyByVector(transform, camera.right, new Cartesian3()); - var roll = Math.atan2(right.z, right.x); + var roll = CesiumMath.TWO_PI - Math.atan2(right.z, right.x); expect(camera.roll).toEqual(roll); }); @@ -384,7 +384,7 @@ defineSuite([ var cart = Cartographic.fromDegrees(-75.0, 42.0, 100.0); camera.setView({ heading : 0.0, - pitch : CesiumMath.PI_OVER_TWO, + pitch : -CesiumMath.PI_OVER_TWO, roll : 0.0, positionCartographic : cart }); @@ -407,7 +407,7 @@ defineSuite([ var cart = Cartographic.fromDegrees(-75.0, 42.0, 100.0); camera.setView({ heading : 0.0, - pitch : CesiumMath.PI_OVER_TWO, + pitch : -CesiumMath.PI_OVER_TWO, roll : 0.0, positionCartographic : cart }); @@ -428,7 +428,7 @@ defineSuite([ var cart = new Cartographic(-75.0, 0.0, 100.0); camera.setView({ heading : 0.0, - pitch : CesiumMath.PI_OVER_TWO, + pitch : -CesiumMath.PI_OVER_TWO, roll : 0.0, positionCartographic : cart }); From fe07d4a5b3ac48f667688b1d3dd026251e3e9674 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 14 Jan 2015 14:39:33 -0500 Subject: [PATCH 29/30] Update doc to explain what heading, pitch and roll angles are and add code examples based on review. --- Source/Core/Quaternion.js | 4 +++- Source/Core/Transforms.js | 8 ++++++-- Source/Scene/Camera.js | 21 +++++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Source/Core/Quaternion.js b/Source/Core/Quaternion.js index 0d6c3bbd0cb6..b2d8a043564c 100644 --- a/Source/Core/Quaternion.js +++ b/Source/Core/Quaternion.js @@ -178,7 +178,9 @@ define([ var scratchHPRQuaternion = new Quaternion(); /** - * Computes a rotation from the given heading, pitch and roll angles. + * Computes a rotation from the given heading, pitch and roll angles. Heading is the rotation about the + * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about + * the positive x axis. * * @param {Number} heading The heading angle in radians. * @param {Number} pitch The pitch angle in radians. diff --git a/Source/Core/Transforms.js b/Source/Core/Transforms.js index 6e1c44517298..1050e7f29e76 100644 --- a/Source/Core/Transforms.js +++ b/Source/Core/Transforms.js @@ -352,7 +352,9 @@ define([ /** * Computes a 4x4 transformation matrix from a reference frame with axes computed from the heading-pitch-roll angles - * centered at the provided origin to the provided ellipsoid's fixed reference frame. + * centered at the provided origin to the provided ellipsoid's fixed reference frame. Heading is the rotation from the local north + * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles + * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis. * * @param {Cartesian3} origin The center point of the local reference frame. * @param {Number} heading The heading angle in radians. @@ -383,7 +385,9 @@ define([ /** * Computes a quaternion from a reference frame with axes computed from the heading-pitch-roll angles - * centered at the provided origin. + * centered at the provided origin. Heading is the rotation from the local north + * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles + * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis. * * @param {Cartesian3} origin The center point of the local reference frame. * @param {Number} heading The heading angle in radians. diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 219fac82f38f..c5d13949160b 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -848,6 +848,27 @@ define([ * @param {Number} [options.heading] The heading in radians or the current heading will be used if undefined. * @param {Number} [options.pitch] The pitch in radians or the current pitch will be used if undefined. * @param {Number} [options.roll] The roll in radians or the current roll will be used if undefined. + * + * @example + * // 1. Set view with heading, pitch and roll + * camera.setView({ + * position : cartesianPosition, + * heading : Cesium.Math.toRadians(90.0), // east, default value is 0.0 (north) + * pitch : Cesium.Math.toRadians(-90), // default value (looking down) + * roll : 0.0 // default value + * }); + * + * // 2. Set default top-down view with a cartographic position + * camera.setView({ + * positionCartographic : cartographic + * }); + * + * // 3. Change heading, pitch and roll with the camera position remaining the same. + * camera.setView({ + * heading : Cesium.Math.toRadians(90.0), // east, default value is 0.0 (north) + * pitch : Cesium.Math.toRadians(-90), // default value (looking down) + * roll : 0.0 // default value + * }); */ Camera.prototype.setView = function(options) { if (this._mode === SceneMode.MORPHING) { From ef1f2406deb1e6115a5fddf6781ad7e50953c922 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Wed, 14 Jan 2015 16:29:37 -0500 Subject: [PATCH 30/30] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 1a0fbf524b48..b6c19d82e935 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Change Log * Added `Camera.setView` (which use heading, pitch, and roll) and `Camera.roll`. * Added `Quaternion.fromHeadingPitchRoll` to create a rotation from heading, pitch, and roll angles. * Added `Transforms.headingPitchRollToFixedFrame` to create a local frame from a position and heading/pitch/roll angles. +* Added `Transforms.headingPitchRollQuaternion` which is the quaternion rotation from `Transforms.headingPitchRollToFixedFrame`. * Added `BillboardGraphics.imageSubRegion`, to enable custom texture atlas use for `Entity` instances. * Added `CheckerboardMaterialProperty` to enable use of the checkerboard material with the entity API. * Added `PolygonHierarchy` to make defining polygons with holes clearer.