123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /*global define*/
- define([
- '../Core/Cartesian3',
- '../Core/defaultValue',
- '../Core/defined',
- '../Core/defineProperties',
- '../Core/DeveloperError',
- '../Core/Ellipsoid',
- '../Core/JulianDate',
- '../Core/Math',
- '../Core/Matrix3',
- '../Core/Transforms',
- '../Scene/SceneMode'
- ], function(
- Cartesian3,
- defaultValue,
- defined,
- defineProperties,
- DeveloperError,
- Ellipsoid,
- JulianDate,
- CesiumMath,
- Matrix3,
- Transforms,
- SceneMode) {
- "use strict";
- var updateTransformMatrix3Scratch1 = new Matrix3();
- var updateTransformMatrix3Scratch2 = new Matrix3();
- var updateTransformMatrix3Scratch3 = new Matrix3();
- var updateTransformCartesian3Scratch1 = new Cartesian3();
- var updateTransformCartesian3Scratch2 = new Cartesian3();
- var updateTransformCartesian3Scratch3 = new Cartesian3();
- var updateTransformCartesian3Scratch4 = new Cartesian3();
- var updateTransformCartesian3Scratch5 = new Cartesian3();
- var updateTransformCartesian3Scratch6 = new Cartesian3();
- var deltaTime = new JulianDate();
- var northUpAxisFactor = 1.25; // times ellipsoid's maximum radius
- function updateTransform(that, camera, updateLookAt, positionProperty, time, ellipsoid) {
- var cartesian = positionProperty.getValue(time, that._lastCartesian);
- if (defined(cartesian)) {
- var hasBasis = false;
- var xBasis;
- var yBasis;
- var zBasis;
- // The time delta was determined based on how fast satellites move compared to vehicles near the surface.
- // Slower moving vehicles will most likely default to east-north-up, while faster ones will be VVLH.
- deltaTime = JulianDate.addSeconds(time, 0.001, deltaTime);
- var deltaCartesian = positionProperty.getValue(deltaTime, updateTransformCartesian3Scratch1);
- if (defined(deltaCartesian)) {
- var toInertial = Transforms.computeFixedToIcrfMatrix(time, updateTransformMatrix3Scratch1);
- var toInertialDelta = Transforms.computeFixedToIcrfMatrix(deltaTime, updateTransformMatrix3Scratch2);
- var toFixed;
- if (!defined(toInertial) || !defined(toInertialDelta)) {
- toFixed = Transforms.computeTemeToPseudoFixedMatrix(time, updateTransformMatrix3Scratch3);
- toInertial = Matrix3.transpose(toFixed, updateTransformMatrix3Scratch1);
- toInertialDelta = Transforms.computeTemeToPseudoFixedMatrix(deltaTime, updateTransformMatrix3Scratch2);
- Matrix3.transpose(toInertialDelta, toInertialDelta);
- } else {
- toFixed = Matrix3.transpose(toInertial, updateTransformMatrix3Scratch3);
- }
- var inertialCartesian = Matrix3.multiplyByVector(toInertial, cartesian, updateTransformCartesian3Scratch5);
- var inertialDeltaCartesian = Matrix3.multiplyByVector(toInertialDelta, deltaCartesian, updateTransformCartesian3Scratch6);
- Cartesian3.subtract(inertialCartesian, inertialDeltaCartesian, updateTransformCartesian3Scratch4);
- var inertialVelocity = Cartesian3.magnitude(updateTransformCartesian3Scratch4) * 1000.0; // meters/sec
- // http://en.wikipedia.org/wiki/Standard_gravitational_parameter
- // Consider adding this to Cesium.Ellipsoid?
- var mu = 3.986004418e14; // m^3 / sec^2
- var semiMajorAxis = -mu / (inertialVelocity * inertialVelocity - (2 * mu / Cartesian3.magnitude(inertialCartesian)));
- if (semiMajorAxis < 0 || semiMajorAxis > northUpAxisFactor * ellipsoid.maximumRadius) {
- // North-up viewing from deep space.
- // X along the nadir
- xBasis = updateTransformCartesian3Scratch2;
- Cartesian3.normalize(cartesian, xBasis);
- Cartesian3.negate(xBasis, xBasis);
- // Z is North
- zBasis = Cartesian3.clone(Cartesian3.UNIT_Z, updateTransformCartesian3Scratch3);
- // Y is along the cross of z and x (right handed basis / in the direction of motion)
- yBasis = Cartesian3.cross(zBasis, xBasis, updateTransformCartesian3Scratch1);
- if (Cartesian3.magnitude(yBasis) > CesiumMath.EPSILON7) {
- Cartesian3.normalize(xBasis, xBasis);
- Cartesian3.normalize(yBasis, yBasis);
- zBasis = Cartesian3.cross(xBasis, yBasis, updateTransformCartesian3Scratch3);
- Cartesian3.normalize(zBasis, zBasis);
- hasBasis = true;
- }
- } else if (!Cartesian3.equalsEpsilon(cartesian, deltaCartesian, CesiumMath.EPSILON7)) {
- // Approximation of VVLH (Vehicle Velocity Local Horizontal) with the Z-axis flipped.
- // Z along the position
- zBasis = updateTransformCartesian3Scratch2;
- Cartesian3.normalize(inertialCartesian, zBasis);
- Cartesian3.normalize(inertialDeltaCartesian, inertialDeltaCartesian);
- // Y is along the angular momentum vector (e.g. "orbit normal")
- yBasis = Cartesian3.cross(zBasis, inertialDeltaCartesian, updateTransformCartesian3Scratch3);
- if (!Cartesian3.equalsEpsilon(yBasis, Cartesian3.ZERO, CesiumMath.EPSILON7)) {
- // X is along the cross of y and z (right handed basis / in the direction of motion)
- xBasis = Cartesian3.cross(yBasis, zBasis, updateTransformCartesian3Scratch1);
- Matrix3.multiplyByVector(toFixed, xBasis, xBasis);
- Matrix3.multiplyByVector(toFixed, yBasis, yBasis);
- Matrix3.multiplyByVector(toFixed, zBasis, zBasis);
- Cartesian3.normalize(xBasis, xBasis);
- Cartesian3.normalize(yBasis, yBasis);
- Cartesian3.normalize(zBasis, zBasis);
- hasBasis = true;
- }
- }
- }
- if (hasBasis) {
- var transform = camera.transform;
- transform[0] = xBasis.x;
- transform[1] = xBasis.y;
- transform[2] = xBasis.z;
- transform[3] = 0.0;
- transform[4] = yBasis.x;
- transform[5] = yBasis.y;
- transform[6] = yBasis.z;
- transform[7] = 0.0;
- transform[8] = zBasis.x;
- transform[9] = zBasis.y;
- transform[10] = zBasis.z;
- transform[11] = 0.0;
- transform[12] = cartesian.x;
- transform[13] = cartesian.y;
- transform[14] = cartesian.z;
- transform[15] = 0.0;
- } else {
- // Stationary or slow-moving, low-altitude objects use East-North-Up.
- Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, camera.transform);
- }
- }
- if (updateLookAt) {
- if (that.scene.mode === SceneMode.SCENE2D) {
- camera.lookAt(that._offset2D, Cartesian3.ZERO, that._up2D);
- } else {
- camera.lookAt(that._offset3D, Cartesian3.ZERO, that._up3D);
- }
- }
- }
- var offset3DCrossScratch = new Cartesian3();
- /**
- * A utility object for tracking an entity with the camera.
- * @alias EntityView
- * @constructor
- *
- * @param {Entity} entity The entity to track with the camera.
- * @param {Scene} scene The scene to use.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use for orienting the camera.
- */
- var EntityView = function(entity, scene, ellipsoid) {
- /**
- * The entity to track with the camera.
- * @type {Entity}
- */
- this.entity = entity;
- /**
- * The scene in which to track the object.
- * @type {Scene}
- */
- this.scene = scene;
- /**
- * The ellipsoid to use for orienting the camera.
- * @type {Ellipsoid}
- */
- this.ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
- //Shadow copies of the objects so we can detect changes.
- this._lastEntity = undefined;
- this._mode = undefined;
- //Re-usable objects to be used for retrieving position.
- this._lastCartesian = new Cartesian3();
- this._offset3D = new Cartesian3();
- this._up3D = new Cartesian3();
- this._offset2D = new Cartesian3();
- this._up2D = new Cartesian3();
- };
- // STATIC properties defined here, not per-instance.
- defineProperties(EntityView, {
- /**
- * Gets or sets a camera offset that will be used to
- * initialize subsequent EntityViews.
- * @memberof EntityView
- * @type {Cartesian3}
- */
- defaultOffset3D : {
- get : function() {
- return this._defaultOffset3D;
- },
- set : function(vector) {
- this._defaultOffset3D = Cartesian3.clone(vector, new Cartesian3());
- this._defaultUp3D = Cartesian3.cross(this._defaultOffset3D, Cartesian3.cross(Cartesian3.UNIT_Z,
- this._defaultOffset3D, offset3DCrossScratch), new Cartesian3());
- Cartesian3.normalize(this._defaultUp3D, this._defaultUp3D);
- this._defaultOffset2D = new Cartesian3(0.0, 0.0, Cartesian3.magnitude(this._defaultOffset3D));
- this._defaultUp2D = Cartesian3.clone(Cartesian3.UNIT_Y);
- }
- }
- });
- // Initialize the static property.
- EntityView.defaultOffset3D = new Cartesian3(-14000, 3500, 3500);
- /**
- * Should be called each animation frame to update the camera
- * to the latest settings.
- * @param {JulianDate} time The current animation time.
- *
- */
- EntityView.prototype.update = function(time) {
- var scene = this.scene;
- var entity = this.entity;
- var ellipsoid = this.ellipsoid;
- //>>includeStart('debug', pragmas.debug);
- if (!defined(time)) {
- throw new DeveloperError('time is required.');
- }
- if (!defined(scene)) {
- throw new DeveloperError('EntityView.scene is required.');
- }
- if (!defined(entity)) {
- throw new DeveloperError('EntityView.entity is required.');
- }
- if (!defined(ellipsoid)) {
- throw new DeveloperError('EntityView.ellipsoid is required.');
- }
- if (!defined(entity.position)) {
- throw new DeveloperError('entity.position is required.');
- }
- //>>includeEnd('debug');
- var positionProperty = entity.position;
- var objectChanged = entity !== this._lastEntity;
- var sceneModeChanged = scene.mode !== this._mode && scene.mode !== SceneMode.MORPHING;
- var offset3D = this._offset3D;
- var up3D = this._up3D;
- var offset2D = this._offset2D;
- var up2D = this._up2D;
- var camera = scene.camera;
- if (objectChanged) {
- var viewFromProperty = entity.viewFrom;
- if (!defined(viewFromProperty) || !defined(viewFromProperty.getValue(time, offset3D))) {
- Cartesian3.clone(EntityView._defaultOffset2D, offset2D);
- Cartesian3.clone(EntityView._defaultUp2D, up2D);
- Cartesian3.clone(EntityView._defaultOffset3D, offset3D);
- Cartesian3.clone(EntityView._defaultUp3D, up3D);
- } else {
- Cartesian3.cross(Cartesian3.UNIT_Z, offset3D, up3D);
- Cartesian3.cross(offset3D, up3D, up3D);
- Cartesian3.normalize(up3D, up3D);
- var mag = Cartesian3.magnitude(offset3D);
- Cartesian3.fromElements(0.0, 0.0, mag, offset2D);
- Cartesian3.clone(this._defaultUp2D, up2D);
- }
- } else if (!sceneModeChanged && scene.mode !== SceneMode.MORPHING) {
- if (this._mode === SceneMode.SCENE2D) {
- var distance = Math.max(camera.frustum.right - camera.frustum.left, camera.frustum.top - camera.frustum.bottom);
- Cartesian3.fromElements(0.0, 0.0, distance, offset2D);
- Cartesian3.clone(camera.up, up2D);
- } else if (this._mode === SceneMode.SCENE3D || this._mode === SceneMode.COLUMBUS_VIEW) {
- Cartesian3.clone(camera.position, offset3D);
- Cartesian3.clone(camera.up, up3D);
- }
- }
- var updateLookAt = objectChanged || sceneModeChanged;
- this._lastEntity = entity;
- this._mode = scene.mode !== SceneMode.MORPHING ? scene.mode : this._mode;
- if (scene.mode !== SceneMode.MORPHING) {
- updateTransform(this, camera, updateLookAt, positionProperty, time, ellipsoid);
- }
- };
- return EntityView;
- });
|