Make the camera zoom-in when tilting, instead of blocking the tilt. Closes: #279

This commit is contained in:
Lukas Rieger (Blue) 2024-11-27 23:12:04 +01:00
parent 05a1cacd98
commit b32f808be1
No known key found for this signature in database
GPG Key ID: AA33883B1BBA03E6
9 changed files with 50 additions and 8 deletions

View File

@ -96,6 +96,7 @@ export class MapControls {
*/
start(manager) {
this.manager = manager;
this.snapDistance = manager.distance;
this.rootElement.addEventListener("contextmenu", this.onContextMenu);
this.hammer.on("tap", this.onTap);
@ -172,9 +173,6 @@ export class MapControls {
this.manager.distance = softClamp(this.manager.distance, this.minDistance, this.maxDistance, 0.8);
// max angle for current distance
let maxAngleForZoom = MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance);
// rotation
this.mouseRotate.update(delta, map);
this.keyRotate.update(delta, map);
@ -193,12 +191,11 @@ export class MapControls {
this.mouseAngle.update(delta, map);
this.keyAngle.update(delta, map);
this.touchAngle.update(delta, map);
this.manager.angle = softClamp(this.manager.angle, 0, maxAngleForZoom, 0.8);
this.manager.angle = softClamp(this.manager.angle, 0, HALF_PI, 0.8);
}
// target height
if (this.manager.ortho === 0 || this.manager.angle === 0) {
this.mapHeight.maxAngle = maxAngleForZoom;
this.mapHeight.update(delta, map);
}
}

View File

@ -24,6 +24,7 @@
*/
import {MathUtils, Vector2} from "three";
import {MapControls} from "./MapControls";
export class MapHeightControls {
@ -36,7 +37,6 @@ export class MapHeightControls {
this.cameraHeightStiffness = cameraHeightStiffness;
this.targetHeightStiffness = targetHeightStiffness;
this.maxAngle = Math.PI / 2;
this.targetHeight = 0;
this.cameraHeight = 0;
@ -78,7 +78,8 @@ export class MapHeightControls {
// camera height
this.minCameraHeight = 0;
if (this.maxAngle >= 0.1) {
let maxAngle = MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance);
if (maxAngle >= 0.1) {
let cameraSmoothing = this.cameraHeightStiffness / (16.666 / delta);
cameraSmoothing = MathUtils.clamp(cameraSmoothing, 0, 1);
@ -88,7 +89,7 @@ export class MapHeightControls {
this.cameraHeight += cameraDelta * cameraSmoothing;
if (Math.abs(cameraDelta) < 0.001) this.cameraHeight = cameraTerrainHeight;
let maxAngleHeight = Math.cos(this.maxAngle) * this.manager.distance;
let maxAngleHeight = Math.cos(maxAngle) * this.manager.distance;
this.minCameraHeight = this.cameraHeight - maxAngleHeight + 1;
}

View File

@ -25,6 +25,8 @@
import {MathUtils} from "three";
import {KeyCombination} from "../../KeyCombination";
import {softMax} from "../../../util/Utils";
import {MapControls} from "../MapControls";
export class KeyAngleControls {
@ -90,6 +92,7 @@ export class KeyAngleControls {
smoothing = MathUtils.clamp(smoothing, 0, 1);
this.manager.angle += this.deltaAngle * smoothing * this.speed * delta * 0.06;
this.manager.angle = softMax(this.manager.angle, MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance), 0.8);
this.deltaAngle *= 1 - smoothing;
if (Math.abs(this.deltaAngle) < 0.0001) {

View File

@ -25,6 +25,7 @@
import {MathUtils} from "three";
import {KeyCombination} from "../../KeyCombination";
import {MapControls} from "../MapControls";
export class KeyZoomControls {
@ -88,6 +89,7 @@ export class KeyZoomControls {
smoothing = MathUtils.clamp(smoothing, 0, 1);
this.manager.distance *= Math.pow(1.5, this.deltaZoom * smoothing * this.speed * delta * 0.06);
this.manager.angle = Math.min(this.manager.angle, MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance));
this.deltaZoom *= 1 - smoothing;
if (Math.abs(this.deltaZoom) < 0.0001) {

View File

@ -24,6 +24,8 @@
*/
import {MathUtils} from "three";
import {MapControls} from "../MapControls";
import {softMax, softSet} from "../../../util/Utils";
export class MouseAngleControls {
@ -40,6 +42,9 @@ export class MouseAngleControls {
this.lastY = 0;
this.deltaAngle = 0;
this.dynamicDistance = false;
this.startDistance = 0;
this.speed = speed;
this.stiffness = stiffness;
@ -56,6 +61,7 @@ export class MouseAngleControls {
this.target.addEventListener("mousedown", this.onMouseDown);
window.addEventListener("mousemove", this.onMouseMove);
window.addEventListener("mouseup", this.onMouseUp);
window.addEventListener("wheel", this.onWheel);
window.addEventListener("resize", this.updatePixelToSpeedMultiplier);
}
@ -64,6 +70,7 @@ export class MouseAngleControls {
this.target.removeEventListener("mousedown", this.onMouseDown);
window.removeEventListener("mousemove", this.onMouseMove);
window.removeEventListener("mouseup", this.onMouseUp);
window.removeEventListener("wheel", this.onWheel);
window.removeEventListener("resize", this.updatePixelToSpeedMultiplier);
}
@ -80,6 +87,12 @@ export class MouseAngleControls {
this.manager.angle += this.deltaAngle * smoothing * this.speed * this.pixelToSpeedMultiplierY;
if (this.dynamicDistance) {
this.manager.distance = softSet(this.manager.distance, Math.min(MapControls.getMaxDistanceForPerspectiveAngle(this.manager.angle), this.startDistance), 0.4);
} else {
this.manager.angle = softMax(this.manager.angle, MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance), 0.8);
}
this.deltaAngle *= 1 - smoothing;
if (Math.abs(this.deltaAngle) < 0.0001) {
this.deltaAngle = 0;
@ -100,6 +113,9 @@ export class MouseAngleControls {
this.moving = true;
this.deltaAngle = 0;
this.lastY = evt.y;
this.startDistance = this.manager.distance;
this.dynamicDistance = this.manager.distance < 1000;
}
}
@ -123,6 +139,10 @@ export class MouseAngleControls {
this.moving = false;
}
onWheel = evt => {
this.dynamicDistance = false;
}
updatePixelToSpeedMultiplier = () => {
this.pixelToSpeedMultiplierY = 1 / this.target.clientHeight;
}

View File

@ -24,6 +24,7 @@
*/
import {MathUtils} from "three";
import {MapControls} from "../MapControls";
export class MouseZoomControls {
@ -66,6 +67,7 @@ export class MouseZoomControls {
smoothing = MathUtils.clamp(smoothing, 0, 1);
this.manager.distance *= Math.pow(1.5, this.deltaZoom * smoothing * this.speed);
this.manager.angle = Math.min(this.manager.angle, MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance));
this.deltaZoom *= 1 - smoothing;
if (Math.abs(this.deltaZoom) < 0.0001) {

View File

@ -24,6 +24,8 @@
*/
import {MathUtils} from "three";
import {softMax} from "../../../util/Utils";
import {MapControls} from "../MapControls";
export class TouchAngleControls {
@ -83,6 +85,7 @@ export class TouchAngleControls {
smoothing = MathUtils.clamp(smoothing, 0, 1);
this.manager.angle += this.deltaAngle * smoothing * this.speed * this.pixelToSpeedMultiplierY;
this.manager.angle = softMax(this.manager.angle, MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance), 0.8);
this.deltaAngle *= 1 - smoothing;
if (Math.abs(this.deltaAngle) < 0.0001) {

View File

@ -23,6 +23,8 @@
* THE SOFTWARE.
*/
import {MapControls} from "../MapControls";
export class TouchZoomControls {
/**
@ -87,6 +89,7 @@ export class TouchZoomControls {
onTouchMove = evt => {
if(this.moving){
this.deltaZoom *= evt.scale / this.lastZoom;
this.manager.angle = Math.min(this.manager.angle, MapControls.getMaxPerspectiveAngleForDistance(this.manager.distance));
}
this.lastZoom = evt.scale;

View File

@ -377,6 +377,17 @@ export const softClamp = (value, min, max, stiffness) => {
return softMax(softMin(value, min, stiffness), max, stiffness);
}
/**
* Softly sets a value
* @param value {number}
* @param target {number}
* @param stiffness {number}
* @returns {number}
*/
export const softSet = (value, target, stiffness) => {
return softClamp(value, target, target, stiffness);
}
export const vecArrToObj = (val, useZ = false) => {
if (val && val.length >= 2) {
if (useZ) return {x: val[0], z: val[1]};