几何方法--实现

几何方法--实现

一个用来实现视景体的功能的类已经在下面呈现出来了。注意下面的代码并没有任何方面的优化,它仅仅只是用来伴随本课程出现的。这个类包含六个平面的数组,加上其他变量比如说视景体的八个顶点和相机的定义参数。平面只是用来裁剪操作,但是保存变量对我们的调试有用并且可视化的目的。

类的头文件如下:

class FrustumG {

private:

    enum {

        TOP = 0, BOTTOM, LEFT,

        RIGHT, NEARP, FARP

    };

public:

    static enum {OUTSIDE, INTERSECT, INSIDE};

    Plane pl[6];

    Vec3 ntl,ntr,nbl,nbr,ftl,ftr,fbl,fbr;

    float nearD, farD, ratio, angle,tang;

    float nw,nh,fw,fh;

    FrustumG::FrustumG();

    FrustumG::~FrustumG();

    void setCamInternals(float angle, float ratio, float nearD, float farD);

    void setCamDef(Vec3 &p, Vec3 &l, Vec3 &u);

    int pointInFrustum(Vec3 &p);

    int sphereInFrustum(Vec3 &p, float raio);

    int boxInFrustum(AABox &b);

};

方法:setCamInternals

这个函数的参数跟gluPerspective的参数是一样的。每一个透视投影的变换,实际上当窗口改变时,这个函数应该也被调用。

#define ANG2RAD 3.14159265358979323846/180.0

void FrustumG::setCamInternals(float angle, float ratio, float nearD, float farD) {

    // store the information

    this->ratio = ratio;

    this->angle = angle;

    this->nearD = nearD;

    this->farD = farD;

    // compute width and height of the near and far plane sections

    tang = (float)tan(ANG2RAD * angle * 0.5) ;

    nh = nearD * tang;

    nw = nh * ratio;

    fh = farD  * tang;

    fw = fh * ratio;

}

这个函数保存了所有的信息,然后计算了用nh(近平面高度),nw(近平面宽度),fh(远平面高度)和fw(远平面宽度)来计算近平面和远平面的矩形高度和宽度。

方法:setCamDef

这个函数包含三个vector3来包含函数gluLookAt的信息:相机的位置,一个用来表示指向相机朝向的点和一个向上的向量。每当相机位置或者方向改变了,这个函数应该被调用。

void FrustumG::setCamDef(Vec3 &p, Vec3 &l, Vec3 &u) {

    Vec3 dir,nc,fc,X,Y,Z;

    // compute the Z axis of camera

    // this axis points in the opposite direction from

    // the looking direction

    Z = p - l;

    Z.normalize();

    // X axis of camera with given "up" vector and Z axis

    X = u * Z;

    X.normalize();

    // the real "up" vector is the cross product of Z and X

    Y = Z * X;

    // compute the centers of the near and far planes

    nc = p - Z * nearD;

    fc = p - Z * farD;

    // compute the 4 corners of the frustum on the near plane

    ntl = nc + Y * nh - X * nw;

    ntr = nc + Y * nh + X * nw;

    nbl = nc - Y * nh - X * nw;

    nbr = nc - Y * nh + X * nw;

    // compute the 4 corners of the frustum on the far plane

    ftl = fc + Y * fh - X * fw;

    ftr = fc + Y * fh + X * fw;

    fbl = fc - Y * fh - X * fw;

    fbr = fc - Y * fh + X * fw;

    // compute the six planes

    // the function set3Points assumes that the points

    // are given in counter clockwise order

    pl[TOP].set3Points(ntr,ntl,ftl);

    pl[BOTTOM].set3Points(nbl,nbr,fbr);

    pl[LEFT].set3Points(ntl,nbl,fbl);

    pl[RIGHT].set3Points(nbr,ntr,fbr);

    pl[NEARP].set3Points(ntl,ntr,nbr);

    pl[FARP].set3Points(ftr,ftl,fbl);

}

这个函数计算了视景体的八个顶点和在前面一节介绍的六个平面。

下面(更有效的)也可以用来计算上面提到的八个点和六个平面的方法:

pl[NEARP].setNormalAndPoint(-Z,nc);

    pl[FARP].setNormalAndPoint(Z,fc);

    Vec3 aux,normal;

    aux = (nc + Y*nh) - p;

    aux.normalize();

    normal = aux * X;

    pl[TOP].setNormalAndPoint(normal,nc+Y*nh);

    aux = (nc - Y*nh) - p;

    aux.normalize();

    normal = X * aux;

    pl[BOTTOM].setNormalAndPoint(normal,nc-Y*nh);

    aux = (nc - X*nw) - p;

    aux.normalize();

    normal = aux * Y;

    pl[LEFT].setNormalAndPoint(normal,nc-X*nw);

    aux = (nc + X*nw) - p;

    aux.normalize();

    normal = Y * aux;

    pl[RIGHT].setNormalAndPoint(normal,nc+X*nw);

英文地址

你可能感兴趣的:(几何方法--实现)