OpenGL编程(五)绘直线以及分析绘直线的算法
2016-03-13 22:15
471 查看
这次主要实现在窗口上绘制点、线以及修改其属性,另外还会分析画直线的原理和相关算法。
1、在窗口指定位置画点
glBegin(GL_POINTS);
glEnd();
使用glBegin()和glEnd()方法向窗口中添加图形。要添加点时,glBegin()函数里的参数填GL_POINTS。然后通过glVertex3f()函数在指定的(坐标)位置画点,如:glVertex3f(100.0f, 100.0f, 0.0f);三个参数分别表示x,y,z坐标。
默认情况下点的大小时一个像素点,在画点之前可以通过函数glPointSize(5.0f)来修改点的大小。
如:
2、画直线
(1)GL_LINES画法:
与画点相似,画直线时在函数glBegin(GL_LINES)中给的参数是GL_LINES,这种画直线的方法是,通过在glBegin和glEnd之间添加偶数个点,第2n和第2n+1个点之间是一条连线,如果添加的点的个数是奇数,那最后一个点时多余的。例如:
(2)GL_LINE_STRIP画法:
这种画直线方法叫做折线画法,该方法与第一种方法类似。不同的地方第一个点和第二个点连线,第二个点和第三个点连线…第n个点和第n+1个连线。
3、画虚线
在glBegin()函数前面调用glEnable(GL_LINE_STIPPLE);glLineStipple(factor, 0x5555);期中glEnable(GL_LINE_STIPPLE)表示启用虚线模式,glLineStipple为甚至画虚线的规则。(下面引用关于glLineStipple函数的解释:http://baike.baidu.com/link?url=t7CeuQzNxSNKqi7l43QIRlmcwhxC4yQX5tC3v6cpWPOejgQx9K-e_X7Ac7WYsb4RmYuml7BIpmRFCTxRVXeOWa)
viod glLineStipple(GLint factor,GLshort pattern);
OpenGL中设置直线的当前点画模式。pattern参数是由1或0组成的16位序列,它们根据需要进行重复,对一条特定的直线进行点画处理。从这个模式的低位开始,一个像素一个像素的进行处理。如果模式中对应的位是1,就绘制这个像素,否则就不绘制。模式可以使用factor参数(表示重复因子)进行扩展,它与1和0的连续子序列相乘。因此,如果模式中出现了3个1,并且factor是2,那么它们就扩展为6个连续的1。必须以GL_LINE_STIPPLE为参数调用glEnable()才能启用直线点画功能。为了禁用直线点画功能,可以向glDisable()函数传递同一个参数。
例如:
glLineStipple(1, Ox3F07);
glEnable(GL_LINE_STIPPLE);
此时模式为Ox3F07(二进制形式为0011111100000111),它所画出来的直线是这样的:先连续绘制3个像素,然后连续5个像素留空,再连续绘制6个像素,最后两个像素留空(注意,首先是从低位开始的)。如果factor是2,那么这个模式便被扩展为:先连续绘制6个像素,然后连续10个像素留空,再连续绘制12个像素,最后4个像素留空。
如果没有启用点画线功能,OpenGL会自动把pattern当做为OxFFFF,把factor当成1。
代码如下:
4、简单分析画直线的算法
以前高中的时候我们就学过两点确定一条直线。图形学中的画直线也是使用这种方法。通过两个端点,确定这条线段(所经过的像素点),然后再调用画点的的方法,给这些像素点画图。
(1)使用两点式公式的方法(为了简便,用两维的举例子):
x1,y1表示点1,x2,y2表示点2的坐标。当|x2-x1|大于|y2-y1时|,假设x1小于x2,我们从x1,x1+1,x1+2…x2,然后按照上面公式求出y坐标对于的值,这些点就是这条直线经过的点。
(2)优化算法提高效率
按照上面的方法,我们每个x坐标的值都要调用一次上面这个公式求出y坐标对应的值。上面的公式涉及到乘法(对计算机来说触发就是乘法的变形)。学过计算机操作系统我们都知道,对于计算机来说,计算乘除法比计算加减法要复杂很多。如果我们能想到其他方法,通过使用加减法去求出线段经过的点的坐标,将大大减小计算量。
a)首先我们求x1到x2的横坐标的变化量(像素点),x2-x1。同样求出y2-y1。再求x坐标每增加要给像素点时,y坐标的变化量,即步长为:
(当|y2-y1|大于|x2-x1|,以y轴为自变量,x轴为因变量)
然后x坐标每次增加1个像素点,y坐标的值增加一个步长。这样我们只需要经过一次除法计算,大大减少了画直线时的计算量,从而提高了运行效率。
注:对于小数点,采用四舍五入的方法求整。
下图引用《计算机图形学》
当然还有更好的画直线的算法。
1、在窗口指定位置画点
glBegin(GL_POINTS);
glEnd();
使用glBegin()和glEnd()方法向窗口中添加图形。要添加点时,glBegin()函数里的参数填GL_POINTS。然后通过glVertex3f()函数在指定的(坐标)位置画点,如:glVertex3f(100.0f, 100.0f, 0.0f);三个参数分别表示x,y,z坐标。
glBegin(GL_POINTS); glVertex3f(100.0f, 100.0f, 0.0f); glVertex3f(100.0f, 200.0f, 0.0f); glVertex3f(200.0f, 100.0f, 0.0f); glVertex3f(200.0f, 200.0f, 0.0f); glEnd();
默认情况下点的大小时一个像素点,在画点之前可以通过函数glPointSize(5.0f)来修改点的大小。
如:
#include <windows.h>
#include <gl/glut.h>
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glPointSize(5.0f);
glBegin(GL_POINTS); glVertex3f(100.0f, 100.0f, 0.0f); glVertex3f(100.0f, 200.0f, 0.0f); glVertex3f(200.0f, 100.0f, 0.0f); glVertex3f(200.0f, 200.0f, 0.0f); glEnd();
glFlush();
}
void main()
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(300, 300);
glutInitWindowPosition(200, 200);
glutCreateWindow("point");
glutDisplayFunc(renderScene);
glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glutMainLoop();
}
2、画直线
(1)GL_LINES画法:
与画点相似,画直线时在函数glBegin(GL_LINES)中给的参数是GL_LINES,这种画直线的方法是,通过在glBegin和glEnd之间添加偶数个点,第2n和第2n+1个点之间是一条连线,如果添加的点的个数是奇数,那最后一个点时多余的。例如:
#include <windows.h> #include <gl/glut.h> void renderScene() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 0.0f, 0.0f); glLineWidth(5.0f); glBegin(GL_LINES); glVertex3f(100.0f, 100.0f, 0.0f); glVertex3f(100.0f, 200.0f, 0.0f); glVertex3f(200.0f, 100.0f, 0.0f); glVertex3f(200.0f, 200.0f, 0.0f); glVertex3f(250.0f, 250.0f, 0.0f); glEnd(); glFlush(); } void main() { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(300, 300); glutInitWindowPosition(200, 200); glutCreateWindow("line"); glutDisplayFunc(renderScene); glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f); glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glutMainLoop(); }
(2)GL_LINE_STRIP画法:
这种画直线方法叫做折线画法,该方法与第一种方法类似。不同的地方第一个点和第二个点连线,第二个点和第三个点连线…第n个点和第n+1个连线。
#include <windows.h> #include <gl/glut.h> void renderScene() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 0.0f, 0.0f); glLineWidth(5.0f); glBegin(GL_LINE_STRIP); glVertex3f(100.0f, 100.0f, 0.0f); glVertex3f(100.0f, 200.0f, 0.0f); glVertex3f(200.0f, 100.0f, 0.0f); glVertex3f(200.0f, 200.0f, 0.0f); glVertex3f(250.0f, 250.0f, 0.0f); glEnd(); glFlush(); } void main() { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(300, 300); glutInitWindowPosition(200, 200); glutCreateWindow("line"); glutDisplayFunc(renderScene); glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f); glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glutMainLoop(); }
3、画虚线
在glBegin()函数前面调用glEnable(GL_LINE_STIPPLE);glLineStipple(factor, 0x5555);期中glEnable(GL_LINE_STIPPLE)表示启用虚线模式,glLineStipple为甚至画虚线的规则。(下面引用关于glLineStipple函数的解释:http://baike.baidu.com/link?url=t7CeuQzNxSNKqi7l43QIRlmcwhxC4yQX5tC3v6cpWPOejgQx9K-e_X7Ac7WYsb4RmYuml7BIpmRFCTxRVXeOWa)
viod glLineStipple(GLint factor,GLshort pattern);
OpenGL中设置直线的当前点画模式。pattern参数是由1或0组成的16位序列,它们根据需要进行重复,对一条特定的直线进行点画处理。从这个模式的低位开始,一个像素一个像素的进行处理。如果模式中对应的位是1,就绘制这个像素,否则就不绘制。模式可以使用factor参数(表示重复因子)进行扩展,它与1和0的连续子序列相乘。因此,如果模式中出现了3个1,并且factor是2,那么它们就扩展为6个连续的1。必须以GL_LINE_STIPPLE为参数调用glEnable()才能启用直线点画功能。为了禁用直线点画功能,可以向glDisable()函数传递同一个参数。
例如:
glLineStipple(1, Ox3F07);
glEnable(GL_LINE_STIPPLE);
此时模式为Ox3F07(二进制形式为0011111100000111),它所画出来的直线是这样的:先连续绘制3个像素,然后连续5个像素留空,再连续绘制6个像素,最后两个像素留空(注意,首先是从低位开始的)。如果factor是2,那么这个模式便被扩展为:先连续绘制6个像素,然后连续10个像素留空,再连续绘制12个像素,最后4个像素留空。
如果没有启用点画线功能,OpenGL会自动把pattern当做为OxFFFF,把factor当成1。
代码如下:
#include <windows.h> #include <gl/glut.h> //画虚线 void renderScene() { GLint factor = 5; glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 0.0f, 0.0f); glLineWidth(5.0f); glEnable(GL_LINE_STIPPLE); glLineStipple(factor, 0x5555); glBegin(GL_LINES); glVertex2f(100.0f, 100.0f); glVertex2f(100.0f, 200.0f); glVertex2f(200.0f, 100.0f); glVertex2f(200.0f, 200.0f); glEnd(); glFlush(); } void main() { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(300, 300); glutInitWindowPosition(200, 200); glutCreateWindow("line"); glutDisplayFunc(renderScene); glOrtho(0.0f, 300.0f, 0.0f, 300.0f, 1.0f, -1.0f); glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glutMainLoop(); }
4、简单分析画直线的算法
以前高中的时候我们就学过两点确定一条直线。图形学中的画直线也是使用这种方法。通过两个端点,确定这条线段(所经过的像素点),然后再调用画点的的方法,给这些像素点画图。
(1)使用两点式公式的方法(为了简便,用两维的举例子):
x1,y1表示点1,x2,y2表示点2的坐标。当|x2-x1|大于|y2-y1时|,假设x1小于x2,我们从x1,x1+1,x1+2…x2,然后按照上面公式求出y坐标对于的值,这些点就是这条直线经过的点。
(2)优化算法提高效率
按照上面的方法,我们每个x坐标的值都要调用一次上面这个公式求出y坐标对应的值。上面的公式涉及到乘法(对计算机来说触发就是乘法的变形)。学过计算机操作系统我们都知道,对于计算机来说,计算乘除法比计算加减法要复杂很多。如果我们能想到其他方法,通过使用加减法去求出线段经过的点的坐标,将大大减小计算量。
a)首先我们求x1到x2的横坐标的变化量(像素点),x2-x1。同样求出y2-y1。再求x坐标每增加要给像素点时,y坐标的变化量,即步长为:
(当|y2-y1|大于|x2-x1|,以y轴为自变量,x轴为因变量)
然后x坐标每次增加1个像素点,y坐标的值增加一个步长。这样我们只需要经过一次除法计算,大大减少了画直线时的计算量,从而提高了运行效率。
注:对于小数点,采用四舍五入的方法求整。
下图引用《计算机图形学》
当然还有更好的画直线的算法。
相关文章推荐
- C++之虚函数
- C++之虚函数
- C++之虚函数
- Java day02 类型转换
- Struts2实现文件的上传和下载
- 检测程序是c还是cpp
- C语言小编程之素数算法剖析
- Java单链表排序方法
- Java实现的单链表反转方法(1)
- 在OS X管理多个Java版本
- PHP更新多行数据库
- python(5)–datetime模块
- 链表中倒数第k个节点
- java dya01 HelloWorld与环境变量
- Unix高级环境编程—进程控制(一)
- 关于多态和数组的比较
- Spring(一)基本知识之IOC和Bean
- 20145109《Java程序设计》第二周学习总结
- win10Java 环境配置
- 20145337 《Java程序设计》第二周学习总结