正文

OpenGL下实现鼠标交互式的程序2009-04-23 22:49:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/jiagleo/42301.html

分享到:

    最近在用OpenGL做三维程序,其中用到了用鼠标使物体旋转的功能,于是欣然将其总结一下,做成另一个完整的程序,下面将给出整个程序的源代码。

 

一,所需支持

    程序使用了GLUT库,需要下载库文件,执行时需要相应的动态链接库。在Windows平台下的下载地址:http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip。如果找不到就在http://www.opengl.org/主页找一下吧。

Windows环境下安装GLUT的步骤:  

1、将下载的压缩包解开,将得到5个文件

2、假设C盘是系统盘,Microsoft Visual Studio安装在c:\Program Files\  

1glut.h 放在“c:\Program Files\Microsoft Visual Studio\VC98\include\GL”;

2glut.libglut32.lib放在“c:\Program Files\Microsoft Visual Studio\VC98\lib”;

3glut.dllglut32.dll放到“C:\Windows\System32

 

二,原理


 x = r * sin(φ) * cos(α)

 z = r * sin(φ) * sin(α)

 y = r * cos(φ)

鼠标的水平移动导致α改变,鼠标的垂直移动导致φ改变

 

三,源程序

(将此代码保存为file.c,然后编译链接即可执行了)

#include <stdlib.h>

#include <stdio.h>

#include <math.h> 

#include <GL/glut.h>            /*OpenGL Utility Toolkit*//*该文件已包含了GL.h Glu.h*/

 

#define DEG_TO_RAD 0.017453

#define TRUE 1

#define FALSE 0

 

struct POINT                      /*用于记录鼠标位置*/

{

       int x;

       int y;

};

 

struct CAMERA                   /*用于摄像机定位*/

{

       GLfloat   xeye;

       GLfloat yeye;

       GLfloat zeye;

};

 

struct POLAR               /*球坐标*/

{

       float r;                   /*距离r*/

       float alpha;                    /*水平偏角α*/

       float fy;                 /*竖直偏角φ(单位均用角度)*/

};

 

struct POLAR        polar={ 3.0f, 60.0f, 45.0f};          /*初始化球坐标*/

struct CAMERA            camera;                 /*这个摄像机的位置就是球坐标的位置*/

 

struct POINT        oldpt={ -1, -1};                    /*记录鼠标的前一个位置*/

 

int                                l_button_down=FALSE;               /*记录鼠标左键按下的状态*/

 

void Init()                     /*初始化场景*/

{

   glClearColor( 1.0, 1.0, 1.0, 1.0);                   /*将背静设为白色*/

   glColor3f( 0.0, 0.0, 0.5);                /*物体用蓝色*/

}

 

void Reshape(int w, int h)                    /*使随窗口大小改变而改变*/

{

   glViewport(0, 0, w, h);

   glMatrixMode(GL_PROJECTION);

   glLoadIdentity();

   glOrtho(-6.0, 6.0,-6.0, 6.0,-6.0, 6.0);                   /*定义剪裁区*/

}

 

void Keyboard(unsigned char key, int x, int y)     /*当有键盘消息时会回调该函数*/

{

   switch (key) {

      case 27:                    /*ESCAPE时退出窗口*/

         exit(0);

         break;

   }

}

 

void Display()               /*在这里绘制图形*/

{

       glClear(GL_COLOR_BUFFER_BIT);

       glMatrixMode(GL_MODELVIEW);

       glLoadIdentity();

       gluLookAt(camera.xeye,camera.yeye,camera.zeye,            /*设定摄像机位置,*/

                                                 /*你所看到的景物将根据摄像机的位置改变而改变,*/

                                                 /*这就是鼠标调整摄像机位置的结果*/

                                   0.0 , 0.0, 0.0,/*这三个参数是摄像机观察的点*/

                                   0.0, 1.0, 0.0);/*这三个参数指定了视图的上方向*/

       glBegin(GL_QUADS);           /*画一个彩色的正方体*/

       /*front*/

              glColor3f( 0.0f, 0.0f, 1.0f);

              glVertex3f(-1.0f,-1.0f, 1.0f);

              glVertex3f( 1.0f,-1.0f, 1.0f);

              glVertex3f( 1.0f, 1.0f, 1.0f);

              glVertex3f(-1.0f, 1.0f, 1.0f);

       /*back*/

              glColor3f( 0.0f, 1.0f, 0.0f);

              glVertex3f(-1.0f,-1.0f,-1.0f);

              glVertex3f(-1.0f, 1.0f,-1.0f);

              glVertex3f( 1.0f, 1.0f,-1.0f);

              glVertex3f( 1.0f,-1.0f,-1.0f);

       /*top*/

              glColor3f( 1.0f, 0.0f, 0.0f);

              glVertex3f(-1.0f, 1.0f,-1.0f);

              glVertex3f(-1.0f, 1.0f, 1.0f);

              glVertex3f( 1.0f, 1.0f, 1.0f);

              glVertex3f( 1.0f, 1.0f,-1.0f);

       /*bottom*/

              glColor3f( 0.0f, 1.0f, 1.0f);

              glVertex3f(-1.0f,-1.0f,-1.0f);

              glVertex3f( 1.0f,-1.0f,-1.0f);

              glVertex3f( 1.0f,-1.0f, 1.0f);

              glVertex3f(-1.0f,-1.0f, 1.0f);

       /*right*/

              glColor3f( 1.0f, 0.0f, 1.0f);

              glVertex3f( 1.0f,-1.0f,-1.0f);

              glVertex3f( 1.0f, 1.0f,-1.0f);

              glVertex3f( 1.0f, 1.0f, 1.0f);

              glVertex3f( 1.0f,-1.0f, 1.0f);

       /*left*/

              glColor3f( 1.0f, 1.0f, 0.0f);

              glVertex3f(-1.0f,-1.0f,-1.0f);

              glVertex3f(-1.0f,-1.0f, 1.0f);

              glVertex3f(-1.0f, 1.0f, 1.0f);

              glVertex3f(-1.0f, 1.0f,-1.0f);

       glEnd();

       glutSwapBuffers();               /*交换前后台缓冲区*/

}

 

                     /*将球坐标转化为直角坐标,并设定为摄像机的位置*/

void SetCamera(GLfloat x, GLfloat y)         /*xy 是水平方向和竖直方向的改变量*/

{

       GLfloat alpha,fy;                  /*和它的名字一样,不过是单位是弧度*/

       if((polar.fy+y)>5.0f && (polar.fy+y)<175.0f)

       {     /*定义竖直偏角只能在5°到175°之间*/

              polar.alpha += x;                  /*根据鼠标移动的方向设置新的球坐标*/

              polar.fy += y;

 

              if(polar.alpha>360.0f) polar.alpha-=360.0f;

              if(polar.alpha<0.0f) polar.alpha+=360.0f;      /*将水平偏角锁定在0°到360°之间*/

 

              alpha=polar.alpha*DEG_TO_RAD;

              fy=polar.fy*DEG_TO_RAD;               /*角度转弧度*/

              camera.xeye = polar.r * sin(fy) * cos(alpha);       /*极坐标转直角坐标*/

              camera.zeye = polar.r * sin(fy) * sin(alpha);

              camera.yeye = polar.r * cos(fy);                 /*注意:竖直方向的是y*/

 

              Display();                     /*每次改变相机位置时重绘*/

              /*当然,我画的是静态的,若景物是动态的,你必须将重绘放在空闲回调函数中*/

       }

}

 

void Mouse(int button, int state, int x, int y)        /*当鼠标按下或拿起时会回调该函数*/

{

   if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)

   {

          l_button_down = TRUE;                /*l_button_downtrue时才可改变相机位置*/

          oldpt.x=x;                      /*记录旧坐标,以便移动发生时计算鼠标移动方向*/

          oldpt.y=y;

   }

   if(button == GLUT_LEFT_BUTTON && state == GLUT_UP)

   {

          l_button_down = FALSE;        /*拿起时不能改变摄像机位置*/

   }

}

 

void OnMouseMove(int x, int y)          /*当鼠标移动时会回调该函数*/

{

       if(l_button_down)         /*如果鼠标没有按下则不改变摄像机位置*/

       {

              SetCamera(float(x-oldpt.x),float(oldpt.y-y));       /*根据增量重新设定摄像机位置*/

 

              oldpt.x=x;              /*将当前坐标置为旧坐标*/

              oldpt.y=y;

       }

}

/*若景物是动态的,则使用该函数调用重绘

void Idle()

{

       Display();

}

*/

int main(int argc, char** argv)

{

   glutInit(&argc, argv);             /*初始化GLUT*/

   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);          /*设置显示模式(双缓冲)*/

   glutInitWindowSize(400, 400);              /*设定窗口大小*/

   glutInitWindowPosition(100, 100);         /*左上角坐标*/

   glutCreateWindow(argv[0]);           /*创建窗口*/

 

   Init();

   SetCamera(0.0f,0.0f);

   glutReshapeFunc(Reshape);

   glutDisplayFunc(Display);

   glutKeyboardFunc(Keyboard);

   glutMouseFunc(Mouse);

   glutMotionFunc(OnMouseMove);          /*设置各种消息处理函数*/

/*   glutIdleFunc(Idle);*/            /*设置空闲回调函数*/

   glutMainLoop();              /*进入消息循环*/

   return 0;

}

阅读(15349) | 评论(7)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册