@onerjs/core 8.36.7 → 8.36.9
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/Audio/analyser.js.map +1 -1
- package/AudioV2/webAudio/subNodes/webAudioAnalyzerSubNode.js.map +1 -1
- package/Behaviors/Cameras/geospatialClippingBehavior.d.ts +3 -4
- package/Behaviors/Cameras/geospatialClippingBehavior.js +9 -14
- package/Behaviors/Cameras/geospatialClippingBehavior.js.map +1 -1
- package/Buffers/buffer.align.js +3 -3
- package/Buffers/buffer.align.js.map +1 -1
- package/Buffers/bufferUtils.d.ts +7 -0
- package/Buffers/bufferUtils.js +31 -13
- package/Buffers/bufferUtils.js.map +1 -1
- package/Cameras/Inputs/geospatialCameraPointersInput.js +2 -2
- package/Cameras/Inputs/geospatialCameraPointersInput.js.map +1 -1
- package/Cameras/Limits/geospatialLimits.d.ts +16 -0
- package/Cameras/Limits/geospatialLimits.js +38 -1
- package/Cameras/Limits/geospatialLimits.js.map +1 -1
- package/Cameras/geospatialCamera.d.ts +10 -9
- package/Cameras/geospatialCamera.js +5 -8
- package/Cameras/geospatialCamera.js.map +1 -1
- package/Cameras/geospatialCameraMovement.d.ts +1 -3
- package/Cameras/geospatialCameraMovement.js +9 -4
- package/Cameras/geospatialCameraMovement.js.map +1 -1
- package/Engines/Extensions/engine.dynamicBuffer.js +3 -3
- package/Engines/Extensions/engine.dynamicBuffer.js.map +1 -1
- package/Engines/Native/nativeDataStream.d.ts +1 -1
- package/Engines/Native/nativeDataStream.js.map +1 -1
- package/Engines/Native/nativeInterfaces.d.ts +4 -4
- package/Engines/Native/nativeInterfaces.js.map +1 -1
- package/Engines/WebGPU/Extensions/engine.rawTexture.d.ts +13 -1
- package/Engines/WebGPU/Extensions/engine.rawTexture.js +26 -8
- package/Engines/WebGPU/Extensions/engine.rawTexture.js.map +1 -1
- package/Engines/WebGPU/webgpuTextureManager.d.ts +2 -1
- package/Engines/WebGPU/webgpuTextureManager.js +19 -6
- package/Engines/WebGPU/webgpuTextureManager.js.map +1 -1
- package/Engines/abstractEngine.d.ts +4 -2
- package/Engines/abstractEngine.functions.d.ts +1 -1
- package/Engines/abstractEngine.functions.js +8 -8
- package/Engines/abstractEngine.functions.js.map +1 -1
- package/Engines/abstractEngine.js +6 -4
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/engine.d.ts +12 -0
- package/Engines/thinNativeEngine.js +1 -1
- package/Engines/thinNativeEngine.js.map +1 -1
- package/Engines/thinWebGPUEngine.js +3 -0
- package/Engines/thinWebGPUEngine.js.map +1 -1
- package/Engines/webgpuEngine.js +18 -18
- package/Engines/webgpuEngine.js.map +1 -1
- package/Lights/Clustered/clusteredLightContainer.js.map +1 -1
- package/Materials/Background/backgroundMaterial.d.ts +16 -8
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js +14 -1
- package/Materials/GaussianSplatting/gaussianSplattingMaterial.js.map +1 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js +1 -1
- package/Materials/Node/Blocks/Fragment/fragmentOutputBlock.js.map +1 -1
- package/Materials/Node/Blocks/Input/inputBlock.js +14 -0
- package/Materials/Node/Blocks/Input/inputBlock.js.map +1 -1
- package/Materials/Node/Blocks/debugBlock.d.ts +2 -0
- package/Materials/Node/Blocks/debugBlock.js +6 -2
- package/Materials/Node/Blocks/debugBlock.js.map +1 -1
- package/Materials/Node/Enums/nodeMaterialSystemValues.d.ts +3 -1
- package/Materials/Node/Enums/nodeMaterialSystemValues.js +2 -0
- package/Materials/Node/Enums/nodeMaterialSystemValues.js.map +1 -1
- package/Materials/Node/nodeMaterial.d.ts +16 -8
- package/Materials/Node/nodeMaterialBlock.js +2 -2
- package/Materials/Node/nodeMaterialBlock.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.d.ts +16 -8
- package/Materials/PBR/pbrBaseMaterial.d.ts +16 -8
- package/Materials/Textures/Loaders/EXR/exrLoader.compression.rle.d.ts +1 -1
- package/Materials/Textures/Loaders/EXR/exrLoader.compression.rle.js.map +1 -1
- package/Materials/Textures/Loaders/EXR/exrLoader.core.d.ts +1 -1
- package/Materials/Textures/Loaders/EXR/exrLoader.core.js.map +1 -1
- package/Materials/Textures/internalTexture.d.ts +6 -0
- package/Materials/Textures/internalTexture.js +24 -2
- package/Materials/Textures/internalTexture.js.map +1 -1
- package/Materials/Textures/rawTexture.d.ts +8 -1
- package/Materials/Textures/rawTexture.js +12 -3
- package/Materials/Textures/rawTexture.js.map +1 -1
- package/Materials/Textures/rawTexture2DArray.d.ts +8 -1
- package/Materials/Textures/rawTexture2DArray.js +14 -3
- package/Materials/Textures/rawTexture2DArray.js.map +1 -1
- package/Materials/imageProcessing.d.ts +47 -8
- package/Materials/standardMaterial.d.ts +16 -8
- package/Meshes/Builders/shapeBuilder.d.ts +4 -0
- package/Meshes/Builders/shapeBuilder.js +12 -9
- package/Meshes/Builders/shapeBuilder.js.map +1 -1
- package/Meshes/Builders/tubeBuilder.d.ts +2 -0
- package/Meshes/Builders/tubeBuilder.js +19 -2
- package/Meshes/Builders/tubeBuilder.js.map +1 -1
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.d.ts +68 -4
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js +349 -30
- package/Meshes/GaussianSplatting/gaussianSplattingMesh.js.map +1 -1
- package/Meshes/geometry.js +15 -2
- package/Meshes/geometry.js.map +1 -1
- package/Meshes/mesh.js +23 -21
- package/Meshes/mesh.js.map +1 -1
- package/Misc/dds.js.map +1 -1
- package/Misc/environmentTextureTools.js +3 -1
- package/Misc/environmentTextureTools.js.map +1 -1
- package/Misc/fileTools.js +9 -1
- package/Misc/fileTools.js.map +1 -1
- package/Particles/Node/nodeParticleSystemSet.helper.js +2 -2
- package/Particles/Node/nodeParticleSystemSet.helper.js.map +1 -1
- package/Physics/v1/physicsImpostor.d.ts +2 -2
- package/Physics/v1/physicsImpostor.js.map +1 -1
- package/Shaders/ShadersInclude/gaussianSplatting.js +16 -3
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/gaussianSplatting.vertex.js +17 -4
- package/Shaders/gaussianSplatting.vertex.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +11 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +17 -4
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/XR/native/nativeXRFrame.d.ts +1 -1
- package/XR/native/nativeXRFrame.js.map +1 -1
- package/package.json +1 -1
- package/types.d.ts +1 -1
- package/types.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatialCameraPointersInput.js","sourceRoot":"","sources":["../../../../../dev/core/src/Cameras/Inputs/geospatialCameraPointersInput.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GeospatialCamera } from \"../../Cameras/geospatialCamera\";\r\nimport type { IPointerEvent } from \"../../Events/deviceInputEvents\";\r\nimport type { PointerTouch } from \"../../Events/pointerEvents\";\r\nimport type { Nullable } from \"../../types\";\r\nimport { OrbitCameraPointersInput } from \"./orbitCameraPointersInput\";\r\n\r\n/**\r\n * @experimental\r\n * Geospatial camera inputs can simulate dragging the globe around or tilting the camera around some point on the globe\r\n * This class will update the GeospatialCameraMovement class's movementDeltaCurrentFrame, and the camera is responsible for using these updates to calculate viewMatrix appropriately\r\n *\r\n * As of right now, the camera correction logic (to keep the camera geospatially oriented around the globe) is happening within the camera class when calculating viewmatrix\r\n * As this is experimental, it is possible we move that correction step to live within the input class (to enable non-corrected translations in the future), say if we want to allow the camera to move outside of the globe's orbit\r\n *\r\n * Left mouse button: drag globe\r\n * Middle mouse button: tilt globe\r\n * Right mouse button: tilt globe\r\n *\r\n */\r\nexport class GeospatialCameraPointersInput extends OrbitCameraPointersInput {\r\n public camera: GeospatialCamera;\r\n\r\n private _initialPinchSquaredDistance: number = 0;\r\n private _pinchCentroid: Nullable<PointerTouch> = null;\r\n\r\n public override getClassName(): string {\r\n return \"GeospatialCameraPointersInput\";\r\n }\r\n\r\n public override onButtonDown(evt: IPointerEvent): void {\r\n this.camera.movement.activeInput = true;\r\n const scene = this.camera.getScene();\r\n switch (evt.button) {\r\n case 0: // Left button - drag/pan globe under cursor\r\n this.camera.movement.startDrag(scene.pointerX, scene.pointerY);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n public override onTouch(point: Nullable<PointerTouch>, offsetX: number, offsetY: number): void {\r\n // Single finger touch (no button property) or left button (button 0) = drag\r\n const button = point?.button ?? 0; // Default to button 0 (drag) if undefined\r\n const scene = this.camera.getScene();\r\n switch (button) {\r\n case 0: // Left button / single touch - drag/pan globe under cursor\r\n this.camera.movement.handleDrag(scene.pointerX, scene.pointerY);\r\n break;\r\n case 1: // Middle button - tilt camera\r\n case 2: // Right button - tilt camera\r\n this._handleTilt(offsetX, offsetY);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Move camera from multitouch (pinch) zoom distances.\r\n * Zooms towards the centroid (midpoint between the two fingers).\r\n * @param previousPinchSquaredDistance\r\n * @param pinchSquaredDistance\r\n */\r\n protected override _computePinchZoom(previousPinchSquaredDistance: number, pinchSquaredDistance: number): void {\r\n // Calculate zoom distance based on pinch delta\r\n const previousDistance = Math.sqrt(previousPinchSquaredDistance);\r\n const currentDistance = Math.sqrt(pinchSquaredDistance);\r\n const pinchDelta = currentDistance - previousDistance;\r\n\r\n // Try to zoom towards centroid if we have it\r\n if (this._pinchCentroid) {\r\n const scene = this.camera.getScene();\r\n const engine = scene.getEngine();\r\n const canvasRect = engine.getInputElementClientRect();\r\n\r\n if (canvasRect) {\r\n // Convert centroid from clientX/Y to canvas-relative coordinates (same as scene.pointerX/Y)\r\n const canvasX = this._pinchCentroid.x - canvasRect.left;\r\n const canvasY = this._pinchCentroid.y - canvasRect.top;\r\n\r\n // Pick at centroid\r\n const pickResult = scene.pick(canvasX, canvasY, this.camera.pickPredicate);\r\n if (pickResult?.pickedPoint) {\r\n // Scale zoom by distance to picked point\r\n const distanceToPoint = this.camera.position.subtract(pickResult.pickedPoint).length();\r\n const zoomDistance = pinchDelta * distanceToPoint * 0.005;\r\n const clampedZoom = this.camera.limits.clampZoomDistance(zoomDistance, this.camera.radius, distanceToPoint);\r\n this.camera.zoomToPoint(pickResult.pickedPoint, clampedZoom);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Fallback: scale zoom by camera radius along lookat vector\r\n const zoomDistance = pinchDelta * this.camera.radius * 0.005;\r\n const clampedZoom = this.camera.limits.clampZoomDistance(zoomDistance, this.camera.radius);\r\n this.camera.zoomAlongLookAt(clampedZoom);\r\n }\r\n\r\n /**\r\n * Move camera from multi touch panning positions.\r\n * In geospatialcamera, multi touch panning tilts the globe (whereas single touch will pan/drag it)\r\n * @param previousMultiTouchPanPosition\r\n * @param multiTouchPanPosition\r\n */\r\n protected override _computeMultiTouchPanning(previousMultiTouchPanPosition: Nullable<PointerTouch>, multiTouchPanPosition: Nullable<PointerTouch>): void {\r\n if (previousMultiTouchPanPosition && multiTouchPanPosition) {\r\n const moveDeltaX = multiTouchPanPosition.x - previousMultiTouchPanPosition.x;\r\n const moveDeltaY = multiTouchPanPosition.y - previousMultiTouchPanPosition.y;\r\n this._handleTilt(moveDeltaX, moveDeltaY);\r\n }\r\n }\r\n\r\n public override onDoubleTap(type: string): void {\r\n const pickResult = this.camera._scene.pick(this.camera._scene.pointerX, this.camera._scene.pointerY, this.camera.pickPredicate);\r\n if (pickResult.pickedPoint) {\r\n void this.camera.flyToPointAsync(pickResult.pickedPoint);\r\n }\r\n }\r\n\r\n public override onMultiTouch(\r\n pointA: Nullable<PointerTouch>,\r\n pointB: Nullable<PointerTouch>,\r\n previousPinchSquaredDistance: number,\r\n pinchSquaredDistance: number,\r\n previousMultiTouchPanPosition: Nullable<PointerTouch>,\r\n multiTouchPanPosition: Nullable<PointerTouch>\r\n ): void {\r\n // Store centroid for use in _computePinchZoom (it's already calculated by parent)\r\n this._pinchCentroid = multiTouchPanPosition;\r\n\r\n // Reset on gesture end\r\n if (pinchSquaredDistance === 0 && multiTouchPanPosition === null) {\r\n this._initialPinchSquaredDistance = 0;\r\n this._pinchCentroid = null;\r\n super.onMultiTouch(pointA, pointB, previousPinchSquaredDistance, pinchSquaredDistance, previousMultiTouchPanPosition, multiTouchPanPosition);\r\n return;\r\n }\r\n\r\n // Track initial distance at gesture start for cumulative threshold detection\r\n if (this._initialPinchSquaredDistance === 0 && pinchSquaredDistance !== 0) {\r\n this._initialPinchSquaredDistance = pinchSquaredDistance;\r\n }\r\n\r\n // Use cumulative delta from gesture start for threshold detection (more forgiving than frame-to-frame)\r\n const cumulativeDelta = Math.abs(Math.sqrt(pinchSquaredDistance) - Math.sqrt(this._initialPinchSquaredDistance));\r\n this._shouldStartPinchZoom = this._twoFingerActivityCount < 20 && cumulativeDelta > this.camera.limits.pinchToPanMax;\r\n\r\n super.onMultiTouch(pointA, pointB, previousPinchSquaredDistance, pinchSquaredDistance, previousMultiTouchPanPosition, multiTouchPanPosition);\r\n }\r\n\r\n public override onButtonUp(_evt: IPointerEvent): void {\r\n this.camera.movement.stopDrag();\r\n this.camera.movement.activeInput = false;\r\n this._initialPinchSquaredDistance = 0;\r\n this._pinchCentroid = null;\r\n super.onButtonUp(_evt);\r\n }\r\n\r\n public override onLostFocus(): void {\r\n this._initialPinchSquaredDistance = 0;\r\n this._pinchCentroid = null;\r\n super.onLostFocus();\r\n }\r\n\r\n private _handleTilt(deltaX: number, deltaY: number): void {\r\n this.camera.movement.rotationAccumulatedPixels.y -= deltaX; // yaw - looking side to side\r\n this.camera.movement.rotationAccumulatedPixels.x -= deltaY; // pitch - look up towards sky / down towards ground\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"geospatialCameraPointersInput.js","sourceRoot":"","sources":["../../../../../dev/core/src/Cameras/Inputs/geospatialCameraPointersInput.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAEtE;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,6BAA8B,SAAQ,wBAAwB;IAA3E;;QAGY,iCAA4B,GAAW,CAAC,CAAC;QACzC,mBAAc,GAA2B,IAAI,CAAC;IAiJ1D,CAAC;IA/ImB,YAAY;QACxB,OAAO,+BAA+B,CAAC;IAC3C,CAAC;IAEe,YAAY,CAAC,GAAkB;QAC3C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrC,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;YACjB,KAAK,CAAC,EAAE,4CAA4C;gBAChD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAC/D,MAAM;YACV;gBACI,MAAM;QACd,CAAC;IACL,CAAC;IAEe,OAAO,CAAC,KAA6B,EAAE,OAAe,EAAE,OAAe;QACnF,4EAA4E;QAC5E,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,0CAA0C;QAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrC,QAAQ,MAAM,EAAE,CAAC;YACb,KAAK,CAAC,EAAE,2DAA2D;gBAC/D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAChE,MAAM;YACV,KAAK,CAAC,CAAC,CAAC,8BAA8B;YACtC,KAAK,CAAC,EAAE,6BAA6B;gBACjC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACnC,MAAM;QACd,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACgB,iBAAiB,CAAC,4BAAoC,EAAE,oBAA4B;QACnG,+CAA+C;QAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACjE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,eAAe,GAAG,gBAAgB,CAAC;QAEtD,6CAA6C;QAC7C,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,MAAM,CAAC,yBAAyB,EAAE,CAAC;YAEtD,IAAI,UAAU,EAAE,CAAC;gBACb,4FAA4F;gBAC5F,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC;gBACxD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC;gBAEvD,mBAAmB;gBACnB,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBACpF,IAAI,UAAU,EAAE,WAAW,EAAE,CAAC;oBAC1B,yCAAyC;oBACzC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC;oBACvF,MAAM,YAAY,GAAG,UAAU,GAAG,eAAe,GAAG,KAAK,CAAC;oBAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;oBAC5G,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;oBAC7D,OAAO;gBACX,CAAC;YACL,CAAC;QACL,CAAC;QAED,4DAA4D;QAC5D,MAAM,YAAY,GAAG,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;QAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3F,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;OAKG;IACgB,yBAAyB,CAAC,6BAAqD,EAAE,qBAA6C;QAC7I,IAAI,6BAA6B,IAAI,qBAAqB,EAAE,CAAC;YACzD,MAAM,UAAU,GAAG,qBAAqB,CAAC,CAAC,GAAG,6BAA6B,CAAC,CAAC,CAAC;YAC7E,MAAM,UAAU,GAAG,qBAAqB,CAAC,CAAC,GAAG,6BAA6B,CAAC,CAAC,CAAC;YAC7E,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAC7C,CAAC;IACL,CAAC;IAEe,WAAW,CAAC,IAAY;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACzI,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;YACzB,KAAK,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC7D,CAAC;IACL,CAAC;IAEe,YAAY,CACxB,MAA8B,EAC9B,MAA8B,EAC9B,4BAAoC,EACpC,oBAA4B,EAC5B,6BAAqD,EACrD,qBAA6C;QAE7C,kFAAkF;QAClF,IAAI,CAAC,cAAc,GAAG,qBAAqB,CAAC;QAE5C,uBAAuB;QACvB,IAAI,oBAAoB,KAAK,CAAC,IAAI,qBAAqB,KAAK,IAAI,EAAE,CAAC;YAC/D,IAAI,CAAC,4BAA4B,GAAG,CAAC,CAAC;YACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,6BAA6B,EAAE,qBAAqB,CAAC,CAAC;YAC7I,OAAO;QACX,CAAC;QAED,6EAA6E;QAC7E,IAAI,IAAI,CAAC,4BAA4B,KAAK,CAAC,IAAI,oBAAoB,KAAK,CAAC,EAAE,CAAC;YACxE,IAAI,CAAC,4BAA4B,GAAG,oBAAoB,CAAC;QAC7D,CAAC;QAED,uGAAuG;QACvG,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACjH,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,uBAAuB,GAAG,EAAE,IAAI,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;QAErH,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,6BAA6B,EAAE,qBAAqB,CAAC,CAAC;IACjJ,CAAC;IAEe,UAAU,CAAC,IAAmB;QAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC;QACzC,IAAI,CAAC,4BAA4B,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAEe,WAAW;QACvB,IAAI,CAAC,4BAA4B,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,KAAK,CAAC,WAAW,EAAE,CAAC;IACxB,CAAC;IAEO,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,6BAA6B;QACzF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,oDAAoD;IACpH,CAAC;CACJ","sourcesContent":["import type { GeospatialCamera } from \"../../Cameras/geospatialCamera\";\r\nimport type { IPointerEvent } from \"../../Events/deviceInputEvents\";\r\nimport type { PointerTouch } from \"../../Events/pointerEvents\";\r\nimport type { Nullable } from \"../../types\";\r\nimport { OrbitCameraPointersInput } from \"./orbitCameraPointersInput\";\r\n\r\n/**\r\n * @experimental\r\n * Geospatial camera inputs can simulate dragging the globe around or tilting the camera around some point on the globe\r\n * This class will update the GeospatialCameraMovement class's movementDeltaCurrentFrame, and the camera is responsible for using these updates to calculate viewMatrix appropriately\r\n *\r\n * As of right now, the camera correction logic (to keep the camera geospatially oriented around the globe) is happening within the camera class when calculating viewmatrix\r\n * As this is experimental, it is possible we move that correction step to live within the input class (to enable non-corrected translations in the future), say if we want to allow the camera to move outside of the globe's orbit\r\n *\r\n * Left mouse button: drag globe\r\n * Middle mouse button: tilt globe\r\n * Right mouse button: tilt globe\r\n *\r\n */\r\nexport class GeospatialCameraPointersInput extends OrbitCameraPointersInput {\r\n public camera: GeospatialCamera;\r\n\r\n private _initialPinchSquaredDistance: number = 0;\r\n private _pinchCentroid: Nullable<PointerTouch> = null;\r\n\r\n public override getClassName(): string {\r\n return \"GeospatialCameraPointersInput\";\r\n }\r\n\r\n public override onButtonDown(evt: IPointerEvent): void {\r\n this.camera.movement.activeInput = true;\r\n const scene = this.camera.getScene();\r\n switch (evt.button) {\r\n case 0: // Left button - drag/pan globe under cursor\r\n this.camera.movement.startDrag(scene.pointerX, scene.pointerY);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n public override onTouch(point: Nullable<PointerTouch>, offsetX: number, offsetY: number): void {\r\n // Single finger touch (no button property) or left button (button 0) = drag\r\n const button = point?.button ?? 0; // Default to button 0 (drag) if undefined\r\n const scene = this.camera.getScene();\r\n switch (button) {\r\n case 0: // Left button / single touch - drag/pan globe under cursor\r\n this.camera.movement.handleDrag(scene.pointerX, scene.pointerY);\r\n break;\r\n case 1: // Middle button - tilt camera\r\n case 2: // Right button - tilt camera\r\n this._handleTilt(offsetX, offsetY);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Move camera from multitouch (pinch) zoom distances.\r\n * Zooms towards the centroid (midpoint between the two fingers).\r\n * @param previousPinchSquaredDistance\r\n * @param pinchSquaredDistance\r\n */\r\n protected override _computePinchZoom(previousPinchSquaredDistance: number, pinchSquaredDistance: number): void {\r\n // Calculate zoom distance based on pinch delta\r\n const previousDistance = Math.sqrt(previousPinchSquaredDistance);\r\n const currentDistance = Math.sqrt(pinchSquaredDistance);\r\n const pinchDelta = currentDistance - previousDistance;\r\n\r\n // Try to zoom towards centroid if we have it\r\n if (this._pinchCentroid) {\r\n const scene = this.camera.getScene();\r\n const engine = scene.getEngine();\r\n const canvasRect = engine.getInputElementClientRect();\r\n\r\n if (canvasRect) {\r\n // Convert centroid from clientX/Y to canvas-relative coordinates (same as scene.pointerX/Y)\r\n const canvasX = this._pinchCentroid.x - canvasRect.left;\r\n const canvasY = this._pinchCentroid.y - canvasRect.top;\r\n\r\n // Pick at centroid\r\n const pickResult = scene.pick(canvasX, canvasY, this.camera.movement.pickPredicate);\r\n if (pickResult?.pickedPoint) {\r\n // Scale zoom by distance to picked point\r\n const distanceToPoint = this.camera.position.subtract(pickResult.pickedPoint).length();\r\n const zoomDistance = pinchDelta * distanceToPoint * 0.005;\r\n const clampedZoom = this.camera.limits.clampZoomDistance(zoomDistance, this.camera.radius, distanceToPoint);\r\n this.camera.zoomToPoint(pickResult.pickedPoint, clampedZoom);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Fallback: scale zoom by camera radius along lookat vector\r\n const zoomDistance = pinchDelta * this.camera.radius * 0.005;\r\n const clampedZoom = this.camera.limits.clampZoomDistance(zoomDistance, this.camera.radius);\r\n this.camera.zoomAlongLookAt(clampedZoom);\r\n }\r\n\r\n /**\r\n * Move camera from multi touch panning positions.\r\n * In geospatialcamera, multi touch panning tilts the globe (whereas single touch will pan/drag it)\r\n * @param previousMultiTouchPanPosition\r\n * @param multiTouchPanPosition\r\n */\r\n protected override _computeMultiTouchPanning(previousMultiTouchPanPosition: Nullable<PointerTouch>, multiTouchPanPosition: Nullable<PointerTouch>): void {\r\n if (previousMultiTouchPanPosition && multiTouchPanPosition) {\r\n const moveDeltaX = multiTouchPanPosition.x - previousMultiTouchPanPosition.x;\r\n const moveDeltaY = multiTouchPanPosition.y - previousMultiTouchPanPosition.y;\r\n this._handleTilt(moveDeltaX, moveDeltaY);\r\n }\r\n }\r\n\r\n public override onDoubleTap(type: string): void {\r\n const pickResult = this.camera._scene.pick(this.camera._scene.pointerX, this.camera._scene.pointerY, this.camera.movement.pickPredicate);\r\n if (pickResult.pickedPoint) {\r\n void this.camera.flyToPointAsync(pickResult.pickedPoint);\r\n }\r\n }\r\n\r\n public override onMultiTouch(\r\n pointA: Nullable<PointerTouch>,\r\n pointB: Nullable<PointerTouch>,\r\n previousPinchSquaredDistance: number,\r\n pinchSquaredDistance: number,\r\n previousMultiTouchPanPosition: Nullable<PointerTouch>,\r\n multiTouchPanPosition: Nullable<PointerTouch>\r\n ): void {\r\n // Store centroid for use in _computePinchZoom (it's already calculated by parent)\r\n this._pinchCentroid = multiTouchPanPosition;\r\n\r\n // Reset on gesture end\r\n if (pinchSquaredDistance === 0 && multiTouchPanPosition === null) {\r\n this._initialPinchSquaredDistance = 0;\r\n this._pinchCentroid = null;\r\n super.onMultiTouch(pointA, pointB, previousPinchSquaredDistance, pinchSquaredDistance, previousMultiTouchPanPosition, multiTouchPanPosition);\r\n return;\r\n }\r\n\r\n // Track initial distance at gesture start for cumulative threshold detection\r\n if (this._initialPinchSquaredDistance === 0 && pinchSquaredDistance !== 0) {\r\n this._initialPinchSquaredDistance = pinchSquaredDistance;\r\n }\r\n\r\n // Use cumulative delta from gesture start for threshold detection (more forgiving than frame-to-frame)\r\n const cumulativeDelta = Math.abs(Math.sqrt(pinchSquaredDistance) - Math.sqrt(this._initialPinchSquaredDistance));\r\n this._shouldStartPinchZoom = this._twoFingerActivityCount < 20 && cumulativeDelta > this.camera.limits.pinchToPanMax;\r\n\r\n super.onMultiTouch(pointA, pointB, previousPinchSquaredDistance, pinchSquaredDistance, previousMultiTouchPanPosition, multiTouchPanPosition);\r\n }\r\n\r\n public override onButtonUp(_evt: IPointerEvent): void {\r\n this.camera.movement.stopDrag();\r\n this.camera.movement.activeInput = false;\r\n this._initialPinchSquaredDistance = 0;\r\n this._pinchCentroid = null;\r\n super.onButtonUp(_evt);\r\n }\r\n\r\n public override onLostFocus(): void {\r\n this._initialPinchSquaredDistance = 0;\r\n this._pinchCentroid = null;\r\n super.onLostFocus();\r\n }\r\n\r\n private _handleTilt(deltaX: number, deltaY: number): void {\r\n this.camera.movement.rotationAccumulatedPixels.y -= deltaX; // yaw - looking side to side\r\n this.camera.movement.rotationAccumulatedPixels.x -= deltaY; // pitch - look up towards sky / down towards ground\r\n }\r\n}\r\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Vector2 } from "../../Maths/math.vector.js";
|
|
1
2
|
/**
|
|
2
3
|
* Limits for geospatial camera
|
|
3
4
|
*/
|
|
@@ -9,6 +10,13 @@ export declare class GeospatialLimits {
|
|
|
9
10
|
pitchMin: number;
|
|
10
11
|
/** Gets the maximum pitch angle (angle from horizon) -- Pi/2 means looking at horizon */
|
|
11
12
|
pitchMax: number;
|
|
13
|
+
/**
|
|
14
|
+
* Controls how pitch is disabled as the camera zooms out.
|
|
15
|
+
* x = radius scale at which full pitch is allowed (e.g., 1.5 means 1.5 * planetRadius)
|
|
16
|
+
* y = radius scale at which pitch is fully disabled (forced to pitchMin)
|
|
17
|
+
* Set to undefined to disable this feature.
|
|
18
|
+
*/
|
|
19
|
+
pitchDisabledRadiusScale?: Vector2;
|
|
12
20
|
/** Gets the minimum yaw angle (rotation around up axis) */
|
|
13
21
|
yawMin: number;
|
|
14
22
|
/** Gets the maximum yaw angle (rotation around up axis) */
|
|
@@ -47,4 +55,12 @@ export declare class GeospatialLimits {
|
|
|
47
55
|
* @returns The clamped zoom distance
|
|
48
56
|
*/
|
|
49
57
|
clampZoomDistance(zoomDistance: number, currentRadius: number, distanceToTarget?: number): number;
|
|
58
|
+
/**
|
|
59
|
+
* Computes the effective maximum pitch based on the current camera radius.
|
|
60
|
+
* When pitchDisabledRadiusScale is set, pitch is interpolated from pitchMax to pitchMin
|
|
61
|
+
* as the camera zooms out from x*planetRadius to y*planetRadius.
|
|
62
|
+
* @param currentRadius The current camera radius (distance from planet center)
|
|
63
|
+
* @returns The effective maximum pitch angle
|
|
64
|
+
*/
|
|
65
|
+
getEffectivePitchMax(currentRadius: number): number;
|
|
50
66
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Epsilon } from "../../Maths/math.constants.js";
|
|
2
|
+
import { Vector2 } from "../../Maths/math.vector.js";
|
|
3
|
+
import { Clamp } from "../../Maths/math.scalar.functions.js";
|
|
2
4
|
/**
|
|
3
5
|
* Limits for geospatial camera
|
|
4
6
|
*/
|
|
@@ -12,7 +14,14 @@ export class GeospatialLimits {
|
|
|
12
14
|
/** Gets the minimum pitch angle (angle from horizon) -- 0 means looking straight down at planet */
|
|
13
15
|
this.pitchMin = Epsilon;
|
|
14
16
|
/** Gets the maximum pitch angle (angle from horizon) -- Pi/2 means looking at horizon */
|
|
15
|
-
this.pitchMax = Math.PI / 2 -
|
|
17
|
+
this.pitchMax = Math.PI / 2 - 0.01;
|
|
18
|
+
/**
|
|
19
|
+
* Controls how pitch is disabled as the camera zooms out.
|
|
20
|
+
* x = radius scale at which full pitch is allowed (e.g., 1.5 means 1.5 * planetRadius)
|
|
21
|
+
* y = radius scale at which pitch is fully disabled (forced to pitchMin)
|
|
22
|
+
* Set to undefined to disable this feature.
|
|
23
|
+
*/
|
|
24
|
+
this.pitchDisabledRadiusScale = new Vector2(2, 4);
|
|
16
25
|
/** Gets the minimum yaw angle (rotation around up axis) */
|
|
17
26
|
this.yawMin = -Infinity;
|
|
18
27
|
/** Gets the maximum yaw angle (rotation around up axis) */
|
|
@@ -73,5 +82,33 @@ export class GeospatialLimits {
|
|
|
73
82
|
return Math.max(zoomDistance, -Math.max(0, maxZoomOut));
|
|
74
83
|
}
|
|
75
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Computes the effective maximum pitch based on the current camera radius.
|
|
87
|
+
* When pitchDisabledRadiusScale is set, pitch is interpolated from pitchMax to pitchMin
|
|
88
|
+
* as the camera zooms out from x*planetRadius to y*planetRadius.
|
|
89
|
+
* @param currentRadius The current camera radius (distance from planet center)
|
|
90
|
+
* @returns The effective maximum pitch angle
|
|
91
|
+
*/
|
|
92
|
+
getEffectivePitchMax(currentRadius) {
|
|
93
|
+
if (!this.pitchDisabledRadiusScale) {
|
|
94
|
+
return this.pitchMax;
|
|
95
|
+
}
|
|
96
|
+
const fullPitchRadius = this.pitchDisabledRadiusScale.x * this._planetRadius;
|
|
97
|
+
const noPitchRadius = this.pitchDisabledRadiusScale.y * this._planetRadius;
|
|
98
|
+
if (currentRadius <= fullPitchRadius) {
|
|
99
|
+
// Full pitch allowed
|
|
100
|
+
return this.pitchMax;
|
|
101
|
+
}
|
|
102
|
+
else if (currentRadius >= noPitchRadius) {
|
|
103
|
+
// No pitch allowed
|
|
104
|
+
return this.pitchMin;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Interpolate between pitchMax and pitchMin
|
|
108
|
+
const t = (currentRadius - fullPitchRadius) / (noPitchRadius - fullPitchRadius);
|
|
109
|
+
const clampedT = Clamp(t, 0, 1);
|
|
110
|
+
return this.pitchMax * (1 - clampedT) + this.pitchMin * clampedT;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
76
113
|
}
|
|
77
114
|
//# sourceMappingURL=geospatialLimits.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatialLimits.js","sourceRoot":"","sources":["../../../../../dev/core/src/Cameras/Limits/geospatialLimits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD;;GAEG;AACH,MAAM,OAAO,gBAAgB;
|
|
1
|
+
{"version":3,"file":"geospatialLimits.js","sourceRoot":"","sources":["../../../../../dev/core/src/Cameras/Limits/geospatialLimits.ts"],"names":[],"mappings":"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","sourcesContent":["import { Epsilon } from \"../../Maths/math.constants\";\r\nimport { Vector2 } from \"../../Maths/math.vector\";\r\nimport { Clamp } from \"../../Maths/math.scalar.functions\";\r\n/**\r\n * Limits for geospatial camera\r\n */\r\nexport class GeospatialLimits {\r\n private _planetRadius: number;\r\n private _radiusMin: number = 10;\r\n private _radiusMax: number = Infinity;\r\n\r\n /** Gets the minimum pitch angle (angle from horizon) -- 0 means looking straight down at planet */\r\n public pitchMin: number = Epsilon;\r\n\r\n /** Gets the maximum pitch angle (angle from horizon) -- Pi/2 means looking at horizon */\r\n public pitchMax: number = Math.PI / 2 - 0.01;\r\n\r\n /**\r\n * Controls how pitch is disabled as the camera zooms out.\r\n * x = radius scale at which full pitch is allowed (e.g., 1.5 means 1.5 * planetRadius)\r\n * y = radius scale at which pitch is fully disabled (forced to pitchMin)\r\n * Set to undefined to disable this feature.\r\n */\r\n public pitchDisabledRadiusScale?: Vector2 = new Vector2(2, 4);\r\n\r\n /** Gets the minimum yaw angle (rotation around up axis) */\r\n public yawMin: number = -Infinity;\r\n\r\n /** Gets the maximum yaw angle (rotation around up axis) */\r\n public yawMax: number = Infinity;\r\n /**\r\n * Defines the distance used to consider the camera in pan mode vs pinch/zoom.\r\n * Basically if your fingers moves away from more than this distance you will be considered\r\n * in pinch mode.\r\n */\r\n public pinchToPanMax: number = 20;\r\n\r\n /**\r\n * @param planetRadius The radius of the planet\r\n */\r\n constructor(planetRadius: number) {\r\n this._planetRadius = planetRadius;\r\n this.radiusMax = planetRadius * 4;\r\n }\r\n\r\n public get radiusMin(): number {\r\n return this._radiusMin;\r\n }\r\n\r\n /**\r\n * Sets the minimum radius\r\n */\r\n public set radiusMin(value: number) {\r\n this._radiusMin = value;\r\n }\r\n\r\n public get radiusMax(): number {\r\n return this._radiusMax;\r\n }\r\n\r\n /**\r\n * Sets the maximum radius\r\n */\r\n public set radiusMax(value: number) {\r\n this._radiusMax = value;\r\n }\r\n\r\n /**\r\n * Gets the planet radius used for altitude/radius conversions\r\n */\r\n public get planetRadius(): number {\r\n return this._planetRadius;\r\n }\r\n\r\n /** Sets the planet radius and updates the radius limits to maintain current altitude */\r\n public set planetRadius(value: number) {\r\n this._planetRadius = value;\r\n }\r\n\r\n /**\r\n * Clamps a zoom distance to respect the radius limits.\r\n * @param zoomDistance The requested zoom distance (positive = zoom in, negative = zoom out)\r\n * @param currentRadius The current camera radius\r\n * @param distanceToTarget Optional distance to the zoom target point (used for zoom-in clamping)\r\n * @returns The clamped zoom distance\r\n */\r\n public clampZoomDistance(zoomDistance: number, currentRadius: number, distanceToTarget?: number): number {\r\n if (zoomDistance > 0) {\r\n // Zooming IN - don't zoom past the surface or below radiusMin\r\n const maxZoomIn = (distanceToTarget ?? currentRadius) - this._radiusMin;\r\n return Math.min(zoomDistance, Math.max(0, maxZoomIn));\r\n } else {\r\n // Zooming OUT - don't exceed radiusMax\r\n const maxZoomOut = this._radiusMax - currentRadius;\r\n return Math.max(zoomDistance, -Math.max(0, maxZoomOut));\r\n }\r\n }\r\n\r\n /**\r\n * Computes the effective maximum pitch based on the current camera radius.\r\n * When pitchDisabledRadiusScale is set, pitch is interpolated from pitchMax to pitchMin\r\n * as the camera zooms out from x*planetRadius to y*planetRadius.\r\n * @param currentRadius The current camera radius (distance from planet center)\r\n * @returns The effective maximum pitch angle\r\n */\r\n public getEffectivePitchMax(currentRadius: number): number {\r\n if (!this.pitchDisabledRadiusScale) {\r\n return this.pitchMax;\r\n }\r\n\r\n const fullPitchRadius = this.pitchDisabledRadiusScale.x * this._planetRadius;\r\n const noPitchRadius = this.pitchDisabledRadiusScale.y * this._planetRadius;\r\n\r\n if (currentRadius <= fullPitchRadius) {\r\n // Full pitch allowed\r\n return this.pitchMax;\r\n } else if (currentRadius >= noPitchRadius) {\r\n // No pitch allowed\r\n return this.pitchMin;\r\n } else {\r\n // Interpolate between pitchMax and pitchMin\r\n const t = (currentRadius - fullPitchRadius) / (noPitchRadius - fullPitchRadius);\r\n const clampedT = Clamp(t, 0, 1);\r\n return this.pitchMax * (1 - clampedT) + this.pitchMin * clampedT;\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -9,19 +9,21 @@ import { GeospatialLimits } from "./Limits/geospatialLimits.js";
|
|
|
9
9
|
import { GeospatialCameraMovement } from "./geospatialCameraMovement.js";
|
|
10
10
|
import type { IVector3Like } from "../Maths/math.like.js";
|
|
11
11
|
import type { EasingFunction } from "../Animations/easing.js";
|
|
12
|
-
type
|
|
12
|
+
export type GeospatialCameraOptions = {
|
|
13
|
+
/**
|
|
14
|
+
* Radius of the planet being orbited
|
|
15
|
+
*/
|
|
13
16
|
planetRadius: number;
|
|
17
|
+
/**
|
|
18
|
+
* If supplied, will be used by the movement class when picking the globe. Can later update camera.movement.pickPredicate directly
|
|
19
|
+
*/
|
|
20
|
+
pickPredicate?: MeshPredicate;
|
|
14
21
|
};
|
|
15
22
|
/**
|
|
16
|
-
*
|
|
17
|
-
* 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
|
|
18
|
-
*
|
|
19
|
-
* Please note this is marked as experimental and the API (including the constructor!) will change until we remove that flag
|
|
23
|
+
* Camera equipped to orbit a spherical planet centered at world origin
|
|
20
24
|
*/
|
|
21
25
|
export declare class GeospatialCamera extends Camera {
|
|
22
26
|
inputs: GeospatialCameraInputsManager;
|
|
23
|
-
/** If supplied, will be used when picking the globe */
|
|
24
|
-
pickPredicate?: MeshPredicate;
|
|
25
27
|
/** Movement controller that turns input pixelDeltas into currentFrameDeltas used by camera*/
|
|
26
28
|
readonly movement: GeospatialCameraMovement;
|
|
27
29
|
private _tempPosition;
|
|
@@ -38,7 +40,7 @@ export declare class GeospatialCamera extends Camera {
|
|
|
38
40
|
perFrameCollisionOffset: Vector3;
|
|
39
41
|
/** Enable or disable collision checking for this camera. Default is false. */
|
|
40
42
|
checkCollisions: boolean;
|
|
41
|
-
constructor(name: string, scene: Scene, options:
|
|
43
|
+
constructor(name: string, scene: Scene, options: GeospatialCameraOptions);
|
|
42
44
|
private _center;
|
|
43
45
|
/** The point on the globe that we are anchoring around. If no alternate rotation point is supplied, this will represent the center of screen*/
|
|
44
46
|
get center(): Vector3;
|
|
@@ -169,4 +171,3 @@ export declare function ComputeLookAtFromYawPitchToRef(yaw: number, pitch: numbe
|
|
|
169
171
|
* @returns The result Vector2
|
|
170
172
|
*/
|
|
171
173
|
export declare function ComputeYawPitchFromLookAtToRef(lookAt: Vector3, center: Vector3, useRightHandedSystem: boolean, currentYaw: number, result: Vector2): Vector2;
|
|
172
|
-
export {};
|
|
@@ -8,13 +8,10 @@ import { Vector3CopyToRef, Vector3Distance, Vector3Dot, Vector3SubtractToRef } f
|
|
|
8
8
|
import { Clamp, NormalizeRadians } from "../Maths/math.scalar.functions.js";
|
|
9
9
|
import { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior.js";
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* 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
|
|
13
|
-
*
|
|
14
|
-
* Please note this is marked as experimental and the API (including the constructor!) will change until we remove that flag
|
|
11
|
+
* Camera equipped to orbit a spherical planet centered at world origin
|
|
15
12
|
*/
|
|
16
13
|
export class GeospatialCamera extends Camera {
|
|
17
|
-
constructor(name, scene, options
|
|
14
|
+
constructor(name, scene, options) {
|
|
18
15
|
super(name, new Vector3(), scene);
|
|
19
16
|
// Temp vars
|
|
20
17
|
this._tempPosition = new Vector3();
|
|
@@ -40,8 +37,7 @@ export class GeospatialCamera extends Camera {
|
|
|
40
37
|
this._resetToDefault(this._limits);
|
|
41
38
|
this._flyingBehavior = new InterpolatingBehavior();
|
|
42
39
|
this.addBehavior(this._flyingBehavior);
|
|
43
|
-
this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, pickPredicate, this._flyingBehavior);
|
|
44
|
-
this.pickPredicate = pickPredicate;
|
|
40
|
+
this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, options.pickPredicate, this._flyingBehavior);
|
|
45
41
|
this.inputs = new GeospatialCameraInputsManager(this);
|
|
46
42
|
this.inputs.addMouse().addMouseWheel().addKeyboard();
|
|
47
43
|
}
|
|
@@ -100,7 +96,8 @@ export class GeospatialCamera extends Camera {
|
|
|
100
96
|
_checkLimits() {
|
|
101
97
|
const limits = this.limits;
|
|
102
98
|
this._yaw = Clamp(this._yaw, limits.yawMin, limits.yawMax);
|
|
103
|
-
|
|
99
|
+
const effectivePitchMax = limits.getEffectivePitchMax(this._radius);
|
|
100
|
+
this._pitch = Clamp(this._pitch, limits.pitchMin, effectivePitchMax);
|
|
104
101
|
this._radius = Clamp(this._radius, limits.radiusMin, limits.radiusMax);
|
|
105
102
|
ClampCenterFromPolesInPlace(this._center);
|
|
106
103
|
}
|
|
@@ -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, Quaternion } from \"../Maths/math.vector\";\r\nimport type { Vector2 } 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 { ClampCenterFromPolesInPlace, ComputeLocalBasisToRefs, GeospatialCameraMovement } from \"./geospatialCameraMovement\";\r\nimport type { IVector3Like } from \"../Maths/math.like\";\r\nimport { Vector3CopyToRef, Vector3Distance, Vector3Dot, Vector3SubtractToRef } from \"../Maths/math.vector.functions\";\r\nimport { Clamp, NormalizeRadians } from \"../Maths/math.scalar.functions\";\r\nimport type { AllowedAnimValue } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport type { Collider } from \"../Collisions/collider\";\r\nimport type { EasingFunction } from \"../Animations/easing\";\r\nimport type { Animation } from \"../Animations/animation\";\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 private _tempCenter: 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 // Collision properties\r\n private _collider?: Collider;\r\n private _collisionVelocity: Vector3 = new Vector3();\r\n /** Public option to customize the collision offset applied each frame - vs the one calculated using internal CollisionCoordinator */\r\n public perFrameCollisionOffset: Vector3 = new Vector3();\r\n /** Enable or disable collision checking for this camera. Default is false. */\r\n public checkCollisions: boolean = false;\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, this._flyingBehavior);\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). Will wrap value to [-π, π)\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 yaw !== this._yaw && 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). Will wrap value to [-π, π)\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 pitch !== this._pitch && 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 radius !== this._radius && 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 ClampCenterFromPolesInPlace(this._center);\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 // Wrap yaw and pitch to [-π, π)\r\n this._yaw = NormalizeRadians(yaw);\r\n this._pitch = NormalizeRadians(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 // Compute lookAt from yaw/pitch\r\n ComputeLookAtFromYawPitchToRef(this._yaw, this._pitch, this._center, this._scene.useRightHandedSystem, this._lookAtVector);\r\n\r\n // Build an orthonormal up aligned with geocentric Up\r\n // When looking straight down (pitch ≈ 0), lookAt is parallel to Up, so use the horizontal direction as the camera's up.\r\n const right = TmpVectors.Vector3[10];\r\n Vector3.CrossToRef(this._tempUp, this._lookAtVector, right);\r\n if (right.lengthSquared() < Epsilon) {\r\n // Looking straight down (or up) - use quaternion rotation to compute horiz\r\n const horiz = TmpVectors.Vector3[11];\r\n const yawScale = this._scene.useRightHandedSystem ? 1 : -1;\r\n const yawQuat = TmpVectors.Quaternion[1];\r\n Quaternion.RotationAxisToRef(this._tempUp, this._yaw * yawScale, yawQuat);\r\n this._tempNorth.rotateByQuaternionToRef(yawQuat, horiz);\r\n // right = cross(horiz, lookAt)\r\n Vector3.CrossToRef(horiz, this._lookAtVector, right);\r\n }\r\n right.normalize();\r\n\r\n // up = normalize(cross(look, right))\r\n Vector3.CrossToRef(this._lookAtVector, right, this.upVector);\r\n this.upVector.normalize();\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 // Recalculate collisionOffset to be applied later when viewMatrix is calculated (allowing camera users to modify the value in afterCheckInputsObservable)\r\n if (this.checkCollisions) {\r\n this.perFrameCollisionOffset = this._getCollisionOffset(this._tempPosition);\r\n }\r\n\r\n this._position.copyFrom(this._tempPosition);\r\n\r\n this._isViewMatrixDirty = true;\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 // For yaw, use shortest path to target.\r\n const deltaYaw = targetYaw !== undefined ? NormalizeRadians(NormalizeRadians(targetYaw) - this._yaw) : 0;\r\n this._flyToTargets.set(\"yaw\", deltaYaw === 0 ? undefined : this._yaw + deltaYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch != undefined ? NormalizeRadians(targetPitch) : undefined);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter?.clone());\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 * @param centerHopScale If supplied, will define the parabolic hop height scale for center animation to create a \"bounce\" effect\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 centerHopScale?: number\r\n ): Promise<void> {\r\n this._flyToTargets.clear();\r\n\r\n // For yaw, use shortest path to target.\r\n const deltaYaw = targetYaw !== undefined ? NormalizeRadians(NormalizeRadians(targetYaw) - this._yaw) : 0;\r\n this._flyToTargets.set(\"yaw\", deltaYaw === 0 ? undefined : this._yaw + deltaYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch !== undefined ? NormalizeRadians(targetPitch) : undefined);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter?.clone());\r\n\r\n let overrideAnimationFunction;\r\n if (targetCenter !== undefined && !targetCenter.equals(this.center)) {\r\n // Animate center directly with custom interpolation\r\n overrideAnimationFunction = (key: string, animation: Animation): void => {\r\n if (key === \"center\") {\r\n // Override the Vector3 interpolation to use SLERP + hop\r\n animation.vector3InterpolateFunction = (startValue, endValue, gradient) => {\r\n // gradient is the eased value (0 to 1) after easing function is applied\r\n\r\n // Slerp between start and end\r\n const newCenter = Vector3.SlerpToRef(startValue, endValue, gradient, this._tempCenter);\r\n\r\n // Apply parabolic hop if requested\r\n if (centerHopScale && centerHopScale > 0) {\r\n // Parabolic formula: peaks at t=0.5, returns to 0 at gradient=0 and gradient=1\r\n // if hopPeakT = .5 the denominator would be hopPeakT * hopPeakT - hopPeakT, which = -.25\r\n const hopPeakOffset = centerHopScale * Vector3Distance(startValue, endValue);\r\n const hopOffset = hopPeakOffset * Clamp((gradient * gradient - gradient) / -0.25);\r\n // Scale the center outward (away from origin)\r\n newCenter.scaleInPlace(1 + hopOffset / newCenter.length());\r\n }\r\n\r\n return newCenter;\r\n };\r\n }\r\n };\r\n }\r\n\r\n return await this._flyingBehavior.animatePropertiesAsync(this._flyToTargets, flightDurationMs, easingFunction, overrideAnimationFunction);\r\n }\r\n\r\n /**\r\n * Helper function to move camera towards a given point by `distanceScale` of the current camera-to-destination distance (by default 50%).\r\n * @param destination point to move towards\r\n * @param distanceScale value between 0 and 1, % of distance to move\r\n * @param durationMs duration of flight, default 1s\r\n * @param easingFn optional easing function for flight interpolation of properties\r\n * @param centerHopScale If supplied, will define the parabolic hop height scale for center animation to create a \"bounce\" effect\r\n */\r\n public async flyToPointAsync(destination: Vector3, distanceScale: number = 0.5, durationMs: number = 1000, easingFn?: EasingFunction, centerHopScale?: number) {\r\n // Move by a fraction of the camera-to-destination distance\r\n const zoomDistance = Vector3Distance(this.position, destination) * distanceScale;\r\n const newRadius = this._getCenterAndRadiusFromZoomToPoint(destination, zoomDistance, this._tempCenter);\r\n await this.flyToAsync(undefined, undefined, newRadius, this._tempCenter, durationMs, easingFn, centerHopScale);\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 restingAltitude = limits.radiusMax !== Infinity ? limits.radiusMax : 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 // Apply the same offset to both position and center to preserve orbital relationship\r\n // This keeps yaw/pitch/radius intact - just lifts the whole \"rig\"\r\n this._position.addInPlace(this.perFrameCollisionOffset);\r\n this._center.addInPlace(this.perFrameCollisionOffset);\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 this._setOrientation(yaw, pitch, this._radius, this._center);\r\n }\r\n }\r\n\r\n private _getCenterAndRadiusFromZoomToPoint(targetPoint: DeepImmutable<IVector3Like>, distance: number, newCenterResult: Vector3): number {\r\n const directionToTarget = Vector3SubtractToRef(targetPoint, this._position, TmpVectors.Vector3[0]);\r\n const distanceToTarget = directionToTarget.length();\r\n\r\n // Don't zoom past the min radius limit.\r\n if (distanceToTarget < this.limits.radiusMin) {\r\n newCenterResult.copyFrom(this._center);\r\n const requestedRadius = this._radius - distance;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n return newRadius;\r\n }\r\n\r\n // Move the camera position towards targetPoint by distanceToTarget\r\n directionToTarget.scaleInPlace(distance / distanceToTarget);\r\n const newPosition = this._position.addToRef(directionToTarget, TmpVectors.Vector3[1]);\r\n\r\n // Project the movement onto the look vector to derive the new center/radius.\r\n const projectedDistance = Vector3Dot(directionToTarget, this._lookAtVector);\r\n const newRadius = this._radius - projectedDistance;\r\n const newRadiusClamped = Clamp(newRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n newCenterResult.copyFrom(newPosition).addInPlace(this._lookAtVector.scale(newRadiusClamped));\r\n\r\n return newRadiusClamped;\r\n }\r\n\r\n /**\r\n * Apply zoom by moving the camera toward/away from a target point.\r\n */\r\n private _applyZoom() {\r\n let zoomDelta = this.movement.zoomDeltaCurrentFrame;\r\n const pickedPoint = this.movement.computedPerFrameZoomPickPoint;\r\n\r\n // Clamp zoom delta to limits before applying\r\n zoomDelta = this._clampZoomDelta(zoomDelta, pickedPoint);\r\n\r\n if (Math.abs(zoomDelta) < Epsilon) {\r\n return;\r\n }\r\n if (pickedPoint) {\r\n // Zoom toward the picked point under cursor\r\n this.zoomToPoint(pickedPoint, zoomDelta);\r\n } else {\r\n // Zoom along lookAt vector (fallback when no surface under cursor)\r\n this.zoomAlongLookAt(zoomDelta);\r\n }\r\n }\r\n\r\n private _clampZoomDelta(zoomDelta: number, pickedPoint?: Vector3): number {\r\n if (Math.abs(zoomDelta) < Epsilon) {\r\n return 0;\r\n }\r\n\r\n const distanceToTarget = pickedPoint ? Vector3Distance(this._position, pickedPoint) : undefined;\r\n return this.limits.clampZoomDistance(zoomDelta, this._radius, distanceToTarget);\r\n }\r\n\r\n public zoomToPoint(targetPoint: DeepImmutable<IVector3Like>, distance: number) {\r\n const newRadius = this._getCenterAndRadiusFromZoomToPoint(targetPoint, distance, this._tempCenter);\r\n // Apply the new orientation\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._tempCenter);\r\n }\r\n\r\n public zoomAlongLookAt(distance: number) {\r\n // Clamp radius to limits\r\n const requestedRadius = this._radius - distance;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n\r\n // Simply change radius without moving center\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._center);\r\n }\r\n\r\n override _checkInputs(): void {\r\n this.inputs.checkInputs();\r\n this.perFrameCollisionOffset.setAll(0);\r\n\r\n // Let movement class handle all per-frame logic\r\n this.movement.computeCurrentFrameDeltas();\r\n\r\n let isCenterMoving = false;\r\n if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricTranslation();\r\n // After a drag, recalculate the center point to ensure it's still on the surface.\r\n isCenterMoving = true;\r\n }\r\n if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricRotation();\r\n }\r\n\r\n if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {\r\n this._applyZoom();\r\n isCenterMoving = true;\r\n }\r\n\r\n // After a movement impacting center or radius, recalculate the center point to ensure it's still on the surface.\r\n this._recalculateCenter(isCenterMoving);\r\n\r\n super._checkInputs();\r\n }\r\n\r\n private _wasCenterMovingLastFrame = false;\r\n\r\n private _recalculateCenter(isCenterMoving: boolean) {\r\n const shouldRecalculateCenterAfterMove = this._wasCenterMovingLastFrame && !isCenterMoving;\r\n this._wasCenterMovingLastFrame = isCenterMoving;\r\n\r\n // Wait until movement impacting center is complete to avoid wasted raycasting\r\n if (shouldRecalculateCenterAfterMove) {\r\n const newCenter = this.movement.pickAlongVector(this._lookAtVector);\r\n if (newCenter?.pickedPoint) {\r\n // Direction from new center to origin\r\n const centerToOrigin = TmpVectors.Vector3[4];\r\n centerToOrigin.copyFrom(newCenter.pickedPoint).negateInPlace().normalize();\r\n\r\n // Check if this direction aligns with camera's lookAt vector\r\n const dotProduct = Vector3Dot(this._lookAtVector, centerToOrigin);\r\n\r\n // Only update if the center is looking toward the origin (dot product > 0) to avoid a center on the opposite side of globe\r\n if (dotProduct > 0) {\r\n // Compute the new radius as distance from camera position to new center\r\n const newRadius = Vector3Distance(this._position, newCenter.pickedPoint);\r\n\r\n // Only update if the new center is in front of the camera\r\n if (newRadius > Epsilon) {\r\n // Compute yaw/pitch that correspond to current lookAt at new center\r\n const yawPitch = TmpVectors.Vector2[0];\r\n ComputeYawPitchFromLookAtToRef(this._lookAtVector, newCenter.pickedPoint, this._scene.useRightHandedSystem, this._yaw, yawPitch);\r\n\r\n // Call _setOrientation with the computed yaw/pitch and new center\r\n this._setOrientation(yawPitch.x, yawPitch.y, newRadius, newCenter.pickedPoint);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Allows extended classes to override how collision offset is calculated\r\n * @param newPosition\r\n * @returns\r\n */\r\n protected _getCollisionOffset(newPosition: Vector3): Vector3 {\r\n const collisionOffset = TmpVectors.Vector3[6].setAll(0);\r\n if (!this.checkCollisions || !this._scene.collisionsEnabled) {\r\n return collisionOffset;\r\n }\r\n\r\n const coordinator = this.getScene().collisionCoordinator;\r\n if (!coordinator) {\r\n return collisionOffset;\r\n }\r\n\r\n if (!this._collider) {\r\n this._collider = coordinator.createCollider();\r\n }\r\n this._collider._radius.setAll(this.limits.radiusMin);\r\n\r\n // Calculate velocity from old position to new position\r\n newPosition.subtractToRef(this._position, this._collisionVelocity);\r\n\r\n // Get the collision-adjusted position\r\n const adjustedPosition = coordinator.getNewPosition(this._position, this._collisionVelocity, this._collider, 3, null, () => {}, this.uniqueId);\r\n\r\n // Calculate the collision offset (how much the position was pushed)\r\n adjustedPosition.subtractToRef(newPosition, collisionOffset);\r\n\r\n return collisionOffset;\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/**\r\n * Compute the lookAt direction vector from yaw and pitch angles at a given center point.\r\n * This is the forward formula used by GeospatialCamera._setOrientation.\r\n * @param yaw - The yaw angle in radians (0 = north, π/2 = east)\r\n * @param pitch - The pitch angle in radians (0 = looking at planet center, π/2 = looking at horizon)\r\n * @param center - The center point on the globe\r\n * @param useRightHandedSystem - Whether the scene uses a right-handed coordinate system\r\n * @param result - The vector to store the result in\r\n * @returns The normalized lookAt direction vector (same as result)\r\n */\r\nexport function ComputeLookAtFromYawPitchToRef(yaw: number, pitch: number, center: Vector3, useRightHandedSystem: boolean, result: Vector3): Vector3 {\r\n const east = TmpVectors.Vector3[0];\r\n const north = TmpVectors.Vector3[1];\r\n const up = TmpVectors.Vector3[2];\r\n ComputeLocalBasisToRefs(center, east, north, up);\r\n\r\n const sinPitch = Math.sin(pitch);\r\n const cosPitch = Math.cos(pitch);\r\n\r\n // Use quaternion rotation to compute horiz = rotate(north, up, yaw * yawScale)\r\n const yawScale = useRightHandedSystem ? 1 : -1;\r\n const yawQuat = TmpVectors.Quaternion[0];\r\n Quaternion.RotationAxisToRef(up, yaw * yawScale, yawQuat);\r\n\r\n const horiz = TmpVectors.Vector3[3];\r\n north.rotateByQuaternionToRef(yawQuat, horiz);\r\n\r\n // lookAt = horiz * sinPitch - up * cosPitch\r\n const t2 = TmpVectors.Vector3[4];\r\n result.copyFrom(horiz).scaleInPlace(sinPitch).addInPlace(t2.copyFrom(up).scaleInPlace(-cosPitch));\r\n return result.normalize();\r\n}\r\n\r\n/**\r\n * Given a lookAt direction and center, compute the yaw and pitch angles that would produce that lookAt.\r\n * This is the inverse of ComputeLookAtFromYawPitchToRef.\r\n * @param lookAt - The normalized lookAt direction vector\r\n * @param center - The center point on the globe\r\n * @param useRightHandedSystem - Whether the scene uses a right-handed coordinate system\r\n * @param currentYaw - The current yaw value to use as fallback when pitch is near 0 (looking straight down/up)\r\n * @param result - The Vector2 to store the result in (x = yaw, y = pitch)\r\n * @returns The result Vector2\r\n */\r\nexport function ComputeYawPitchFromLookAtToRef(lookAt: Vector3, center: Vector3, useRightHandedSystem: boolean, currentYaw: number, result: Vector2): Vector2 {\r\n // Compute local basis at center\r\n const east = TmpVectors.Vector3[6];\r\n const north = TmpVectors.Vector3[7];\r\n const up = TmpVectors.Vector3[8];\r\n ComputeLocalBasisToRefs(center, east, north, up);\r\n\r\n // lookAt = horiz*sinPitch - up*cosPitch\r\n // where horiz = rotate(north, up, yaw * yawScale) via quaternion\r\n //\r\n // The vertical component of lookAt (along up) gives us cosPitch:\r\n // lookAt · up = -cosPitch\r\n const lookDotUp = Vector3Dot(lookAt, up);\r\n const cosPitch = -lookDotUp;\r\n\r\n // Clamp cosPitch to valid range to avoid NaN from acos\r\n const clampedCosPitch = Clamp(cosPitch, -1, 1);\r\n const pitch = Math.acos(clampedCosPitch);\r\n\r\n // The horizontal component gives us yaw\r\n // lookHorizontal = lookAt + up*cosPitch = horiz*sinPitch\r\n const lookHorizontal = TmpVectors.Vector3[9];\r\n const scaledUp = TmpVectors.Vector3[10];\r\n scaledUp.copyFrom(up).scaleInPlace(cosPitch);\r\n lookHorizontal.copyFrom(lookAt).addInPlace(scaledUp);\r\n\r\n const sinPitch = Math.sin(pitch);\r\n if (Math.abs(sinPitch) < Epsilon) {\r\n // Looking straight down or up, yaw is undefined - keep current\r\n result.x = currentYaw;\r\n result.y = pitch;\r\n return result;\r\n }\r\n\r\n // horiz = lookHorizontal / sinPitch\r\n const horiz = lookHorizontal.scaleInPlace(1 / sinPitch);\r\n\r\n // The quaternion rotation produces: horiz = rotate(north, up, angle)\r\n // This is equivalent to: horiz = north*cos(angle) + cross(up, north)*sin(angle) = north*cos(angle) - east*sin(angle)\r\n // (since cross(up, north) = -east in our basis)\r\n // So: cosYaw = horiz · north, sinYaw = -(horiz · east)\r\n const cosYaw = Vector3Dot(horiz, north);\r\n const sinYaw = -Vector3Dot(horiz, east);\r\n\r\n const yawScale = useRightHandedSystem ? 1 : -1;\r\n result.x = Math.atan2(sinYaw, cosYaw) * yawScale;\r\n result.y = pitch;\r\n return result;\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, Quaternion } from \"../Maths/math.vector\";\r\nimport type { Vector2 } 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 { ClampCenterFromPolesInPlace, ComputeLocalBasisToRefs, GeospatialCameraMovement } from \"./geospatialCameraMovement\";\r\nimport type { IVector3Like } from \"../Maths/math.like\";\r\nimport { Vector3CopyToRef, Vector3Distance, Vector3Dot, Vector3SubtractToRef } from \"../Maths/math.vector.functions\";\r\nimport { Clamp, NormalizeRadians } from \"../Maths/math.scalar.functions\";\r\nimport type { AllowedAnimValue } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport type { Collider } from \"../Collisions/collider\";\r\nimport type { EasingFunction } from \"../Animations/easing\";\r\nimport type { Animation } from \"../Animations/animation\";\r\n\r\nexport type GeospatialCameraOptions = {\r\n /**\r\n * Radius of the planet being orbited\r\n */\r\n planetRadius: number;\r\n /**\r\n * If supplied, will be used by the movement class when picking the globe. Can later update camera.movement.pickPredicate directly\r\n */\r\n pickPredicate?: MeshPredicate;\r\n};\r\n\r\n/**\r\n * Camera equipped to orbit a spherical planet centered at world origin\r\n */\r\nexport class GeospatialCamera extends Camera {\r\n override inputs: GeospatialCameraInputsManager;\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 private _tempCenter: 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 // Collision properties\r\n private _collider?: Collider;\r\n private _collisionVelocity: Vector3 = new Vector3();\r\n /** Public option to customize the collision offset applied each frame - vs the one calculated using internal CollisionCoordinator */\r\n public perFrameCollisionOffset: Vector3 = new Vector3();\r\n /** Enable or disable collision checking for this camera. Default is false. */\r\n public checkCollisions: boolean = false;\r\n\r\n constructor(name: string, scene: Scene, options: GeospatialCameraOptions) {\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, options.pickPredicate, this._flyingBehavior);\r\n\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). Will wrap value to [-π, π)\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 yaw !== this._yaw && 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). Will wrap value to [-π, π)\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 pitch !== this._pitch && 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 radius !== this._radius && 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 const effectivePitchMax = limits.getEffectivePitchMax(this._radius);\r\n this._pitch = Clamp(this._pitch, limits.pitchMin, effectivePitchMax);\r\n this._radius = Clamp(this._radius, limits.radiusMin, limits.radiusMax);\r\n ClampCenterFromPolesInPlace(this._center);\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 // Wrap yaw and pitch to [-π, π)\r\n this._yaw = NormalizeRadians(yaw);\r\n this._pitch = NormalizeRadians(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 // Compute lookAt from yaw/pitch\r\n ComputeLookAtFromYawPitchToRef(this._yaw, this._pitch, this._center, this._scene.useRightHandedSystem, this._lookAtVector);\r\n\r\n // Build an orthonormal up aligned with geocentric Up\r\n // When looking straight down (pitch ≈ 0), lookAt is parallel to Up, so use the horizontal direction as the camera's up.\r\n const right = TmpVectors.Vector3[10];\r\n Vector3.CrossToRef(this._tempUp, this._lookAtVector, right);\r\n if (right.lengthSquared() < Epsilon) {\r\n // Looking straight down (or up) - use quaternion rotation to compute horiz\r\n const horiz = TmpVectors.Vector3[11];\r\n const yawScale = this._scene.useRightHandedSystem ? 1 : -1;\r\n const yawQuat = TmpVectors.Quaternion[1];\r\n Quaternion.RotationAxisToRef(this._tempUp, this._yaw * yawScale, yawQuat);\r\n this._tempNorth.rotateByQuaternionToRef(yawQuat, horiz);\r\n // right = cross(horiz, lookAt)\r\n Vector3.CrossToRef(horiz, this._lookAtVector, right);\r\n }\r\n right.normalize();\r\n\r\n // up = normalize(cross(look, right))\r\n Vector3.CrossToRef(this._lookAtVector, right, this.upVector);\r\n this.upVector.normalize();\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 // Recalculate collisionOffset to be applied later when viewMatrix is calculated (allowing camera users to modify the value in afterCheckInputsObservable)\r\n if (this.checkCollisions) {\r\n this.perFrameCollisionOffset = this._getCollisionOffset(this._tempPosition);\r\n }\r\n\r\n this._position.copyFrom(this._tempPosition);\r\n\r\n this._isViewMatrixDirty = true;\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 // For yaw, use shortest path to target.\r\n const deltaYaw = targetYaw !== undefined ? NormalizeRadians(NormalizeRadians(targetYaw) - this._yaw) : 0;\r\n this._flyToTargets.set(\"yaw\", deltaYaw === 0 ? undefined : this._yaw + deltaYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch != undefined ? NormalizeRadians(targetPitch) : undefined);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter?.clone());\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 * @param centerHopScale If supplied, will define the parabolic hop height scale for center animation to create a \"bounce\" effect\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 centerHopScale?: number\r\n ): Promise<void> {\r\n this._flyToTargets.clear();\r\n\r\n // For yaw, use shortest path to target.\r\n const deltaYaw = targetYaw !== undefined ? NormalizeRadians(NormalizeRadians(targetYaw) - this._yaw) : 0;\r\n this._flyToTargets.set(\"yaw\", deltaYaw === 0 ? undefined : this._yaw + deltaYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch !== undefined ? NormalizeRadians(targetPitch) : undefined);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter?.clone());\r\n\r\n let overrideAnimationFunction;\r\n if (targetCenter !== undefined && !targetCenter.equals(this.center)) {\r\n // Animate center directly with custom interpolation\r\n overrideAnimationFunction = (key: string, animation: Animation): void => {\r\n if (key === \"center\") {\r\n // Override the Vector3 interpolation to use SLERP + hop\r\n animation.vector3InterpolateFunction = (startValue, endValue, gradient) => {\r\n // gradient is the eased value (0 to 1) after easing function is applied\r\n\r\n // Slerp between start and end\r\n const newCenter = Vector3.SlerpToRef(startValue, endValue, gradient, this._tempCenter);\r\n\r\n // Apply parabolic hop if requested\r\n if (centerHopScale && centerHopScale > 0) {\r\n // Parabolic formula: peaks at t=0.5, returns to 0 at gradient=0 and gradient=1\r\n // if hopPeakT = .5 the denominator would be hopPeakT * hopPeakT - hopPeakT, which = -.25\r\n const hopPeakOffset = centerHopScale * Vector3Distance(startValue, endValue);\r\n const hopOffset = hopPeakOffset * Clamp((gradient * gradient - gradient) / -0.25);\r\n // Scale the center outward (away from origin)\r\n newCenter.scaleInPlace(1 + hopOffset / newCenter.length());\r\n }\r\n\r\n return newCenter;\r\n };\r\n }\r\n };\r\n }\r\n\r\n return await this._flyingBehavior.animatePropertiesAsync(this._flyToTargets, flightDurationMs, easingFunction, overrideAnimationFunction);\r\n }\r\n\r\n /**\r\n * Helper function to move camera towards a given point by `distanceScale` of the current camera-to-destination distance (by default 50%).\r\n * @param destination point to move towards\r\n * @param distanceScale value between 0 and 1, % of distance to move\r\n * @param durationMs duration of flight, default 1s\r\n * @param easingFn optional easing function for flight interpolation of properties\r\n * @param centerHopScale If supplied, will define the parabolic hop height scale for center animation to create a \"bounce\" effect\r\n */\r\n public async flyToPointAsync(destination: Vector3, distanceScale: number = 0.5, durationMs: number = 1000, easingFn?: EasingFunction, centerHopScale?: number) {\r\n // Move by a fraction of the camera-to-destination distance\r\n const zoomDistance = Vector3Distance(this.position, destination) * distanceScale;\r\n const newRadius = this._getCenterAndRadiusFromZoomToPoint(destination, zoomDistance, this._tempCenter);\r\n await this.flyToAsync(undefined, undefined, newRadius, this._tempCenter, durationMs, easingFn, centerHopScale);\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 restingAltitude = limits.radiusMax !== Infinity ? limits.radiusMax : 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 // Apply the same offset to both position and center to preserve orbital relationship\r\n // This keeps yaw/pitch/radius intact - just lifts the whole \"rig\"\r\n this._position.addInPlace(this.perFrameCollisionOffset);\r\n this._center.addInPlace(this.perFrameCollisionOffset);\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 this._setOrientation(yaw, pitch, this._radius, this._center);\r\n }\r\n }\r\n\r\n private _getCenterAndRadiusFromZoomToPoint(targetPoint: DeepImmutable<IVector3Like>, distance: number, newCenterResult: Vector3): number {\r\n const directionToTarget = Vector3SubtractToRef(targetPoint, this._position, TmpVectors.Vector3[0]);\r\n const distanceToTarget = directionToTarget.length();\r\n\r\n // Don't zoom past the min radius limit.\r\n if (distanceToTarget < this.limits.radiusMin) {\r\n newCenterResult.copyFrom(this._center);\r\n const requestedRadius = this._radius - distance;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n return newRadius;\r\n }\r\n\r\n // Move the camera position towards targetPoint by distanceToTarget\r\n directionToTarget.scaleInPlace(distance / distanceToTarget);\r\n const newPosition = this._position.addToRef(directionToTarget, TmpVectors.Vector3[1]);\r\n\r\n // Project the movement onto the look vector to derive the new center/radius.\r\n const projectedDistance = Vector3Dot(directionToTarget, this._lookAtVector);\r\n const newRadius = this._radius - projectedDistance;\r\n const newRadiusClamped = Clamp(newRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n newCenterResult.copyFrom(newPosition).addInPlace(this._lookAtVector.scale(newRadiusClamped));\r\n\r\n return newRadiusClamped;\r\n }\r\n\r\n /**\r\n * Apply zoom by moving the camera toward/away from a target point.\r\n */\r\n private _applyZoom() {\r\n let zoomDelta = this.movement.zoomDeltaCurrentFrame;\r\n const pickedPoint = this.movement.computedPerFrameZoomPickPoint;\r\n\r\n // Clamp zoom delta to limits before applying\r\n zoomDelta = this._clampZoomDelta(zoomDelta, pickedPoint);\r\n\r\n if (Math.abs(zoomDelta) < Epsilon) {\r\n return;\r\n }\r\n if (pickedPoint) {\r\n // Zoom toward the picked point under cursor\r\n this.zoomToPoint(pickedPoint, zoomDelta);\r\n } else {\r\n // Zoom along lookAt vector (fallback when no surface under cursor)\r\n this.zoomAlongLookAt(zoomDelta);\r\n }\r\n }\r\n\r\n private _clampZoomDelta(zoomDelta: number, pickedPoint?: Vector3): number {\r\n if (Math.abs(zoomDelta) < Epsilon) {\r\n return 0;\r\n }\r\n\r\n const distanceToTarget = pickedPoint ? Vector3Distance(this._position, pickedPoint) : undefined;\r\n return this.limits.clampZoomDistance(zoomDelta, this._radius, distanceToTarget);\r\n }\r\n\r\n public zoomToPoint(targetPoint: DeepImmutable<IVector3Like>, distance: number) {\r\n const newRadius = this._getCenterAndRadiusFromZoomToPoint(targetPoint, distance, this._tempCenter);\r\n // Apply the new orientation\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._tempCenter);\r\n }\r\n\r\n public zoomAlongLookAt(distance: number) {\r\n // Clamp radius to limits\r\n const requestedRadius = this._radius - distance;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n\r\n // Simply change radius without moving center\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._center);\r\n }\r\n\r\n override _checkInputs(): void {\r\n this.inputs.checkInputs();\r\n this.perFrameCollisionOffset.setAll(0);\r\n\r\n // Let movement class handle all per-frame logic\r\n this.movement.computeCurrentFrameDeltas();\r\n\r\n let isCenterMoving = false;\r\n if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricTranslation();\r\n // After a drag, recalculate the center point to ensure it's still on the surface.\r\n isCenterMoving = true;\r\n }\r\n if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricRotation();\r\n }\r\n\r\n if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {\r\n this._applyZoom();\r\n isCenterMoving = true;\r\n }\r\n\r\n // After a movement impacting center or radius, recalculate the center point to ensure it's still on the surface.\r\n this._recalculateCenter(isCenterMoving);\r\n\r\n super._checkInputs();\r\n }\r\n\r\n private _wasCenterMovingLastFrame = false;\r\n\r\n private _recalculateCenter(isCenterMoving: boolean) {\r\n const shouldRecalculateCenterAfterMove = this._wasCenterMovingLastFrame && !isCenterMoving;\r\n this._wasCenterMovingLastFrame = isCenterMoving;\r\n\r\n // Wait until movement impacting center is complete to avoid wasted raycasting\r\n if (shouldRecalculateCenterAfterMove) {\r\n const newCenter = this.movement.pickAlongVector(this._lookAtVector);\r\n if (newCenter?.pickedPoint) {\r\n // Direction from new center to origin\r\n const centerToOrigin = TmpVectors.Vector3[4];\r\n centerToOrigin.copyFrom(newCenter.pickedPoint).negateInPlace().normalize();\r\n\r\n // Check if this direction aligns with camera's lookAt vector\r\n const dotProduct = Vector3Dot(this._lookAtVector, centerToOrigin);\r\n\r\n // Only update if the center is looking toward the origin (dot product > 0) to avoid a center on the opposite side of globe\r\n if (dotProduct > 0) {\r\n // Compute the new radius as distance from camera position to new center\r\n const newRadius = Vector3Distance(this._position, newCenter.pickedPoint);\r\n\r\n // Only update if the new center is in front of the camera\r\n if (newRadius > Epsilon) {\r\n // Compute yaw/pitch that correspond to current lookAt at new center\r\n const yawPitch = TmpVectors.Vector2[0];\r\n ComputeYawPitchFromLookAtToRef(this._lookAtVector, newCenter.pickedPoint, this._scene.useRightHandedSystem, this._yaw, yawPitch);\r\n\r\n // Call _setOrientation with the computed yaw/pitch and new center\r\n this._setOrientation(yawPitch.x, yawPitch.y, newRadius, newCenter.pickedPoint);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Allows extended classes to override how collision offset is calculated\r\n * @param newPosition\r\n * @returns\r\n */\r\n protected _getCollisionOffset(newPosition: Vector3): Vector3 {\r\n const collisionOffset = TmpVectors.Vector3[6].setAll(0);\r\n if (!this.checkCollisions || !this._scene.collisionsEnabled) {\r\n return collisionOffset;\r\n }\r\n\r\n const coordinator = this.getScene().collisionCoordinator;\r\n if (!coordinator) {\r\n return collisionOffset;\r\n }\r\n\r\n if (!this._collider) {\r\n this._collider = coordinator.createCollider();\r\n }\r\n this._collider._radius.setAll(this.limits.radiusMin);\r\n\r\n // Calculate velocity from old position to new position\r\n newPosition.subtractToRef(this._position, this._collisionVelocity);\r\n\r\n // Get the collision-adjusted position\r\n const adjustedPosition = coordinator.getNewPosition(this._position, this._collisionVelocity, this._collider, 3, null, () => {}, this.uniqueId);\r\n\r\n // Calculate the collision offset (how much the position was pushed)\r\n adjustedPosition.subtractToRef(newPosition, collisionOffset);\r\n\r\n return collisionOffset;\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/**\r\n * Compute the lookAt direction vector from yaw and pitch angles at a given center point.\r\n * This is the forward formula used by GeospatialCamera._setOrientation.\r\n * @param yaw - The yaw angle in radians (0 = north, π/2 = east)\r\n * @param pitch - The pitch angle in radians (0 = looking at planet center, π/2 = looking at horizon)\r\n * @param center - The center point on the globe\r\n * @param useRightHandedSystem - Whether the scene uses a right-handed coordinate system\r\n * @param result - The vector to store the result in\r\n * @returns The normalized lookAt direction vector (same as result)\r\n */\r\nexport function ComputeLookAtFromYawPitchToRef(yaw: number, pitch: number, center: Vector3, useRightHandedSystem: boolean, result: Vector3): Vector3 {\r\n const east = TmpVectors.Vector3[0];\r\n const north = TmpVectors.Vector3[1];\r\n const up = TmpVectors.Vector3[2];\r\n ComputeLocalBasisToRefs(center, east, north, up);\r\n\r\n const sinPitch = Math.sin(pitch);\r\n const cosPitch = Math.cos(pitch);\r\n\r\n // Use quaternion rotation to compute horiz = rotate(north, up, yaw * yawScale)\r\n const yawScale = useRightHandedSystem ? 1 : -1;\r\n const yawQuat = TmpVectors.Quaternion[0];\r\n Quaternion.RotationAxisToRef(up, yaw * yawScale, yawQuat);\r\n\r\n const horiz = TmpVectors.Vector3[3];\r\n north.rotateByQuaternionToRef(yawQuat, horiz);\r\n\r\n // lookAt = horiz * sinPitch - up * cosPitch\r\n const t2 = TmpVectors.Vector3[4];\r\n result.copyFrom(horiz).scaleInPlace(sinPitch).addInPlace(t2.copyFrom(up).scaleInPlace(-cosPitch));\r\n return result.normalize();\r\n}\r\n\r\n/**\r\n * Given a lookAt direction and center, compute the yaw and pitch angles that would produce that lookAt.\r\n * This is the inverse of ComputeLookAtFromYawPitchToRef.\r\n * @param lookAt - The normalized lookAt direction vector\r\n * @param center - The center point on the globe\r\n * @param useRightHandedSystem - Whether the scene uses a right-handed coordinate system\r\n * @param currentYaw - The current yaw value to use as fallback when pitch is near 0 (looking straight down/up)\r\n * @param result - The Vector2 to store the result in (x = yaw, y = pitch)\r\n * @returns The result Vector2\r\n */\r\nexport function ComputeYawPitchFromLookAtToRef(lookAt: Vector3, center: Vector3, useRightHandedSystem: boolean, currentYaw: number, result: Vector2): Vector2 {\r\n // Compute local basis at center\r\n const east = TmpVectors.Vector3[6];\r\n const north = TmpVectors.Vector3[7];\r\n const up = TmpVectors.Vector3[8];\r\n ComputeLocalBasisToRefs(center, east, north, up);\r\n\r\n // lookAt = horiz*sinPitch - up*cosPitch\r\n // where horiz = rotate(north, up, yaw * yawScale) via quaternion\r\n //\r\n // The vertical component of lookAt (along up) gives us cosPitch:\r\n // lookAt · up = -cosPitch\r\n const lookDotUp = Vector3Dot(lookAt, up);\r\n const cosPitch = -lookDotUp;\r\n\r\n // Clamp cosPitch to valid range to avoid NaN from acos\r\n const clampedCosPitch = Clamp(cosPitch, -1, 1);\r\n const pitch = Math.acos(clampedCosPitch);\r\n\r\n // The horizontal component gives us yaw\r\n // lookHorizontal = lookAt + up*cosPitch = horiz*sinPitch\r\n const lookHorizontal = TmpVectors.Vector3[9];\r\n const scaledUp = TmpVectors.Vector3[10];\r\n scaledUp.copyFrom(up).scaleInPlace(cosPitch);\r\n lookHorizontal.copyFrom(lookAt).addInPlace(scaledUp);\r\n\r\n const sinPitch = Math.sin(pitch);\r\n if (Math.abs(sinPitch) < Epsilon) {\r\n // Looking straight down or up, yaw is undefined - keep current\r\n result.x = currentYaw;\r\n result.y = pitch;\r\n return result;\r\n }\r\n\r\n // horiz = lookHorizontal / sinPitch\r\n const horiz = lookHorizontal.scaleInPlace(1 / sinPitch);\r\n\r\n // The quaternion rotation produces: horiz = rotate(north, up, angle)\r\n // This is equivalent to: horiz = north*cos(angle) + cross(up, north)*sin(angle) = north*cos(angle) - east*sin(angle)\r\n // (since cross(up, north) = -east in our basis)\r\n // So: cosYaw = horiz · north, sinYaw = -(horiz · east)\r\n const cosYaw = Vector3Dot(horiz, north);\r\n const sinYaw = -Vector3Dot(horiz, east);\r\n\r\n const yawScale = useRightHandedSystem ? 1 : -1;\r\n result.x = Math.atan2(sinYaw, cosYaw) * yawScale;\r\n result.y = pitch;\r\n return result;\r\n}\r\n"]}
|
|
@@ -8,9 +8,6 @@ import type { Nullable } from "../types.js";
|
|
|
8
8
|
import type { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior.js";
|
|
9
9
|
import type { GeospatialCamera } from "./geospatialCamera.js";
|
|
10
10
|
/**
|
|
11
|
-
* @experimental
|
|
12
|
-
* This class is subject to change as the geospatial camera evolves.
|
|
13
|
-
*
|
|
14
11
|
* Geospatial-specific camera movement system that extends the base movement with
|
|
15
12
|
* raycasting and altitude-aware zoom constraints.
|
|
16
13
|
*
|
|
@@ -56,6 +53,7 @@ export declare class GeospatialCameraMovement extends CameraMovement {
|
|
|
56
53
|
handleZoom(zoomDelta: number, toCursor: boolean): void;
|
|
57
54
|
pickAlongVector(vector: Vector3): Nullable<PickingInfo>;
|
|
58
55
|
}
|
|
56
|
+
/** @internal */
|
|
59
57
|
export declare function ClampCenterFromPolesInPlace(center: Vector3): Vector3;
|
|
60
58
|
/**
|
|
61
59
|
* Helper to build east/north/up basis vectors at a world position.
|
|
@@ -6,9 +6,6 @@ import { Ray } from "../Culling/ray.js";
|
|
|
6
6
|
import { Vector3Distance } from "../Maths/math.vector.functions.js";
|
|
7
7
|
import { Clamp } from "../Maths/math.scalar.functions.js";
|
|
8
8
|
/**
|
|
9
|
-
* @experimental
|
|
10
|
-
* This class is subject to change as the geospatial camera evolves.
|
|
11
|
-
*
|
|
12
9
|
* Geospatial-specific camera movement system that extends the base movement with
|
|
13
10
|
* raycasting and altitude-aware zoom constraints.
|
|
14
11
|
*
|
|
@@ -82,11 +79,18 @@ export class GeospatialCameraMovement extends CameraMovement {
|
|
|
82
79
|
}
|
|
83
80
|
handleDrag(pointerX, pointerY) {
|
|
84
81
|
if (this._hitPointRadius) {
|
|
85
|
-
const pickResult = this._scene.pick(pointerX, pointerY);
|
|
82
|
+
const pickResult = this._scene.pick(pointerX, pointerY, this.pickPredicate);
|
|
86
83
|
if (pickResult.ray) {
|
|
87
84
|
const localToEcef = TmpVectors.Matrix[0];
|
|
88
85
|
this._recalculateDragPlaneHitPoint(this._hitPointRadius, pickResult.ray, localToEcef);
|
|
89
86
|
const delta = this._dragPlaneHitPointLocal.subtractToRef(this._previousDragPlaneHitPointLocal, TmpVectors.Vector3[6]);
|
|
87
|
+
// When the camera is pitched nearly parallel to the drag plane, ray-plane intersection
|
|
88
|
+
// can produce enormous deltas. Clamp the delta to avoid massive jumps.
|
|
89
|
+
const maxDragDelta = this._hitPointRadius * 0.1; // Max 10% of hit radius per frame
|
|
90
|
+
const deltaLength = delta.length();
|
|
91
|
+
if (deltaLength > maxDragDelta) {
|
|
92
|
+
delta.scaleInPlace(maxDragDelta / deltaLength);
|
|
93
|
+
}
|
|
90
94
|
this._previousDragPlaneHitPointLocal.copyFrom(this._dragPlaneHitPointLocal);
|
|
91
95
|
Vector3.TransformNormalToRef(delta, localToEcef, delta);
|
|
92
96
|
this._dragPlaneOriginPointEcef.addInPlace(delta);
|
|
@@ -149,6 +153,7 @@ export class GeospatialCameraMovement extends CameraMovement {
|
|
|
149
153
|
return this._scene.pickWithRay(this._tempPickingRay, this.pickPredicate);
|
|
150
154
|
}
|
|
151
155
|
}
|
|
156
|
+
/** @internal */
|
|
152
157
|
export function ClampCenterFromPolesInPlace(center) {
|
|
153
158
|
const sineOfSphericalLatitudeLimit = 0.998749218; // ~90 degrees
|
|
154
159
|
const centerMagnitude = center.length(); // distance from planet origin
|