-
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define GLUT_DISABLE_ATEXIT_HACK
#define FILE_NAME
//
指定对
应的
FILE NAME
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define SCREEN_DEPTH 16
#define MAX_TEXTURES 100
//
最大的纹理数目
#define PRIMARY
0x4D4D//
基本块
(Primary
Chunk)
,位于文件的开始
//
主块
(Main Chunks)
#define OBJECTINFO
0x3D3D
//
网格对象的版本号
#define
VERSION
0x0002
//
.3ds
文件的版本
#define
EDITKEYFRAME
0xB000
//
所有关键帧信息的头部
//
对象的次级定义
(
< br>包括对象的材质和对象)
#define
MATERIAL
0xAFFF
//
保存纹理信息
#define
OBJECT
0x4000
//
保存对象的面、顶点等信息
//
材质的次级定义
#define MATNAME
0xA000
//
保存材质名称
#define
MATDIFFUSE
0xA020
//
对象
/
材质的颜色
#define
MATMAP
0xA200
//
新材质的头部
#define
MATMAPFILE
0xA300
//
保存纹理的文件名
#define
OBJECT_MESH
0x4100
//
新的网格对象
//
OBJECT_MESH
的次级定义
#define OBJECT_VERTICES
0x4110
//
对象顶点
#define OBJECT_FACES
0x4120
//
对象的面
#define OBJECT_MATERIAL
0x4130
//
对象的材质
#define OBJECT_UV
0x4140
//
对象的
UV
纹理坐标
int
g_ViewMode
=
GL_TRIANGLES;
bool
g_bLighting
= true;
float g_Rotatex
=
0;
float g_Rotatey
= 0;
float
g_Rotatez
=
0;
float g_x
=0;
float g_y
=0;
float g_z
=0;
//
。
。
。
。
。
。
。
。
。
p>
。
。
。
。
。
。
。
。
。
。
。定义需要导入的数据
float Rotatex
;
float Rotatey
;
float Rotatez
;
float x
;
float y
;
float z
;
double gl_x; double gl_y; double gl_z;
double
gl_pitch; double gl_roll; double gl_yaw;
double gl_wcpitch;double
gl_wcroll;double gl_wcyaw;
using namespace std;
UINT
g_Texture[MAX_TEXTURES] = {0};
HWND
g_hWnd;
RECT
g_rRect;
HDC
g_hDC;
HGLRC g_hRC;
HINSTANCE g_hInstance;
HINSTANCE
hInstance;
MMRESULT
idtimer_Opengl;
HWND
CreateMyWindow(LPSTR
strWindowName,
int
width,
int
height,
DWORD
dwStyle,
HINSTANCE hInstance);//
生成用户窗口
LRESULT
CALLBACK
WinProc(HWND
gl_hwnd,
UINT
message,
WPARAM
wParam,
LPARAM
lParam);//
消息响应
void Init(HWND gl_hWnd);//
初始化整个程序
void
InitializeOpenGL(int width, int height);//
初始化
OpenGL
bool
bSetupPixelFormat(HDC hdc);//
设置像素格式
void
SizeOpenGLScreen(int width, int height);//
初始化投影变换
int
MainLoop();//
主循环
void
RenderScene(double
gl_x,
double
gl_y,
double
gl_z,
double
gl_roll,
double
gl_pitch,
double gl_yaw)
void
DeInit();//
释放程序占用的内存空间
void
myDisplaycube();//
绘制外框架
void
glprintf();//
输出文字
//-------------
---
定义结构变量
-------------------
--------------------------------------------------
--------
//
定义
3D<
/p>
点的类,用于保存模型中的顶点
class CVector3
{
public:
float x,
y, z;
};
//
定义
2D
点类,用于保存模型的
UV
纹理坐标
class
CVector2
{
public:
float x,
y;
};
//
面的结构定义
struct tFace
{
int vertIndex[3];
int coordIndex[3];
};
//
材质信息结构体
struct
tMaterialInfo
{
char
strName[255];
char
strFile[255];
BYTE
color[3];
int
texureId;
float uTile;
float vTile;
float uOffset;
float vOffset;
}
//
对象信息结构体
struct
t3DObject
{
int
numOfVerts;
int
numOfFaces;
int
numTexVertex;
int
materialID;
char
strName[255];
CVector3
*pVerts;
//
顶点索引
//
纹理坐标索引
//
纹理名称
//
如果存在纹理映射,则表示纹理文件名称
//
对象的
RGB
颜色
//
纹理
ID
// u
重复
// v
重复
// u
纹理偏移
// v
纹理偏移
//
模型中顶点的数目
//
模型中面的数目
//
模型中纹理坐标的数目
//
纹理
ID
//
对象的名称
//
对象的顶点
CVector3
*pNormals;
//
对象的法向量
CVector2
*pTexVerts;
//
纹理
UV
坐标
tFace *pFaces;
//
对象的面信息
};
//
模型信息结构体
struct
t3DModel
{
int numOfObjects;
//
模型中对象的数目
int numOfMaterials;
//
模型中材质的数目
vector
材质链表信息
vector
//
模型中对象链表信息
};
struct tIndices
{
unsigned short a, b, c,
bVisible;
};
//
保存块信息的结构
struct tChunk
{
unsigned short int ID;
//
块的
ID
unsigned int length;
//
块的长度
unsigned int bytesRead;
//
需要读的块数据的字节数
};
//
CLoad3DS
类处理所有的装入代码
class CLoad3DS
{
public://
可以被该类中的函数、子类的函数、其友元函数访问
,
也可以由该类的对象访问
CLoad3DS();
//
初始化数据成员
//
装入
3ds
文件到模型结构中
bool
Import3DS(t3DModel *pModel, char *strFileName);
//
只能由该类中的函数、其友元函
数访问
,
不能被任何其他访问,该类的对象也不能访问
//
读一个字符串
int GetString(char *);
//
读下一个块
void ReadChunk(tChunk *);
//
读下一个块
void ProcessNextChunk(t3DModel *pModel,
tChunk *);
//
读下一个对象块
void ProcessNextObjectChunk(t3DModel
*pModel, t3DObject *pObject, tChunk *);
//
读下一个材质块
void ProcessNextMaterialChunk(t3DModel
*pModel, tChunk *);
//
读对象颜色的
RGB
值
void
ReadColorChunk(tMaterialInfo *pMaterial, tChunk
*pChunk);
//
读对象的顶点
void ReadVertices(t3DObject *pObject,
tChunk *);
//
读对象的面信息
void ReadVertexIndices(t3DObject
*pObject, tChunk *);
//
读对象的纹理坐标
void ReadUVCoordinates(t3DObject
*pObject, tChunk *);
//
读赋予对象的材质名称
void
ReadObjectMaterial(t3DModel
*pModel,
t3DObject
*pObject,
tChunk
*pPreviousChunk);
//
计算对象顶点的法向量
void
ComputeNormals(t3DModel *pModel);
//
关闭文件,释放内存空间
void CleanUp();
//
文件指针
FILE *m_FilePointer;
tChunk
*m_CurrentChunk;//
当前块
tChunk
*m_TempChunk;//
下一个块
};
CLoad3DS
g_Load3ds;
t3DModel
g_3DModel;
//.............
............
程序函数
............
..................................................
..............
int
OpenGL_Main()//
入口程序
{
<
/p>
gl_hWnd=CreateMyWindow(
飞机动态飞行
模拟
0,
hInstance);
if(gl_hWnd == NULL) return true;
Init(gl_hWnd);//
初始化整个程序
MainLoop();
return 0;}
//
创建窗口
HWND
CreateMyWindow(LPSTR
strWindowName,
int
width,
int
height,
DWORD
dwStyle,
HINSTANCE
hInstance)
{
HWND gl_hWnd;
WNDCLASS
wndclass;/*wndclass
用来保存我们的窗口类的结构。窗口类结构中保存着
我们的窗口
信息。
通过改变类的不同字段我们可以改变窗口的外观和行为。
p>
每个窗口都属于一个窗口类。当您创建窗口时,您必须为窗口注
册类
。
*/
memset(&wndclass, 0, sizeof(WNDCLASS));
= CS_HREDRAW |
CS_VREDRAW;//
设置窗口风格
dProc =
WinProc;
//
WndProc
处理消息
其实就是键盘响应
nce
= hInstance;
//
设置实例
=
LoadIcon(NULL,
IDI_APPLICATION);//
装
入
缺
省
图
标
要
使
用
windows
预定义的图标
p>
,
这时
hInstance
必须设置成
NULL
r = LoadCursor(NULL, IDC_ARROW);
//
装入鼠标指针
kground = (HBRUSH) (COLOR_W
INDOW+1);//
设置
opengl
的背景色
assName =
//
只是设定一个类型名
RegisterClass(&
wndclass);//
注册窗口的
if(!dwStyle)
dwStyle
=
WS_OVERLAPPEDWINDOW
|
WS_CLIPSIBLINGS
|
WS_CLIPCHILDREN;//
拓展窗口风格的
<
/p>
/*WS_CLIPCHILDREN
裁剪子窗口。
。
。就是不绘制与子窗口重合的父窗口部分子窗口间相
互裁减。
当两个窗口相互重叠时,设置了
< br>WS_CLIPSIBLINGS
样式的子窗口重绘时不能绘制被重叠
的部分。
WS_OVERLAPPEDWIND
OW
可以创建一个拥有各种窗口风格的窗体,包括标题,系统菜
单,边框,最小化和最大化按钮等
*/
g_hInstance = hInstance;
RECT rWindow;//
取得矩形的左上角和右下角的坐标值
= 0;
//
将
Left
设为
0
=
width;
//
宽度
=
0;
=
height;//
高度
AdjustWindowRect( &rWindow,
dwStyle, false);//
该函数依据所需计算需要的窗口矩形的
大小随后传递给
CreateWindow
函数
,用于创建一个客户区所需大小的窗口。
gl_hWnd =
CreateWindow(
- , - ,
NULL, //
无父窗口
NULL,//
无菜单
hInstance,//
实例
NULL);//
不向
WM_CREATE
传递信息
if(!gl_hWnd)
return NULL
ShowWindow(gl_hWnd, SW_SHOWNORMAL);
//
该函数设置指定窗口的显示状态
SW_SHOWNORMAL
运行时
正常大小显示
< br>UpdateWindow(gl_hWnd);//
指定客户区
Set
Focus(gl_hWnd);//
设置键盘焦点
return gl_hWnd;
}
LRESULT CALLBACK
WinProc(HWND gl_hWnd,UINT uMsg, WPARAM wParam,
LPARAM
lParam)//
窗口响应
{
static int cxClient,cyClient;
LONG
lRet = 0;
switch (uMsg)
{
case
WM_SIZE://
用于控制窗口的形状变化
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_CLOSE:
//
关闭
窗口的响应
ShowWindow(gl_hWnd,SW_HIDE)
//
隐藏窗口
break;
default:
lRet = DefWindowProc (gl_hWnd, uMsg,
wParam, lParam); //
处理无关消息
break;
}
return lRet;
}
void Init(HWND
gl_hWnd)//
初始化整个窗口
{
g_hWnd =
gl_hWnd;
GetClientRect(g_hWnd,
&g_rRect);//
该函数获取窗口客户区的坐标。
InitializeOpenGL(g_, g_);//
以
hWnd
代表的客户区的矩形的宽和高
为变量初始化
opengl
g_3DS(&g_3DModel, FILE_NAME);
//
将
3
ds
文件装入到模型
结构体中
glEnable(GL_LIGHT0); //
使用默认的
0
号灯
glEnable(GL_LIGHTING);
//
使用灯光
glEnable(GL_COLOR_MA
TERIAL);
//
使用颜色材质
}
void InitializeOpenGL(int
width, int height) //
初始化
OpenGL
{
g_hDC =
GetDC(g_hWnd);
if (!bSetupPixelFormat(g_hDC))
PostQuitMessage (0);
g_hRC =
wglCreateContext(g_hDC);
//
函
数建立一个适合在指定
hdc
上绘制的
RC
,
RC
与
DC
有相同的像素格式
wglMakeCurrent(g_hDC,
g_hRC);
glEnable(GL_TEXTURE_2D);//
开启
2D
纹理贴图功能
glEnable(GL_DEPTH_TEST);
//
开启深度测试
SizeOpenGLScreen(width, height);
}
bool bSetupPixelFormat(HDC hdc)
//
设置设置像素格式
{
PIXELFORMATDESCRIPTOR pfd;
int pixelformat;
=
sizeof(PIXELFORMATDESCRIPTOR);
on = 1;
s
=
PFD_DRAW_TO_WINDOW
|
PFD_SUPPORT_OPENGL
|
PFD_DOUBLEBUFFER;
rMask = PFD_MAIN_PLANE;
Type =
PFD_TYPE_RGBA;
Bits = SCREEN_DEPTH;
Bits = SCREEN_DEPTH;
Bits = 0;
ilBits = 0;
if
( (pixelformat = ChoosePixelFormat(hdc, &pfd)) ==
FALSE ) //
获取
opengl
最佳像素
{
return FALSE;
}
if (SetPixelFormat(hdc,
pixelformat, &pfd) == FALSE)
//
设置像素格式
{
return FALSE;
}
return TRUE;
}
void SizeOpenGLScreen(int width, int
height)//
初始化投影变换
{
if
(height==0)
{
height=1;
}
glViewport(0,0,width,height);//
设置实际图像映射的像素矩形
glMatrixMode(GL_PROJECTION)
;//
指定当前矩阵
glLoadIdentity(
);//
变成单位矩阵
gluPerspective(
45.0f,////
角度
(GLfloat)width/(GLfloat)hei
ght,//
视景体的宽高比
.5f ,//
沿
< br>z
轴方向的两裁面之间的距离的近处
150.0f//
沿
z
轴方向的两裁面之间的距离的远处
);//
设置透视投影矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int
MainLoop()//
主循环
{
MSG msg;
while(1)
{
if
(PeekMessage(&msg,
NULL,
0,
0,
PM_REMOVE))
//
该函数为一个消息检查线程
消息队
列,并将该消息(如果存在)放于指定的结构。
p>
//PM_REMOVE
:
PeekMes
sage
处理后,消息从队列里除掉
{
if(e == WM_CLOSE)
break;
TranslateMessage(&msg);
//
键盘码的转化
DispatchMessage(&msg);
//
分发消息到回调函数,系统通过调用回调函数实
现在窗体中实现对应操作
}
else
{
glprintf();//
输出状
态文字
gl_x=0;gl_y=0;gl_z=0;
gl_wcpitch=;gl_wcroll=;gl_wcyaw=;
gl_pitch=gl_wcp
itch;gl_roll=gl_wcroll;gl_yaw=gl_wcyaw;
RenderScene(gl_
x,gl_y,gl_z,gl_roll,gl_pitch,gl_yaw);//
控制飞机的姿态和观察角度并
且对应的在
opengl
中绘制
3ds
模型
}
}
for(int i = 0; i <
g_bjects; i++)//
清空图形的相关变量
{
//
删除所有的变量
delete []
g_t[i].pFaces;//
对象的面
delete []
g_t[i].pNormals;//
给出法向量
delete []
g_t[i].pVerts; //
对象的顶点
delete []
g_t[i].pTexVerts;//
纹理
UV
坐标
}
DeInit();
//
释放程序占用的内存空间
return();
}
void DeInit()//
释放程序占用的内存空间
{
if (g_hRC)
{
wglMakeCurrent(NULL, NULL);
//
用
于
释
放
opengl
里
面
的
上
下
文
环
境
--------------------
渲染上下文句柄
为
null
时才有这个功能
wgl
DeleteContext(g_hRC);//
删除渲染内容的句柄
}
if (g_hDC)
ReleaseDC(g_hWnd, g_hDC);//
函
数释放设备上下文环境(
DC
)供其他应用程序使用
p>
UnregisterClass(
//
该
函数注销一个窗口类,一类释放所需的内
存
PostQuitMessage (0);
}
//
文字显示
void glprintf()
{
char str0[100];
sprintf(str0,
char
str_pitch[] =
俯仰角度:
strcat(str_pitch, str0);
SetBkColor(g_hDC,NULL);
Text
Out(g_hDC,5,5,str_pitch,strlen(str_pitch));
SetTextColor(g_hDC,RGB(0,200,0));
char str1[100];
sprintf(str1,
char
str_roll[] =
滚转角度:
strcat(str_roll, str1);
SetBkColor(g_hDC,NULL);
Text
Out(g_hDC,5,20,str_roll,strlen(str_roll));
SetTextColor(g_hDC,RGB(0,200,0));
char str2[100];
sprintf(str2,
char str_yaw[]
=
偏航角度:
strcat(str
_yaw, str2);
SetBkColor(g_hDC,NULL);
p>
TextOut(g_hDC,5,35,str_yaw,strlen(str_yaw
));
SetTextColor(g_hDC,RGB(0,200,0));
char str3[100];
sprintf(str3,
char str_x[] =
轴位移:
strcat(str_x, str3);
SetBkColor(g_hDC,NULL);
Text
Out(g_hDC,5,60,str_x,strlen(str_x));
SetTextColor(g_hDC,RGB(0,200,0));
char str4[100];
sprintf(str4,
char str_y[] =
轴位移:
strcat(str_y, str4);
SetBkColor(g_hDC,NULL);
Text
Out(g_hDC,5,75,str_y,strlen(str_y));
SetTextColor(g_hDC,RGB(0,200,0));
char str5[100];
sprintf(str5,
char str_z[] =
轴位移:
strcat(str_z, str5);
SetBkColor(g_hDC,NULL);
Text
Out(g_hDC,5,90,str_z,strlen(str_z));
SetTextColor(g_hDC,RGB(0,200,0));
}
void
RenderScene(double
gl_x,
double
gl_y,
double
gl_z,
double
gl_roll,
double
gl_pitch,
double gl_yaw)
{
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT); //
清
除
p>
颜色
缓冲以
及
深度
缓冲
glLoadIdentit
y();//
设置为单位矩阵
gluLookAt(1.2,1.2,-1.2,
0,
0, 0,
-1,-1,-1);//
设置观察坐标,视点坐
标,视线朝向
glPushMatrix();
myDisplaycub
e();glPopMatrix();//
绘制外部正方体框架
g_x=gl_x;
g_y=gl_y; g_z=gl_z;
g_Rotatex=gl_roll;g_Rotatey=
gl_pitch;g_Rotatez=gl_yaw;
glTranslatef(g_
x,g_y,g_z);//
机翼是
y
方向从机头前方看右侧有正,机身前后方向是
x
机
头方向为正方向
,机身垂直是
z
向下为正方向
glRotatef(g_Rotatex,1.0f,
0, 0);//
是飞机
roll
p>
的角度
glRotatef(g_Rotatey, 0, 1.0f,
0);//pitch
的角度
glRotatef(g_Rotatez,
0,
0,1.0f);//yaw
的角度
glPushMatrix();
//
将当前变换矩阵
(
单位阵
)
压入堆栈
glPopMatrix();
//
遍历模型中所有的对象(将显示列表里的信息显示出来)
for(int i = 0; i <
g_bjects; i++)
{
//
如果模型中没有对应的对象,则退出
if(g_() <= 0) break;
//
获得当前显示的对象
t3DObject *pObject =
&g_t[i];
glBegin(g_ViewMode);//
开始以
p>
g_ViewMode
模式绘制
-
-
-
-
-
-
-
-
-
上一篇:英语语篇教学
下一篇:hypermesh网格划分小技巧