openGL学习笔记之一--视图

来源:互联网 发布:qq群监控软件 编辑:程序博客网 时间:2024/04/30 05:12

最近在编写三维显示程序的过程中,遇到了OpenGL视图方面的相关内容,对于一些基本变换的操作感到迷惑,于是重新回顾了《openGl 编程指南》第三章关于视图的相关内容。现在将自己理解的内容总结如下。


  一、OpenGl 在渲染场景的过程中有四个基本的变换:

1、视图变换--主要作用是确定相机的姿态,更形象点来讲是将相机固定到三角架上,对准要拍摄的物体。

2、模型变换--主要是用来绘制物体,确定物体的姿态和位置。 相当于人在照相时,摆好pose.

  注意,一般而言,视图变换和模型变换可以相互转化,比如,相机平移(0,0,1)想当于人平移(0,0,-1)因此OpenGL 引入了GL_MODELVIEW变量来统一管理模型和视图变换。


         glMatrixMode(GL_MODELVIEW);

          glLoadIdentity();   // 吧当前矩阵设置为单位矩阵,很重要,因为绝大部分的变换都是把当前矩阵与指定的矩阵相                                          //乘,如果没有加载单位矩阵来清除当前矩阵,他所进行的变换实际上是把当前的变换与上一                                           //次变换相组合

         glLookAt(0,0,0,0,0,0,0,0,0)// 相机位置

         glTranslate(0,0,0);

         glScale(0,0,0);

         draw_object();


3、投影变换--主要作用是进行透视变换,形象点解释是为相机选择镜头。分为透视投影和正交投影。


        glMatrxiMode(GL_PROJECTION)

        glLoadIdentity();//

         /**********透视投影************/

        gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far);

        或者

        glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

        /*********正交投影************/

        glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

4、视口变换--将投影后的物体坐标最终对应到窗口坐标系中。


       glViewport(GLint x, GLint y, GLsizei width GLdizei height);

        注意此处中 width 和 height 的比例应该和透视投影中的aspect 相同,否则得到的的物体会发生变形。


二、全局固定坐标系和局部移动坐标系

其实是对同意中坐标转换的不同的理解,主要是在物体的绘制过程中。

            glMatrixMode(GL_MODELVIEW)

            glLoadIdentity();

            glMultiMatrix(T);

            glMultiMatix(R);

           draw_the_object();


从全局度固定坐标系的角度来理解,对于上述的矩阵变化是从下往上: 绘制物体,先绕全局原点进行旋转,然后绕全局的坐标系进行平移。

从局部移动坐标系的角度来理解, 对于上述的矩阵变化是从上往下: 绘制物体,先进行平移(局部坐标原点开始与全局坐标原点重合,随着物体平移),然后绕着局部坐标系原点进行旋转。

另一种情况:

                   glMultiMatix(R);

                   glMultiMatrix(T);

注意,假设采用局部移动坐标系,先进行旋转,此时原点仍然重合,但是坐标轴已经发生变化。


3、关于矩阵操作

对于视图矩阵,投影矩阵,和视口矩阵都分别有一个对应的矩阵堆栈,具体选择哪种矩阵堆栈使用glMatrixMode(GL_PROJECTION)操作,表示下面的矩阵是影响投影矩阵。


通常情况下,发挥作用的是矩阵堆栈的的最顶部的矩阵。但是在实际操作过程中,通常需要进行分层次创建。比如在绘制汽车时,先绘制车体(此时位于车体坐标系)然后绘制左前轮,绘制玩左前轮后通常是回到车体坐标系,然后绘制右前轮。 此时需要先保存车体坐标系。

为了实现这种操作openGL 采用了glPushMatrix() 和glPopMatrix()两个矩阵堆栈的操作。


glPushMatrix()复制一份当前矩阵(注意,当前矩阵就是堆栈最顶部的矩阵)并将当前矩阵下压一级,也就是说此时的矩阵堆栈中,最顶的两级中的矩阵是相同的。

glPopMatrix() 将最顶部的矩阵弹出并销毁。


for(int i=0; i<5; i++)

{

    glPushMatrix();//最顶的两级相同

    glRotatef(R);// 最顶部的矩阵发生变化

    glTranlatef(T);

    draw_bolt();

    glPopMatrix(); //恢复初始的坐标系

}

 四、基本的框架


void init(void);//初始化

void dispaly(void); {  //绘制物体


//模型变换

glTranslatef(T);

glRotatef(R);

draw_object();


}


void reshape(int w, int h) { //


//视口变换

glViewport(0,0, (GLsizei)w, (GLsizei)h);


//投影变换

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glPerspective();

//视图模型变换

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glLookAt() //有时候也放到reshape 的开头

}