Touch device camera pinch zoom, pan and rotate
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Touch device camera pinch zoom, pan and rotate
I'm working on a multi-touch device where user can adjust the camera by two touches. I want to implement PinchZoom, Pan and Rotate when the user makes two touches on the screen.
I've four 2D points touch1.start, touch1.end, touch2.start and touch2.end.
I can identify the zoom action by finding whether the direction of touch1 and touch2 are opposite to each other.
But I need the screen to behave exactly as how human brain thinks. i.e. it should rotate, pan and zoom along with the finger movements if you know what I mean.. Any help will be appreciated.
I've four 2D points touch1.start, touch1.end, touch2.start and touch2.end.
I can identify the zoom action by finding whether the direction of touch1 and touch2 are opposite to each other.
But I need the screen to behave exactly as how human brain thinks. i.e. it should rotate, pan and zoom along with the finger movements if you know what I mean.. Any help will be appreciated.
Re: Touch device camera pinch zoom, pan and rotate
What's your problem exactly? Do you just want to know how to find out how big the rotaton, zoom and move is or do you want to know how to transform the camera with these values?
You can easily read out the rotation, zoom and movement using basic maths.
I assume that all the 2D points are floats. You may have to convert them first.
//ROTATION
//assuming that atan2 takes first the y and then the x value
f32 startRotation = atan2(touch2.start.Y - touch1.start.Y, touch2.start.X - touch1.start.X);
f32 endRotation = atan2(touch2.end.Y - touch1.end.Y, touch2.end.X - touch1.end.X);
f32 rotationDif = endRotation - startRotation; //the actual rotation around the view axis in radians i think. you may have to convert it to degrees
//ZOOM
f32 startDist = touch1.start.getDistanceFrom(touch2.start);
f32 endDist = touch1.end.getDistanceFrom(touch2.end);
f32 zoomDif = endDist / startDist; //Zoom factor. less than 1 for zoom in, more than one to zoom out.
//MOVE
vector2df centerStart = (touch1.start + touch2.start) / 2;
vector2df centerEnd = (touch1.end + touch2.end) / 2;
vector2df moveDif = centerEnd - centerStart; //Movement on view plane
You can easily read out the rotation, zoom and movement using basic maths.
I assume that all the 2D points are floats. You may have to convert them first.
//ROTATION
//assuming that atan2 takes first the y and then the x value
f32 startRotation = atan2(touch2.start.Y - touch1.start.Y, touch2.start.X - touch1.start.X);
f32 endRotation = atan2(touch2.end.Y - touch1.end.Y, touch2.end.X - touch1.end.X);
f32 rotationDif = endRotation - startRotation; //the actual rotation around the view axis in radians i think. you may have to convert it to degrees
//ZOOM
f32 startDist = touch1.start.getDistanceFrom(touch2.start);
f32 endDist = touch1.end.getDistanceFrom(touch2.end);
f32 zoomDif = endDist / startDist; //Zoom factor. less than 1 for zoom in, more than one to zoom out.
//MOVE
vector2df centerStart = (touch1.start + touch2.start) / 2;
vector2df centerEnd = (touch1.end + touch2.end) / 2;
vector2df moveDif = centerEnd - centerStart; //Movement on view plane
Last edited by Foaly on Thu Aug 07, 2014 8:14 pm, edited 1 time in total.
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Re: Touch device camera pinch zoom, pan and rotate
The trouble is I've to update the viewCamera's position, rotation and Target position in 3D to apply Pan, Zoom and Rotation simultaneously.
Re: Touch device camera pinch zoom, pan and rotate
Sorry, I did a mistake in the last post. The zoom factor is "endDist / startDist".
So you want all that for a 3D application. Then what do you actually want to do?
Do you want to orbit aroud something, or just rotate around the view axis and move on the view plane?
Do you have an orthographic or a perspective camera?
Do your want to actually "zoom" like a camera, or just move forward and backward?
We can't help you, if you don't explain what you need.
So you want all that for a 3D application. Then what do you actually want to do?
Do you want to orbit aroud something, or just rotate around the view axis and move on the view plane?
Do you have an orthographic or a perspective camera?
Do your want to actually "zoom" like a camera, or just move forward and backward?
We can't help you, if you don't explain what you need.
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Re: Touch device camera pinch zoom, pan and rotate
I've done the swipe action as moving the camera around the target in a fixed radius(spherical movement). Zooming in or out should decrease/increase the radius. Pan should move the target and rotation should rotate the camera.
Swipe is a 1 touch event and Zoom, Pan and Rotate are two touch events.
It's a perspective camera like an eye.
Swipe is a 1 touch event and Zoom, Pan and Rotate are two touch events.
It's a perspective camera like an eye.
Re: Touch device camera pinch zoom, pan and rotate
Did you already implement the swipe action?
Then I think I'd know how to do the others.
You'll have to calculate rotationDif, zoomDif and moveDif first.
Code is untested!!! Maybe you have to invert some vectors etc.
Then I think I'd know how to do the others.
You'll have to calculate rotationDif, zoomDif and moveDif first.
Code is untested!!! Maybe you have to invert some vectors etc.
Code: Select all
ICameraSceneNode* cam; //This has to be the camera you want to move. I'm not sure if you have to bind rotation and target.
vector3df camStartUpVector;
vector3df camStartPosition;
vector3df camStartTarget;
bool isTwoTouchEvent;
//Call this every time when event starts, stores initial values
void startTwoTouchEvent()
{
isTwoTouchEvent = true;
camStartUpVector = cam.getUpVector();
camStartPosition = cam.getPosition();
camStartTarget = cam.getTarget();
}
void endTwoTouchEvent()
{
isTwoTouchEvent = false;
}
Code: Select all
//Every frame
if (isTwoTouchEvent)
{
//ROTATION
//assuming that atan2 takes first the y and then the x value
f32 startRotation = atan2(touch2.start.Y - touch1.start.Y, touch2.start.X - touch1.start.X);
f32 endRotation = atan2(touch2.end.Y - touch1.end.Y, touch2.end.X - touch1.end.X);
f32 rotationDif = endRotation - startRotation; //the actual rotation around the view axis in radians i think.
//ZOOM
f32 startDist = touch1.start.getDistanceFrom(touch2.start);
f32 endDist = touch1.end.getDistanceFrom(touch2.end);
f32 zoomDif = endDist / startDist; //Zoom factor. less than 1 for zoom in, more than one to zoom out.
//MOVE
vector2df centerStart = (touch1.start + touch2.start) / 2;
vector2df centerEnd = (touch1.end + touch2.end) / 2;
vector2df moveDif = centerEnd - centerStart; //Movement on view plane
vector3df camForward = (camStartTarget - camStartPosition).normalize();
vector3df camRight = camForward.crossProduct(camStartUpVecor).normalize();
vector3df camUpReal = camRight.crossProduct(camForward).normalize(); //Actually, it should be 1 unit long, normalize shouldn't be needed...
//Apply rotation
core::quaternion quat;
quat.fromAngleAxis(rotationDif, camForward); //This takes rotation in rad, so it's already right
core::matrix4 mat = quat.getMatrix();
mat.rotateVect(camUpReal);
mat.rotateVect(camRight);
cam.setUpVector(camUpReal);
//Apply scale
f32 targetDist = camStartPosition.getDistanceFrom(camStartTarget);
f32 moveDist = targetDist - targetDist * zoomDif;
cam.setPosition(camStartPosition + camForward * moveDist);
//Apply movement
vector3df movement = camRight*moveDif.X + camUpReal*moveDif.Y;
cam.setPosition(cam.getPosition() + movement);
cam.setTarget(camStartTarget + movement);
}
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Re: Touch device camera pinch zoom, pan and rotate
Yeah. Thank you so much.. I'll test it and let you know how it behaves
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Re: Touch device camera pinch zoom, pan and rotate
There are problems with rotation.
Also zoom should be startDist / endDist
Also zoom should be startDist / endDist
Re: Touch device camera pinch zoom, pan and rotate
What are the problems with rotation?
Move and zoom work as they should?
Move and zoom work as they should?
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Re: Touch device camera pinch zoom, pan and rotate
Only problem I have now is swipe.
Code: Select all
vector3df cameraAngle, cameraTarget;
float cameraRadius;
void updateCamera()
{
vector3df newCameraPosition;
newCameraPosition.Y = cameraTarget.Y + cameraRadius * sin(cameraAngle.Y * 3.1415 / 180.0f);
newCameraPosition.X = cameraTarget.X + cameraRadius * cos(cameraAngle.Y * 3.1415 / 180.0f) * cos(cameraAngle.X * 3.1415 / 180.0f);
newCameraPosition.Z = cameraTarget.Z + cameraRadius * cos(cameraAngle.Y * 3.1415 / 180.0f) * sin(cameraAngle.X * 3.1415 / 180.0f);
viewCamera->setPosition(newCameraPosition);
viewCamera->updateAbsolutePosition();
viewCamera->setTarget(cameraTarget);
}
void swipeProgress(vector2df touch)
{
vector2df moveDif = (prevTouchPoints[0]-touch);
//Have to find the value of cameraAngle here
updateCamera();
prevTouchPoints[0] = touch;
}
void panProgress(vector2df touch1, vector2df touch2){
//ZOOM
f32 startDist = prevTouchPoints[0].getDistanceFrom(prevTouchPoints[1]);
f32 endDist = touch1.getDistanceFrom(touch2);
f32 zoomDif = startDist / endDist;
cameraRadius = max(0.01f, cameraRadius*zoomDif);
//MOVE
vector2df centerStart = (prevTouchPoints[0] + prevTouchPoints[1]) / 2.0;
vector2df centerEnd = (touch1 + touch2) / 2.0;
vector2df moveDif = (centerEnd - centerStart) / 10.0; //Divided by 10.0 to reduce pan movement speed.
vector3df camForward = (viewCamera->getTarget() - viewCamera->getPosition()).normalize();
vector3df camRight = camForward.crossProduct(viewCamera->getUpVector()).normalize();
vector3df camUpReal = camRight.crossProduct(camForward).normalize();
cameraTarget = viewCamera->getTarget() + camRight*moveDif.X + camUpReal*moveDif.Y;
//ROTATION
f32 startRotation = atan2(prevTouchPoints[1].Y - prevTouchPoints[0].Y, prevTouchPoints[1].X - prevTouchPoints[0].X);
f32 endRotation = atan2(touch2.Y - touch1.Y, touch2.X - touch1.X);
f32 rotationDif = endRotation - startRotation;
core::quaternion quat;
quat.fromAngleAxis(rotationDif, camForward);
core::matrix4 mat = quat.getMatrix();
mat.rotateVect(camUpReal);
mat.rotateVect(camRight);
viewCamera->setUpVector(camUpReal);
updateCamera();
prevTouchPoints[0] = touch1; prevTouchPoints[1] = touch2;
}
Re: Touch device camera pinch zoom, pan and rotate
So all two touch actions work?
How do you actually want the "swipe" to behave? Do you want to rotate around the target or do you want a look motion like in a first person shooter?
How do you actually want the "swipe" to behave? Do you want to rotate around the target or do you want a look motion like in a first person shooter?
-
- Posts: 41
- Joined: Thu Feb 27, 2014 10:55 am
Re: Touch device camera pinch zoom, pan and rotate
Rotate around the target!
Re: Touch device camera pinch zoom, pan and rotate
Well, there are different possibilities to do that...
I think the best is to remember the distance to the target.
Then get the current direction to the target: (targetPos - camerapos).Normalize()
Then you rotate that direction using quaternions and matrices. (Just look at the two touch rotation, there you already use this kind of rotation).
You have to rotate it around the camera up axis and the camera right axis (camera up axis for y movement of the touch, right axis for x movement).
After that you multiply this new direction with the distance and add it to the target position.
I hope this helps you. (And I hope it's correct)
Please try to figure it out yourself before you ask again. It will help you more for future projects if you learn to find out things yourself.
But if you really don't make any progress, you can ask again.
I think the best is to remember the distance to the target.
Then get the current direction to the target: (targetPos - camerapos).Normalize()
Then you rotate that direction using quaternions and matrices. (Just look at the two touch rotation, there you already use this kind of rotation).
You have to rotate it around the camera up axis and the camera right axis (camera up axis for y movement of the touch, right axis for x movement).
After that you multiply this new direction with the distance and add it to the target position.
I hope this helps you. (And I hope it's correct)
Please try to figure it out yourself before you ask again. It will help you more for future projects if you learn to find out things yourself.
But if you really don't make any progress, you can ask again.