OpenGL进阶示例1——动态画线(虚线、实线、颜色、速度等)

http://blog.csdn.net/lynch0571/article/details/30496205


用OpenGL动态绘制线段,其实很简单,但到现在为止,网上可参考资料并不多。于是亲自动手写一个函数,方便动态绘制线段。代码如下:


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<GL/glut.h>                       //OpenGL实用工具包  
  2. #include <Windows.h>  
  3.   
  4. /*所遇问题: 
  5. 1、系统API函数Sleep()不听话,睡眠时快时慢(可能跟我计算机当前运行程序有关吧) 
  6. 解决方案:重写Sleep()函数,实质为空循环。仅用于Debug下,Release会将其优化 
  7.  
  8. 2、动态画直线,朝某些方向画线时出现块状 
  9. 解决方案:认认真真把直线方程推导一遍,斜率存在或不存在分别讨论,将数学思想转换为编程思想 
  10. */  
  11.   
  12. void init(void)  
  13. {  
  14.     glClearColor(0.0,0.0,0.0,0.0);      //指定清除颜色(黑色),即背景颜色  
  15.     glShadeModel(GL_FLAT);              //设置着色模式,采用恒定着色  
  16. }  
  17.   
  18. void Sleep(int ms)          //覆盖系统API函数  
  19. {  
  20.     for(int i=0;i<ms*ms*ms*10;i++)       //数值大小根据实际情况调试  
  21.     {  
  22.         ;  
  23.     }  
  24. }  
  25.   
  26. //特别注意:1、斜率不存在。2、直线斜率一定要保持一致,将直线两点式方程转化为斜率式方程y=kx+c  
  27. //k=(y2-y1)/(x2-x1);      
  28. //c=(x2*y1-x1*y2)/(x2-x1);  
  29. void DrawDynamicLine(GLfloat x1, GLfloat y1,        //起点坐标  
  30.     GLfloat x2, GLfloat y2,                         //终点坐标  
  31.     GLfloat red,GLfloat green,GLfloat blue,         //线段颜色  
  32.     int speed,                                      //绘制速度,0-100,值越大速度越大  
  33.     int type                                        //虚线类型,16位2进制表示,1为实点,0为虚点,0xFFFF为实线  
  34.     )  
  35. {  
  36.     glEnable(GL_LINE_STIPPLE);                      //点画线模式  
  37.     glColor3f(red,green,blue);                      //设置线段绘制颜色  
  38.     glLineStipple(1,type);                          //dashed(虚线),type为16位2进制数,0表示实点,1表示虚点  
  39.       
  40.     if (x1!=x2)                                     //如果斜率存在  
  41.     {  
  42.         GLfloat k=(y2-y1)/(x2-x1);                  //直线斜率 y=kx+c  
  43.         GLfloat c=(x2*y1-x1*y2)/(x2-x1);            //直线常数  
  44.         //假定以A为原点建立二维坐标系,则下边4个if分别对应于:第一象限,第二象限,第三象限,第四象限  
  45.         if (x1<x2&&y1<=y2)                            //从A(x1,y1)到B(x2,y2)画线,B点在A点的右上方  
  46.         {  
  47.             for (int i=0;i<=x2-x1;i++)               //注意循环条件  
  48.             {  
  49.                 glBegin(GL_LINES);    
  50.                 glVertex2f(x1,y1);  
  51.                 glVertex2f(x1+i,k*(x1+i)+c);  
  52.                 glEnd();  
  53.                 Sleep(100-speed);  
  54.                 glFlush();                          //立刻开始处理保存在缓冲区中的OpenGL函数调用  
  55.             }  
  56.         }     
  57.         else if (x1>x2&&y1<=y2)                       //从A(x1,y1)到B(x2,y2)画线,B点在A点的左下方  
  58.         {  
  59.             for (int i=0;i>=x2-x1;i--)               //特别注意循环条件,既要避免死循环又要避免少循环  
  60.             {  
  61.                 glBegin(GL_LINES);    
  62.                 glVertex2f(x1,y1);  
  63.                 glVertex2f(x1+i,k*(x1+i)+c);  
  64.                 glEnd();  
  65.                 Sleep(100-speed);  
  66.                 glFlush();                          //立刻开始处理保存在缓冲区中的OpenGL函数调用  
  67.             }  
  68.         }     
  69.         else if (x1>x2&&y1>=y2)                       //从A(x1,y1)到B(x2,y2)画线,B点在A点的左上方  
  70.         {  
  71.             for (int i=0;i>=x2-x1;i--)               //特别注意循环条件,既要避免死循环又要避免少循环  
  72.             {  
  73.                 glBegin(GL_LINES);    
  74.                 glVertex2f(x1,y1);  
  75.                 glVertex2f(x1+i,k*(x1+i)+c);  
  76.                 glEnd();  
  77.                 Sleep(100-speed);  
  78.                 glFlush();                          //立刻开始处理保存在缓冲区中的OpenGL函数调用  
  79.             }  
  80.         }     
  81.         else if (x1<x2&&y1>=y2)                       //从A(x1,y1)到B(x2,y2)画线,B点在A点的左上方  
  82.         {  
  83.             for (int i=0;i<=x2-x1;i++)               //特别注意循环条件,既要避免死循环又要避免少循环  
  84.             {  
  85.                 glBegin(GL_LINES);    
  86.                 glVertex2f(x1,y1);  
  87.                 glVertex2f(x1+i,k*(x1+i)+c);  
  88.                 glEnd();  
  89.                 Sleep(100-speed);  
  90.                 glFlush();                          //立刻开始处理保存在缓冲区中的OpenGL函数调用  
  91.             }  
  92.         }     
  93.     }  
  94.     else  
  95.     {  
  96.         if (y1<y2)                                   //沿y轴正方向画线  
  97.         {  
  98.             for (int i=0;i<=y2-y1;i++)               //特别注意循环条件,既要避免死循环又要避免少循环  
  99.             {  
  100.                 glBegin(GL_LINES);    
  101.                 glVertex2f(x1,y1);  
  102.                 glVertex2f(x1,y1+i);  
  103.                 glEnd();  
  104.                 Sleep(100-speed);  
  105.                 glFlush();                          //立刻开始处理保存在缓冲区中的OpenGL函数调用  
  106.             }  
  107.         }  
  108.         else                                        //沿y轴负方向画线  
  109.         {  
  110.             for (int i=0;i>=y2-y1;i--)               //特别注意循环条件,既要避免死循环又要避免少循环  
  111.             {  
  112.                 glBegin(GL_LINES);    
  113.                 glVertex2f(x1,y1);  
  114.                 glVertex2f(x1,y1+i);  
  115.                 glEnd();  
  116.                 Sleep(100-speed);  
  117.                 glFlush();                          //立刻开始处理保存在缓冲区中的OpenGL函数调用  
  118.             }  
  119.         }  
  120.     }  
  121.       
  122. }  
  123.   
  124. void display(void)  
  125. {  
  126.     glClear(GL_COLOR_BUFFER_BIT);           //清除所有的像素  
  127.     //正方形ABCD  
  128.     DrawDynamicLine(100,500,500,500,1,1,0,60,0xFFFF);           //AB  
  129.     DrawDynamicLine(500,500,500,100,1,0,1,70,0xFFFF);           //BC  
  130.     DrawDynamicLine(500,100,100,100,1,1,1,80,0xFFFF);           //CD  
  131.     DrawDynamicLine(100,100,100,500,0,1,1,90,0xFFFF);           //DA  
  132.   
  133.   
  134.     //沿顺时针方向测试动态画线:第一象限,第四象限,第三象限,第二象限  
  135.     DrawDynamicLine(300,300,300,500,1,0,0,90,0xFFFF);           //1  
  136.     DrawDynamicLine(300,300,400,500,1,0,0,90,0x00FF);  
  137.     DrawDynamicLine(300,300,500,500,1,0,0,90,0xFFFF);  
  138.     DrawDynamicLine(300,300,500,400,1,0,0,90,0x00FF);  
  139.     DrawDynamicLine(300,300,500,300,1,0,0,90,0xFFFF);  
  140.   
  141.     DrawDynamicLine(300,300,500,300,1,0,0,90,0xFFFF);           //2  
  142.     DrawDynamicLine(300,300,500,200,1,0,0,90,0x00FF);  
  143.     DrawDynamicLine(300,300,500,100,1,0,0,90,0xFFFF);  
  144.     DrawDynamicLine(300,300,400,200,1,0,0,90,0x00FF);  
  145.     DrawDynamicLine(300,300,400,100,1,0,0,90,0x00FF);  
  146.   
  147.     DrawDynamicLine(300,300,300,100,1,0,0,90,0xFFFF);           //3  
  148.     DrawDynamicLine(300,300,200,100,1,0,0,90,0x00FF);  
  149.     DrawDynamicLine(300,300,100,100,1,0,0,90,0xFFFF);  
  150.     DrawDynamicLine(300,300,100,200,1,0,0,90,0x00FF);  
  151.     DrawDynamicLine(300,300,100,300,1,0,0,90,0xFFFF);  
  152.   
  153.     DrawDynamicLine(300,300,100,300,1,0,0,90,0xFFFF);           //4  
  154.     DrawDynamicLine(300,300,100,400,1,0,0,90,0x00FF);  
  155.     DrawDynamicLine(300,300,100,500,1,0,0,90,0xFFFF);  
  156.     DrawDynamicLine(300,300,200,500,1,0,0,90,0x00FF);  
  157.     DrawDynamicLine(300,300,300,500,1,0,0,90,0xFFFF);  
  158.   
  159. }  
  160.   
  161. void reshape(int w,int h)  
  162. {  
  163.     glViewport(0,0,(GLsizei)w,(GLsizei)h);           //为了选择一个更小的绘图区域,在窗口中定义一个像素矩形,将图像映射到这个矩形中  
  164.     glMatrixMode(GL_PROJECTION);                     //指定哪一个矩阵是当前矩阵(GL_PROJECTION,对投影矩阵应用随后的矩阵操作)  
  165.     glLoadIdentity();                                //将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作    
  166.     gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);     //将当前的可视空间设置为正投影空间,这个函数描述了一个平行修剪空间,意味着离观察者较远的对象看上去不会变小    
  167. }  
  168.   
  169. int main(int argc,char** argv)                      //注意参数  
  170. {  
  171.     glutInit(&argc,argv);                           //初始化GLUT并处理命令行参数  
  172.     glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);      //指定模式:单缓存OR双缓存;RGBA模式OR颜色索引模式  
  173.     glutInitWindowSize(600,600);                    //指定窗口大小(像素)  
  174.     glutInitWindowPosition(300,50);                 //指定窗口左上角在屏幕上的位置  
  175.     glutCreateWindow(argv[0]);                      //使用OpenGL场景创建一个窗口,参数为窗口名称  
  176.     init();                                         //调用初始化函数  
  177.     glutDisplayFunc(display);                       //注册用于显示图形的回调函数,每当GLUT认为需要重绘窗口时,都会执行该函数,故应将重绘场景所需调用的函数都放到显示回调函数中。  
  178.     glutReshapeFunc(reshape);                       //重绘回调函数  
  179.     glutMainLoop();                                 //进入主循环并处理事件,此时创建的所有窗口都会显示出来,被渲染到这些窗口中的内容也将显示出来,程序开始处理事件,注册的显示回调函数被触发  
  180.     return 0;                                       //ANSI C要求函数main()返回一个int值  
  181. }  

效果如下:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值