图形学实验报告 OpenGL中的变换

《计算机图形学基础》

实验6 OpenGL中的变换


一、实验目的及要求

1.理解OpenGL中的各种变换的实现原理;

2.掌握OpenGL中模型视图矩阵的操作方法。

3.掌握OpenGL中投影变换的实现方法。

二、实验环境

主要是软件开发环境 VC 6.0

三、实验内容

1、分子动画示例

2、深度测试示例

四、实验结果

1、分子动画

五、程序代码

1.分子动画

#include <gl/glut.h>

void Initial()

{

      glEnable(GL_DEPTH_TEST);       // 启用深度测试

      glClearColor(1.0f, 1.0f, 1.0f, 1.0f ); //背景为白色

}

void ChangeSize(int w, int h)

{

      if(h == 0)  h = 1;

    glViewport(0, 0, w, h);               // 设置视区尺寸

      glMatrixMode(GL_PROJECTION);    // 指定当前操作投影矩阵堆栈

      glLoadIdentity();                   // 重置投影矩阵

      GLfloat fAspect;

      fAspect = (float)w/(float)h;            // 计算视区的宽高比

      gluPerspective(45.0, fAspect, 1.0, 500.0); // 指定透视投影的观察空间

      glMatrixMode(GL_MODELVIEW);  

      glLoadIdentity();

}

void Display(void)

{

      static float fElect1 = 0.0f;           // 绕原子旋转的角度

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜色和深度缓冲区

      glMatrixMode(GL_MODELVIEW);  // 指定当前操作模型视图矩阵堆栈

      glLoadIdentity();                  // 重置模型视图矩阵

      glTranslatef(0.0f, 0.0f, -250.0f);    //将图形沿z轴负向移动

      glColor3f(1.0f, 0.0f, 0.0f);

      glutSolidSphere(12.0f, 15, 15);      // 绘制红色的原子

      glColor3f(0.0f, 0.0f, 0.0f);

      glPushMatrix();                  // 保存当前的模型视图矩阵

      glRotatef(fElect1, 0.0f, 1.0f, 0.0f);   // 绕y轴旋转一定的角度

      glTranslatef(90.0f, 0.0f, 0.0f);       // 平移一段距离

      glutSolidSphere(6.0f, 15, 15);       // 画出第一个电子

      glPopMatrix();       // 恢复模型视图矩阵

      glPushMatrix();      // 保存当前的模型视图矩阵

      glRotatef(45.0f, 0.0f, 0.0f, 1.0f);     //绕z轴旋转45°

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

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

      glutSolidSphere(6.0f, 15, 15);       // 画出第二个电子

     

      glPopMatrix();        // 恢复模型视图矩阵

      glPushMatrix();       // 保存当前的模型视图矩阵

      glRotatef(-45.0f,0.0f, 0.0f, 1.0f);    //绕z轴旋转-45°

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

      glTranslatef(0.0f, 0.0f, 60.0f);

      glutSolidSphere(6.0f, 15, 15);      // 画出第三个电子

      glPopMatrix();

     

      fElect1 += 10.0f;     // 增加旋转步长,产生动画效果

      if(fElect1 > 360.0f)    fElect1 = 10.0f;

      glutSwapBuffers();

}

void TimerFunc(int value)

{

    glutPostRedisplay();

    glutTimerFunc(100, TimerFunc, 1);

}

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

{

      glutInit(&argc, argv);

      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

      glutCreateWindow("分子动画示例");

      glutReshapeFunc(ChangeSize);

      glutDisplayFunc(Display);

    glutTimerFunc(500, TimerFunc, 1);     //指定定时器回调函数

      Initial();

      glutMainLoop();

      return 0;

}

六、心得体会

    这次的分子动画实验比较有意思,就是对代码的理解性不是很高。而且如果没有代码,就不能做出来这个实验。通过这次的实验有助于学习三维动画设计。

 

第二篇:计算机图形学实验报告

河南理工大学测绘学院

《计算机图形学》实验报告

学号             

 


姓名            

 


成绩              

 


评语:

 

交报告日期:  20##年 6 月 25 日


实验项目一:图形学光栅化算法验证实验

实验日期:2012 年6 月 5日

一、实验目的:

1、加强对直线、圆的光栅化算法的理解。工程中的绘图函数不允许使用微软MFC类库CDC类提供的方法,必须使用图形学教材上的光栅化算法。

2、掌握基本图形系统交互设计方法。

3、熟悉windows程序的基本消息处理。

二、你认为实验中的较好的设计或代码:


void CGIS1002_10View::Breshenham_Line(CPoint pt1, CPoint pt2, CDC * pDC)

{

      int dx,dy,x,y,d,d1,d2,inc,tmp;

      dx=pt2.x - pt1.x ;

      dy=pt2.y - pt1.y;

      CPoint b;

      if(dx * dy>=0)          //准备x,y单位的递变值

             inc = 1;

      else

             inc = -1;

      if(abs(dx)>abs(dy))

      {

             if(dx<0)           //将2a,3a区域的直线变换到1a,4a区域

             {

                    tmp = pt2.x;pt2.x = b.x;b.x = tmp;

                    tmp = pt2.y;pt2.y = b.y;b.y = tmp;

                    dx = -dx;dy=-dy;

             }

         if(dy<0)………………

         dy=-dy;………………

             d = 2*dy - dx;

             d1 = 2*dy;

             d2 = 2*(dy - dx);

             x = pt1.x;

             y = pt1.y;

             pDC->SetPixel(x,y,RGB(0,0,255));

             while(x <  pt2.x)

             {

                    x++;

                    if(d<0)

                           d+=d1;

                    else

                    {

                           y+=inc;

                           d+=d2;

                    }

             pDC->SetPixel(x,y,RGB(0,0,255));

             }

      }

      else

      {

             if(dy<0)           //将3b,4b区域的直线变换到1b,2b区域

             {

                    tmp = pt2.x;pt2.x = b.x;b.x = tmp;

                    tmp = pt2.y;pt2.y = b.y;b.y = tmp;

                    dx = -dx;dy=-dy;

             }

         if(dx<0) ………………

         dx=-dx;……………….

          d = 2*dx - dy;

             d1 = 2*dx;

             d2 = 2*(dx - dy);

             x = pt1.x;

             y = pt1.y;

             pDC->SetPixel(x,y,RGB(0,0,255));

             while(y<  pt2.y)

             {

                    y++;

                    if(d<0)

                           d+=d1;

                    else

                    {

                           x+=inc;

                           d+=d2;

                    }

             pDC->SetPixel(x,y,RGB(0,0,255));

             }

      }

      ReleaseDC(pDC);

}

上述代码为直线的Breshenham画线算法,它是计算机图形学领域使用最广泛的直线生成算法。它的基本原理是:过各行各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。其中的①②③④将直线画线的象限区域范围扩大了,如上图所示。


三、实验总结:

通过本次试验,我发现了这种画线算法的优越性,但是由于对代码本身的不理解以及对类的知识点的遗忘,所以在改书中代码时费了很大功夫。另外,通过本次试验我加强了对直线、圆的光栅化算法的理解,基本掌握了基本图形系统交互设计方法,熟悉了windows程序的基本消息处理,基本完成实验目的。

实验项目二: 基于OpenGL的图形学编程实验

实验日期:2012 年 6 月 13日

一、实验目的:

1、掌握Windows编程环境中的OpenGL程序框架设计和一般的OpenGL绘图环境设置和三维场景绘制步骤。

2、掌握基本的OpenGL API应用函数的使用和参数设置。

二、你认为实验中的较好的设计或代码:

void CGIS1002_10View::ReadTexture()

{

      CString strCurrentPath = ((CGIS1002_10App*)AfxGetApp())->m_pszHelpFilePath;

      strCurrentPath.TrimLeft();

      strCurrentPath.TrimRight();

      int pos = strCurrentPath.ReverseFind('\\');

      strCurrentPath = strCurrentPath.Left(pos-2);

      pos = strCurrentPath.ReverseFind('\\');

      strCurrentPath = strCurrentPath.Left(pos+1);

      CString pszFileName = strCurrentPath+"b.bmp";

      CFile myFile;

      CFileException fileException;

      if ( !myFile.Open( pszFileName, CFile::modeRead, &fileException ) )

      {

             TRACE( "Can't open file %s, error = %u\n",

                pszFileName, fileException.m_cause );

      }

     

      HDIB hdib = ::ReadDIBFile(myFile);

      LPSTR lp = (LPSTR)::GlobalLock(HGLOBAL(hdib));

      imgHeight = ::DIBHeight(lp);

      imgWidth = ::DIBWidth(lp);

      LPSTR lpdibdata=(LPSTR)::FindDIBBits(lp);

      memcpy(texBits,lpdibdata,imgHeight*imgWidth*3);

      ::GlobalUnlock(HGLOBAL(hdib));

      myFile.Close();

}

void CGIS1002_10View::RenderScene()

{

      glPushMatrix();

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

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

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      glTexImage2D(GL_TEXTURE_2D, 0, 3, imgHeight, imgWidth, 0,GL_BGR_EXT,GL_UNSIGNED_BYTE, &(GLubyte)texBits[0][0][0]);

      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    glEnable(GL_TEXTURE_2D);

    glBegin(GL_QUADS);

      glNormal3f( 0.0F, 0.0F, 1.0F);

      glTexCoord2f(1.0,1.0);

    glVertex3f( 0.5F, 0.5F, 0.5F);

      glTexCoord2f(0.0,1.0);

      glVertex3f(-0.5F, 0.5F, 0.5F);

      glTexCoord2f(0.0,0.0);

      glVertex3f(-0.5F,-0.5F, 0.5F);

      glTexCoord2f(1.0,0.0);

      glVertex3f( 0.5F,-0.5F, 0.5F);

      glDisable(GL_TEXTURE_2D);

    glNormal3f( 0.0F, 0.0F,-1.0F);

      glTexCoord2f(1.0,1.0);

    glVertex3f(-0.5F,-0.5F,-0.5F);

      glTexCoord2f(0.0,1.0);

      glVertex3f(-0.5F, 0.5F,-0.5F);

      glTexCoord2f(0.0,0.0);

    glVertex3f( 0.5F, 0.5F,-0.5F);

      glTexCoord2f(1.0,0.0);

      glVertex3f( 0.5F,-0.5F,-0.5F);

      glDisable(GL_TEXTURE_2D);

    glNormal3f( 0.0F, 1.0F, 0.0F);

      glTexCoord2f(1.0,1.0);

    glVertex3f( 0.5F, 0.5F, 0.5F);

      glTexCoord2f(0.0,1.0);

      glVertex3f( 0.5F, 0.5F,-0.5F);

      glTexCoord2f(0.0,0.0);

    glVertex3f(-0.5F, 0.5F,-0.5F);

      glTexCoord2f(1.0,0.0);

      glVertex3f(-0.5F, 0.5F, 0.5F);

      glDisable(GL_TEXTURE_2D);

    glNormal3f( 0.0F,-1.0F, 0.0F);

      glTexCoord2f(1.0,1.0);

    glVertex3f(-0.5F,-0.5F,-0.5F);

      glTexCoord2f(0.0,1.0);

      glVertex3f( 0.5F,-0.5F,-0.5F);

      glTexCoord2f(0.0,0.0);

    glVertex3f( 0.5F,-0.5F, 0.5F);

      glTexCoord2f(1.0,0.0);

      glVertex3f(-0.5F,-0.5F, 0.5F);

      glDisable(GL_TEXTURE_2D);

    glNormal3f( 1.0F, 0.0F, 0.0F);

      glTexCoord2f(1.0,1.0);

    glVertex3f( 0.5F, 0.5F, 0.5F);

      glTexCoord2f(0.0,1.0);

      glVertex3f( 0.5F,-0.5F, 0.5F);

      glTexCoord2f(0.0,0.0);

    glVertex3f( 0.5F,-0.5F,-0.5F);

      glTexCoord2f(1.0,0.0);

      glVertex3f( 0.5F, 0.5F,-0.5F);

      glDisable(GL_TEXTURE_2D);

    glNormal3f(-1.0F, 0.0F, 0.0F);

    glVertex3f(-0.5F,-0.5F,-0.5F);

      glVertex3f(-0.5F,-0.5F, 0.5F);

    glVertex3f(-0.5F, 0.5F, 0.5F);

      glVertex3f(-0.5F, 0.5F,-0.5F);

    glEnd();

      SwapBuffers(m_pDC->GetSafeHdc());

      glPopMatrix();

}

本次实验主要是基于OpenGL的图形学编程实验,上述代码为读纹理函数的代码以及绘场景函数RenderScene()的代码,将代码及图像文件做了稍微的改动,即将图像文件"tail.bmp"改为"b.bmp",则运行结果出现了如下图所示的画面。

三、实验总结:

通过本次的实验,我掌握了Windows编程环境中的OpenGL程序框架设计和一般的OpenGL绘图环境设置和三维场景绘制步骤,并基本了解了基本的OpenGL API应用函数的使用和参数设置,基本完成实验要求。

实验项目三:简单矢量地图系统

实验日期:2012 年 6 月 20  日

一、实验目的:

1、加强矢量数据存储管理和数据结构设计的理解。

2、理解空间数据绘制的用户-视口映射原理,掌握GIS软件视图放大\缩小\漫游操作原理及地图缓存位图绘图刷新的机制。

3、进一步掌握图形交互技术。

二、你认为实验中的较好的设计或代码:

void CGIS1002_10View::InitialCoordPara()

{

      CRect rClient;

      GetClientRect(&rClient);

      double dScaleInX =  double(rClient.Width()-2)/(map.xMax-map.xMin);

      double dScaleInY = double(rClient.Height()-2)/(map.yMax-map.yMin);

      CCoordTranse::scale = dScaleInX<dScaleInY? dScaleInX:dScaleInY;

      CCoordTranse::dx = -map.xMin*CCoordTranse::scale;

      CCoordTranse::dy =  map.yMin*CCoordTranse::scale+rClient.bottom;

      if (CCoordTranse::scale==dScaleInX)

             CCoordTranse::dy += (map.yMax-map.yMin)/2*CCoordTranse::scale-(rClient.Height()-2)/2;

      else if (CCoordTranse::scale==dScaleInY)

             CCoordTranse::dx += (rClient.Width()-2)/2-(map.xMax-map.xMin)/2*CCoordTranse::scale;

}

void CGIS1002_10View::OnDraw(CDC* pDC)

{

      CGIS1002_10Doc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      // TODO: add draw code for native data here

      COLORREF bkColor = RGB(230,230,210);

      CRect rClient;

      GetClientRect(&rClient);

      GetParentFrame()->SetWindowText("中国电子地图");

      CDC* pMemDC = new CDC;

      pMemDC->CreateCompatibleDC(pDC);

      CBitmap* pOldBmp = pMemDC->SelectObject(m_pMapBmp);

      CBrush brush(RGB(253,253,245));

      pMemDC->FillRect(rClient, &brush);

      map.DrawMap(pMemDC,bkColor);

      pDC->BitBlt(0,0,rClient.Width(), rClient.Height(), pMemDC, 0, 0, SRCCOPY);

      pMemDC->SelectObject(pOldBmp);

      delete pMemDC;

}

成员函数InitialCoordPara(),其功能是用于地图坐标变换的参数设置,它较好地把地图坐标转换为屏幕坐标;OnDraw()函数中的代码用于绘制地图;

三、实验总结:

通过本次实验,我加深了对矢量数据存储管理和数据结构设计以及对空间数据绘制的用户-视口映射原理的理解,并掌握了GIS软件视图放大\缩小\漫游操作原理及地图缓存位图绘图刷新的机制,进一步掌握了图形交互技术,基本完成实验要求。

相关推荐