[开发总结]系统架构及数据模型----OpenGL模式显示及临时显示篇(二)

来源:互联网 发布:烂电影知乎 编辑:程序博客网 时间:2024/04/28 22:34

一、系统启动时序图及GL环境初始化的时机。

GLShow

OpenGL环境建立及绘制实现原理大致如下:

    1)创建与屏幕设备兼容的内存绘图场景:

       CDC* pMemDc = new CDC() ;

        pMemDc.Attach(CreateCompatibleDC(hdc));

        hdc:为视图(CView)的绘图设备句柄。

     2)创建位图(画布),并将位图选入内存绘图场景:::SelectObject(m_hdcMem,m_hBM);

     3)创建OpenGL资源场景,并建立资源场景与内存场景的关联。因为在OpenGL 中,所有的操作是面向资源绘图场景,然后待到刷新显示列表时(glFlush),再完成资源场景到内存场景的映射过程。
            HGLRC  m_hglRC=wglCreateContext(m_pMemDC->GetSafeHdc());//资源场景与内存绘图环境兼容

            wglMakeCurrent(m_pMemDC->GetSafeHdc(),m_hglRC)//建立关联

            wglMakeCurrent(NULL,NULL)//断开关联

        4)这样,OpenGL 的所有绘图操作,都针对内存pMemDc绘图场景(也可以看成往内存位图中绘制)。

  5)在视图的CView的WM_PAINT发生时,将内存绘图场景(pMemDc)的内容往设备绘图场景中拷贝(也就是将位图中的图形,拷贝到屏幕中)。

             BitBlt(hdcDest,xDest,yDest,cx,cy,m_hdcMem,xSrc,ySrc,SRCCOPY);

---------------------------------------------------------------------------------------------

1、临时线

是通过GDI/GL模式下的“异或”画法来实现。SetROP2(R2_XORPEN)

“异或”,大致原理应该是(猜的,并未从相关书籍中求证):在“异或”方式下绘制图形前,以背景色檫除掉所记录下来的前一次“异或”方式绘制的图形,这一过程由操作系统自动完成。

2、投影变换:图形缩放

是通过视口变换(glViewport,视口大小不变,为位图大小)和正交投影变换(glOrtho,改变正交视景体的大小)实现。如下:

(说明:OPENGL的绘制模型的坐标系统,采用的是世界坐标系统,从模型坐标到屏幕坐标的映射是通过视口与投影变换来自动完成这一个过程。逆向映射,请看第3点说明。)

 //定义视口:决定了显示窗口的大小(象素单位)。

glViewport(m_ptOrg.x,-m_ptOrg.y,m_mainBM.GetSize().cx,m_mainBM.GetSize().cy);

说明:

m_ptOrg.:为视图CView窗口的绘图区的左上角象素坐标值,映射到OPENGL视口的左下角坐标

(在定义视口之前,Opengl的绘图环境已经与窗口绘图区建立关联,所以,该glViewport函数所传入的坐标值是以“窗口区”的左下角为坐标原点,这恰恰与“屏幕坐标系统以左上角为原点”相反,所以在第二个参数前,加了“—”号)

后面两个参数为DIB(Device_independent Bitmap)位图的大小。

//正交投影:定义平行视景体。

 glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
  glOrtho(EyePos.x-dx/scale,/
       EyePos.x+dx/scale,/
       EyePos.y-dy/scale,/
       EyePos.y+dy/scale,/
       -10000.,10000.);
     glMatrixMode(GL_MODELVIEW);

说明:

参数用于确定剪裁面的位置。

EyePos为观察点位置,也就是“眼睛”所在的位置。(默认情况下,观察点位置在世界坐标系的原点处)

dx为视景体的宽一半

dy为视景的高一半

10000为视景体的长,在二维系统中,这个值没有作用。

视景体的dx/dy宽高比值必须与视口的宽高比值一致,否则图形变形。

scale缩放比率。

所以在图形缩放时,只需要将视景体的宽高按比率(scale)缩小或放大即可,即:

宽缩放后:dx/scal;

高缩放后:dx/scal;

变换过程如下图所示:

opengl3

图形缩放实际上是利用投影变换的剪裁面去填充视口而实现的:

剪裁面越小,则视口中显示的图形越大。反之,亦然。

剪裁面,就是剪裁窗口:二维场景(世界坐标系)要显示的部分,叫做剪裁窗口(clipping window)。也称观察窗口。
可看成是相机的镜头,在OPENGL中对应函数:

gluOrtho2D(...);

对应于观察窗口,在设备坐标系中的视口就当做胶片,剪裁窗口大小不变时,胶片越大(也就是视口越大),图象越大.其对应的函数
glViewPort(...);

二维世界坐标系场景描述到设备坐标系的映射,称为二维观察变换.也简称为窗口到视口的变换或窗口变换.

3、屏幕坐标到OPENGL坐标转换

屏幕坐标(象素单位)是通过CView的mousemove捕获得,该坐标值是相对于CChildFrame绘图区的左上角的像素值。其转换的大致过程是:先根据当前屏幕坐标(相对窗口绘图区)找到相对于t视口viewport(也就是DIB位图)所在的坐标位置,然后根据映射到视口(viewport)中的位置和投影体的近裁剪面的四点坐标,求得对应的OPENGL世界坐标系中的坐标值。

4、模型变换:平移,缩放、旋转

模型变换通过图元的几个关键点的变换来实现。

点的变换,是通过点与变换矩阵相乘来实现。

待续。。。。

原创粉丝点击