SceneTransitioner.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*global define*/
  2. define([
  3. '../Core/Cartesian3',
  4. '../Core/defaultValue',
  5. '../Core/defined',
  6. '../Core/destroyObject',
  7. '../Core/DeveloperError',
  8. '../Core/EasingFunction',
  9. '../Core/Ellipsoid',
  10. '../Core/Math',
  11. '../Core/Matrix4',
  12. '../Core/ScreenSpaceEventHandler',
  13. '../Core/ScreenSpaceEventType',
  14. './Camera',
  15. './OrthographicFrustum',
  16. './PerspectiveFrustum',
  17. './SceneMode'
  18. ], function(
  19. Cartesian3,
  20. defaultValue,
  21. defined,
  22. destroyObject,
  23. DeveloperError,
  24. EasingFunction,
  25. Ellipsoid,
  26. CesiumMath,
  27. Matrix4,
  28. ScreenSpaceEventHandler,
  29. ScreenSpaceEventType,
  30. Camera,
  31. OrthographicFrustum,
  32. PerspectiveFrustum,
  33. SceneMode) {
  34. "use strict";
  35. /**
  36. * @private
  37. */
  38. var SceneTransitioner = function(scene, ellipsoid) {
  39. //>>includeStart('debug', pragmas.debug);
  40. if (!defined(scene)) {
  41. throw new DeveloperError('scene is required.');
  42. }
  43. //>>includeEnd('debug');
  44. this._scene = scene;
  45. ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
  46. // Position camera and size frustum so the entire 2D map is visible
  47. var maxRadii = ellipsoid.maximumRadius;
  48. var position = new Cartesian3(0.0, 0.0, 2.0 * maxRadii);
  49. var direction = new Cartesian3();
  50. direction = Cartesian3.normalize(Cartesian3.negate(position, direction), direction);
  51. var up = Cartesian3.clone(Cartesian3.UNIT_Y);
  52. var position2D = Matrix4.multiplyByPoint(Camera.TRANSFORM_2D, position, new Cartesian3());
  53. var direction2D = Matrix4.multiplyByPointAsVector(Camera.TRANSFORM_2D, direction, new Cartesian3());
  54. var up2D = Matrix4.multiplyByPointAsVector(Camera.TRANSFORM_2D, up, new Cartesian3());
  55. var frustum = new OrthographicFrustum();
  56. frustum.right = maxRadii * Math.PI;
  57. frustum.left = -frustum.right;
  58. frustum.top = frustum.right * (scene.drawingBufferHeight / scene.drawingBufferWidth);
  59. frustum.bottom = -frustum.top;
  60. this._camera2D = {
  61. position : position,
  62. direction : direction,
  63. up : up,
  64. position2D : position2D,
  65. direction2D : direction2D,
  66. up2D : up2D,
  67. frustum : frustum
  68. };
  69. position = new Cartesian3(0.0, -1.0, 1.0);
  70. position = Cartesian3.multiplyByScalar(Cartesian3.normalize(position, position), 5.0 * maxRadii, position);
  71. direction = new Cartesian3();
  72. direction = Cartesian3.normalize(Cartesian3.subtract(Cartesian3.ZERO, position, direction), direction);
  73. var right = new Cartesian3();
  74. right = Cartesian3.normalize(Cartesian3.cross(direction, Cartesian3.UNIT_Z, right), right);
  75. up = new Cartesian3();
  76. up = Cartesian3.normalize(Cartesian3.cross(right, direction, up), up);
  77. position2D = Matrix4.multiplyByPoint(Camera.TRANSFORM_2D, position, new Cartesian3());
  78. direction2D = Matrix4.multiplyByPointAsVector(Camera.TRANSFORM_2D, direction, new Cartesian3());
  79. var right2D = Matrix4.multiplyByPointAsVector(Camera.TRANSFORM_2D, right, new Cartesian3());
  80. up2D = new Cartesian3();
  81. up2D = Cartesian3.normalize(Cartesian3.cross(right2D, direction2D, up2D), up2D);
  82. frustum = new PerspectiveFrustum();
  83. frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
  84. frustum.fov = CesiumMath.toRadians(60.0);
  85. this._cameraCV = {
  86. position : position,
  87. direction : direction,
  88. up : up,
  89. position2D : position2D,
  90. direction2D : direction2D,
  91. up2D : up2D,
  92. frustum : frustum
  93. };
  94. position = new Cartesian3();
  95. position = Cartesian3.multiplyByScalar(Cartesian3.normalize(new Cartesian3(0.0, -2.0, 1.0), position), 2.0 * maxRadii, position);
  96. direction = new Cartesian3();
  97. direction = Cartesian3.normalize(Cartesian3.subtract(Cartesian3.ZERO, position, direction), direction);
  98. right = new Cartesian3();
  99. right = Cartesian3.normalize(Cartesian3.cross(direction, Cartesian3.UNIT_Z, right), right);
  100. up = new Cartesian3();
  101. up = Cartesian3.normalize(Cartesian3.cross(right, direction, up), up);
  102. this._camera3D = {
  103. position : position,
  104. direction : direction,
  105. up : up,
  106. frustum : frustum
  107. };
  108. this._currentTweens = [];
  109. this._morphHandler = undefined;
  110. this._morphCancelled = false;
  111. this._completeMorph = undefined;
  112. };
  113. SceneTransitioner.prototype.completeMorph = function() {
  114. if (defined(this._completeMorph)) {
  115. this._completeMorph();
  116. }
  117. };
  118. SceneTransitioner.prototype.morphTo2D = function(duration, ellipsoid) {
  119. if (defined(this._completeMorph)) {
  120. this._completeMorph();
  121. }
  122. var scene = this._scene;
  123. this._previousMode = scene.mode;
  124. if (this._previousMode === SceneMode.SCENE2D || this._previousMode === SceneMode.MORPHING) {
  125. return;
  126. }
  127. this._scene.morphStart.raiseEvent(this, this._previousMode, SceneMode.SCENE2D, true);
  128. updateFrustums(this);
  129. scene.mode = SceneMode.MORPHING;
  130. createMorphHandler(this, complete2DCallback);
  131. if (this._previousMode === SceneMode.COLUMBUS_VIEW) {
  132. morphFromColumbusViewTo2D(this, duration, ellipsoid, complete2DCallback);
  133. } else {
  134. morphFrom3DTo2D(this, duration, ellipsoid, complete2DCallback);
  135. }
  136. if (duration === 0.0 && defined(this._completeMorph)) {
  137. this._completeMorph();
  138. }
  139. };
  140. SceneTransitioner.prototype.morphToColumbusView = function(duration, ellipsoid) {
  141. if (defined(this._completeMorph)) {
  142. this._completeMorph();
  143. }
  144. var scene = this._scene;
  145. this._previousMode = scene.mode;
  146. if (this._previousMode === SceneMode.COLUMBUS_VIEW || this._previousMode === SceneMode.MORPHING) {
  147. return;
  148. }
  149. this._scene.morphStart.raiseEvent(this, this._previousMode, SceneMode.COLUMBUS_VIEW, true);
  150. updateFrustums(this);
  151. scene.mode = SceneMode.MORPHING;
  152. createMorphHandler(this, completeColumbusViewCallback);
  153. if (this._previousMode === SceneMode.SCENE2D) {
  154. morphFrom2DToColumbusView(this, duration, ellipsoid, completeColumbusViewCallback);
  155. } else {
  156. morphFrom3DToColumbusView(this, duration, this._cameraCV, completeColumbusViewCallback);
  157. }
  158. if (duration === 0.0 && defined(this._completeMorph)) {
  159. this._completeMorph();
  160. }
  161. };
  162. SceneTransitioner.prototype.morphTo3D = function(duration, ellipsoid) {
  163. if (defined(this._completeMorph)) {
  164. this._completeMorph();
  165. }
  166. var scene = this._scene;
  167. this._previousMode = scene.mode;
  168. if (this._previousMode === SceneMode.SCENE3D || this._previousMode === SceneMode.MORPHING) {
  169. return;
  170. }
  171. this._scene.morphStart.raiseEvent(this, this._previousMode, SceneMode.SCENE3D, true);
  172. updateFrustums(this);
  173. scene.mode = SceneMode.MORPHING;
  174. createMorphHandler(this, complete3DCallback);
  175. if (this._previousMode === SceneMode.SCENE2D) {
  176. morphFrom2DTo3D(this, duration, ellipsoid, complete3DCallback);
  177. } else {
  178. morphFromColumbusViewTo3D(this, duration, ellipsoid, complete3DCallback);
  179. }
  180. if (duration === 0.0 && defined(this._completeMorph)) {
  181. this._completeMorph();
  182. }
  183. };
  184. /**
  185. * Returns true if this object was destroyed; otherwise, false.
  186. * <br /><br />
  187. * If this object was destroyed, it should not be used; calling any function other than
  188. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  189. *
  190. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  191. */
  192. SceneTransitioner.prototype.isDestroyed = function() {
  193. return false;
  194. };
  195. /**
  196. * Once an object is destroyed, it should not be used; calling any function other than
  197. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  198. * assign the return value (<code>undefined</code>) to the object as done in the example.
  199. *
  200. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  201. *
  202. * @example
  203. * transitioner = transitioner && transitioner.destroy();
  204. */
  205. SceneTransitioner.prototype.destroy = function() {
  206. destroyMorphHandler(this);
  207. return destroyObject(this);
  208. };
  209. function createMorphHandler(transitioner, completeMorphFunction) {
  210. if (transitioner._scene.completeMorphOnUserInput) {
  211. transitioner._morphHandler = new ScreenSpaceEventHandler(transitioner._scene.canvas);
  212. var completeMorph = function() {
  213. transitioner._morphCancelled = true;
  214. completeMorphFunction(transitioner);
  215. };
  216. transitioner._completeMorph = completeMorph;
  217. transitioner._morphHandler.setInputAction(completeMorph, ScreenSpaceEventType.LEFT_DOWN);
  218. transitioner._morphHandler.setInputAction(completeMorph, ScreenSpaceEventType.MIDDLE_DOWN);
  219. transitioner._morphHandler.setInputAction(completeMorph, ScreenSpaceEventType.RIGHT_DOWN);
  220. transitioner._morphHandler.setInputAction(completeMorph, ScreenSpaceEventType.WHEEL);
  221. }
  222. }
  223. function destroyMorphHandler(transitioner) {
  224. var tweens = transitioner._currentTweens;
  225. for ( var i = 0; i < tweens.length; ++i) {
  226. tweens[i].cancelTween();
  227. }
  228. transitioner._currentTweens.length = 0;
  229. transitioner._morphHandler = transitioner._morphHandler && transitioner._morphHandler.destroy();
  230. }
  231. function morphFromColumbusViewTo3D(transitioner, duration, ellipsoid, complete) {
  232. var scene = transitioner._scene;
  233. var camera = scene.camera;
  234. camera.setTransform(Matrix4.IDENTITY);
  235. var startPos = camera.position;
  236. var startDir = camera.direction;
  237. var startUp = camera.up;
  238. var endPos = Cartesian3.clone(transitioner._camera2D.position);
  239. var endDir = Cartesian3.clone(transitioner._camera2D.direction);
  240. var endUp = Cartesian3.clone(transitioner._camera2D.up);
  241. var update = function(value) {
  242. camera.position = columbusViewMorph(startPos, endPos, value.time);
  243. camera.direction = columbusViewMorph(startDir, endDir, value.time);
  244. camera.up = columbusViewMorph(startUp, endUp, value.time);
  245. camera.right = Cartesian3.cross(camera.direction, camera.up, camera.right);
  246. Cartesian3.normalize(camera.right, camera.right);
  247. };
  248. var tween = scene.tweens.add({
  249. duration : duration,
  250. easingFunction : EasingFunction.QUARTIC_OUT,
  251. startObject : {
  252. time : 0.0
  253. },
  254. stopObject : {
  255. time : 1.0
  256. },
  257. update : update
  258. });
  259. transitioner._currentTweens.push(tween);
  260. addMorphTimeAnimations(transitioner, scene, 0.0, 1.0, duration, complete);
  261. }
  262. function morphFrom2DTo3D(transitioner, duration, ellipsoid, complete) {
  263. duration *= 0.5;
  264. var camera = transitioner._scene.camera;
  265. camera.setTransform(Matrix4.IDENTITY);
  266. morphOrthographicToPerspective(transitioner, duration, ellipsoid, function() {
  267. camera.frustum = transitioner._cameraCV.frustum.clone();
  268. morphFromColumbusViewTo3D(transitioner, duration, ellipsoid, complete);
  269. });
  270. }
  271. function columbusViewMorph(startPosition, endPosition, time) {
  272. // Just linear for now.
  273. return Cartesian3.lerp(startPosition, endPosition, time, new Cartesian3());
  274. }
  275. function morphPerspectiveToOrthographic(transitioner, duration, complete) {
  276. var scene = transitioner._scene;
  277. var camera = scene.camera;
  278. var startPos = camera.position;
  279. var startFOV = camera.frustum.fov;
  280. var endFOV = CesiumMath.RADIANS_PER_DEGREE * 0.5;
  281. var d = Cartesian3.magnitude(startPos) * Math.tan(startFOV * 0.5);
  282. camera.frustum.far = d / Math.tan(endFOV * 0.5) + 10000000.0;
  283. var update = function(value) {
  284. camera.frustum.fov = CesiumMath.lerp(startFOV, endFOV, value.time);
  285. var distance = d / Math.tan(camera.frustum.fov * 0.5);
  286. var pos = new Cartesian3();
  287. camera.position = Cartesian3.multiplyByScalar(Cartesian3.normalize(camera.position, pos), distance, pos);
  288. };
  289. var tween = scene.tweens.add({
  290. duration : duration,
  291. easingFunction : EasingFunction.QUARTIC_OUT,
  292. startObject : {
  293. time : 0.0
  294. },
  295. stopObject : {
  296. time : 1.0
  297. },
  298. update : update,
  299. complete : function() {
  300. camera.frustum = transitioner._camera2D.frustum.clone();
  301. complete(transitioner);
  302. }
  303. });
  304. transitioner._currentTweens.push(tween);
  305. }
  306. function morphFromColumbusViewTo2D(transitioner, duration, ellipsoid, complete) {
  307. var scene = transitioner._scene;
  308. var camera = scene.camera;
  309. camera.setTransform(Matrix4.IDENTITY);
  310. var maxRadii = ellipsoid.maximumRadius;
  311. var startPos = Cartesian3.clone(camera.position);
  312. var startDir = Cartesian3.clone(camera.direction);
  313. var startUp = Cartesian3.clone(camera.up);
  314. var tanPhi = Math.tan(transitioner._cameraCV.frustum.fovy * 0.5);
  315. var tanTheta = transitioner._cameraCV.frustum.aspectRatio * tanPhi;
  316. var d = (maxRadii * Math.PI) / tanTheta;
  317. var endPos = new Cartesian3();
  318. endPos = Cartesian3.multiplyByScalar(Cartesian3.normalize(transitioner._camera2D.position, endPos), d, endPos);
  319. var endDir = Cartesian3.clone(transitioner._camera2D.direction);
  320. var endUp = Cartesian3.clone(transitioner._camera2D.up);
  321. var updateCV = function(value) {
  322. camera.position = columbusViewMorph(startPos, endPos, value.time);
  323. camera.direction = columbusViewMorph(startDir, endDir, value.time);
  324. camera.up = columbusViewMorph(startUp, endUp, value.time);
  325. camera.right = Cartesian3.cross(camera.direction, camera.up, camera.right);
  326. Cartesian3.normalize(camera.right, camera.right);
  327. };
  328. duration *= 0.5;
  329. var tween = scene.tweens.add({
  330. duration : duration,
  331. easingFunction : EasingFunction.QUARTIC_OUT,
  332. startObject : {
  333. time : 0.0
  334. },
  335. stopObject : {
  336. time : 1.0
  337. },
  338. update : updateCV,
  339. complete : function() {
  340. morphPerspectiveToOrthographic(transitioner, duration, complete);
  341. }
  342. });
  343. transitioner._currentTweens.push(tween);
  344. }
  345. function morphFrom3DTo2D(transitioner, duration, ellipsoid, complete) {
  346. duration *= 0.5;
  347. var maxRadii = ellipsoid.maximumRadius;
  348. var tanPhi = Math.tan(transitioner._camera3D.frustum.fovy * 0.5);
  349. var tanTheta = transitioner._camera3D.frustum.aspectRatio * tanPhi;
  350. var d = (maxRadii * Math.PI) / tanTheta;
  351. var camera3DTo2D = {};
  352. var pos2D = new Cartesian3();
  353. camera3DTo2D.position2D = Cartesian3.multiplyByScalar(Cartesian3.normalize(transitioner._camera2D.position2D, pos2D), d, pos2D);
  354. camera3DTo2D.direction2D = Cartesian3.clone(transitioner._camera2D.direction2D);
  355. camera3DTo2D.up2D = Cartesian3.clone(transitioner._camera2D.up2D);
  356. var completeCallback = function() {
  357. morphPerspectiveToOrthographic(transitioner, duration, complete);
  358. };
  359. morphFrom3DToColumbusView(transitioner, duration, camera3DTo2D, completeCallback);
  360. }
  361. function morphOrthographicToPerspective(transitioner, duration, ellipsoid, complete) {
  362. var scene = transitioner._scene;
  363. var camera = scene.camera;
  364. var maxRadii = ellipsoid.maximumRadius;
  365. var tanPhi = Math.tan(transitioner._cameraCV.frustum.fovy * 0.5);
  366. var tanTheta = transitioner._cameraCV.frustum.aspectRatio * tanPhi;
  367. var d = (maxRadii * Math.PI) / tanTheta;
  368. var endPos2D = new Cartesian3();
  369. endPos2D = Cartesian3.multiplyByScalar(Cartesian3.normalize(transitioner._camera2D.position, endPos2D), d, endPos2D);
  370. var top = camera.frustum.top;
  371. var bottom = camera.frustum.bottom;
  372. var right = camera.frustum.right;
  373. var left = camera.frustum.left;
  374. var frustum2D = transitioner._camera2D.frustum;
  375. var frustumCV = transitioner._cameraCV.frustum;
  376. var startPos = Cartesian3.clone(camera.position);
  377. var update2D = function(value) {
  378. camera.position = columbusViewMorph(startPos, endPos2D, value.time);
  379. camera.frustum.top = CesiumMath.lerp(top, frustum2D.top, value.time);
  380. camera.frustum.bottom = CesiumMath.lerp(bottom, frustum2D.bottom, value.time);
  381. camera.frustum.right = CesiumMath.lerp(right, frustum2D.right, value.time);
  382. camera.frustum.left = CesiumMath.lerp(left, frustum2D.left, value.time);
  383. };
  384. var startTime = (right - left) / (2.0 * maxRadii * Math.PI);
  385. var endTime = 1.0;
  386. if (startTime > endTime) {
  387. startTime = 0.0;
  388. }
  389. var partialDuration = (endTime - startTime) * duration;
  390. if (partialDuration < CesiumMath.EPSILON6) {
  391. if (!Cartesian3.equalsEpsilon(startPos, endPos2D, CesiumMath.EPSILON6)) {
  392. partialDuration = duration;
  393. startTime = 0.0;
  394. endTime = 1.0;
  395. } else {
  396. // If the camera and frustum are already in position for the switch to
  397. // a perspective projection, nothing needs to be animated.
  398. camera.position = endPos2D;
  399. camera.frustum = frustumCV.clone();
  400. complete(transitioner);
  401. return;
  402. }
  403. }
  404. var tween = scene.tweens.add({
  405. easingFunction : EasingFunction.QUARTIC_OUT,
  406. duration : partialDuration,
  407. startObject : {
  408. time : startTime
  409. },
  410. stopObject : {
  411. time : endTime
  412. },
  413. update : update2D,
  414. complete : function() {
  415. camera.frustum = frustumCV.clone();
  416. complete(transitioner);
  417. }
  418. });
  419. transitioner._currentTweens.push(tween);
  420. }
  421. function morphFrom2DToColumbusView(transitioner, duration, ellipsoid, complete) {
  422. var scene = transitioner._scene;
  423. var camera = scene.camera;
  424. camera.setTransform(Matrix4.IDENTITY);
  425. duration *= 0.5;
  426. var completeFrustumChange = function() {
  427. var startPos = Cartesian3.clone(camera.position);
  428. var startDir = Cartesian3.clone(camera.direction);
  429. var startUp = Cartesian3.clone(camera.up);
  430. var endPos = Cartesian3.clone(transitioner._cameraCV.position);
  431. var endDir = Cartesian3.clone(transitioner._cameraCV.direction);
  432. var endUp = Cartesian3.clone(transitioner._cameraCV.up);
  433. var updateCV = function(value) {
  434. camera.position = columbusViewMorph(startPos, endPos, value.time);
  435. camera.direction = columbusViewMorph(startDir, endDir, value.time);
  436. camera.up = columbusViewMorph(startUp, endUp, value.time);
  437. camera.right = Cartesian3.cross(camera.direction, camera.up, camera.right);
  438. Cartesian3.normalize(camera.right, camera.right);
  439. };
  440. var tween = scene.tweens.add({
  441. duration : duration,
  442. easingFunction : EasingFunction.QUARTIC_OUT,
  443. startObject : {
  444. time : 0.0
  445. },
  446. stopObject : {
  447. time : 1.0
  448. },
  449. update : updateCV,
  450. complete : function() {
  451. complete(transitioner);
  452. }
  453. });
  454. transitioner._currentTweens.push(tween);
  455. };
  456. morphOrthographicToPerspective(transitioner, duration, ellipsoid, completeFrustumChange);
  457. }
  458. function morphFrom3DToColumbusView(transitioner, duration, endCamera, complete) {
  459. var scene = transitioner._scene;
  460. var camera = scene.camera;
  461. camera.setTransform(Matrix4.IDENTITY);
  462. var startPos = Cartesian3.clone(camera.position);
  463. var startDir = Cartesian3.clone(camera.direction);
  464. var startUp = Cartesian3.clone(camera.up);
  465. var endPos = Cartesian3.clone(endCamera.position2D);
  466. var endDir = Cartesian3.clone(endCamera.direction2D);
  467. var endUp = Cartesian3.clone(endCamera.up2D);
  468. var update = function(value) {
  469. camera.position = columbusViewMorph(startPos, endPos, value.time);
  470. camera.direction = columbusViewMorph(startDir, endDir, value.time);
  471. camera.up = columbusViewMorph(startUp, endUp, value.time);
  472. camera.right = Cartesian3.cross(camera.direction, camera.up, camera.right);
  473. Cartesian3.normalize(camera.right, camera.right);
  474. };
  475. var tween = scene.tweens.add({
  476. duration : duration,
  477. easingFunction : EasingFunction.QUARTIC_OUT,
  478. startObject : {
  479. time : 0.0
  480. },
  481. stopObject : {
  482. time : 1.0
  483. },
  484. update : update,
  485. complete : function() {
  486. camera.position = endPos;
  487. camera.direction = endDir;
  488. camera.up = endUp;
  489. camera.right = Cartesian3.cross(endDir, endUp, camera.right);
  490. Cartesian3.normalize(camera.right, camera.right);
  491. }
  492. });
  493. transitioner._currentTweens.push(tween);
  494. addMorphTimeAnimations(transitioner, scene, 1.0, 0.0, duration, complete);
  495. }
  496. function addMorphTimeAnimations(transitioner, scene, start, stop, duration, complete) {
  497. // Later, this will be linear and each object will adjust, if desired, in its vertex shader.
  498. var options = {
  499. object : scene,
  500. property : 'morphTime',
  501. startValue : start,
  502. stopValue : stop,
  503. duration : duration,
  504. easingFunction : EasingFunction.QUARTIC_OUT
  505. };
  506. if (defined(complete)) {
  507. options.complete = function() {
  508. complete(transitioner);
  509. };
  510. }
  511. var tween = scene.tweens.addProperty(options);
  512. transitioner._currentTweens.push(tween);
  513. }
  514. function updateFrustums(transitioner) {
  515. var scene = transitioner._scene;
  516. var ratio = scene.drawingBufferHeight / scene.drawingBufferWidth;
  517. var frustum = transitioner._camera2D.frustum;
  518. frustum.top = frustum.right * ratio;
  519. frustum.bottom = -frustum.top;
  520. ratio = 1.0 / ratio;
  521. frustum = transitioner._cameraCV.frustum;
  522. frustum.aspectRatio = ratio;
  523. frustum = transitioner._camera3D.frustum;
  524. frustum.aspectRatio = ratio;
  525. var camera = scene.camera;
  526. switch (scene.mode) {
  527. case SceneMode.SCENE3D:
  528. camera.frustum = transitioner._camera3D.frustum.clone();
  529. break;
  530. case SceneMode.COLUMBUS_VIEW:
  531. camera.frustum = transitioner._cameraCV.frustum.clone();
  532. break;
  533. case SceneMode.SCENE2D:
  534. camera.frustum = transitioner._camera2D.frustum.clone();
  535. break;
  536. }
  537. }
  538. function complete3DCallback(transitioner) {
  539. var scene = transitioner._scene;
  540. scene.mode = SceneMode.SCENE3D;
  541. scene.morphTime = SceneMode.getMorphTime(SceneMode.SCENE3D);
  542. destroyMorphHandler(transitioner);
  543. updateFrustums(transitioner);
  544. if (transitioner._previousMode !== SceneMode.MORPHING || transitioner._morphCancelled) {
  545. transitioner._morphCancelled = false;
  546. // TODO: Match incoming columbus-view or 2D position
  547. var camera = scene.camera;
  548. camera.position = Cartesian3.clone(transitioner._camera3D.position);
  549. camera.direction = Cartesian3.clone(transitioner._camera3D.direction);
  550. camera.up = Cartesian3.clone(transitioner._camera3D.up);
  551. camera.right = Cartesian3.cross(camera.direction, camera.up, camera.right);
  552. Cartesian3.normalize(camera.right, camera.right);
  553. }
  554. var wasMorphing = defined(transitioner._completeMorph);
  555. transitioner._completeMorph = undefined;
  556. transitioner._scene.morphComplete.raiseEvent(transitioner, transitioner._previousMode, SceneMode.SCENE3D, wasMorphing);
  557. }
  558. function complete2DCallback(transitioner) {
  559. var scene = transitioner._scene;
  560. scene.mode = SceneMode.SCENE2D;
  561. scene.morphTime = SceneMode.getMorphTime(SceneMode.SCENE2D);
  562. destroyMorphHandler(transitioner);
  563. updateFrustums(transitioner);
  564. // TODO: Match incoming columbus-view or 3D position
  565. var camera = scene.camera;
  566. Cartesian3.clone(transitioner._camera2D.position, camera.position);
  567. Cartesian3.clone(transitioner._camera2D.direction, camera.direction);
  568. Cartesian3.clone(transitioner._camera2D.up, camera.up);
  569. Cartesian3.cross(camera.direction, camera.up, camera.right);
  570. Cartesian3.normalize(camera.right, camera.right);
  571. var wasMorphing = defined(transitioner._completeMorph);
  572. transitioner._completeMorph = undefined;
  573. transitioner._scene.morphComplete.raiseEvent(transitioner, transitioner._previousMode, SceneMode.SCENE2D, wasMorphing);
  574. }
  575. function completeColumbusViewCallback(transitioner) {
  576. var scene = transitioner._scene;
  577. scene.mode = SceneMode.COLUMBUS_VIEW;
  578. scene.morphTime = SceneMode.getMorphTime(SceneMode.COLUMBUS_VIEW);
  579. destroyMorphHandler(transitioner);
  580. updateFrustums(transitioner);
  581. if (transitioner._previousModeMode !== SceneMode.MORPHING || transitioner._morphCancelled) {
  582. transitioner._morphCancelled = false;
  583. // TODO: Match incoming 2D or 3D position
  584. var camera = scene.camera;
  585. Cartesian3.clone(transitioner._cameraCV.position, camera.position);
  586. Cartesian3.clone(transitioner._cameraCV.direction, camera.direction);
  587. Cartesian3.clone(transitioner._cameraCV.up, camera.up);
  588. Cartesian3.cross(camera.direction, camera.up, camera.right);
  589. Cartesian3.normalize(camera.right, camera.right);
  590. }
  591. var wasMorphing = defined(transitioner._completeMorph);
  592. transitioner._completeMorph = undefined;
  593. transitioner._scene.morphComplete.raiseEvent(transitioner, transitioner._previousMode, SceneMode.COLUMBUS_VIEW, wasMorphing);
  594. }
  595. return SceneTransitioner;
  596. });