diff --git a/CHANGES.md b/CHANGES.md index 4e7e3c3d086c..b30d43978dae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ ##### Fixes :wrench: +- Fixed an issue where the camera zooming is stuck when looking up. [#9126](https://github.com/CesiumGS/cesium/pull/9126) - Fixed an issue where Plane doesn't rotate correctly around the main local axis. [#8268](https://github.com/CesiumGS/cesium/issues/8268) ### 1.73 - 2020-09-01 diff --git a/Source/Scene/ScreenSpaceCameraController.js b/Source/Scene/ScreenSpaceCameraController.js index 9866dde783a2..a55ee9a03110 100644 --- a/Source/Scene/ScreenSpaceCameraController.js +++ b/Source/Scene/ScreenSpaceCameraController.js @@ -705,161 +705,168 @@ function handleZoom( ); // If centerPosition is not defined, it means the globe does not cover the center position of screen - if ( - defined(centerPosition) && - camera.positionCartographic.height < 1000000 - ) { - var cameraPosition = scratchCameraPosition; - Cartesian3.clone(camera.position, cameraPosition); - var target = object._zoomWorldPosition; - - var targetNormal = scratchTargetNormal; - - targetNormal = Cartesian3.normalize(target, targetNormal); - - if (Cartesian3.dot(targetNormal, cameraPositionNormal) < 0.0) { - return; - } + if (!defined(centerPosition)) { + zoomOnVector = true; + } else if (camera.positionCartographic.height < 1000000) { + // The math in the else block assumes the camera + // points toward the earth surface, so we check it here. + // Theoretically, we should check for 90 degree, but it doesn't behave well when parallel + // to the earth surface + if (Cartesian3.dot(camera.direction, cameraPositionNormal) >= -0.5) { + zoomOnVector = true; + } else { + var cameraPosition = scratchCameraPosition; + Cartesian3.clone(camera.position, cameraPosition); + var target = object._zoomWorldPosition; + + var targetNormal = scratchTargetNormal; + + targetNormal = Cartesian3.normalize(target, targetNormal); + + if (Cartesian3.dot(targetNormal, cameraPositionNormal) < 0.0) { + return; + } + + var center = scratchCenter; + var forward = scratchForwardNormal; + Cartesian3.clone(camera.direction, forward); + Cartesian3.add( + cameraPosition, + Cartesian3.multiplyByScalar(forward, 1000, scratchCartesian), + center + ); - var center = scratchCenter; - var forward = scratchForwardNormal; - Cartesian3.clone(camera.direction, forward); - Cartesian3.add( - cameraPosition, - Cartesian3.multiplyByScalar(forward, 1000, scratchCartesian), - center - ); + var positionToTarget = scratchPositionToTarget; + var positionToTargetNormal = scratchPositionToTargetNormal; + Cartesian3.subtract(target, cameraPosition, positionToTarget); - var positionToTarget = scratchPositionToTarget; - var positionToTargetNormal = scratchPositionToTargetNormal; - Cartesian3.subtract(target, cameraPosition, positionToTarget); + Cartesian3.normalize(positionToTarget, positionToTargetNormal); - Cartesian3.normalize(positionToTarget, positionToTargetNormal); + var alphaDot = Cartesian3.dot( + cameraPositionNormal, + positionToTargetNormal + ); + if (alphaDot >= 0.0) { + // We zoomed past the target, and this zoom is not valid anymore. + // This line causes the next zoom movement to pick a new starting point. + object._zoomMouseStart.x = -1; + return; + } + var alpha = Math.acos(-alphaDot); + var cameraDistance = Cartesian3.magnitude(cameraPosition); + var targetDistance = Cartesian3.magnitude(target); + var remainingDistance = cameraDistance - distance; + var positionToTargetDistance = Cartesian3.magnitude( + positionToTarget + ); - var alphaDot = Cartesian3.dot( - cameraPositionNormal, - positionToTargetNormal - ); - if (alphaDot >= 0.0) { - // We zoomed past the target, and this zoom is not valid anymore. - // This line causes the next zoom movement to pick a new starting point. - object._zoomMouseStart.x = -1; - return; - } - var alpha = Math.acos(-alphaDot); - var cameraDistance = Cartesian3.magnitude(cameraPosition); - var targetDistance = Cartesian3.magnitude(target); - var remainingDistance = cameraDistance - distance; - var positionToTargetDistance = Cartesian3.magnitude(positionToTarget); - - var gamma = Math.asin( - CesiumMath.clamp( - (positionToTargetDistance / targetDistance) * Math.sin(alpha), - -1.0, - 1.0 - ) - ); - var delta = Math.asin( - CesiumMath.clamp( - (remainingDistance / targetDistance) * Math.sin(alpha), - -1.0, - 1.0 - ) - ); - var beta = gamma - delta + alpha; + var gamma = Math.asin( + CesiumMath.clamp( + (positionToTargetDistance / targetDistance) * Math.sin(alpha), + -1.0, + 1.0 + ) + ); + var delta = Math.asin( + CesiumMath.clamp( + (remainingDistance / targetDistance) * Math.sin(alpha), + -1.0, + 1.0 + ) + ); + var beta = gamma - delta + alpha; - var up = scratchCameraUpNormal; - Cartesian3.normalize(cameraPosition, up); - var right = scratchCameraRightNormal; - right = Cartesian3.cross(positionToTargetNormal, up, right); - right = Cartesian3.normalize(right, right); + var up = scratchCameraUpNormal; + Cartesian3.normalize(cameraPosition, up); + var right = scratchCameraRightNormal; + right = Cartesian3.cross(positionToTargetNormal, up, right); + right = Cartesian3.normalize(right, right); - Cartesian3.normalize( - Cartesian3.cross(up, right, scratchCartesian), - forward - ); + Cartesian3.normalize( + Cartesian3.cross(up, right, scratchCartesian), + forward + ); - // Calculate new position to move to - Cartesian3.multiplyByScalar( - Cartesian3.normalize(center, scratchCartesian), - Cartesian3.magnitude(center) - distance, - center - ); - Cartesian3.normalize(cameraPosition, cameraPosition); - Cartesian3.multiplyByScalar( - cameraPosition, - remainingDistance, - cameraPosition - ); + // Calculate new position to move to + Cartesian3.multiplyByScalar( + Cartesian3.normalize(center, scratchCartesian), + Cartesian3.magnitude(center) - distance, + center + ); + Cartesian3.normalize(cameraPosition, cameraPosition); + Cartesian3.multiplyByScalar( + cameraPosition, + remainingDistance, + cameraPosition + ); - // Pan - var pMid = scratchPan; - Cartesian3.multiplyByScalar( - Cartesian3.add( - Cartesian3.multiplyByScalar( - up, - Math.cos(beta) - 1, - scratchCartesianTwo - ), - Cartesian3.multiplyByScalar( - forward, - Math.sin(beta), - scratchCartesianThree + // Pan + var pMid = scratchPan; + Cartesian3.multiplyByScalar( + Cartesian3.add( + Cartesian3.multiplyByScalar( + up, + Math.cos(beta) - 1, + scratchCartesianTwo + ), + Cartesian3.multiplyByScalar( + forward, + Math.sin(beta), + scratchCartesianThree + ), + scratchCartesian ), - scratchCartesian - ), - remainingDistance, - pMid - ); - Cartesian3.add(cameraPosition, pMid, cameraPosition); + remainingDistance, + pMid + ); + Cartesian3.add(cameraPosition, pMid, cameraPosition); - Cartesian3.normalize(center, up); - Cartesian3.normalize( - Cartesian3.cross(up, right, scratchCartesian), - forward - ); + Cartesian3.normalize(center, up); + Cartesian3.normalize( + Cartesian3.cross(up, right, scratchCartesian), + forward + ); - var cMid = scratchCenterMovement; - Cartesian3.multiplyByScalar( - Cartesian3.add( - Cartesian3.multiplyByScalar( - up, - Math.cos(beta) - 1, - scratchCartesianTwo - ), - Cartesian3.multiplyByScalar( - forward, - Math.sin(beta), - scratchCartesianThree + var cMid = scratchCenterMovement; + Cartesian3.multiplyByScalar( + Cartesian3.add( + Cartesian3.multiplyByScalar( + up, + Math.cos(beta) - 1, + scratchCartesianTwo + ), + Cartesian3.multiplyByScalar( + forward, + Math.sin(beta), + scratchCartesianThree + ), + scratchCartesian ), - scratchCartesian - ), - Cartesian3.magnitude(center), - cMid - ); - Cartesian3.add(center, cMid, center); - - // Update camera + Cartesian3.magnitude(center), + cMid + ); + Cartesian3.add(center, cMid, center); - // Set new position - Cartesian3.clone(cameraPosition, camera.position); + // Update camera - // Set new direction - Cartesian3.normalize( - Cartesian3.subtract(center, cameraPosition, scratchCartesian), - camera.direction - ); - Cartesian3.clone(camera.direction, camera.direction); + // Set new position + Cartesian3.clone(cameraPosition, camera.position); - // Set new right & up vectors - Cartesian3.cross(camera.direction, camera.up, camera.right); - Cartesian3.cross(camera.right, camera.direction, camera.up); + // Set new direction + Cartesian3.normalize( + Cartesian3.subtract(center, cameraPosition, scratchCartesian), + camera.direction + ); + Cartesian3.clone(camera.direction, camera.direction); - camera.setView(scratchZoomViewOptions); - return; - } + // Set new right & up vectors + Cartesian3.cross(camera.direction, camera.up, camera.right); + Cartesian3.cross(camera.right, camera.direction, camera.up); - if (defined(centerPosition)) { + camera.setView(scratchZoomViewOptions); + return; + } + } else { var positionNormal = Cartesian3.normalize( centerPosition, scratchPositionNormal @@ -885,8 +892,6 @@ function handleZoom( var scalar = distance / denom; camera.rotate(axis, angle * scalar); } - } else { - zoomOnVector = true; } } }