Sign in to follow this  
dustinhorne

Convert (Project) ViewFrustrum to 2D

Recommended Posts

Hello everyone. I have an intersting question for you. I'm not a trig / geometry wizard so any math related answers will need to be written for dummies. :) I'm attempting to project my view frustrum onto a 2D plane... more precisely, I have a ground plane... I want to determine the intersection points where the ground plane is visible and convert my view frustrum into a 2D shape on the ground. Let's assume that the player could be looking up and none of the rays from the view frustrum intersect the ground plane. Let's also assume that the player could be looking straight down and all four rays intersect the ground plane.

I have access to the View and Projection matrices and can construct a BoundingFrustrum to get the necessary information (i.e. the Corners) if need be. My target shape will be a 4 sided polygon. I've posted in the AppHub forums and the response was decent but very general. Here are the bits of detail I posted:
[list=1][*]I don't need to draw the polygon, only generate the set of 4 points that make it up.[*]I have an axis aligned plane. Let's just assume it's a plane lying flat on the x and z axis.[*]My view frustrum is a standard perspective camera but could be of a different type. I have access to the View and Projection matrices.[*]My player camera may not be looking straight, it may be looking at an angle either side to side or up and down (free camera).[*]The camera could be looking straight down.[/list]So what I need to do is find the parts of the plane that are visible to the camera and plot points there, also factoring in maximum viewing distance of the camera. The points need to be aligned on the same plane as the ground plane... so if the camera is looking at an upward angle or a downward angle I need to account for that and put the points on the visible parts of the terrain. I also need to be able to determine when none of the plane is visible in the camera.

Background:
There is a reason I'm doing all of this... and I'm going to add the solution to my blog. I'm developing a terrain using a quad tree. It features LOD and View Frustrum Culling. It all works perfectly well and I've been writing a tutorial series on it, however I'm looking to improve performance.

Currently it uses intersection tests between bounding boxes and the view frustrum to determine which geometry to draw. Instead, I'd like to use bounding shapes (a rectangle for each quad and a 4-sided polygon for the view frustrum) and perform a SAT test to determine intersection. I've already developed the code to do the SAT test so that piece isn't necessary. All I need to do is figure out how to get the View Frustrum onto the plane. We'll assume that the plane's Y position is 0 so the view frustrum generated polygon will also have a Y position of 0, but that piece isn't imporant. In fact, all I need to determine are the X and Z positions of the polygon as it's projected onto the ground plane.

How do I go about extracting the 4 corners of the far plane? Just as importantly, how do I extract that info from a View and Projection matrix?

I'm pretty sure my far plane will intersect the ground plane. Just imagine this as an FPS where the player is standing on the terrain and looking out. The view frustrum will pass through the terrain with it's bottom plane and parts of hte left and right planes but the top plane may not pass through the ground (it will if you're looking down at enough of an angle). If the top plane doesn't intersect the ground plane then my far points will be where the far clipping plane intersects the ground plane. I could determine that from my far clipping plane distance but I'd need to know how to get that distance from the projection matrix.

I suppose it would be possible for the camera to be upside down... or sideways... so I guess:

[list=1][*]If none of the rays are intersecting the ground plane, then there's no reason to project the frustrum.[*]If two rays are intersecting, then two of my points would be where they intersect, the other two would be where the ground plane hits the maximum viewing distance and I could determine the spacing of this points based on the distance and FOV (assuming I can extract it from the projection matrix) or just from the width of the far clipping plane (again not sure how to get the info).[*]If exactly 1 or 3 rays are intersecting, i.e. the camera is tilted, I would need to figure out based on the adjacent ray angles where the intersection points would be.[/list] I do need to account for leaning or rotating of the camera but I think once I have the corners this will be a piece of cake. So, that brings me to what should be my final question:

Assume the player is looking down (no leaning). My far clipping plane will be below the terrain. If I know my point of origin and my far clipping plane corners I can determine the direction vector of my 4 rays. My trig is weak so you'll have to bare with me... ok:

Given:
source point - x:0, y:10, z:0
target point - x: 5, y: -50, z: -100

Solve for X and Z where Y = 0

So...basically I know my source and target and can find direction... how do I find a point on the line where y is equal to zero?



Share this post


Link to post
Share on other sites
Just as an update... I did figure out how to find my point based on the known Y using a parametric equation. The rest of my questions are still open:


[code]
public static Vector3 GetDirectionVector(Vector3 point1, Vector3 point2) { return new Vector3(point2.X - point1.X, point2.Y - point1.Y, point2.Z - point1.Z); } public static Vector3 LinePointFromKnownY(Vector3 point1, Vector3 point2, float y) { var direction = GetDirectionVector(point1, point2); //parameteric equation //Point1.Y - (direction.Y * t) = knownY //solve for T //so --> Point1.Y - knownY = direction.Y * t //t = (Point1.Y - knownY) / direction.Y // //unknown X: Point1.X - (direction.X * t) //unknown Z: Point1.Z - (direction.Z * t) var t = (point1.Y - y) / direction.Y; var x = point1.X - (direction.X * t); var z = point1.Z - (direction.Z * t); return new Vector3(x, y, z); }

[/code]

Share this post


Link to post
Share on other sites
[quote name='yckx' timestamp='1317924261' post='4869847']
I'd think you could approach this with [b]D3DXVec3Unproject()[/b]. The Pick or Pick10 samples in the DirectX SDK may help you.
[/quote]

Thanks for the reply. I should have specified I'm using XNA. I may have it figured out but it's going to take some coding before I can test. I'm trying to account for all possible permutations of the camera (less symmetry) in case it's rotated / tilted.

Share this post


Link to post
Share on other sites
Then [url="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.unproject.aspx"]Viewport.Unproject()[/url] is likely what you need. Unproject the corners of the viewport, and then find the intersection of the resulting vectors with the plane.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this