OpenGL 图形变换

来源:互联网 发布:手机屏幕长截图软件 编辑:程序博客网 时间:2024/06/05 17:54
OpenGL 图形变换


前言:
一天过去了,很快。也没学进去多少东西,有点难受,下周导师要检查我们的进度,需要加紧了。
路漫漫其修远兮,吾将上下而求索      致自己


在分享今天学习的图形操作之前,先更改一下,在OpenGL 单文档配置的一些问题;
在OnSize()函数中,设置模式转换、视点等函数,后面讲解:
void CStepinGLView::OnSize(UINT nType, int cx, int cy){CView::OnSize(nType, cx, cy);// TODO: 在此处添加消息处理程序代码if (cy > 0){if((m_oldRect.right > cx)||(m_oldRect.bottom > cy))RedrawWindow();m_oldRect.right = cx;m_oldRect.bottom = cy;glMatrixMode(GL_PROJECTION);glLoadIdentity();glFrustum(-1.0,1.0,-1.0,1.0,0.0,7.0);glViewport(0,0,cx,cy);}}

在OnDraw()函数中,使用双缓存和一些初始化设定,可以同时绘制多个图形:
void CStepinGLView::OnDraw(CDC* pDC){CStepinGLDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// 双缓存应用(与下面语句成对使用)static BOOL bBusy = FALSE;  if(bBusy)return;bBusy = TRUE;//背景色,没有下面语句时背景为黑色//glClearColor(0.2f,0.2f,0.5f,1.0f);glClearColor(1.0f,1.0f,1.0f,1.0f);glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);    //清除缓存,将其背景色置空glMatrixMode(GL_MODELVIEW);                           //启动模型矩阵glLoadIdentity();                                     //初始化矩阵DrawScene();//DrawTriangles();glFinish();SwapBuffers(wglGetCurrentDC());        //双缓存应用(为了动画显示无滞留闪烁)bBusy = FALSE;}


一.投影变换

投影变换就是要将三维物体变换为二维图形。OpenGL提供两种投影方式:
平行投影(Orthographic Projection)和透视投影(Perspective Projection)
为了使一个盒子看起来更加真实,必须采用透视投影;

在进行投影变换之前应告诉OpenGL将操作透视矩阵(Perspective Matrix):
glMatrixMode(GL_PROJECTION);
常采用此函数,在矩阵堆栈中选择透视矩阵。因此透视矩阵必须初始化:
glLoadIdentity();
glLoadIdentity() 用一个4*4的单位矩阵初始化当前选定的矩阵。

1.1平行投影
平行投影,又叫正交投影。它的视景体为一个长方体:

平行投影不会因为物体的远近而改变大小 尺寸,便于我们观察。OpenGL提供两个函数来实现平行投影变换。其一:
void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
改函数,近剪切面的左下角(left,bottom,-near)被映射到窗口的左下角,右上角点(right,top,-near)映射到窗口的右上角。-near确定了近剪切面的位置,-far确定了远剪切面的位置。两者必须具有相同的符号。
另一个函数:
void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top);
该函数是将二维图像变换到二维平面上,near和top的缺省值分别是 -1.0和1.0。

1.2透视投影
 OpenGL提供了两个透视投影函数。其一:
void glFrustum(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);

有一点,near和far表示近剪切面和远剪切面距离视点的远近,必须为非负。例如:
glFrustum(-1.0,1.0,-1.0,1.0,0.0,7.0);
另一个函数:
void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble near,GLdouble far);



二.几何变换

2.1平移变换
如果将OnSize()函数中的投影函数修改为:
glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);
编译之后就会找不到图形;原因是盒子此时处于视景之外。
解决这一问题的方法就是把盒子沿z轴负方向平移,使其进人视景。

在DrawScene()函数中,加入:
glTranslatef(0.0f,0.0f,-4.5f);

同样的,也可以使用此函数,对图形进行平移。

2.2旋转变换
可以使用:
glRotatef(rtri,0.0f,0.0f,0.0f);
对图形进行旋转操作,第一参数表示旋转角度,后面分别表示绕X/Y/Z轴旋转;例如:
glRotatef(90,0.0f,0.1f,0.0f);
就是将图形绕Y轴旋转90度。

另:如果想把图形自动绕某个轴旋转,可以设定一个定时器,WM_TIMER;大概步骤如下:
GLfloat     rtri;CStepinGLView::CStepinGLView()   //构造函数{// TODO: 在此处添加构造代码rtri = 0.0f;             //初始化}void CStepinGLView::OnTimer(UINT_PTR nIDEvent){// 定时器中设置如果旋转360度 重新if (rtri == 360.0f){rtri = 1.f;}elsertri += 1.f;Invalidate(FALSE);CView::OnTimer(nIDEvent);}int CStepinGLView::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CView::OnCreate(lpCreateStruct) == -1)return -1;// 启动定时器SetTimer(1,120,NULL);return 0;}void CStepinGLView::OnDestroy(){KillTimer(1);     //销毁定时器CView::OnDestroy();}//最后绘制时void CStepinGLView::DrawScene(void){glRotatef(rtri,0.0f,0.1f,0.0f);glutSolidTeapot(0.3);}


2.3缩放变换
glScalef(1.5f,1.5f,1.5f);
就是将物体等比放大1.5倍,也可以不进行等比缩放;


三.视口变换
OpenGL提供了一个定义视口大小的函数:
void glViewPoint(GLint x,GLint y,GLsizei width,GLsizei height);
视口就是一个用来绘制场景的矩形区域。视口变换决定把场景中的点怎样映射到绘图区。
x和y分别说明视口的左下角点在窗口中的位置,width和height分别是视口的宽度和高度,以像素为单位。

到这里,OnSize ()函数里的函数都讲完了。

四.剪切变换
void glClipPlane(GLenum plane,const GLdouble * equation);



大概就先讲这么多吧,有点累了,明天分享光照和交互!