Plane & View Frustum Classification

Started by
5 comments, last by cpcollis 19 years, 8 months ago
Can someone explain how to classify a viewing frustum with respect to a plane in DirectX. I can classify a vector with respect to a plane easily enough, but I don't know how to handle the odd shape of the frustum i.e. I have a camera with a Far/Near Clipping plane, an Up vector, a Target vector, a Position vector and a field of view and I have a plane. I want to know if the frustum is infront, behind or spanning the plane. I can't seem to find anything on how this is acheived. Thank you, Chris
Advertisement
Keep in mind that the view frustum is really just a representation (in world space) of what ends up being contained in screen space after all transforms have been performed.

With that said, consider why the frustum is shaped the way that it is. The near plane and the far plane are the same shape (rectangles proportional to the screen dimensions), but the far plane is much larger. But after a scene is tranformed and put into screen space, the near and far plane end up as the same size. This is due to the perspective transform, which essentially applies an aspect ratio for your scene.

So, what does this have to do with your question you ask? You need to use your perspective matrix along with your view matrix to determine the world space shape of the frustum. Google for "Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix" written by Gil Gribb and Klaus Hartmann. Its a quick and straight forward method to get a description of the six planes of the view frustum.

Once you have the frustum representation (essentially just six planes), you can simply perform plane to plane tests to determine frustum position relative to a plane or vice versa.

If you still have trouble understanding or have more questions, post again. I had trouble getting it at first, but once you "see" it, it makes a lot of sense.

Hope this helps,

Jason Z
Excellent Jason! I did what you said, found the article thanks, it was just what I needed! Anyway, I put bounding boxes through my tree and I generate the frustum planes every frame. It sort of works, if I am looking straight at an object it thinks it is within the planes, but if I move the camera slightly the the top, side etc the object is classified as outside the frustum. I've checked stuff over but I can't seem to figure out where I'm going wrong. You had anything like this ?

Thanks,

Chris
ugh, i've been bashing at this for hours now with only half luck. I'm going to post what I've done and can you try and tell me where I'm going wrong.

Ok here goes, for my plane extraction I'm doing the following:

Matrix PV = m_ViewMatrix * m_ProjectionMatrix;// Left Planem_LeftPlane.A = PV.M14 + PV.M11;m_LeftPlane.B = PV.M24 + PV.M21;m_LeftPlane.C = PV.M34 + PV.M31;m_LeftPlane.D = PV.M44 + PV.M41;// Right Planem_RightPlane.A = PV.M14 - PV.M11;m_RightPlane.B = PV.M24 - PV.M21;m_RightPlane.C = PV.M34 - PV.M31;m_RightPlane.D = PV.M44 - PV.M41;// Bottom Planem_BottomPlane.A = PV.M14 + PV.M12;m_BottomPlane.B = PV.M24 + PV.M22;m_BottomPlane.C = PV.M34 + PV.M32;m_BottomPlane.D = PV.M44 + PV.M42;// Top Planem_TopPlane.A = PV.M14 - PV.M12;m_TopPlane.B = PV.M24 - PV.M22;m_TopPlane.C = PV.M34 - PV.M32;m_TopPlane.D = PV.M44 - PV.M42;// Near Planem_NearPlane.A = PV.M13;m_NearPlane.B = PV.M23;m_NearPlane.C = PV.M33;m_NearPlane.D = PV.M43;// Far Planem_FarPlane.A = PV.M14 - PV.M13;m_FarPlane.B = PV.M24 - PV.M23;m_FarPlane.C = PV.M34 - PV.M33;m_FarPlane.D = PV.M44 - PV.M43;


just like the article explained that you directed me to.

I have created bounding boxes around my nodes in my BSP tree, I've been testing with a simple cube which is contained in its own node, so no split polygons and I manually checked the generate bounding box, it matches the size of the cube it encompasses, so no problems there.

When I come to test the box against the frustums i do the following:

public bool CheckBox(BoundingBox box){	// Check the 8 corners of the box, if any point is within the frustum	// we will have to return true.	for (int i = 0; i < 8; i++)	{		if (CheckPoint(box.Corners))			return true;	}	// No points were inside the frustum	return false;}public bool CheckPoint(Vector3 point){	if (SpacePartition.ClassifyPoint(m_LeftPlane, point, m_PlaneThickness) == Side.Behind)		return false;		if (SpacePartition.ClassifyPoint(m_RightPlane, point, m_PlaneThickness) == Side.Behind)		return false;		if (SpacePartition.ClassifyPoint(m_TopPlane, point, m_PlaneThickness) == Side.Behind)		return false;	if (SpacePartition.ClassifyPoint(m_BottomPlane, point, m_PlaneThickness) == Side.Behind)		return false;	if (SpacePartition.ClassifyPoint(m_NearPlane, point, m_PlaneThickness) == Side.Behind)		return false;	if (SpacePartition.ClassifyPoint(m_FarPlane, point, m_PlaneThickness) == Side.Behind)		return false;	return true;}


SpacePartition.ClassifyPoint just does the standard Ax + By +Cz + D = 0 test and returns which side the point is in. Based on the return value of CheckBox i decide whether to draw the cube or not.

Currently I get strange effects, like the cube will be visble and then I move slightly left and it vanishes. It almost seems like one of my planes is through the center of the screen :/ But I've checked the plane extractions over and over, they seem ok.

Please help if you can I'm totally at an ends. If there is ANY other info u need to understand my problem pls say.

Thank you very much for your help,

Chris
Your code for calculating the view frustum and then checking a bounding box looks correct. This would mean your bounding box information must be incorrect. The problem you are describing sounds similiar to what would happen if your 'y' values for the bounding box corners were set incorrectly. Are you insuring that your values for the bounding box are set correctly? IE- you need to traverse through every vertex inside a bounding box and determine the highest and lowest points - you can't just set the y value of the top right point to be the y value of the top right vertex for example. This is also assuming your bounding boxes are axis aligned.
I'm pretty sure my bounding boxes are correct. Heres the code to create them:

private BoundingBox BuildBoundingBox(PolygonNode node){	BoundingBox box = new BoundingBox(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue, float.MaxValue, float.MinValue);	BoundingBox behind = new BoundingBox(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue, float.MaxValue, float.MinValue);	BoundingBox infront = new BoundingBox(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue, float.MaxValue, float.MinValue);	// Get our childs to generate their boxes	if (node.Behind	!= null)		behind = BuildBoundingBox(node.Behind);	if (node.Infront != null)		infront = BuildBoundingBox(node.Infront);	// Choose the largest properties from each of our bounding boxes	box.Left = (behind.Left < infront.Left) ? behind.Left : infront.Left;	box.Right = (behind.Right > infront.Right) ? behind.Right : infront.Right;	box.Bottom = (behind.Bottom < infront.Bottom) ? behind.Bottom : infront.Bottom;		box.Top = (behind.Top > infront.Top) ? behind.Top : infront.Top;	box.Front = (behind.Front < infront.Front) ? behind.Front : infront.Front;	box.Back = (behind.Back > infront.Back) ? behind.Back : infront.Back;	// If we have no data, just return the box	if (node.Polygons == null)		return box;	for (int i = 0; i < node.Polygons.Length; i++)	{		for (int j = 0; j < node.Polygons.Points.Count; j++)		{			Vector3 vertex = ((VertexPNT) m_Verticies[node.Polygons.Points[j]]).Position;			// Left			if (vertex.X < box.Left)				box.Left = vertex.X;			// Right			if (vertex.X > box.Right)				box.Right = vertex.X;			// Bottom			if (vertex.Y < box.Bottom)				box.Bottom = vertex.Y;			// Top			if (vertex.Y > box.Top)				box.Top = vertex.Y;			// Front			if (vertex.Z < box.Front)				box.Front = vertex.Z;						// Back			if (vertex.Z > box.Back)				box.Back = vertex.Z;		}	}	// Store the bounding box for this node and generate the corners	box.Generate();	node.Bounds = box;	return box;}


I've checked it over, maybe something I can't see... The box.Generate() creates a set of verticies for the corners of the box:

public void Generate(){	if (m_Corners == null)		m_Corners = new Vector3[8];	m_Corners[0] = new Vector3(Left, Top, Front);		// Front, Top, Left	m_Corners[1] = new Vector3(Left, Bottom, Front);	// Front, Bottom, Left	m_Corners[2] = new Vector3(Right, Bottom, Front);	// Front, Bottom, Right	m_Corners[3] = new Vector3(Right, Top, Front);		// Front, Top, Right	m_Corners[4] = new Vector3(Left, Top, Back);		// Back, Top, Left	m_Corners[5] = new Vector3(Left, Bottom, Back);		// Back, Bottom, Left	m_Corners[6] = new Vector3(Right, Bottom, Back);	// Back, Bottom, Right	m_Corners[7] = new Vector3(Right, Top, Back);		// Back, Top, Right}


Hmmm.... still pulling hair out here, I know its something simple but I just can't find it :/

Thanks for your reply

Chris
Ok, it seems to work! I have NO idea what I did, but It works as expected now, very strange. Thanks for all you help everyone.

Chris

This topic is closed to new replies.

Advertisement