openGL3D机器人鼠标变换视角,键盘移动

openGL3D机器人鼠标变换视角,键盘移动

简单实现3D机器人的移动和视角变换

简单机器人。设计机器人有四大部分组成,即头,身,双手和双腿,分别由立方体经过图形变换而成。
实现

  1. 移动时双手双腿摆动
  2. 视角改变
  3. 视角放缩

机器人组成实现

手腿代码中 glRotatef(-A, 1, 0, 0),参数A为手臂旋转角度

void draw_body(void) {
	glPushMatrix();
	glTranslatef(0, 2.2, 0);
	glScalef(0.5, 1, 0.4);
	glutSolidCube(4);
	glPopMatrix();
}
void draw_leftshoulder(void) {
	glPushMatrix();
	glTranslatef(1.5, 3.1, 0);//最后平移到
	glRotatef(-A, 1, 0, 0);//再摆动
	glTranslatef(0, -0.9, 0);//先平移到需摆动位置
	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_rightshoulder(void) {
	glPushMatrix();
	glTranslatef(-1.5, 3.1, 0);
	glRotatef(A, 1, 0, 0);
	glTranslatef(0, -0.9, 0);

	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_head(void)
{
	glPushMatrix();
	glTranslatef(0, 5.2, 0);
	glutWireSphere(1, 200, 500);
	glPopMatrix();
}
void draw_leftfoot(void) {
	glPushMatrix();
	glTranslatef(-0.6, -0.1, 0);
	glRotatef(-A, 1, 0, 0);
	glTranslatef(0, -1.8, 0);
	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_rightfoot(void) 
{
	glPushMatrix();
	glTranslatef(0.6, -0.1, 0);
	glRotatef(A, 1, 0, 0);
	glTranslatef(0, -1.8, 0);
	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_floor()
{
	glColor3f(0.6, 0.3, 0.1);
	glPushMatrix();
	glScalef(100, 0.00001, 100);
	glutSolidCube(1);
	glColor3f(0,1,0);
	glutWireCube(1);
	glPopMatrix();
}

机器人键盘响应

q,e操作图形缩放,通过控制裁剪窗口的大小实现
a,d操作机器人转向,控制自转角度angle实现
w,s操作机器人前进后退,用数组储存每次移动时的角度,display()循环数组平移实现同时移动时改变A的大小实现手臂摆动

void myKeyBoard(unsigned char key,int x,int y) 
{
	switch (key)
	{
	case 'q':
		distance = distance * 1.1;
		break;
	case 'e':
		distance = distance * 0.9;
		break;
	case 'a':
		angle += 5;
		break;
	case 'd':
		angle -= 5;
		break;
	case 'w':
		if (A >= 40 || A <= -40)
			flag = !flag;
		if (flag)
			A += 5;
		else
			A -= 5;
		advance[k]=angle;
		f[k] = 1;
		k++;
		break;
	case 's':
		if (A >= 40 || A <= -40)
			flag = !flag;
		if (flag)
			A -= 5;
		else
			A += 5;
		advance[k] =angle;
		f[k] = -1;
		k++;
		break;
	default:
		break;
	}
	glutPostRedisplay();
}

机器人鼠标改变视角

左键拖动改变视角,右键恢复到初始视角

void view() 
{
	ry = cos(u);
	rx = sin(u) * cos(v);
	rz = sin(u) * sin(v);
	gluLookAt(rx, ry,rz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);// 设置视点
}
//左键拉视角,右键回归原始视角
void mymouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
			lastX = x;
			lastY = y;
	}
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
	{
		glutPostRedisplay();
	}
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
	{
		u = PI / 2;
		v = PI / 2;
		glutPostRedisplay();
	}
}
//鼠标控制视角
void mymotion(int x, int y)
{
	xoffset = lastX-x ;
	yoffset = y-lastY;
	lastX = x;
	lastY = y;
	if (xoffset > 0)
		v -= 0.01;
	if (xoffset < 0)
		v += 0.01;
	if (yoffset > 0)
		u -= 0.01;
	if (yoffset < 0)
		u += 0.01;
	glutPostRedisplay();
}

机器人实现代码

#include <GL/glut.h>
#include<iostream>
#include<math.h>
#define PI 3.141592
void view();
void myKeyBoard(unsigned char key, int x, int y);
void mymouse(int button, int state, int x, int y);
void reshape(int w, int h);
void init();
void display();
void mymotion(int x, int y);
void draw_body(void);
void draw_leftshoulder(void);
void draw_rightshoulder(void);
void draw_head(void);
void draw_leftfoot(void);
void draw_rightfoot(void);
void draw_floor();
bool flag = true;
int f[60000];
int k = 0;
GLfloat u = PI / 2, v = PI / 2;
GLfloat advance[60000] = {0}, angle = 0;
GLfloat A = 0;
GLfloat distance = 1;
GLfloat radius = 3.0;  // 摄像机的旋转半径
GLfloat rx = 0, ry = 0, rz = radius;
GLfloat lastX = 0;  // 鼠标上一帧的位置
GLfloat lastY = 0;
GLfloat xoffset;    // 鼠标x坐标的偏移量
GLfloat yoffset;
int main(HINSTANCE hInstance,
	HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int
	nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
	char* argv[] = { (char*)"hello ",(char*)" " };
	int argc = 2; // must / should match the number of strings in argv
	glutInit(&argc, argv);//初始化 GLUT库
	//设置深度检测下的显示模式(缓存,颜色类型,深度值)
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(600, 500);
	glutInitWindowPosition(1024 / 2 - 250, 768 / 2 - 250);
	glutCreateWindow("简单机器人");// 创建窗口
	glutKeyboardFunc(myKeyBoard);
	glutReshapeFunc(reshape);
	glutMouseFunc(mymouse);
	glutMotionFunc(mymotion);
	init();
	glutDisplayFunc(display);//用于绘制当前窗口
	glutMainLoop();//表示开始运行程序,用于程序的结尾
	return 0;
}
void reshape(int w, int h)
{
	glViewport(0, 0, w, h);
}
void init()
{
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	glEnable(GL_POINT_SMOOTH);
	glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glEnable(GL_POLYGON_SMOOTH);
	glLineWidth(3);
	glEnable(GL_DEPTH_TEST);//启用深度检测
}
void display()
{
	GLfloat w = glutGet(GLUT_SCREEN_WIDTH);//获取屏幕宽度
	GLfloat h = glutGet(GLUT_SCREEN_HEIGHT);//获取屏幕高度
	GLfloat ratio = w / h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)//保持形状不变
		glOrtho(-40 * distance, 40 * distance, -40 * distance*w/h, 40 * distance*w/h, -2000, 2000);//定义三维观察体
	else
		glOrtho(-40 * distance * ratio, 40 * distance * ratio, -40 * distance, 40 * distance, -2000, 2000);//定义三维观察体
	// gluPerspective(60, w / h, 1, 200);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// 启用深度检测下的清屏模式
	glMatrixMode(GL_MODELVIEW);// 矩阵模式设置
	glLoadIdentity();//清空矩阵堆栈
	view();// 设置视点
	//地面
	draw_floor();
	glPushMatrix();
		for (int i = 0;i <= k;i++)
	{
		glTranslatef(f[i] * 0.1*sin(advance[i] / 180*PI), 0, f[i] * 0.1*cos(advance[i] / 180*PI));
		//glTranslatef(f[i] * sin(advance[i] / 360), 0, f[i] * cos(advance[i] / 360));
	}
	//机器人
		glRotatef(angle, 0, 1, 0);
		glTranslatef(0, 4, 0);
		glColor3f(1, 0, 0);
		draw_body();
		glColor3f(1, 0, 1);
		draw_head();
		glColor3f(1, 1, 0);
		draw_leftshoulder();
		glColor3f(1, 1, 0);
		draw_rightshoulder();
		glColor3f(0, 1, 1);
		draw_leftfoot();
		glColor3f(0, 1, 1);
		draw_rightfoot();
	glPopMatrix();
	glutSwapBuffers(); //双缓冲下的刷新方法
}

//视角转换
void view() 
{
	ry = cos(u);
	rx = sin(u) * cos(v);
	rz = sin(u) * sin(v);
	gluLookAt(rx, ry,rz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);// 设置视点
}
//左键拉视角,右键回归原始视角
void mymouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
			lastX = x;
			lastY = y;
	}
	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
	{
		glutPostRedisplay();
	}
	if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
	{
		u = PI / 2;
		v = PI / 2;
		glutPostRedisplay();
	}
}
//鼠标控制视角
void mymotion(int x, int y)
{
	xoffset = lastX-x ;
	yoffset = y-lastY;
	lastX = x;
	lastY = y;
	if (xoffset > 0)
		v -= 0.01;
	if (xoffset < 0)
		v += 0.01;
	if (yoffset > 0)
		u -= 0.01;
	if (yoffset < 0)
		u += 0.01;
	glutPostRedisplay();
}
//q,e放缩视角;w,s前进后退;a,d控制方向
void myKeyBoard(unsigned char key,int x,int y) 
{
	switch (key)
	{
	case 'q':
		distance = distance * 1.1;
		break;
	case 'e':
		distance = distance * 0.9;
		break;
	case 'a':
		angle += 5;
		break;
	case 'd':
		angle -= 5;
		break;
	case 'w':
		if (A >= 40 || A <= -40)
			flag = !flag;
		if (flag)
			A += 5;
		else
			A -= 5;
		advance[k]=angle;
		f[k] = 1;
		k++;
		break;
	case 's':
		if (A >= 40 || A <= -40)
			flag = !flag;
		if (flag)
			A -= 5;
		else
			A += 5;
		advance[k] =angle;
		f[k] = -1;
		k++;
		break;
	default:
		break;
	}
	glutPostRedisplay();
}
void draw_body(void) {
	glPushMatrix();
	glTranslatef(0, 2.2, 0);
	glScalef(0.5, 1, 0.4);
	glutSolidCube(4);
	glPopMatrix();
}
void draw_leftshoulder(void) {
	glPushMatrix();
	glTranslatef(1.5, 3.1, 0);
	glRotatef(-A, 1, 0, 0);
	glTranslatef(0, -0.9, 0);
	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_rightshoulder(void) {
	glPushMatrix();
	glTranslatef(-1.5, 3.1, 0);
	glRotatef(A, 1, 0, 0);
	glTranslatef(0, -0.9, 0);

	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_head(void)
{
	glPushMatrix();
	glTranslatef(0, 5.2, 0);
	glutWireSphere(1, 200, 500);
	glPopMatrix();
}
void draw_leftfoot(void) {
	glPushMatrix();
	glTranslatef(-0.6, -0.1, 0);
	glRotatef(-A, 1, 0, 0);
	glTranslatef(0, -1.8, 0);
	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_rightfoot(void) 
{
	glPushMatrix();
	glTranslatef(0.6, -0.1, 0);
	glRotatef(A, 1, 0, 0);
	glTranslatef(0, -1.8, 0);
	glScalef(0.4, 2, 0.5);
	glutSolidCube(2);
	glColor3f(1, 1, 1);
	glutWireCube(2);
	glPopMatrix();
}
void draw_floor()
{
	glColor3f(0.6, 0.3, 0.1);
	glPushMatrix();
	glScalef(100, 0.00001, 100);
	glutSolidCube(1);
	glColor3f(0,1,0);
	glutWireCube(1);
	glPopMatrix();
}


  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值