Viewing Frustrum Clipping [RESOLVED]

Started by
5 comments, last by Jacob Roman 18 years, 7 months ago
After going to countless sites, I still can't get the the maths right for clipping polygons within the viewing frustrum. So I'm gonna make this simple for you guys, in order for me to get the help I am looking for. All I want is a mathematical way to determin if a transformed vertex is within the viewing frustrum. To obtain a transformed vertex all you would have to do is this:

D3DXMatrixIdentity Transformation_Matrix(0)
Temp_Vertex.X = Vertex_List(0).X: Temp_Vertex.Y = Vertex_List(0).Y: Temp_Vertex.Z = Vertex_List(0).Z: Temp_Vertex.W = 1
D3DXMatrixMultiply Transformation_Matrix(0), World_Transformation_Matrix, Camera_Transformation_Matrix
D3DXMatrixMultiplyByVertex Transformation_Vertex(0), Transformation_Matrix(0), Temp_Vertex




Assuming you had this function that you had to manually create:


Public Sub D3DXMatrixMultiplyByVertex(VOut As D3DVECTOR4, Matrix As D3DMATRIX, Vertex As D3DVECTOR4)
    
    VOut.X = (Vertex.X * Matrix.m11) + (Vertex.Y * Matrix.m21) + (Vertex.Z * Matrix.m31) + (Vertex.W * Matrix.m41)
    VOut.Y = (Vertex.X * Matrix.m12) + (Vertex.Y * Matrix.m22) + (Vertex.Z * Matrix.m32) + (Vertex.W * Matrix.m42)
    VOut.Z = (Vertex.X * Matrix.m13) + (Vertex.Y * Matrix.m23) + (Vertex.Z * Matrix.m33) + (Vertex.W * Matrix.m43)
    VOut.W = (Vertex.X * Matrix.m14) + (Vertex.Y * Matrix.m24) + (Vertex.Z * Matrix.m34) + (Vertex.W * Matrix.m44)

End Sub




So what are the correct maths to determine if this vertex is within the viewing frustrum? I know DirectX takes care of it for ya, but I want to add a manual clipper as an experiment. Thanks in advance. [Edited by - Jacob Roman on August 23, 2005 6:48:57 PM]
Advertisement
The 9.0B version of the directx sdk has a clipping sample program that tells if a bounding box is within the view frustum, if this helps. You might have to search the web to find the older version of the sdk, or it could be in the msdn archives. You should be able to tweak it to suit your needs.

Hope this helps,
ProgrammingNerd
Only problem with that sample is that it uses a very slow method of frustum culling. It does something like transforming a box for each object, then checking all eight vertices of the box against the view frustum and determines if it's intersecting an edge, a face, is in, or out, etc. Add to that it's very messily coded and hard to follow.

I use a routine to test if a sphere is outside teh view frustum. It takes the View*Projection matrix, the world X, Y, and Z position of the sphere and the radius of the sphere. It returns a True if the object is outside the frustum and a False if it's inside the frustum (sounds backwards, but there's a reason). The only thing is that it tests only the left, right, top, and bottom for speed.. any objects that would be culled by the near plane are taken care of by left and right, and the far plane isn't tested at all. If you'd like, I could give you the code to test the near and far planes as well.

Here it is translated to VB (to the best of my ability.. I have no idea how most things are defined in VB, and don't know how D3DXMATRIX is laid out especially):

Sub cullSphereToViewFrustum(ByRef MatViewProj as D3DXMATRIX, x As Float, y As Float, z As Float, radius As Float) As Boolean	Dim p As D3DXPLANE	radius=-radius	'left plane	p.a=MatViewProj.m(0,3)+MatViewProj.m(0,0)	p.b=MatViewProj.m(1,3)+MatViewProj.m(1,0)	p.c=MatViewProj.m(2,3)+MatViewProj.m(2,0)	p.d=MatViewProj.m(3,3)+MatViewProj.m(3,0)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=radius		Return True	'right plane	p.a=MatViewProj.m(0,3)-MatViewProj.m(0,0)	p.b=MatViewProj.m(1,3)-MatViewProj.m(1,0)	p.c=MatViewProj.m(2,3)-MatViewProj.m(2,0)	p.d=MatViewProj.m(3,3)-MatViewProj.m(3,0)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=radius		Return True	'top plane	p.a=MatViewProj.m(0,3)-MatViewProj.m(0,1)	p.b=MatViewProj.m(1,3)-MatViewProj.m(1,1)	p.c=MatViewProj.m(2,3)-MatViewProj.m(2,1)	p.d=MatViewProj.m(3,3)-MatViewProj.m(3,1)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=radius		Return True	'bottom plane	p.a=MatViewProj.m(0,3)+MatViewProj.m(0,1)	p.b=MatViewProj.m(1,3)+MatViewProj.m(1,1)	p.c=MatViewProj.m(2,3)+MatViewProj.m(2,1)	p.d=MatViewProj.m(3,3)+MatViewProj.m(3,1)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=radius		Return True	Return FalseEnd Sub


If you just want to test a single vertex, here's the function modified to just test the X, Y, and Z without the radius:

Sub cullSphereToViewFrustum(ByRef MatViewProj as D3DXMATRIX, x As Float, y As Float, z As Float) As Boolean	Dim p As D3DXPLANE	'left plane	p.a=MatViewProj.m(0,3)+MatViewProj.m(0,0)	p.b=MatViewProj.m(1,3)+MatViewProj.m(1,0)	p.c=MatViewProj.m(2,3)+MatViewProj.m(2,0)	p.d=MatViewProj.m(3,3)+MatViewProj.m(3,0)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=0		Return True	'right plane	p.a=MatViewProj.m(0,3)-MatViewProj.m(0,0)	p.b=MatViewProj.m(1,3)-MatViewProj.m(1,0)	p.c=MatViewProj.m(2,3)-MatViewProj.m(2,0)	p.d=MatViewProj.m(3,3)-MatViewProj.m(3,0)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=0		Return True	'top plane	p.a=MatViewProj.m(0,3)-MatViewProj.m(0,1)	p.b=MatViewProj.m(1,3)-MatViewProj.m(1,1)	p.c=MatViewProj.m(2,3)-MatViewProj.m(2,1)	p.d=MatViewProj.m(3,3)-MatViewProj.m(3,1)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=0		Return True	'bottom plane	p.a=MatViewProj.m(0,3)+MatViewProj.m(0,1)	p.b=MatViewProj.m(1,3)+MatViewProj.m(1,1)	p.c=MatViewProj.m(2,3)+MatViewProj.m(2,1)	p.d=MatViewProj.m(3,3)+MatViewProj.m(3,1)	D3DXPlaneNormalize p,p	If ((p.a*x)+(p.b*y)+(p.c*z)+p.d)<=0		Return True	Return FalseEnd Sub


Hope that helps.
_______________________________________________________________________Hoo-rah.
I didn't say that it was a GOOD sample. Just something to point him in the right direction. I have to admit, all of the sample apps are written horribly. Well, maybe the pathetic tutorials are OK. It is a very slow method, althought I was able to optimize it.

Thanks for pointing that out; I wouldn't want to screw him into a slow solution,
ProgrammingNerd
It's alright, didn't mean to steal your thunder :) I just remember looking at that sample and thinking "what prompted them to do this like this?!" It's like they got a bunch of mathematicians together to write the sample instead of people who had had experience writing game engines.
_______________________________________________________________________Hoo-rah.
Yeah the sample code from the SDK was a mess. It was confusing and I still couldn't get it working properly. I'm gonna try the method that Drakex just gave me when I get home from work. If anybody else has any ideas, feel free to tell me.
Drakex, you are the man! It freakin works!!! I wish there was more documentation on implementing it like this. Problem resolved!

This topic is closed to new replies.

Advertisement