Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Damping (Inertia) to Panorama Rotation

I am aware of OrbitControls.js having a damping feature, which adds a smooth dragging of panorama, also known as easing. I want to implement the same functionality but without using this library. The reason is that I need to reduce amount of code used and get a tighter control of mouse or tap events.

I have built this Plunker to show the demo I use as a starter project for my panorama view.

https://plnkr.co/edit/eX2dwgbrfNoX9RwWaPaH?p=preview

In this demo, mouse coordinates are converted to latitude/longitude, which would adjust camera position. This is the most basic, minimal panorama example from three.js site.

When I was playing around with damping from OrbitControls.js (see this line) I could not quite get the same smooth behavior - interaction caused panorama to jump around:

if ( scope.enableDamping === true ) {
    sphericalDelta.theta *= ( 1 - scope.dampingFactor );
    sphericalDelta.phi *= ( 1 - scope.dampingFactor );
    panOffset.multiplyScalar( 1 - scope.dampingFactor );
}

I do not believe I can fully understand how to apply it to my example in the Plunker.

Can anyone guide me in the right direction to apply damping to my example from Plunker?

Update:

I managed to progress by adding new delta values for longitude and latitude: see latDelta and lonDelta in updated Plunker. I got the idea how it works in OrbitControls.js. You can now observe an ideal smooth scroll on initial page load because of lonDelta = 0.35. However, I am not sure how this is to be manipulated during user mouse scroll. At least I am moving in the right direction.

like image 830
Vad Avatar asked Mar 20 '18 19:03

Vad


1 Answers

You're close! The basic idea is to work out how fast the user was panning, and continue panning at the same speed. Then you can gradually reduce the speed to simulate friction. If you didn't know, 'delta', or d, usually means distance. If you can get the distance the user moved, and the time they took to do it, then you can calculate the speed and apply it using high school physics.

https://plnkr.co/edit/xgDTcdOY5ZfnoVuW599u?p=preview

Here's the important part, from update:

// Get time since last frame
var now = Date.now();
var dT = now - then;

if ( isUserInteracting ) {
    // Get distance travelled since last frame
    var dLon = lon - prevLon;
    var dLat = lat - prevLat;
    // velocity = distance / time
    lonVelocity = dLon / dT;
    latVelocity = dLat / dT;
} else {
    // old position + ( velocity * time ) = new position
    lon += lonVelocity * dT;
    lat += latVelocity * dT;
    // friction
    lonVelocity *= ( 1 - dampingFactor );
    latVelocity *= ( 1 - dampingFactor );
}

// Save these for next frame
then = now;
prevLon = lon;
prevLat = lat;
like image 185
Ben West Avatar answered Oct 20 '22 05:10

Ben West