代码如下:
#include
#include
#include
using namespace std;
const GLfloat PI=3.14;
static int shoulder = 0, elbow = 0; //shoulder:肩部角度,elbow: 肘部角度
/// record the state of mouse
GLboolean mouserdown = GL_FALSE;
GLboolean mouseldown = GL_FALSE;
GLboolean mousemdown = GL_FALSE;
/// when a mouse-key is pressed, record current mouse position
static GLint mousex = 0, mousey = 0;
static GLfloat center[3] = {0.0f, 0.0f, 0.0f}; /// center position
static GLfloat eye[3]; /// eye's position
static GLfloat yrotate = PI/4; /// angle between y-axis and look direction
static GLfloat xrotate = PI/4; /// angle between x-axis and look direction
static GLfloat celength = 20.0f;/// lenght between center and eye
static GLfloat mSpeed = 0.4f; /// center move speed
static GLfloat rSpeed = 0.02f; /// rotate speed
static GLfloat lSpeed = 0.4f; /// reserved
/// calculate the eye position according to center position and angle,length
void CalEyePostion()
{
if(yrotate > PI/2.2) yrotate = PI/2.2; /// 限制看得方向
if(yrotate < 0.01) yrotate = 0.01;
if(xrotate > 2*PI) xrotate = 0.01;
if(xrotate < 0) xrotate = 2 * PI;
if(celength > 50) celength = 50; /// 缩放距离限制
if(celength < 5) celength = 5;
/// 下面利用球坐标系计算 eye 的位置,
eye[0] = center[0] + celength * sin(yrotate) * cos(xrotate);
eye[2] = center[2] + celength * sin(yrotate) * sin(xrotate);
eye[1] = center[1] + celength * cos(yrotate);
}
/// center moves
void MoveBackward() /// center 点沿视线方向水平向后移动
{
center[0] += mSpeed * cos(xrotate);
center[2] += mSpeed * sin(xrotate);
CalEyePostion();
}
void MoveForward()
{
center[0] -= mSpeed * cos(xrotate);
center[2] -= mSpeed * sin(xrotate);
CalEyePostion();
}
/// visual angle rotates
void RotateLeft()
{
xrotate -= rSpeed;
CalEyePostion();
}
void RotateRight()
{
xrotate += rSpeed;
CalEyePostion();
}
void RotateUp()
{
yrotate += rSpeed;
CalEyePostion();
}
void RotateDown()
{
yrotate -= rSpeed;
CalEyePostion();
}
/// CALLBACK func for keyboard presses
void KeyFunc(unsigned char key, int x, int y)
{
switch(key)
{
case 'a': RotateLeft(); break;
case 'd': RotateRight();break;
case 'w': MoveForward(); break;
case 's': MoveBackward(); break;
case 'q': RotateUp(); break;
case 'e': RotateDown(); break;
}
glutPostRedisplay();
}
/// CALLBACK func for mouse kicks
void MouseFunc(int button, int state, int x, int y)
{
if(state == GLUT_DOWN)
{
if(button == GLUT_RIGHT_BUTTON) mouserdown = GL_TRUE;
if(button == GLUT_LEFT_BUTTON) mouseldown = GL_TRUE;
if(button == GLUT_MIDDLE_BUTTON)mousemdown = GL_TRUE;
}
else
{
if(button == GLUT_RIGHT_BUTTON) mouserdown = GL_FALSE;
if(button == GLUT_LEFT_BUTTON) mouseldown = GL_FALSE;
if(button == GLUT_MIDDLE_BUTTON)mousemdown = GL_FALSE;
}
mousex = x, mousey = y;
}
/// CALLBACK func for mouse motions
void MouseMotion(int x, int y)
{
if(mouserdown == GL_TRUE)
{ /// 所除以的数字是调整旋转速度的,随便设置,达到自己想要速度即可
xrotate += (x - mousex) / 80.0f;
yrotate -= (y - mousey) / 120.0f;
}
if(mouseldown == GL_TRUE)
{
celength += (y - mousey) / 25.0f;
}
mousex = x, mousey = y;
CalEyePostion();
glutPostRedisplay();
}
void LookAt() /// 调用 gluLookAt(), 主要嫌直接调用要每次都写好几个参数。。
{
CalEyePostion();
gluLookAt(eye[0], eye[1], eye[2],center[0], center[1], center[2],0, 1, 0);
}
void init(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix(); //把当前的变换矩阵压入OpenGL内部栈中,用以保存当前矩阵
//画机器人的上臂
glTranslatef(-1.0f, 0.0f, 0.0f); //用平移矩阵乘当前矩阵,格式为:glTranslatef(x,y,z)
glRotatef((GLfloat) shoulder, 0.0f, 0.0f, 1.0f); //用旋转矩阵乘当前矩阵,格式为glRotatef (角度,x轴,y轴,z轴),这里是绕Z轴旋转
glTranslatef(1.0f, 0.0f, 0.0f); //再用平移矩阵乘当前矩阵,注意顺序
glPushMatrix(); //变换矩阵压栈
glScalef(2.0f, 0.4f, 1.0f); //用缩放矩阵乘以当前矩阵,格式为glScalef(x缩放比例,y缩放比例,z缩放比例)
glutWireCube(1.0f); //glut库函数,画一个三维的Cube,参数为边长
glPopMatrix(); //弹栈,现在矩阵恢复到使用缩放前的样子
//画机器人的前臂,请注意平移矩阵和旋转矩阵的变化
glTranslatef(1.0f, 0.0f, 0.0f);
glRotatef((GLfloat) elbow, 0.0f, 0.0f, 1.0f);
glTranslatef(1.0f, 0.0f, 0.0f);
glPushMatrix();
glScalef(2.0f, 0.4f, 1.0f);
glutWireCube(1.0f);
glPopMatrix();
glPopMatrix();
glFlush();
}
void reshape (int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0f, (GLfloat)width/(GLfloat)height, 1.0f, 20.0f); //建立一个透视投影视图体,格式为:gluPerspective(视域的角度,宽高比,视点到近裁剪面的距离(总为正),视点到远裁剪面的距离(总为正))
glMatrixMode(GL_MODELVIEW);
LookAt();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f); //用平移矩阵乘当前矩阵,注意,这会将所有绘制过程中绘制的物体平移
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'a': //处理四个按键,改变旋转角度,转动手臂
shoulder = (shoulder + 5) % 360;
glutPostRedisplay(); //重画
break;
case 'd':
shoulder = (shoulder - 5) % 360;
glutPostRedisplay();
break;
case 'q':
elbow = (elbow + 5) % 360;
glutPostRedisplay();
break;
case 'e':
elbow = (elbow - 5) % 360;
glutPostRedisplay();
break;
case 'x':
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(1000,1000);
glutInitWindowPosition(100, 100);
glutCreateWindow("1352453_王用");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard); //键盘按键
glutMouseFunc(MouseFunc); //鼠标按键
glutMotionFunc(MouseMotion); //鼠标移动
glutMainLoop();
return 0;
}