C++ 边界球体截锥剔除问题

C++ 边界球体截锥剔除问题,c++,opengl,linear-algebra,glm-math,perspectivecamera,C++,Opengl,Linear Algebra,Glm Math,Perspectivecamera,下面我将发布我的截锥剔除代码,用于剔除边界球体。 我的算法应该相当简单且易于理解:更新方法(称为每帧更新)通过计算平截头体平面的角点以及相应的法线来更新平截头体的平面。法线应全部指向平截头体的中心 在INFORSUM方法中,计算到各个平面的有符号距离,我的想法是,如果一个点到左平面和右平面都有正距离,那么它必须位于这两个平面之间。使用左-右、上-下和近-远进行此操作应确定该点是否可见。只要旋转角度不超过180°,那么平截头体中的点就不可见了。 cam->up和cam->dir是相机的上方向向量和

下面我将发布我的截锥剔除代码,用于剔除边界球体。 我的算法应该相当简单且易于理解:更新方法(称为每帧更新)通过计算平截头体平面的角点以及相应的法线来更新平截头体的平面。法线应全部指向平截头体的中心

在INFORSUM方法中,计算到各个平面的有符号距离,我的想法是,如果一个点到左平面和右平面都有正距离,那么它必须位于这两个平面之间。使用左-右、上-下和近-远进行此操作应确定该点是否可见。只要旋转角度不超过180°,那么平截头体中的点就不可见了。 cam->up和cam->dir是相机的上方向向量和相机的视图光线向量,近、远和fov_度是相应的投影变量。你知道为什么它不能正常工作吗?该问题还与凸轮的位置相对应

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;
    }
};
类平面{
私人:
浮子a、b、c、d;
公众:
无效集(glm::vec3 p0、glm::vec3 p1、glm::vec3 p2){
使用名称空间glm;
vec3v=p1-p0;
vec3u=p2-p0;
vec3n=归一化(交叉(v,u));
a=n.x;
b=n.y;
c=n.z;
d=点(-n,p0);
}
空集(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;
}
浮点距离到(glm::vec3 p)常量{
返回a*p.x+b*p.y+c*p.z+d;
}
};
平截头类{
私人:
平面前、后、左、右、上、下;
公众:
平截头(摄像机和凸轮){
更新(cam);
}
无效更新(摄影机和cam){
使用名称空间glm;
vec3 ndir=标准化(cam->dir);
vec3 nup=正常化(cam->up);
vec3 nright=规格化(交叉(凸轮->方向,凸轮->向上));
//对齐平面
vec3 onn=cam->pos+ndir*cam->near;
vec3 onf=cam->pos+ndir*cam->far;
前.组(onn,ndir);
设置(onf,-ndir);
//远近维度
vec2-fardim=vec2(0.0f,凸轮->远*tan(弧度(凸轮->视场度/2.0f));
fardim.x=fardim.y*cam->纵横比();
vec2 neardim=vec2(0.0f,凸轮->近*tan(弧度(凸轮->视场度/2.0f));
neardim.x=neardim.y*cam->纵横比();
//视锥台角//l=左,r=右,u=上,b=下,n=近,f=远
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;
//不对齐平面
vec3 leftn=规格化(交叉(n_lb-n_lu,f_lu-n_lu));
左。设置(n_lu,leftn);
vec3 rightn=归一化(交叉(n_ru-n_rb,f_rb-n_rb));
右。设置(n_-ru,rightn);
vec3 topn=归一化(交叉(n_lu-n_ru,f_ru-n_ru));
顶置(n_-ru,topn);
vec3 botn=归一化(交叉(f_rb-n_rb,n_lb-n_rb));
底部。设置(n_rb,顶部);
}
布尔信息(glm::vec3 p,浮动半径){
浮动dt=顶部距离(p);
浮动db=底部距离(p);
浮动dl=左。距离(p);
浮动dr=右侧。距离(p);
浮动df=前距离(p);
浮点数dn=背面距离(p);
布尔ix,iy,iz;

ix=(dl>0&&dr>0)| glm::abs(dl)0)| glm::abs(dt)0)| glm::abs(df)我解决了这个问题,问题是
d=p.x*n.x+p.y*n.y+p.z*n.z;
在集合中,它应该是
dot(-n,p)
而不是
dot(n,p)