三维空间球体爆炸

警告:本计算机程序受著作权法和国际条约保护,如未经授权而擅自复制或传播本程序,,将受到严厉的民事制裁和刑事制裁,并将在法律许可的最大程度内受到起诉。


本程序功能:

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;
}



你可能感兴趣的:(计算机,三维,爆炸,图形学,球体爆炸)