Frustum Culling Frustration

Started by
6 comments, last by Deftoned 16 years ago
Hey guys, I have spent the last (long time), trying to debug this code, and i finally had to swallow my pride and ask for help =\. The problem is that it my frustum culling sort of work...but i am getting some wacky results, it almost looks like my frustum isn't moving with me...or something if that effect. I have got the non-identity model view matrix, extracted the planes and check my spheres against them, and it works, but not how i want it to, the further i get away from the starting point the worse it looks... ummm yeah, got some code, if anyone could help that would be great. *Note i have to use C in this project*

quatBuildCamera();

MultSingleMatrix44f(nimvMatrix);
	
//Extracts Planes and Normalizes them
ExtractPlanes(plane, nimvMatrix);


float *MultSingleMatrix44f(float *nimvMatrix)
{
	float pMatrix[16];
	float mvMatrix[16];
	//Model View Matrix * Projection Matris = Non-Identity Model View Matrix
	glGetFloatv(GL_MODELVIEW_MATRIX, mvMatrix);
	glGetFloatv(GL_PROJECTION_MATRIX, pMatrix);

	//Column 1
	nimvMatrix[0] = ((mvMatrix[0] * pMatrix[0]) + (mvMatrix[1] * pMatrix[4])     + (mvMatrix[2] * pMatrix[8]) + (mvMatrix[3] * pMatrix[12]));
	nimvMatrix[4] = ((mvMatrix[0] * pMatrix[1]) + (mvMatrix[1] * pMatrix[5]) + (mvMatrix[2] * pMatrix[9]) + (mvMatrix[3] * pMatrix[13]));
	nimvMatrix[8] = ((mvMatrix[0] * pMatrix[2]) + (mvMatrix[1] * pMatrix[6]) + (mvMatrix[2] * pMatrix[10]) + (mvMatrix[3] * pMatrix[14]));
	nimvMatrix[12] = ((mvMatrix[0] * pMatrix[3]) + (mvMatrix[1] * pMatrix[7]) + (mvMatrix[2] * pMatrix[11]) + (mvMatrix[3] * pMatrix[15]));

	//Column 2
	nimvMatrix[1] = ((mvMatrix[4] * pMatrix[0]) + (mvMatrix[5] * pMatrix[4]) + (mvMatrix[6] * pMatrix[8]) + (mvMatrix[7] * pMatrix[12]));
	nimvMatrix[5] = ((mvMatrix[4] * pMatrix[1]) + (mvMatrix[5] * pMatrix[5]) + (mvMatrix[6] * pMatrix[9]) + (mvMatrix[7] * pMatrix[13]));
	nimvMatrix[9] = ((mvMatrix[4] * pMatrix[2]) + (mvMatrix[5] * pMatrix[6]) + (mvMatrix[6] * pMatrix[10]) + (mvMatrix[7] * pMatrix[14]));
	nimvMatrix[13] = ((mvMatrix[4] * pMatrix[3]) + (mvMatrix[5] * pMatrix[7]) + (mvMatrix[6] * pMatrix[11]) + (mvMatrix[7] * pMatrix[15]));
	
	//Column 3
	nimvMatrix[2] = ((mvMatrix[8] * pMatrix[0]) + (mvMatrix[9] * pMatrix[4]) + (mvMatrix[10] * pMatrix[8]) + (mvMatrix[11] * pMatrix[12]));
	nimvMatrix[6] = ((mvMatrix[8] * pMatrix[1]) + (mvMatrix[9] * pMatrix[5]) + (mvMatrix[10] * pMatrix[9]) + (mvMatrix[11] * pMatrix[13]));
	nimvMatrix[10] = ((mvMatrix[8] * pMatrix[2]) + (mvMatrix[9] * pMatrix[6]) + (mvMatrix[10] * pMatrix[10]) + (mvMatrix[11] * pMatrix[14]));
	nimvMatrix[14] = ((mvMatrix[8] * pMatrix[3]) + (mvMatrix[9] * pMatrix[7]) + (mvMatrix[10] * pMatrix[11]) + (mvMatrix[11] * pMatrix[15]));

	//Column 4
	nimvMatrix[3] = ((mvMatrix[12] * pMatrix[0]) + (mvMatrix[13] * pMatrix[4]) + (mvMatrix[14] * pMatrix[8]) + (mvMatrix[15] * pMatrix[12]));
	nimvMatrix[7] = ((mvMatrix[12] * pMatrix[1]) + (mvMatrix[13] * pMatrix[5]) + (mvMatrix[14] * pMatrix[9]) + (mvMatrix[15] * pMatrix[13]));
	nimvMatrix[11] = ((mvMatrix[12] * pMatrix[2]) + (mvMatrix[13] * pMatrix[6]) + (mvMatrix[14] * pMatrix[10]) + (mvMatrix[15] * pMatrix[14]));
	nimvMatrix[15] = ((mvMatrix[12] * pMatrix[3]) + (mvMatrix[13] * pMatrix[7]) + (mvMatrix[14] * pMatrix[11]) + (mvMatrix[15] * pMatrix[15]));

	return (nimvMatrix);
}


Plane *ExtractPlanes(Plane *plane, SingleMatrix44f nimvMatrix)
{
	//Left Plane
	plane[0].a = nimvMatrix[3] + nimvMatrix[1];
	plane[0].b = nimvMatrix[7] + nimvMatrix[4];
	plane[0].c = nimvMatrix[11] + nimvMatrix[8];
	plane[0].d = nimvMatrix[15] + nimvMatrix[12];

	//Right Plane
	plane[1].a = nimvMatrix[3] - nimvMatrix[0];
	plane[1].b = nimvMatrix[7] - nimvMatrix[4];
	plane[1].c = nimvMatrix[11] - nimvMatrix[8];
	plane[1].d = nimvMatrix[15] - nimvMatrix[12];

	//Top Plane
	plane[2].a = nimvMatrix[3] - nimvMatrix[1];
	plane[2].b = nimvMatrix[7] - nimvMatrix[5];
	plane[2].c = nimvMatrix[11] - nimvMatrix[9];
	plane[2].d = nimvMatrix[15] - nimvMatrix[13];

	//Bottom Plane
	plane[3].a = nimvMatrix[3] + nimvMatrix[1];
	plane[3].b = nimvMatrix[7] + nimvMatrix[5];
	plane[3].c = nimvMatrix[11] + nimvMatrix[9];
	plane[3].d = nimvMatrix[15] + nimvMatrix[13];

	//Near Plane
	plane[4].a = nimvMatrix[3] + nimvMatrix[2];
	plane[4].b = nimvMatrix[7] + nimvMatrix[6];
	plane[4].c = nimvMatrix[11] + nimvMatrix[10];
	plane[4].d = nimvMatrix[15] + nimvMatrix[14];

	//Far Plane
	plane[5].a = nimvMatrix[3] - nimvMatrix[2];
	plane[5].b = nimvMatrix[7] - nimvMatrix[6];
	plane[5].c = nimvMatrix[11] - nimvMatrix[10];
	plane[5].d = nimvMatrix[15] - nimvMatrix[14];

	//Normalizing Planes
	plane[0] = NormalizePlane(plane[0]);
	plane[1] = NormalizePlane(plane[1]);
	plane[2] = NormalizePlane(plane[2]);
	plane[3] = NormalizePlane(plane[3]);
	plane[4] = NormalizePlane(plane[4]);
	plane[5] = NormalizePlane(plane[5]);


	return plane;
}



Plane NormalizePlane(Plane plane)
{
	float pointMag;

	pointMag = sqrt((plane.a * plane.a) + (plane.b * plane.b) + (plane.c * plane.c) + plane.d);

	plane.a /= pointMag;
	plane.b /= pointMag;
	plane.c /= pointMag;
	plane.d /= pointMag;

	return plane;
}


int SphereInFrustum(BaseObject *model, Plane *plane)
{
	int planeCount;
	float dist;
	int inFrust = 0;

	for( planeCount = 0; planeCount < 6; planeCount++ )
	{
		dist = ((plane[planeCount].a * model->m_position[0]) + 
				(plane[planeCount].b * model->m_position[1]) + 
				(plane[planeCount].c * model->m_position[2]) +
				plane[planeCount].d);
		
		if(dist >= (model->m_model->bounding_radius))
		{
			inFrust = 1;
			//planeCount =6;
		}
	}
	
	return inFrust;
}

thanks for any help.
Advertisement
I am using this code (however, I am not sure whether it has been tested yet so be careful):

EPHClassification U3D_STD_CALL CPHViewFrustum::ClassifySphere(	const CPHBoundingSphere* p_piSphere) const	{	EPHClassification eResult = EPHClassification_Inside;	for (register uIntT i = 0; i < 6; i++)		{ 		const Maths::CPlane3* pcPlane = &this->m_apPlanes;		// check center point of the plane		const CVector3& vN = p_piSphere->m_vCenter;		const sFloat32 fTemp = pcPlane->n.x * 			vN.x plus pcPlane->n.y * vN.y plus pcPlane->n.z * vN.z;		if (fTemp plus p_piSphere->m_fRadius > -pcPlane->d)			return EPHClassification_Outside;		if (fTemp minus p_piSphere->m_fRadius > -pcPlane->d)			eResult = EPHClassification_Intersecting;		}	return eResult;	}


Hope it helps you. I have replaced *the plus sign* with plus, what do I have to do to keep GD.net from removing *the plus sign* characters?

And I'm sorry for you that you must use C ;-)

Best regards,
Porthos
Quote:Original post by Porthos
I have replaced *the plus sign* with plus, what do I have to do to keep GD.net from removing *the plus sign* characters?

It's just a quirk with the preview. They're there in the actual post: +++
</offtopichelp>
I think your SphereInFrustrum is wrong. It seems to be saying 'is the sphere inside ANY of the faces', whereas I would say it should be 'is the sphere inside ALL the faces', i.e. (pseudo)
for(each face){  float dist = (big long calculation I didn't check but which is probably right);  if(dist > radius) return false; // or (-dist) depending on your sign convention}return true;
I didn't make it through everything, but your plane normalize function is off: it should be:

Plane NormalizePlane(Plane plane){	float normalLen;	normalLen = sqrt((plane.a * plane.a) + (plane.b * plane.b) + (plane.c * plane.c));	plane.a /= normalLen;	plane.b /= normalLen;	plane.c /= normalLen;	plane.d /= normalLen;	return plane;}
Well thansk for the help guys, still have the problem that it is culling stuff when it is still in the frustum, i think it must be a problem of me mixing column major and row major stuff, but i don't know
Here's an alternative method for creating the view frustum which you can try.
It works great for me.
while (tired) DrinkCoffee();
ok got it working now guys :)
Thanks for all your help, when the project is ready i will post it up

This topic is closed to new replies.

Advertisement