计算机图形学:机器人的画法与填充
2015-11-09 15:24
435 查看
详情请见 http://cuiqingcai.com/1597.html http://cuiqingcai.com/1640.html
#include<windows.h> #include<iostream> #include<GL/glut.h> #include <math.h> #include<stack> #define PI 3.1415926 using namespace std; int halfWidth,halfHeight; GLubyte borderColor[3]; struct Point { int x; int y; }; //画矩形,传入的是左下角XY坐标和右上角XY坐标 void glRect(int leftX,int leftY,int rightX,int rightY){ //画封闭曲线 glBegin(GL_LINE_LOOP); //左下角 glVertex2d(leftX,leftY); //右下角 glVertex2d(rightX,leftY); //右上角 glVertex2d(rightX,rightY); //左上角 glVertex2d(leftX,rightY); //结束画线 glEnd(); } //画圆角矩形,传入矩形宽高,角半径,矩形中心点坐标 void glRoundRec(int centerX,int centerY,int width,int height,float cirR){ //二分之PI,一个象限的角度 float PI_HALF = PI/2; //划分程度,值越大画得越精细 float divide=20.0; //圆角矩形的坐标 float tx,ty; //画封闭曲线 glBegin(GL_LINE_LOOP); //四个象限不同的操作符 int opX[4]={1,-1,-1,1}; int opY[4]={1,1,-1,-1}; //用来计数,从第一象限到第四象限 float x=0; //x自增时加的值 float part=1/divide; //计算内矩形宽高一半的数值 int w=width/2-cirR; int h=height/2-cirR; //循环画线 for(x=0;x<4;x+=part){ //求出弧度 float rad = PI_HALF*x; //计算坐标值 tx=cirR*cos(rad)+opX[(int)x]*w+centerX; ty=cirR*sin(rad)+opY[(int)x]*h+centerY; //传入坐标画线 glVertex2f(tx,ty); } //结束画线 glEnd(); } //画弧线,相对偏移量XY,开始的弧度,结束的弧度,半径 void glArc(double x,double y,double start_angle,double end_angle,double radius) { //开始绘制曲线 glBegin(GL_LINE_STRIP); //每次画增加的弧度 double delta_angle=PI/180; //画圆弧 for (double i=start_angle;i<=end_angle;i+=delta_angle) { //绝对定位加三角函数值 double vx=x+radius * cos(i); double vy=y+radius*sin(i); glVertex2d(vx,vy); } //结束绘画 glEnd(); } //画圆 void glCircle(double x, double y, double radius) { //画全圆 glArc(x,y,0,2*PI,radius); } //画三角形,传入三个点的坐标 void glTri(int x1,int y1,int x2,int y2,int x3,int y3){ //画封闭线 glBegin(GL_LINE_LOOP); //一点 glVertex2d(x1,y1); //二点 glVertex2d(x2,y2); //三点 glVertex2d(x3,y3); //结束画线 glEnd(); } //画线,传入两点坐标 void glLine(int x1,int y1,int x2,int y2){ //画封闭线 glBegin(GL_LINE_STRIP); //一点 glVertex2d(x1,y1); //二点 glVertex2d(x2,y2); //结束画线 glEnd(); } //传入两个颜色的RGB值,比较是否相同,容差为dis bool sameColor(int r1,int g1,int b1,int r2,int g2,int b2){ //容差度 int dis = 10; if(abs(r1-r2)<=dis&&abs(g1-g2)<=dis&&abs(b1-b2)<=dis){ return true; }else{ return false; } } //画点 void glPoint(int x,int y,int r,int g,int b){ glColor3ub (r,g,b); glPointSize(1); glBegin(GL_POINTS); glVertex2i(x,y); glEnd(); glFlush(); } //种子填充算法 void zzFill(int startX,int startY,int r,int g,int b){ GLubyte iPixel[3]; stack<Point> pixelStack; //x,y是给定的种子像素点,rgb就是要填充的颜色的RGB值 Point point = {startX,startY}; pixelStack.push(point); int saveX; int xRight,xLeft; int x,y; //如果栈不为空 while(!pixelStack.empty()){ //获取最顶端的元素 Point tempPoint=pixelStack.top(); //删除最顶端的元素 pixelStack.pop(); saveX=tempPoint.x; x=tempPoint.x; y=tempPoint.y; glReadPixels(x+halfWidth,y+halfHeight,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); //如果没有到达右边界,就填充 while(!sameColor(iPixel[0],iPixel[1],iPixel[2],borderColor[0],borderColor[1],borderColor[2])){ glPoint(x,y,r,g,b); x=x+1; glReadPixels(x+halfWidth,y+halfHeight,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); } xRight=x-1; x=saveX-1; glReadPixels(x+halfWidth,y+halfWidth,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); //如果没有到达左边界,就填充 while(!sameColor(iPixel[0],iPixel[1],iPixel[2],borderColor[0],borderColor[1],borderColor[2])){ glPoint(x,y,r,g,b); x=x-1; glReadPixels(x+halfWidth,y+halfWidth,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); } //保存左端点 xLeft=x+1; //从右边的点开始 x=xRight; //检查上端的扫描线 y=y+1; while(x>=xLeft){ glReadPixels(x+halfWidth,y+halfWidth,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); if(!sameColor(iPixel[0],iPixel[1],iPixel[2],borderColor[0],borderColor[1],borderColor[2])&&!sameColor(iPixel[0],iPixel[1],iPixel[2],r,g,b)){ //如果上方的点不是边界点,直接压入 Point p={x,y}; pixelStack.push(p); //压入之后停止循环 break; }else{ x--; glReadPixels(x+halfWidth,y+halfWidth,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); } } //检查下端的扫描线 y=y-2; //从右边的点开始 x=xRight; while(x>=xLeft){ glReadPixels(x+halfWidth,y+halfWidth,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); if(!sameColor(iPixel[0],iPixel[1],iPixel[2],borderColor[0],borderColor[1],borderColor[2])&&!sameColor(iPixel[0],iPixel[1],iPixel[2],r,g,b)){ //如果上方的点不是边界点,直接压入 Point p={x,y}; //压入之后停止循环 pixelStack.push(p); break; }else{ x--; glReadPixels(x+halfWidth,y+halfWidth,1,1,GL_RGB,GL_UNSIGNED_BYTE,&iPixel); } } } } //函数用来画图 void display(void) { //GL_COLOR_BUFFER_BIT表示清除颜色 glClear(GL_COLOR_BUFFER_BIT); //设置画线颜色 //glColor3f(0.5,0.5,0.5); glColor3ub(100,100,100); borderColor[0]=borderColor[1]=borderColor[2]=100; //画点大小 glPointSize(2); //画圆角矩形,大肚子 glRoundRec(0,0,146,120,15); //画圆,中间小圈 glCircle(0,0,10); //画矩形,脖子 glRect(-25,60,25,76); //画圆角矩形,大脸 glRoundRec(0,113,128,74,10); //两个眼睛 glCircle(-30,111,10); glCircle(30,111,10); //两条天线 glLine(-35,150,-35,173); glLine(35,150,35,173); //圆角矩形,两个耳朵 glRoundRec(81,115,20,34,5); glRoundRec(-81,115,20,34,5); //圆弧,画嘴 glArc(0,133,11*PI/8,13*PI/8,45); //画三角,肚子里的三角 glTri(-30,-15,30,-15,0,28); //画矩形,胳膊连接处 glRect(-81,43,-73,25); glRect(81,43,73,25); //画矩形,上臂 glRect(-108,45,-81,0); glRect(108,45,81,0); //画矩形,中臂 glRect(-101,0,-88,-4); glRect(101,0,88,-4); //画矩形,下臂 glRect(-108,-4,-81,-37); glRect(108,-4,81,-37); //画圆形,手掌 glCircle(-95,-47,10); glCircle(95,-47,10); //画腿连接处 glRect(-41,-62,-21,-66); glRect(41,-62,21,-66); //画圆角矩形,大长腿 glRoundRec(-32,-92,38,52,10); glRoundRec(32,-92,38,52,10); //画矩形,脚踝 glRect(-41,-125,-21,-117); glRect(41,-125,21,-117); //画矩形,大脚掌 glRect(-59,-125,-8,-137); glRect(59,-125,8,-137); //灰色:195,195,195 //黄色:255,243,0 //红色:237,28,36 //深灰色:126,126,126 //脖子 zzFill(0,70,195,195,195); //头 zzFill(-50,110,195,195,195); zzFill(0,93,195,195,195); //肚子 zzFill(-50,0,195,195,195); //耳朵 zzFill(-80,115,126,126,126); zzFill(80,115,126,126,126); //肚子三角 zzFill(-20,-10,255,243,0); //肚子红色圆 zzFill(0,0,237,28,36); //zzFill(-50,0,128,255,33); //大臂 zzFill(-90,30,126,126,126); zzFill(90,30,126,126,126); //小臂 zzFill(-90,-20,126,126,126); zzFill(90,-20,126,126,126); //手 zzFill(-75,40,195,195,195); zzFill(75,40,195,195,195); //手 zzFill(-95,-47,195,195,195); zzFill(95,-47,195,195,195); //大腿连接处 zzFill(-40,-64,195,195,195); zzFill(40,-64,195,195,195); //大腿 zzFill(-40,-100,126,126,126); zzFill(40,-100,126,126,126); //脚踝 zzFill(-40,-121,195,195,195); zzFill(40,-121,195,195,195); //脚掌 zzFill(-40,-130,126,126,126); zzFill(40,-130,126,126,126); system("pause"); //保证前面的OpenGL命令立即执行,而不是让它们在缓冲区中等待 glFlush(); } //窗口大小变化时调用的函数 void ChangeSize(GLsizei w,GLsizei h) { //避免高度为0 if(h==0) { h=1; } //定义视口大小,宽高一致 glViewport(0,0,w,h); int half = 200; //重置坐标系统,使投影变换复位 glMatrixMode(GL_PROJECTION); //将当前的用户坐标系的原点移到了屏幕中心 glLoadIdentity(); //定义正交视域体 if(w<h) { //如果高度大于宽度,则将高度视角扩大,图形显示居中 glOrtho(-half,half,-half*h/w,half*h/w,-half,half); } else { //如果宽度大于高度,则将宽度视角扩大,图形显示居中 glOrtho(-half*w/h,half*w/h,-half,half,-half,half); } } //程序入口 int main(int argc, char *argv[]){ //对GLUT进行初始化,并处理所有的命令行参数 glutInit(&argc, argv); //指定RGB颜色模式和单缓冲窗口 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //定义窗口的位置 glutInitWindowPosition(100, 100); //定义窗口的大小 glutInitWindowSize(400, 400); halfHeight=halfWidth=200; //创建窗口,同时为之命名 glutCreateWindow("OpenGL"); //设置窗口清除颜色为白色 glClearColor(1.0f,1.0f,1.0f,1.0f); //参数为一个函数,绘图时这个函数就会被调用 glutDisplayFunc(&display); //参数为一个函数,当窗口大小改变时会被调用 glutReshapeFunc(ChangeSize); //该函数让GLUT框架开始运行,所有设置的回调函数开始工作,直到用户终止程序为止 glutMainLoop(); //程序返回 return 0; }
相关文章推荐
- Android快速开发Android-Async-Http
- IOS网络图片缓存详解
- python数据结构学习笔记-4-链表
- 计算机的潜意识
- 数据结构与算法javascript描述(三) 二叉查找树 先序,中序,后续遍历
- ARM硬件平台上基于UCOS移植Lwip网络协议栈
- DNS可以使用TCP和UDP 协议,TCP和UDP的区别
- 反向传播神经网络极简入门
- 机器视觉会议以及牛人
- Android OkHttp
- VMware虚拟机上网络连接(network type)的三种模式--bridged、host-only、NAT
- HttpClient工具类
- 网络收集javaScript中常用的基本验证
- http协议下载文件
- 一个异步网络请求的坑:关于NSURLConnection和NSRunLoopCommonModes
- nc.exe 使用方法
- http://my.oschina.net/u/1245614/blog/481573?p={{page}}
- 打杂程序员之公司网络配置
- Android学习之Android中Http通信:Http协议
- TCP——_SYN、ACK_、FIN、RST、PSH、URG_详解