Jeromer
Jeromer

Reputation: 49

Current frustum culling effects results in flickering objects in openTk

I am having some issues with the way in which I do my frustum culling. The current way does resolve in culling but there is a really odd effect. When I get too close to my main parent object, I am using a scenegraph to render everything, the objects starts flickering really fast. This is gone when I move away. I have tried a lot of things but have no ideas anymore. Do you guys have any thoughts. Any help is greatly appreciated.

I first create a boundingbox consisting of eight points around my models. These are correct as far as i am aware after a lot of testing.

This is my way of calculating the points of the frustum planes. THe camera position is the position in world space and the orientation is the direction it is looking at. Furhtermore the cameraUp and cameraRight are calculated every time the camera is rotated.

    Vector3 pos = Camera.staticPosition;
    Vector3 view = Camera.staticOrientation;
    Vector3 upVector3 = Camera.cameraUp;
    Vector3 rightVector3 = Camera.cameraRight;
    float toRadians = (float)Math.PI / 180.0f;
    float nearDis = .1f;
    float farDistance = 1000f;
    float fov = Game.FOV;
    float aspectRatio = 1.3f;

    //Get with and height of near and far plane
    float tanDiv = 2 * (float) Math.Tan(fov*toRadians / 2);
    float heightNear = tanDiv * nearDis;
    float widthNear = heightNear * aspectRatio;

    float heightFar = tanDiv * farDistance;
    float widthFar = heightFar * aspectRatio;

    // get the centre points of the planes so they can be used to calculate the edge points
    Vector3 centreNear = pos + view * nearDis;
    Vector3 centreFar = pos + view * farDistance;

    // get the halfht values of the width and hegiht to make sure you can get the points
    float hNearHalf = heightNear / 2;
    float wNearHalf = widthNear / 2;
    float hFarHalf = heightFar / 2;
    float wFarHalf = widthFar / 2;

    Vector3 nearTopLeft = centreNear + (upVector3 * hNearHalf) - (rightVector3 * wNearHalf);
    Vector3 nearTopRight = centreNear + (upVector3 * hNearHalf) + (rightVector3 * wNearHalf);
    Vector3 nearBottomLeft = centreNear - (upVector3 * hNearHalf) - (rightVector3 * wNearHalf);
    Vector3 nearBottomRight = centreNear - (upVector3 * hNearHalf) + (rightVector3 * wNearHalf);

    Vector3 farTopLeft = centreFar + (upVector3 * hFarHalf) - (rightVector3 * wFarHalf);
    Vector3 farTopRight = centreFar + (upVector3 * hFarHalf) + (rightVector3 * wFarHalf);
    Vector3 farBotomLeft = centreFar - (upVector3 * hFarHalf) - (rightVector3 * wFarHalf);
    Vector3 farBottomRight = centreFar - (upVector3 * hFarHalf) + (rightVector3 * wFarHalf);

I store my frustum points in an array. First thhe nearplane points, then the farplane, topplane, bottomplane, leftplane and lastly the rightplane. Then i loop through all the six planes and 8 points of the boundinbox if the point is on the right side of the plane increment the value of that key in the dictionary.

    Vector3[] frustumPoints = new Vector3[18]
    {
        nearTopLeft, nearTopRight, nearBottomLeft, farTopLeft, farTopRight, farBotomLeft, nearTopLeft, farTopLeft,
        nearTopRight, nearBottomLeft, farBotomLeft, nearBottomRight, nearTopLeft, nearBottomLeft, farTopLeft,
        nearTopRight, nearBottomRight, farTopRight
    };
    Dictionary<Vector3, int> count = new Dictionary<Vector3, int>(8);
    for (int value = 0; value < 8; value++)
    {
        count.Add(cubePositions[value], 0);
    }

    for (int x = 0; x < 18; x += 3)
    {
        Vector3 normal = NormalPlane(frustumPoints[x], frustumPoints[x + 1], frustumPoints[x + 2]);

        for (int y = 0; y < 8; y++)
        {
            Vector3 pointPlane = frustumPoints[x] - cubePositions[y];
            float dot = Vector3.Dot(pointPlane, normal);


            if (dot <= 0 && x % 6 == 0)
            {
                count[cubePositions[y]]++;
            }
            else if (dot >= 0 && x % 3 == 0)
            {
                count[cubePositions[y]]++;
            }

        }
    }

This is my method to get the normals of the plane

   Vector3 NormalPlane(Vector3 pointOne, Vector3 pointTwo, Vector3 pointThree)
{
    Vector3 normal;
    Vector3 edgeOne = pointTwo - pointOne; // calculate vector from point one to point two
    Vector3 edgeTwo = pointThree - pointOne; // calculate vector from point one to point three

    normal = Vector3.Normalize(Vector3.Cross(edgeOne, edgeTwo)); // calculate the cross product of the two given vectors. Then normalize it so you have normal of plane

    return normal; // return the normal 
}

If for one of these points on the cube the count is six, the points is within all planes and thus the frustum and I draw the object. If none of the points is equal to 6 the objects don't get drawn.

Problem is i have no idea where I am making a mistake so do you guys have any ideas?

Thanks in advance,

Jeromer

Upvotes: 2

Views: 396

Answers (1)

derhass
derhass

Reputation: 45352

If for one of these points on the cube the count is six, the points is within all planes and thus the frustum and I draw the object. If none of the points is equal to 6 the objects don't get drawn.

Your logic here seems to be

  • "if there is no vertex of the cube lying inside the frustum, the cube is not visible."

However. This is just wrong. Even if all 8 vertices of the cube lie outside the frustum, the cube still can intersect the frustum, as demonstrated in this 2D sketch:

                  *----------*
                  |          |
+-----------------+--+       |
 \                | /        |
  \               |/         |
   \              /          |
    \            /|          |
     \          / *----------*
      \        /
       \      /
        +----+

Hence you cull stuff which is potentially visible.

The usual logic for frustum culling is to cull the box only if all of its vertices are rejected by the same plane. (This will result in some odd cases where the box is completely outside and not culled, but these situations are quite unlikely and usually not a big deal to worry about.)

Upvotes: 3

Related Questions