#include <windows.h>
#include <stdio.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "Flower.h"
#include "resource.h"
#pragma comment( lib, "opengl32.lib")
#pragma comment( lib, "glu32.lib")
#pragma comment( lib, "glaux.lib")
#pragma comment( lib, "scrnsave.lib")
// 用户定义变量
GLuint texture[3]; // 存储三个纹理
// 蝴蝶的数据结构
struct Butterfly
{
int tex; // 纹理标识
float x; // X坐标
float y; // Y坐标
float z; // Z坐标
float yi; // Y增加的速度,即下降的速度
float spinz; // 绕Z轴旋转
float spinzi; // 绕Z轴旋转的速度
float flap; // 三角形张合模拟蝴蝶扇翅膀:)
float fi; // 扇翅膀的方向(开还是合)
};
// 用蝴蝶的数据结构建立50个对象
Butterfly obj[50];
//为每只蝴蝶设置(随机)初始值
void SetObject(int loop)
{
obj[loop].tex = rand() % 3; // 三个纹理中随机取一个
obj[loop].x = rand() % 34 - 17.0f; // x坐标值取[-17.0,17.0]的随机值
obj[loop].y = 18.0f; // 设置y坐标为18 (屏幕顶端之外)
obj[loop].z = -((rand()%30000/1000.0f)+10.0f); // z取[-40.0,-10.0]的随机值
obj[loop].spinzi = (rand()%10000)/5000.0f-1.0f; // spinzi为[-1.0,1.0]的随机值
obj[loop].flap = 0.0f; // 扇翅膀从0.0开始
obj[loop].fi = 0.05f+(rand()%100)/1000.0f; // fi为[0.05,0.15]的随机值
obj[loop].yi = 0.001f+(rand()%1000)/10000.0f; // yi为[0.001,0.101]的随机值
}
// 从资源文件的位图信息中创建纹理
void LoadGLTextures()
{
HBITMAP hBMP; // 位图句柄
BITMAP BMP; // 位图结构
// 资源文件中定义的纹理图像的ID
byte Texture[]={IDB_BUTTERFLY1, IDB_BUTTERFLY2, IDB_BUTTERFLY3 };
glGenTextures(sizeof(Texture), &texture[0]); // 生成三个纹理的ID
for (int loop=0; loop<sizeof(Texture); loop++) // 循环处理所有位图
{
// 从资源文件中读取
hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(Texture[loop]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (hBMP) // 位图是否存在?
{ // 存在...
GetObject(hBMP, sizeof(BMP), &BMP); // 读取该位图,获取位图句柄,位图内容存于BMP中
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glBindTexture(GL_TEXTURE_2D, texture[loop]); // 绑定纹理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线性滤波
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Mipmap线性滤波
// 生成Mipmap纹理
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, BMP.bmWidth, BMP.bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); // 删除位图对象
}
}
}
// 初始化
BOOL Initialize()
{
LoadGLTextures(); // 从资源文件中装入纹理
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景
glClearDepth(1.0f); // 深度缓存
glDepthFunc(GL_LEQUAL); // 深度测试类型
glDisable(GL_DEPTH_TEST); // 禁止深度检测
glShadeModel(GL_SMOOTH); // 选择平滑明暗处理
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 设置精确的透视投影计算
glEnable(GL_TEXTURE_2D); // 激活纹理映射
glBlendFunc(GL_ONE, GL_SRC_ALPHA); // 设置颜色融合模式
glEnable(GL_BLEND); // 激活颜色融合
for (int loop=0; loop<50; loop++) // 初始化50个蝴蝶对象
{
SetObject(loop); // 设置蝴蝶对象的随机初始值
}
return TRUE; // 返回TRUE
}
// 绘制场景
void DrawGLScene(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色缓存和深度缓存
for (int loop=0; loop<50; loop++) // 在50个对象间循环
{
glLoadIdentity (); // 重置造型视图矩阵
glBindTexture(GL_TEXTURE_2D, texture[obj[loop].tex]); // 绑定纹理
glTranslatef(obj[loop].x, obj[loop].y, obj[loop].z); // 放置蝴蝶对象
glRotatef(45.0f,1.0f,0.0f,0.0f); // 绕X轴旋转
glRotatef((obj[loop].spinz),0.0f,0.0f,1.0f); // 绕Z轴旋转
glBegin(GL_TRIANGLES); // 绘制三角形
// 第一个三角形 _____
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // (2)| / (1)
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f, 1.0f, obj[loop].flap); // | /
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // (3)|/
// 第二个三角形
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // /|(1)
glTexCoord2f(0.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // / |
glTexCoord2f(1.0f,0.0f); glVertex3f( 1.0f,-1.0f, obj[loop].flap); // (2)/____|(3)
glEnd(); // 绘制完毕
obj[loop].y -= obj[loop].yi; // 将蝴蝶对象向屏幕下方移动
obj[loop].spinz += obj[loop].spinzi; // 增加绕Z轴的旋转角
obj[loop].flap += obj[loop].fi; // 增加翅膀扇的程度
if (obj[loop].y < -18.0f) // 蝴蝶飞到屏幕外了吗?
{
SetObject(loop); // 重新设置这只蝴蝶的数值
}
if ((obj[loop].flap > 1.0f) || (obj[loop].flap < -1.0f))// 翅膀扇到最大程度或最小程度了?
{
obj[loop].fi = -obj[loop].fi; // 反向扇
}
}
glFlush();
}
HDC hDC = NULL; // 设备描述表
HGLRC hRC = NULL; // 永久的绘制描述表
HWND hWnd = NULL; // 窗口句柄
HINSTANCE hInstance; // 应用程序实例
DEVMODE DMsaved; // 前一个屏幕设置
UINT uTimer; // 定时器标识
int width, height;
// 用户定义变量
float angle;
float curTime, lastTickCount;
class Vector3
{
public:
float x, y, z, r;
Vector3(float a, float b, float c)
{
x = a;
y = b;
z = c;
}
Vector3(){}
};
// 设置正交视图
void ViewOrtho()
{
glMatrixMode(GL_PROJECTION); // 选择投影矩阵
glPushMatrix(); // 矩阵入栈
glLoadIdentity(); // 装入单位矩阵
glOrtho( 0, width, height, 0, -1, 1); // 选择正交模式(WIDTHxHEIGHT)
glMatrixMode(GL_MODELVIEW); // 选择造型视图矩阵
glPushMatrix(); // 矩阵入栈
glLoadIdentity(); // 装入单位矩阵
}
// 设置透视视图
void ViewPerspective()
{
glMatrixMode( GL_PROJECTION ); // 选择投影矩阵
glPopMatrix(); // 弹出矩阵
glMatrixMode( GL_MODELVIEW ); // 选择造型视图矩阵
glPopMatrix(); // 弹出矩阵
}
// 改变OpenGL窗口的大小并对其进行初始化
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
glViewport (0, 0, (GLsizei)(width), (GLsizei)(height)); // 重置当前视口
glMatrixMode (GL_PROJECTION); // 选择投影矩阵
glLoadIdentity (); // 投影矩阵设为单位矩阵
gluPerspective(50, (float)width/(float)height, 5, 2000);
glMatrixMode (GL_MODELVIEW); // 选择造型视图矩阵
glLoadIdentity (); // 造型视图矩阵设为单位矩阵
}
GLvoid KillGLWindow(GLvoid) // 销毁窗口
{
if (hRC) // 是否有一个正确的绘制描述表
{
if (!wglMakeCurrent(NULL,NULL)) // 能否销毁DC和RC?
{
MessageBox(NULL,"释放DC与RC失败","程序关闭出错", MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // 能否删除RC?
{
MessageBox(NULL,"释放RC失败.","程序关闭出错", MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // 将RC设置为NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // 能否释放DC
{
MessageBox(NULL, "释放设备描述表失败","程序关闭出错", MB_OK | MB_ICONINFORMATION);
hDC=NULL; // 将DC设置为NULL
}
}
// 创建用于OpenGL绘制的窗口
BOOL CreateGLWindow(HWND hWnd, int bits)
{
GLuint PixelFormat;
RECT WindowRect; // 窗口的矩形
hInstance = GetModuleHandle(NULL); // 窗口实例句柄
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DMsaved); // 保存当前显示状态(NEW)
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // 像素格式描述表结构的大小
1, // 版本号
PFD_DRAW_TO_WINDOW | // 支持窗口模式
PFD_SUPPORT_OPENGL | // 支持OpenGL
PFD_DOUBLEBUFFER, // 支持双缓存
PFD_TYPE_RGBA, // 请求RGBA格式
bits, // 颜色深度
0, 0, 0, 0, 0, 0, // 忽略
0, // 不用Alpha缓存
0, // 忽略
0,