C++编写的太阳系与八大行星关系程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在VC6.0坏境下,用API编写的太阳系与八大行星关系程序
具体操作步骤如下:
(1)新建Win32API程序,工程名为:太阳系模拟。

(2)在工程目录下新建Data文件夹,在里面存放太阳.jpg ,水星金星.jpg ,地球.jpg,火星.jpg, 木星.jpg ,土星.jpg,天王星.jpg, 海王星.jpg,土星光环.jpg十张图片。

(3)新建文件:5DG’ SCuttingEarth.cpp,T exture.cpp,Vector3D.cpp,trxture.h,vector3d.h
(4)在工程主文件中编写代码如下。

1.//5DG’ SCuttingEarth.cpp
#define WM_TOGGLEFULLSCREEN (WM_USER + 1) // 定义全屏/窗口切换消息
#define TIMER1 101 // 定义时钟代号,设置为101号
#define TITLE "5DG's Cutting Earth" // 定义窗口标题#define CLASSNAME "5DG_OPENGL" // 定义窗口类名
#define WIDTH 640 // 定义窗口宽度
#define HEIGHT 480 // 定义窗口高度
#define BPP 16 // 定义每象素的位数
#define MAXTEXTURE 10 // 最大纹理数为2
// 在此处引用程序要求的头文件:
#include <windows.h> // Windows 的头文件
#include <gl\gl.h> // OpenGL32库的头文件
#include <gl\glu.h> // Glu32库的头文件
#include <math.h> // 数学函数库的头文件
#include <stdio.h> // 标准输入/输出库的头文件
#include "Texture.h" // 纹理载入的头文件
#include "Vector3D.h"
// 在此处加入程序要求的库到链接器中:
#pragma comment(lib, "opengl32.lib") // 链接时查找OpenGL32.lib
#pragma comment(lib, "glu32.lib") // 链接时查
找glu32.lib
// 在此处定义与窗口相关的结构体:
typedef struct { // 定义处理键盘的结构体
BOOL keyDown [256]; // 存储键盘按键状态的数组
} Keys;
typedef struct { // 定义存储应用程序实例的结构体
HINSTANCE hInstance; // 应用程序实例
const char* className; // 应用程序类名
} Application;
typedef struct { // 定义初始化窗口所需信息
Application* application; // 所属的应用程序
char* title; // 窗口标题int width; // 窗口宽度
int height; // 窗口高度
int bitsPerPixel; // 每像素的位数
BOOL isFullScreen; // 是否全屏} GL_WindowInit;
typedef struct { // 定义窗口结构体
Keys* keys; // 键盘HWND hWnd; // 窗口句柄
HDC hDC; // 设备描述表
HGLRC hRC; // 绘制描述表
GL_WindowInit init; // 提供Window初始化信息的结构体
} GL_Window;
// 此代码模块中包含的函数的前向声明:
BOOL Initialize(GL_Window* window, Keys* keys); // 设置你绘制前的初始化值
void DrawSceneGL(void); // 在这里完成场景的绘制
void Update(void); // 在此处更新对消息的动作
void Deinitialize(void); // 在此处做退出前扫尾工作
GL_Window* OGL_window; // 存储窗口信息
Keys* OGL_keys; // 存储按键信息
// 在此处定义用户变量:
GLuint texture[MAXTEXTURE]; // 存储纹理
GLfloat pos_z = -70.0f; // 初始化场景的深度
GLfloat angle_Y =0.0f ; // 用来绕Y 轴旋转物体
GLfloat p1 = 0.0f;
GLUquadricObj *qSphere; // 用来绘制球体
CVector3 specalPoint[8];
// 定义切割平面的位置和控制变量
GLint aType = 0;
BOOL stopRot=FALSE; // 控制地球是否自转
BOOL plane0_on = FALSE; // 第零号切割平面(上下切割)
GLdouble plane0[] = {0.0f, 1.0f, 0.0f, 0.0f};
GLfloat plane0_y = 1.0f;
BOOL plane1_on = FALSE; // 第一号切割平面(左右切割)
GLdouble plane1[] = {-1.0f, 0.0f, 0.0f, 0.0f};
GLfloat plane1_x = -1.0f;
BOOL plane2_on = TRUE; // 深度缓存切割平面(内外切割)
GLfloat plane2_z = -1.0f;
GLfloat speed = 0.2f;
BOOL pKey3 = FALSE ;
BOOL pKeyS = FALSE ;
BOOL Pause = FALSE;
void ResizeWindowGL(int width, int height) // 重新设置窗口大小
{
glViewport(0, 0, (GLsizei)(width), (GLsizei)(height));// 重置当前视口大小glMatrixMode(GL_PROJECTION); // 切换到投影矩阵模式
glLoadIdentity(); // 重置投影矩阵
gluPerspective(45, (float)width/(float)height, 0.1, 100); // 设置透视投影
glMatrixMode(GL_MODELVIEW); // 切换到模型视图矩阵
glLoadIdentity(); // 重置模型视图矩阵
}
BOOL ChangeScreenResolution(int width, int height, int bitsPerPixel) // 修改屏幕分辨率
{
DEVMODE dmScreenSettings; // 设备设置模式
ZeroMemory(&dmScreenSettings, sizeof(DEVMODE));// 清空
dmScreenSettings.dmSize = sizeof(DEVMODE); // Devmode结构的大小
dmScreenSettings.dmPelsWidth = width; // 设置为屏幕宽度
dmScreenSettings.dmPelsHeight = height; // 设置为屏幕高度
dmScreenSettings.dmBitsPerPel = bitsPerPixel; // 设为指定位长;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// 尝试设置显示模式并返回结果。

注: CDS_FULLSCREEN 移去了状态栏
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
return FALSE; // 分辨率修改失败,返回False
}
return TRUE; // 分辨率修改成功,返回True;
}
BOOL CreateWindowGL(GL_Window* window) // 建立OpenGL窗口
{
DWORD windowStyle = WS_OVERLAPPEDWINDOW; // 设置窗口样式
DWORD windowExtendedStyle = WS_EX_APPWINDOW;// 设置窗口扩展样式
PIXELFORMATDESCRIPTOR pfd = // 像素格式描述符(pfd)的设置
{
sizeof(PIXELFORMATDESCRIPTOR), // 像素的尺寸
1, // 版本号
PFD_DRAW_TO_WINDOW | // pfd必须支持窗口绘制
PFD_SUPPORT_OPENGL | // pfd必须支持OpenGL
PFD_DOUBLEBUFFER, // pfd必须支持双缓存
PFD_TYPE_RGBA, // 像素格式为RGBA
window->init.bitsPerPixel, // 设置颜色深度
0, 0, 0, 0, 0, 0, // 忽略颜色位数
0, // 无Alpha缓存
0, // 忽略偏移位
0, // 无累积缓存
0, 0, 0, 0, // 忽略累积缓存位
16, // 深度缓存为16位
0, // 无模板缓存
0, // 无辅助缓存
PFD_MAIN_PLANE, // 主要绘制层
0, //
保留位
0, 0, 0 // 忽略层遮罩
};
RECT windowRect = {0, 0, window->init.width, window->init.height}; // 定义窗口大小
GLuint PixelFormat; // 保存像素格式
if (window->init.isFullScreen == TRUE) // 切换全屏
{
if (ChangeScreenResolution(window->init.width, window->init.height, window->init.bitsPerPixel) == FALSE)
{
// 全屏切换失败
MessageBox(HWND_DESKTOP, "无法切换到全屏模式,在窗口模式下运行.\nMode Switch Failed,Running In Windowed Mode.", "Error", MB_OK | MB_ICONEXCLAMATION);
window->init.isFullScreen = FALSE; // 设置isFullscreen 为False
}
else // 全屏切换成功
{
ShowCursor (FALSE); // 隐藏鼠标
windowStyle = WS_POPUP; // 设置窗口样式
windowExtendedStyle |= WS_EX_TOPMOST; // 设置窗口扩展样式
}
}
else
{
// 调整窗口大小,包括窗口边界
AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);
}
// 开始创建OpenGL 窗口
window->hWnd = CreateWindowEx(windowExtendedStyle, // 窗口扩展样式
window->init.application->className,// 应用程序类名
window->init.title, // 窗口标题
windowStyle, // 窗口样式
0, 0, // 窗口的X,Y 坐标位置
windowRect.right - windowRect.left, // 窗口宽度
windowRect.bottom - windowRect.top, // 窗口高度
HWND_DESKTOP, // 父窗口为桌面
0, // 无菜单
window->init.application->hInstance,// 传入应用程序实例
window);
if (window->hWnd == 0) // 窗口是否成功创建
{
return FALSE; // 若失败,则返回FALSE
}
window->hDC = GetDC(window->hWnd); // 取得当前窗口的设备描述表
if (window->hDC == 0) // 若未得到设备描述表
{
DestroyWindow(window->hWnd); // 销毁该窗口
window->hWnd = 0; // 窗口句柄清零
return FALSE; // 返回FALSE
}
PixelFormat = ChoosePixelFormat(window->hDC, &pfd); // 选择兼容的像素格式
if (PixelFormat == 0) // 若选择失败
{
ReleaseDC(window->hWnd, window->hDC); // 释放设备描述表
window->hDC = 0; // 将设备描述表清零
DestroyWindow(window->hWnd); // 销毁窗口
window->hWnd = 0; // 窗口句柄清零
return FALSE; // 返回FALSE
}
if (SetPixelFormat(window->hDC, PixelFormat, &pfd) == FALSE) // 设置像素格式并判断是否失败
{
ReleaseDC(window->hWnd, window->hDC); // 释放设备描述表
window->hDC = 0; // 将设备描述表清零
DestroyWindow(window->hWnd); // 销毁窗口
window->hWnd = 0; // 窗口句柄清零
return FALSE; // 返回FALSE
}
window->hRC = wglCreateContext(window->hDC); // 取得绘制描述表
if (window->hRC == 0) // 若未得到绘制描述表
{
ReleaseDC(window->hWnd, window->hDC); // 释放设备描述表
window->hDC = 0; // 将设备描述表清零
DestroyWindow(window->hWnd); // 销毁窗口
window->hWnd = 0; // 窗口句柄清零
return FALSE; // 返回FALSE
}
if (wglMakeCurrent(window->hDC, window->hRC) == FALSE) // 设置绘制描述表并判断是否失败
{
wglDeleteContext(window->hRC); // 删除绘制描述表
window->hRC = 0; // 将绘制描述表清零
ReleaseDC(window->hWnd, window->hDC); // 释放设备描述表
window->hDC = 0; // 将设备描述表清零
DestroyWindow(window->hWnd); // 销毁窗口
window->hWnd = 0; // 窗口
句柄清零
return FALSE; // 返回FALSE
}
ShowWindow(window->hWnd, SW_NORMAL); // 显示窗口
ResizeWindowGL(window->init.width, window->init.height); // 重设窗口
ZeroMemory(window->keys, sizeof (Keys)); // 清空键盘缓冲区
return TRUE; // 窗口创建成功
}
BOOL DestroyWindowGL(GL_Window* window) // 销毁窗口并释放程序所用的资源
{
if (window->hWnd != 0) // 窗口释放有句柄?
{
if (window->hDC != 0) // 窗口是否有得到绘制描述表?
{
wglMakeCurrent(window->hDC, 0); // 将当前描述表指针置为0
if (window->hRC != 0) // 该窗口是否有绘制描述表
{
wglDeleteContext(window->hRC); // 释放绘制描述表
window->hRC = 0; // 将绘制描述表清零
}
ReleaseDC(window->hWnd, window->hDC); // 释放设备描述表
window->hDC = 0; // 将设备描述表清零
}
DestroyWindow(window->hWnd); // 销毁窗口
window->hWnd = 0; // 将窗口句柄清零
}
if (window->init.isFullScreen) // 若窗口在全屏模式下
{
ChangeDisplaySettings(NULL ,0); // 切换为桌面分辨率
ShowCursor(TRUE); // 显示鼠标}
return TRUE; // 返回TRUE
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)// 窗口消息处理
{
GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA));// 取得窗口信息
switch (uMsg) // 取得Window的消息
{
case WM_SYSCOMMAND: // 截取系统命令
{
switch (wParam) // 监听系统调用
{
case SC_SCREENSAVE: // 要运行屏保?
case SC_MONITORPOWER: // 显示器进入节电模式?
return 0; // 提前返回0,防止系统调用执行
}
break; // 退出}
case WM_CREATE: // 创建窗口
{
CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // 保存窗口结构指针
window = (GL_Window*)(creation->lpCreateParams);
SetWindowLong(hWnd, GWL_USERDATA, (LONG)(window));// 改变
return 0; // 返回}
case WM_TIMER: // TIMER事件
{
InvalidateRect(window->hWnd, NULL, FALSE); // 使窗口失效
break;
}
case WM_PAINT: // PAINT 消息处理,在此处绘图
{
DrawSceneGL(); // 在此处绘图
SwapBuffers(window->hDC); // 交换缓存
ValidateRect(window->hWnd, NULL); // 使窗口有效
break;
}
case WM_CLOSE: // 关闭窗口
{
PostMessage(window->hWnd, WM_QUIT, 0, 0); // 结束程序
return 0;
}
case WM_SIZE: // 窗口大小变化
{
ResizeWindowGL(LOWORD(lParam), HIWORD(lParam)); // 修改窗口大小为Width = LoWord, Height = HiWord
return 0; // 返回}
case WM_KEYDOWN: // 按键按下时更新键盘缓冲
if ((wParam >= 0) && (wParam <= 255)) // 按键是否合法?
{
window->keys->keyDown[wParam] = TRUE; // 设相应键
return 0; // 返回}
break; // 退出
case WM_KEYUP: // 按键松开时更新键盘缓冲
if ((wParam >= 0) && (wParam <= 255)) // 按键是否合法?
{
window->keys->keyDown[wParam] = FALSE; // 设相应键为为FALSE
return 0; // 返回}
break; // 退出
case WM_TOGGLEFULLSCREEN: // 开关全屏模式
{
Deinitialize(); // 做扫尾工作
DestroyWindowGL(window); // 销毁窗口
window->init.isFullScreen = !window->init.isFullScreen; // 改变窗口模式
CreateWindowGL(window); // 重新创建窗口
Initialize(window, window->keys); // 初始化OpenGL绘制程序
break; // 退出}
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam); // 将本程序不处理的消息传给DefWindowProc
}
BOOL RegisterWindowClass(Application* application) // 为本应用程序注册一个类
{
WNDCLASSEX windowClass; // 窗口类
ZeroMemory (&windowClass, sizeof(WNDCLASSEX));// 清空内存
windowClass.cbSize = sizeof(WNDCLASSEX); // 窗口类的大小
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;// 在窗口移动,改变大小的时候重绘
windowClass.lpfnWndProc = (WNDPROC)(WindowProc); // 用WindowProc函数处理消息
windowClass.hInstance = application->hInstance; // 设置实例
windowClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE); // 类背景的画刷颜色
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 载入鼠标指针
windowClass.lpszClassName = application->className; // 设置应用程序的类名
if (RegisterClassEx(&windowClass) == 0) // 注册类失败?
{
MessageBox(HWND_DESKTOP, "应用程序类注册失败!\nRegisterClassEx Failed!", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回False (注册失败)
}
return TRUE; // 返回True (注册成功)
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Application application; // 应用程序GL_Window window; // 窗口Keys keys; // 键盘按键MSG msg; // Window消息
BOOL bRet; // 保存消息获得是否成功
// 给应用程序赋值
application.className = CLASSNAME; // 程序类名字
application.hInstance = hInstance;// 程序入口
// 窗口相关信息设置
ZeroMemory(&window, sizeof(GL_Window));// 清零窗口变量的内存空间
window.keys = &keys; // 设置按键window.init.application = &application; // 设置窗口程序
window.init.title = TITLE; // 设置标题
window.init.width = WIDTH; // 设置窗口宽度window.init.height = HEIGHT; // 设置窗口高度
window.init.bitsPerPixel = BPP; // 设置每像素的位数
window.init.isFullScreen = FALSE; // 设置初始窗口是否全屏否(FALSE)
ZeroMemory(&keys, sizeof(Keys)); // 键盘缓冲清零
if (RegisterWindowClass(&application) == FALSE) // 注册类是否失败
{
MessageBox(HWND_DESKTOP, "窗口类注册失败!\nError Registering Window Class!", "Error", MB_OK | MB_ICONEXCLAMATION);
return -1; // 结束程序}
if (CreateWindowGL(&window) == TRUE) // 创建窗口是否成功
{
if (Initialize(&window, &keys) == FALSE) // 初始化OpenGL绘制程序
{
PostMessage(window.hWnd, WM_QUIT, 0, 0); // 抛出消息WM_QUIT
}
}
else
{
return 0; // 退出程序}
while ((bRet = GetMessage(&msg, NULL, 0, 0) != 0)) // 循环直到收到消息为WM_QUIT
{
if (bRet != -1)
{
Update(); // 更新处理消息事件
TranslateMessage(&msg); // 传递
消息
DispatchMessage(&msg); // 分派消息
}
else
{
break; // 退出循环
}
}
// 退出消息循环,准备退出程序
Deinitialize(); // 做退出前的扫尾工作
DestroyWindowGL(&window); // 销毁窗口
UnregisterClass(application.className, application.hInstance); // 注销窗口类
return 0; // 退出程序}
// 绘制地球,需要给出半径和纹理名字
void DrawBall(GLfloat radius, GLuint textureName)
{
glPushMatrix();
glEnable(GL_LIGHTING); // 开启光照
glEnable(GL_LIGHT0); // 开启光源0
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureName);
glRotatef(-90.0f, 1.0f, 0.0f,0.0f);
gluSphere(qSphere, radius, 64,64);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHT0); // 禁用光源0
glDisable(GL_LIGHTING); // 关闭光照
glPopMatrix();
}
BOOL Initialize(GL_Window* window, Keys* keys)
{
//设置全局变量
OGL_window = window;
OGL_keys = keys;
SetTimer(window->hWnd, TIMER1, 33, NULL); //建立时钟
// 在此处初始化绘制场景
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 清屏为黑色
glClearDepth(1.0f); // 设置深度缓存
glDepthFunc(GL_LEQUAL); // 选择深度测试方式
glEnable(GL_DEPTH_TEST); // 开启深度测试
glShadeModel(GL_SMOOTH); // 阴暗处理采用平滑方式
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 最精细的透视计算
BuildTexture("Data/太阳.jpg", texture[0]);
BuildTexture("Data/水星.jpg", texture[1]);
BuildTexture("Data/金星.jpg", texture[2]);
BuildTexture("Data/地球.jpg", texture[3]);
BuildTexture("Data/火星.jpg", texture[4]);
BuildTexture("Data/木星.jpg", texture[5]);
BuildTexture("Data/土星.jpg", texture[6]);
BuildTexture("Data/天王星.jpg", texture[7]);
BuildTexture("Data/海王星.jpg", texture[8]);
// BuildTexture("Data/土星光环.jpg", texture[9]);
//创建二次曲面对象
qSphere = gluNewQuadric(); // 创建二次曲面对象
gluQuadricTexture(qSphere, GL_TRUE); // 允许二次曲面可以生成纹理坐标
specalPoint[0].Set( 0.0f, 0.0f, 30.0f);
specalPoint[1].Set( 60.0f, 60.0f, 60.0f);
specalPoint[2].Set( 15.0f, 0.0f, 0.0f);
specalPoint[3].Set( 0.0f, 60.0f,-30.0f);
specalPoint[4].Set( 0.0f, 0.0f,-15.0f);
specalPoint[5].Set(-30.0f, 0.0f,-30.0f);
specalPoint[6].Set(-15.0f, 0.0f, 0.0f);
specalPoint[7].Set(-30.0f, 30.0f, 0.0f);
return TRUE; // 初始化成功返回TRUE
}
void MoveCameraPassSpecalPoint(void)
CVector3 direction; // 保存视点的运动方向
static CVector3 currentPos = specalPoint[0]; // 保存当前视点的位置
static CVector3 targetPoint = specalPoint[1]; // 保存当前视点的移动目标点
static int TargetPointId = 1; // 保存当前视点的移动目标点序号
// 更新视点位置
if (!Pause) // 如果没有暂停视点的移动
{
direction = targetPoint - currentPos; // 得到视点的运动方向
if ( direction.GetLength() > speed) // 如果视点不在目标点的周围的范围内
{
currentPos = currentPos + direction.GetNormalized()*speed;// 沿视点的运动方向更新视点的位置
}
else // 否则
{
currentPos = targetPoint; // 将视点放置在目标点上
TargetPointId = (TargetPointId + 1) % 8; // 更新目标点序号
targetPoint = specalPoint[TargetPointId]; // 更新目标点值}
}
gluLookAt(currentPos.x, currentPos.y, currentPos.z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
}
void DrawSceneGL(void) // 绘制场景{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除场景和深度缓存
glLoadIdentity(); // 重置当前矩阵
// 在此处添加代码进行绘制:
MoveCameraPassSpecalPoint();
//glTranslatef(0.0f, 0.0f ,pos_z); // 移入场景
glRotatef(angle_Y, 0.0f, 1.0f, 0.0f); // 旋转坐标系
if (!stopRot)
{
angle_Y += 1.0f;
if (angle_Y > 360.0f)
angle_Y -= 360.0f;;
}
// 太阳
DrawBall(7.0f, texture[0]);
//水星
glPushMatrix();
glTranslatef(4.5f,0.3f,0.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(0.5f, texture[1]); glPopMatrix();
//金星
glPushMatrix();
glTranslatef(9.0f,0.0f,0.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(1.2f, texture[2]); glPopMatrix();
//地球
glPushMatrix();
glTranslatef(13.5f,-0.3f,0.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(1.3f, texture[3]); glPopMatrix();
//火星
glPushMatrix();
glTranslatef(-18.0f,0.0f,0.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(0.6f, texture[4]); glPopMatrix();
//木星
glPushMatrix();
glTranslatef(-20.5f,0.0f,-6.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(3.0f, texture[5]);
glPopMatrix();
//土星
glPushMatrix();
glTranslatef(25.0f,0.0f,0.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(2.5f, texture[6]);
glPopMatrix();
//天王星
glPushMatrix();
glTranslatef(-30.0f,0.0f,-5.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(2.3f, texture[7]);
glPopMatrix();
//海王星
glPushMatrix();
glTranslatef(-35.0f,0.0f,4.0f);
glRotatef(angle_Y,0.0f,1.0f,0.0f);
DrawBall(2.0f, texture[8]);
glPopMatrix();
glFlush(); // 刷新GL命令队列
}
void Update(void)
{
if (OGL_keys->keyDown[VK_ESCAPE] == TRUE) // 判断ESC键是否按下
{
PostMessage(OGL_window->hWnd, WM_QUIT, 0, 0); // 结束程序
}
if (OGL_keys->keyDown[VK_F1] == TRUE) // 判断F1是否按下
{
PostMessage(OGL_window->hWnd, WM_TOGGLEFULLSCREEN, 0, 0); // 在全屏/窗口模式间切换
}
if (OGL_keys->keyDown['1'] == TRUE) // 判断1键是否按下
{
if (!plane0_on)
{
plane0_on = TRUE;
plane0_y = 1.0f;
plane1_on = FALSE;
aType = 1;
}
}
if (OGL_keys->keyDown['2'] == TRUE) // 判断2键是否按下
{
if (!plane1_on)
{
plane1_on = TRUE;
plane1_x = -1.0f;
plane0_on = FALSE;
aType = 2;
}
}
if (OGL_keys->keyDown['3'] == TRUE && !pKey3) // 判断3键是否按下
{
pKey3 = TRUE;
plane2_on = !plane2_on;
if (!plane2_on)
{
plane2_z = -1.0f;
}
}
if (OGL_keys->keyDown['3'] == FALSE)
{
pKey3 = FALSE;
}
if (OGL_keys->keyDown['S'] == TRUE && !pKeyS) // 判断S键是否按下
{
pKeyS = TRUE;
stopRot = !stopRot;
}
if (OGL_keys->keyDown['S'] == FALSE)
{
pKeyS = FALSE;
}
if (OGL_keys->keyDown[VK_DOWN] == TRUE)
// 判断DOWN键是否按下
{
plane2_z += 0.04f;
}
if (OGL_keys->keyDown[VK_UP] == TRUE) // 判断UP键是否按下
{
plane2_z -= 0.04f;
}
}
void Deinitialize(void) // 在此处做退出前扫尾工作
{
gluDeleteQuadric(qSphere);
KillTimer(OGL_window->hWnd, TIMER1);
}
2.//Texture.cpp,
#include <stdio.h> // 标准输入输出头文件
#include <olectl.h> // OLE控制库头文件
#include <math.h> // 数学函数头文件
#include <gl\gl.h> // OpenGL32库的头文件
#include "Texture.h"
BOOL BuildTexture(char *szPathName, GLuint &texid) // 载入图片并转换为纹理
{
HDC hdcTemp; // DC用来保存位图
HBITMAP hbmpTemp; // 保存临时位图
IPicture *pPicture; // 定义IPicture Interface
OLECHAR wszPath[MAX_PATH+1]; // 图片的完全路径
char szPath[MAX_PATH+1]; // 图片的完全路径
long lWidth; // 图像宽度long lHeight; // 图像高度
long lWidthPixels; // 图像的宽带(以像素为单位)
long lHeightPixels; // 图像的高带(以像素为单位)
GLint glMaxTexDim ; // 保存纹理的最大尺寸
if (strstr(szPathName, "http://")) // 如果路径包含http:// 则...
{
strcpy(szPath, szPathName); // 把路径拷贝到szPath
}
else // 否则从文件导入图片
{
GetCurrentDirectory(MAX_PATH, szPath); // 取得当前路径
strcat(szPath, "\\"); // 添加字符"\"
strcat(szPath, szPathName); // 添加图片的相对路径
}
MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); // 把ASCII码转化为Unicode标准码
HRESULT hr = OleLoadPicturePath(wszPath, 0, 0, 0, IID_IPicture, (void**)&pPicture);
if(FAILED(hr)) // 如果导入失败
{
// 图片载入失败出错信息
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
}
hdcTemp = CreateCompatibleDC(GetDC(0)); // 建立窗口设备描述表
if(!hdcTemp) // 建立失
败?
{
pPicture->Release(); // 释放IPicture
// 图片载入失败出错信息
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim); // 取得支持的纹理最大尺寸
pPicture->get_Width(&lWidth); // 取得IPicture 宽度(转换为Pixels格式)
lWidthPixels = MulDiv(lWidth, GetDeviceCaps(hdcTemp, LOGPIXELSX), 2540);
pPicture->get_Height(&lHeight); // 取得IPicture 高度(转换为Pixels格式)
lHeightPixels = MulDiv(lHeight, GetDeviceCaps(hdcTemp, LOGPIXELSY), 2540);
// 调整图片到最好的效果
if (lWidthPixels <= glMaxTexDim) // 图片宽度是否超过显卡最大支持尺寸
lWidthPixels = 1 << (int)floor((log((double)lWidthPixels)/log(2.0f)) + 0.5f);
else // 否则,将图片宽度设为显卡最大支持尺寸
lWidthPixels = glMaxTexDim;
if (lHeightPixels <= glMaxTexDim) // 图片高度是否超过显卡最大支持尺寸
lHeightPixels = 1 << (int)floor((log((double)lHeightPixels)/log(2.0f)) + 0.5f);
else // 否则,将图片高度设为显卡最大支持尺寸
lHeightPixels = glMaxTexDim;
// 建立一个临时位图
BITMAPINFO bi = {0}; // 位图的类型
DWORD *pBits = 0; // 指向位图Bits的指针
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // 设置结构大小
bi.bmiHeader.biBitCount = 32; // 32 位
bi.bmiHeader.biWidth = lWidthPixels; // 宽度像素值bi.bmiHeader.biHeight = lHeightPixels; // 高度像素值bi.bmiHeader.biCompression = BI_RGB; // RGB 格式
bi.bmiHeader.biPlanes = 1; // 一个位平面
// 建立一个位图这样我们可以指定颜色和深度并访问每位的值
hbmpTemp = CreateDIBSection(hdcTemp, &bi, DIB_RGB_COLORS, (void**)&pBits, 0, 0);
if(!hbmpTemp) // 建立失败?
{
DeleteDC(hdcTemp); // 删除设备描述表
pPicture->Release(); // 释放IPicture
// 图片载入失败出错信息
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
}
SelectObject(hdcTemp, hbmpTemp); // 选择临时DC句柄和临时位图对象
// 在位图上绘制IPicture
pPicture->Render(hdcTemp, 0, 0, lWidthPixels, lHeightPixels, 0, lHeight, lWidth, -lHeight, 0);
// 将BGR转换为RGB将ALPHA值设为255
for(long i = 0; i < lWidthPixels * lHeightPixels; i++) // 循环遍历所有的像素{
BYTE* pPixel = (BYTE*)(&pBits[i]); // 获取当前像素
BYTE temp = pPixel[0]; // 临时存储第一个颜色像素(蓝色)
pPixel[0] = pPixel[2]; // 将红色值存到第一位
pPixel[2] = temp; // 将蓝色值存到第三位
pPixel[3] = 255; // ALPHA值设为255
}
glGenTextures(1, &texid); // 创建纹理
// 使用来自位图数据生成的典型纹理
glBindTexture(GL_TEXTURE_2D, texid); // 绑定纹理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线形滤波glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线形滤波
// 生成纹理
glTexImage2D(GL_TEXTURE_2D, 0, 3, lWidthPixels, lHeightPixels, 0, GL_RGBA, GL_UNSIGNED_BYTE, pBits);
DeleteObject(hbmpTemp); // 删除对象
DeleteDC(hdcTemp); // 删除设备描述表
pPicture->Release(); // 释放IPicture
return TRUE; // 返回TRUE
}
BOOL BuildTexture(char *filename, TextureTga *texture) // 载入一个.TGA 文件到内存
{
GLubyte TGAheader[12] = {0,0,2,0,0,0,0,0,0,0,0,0}; // 没有压缩的TGA Header
GLubyte TGAcompare[12]; // 用来比较TGA Header
GLubyte header[6]; // Header里,头六个有用字节
GLuint bytesPerPixel; // 保存TGA 文件里每个像素用到的字节数
GLuint imageSize; // 用来保存随机产生的图像的大小
GLuint temp; // 临时变量
GLuint type = GL_RGBA; // 将默认的GL模式设置为RBGA (32 BPP)
FILE *file = fopen(filename, "rb"); // 打开TGA 文件
if (file == NULL) // 文件是否
{
// 图片载入失败出错信息
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
}
if (fread(TGAcompare,1,sizeof(TGAcompare),file) != sizeof(TGAcompare)// 是否有十二个字节可读?
|| memcmp(TGAheader,TGAcompare,sizeof(TGAheader)) != 0 // header和我们想要的是否相符?
|| fread(header,1,sizeof(header),file) != sizeof(header)) // 如果是读下六个字节
{
fclose(file); // 如果失败,关闭文件
// 图片载入失败出错信息
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
}
texture->width = header[1] * 256 + header[0]; // 确定的TGA 宽度(高字节*256+低字节)
texture->height = header[3] * 256 + header[2]; // 确定的TGA 高度(高字节*256+低字节)
if (texture->width <= 0 // 宽度是否小于等于0
|| texture->height <= 0 // 高度是否小于等于0
||(header[4] != 24 && header[4] != 32)) // TGA 是24位或32位?
{
fclose(file); // 任何一个不成立, 则关闭文件
// 图片载入失败出错信息
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
texture->bpp = header[4]; // 获取TGA每个像素的位(24 or 32)
bytesPerPixel = texture->bpp / 8; // 除以8以取得每个像素的字节
imageSize = texture->width*texture->height*bytesPerPixel; // 计算TAG数据所需要的内存
texture->imageData = (GLubyte *)malloc(imageSize); // 开辟一个内存空间用来存储TGA数据
if (texture->imageData == NULL // 用来存储的内存是否存在?
|| fread(texture->imageData, 1, imageSize, file) != imageSize) // 图像大小是否和内存空间大小相符?
{
if (texture->imageData != NULL) // 图像数据是否载入
{
free(texture->imageData); // 如果是释放图像数据
}
fclose(file); // 关闭文件
MessageBox (HWND_DESKTOP, "图片导入失败!\n(TextureLoad Failed!)", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // 返回FALSE
}
for (GLuint i=0; i<int(imageSize); i+=bytesPerPixel) // 循环遍历图像数据{ // 交换第一和第三字节(红和蓝)
temp=texture->imageData[i]; // 将图像数据‘i’的值存在临时变量中
texture->imageData[i] = texture->imageData[i + 2]; // 将第三个字节的值存到第一个字节里
texture->imageData[i + 2] = temp; // 将临时变量的值存入第三字节(第一字节的值)
}
fclose (file); // 关闭文件//创建一种纹理
glGenTextures(1, &texture->texID); // 产生OpenGL纹理ID
glBindTexture(GL_TEXTURE_2D, texture->texID); // 绑定纹理
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线性滤波glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FIL TER, GL_LINEAR); // 线性滤波
if (texture->bpp == 24) // TGA图片是不是24 位的
{
type = GL_RGB; // 如果是将'type'设置为GL_RGB
}
glTexImage2D(GL_TEXTURE_2D, 0, type, texture->width, texture->height, 0, type, GL_UNSIGNED_BYTE, texture->imageData);
return TRUE; // 纹理创建成功,返回正确
}
3. //Vector3D.cpp,
#include "VECTOR3D.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// 设置向量的三个属性
void CVector3::Set(float newX, float newY, float newZ)
{
x = newX;
y = newY;
z = newZ;
}
// 计算向量的叉乘
CVector3 CVector3::CrossProduct(const CVector3 &rhs) const
{
return CVector3(y*rhs.z-z*rhs.y, z*rhs.x-x*rhs.z, x*rhs.y-y*rhs.x);
}
// 计算向量的点乘
float CVector3::DotProduct(const CVector3 &rhs) const
{
return x*rhs.x + y*rhs.y + z*rhs.z;
}
// 向量单位化
void CVector3::Normalize()
{
float length=GetLength();
if(length==1 || length==0)
return;
float scalefactor = 1.0f/length;
x *= scalefactor;
y *= scalefactor;
z *= scalefactor;
}
// 向量单位化
CVector3 CVector3::GetNormalized() const
{
CVector3 result(*this);
result.Normalize();
return result;
}
// 计算向量的长度
float CVector3::GetLength() const
{
return (float)sqrt((x*x)+(y*y)+(z*z));
}
// 计算向量的长度的平方
float CVector3::GetSquaredLength() const
{
return (x*x)+(y*y)+(z*z);
}
// 绕X轴旋转向量,返回旋转后的向量
CVector3 CVector3::GetRotatedX(double angle) const {
if(angle==0.0)
return (*this);
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
return CVector3(x, y*cosAngle - z*sinAngle, y*sinAngle + z*cosAngle); }
// 绕X轴旋转向量
void CVector3::RotateX(double angle)
{
(*this)=GetRotatedX(angle);
}
// 绕Y轴旋转向量,返回旋转后的向量
CVector3 CVector3::GetRotatedY(double angle) const
{
if(angle==0.0)
return (*this);
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
return CVector3(x*cosAngle + z*sinAngle, y, -x*sinAngle + z*cosAngle); }
// 绕Y轴旋转向量
void CVector3::RotateY(double angle)
{
(*this)=GetRotatedY(angle);
}
// 绕Y轴旋转向量,返回旋转后的向量
CVector3 CVector3::GetRotatedZ(double angle) const
{
if(angle==0.0)
return (*this);
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
return CVector3(x*cosAngle - y*sinAngle,
x*sinAngle + y*cosAngle,
z);。

相关文档
最新文档