图形学上机实验

2022-11-01 16:17:33 浏览数 (1)

实验环境:win10、VS 2017、OPenGL库

实验一 基于OpenGL的二维图形绘制

要求

编程实现绘制一个五角星(基于OpenGL),效果如下图所示

问题分析

可以将一个五角星划分为10个三角形,假设五角星的各边长,分别计算出10个定点的坐标,然后逐个绘制三角形,将其拼接为五角星;

也可以利用参数方程,如下图所示,设大圆和小圆的半径分别为R、r,已知夹角为37度,在循环中计算绘制三角形。

代码

ProjectOne.cpp

代码语言:javascript复制
#include <GL/glew.h>//OpenGL库
#include <GL/glut.h>//OpenGL辅助库
#include <math.h>
#pragma comment(linker, "/subsystem:"windows" /entry:"mainCRTStartup"") //这句是不让控制台窗体出现,如果想要出现,去掉即可。

// 明确 计算三角函数 需要 theta * pi / 180
// 由于 两个三角形的theta角有36度的差值
// 点的坐标为 x = x0   r(R) * sin(cos) theta
// 对于大圆 theta 为( 0   72 * i )* pi/180 == 0.4i * pi 
// 小圆theta 为 (36   72 * i) * pi / 180 == 0.2*pi   0.4i * pi
// 两者相差只有 0.2 * pi


void init(void)
{
	glClearColor(1.0, 1.0, 1.0, 1.0);//设置背景色白色
}


void DrawStar1(float cx, float cy, float R, float r, float o)//五角星中心坐标x,y,大圆半径,小圆半径,初始角度
{
	float x0, y0, x1, y1;//
	float    Theta = o;//大圆对应角度
	float    theta = o   0.2 * 3.14;//小圆对应角度
	for (int i = 0; i < 10; i  )
	{
		x0 = cx   R * cos(Theta);//大圆对应的x坐标
		y0 = cy   R * sin(Theta);//大圆对应y坐标

		x1 = cx   r * cos(theta);//小圆对应x坐标
		y1 = cy   r * sin(theta);//小圆对应y坐标
		glBegin(GL_LINES);//绘制
		glColor3f(1, 0, 0);
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glEnd();
		if (i % 2 == 0)
		{
			Theta = Theta   0.4 * 3.14;//大圆对应角度变换
		}
		else
		{
			theta = theta   0.4 * 3.14;//小圆对应角度变换
		}
	}
}

void DrawStar2(float cx, float cy, float R, float r, float o)//五角星中心坐标x,y,大圆半径,小圆半径,初始角度
{
	float x0, y0, x1, y1;//
	float    Theta = o;//大圆对应角度
	float    theta = o   0.2 * 3.14;//小圆对应角度
	for (int i = 0; i < 10; i  )
	{
		x0 = cx   R * cos(Theta);//大圆对应的x坐标
		y0 = cy   R * sin(Theta);//大圆对应y坐标
		x1 = cx   r * cos(theta);//小圆对应x坐标
		y1 = cy   r * sin(theta);//小圆对应y坐标
		glColor3f(1, 0, 0);
		glBegin(GL_POLYGON);//绘制
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glVertex2f(cx, cy);
		glEnd();
		if (i % 2 == 0)
		{
			Theta = Theta   0.4 * 3.14;//大圆对应角度变换
		}
		else
		{
			theta = theta   0.4 * 3.14;//小圆对应角度变换
		}
	}
}

void DrawStar3(float cx, float cy, float R, float r, float o)//五角星中心坐标x,y,大圆半径,小圆半径,初始角度
{
	float x0, y0, x1, y1;
	float    Theta = o;				//大圆对应角度
	float    theta = o   0.2 * 3.14;	//小圆对应角度
	for (int i = 0; i < 10; i  )
	{
		x0 = cx   R * cos(Theta);//大圆对应的x坐标
		y0 = cy   R * sin(Theta);//大圆对应y坐标
		x1 = cx   r * cos(theta);//小圆对应x坐标
		y1 = cy   r * sin(theta);//小圆对应y坐标
		if (i % 2 == 0)
		{
			glColor3f(1, 0, 0);
		}
		else
		{
			glColor3f(0, 1, 1);
		}
		glBegin(GL_POLYGON);//绘制
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glVertex2f(cx, cy);
		glEnd();
		if (i % 2 == 0)
		{
			Theta = Theta   0.4 * 3.14;	//大圆对应角度变换
		}
		else
		{
			theta = theta   0.4 * 3.14;	//小圆对应角度变换
		}
	}
}
void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);	//清除帧缓存
	DrawStar1(150, 300, 120, 50, 0);	//glFlush();//单缓冲时必须要,说明绘图命令(函数)结束
	DrawStar2(400, 300, 120, 50, 0);
	DrawStar3(650, 300, 120, 50, 0);
	glutSwapBuffers();//交换缓冲(双缓冲时使用)
}

void reshape(int width, int height)
{
	glViewport(0, 0, width, height);//设置视区(窗口内绘图区域)
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, width, 0, height);//设置图形数据范围
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
}
int main(int argc, char* argv[])
{
	glutInitWindowPosition(200, 200);//应用程序窗口位置
	glutInitWindowSize(800, 600);//窗口大小
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);//双缓冲,单缓冲为GLUT_SINGLE
	glutCreateWindow("五角星绘制");//创建窗口,参数为窗口标题
	init();
	glutDisplayFunc(display);//图形绘制
	glutReshapeFunc(reshape);//窗口大小变化
	glutKeyboardFunc(keyboard);//键盘交互
	glutMainLoop();//必须,进入GLUT事件处理循环
	return 0;
}

效果展示

实验二 二维图形的几何变换

要求

  1. 实现一个五角星以任意角度在矩形四条边内部滚动,与边界碰撞时发生的反弹,参考台球在桌案上的滚动效果。
  2. 实现矩形框内一个五角星的连续放缩(大小变化)
  3. 注意:两个五角星在同一矩形内;放缩五角星的参照点为五角星的中心,五角星位置固定;滚动五角星的旋转角度和平移距离尽量一致。

问题分析

  1. 将滚动五角星看做半径为R的圆,滚动五角星的碰撞条件判断为:它的圆心到矩形边界的距离是否大于半径R。图示如下

红色矩形所框选的范围即为滚动五角星圆心所运动的区域。

  1. 旋转五角星只需要不停地调用放缩函数即可。

代码

ProjectTwo.cpp

代码语言:javascript复制
// OpenGLOld.cpp : 定义控制台应用程序的入口点。
//
#include <GL/glew.h>//OpenGL库
#include <GL/glut.h>//OpenGL辅助库
#include <math.h>
#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" ) //这句是不让控制台窗体出现,如果想要出现,去掉即可。

void init(void)
{
	glClearColor(0.2, 0.3, 0.3, 1.0);//设置背景色
}

float alpha=0.0f;
float x = 0.0f, y = 0.0f;
double Scale = 0;

void DrawStar3(float cx, float cy, float R, float r, float o)//五角星中心坐标x,y,大圆半径,小圆半径,初始角度
{
	float x0, y0, x1, y1;
	float    Theta = o;				//大圆对应角度
	float    theta = o   0.2 * 3.14;	//小圆对应角度
	for (int i = 0; i < 10; i  )
	{
		x0 = cx   R * cos(Theta);//大圆对应的x坐标
		y0 = cy   R * sin(Theta);//大圆对应y坐标
		x1 = cx   r * cos(theta);//小圆对应x坐标
		y1 = cy   r * sin(theta);//小圆对应y坐标
		if (i % 2 == 0)
		{
			glColor3f(1, 0, 0);
		}
		else
		{
			glColor3f(0, 1, 1);
		}
		glBegin(GL_POLYGON);//绘制
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glVertex2f(cx, cy);
		glEnd();
		if (i % 2 == 0)
		{
			Theta = Theta   0.4 * 3.14;	//大圆对应角度变换
		}
		else
		{
			theta = theta   0.4 * 3.14;	//小圆对应角度变换
		}
	}
}

void MyDrawRect()
{
	glBegin(GL_LINE_LOOP);
	glVertex2f(0, 0);
	glVertex2f(0, 700);
	glVertex2f(1000, 700);
	glVertex2f(1000, 0);
	glEnd();

}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);//清除帧缓存
	
	//模型观察矩阵初始化
	glMatrixMode(GL_MODELVIEW);
	
	// 旋转与碰撞
	glPushMatrix();
	glTranslatef(150.0f x,300.0f y,0.0f);
	glRotatef(alpha, 0, 0, 1);
	glTranslatef(-150.0f-x, -300.0f-y, 0.0f);

	DrawStar3(150 x, 300 y, 100, 40, 0);
	//glLoadIdentity();
	glPopMatrix();

	//缩放
	glPushMatrix();
	glTranslatef(300.0, 200.0, 0.0);
	glScalef(Scale, Scale, 1);
	glTranslatef(-300.0, -200.0, 0.0);

	DrawStar3(300, 200, 100, 40, 0.1*3.14);
	//glLoadIdentity();
	glPopMatrix();

	MyDrawRect();

	//glFlush();//单缓冲时必须要,说明绘图命令(函数)结束
	glutSwapBuffers();//交换缓冲(双缓冲时使用)
}

void reshape(int width, int height)
{
	glViewport(0, 0, width, height);//设置视区(窗口内绘图区域)

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, width, 0, height);//设置图形数据范围
//	glMatrixMode(GL_MODELVIEW);
//	glLoadIdentity();
}

int flag = 0, flagX = 0, flagY = 0;


void change()
{
	alpha  = 0.2f;
	if (alpha > 360) alpha -= 360;

	// 放缩判断
	if (flag == 0) {
		Scale  = 0.002;
		if (Scale > 2.5) {
			flag = 1;
		}
	} else if (flag == 1) {
		Scale -= 0.002;
		if (Scale < 0.2) {
			flag = 0;
		}
	}

	// X取值范围判断	(x1, x2)   
	// x1 = x - R 
	// x2 = x   R
	if (flagX == 0) {
		x  = 0.2f;
		if (x   150 >= 900) {
			flagX = 1;
		}
	}
	else if (flagX == 1) {
		x -= 0.2f;
		if (x   150 <= 100) {
			flagX = 0;
		}
	}

	// Y值取值范围判断 (y1, y2)
	// y1 = y - R
	// y2 = y   R

	if (flagY == 0) {
		y  = 0.2f;
		if (y   300 >= 600) {
			flagY = 1;
		}
	}else if (flagY == 1) {
		y -= 0.2f;
		if (y   300 <= 100) {
			flagY = 0;
		}
	}

	glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y)
{

}

int main(int argc, char* argv[])
{
	glutInitWindowPosition(200, 200);//应用程序窗口位置
	glutInitWindowSize(800, 600);//窗口大小
	
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);//双缓冲,单缓冲为GLUT_SINGLE
	glutCreateWindow("Project Two");//创建窗口,参数为窗口标题
	init();

	glutDisplayFunc(display);//图形绘制
	glutReshapeFunc(reshape);//窗口大小变化
	glutKeyboardFunc(keyboard);//键盘交互
	glutIdleFunc(change);//键盘交互

	glutMainLoop();//必须,进入GLUT事件处理循环

	return 0;
}

效果展示

实验三 & 实验四

要求

  1. 构建一个丰富的三维场景,包括立方体、球体、圆柱体;
  2. 为它们添加合适的纹理;
  3. 在场景中添加光源;
  4. 可以使用按键控制你视角的移动及光源的移动。

代码

ProjectFour.cpp

代码语言:javascript复制
// OpenGLOld.cpp : 定义控制台应用程序的入口点。
//
#include <Windows.h>
#include <GL/glew.h>//OpenGL库
#include <GL/glut.h>//OpenGL辅助库

#include <math.h>
#include "SOIL/SOIL.h"

#include "cgSphere.h"
#include "cgCylinder.h"
#include "cgCube.h"
#include "cgQuad.h"

#include "Bitmap.h"
#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" ) //这句是不让控制台窗体出现,如果想要出现,去掉即可。

float alpha=0.0f;
float pos[]={0.0,1.5,0.0};
float headdir[]={0.0f,0.0f,-1.0f};
float rightdir[]={1.0f,0.0f,0.0f};

float step = 0.10f;
float beta = 180.0f;//与z轴正向夹角
float betastep = 1.0f;

cgSphere sphere, sun;
cgCylinder cylinder;
cgCube cube;

//光照变量
GLfloat light_position[] = { 0.0, 2.0, 1.0, 0.1 };
GLfloat light_color[] = { 1.0, 0.0, 0.0, 0.0 };
// 添加的光照
GLfloat sun_position[] = { -10.0, 5.0, 0.0, 0.0 };
GLfloat sun_color[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat aMaterial[] = { .20, 0.20, 0.20, 1.0 };		//环境光反射系数
GLfloat dMaterial[] = { .60, 0.60, 0.60, 1.0 };		//漫反射光反射系数
GLfloat sMaterial[] = { 0.4, 0.4,0.4, 1 };			//镜面反射光反射系数
GLfloat shiniess = 20;								//高光指数

int rendermode = 2;//0:填充; 1:线框;2:纹理

GLuint textureID;
int  frames=0;

GLuint LoadTexture(char* fname)
{
	GLuint tID;
	
	int width, height, nrComponents;
	unsigned char *data;
	
	data = SOIL_load_image(fname, &width, &height, &nrComponents,SOIL_LOAD_RGB);// 
	
	if (data)
	{
		GLenum internalFormat;
		GLenum dataFormat;
		bool gammaCorrection = false;
		if (nrComponents == 1)
		{
			internalFormat = dataFormat = GL_RED;
		}
		else if (nrComponents == 3)
		{
			internalFormat = gammaCorrection ? GL_SRGB : GL_RGB;
			dataFormat = GL_RGB;
		}
		else if (nrComponents == 4)
		{
			internalFormat = gammaCorrection ? GL_SRGB_ALPHA : GL_RGBA;
			dataFormat = GL_RGBA;
		}

		//生成纹理
		glGenTextures(1, &tID);
		glBindTexture(GL_TEXTURE_2D, tID);
	
		//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);//这个函数居然不能用
		gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, dataFormat, GL_UNSIGNED_BYTE, data);
			
		//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
	
		glBindTexture(GL_TEXTURE_2D, 0);

		SOIL_free_image_data(data);

		return tID;
	}

	return -1;	
}

void init(void)
{
	glClearColor(0.5, 1.0, 1.0, 1.0);//设置背景色白色
	glEnable(GL_DEPTH_TEST);

	/*GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR属性。这三个属性与光源的三个对应属性类似,每一属性都由四个值组成。
	GL_AMBIENT表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度(颜色)。
	GL_DIFFUSE表示光线照射到该材质上,经过漫反射后形成的光线强度(颜色)。
	GL_SPECULAR表示光线照射到该材质上,经过镜面反射后形成的光线强度(颜色)。
	通常,GL_AMBIENT和GL_DIFFUSE都取相同的值,可以达到比较真实的效果。
	使用GL_AMBIENT_AND_DIFFUSE可以同时设置GL_AMBIENT和GL_DIFFUSE属性。*/

	//光照
	glLightfv(GL_LIGHT0, GL_POSITION, light_position);

    glLightfv(GL_LIGHT0, GL_AMBIENT, light_color);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_color);

	glLightfv(GL_LIGHT1, GL_POSITION, sun_position);

    glLightfv(GL_LIGHT1, GL_AMBIENT, sun_color);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, sun_color);
    glLightfv(GL_LIGHT1, GL_SPECULAR, sun_color);

	// void glMaterial{if}(GLenum face, GLenum pname, TYPE param);
	// 参数pname的可能取值。
	// GL_AMBIENT_AND_DIFFUSE让您能够同时设置材质的环境颜色和散射颜色,并将它们设置为相同的RGBA值。
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, aMaterial);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, dMaterial);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, sMaterial);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shiniess);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
	glEnable(GL_LIGHT1);
	///////////////////////////

	//地球仪
	sphere.InitData(1.0f);
	sphere.SetPos(cgPoint3D(0.0f, 2.5f,-8.0f));
	sphere.SetTexture(LoadTexture("Textures/earth2.jpg"));

	// 太阳光照
	sun.InitData(3.0f);
	sun.SetPos(cgPoint3D(sun_position[0], sun_position[1], sun_position[2]));
	sun.SetTexture(LoadTexture("Textures/sun.jpeg"));

	// 正方体
	cube.InitData(1.0f);
	cube.SetPos(cgPoint3D(1.0f, 1.0f, -5.0f));
	cube.SetTexture(LoadTexture("Textures/timg.bmp"));

	// 圆柱体
	cylinder.InitData(1.0f, 5.0f);
	cylinder.SetPos(cgPoint3D(3.0f, 4.0f, -3.0f));
	cylinder.SetTextureID(LoadTexture("Textures/desert.bmp"));
	
	//地面纹理
	textureID = LoadTexture("Textures/timg.jpg");	
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT );//清除帧缓存和深度缓存
	
	//模型观察矩阵初始化
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	float at[3];
	for (int i=0; i<3; i  )
		at[i] = pos[i]   headdir[i];

	gluLookAt(pos[0], pos[1], pos[2], at[0], at[1], at[2], 0.0, 1.0, 0.0);

	if (rendermode==1)
		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	else
		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

	//地面
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, textureID);
	glColor3f(1.0f,1.0f,1.0f);
	glBegin(GL_QUADS);
		glTexCoord2f(0.0f,0.0f);//指定顶点纹理坐标
		glNormal3f(0,1,0);//指定顶点法向量
		glVertex3f(-50.0f,0.0f,50.0f);//指定顶点坐标

		glTexCoord2f(10.0f,0.0f);
		glNormal3f(0,1,0);
		glVertex3f(50.0f,0.0f,50.0f);

		glTexCoord2f(10.0f,10.0f);
		glNormal3f(0,1,0);
		glVertex3f(50.0f,0.0f,-50.0f);
		
		glTexCoord2f(0.0f,10.0f);
		glNormal3f(0,1,0);
		glVertex3f(-50.0f,0.0f,-50.0f);
	glEnd();
	glDisable(GL_TEXTURE_2D);

	glColor3f(0.25,0.5,0.5);
	sphere.Render();

	glColor3f(1.0,0.0,0.0);
	cube.Render();
	sun.Render();
	cylinder.Render();
	
	glutSwapBuffers();//交换缓冲(双缓冲时使用)
}

void reshape(int width, int height)
{
	glViewport(0, 0, width, height);//设置视区(窗口内绘图区域)

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	
	gluPerspective(60,(GLfloat) width/(GLfloat)height, 1.0, 200.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void change()
{
	glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
		case 'W':   //上移
		case 'w':
			for (int i=0; i<3; i  )
				pos[i]  = step*headdir[i];
			break;
		case 'S':   //下移
		case 's':
			for (int i=0; i<3; i  )
				pos[i] -= step*headdir[i];
			break;
		case 'A':  //左移
		case 'a':
			for (int i=0; i<3; i  )
				pos[i] -= step*rightdir[i];	
			break;
		case 'D':   //右移
		case 'd':
			for (int i=0; i<3; i  )
				pos[i]  = step*rightdir[i];
			break;

		case 'Z':   
		case 'z':
			//抬高相机
	         pos[1]  = .30f;
			break;

		case 'X':   
		case 'x':
			//降低相机
	         pos[1] -= .30f;
			break;

		case 'T':   //修改绘制模式
		case 't':
			rendermode = (  rendermode)%2;
			break;	

		// 光源移动
		case '1':
			sun_position[0]  = 1.0f;
			glLightfv(GL_LIGHT1, GL_POSITION, sun_position);
			sun.SetPos(cgPoint3D(sun_position[0], sun_position[1], sun_position[2]));
			break;
		case '2':
			sun_position[0] -= 1.0f;
			glLightfv(GL_LIGHT1, GL_POSITION, sun_position);
			sun.SetPos(cgPoint3D(sun_position[0], sun_position[1], sun_position[2]));
			break;
		case '3':
			sun_position[1]  = 1.0f;
			glLightfv(GL_LIGHT1, GL_POSITION, sun_position);
			sun.SetPos(cgPoint3D(sun_position[0], sun_position[1], sun_position[2]));
			break;
		case '4':
			sun_position[1] -= 1.0f;
			glLightfv(GL_LIGHT1, GL_POSITION, sun_position);
			sun.SetPos(cgPoint3D(sun_position[0], sun_position[1], sun_position[2]));
			break;
		case '5':
			glEnable(GL_LIGHT1);
			break;
		case '6':
			glDisable(GL_LIGHT1);
			break;
		case '7':
			glEnable(GL_LIGHT0);
			break;
		case '8':
			glDisable(GL_LIGHT0);
			break;

		case 'n':
		case 'N':
			cube.UpdateTexCord();
			break;
	}

	glutPostRedisplay();
}

void SpecialKey(GLint key,GLint x,GLint y)
{
	switch (key)
	{
		case GLUT_KEY_UP:
			headdir[1]  = 0.05f;
			break;

		case GLUT_KEY_DOWN:
			headdir[1] -= 0.05f;
			break;

		case GLUT_KEY_LEFT:
			//修改前进方向
			beta  = betastep;
			headdir[0] = sin(beta / 180 * 3.14);
			headdir[2] = cos(beta / 180 * 3.14);
			headdir[1] = headdir[1];

			//修改右向方向
			rightdir[0] = -cos(beta / 180 * 3.14);
			rightdir[2] = sin(beta / 180 * 3.14);
			rightdir[1] = rightdir[1];
			break;

		case GLUT_KEY_RIGHT:
			//修改前进方向
			beta -= betastep;
			headdir[0] = sin(beta / 180 * 3.14);
			headdir[2] = cos(beta / 180 * 3.14);
			headdir[1] = headdir[1];

			//修改右向方向
			rightdir[0] = -cos(beta / 180 * 3.14);;
			rightdir[2] = sin(beta / 180 * 3.14);;
			rightdir[1] = rightdir[1];
			break;

	}

	glutPostRedisplay();
}

int main(int argc, char* argv[])
{
	glutInitWindowPosition(200, 200);//应用程序窗口位置
	glutInitWindowSize(800, 600);//窗口大小
	
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE| GLUT_DEPTH );//双缓冲,单缓冲为GLUT_SINGLE,深度缓存
	glutCreateWindow("Project Four");//创建窗口,参数为窗口标题
	init();

	glutDisplayFunc(display);//图形绘制
	glutReshapeFunc(reshape);//窗口大小变化
	glutKeyboardFunc(keyboard);//键盘交互
	glutSpecialFunc(&SpecialKey);//方向键
	glutIdleFunc(change);//空闲时间执行

	glutMainLoop();//必须,进入GLUT事件处理循环

	return 0;
}

效果展示

0 人点赞