用OpenGL绘制旋转的机器人手臂


代码如下:

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


你可能感兴趣的:(OpenGL,C/C++)