OpenGL:クリップ面で切る

本物のページはこちら→clipplane

Included page "clipplane" does not exist (create it now)

glClipPlane(GLenum plane,GLdouble *equation)

引数

GLenum plane

GL_CLIP_PLANE0,
GL_CLIP_PLANE1,
GL_CLIP_PLANE2,
GL_CLIP_PLANE3,…
みたいな定数を渡す。
あとで

glEnable(GL_CLIP_PLANEi);
...
glDisable(GL_CLIP_PLANEi);

という風に使うのだ。

GLdouble *equatiobn

Ax+By+Cz+D=0
という平面の方程式のパラメータを渡す。
Ax + By + Cz + d≧0
をみたす部分だけを描画するものである。

使用上の注意

ここでの数値の扱いはカメラ座標系である。クリップ座標系ではない。

GLSLと併用する場合

普通に
glClipPlane(GL_CLIPPLANE0,eqn);
glEnable(GL_CLIP_PLANE0);
した上で更に、
頂点シェーダでgl_ClipVertexに値を渡してあげる必要がある。

gl_ClipVertex= ModelView*gl_Vertex;

これをしないと、クリップしてくれない。

シェーダだけで実現する方法

grasshopper-Clip Planes

平面の方程式

float gClipPlane=0.6f;
GLdouble eqn[]={0.0,0.0,1.0,gClipPlane};

みたいな値を渡すけど、どこで

したかによって変わってくる。これも、頂点座標を渡すのと同じと思っていい。
だから、オブジェクトと平行に切ることもできるし、
モデル行列を渡す前にやれば、視点からどのくらいの距離までを切る、みたいなことも出来る。

どの段階でglClipPlane(GL_CLIP_PLANE0,m_Eqn);するのか?

によって、変わってくる。
視点からpushする形にしたいなら、
クリップ面をobjectト alignedにしたいなら、平行移動、回転操作をした直後に

lClipPlane(GL_CLIP_PLANE0,m_ClippingEquation);
    glEnable(GL_CLIP_PLANE0);

する。
view alignedにしたいなら、平行移動回転操作するまえにやる。

クリップ面を描く

使用上の注意
これを書くとき、mBoundingBoxにだけglTranslateしないこと。
するぐらいだったら、mBoundingBoxの頂点位置データを平行移動させる。
じゃないと、クリッピング面がズレズレになっちゃうよ。

void CMeasure::DrawClipPlane(){
    vec3<float> intersection[6];
    float m[16];
    glGetFloatv(GL_MODELVIEW_MATRIX,m);
    bool visible=mBoundingBox.CalcClipPlaneVerts(m,-m_pClipped->getDis(),intersection);
    //mFontColor.glColor();
    if(visible){
        glBegin(GL_LINE_LOOP);
        for(int i = 0; i < 6; ++i) {
            intersection[i].glVertex();
        }
        glEnd();
    }
 
}
        //_distCam=視点と平面の距離 0にしたら箱の真中に平面が来るけど。。??
        bool CalcClipPlaneVerts(float _modelview[16],float _distCam,vec3<T> intersection[6]){
            vec3<float> viewVec(-_modelview[2],-_modelview[6],-_modelview[10]);
 
            float dMaxDist = viewVec.innerProduct( corner[0]);
            float dMinDist = dMaxDist;
            int nMaxIdx = 0;
            for(int i = 1; i < 8; ++i) {
                float dist = viewVec.innerProduct( corner[i]);
                if ( dist > dMaxDist) {
                    dMaxDist = dist;
                    nMaxIdx = i;
                }
                if ( dist < dMinDist) {
                    dMinDist = dist;
                }
 
            }
            vec3<float> vecStart[12];
            vec3<float> vecDir[12];
            float lambda[12];
            float denom;
 
            dMinDist += FLT_EPSILON;
            dMaxDist -= FLT_EPSILON;
 
            float dVertices[12*3];
            float dEdges[12*3];
 
            for(int i = 0; i < 12; i++) {
                vecStart[i] = corner[edges[edgeList[nMaxIdx][i]].nV1];
                vecDir[i]   = corner[edges[edgeList[nMaxIdx][i]].nV2] - corner[edges[edgeList[nMaxIdx][i]].nV1];
 
                denom = vecDir[i].innerProduct(viewVec);
 
                if (1.0 + denom != 1.0) {
                    lambda[i]     = (_distCam - vecStart[i].innerProduct(viewVec))/denom;//
                } else {
                    lambda[i]     = -1.0;
                }
 
                dVertices[3*i]   = vecStart[i].x;
                dVertices[3*i+1] = vecStart[i].y;
                dVertices[3*i+2] = vecStart[i].z;
                dEdges[3*i]      = vecDir[i].x;
                dEdges[3*i+1]    = vecDir[i].y;
                dEdges[3*i+2]    = vecDir[i].z;
            };
 
            bool visible=true;
            //lmb:辺のどのあたりに交点があるのかの、割合。
 
            if      ((lambda[0] >= 0.0) && (lambda[0] < 1.0)) intersection[0] = vecStart[0] + vecDir[0]*lambda[0] ;
            else if ((lambda[1] >= 0.0) && (lambda[1] < 1.0)) intersection[0] = vecStart[1] + vecDir[1]* lambda[1] ;
            else if ((lambda[3] >= 0.0) && (lambda[3] < 1.0)) intersection[0] = vecStart[3] + vecDir[3]* lambda[3] ;
            else {return false;}//このボックスにクリッピング面は交差していません。
 
            if        ((lambda[2] >= 0.0) && (lambda[2] < 1.0)) intersection[1] = vecStart[2] + vecDir[2]*lambda[2] ;
            else if ((lambda[0] >= 0.0) && (lambda[0] < 1.0)) intersection[1] = vecStart[0] + vecDir[0]*lambda[0] ;
            else if ((lambda[1] >= 0.0) && (lambda[1] < 1.0)) intersection[1] = vecStart[1] + vecDir[1]*lambda[1] ;
            else intersection[1] = vecStart[3] + vecDir[3] * lambda[3];
 
            if      ((lambda[4] >= 0.0) && (lambda[4] < 1.0)) intersection[2] = vecStart[4] +vecDir[4]* lambda[4] ;
            else if ((lambda[5] >= 0.0) && (lambda[5] < 1.0)) intersection[2] = vecStart[5] +  vecDir[5]*lambda[5] ;
            else intersection[2] = vecStart[7] + vecDir[7]*lambda[7]  ;
 
            if        ((lambda[6] >= 0.0) && (lambda[6] < 1.0)) intersection[3] = vecStart[6] + vecDir[6]*lambda[6]  ;
            else if ((lambda[4] >= 0.0) && (lambda[4] < 1.0)) intersection[3] = vecStart[4] +  vecDir[4]*lambda[4] ;
            else if ((lambda[5] >= 0.0) && (lambda[5] < 1.0)) intersection[3] = vecStart[5] +  vecDir[5]*lambda[5] ;
            else intersection[3] = vecStart[7] + vecDir[7]*lambda[7];
 
            if        ((lambda[8] >= 0.0) && (lambda[8] < 1.0)) intersection[4] = vecStart[8] +  vecDir[8]*lambda[8]  ;
            else if ((lambda[9] >= 0.0) && (lambda[9] < 1.0)) intersection[4] = vecStart[9] +  vecDir[9]*lambda[9]  ;
            else intersection[4] = vecStart[11]+ vecDir[11]*lambda[11];
 
            if        ((lambda[10]>= 0.0) && (lambda[10]< 1.0)) intersection[5] = vecStart[10]+ vecDir[10]*lambda[10]; 
            else if ((lambda[8] >= 0.0) && (lambda[8] < 1.0)) intersection[5] = vecStart[8] + vecDir[8]*lambda[8]  ;
            else if ((lambda[9] >= 0.0) && (lambda[9] < 1.0)) intersection[5] = vecStart[9] + vecDir[9]*lambda[9]   ;
            else intersection[5] = vecStart[11]+ vecDir[11]*lambda[11];
 
            return visible;
 
        }

サポートサイト Wikidot.com