Open入门学习(三)

在第二课中,我们学习了如何绘制几何图形,但大家如果多写几个程序,就会发现其实还是有些郁闷之处。例如:点太小,难以看清楚;直线也太细,不舒服;或者想画虚线,但不知道方法只能用许多短直线,甚至用点组合而成。
这些问题将在本课中被解决。

下面就点、直线、多边形分别讨论。


1、关于点
点的大小默认为1个像素,但也可以改变之。改变的命令为glPointSize,其函数原型如下:
void glPointSize(GLfloat size);
size必须大于0.0f,默认值为1.0f,单位为“像素”。
注意:对于具体的OpenGL实现,点的大小都有个限度的,如果设置的size超过最大值,则设置可能会有问题。
例子:
void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPointSize(5.0f);
    glBegin(GL_POINTS);
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.5f, 0.5f);
    glEnd();
    glFlush();
}

2、关于直线
(1)直线可以指定宽度:
void glLineWidth(GLfloat width);
其用法跟glPointSize类似。
(2)画虚线。
首先,使用glEnable(GL_LINE_STIPPLE);来启动虚线模式(使用glDisable(GL_LINE_STIPPLE)可以关闭之)。
然后,使用glLineStipple来设置虚线的样式。
void glLineStipple(GLint factor, GLushort pattern);
pattern是由1和0组成的长度为16的序列,从最低位开始看,如果为1,则直线上接下来应该画的factor个点将被画为实的;如果为0,则直线上接下来应该画的factor个点将被画为虚的。
以下是一些例子:
http://blog.programfan.com/upfile/200608/20060801172519.gif
声明:该图片来自www.opengl.org,该图片是《OpenGL编程指南》一书的附图,由于该书的旧版(第一版,1994年)已经流传于网络,我希望没有触及到版权问题。
示例代码:
void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_LINE_STIPPLE);
    glLineStipple(2, 0x0F0F);
    glLineWidth(10.0f);
    glBegin(GL_LINES);
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.5f, 0.5f);
    glEnd();
    glFlush();
}


3、关于多边形
多边形的内容较多,我们将讲述以下四个方面。
(1)多边形的两面以及绘制方式。
虽然我们目前还没有真正的使用三维坐标来画图,但是建立一些三维的概念还是必要的。
从三维的角度来看,一个多边形具有两个面。每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点,其中“填充”是默认的方式。可以为两个面分别设置不同的方式。
glPolygonMode(GL_FRONT, GL_FILL);           // 设置正面为填充方式
glPolygonMode(GL_BACK, GL_LINE);            // 设置反面为边缘绘制方式
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式


(2)反转
一般约定为“顶点以逆时针顺序出现在屏幕上的面”为“正面”,另一个面即成为“反面”。生活中常见的物体表面,通常都可以用这样的“正面”和“反面”,“合理的”被表现出来(请找一个比较透明的矿泉水瓶子,在正对你的一面沿逆时针画一个圆,并标明画的方向,然后将背面转为正面,画一个类似的圆,体会一下“正面”和“反面”。你会发现正对你的方向,瓶的外侧是正面,而背对你的方向,瓶的内侧才是正面。正对你的内侧和背对你的外侧则是反面。这样一来,同样属于“瓶的外侧”这个表面,但某些地方算是正面,某些地方却算是反面了)。
但也有一些表面比较特殊。例如“麦比乌斯带”(请自己Google一下),可以全部使用“正面”或全部使用“背面”来表示。
可以通过glFrontFace函数来交换“正面”和“反面”的概念。
glFrontFace(GL_CCW);  // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
glFrontFace(GL_CW);   // 设置CW方向为“正面”,CW即ClockWise,顺时针
下面是一个示例程序,请用它替换第一课中的myDisplay函数,并将glFrontFace(GL_CCW)修改为glFrontFace(GL_CW),并观察结果的变化。
void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式
    glPolygonMode(GL_BACK, GL_LINE);  // 设置反面为线形模式
    glFrontFace(GL_CCW);              // 设置逆时针方向为正面
    glBegin(GL_POLYGON);              // 按逆时针绘制一个正方形,在左下方
        glVertex2f(-0.5f, -0.5f);
        glVertex2f(0.0f, -0.5f);
        glVertex2f(0.0f, 0.0f);
        glVertex2f(-0.5f, 0.0f);
    glEnd();
    glBegin(GL_POLYGON);              // 按顺时针绘制一个正方形,在右上方
        glVertex2f(0.0f, 0.0f);
        glVertex2f(0.0f, 0.5f);
        glVertex2f(0.5f, 0.5f);
        glVertex2f(0.5f, 0.0f);
    glEnd();
    glFlush();
}
(3)剔除多边形表面
在三维空间中,一个多边形虽然有两个面,但我们无法看见背面的那些多边形,而一些多边形虽然是正面的,但被其他多边形所遮挡。如果将无法看见的多边形和可见的多边形同等对待,无疑会降低我们处理图形的效率。在这种时候,可以将不必要的面剔除。
首先,使用glEnable(GL_CULL_FACE);来启动剔除功能(使用glDisable(GL_CULL_FACE)可以关闭之)
然后,使用glCullFace来进行剔除。
glCullFace的参数可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK,分别表示剔除正面、剔除反面、剔除正反两面的多边形。
注意:剔除功能只影响多边形,而对点和直线无影响。例如,使用glCullFace(GL_FRONT_AND_BACK)后,所有的多边形都将被剔除,所以看见的就只有点和直线。

(4)镂空多边形
直线可以被画成虚线,而多边形则可以进行镂空。
首先,使用glEnable(GL_POLYGON_STIPPLE);来启动镂空模式(使用glDisable(GL_POLYGON_STIPPLE)可以关闭之)。
然后,使用glPolygonStipple来设置镂空的样式。
void glPolygonStipple(const GLubyte *mask);
其中的参数mask指向一个长度为128字节的空间,它表示了一个32*32的矩形应该如何镂空。其中:第一个字节表示了最左下方的从左到右(也可以是从右到左,这个可以修改)8个像素是否镂空(1表示不镂空,显示该像素;0表示镂空,显示其后面的颜色),最后一个字节表示了最右上方的8个像素是否镂空。
但是,如果我们直接定义这个mask数组,像这样:
static GLubyte Mask[128] =
{
    0x00, 0x00, 0x00, 0x00,   //  这是最下面的一行
    0x00, 0x00, 0x00, 0x00,
    0x03, 0x80, 0x01, 0xC0,   //  
    0x06, 0xC0, 0x03, 0x60,   //  
    0x04, 0x60, 0x06, 0x20,   //  
    0x04, 0x30, 0x0C, 0x20,   //  
    0x04, 0x18, 0x18, 0x20,   //  
    0x04, 0x0C, 0x30, 0x20,   //  
    0x04, 0x06, 0x60, 0x20,   //  
    0x44, 0x03, 0xC0, 0x22,   //  
    0x44, 0x01, 0x80, 0x22,   //  
    0x44, 0x01, 0x80, 0x22,   //  
    0x44, 0x01, 0x80, 0x22,   //  使
    0x44, 0x01, 0x80, 0x22,   //  
    0x44, 0x01, 0x80, 0x22,
    0x44, 0x01, 0x80, 0x22,
    0x66, 0x01, 0x80, 0x66,
    0x33, 0x01, 0x80, 0xCC,
    0x19, 0x81, 0x81, 0x98,
    0x0C, 0xC1, 0x83, 0x30,
    0x07, 0xE1, 0x87, 0xE0,
    0x03, 0x3F, 0xFC, 0xC0,
    0x03, 0x31, 0x8C, 0xC0,
    0x03, 0x3F, 0xFC, 0xC0,
    0x06, 0x64, 0x26, 0x60,
    0x0C, 0xCC, 0x33, 0x30,
    0x18, 0xCC, 0x33, 0x18,
    0x10, 0xC4, 0x23, 0x08,
    0x10, 0x63, 0xC6, 0x08,
    0x10, 0x30, 0x0C, 0x08,
    0x10, 0x18, 0x18, 0x08,
    0x10, 0x00, 0x00, 0x08   // 这是最上面的一行
};
这样一堆数据非常缺乏直观性,我们需要很费劲的去分析,才会发现它表示的竟然是一只苍蝇。
如果将这样的数据保存成图片,并用专门的工具进行编辑,显然会方便很多。下面介绍如何做到这一点。


首先,用Windows自带的画笔程序新建一副图片,取名为mask.bmp,注意保存时,应该选择“单色位图”。在“图象”->“属性”对话框中,设置图片的高度和宽度均为32。
用放大镜观察图片,并编辑之。黑色对应二进制零(镂空),白色对应二进制一(不镂空),编辑完毕后保存。
然后,就可以使用以下代码来获得这个Mask数组了。
static GLubyte Mask[128];
FILE *fp;
fp = fopen("mask.bmp", "rb");
if( !fp )
    exit(0);
// 移动文件指针到这个位置,使得再读sizeof(Mask)个字节就会遇到文件结束
// 注意-(int)sizeof(Mask)虽然不是什么好的写法,但这里它确实是正确有效的
// 如果直接写-sizeof(Mask)的话,因为sizeof取得的是一个无符号数,取负号会有问题
if( fseek(fp, -(int)sizeof(Mask), SEEK_END) )
    exit(0);
// 读取sizeof(Mask)个字节到Mask
if( !fread(Mask, sizeof(Mask), 1, fp) )
    exit(0);
fclose(fp);


好的,现在请自己编辑一个图片作为mask,并用上述方法取得Mask数组,运行后观察效果。
说明:绘制虚线时可以设置factor因子,但多边形的镂空无法设置factor因子。请用鼠标改变窗口的大小,观察镂空效果的变化情况。
#include <stdio.h>
#include <stdlib.h>
void myDisplay(void)
{
    static GLubyte Mask[128];
    FILE *fp;
    fp = fopen("mask.bmp", "rb");
    if( !fp )
        exit(0);
    if( fseek(fp, -(int)sizeof(Mask), SEEK_END) )
        exit(0);
    if( !fread(Mask, sizeof(Mask), 1, fp) )
        exit(0);
    fclose(fp);
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_POLYGON_STIPPLE);
    glPolygonStipple(Mask);
    glRectf(-0.5f, -0.5f, 0.0f, 0.0f);  // 在左下方绘制一个有镂空效果的正方形
    glDisable(GL_POLYGON_STIPPLE);
    glRectf(0.0f, 0.0f, 0.5f, 0.5f);    // 在右上方绘制一个无镂空效果的正方形
    glFlush();
}


小结
本课学习了绘制几何图形的一些细节。
点可以设置大小。
直线可以设置宽度;可以将直线画成虚线。
多边形的两个面的绘制方法可以分别设置;在三维空间中,不可见的多边形可以被剔除;可以将填充多边形绘制成镂空的样式。
了解这些细节会使我们在一些图象绘制中更加得心应手。
另外,把一些数据写到程序之外的文件中,并用专门的工具编辑之,有时可以显得更方便。

 

本文来自:http://blog.chinaunix.net/u/26313/showart_218521.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenDDS是一个开源的分布式数据服务(DDS)实现,用于构建分布式实时应用程序。它提供了图形用户界面(GUI)和命令行界面(CLI)工具,方便开发者使用。 在Windows平台上使用OpenDDS进行开发,我们可以选择集成Qt框架。Qt是一个跨平台的应用程序开发框架,支持多种操作系统和开发语言。使用Qt将OpenDDS和Windows平台进行结合,可以提供更加方便的开发环境和工具。 首先,我们需要在Windows上安装Qt和OpenDDS。可以从官方网站下载Qt安装程序,并按照提示进行安装。OpenDDS可以从OpenDDS社区的网站上下载源代码,并按照指南进行编译和安装。 安装完成后,我们可以使用Qt Creator作为集成开发环境(IDE)来开发OpenDDS应用程序。在Qt Creator中,我们可以创建一个新的Qt项目,并添加OpenDDS库文件和头文件。然后我们可以开始编写代码,使用OpenDDS提供的API来创建DDS实体、定义数据类型、发布和订阅数据。 在开发过程中,我们可以使用Qt Creator提供的调试工具来调试应用程序。通过设置断点、查看变量和调用栈,我们可以更好地理解和修复代码中的问题。 最后,我们可以使用Qt Creator提供的构建工具来构建和部署OpenDDS应用程序。可以将应用程序打包为可执行文件,并在Windows平台上运行。 总而言之,使用OpenDDS和Qt进行Windows平台开发,可以提供强大的分布式数据服务和丰富的开发工具。通过充分利用OpenDDS和Qt的特性,可以快速构建高效的分布式实时应用程序。 ### 回答2: OpenDDS是一种开源的分布式数据服务(DDS)的实现,它支持多种平台,包括Windows和Qt。下面是在Windows平台使用Qt入门OpenDDS的步骤。 1.准备工作: 在Windows上安装Qt开发环境,可以从Qt官方网站上下载安装程序。 在OpenDDS官方网站上下载OpenDDS的最新版本。 2.安装OpenDDS: 解压下载好的OpenDDS文件,并将其放在合适的位置,例如C:\opendds。 3.配置环境变量: 添加一个名为DDS_ROOT的环境变量,并将其值设置为OpenDDS的安装路径,例如C:\opendds。 在环境变量PATH中添加DDS_ROOT\bin目录,以便系统能够找到OpenDDS的可执行文件。 4.创建工程: 在Qt Creator中创建一个新的Qt项目,选择适当的模板,例如Qt Widgets Application。 在项目文件(.pro)的源代码中添加OpenDDS相关的头文件路径和库文件路径,例如: INCLUDEPATH += $$DDS_ROOT/include LIBS += -L$$DDS_ROOT/lib -lOpenDDS 5.编写代码: 在Qt项目中开始编写OpenDDS相关的代码,使用OpenDDS的API进行数据发布和订阅操作。 可以参考OpenDDS官方文档和示例代码来学习如何使用OpenDDS。 6.设置DDS配置: 在Qt项目中配置DDS的QoS(服务质量)和其他参数,例如订阅和发布的主题,传输协议等等。 可以通过在代码中使用OpenDDS的API来设置这些参数。 7.编译和运行: 使用Qt Creator编译并运行Qt项目,可以在控制台或者界面上看到OpenDDS的输出信息。 总结: 以上是在Windows上使用Qt入门OpenDDS的基本步骤,通过学习OpenDDS的相关文档和示例代码,可以进一步深入了解和扩展OpenDDS的功能。希望这些信息能够帮助您开始使用OpenDDS和Qt进行分布式数据服务的开发。 ### 回答3: OpenDDS是一个开源的、高性能的、分布式数据共享系统,主要用于构建实时/嵌入式系统。它支持多种平台和编程语言,并提供了一套强大的开发工具和库。 在Windows环境中使用Qt框架进行OpenDDS入门,可以按照以下步骤进行操作: 步骤一:准备工作 1. 下载并安装Qt开发环境,确保你已经熟悉Qt的基本使用。 2. 下载OpenDDS的最新版本,并解压到一个目录中。 步骤二:生成OpenDDS的MPC文件 1. 打开命令提示符(cmd),进入OpenDDS目录。 2. 运行"configure"命令,该命令会生成OpenDDS的MPC文件用于编译。 3. 运行"generate"命令,该命令会根据MPC文件生成Qt所需的项目文件。 步骤:使用Qt进行开发 1. 打开Qt开发环境,选择“打开项目”,导入OpenDDS项目文件。 2. 在Qt中编写代码,使用OpenDDS提供的库进行分布式数据共享的开发。 3. 编译和运行项目,检查功能是否正常。 步骤四:进阶操作 1. 阅读OpenDDS的官方文档,了解更多关于OpenDDS的详细信息。 2. 参考OpenDDS的示例代码,学习如何使用OpenDDS进行更复杂的操作。 3. 加入OpenDDS的开发者社区,与其他开发者交流经验和技术。 总之,通过以上步骤,你可以在Windows环境中使用Qt进行OpenDDS的入门开发。希望你能够顺利掌握OpenDDS的基本使用,并能够在实际项目中应用它的强大功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值