1
\$\begingroup\$

I did Frustum Culling in my engine, but it does not work correctly. All shown in the video:

Video

If the approximation is too close, the model disappears. On the right in the console you can see that one model is rendered less. With what it can be connected?

Frustum creation code:

bool FrustumCulling::update(ID3D11Device* device, const Camera & view, float angle, float ratio, float _near, float rear)
{   
    Vector3 pos = (Vector3)view.getViewPosition();
    Vector3 d = pos - (Vector3)view.getViewDirection();
    d.normalize();
    Vector3 right = (Vector3)view.getViewHeight();
    right = right.cross(d);
    right.normalize();
    Vector3 up = Vector3::cross(d, right);
    // get h and w near and rear planes
    float val = angle * 0.5;
    float tang = (float)tan(val);
    float nh = _near * tang; // near height
    float nw = nh * ratio; // near width
    float rh = rear * tang; // rear height
    float rw = rh * ratio; // near width
    // generate 8 vertex frustum
    Vector3 fc = pos - d * rear;
    Vector3 ftl = fc + up * rh - right * rw; // ftl - Far(rear) Top Left
    Vector3 ftr = fc + up * rh + right * rw; 
    Vector3 fbl = fc - up * rh - right * rw; 
    Vector3 fbr = fc - up * rh + right * rw; 
    Vector3 nc = pos - d * _near;
    Vector3 ntl = nc + up * nh - right * nw; 
    Vector3 ntr = nc + up * nh + right * nw; 
    Vector3 nbl = nc - up * nh - right * nw; 
    Vector3 nbr = nc - up * nh + right * nw; 
    // generate 6 planes frustum
    Plane3 p(ntr, ntl, ftl);
    data.planes[TOP] = PlanesFrustum(p.getPlane());

    p = Plane3(nbl, nbr, fbr);
    data.planes[BOTTOM] = PlanesFrustum(p.getPlane());

    p = Plane3(ntl, nbl, fbl);
    data.planes[LEFT] = PlanesFrustum(p.getPlane());

    p = Plane3(nbr, ntr, fbr);
    data.planes[RIGHT] = PlanesFrustum(p.getPlane());

    p = Plane3(ftr, ftl, fbl);
    data.planes[FARP] = PlanesFrustum(p.getPlane());

    p = Plane3(ntl, ntr, nbr);
    data.planes[NEARP] = PlanesFrustum(p.getPlane());
}

Model verification code (cube bbox) to hit frustum:

bool modelCheckFrustum(Vector3 * v)
{
    for(int k = 0;k<8;k++)
    {
        Vector3 p0 = v[k];
        int isFrustum(0);
        for(int l = 0; l<PLANES_SIZE;l++)
        {
            Vector4 n = planes[l].pl; // 
            float value = shortDistanseFromPointToPlane(n, p0);
            if(value > 0.f) // point in current plane
                ++isFrustum;
        }
        if (isFrustum == PLANES_SIZE)// point in frusrtum
            return true; // model in frustum
    }
    return false; // model not in frustum
}

PLANES_SIZE - count planes, == 6

planes - array planes frustum

planes - Vector4, when x,y,z - a,b,c, and w - d

Method shortDistanseFromPointToPlane:

float shortDistanseFromPointToPlane(Vector4 p, Vector3 p0)
{
    return p.x*p0.x + p.y*p0.y + p.z*p0.z + p.w;
}

Distance to the front and rear planes:

float SCREEN_DEPTH = 1000.f;
float SCREEN_NEAR = 0.01f;

Creating a matrix of perspectives:

matrixProjection = Matrix::CreatePerspectiveFovLHMatrix(GeneralMath::PI / 4, w / (float)h, SCREEN_NEAR, SCREEN_DEPTH); 

w, i - width and height window

How to fix this nasty bug? Thank.

P.S.: I did frustum culing in this lesson.

UPD1:

I created a model frustum, and it shows that not a single BBox vertex got inside the frustum. Now I know the reason, it remains to come up with a solution to this problem :)

Image: enter image description here

\$\endgroup\$
1
\$\begingroup\$

I solved this problem. I added an extra sphere - test. Although the method has errors, but it solves my problem completely. Since this is an editor, it is appropriate here. But there will be a collision in the game, and there will be no such need there. The essence of the method is as follows:

int testBSphereInFrustum(float3 p0, float3 cen) //  p0 - coord BBox model, cen - center BBox model
{
    float radius = length(p0 - cen); // get radiuse sphere around the model
    float sCenterToPlaneNearCenter = length((float3)centerNear - cen); // get length center BBox model and center near plane frustum
    int res = sCenterToPlaneNearCenter <= radius ? 1 : 0;
    return res; // return result
}

I measure the radius of the sphere around the model and the distance from the center of the model to the center near the plane of the frustum. If the radius is less than or equal to - then the test is passed.

\$\endgroup\$
  • \$\begingroup\$ I have a similar problem long times ago. It was because I used corner detection to find whether the object in the frustum or not. So there would be a case that all corners are not in the frustum but object is still in it. \$\endgroup\$ – sirian_ye Jan 18 at 3:45
  • \$\begingroup\$ @sirian_ye Yes, it can be seen on the screenshot :) \$\endgroup\$ – Range Jan 18 at 4:39

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.