您的位置:首页 > 其它

裁剪平面ClipPlane

2016-07-18 20:05 295 查看
转自:http://blog.csdn.net/oktears/article/details/42915623

除了视景体的6个裁剪平面(左、右、底、顶、近和远)之外,还可以另外再指定最多可达6个的其他裁剪平面,对视景体施加进一步的限制。

每个平面都是由它的方程式Ax + By + Cz + D= 0的系数所指定的。裁剪平面会根据模型和视图矩阵自动执行适当的变换。最终的裁剪区域将是视景体与其他裁剪平面定义的所有半空间的交集。记住,OpenGL会自动对部分被裁剪的多边形的边进行正确的重构。

[cpp] view
plain copy

void glClipPlane(GLenum plane, const GLdouble *equation);   

定义一个裁剪平面。equation参数指向平面方程Ax + By + Cz + D = 0的4个系数。满足(A B C D)M-1 (xe ye ze we) T≥0的所有视觉坐标(xe ye ze we)点都位于这个平面定义的半空间中,其中M是在调用glClipPlane()时的当前模型视图矩阵。所有不是位于这个半空间内的点都将裁剪掉。plane参数是GL_CLIP_PLANEi,其中i是一个整数,表示需要定义哪个有效裁剪平面。i的值位于0和最大其他裁剪平面数减1之间。

我们需要启用每个被定义的裁剪平面:

[cpp] view
plain copy

glEnable(GL_CLIP_PLANEi);   

也可以用下面这个函数禁用一个裁剪平面:

[cpp] view
plain copy

glDisable(GL_CLIP_PLANEi);   

所有的OpenGL实现都必须支持至少6个其他裁剪平面,有些实现可能允许超过6个的其他裁剪平面。可以用GL_MAX_CLIP_PLANES为参数调用glGetIntegerv()函数,查询自己使用的OpenGL实现所支持的其他裁剪平面的最大数量。

调用glClipPlane()函数所执行的裁剪是在视觉坐标中完成的,而不是在裁剪坐标中进行的。如果投影矩阵为奇异矩阵(也就是把三维坐标压平到二维坐标的真正投影矩阵),这个区别就非常大。在视觉坐标中进行裁剪时,即使投影矩阵是奇异矩阵,裁剪仍然是在三维空间中进行的。

下面的例子通过两个裁剪平面对球体进行了裁剪。

[cpp] view
plain copy

//  

//  main.cpp  

//  OpenGL_10_ClipPlane  

//  

//  Created by apple on 15/1/19.  

//  Copyright (c) 2015年 cc. All rights reserved.  

//  

  

#include <iostream>  

  

#include <GLUT/GLUT.h>  

  

/** 

 *  初始化操作 

 */  

void init() {  

    //设置清屏色  

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  

    //设置着色模式,填充色与顶点一致  

    glShadeModel(GL_FLAT);  

}  

  

/** 

 *  展示绘制效果 

 */  

void display() {  

      

    //清理颜色缓冲区  

    glClear(GL_COLOR_BUFFER_BIT);  

    //设置绘制颜色  

    glColor3f(1.0, 1.0, 1.0);  

    //复制当前矩阵并保存到栈顶  

    glPushMatrix();  

    //沿z轴负方向移动5个单位长度  

    glTranslatef(0.0f, 0.0f, -5.0f);  

      

    //定义裁剪平面数组, Ax + By + Cz + D = 0  

    GLdouble equn[4] = {0.0f, 1.0f, 0.0f, 0.0f};  

    GLdouble equn2[4] = {1.0f, 0.0f, 0.0f, 0.0f};  

  

    //设置裁剪平面,y>0  

    glClipPlane(GL_CLIP_PLANE0, equn);  

    glEnable(GL_CLIP_PLANE0);  

      

    //设置裁剪平面,x>0  

    glClipPlane(GL_CLIP_PLANE1, equn2);  

    glEnable(GL_CLIP_PLANE1);  

      

    //沿x轴旋转90度  

    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);  

  

    //渲染一个球体,球体半径,以Z轴上线段为直径分布的圆周线的条数(经线),围绕在Z轴周围的线的条数(维线)  

    glutWireSphere(2.0f, 20.0f, 16.0f);  

      

    //弹出栈顶矩阵  

    glPopMatrix();  

      

    //强制完成绘制指令  

    glFlush ();  

}  

  

/** 

 *  调整窗口尺寸 

 * 

 *  @param width  宽度 

 *  @param height 高度 

 */  

void reshape(int width, int height) {  

    //设置视口矩形区域,在默认情况下,视口被设置为占据打开窗口的整个像素矩形  

    glViewport(0, 0, (GLsizei)width, (GLsizei)height);  

    //之后的矩阵操作定义为投影矩阵操作  

    glMatrixMode(GL_PROJECTION);  

    //等于是将之前矩阵变换导致变化过的栈顶矩阵重新归位,置为单位矩阵!等于是之前的矩阵变换带来的影响到此为止了!  

    glLoadIdentity();  

      

    //创建一个表示对称透视视图平截头体的矩阵  

    //设置眼睛睁开的角度,视景体的宽高比,近截面的距离,远截面的距离  

    gluPerspective(60.0f, (GLfloat)width / (GLfloat)height, 1.0f, 20.0f);  

      

    //之后的矩阵操作定义为模型视图矩阵操作  

    glMatrixMode(GL_MODELVIEW);  

      

}  

  

int main(int argc, const char * argv[]) {  

      

    //初始化GLUT库  

    glutInit(&argc, (char**)argv);  

    //设置单缓冲,RGB像素格式的窗口  

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  

    //设置窗口大小  

    glutInitWindowSize(500, 500);  

    //设置窗口坐标  

    glutInitWindowPosition (100, 100);  

    //创建窗口  

    glutCreateWindow("ClipPlane");  

      

    //初始化操作  

    init();  

      

    //设置展示的回调方法  

    glutDisplayFunc(display);  

    glutReshapeFunc(reshape);  

      

    //绘制线程开始循环  

    glutMainLoop();  

      

    return 0;  

}  



本文由CC原创总结,如需转载请注明出处:http://blog.csdn.net/oktears/article/details/42915623
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: