Hello everybody. I have a rather complex scene I want to cull via the frustum. However, for some strange reason my implementation is not working (nothing is drawn). I have looked at *many* of other people implementations, and it seems as if they are identical to mine.
Here are my various data structures:
struct Plane
{
f32 a, b, c, d;
};
struct Matrix4x4
{
f32 m[16];
};
struct vector3df
{
f32 x, y, z;
};
Here are various mathematical functions:
FASTCALL struct Matrix4x4 multiplyMatrix4x4(struct Matrix4x4 a, struct Matrix4x4 b)
{
struct Matrix4x4 c;
c.m[0] = a.m[0] * b.m[0] + a.m[1] * b.m[4] + a.m[2] * b.m[8] + a.m[3] * b.m[12];
c.m[1] = a.m[0] * b.m[1] + a.m[1] * b.m[5] + a.m[2] * b.m[9] + a.m[3] * b.m[13];
c.m[2] = a.m[0] * b.m[2] + a.m[1] * b.m[6] + a.m[2] * b.m[10] + a.m[3] * b.m[14];
c.m[3] = a.m[0] * b.m[3] + a.m[1] * b.m[7] + a.m[2] * b.m[11] + a.m[3] * b.m[15];
c.m[4] = a.m[4] * b.m[0] + a.m[5] * b.m[4] + a.m[6] * b.m[8] + a.m[7] * b.m[12];
c.m[5] = a.m[4] * b.m[1] + a.m[5] * b.m[5] + a.m[6] * b.m[9] + a.m[7] * b.m[13];
c.m[6] = a.m[4] * b.m[2] + a.m[5] * b.m[6] + a.m[6] * b.m[10] + a.m[7] * b.m[14];
c.m[7] = a.m[4] * b.m[3] + a.m[5] * b.m[7] + a.m[6] * b.m[11] + a.m[7] * b.m[15];
c.m[8] = a.m[8] * b.m[0] + a.m[9] * b.m[4] + a.m[10] * b.m[8] + a.m[11] * b.m[12];
c.m[9] = a.m[8] * b.m[1] + a.m[9] * b.m[5] + a.m[10] * b.m[9] + a.m[11] * b.m[13];
c.m[10] = a.m[8] * b.m[2] + a.m[9] * b.m[6] + a.m[10] * b.m[10] + a.m[11] * b.m[14];
c.m[11] = a.m[8] * b.m[3] + a.m[9] * b.m[7] + a.m[10] * b.m[11] + a.m[11] * b.m[15];
c.m[12] = a.m[12] * b.m[0] + a.m[13] * b.m[4] + a.m[14] * b.m[8] + a.m[15] * b.m[12];
c.m[13] = a.m[12] * b.m[1] + a.m[13] * b.m[5] + a.m[14] * b.m[9] + a.m[15] * b.m[13];
c.m[14] = a.m[12] * b.m[2] + a.m[13] * b.m[6] + a.m[14] * b.m[10] + a.m[15] * b.m[14];
c.m[15] = a.m[12] * b.m[3] + a.m[13] * b.m[7] + a.m[14] * b.m[11] + a.m[15] * b.m[15];
return c;
}
FASTCALL void normalizePlane(struct Plane * plane)
{
f32 mag = sqrtf(plane->a * plane->a + plane->b * plane->b + plane->c * plane->c);
if(mag)
{
plane->a /= mag;
plane->b /= mag;
plane->c /= mag;
plane->d /= mag;
}
}
Here is the global frustum planes declaration:
struct Plane frustumPlane[6];
Here is the frustum extraction function:
FASTCALL void updateFrustum()
{
struct Matrix4x4 proj, modl, clip;
struct Plane * p;
glPushMatrix();
glLoadIdentity();
glGetFloatv(GL_PROJECTION_MATRIX, &proj.m[0]);
glGetFloatv(GL_MODELVIEW_MATRIX, &modl.m[0]);
glPopMatrix();
clip = multiplyMatrix4x4(proj, modl);
printf("{%f, %f, %f, %f\n %f, %f, %f, %f\n %f, %f, %f, %f\n %f, %f, %f, %f}\n\n",
clip.m[0], clip.m[1], clip.m[2], clip.m[3],
clip.m[4], clip.m[5], clip.m[6], clip.m[7],
clip.m[8], clip.m[9], clip.m[10], clip.m[11],
clip.m[12], clip.m[13], clip.m[14], clip.m[15]);
p = &frustumPlane;
p->a = clip.m[3] - clip.m[0];
p->b = clip.m[7] - clip.m[4];
p->c = clip.m[11] - clip.m[8];
p->d = clip.m[15] - clip.m[12];
p = &frustumPlane;
p->a = clip.m[3] + clip.m[0];
p->b = clip.m[7] + clip.m[4];
p->c = clip.m[11] + clip.m[8];
p->d = clip.m[15] + clip.m[12];
p = &frustumPlane[BOTTOM];
p->a = clip.m[3] + clip.m[1];
p->b = clip.m[7] + clip.m[5];
p->c = clip.m[11] + clip.m[9];
p->d = clip.m[15] + clip.m[13];
p = &frustumPlane[TOP];
p->a = clip.m[3] - clip.m[1];
p->b = clip.m[7] - clip.m[5];
p->c = clip.m[11] - clip.m[9];
p->d = clip.m[15] - clip.m[13];
p = &frustumPlane[BACK];
p->a = clip.m[3] - clip.m[2];
p->b = clip.m[7] - clip.m[6];
p->c = clip.m[11] - clip.m[10];
p->d = clip.m[15] - clip.m[14];
p = &frustumPlane[FRONT];
p->a = clip.m[3] + clip.m[2];
p->b = clip.m[7] + clip.m[6];
p->c = clip.m[11] + clip.m[10];
p->d = clip.m[15] + clip.m[14];
u8 i;
for (i = 0; i < 6; i++)
normalizePlane(&frustumPlane);
}
Here is the function to test if a vertex is in the frustum:
FASTCALL bool isVector3dfInFrustum(struct vector3df d)
{
if(frustumPlane.a * d.x + frustumPlane.b * d.y + frustumPlane.c * d.z + frustumPlane.d > 0)
return false;
if(frustumPlane.a * d.x + frustumPlane.b * d.y + frustumPlane.c * d.z + frustumPlane.d > 0)
return false;
if(frustumPlane[BACK].a * d.x + frustumPlane[BACK].b * d.y + frustumPlane[BACK].c * d.z + frustumPlane[BACK].d > 0)
return false;
if(frustumPlane[FRONT].a * d.x + frustumPlane[FRONT].b * d.y + frustumPlane[FRONT].c * d.z + frustumPlane[FRONT].d > 0)
return false;
if(frustumPlane[TOP].a * d.x + frustumPlane[TOP].b * d.y + frustumPlane[TOP].c * d.z + frustumPlane[TOP].d > 0)
return false;
if(frustumPlane[BOTTOM].a * d.x + frustumPlane[BOTTOM].b * d.y + frustumPlane[BOTTOM].c * d.z + frustumPlane[BOTTOM].d > 0)
return false;
return true;
}
And a simple test case scenario:
glBegin(GL_POINTS);
glPointSize(5.0f);
s32 x, y, z;
u32 count = 0;
for(x = -100; x < 100; x++)
for(y = -100; y < 100; y++)
for(z = -100; z < 100; z++)
if(isVector3dfInFrustum(makeVector3df(x, y, z)))
{
glVertex3i(x, y, z);
count++;
}
glEnd();
printf("%lu\n", count);
This test case scenario renders 0 of the points, regardless of the camera orientation. Any ideas on what I might be doing wrong?
[Edited by - n0obAtroN on June 10, 2009 2:39:47 AM]