Frustum culling
Hello,
I have recently implemented terrain rendering using a quad tree and now i am willing to do frustum culling to reduce the polygons number..
I have read the Mark Morley's tutorial about frustum culling. I used his code to extract the viewing frustum and his functions PointInFrustum, SphereInFrustum and CubeInFrustum.
Now my problem is this. Each frame, i extract the frustum and then make a call to my Refine() method which is responsible to build the mesh before drawing it to the screen.
In that method i'm doing a CubeInFrustum test by giving the x,y,z coordinates of the center of the quad node and it's size. If it is not in the frustum i simply disable this node. It "seems" to work and i get a "good" frame rate... but I can see holes, big nodes drawn and all the imperfections... (does that make sense ? :)) making everything to look somewhat "ugly".
Have someone an idea of what is happening ? :/
Here is my Refine() method :
void QuadTreeTerrain::Refine(int x, int z, int width)
{
float distance = 0.0f; // distance from center of node to camera position
float f = 0.0f; // subdivision criterion (f in Röttger's whitepaper)
int newWidth = 0; // edgelength of the "possible" childrens to subdivide
// if we are at the smallest edgelength then stop recursion !
if (width<=2)
{
return;
}
newWidth = width / 2;
int index = x + newWidth + (z+newWidth)*tData.size;
if (!Frustum::CubeInFrustum(frustum,(x+newWidth)*tScale.x,GetHeight(x+newWidth,z+newWidth)*tScale.y,(z+newWidth)*tScale.z,width*tScale.x))
//if (!Frustum::CubeInFrustum(frustum,x*tScale.x,GetHeight(x,z)*tScale.y,z*tScale.z,width*tScale.x))
{
// it is not needed to draw it, we don't see it !
quadTree[index]=0;
return;
}
// Calculate the distance using the L1-Norm
// d = |x2 - x1| + |y2 - y1| + |z2 - z1|
distance = fabs(cameraPos.x-(x*tScale.x)) + fabs(cameraPos.y-(GetHeight(x,z)*tScale.y)) + fabs(cameraPos.z-(z*tScale.z));
// calculate the subdivision criterion f
// f = d / (edgelength * C * MAX(c*d2,1))
f = distance / (width * minResolution * MAX(desiredResolution * errorTree[index],1));
quadTree[index] = 1;
if (f<1.0f)
{
Refine(x,z,newWidth);
Refine(x+newWidth,z,newWidth);
Refine(x,z+newWidth,newWidth);
Refine(x+newWidth,z+newWidth,newWidth);
}
}
Here is my RenderNode() method :
void QuadTreeTerrain::RenderNode(int x, int z, int width)
{
int halfWidth = width/2;
int quarterWidth = width/4;
int index = x + halfWidth + (z + halfWidth)*tData.size;
int nIndex = index - width*tData.size;
int sIndex = index + width*tData.size;
int eIndex = index + width;
int wIndex = index - width;
int mapSize = SQUARE(tData.size);
// checking map limits
if (nIndex >= mapSize || nIndex < 0)
{
nIndex = 0;
}
if (sIndex >= mapSize || sIndex < 0)
{
sIndex = 0;
}
if (eIndex >= mapSize || eIndex < 0)
{
eIndex = 0;
}
if (wIndex >= mapSize || wIndex < 0)
{
wIndex = 0;
}
// get the top left, top right, bottom left and bottom right child index in the quad tree
int tlChild = (index - quarterWidth) - (quarterWidth*tData.size);
int trChild = (index + quarterWidth) - (quarterWidth*tData.size);
int blChild = (index - quarterWidth) + (quarterWidth*tData.size);
int brChild = (index + quarterWidth) + (quarterWidth*tData.size);
// do not render the node if it's disabled !
if (quadTree[index]==0)
{
return;
}
// if any of our chilren are active then recurse and draw them!
// (this simplification disallows partial triangle fans)
else if (quadTree[tlChild]!=0 ||
quadTree[trChild]!=0 ||
quadTree[blChild]!=0 ||
quadTree[brChild]!=0)
{
RenderNode(x,z,halfWidth);
RenderNode(x+halfWidth,z,halfWidth);
RenderNode(x,z+halfWidth,halfWidth);
RenderNode(x+halfWidth,z+halfWidth,halfWidth);
}
// else it's a leaf node and we draw a triangle fan !
else
{
// render a triangle fan and omit vertices if needed
glBegin(GL_TRIANGLE_FAN);
// center vertex
RenderVertex(x+halfWidth,z+halfWidth);
// top left vertex
RenderVertex(x,z);
if (quadTree[wIndex]!=0)
{
RenderVertex(x,z+halfWidth);
}
// bottom left vertex
RenderVertex(x,z+width);
// bottom vertex
if (quadTree[sIndex]!=0)
{
RenderVertex(x+halfWidth,z+width);
}
// bottom right vertex
RenderVertex(x+width,z+width);
// right vertex
if (quadTree[eIndex]!=0)
{
RenderVertex(x+width,z+halfWidth);
}
// top right vertex
RenderVertex(x+width,z);
// top vertex
if (quadTree[nIndex]!=0)
{
RenderVertex(x+halfWidth,z);
}
// top left vertex once again
RenderVertex(x,z);
glEnd();
}
}
Help would be appreciated ;) Thx
Best Regards, RaPhiuS / PaRaSiTe
[ source] CODE_GOES_HERE [ /source]
use that to save the page from becomming massively long. I'm just going to read through what you have put know ;-)
use that to save the page from becomming massively long. I'm just going to read through what you have put know ;-)
____________________________________________________________Programmers Resource Central
Sorry and thank you for the info ;-)
An idea about what is wrong in there :/ :-)
An idea about what is wrong in there :/ :-)
Best Regards, RaPhiuS / PaRaSiTe
Sorry and thank you for the info ;-)
An idea about what is wrong in there :/ :-)
An idea about what is wrong in there :/ :-)
Best Regards, RaPhiuS / PaRaSiTe
you could still edit your post and add the source tags :/
i dont think i could help you then but it would sure help others to help you.
i dont think i could help you then but it would sure help others to help you.
Now get down on your hands and knees and start repeating "Open Source Good, M$ Evil", smacking your head against the pavement after each repetition. Once you have completed your training you may change your first name to GNU/, to show that you are free from the slavery of the closed source world. -Michalson
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement