# Panning a 3d viewport in 2d direction with rotated camera

I am using below code to pan the viewport (action script 3 code using flare3d framework)

_mainCamera.x-= Input3D.mouseXSpeed;
_mainCamera.z+= Input3D.mouseYSpeed;


Where as Input3D.mouse[X|Y]Speed gives the displacement of the mouse on the X/Y axis starting from the position of the last frame.

This works perfect if my camera is not rotated. However, if I rotate the camera (x by 30, y by 60) and pan the camera then it goes wrong. Which is actually correctly panning according to the code. But this is not desired and I know I need to do some math to get the correct x/y which I am not aware of it.

Can some one help me achieving it?

Update:

I am getting an Idea but I am not sure how to do it :(

1. Get the mouseX/Y deltas (xd,yd)
2. Get the current camera coords (pos3d)
3. Convert to screen coords (pos2d)
4. Add deltas to screen coords (pos2d+ (xd,yd))
5. Convert above coords to 3d coords
• If you need help with my answer just say anything.... – jmacedo Oct 22 '12 at 17:06
• I am very new to 3d, so if you can help me understand how your code achieves my requirement would be helpful. – Noob Game Developer Oct 23 '12 at 5:39
• Your camera rotates around 1 or 2 axis? My answer only takes into account rotation around a single axis. I'll create an illustration of it. – jmacedo Oct 23 '12 at 19:54
• The illustration explaining my reasoning is done, I updated my answer :) – jmacedo Oct 23 '12 at 21:25

I've faced this exact same issue a few days ago. I have a camera class which deals with camera logic. It has a method which receives the mouse deltas and according to it, changes the camera speed (because I have a smooth panning using speed instead of position), but for the position the reasoning is completly analogous. This code is in java but you can easily extract the math from it:

public void incSpeed(float deltaX, float deltaY){
//{upx,upy} is the up vector of your camera
float angDifUp = - (float) (Math.PI/2.0) + MyMath.vector2dAngle(new float[]{upx,upy});
float angDelta = MyMath.vector2dAngle(new float[]{deltaX,deltaY});
//Norm of the delta vector
float normDelta = MyMath.distance2d(new float[]{deltaX,deltaY}, new float[]{0,0});
float newDelta[] = new float[]{normDelta*FloatMath.cos(angDelta+angDifUp),normDelta*FloatMath.sin(angDelta+angDifUp)};

vx += newDelta;
vy += newDelta;
}


This works by manipulating the panning vector according to the rotation of the camera.

You might have to provide the negative of deltaX and/or deltaY to the method for it to work correctly depending on how you calculate the deltas.

You may also need to take the minus sign out of the angDifUp variable.

If I were you I'd try the 8 combinations of (+/-|+/-|+/-) if it doest work right away.

If you want I might add extra explanations later.

Good luck.

Edit I made a sketchy illustration explaining the reasioning: • can you please help me translate this. I need to know what exactly vector2dangle does? – Noob Game Developer Oct 20 '12 at 11:29
• In actionscript I think the atan2 function does exactly the same... try it. Anyway, if it doesnt work , use this: public static float vector2dAngle(float[] vector){ if(vector != 0){ return (float) (vector > 0 ? Math.atan(vector/vector) : Math.atan(vector/vector) - Math.PI);} else{ return (float) (vector > 0 ? Math.PI/2 : -Math.PI/2);} } – jmacedo Oct 20 '12 at 12:21
• @NoobGameDeveloper To know what the code above calculates see: people.sinclair.edu/nickreeder/eet155/PageArt/vector.gif – jmacedo Oct 20 '12 at 12:42