在本次的工程实践中,个人题目是《基于opengl的车载虚拟仪表软件开发》,是一项校企合做的项目,在项目中之前作过的学长也向咱们分享了以往作过的相关的项目的源代码,代码主要是由c语言写出,经过调用opengl的api接口规范来实现的图像旋转,拉伸,平移等操做,源代码以下 :编程
#include "config.h"
#include "main.h"
#include "./lib/lib_opengl.h"
#include "./font.h"
#include "./resource.h"api
#ifdef DEBUG_LOCATION
#undef DEBUG_LOCATION
#endif
#define DEBUG_LOCATION "MAIN"数组
pthread_t taskTimer;
extern void *threadTimer(void);缓存
int main(int argc, char* argv[])
{
float rotate = 0;
FT_ULong strW[10] = {0};
u32 delay = 0;
InitGL();
initFont();
initResource();
loadImage(IDIMG_BG);服务器
enableGlStatus();网络
//多线程
//pthread_create(&taskTimer, NULL, threadTimer, NULL)多线程
while(1)
{
delay++;
if(delay > 1000)
{
if(rotate < 9.0)
rotate += 1.0;
else
rotate = 0; 编程语言
delay = 0;编辑器
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 255.0f);
#if 0
glPushMatrix();
//themeHandle();函数
glTranslatef(960, 360, 0);
glDisable(GL_TEXTURE_2D);
glRotatef(45, 1, 0, 0);
glRotatef( rotate, 0, 1, 0);
//glVertexPointer(3, GL_FLOAT, 0, vertices);
glColor4f(255, 0, 0, 255);
static GLfloat front[] = { SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX,SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX,-SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX,-SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX,};
glVertexPointer(3, GL_FLOAT, 0, front);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glColor4f(0, 255, 0, 255);
static GLfloat back[] = { -SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX,-SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX,SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX,SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX,};
glVertexPointer(3, GL_FLOAT, 0, back);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glColor4f(0, 0, 255, 255);
static GLfloat top[] = {SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX,-SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX,};
glVertexPointer(3, GL_FLOAT, 0, top);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glColor4f(255, 255, 0, 255);
static GLfloat bottom[] = { -SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX,-SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX,SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX,SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX, };
glVertexPointer(3, GL_FLOAT, 0, bottom);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glColor4f(0, 255, 255, 255);
static GLfloat left[] = {-SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX,-SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX,};
glVertexPointer(3, GL_FLOAT, 0, left);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glColor4f(255, 0, 255, 255);
static GLfloat right[] = {SIZE_OF_BOX, -SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX, -SIZE_OF_BOX,SIZE_OF_BOX, -SIZE_OF_BOX, SIZE_OF_BOX,SIZE_OF_BOX, SIZE_OF_BOX, SIZE_OF_BOX,};
glVertexPointer(3, GL_FLOAT, 0, right);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glPopMatrix();
#endif
glPushMatrix();
glEnable(GL_TEXTURE_2D);
drawImage(IDIMG_BG, 0, 0);
setFontColor(255, 255, 255, 255);
memset(strW, 0, sizeof(strW));
sprintl(strW, "%.0f", rotate);
drawFont(FONT_GEELY, 100, 100, 32, strW);
memset(strW, 0, sizeof(strW));
sprintl(strW, "%.0f", 9.0 - rotate);
drawFont(FONT_GEELY, 100, 150, 32, strW);
setFontColor(255, 255, 255, 255);
glPopMatrix();
swapBuffers();
}
}
return 0;
}
目录结构中包括了主函数的.c和.h文件,此外还写了一些函数和方法,和.h文件做为头文件,有一个lib文件夹用于放一些opengl所须要的库,这些都构成了这个程序可以正确运行的基础。
文件名主要突出了各个部件的功能,是按实际的效果命名的,好比像上图中的Layout_AnimyPlane.c文件主要就是负责界面的布局显示的效果,readme主要是这套代码的介绍;
类名中主要是调用了opengl库中的一些经常使用的类以下:
函数名中 glClear主要用于清除指定的缓存数据并重设为当前的清除值。mask是一个能够经过逻辑或操做来指定多个数值的参数;
glClearClolor用于设置当前使用的清除颜色值,用于RGBA模式下对颜色缓存的清除工做。这里的red,green,blue,alpha都会被截断到【0,1】的范围内。默认的清除颜色是(0,0,0,0)表示黑色。
glPushMatrix();glPushMatrix、glPopMatrix操做其实就至关于栈里的入栈和出栈。
OpenGL是Open Graphics Library(开放性图形库)的缩写,是一套三维图形处理库,也是该领域的工业标准。计算机三维图形是指将用数据描述的三维空间经过计算转换成二维图像并显示或打印出来的技术。
OpenGL就是支持这种转换的程序库,它源于SGI公司为其图形工做站开发的IRIS GL,在跨平台移植过程当中发展成为OpenGL。SGI在1992年7月发布1.0版,后成为工业标准,由成立于1992年的独立财团OpenGL Architecture Review Board (ARB)控制。SGI等ARB成员以投票方式产生标准,并制成规范文档(Specification)公布,各软硬件厂商据此开发本身系统上的实现。只有经过了ARB规范所有测试的实现才能称为OpenGL。1995年12月ARB批准了1.1版本,最新版规范是1999.5经过的1.2.1。
OpenGL被设计成独立于硬件,独立于窗口系统的,在运行各类操做系统的各类计算机上均可用,并能在网络环境下以客户/服务器模式工做,是专业图形处理、科学计算等高端应用领域的标准图形库。它低端应用上的主要竞争对手是MS-Direct3D,该图形库是以COM接口形式提供的,因此极为较复杂,稳定性差,另外微软公司拥有该库版权,目前只在Windows平台上可用。D3D的优点在速度上,但如今低价显卡都能提供很好的OpenGL硬件加速,因此作3D使用Direct3D已没有特别的必要,在专业图形处理特别是高端应用方面目前尚未出现以Direct3D技术为基础的例子,而游戏等低端应用也有转向OpenGL的趋势。
微软在Windows NT对OpenGL的支持始于3.51,在Windows9x中的支持始于Win95 OEM Service Release 2。Windows下经常使用的OpenGL库有两种,MS实现的和SGI实现的,MS-OpenGL调用会自动检测是否存在显示卡制造商提供的ICD(Installable Client DeviceDriver)驱动程序,有则调用ICD中的例程,不然才用CPU进行计算,因此能利用显示卡的OpenGL加速能力。对开发者来讲使用方法并无区别,只是有ICD驱动时更快些。SGI的版本是纯软件实现不能利用硬件加速而且SGI已经在1999年宣布中止支持,但这套库便于调试程序,仍有很多开发者使用。
SGI曾经宣布研发OpenGL++,该图形库最大的特色是面象对象,提供了树形场景支持,大大减省了使用OpenGL处理复杂场景的工做量。后来(1999)SGI宣布与M$合做开发Ferihant,即Windows的下一代图形处理体系,包括DirectX与OpenGL的低级图形处理接口和以场景图支持为特色的高级接口,而且就此中止对其在Windows下的OpenGL实现的支持以示决心。此举世瞩目,你们都觉得Windows图形处理快要过上幸福生活了,然而,不久,SGI宣布停止合做,并撤回派出的科学家,Ferihant基本上夭折。SGI 称终止合做的缘由是M$不愿积极合做,光想把SGI 的技术合并进DirectX,真正内幕不详。不过以SGI在图形处理界的老大地位来讲,仍是有几分可信度的,由于M$初支持OpenGL就不积极。
OpenGL的特色
1.硬件无关的软件接口
能够在不一样的平台如Windows 9五、Windows NT、Unix、Linux、MacOS、OS/2之间进行移植。所以,支持OpenGL的软件具备很好的移植性,能够得到很是普遍的应用。
2.能够在客户机/服务器系统中工做,即具备网络功能。
这一点对于制做大型3D图形、动画很是有用。例如,《玩具总动员》、《泰坦尼克号》等电影的电脑特技画面就是经过应用OpenGL的网络功能,使120多台图形工做站共同工做来完成的。
因为OpenGL是与硬件无关的3D图形接口,在 Windows、Unix/X-Windows、 MacOS、OS/2等不一样版本的窗口相关部分(系统相关)略有差别。因为OpenGL是3D图形的底层图形库,没有提供几何实体图元,不能直接用以描述场景。可是,经过一些转换程序,能够很方便地将AutoCAD、3DS等3D图形设计软件制做的DFX和3DS模型文件转换成OpenGL的顶点数组。
另外,在OpenGL的基础上还有Open Inventor、Cosmo3D、Optimizer等多种高级图形库,适应不一样应用。其中,Open Inventor应用最为普遍。该软件是基于OpenGL面向对象的工具包,提供建立交互式3D图形应用程序的对象和方法,提供了预约义的对象和用于交互的事件处理模块,建立和编辑3D场景的高级应用程序单元,有打印对象和用其它图形格式交换数据的能力。
1 文件结构
1.1 头文件和定义文件的名称是否合理?
1.2 头文件和定义文件的目录结构是否合理?
1.3 版权和版本声明是否完整?
1.4 头文件是否使用了 ifndef/define/endif 预处理块?
1.5 头文件中是否只存放“声明”而不存放“定义”?
2 程序的版式
2.1 空行是否得体?
2.2 代码行内的空格是否得体?
2.3 长行拆分是否得体?
2.4 “{” 和 “}” 是否各占一行而且对齐于同一列?
2.5 一行代码是否只作一件事?如只定义一个变量,只写一条语句。
2.6 If、for、while、do 等语句自占一行,不论执行语句多少都要加“{}”。
2.7 在定义变量(或参数)时,是否将修饰符 * 和 & 紧靠变量名?
2.8 注释是否清晰而且必要?
2.9 注释是否有错误或者可能致使误解?
2.10 类结构的 public, protected, private 顺序是否在全部的程序中保持一致?
3 命名规则
3.1 命名规则是否与所采用的操做系统或开发工具的风格保持一致?
3.2 标识符是否直观且能够拼读?
3.3 标识符的长度应当符合“min-length && max-information”原则?
3.4 程序中是否出现相同的局部变量和所有变量?
3.5 类名、函数名、变量和参数、常量的书写格式是否遵循必定的规则?
3.6 静态变量、全局变量、类的成员变量是否加前缀?
4 表达式与基本语句
4.1 若是代码行中的运算符比较多,是否已经用括号清楚地肯定表达式的操做顺序?
4.2 是否编写太复杂或者多用途的复合表达式?
4.3 是否将复合表达式与“真正的数学表达式”混淆?
4.4 是否用隐含错误的方式写 if 语句? 例如
(1) 将布尔变量直接与 TRUE、FALSE 或者 一、0 进行比较。
(2) 将浮点变量用“==”或“!=”与任何数字比较。
(3) 将指针变量用“==”或“!=”与 NULL 比较。
4.5 若是循环体内存在逻辑判断,而且循环次数很大,是否已经将逻辑判断移到循环体的外面?
4.6 Case 语句的结尾是否忘了加break?
4.7 是否忘记写 switch 的 default 分支?
4.8 使用 goto 语句时是否留下隐患? 例如跳过了某些对象的构造、变量的初始化、重要的计算等。
5 常量
5.1 是否使用含义直观的常量来表示那些将在程序中屡次出现的数字或字符串?
5.2 在 C++ 程序中,是否用const 常量取代宏常量?
5.3 若是某一常量与其它常量密切相关,是否在定义中包含了这种关系?
5.4 是否误解了类中的const 数据成员?由于const 数据成员只在某个对象生存期内是常量,而对于整个类而言倒是可变的。
6 函数设计
6.1 参数的书写是否完整?不要贪图省事只写参数的类型而省略参数名字。
6.2 参数命名、顺序是否合理?
6.3 参数的个数是否太多?
6.4 是否使用类型和数目不肯定的参数?
6.5 是否省略了函数返回值的类型?
6.6 函数名字与返回值类型在语义上是否冲突?
6.7 是否将正常值和错误标志混在一块儿返回?正常值应当用输出参数得到,而错误标志用 return 语句返回。
6.8 在函数体的“入口处”,是否用 assert 对参数的有效性进行检查?
6.9 使用滥用了 assert? 例如混淆非法状况与错误状况,后者是必然存在的而且是必定要做出处理的。
6.10 return 语句是否返回指向“栈内存”的“指针”或者“引 用”?
6.11 是否使用const 提升函数的健壮性?const 能够强制保护函数的参数、返回值,甚至函数的定义体。“Use const whenever you need”
7 内存管理
7.1 用 malloc 或 new 申请内存以后,是否当即检查指针值是否为 NULL?(防止使用指针值为 NULL 的内存)
7.2 是否忘记为数组和动态内存赋初值?(防止将未被初始化的内存做为右值使用)
7.3 数组或指针的下标是否越界?
7.4 动态内存的申请与释放是否配对?(防止内存泄漏)
7.5 是否有效地处理了“内存耗尽”问题?
7.6 是否修改“指向常量的指针”的内容?
7.7 是否出现野指针?例如
I 指针变量没有被初始化。
II 用 free 或delete 释放了内存以后,忘记将指针设置为 NULL。
7.8 是否将 malloc/free 和 new/delete 混淆使用?
7.9 malloc 语句是否正确无误?例如字节数是否正确?类型转换是否正确?
7.10 在建立与释放动态对象数组时,new/delete 的语句是否正确无误?
8 C++ 函数的高级特性
8.1 重载函数是否有二义性?
8.2 是否混淆了成员函数的重载、覆盖与隐藏?
8.3 运算符的重载是否符合制定的编程规范?
8.4 是否滥用内联函数?例如函数体内的代码比较长,函数体内出现循环。
8.5 是否用内联函数取代了宏代码?
9 类的构造函数、析构函数和赋值函数
9.1 是否违背编程规范而让 C++ 编译器自动为类产生四个缺省的函数:
(1)缺省的无参数构造函数;
(2)缺省的拷贝构造函数;
(3)缺省的析构函数;
(4)缺省的赋值函数。
9.2 构造函数中是否遗漏了某些初始化工做?
9.3 是否正确地使用构造函数的初始化表?
9.4 析构函数中是否遗漏了某些清除工做?
9.5 是否错写、错用了拷贝构造函数和赋值函数?
9.6 赋值函数通常分四个步骤:
(1)检查自赋值;
(2)释放原有内存资源;
(3)分配新的内存资源,并复制内容;
(4)返回 *this。是否遗漏了重要步骤?
9.7 是否正确地编写了派生类的构造函数、析构函数、赋值函数?注意事项:
I 派生类不可能继承基类的构造函数、析构函数、赋值函数。
II 派生类的构造函数应在其初始化表里调用基类的构造函数。
III 基类与派生类的析构函数应该为虚(即加 virtual 关键字)。
IV 在编写派生类的赋值函数时,注意不要忘记对基类的数据成员从新赋值。
10 类的高级特性
是否违背了继承和组合的规则?
I 若在逻辑上 B 是 A 的“一种”,而且 A 的全部功能和属性对B 而言都有意义,则容许B 继承A 的功能和属性。
II 若在逻辑上 A 是 B 的“一部分”(a part of),则不容许 B 从A 派生,而是要用A 和其它东西组合出 B。
11 其它常见问题
11.1 数据类型问题:
(1)变量的数据类型有错误吗?
(2)存在不一样数据类型的赋值吗?
(3)存在不一样数据类型的比较吗?
11.2 变量值问题:
(1)变量的初始化或缺省值有错误吗?
(2)变量发生上溢或下溢吗?
(3)变量的精度够吗?
11.3 逻辑判断问题:
(1)因为精度缘由致使比较无效吗?
(2)表达式中的优先级有误吗?
(3)逻辑判断结果颠倒吗?
11.4 循环问题:
(1)循环终止条件不正确吗?
(2)没法正常终止(死循环)吗?
(3)错误地修改循环变量吗?
(4)存在偏差累积吗?
11.5 错误处理问题:
(1)忘记进行错误处理吗?
(2)错误处理程序块一直没有机会被运行?
(3)错误处理程序块自己就有毛病吗?如报告的错误与实际错误不一致,处理方式不正确等等。
(4)错误处理程序块是“马后炮”吗?如在被它被调用以前软件已经出错。
11.6 文件 I/O 问题:
(1)对不存在的或者错误的文件进行操做吗?(2)文件以不正确的方式打开吗?(3)文件结束判断不正确吗?(4)没有正确地关闭文件吗?