/home/lindsay/xeolabs/xeogl-next/xeogl/src/animation/cameraFlightAnimation.js
API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/animation/cameraFlightAnimation.js

  1. /**
  2. A **CameraFlightAnimation** jumps or flies the {{#crossLink "Scene"}}Scene's{{/crossLink}} {{#crossLink "Camera"}}{{/crossLink}} to look at a given target.
  3.  
  4. <a href="../../examples/#animation_camera_flight"><img src="http://i.giphy.com/3o7TKP0jN800EQ99EQ.gif"></img></a>
  5.  
  6. * TODO: Document behaviour for ortho projection
  7. * TODO: Update docs for camera refactor, where ortho and perspective components will always be present on camera
  8.  
  9. ## Overview
  10.  
  11. * Can be made to either fly or jump to its target.
  12. * While busy flying to a target, it can be stopped, or redirected to fly to a different target.
  13.  
  14. A CameraFlightAnimation's target can be:
  15.  
  16. * specific ````eye````, ````look```` and ````up```` positions,
  17. * an axis-aligned World-space bounding box (AABB), or
  18. * an instance or ID of any {{#crossLink "Component"}}{{/crossLink}} subtype that provides a World-space AABB.
  19.  
  20. You can configure its {{#crossLink "CameraFlightAnimation/fit:property"}}{{/crossLink}}
  21. and {{#crossLink "CameraFlightAnimation/fitFOV:property"}}{{/crossLink}} properties to make it stop at the point where the target
  22. occupies a certain amount of the field-of-view.
  23.  
  24. ## Examples
  25.  
  26. * [Flying to random meshes](../../examples/#animation_camera_flight)
  27.  
  28. ## Flying to a Mesh
  29.  
  30. Flying to a {{#crossLink "Mesh"}}{{/crossLink}}:
  31.  
  32. ````Javascript
  33. // Create a CameraFlightAnimation that takes one second to fly
  34. // the default Scene's Camera to each specified target
  35. var cameraFlight = new xeogl.CameraFlightAnimation({
  36. fit: true, // Default
  37. fitFOV: 45, // Default, degrees
  38. duration: 1 // Default, seconds
  39. }, function() {
  40. // Arrived
  41. });
  42.  
  43. // Create a Mesh, which gets all the default components
  44. var mesh = new Mesh();
  45.  
  46. // Fly to the Mesh's World-space AABB
  47. cameraFlight.flyTo(mesh);
  48. ````
  49. ## Flying to a position
  50.  
  51. Flying the CameraFlightAnimation from the previous example to specified eye, look and up positions:
  52.  
  53. ````Javascript
  54. cameraFlight.flyTo({
  55. eye: [-5,-5,-5],
  56. look: [0,0,0]
  57. up: [0,1,0],
  58. duration: 1 // Default, seconds
  59. }, function() {
  60. // Arrived
  61. });
  62. ````
  63.  
  64. ## Flying to an AABB
  65.  
  66. Flying the CameraFlightAnimation from the previous two examples explicitly to the {{#crossLink "Boundary3D"}}Boundary3D's{{/crossLink}}
  67. axis-aligned bounding box:
  68.  
  69. ````Javascript
  70. cameraFlight.flyTo(mesh.aabb);
  71. ````
  72.  
  73. @class CameraFlightAnimation
  74. @module xeogl
  75. @submodule animation
  76. @constructor
  77. @param [owner] {Component} Owner component. When destroyed, the owner will destroy this component as well. Creates this component within the default {{#crossLink "Scene"}}{{/crossLink}} when omitted.
  78. @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}}, generated automatically when omitted.
  79. @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this CameraFlightAnimation.
  80. @param [cfg.fit=true] {Boolean} When true, will ensure that when this CameraFlightAnimation has flown or jumped to a boundary
  81. it will adjust the distance between the {{#crossLink "Camera"}}{{/crossLink}}'s {{#crossLink "Lookat/eye:property"}}eye{{/crossLink}}
  82. and {{#crossLink "Lookat/look:property"}}{{/crossLink}} position so as to ensure that the target boundary is filling the view volume.
  83. @param [cfg.fitFOV=45] {Number} How much field-of-view, in degrees, that a target boundary should
  84. fill the canvas when fitting the {{#crossLink "Camera"}}Camera{{/crossLink}} to the target boundary. Only applies when the {{#crossLink "Camera"}}Camera{{/crossLink}}'s active projection is a{{#crossLink "Perspective"}}{{/crossLink}}.
  85. @param [cfg.trail] {Boolean} When true, will cause this CameraFlightAnimation to point the {{#crossLink "Camera"}}{{/crossLink}} in the direction that it is travelling.
  86. @param [cfg.duration=1] {Number} Flight duration, in seconds, when calling {{#crossLink "CameraFlightAnimation/flyTo:method"}}CameraFlightAnimation#flyTo(){{/crossLink}}.
  87. @extends Component
  88. */
  89.  
  90. import {math} from '../math/math.js';
  91. import {utils} from '../utils.js';
  92. import {tasks} from '../tasks.js';
  93. import {Component} from '../component.js';
  94. import {Mesh} from '../objects/mesh.js';
  95. import {AABBGeometry} from '../geometry/aabbGeometry.js';
  96. import {PhongMaterial} from '../materials/phongMaterial.js';
  97. import {componentClasses} from "./../componentClasses.js";
  98.  
  99. const type = "xeogl.CameraFlightAnimation";
  100.  
  101. const tempVec3 = math.vec3();
  102. const newLook = math.vec3();
  103. const newEye = math.vec3();
  104. const newUp = math.vec3();
  105. const newLookEyeVec = math.vec3();
  106. const lookEyeVec = math.vec3();
  107.  
  108. class CameraFlightAnimation extends Component {
  109.  
  110. /**
  111. JavaScript class name for this Component.
  112.  
  113. For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
  114.  
  115. @property type
  116. @type String
  117. @final
  118. */
  119. get type() {
  120. return type;
  121. }
  122.  
  123. init(cfg) {
  124.  
  125. super.init(cfg);
  126.  
  127. this._aabbHelper = new Mesh(this, { // Shows a wireframe box for target AABBs
  128. geometry: new AABBGeometry(this),
  129. material: new PhongMaterial(this, {
  130. diffuse: [0, 0, 0],
  131. ambient: [0, 0, 0],
  132. specular: [0, 0, 0],
  133. emissive: [0.5, 1.0, 0.5],
  134. lineWidth: 2
  135. }),
  136. visible: false,
  137. collidable: false
  138. });
  139.  
  140. this._look1 = math.vec3();
  141. this._eye1 = math.vec3();
  142. this._up1 = math.vec3();
  143. this._look2 = math.vec3();
  144. this._eye2 = math.vec3();
  145. this._up2 = math.vec3();
  146. this._orthoScale1 = 1;
  147. this._orthoScale2 = 1;
  148. this._flying = false;
  149. this._flyEyeLookUp = false;
  150. this._flyingEye = false;
  151. this._flyingLook = false;
  152. this._callback = null;
  153. this._callbackScope = null;
  154. this._time1 = null;
  155. this._time2 = null;
  156. this.easing = cfg.easing !== false;
  157.  
  158. this.duration = cfg.duration;
  159. this.fit = cfg.fit;
  160. this.fitFOV = cfg.fitFOV;
  161. this.trail = cfg.trail;
  162. }
  163.  
  164. /**
  165. * Begins flying the {{#crossLink "Camera"}}{{/crossLink}}'s {{#crossLink "Camera"}}{{/crossLink}} to the given target.
  166. *
  167. * * When the target is a boundary, the {{#crossLink "Camera"}}{{/crossLink}} will fly towards the target
  168. * and stop when the target fills most of the canvas.
  169. * * When the target is an explicit {{#crossLink "Camera"}}{{/crossLink}} position, given as ````eye````, ````look```` and ````up````
  170. * vectors, then this CameraFlightAnimation will interpolate the {{#crossLink "Camera"}}{{/crossLink}} to that target and stop there.
  171. * @method flyTo
  172. * @param [params=scene] {*|Component} Either a parameters object or a {{#crossLink "Component"}}{{/crossLink}} subtype that has an AABB.
  173. * @param[params.arc=0] {Number} Factor in range [0..1] indicating how much the
  174. * {{#crossLink "Lookat/eye:property"}}Camera's eye{{/crossLink}} position will
  175. * swing away from its {{#crossLink "Lookat/eye:property"}}look{{/crossLink}} position as it flies to the target.
  176. * @param [params.component] {Number|String|Component} ID or instance of a component to fly to. Defaults to the entire {{#crossLink "Scene"}}{{/crossLink}}.
  177. * @param [params.aabb] {*} World-space axis-aligned bounding box (AABB) target to fly to.
  178. * @param [params.eye] {Float32Array} Position to fly the eye position to.
  179. * @param [params.look] {Float32Array} Position to fly the look position to.
  180. * @param [params.up] {Float32Array} Position to fly the up vector to.
  181. * @param [params.fit=true] {Boolean} Whether to fit the target to the view volume. Overrides {{#crossLink "CameraFlightAnimation/fit:property"}}{{/crossLink}}.
  182. * @param [params.fitFOV] {Number} How much of field-of-view, in degrees, that a target {{#crossLink "Object"}}{{/crossLink}} or its AABB should
  183. * fill the canvas on arrival. Overrides {{#crossLink "CameraFlightAnimation/fitFOV:property"}}{{/crossLink}}.
  184. * @param [params.duration] {Number} Flight duration in seconds. Overrides {{#crossLink "CameraFlightAnimation/duration:property"}}{{/crossLink}}.
  185. * @param [params.orthoScale] {Number} TODO: document this
  186. * @param [callback] {Function} Callback fired on arrival
  187. * @param [scope] {Object} Optional scope for callback
  188. */
  189. flyTo(params, callback, scope) {
  190.  
  191. params = params || this.scene;
  192.  
  193. if (this._flying) {
  194. this.stop();
  195. }
  196.  
  197. this._flying = false;
  198.  
  199. this._callback = callback;
  200. this._callbackScope = scope;
  201.  
  202. const camera = this.scene.camera;
  203.  
  204. this._eye1[0] = camera.eye[0];
  205. this._eye1[1] = camera.eye[1];
  206. this._eye1[2] = camera.eye[2];
  207.  
  208. this._look1[0] = camera.look[0];
  209. this._look1[1] = camera.look[1];
  210. this._look1[2] = camera.look[2];
  211.  
  212. this._up1[0] = camera.up[0];
  213. this._up1[1] = camera.up[1];
  214. this._up1[2] = camera.up[2];
  215.  
  216. this._orthoScale1 = camera.ortho.scale;
  217. this._orthoScale2 = params.orthoScale || this._orthoScale1;
  218.  
  219. let aabb;
  220. let eye;
  221. let look;
  222. let up;
  223. let componentId;
  224.  
  225. if (params.aabb) {
  226. aabb = params.aabb;
  227.  
  228. } else if (params.length === 6) {
  229. aabb = params;
  230.  
  231. } else if ((params.eye && params.look) || params.up) {
  232. eye = params.eye;
  233. look = params.look;
  234. up = params.up;
  235.  
  236. } else if (params.eye) {
  237. eye = params.eye;
  238.  
  239. } else if (params.look) {
  240. look = params.look;
  241.  
  242. } else { // Argument must be an instance or ID of a Component (subtype)
  243.  
  244. let component = params;
  245. if (utils.isNumeric(component) || utils.isString(component)) {
  246. componentId = component;
  247. component = this.scene.components[componentId];
  248. if (!component) {
  249. this.error("Component not found: " + utils.inQuotes(componentId));
  250. if (callback) {
  251. if (scope) {
  252. callback.call(scope);
  253. } else {
  254. callback();
  255. }
  256. }
  257. return;
  258. }
  259. }
  260. aabb = component.aabb || this.scene.aabb;
  261. }
  262.  
  263. const poi = params.poi;
  264.  
  265. if (aabb) {
  266. if (aabb[3] < aabb[0] || aabb[4] < aabb[1] || aabb[5] < aabb[2]) { // Don't fly to an inverted boundary
  267. return;
  268. }
  269. if (aabb[3] === aabb[0] && aabb[4] === aabb[1] && aabb[5] === aabb[2]) { // Don't fly to an empty boundary
  270. return;
  271. }
  272. if (params.showAABB !== false) { // Show boundary
  273. this._aabbHelper.geometry.targetAABB = aabb;
  274. //this._aabbHelper.visible = true;
  275. }
  276.  
  277. aabb = aabb.slice();
  278. const aabbCenter = math.getAABB3Center(aabb);
  279.  
  280. this._look2 = poi || aabbCenter;
  281.  
  282. const eyeLookVec = math.subVec3(this._eye1, this._look1, tempVec3);
  283. const eyeLookVecNorm = math.normalizeVec3(eyeLookVec);
  284. const diag = poi ? math.getAABB3DiagPoint(aabb, poi) : math.getAABB3Diag(aabb);
  285. const fitFOV = params.fitFOV || this._fitFOV;
  286. const sca = Math.abs(diag / Math.tan(fitFOV * math.DEGTORAD));
  287.  
  288. this._orthoScale2 = diag * 1.1;
  289.  
  290. this._eye2[0] = this._look2[0] + (eyeLookVecNorm[0] * sca);
  291. this._eye2[1] = this._look2[1] + (eyeLookVecNorm[1] * sca);
  292. this._eye2[2] = this._look2[2] + (eyeLookVecNorm[2] * sca);
  293.  
  294. this._up2[0] = this._up1[0];
  295. this._up2[1] = this._up1[1];
  296. this._up2[2] = this._up1[2];
  297.  
  298. this._flyEyeLookUp = false;
  299.  
  300. } else if (eye || look || up) {
  301.  
  302. this._flyEyeLookUp = !!eye && !!look && !!up;
  303. this._flyingEye = !!eye && !look;
  304. this._flyingLook = !!look && !eye;
  305.  
  306. if (look) {
  307. this._look2[0] = look[0];
  308. this._look2[1] = look[1];
  309. this._look2[2] = look[2];
  310. }
  311.  
  312. if (eye) {
  313. this._eye2[0] = eye[0];
  314. this._eye2[1] = eye[1];
  315. this._eye2[2] = eye[2];
  316. }
  317.  
  318. if (up) {
  319. this._up2[0] = up[0];
  320. this._up2[1] = up[1];
  321. this._up2[2] = up[2];
  322. }
  323. }
  324.  
  325. this.fire("started", params, true);
  326.  
  327. this._time1 = Date.now();
  328. this._time2 = this._time1 + (params.duration ? params.duration * 1000 : this._duration);
  329.  
  330. this._flying = true; // False as soon as we stop
  331.  
  332. tasks.scheduleTask(this._update, this);
  333. }
  334.  
  335. /**
  336. * Jumps the {{#crossLink "Camera"}}{{/crossLink}}'s {{#crossLink "Camera"}}{{/crossLink}} to the given target.
  337. *
  338. * * When the target is a boundary, this CameraFlightAnimation will position the {{#crossLink "Camera"}}{{/crossLink}}
  339. * at where the target fills most of the canvas.
  340. * * When the target is an explicit {{#crossLink "Camera"}}{{/crossLink}} position, given as ````eye````, ````look```` and ````up````
  341. * vectors, then this CameraFlightAnimation will jump the {{#crossLink "Camera"}}{{/crossLink}} to that target.
  342. *
  343. * @method flyTo
  344. * @param params {*|Component} Either a parameters object or a {{#crossLink "Component"}}{{/crossLink}} subtype that has a World-space AABB.
  345. * @param[params.arc=0] {Number} Factor in range [0..1] indicating how much the
  346. * {{#crossLink "Camera/eye:property"}}Camera's eye{{/crossLink}} position will
  347. * swing away from its {{#crossLink "Camera/eye:property"}}look{{/crossLink}} position as it flies to the target.
  348. * @param [params.component] {Number|String|Component} ID or instance of a component to fly to.
  349. * @param [params.aabb] {*} World-space axis-aligned bounding box (AABB) target to fly to.
  350. * @param [params.eye] {Float32Array} Position to fly the eye position to.
  351. * @param [params.look] {Float32Array} Position to fly the look position to.
  352. * @param [params.up] {Float32Array} Position to fly the up vector to.
  353. * @param [params.fitFOV] {Number} How much of field-of-view, in degrees, that a target {{#crossLink "Object"}}{{/crossLink}} or its AABB should
  354. * fill the canvas on arrival. Overrides {{#crossLink "CameraFlightAnimation/fitFOV:property"}}{{/crossLink}}.
  355. * @param [params.fit] {Boolean} Whether to fit the target to the view volume. Overrides {{#crossLink "CameraFlightAnimation/fit:property"}}{{/crossLink}}.
  356. */
  357. jumpTo(params) {
  358. this._jumpTo(params);
  359. }
  360.  
  361. _jumpTo(params) {
  362.  
  363. if (this._flying) {
  364. this.stop();
  365. }
  366.  
  367. const camera = this.scene.camera;
  368.  
  369. var aabb;
  370. var componentId;
  371. var newEye;
  372. var newLook;
  373. var newUp;
  374.  
  375. if (params.aabb) { // Boundary3D
  376. aabb = params.aabb;
  377.  
  378. } else if (params.length === 6) { // AABB
  379. aabb = params;
  380.  
  381. } else if (params.eye || params.look || params.up) { // Camera pose
  382. newEye = params.eye;
  383. newLook = params.look;
  384. newUp = params.up;
  385.  
  386. } else { // Argument must be an instance or ID of a Component (subtype)
  387.  
  388. let component = params;
  389.  
  390. if (utils.isNumeric(component) || utils.isString(component)) {
  391. componentId = component;
  392. component = this.scene.components[componentId];
  393. if (!component) {
  394. this.error("Component not found: " + utils.inQuotes(componentId));
  395. return;
  396. }
  397. }
  398. aabb = component.aabb || this.scene.aabb;
  399. }
  400.  
  401. const poi = params.poi;
  402.  
  403. if (aabb) {
  404.  
  405. if (aabb[3] <= aabb[0] || aabb[4] <= aabb[1] || aabb[5] <= aabb[2]) { // Don't fly to an empty boundary
  406. return;
  407. }
  408.  
  409. var diag = poi ? math.getAABB3DiagPoint(aabb, poi) : math.getAABB3Diag(aabb);
  410.  
  411. newLook = poi || math.getAABB3Center(aabb, newLook);
  412.  
  413. if (this._trail) {
  414. math.subVec3(camera.look, newLook, newLookEyeVec);
  415. } else {
  416. math.subVec3(camera.eye, camera.look, newLookEyeVec);
  417. }
  418.  
  419. math.normalizeVec3(newLookEyeVec);
  420. let dist;
  421. const fit = (params.fit !== undefined) ? params.fit : this._fit;
  422.  
  423. if (fit) {
  424. dist = Math.abs((diag) / Math.tan((params.fitFOV || this._fitFOV) * math.DEGTORAD));
  425.  
  426. } else {
  427. dist = math.lenVec3(math.subVec3(camera.eye, camera.look, tempVec3));
  428. }
  429.  
  430. math.mulVec3Scalar(newLookEyeVec, dist);
  431.  
  432. camera.eye = math.addVec3(newLook, newLookEyeVec, tempVec3);
  433. camera.look = newLook;
  434.  
  435. } else if (newEye || newLook || newUp) {
  436.  
  437. if (newEye) {
  438. camera.eye = newEye;
  439. }
  440. if (newLook) {
  441. camera.look = newLook;
  442. }
  443. if (newUp) {
  444. camera.up = newUp;
  445. }
  446. }
  447. }
  448.  
  449. _update() {
  450. if (!this._flying) {
  451. return;
  452. }
  453. const time = Date.now();
  454. let t = (time - this._time1) / (this._time2 - this._time1);
  455. const stopping = (t >= 1);
  456. if (t > 1) {
  457. t = 1;
  458. }
  459. t = this.easing ? this._ease(t, 0, 1, 1) : t;
  460. const camera = this.scene.camera;
  461. if (this._flyingEye || this._flyingLook) {
  462. if (this._flyingEye) {
  463. math.subVec3(camera.eye, camera.look, newLookEyeVec);
  464. camera.eye = math.lerpVec3(t, 0, 1, this._eye1, this._eye2, newEye);
  465. camera.look = math.subVec3(newEye, newLookEyeVec, newLook);
  466. } else if (this._flyingLook) {
  467. camera.look = math.lerpVec3(t, 0, 1, this._look1, this._look2, newLook);
  468. // camera.eye = math.addVec3(newLook, newLookEyeVec, newEye);
  469. camera.up = math.lerpVec3(t, 0, 1, this._up1, this._up2, newUp);
  470. }
  471. } else if (this._flyEyeLookUp) {
  472. camera.eye = math.lerpVec3(t, 0, 1, this._eye1, this._eye2, newEye);
  473. camera.look = math.lerpVec3(t, 0, 1, this._look1, this._look2, newLook);
  474. camera.up = math.lerpVec3(t, 0, 1, this._up1, this._up2, newUp);
  475. } else {
  476. math.lerpVec3(t, 0, 1, this._look1, this._look2, newLook);
  477. let dist;
  478. if (this._trail) {
  479. math.subVec3(newLook, camera.look, newLookEyeVec);
  480. } else {
  481. math.subVec3(camera.eye, camera.look, newLookEyeVec);
  482. }
  483. math.normalizeVec3(newLookEyeVec);
  484. math.lerpVec3(t, 0, 1, this._eye1, this._eye2, newEye);
  485. math.subVec3(newEye, newLook, lookEyeVec);
  486. dist = math.lenVec3(lookEyeVec);
  487. math.mulVec3Scalar(newLookEyeVec, dist);
  488. camera.eye = math.addVec3(newLook, newLookEyeVec, newEye);
  489. camera.look = newLook;
  490. }
  491. this.scene.camera.ortho.scale = this._orthoScale1 + (t * (this._orthoScale2 - this._orthoScale1));
  492. if (stopping) {
  493. this.stop();
  494. return;
  495. }
  496. tasks.scheduleTask(this._update, this); // Keep flying
  497. }
  498.  
  499. _ease(t, b, c, d) { // Quadratic easing out - decelerating to zero velocity http://gizma.com/easing
  500. t /= d;
  501. return -c * t * (t - 2) + b;
  502. }
  503.  
  504. /**
  505. * Stops an earlier flyTo, fires arrival callback.
  506. * @method stop
  507. */
  508. stop() {
  509. if (!this._flying) {
  510. return;
  511. }
  512. this._aabbHelper.visible = false;
  513. this._flying = false;
  514. this._time1 = null;
  515. this._time2 = null;
  516. const callback = this._callback;
  517. if (callback) {
  518. this._callback = null;
  519. if (this._callbackScope) {
  520. callback.call(this._callbackScope);
  521. } else {
  522. callback();
  523. }
  524. }
  525. this.fire("stopped", true, true);
  526. }
  527.  
  528. /**
  529. * Cancels an earlier flyTo without calling the arrival callback.
  530. * @method cancel
  531. */
  532. cancel() {
  533. if (!this._flying) {
  534. return;
  535. }
  536. this._aabbHelper.visible = false;
  537. this._flying = false;
  538. this._time1 = null;
  539. this._time2 = null;
  540. if (this._callback) {
  541. this._callback = null;
  542. }
  543. this.fire("canceled", true, true);
  544. }
  545.  
  546. /**
  547. * Flight duration, in seconds, when calling {{#crossLink "CameraFlightAnimation/flyTo:method"}}CameraFlightAnimation#flyTo(){{/crossLink}}.
  548. *
  549. * Stops any flight currently in progress.
  550. *
  551. * @property duration
  552. * @default 0.5
  553. * @type Number
  554. */
  555. set duration(value) {
  556. this._duration = value ? (value * 1000.0) : 500;
  557. this.stop();
  558. }
  559.  
  560. get duration() {
  561. return this._duration / 1000.0;
  562. }
  563.  
  564. /**
  565. * When true, will ensure that this CameraFlightAnimation is flying to a boundary it will always adjust the distance between the
  566. * {{#crossLink "CameraFlightAnimation/camera:property"}}camera{{/crossLink}}'s {{#crossLink "Lookat/eye:property"}}eye{{/crossLink}}
  567. * and {{#crossLink "Lookat/look:property"}}{{/crossLink}}
  568. * so as to ensure that the target boundary is always filling the view volume.
  569. *
  570. * When false, the eye will remain at its current distance from the look position.
  571. *
  572. * @property fit
  573. * @type Boolean
  574. * @default true
  575. */
  576. set fit(value) {
  577. this._fit = value !== false;
  578. }
  579.  
  580. get fit() {
  581. return this._fit;
  582. }
  583.  
  584.  
  585. /**
  586. * How much of the perspective field-of-view, in degrees, that a target {{#crossLink "Object"}}{{/crossLink}} or its AABB should
  587. * fill the canvas when calling {{#crossLink "CameraFlightAnimation/flyTo:method"}}CameraFlightAnimation#jumpTo(){{/crossLink}} or {{#crossLink "CameraFlightAnimation/jumpTo:method"}}{{/crossLink}}.
  588. *
  589. * @property fitFOV
  590. * @default 45
  591. * @type Number
  592. */
  593. set fitFOV(value) {
  594. this._fitFOV = value || 45;
  595. }
  596.  
  597. get fitFOV() {
  598. return this._fitFOV;
  599. }
  600.  
  601. /**
  602. * When true, will cause this CameraFlightAnimation to point the {{#crossLink "CameraFlightAnimation/camera:property"}}{{/crossLink}}
  603. * in the direction that it is travelling.
  604. *
  605. * @property trail
  606. * @type Boolean
  607. * @default false
  608. */
  609. set trail(value) {
  610. this._trail = !!value;
  611. }
  612.  
  613. get trail() {
  614. return this._trail;
  615. }
  616. }
  617.  
  618. componentClasses[type] = CameraFlightAnimation;
  619.  
  620. export {CameraFlightAnimation};
  621.