Jump to content
  • Advertisement
Sign in to follow this  

Frustum problems

This topic is 2443 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I made a Frustum class to go with my octree/quadtree view culling.

struct Frustum
D3DXVECTOR3 Normals[6];
float D[0];
Frustum(D3DXMATRIX viewProj)
D3DXVECTOR3 corners[8] =
D3DXVECTOR3(-1, -1, 0), // bottom left front
D3DXVECTOR3( 1, -1, 0), // top left front
D3DXVECTOR3(-1, 1, 0), // bottom right front
D3DXVECTOR3( 1, 1, 0), // top right front
D3DXVECTOR3(-1, -1, 1),
D3DXVECTOR3( 1, -1, 1),
D3DXVECTOR3(-1, 1, 1),
D3DXVECTOR3( 1, 1, 1),
D3DXVECTOR3 worldCorners[8];
// Corners are currently in projection space. To get the corners in world-space, transform by inverse of view proj
D3DXMATRIX inverseViewProj;
float determinant;
D3DXMatrixInverse(&inverseViewProj, &determinant, &viewProj);
// transform the proj space corners into world space
D3DXVec3TransformCoordArray(worldCorners, sizeof(D3DXVECTOR3), corners, sizeof(D3DXVECTOR3), &inverseViewProj, 8);

// get some edges to be used
// edgeA_B is constructed as (corners[A] - corners)
D3DXVECTOR3 edge5_1 = worldCorners[5] - worldCorners[1];
D3DXVECTOR3 edge0_1 = worldCorners[0] - worldCorners[1];
D3DXVECTOR3 edge3_1 = worldCorners[1] - worldCorners[1];
D3DXVECTOR3 edge4_6 = worldCorners[4] - worldCorners[6];
D3DXVECTOR3 edge2_6 = worldCorners[2] - worldCorners[6];
D3DXVECTOR3 edge7_6 = worldCorners[6] - worldCorners[6];

// get the normals to the planes by crossing edges on those planes. all normals point outwards
D3DXVec3Cross(&Normals[FF_Left], &edge0_1, &edge5_1);
D3DXVec3Cross(&Normals[FF_Right], &edge2_6, &edge7_6);
D3DXVec3Cross(&Normals[FF_Top], &edge5_1, &edge3_1);
D3DXVec3Cross(&Normals[FF_Bottom], &edge4_6, &edge2_6);
D3DXVec3Cross(&Normals[FF_Front], &edge3_1, &edge0_1);
D3DXVec3Cross(&Normals[FF_Back], &edge7_6, &edge4_6);

// get the D values. r.n = d
D[FF_Left] = D3DXVec3Dot(&worldCorners[0], &Normals[FF_Left]);
D[FF_Right] = D3DXVec3Dot(&worldCorners[3], &Normals[FF_Right]);
D[FF_Top] = D3DXVec3Dot(&worldCorners[1], &Normals[FF_Top]);
D[FF_Bottom] = D3DXVec3Dot(&worldCorners[2], &Normals[FF_Bottom]);
D[FF_Front] = D3DXVec3Dot(&worldCorners[0], &Normals[FF_Front]);
D[FF_Back] = D3DXVec3Dot(&worldCorners[7], &Normals[FF_Back]);

// normalize all planes so D represents distance to origin
for (int i = 0; i < 6; i++)
float len = D3DXVec3Length(&Normals);
Normals /= len;
D /= len;

The constructor is called in main()

D3DXMATRIX world, view, proj;
<snip initialisation>
Frustum frustum(world * view * proj);

However, when I quit, VC++ 08 express gives me an error
"The stack around the variable 'frustum' was corrupted"
Also, even though this frustum class is not currently in use, it is affecting the drawing of some meshes - probably because of the stack corruption. I have no idea of how to stop this happening, can anyone help me out?

PS. I'm pretty sure my maths is correct, but if not, could you point out where? Thanks a lot

Share this post

Link to post
Share on other sites
OK, by commenting out some of the constructor, eventually I deduced that it was down to accessing and writing to the D array, and then I noticed that it was of size 0. Sorry for sharing my stupidity, this has now been solved. However, I think I should leave this open in case I have more problems - I have never done frustum culling before.

Share this post

Link to post
Share on other sites
You are really making it hard on yourself. Extracting the 6 planes is as simple as this:

// Left clipping plane
m_frustumPlanes[0].m_normal.x = matComb._14 + matComb._11;
m_frustumPlanes[0].m_normal.y = matComb._24 + matComb._21;
m_frustumPlanes[0].m_normal.z = matComb._34 + matComb._31;
m_frustumPlanes[0].m_distance = matComb._44 + matComb._41;

// Right clipping plane
m_frustumPlanes[1].m_normal.x = matComb._14 - matComb._11;
m_frustumPlanes[1].m_normal.y = matComb._24 - matComb._21;
m_frustumPlanes[1].m_normal.z = matComb._34 - matComb._31;
m_frustumPlanes[1].m_distance = matComb._44 - matComb._41;

// Top clipping plane
m_frustumPlanes[2].m_normal.x = matComb._14 - matComb._12;
m_frustumPlanes[2].m_normal.y = matComb._24 - matComb._22;
m_frustumPlanes[2].m_normal.z = matComb._34 - matComb._32;
m_frustumPlanes[2].m_distance = matComb._44 - matComb._42;

// Bottom clipping plane
m_frustumPlanes[3].m_normal.x = matComb._14 + matComb._12;
m_frustumPlanes[3].m_normal.y = matComb._24 + matComb._22;
m_frustumPlanes[3].m_normal.z = matComb._34 + matComb._32;
m_frustumPlanes[3].m_distance = matComb._44 + matComb._42;

// Near clipping plane
m_frustumPlanes[4].m_normal.x = matComb._13;
m_frustumPlanes[4].m_normal.y = matComb._23;
m_frustumPlanes[4].m_normal.z = matComb._33;
m_frustumPlanes[4].m_distance = matComb._43;

// Far clipping plane
m_frustumPlanes[5].m_normal.x = matComb._14 - matComb._13;
m_frustumPlanes[5].m_normal.y = matComb._24 - matComb._23;
m_frustumPlanes[5].m_normal.z = matComb._34 - matComb._33;
m_frustumPlanes[5].m_distance = matComb._44 - matComb._43;

Then normalize the planes.
The site explains the details, but note that the near plane should actually be:

// Near clipping plane
m_frustumPlanes[4].m_normal.x = matComb._14 + matComb._13;
m_frustumPlanes[4].m_normal.y = matComb._24 + matComb._23;
m_frustumPlanes[4].m_normal.z = matComb._34 + matComb._33;
m_frustumPlanes[4].m_distance = matComb._44 + matComb._43;

L. Spiro

Share this post

Link to post
Share on other sites
Thanks, thats a great optimisation, and I did notice the mistake in the near-plane, when it failed to cull some cubes.

Now, for my culling method, what I do for AABBS is for each corner of the AABB I measure the signed distances to each plane using

for each plane
float dist[8]
for each corner(8)
dist = D - dot(planeNorm, cornerPos)
if (all distances < 0)
// reject this aabb node
// test the child nodes if it has any

I know it's working flawlessly, because I made it count the number of aabbs that are calculated as visible, and combined with the drawing of wireframe boxes, it always agrees with what I see when flying around my scene. At the mometn I have a small FPS style map with the quadtree two subdivisions, making for a total of 16 nodes, and when I stand in the corner looking at the centre of the map, it says 14-16 nodes are drawn, but when looking away from the centre of the map, only 1 node is drawn. Just wondered if there was a more efficient way of doing this, if not I can get onto some other stuff, like dynamic meshes in the octree.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!