#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