0
votes

I want to pinch zoom around a specific coordinate on a tiled 15f x 15f 3D board. I.e. I don't want to zoom around origin. Thus I need to pan the board accordingly.

I am using a PerspectiveCamera (near=0.1f, far=100f). For a perfect fit of the screen the camera is located at approx.z=13.4 before zooming.

Now what (I think) I want to do is to:

Unproject the screen coordinates (GestureDetector.pinch method) done once for each pinch zoom:

float icx = (initialPointer1.x + initialPointer2.x) / 2;
float icy = (initialPointer1.y + initialPointer2.y) / 2;
pointToMaintain = new Vector3(icx, icy, 0f);
mCamera.unproject(pointToMaintain);

Now for each zoom cycle (as I adjust the mCamera.z accordingly and do mCamera.update()) I project the point back to screen coordinates:

Vector3 pointNewPos = new Vector3(pointToMaintain);
mCamera.project(pointNewPos);

Then calculate the delta and pan accordingly:

int dX = (int) (pointNewPos.x - icx);
int dY = (int) (pointNewPos.y - icy);
pan(...); /* I.e. mCamera.translate(...) */

My problem is that the mCamera.z is initially above pointToMaintain.z and then goes below as the user moves the fingers:

   cam.z   ptm.z   dX    dY
0  13.40
1  13.32   13.30   12   134
2  13.24   13.30   12  -188
...

(0) is the original value of mCamera.z before zooming starts. (1) is not not valid? However (2) should be OK.

My questions are:

(1) How can I get a "valid" pointToMaintain when unprojecting the screen coordinates on the camera. I.e. a point that is not less than cam.z. (The reason I get the point to 13.30 is (I guess) because near=0.1f. But as seen above this results in (weird?) screen coordinates).

(2) Is this a good strategy for moving the tiles board closer to the coordinates the user pinched zoomed on?

1

1 Answers

2
votes

To mantain focus points, I did this code:

Obs: This code relies on overloaded operators, you need to change the vectors operators by its method (addMe, subtract, etc)

void zoomAt(float changeAmmount, Vector2D focus) {
    float newZoom = thisZoom + changeAmmount;
    offset = focus - ((focus - offset) * newZoom / thisZoom);
    thisZoom = newZoom;
}

Where

focus = Current center point to mantain

offset = Distance from 0,0

thisZoom = current zoom ammount; (starts at 1)

changeAmmount = value to increase or decrease zoom

It took me 4 tries along of 3 years to make it done, and was pretty easy when you drawn it down, its just two triangles.