警告:本计算机程序受著作权法和国际条约保护,如未经授权而擅自复制或传播本程序,,将受到严厉的民事制裁和刑事制裁,并将在法律许可的最大程度内受到起诉。
本程序功能:
1.按方向键(上下左右)控制球体旋转。
2.按数字1 启用第一种绘图模式 按数字2 启用第二种绘图模式。
3.按'w'实现前进,按's'实现后缀 从而实现球体大小的变化。
4.在正常状态(没有处于爆炸或者复原过程),按下'r',球面的各个多边形会在原地旋转,再次按下'r',则反向旋转,
直到回复原状。
5.在正常或多边形原地正向、反向旋转状态点击鼠标左键,球体发生爆炸(无引力场),碎裂成三角形或四边形,向各个方向散去,
并在规定的空间大小边界处停止。
6.在爆炸过程中可点击右键,那么球体会按爆炸过程的逆过程回恢复原状。
7.可以在任何时刻按下空格键使画面静止,再次按下即可恢复正常运行。
#include <stdlib.h> #include <GL/glut.h> #include <stdio.h> #include <math.h> typedef struct{ double x; double y; double z; }POINT; //点 typedef struct{ POINT P[4]; //构成多边形的几个点 POINT center_p[2]; //旋转点 double times; //倍率 double incre_time; //增加的倍率 double axis[3]; //绕哪个轴转动 double angl; //旋转了多少度 double incre_ang; //增加的旋转角度 int color[3]; //三个颜色的分量 int n; //有几个点 }QUAD; //描述多边形的结构体 #define MAXSIZE 100000 //最大的粒子数 #define WINDOW_W 1300 //窗口的宽度 #define WINDOW_H 740 //窗口的高度 #define PI 3.14159265 //常量圆周率 #define RATE 2 //产生三角形的概率 POINT all_points[MAXSIZE]; QUAD my_quad[MAXSIZE]; GLfloat angle_x=0,angle_y=0,angle_z=0; //整个画面的旋转量 GLfloat angle_x_v=0,angle_y_v=0.5f,angle_z_v=0; //各个方向旋转速度 int BALL_STATE=0; //1 表示正在爆炸 0表示状态稳定 2 表示正在恢复 int NUMBER_POINTS; //总共有多少个点 int NUMBER_QUAD; //总共有几个多边形 int running=1; //是否暂停0 表示停止 double view_z=-7.0f; //与多面球的距离 int DRAW_MODE=1; //画球模式,1表示涂色,2 表示线框球 int RAD=10; //球的半径,比例化以后失去意义 int INCRE_ANGLE= 10; //划线密度值,角度增量 double space_size=40.0f; //封闭空间的大小 double create_incre_times() //产生一个随机增长倍率(0.1~0.3) { double res; res=rand()%3000/10000.0; return 0.1+res; } double create_incre_ang() //产生一个随机增长角度 { return rand()%2==0?0.7f+rand()%5:-0.7f+rand()%5; } void create_point() //找到所有的球面关键点 { double c=PI/180; NUMBER_POINTS=0; for(int i=0;i<=(180/INCRE_ANGLE);i++) { for(int j=0;j<(360/INCRE_ANGLE);j++) { double x,y,z; double depth_ang=INCRE_ANGLE*i*c; double breadth_ang=-INCRE_ANGLE*j*c; x=(RAD*sin(depth_ang))*cos(breadth_ang); y=RAD*cos(depth_ang); z=(RAD*sin(depth_ang))*sin(breadth_ang); all_points[NUMBER_POINTS].x=x/RAD; all_points[NUMBER_POINTS].y=y/RAD; all_points[NUMBER_POINTS].z=z/RAD; NUMBER_POINTS++; } } } void create_quad() //根据找到的关键点 创建多边形(三角形或四边形) { NUMBER_QUAD=0; int circle_points=360/INCRE_ANGLE; int c1,c2,min1,min2; for(int i=0;i<NUMBER_POINTS-circle_points;i++) { c1=i/circle_points; c2=c1+1; min1=c1*circle_points; min2=c2*circle_points; if(rand()%RATE==0) // 1/RATE的概率画三角形 { if(rand()%2==0) //生成正向三角形 { my_quad[NUMBER_QUAD].P[0]=all_points[i]; my_quad[NUMBER_QUAD].P[1]=all_points[min2+(i+circle_points)%circle_points]; my_quad[NUMBER_QUAD].P[2]=all_points[min2+(i+circle_points+1)%circle_points]; my_quad[NUMBER_QUAD].center_p[0].x=(my_quad[NUMBER_QUAD].P[0].x+my_quad[NUMBER_QUAD].P[1].x+my_quad[NUMBER_QUAD].P[2].x)/3; my_quad[NUMBER_QUAD].center_p[0].y=(my_quad[NUMBER_QUAD].P[0].y+my_quad[NUMBER_QUAD].P[1].y+my_quad[NUMBER_QUAD].P[2].y)/3; my_quad[NUMBER_QUAD].center_p[0].z=(my_quad[NUMBER_QUAD].P[0].z+my_quad[NUMBER_QUAD].P[1].z+my_quad[NUMBER_QUAD].P[2].z)/3; my_quad[NUMBER_QUAD].color[0]=rand()%256; my_quad[NUMBER_QUAD].color[1]=rand()%256; my_quad[NUMBER_QUAD].color[2]=rand()%256; my_quad[NUMBER_QUAD].axis[0]=rand()%200; my_quad[NUMBER_QUAD].axis[1]=rand()%200; my_quad[NUMBER_QUAD].axis[2]=rand()%200; my_quad[NUMBER_QUAD].angl=0; my_quad[NUMBER_QUAD].incre_ang=0.0f; my_quad[NUMBER_QUAD].times=1.0f; my_quad[NUMBER_QUAD].incre_time=0.0f; my_quad[NUMBER_QUAD].n=3; NUMBER_QUAD++; my_quad[NUMBER_QUAD].P[0]=all_points[i]; my_quad[NUMBER_QUAD].P[1]=all_points[min1+(i+1)%circle_points]; my_quad[NUMBER_QUAD].P[2]=all_points[min2+(i+1+circle_points)%circle_points]; my_quad[NUMBER_QUAD].center_p[0].x=(my_quad[NUMBER_QUAD].P[0].x+my_quad[NUMBER_QUAD].P[1].x+my_quad[NUMBER_QUAD].P[2].x)/3; my_quad[NUMBER_QUAD].center_p[0].y=(my_quad[NUMBER_QUAD].P[0].y+my_quad[NUMBER_QUAD].P[1].y+my_quad[NUMBER_QUAD].P[2].y)/3; my_quad[NUMBER_QUAD].center_p[0].z=(my_quad[NUMBER_QUAD].P[0].z+my_quad[NUMBER_QUAD].P[1].z+my_quad[NUMBER_QUAD].P[2].z)/3; my_quad[NUMBER_QUAD].color[0]=rand()%256; my_quad[NUMBER_QUAD].color[1]=rand()%256; my_quad[NUMBER_QUAD].color[2]=rand()%256; my_quad[NUMBER_QUAD].axis[0]=rand()%200; my_quad[NUMBER_QUAD].axis[1]=rand()%200; my_quad[NUMBER_QUAD].axis[2]=rand()%200; my_quad[NUMBER_QUAD].angl=0; my_quad[NUMBER_QUAD].incre_ang=0.0f; my_quad[NUMBER_QUAD].times=1.0f; my_quad[NUMBER_QUAD].incre_time=0.0f; my_quad[NUMBER_QUAD].n=3; NUMBER_QUAD++; } else //生成反向三角形 { my_quad[NUMBER_QUAD].P[0]=all_points[i]; my_quad[NUMBER_QUAD].P[1]=all_points[min1+(i+1)%circle_points]; my_quad[NUMBER_QUAD].P[2]=all_points[min2+(i+circle_points)%circle_points]; my_quad[NUMBER_QUAD].center_p[0].x=(my_quad[NUMBER_QUAD].P[0].x+my_quad[NUMBER_QUAD].P[1].x+my_quad[NUMBER_QUAD].P[2].x)/3; my_quad[NUMBER_QUAD].center_p[0].y=(my_quad[NUMBER_QUAD].P[0].y+my_quad[NUMBER_QUAD].P[1].y+my_quad[NUMBER_QUAD].P[2].y)/3; my_quad[NUMBER_QUAD].center_p[0].z=(my_quad[NUMBER_QUAD].P[0].z+my_quad[NUMBER_QUAD].P[1].z+my_quad[NUMBER_QUAD].P[2].z)/3; my_quad[NUMBER_QUAD].color[0]=rand()%256; my_quad[NUMBER_QUAD].color[1]=rand()%256; my_quad[NUMBER_QUAD].color[2]=rand()%256; my_quad[NUMBER_QUAD].axis[0]=rand()%200; my_quad[NUMBER_QUAD].axis[1]=rand()%200; my_quad[NUMBER_QUAD].axis[2]=rand()%200; my_quad[NUMBER_QUAD].angl=0; my_quad[NUMBER_QUAD].incre_ang=0.0f; my_quad[NUMBER_QUAD].times=1.0f; my_quad[NUMBER_QUAD].incre_time=0.0f; my_quad[NUMBER_QUAD].n=3; NUMBER_QUAD++; my_quad[NUMBER_QUAD].P[0]=all_points[min1+(i+1)%circle_points]; my_quad[NUMBER_QUAD].P[1]=all_points[min2+(i+1+circle_points)%circle_points]; my_quad[NUMBER_QUAD].P[2]=all_points[min2+(i+circle_points)%circle_points]; my_quad[NUMBER_QUAD].center_p[0].x=(my_quad[NUMBER_QUAD].P[0].x+my_quad[NUMBER_QUAD].P[1].x+my_quad[NUMBER_QUAD].P[2].x)/3; my_quad[NUMBER_QUAD].center_p[0].y=(my_quad[NUMBER_QUAD].P[0].y+my_quad[NUMBER_QUAD].P[1].y+my_quad[NUMBER_QUAD].P[2].y)/3; my_quad[NUMBER_QUAD].center_p[0].z=(my_quad[NUMBER_QUAD].P[0].z+my_quad[NUMBER_QUAD].P[1].z+my_quad[NUMBER_QUAD].P[2].z)/3; my_quad[NUMBER_QUAD].color[0]=rand()%256; my_quad[NUMBER_QUAD].color[1]=rand()%256; my_quad[NUMBER_QUAD].color[2]=rand()%256; my_quad[NUMBER_QUAD].axis[0]=rand()%200; my_quad[NUMBER_QUAD].axis[1]=rand()%200; my_quad[NUMBER_QUAD].axis[2]=rand()%200; my_quad[NUMBER_QUAD].angl=0; my_quad[NUMBER_QUAD].incre_ang=0.0f; my_quad[NUMBER_QUAD].times=1.0f; my_quad[NUMBER_QUAD].incre_time=0.0f; my_quad[NUMBER_QUAD].n=3; NUMBER_QUAD++; } } else //否则生成四边形 { my_quad[NUMBER_QUAD].P[0]=all_points[i]; my_quad[NUMBER_QUAD].P[1]=all_points[min1+(i+1)%circle_points]; my_quad[NUMBER_QUAD].P[2]=all_points[min2+(i+1+circle_points)%circle_points]; my_quad[NUMBER_QUAD].P[3]=all_points[min2+(i+circle_points)%circle_points]; my_quad[NUMBER_QUAD].center_p[0].x=(my_quad[NUMBER_QUAD].P[0].x+my_quad[NUMBER_QUAD].P[1].x+my_quad[NUMBER_QUAD].P[2].x+my_quad[NUMBER_QUAD].P[3].x)/4; my_quad[NUMBER_QUAD].center_p[0].y=(my_quad[NUMBER_QUAD].P[0].y+my_quad[NUMBER_QUAD].P[1].y+my_quad[NUMBER_QUAD].P[2].y+my_quad[NUMBER_QUAD].P[3].y)/4; my_quad[NUMBER_QUAD].center_p[0].z=(my_quad[NUMBER_QUAD].P[0].z+my_quad[NUMBER_QUAD].P[1].z+my_quad[NUMBER_QUAD].P[2].z+my_quad[NUMBER_QUAD].P[3].z)/4; my_quad[NUMBER_QUAD].color[0]=rand()%256; my_quad[NUMBER_QUAD].color[1]=rand()%256; my_quad[NUMBER_QUAD].color[2]=rand()%256; my_quad[NUMBER_QUAD].axis[0]=rand()%200; my_quad[NUMBER_QUAD].axis[1]=rand()%200; my_quad[NUMBER_QUAD].axis[2]=rand()%200; my_quad[NUMBER_QUAD].angl=0; my_quad[NUMBER_QUAD].incre_ang=0.0f; my_quad[NUMBER_QUAD].times=1.0f; my_quad[NUMBER_QUAD].incre_time=0.0f; my_quad[NUMBER_QUAD].n=4; NUMBER_QUAD++; } } for(int i=0;i<NUMBER_QUAD;i++) //用于存贮原先的位置 my_quad[i].center_p[1]=my_quad[i].center_p[0]; } void ReShap(int width, int height) // 重置OpenGL窗口大小 { glViewport(0,0,width,height); // 重置当前的视口 glMatrixMode(GL_PROJECTION); // 选择投影矩阵 glLoadIdentity(); // 重置投影矩阵 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); // 选择模型观察矩阵 glLoadIdentity(); // 重置模型观察矩阵 } void Initial() //初始化 { create_point(); create_quad(); printf("共有%d个点\n",NUMBER_POINTS); printf("共有%d个多边形\n",NUMBER_QUAD); glMatrixMode(GL_PROJECTION); // 选择投影矩阵 glLoadIdentity(); // 重置投影矩阵 gluPerspective(30.0f,(GLfloat)WINDOW_W/(GLfloat)WINDOW_H,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); // 选择模型观察矩阵 glLoadIdentity(); // 重置模型观察矩阵 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景 glClearDepth(1.0f); // 设置深度缓存 glEnable(GL_DEPTH_TEST); // 启用深度测试 glDepthFunc(GL_LEQUAL); // 所作深度测试的类型 glHint(GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST); // 告诉系统对透视进行修正 } void draw001() //第一种绘图模式的绘制函数 { POINT center_p; double x,y,z,d; for(int i=0;i<NUMBER_QUAD;i++) { x=my_quad[i].center_p[0].x; y=my_quad[i].center_p[0].y; z=my_quad[i].center_p[0].z; d=sqrt(x*x+y*y+z*z); d*=my_quad[i].times; if(my_quad[i].incre_time<0||d<space_size) my_quad[i].times+=my_quad[i].incre_time; if(my_quad[i].incre_time<0&&d-1<0) //复原状态而且进入 { my_quad[i].center_p[0]=my_quad[i].center_p[1]; my_quad[i].times=1.0f; my_quad[i].incre_time=0.0f; my_quad[i].incre_ang=0.0f; my_quad[i].angl=0.0f; if(i==NUMBER_QUAD-1) BALL_STATE=0; //最后一个粒子完成任务///错误 } if(BALL_STATE==5&&abs(my_quad[i].angl)<0.1) //原地旋转 { my_quad[i].incre_ang=0.0f; my_quad[i].angl=0.0f; if(i==NUMBER_QUAD-1) BALL_STATE=0; //最后一个粒子完成任务///错误 } center_p=my_quad[i].center_p[0]; glPushMatrix(); glTranslatef(center_p.x*my_quad[i].times,center_p.y*my_quad[i].times,center_p.z*my_quad[i].times); glPushMatrix(); my_quad[i].angl+=my_quad[i].incre_ang; glRotatef(my_quad[i].angl,my_quad[i].axis[0],my_quad[i].axis[1],my_quad[i].axis[2]); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glColor3ub(my_quad[i].color[0],my_quad[i].color[1],my_quad[i].color[2]); glBegin(GL_POLYGON); for(int j=0;j<my_quad[i].n;j++) glVertex3f(my_quad[i].P[j].x-center_p.x,my_quad[i].P[j].y-center_p.y,my_quad[i].P[j].z-center_p.z); glEnd(); glPopMatrix(); glPopMatrix(); } } void draw002() //第二种绘图模式的绘制函数 { POINT center_p; double x,y,z,d; for(int i=0;i<NUMBER_QUAD;i++) { x=my_quad[i].center_p[0].x; y=my_quad[i].center_p[0].y; z=my_quad[i].center_p[0].z; d=sqrt(x*x+y*y+z*z); d*=my_quad[i].times; //printf("d=%f\n",d); if(my_quad[i].incre_time<0||d<space_size) my_quad[i].times+=my_quad[i].incre_time; if(my_quad[i].incre_time<0&&d-1<0) //复原状态而且进入 { my_quad[i].center_p[0]=my_quad[i].center_p[1]; my_quad[i].times=1.0f; my_quad[i].incre_time=0.0f; my_quad[i].incre_ang=0.0f; my_quad[i].angl=0.0f; if(i==NUMBER_QUAD-1) BALL_STATE=0; //最后一个粒子完成任务///错误 } if(BALL_STATE==5&&abs(my_quad[i].angl)<0.1) //原地旋转 { my_quad[i].incre_ang=0.0f; my_quad[i].angl=0.0f; if(i==NUMBER_QUAD-1) BALL_STATE=0; //最后一个粒子完成任务///错误 } center_p=my_quad[i].center_p[0]; glPushMatrix(); glTranslatef(center_p.x*my_quad[i].times,center_p.y*my_quad[i].times,center_p.z*my_quad[i].times); glPushMatrix(); my_quad[i].angl+=my_quad[i].incre_ang; glRotatef(my_quad[i].angl,my_quad[i].axis[0],my_quad[i].axis[1],my_quad[i].axis[2]); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glColor3ub(255,255,0); glBegin(GL_POLYGON); for(int j=0;j<my_quad[i].n;j++) glVertex3f(my_quad[i].P[j].x-center_p.x,my_quad[i].P[j].y-center_p.y,my_quad[i].P[j].z-center_p.z); glEnd(); glPopMatrix(); glPopMatrix(); } } void Display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存 glLoadIdentity(); //重置当前的模型观察矩阵 glTranslatef(0.0f,0.0f,view_z); glRotatef(angle_x,1.0f,0.0f,0.0f); glRotatef(angle_y,0.0f,1.0f,0.0f); glRotatef(angle_z,0.0f,0.0f,1.0f); if(DRAW_MODE==1) draw001(); if(DRAW_MODE==2) draw002(); angle_x+=angle_x_v; angle_y+=angle_y_v; // 整个画面的旋转量 glFlush(); } void timer(int value) //定时器函数,刷新屏幕 { if(running) glutPostRedisplay(); glutTimerFunc(20,timer,1); } void mouse(int btn, int state, int x, int y) //监听鼠标 { if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) { if(BALL_STATE==0||BALL_STATE==4||BALL_STATE==5) //正常,正向,反向状态 { for(int i=0;i<NUMBER_QUAD;i++) { my_quad[i].incre_time=create_incre_times(); my_quad[i].incre_ang=create_incre_ang(); } BALL_STATE=1; //爆炸状态 } } if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN) { if(BALL_STATE==1) //爆炸状态 { for(int i=0;i<NUMBER_QUAD;i++) { my_quad[i].incre_time*=-1.0f; my_quad[i].incre_ang*=-1.0f; } BALL_STATE=2; //复原状态 } } } void keys(unsigned char key, int x, int y) { int i=0; switch(key) { case '1': DRAW_MODE=1; BALL_STATE=0; break; case '2': DRAW_MODE=2; BALL_STATE=0; break; case 'w': view_z+=0.5; break; case 's': view_z-=0.5; break; case '=': BALL_STATE=0; INCRE_ANGLE+=5; if(INCRE_ANGLE>90) INCRE_ANGLE=90; create_point(); create_quad(); printf("共有%d个点\n",NUMBER_POINTS); printf("共有%d个多边形\n",NUMBER_QUAD); break; case '-': BALL_STATE=0; INCRE_ANGLE-=5; if(INCRE_ANGLE<5) INCRE_ANGLE=5; create_point(); create_quad(); printf("共有%d个点\n",NUMBER_POINTS); printf("共有%d个多边形\n",NUMBER_QUAD); break; case ' ': running++; running%=2; break; case 'r': if(BALL_STATE==0) //正常状态 { for(i=0;i<NUMBER_QUAD;i++) my_quad[i].incre_ang=create_incre_ang(); BALL_STATE=4; //正向旋转状态 } else if(BALL_STATE==4) { for(i=0;i<NUMBER_QUAD;i++) my_quad[i].incre_ang*=-1.0f; BALL_STATE=5; //反向旋转状态 } break; default: break; } } void specialFunc(int reductionKey,int x,int y) //特殊按键监听 { switch(reductionKey) { case GLUT_KEY_UP: angle_x_v-=0.5; break; case GLUT_KEY_DOWN: angle_x_v+=0.5; break; case GLUT_KEY_LEFT: angle_y_v-=0.5; break; case GLUT_KEY_RIGHT: angle_y_v+=0.5; break; default: break; } } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); //初始化窗口的显示模式 glutInitWindowSize(WINDOW_W,WINDOW_H); //设置窗口的尺寸 glutInitWindowPosition(0,0); //设置窗口的位置 glutCreateWindow("矩形"); //创建一个名为矩形的窗口 glutDisplayFunc(Display); //设置当前窗口的显示回调函数 Initial(); //完成窗口初始化 glutTimerFunc(50,timer,1); //注册定时器 glutMouseFunc (mouse); glutKeyboardFunc(keys); glutSpecialFunc(specialFunc); glutReshapeFunc(ReShap); glutMainLoop(); return 0; }