第3课:OpenGL几何图原——线

 先看一个基础的程序吧: 
(相信有了前两节课的基础这是不难做到的) 
#include < windows.h >   
#include 
< GL / glut.h >   

void  myDisplay( void )  
{  
    glClear(GL_COLOR_BUFFER_BIT);  
    glEnable(GL_LINE_STIPPLE); 
// 启动虚线模式(使用glDisable(GL_LINE_STIPPLE)可以关闭之)  
    glLineStipple( 2 0x0F0F );  
    glLineWidth(
10.0f );  
    glBegin(GL_LINES);  
        glVertex2f(
0.0f 0.0f );  
        glVertex2f(
0.5f 0.5f );  
    glEnd();  
    glFlush();  
}  

int  main( int  argc,  char   * argv[])  
{  
    glutInit(
& argc, argv);  
    glutInitDisplayMode(GLUT_RGB 
|  GLUT_SINGLE);  
    glutInitWindowPosition(
100 100 );  
    glutInitWindowSize(
400 400 );  
    glutCreateWindow(
" 画虚线 " );  
    glutDisplayFunc(
& myDisplay);  
    glutMainLoop();  
    
return   0 ;  


效果图如下: 

比如,将程序中glLineStipple(2, 0x0F0F);换成glLineStipple(2, 0xAAAA);将虚线宽度glLineWidth(10.0f);换成glLineWidth(2.0f);则效果图如下:  

使用glLineStipple来设置虚线的样式。 
void glLineStipple(GLint factor, GLushort pattern); 
pattern是由1和0组成的长度为16的序列,从最低位开始看,如果为1,则直线上接下来应该画的factor个点将被画为实的;如果为0,则直线上接下来应该画的factor个点将被画为虚的。 
以下是一些例子(来自网上) : 

一些必要的说明:  

1、void glEnable(GL_LINE_STIPPLE); 是启动虚线模式,使用glDisable(GL_LINE_STIPPLE) 该模式,在以后它的应用是经常性的,至于可以用哪些模式,通过http://www.google.cn可以搜索到很多的。 

2、void glLineStipple(GLint factor, GLushort pattern);该函数设置当前点的划线方式。factor表示连续画线的次数,范围为1~255,pattern是由0和1组成的16进制数,当位值为1时绘制直线,为0时不绘制直线,例如:0000111100001111的16进制为0x0F0F,表示绘制的是一条短线段,即我们说的破折线。 

3、void glLineWidth(GLfloat width);表示划线宽度的函数。

关于虚线的模式,通过一个直观的程序给出:     

#include  < windows.h >     
#include 
< GL / glut.h >     
#include 
< stdlib.h >     

void  drawALine(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)    
{    
glBegin(GL_LINES);    
    glVertex2f((x1),(y1));    
    glVertex2f((x2),(y2));    
glEnd();    
}    

void  init( void )    
{    
glClearColor(
0.0 , 0.0 , 0.0 , 0.0 ); // 清除屏幕颜色为白色    
glShadeModel(GL_FLAT);    
}    

void  display( void )    
{    
int  i;    
glClear(GL_COLOR_BUFFER_BIT);    
    glColor3f(
1.0 , 1.0 , 1.0 );    

// 画第一行    
glEnable(GL_LINE_STIPPLE);    
glLineWidth(
3.0 );    
glLineStipple(
1 , 0x0101 );    
drawALine(
50.0 , 125.0 , 150.0 , 125.0 ); // 调用drawALine()函数    
glLineStipple( 1 , 0x00FF );    
drawALine(
150.0 , 125.0 , 250.0 , 125.0 );    
glLineStipple(
1 , 0x1C47 );    
drawALine(
250.0 , 125.0 , 350.0 , 125.0 );    

// 画第二行    
glLineWidth( 6.0 );    
glLineStipple(
1 , 0x0101 );    
drawALine(
50.0 , 100.0 , 150.0 , 100.0 );    
glLineStipple(
1 , 0x00FF );    
drawALine(
150.0 , 100.0 , 250.0 , 100.0 );    
glLineStipple(
1 , 0x1C47 );    
drawALine(
250.0 , 100.0 , 350.0 , 100.0 );    

// 画第三行    
glLineWidth( 3.0 );    
glLineStipple(
1 , 0x1C47 );    
glBegin(GL_LINE_STRIP);    
for (i = 0 ;i < 7 ;i ++ )    
glVertex2f(
50.0 + ((GLfloat)i * 50.0 ), 75.0 );    
glEnd();    

// 画第四行    
for (i = 0 ;i < 6 ;i ++ )    
{    
drawALine(
50.0 + ((GLfloat)i * 50.0 ), 50.0 , 50.0 + ((GLfloat)(i + 1 ) * 50.0 ), 50.0 );    
}    

// 画第五行    
glLineStipple( 5 , 0x1C47 );    
drawALine(
50.0 , 25.0 , 350.0 , 25.0 );    
glFlush();    
}    

void  reshape( int  w, int  h)    
{    
glViewport(
0 , 0 ,(GLsizei)w,(GLsizei)h);    
glMatrixMode(GL_PROJECTION);    
glLoadIdentity();    
gluOrtho2D(
0.0 ,(GLdouble)w, 0.0 ,(GLdouble)h);    
}    

int  main( int  argc,  char   * argv[])    
{    
    glutInit(
& argc, argv);    
    glutInitDisplayMode(GLUT_SINGLE
| GLUT_RGB);    
    glutInitWindowPosition(
100 100 );    
    glutInitWindowSize(
400 400 );    
    glutCreateWindow(
" OpenGL Stipple " );    
    init();                          
    glutReshapeFunc(
& reshape);    
    glutDisplayFunc(
& display);    
    glutMainLoop();    
    
return   0 ;    
}   


运行效果如图所示:  

对如上程序作如下说明:

1、void drawALine(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)是用户自己编写的函数,实现画线功能:画出以(x1,y1)和(x2,y2)为端点的线段。因为后面的void display(void)函数要反复调用该函数。

2、对于函数:
void reshape(int w,int h)   
{   
glViewport(0,0,(GLsizei)w,(GLsizei)h);   
glMatrixMode(GL_PROJECTION);   
glLoadIdentity();   
gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);   
}   

作如下解释:
(1)函数原型为void reshape(GLsizei w,GLsizei h),其中w表示视口(视口:是在屏幕上所绘制的一个矩形区域)宽度,h表示视口高度,通过协调w,h来实现改变视口的大小,当然也可以使视口保持不变的。尤其是在被调用时能够恢复视口大小。
(2)主函数main()中的glutReshapeFunc(&reshape);对void reshape(int w,int h)进行调用,使得无论何时改变窗口的大小,都能够使正方形看起来仍然是正方形,当减小窗口时,正方形也将变小。   
(3)glViewport(0,0,(GLsizei)w,(GLsizei)h);的函数原型为:
       void glViewport(GLint x,GLint y,GLsizei width,GLsizei height);
其中(x,y)定义了视口左下角的坐标,width和height定义了视口的宽度和高度,默认情况下视口区域初始值为(0,0,winWidth,winHeight),这里winWidth,winHeight分别为窗口的宽度和高度。
(4)glMatrixMode(GL_PROJECTION);的函数原型为:
                  void glMatrixMode(GLenum mode); 
通过该函数可以实现用户所希望的矩阵模式,moded可以取值为GL_MODEVIEW、GL_PROJECTION、GL_TEXTURE,分别指定当前操纵的矩阵式模型视景矩阵、投影矩阵、纹理矩阵,随后的转换命令只影响指定的矩阵。
(5)glLoadIdentity();表示清除当前矩阵为单位矩阵。若不进行矩阵转换,当前矩阵就是单位矩阵。之所以在每步矩阵转换之后调用glLoadIdentity();是因为,下次进行矩阵转换的话就要乘以当前矩阵,如果没有调用glLoadIdentity();则直接乘以上次转换的矩阵(不是单位矩阵)就与用户的意愿偏离了,达不到预期效果。
(6)gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);的函数原型为:
void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);
该函数创建了一个平行的视景体。(left,bottom,near)和(right,top,near)定义了近切面左下角和右上角的坐标,(left,bottom,far)和(right,top,far)定义了远切面的左下角和右上角的坐标。例如:gluOrtho2D()定义的正视投影,直观地如下图(来自网络)所示: 

 





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值