有两个例子 1比较好的 http://blog.csdn.net/dizuo/archive/2008/04/15/2295278.aspx 类 #include <math.h> #include <GL/glut.h> class CTrackBall { public: #define M_PI 3.1415926 CTrackBall() :angle(0.0), trackingMouse(false), trackBallMove(false),reDrawContinue(false) { for(int i=0; i<3; i++) axis[i]=lastPos[i]=0.0F; }; ~CTrackBall(){}; void SetWinWidth(int w) { winWidth=w; } void SetWinHeight(int h){ winHeight=h; } void MakeRotate() { glRotatef(angle, axis[0], axis[1], axis[2]); } //根据二维的坐标x,y产生一组三维的坐标,单位化后存放到v中 void trackball_Prov(int x, int y, float v[3]) { GLfloat d, a; /*Project x,y to a hemi-sphere centered within width,height*/ v[0]=(2.0F*x-winWidth) / winWidth; v[1]=(winHeight-2.0F*x) / winHeight; d=(float)sqrt(v[0]*v[0]+v[1]*v[1]); v[2]=(float)cos ( (M_PI/2.0F)* ( (d<1.0) ? d : 1.0F ) ); //make identity 单位化 a=1.0F / (float)sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); v[0] *=a; v[1] *=a; v[2] *=a; } //GUI的接口函数 void onMouseMotion(int x, int y) { float curPos[3], dx, dy, dz; trackball_Prov(x, y, curPos); if(trackingMouse) { dx=curPos[0]-lastPos[0]; dy=curPos[1]-lastPos[1]; dz=curPos[2]-lastPos[2]; if(dx || dy || dz) { angle=90.0F*sqrt(dx*dx+dy*dy+dz*dz); //vector Cross:lastPos×curPos; axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1]; axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2]; axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0]; //refresh the lastPos lastPos[0] = curPos[0]; lastPos[1] = curPos[1]; lastPos[2] = curPos[2]; } } glutPostRedisplay(); } //交互方式可以修改的, void onMouseButton(int button, int state, int x, int y) { if(button==GLUT_RIGHT_BUTTON) exit(0); if(button==GLUT_LEFT_BUTTON) switch(state) { case GLUT_DOWN: y=winHeight-y; startMotion(x, y); break; case GLUT_UP: stopMotion(x, y); break; } } void startMotion(int x, int y) { trackingMouse = true; reDrawContinue = false; startX = x; startY = y; curX = x; curY = y; trackball_Prov(x, y, lastPos); trackBallMove = true; } void stopMotion(int x, int y) { trackingMouse = false; if(startX != x || startY!= y) reDrawContinue=true; else { angle=0.0; reDrawContinue=false; trackBallMove = false; } } //control switch variable: bool trackingMouse; bool trackBallMove; bool reDrawContinue; private: int winWidth, winHeight; float angle; float axis[3]; float lastPos[3]; //for the use of mouse int curX, curY; int startX, startY; }; 接口的使用: void Display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /*view transform*/ if(trackBall.trackBallMove) { //printf("%f ", angle); trackBall.MakeRotate(); } // colorCube(); 绘制物体函数调用; glutSwapBuffers(); } void myReshape(int w, int h) { glViewport(0,0,w,h); trackBall.SetWinWidth(w); trackBall.SetWinHeight(h); } void spinCube() // { if(trackBall.reDrawContinue) glutPostRedisplay(); } void onMouseMotion(int x, int y) { trackBall.onMouseMotion(x, y); } void onMouseButton(int button, int state, int x, int y) { trackBall.onMouseButton(button, state, x, y); } 2..nehe 48讲 中有实现方法 3.另外 #include <math.h> #include <stdlib.h> #include <GL/glut.h> //#define false 0 //#define true 1 #define M_PI 3.14159 int winWidth,winHeight; float angle=0,axis[3],trans[3]; bool trackingMouse=false; bool redrawContinue=false; bool trackballMove=false; GLfloat vertices[][3]={{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1},{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1}}; GLfloat colors[][3]={{1,1,1},{1,0,0},{1,1,0},{0,1,0},{0,0,1},{1,0,1},{1,1,1},{0,1,1}}; void polygon(int a,int b,int c,int d,int face) { glBegin(GL_POLYGON); glColor3fv(colors[face]); glVertex3fv(vertices[a]); glColor3fv(colors[face]); glVertex3fv(vertices[b]); glColor3fv(colors[face]); glVertex3fv(vertices[c]); glColor3fv(colors[face]); glVertex3fv(vertices[d]); glEnd(); } void colorcube() { polygon(1,0,3,2,0); polygon(3,7,6,2,1); polygon(7,3,0,4,2); polygon(2,6,5,1,3); polygon(4,5,6,7,4); polygon(5,4,0,1,5); } float lastPos[3]={0,0,0}; int curx,cury; int startX,startY; void trackball_ptov(int x,int y,int width,int height,float v[3]) { float d,a; v[0]=(2.0*x-width)/width; v[1]=(height-2.0*y)/height; d=(float)sqrt(v[0]*v[0]+v[1]*v[1]); v[2]=cos((M_PI/2)*((d<1)? d:1)); a=1.0/(float)sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); v[0]*=a; v[1]*=a; v[2]*=a; } void mouseMotion(int x,int y) { float curPos[3],dx,dy,dz; trackball_ptov(x,y,winWidth,winHeight,curPos); if(trackingMouse) { dx = curPos[0] - lastPos[0]; dy = curPos[1] - lastPos[1]; dz = curPos[2] - lastPos[2]; if(dx||dy||dz) { angle = 90*sqrt(dx*dx+dy*dy+dz*dz); axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1]; axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2]; axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0]; lastPos[0] = curPos[0]; lastPos[1] = curPos[1]; lastPos[2] = curPos[2]; } } glutPostRedisplay(); } void startMotion(int x,int y) { trackingMouse = true; redrawContinue = false; startX = x; startY = y; curx = x; cury = y; trackball_ptov(x,y,winWidth,winHeight,lastPos); trackballMove = true; } void stopMotion(int x,int y) { trackingMouse = false; if(startX!=x||startY!=y) { redrawContinue = true; } else { angle = 0; redrawContinue = false; trackballMove = false; } } void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); if(trackballMove) { glRotatef(angle,axis[0],axis[1],axis[2]); } colorcube(); glutSwapBuffers(); } void mouseButton(int button,int state,int x,int y) { if(button == GLUT_RIGHT_BUTTON) exit(0); if(button == GLUT_LEFT_BUTTON) { switch(state) { case GLUT_DOWN: y = winHeight - y; startMotion(x,y); break; case GLUT_UP: stopMotion(x,y); break; } } } void myReshape(int w,int h) { glViewport(0,0,w,h); winWidth = w; winHeight = h; } void spinCube() { if(redrawContinue) glutPostRedisplay(); } void main(int argc,char **argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(500,500); glutCreateWindow("colorcube"); glutReshapeFunc(myReshape); glutDisplayFunc(display); //glutIdleFunc(spinCube); glutMouseFunc(mouseButton); glutMotionFunc(mouseMotion); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-2,2,-2,2,-2,2); glMatrixMode(GL_MODELVIEW); glutMainLoop(); }