OpenGL显示枫叶蝴蝶,无聊作品

这是一个使用OpenGL和GLUT库创建3D蝴蝶飞行动画的程序。代码中包括了键盘控制、鼠标交互、场景渲染等功能,通过改变翅膀角度模拟蝴蝶的开合。程序还实现了地面网格的绘制和光源效果,提供了丰富的交互体验。
摘要由CSDN通过智能技术生成

#include <windows.h>

#include <iostream>
#include <gl/gl.h>
#include <gl/GLUT.h>
#include <math.h>

#include "maple.h"

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glut32.lib")

//全局变量定义
enum                              //枚举鼠标变量
{
	BUTTON_LEFT = 0,
	BUTTON_RIGHT,
};


const int ESC = 27;
int wireframe = 0;    //判断是否填充的变量

int mButton = -1;
int mOldY, mOldX;        //鼠标位置的变量
float eye[3] = { 0.0f, 0.0f, 10.0f };   //观察视角
float rot[3] = { 0.0f, 0.0f, 0.0f }; //旋转变量
int bOrbitOn = 0;      //判断是否转动的变量
float f = 1;         //转动速度的变量

model_obj m;            //蝴蝶模型
float flyangle = 22.5f; //翅膀之间的角度
bool flyopen = true;    //翅膀开合


void glutResize(int width, int height)//重置OpenGL窗口大小
{

	glViewport(0, 0, width, height);  //重置当前视口
	glMatrixMode(GL_PROJECTION);     //选择投影矩阵
	glLoadIdentity();                //重置投影矩阵
	gluPerspective(55.0, (float)width / (float)height, 1.0, 300.0);//设置视口大小
	glMatrixMode(GL_MODELVIEW);      //选择模型观察矩阵
	glLoadIdentity();                //重置模型观察矩阵
}

void glutKeyboard(unsigned char key, int x, int y)//键盘控制函数
{
	switch (key)
	{
	case ESC:
		//退出程序
		exit(0);
		break;
	case ' ':
		//暂停OR旋转
		bOrbitOn = !bOrbitOn;
		glutPostRedisplay();
		break;
	case 'a':
		//加速
		f++;
		break;
	case 'd':
		//减速
		f--;
		break;
	case 'p':
		//全屏
		glutFullScreen();
		break;
	case 'q':
		//非全屏
		glutReshapeWindow(800, 600);
		break;
	}
}

void clamp(float *v)//旋转
{
	int i;
	for (i = 0; i < 3; i++)
		//图像旋转一周后回到原地
		if (v[i] > 360 || v[i] < -360)
			v[i] = 0;
}

void glutMotion(int x, int y)//图像移动函数
{
	if (mButton == BUTTON_LEFT)
		//按下左键时可以任意旋转图像
	{
		rot[0] -= (mOldY - y);
		rot[1] -= (mOldX - x);
		clamp(rot);
	}
	else if (mButton == BUTTON_RIGHT)
		//按右键可缩放图像
	{
		eye[2] -= (mOldY - y) * 0.05f;
		clamp(rot);
	}
	mOldX = x;
	mOldY = y;
}

void glutMouse(int button, int state, int x, int y)//鼠标控制函数
{
	if (state == GLUT_DOWN)
	{
		mOldX = x;
		mOldY = y;
		switch (button)
		{
		case GLUT_LEFT_BUTTON:
			mButton = BUTTON_LEFT;
			break;
		case GLUT_RIGHT_BUTTON:
			mButton = BUTTON_RIGHT;
			break;
		}
	}
	else if (state == GLUT_UP)
		mButton = -1;
}

//改变摄像机
void LookAt()
{
	glTranslatef(-eye[0], -eye[1], -eye[2]);//视口

											//控制旋转
	glRotatef(rot[0], -1.0f, 0.0f, 0.0f);
	//glRotatef(rot[1], 0.0f, 0.0f, -1.0f);
	glRotatef(rot[1], 0.0f, 1.0f, 0.0f);
	glRotatef(rot[2], 0.0f, 1.0f, 0.0f);
}

//绘制蝴蝶
//angle 两个翅膀之间的角度
void DrawButterfly(float angle)
{
	glRotatef(20, 0.0f, 0.0f, 1.0f);

	//左半块
	glPushMatrix();//入栈

	glRotatef(-angle, 0.0f, 1.0f, 0.0f);
	glRotatef(-45, 0.0f, 0.0f, 1.0f);

	DrawMaple();    //绘制半个枫叶

	glTranslatef(0.25f, -0.125f, -0.0125f);   //做一些偏移
	glRotatef(200.0f, 0.0f, 0.0f, 1.0f);    //两个翅膀的角度
	glRotatef(175.0f, 0.0f, 1.0f, 0.0f);
	glRotatef(-80.0f, 0.0f, 0.0f, 1.0f);
	glScalef(0.75f, 0.75f, 0.75f);

	DrawMaple();    //绘制半个枫叶

	glPopMatrix();  //出栈


					//右半块
	glPushMatrix();//入栈

				   //旋转
	glRotatef(angle, 0.0f, 1.0f, 0.0f);
	glRotatef(-45, 0.0f, 0.0f, 1.0f);

	DrawMaple();    //绘制半个枫叶

	glTranslatef(0.25f, -0.125f, 0.0125f);    //做一些偏移
	glRotatef(200.0f, 0.0f, 0.0f, 1.0f);    //两个翅膀的角度
	glRotatef(185.0f, 0.0f, 1.0f, 0.0f);
	glRotatef(-80.0f, 0.0f, 0.0f, 1.0f);
	glScalef(0.75f, 0.75f, 0.75f);

	DrawMaple();    //绘制半个枫叶

	glPopMatrix();  //出栈
}

//绘制地面网格
void DrawGrid()
{
	glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
	glBegin(GL_LINES);
	for (int i = -10; i <= 10; ++i) {
		glVertex3f(-10.0f, 0.0f, i);
		glVertex3f(10.0f, 0.0f, i);
	}
	for (int i = -10; i <= 10; ++i) {
		glVertex3f(i, 0.0f, -10.0f);
		glVertex3f(i, 0.0f, 10.0f);
	}
	glEnd();
}

void glutDisplaytTest(void)//显示函数
{
	glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空颜色和深度缓冲

	glLoadIdentity();

	glPushMatrix();//入栈

	LookAt();//改变摄像头

			 //根据摄像头角度,更改光源位置(太阳)
	GLfloat first_light_position[] = { -10.0f, 10.0f, -10.0f, 0.0f }; // 光源的位置
	glLightfv(GL_LIGHT0, GL_POSITION, first_light_position); //指定第0号光源的位置

	DrawGrid();//绘制网格

			   //蝴蝶的颜色
	glColor3f(1.0, 0.0, 0.0);

	if (bOrbitOn) {    //用这个变量做个小动画,空格控制开合
		if (flyopen) {
			flyangle += 0.1f;
			if (flyangle > 80.0f) {
				flyopen = false;
			}
		}
		else {
			flyangle -= 0.1f;
			if (flyangle < 10.0f) {
				flyopen = true;
			}
		}
	}

	//绘制蝴蝶
	DrawButterfly(flyangle);

	glPopMatrix();  //出栈


	glFlush();
	glutSwapBuffers();

	//if (bOrbitOn)    //判断是否旋转
	//    rot[1] += f;    //旋转速度
}

//做一些初始化操作
void Init()
{
	//定义光源属性

	// 定义太阳光源,它是一种白色的光源
	{
		GLfloat first_light_position[] = { -10.0f, 10.0f, -10.0f, 0.0f }; // 光源的位置
		GLfloat first_light_ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };     //微弱的环境光
		GLfloat first_light_diffuse[] = { 0.8f, 0.4f, 0.4f, 1.0f };     //稍微发红的漫反射光
		GLfloat first_light_specular[] = { 1.0f, 0.0f, 0.0f, 1.0f };    //红色的高光

		glLightfv(GL_LIGHT0, GL_POSITION, first_light_position); //指定第0号光源的位置
		glLightfv(GL_LIGHT0, GL_AMBIENT, first_light_ambient); //环境
		glLightfv(GL_LIGHT0, GL_DIFFUSE, first_light_diffuse); //漫反射
		glLightfv(GL_LIGHT0, GL_SPECULAR, first_light_specular);//镜面反射

		glEnable(GL_LIGHT0); //使用第0号光照
		glEnable(GL_LIGHTING); //在后面的渲染中使用光照
		glEnable(GL_DEPTH_TEST); //启用深度测试

		glDepthFunc(GL_LEQUAL);//default
		glClearDepth(1.0);//设置清除深度缓冲区所用的值
	}

	//定义红色粉笔盒

	//*
	GLfloat mat_ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
	GLfloat mat_diffuse[] = { 0.4f, 0.4f, 0.4f, 1.0f };
	//GLfloat mat_specular[] = { 0.4f, 0.4f, 0.4f, 1.0f};
	GLfloat mat_specular[] = { 0.60f, 0.60f, 0.60f, 1.0f };
	GLfloat mat_emission[] = { 0.0f, 0.0f, 0.f, 1.0f };
	GLfloat mat_shininess = 32.0f; //壳体的粗糙度

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);//环境光:各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线颜色
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);//漫反射光:光线照射到该材质上,经过漫反射后形成的光线颜色
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);//镜面反射光:光线照射到该材质上,经过镜面反射后形成的光线颜色
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emission);//辐射光:微微的向外发射光线,眼睛感觉到这样的颜色,又比较微弱,以至于不会影响到其它物体的颜色
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);//“镜面指数”,取值范围是0到128。该值越小,越粗糙,值越大,越类似于镜面,产生较小的亮点。
																//*/

	glEnable(GL_COLOR_MATERIAL);//开启颜色追踪

	glShadeModel(GL_SMOOTH);//投影模式,好像不管用
	glEnable(GL_CULL_FACE);//剔除背面
						   //glDisable(GL_CULL_FACE);//剔除背面

						   //打开混合
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

}

int main(int argc, char** argv)  //主函数
{
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);    //设置初始显示模式 双缓存窗口 深度缓存 RGBA颜色模式
	glutInitWindowPosition(0, 0);  //窗口位置
	glutInitWindowSize(800, 600);             //窗口大小
	glutInit(&argc, argv);//初始化GLUT
	glutCreateWindow("计算机图形学范例");                      //窗口名称

														 //初始化
	Init();

	//@@@@@@@@@@@@@@@@@@@@@@@@@
	glutDisplayFunc(glutDisplaytTest);                                  //注册一个绘图函数,必要时刻就会对窗体进行重新绘制操作
	glutIdleFunc(glutDisplaytTest);                                     //设置全局的回调函数
	glutPostRedisplay();
	//@@@@@@@@@@@@@@@@@@@@@@@@@


	glutReshapeFunc(glutResize);                                   //根据缩放后的窗口重新设置
	glutKeyboardFunc(glutKeyboard);                                //处理键盘输入事件的函数名
	glutMouseFunc(glutMouse);                                      //处理鼠标输入事件的函数名
	glutMotionFunc(glutMotion);    //当有鼠标键按下的时候,mouse move消息会导致glut调用glutMotionFunc
	glutMainLoop();                                                //进入GLUT事件处理循环
	return 0;                                                      //返回
}

 蝴蝶绘制代码

https://download.csdn.net/download/sdragonx/14035372

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值