题外话

  随着学习的增长,越来越觉得自己很水.关于上一篇博文中推荐用一个 学习opengl的 基于VS2015的 simplec框架.存在

一些问题.

   1.这个框架基于VS 的Debug 模式下,没有考虑Release版本

   2.这个版本中chead,c基础头文件中有些宏设计的不好,例如

//4.0 控制台打印错误信息
#ifndef CERR
#define CERR(fmt,...) \
fprintf(stderr,fmt,##__VA_ARGS__),putchar('\n')
#endif/* !CERR */ //4.1 控制台打印错误信息并退出
#ifndef ERR_EXIT
#define ERR_EXIT(fmt,...) \
CERR(fmt,##__VA_ARGS__),exit(EXIT_FAILURE)
#endif/* !ERR */

    更加合理的是

//错误打印宏
#define CERR_EXIT(fmt,...) \
 fprintf(stderr,"[%s:%d]", __FILE__, __LINE__), fprintf(stderr, fmt, ##__VA_ARGS__), fputs("\r\n",stderr)

    这里的辅助宏需要重新设计

    3.原先的sc_log 模块,简单的日志记录系统.适用于单用户多线程模式.随着项目的增加,需要支持多用户.需要重构,让其具备海量多用户日志记录能力

   4.需要添加一个Session模块,适用多用户

    5.内部有些模块需要重构,用树结构替代链表结构,提高查找速率.

以上这些就是推荐学习opengl 使用 simplec框架目前不爽的地方.争取下一个版本全部搞好.加班太多了,真不想......

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

分享一个程序员伤感的故事

  有一天晚上,两个程序员吃完饭,碰见了不该碰见的人.发现自己都是备胎,

互相安慰说.

    还是上去写写代码压压惊吧.哈哈

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

正题

本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念。

一、点、直线和多边形
我们知道数学(具体的说,是几何学)中有点、直线和多边形的概念,但这些概念在计算机中会有所不同。
数学上的点,只有位置,没有大小。但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点。另一方面,无论图形输出设备(例如,显示器)如何精确,始终不能输出一个无穷小的点。一般情况下,OpenGL中的点将被画成单个的像素(像素的概念,请自己搜索之~),虽然它可能足够小,但并不会是无穷小。同一像素上,OpenGL可以绘制许多坐标只有稍微不同的点,但该像素的具体颜色将取决于OpenGL的实现。当然,过度的注意细节就是钻牛角尖,我们大可不必花费过多的精力去研究“多个点如何画到同一像素上”。
同样的,数学上的直线没有宽度,但OpenGL的直线则是有宽度的。同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
多边形是由多条线段首尾相连而形成的闭合区域。OpenGL规定,一个多边形必须是一个“凸多边形”(其定义为:多边形内任意两点所确定的线段都在多边形内,由此也可以推导出,凸多边形不能是空心的)。多边形可以由其边的端点(这里可称为顶点)来确定。(注意:如果使用的多边形不是凸多边形,则最后输出的效果是未定义的——OpenGL为了效率,放宽了检查,这可能导致显示错误。要避免这个错误,尽量使用三角形,因为三角形都是凸多边形)

可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个“曲面”。

二、在OpenGL中指定顶点
由以上的讨论可以知道,“点”是一切的基础。
如何指定一个点呢?OpenGL提供了一系列函数。它们都以glVertex开头,后面跟一个数字和1~2个字母。例如:
glVertex2d
glVertex2f
glVertex3f
glVertex3fv
等等。
数字表示参数的个数,2表示有两个参数,3表示三个,4表示四个(我知道有点罗嗦~)。
字母表示参数的类型,s表示16位整数(OpenGL中将这个类型定义为GLshort),
                   i表示32位整数(OpenGL中将这个类型定义为GLint和GLsizei),
                   f表示32位浮点数(OpenGL中将这个类型定义为GLfloat和GLclampf),
                   d表示64位浮点数(OpenGL中将这个类型定义为GLdouble和GLclampd)。
                   v表示传递的几个参数将使用指针的方式,见下面的例子。
这些函数除了参数的类型和个数不同以外,功能是相同的。例如,以下五个代码段的功能是等效的:
(一)glVertex2i(1, 3);
(二)glVertex2f(1.0f, 3.0f);
(三)glVertex3f(1.0f, 3.0f, 0.0f);
(四)glVertex4f(1.0f, 3.0f, 0.0f, 1.0f);
(五)GLfloat VertexArr3[] = {1.0f, 3.0f, 0.0f};
      glVertex3fv(VertexArr3);
以后我们将用glVertex*来表示这一系列函数。
注意:OpenGL的很多函数都是采用这样的形式,一个相同的前缀再加上参数说明标记,这一点会随着学习的深入而有更多的体会。

这里扩展一下,在现在的编译器中,能够识别 5.f 相当于 5.0f. 这些技巧推荐用也推荐不用.看人吧. 例如 有时写代码觉得 C99/C11 风格好,

有时还是觉得C89的风格最稳妥.

举例如下:

//C89
int hoge;
int piyo; hoge = 16;
piyo = 1;
printf("hoge = %d, piyo = %d\n",hoge,piyo); //C99 / C11 int hoge = 13;
printf("hoge = %d.\n",hoge);
int piyo = 5;
printf("heoo piyo is %d.\n",piyo);

继续回到正题

三、开始绘制
假设现在我已经指定了若干顶点,那么OpenGL是如何知道我想拿这些顶点来干什么呢?是一个一个的画出来,还是连成线?或者构成一个多边形?或者做其它什么事情?
为了解决这一问题,OpenGL要求:指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略)。并由glBegin来指明如何使用这些点。
例如我写:
glBegin(GL_POINTS);
     glVertex2f(0.0f, 0.0f);
     glVertex2f(0.5f, 0.0f);
glEnd();
则这两个点将分别被画出来。如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。
我们还可以指定更多的顶点,然后画出更复杂的图形。
另一方面,glBegin支持的方式除了GL_POINTS和GL_LINES,还有GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN等.

这里简单对上面两个函数总结如下:

函数原型:
void glBegin(GLenum mode);
void glEnd(void);
参数说明:
  mode:创建图元的类型。可以是以下数值
  GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制N个点
  GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段
  GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制n-1条线段
  GL_LINE_LOOP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,总共绘制n条线段
  GL_TRIANGLES:把每个顶点作为一个独立的三角形,顶点3n-2、3n-1和3n定义了第n个三角形,总共绘制N/3个三角形
  GL_TRIANGLE_STRIP:绘制一组相连的三角形,对于奇数n,顶点n、n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1、n和n+2定义了第n个三角形,总共绘制N-2个三角形
  GL_TRIANGLE_FAN:绘制一组相连的三角形,三角形是由第一个顶点及其后给定的顶点确定,顶点1、n+1和n+2定义了第n个三角形,总共绘制N-2个三角形
  GL_QUADS:绘制由四个顶点组成的一组单独的四边形。顶点4n-3、4n-2、4n-1和4n定义了第n个四边形。总共绘制N/4个四边形
  GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1、2n、2n+2和2n+1定义了第n个四边形,总共绘制N/2-1个四边形
  GL_POLYGON:绘制一个凸多边形。顶点1到n定义了这个多边形。

我并不准备在glBegin的各种方式上大作文章。大家可以自己尝试改变glBegin的方式和顶点的位置,生成一些有趣的图案。
程序代码:

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin( /* 在这里填上你所希望的模式 */ );
/* 在这里使用glVertex*系列函数 */
/* 指定你所希望的顶点位置 */
glEnd();
glFlush();
}

把这段代码改成你喜欢的样子,然后用它替换第一课中的myDisplay函数,编译后即可运行。

下面 我举三个例子

先画一个 圆,思路是打点,按照 圆的参数方程(r*cos t , r*sin t) ,t 属于[0,2*Pi]

代码如下:

#include <glut.h>
#define _USE_MATH_DEFINES //开启 math.h中默认的常量宏
#include <math.h> //绘制圆的顶点数
#define _INT_N (20)
/*
*这里绘制 一个圆
*/
static void display(void)
{
int i;
GLdouble r = 0.5; glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON);
for (i = ;i < _INT_N;++i) {
double p = * M_PI * i / _INT_N;
glVertex2d(r*cos(p),r*sin(p)); //打点连线
}
glEnd(); glFlush();
} int main(int argc, char *argv[])
{
glutInit(&argc,argv); //glut 初始化 为 rgb颜色模式,单缓冲
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //glut窗体创建
glutInitWindowSize(, );
glutInitWindowPosition(,);
glutCreateWindow("这里测试圆的绘制");

   // 设置绘制函数
    glutDisplayFunc(display);
//glut窗体主循环
glutMainLoop(); return ;
}

按照上面代码敲一遍,基本都明白了.这里再说一些废话,前提你需要搭好环境.搭环境完成后学习就已经完成了1/3

学习编程技术 目前 总结 如下

    前线作战 => 搭环境 hello world + 学习基础api + 项目 => 可以进入战斗模式了

后线指挥 => 设计理念 + 抗压和应急解决问题的实力 => 领跑者

第二个例子是画一个五角星

实例图如下:

画这个 五角星 需要 你自己计算各个点的位置,需要初中几何知识. 代码参照如下:

#include <glut.h>
#define _USE_MATH_DEFINES //开启 math.h中默认的常量宏
#include <math.h> //绘制圆的顶点数
#define _INT_N (20) //将角度值转成弧度数
#define TO_F_PII(d) \
(d*(float)M_PI/) /*
*这里绘制 一个五角星
*/
static void display(void)
{
//5x = 360 => x = 72度, x/2 = 36度 数学是不将中国道理的
GLfloat a = 0.5f;//默认比例是一半 当前屏幕 opengl坐标系 以屏幕中央为(0,0)
//计算 纵坐标 从上 到下 为 a , a*cos(72度) , -a*cos(36度)
//计算的横坐标 从左到右 为 -a*sin(72度) , -a*sin(36度), 0, a*sin(36度) , a*sin(72度) //A,B,C,D,E 坐标 依次 如下,需要 你自己计算 三角函数
GLfloat pii72 = TO_F_PII(.f);
GLfloat pii36 = TO_F_PII(.f);
GLfloat
pointA[] = { -a*sinf(pii72), a*cosf(pii72) },
pointB[] = { .f , a },
pointC[] = { a*sinf(pii72) , a*cosf(pii72) },
pointD[] = { a*sinf(pii36) , -a*cosf(pii36) },
pointE[] = { -a*sinf(pii36) , -a*cosf(pii36) }; glClear(GL_COLOR_BUFFER_BIT); //从 A->C->E->B->D->A 顺序一笔画成
glBegin(GL_LINE_LOOP); glVertex2fv(pointA);
glVertex2fv(pointC);
glVertex2fv(pointE);
glVertex2fv(pointB);
glVertex2fv(pointD); glEnd(); glFlush();
}

五角星还是比较神圣的,可是自己已经污染了,热爱家人吧.感谢他们给了我生命和一切.

下面是最后一个例子 绘制 f(x) = sinx , 这个例子是最简单,做了一点修改是 坐标系扩大了一点,具体看下面代码.

#define _USE_MATH_DEFINES //开启 math.h中默认的常量宏
#include <math.h> //绘制三角函数
static void display(void)
{
GLfloat fz = .f,p; glClear(GL_COLOR_BUFFER_BIT); //先绘制坐标系
glBegin(GL_LINES);
glVertex2f(-.f,.f);
glVertex2f(.f,.f);
glVertex2f(.f,.f);
glVertex2f(.f,-.f);
glEnd(); //绘制三角函数
glBegin(GL_LINE_STRIP);
for (p = -fz;p < fz;p += 0.01f)
glVertex2f(p/fz,sinf(p)/fz);
glEnd(); glFlush();
}

到这里关于 opengl 基础学习的 第二节 基本完工了.上面例子很简单,但需要 自己敲过才能知道一些. 这里再说一些题外话.有没有读者对 上面 使用static 感到好奇.

这是为了在一个项目中 添加多个 main 文件 ,都用display 命名函数使用的技巧.因为 static 修饰的函数只在当前文件内有效,就不会出现 同名函数编译不通过的问题.

关于static 和 extern 关键字 还是有很多学问的. 朋友们可以自己 科普一下.

最后说一点,当初写博文之前,是实在不(ˇˍˇ) 想~看水文.后面自己写了,才知道,好难.自己也成功的进入了 水笔行业. 对每一个写博文的同行都表示 敬意.

做过,写过,思考过,才知道 有些事 贵在坚持,难在 不想 坑人.

(有问题请随时拍砖,马上改)

opengl基础学习专题 (二) 点直线和多边形的更多相关文章

  1. opengl基础学习专题 (一 )编程环境搭建

    题外话: 第一次在博客园上同大家分享博文.水的的地方,错别字的地方.环境交流.批评.知道了马上改. 以前在百度空间中写技术分享博文,后来百度啥也没说就把整个空间封了.当时感觉 还是有点寒心.只想黑一下 ...

  2. opengl基础学习专题 (三) 多边形绘制的几种样式

    题外话 聪明人之所以不会成功,是由于他们缺乏坚韧的毅力. ——艾萨克·牛顿(1643年1月4日—1727年3月31日)英国 也许可以理解为 想更深一步的时候,坚持,努力和聪明缺一不可. 挺直腰杆在此向 ...

  3. AspectJ基础学习之二搭建环境(转载)

    AspectJ基础学习之二搭建环境(转载) 一.下载Aspectj以及AJDT 上一章已经列出了他的官方网站,自己上去download吧.AJDT是一个eclipse插件,开发aspectj必装,他可 ...

  4. 【笔记】MySQL的基础学习(二)

    [笔记]MySQL的基础学习(二) MySQL 老男孩  一 视图 视图其实就是给表起个别名 1.创建视图 格式:CREATE VIEW 视图名称 AS SQL语句 CREATE VIEW v1 AS ...

  5. OpenGL入门学习(二)

    http://developer.178.com/201103/94954661733.html 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中 ...

  6. JavaScript 基础学习(二)js 和 html 的结合方式

    第一种 使用一个标签 <script type="text/javascript"> js代码; </script> 第二种 使用 script 标签,引入 ...

  7. JavaScript 基础 学习 (二)

    JavaScript 基础 学习 节点属性 ​ 每一个节点都有自己的特点 ​ 这个节点属性就记录着属于自己节点的特点 1. nodeType(以一个数字来表示这个节点类型) ​ 语法:节点.nodeT ...

  8. Java基础学习笔记二十八 管家婆综合项目

    本项目为JAVA基础综合项目,主要包括: 熟练View层.Service层.Dao层之间的方法相互调用操作.熟练dbutils操作数据库表完成增删改查. 项目功能分析 查询账务 多条件组合查询账务 添 ...

  9. pytorch基础学习(二)

    在神经网络训练时,还涉及到一些tricks,如网络权重的初始化方法,优化器种类(权重更新),图片预处理等,继续填坑. 1. 神经网络初始化(Network Initialization ) 1.1 初 ...

随机推荐

  1. cisco VPN配置

    拓扑拿朋友的. r1(config)#int f0/0 r1(config-if)#ip add 50.50.50.50 255.255.255.0 r1(config-if)#no shu r1(c ...

  2. 多文件目录下makefile文件递归执行编译所有c文件

    首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的. 意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文 ...

  3. Solarwinds Orion NPM实战视频演示

    Orion Network Performance Monitor是全面的带宽性能监控和故障管理软件,能监控并收集来自路由器.交换机.服务器和其他SNMP设备中的数据,您可以直接从Web浏览器上观察您 ...

  4. VC 宏与预处理使用方法总结

    目录(?) C/C++ 预定义宏^ C/C++ 预定义宏用途:诊断与调试输出^ CRT 和 C 标准库中的宏^ NULL 空指针^ limits.h 整数类型常量^ float.h 浮点类型常量^ m ...

  5. WWF3事件类型活动<第三篇>

    WWF将工作流分为两大类: 面向Human:在工作流运行时通过用户对外部应用程序的操作来影响工作流的业务流转. 面向System:应用程序控制流程. 工作流与应用程序都是可以单独存在的,因此它们之间的 ...

  6. WeChat 6.3 wipe deleted chat messages as well as LINE 5.3 and above

    Let me show you the WeChat version first. It is 6.3. What will happen to WeChat deleted chat message ...

  7. 查看cics 运行状态

     查看cics 运行状态cicscp -v status all 

  8. s3c6410_uart初始化及读写

    参考: 1)<USER'S MANUAL-S3C6410X>第31章 UART 2)u-boot uart初始化及读写:u-boot-x.x.x/board/samsumg/smdk641 ...

  9. Linux下tftp安装与配置

    1. 背景 开发板在u-boot下从pc获取文件的方式有三种: 1)dnw传输:http://www.cnblogs.com/tanghuimin0713/p/3614768.html 2)串口传输: ...

  10. pap与chap协议

    1.pap:直接在网络上发送密码明文 2.chap: 网络上发送的是密码的密文;server给client发一段随机数(challenge),client利用随机数对密码进行加密,将用户名和加密后的密 ...