Performing Pan Tilt and Zoom using Orthographic camera

Started by
8 comments, last by dave09cbank 8 years ago
I'm trying to perform Pan Tilt and Zoom using a orthographic camera ? Is this possible ?
Currently I can perform Zoom which seems to be working fine but cannot perform Pan/Tilt ?
Not sure how to achieve this ?
One way i'v though is either not use the orthographic camera and rather clip the texture, so that the my clipped texture will be drawn onto my directx surface covering the entire view. I could possibly perform the clipping using a constant buffer but then that would stretch the entire clipped texture over my viewport area.
Also I could relate this post to one of my older post but wasn't sure if it should be posted within that post or not hence i'm posting here.
Any suggestions on the above ?
I'm using Directx11, SharpDx with D3DImage & C#.
Do note: I'v created my vertexes directly screen co-ordinates.
Advertisement

I don't know the specifics of DirectX but you would have a transformation that is your cameras projection and a transformation that defines where your camera is and where it is looking (the view matrix). You will want to leave the projection matrix as it is but instead change the view matrix. You can move using the projection matrix (by changing the left/right, top/bottom values of your orthogonal projection) but I wouldn't advise it. Keeping them separate will be much easier to work with. The fact that you have defined vertices in screen-coordinates shouldn't make a difference.

Checking your other post and it seems like your game is 2D, is that correct? In that case tilting might not be of use to you and both pan and zoom can happily live in the projection matrix easily enough.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

For pan/tilt, the easiest thing to do is setup your view matrix as a 2D camera, you can set it up with a fixed axis (the Z axis typically) since you're always looking towards your scene, and still move the translation/up/right vectors of the matrix. Note that a view matrix is (basically?) an inverted world matrix. Matrices move points from one space to another, so the object matrix moves it from object space to world space, and the view matrix moves it from world space to view space. World space has some arbitrary center at 0,0,0, while view space has an absolute center at the viewer itself. So it ultimately subtracts the viewers world space coordinates to move it to be centered around the viewer.

For panning, you just move the cameras position left/right/up/down/etc. This will give you a more intuitive way of panning since it's really just moving the camera around the scene.

The same holds true for tilt, if you rotate the camera, the view matrix rotation will be the inverse of that, and will rotate things into view space. You can use Matrix.RotationZ to create a matrix that just rotates around the Z axis, so it will still look towards your scene (the Z axis doesn't change), but the up/left axis rotate around. This gives you a simpler 2D rotation which will tilt your scene.

To sum up, move/rotate your camera around your scene, then create a final world space matrix from the camera translation/rotation, then invert that to get the view matrix.

@Nanoha

Yes thats correct. My application is isn't really a game its more of a video player.

Now i can perform zoom by changing the Z which again zooms at the center.

The idea behind pan/tilt was to perform zoom on any offset position away from the center hence I'm trying to perform pan/tilt.

Could i still achieve zoom on a position that is offset from the center ? Probably should have explained a bit more clearly.

@Nanoha

Yes thats correct. My application is isn't really a game its more of a video player.

Now i can perform zoom by changing the Z which again zooms at the center.

The idea behind pan/tilt was to perform zoom on any offset position away from the center hence I'm trying to perform pan/tilt.

Could i still achieve zoom on a position that is offset from the center ? Probably should have explained a bit more clearly.

By tilt I was under the impression you meant changing the pitch, I guess that is not the case. You certainly can zoom on a position that is not the centre. There's a variety of ways to do it which depends how you are setting up the projection matrix. I think the simplest way to do it would be by setting up your projection using left/right, top/bottom and far/near values as described here: https://en.wikipedia.org/wiki/Orthographic_projection I would think that DirectX has a function that will do that (you are probably already doing it). Your zoom is effectively the distance between the left and right values (and top/bottom of course but they are related by aspect ratio so it will all work out). If for example your screen is 800*600 the centre being 400,300 then the left value would be 0 and the right would be 800 (800/2 - 800/2, 800/2 + 800/2). The width is 800 which means a zoom of 100%, if you change the width to only 400 then the 'zoom' would be 200% (and left would be 200, right 600 800/2 - 400/2, 800/2 + 400/2).

For zooming on a particular location you just need to add on the offset, if you want to zoom in on the area 100 pixels to the right of the centre then just add on 100 to both left and right values. The same principle applies for vertical. I think a formula that should work would be:

left = width/2 - width/(2*zoom) + (horzPosition - width/2);

right = width/2 + width(2*zoom) + (horzPosition - width/2)

Where zoom would be 1 (100%), 2 (200%) etc. Width is whatever width values you decide to use (pixels for example) and same for horzPosition, that would be in the same units, that's the location you want to zoom on.

You'd need to do the same for top/bottom and once you have those values you just create the orthogonal projection matrix using them.

Rearranged my formula a bit:

left = -width/(2*zoom) + horzPosition

right = width/(2*zoom) + horzPoition

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

@Nanoha

For zooming on a particular location you just need to add on the offset, if you want to zoom in on the area 100 pixels to the right of the centre then just add on 100 to both left and right values. The same principle applies for vertical. I think a formula that should work would be:

left = width/2 - width/(2*zoom) + (horzPosition - width/2);

right = width/2 + width(2*zoom) + (horzPosition - width/2)

Where zoom would be 1 (100%), 2 (200%) etc. Width is whatever width values you decide to use (pixels for example) and same for horzPosition, that would be in the same units, that's the location you want to zoom on.

You'd need to do the same for top/bottom and once you have those values you just create the orthogonal projection matrix using them.

Rearranged my formula a bit:

left = -width/(2*zoom) + horzPosition

right = width/(2*zoom) + horzPoition

i would use your solution but the problem is my texture co-ordinates are based on screen dimension and as a result of which i initialize my projection matrix as


 m_projectionMatrix = Matrix.OrthoOffCenterLH(0, (float)m_displaySize.Width, (float)m_displaySize.Height, 0, 0f, 100.0f);

hence my question here is: If i was to say create my projection matrix based on left, right, top and bottom positions, then any position of my vertices outside my projection matrix dimension would not be rendered. Am i understanding this correctly ?

@xycsosycx

For panning, you just move the cameras position left/right/up/down/etc. This will give you a more intuitive way of panning since it's really just moving the camera around the scene.

The same holds true for tilt, if you rotate the camera, the view matrix rotation will be the inverse of that, and will rotate things into view space. You can use Matrix.RotationZ to create a matrix that just rotates around the Z axis, so it will still look towards your scene (the Z axis doesn't change), but the up/left axis rotate around. This gives you a simpler 2D rotation which will tilt your scene.

To sum up, move/rotate your camera around your scene, then create a final world space matrix from the camera translation/rotation, then invert that to get the view matrix.

With the above explanation, if i understand correctly then i would need to update my view matrix constantly.

Also i wont be able to perform zoom if my Z axis doesn't change (or have it understood it incorrectly) as i'm trying to achieve zoom on a particular point within the texture and yet displaying the texture within my entire camera display area.

@Nanoha

For zooming on a particular location you just need to add on the offset, if you want to zoom in on the area 100 pixels to the right of the centre then just add on 100 to both left and right values. The same principle applies for vertical. I think a formula that should work would be:

left = width/2 - width/(2*zoom) + (horzPosition - width/2);
right = width/2 + width(2*zoom) + (horzPosition - width/2)

Where zoom would be 1 (100%), 2 (200%) etc. Width is whatever width values you decide to use (pixels for example) and same for horzPosition, that would be in the same units, that's the location you want to zoom on.

You'd need to do the same for top/bottom and once you have those values you just create the orthogonal projection matrix using them.

Rearranged my formula a bit:
left = -width/(2*zoom) + horzPosition
right = width/(2*zoom) + horzPoition



i would use your solution but the problem is my texture co-ordinates are based on screen dimension and as a result of which i initialize my projection matrix as

 m_projectionMatrix = Matrix.OrthoOffCenterLH(0, (float)m_displaySize.Width, (float)m_displaySize.Height, 0, 0f, 100.0f);
hence my question here is: If i was to say create my projection matrix based on left, right, top and bottom positions, then any position of my vertices outside my projection matrix dimension would not be rendered. Am i understanding this correctly ?


I can't say you would simply be able to plug it right in but it should work just fine. Just because your vertices are outside of the projection doesn't mean the primitives they define are. I don't know enough about your specific situation but it should work without issue. The function you are using to create the matrix is also the one you need to use left/right etc too.

This is slightly guess work but it should give you some idea:


// going to zoom in 200% on 3/4 the way across the screen and half way down
float zoom = 2; // 200%
float xPos = 0.75*m_displaySize.Width; // where we are centred
float yPos = 0.5*m_displaySize.Height; // where we are centred
float left = -m_displaySize.Width/(2*zoom) + xPos;
float right = m_displaySize.Width/(2*zoom) + xPos;
float top = -m_displaySize.Height/(2*zoom) + yPos;
float bottom = m_displaySize.Height/(2*zoom) + yPos;
m_projectionMatrix = Matrix.OrthoOffCenterLH(left, right, bottom, top, 0f, 100.0f);

As long as the original quad that you are drawing (I assume you are drawing a textured quad) shows the entire texture and the vertices are defined as going 0 to width, 0 to height then that 'should' work. The vertices you define won't be in the clip volume but the primitives they define are still there and won't be culled.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Thanks for the explanation with some code.

I was having trouble earlier in understanding with the primitives be affected which aren't but rather the texture's UV co-ordinates.

As long as the original quad that you are drawing (I assume you are drawing a textured quad) shows the entire texture and the vertices are defined as going 0 to width, 0 to height then that 'should' work. The vertices you define won't be in the clip volume but the primitives they define are still there and won't be culled.

the above explains it a bit more clearly.

Thanks.

@Nanoha

Your solution work pretty well and as expected in my problem.

However my question is:
From what I have read from different resources that I shouldn't be really changing the projection matrix ? If this case is true then does updating/changing constantly be true and efficient in my situation ?

This topic is closed to new replies.

Advertisement