代码分析

简介:
  这是susu给我的一份关于glut的示例代码,里面涉及到的内容有:用glut来完成菜单管理,文本显示,显示列表,材质,光照,多窗口显示,鼠标事件处理,键盘事件处理,菜单事件处理,窗口创建,缩放,销毁,动画播放,定时器等功能,运行效果如图:

200782201.jpg
      我分成几个部分来对代码进行分析:

1,命令行参数检查

void checkArgs(int argc, char *argv[])
{
  int argp;
  GLboolean quit = GL_FALSE;
  GLboolean error = GL_FALSE;
#define AA argv[argp]
  argp = 1;
  while (argp < argc)
  {
    if (match(AA, "-help"))
    {
      commandLineHelp();
      quit = GL_TRUE;
    } 
    else if (match(AA, "-version"))
    {
      printf(VERSIONLONG "\n");
      quit = GL_TRUE;
    } 
    else if (match(AA, "-auto"))
    {//自动运行
      demoMode = GL_TRUE;
    } 
    else if (match(AA, "-scale"))
    {//放缩
      argp++;
      scaleFactor = atof(argv[argp]);//设置缩放因子
    } 
    else 
    {//出错处理
      fprintf(stderr, "Unknown arg: %s\n", AA);
      error = GL_TRUE;
      quit = GL_TRUE;
    }
    argp++;
  }
GLboolean match(char *arg, char *t)
{
  if (strstr(t, arg))
    return GL_TRUE;
  else
    return GL_FALSE;
}
  if (error) 
  {
    commandLineHelp();
    exit(1);
  }
  if (quit)
    exit(0);
}
这里match函数考虑到-help可能被输入为-h等形式,因此用的是strstr而不是strcmp来进行字符串的匹配。

2,窗口的缩放

通过对窗口原点和大小的调整就可以实现窗口的缩放。

int pos[MAXWIN][2] =
{//各个窗口的左上角坐标
  {50, 150},            /* win 0  */
  {450, 150},           /* win 1  */
  {50, 600},            /* win 2  */
  {450, 600},           /* win 3  */
  {10, 10},             /* subwin 4 (relative to parent win 0) */
  {300, 400},           /* help win 5  */
  {850, 150},           /* cmap win 6  */
  {850, 600},           /* cmap win 7  */
  {250, 450}            /* text win 8  */
};
int size[MAXWIN][2] =
{//各个窗口大小(宽度,高度)
  {350, 350},           /* win 0  */
  {350, 350},           /* win 1  */
  {350, 350},           /* win 2  */
  {350, 350},           /* win 3  */
  {200, 200},           /* subwin 4  */
  {700, 300},           /* help win 5  */
  {350, 350},           /* cmap win 6  */
  {350, 350},           /* cmap win 7  */
  {800, 450}            /* text win 8  */
};
void scaleWindows(float scale)
{//放缩初始窗口大小和位置 
  int i;
  for (i = 0; i < MAXWIN; i++)
  {
    pos[i][0] = pos[i][0] * scale;//x坐标
    pos[i][1] = pos[i][1] * scale;//y坐标
    size[i][0] = size[i][0] * scale;//宽度
    size[i][1] = size[i][1] * scale;//高度
  }
}
3,设置显示模式、

Int型的数组modes用来记录各个模式位的值(0或者1),从而表明窗口是否支持这种模式。displayMode |= glutMode[i];通过这样的按位或运算最终获得窗口的显示模式。

int modes[MODES] ={0};
modes[RGBA] = 1;
  modes[DOUBLEBUFFER] = 1;
  modes[DEPTH] = 1;
  setInitDisplayMode()
void setInitDisplayMode(void)
{//设置初始显示模式
  int i;
  displayMode = 0;
  for (i = 0; i < MODES; i++) {
    if (modes[i]) {
      /* printf("Requesting %s \n", modeNames[i]);  */
      displayMode |= glutMode[i];//进行按位或运行,
    }
  }
  glutInitDisplayMode(displayMode);
  createMenu6();
  if (!glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
    warning("This display mode not supported\n");
}
4,菜单管理

menu1到menu8这8个int型变量用来保存创建的菜单项,并且menu2到menu8都作为menu1的子菜单加入到menu1中。

创建菜单
5,创建窗口

本文中创建的窗口有4种类型,第1种是普通的RGB窗口,用来显示要绘制的图形,第2种是第1种窗口的子窗口(类似于“画中画”的效果),第3种是文本窗口和帮助窗口,第4种是颜色索引窗口。设置好窗口的显示模式,并根据保存的窗口大小和位置创建完窗口后,就可以对窗口进行OpenGL绘制的初始化工作,这是在gfxInit函数中完成的,最后就是为窗口加上各种事件处理函数。

创建窗口
为每个窗口初始化OpenGL时,首先通过redefineShapes为窗口建立其显示列表,然后渲染其背景矩阵,接着进行投影变换和视图变换,为了简单起见,作者采用了默认的白色光源来进行材质和光源位置的设置,最后就是启用光照并设置窗口的背景颜色。

OpenGL初始化
6,动画效果

我在MFC中是通过设置一个定时器,并且在定时方法中修改旋转角度来刷新屏幕的,从而实现动画旋转的效果,在这里作者把这部分代码放到窗口的空闲事件处理函数中进行。每次执行时角度都进行了变换,并且通知窗口强制其重绘。

/* idleFunc - GLUT idle func callback - animates windows */
void idleFunc(void)
{
  int i;
  if (!leftDown && !middleDown)//旋转角度加1
    angle += 1;
    angle = angle % 360;
  for (i = 0; i < MAXWIN; i++)
  {
    if (winId[i] && winVis[i] && !winFreeze[i]) 
    {
      glutSetWindow(winId[i]);
      glutPostRedisplay();//强制重画
    }
  }
}

7,自动演示

这里采用了一个小的技巧来实现多个窗口连续创建的自动演示功能。通过执行当前的动作后,为下一个应该接着发生的动作设置一个定时器,从而实现动作之间的接连发送效果。

旋转动画
8,图形绘制代码部分

所有窗口都使用drawScene来绘制其图形,只是各个窗口调用的显示列表不同而已,这通过各个窗口的标识符来进行区别,并且通过调用trackBall(APPLY, 0, 0, 0, 0);来绘制鼠标左键控制的结果(旋转后的角度或者平移后的距离),如果窗口还有文本要显示,则调用showText来显示文本信息。

图形绘制代码
9.文本显示

这里有两种文本的显示方式,第一种采用位图字体来显示文本,第二种采用Stroke 字体来显示文本。

void textString(int x, int y, char *msg, void *font)
{//显示文本,x,y是起始坐标,msg:要显示的文本,font:显示的字体
  glRasterPos2f(x, y);//定位位图字体
  while (*msg)
  {
    glutBitmapCharacter(font, *msg);
    msg++;
  }
}

/* strokeString - Stroke font string */
void strokeString(int x, int y, char *msg, void *font)
{
  glPushMatrix();
  glTranslatef(x, y, 0);
  glScalef(.04, .04, .04);
  while (*msg) 
  {
    glutStrokeCharacter(font, *msg);
    msg++;
  }
  glPopMatrix();
}
10,显示列表

显示列表由于是已经编译好的代码段,因此可以加快程序的速度。这里每种要绘制的图形(如球,茶壶等)都有实体和虚体两种模式可以选择。

显示列表
11,鼠标事件处理

这里鼠标有三种控制方式,1)左键进行旋转。2)中键进行xy平面的平移。3)左键+中键进行关于Z轴的平移(产生缩放的效果)。鼠标的事件模式这里有RESET,MOUSEBUTTON,APPLY, MOUSEMOTION四种,其中RESET是用来对清空以往的操作,让图形回到原点处。MOUSEBUTTON是鼠标按下激发的,用来记录下鼠标的位置,MOUSEMOTION是鼠标按下后并移动鼠标时,用来计算旋转的角度或者平移的距离,而最终这些变换后产生的效果的绘制是APPLY发生的,在这里进行了实际的旋转和平移动作。

鼠标控制
最后,代码中还加入了对空间球,图形板,拨号按键盒的事件处理支持。




本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2007/08/22/865803.html,如需转载请自行联系原作者
目录
相关文章
|
IDE 开发工具 Android开发
Kotlin 的静态代码分析工具
Kotlin 的静态代码分析工具
201 0
|
5月前
|
安全 算法 测试技术
静态代码分析的这些好处,我竟然都不知道?
软件开发中,单元测试确保模块功能,但静态代码分析是质量保证的关键。静态分析检查代码结构,发现潜在错误,补充单元测试的不足。虽然静态分析工具不能替代人工验证,它们在识别复杂逻辑错误和提升代码质量方面至关重要。结合单元测试和静态分析能提高代码安全性与整体质量,减少后期问题,降低成本。SonarQube等工具简化了静态分析过程,强调早期错误检测的重要性。
|
6月前
|
安全 JavaScript 前端开发
提高代码质量,从静态代码分析开始
每个开发者都应该明白代码质量的重要性,因为良好的代码质量可以确保项目的可维护性、稳定性和可扩展性。而静态代码分析工具 SonarQube 可以帮助开发者提高代码质量,同时也可以简化代码审查和测试流程。本文将介绍 SonarQube 的概念和用法,以及如何将其应用于实践中,提高代码质量。
|
6月前
|
安全 数据可视化 Oracle
提高代码质量,从静态代码分析工具SonarQube开始
在软件开发过程中,代码质量是至关重要的。而静态代码分析工具SonarQube可以帮助开发人员有效地管理代码质量。本文将介绍SonarQube的概念和实践,以及如何使用它来提高代码质量。
336 1
|
6月前
|
存储 RDMA 内存技术
nvmf代码分析
nvmf代码分析
|
IDE Java 程序员
什么是代码调试(debugging)?进行代码调试的基本方法有哪些?
什么是代码调试(debugging)?进行代码调试的基本方法有哪些?
711 0
什么是代码调试(debugging)?进行代码调试的基本方法有哪些?
|
PHP
什么?你还不会断点调试代码
什么?你还不会断点调试代码
112 0
什么?你还不会断点调试代码
|
计算机视觉 异构计算
对Any_percision的代码分析
首先是数据集的选择:cifar10, imagenet,svnh 网络的选择:resent20q
77 0
|
PHP
什么?你还不会断点调试代码(2)
什么?你还不会断点调试代码
104 0
什么?你还不会断点调试代码(2)
|
Android开发
配置Android项目 - 静态代码分析工具(二)
配置Android项目 - 静态代码分析工具(二)
187 0
配置Android项目 - 静态代码分析工具(二)