no-wrap option; pivoted exponential zoom
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package world
|
||||
|
||||
// PivotZoomCameraNoWrap adjusts camera center so that the world point under the cursor remains fixed
|
||||
// when zoom changes from oldZoomFp to newZoomFp.
|
||||
//
|
||||
// Coordinate conventions:
|
||||
// - CameraXWorldFp/YWorldFp is the center of the viewport in world-fixed units.
|
||||
// - cursorXPx/cursorYPx are pixel coordinates relative to the top-left of the viewport.
|
||||
// - viewportW/H are viewport size in pixels.
|
||||
//
|
||||
// This function does not clamp the result; caller should clamp for no-wrap mode using ClampCameraNoWrapViewport.
|
||||
func PivotZoomCameraNoWrap(
|
||||
cameraXWorldFp, cameraYWorldFp int,
|
||||
viewportW, viewportH int,
|
||||
cursorXPx, cursorYPx int,
|
||||
oldZoomFp, newZoomFp int,
|
||||
) (newCamX, newCamY int) {
|
||||
if oldZoomFp <= 0 || newZoomFp <= 0 {
|
||||
panic("PivotZoomCameraNoWrap: invalid zoom")
|
||||
}
|
||||
if viewportW <= 0 || viewportH <= 0 {
|
||||
panic("PivotZoomCameraNoWrap: invalid viewport")
|
||||
}
|
||||
|
||||
// Offset of cursor from viewport center in pixels.
|
||||
offXPx := cursorXPx - viewportW/2
|
||||
offYPx := cursorYPx - viewportH/2
|
||||
|
||||
// World-fixed per 1 pixel at each zoom.
|
||||
// (Conservative: integer arithmetic, consistent with PixelSpanToWorldFixed.)
|
||||
oldWorldPerPx := PixelSpanToWorldFixed(1, oldZoomFp)
|
||||
newWorldPerPx := PixelSpanToWorldFixed(1, newZoomFp)
|
||||
|
||||
// World point under cursor before zoom:
|
||||
// world = camera + offsetPx * worldPerPx
|
||||
worldX := cameraXWorldFp + offXPx*oldWorldPerPx
|
||||
worldY := cameraYWorldFp + offYPx*oldWorldPerPx
|
||||
|
||||
// Choose new camera so that the same world point stays under cursor:
|
||||
// camera' = world - offsetPx * newWorldPerPx
|
||||
newCamX = worldX - offXPx*newWorldPerPx
|
||||
newCamY = worldY - offYPx*newWorldPerPx
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user