簡體   English   中英

邊界球體截錐體剔除問題

[英]Problem with Bounding Sphere Frustum Culling

下面我將發布用於剔除邊界球體的截錐剔除代碼。 我的算法應該相當簡單易懂:更新方法(稱為每幀更新)通過計算平截頭體平面的角以及相應的法線來更新平截頭體的平面。 法線都應該指向平截頭體的中心。

在 inFrustum 方法中,計算到各個平面的有符號距離,我的想法是,如果一個點與左側和右側平面的距離為正,則它必須位於這兩個平面之間。 使用左右、上下和近遠來執行此操作應確定該點是否可見的天氣。 只要我轉動的角度不超過 180°,這樣就可以正常工作,那么位於截錐體中的點就會變得不可見。 cam->up 和 cam->dir 是相機的向上向量和相機的視線向量,near、far 和 fov_degree 是對應的投影變量。 你知道為什么這不能正常工作嗎? 該問題也似乎與凸輪的 position 相對應。

class plane{
private:
    float a, b, c, d;
public:
    void set(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2){
        using namespace glm;
        vec3 v = p1-p0;
        vec3 u = p2-p0;
        vec3 n = normalize(cross(v, u));
        a = n.x;
        b = n.y;
        c = n.z;
        d = dot(-n, p0);
    }
    void set(glm::vec3 p, glm::vec3 n){
        a = n.x;
        b = n.y;
        c = n.z;
        d = p.x*n.x + p.y*n.y + p.z*n.z;
    }
    float distanceTo(glm::vec3 p) const{
        return a*p.x + b*p.y + c*p.z + d;
    }
};
class frustumCulling{
private:
    plane front, back, left, right, top, bottom;
public:
    frustumCulling(Camera& cam){
        update(cam);
    }
    void update(Camera& cam){
        using namespace glm;
        vec3 ndir = normalize(cam->dir);
        vec3 nup = normalize(cam->up);
        vec3 nright = normalize(cross(cam->dir, cam->up));
        //aligned planes
        vec3 onn = cam->pos + ndir*cam->near;
        vec3 onf = cam->pos + ndir*cam->far;
        front.set(onn, ndir);
        back.set(onf, -ndir);
        //far and near dimensions
        vec2 fardim = vec2(0.0f, cam->far*tan(radians(cam->fov_degree/2.0f)));
        fardim.x= fardim.y*cam->aspect_ratio();
        vec2 neardim = vec2(0.0f, cam->near*tan(radians(cam->fov_degree/2.0f)));
        neardim.x = neardim.y*cam->aspect_ratio();
        //view frustum corners //l = left, r = right, u = up, b=bottom, n= near, f = far
        vec3 n_lu = onn + nup*neardim.y*0.5f - nright*neardim.x*0.5f;
        vec3 n_ru = onn + nup*neardim.y*0.5f + nright*neardim.x*0.5f;
        vec3 n_rb = onn - nup*neardim.y*0.5f + nright*neardim.x*0.5f;
        vec3 n_lb = onn - nup*neardim.y*0.5f - nright*neardim.x*0.5f;


        vec3 f_lu = onf + nup*fardim.y*0.5f - nright*fardim.x*0.5f;
        vec3 f_ru = onf + nup*fardim.y*0.5f + nright*fardim.x*0.5f;
        vec3 f_rb = onf - nup*fardim.y*0.5f + nright*fardim.x*0.5f;
        vec3 f_lb = onf - nup*fardim.y*0.5f - nright*fardim.x*0.5f;
        //non aligned planes
        vec3 leftn = normalize(cross(n_lb-n_lu, f_lu-n_lu));
        left.set(n_lu, leftn);

        vec3 rightn = normalize(cross(n_ru-n_rb, f_rb-n_rb));
        right.set(n_ru, rightn);

        vec3 topn = normalize(cross(n_lu - n_ru, f_ru - n_ru));
        top.set(n_ru, topn);

        vec3 botn = normalize(cross(f_rb - n_rb, n_lb - n_rb));
        bottom.set(n_rb, topn);
    }
    bool inFrustum(glm::vec3 p, float radius){
        float dt = top.distanceTo(p);
        float db = bottom.distanceTo(p);
        float dl = left.distanceTo(p);
        float dr = right.distanceTo(p);
        float df = front.distanceTo(p);
        float dn = back.distanceTo(p);
        bool ix, iy, iz;
        ix = (dl > 0 && dr > 0) || glm::abs(dl) <= radius || glm::abs(dr) <= radius;
        iy = (dt > 0 && db > 0) || glm::abs(dt) <= radius || glm::abs(db) <= radius;
        iz = (df > 0 && dn > 0) || glm::abs(df) <= radius || glm::abs(dn) <= radius;

        //just for debugging; should be ix&&iy&&iz
        return ix;
    }
};

我解決了問題是d = px*nx + py*ny + pz*nz; 在集合中,它應該是dot(-n, p)而不是我做了dot(n,p)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM