当前位置:文档之家› OPENGL沙漏程序

OPENGL沙漏程序

#include
#include
#include
#define MAXSIZE 100000 //数组存储的最大值
using namespace std;

struct point
{
public:
double x,y;
double n_x,n_y;
}; //沙子数据结构,x,y记录沙子初始位置,n_x,n_y记录沙子当前的位置

point point[MAXSIZE]; //沙子位置存储数组
int WW=600,WH=600; //窗口大小
int p=0; //时间函数控制沙子
int type=1; //1下落 2旋转 -1或者-2暂停

double angle_z=0.0f; //旋转角度记录变量
double dis_of_point=5.0f; //沙子间的距离
int time=0; //记录时间的变量
int num=0; //沙子总数
int height=500; //沙漏高度
int trangle_width=500; //沙漏宽度
int timer=1; //时间回调函数间隔

int t_height=0; //沙漏高度变化缓冲变量
int t_width=0; //沙漏宽度变化缓冲变量

int h1,h2,h3,h4,h5;
int d1,d2,d3,d4;

void displaytip()
{
printf("***************************************************************\n");
printf("按e输出当前时间\n");
printf("按r直接旋转\n");
printf("按u增加沙子间距\n");
printf("按i减少沙子间距\n");
printf("按z减缓下落速度(仅供测试用)\n");
printf("按x恢复下落速度\n");
printf("按上方向键,增加沙漏的高度,在旋转一次重置后生效\n");
printf("按下方向键,减少沙漏的高度,在旋转一次重置后生效\n");
printf("按左方向键,增加沙漏的宽度,在旋转一次重置后生效\n");
printf("按右方向键,减少沙漏的宽度,在旋转一次重置后生效\n");
printf("空格和鼠标单击暂停\n");
printf("***************************************************************\n");
printf("当前共有%d个沙子\n",num);
printf("一共需要%d'%d''\n",num/1000,num%1000);

}
/************************沙子位置初始化********************************************************/
void init(int o)//o为1时重置沙子位置在上半部,为-1时沙子位置的下半个沙漏

{
num=0;
int y_num=height/dis_of_point-1,x_num; //y_num计算一共有多少行沙子
for(int i=y_num;i>=0;i--)

{
double h=i*dis_of_point; //当前高度
double length=(trangle_width*h)/height; //当前宽度
x_num=length/dis_of_point; //x_num计算每行有多少个沙子
for(int j=0;j{ //右边的沙子
point[num].x=j*dis_of_point/WW; //记录相对于窗口的坐标
point[num].y=i*dis_of_point/WH;
point[num].n_x=j*dis_of_point/WW;
point[num].n_y=i*o*dis_of_point/WH;
//左边的沙子
num++;
point[num].x=-j*dis_of_point/WW;
point[num].y=i*dis_of_point/WH;
point[num].n_x=-j*dis_of_point/WW;
point[num].n_y=i*o*dis_of_point/WH;
num++;

}
}



h5=height/dis_of_point-1;
h4=16*h5/25;
h3=9*h5/25;
h2=4*h5/25;
h1=1*h5/25;

d1=h2-h1;
d2=

h3-h2;
d3=h4-h3;
d4=h5-h4;
}

/************************重置OpenGL窗口********************************************************/
void re_shap(int ww, int wh) // 重置OpenGL窗口大小
{
glViewport(0,0,ww,wh); // 重置当前的视口
glClearColor(0.0, 0.0, 0.0, 1.0);
glLoadIdentity();
glMatrixMode (GL_PROJECTION);
gluOrtho2D(-1, 1, -1, 1); //指定二维裁剪窗口
}
/************************沙子绘制********************************************************/
void points ()
{
glColor3f(1.0, 1.0, 0.0);

glBegin(GL_POINTS);
for(int i=0;i{
glVertex2f(point[i].n_x, point[i].n_y);
}
glEnd();
}
/************************三角形绘制********************************************************/
void triangle ()
{
glColor3f(1.0, 0.0, 0.0);

double w=trangle_width/(WW*1.0f);
double h=height/(WH*1.0f);
glPushMatrix();//压入当前矩阵堆栈
// glViewport(25, 25, 400, 400);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);//多边形模式为线框

glBegin(GL_TRIANGLES);
glVertex2f(0.0, 0.0);
glVertex2f(w, -h);
glVertex2f(-w, -h);
glVertex2f(0.0, 0.0);
glVertex2f(w, h);
glVertex2f(-w, h);
glEnd();
glPopMatrix();//弹出栈顶的矩阵,并将其删除
}
/************************窗口初始化********************************************************/
void initial(void)
{

init(1);
displaytip();

glClearColor(0.0, 0.0, 0.0, 0.0);
glViewport(0,0,WW,WH);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1, 1, -1, 1); //指定二维裁剪窗口
}
/************************实时绘制函数********************************************************/
void display(void)
{

glClear(GL_COLOR_BUFFER_BIT);

if(type==2)//type=2为旋转
{
glLoadIdentity();
angle_z+=1.0;
glRotatef(angle_z,0.0,0.0,1.0);
if(angle_z>=180)
{
glLoadIdentity();
type=1;
if(t_height!=0)//改变沙漏高度
{
height=height+50*t_height;
t_height=0;
}
if(t_width!=0)//改变沙漏宽度
{
trangle_width=trangle_width+50*t_width;
t_width=0;
}
init(1);//旋转后重置沙子位置

angle_z=0.0;
time=0;//旋转后时间清零
system("cls");
displaytip();
}
}
points();
triangle();

glFlush();
glutSwapBuffers ();
}
/************************时间函数********************************************************/
void TimerFunc(int value)
{

if(type==1)//type=1为下落,一次取5个沙子产生下落的细节
{
if(p>=0)
{
point[p].n_y=dis_of_point*(-h1-(rand()%d1+1))/WH;
point[p].n_x=0;
}
if(p>=1)
{
point[p-1].n_y=dis_of_point*(-h2-(rand()%d2+1))/WH;
point[p-1].n_x=0;
}
if(p>=2)
{
point[p-2].n_y=dis_of_point*(-h3-(rand()%h3+1))/WH;
point[p-2].n_x=0;
}
if(p>=3)
{
point[p-3].n_y=dis_of_point*(-h4-(rand()%d4+1))/WH;

point[p-3].n_x=0;
}
if(p>=4)
{
point[p-4].n_x=point[p-4].x;
point[p-4].n_y=-point[p-4].y;
}
if(p==num)
{
for(int i=num;i>num-5;i--)

{
point[i].n_x=point[i].x;
point[i].n_y=-point[i].y;
}
}
time++;
p++;
if(p>num)
{
type=2;//全部下落后旋转
p=0;
cout<<"计时结束";
}
}
glutPostRedisplay();
glutTimerFunc(timer, TimerFunc, 1);
}
/************************鼠标输入监听********************************************************/
void mouse(int btn, int state, int x, int y)
{
if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) //鼠标单击取type负值,实现暂停
{
type=-type;
}
}
/************************键盘输入监听********************************************************/
void keyboard (unsigned char key, int x, int y)
{
switch (key)
{
case 'e'://按e键,显示当前时间
system("cls");
displaytip();
printf("当前时间为%d'%d''\n",time/1000,time%1000);
break;
case 'r'://按r,重置沙子在下半部后直接旋转
type=2;
init(-1);
p=0;
break;
case 'u'://按u,增加沙子间的间距,最大距离为45
dis_of_point=dis_of_point+5.0f;
if(dis_of_point==50)
dis_of_point=dis_of_point-5.0f;
break;
case 'i'://按i,减少沙子间的间距,最小距离为5
dis_of_point=dis_of_point-5.0f;
if(dis_of_point==0)
dis_of_point=dis_of_point+5.0f;
break;
case ' '://按空格暂停
type=-type;
break;
case 'z'://
timer=100;
break;
case 'x'://
timer=1;
break;

default:
break;
}
}
/************************特殊按键监听********************************************************/
void specialFunc(int reductionKey,int x,int y)
{

switch(reductionKey)
{
case GLUT_KEY_UP://上方向键,增加沙漏的高度,在旋转一次重置后生效
if(height<600)
t_height=1;
break;
case GLUT_KEY_DOWN://下方向键,减少沙漏的高度,在旋转一次重置后生效
if(height>100)
t_height=-1;
break;
case GLUT_KEY_LEFT://左方向键,增加沙漏的宽度,在旋转一次重置后生效
if(trangle_width<600)
t_width=1;
break;
case GLUT_KEY_RIGHT://右方向键,减少沙漏的宽度,在旋转一次重置后生效
if(trangle_width>100)
t_width=-1;
break;
default: break;
}
}

/************************主函数********************************************************/
void main(int argc, char **argv)
{

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize(WW, WH);
glutInitWindowPosition(300, 50);
glutCreateWindow("沙漏");
initial();
glutDisplayFunc(display);//各种回调函数

glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutSpecialFunc(specialFunc);
glutTimerFunc(timer, TimerFunc, 1);
glutReshapeFunc(re_shap);

glutMainLoop();
}


相关主题
文本预览
相关文档 最新文档