How to apply 2-finger touch anywhere in the image, such that the point stays at the same location

I have a 2D texture image that is zoomed in/out via 2-finger touch and pinch.
Currently the image is not panned, i.e. the center of the image is always in the middle.
I want the center point between the twoFinger touch to stay between the 2 fingers.

If I pinch exactly in the center of the image, then the center image point will stay between the fingers - good!
But if I pinch near the corner of the image the point will move away, relative to the 2 fingers, because of the zoom.
So I need to apply some pan in addition to the zoom, to make the point appear in the same place.

I basically need to transftorm the camera position such that, for every zoom, the same world coordinate is projected to the same screen coord.

Figures 1-3 illustrate the problem.
Figure1 is the original image.
Currently when I zoom in the camera stays in the same position, so the object between the 2 fingers (the cat’s eye on the right) is drifted from being between the 2 fingers, as the image zooms (Figure 2).
I want to pan the camera such that the object between the 2 fingers stays between the 2 fingers even after the zooming the image (Figure 3).

I used the code below, but the object still drifts as the image zooms in/out.

How should I calculate the amount of shift that needs to be applied to the camera?
Thanks

Code to calculate the amount of shift that needs to be applied to the camera

handleTwoFingerTouchMove( p3_inScreenCoord) {
    // normalize the screen coord to be in the range of [-1, 1]
    // (See method1 in https://stackoverflow.com/questions/13542175/three-js-ray-intersect-fails-by-adding-div/)
    let point2dNormalizedX = ( ( p3_inScreenCoord.x - windowOffset.left ) / windowWidth) * 2 - 1;
    let point2dNormalizedY = -( ( p3_inScreenCoord.y - windowOffset.top ) / windowHeight) * 2 + 1;

    // calc p3 before zoom (in world coords)
    let p3_beforeZoom = new THREE_Vector3( point2dNormalizedX, point2dNormalizedY, -1 ).unproject( this.camera );
    
    // Apply zoom        
    this.dollyInOut( this.getZoomScale(), true );

    // calc p3 after zoom (in world coords)
    let p3_afterZoom = new THREE_Vector3( point2dNormalizedX, point2dNormalizedY, -1 ).unproject( this.camera );

    // calc the required shift in camera position
    let deltaX = p3_afterZoom.x - p3_beforeZoom.x;
    let deltaZ = p3_afterZoom.z - p3_beforeZoom.z;

    // shift in camera position
    this.pan( deltaX, deltaZ );
};

I solved my problem. Yo can see the solution here:

2 Likes