opengl编程投影变换:Win32 OpenGL编程(9) 投影变换

  提要

  在前文(系列文章(7)以下简称XO7系列其他文章类似)中照相机比喻中提到了4种3D变换如下:

  1.确定照相机位置过程对应于“视图变换”(Viewing Transformations)

  2.确定物体位置过程对应于“模型变换”(Modeling Transformations)

  3.确定照相机放大倍数过程对应于“投影变换”(Projection Transformations)

  4.确定照片大小过程对应于“视口变换”(Viewport Transformations)

  XO7中我们讲是第种变换视图变换即改变观察者本身位置视角等变换效果XO8中讲是第 2种变换模型变换本文开始继续按顺序讲解下个3D变换过程投影变换

  正投影

  投影变换过程就像是照相机选镜头过程是确定视野其实说起来投影我在学习工程制图时候就接触过了不知道大家是否学过这门课程工程制图就是种将 3维空间事物设想投影在 2维空间中然后画下来工程中应用非常广泛那时候学那些剖面图什么也是累死我了-_-!OpenGL就可以模拟这样过程并且名字和工程制图中名字是叫正投影

  OpenGL以glOrtho来指定个正交平行矩形屏幕上显示就是此物体在此矩形正面投影在XO2中用过gluOrtho2D实际上是此个去掉Z轴坐标简化版而glOrtho包括参数 nearVal,farVal表示此矩形后两面超出此矩形范围图形将会被裁掉

  OpenGL Programming Guide:

    glOrtho — multiply the current matrix with an orthographic matrix
    C Specication
    void glOrtho(    GLdouble      left,
         GLdouble      right,
         GLdouble      bottom,
         GLdouble      top,
         GLdouble      nearVal,
         GLdouble      farVal);
    Parameters
    left, right
                            Specy the coordinates for the left and right vertical clipping planes.
    bottom, top
                            Specy the coordinates for the bottom and top horizontal clipping planes.
    nearVal, farVal
                            Specy the distances to the nearer and farther depth clipping planes.
                            These values are negative  the plane is to be behind the viewer.


  用此通过调整nearVal和farVal我们可以实现类似工程制图中剖面效果见下例:

GLfloat gfNear = 1.0;
//这里进行所有绘图工作
void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    glOrtho(-1.0, 1.0, -1.0, 1.0, gfNear, -1.0);

    glPushMatrix;
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;
    glFlush;
}  
///////////////////////////////////////////////////////////
 Game_Main(void *parms = NULL,  num_parms = 0)
{
    DWORD dwStartTime;
    dwStartTime = GetTickCount;
    // this is the  loop of the game, do all your processing
    // here
    // for now test  user is hitting ESC and send WM_CLOSE
     (KEYDOWN(VK_ESCAPE))
        SendMessage(ghWnd,WM_CLOSE,0,0);
     (KEYDOWN(VK_UP))
    {
        gfNear -= 0.01;
    }
     (KEYDOWN(VK_DOWN))
    {
        gfNear  0.01;
    }

    SceneShow;

    // 控制帧率
    while(GetTickCount - dwStartTime < TIME_IN_FRAME)
    {
        Sleep(1);
    }

    //  success or failure or your own  code here
    (1);
} // end Game_Main


  以下就是当nearVal为0.8时效果也就是说Z轴坐标大于0.8律被截掉了在工程制图中我们老师常将此时假设在此用刀将物体切掉

  上面源代码中还出现了个新glMatrixmode用于指定以下变换是针对哪个变换

  glMatrixMode(GL_PROJECTION);

  用于指定以下变换是针对投影变换而用

  glMatrixMode(GL_MODELVIEW);

  方式(默认值)表示针对模型变换

  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2008-10-28\glOrthoSample 目录获取方式见文章最后有关获取博客完整源代码介绍说明



  图片看不清楚?请点击这里查看原图(大图)

  透视投影

  上述正投影仅仅存在于想象的中主要是工程制图(或者CAD)中能够正确反映物体真实尺寸现实中我们看东西越远越小越近越大并且所有物体最终会消失在远方(地平线)OpenGL常用于VR(虚拟现实)这样程度视觉仿真效果自然是有在OpenGL中这样投影叫做透视投影 OpenGL提供了两个用于指定透视投影两个仅仅是参数表示方式区别事实上效果是

  OpenGL Programming Guide:

    glFrustum — multiply the current matrix by a perspective matrix
    C Specication
    void glFrustum(    GLdouble      left,
         GLdouble      right,
         GLdouble      bottom,
         GLdouble      top,
         GLdouble      nearVal,
         GLdouble      farVal);
    Parameters
    left, right
                            Specy the coordinates for the left and right vertical clipping planes.
    bottom, top
                            Specy the coordinates for the bottom and top horizontal clipping planes.
    nearVal, farVal
                            Specy the distances to the near and far depth clipping planes.
                            Both distances must be positive.
    gluPerspective —  up a perspective projection matrix
    C Specication
    void gluPerspective(    GLdouble      fovy,
         GLdouble      aspect,
         GLdouble      zNear,
         GLdouble      zFar);
    Parameters
    fovy
                            Species the field of view angle, in degrees, in the y direction.
    aspect
                            Species the aspect ratio that determines
                            the field of view in the x direction.
                            The aspect ratio is the ratio of x (width) to y (height).
    zNear
                            Species the distance from the viewer to the near clipping plane
                            (always positive).
    zFar
                            Species the distance from the viewer to the far clipping plane
                            (always positive).


  事实上glFrustum指定方式和glOrtho很像参数意义也仅仅是使用后OpenGL使用投影方式区别gluPerspective指定方式是模拟观察者(照相机)视角用fovy指定观察者上下视角(及在y-z平面上观察角度)aspect指定观察宽度和高度然后用zNear指定离观察者较近截面用zFar指定离观察者较远截面(都指离观察者距离)下例展示了原来那个 3角锥从远方个小点然后到放大到原来大小过程:

GLfloat gfDis = 5.0;
//这里进行所有绘图工作
void SceneShow(GLvoid)        
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
    gluLookAt(0.0, 0.0, gfDis, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);
    glPushMatrix;
    DrawSmoothColorPyramid(0.5);
    glPopMatrix;

    glFlush;
}  
 Game_Main(void *parms = NULL,  num_parms = 0)
{
    DWORD dwStartTime;
    dwStartTime = GetTickCount;
    // this is the  loop of the game, do all your processing
    // here
    // for now test  user is hitting ESC and send WM_CLOSE
     (KEYDOWN(VK_ESCAPE))
        SendMessage(ghWnd,WM_CLOSE,0,0);
     (KEYDOWN(VK_UP))
    {
        gfDis -= 0.01f;
    }
     (KEYDOWN(VK_DOWN))
    {
        gfDis  0.01f;
    }
    SceneShow;
    // 控制帧率
    while(GetTickCount - dwStartTime < TIME_IN_FRAME)
    {
        Sleep(1);
    }
    //  success or failure or your own  code here
    (1);
} // end Game_Main


  上面例子中靠

gluLookAt(0.0, 0.0, gfDis, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);

  来调整观察者位置通过上下键调节会模拟出种慢慢走近 3角锥过程 3角锥也是随着走近由小慢慢变大

  实际上最重要还是

glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);


   3句确定透视投影方式

 

  为节省篇幅仅贴出关键片段完整源代码见我博客源代码2008-10-28\glPerspective 目录获取方式见文章最后有关获取博客完整源代码介绍说明

  小结:

  相对来说个人认为投影变换是属于OpenGL中重要但是确较难理解部分动态变化上述参数准确理解上述中每个参数意义是种不错学习途径其中Nate RobinOpenGL教程有个很形象教学推荐给大家(实际上为OpenGL Programming Guide中推荐)http://www.xmission.com/~nate/tutors.html中有下载对应投影变换教程为projection



Tags:  opengl编程投影变换

延伸阅读

最新评论

发表评论