Hello,
I've been working on some culling-techniques for a project. We've built our own engine so pretty much everything is built from scratch. I've set up a frustum with the following code, assuming that the FOV is 90 degrees.
float angle = CU::ToRadians(45.f);
Plane<float> nearPlane(Vector3<float>(0, 0, aNear), Vector3<float>(0, 0, -1));
Plane<float> farPlane(Vector3<float>(0, 0, aFar), Vector3<float>(0, 0, 1));
Plane<float> right(Vector3<float>(0, 0, 0), Vector3<float>(angle, 0, -angle));
Plane<float> left(Vector3<float>(0, 0, 0), Vector3<float>(-angle, 0, -angle));
Plane<float> up(Vector3<float>(0, 0, 0), Vector3<float>(0, angle, -angle));
Plane<float> down(Vector3<float>(0, 0, 0), Vector3<float>(0, -angle, -angle));
myVolume.AddPlane(nearPlane);
myVolume.AddPlane(farPlane);
myVolume.AddPlane(right);
myVolume.AddPlane(left);
myVolume.AddPlane(up);
myVolume.AddPlane(down);
When checking the intersections I am using a BoundingSphere of my models, which is calculated by taking the average position of all vertices and then choosing the furthest distance to a vertex for radius. The actual intersection test looks like this, where the "myFrustum90" is the actual frustum described above.
The orientationInverse is actually the viewMatrix-inverse in this case.
bool CFrustum::Intersects(const SFrustumCollider& aCollider)
{
CU::Vector4<float> position = CU::Vector4<float>(aCollider.myCenter.x, aCollider.myCenter.y, aCollider.myCenter.z, 1.f) * myOrientationInverse;
return myFrustum90.Inside({ position.x, position.y, position.z }, aCollider.myRadius);
}
The Inside() function looks like this.
template <typename T>
bool PlaneVolume<T>::Inside(Vector3<T> aPosition, T aRadius) const
{
for (unsigned short i = 0; i < myPlaneList.size(); ++i)
{
if (myPlaneList[i].ClassifySpherePlane(aPosition, aRadius) > 0)
{
return false;
}
}
return true;
}
And this is the ClassifySpherePlane() function. (The plane is defined as a Vector4 called myABCD, where ABC is the normal)
template <typename T>
inline int Plane<T>::ClassifySpherePlane(Vector3<T> aSpherePosition, float aSphereRadius) const
{
float distance = (aSpherePosition.Dot(myNormal)) - myABCD.w;
// completely on the front side
if (distance >= aSphereRadius)
{
return 1;
}
// completely on the backside (aka "inside")
if (distance <= -aSphereRadius)
{
return -1;
}
//sphere intersects the plane
return 0;
}
Please bare in mind that this code is not optimized nor well-written by any means. I am just looking to get it working.
The result of this culling is that the models seem to be culled a bit "too early", so that the culling is visible and the models pops away.
How do I get the culling to work properly?
I have tried different techniques but haven't gotten any of them to work.
If you need more code or explanations feel free to ask for it.
Thanks.
↧