您的位置:首页 > 理论基础

计算机图形学:机器人的画法与填充

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: