@babylonjs/core 8.37.0 → 8.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Animations/animationGroup.js +1 -4
- package/Animations/animationGroup.js.map +1 -1
- package/Behaviors/Cameras/interpolatingBehavior.d.ts +58 -0
- package/Behaviors/Cameras/interpolatingBehavior.js +157 -0
- package/Behaviors/Cameras/interpolatingBehavior.js.map +1 -0
- package/Cameras/Inputs/arcRotateCameraPointersInput.d.ts +5 -20
- package/Cameras/Inputs/arcRotateCameraPointersInput.js +9 -69
- package/Cameras/Inputs/arcRotateCameraPointersInput.js.map +1 -1
- package/Cameras/Inputs/freeCameraDeviceOrientationInput.js +11 -9
- package/Cameras/Inputs/freeCameraDeviceOrientationInput.js.map +1 -1
- package/Cameras/Inputs/geospatialCameraKeyboardInput.d.ts +81 -0
- package/Cameras/Inputs/geospatialCameraKeyboardInput.js +223 -0
- package/Cameras/Inputs/geospatialCameraKeyboardInput.js.map +1 -0
- package/Cameras/Inputs/geospatialCameraMouseWheelInput.js +1 -1
- package/Cameras/Inputs/geospatialCameraMouseWheelInput.js.map +1 -1
- package/Cameras/Inputs/geospatialCameraPointersInput.d.ts +17 -21
- package/Cameras/Inputs/geospatialCameraPointersInput.js +49 -71
- package/Cameras/Inputs/geospatialCameraPointersInput.js.map +1 -1
- package/Cameras/Inputs/orbitCameraPointersInput.d.ts +49 -0
- package/Cameras/Inputs/orbitCameraPointersInput.js +105 -0
- package/Cameras/Inputs/orbitCameraPointersInput.js.map +1 -0
- package/Cameras/Limits/geospatialLimits.d.ts +60 -0
- package/Cameras/Limits/geospatialLimits.js +89 -0
- package/Cameras/Limits/geospatialLimits.js.map +1 -0
- package/Cameras/Stereoscopic/stereoscopicScreenUniversalCamera.js +1 -1
- package/Cameras/Stereoscopic/stereoscopicScreenUniversalCamera.js.map +1 -1
- package/Cameras/VR/vrExperienceHelper.js +2 -2
- package/Cameras/VR/vrExperienceHelper.js.map +1 -1
- package/Cameras/cameraMovement.d.ts +150 -0
- package/Cameras/cameraMovement.js +190 -0
- package/Cameras/cameraMovement.js.map +1 -0
- package/Cameras/deviceOrientationCamera.js +5 -3
- package/Cameras/deviceOrientationCamera.js.map +1 -1
- package/Cameras/flyCamera.d.ts +2 -1
- package/Cameras/flyCamera.js.map +1 -1
- package/Cameras/geospatialCamera.d.ts +78 -49
- package/Cameras/geospatialCamera.js +210 -191
- package/Cameras/geospatialCamera.js.map +1 -1
- package/Cameras/geospatialCameraInputsManager.d.ts +5 -0
- package/Cameras/geospatialCameraInputsManager.js +9 -0
- package/Cameras/geospatialCameraInputsManager.js.map +1 -1
- package/Cameras/geospatialCameraMovement.d.ts +66 -0
- package/Cameras/geospatialCameraMovement.js +199 -0
- package/Cameras/geospatialCameraMovement.js.map +1 -0
- package/Cameras/targetCamera.d.ts +1 -1
- package/Cameras/targetCamera.js +2 -2
- package/Cameras/targetCamera.js.map +1 -1
- package/Decorators/nodeDecorator.d.ts +9 -7
- package/Decorators/nodeDecorator.js +9 -7
- package/Decorators/nodeDecorator.js.map +1 -1
- package/Engines/Native/nativeInterfaces.d.ts +14 -6
- package/Engines/Native/nativeInterfaces.js +6 -1
- package/Engines/Native/nativeInterfaces.js.map +1 -1
- package/Engines/WebGPU/webgpuTextureManager.js +2 -2
- package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/nativeEngine.js +2 -2
- package/Engines/nativeEngine.js.map +1 -1
- package/FlowGraph/Blocks/Data/Math/flowGraphVectorMathBlocks.js +1 -1
- package/FlowGraph/Blocks/Data/Math/flowGraphVectorMathBlocks.js.map +1 -1
- package/FlowGraph/flowGraphMath.d.ts +25 -0
- package/FlowGraph/flowGraphMath.js +40 -0
- package/FlowGraph/flowGraphMath.js.map +1 -0
- package/FrameGraph/Node/Blocks/Layers/glowLayerBlock.js +1 -1
- package/FrameGraph/Node/Blocks/Layers/glowLayerBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/Layers/highlightLayerBlock.js +1 -1
- package/FrameGraph/Node/Blocks/Layers/highlightLayerBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/basePostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/baseWithPropertiesPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/circleOfConfusionPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/colorCorrectionPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/depthOfFieldPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/filterPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/imageProcessingPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/ssao2PostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/ssao2PostProcessBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/ssrPostProcessBlock.js +1 -1
- package/FrameGraph/Node/Blocks/PostProcesses/ssrPostProcessBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.d.ts +6 -0
- package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.js +26 -0
- package/FrameGraph/Node/Blocks/Rendering/baseObjectRendererBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.d.ts +6 -0
- package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.js +48 -22
- package/FrameGraph/Node/Blocks/Rendering/geometryRendererBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/Textures/clearBlock.js +3 -3
- package/FrameGraph/Node/Blocks/Textures/clearBlock.js.map +1 -1
- package/FrameGraph/Node/Blocks/Textures/copyTextureBlock.js +1 -1
- package/FrameGraph/Node/Blocks/Textures/generateMipmapsBlock.js +1 -1
- package/FrameGraph/Node/Blocks/Textures/generateMipmapsBlock.js.map +1 -1
- package/FrameGraph/Node/nodeRenderGraph.js +2 -1
- package/FrameGraph/Node/nodeRenderGraph.js.map +1 -1
- package/FrameGraph/Passes/{cullPass.d.ts → objectListPass.d.ts} +8 -8
- package/FrameGraph/Passes/{cullPass.js → objectListPass.js} +9 -9
- package/FrameGraph/Passes/objectListPass.js.map +1 -0
- package/FrameGraph/Passes/renderPass.d.ts +6 -2
- package/FrameGraph/Passes/renderPass.js +14 -2
- package/FrameGraph/Passes/renderPass.js.map +1 -1
- package/FrameGraph/Tasks/Misc/cullObjectsTask.js +2 -2
- package/FrameGraph/Tasks/Misc/cullObjectsTask.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/geometryRendererTask.d.ts +8 -0
- package/FrameGraph/Tasks/Rendering/geometryRendererTask.js +10 -0
- package/FrameGraph/Tasks/Rendering/geometryRendererTask.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/objectRendererTask.d.ts +8 -0
- package/FrameGraph/Tasks/Rendering/objectRendererTask.js +13 -0
- package/FrameGraph/Tasks/Rendering/objectRendererTask.js.map +1 -1
- package/FrameGraph/Tasks/Texture/clearTextureTask.d.ts +1 -1
- package/FrameGraph/Tasks/Texture/clearTextureTask.js +7 -5
- package/FrameGraph/Tasks/Texture/clearTextureTask.js.map +1 -1
- package/FrameGraph/frameGraph.d.ts +10 -4
- package/FrameGraph/frameGraph.js +22 -9
- package/FrameGraph/frameGraph.js.map +1 -1
- package/FrameGraph/frameGraphTask.js +3 -3
- package/FrameGraph/frameGraphTask.js.map +1 -1
- package/FrameGraph/index.d.ts +1 -1
- package/FrameGraph/index.js +1 -1
- package/FrameGraph/index.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
- package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.js +5 -1
- package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.js.map +1 -1
- package/Materials/Node/Blocks/GaussianSplatting/splatReaderBlock.js +6 -5
- package/Materials/Node/Blocks/GaussianSplatting/splatReaderBlock.js.map +1 -1
- package/Materials/shaderMaterial.d.ts +9 -0
- package/Materials/shaderMaterial.js +39 -2
- package/Materials/shaderMaterial.js.map +1 -1
- package/Maths/math.vector.functions.d.ts +5 -24
- package/Maths/math.vector.functions.js +32 -35
- package/Maths/math.vector.functions.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +1 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +51 -16
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/csg2.js +1 -1
- package/Meshes/csg2.js.map +1 -1
- package/Meshes/thinInstanceMesh.js +15 -0
- package/Meshes/thinInstanceMesh.js.map +1 -1
- package/Misc/fileTools.js.map +1 -1
- package/Misc/tools.d.ts +3 -0
- package/Misc/tools.js +43 -4
- package/Misc/tools.js.map +1 -1
- package/Particles/EmitterTypes/coneParticleEmitter.d.ts +3 -1
- package/Particles/EmitterTypes/coneParticleEmitter.js +7 -1
- package/Particles/EmitterTypes/coneParticleEmitter.js.map +1 -1
- package/Particles/Node/Blocks/Emitters/coneShapeBlock.d.ts +9 -0
- package/Particles/Node/Blocks/Emitters/coneShapeBlock.js +43 -12
- package/Particles/Node/Blocks/Emitters/coneShapeBlock.js.map +1 -1
- package/Particles/Node/Blocks/Update/basicColorUpdateBlock.d.ts +1 -1
- package/Particles/Node/Blocks/Update/basicColorUpdateBlock.js +1 -1
- package/Particles/Node/Blocks/Update/basicColorUpdateBlock.js.map +1 -1
- package/Particles/Node/Blocks/Update/basicPositionUpdateBlock.d.ts +1 -1
- package/Particles/Node/Blocks/Update/basicPositionUpdateBlock.js +3 -3
- package/Particles/Node/Blocks/Update/basicPositionUpdateBlock.js.map +1 -1
- package/Particles/Node/Blocks/Update/updateSizeBlock.d.ts +35 -0
- package/Particles/Node/Blocks/Update/updateSizeBlock.js +73 -0
- package/Particles/Node/Blocks/Update/updateSizeBlock.js.map +1 -0
- package/Particles/Node/Blocks/index.d.ts +1 -0
- package/Particles/Node/Blocks/index.js +1 -0
- package/Particles/Node/Blocks/index.js.map +1 -1
- package/Particles/Node/Blocks/particleInputBlock.js +2 -0
- package/Particles/Node/Blocks/particleInputBlock.js.map +1 -1
- package/Particles/Node/Blocks/particleRandomBlock.d.ts +5 -2
- package/Particles/Node/Blocks/particleRandomBlock.js +32 -14
- package/Particles/Node/Blocks/particleRandomBlock.js.map +1 -1
- package/Particles/Node/Blocks/systemBlock.d.ts +20 -12
- package/Particles/Node/Blocks/systemBlock.js +26 -22
- package/Particles/Node/Blocks/systemBlock.js.map +1 -1
- package/Particles/Node/Enums/nodeParticleContextualSources.d.ts +5 -1
- package/Particles/Node/Enums/nodeParticleContextualSources.js +4 -0
- package/Particles/Node/Enums/nodeParticleContextualSources.js.map +1 -1
- package/Particles/Node/nodeParticleBuildState.d.ts +5 -5
- package/Particles/Node/nodeParticleBuildState.js +11 -7
- package/Particles/Node/nodeParticleBuildState.js.map +1 -1
- package/Particles/Node/nodeParticleSystemSet.helper.d.ts +0 -2
- package/Particles/Node/nodeParticleSystemSet.helper.js +524 -147
- package/Particles/Node/nodeParticleSystemSet.helper.js.map +1 -1
- package/Particles/particle.d.ts +4 -0
- package/Particles/particle.js +2 -0
- package/Particles/particle.js.map +1 -1
- package/Particles/thinParticleSystem.d.ts +3 -7
- package/Particles/thinParticleSystem.function.d.ts +1 -1
- package/Particles/thinParticleSystem.function.js +9 -6
- package/Particles/thinParticleSystem.function.js.map +1 -1
- package/Particles/thinParticleSystem.js +5 -7
- package/Particles/thinParticleSystem.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js +5 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplattingUboDeclaration.js +2 -1
- package/Shaders/ShadersInclude/gaussianSplattingUboDeclaration.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplattingVertexDeclaration.js +1 -1
- package/Shaders/ShadersInclude/gaussianSplattingVertexDeclaration.js.map +1 -1
- package/Shaders/gaussianSplatting.vertex.js +3 -3
- package/Shaders/gaussianSplatting.vertex.js.map +1 -1
- package/Shaders/gaussianSplattingDepth.vertex.js +2 -2
- package/Shaders/gaussianSplattingDepth.vertex.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +35 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplattingUboDeclaration.js +2 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplattingUboDeclaration.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplattingVertexDeclaration.js +1 -2
- package/ShadersWGSL/ShadersInclude/gaussianSplattingVertexDeclaration.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +3 -3
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/ShadersWGSL/gaussianSplattingDepth.vertex.js +2 -2
- package/ShadersWGSL/gaussianSplattingDepth.vertex.js.map +1 -1
- package/XR/webXRCamera.d.ts +5 -1
- package/XR/webXRCamera.js +2 -2
- package/XR/webXRCamera.js.map +1 -1
- package/XR/webXRExperienceHelper.js +1 -1
- package/XR/webXRExperienceHelper.js.map +1 -1
- package/package.json +1 -1
- package/FrameGraph/Passes/cullPass.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatialCamera.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCamera.ts"],"names":[],"mappings":"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","sourcesContent":["import { GeospatialCameraInputsManager } from \"./geospatialCameraInputsManager\";\r\nimport { Vector3, Matrix, TmpVectors } from \"../Maths/math.vector\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport { Scalar } from \"../Maths/math.scalar\";\r\nimport { Camera } from \"./camera\";\r\nimport { Ray } from \"../Culling/ray\";\r\nimport type { Scene } from \"../scene\";\r\nimport type { MeshPredicate } from \"../Culling/ray.core\";\r\nimport type { Nullable } from \"../types\";\r\n\r\ntype CameraOptions = {\r\n planetRadius: number; // Radius of the planet\r\n minAltitude?: number; // Minimum altitude of the camera above the planet surface\r\n maxAltitude?: number; // Maximum altitude of the camera above the planet surface\r\n restingAltitude?: number; // The altitude the camera will return to when not being actively zoomed in or out\r\n};\r\n\r\n/**\r\n * @experimental\r\n * This camera's movements are limited to a camera orbiting a globe, and as the API evolves it will introduce conversions between cartesian coordinates and true lat/long/alt\r\n *\r\n * Please note this is marked as experimental and the API (including the constructor!) will change until we remove that flag\r\n *\r\n * Still TODO:\r\n * - Pitch/yaw limits, input speeds\r\n * - ZoomToPoint\r\n * - Conversion between lat/long/alt and cartesian coordinates\r\n */\r\nexport class GeospatialCamera extends Camera {\r\n override inputs: GeospatialCameraInputsManager;\r\n\r\n // Changed by the inputs, reset on every frame\r\n /** @internal */\r\n public _perFrameGeocentricTranslation: Vector3; // Translation that keeps camera at the same radius from the center of the globe\r\n /** @internal */\r\n public _perFrameGeocentricRotation: Vector3; // Rotation around center (distinct from rotation around camera that can cause looking off into space)\r\n /** @internal */\r\n public _perFrameZoom: number;\r\n\r\n /** If supplied, will be used when picking the globe */\r\n public pickPredicate?: MeshPredicate;\r\n\r\n /**\r\n * Enables rotation around a specific point, instead of default rotation around center\r\n * @internal\r\n */\r\n public _alternateRotationPt: Nullable<Vector3>;\r\n\r\n /** The point on the globe that we are anchoring around. If no alternate rotation point is supplied, this will represent the center of screen*/\r\n public get center(): Vector3 {\r\n // NOTE that for now we are falling back to target if no pick on globe (because that shouldn't happen with current implemented inputs)\r\n // but eventually we want to return a point on the globe even if the camera is looking off into space\r\n return this._pickAlongLook?.pickedPoint ?? this._target;\r\n }\r\n\r\n // Temp vars\r\n private _tempGeocentricNormal: Vector3;\r\n private _tempRotationAxis: Vector3;\r\n private _tempRotationMatrix: Matrix;\r\n private _tempPickingRay: Ray;\r\n private _tempPosition: Vector3;\r\n\r\n private _viewMatrix: Matrix;\r\n private _isViewMatrixDirty: boolean;\r\n private _lookAtVector: Vector3;\r\n\r\n // Camera configuration vars\r\n private _planetRadius: number;\r\n private _minAltitude: number;\r\n private _maxAltitude?: number;\r\n private _maxCameraRadius?: number;\r\n private _restingAltitude: number;\r\n\r\n /** Target of camera when looking along lookAtVector from current position. This does not necessarily represent a point on the globe */\r\n private get _target(): Vector3 {\r\n return this.position.addToRef(this._lookAtVector, this._tempPosition);\r\n }\r\n\r\n /** The point around which the camera will geocentrically rotate. Uses center (pt we are anchored to) if no alternateRotationPt is defined */\r\n private get _geocentricRotationPt(): Vector3 {\r\n return this._alternateRotationPt ?? this.center;\r\n }\r\n\r\n constructor(name: string, scene: Scene, options: CameraOptions, pickPredicate?: MeshPredicate) {\r\n super(name, Vector3.Zero(), scene);\r\n this._resetToDefault(options);\r\n this.pickPredicate = pickPredicate;\r\n this.inputs = new GeospatialCameraInputsManager(this);\r\n this.inputs.addMouse().addMouseWheel();\r\n }\r\n\r\n private _resetToDefault(options: CameraOptions): void {\r\n // Camera configuration vars\r\n this._minAltitude = options.minAltitude ?? 5;\r\n this._maxAltitude = options.maxAltitude;\r\n this._planetRadius = options.planetRadius;\r\n this._maxCameraRadius = this._maxAltitude ? this._planetRadius + this._maxAltitude : undefined;\r\n this._restingAltitude = options.restingAltitude ?? this._maxCameraRadius ?? this._planetRadius * 4;\r\n this.position.copyFromFloats(0, 0, -this._restingAltitude);\r\n\r\n // Input vars\r\n this._perFrameGeocentricRotation = Vector3.Zero();\r\n this._perFrameGeocentricTranslation = Vector3.Zero();\r\n this._perFrameZoom = 0;\r\n\r\n // Temp vars\r\n this._tempPosition = Vector3.Zero();\r\n this._tempRotationAxis = Vector3.Right(); // starting axis used to calculate pitch rotation matrix\r\n this._tempRotationMatrix = Matrix.Identity();\r\n this._tempGeocentricNormal = Vector3.Zero();\r\n this._tempPickingRay = new Ray(this.position, this._lookAtVector);\r\n this._tempPickingRay.direction = Vector3.Zero();\r\n\r\n // View matrix calculation vars\r\n this.upVector = Vector3.Up(); // Up vector of the camera\r\n this._lookAtVector = this.position.negate().normalize(); // Lookat vector of the camera\r\n this._viewMatrix = Matrix.Identity();\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n /** @internal */\r\n override _getViewMatrix() {\r\n if (!this._isViewMatrixDirty) {\r\n return this._viewMatrix;\r\n }\r\n this._isViewMatrixDirty = false;\r\n\r\n // Ensure vectors are normalized\r\n this.upVector.normalize();\r\n this._lookAtVector.normalize();\r\n\r\n // Calculate view matrix with camera position and target\r\n if (this.getScene().useRightHandedSystem) {\r\n Matrix.LookAtRHToRef(this.position, this._target, this.upVector, this._viewMatrix);\r\n } else {\r\n Matrix.LookAtLHToRef(this.position, this._target, this.upVector, this._viewMatrix);\r\n }\r\n\r\n return this._viewMatrix;\r\n }\r\n\r\n /** @internal */\r\n override _isSynchronizedViewMatrix(): boolean {\r\n if (!super._isSynchronizedViewMatrix() || this._isViewMatrixDirty) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Applies rotation correction to the camera by calculating a changeOfBasis matrix from the camera's current position to the new position\r\n * and transforming the lookAt and up vectors by that matrix before updating the camera position and marking the view matrix as dirty\r\n * @param newPos The camera's desired position, before correction is applied\r\n */\r\n private _applyRotationCorrectionAndSetPos(newPos: Vector3): void {\r\n // Compute changeOfBasis between current camera position and new position\r\n ComputeChangeOfBasisToRef(this.position, newPos, this._tempRotationMatrix);\r\n\r\n // Apply rotation correction to lookat/up vectors\r\n Vector3.TransformNormalToRef(this._lookAtVector, this._tempRotationMatrix, this._lookAtVector);\r\n Vector3.TransformNormalToRef(this.upVector, this._tempRotationMatrix, this.upVector);\r\n\r\n // Apply position change and mark viewMatrix as dirty\r\n this.position.copyFrom(newPos);\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n /**\r\n * When the geocentric normal has any translation change (due to dragging), we must ensure the camera remains orbiting around the world origin\r\n * We thus need to perform 2 correction steps\r\n * 1. Translation correction that keeps the camera at the same radius as before the drag\r\n * 2. Rotation correction that keeps the camera facing the globe (so that as we pan, the globe stays centered on screen)\r\n */\r\n private _applyGeocentricTranslation() {\r\n // Store pending position (without any corrections applied)\r\n this.position.addToRef(this._perFrameGeocentricTranslation, this._tempPosition);\r\n\r\n // 1. Calculate the altitude correction to keep camera at the same radius when applying translation\r\n const tempPositionScaled = TmpVectors.Vector3[2];\r\n const offset = TmpVectors.Vector3[3];\r\n this._tempPosition.normalizeToRef(tempPositionScaled).scaleInPlace(this.position.length()); // what would tempPosition be if it were scaled to same radius as before\r\n this._tempPosition.subtractToRef(tempPositionScaled, offset); // find offset between tempPosition and the tempScaledPosition\r\n this._tempPosition.subtractInPlace(offset); // reduce tempPosition by that offset\r\n\r\n // 2. Calculate the rotation correction to keep camera facing globe\r\n this._applyRotationCorrectionAndSetPos(this._tempPosition);\r\n }\r\n\r\n /**\r\n * This rotation keeps the camera oriented towards the globe as it orbits around it. This is different from cameraCentricRotation which is when the camera rotates around its own axis\r\n */\r\n private _applyGeocentricRotation(): void {\r\n // Normalize key vectors\r\n this._geocentricRotationPt.normalizeToRef(this._tempGeocentricNormal);\r\n this.upVector.normalize();\r\n this._lookAtVector.normalize();\r\n\r\n const pitchRotationMatrix = Matrix.Identity();\r\n const yawRotationMatrix = Matrix.Identity();\r\n // First apply pitch\r\n if (this._perFrameGeocentricRotation.x !== 0) {\r\n // Compute a rotation axis that is perpendicular to both the upVector and the geocentricNormalOfPitchPoint\r\n Vector3.CrossToRef(this.upVector, this._tempGeocentricNormal, this._tempRotationAxis);\r\n\r\n // If upVector and geocentricNormalOfPitchPoint are parallel, fall back to cross(lookAtDirection, geocentricNormalOfPitchPoint)\r\n if (this._tempRotationAxis.lengthSquared() <= Epsilon) {\r\n Vector3.CrossToRef(this._lookAtVector, this._tempGeocentricNormal, this._tempRotationAxis);\r\n }\r\n\r\n const pitchSign = Math.sign(Vector3.Dot(this._tempGeocentricNormal, this.upVector)); // If negative, camera is upside down\r\n // Since these are pointed in opposite directions, we must negate the dot product to get the proper angle\r\n const currentPitch = pitchSign * Math.acos(Scalar.Clamp(-Vector3.Dot(this._lookAtVector, this._tempGeocentricNormal), -1, 1));\r\n const newPitch = Scalar.Clamp(currentPitch + this._perFrameGeocentricRotation.x, 0, 0.5 * Math.PI - Epsilon);\r\n // Build rotation matrix around normalized axis\r\n Matrix.RotationAxisToRef(this._tempRotationAxis.normalize(), newPitch - currentPitch, pitchRotationMatrix);\r\n }\r\n\r\n // Then apply yaw\r\n if (this._perFrameGeocentricRotation.y !== 0) {\r\n Matrix.RotationAxisToRef(this._tempGeocentricNormal, this._perFrameGeocentricRotation.y, yawRotationMatrix); // this axis changes if we aren't using center of screen for tilt\r\n }\r\n pitchRotationMatrix.multiplyToRef(yawRotationMatrix, this._tempRotationMatrix);\r\n\r\n // Offset camera to be (position-pitchPoint) distance from geocentricOrigin, apply rotation to position/up/lookat vectors, then add back the pitchPoint offset\r\n this.position.subtractInPlace(this._geocentricRotationPt);\r\n\r\n Vector3.TransformCoordinatesToRef(this.position, this._tempRotationMatrix, this.position);\r\n Vector3.TransformNormalToRef(this.upVector, this._tempRotationMatrix, this.upVector);\r\n Vector3.TransformNormalToRef(this._lookAtVector, this._tempRotationMatrix, this._lookAtVector);\r\n\r\n this.position.addInPlace(this._geocentricRotationPt);\r\n }\r\n\r\n private _clampZoomDistance(requestedDistance: number, pickResultDistance: number | undefined): number {\r\n // If pickResult is defined\r\n if (requestedDistance > 0) {\r\n if (pickResultDistance !== undefined) {\r\n // If there is a pick, allow movement up to pick - minAltitude\r\n if (pickResultDistance - this._minAltitude < 0) {\r\n return 0;\r\n }\r\n return Math.min(requestedDistance, pickResultDistance - this._minAltitude);\r\n } else {\r\n return requestedDistance;\r\n }\r\n }\r\n\r\n if (requestedDistance < 0) {\r\n const maxZoomOut = this._maxCameraRadius ? this._maxCameraRadius - this.position.length() : Number.POSITIVE_INFINITY;\r\n return Math.max(requestedDistance, -maxZoomOut);\r\n }\r\n return 0;\r\n }\r\n\r\n private _applyZoom(distance: number) {\r\n const pickResult = this._scene.pick(this._scene.pointerX, this._scene.pointerY, this.pickPredicate);\r\n if (pickResult.hit && pickResult.ray) {\r\n // Zoom to cursor\r\n this._moveCameraAlongVectorByDistance(pickResult.ray.direction, this._clampZoomDistance(distance, pickResult.distance));\r\n } else {\r\n // If no hit under cursor, zoom along lookVector instead\r\n this._moveCameraAlongVectorByDistance(this._lookAtVector, this._clampZoomDistance(distance, this._pickAlongLook?.distance));\r\n }\r\n }\r\n\r\n private _moveCameraAlongVectorByDistance(vector: Vector3, distance: number) {\r\n if (distance) {\r\n vector.scaleAndAddToRef(distance, this._tempPosition);\r\n this._applyRotationCorrectionAndSetPos(this._tempPosition);\r\n }\r\n }\r\n\r\n private get _pickAlongLook() {\r\n this._tempPickingRay.origin.copyFrom(this.position);\r\n this._tempPickingRay.direction.copyFrom(this._lookAtVector);\r\n return this._scene.pickWithRay(this._tempPickingRay, this.pickPredicate);\r\n }\r\n\r\n override _checkInputs(): void {\r\n this.inputs.checkInputs();\r\n if (this._perFrameGeocentricTranslation.lengthSquared() > 0) {\r\n this._applyGeocentricTranslation();\r\n this._perFrameGeocentricTranslation.setAll(0);\r\n this._isViewMatrixDirty = true;\r\n }\r\n if (this._perFrameGeocentricRotation.lengthSquared() > 0) {\r\n this._applyGeocentricRotation();\r\n this._perFrameGeocentricRotation.setAll(0);\r\n this._isViewMatrixDirty = true;\r\n }\r\n if (this._perFrameZoom !== 0) {\r\n this._applyZoom(this._perFrameZoom);\r\n this._perFrameZoom = 0;\r\n this._isViewMatrixDirty = true;\r\n }\r\n super._checkInputs();\r\n }\r\n\r\n override attachControl(noPreventDefault?: boolean): void {\r\n this.inputs.attachElement(noPreventDefault);\r\n }\r\n\r\n override detachControl(): void {\r\n this.inputs.detachElement();\r\n }\r\n}\r\n\r\n// Helper to build east/north/up basis vectors at a world position\r\nfunction ComputeLocalBasisToRefs(worldPos: Vector3, refEast: Vector3, refNorth: Vector3, refUp: Vector3) {\r\n // up = normalized position (geocentric normal)\r\n refUp.copyFrom(worldPos).normalize();\r\n\r\n // east = normalize(up × worldUp)\r\n // (cross product of up with world Y gives east except at poles)\r\n const worldUp = Vector3.Up(); // (0,1,0)\r\n Vector3.CrossToRef(refUp, worldUp, refEast);\r\n\r\n // at poles, cross with worldForward instead\r\n if (refEast.lengthSquared() < Epsilon) {\r\n Vector3.CrossToRef(refUp, Vector3.Forward(), refEast);\r\n }\r\n refEast.normalize();\r\n\r\n // north = up × east (completes right-handed basis)\r\n Vector3.CrossToRef(refUp, refEast, refNorth);\r\n refNorth.normalize();\r\n}\r\n\r\n/**\r\n * Calculates changeOfBasis matrix from currentPos to newPos and stores it in ref\r\n * @param currentPos\r\n * @param newPos\r\n * @param ref\r\n * @returns The changeOfBasis matrix from currentPos to newPos\r\n */\r\nfunction ComputeChangeOfBasisToRef(currentPos: Vector3, newPos: Vector3, ref: Matrix): Matrix {\r\n const currentBasis = TmpVectors.Matrix[5];\r\n const newBasis = TmpVectors.Matrix[6];\r\n const inverse = TmpVectors.Matrix[7];\r\n const east = TmpVectors.Vector3[3];\r\n const north = TmpVectors.Vector3[4];\r\n const up = TmpVectors.Vector3[5];\r\n\r\n ComputeLocalBasisToRefs(currentPos, east, north, up);\r\n Matrix.FromXYZAxesToRef(east, north, up, currentBasis);\r\n\r\n ComputeLocalBasisToRefs(newPos, east, north, up);\r\n Matrix.FromXYZAxesToRef(east, north, up, newBasis);\r\n\r\n // Change of basis matrix = basis2 * basis1.inverse()\r\n // (since orthonormal, inverse = transpose)\r\n currentBasis.transposeToRef(inverse).multiplyToRef(newBasis, ref);\r\n\r\n return ref;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"geospatialCamera.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCamera.ts"],"names":[],"mappings":"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","sourcesContent":["import { GeospatialCameraInputsManager } from \"./geospatialCameraInputsManager\";\r\nimport { Vector3, Matrix, TmpVectors } from \"../Maths/math.vector\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport { Camera } from \"./camera\";\r\nimport type { Scene } from \"../scene\";\r\nimport type { MeshPredicate } from \"../Culling/ray.core\";\r\nimport type { DeepImmutable } from \"../types\";\r\nimport { GeospatialLimits } from \"./Limits/geospatialLimits\";\r\nimport { ComputeLocalBasisToRefs, GeospatialCameraMovement } from \"./geospatialCameraMovement\";\r\nimport type { IVector3Like } from \"../Maths/math.like\";\r\nimport { Vector3CopyToRef, Vector3Dot } from \"../Maths/math.vector.functions\";\r\nimport { Clamp } from \"../Maths/math.scalar.functions\";\r\nimport type { AllowedAnimValue } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport type { EasingFunction } from \"../Animations/easing\";\r\n\r\ntype CameraOptions = {\r\n planetRadius: number; // Radius of the planet\r\n};\r\n\r\n/**\r\n * @experimental\r\n * This camera's movements are limited to a camera orbiting a globe, and as the API evolves it will introduce conversions between cartesian coordinates and true lat/long/alt\r\n *\r\n * Please note this is marked as experimental and the API (including the constructor!) will change until we remove that flag\r\n */\r\nexport class GeospatialCamera extends Camera {\r\n override inputs: GeospatialCameraInputsManager;\r\n\r\n /** If supplied, will be used when picking the globe */\r\n public pickPredicate?: MeshPredicate;\r\n\r\n /** Movement controller that turns input pixelDeltas into currentFrameDeltas used by camera*/\r\n public readonly movement: GeospatialCameraMovement;\r\n\r\n // Temp vars\r\n private _tempPosition: Vector3 = new Vector3();\r\n\r\n private _viewMatrix = new Matrix();\r\n private _isViewMatrixDirty: boolean;\r\n private _lookAtVector: Vector3 = new Vector3();\r\n\r\n /** Behavior used for smooth flying animations */\r\n private _flyingBehavior: InterpolatingBehavior<GeospatialCamera>;\r\n private _flyToTargets: Map<keyof GeospatialCamera, AllowedAnimValue> = new Map();\r\n\r\n constructor(name: string, scene: Scene, options: CameraOptions, pickPredicate?: MeshPredicate) {\r\n super(name, new Vector3(), scene);\r\n\r\n this._limits = new GeospatialLimits(options.planetRadius);\r\n this._resetToDefault(this._limits);\r\n\r\n this._flyingBehavior = new InterpolatingBehavior();\r\n this.addBehavior(this._flyingBehavior);\r\n\r\n this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, pickPredicate);\r\n\r\n this.pickPredicate = pickPredicate;\r\n this.inputs = new GeospatialCameraInputsManager(this);\r\n this.inputs.addMouse().addMouseWheel().addKeyboard();\r\n }\r\n\r\n private _center: Vector3 = new Vector3();\r\n /** The point on the globe that we are anchoring around. If no alternate rotation point is supplied, this will represent the center of screen*/\r\n public get center(): Vector3 {\r\n return this._center;\r\n }\r\n\r\n /**\r\n * Sets the camera position to orbit around a new center point\r\n * @param center The world position (ECEF) to orbit around\r\n */\r\n public set center(center: IVector3Like) {\r\n this._center.copyFromFloats(center.x, center.y, center.z);\r\n this._setOrientation(this._yaw, this._pitch, this._radius, this._center);\r\n }\r\n\r\n private _yaw: number = 0;\r\n /**\r\n * Gets the camera's yaw (rotation around the geocentric normal) in radians\r\n */\r\n public get yaw(): number {\r\n return this._yaw;\r\n }\r\n\r\n /**\r\n * Sets the camera's yaw (rotation around the geocentric normal)\r\n * @param yaw The desired yaw angle in radians (0 = north, π/2 = east)\r\n */\r\n public set yaw(yaw: number) {\r\n this._setOrientation(yaw, this.pitch, this.radius, this.center);\r\n }\r\n\r\n private _pitch: number = 0;\r\n\r\n /**\r\n * Gets the camera's pitch (angle from looking straight at globe)\r\n * Pitch is measured from looking straight down at planet center:\r\n * - zero pitch = looking straight at planet center (down)\r\n * - positive pitch = tilting up away from planet\r\n * - π/2 pitch = looking at horizon (perpendicular to geocentric normal)\r\n */\r\n public get pitch(): number {\r\n return this._pitch;\r\n }\r\n\r\n /**\r\n * Sets the camera's pitch (angle from looking straight at globe)\r\n * @param pitch The desired pitch angle in radians (0 = looking at planet center, π/2 = looking at horizon)\r\n */\r\n public set pitch(pitch: number) {\r\n this._setOrientation(this.yaw, pitch, this.radius, this.center);\r\n }\r\n\r\n private _radius: number = 0;\r\n public get radius(): number {\r\n return this._radius;\r\n }\r\n\r\n /**\r\n * Sets the camera's distance from the current center point\r\n * @param radius The desired radius\r\n */\r\n public set radius(radius: number) {\r\n this._setOrientation(this.yaw, this.pitch, radius, this.center);\r\n }\r\n\r\n protected _checkLimits() {\r\n const limits = this.limits;\r\n this._yaw = Clamp(this._yaw, limits.yawMin, limits.yawMax);\r\n this._pitch = Clamp(this._pitch, limits.pitchMin, limits.pitchMax);\r\n this._radius = Clamp(this._radius, limits.radiusMin, limits.radiusMax);\r\n }\r\n\r\n private _tempVect = new Vector3();\r\n private _tempEast = new Vector3();\r\n private _tempNorth = new Vector3();\r\n private _tempUp = new Vector3();\r\n\r\n private _setOrientation(yaw: number, pitch: number, radius: number, center: DeepImmutable<IVector3Like>): void {\r\n this._yaw = yaw;\r\n this._pitch = pitch;\r\n this._radius = radius;\r\n\r\n Vector3CopyToRef(center, this._center);\r\n\r\n // Clamp to limits\r\n this._checkLimits();\r\n\r\n // Refresh local basis at center (treat these as read-only for the whole call)\r\n ComputeLocalBasisToRefs(this._center, this._tempEast, this._tempNorth, this._tempUp);\r\n\r\n // Trig\r\n const yawScale = this._scene.useRightHandedSystem ? 1 : -1;\r\n const cosYaw = Math.cos(this._yaw * yawScale);\r\n const sinYaw = Math.sin(this._yaw * yawScale);\r\n const sinPitch = Math.sin(this._pitch); // horizontal weight\r\n const cosPitch = Math.cos(this._pitch); // vertical weight (toward center)\r\n\r\n // Temps\r\n const horiz = TmpVectors.Vector3[0];\r\n const t1 = TmpVectors.Vector3[1];\r\n const t2 = TmpVectors.Vector3[2];\r\n const right = TmpVectors.Vector3[3];\r\n\r\n // horizontalDirection = North*cosYaw + East*sinYaw (avoids mutating _temp basis vectors)\r\n horiz.copyFrom(this._tempNorth).scaleInPlace(cosYaw).addInPlace(t1.copyFrom(this._tempEast).scaleInPlace(sinYaw));\r\n\r\n // look = horiz*sinPitch - Up*cosPitch\r\n this._lookAtVector.copyFrom(horiz).scaleInPlace(sinPitch).addInPlace(t2.copyFrom(this._tempUp).scaleInPlace(-cosPitch)).normalize(); // keep it unit\r\n\r\n // Build an orthonormal up aligned with geocentric Up\r\n // right = normalize(cross(upRef, look))\r\n Vector3.CrossToRef(this._tempUp, this._lookAtVector, right);\r\n\r\n // up = normalize(cross(look, right))\r\n Vector3.CrossToRef(this._lookAtVector, right, this.upVector);\r\n\r\n // Position = center - look * radius (preserve unit look)\r\n this._tempVect.copyFrom(this._lookAtVector).scaleInPlace(-this._radius);\r\n this._tempPosition.copyFrom(this._center).addInPlace(this._tempVect);\r\n\r\n this._position.copyFrom(this._tempPosition);\r\n\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n /** The point around which the camera will geocentrically rotate. Uses center (pt we are anchored to) if no alternateRotationPt is defined */\r\n private get _geocentricRotationPt(): Vector3 {\r\n return this.movement.alternateRotationPt ?? this.center;\r\n }\r\n\r\n /**\r\n * If camera is actively in flight, will update the target properties and use up the remaining duration from original flyTo call\r\n *\r\n * To start a new flyTo curve entirely, call into flyToAsync again (it will stop the inflight animation)\r\n * @param targetYaw\r\n * @param targetPitch\r\n * @param targetRadius\r\n * @param targetCenter\r\n */\r\n public updateFlyToDestination(targetYaw?: number, targetPitch?: number, targetRadius?: number, targetCenter?: Vector3): void {\r\n this._flyToTargets.clear();\r\n\r\n this._flyToTargets.set(\"yaw\", targetYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter);\r\n\r\n this._flyingBehavior.updateProperties(this._flyToTargets);\r\n }\r\n\r\n /**\r\n * Animate camera towards passed in property values. If undefined, will use current value\r\n * @param targetYaw\r\n * @param targetPitch\r\n * @param targetRadius\r\n * @param targetCenter\r\n * @param flightDurationMs\r\n * @param easingFunction\r\n * @returns Promise that will return when the animation is complete (or interuppted by pointer input)\r\n */\r\n public async flyToAsync(\r\n targetYaw?: number,\r\n targetPitch?: number,\r\n targetRadius?: number,\r\n targetCenter?: Vector3,\r\n flightDurationMs: number = 1000,\r\n easingFunction?: EasingFunction\r\n ): Promise<void> {\r\n this._flyToTargets.clear();\r\n\r\n this._flyToTargets.set(\"yaw\", targetYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter);\r\n\r\n return await this._flyingBehavior.animatePropertiesAsync(this._flyToTargets, flightDurationMs, easingFunction);\r\n }\r\n\r\n private _limits: GeospatialLimits;\r\n public get limits(): GeospatialLimits {\r\n return this._limits;\r\n }\r\n\r\n private _resetToDefault(limits: GeospatialLimits): void {\r\n // Camera configuration vars\r\n const maxCameraRadius = limits.altitudeMax !== undefined ? limits.planetRadius + limits.altitudeMax : undefined;\r\n const restingAltitude = maxCameraRadius ?? limits.planetRadius * 4;\r\n this.position.copyFromFloats(restingAltitude, 0, 0);\r\n this._center.copyFromFloats(limits.planetRadius, 0, 0);\r\n this._radius = Vector3.Distance(this.position, this.center);\r\n\r\n // Temp vars\r\n this._tempPosition = new Vector3();\r\n\r\n // View matrix calculation vars\r\n this._viewMatrix = Matrix.Identity();\r\n this._center.subtractToRef(this._position, this._lookAtVector).normalize(); // Lookat vector of the camera\r\n this.upVector = Vector3.Up(); // Up vector of the camera (does work for -X look at)\r\n this._isViewMatrixDirty = true;\r\n\r\n this._setOrientation(this._yaw, this._pitch, this._radius, this._center);\r\n }\r\n\r\n /** @internal */\r\n override _getViewMatrix() {\r\n if (!this._isViewMatrixDirty) {\r\n return this._viewMatrix;\r\n }\r\n this._isViewMatrixDirty = false;\r\n\r\n // Ensure vectors are normalized\r\n this.upVector.normalize();\r\n this._lookAtVector.normalize();\r\n\r\n // Calculate view matrix with camera position and center\r\n if (this.getScene().useRightHandedSystem) {\r\n Matrix.LookAtRHToRef(this.position, this._center, this.upVector, this._viewMatrix);\r\n } else {\r\n Matrix.LookAtLHToRef(this.position, this._center, this.upVector, this._viewMatrix);\r\n }\r\n\r\n return this._viewMatrix;\r\n }\r\n\r\n /** @internal */\r\n override _isSynchronizedViewMatrix(): boolean {\r\n if (!super._isSynchronizedViewMatrix() || this._isViewMatrixDirty) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private _applyGeocentricTranslation() {\r\n // Store pending position (without any corrections applied)\r\n this.center.addToRef(this.movement.panDeltaCurrentFrame, this._tempPosition);\r\n\r\n if (!this.movement.isInterpolating) {\r\n // Calculate the position correction to keep camera at the same radius when applying translation\r\n this._tempPosition.normalize().scaleInPlace(this.center.length());\r\n }\r\n // Set center which will call _setOrientation\r\n this.center = this._tempPosition;\r\n }\r\n\r\n /**\r\n * This rotation keeps the camera oriented towards the globe as it orbits around it. This is different from cameraCentricRotation which is when the camera rotates around its own axis\r\n */\r\n private _applyGeocentricRotation(): void {\r\n const rotationDeltaCurrentFrame = this.movement.rotationDeltaCurrentFrame;\r\n if (rotationDeltaCurrentFrame.x !== 0 || rotationDeltaCurrentFrame.y !== 0) {\r\n const pitch = rotationDeltaCurrentFrame.x !== 0 ? Clamp(this._pitch + rotationDeltaCurrentFrame.x, 0, 0.5 * Math.PI - Epsilon) : this._pitch;\r\n const yaw = rotationDeltaCurrentFrame.y !== 0 ? this._yaw + rotationDeltaCurrentFrame.y : this._yaw;\r\n\r\n // TODO: If _geocentricRotationPt is not the center, this will need to be adjusted.\r\n this._setOrientation(yaw, pitch, this._radius, this._geocentricRotationPt);\r\n }\r\n }\r\n\r\n private _applyZoom(zoomVector: Vector3, distance: number) {\r\n // TODO this function will be re-worked shortly after checkin, becuase today it breaks down if you zoom to a point past the center\r\n // (ex: tilted view zooming towards cursor near horizon where the center is closer than the cursor point).\r\n\r\n // Project zoom vector onto lookAt vector to find the amount the camera-to-center distance should change.\r\n // - zoom vector is normalized\r\n // - distance is how much to move in this call\r\n const directionDotLookAt = Vector3Dot(zoomVector, this._lookAtVector);\r\n const hasRadialComponent = Math.abs(directionDotLookAt) > Epsilon;\r\n const requestedRadius = hasRadialComponent ? this._radius - distance * directionDotLookAt : this._radius;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n const actualRadiusChange = newRadius - this._radius;\r\n const actualDistanceChange = hasRadialComponent ? actualRadiusChange / directionDotLookAt : 0;\r\n\r\n // Use this to compute new camera position and new center position.\r\n const newCameraPosition = this._position.add(zoomVector.scale(-actualDistanceChange));\r\n const newCenter = newCameraPosition.add(this._lookAtVector.scaleToRef(newRadius, TmpVectors.Vector3[3]));\r\n\r\n // Rescale new center to maintain same altitude as the old center.\r\n const currentCenterRadius = this._center.length();\r\n const newCenterRadius = newCenter.length();\r\n const newCenterRescale = currentCenterRadius / newCenterRadius;\r\n newCenter.scaleInPlace(newCenterRescale);\r\n\r\n // Apply changes\r\n this._setOrientation(this._yaw, this._pitch, newRadius, newCenter);\r\n }\r\n\r\n override _checkInputs(): void {\r\n this.inputs.checkInputs();\r\n\r\n // Let movement class handle all per-frame logic\r\n this.movement.computeCurrentFrameDeltas();\r\n\r\n if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricTranslation();\r\n this._isViewMatrixDirty = true;\r\n }\r\n if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricRotation();\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {\r\n this._applyZoom(this.movement.computedPerFrameZoomVector, this.movement.zoomDeltaCurrentFrame);\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n super._checkInputs();\r\n }\r\n\r\n override attachControl(noPreventDefault?: boolean): void {\r\n this.inputs.attachElement(noPreventDefault);\r\n }\r\n\r\n override detachControl(): void {\r\n this.inputs.detachElement();\r\n }\r\n}\r\n"]}
|
|
@@ -20,4 +20,9 @@ export declare class GeospatialCameraInputsManager extends CameraInputsManager<G
|
|
|
20
20
|
* @returns the current input manager
|
|
21
21
|
*/
|
|
22
22
|
addMouseWheel(): GeospatialCameraInputsManager;
|
|
23
|
+
/**
|
|
24
|
+
* Add mouse wheel input support to the input manager
|
|
25
|
+
* @returns the current input manager
|
|
26
|
+
*/
|
|
27
|
+
addKeyboard(): GeospatialCameraInputsManager;
|
|
23
28
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CameraInputsManager } from "./cameraInputsManager.js";
|
|
2
2
|
import { GeospatialCameraPointersInput } from "./Inputs/geospatialCameraPointersInput.js";
|
|
3
3
|
import { GeospatialCameraMouseWheelInput } from "./Inputs/geospatialCameraMouseWheelInput.js";
|
|
4
|
+
import { GeospatialCameraKeyboardInput } from "./Inputs/geospatialCameraKeyboardInput.js";
|
|
4
5
|
/**
|
|
5
6
|
* Default Inputs manager for the GeospatialCamera.
|
|
6
7
|
* It groups all the default supported inputs for ease of use.
|
|
@@ -29,5 +30,13 @@ export class GeospatialCameraInputsManager extends CameraInputsManager {
|
|
|
29
30
|
this.add(new GeospatialCameraMouseWheelInput());
|
|
30
31
|
return this;
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Add mouse wheel input support to the input manager
|
|
35
|
+
* @returns the current input manager
|
|
36
|
+
*/
|
|
37
|
+
addKeyboard() {
|
|
38
|
+
this.add(new GeospatialCameraKeyboardInput());
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
32
41
|
}
|
|
33
42
|
//# sourceMappingURL=geospatialCameraInputsManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatialCameraInputsManager.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCameraInputsManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"geospatialCameraInputsManager.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCameraInputsManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAC3F,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AAEvF;;;GAGG;AACH,MAAM,OAAO,6BAA8B,SAAQ,mBAAqC;IACpF;;;OAGG;IACH,YAAY,MAAwB;QAChC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;IAED;;;OAGG;IACI,QAAQ;QACX,IAAI,CAAC,GAAG,CAAC,IAAI,6BAA6B,EAAE,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACI,aAAa;QAChB,IAAI,CAAC,GAAG,CAAC,IAAI,+BAA+B,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACI,WAAW;QACd,IAAI,CAAC,GAAG,CAAC,IAAI,6BAA6B,EAAE,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ","sourcesContent":["import { CameraInputsManager } from \"./cameraInputsManager\";\r\nimport type { GeospatialCamera } from \"./geospatialCamera\";\r\nimport { GeospatialCameraPointersInput } from \"./Inputs/geospatialCameraPointersInput\";\r\nimport { GeospatialCameraMouseWheelInput } from \"./Inputs/geospatialCameraMouseWheelInput\";\r\nimport { GeospatialCameraKeyboardInput } from \"./Inputs/geospatialCameraKeyboardInput\";\r\n\r\n/**\r\n * Default Inputs manager for the GeospatialCamera.\r\n * It groups all the default supported inputs for ease of use.\r\n */\r\nexport class GeospatialCameraInputsManager extends CameraInputsManager<GeospatialCamera> {\r\n /**\r\n * Instantiates a new GeospatialCameraInputsManager.\r\n * @param camera Defines the camera the inputs belong to\r\n */\r\n constructor(camera: GeospatialCamera) {\r\n super(camera);\r\n }\r\n\r\n /**\r\n * Add mouse input support to the input manager\r\n * @returns the current input manager\r\n */\r\n public addMouse(): GeospatialCameraInputsManager {\r\n this.add(new GeospatialCameraPointersInput());\r\n return this;\r\n }\r\n\r\n /**\r\n * Add mouse wheel input support to the input manager\r\n * @returns the current input manager\r\n */\r\n public addMouseWheel(): GeospatialCameraInputsManager {\r\n this.add(new GeospatialCameraMouseWheelInput());\r\n return this;\r\n }\r\n\r\n /**\r\n * Add mouse wheel input support to the input manager\r\n * @returns the current input manager\r\n */\r\n public addKeyboard(): GeospatialCameraInputsManager {\r\n this.add(new GeospatialCameraKeyboardInput());\r\n return this;\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CameraMovement } from "./cameraMovement.js";
|
|
2
|
+
import type { GeospatialLimits } from "./Limits/geospatialLimits.js";
|
|
3
|
+
import { Vector3 } from "../Maths/math.vector.js";
|
|
4
|
+
import type { MeshPredicate } from "../Culling/ray.core.js";
|
|
5
|
+
import type { Scene } from "../scene.js";
|
|
6
|
+
import type { PickingInfo } from "../Collisions/pickingInfo.js";
|
|
7
|
+
import type { Nullable } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* @experimental
|
|
10
|
+
* This class is subject to change as the geospatial camera evolves.
|
|
11
|
+
*
|
|
12
|
+
* Geospatial-specific camera movement system that extends the base movement with
|
|
13
|
+
* raycasting and altitude-aware zoom constraints.
|
|
14
|
+
*
|
|
15
|
+
* This class encapsulates geospatial camera movement logic:
|
|
16
|
+
* - Dragging in a way which keeps cursor anchored to globe
|
|
17
|
+
* - Latitude-based pan speed dampening
|
|
18
|
+
* - Zoom speed scaling based on distance to center
|
|
19
|
+
* - Raycasting to determine zoom constraints based on terrain/globe
|
|
20
|
+
* - Altitude-based zoom clamping
|
|
21
|
+
* - Zoom direction calculation (towards cursor vs along look vector)
|
|
22
|
+
*/
|
|
23
|
+
export declare class GeospatialCameraMovement extends CameraMovement {
|
|
24
|
+
limits: GeospatialLimits;
|
|
25
|
+
private _cameraCenter;
|
|
26
|
+
private _cameraLookAt;
|
|
27
|
+
/** Predicate function to determine which meshes to pick against (e.g., globe mesh) */
|
|
28
|
+
pickPredicate?: MeshPredicate;
|
|
29
|
+
computedPerFrameZoomVector: Vector3;
|
|
30
|
+
zoomToCursor: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Enables rotation around a specific point, instead of default rotation around center
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
alternateRotationPt?: Vector3;
|
|
36
|
+
private _tempPickingRay;
|
|
37
|
+
private _storedZoomPickDistance;
|
|
38
|
+
private _hitPointRadius?;
|
|
39
|
+
private _dragPlane;
|
|
40
|
+
private _dragPlaneNormal;
|
|
41
|
+
private _dragPlaneOriginPointEcef;
|
|
42
|
+
private _dragPlaneHitPointLocal;
|
|
43
|
+
private _previousDragPlaneHitPointLocal;
|
|
44
|
+
constructor(scene: Scene, limits: GeospatialLimits, cameraPosition: Vector3, _cameraCenter: Vector3, _cameraLookAt: Vector3, pickPredicate?: MeshPredicate);
|
|
45
|
+
startDrag(pointerX: number, pointerY: number): void;
|
|
46
|
+
stopDrag(): void;
|
|
47
|
+
/**
|
|
48
|
+
* The previous drag plane hit point in local space is stored to compute the movement delta.
|
|
49
|
+
* As the drag movement occurs, we will continuously recalculate this point. The delta between the previous and current hit points is the delta we will apply to the camera's localtranslation
|
|
50
|
+
* @param hitPointRadius The distance between the world origin (center of globe) and the initial drag hit point
|
|
51
|
+
* @param ray The ray from the camera to the new cursor location
|
|
52
|
+
* @param localToEcefResult The matrix to convert from local to ECEF space
|
|
53
|
+
*/
|
|
54
|
+
private _recalculateDragPlaneHitPoint;
|
|
55
|
+
handleDrag(pointerX: number, pointerY: number): void;
|
|
56
|
+
/** @override */
|
|
57
|
+
computeCurrentFrameDeltas(): void;
|
|
58
|
+
private _handleZoom;
|
|
59
|
+
private _clampZoomDistance;
|
|
60
|
+
pickAlongVector(vector: Vector3): Nullable<PickingInfo>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper to build east/north/up basis vectors at a world position.
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
export declare function ComputeLocalBasisToRefs(worldPos: Vector3, refEast: Vector3, refNorth: Vector3, refUp: Vector3): void;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { CameraMovement } from "./cameraMovement.js";
|
|
2
|
+
import { Epsilon } from "../Maths/math.constants.js";
|
|
3
|
+
import { Matrix, TmpVectors, Vector3 } from "../Maths/math.vector.js";
|
|
4
|
+
import { Plane } from "../Maths/math.plane.js";
|
|
5
|
+
import { Ray } from "../Culling/ray.js";
|
|
6
|
+
import { Vector3Distance } from "../Maths/math.vector.functions.js";
|
|
7
|
+
/**
|
|
8
|
+
* @experimental
|
|
9
|
+
* This class is subject to change as the geospatial camera evolves.
|
|
10
|
+
*
|
|
11
|
+
* Geospatial-specific camera movement system that extends the base movement with
|
|
12
|
+
* raycasting and altitude-aware zoom constraints.
|
|
13
|
+
*
|
|
14
|
+
* This class encapsulates geospatial camera movement logic:
|
|
15
|
+
* - Dragging in a way which keeps cursor anchored to globe
|
|
16
|
+
* - Latitude-based pan speed dampening
|
|
17
|
+
* - Zoom speed scaling based on distance to center
|
|
18
|
+
* - Raycasting to determine zoom constraints based on terrain/globe
|
|
19
|
+
* - Altitude-based zoom clamping
|
|
20
|
+
* - Zoom direction calculation (towards cursor vs along look vector)
|
|
21
|
+
*/
|
|
22
|
+
export class GeospatialCameraMovement extends CameraMovement {
|
|
23
|
+
constructor(scene, limits, cameraPosition, _cameraCenter, _cameraLookAt, pickPredicate) {
|
|
24
|
+
super(scene, cameraPosition);
|
|
25
|
+
this.limits = limits;
|
|
26
|
+
this._cameraCenter = _cameraCenter;
|
|
27
|
+
this._cameraLookAt = _cameraLookAt;
|
|
28
|
+
this.computedPerFrameZoomVector = new Vector3();
|
|
29
|
+
this.zoomToCursor = true;
|
|
30
|
+
this._hitPointRadius = undefined;
|
|
31
|
+
this._dragPlane = new Plane(0, 0, 0, 0);
|
|
32
|
+
this._dragPlaneNormal = Vector3.Zero();
|
|
33
|
+
this._dragPlaneOriginPointEcef = Vector3.Zero();
|
|
34
|
+
this._dragPlaneHitPointLocal = Vector3.Zero();
|
|
35
|
+
this._previousDragPlaneHitPointLocal = Vector3.Zero();
|
|
36
|
+
this.computedPerFrameZoomVector.copyFrom(this._cameraLookAt);
|
|
37
|
+
this.pickPredicate = pickPredicate;
|
|
38
|
+
this._tempPickingRay = new Ray(this._cameraPosition, this._cameraLookAt);
|
|
39
|
+
this.panInertia = 0;
|
|
40
|
+
this.rotationInertia = 0;
|
|
41
|
+
this.rotationXSpeed = Math.PI / 500; // Move 1/500th of a half circle per pixel
|
|
42
|
+
this.rotationYSpeed = Math.PI / 500; // Move 1/500th of a half circle per pixel
|
|
43
|
+
}
|
|
44
|
+
startDrag(pointerX, pointerY) {
|
|
45
|
+
const pickResult = this._scene.pick(pointerX, pointerY, this.pickPredicate);
|
|
46
|
+
if (pickResult.pickedPoint && pickResult.ray) {
|
|
47
|
+
// Store radius from earth center to pickedPoint, used when calculating drag plane
|
|
48
|
+
this._hitPointRadius = pickResult.pickedPoint.length();
|
|
49
|
+
this._recalculateDragPlaneHitPoint(this._hitPointRadius, pickResult.ray, TmpVectors.Matrix[0]);
|
|
50
|
+
this._previousDragPlaneHitPointLocal.copyFrom(this._dragPlaneHitPointLocal);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
this._hitPointRadius = undefined; // can't drag without a hit on the globe
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
stopDrag() {
|
|
57
|
+
this._hitPointRadius = undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The previous drag plane hit point in local space is stored to compute the movement delta.
|
|
61
|
+
* As the drag movement occurs, we will continuously recalculate this point. The delta between the previous and current hit points is the delta we will apply to the camera's localtranslation
|
|
62
|
+
* @param hitPointRadius The distance between the world origin (center of globe) and the initial drag hit point
|
|
63
|
+
* @param ray The ray from the camera to the new cursor location
|
|
64
|
+
* @param localToEcefResult The matrix to convert from local to ECEF space
|
|
65
|
+
*/
|
|
66
|
+
_recalculateDragPlaneHitPoint(hitPointRadius, ray, localToEcefResult) {
|
|
67
|
+
// Use the camera's geocentric normal to find the dragPlaneOriginPoint which lives at hitPointRadius along the camera's geocentric normal
|
|
68
|
+
this._cameraPosition.normalizeToRef(this._dragPlaneNormal);
|
|
69
|
+
this._dragPlaneNormal.scaleToRef(hitPointRadius, this._dragPlaneOriginPointEcef);
|
|
70
|
+
// The dragPlaneOffsetVector will later be recalculated when drag occurs, and the delta between the offset vectors will be applied to localTranslation
|
|
71
|
+
ComputeLocalBasisToRefs(this._dragPlaneOriginPointEcef, TmpVectors.Vector3[0], TmpVectors.Vector3[1], TmpVectors.Vector3[2]);
|
|
72
|
+
const localToEcef = Matrix.FromXYZAxesToRef(TmpVectors.Vector3[0], TmpVectors.Vector3[1], TmpVectors.Vector3[2], localToEcefResult);
|
|
73
|
+
localToEcef.setTranslationFromFloats(this._dragPlaneOriginPointEcef.x, this._dragPlaneOriginPointEcef.y, this._dragPlaneOriginPointEcef.z);
|
|
74
|
+
const ecefToLocal = localToEcef.invertToRef(TmpVectors.Matrix[1]);
|
|
75
|
+
// Now create a plane at that point, perpendicular to the camera's geocentric normal
|
|
76
|
+
Plane.FromPositionAndNormalToRef(this._dragPlaneOriginPointEcef, this._dragPlaneNormal, this._dragPlane);
|
|
77
|
+
// Lastly, find the _dragPlaneHitPoint where the ray intersects the _dragPlane.
|
|
78
|
+
if (IntersectRayWithPlaneToRef(ray, this._dragPlane, this._dragPlaneHitPointLocal)) {
|
|
79
|
+
// If hit, convert the drag plane hit point into the local space.
|
|
80
|
+
Vector3.TransformCoordinatesToRef(this._dragPlaneHitPointLocal, ecefToLocal, this._dragPlaneHitPointLocal);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
handleDrag(pointerX, pointerY) {
|
|
84
|
+
if (this._hitPointRadius) {
|
|
85
|
+
const pickResult = this._scene.pick(pointerX, pointerY);
|
|
86
|
+
if (pickResult.ray) {
|
|
87
|
+
const localToEcef = TmpVectors.Matrix[0];
|
|
88
|
+
this._recalculateDragPlaneHitPoint(this._hitPointRadius, pickResult.ray, localToEcef);
|
|
89
|
+
const delta = this._dragPlaneHitPointLocal.subtractToRef(this._previousDragPlaneHitPointLocal, TmpVectors.Vector3[6]);
|
|
90
|
+
this._previousDragPlaneHitPointLocal.copyFrom(this._dragPlaneHitPointLocal);
|
|
91
|
+
Vector3.TransformNormalToRef(delta, localToEcef, delta);
|
|
92
|
+
this._dragPlaneOriginPointEcef.addInPlace(delta);
|
|
93
|
+
this.panAccumulatedPixels.subtractInPlace(delta);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** @override */
|
|
98
|
+
computeCurrentFrameDeltas() {
|
|
99
|
+
const cameraCenter = this._cameraCenter;
|
|
100
|
+
// If a pan drag is occurring, stop zooming.
|
|
101
|
+
const isDragging = this._hitPointRadius !== undefined;
|
|
102
|
+
if (isDragging) {
|
|
103
|
+
this._zoomSpeedMultiplier = 0;
|
|
104
|
+
this._zoomVelocity = 0;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Scales zoom movement speed based on camera distance to origin (so long as no active pan is occurring)
|
|
108
|
+
this._zoomSpeedMultiplier = Vector3Distance(this._cameraPosition, cameraCenter) * 0.01;
|
|
109
|
+
}
|
|
110
|
+
// Before zero-ing out pixel deltas, capture if we have any active zoom in this frame (compared to zoom from inertia)
|
|
111
|
+
const activeZoom = Math.abs(this.zoomAccumulatedPixels) > 0;
|
|
112
|
+
super.computeCurrentFrameDeltas();
|
|
113
|
+
this._handleZoom(activeZoom);
|
|
114
|
+
}
|
|
115
|
+
_handleZoom(activeZoom) {
|
|
116
|
+
if (Math.abs(this.zoomDeltaCurrentFrame) > Epsilon) {
|
|
117
|
+
let pickDistance;
|
|
118
|
+
if (!activeZoom) {
|
|
119
|
+
// During inertia, use the previously stored pick distance
|
|
120
|
+
// TODO fix this to work with raycasting
|
|
121
|
+
pickDistance = this._storedZoomPickDistance;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Active zoom - pick and store the distance
|
|
125
|
+
const pickResult = this._scene.pick(this._scene.pointerX, this._scene.pointerY, this.pickPredicate);
|
|
126
|
+
if (pickResult.hit && pickResult.pickedPoint && pickResult.ray && this.zoomToCursor) {
|
|
127
|
+
// Store both the zoom direction and the pick distance for use during inertia
|
|
128
|
+
pickResult.ray.direction.normalizeToRef(this.computedPerFrameZoomVector);
|
|
129
|
+
pickDistance = pickResult.distance;
|
|
130
|
+
this._storedZoomPickDistance = pickDistance;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// If no hit under cursor, zoom along lookVector instead
|
|
134
|
+
this._cameraLookAt.normalizeToRef(this.computedPerFrameZoomVector);
|
|
135
|
+
const lookPickResult = this.pickAlongVector(this.computedPerFrameZoomVector);
|
|
136
|
+
pickDistance = lookPickResult?.distance;
|
|
137
|
+
this._storedZoomPickDistance = pickDistance;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Clamp distance based on limits and update center
|
|
141
|
+
this._clampZoomDistance(this.zoomDeltaCurrentFrame, pickDistance);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
_clampZoomDistance(requestedDistance, pickResultDistance) {
|
|
145
|
+
// If pickResult is defined
|
|
146
|
+
if (requestedDistance > 0) {
|
|
147
|
+
if (pickResultDistance !== undefined) {
|
|
148
|
+
// If there is a pick, allow movement up to pick - minAltitude
|
|
149
|
+
if (pickResultDistance - this.limits.altitudeMin < 0) {
|
|
150
|
+
this.zoomDeltaCurrentFrame = 0;
|
|
151
|
+
}
|
|
152
|
+
this.zoomDeltaCurrentFrame = Math.min(requestedDistance, pickResultDistance - this.limits.altitudeMin);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
this.zoomDeltaCurrentFrame = requestedDistance;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (requestedDistance < 0) {
|
|
159
|
+
const maxZoomOut = this.limits.radiusMax ? this.limits.radiusMax - this._cameraPosition.length() : Number.POSITIVE_INFINITY;
|
|
160
|
+
this.zoomDeltaCurrentFrame = Math.max(requestedDistance, -maxZoomOut);
|
|
161
|
+
}
|
|
162
|
+
return this.zoomDeltaCurrentFrame;
|
|
163
|
+
}
|
|
164
|
+
pickAlongVector(vector) {
|
|
165
|
+
this._tempPickingRay.origin.copyFrom(this._cameraPosition);
|
|
166
|
+
this._tempPickingRay.direction.copyFrom(vector);
|
|
167
|
+
return this._scene.pickWithRay(this._tempPickingRay, this.pickPredicate);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function IntersectRayWithPlaneToRef(ray, plane, ref) {
|
|
171
|
+
// Distance along the ray to the plane; null if no hit
|
|
172
|
+
const dist = ray.intersectsPlane(plane);
|
|
173
|
+
if (dist !== null && dist >= 0) {
|
|
174
|
+
ray.origin.addToRef(ray.direction.scaleToRef(dist, TmpVectors.Vector3[0]), ref);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Helper to build east/north/up basis vectors at a world position.
|
|
181
|
+
* @internal
|
|
182
|
+
*/
|
|
183
|
+
export function ComputeLocalBasisToRefs(worldPos, refEast, refNorth, refUp) {
|
|
184
|
+
// up = normalized position (geocentric normal)
|
|
185
|
+
refUp.copyFrom(worldPos).normalize();
|
|
186
|
+
// east = normalize(worldNorth × up)
|
|
187
|
+
// (cross product of Earth rotation axis with up gives east except near poles)
|
|
188
|
+
const worldNorth = Vector3.LeftHandedForwardReadOnly; // (0,0,1)
|
|
189
|
+
Vector3.CrossToRef(worldNorth, refUp, refEast);
|
|
190
|
+
// at poles, cross with worldRight instead
|
|
191
|
+
if (refEast.lengthSquared() < Epsilon) {
|
|
192
|
+
Vector3.CrossToRef(Vector3.Right(), refUp, refEast);
|
|
193
|
+
}
|
|
194
|
+
refEast.normalize();
|
|
195
|
+
// north = up × east (completes right-handed basis)
|
|
196
|
+
Vector3.CrossToRef(refUp, refEast, refNorth);
|
|
197
|
+
refNorth.normalize();
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=geospatialCameraMovement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geospatialCameraMovement.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCameraMovement.ts"],"names":[],"mappings":"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","sourcesContent":["import { CameraMovement } from \"./cameraMovement\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport type { GeospatialLimits } from \"./Limits/geospatialLimits\";\r\nimport { Matrix, TmpVectors, Vector3 } from \"../Maths/math.vector\";\r\nimport type { MeshPredicate } from \"../Culling/ray.core\";\r\nimport { Plane } from \"../Maths/math.plane\";\r\nimport { Ray } from \"../Culling/ray\";\r\nimport type { Scene } from \"../scene\";\r\nimport { Vector3Distance } from \"../Maths/math.vector.functions\";\r\nimport type { PickingInfo } from \"../Collisions/pickingInfo\";\r\nimport type { Nullable } from \"../types\";\r\n\r\n/**\r\n * @experimental\r\n * This class is subject to change as the geospatial camera evolves.\r\n *\r\n * Geospatial-specific camera movement system that extends the base movement with\r\n * raycasting and altitude-aware zoom constraints.\r\n *\r\n * This class encapsulates geospatial camera movement logic:\r\n * - Dragging in a way which keeps cursor anchored to globe\r\n * - Latitude-based pan speed dampening\r\n * - Zoom speed scaling based on distance to center\r\n * - Raycasting to determine zoom constraints based on terrain/globe\r\n * - Altitude-based zoom clamping\r\n * - Zoom direction calculation (towards cursor vs along look vector)\r\n */\r\nexport class GeospatialCameraMovement extends CameraMovement {\r\n /** Predicate function to determine which meshes to pick against (e.g., globe mesh) */\r\n public pickPredicate?: MeshPredicate;\r\n public computedPerFrameZoomVector: Vector3 = new Vector3();\r\n\r\n public zoomToCursor: boolean = true;\r\n\r\n /**\r\n * Enables rotation around a specific point, instead of default rotation around center\r\n * @internal\r\n */\r\n public alternateRotationPt?: Vector3;\r\n\r\n private _tempPickingRay: Ray;\r\n private _storedZoomPickDistance: number | undefined;\r\n\r\n private _hitPointRadius?: number = undefined;\r\n private _dragPlane: Plane = new Plane(0, 0, 0, 0);\r\n private _dragPlaneNormal: Vector3 = Vector3.Zero();\r\n private _dragPlaneOriginPointEcef: Vector3 = Vector3.Zero();\r\n private _dragPlaneHitPointLocal: Vector3 = Vector3.Zero();\r\n private _previousDragPlaneHitPointLocal: Vector3 = Vector3.Zero();\r\n\r\n constructor(\r\n scene: Scene,\r\n public limits: GeospatialLimits,\r\n cameraPosition: Vector3,\r\n private _cameraCenter: Vector3,\r\n private _cameraLookAt: Vector3,\r\n pickPredicate?: MeshPredicate\r\n ) {\r\n super(scene, cameraPosition);\r\n this.computedPerFrameZoomVector.copyFrom(this._cameraLookAt);\r\n this.pickPredicate = pickPredicate;\r\n this._tempPickingRay = new Ray(this._cameraPosition, this._cameraLookAt);\r\n this.panInertia = 0;\r\n this.rotationInertia = 0;\r\n this.rotationXSpeed = Math.PI / 500; // Move 1/500th of a half circle per pixel\r\n this.rotationYSpeed = Math.PI / 500; // Move 1/500th of a half circle per pixel\r\n }\r\n\r\n public startDrag(pointerX: number, pointerY: number) {\r\n const pickResult = this._scene.pick(pointerX, pointerY, this.pickPredicate);\r\n if (pickResult.pickedPoint && pickResult.ray) {\r\n // Store radius from earth center to pickedPoint, used when calculating drag plane\r\n this._hitPointRadius = pickResult.pickedPoint.length();\r\n\r\n this._recalculateDragPlaneHitPoint(this._hitPointRadius, pickResult.ray, TmpVectors.Matrix[0]);\r\n this._previousDragPlaneHitPointLocal.copyFrom(this._dragPlaneHitPointLocal);\r\n } else {\r\n this._hitPointRadius = undefined; // can't drag without a hit on the globe\r\n }\r\n }\r\n\r\n public stopDrag() {\r\n this._hitPointRadius = undefined;\r\n }\r\n\r\n /**\r\n * The previous drag plane hit point in local space is stored to compute the movement delta.\r\n * As the drag movement occurs, we will continuously recalculate this point. The delta between the previous and current hit points is the delta we will apply to the camera's localtranslation\r\n * @param hitPointRadius The distance between the world origin (center of globe) and the initial drag hit point\r\n * @param ray The ray from the camera to the new cursor location\r\n * @param localToEcefResult The matrix to convert from local to ECEF space\r\n */\r\n private _recalculateDragPlaneHitPoint(hitPointRadius: number, ray: Ray, localToEcefResult: Matrix): void {\r\n // Use the camera's geocentric normal to find the dragPlaneOriginPoint which lives at hitPointRadius along the camera's geocentric normal\r\n this._cameraPosition.normalizeToRef(this._dragPlaneNormal);\r\n this._dragPlaneNormal.scaleToRef(hitPointRadius, this._dragPlaneOriginPointEcef);\r\n\r\n // The dragPlaneOffsetVector will later be recalculated when drag occurs, and the delta between the offset vectors will be applied to localTranslation\r\n ComputeLocalBasisToRefs(this._dragPlaneOriginPointEcef, TmpVectors.Vector3[0], TmpVectors.Vector3[1], TmpVectors.Vector3[2]);\r\n const localToEcef = Matrix.FromXYZAxesToRef(TmpVectors.Vector3[0], TmpVectors.Vector3[1], TmpVectors.Vector3[2], localToEcefResult);\r\n localToEcef.setTranslationFromFloats(this._dragPlaneOriginPointEcef.x, this._dragPlaneOriginPointEcef.y, this._dragPlaneOriginPointEcef.z);\r\n const ecefToLocal = localToEcef.invertToRef(TmpVectors.Matrix[1]);\r\n\r\n // Now create a plane at that point, perpendicular to the camera's geocentric normal\r\n Plane.FromPositionAndNormalToRef(this._dragPlaneOriginPointEcef, this._dragPlaneNormal, this._dragPlane);\r\n\r\n // Lastly, find the _dragPlaneHitPoint where the ray intersects the _dragPlane.\r\n if (IntersectRayWithPlaneToRef(ray, this._dragPlane, this._dragPlaneHitPointLocal)) {\r\n // If hit, convert the drag plane hit point into the local space.\r\n Vector3.TransformCoordinatesToRef(this._dragPlaneHitPointLocal, ecefToLocal, this._dragPlaneHitPointLocal);\r\n }\r\n }\r\n\r\n public handleDrag(pointerX: number, pointerY: number) {\r\n if (this._hitPointRadius) {\r\n const pickResult = this._scene.pick(pointerX, pointerY);\r\n if (pickResult.ray) {\r\n const localToEcef = TmpVectors.Matrix[0];\r\n this._recalculateDragPlaneHitPoint(this._hitPointRadius, pickResult.ray, localToEcef);\r\n\r\n const delta = this._dragPlaneHitPointLocal.subtractToRef(this._previousDragPlaneHitPointLocal, TmpVectors.Vector3[6]);\r\n this._previousDragPlaneHitPointLocal.copyFrom(this._dragPlaneHitPointLocal);\r\n\r\n Vector3.TransformNormalToRef(delta, localToEcef, delta);\r\n this._dragPlaneOriginPointEcef.addInPlace(delta);\r\n\r\n this.panAccumulatedPixels.subtractInPlace(delta);\r\n }\r\n }\r\n }\r\n\r\n /** @override */\r\n public override computeCurrentFrameDeltas(): void {\r\n const cameraCenter = this._cameraCenter;\r\n\r\n // If a pan drag is occurring, stop zooming.\r\n const isDragging = this._hitPointRadius !== undefined;\r\n if (isDragging) {\r\n this._zoomSpeedMultiplier = 0;\r\n this._zoomVelocity = 0;\r\n } else {\r\n // Scales zoom movement speed based on camera distance to origin (so long as no active pan is occurring)\r\n this._zoomSpeedMultiplier = Vector3Distance(this._cameraPosition, cameraCenter) * 0.01;\r\n }\r\n\r\n // Before zero-ing out pixel deltas, capture if we have any active zoom in this frame (compared to zoom from inertia)\r\n const activeZoom = Math.abs(this.zoomAccumulatedPixels) > 0;\r\n super.computeCurrentFrameDeltas();\r\n\r\n this._handleZoom(activeZoom);\r\n }\r\n\r\n private _handleZoom(activeZoom: boolean) {\r\n if (Math.abs(this.zoomDeltaCurrentFrame) > Epsilon) {\r\n let pickDistance: number | undefined;\r\n\r\n if (!activeZoom) {\r\n // During inertia, use the previously stored pick distance\r\n // TODO fix this to work with raycasting\r\n pickDistance = this._storedZoomPickDistance;\r\n } else {\r\n // Active zoom - pick and store the distance\r\n const pickResult = this._scene.pick(this._scene.pointerX, this._scene.pointerY, this.pickPredicate);\r\n\r\n if (pickResult.hit && pickResult.pickedPoint && pickResult.ray && this.zoomToCursor) {\r\n // Store both the zoom direction and the pick distance for use during inertia\r\n pickResult.ray.direction.normalizeToRef(this.computedPerFrameZoomVector);\r\n pickDistance = pickResult.distance;\r\n this._storedZoomPickDistance = pickDistance;\r\n } else {\r\n // If no hit under cursor, zoom along lookVector instead\r\n this._cameraLookAt.normalizeToRef(this.computedPerFrameZoomVector);\r\n const lookPickResult = this.pickAlongVector(this.computedPerFrameZoomVector);\r\n pickDistance = lookPickResult?.distance;\r\n this._storedZoomPickDistance = pickDistance;\r\n }\r\n }\r\n\r\n // Clamp distance based on limits and update center\r\n this._clampZoomDistance(this.zoomDeltaCurrentFrame, pickDistance);\r\n }\r\n }\r\n\r\n private _clampZoomDistance(requestedDistance: number, pickResultDistance: number | undefined): number {\r\n // If pickResult is defined\r\n if (requestedDistance > 0) {\r\n if (pickResultDistance !== undefined) {\r\n // If there is a pick, allow movement up to pick - minAltitude\r\n if (pickResultDistance - this.limits.altitudeMin < 0) {\r\n this.zoomDeltaCurrentFrame = 0;\r\n }\r\n this.zoomDeltaCurrentFrame = Math.min(requestedDistance, pickResultDistance - this.limits.altitudeMin);\r\n } else {\r\n this.zoomDeltaCurrentFrame = requestedDistance;\r\n }\r\n }\r\n\r\n if (requestedDistance < 0) {\r\n const maxZoomOut = this.limits.radiusMax ? this.limits.radiusMax - this._cameraPosition.length() : Number.POSITIVE_INFINITY;\r\n this.zoomDeltaCurrentFrame = Math.max(requestedDistance, -maxZoomOut);\r\n }\r\n\r\n return this.zoomDeltaCurrentFrame;\r\n }\r\n\r\n public pickAlongVector(vector: Vector3): Nullable<PickingInfo> {\r\n this._tempPickingRay.origin.copyFrom(this._cameraPosition);\r\n this._tempPickingRay.direction.copyFrom(vector);\r\n return this._scene.pickWithRay(this._tempPickingRay, this.pickPredicate);\r\n }\r\n}\r\n\r\nfunction IntersectRayWithPlaneToRef(ray: Ray, plane: Plane, ref: Vector3): boolean {\r\n // Distance along the ray to the plane; null if no hit\r\n const dist = ray.intersectsPlane(plane);\r\n\r\n if (dist !== null && dist >= 0) {\r\n ray.origin.addToRef(ray.direction.scaleToRef(dist, TmpVectors.Vector3[0]), ref);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Helper to build east/north/up basis vectors at a world position.\r\n * @internal\r\n */\r\nexport function ComputeLocalBasisToRefs(worldPos: Vector3, refEast: Vector3, refNorth: Vector3, refUp: Vector3) {\r\n // up = normalized position (geocentric normal)\r\n refUp.copyFrom(worldPos).normalize();\r\n\r\n // east = normalize(worldNorth × up)\r\n // (cross product of Earth rotation axis with up gives east except near poles)\r\n const worldNorth = Vector3.LeftHandedForwardReadOnly; // (0,0,1)\r\n Vector3.CrossToRef(worldNorth, refUp, refEast);\r\n\r\n // at poles, cross with worldRight instead\r\n if (refEast.lengthSquared() < Epsilon) {\r\n Vector3.CrossToRef(Vector3.Right(), refUp, refEast);\r\n }\r\n refEast.normalize();\r\n\r\n // north = up × east (completes right-handed basis)\r\n Vector3.CrossToRef(refUp, refEast, refNorth);\r\n refNorth.normalize();\r\n}\r\n"]}
|
|
@@ -30,7 +30,7 @@ export declare class TargetCamera extends Camera {
|
|
|
30
30
|
/**
|
|
31
31
|
* Define the current rotation of the camera as a quaternion to prevent Gimbal lock
|
|
32
32
|
*/
|
|
33
|
-
rotationQuaternion: Quaternion
|
|
33
|
+
rotationQuaternion: Nullable<Quaternion>;
|
|
34
34
|
/**
|
|
35
35
|
* Define the current speed of the camera
|
|
36
36
|
*/
|
package/Cameras/targetCamera.js
CHANGED
|
@@ -144,7 +144,7 @@ export class TargetCamera extends Camera {
|
|
|
144
144
|
}
|
|
145
145
|
this.position = this._storedPosition.clone();
|
|
146
146
|
this.rotation = this._storedRotation.clone();
|
|
147
|
-
if (this.rotationQuaternion) {
|
|
147
|
+
if (this.rotationQuaternion && this._storedRotationQuaternion) {
|
|
148
148
|
this.rotationQuaternion = this._storedRotationQuaternion.clone();
|
|
149
149
|
}
|
|
150
150
|
this.cameraDirection.copyFromFloats(0, 0, 0);
|
|
@@ -453,7 +453,7 @@ export class TargetCamera extends Camera {
|
|
|
453
453
|
break;
|
|
454
454
|
}
|
|
455
455
|
case Camera.RIG_MODE_VR:
|
|
456
|
-
if (camLeft.rotationQuaternion) {
|
|
456
|
+
if (camLeft.rotationQuaternion && camRight.rotationQuaternion && this.rotationQuaternion) {
|
|
457
457
|
camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
|
|
458
458
|
camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
|
|
459
459
|
}
|