diff --git a/package.json b/package.json index 9fca65f5..5edcd2fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@openglobus/og", - "version": "0.26.3", + "version": "0.26.5", "description": "[openglobus](https://www.openglobus.org/) is a javascript/typescript library designed to display interactive 3d maps and planets with map tiles, imagery and vector data, markers, and 3D objects. It uses the WebGL technology, open source, and completely free.", "main": "lib/og.es.js", "types": "lib/index.d.ts", diff --git a/sandbox/modelLoad/dracoLoader.js b/sandbox/modelLoad/dracoLoader.js index d629327d..f2fe01d1 100644 --- a/sandbox/modelLoad/dracoLoader.js +++ b/sandbox/modelLoad/dracoLoader.js @@ -29,6 +29,7 @@ import { EntityCollection, scene, Gltf, + Easing } from "../../lib/og.es.js"; let renderer = new Renderer("frame", { @@ -50,7 +51,22 @@ class MyScene extends RenderNode { collection.addTo(this); - this.renderer.activeCamera.set(new Vec3(20, 21, 23), new Vec3(10, 0, 0)); + const cameraPositions = [ + [new Vec3(20, 21, 23), new Vec3(0, 2, 2), Vec3.UP, Easing.ElasticOut], + [new Vec3(40, 10, 15), new Vec3(10, 0, 0), Vec3.LEFT, Easing.ElasticOut], + [new Vec3(10, 30, 45), new Vec3(10, 0, 0), Vec3.DOWN, Easing.CubicInOut], + [new Vec3(40, 10, 15), new Vec3(10, 10, 0), Vec3.RIGHT, Easing.BackInOut], + ]; + let i = 0; + setInterval(() => { + this.renderer.activeCamera.flyCartesian(cameraPositions[i][0], { + look: cameraPositions[i][1], + up: cameraPositions[i][2], + ease: cameraPositions[i][3], + }); + i = (i + 1) % cameraPositions.length; + }, 1500); + console.log(this.renderer.activeCamera); DracoDecoderModule().then((decoderModule) => { Gltf.connectDracoDecoderModule(decoderModule); diff --git a/src/camera/Camera.ts b/src/camera/Camera.ts index a0add68a..17cb552a 100644 --- a/src/camera/Camera.ts +++ b/src/camera/Camera.ts @@ -1,20 +1,23 @@ import * as math from "../math"; -import {type EventsHandler, createEvents} from "../Events"; -import {Frustum} from "./Frustum"; -import {Mat3} from "../math/Mat3"; -import type {NumberArray9} from "../math/Mat3"; -import {Mat4} from "../math/Mat4"; -import type {NumberArray16} from "../math/Mat4"; -import {Renderer} from "../renderer/Renderer"; -import {Vec2} from "../math/Vec2"; -import type {NumberArray2} from "../math/Vec2"; -import {Vec3} from "../math/Vec3"; -import {Vec4} from "../math/Vec4"; -import {Sphere} from "../bv/Sphere"; -import {Quat} from "../math/Quat"; -import {DEGREES_DOUBLE, RADIANS, RADIANS_HALF} from "../math"; +import { type EventsHandler, createEvents } from "../Events"; +import { Frustum } from "./Frustum"; +import { Mat3 } from "../math/Mat3"; +import type { NumberArray9 } from "../math/Mat3"; +import { Mat4 } from "../math/Mat4"; +import type { NumberArray16 } from "../math/Mat4"; +import { Renderer } from "../renderer/Renderer"; +import { Vec2 } from "../math/Vec2"; +import type { NumberArray2 } from "../math/Vec2"; +import { Vec3 } from "../math/Vec3"; +import { Vec4 } from "../math/Vec4"; +import { Sphere } from "../bv/Sphere"; +import { Quat } from "../math/Quat"; +import { DEGREES_DOUBLE, RADIANS, RADIANS_HALF } from "../math"; +import { Easing, EasingFunction } from "../utils/easing"; +import { LonLat } from "../LonLat"; +import { Ray } from "../math/Ray"; -export type CameraEvents = ["viewchange", "moveend"]; +export type CameraEvents = ["viewchange", "moveend", "flystart", "flyend", "flystop"]; const EVENT_NAMES: CameraEvents = [ /** @@ -27,7 +30,25 @@ const EVENT_NAMES: CameraEvents = [ * Camera is stopped. * @event og.Camera#moveend */ - "moveend" + "moveend", + + /** + * Triggered before camera flight. + * @event og.Camera#flystart + */ + "flystart", + + /** + * Triggered when camera finished flight. + * @event og.Camera#flyend + */ + "flyend", + + /** + * Triggered when flight was stopped. + * @event og.Camera#flystop + */ + "flystop" ]; export interface ICameraParams { @@ -35,12 +56,42 @@ export interface ICameraParams { viewAngle?: number; look?: Vec3; up?: Vec3; - frustums?: NumberArray2[] + frustums?: NumberArray2[]; width?: number; height?: number; } -const getHorizontalViewAngleByFov = (fov: number, aspect: number) => DEGREES_DOUBLE * Math.atan(Math.tan(RADIANS_HALF * fov) * aspect); +export interface IFlyCartesianParams extends IFlyBaseParams { + look?: Vec3 | LonLat; + up?: Vec3; +} + +export interface IFlyBaseParams { + duration?: number; + ease?: EasingFunction; + completeCallback?: Function; + startCallback?: Function; + frameCallback?: Function; +} + +export const DEFAULT_FLIGHT_DURATION = 800; +export const DEFAULT_EASING = Easing.CubicInOut; + +type CameraFrame = { + eye: Vec3; + n: Vec3; + u: Vec3; + v: Vec3; +}; + +type CameraFlight = { + fly: (progress: number) => CameraFrame; + duration: number; + startedAt: number; +}; + +const getHorizontalViewAngleByFov = (fov: number, aspect: number) => + DEGREES_DOUBLE * Math.atan(Math.tan(RADIANS_HALF * fov) * aspect); /** * Camera class. @@ -59,7 +110,6 @@ const getHorizontalViewAngleByFov = (fov: number, aspect: number) => DEGREES_DOU * @fires EventsHandler#moveend */ class Camera { - static __counter__: number = 0; protected __id: number; @@ -172,12 +222,17 @@ class Camera { public _height: number; + protected _flight: CameraFlight | null; + protected _completeCallback: Function | null; + protected _frameCallback: Function | null; + + protected _flying: boolean; + // public dirForwardNED: Vec3; // public dirUpNED: Vec3; // public dirRightNED: Vec3; constructor(options: ICameraParams = {}) { - this.__id = Camera.__counter__++; this.events = createEvents(EVENT_NAMES, this); @@ -213,6 +268,11 @@ class Camera { this._peye = this.eye.clone(); this.isMoving = false; + this._flight = null; + this._completeCallback = null; + this._frameCallback = null; + this._flying = false; + this._tanViewAngle_hrad = 0.0; this._tanViewAngle_hradOneByHeight = 0.0; @@ -226,7 +286,7 @@ class Camera { let fr = new Frustum({ fov: this._viewAngle, - aspect: this.getAspectRatio(),//this._aspect, + aspect: this.getAspectRatio(), //this._aspect, near: fi[0], far: fi[1] }); @@ -234,7 +294,11 @@ class Camera { fr.cameraFrustumIndex = this.frustums.length; this.frustums.push(fr); //this.frustumColors.push.apply(this.frustumColors, fr._pickingColorU); - this.frustumColors.push(fr._pickingColorU[0], fr._pickingColorU[1], fr._pickingColorU[2]); + this.frustumColors.push( + fr._pickingColorU[0], + fr._pickingColorU[1], + fr._pickingColorU[2] + ); } } else { let near = 0.1, @@ -249,7 +313,11 @@ class Camera { fr.cameraFrustumIndex = this.frustums.length; this.frustums.push(fr); - this.frustumColors.push(fr._pickingColorU[0], fr._pickingColorU[1], fr._pickingColorU[2]); + this.frustumColors.push( + fr._pickingColorU[0], + fr._pickingColorU[1], + fr._pickingColorU[2] + ); } this.FARTHEST_FRUSTUM_INDEX = this.frustums.length - 1; @@ -272,6 +340,130 @@ class Camera { return this.__id; } + /** + * Flies to the cartesian coordinates. + * @public + * @param {Vec3} [cartesian] - Finish cartesian coordinates. + * @param {IFlyCartesianParams} [params] - Flight parameters + */ + flyCartesian(cartesian: Vec3, params: IFlyCartesianParams = {}): void { + this.stopFlying(); + params.look = params.look || Vec3.ZERO; + params.up = params.up || Vec3.UP; + params.duration = params.duration || DEFAULT_FLIGHT_DURATION; + const ease = params.ease || DEFAULT_EASING; + + this._completeCallback = params.completeCallback || (() => { + }); + + this._frameCallback = params.frameCallback || (() => { + }); + + if (params.startCallback) { + params.startCallback.call(this); + } + + let ground_a = this.eye.clone(); + + let v_a = this._u, + n_a = this._b; + + let up_b = params.up; + let ground_b = cartesian.clone(); + let n_b = Vec3.sub(cartesian, params.look as Vec3); + let u_b = up_b.cross(n_b); + n_b.normalize(); + u_b.normalize(); + let v_b = n_b.cross(u_b); + + this._flight = { + fly: (progress: number) => { + let t = ease(progress); + let d = 1 - t; + // camera path and orientations calculation + let g_i = ground_a.smerp(ground_b, d); + let eye_i = g_i; + let up_i = v_a.smerp(v_b, d); + let look_i = Vec3.add(eye_i, n_a.smerp(n_b, d).negateTo()); + + let n = new Vec3(eye_i.x - look_i.x, eye_i.y - look_i.y, eye_i.z - look_i.z); + let u = up_i.cross(n); + n.normalize(); + u.normalize(); + + let v = n.cross(u); + return { + eye: eye_i, + n: n, + u: u, + v: v + }; + }, + duration: params.duration, + startedAt: Date.now() + } + this._flying = true; + this.events.dispatch(this.events.flystart, this); + } + + /** + * Breaks the flight. + * @public + */ + stopFlying() { + if (!this._flying) { + return; + } + this._flying = false; + this._flight = null; + this._frameCallback = null; + this.events.dispatch(this.events.flystop, this); + } + + /** + * Prepare camera to the frame. Used in render node frame function. + * @public + */ + public checkFly() { + if (this._flying && this._flight !== null) { + let progress = Math.min( + (Date.now() - this._flight.startedAt) / this._flight.duration, + 1 + ); + + const frame = this._flight.fly(progress); + this.eye = frame.eye; + this._r = frame.u; + this._u = frame.v; + this._b = frame.n; + this._f.set(-this._b.x, -this._b.y, -this._b.z); + + if (this._frameCallback) { + this._frameCallback(); + } + + this.update(); + + if (progress >= 1) { + this.stopFlying(); + if (this._completeCallback) { + this.events.dispatch(this.events.flyend, this); + this._completeCallback(); + this._completeCallback = null; + } + } + } + } + + /** + * Returns camera is flying. + * @public + * @returns {boolean} + */ + isFlying() { + return this._flying; + } + public checkMoveEnd() { let r = this._r, u = this._u, @@ -311,7 +503,6 @@ class Camera { * @param {Vec3} [options.up] - Camera eye position. Default (0,1,0) */ protected _init(options: ICameraParams) { - this._setProj(this._viewAngle, this.getAspectRatio()); this.set( @@ -359,17 +550,41 @@ class Camera { Vec3.doubleToTwoFloat32Array(eye, this.eyeHigh, this.eyeLow); this._viewMatrix.set([ - u.x, v.x, n.x, 0.0, - u.y, v.y, n.y, 0.0, - u.z, v.z, n.z, 0.0, - -eye.dot(u), -eye.dot(v), -eye.dot(n), 1.0 + u.x, + v.x, + n.x, + 0.0, + u.y, + v.y, + n.y, + 0.0, + u.z, + v.z, + n.z, + 0.0, + -eye.dot(u), + -eye.dot(v), + -eye.dot(n), + 1.0 ]); this._viewMatrixRTE.set([ - u.x, v.x, n.x, 0.0, - u.y, v.y, n.y, 0.0, - u.z, v.z, n.z, 0.0, - 0, 0, 0, 1.0 + u.x, + v.x, + n.x, + 0.0, + u.y, + v.y, + n.y, + 0.0, + u.z, + v.z, + n.z, + 0.0, + 0, + 0, + 0, + 1.0 ]); // do not clean up, someday it will be using @@ -440,7 +655,12 @@ class Camera { protected _updateViewportParameters() { this._tanViewAngle_hrad = Math.tan(this._viewAngle * math.RADIANS_HALF); this._tanViewAngle_hradOneByHeight = this._tanViewAngle_hrad * (1.0 / this._height); - this._projSizeConst = Math.min(this._width < 512 ? 512 : this._width, this._height < 512 ? 512 : this._height) / (this._viewAngle * RADIANS); + this._projSizeConst = + Math.min( + this._width < 512 ? 512 : this._width, + this._height < 512 ? 512 : this._height + ) / + (this._viewAngle * RADIANS); } /** @@ -665,8 +885,12 @@ class Camera { let px = (x - w) / w, py = -(y - h) / h; - let world1 = this.frustums[0].inverseProjectionViewMatrix.mulVec4(new Vec4(px, py, -1.0, 1.0)).affinity(), - world2 = this.frustums[0].inverseProjectionViewMatrix.mulVec4(new Vec4(px, py, 0.0, 1.0)).affinity(); + let world1 = this.frustums[0].inverseProjectionViewMatrix + .mulVec4(new Vec4(px, py, -1.0, 1.0)) + .affinity(), + world2 = this.frustums[0].inverseProjectionViewMatrix + .mulVec4(new Vec4(px, py, 0.0, 1.0)) + .affinity(); return world2.subA(world1).toVec3().normalize(); } @@ -703,7 +927,12 @@ class Camera { * @param {Vec3} [center] - Point that the camera rotates around * @param {Vec3} [up] - Camera up vector */ - public rotateAround(angle: number, isArc: boolean = false, center: Vec3 = Vec3.ZERO, up: Vec3 = Vec3.UP) { + public rotateAround( + angle: number, + isArc: boolean = false, + center: Vec3 = Vec3.ZERO, + up: Vec3 = Vec3.UP + ) { up = isArc ? this._u : up; let rot = Mat4.getRotation(angle, up); let trm = Mat4.getRotationAroundPoint(angle, center, up); @@ -767,7 +996,7 @@ class Camera { public setCurrentFrustum(k: number) { this.currentFrustumIndex = k; - this.frustumColorIndex = (k + 1) * 10.0 / 255.0; + this.frustumColorIndex = ((k + 1) * 10.0) / 255.0; this.isFirstPass = k === this.FARTHEST_FRUSTUM_INDEX; } @@ -856,4 +1085,4 @@ class Camera { } } -export {Camera}; +export { Camera }; diff --git a/src/camera/PlanetCamera.ts b/src/camera/PlanetCamera.ts index 5e48eac4..c6db7cd3 100644 --- a/src/camera/PlanetCamera.ts +++ b/src/camera/PlanetCamera.ts @@ -1,6 +1,6 @@ import * as mercator from "../mercator"; import * as math from "../math"; -import {Camera, CameraEvents, type ICameraParams} from "./Camera"; +import {Camera, DEFAULT_EASING, DEFAULT_FLIGHT_DURATION, type IFlyCartesianParams, type ICameraParams} from "./Camera"; import {Key} from "../Lock"; import {LonLat} from "../LonLat"; import {Mat4} from "../math/Mat4"; @@ -11,54 +11,18 @@ import {Vec3} from "../math/Vec3"; import {Extent} from "../Extent"; import {Segment} from "../segment/Segment"; import {RADIANS} from "../math"; -import { EventsHandler } from "../Events"; -import { Easing, EasingFunction } from "../utils/easing"; export interface IPlanetCameraParams extends ICameraParams { minAltitude?: number; maxAltitude?: number; } -export type PlanetCameraEventsList = [ - "flystart", - "flyend", - "flystop", -]; - -const PLANET_CAMERA_EVENTS: PlanetCameraEventsList = [ - /** - * Triggered before camera flight. - * @event og.PlanetCamera#flystart - */ - "flystart", - - /** - * Triggered when camera finished flight. - * @event og.PlanetCamera#flyend - */ - "flyend", - - /** - * Triggered when flight was stopped. - * @event og.PlanetCamera#flystop - */ - "flystop", -]; - -export const DEFAULT_FLIGHT_DURATION = 800; -export const DEFAULT_EASING = Easing.CubicInOut; - -type CameraFrame = { - eye: Vec3; - n: Vec3; - u: Vec3; - v: Vec3; +export interface IPlanetFlyCartesianParams extends IFlyCartesianParams { + amplitude?: number; } -type CameraFlight = { - fly: (progress: number) => CameraFrame; - duration: number; - startedAt: number; +export interface IPlanetFlyDistanceParams extends IPlanetFlyCartesianParams { + distance?: number; } /** @@ -78,9 +42,9 @@ type CameraFlight = { * @param {Vec3} [options.up] - Camera eye position. Default (0,1,0) * @fires og.Camera#viewchange * @fires og.Camera#moveend - * @fires og.PlanetCamera#flystart - * @fires og.PlanetCamera#flyend - * @fires og.PlanetCamera#flystop + * @fires og.Camera#flystart + * @fires og.Camera#flyend + * @fires og.Camera#flystop */ class PlanetCamera extends Camera { /** @@ -90,8 +54,6 @@ class PlanetCamera extends Camera { */ public planet: Planet; - public override events: EventsHandler & EventsHandler; - /** * Minimal altitude that camera can reach over the terrain. * @public @@ -145,11 +107,7 @@ class PlanetCamera extends Camera { public slope: number; protected _keyLock: Key; - protected _flight: CameraFlight | null; - protected _completeCallback: Function | null; - protected _frameCallback: Function | null; - protected _flying: boolean; protected _checkTerrainCollision: boolean; public eyeNorm: Vec3; @@ -161,9 +119,6 @@ class PlanetCamera extends Camera { } ); - //@ts-ignore - this.events = this.events.registerNames(PLANET_CAMERA_EVENTS); - this.planet = planet; this.minAltitude = options.minAltitude || 1; @@ -378,36 +333,15 @@ class PlanetCamera extends Camera { * @public * @param {Extent} extent - Current extent. * @param {number} [height] - Destination height. - * @param {Vec3} [up] - Camera UP in the end of flying. Default - (0,1,0) - * @param {Number} [ampl] - Altitude amplitude factor. - * @param {Number} [duration] - Animation duration - * @param {EasingFunction} [ease] - Animation easing - * @param {Function} [completeCallback] - Callback that calls after flying when flying is finished. - * @param {Function} [startCallback] - Callback that calls before the flying begins. - * @param {Function} [frameCallback] - Each frame callback + * @param {IPlanetFlyCartesianParams} [params] - Flight parameters */ public flyExtent( extent: Extent, height?: number | null, - up?: Vec3 | null, - ampl?: number | null, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback?: Function | null, - startCallback?: Function | null, - frameCallback?: Function | null + params: IPlanetFlyCartesianParams = {} ) { - this.flyCartesian( - this.getExtentPosition(extent, height), - Vec3.ZERO, - up, - ampl == null ? 1 : ampl, - duration, - ease, - completeCallback, - startCallback, - frameCallback - ); + params.look = Vec3.ZERO; + this.flyCartesian(this.getExtentPosition(extent, height), params); } public override viewDistance(cartesian: Vec3, distance: number = 10000.0) { @@ -424,15 +358,24 @@ class PlanetCamera extends Camera { this.update(); } + /** + * Flies to the geo coordinates. + * @public + * @param {LonLat} lonlat - Finish coordinates. + * @param {IPlanetFlyCartesianParams} [params] - Flight parameters + */ + flyLonLat( + lonlat: LonLat, + params: IPlanetFlyCartesianParams = {} + ) { + let _lonLat = new LonLat(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height); + this.flyCartesian(this.planet.ellipsoid.lonLatToCartesian(_lonLat), params); + } + public flyDistance( cartesian: Vec3, distance: number = 10000.0, - ampl: number = 0.0, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback?: Function, - startCallback?: Function, - frameCallback?: Function + params: IPlanetFlyCartesianParams = {}, ) { let p0 = this.eye.add(this.getForward().scaleTo(distance)); let _rot = Quat.getRotationBetweenVectors(p0.getNormal(), cartesian.getNormal()); @@ -442,63 +385,35 @@ class PlanetCamera extends Camera { } else { let newPos = cartesian.add(_rot.mulVec3(this.getBackward()).scale(distance)), newUp = _rot.mulVec3(this.getUp()); - this.flyCartesian( - newPos, - cartesian, - newUp, - ampl, - duration, - ease, - completeCallback, - startCallback, - frameCallback - ); + params.look = cartesian; + params.up = newUp; + this.flyCartesian(newPos, params); } } - /** - * Flies to the cartesian coordinates. - * @public - * @param {Vec3} cartesian - Finish cartesian coordinates. - * @param {Vec3} [look] - Camera LOOK in the end of flying. Default - (0,0,0) - * @param {Vec3} [up] - Camera UP vector in the end of flying. Default - (0,1,0) - * @param {Number} [ampl=1.0] - Altitude amplitude factor. - * @param {Number} [duration] - Animation duration - * @param {EasingFunction} [ease] - Animation easing - * @param {Function} [completeCallback] - Callback that calls after flying when flying is finished. - * @param {Function} [startCallback] - Callback that calls before the flying begins. - * @param {Function} [frameCallback] - Each frame callback - */ - flyCartesian( - cartesian: Vec3, - look: Vec3 | LonLat | null = Vec3.ZERO, - up: Vec3 | null = Vec3.NORTH, - ampl: number = 1.0, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback: Function | null = () => { - }, - startCallback: Function | null = () => { - }, - frameCallback: Function | null = () => { - } - ) { - + override flyCartesian(cartesian: Vec3, params: IPlanetFlyCartesianParams = {}): void { this.stopFlying(); + this.planet.layerLock.lock(this._keyLock); + this.planet.terrainLock.lock(this._keyLock); + this.planet.normalMapCreator.lock(this._keyLock); + params.amplitude = params.amplitude || 1.0; + params.look = params.look || Vec3.ZERO; + params.up = params.up || Vec3.NORTH; + params.duration = params.duration || DEFAULT_FLIGHT_DURATION; + const ease = params.ease || DEFAULT_EASING; - look = look || Vec3.ZERO; - up = up || Vec3.NORTH; + this._completeCallback = params.completeCallback || (() => { + }); - this._completeCallback = completeCallback; + this._frameCallback = params.frameCallback || (() => { + }); - this._frameCallback = frameCallback; - - if (startCallback) { - startCallback.call(this); + if (params.startCallback) { + params.startCallback.call(this); } - if (look instanceof LonLat) { - look = this.planet.ellipsoid.lonLatToCartesian(look); + if (params.look instanceof LonLat) { + params.look = this.planet.ellipsoid.lonLatToCartesian(params.look); } let ground_a = this.eye.clone(); @@ -507,11 +422,11 @@ class PlanetCamera extends Camera { n_a = this._b; let lonlat_b = this.planet.ellipsoid.cartesianToLonLat(cartesian); - let up_b = up; + let up_b = params.up; let ground_b = this.planet.ellipsoid.lonLatToCartesian( new LonLat(lonlat_b.lon, lonlat_b.lat, 0) ); - let n_b = Vec3.sub(cartesian, look as Vec3); + let n_b = Vec3.sub(cartesian, params.look as Vec3); let u_b = up_b.cross(n_b); n_b.normalize(); u_b.normalize(); @@ -520,7 +435,7 @@ class PlanetCamera extends Camera { let an = ground_a.getNormal(); let bn = ground_b.getNormal(); let anbn = 1.0 - an.dot(bn); - let hM_a = ampl * math.SQRT_HALF * Math.sqrt(anbn > 0.0 ? anbn : 0.0); + let hM_a = params.amplitude * math.SQRT_HALF * Math.sqrt(anbn > 0.0 ? anbn : 0.0); let maxHeight = 6639613; let currMaxHeight = Math.max(this._lonLat.height, lonlat_b.height); @@ -561,76 +476,21 @@ class PlanetCamera extends Camera { v: v }; }, - duration, + duration: params.duration, startedAt: Date.now() } this._flying = true; this.events.dispatch(this.events.flystart, this); } - /** - * Flies to the geo coordinates. - * @public - * @param {LonLat} lonlat - Finish coordinates. - * @param {Vec3 | LonLat} [look] - Camera LOOK in the end of flying. Default - (0,0,0) - * @param {Vec3} [up] - Camera UP vector in the end of flying. Default - (0,1,0) - * @param {number} [ampl] - Altitude amplitude factor. - * @param {Number} [duration] - Animation duration - * @param {EasingFunction} [ease] - Animation easing - * @param {Function} [completeCallback] - Callback that calls after flying when flying is finished. - * @param {Function} [startCallback] - Callback that calls befor the flying begins. - * @param {Function} [frameCallback] - each frame callback - */ - flyLonLat( - lonlat: LonLat, - look?: Vec3 | LonLat, - up?: Vec3, - ampl?: number, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback?: Function, - startCallback?: Function, - frameCallback?: Function - ) { - let _lonLat = new LonLat(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height); - this.flyCartesian( - this.planet.ellipsoid.lonLatToCartesian(_lonLat), - look, - up, - ampl, - duration, - ease, - completeCallback, - startCallback, - frameCallback - ); - } - - /** - * Breaks the flight. - * @public - */ - stopFlying() { + override stopFlying(): void { if (!this._flying) { return; } this.planet.layerLock.free(this._keyLock); this.planet.terrainLock.free(this._keyLock); this.planet.normalMapCreator.free(this._keyLock); - - this._flying = false; - this._flight = null; - this._frameCallback = null; - this.events.dispatch(this.events.flystop, this); - } - - /** - * Returns camera is flying. - * @public - * @returns {boolean} - */ - isFlying(): boolean { - return this._flying; + super.stopFlying(); } /** @@ -714,42 +574,6 @@ class PlanetCamera extends Camera { } } - /** - * Prepare camera to the frame. Used in render node frame function. - * @public - */ - public checkFly() { - if (this._flying && this._flight !== null) { - let progress = Math.min((Date.now() - this._flight.startedAt) / this._flight.duration, 1); - - this.planet.layerLock.lock(this._keyLock); - this.planet.terrainLock.lock(this._keyLock); - this.planet.normalMapCreator.lock(this._keyLock); - - const frame = this._flight.fly(progress); - this.eye = frame.eye; - this._r = frame.u; - this._u = frame.v; - this._b = frame.n; - this._f.set(-this._b.x, -this._b.y, -this._b.z); - - if (this._frameCallback) { - this._frameCallback(); - } - - this.update(); - - if (progress >= 1) { - this.stopFlying(); - if (this._completeCallback) { - this.events.dispatch(this.events.flyend, this); - this._completeCallback(); - this._completeCallback = null; - } - } - } - } - public checkTerrainCollision() { this._terrainAltitude = this._lonLat.height; if (this._insideSegment && this._insideSegment.planet) { diff --git a/src/control/CompassButton.ts b/src/control/CompassButton.ts index 2ef24962..398ced3f 100644 --- a/src/control/CompassButton.ts +++ b/src/control/CompassButton.ts @@ -116,15 +116,11 @@ export class CompassButton extends Control { if (c) { planet.flyCartesian( c.normal().scaleTo(c.length() + c.distance(planet.camera.eye)), - null, - null, - 0, - undefined, - undefined, - null, - null, - () => { - planet.camera.look(c!); + { + amplitude: 0, + completeCallback: () => { + planet.camera.look(c!); + } } ); } else { diff --git a/src/control/elevationProfile/ElevationProfileScene.ts b/src/control/elevationProfile/ElevationProfileScene.ts index e67c83cf..45e3d27d 100644 --- a/src/control/elevationProfile/ElevationProfileScene.ts +++ b/src/control/elevationProfile/ElevationProfileScene.ts @@ -198,7 +198,9 @@ class ElevationProfileScene extends RenderNode { if (ll.height > maxHeight) maxHeight = ll.height; } - this._planet!.camera.flyExtent(new Extent(new LonLat(minLon, minLat), new LonLat(maxLon, maxLat)), maxHeight, null, 0); + this._planet!.camera.flyExtent(new Extent(new LonLat(minLon, minLat), new LonLat(maxLon, maxLat)), maxHeight, { + amplitude: 0 + }); } } diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index 962f4b42..d5cae4f3 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -1008,6 +1008,8 @@ class Renderer { e.dispatch(e.draw, this); + this.activeCamera!.checkFly(); + let frustums = this.activeCamera!.frustums; let pointerEvent = e.pointerEvent(); diff --git a/src/scene/Planet.ts b/src/scene/Planet.ts index e7e8d38d..eb43b488 100644 --- a/src/scene/Planet.ts +++ b/src/scene/Planet.ts @@ -24,7 +24,7 @@ import {LonLat} from "../LonLat"; import {Node} from "../quadTree/Node"; import {NormalMapCreator} from "../utils/NormalMapCreator"; import {PlainSegmentWorker} from "../utils/PlainSegmentWorker"; -import {DEFAULT_EASING, DEFAULT_FLIGHT_DURATION, PlanetCamera} from "../camera/PlanetCamera"; +import {IPlanetFlyCartesianParams, PlanetCamera} from "../camera/PlanetCamera"; import {Quat} from "../math/Quat"; import {QuadTreeStrategy} from "../quadTree/QuadTreeStrategy"; import {Ray} from "../math/Ray"; @@ -41,6 +41,7 @@ import type {WebGLBufferExt, WebGLTextureExt, IDefaultTextureParams} from "../we import {Program} from "../webgl/Program"; import {Segment} from "../segment/Segment"; import type {AtmosphereParameters} from "../shaders/atmos/atmos"; +import { DEFAULT_EASING, DEFAULT_FLIGHT_DURATION } from "../camera/Camera"; import {Easing, EasingFunction} from "../utils/easing"; export interface IPlanetParams { @@ -1137,7 +1138,6 @@ export class Planet extends RenderNode { this._distBeforeMemClear += this._prevCamEye.distance(cam.eye); this._prevCamEye.copy(cam.eye); - cam.checkFly(); // free memory if (this._createdNodesCount > this._maxNodes && this._distBeforeMemClear > this._minDistanceBeforeMemClear) { @@ -1882,80 +1882,37 @@ export class Planet extends RenderNode { * @public * @param {Extent} extent - Geographical extent. * @param {Number} [height] - Height on the end of the flight route. - * @param {Vec3} [up] - Camera UP vector on the end of a flying. - * @param {Number} [ampl] - Altitude amplitude factor. - * @param {Number} [duration] - Animation duration - * @param {EasingFunction} [ease] - Animation easing - * @param {Function} [startCallback] - Callback that calls before the flying begins. - * @param {Function} [completeCallback] - Callback that calls after flying when flying is finished. - * @param {Function} [frameCallback] - Each frame callback + * @param {IPlanetFlyCartesianParams} params - Flight parameters. */ public flyExtent( extent: Extent, height?: number, - up?: Vec3, - ampl?: number, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback?: Function, - startCallback?: Function, - frameCallback?: Function + params: IPlanetFlyCartesianParams = {} ) { - this.camera.flyExtent(extent, height, up, ampl, duration, ease, completeCallback, startCallback, frameCallback); + this.camera.flyExtent(extent, height, params); } /** * Fly camera to the point. * @public - * @param {Vec3} cartesian - Point coordinates. - * @param {Vec3} [look] - Camera "look at" point. - * @param {Vec3} [up] - Camera UP vector on the end of a flying. - * @param {Number} [ampl] - Altitude amplitude factor. - * @param {Number} [duration] - Animation duration - * @param {EasingFunction} [ease] - Animation easing - * @param {Function} [completeCallback] - Call the function in the end of flight - * @param {Function} [startCallback] - Call the function in the beginning - * @param {Function} [frameCallback] - Each frame callback + * @param {Vec3} cartesian - Fly cartesian coordinates. + * @param {IPlanetFlyCartesianParams} params - Flight parameters. */ - public flyCartesian( - cartesian: Vec3, - look?: Vec3 | null, - up?: Vec3 | null, - ampl?: number, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback?: Function | null, - startCallback?: Function | null, - frameCallback?: Function | null, - ) { - this.camera.flyCartesian(cartesian, look, up, ampl, duration, ease, completeCallback, startCallback, frameCallback); + public flyCartesian(cartesian: Vec3, params?: IPlanetFlyCartesianParams) { + this.camera.flyCartesian(cartesian, params); } /** * Fly camera to the geodetic position. * @public * @param {LonLat} lonlat - Fly geographical coordinates. - * @param {Vec3 | LonLat} [look] - Camera viewpoint in the end of the flight. - * @param {Vec3} [up] - Camera UP vector on the end of a flying. - * @param {Number} [ampl] - Altitude amplitude factor. - * @param {Number} [duration] - Animation duration - * @param {EasingFunction} [ease] - Animation easing - * @param {Function} [completeCallback] - Call the function in the end of flight - * @param {Function} [startCallback] - Call the function in the beginning - * @param {Function} [frameCallback] - Each frame callback + * @param {IPlanetFlyCartesianParams} params - Flight parameters. */ public flyLonLat( lonlat: LonLat, - look?: Vec3 | LonLat, - up?: Vec3, - ampl?: number, - duration: number = DEFAULT_FLIGHT_DURATION, - ease: EasingFunction = DEFAULT_EASING, - completeCallback?: Function, - startCallback?: Function, - frameCallback?: Function + params: IPlanetFlyCartesianParams = {} ) { - this.camera.flyLonLat(lonlat, look, up, ampl, duration, ease, completeCallback, startCallback, frameCallback); + this.camera.flyLonLat(lonlat, params); } /**