📄 terrain3dtestview.cpp
字号:
// Terrain3DTestView.cpp : implementation of the CTerrain3DTestView class
//
#include "stdafx.h"
#include "Terrain3DTest.h"
#include "MilkShapeModel.h"
#include "Terrain3DTestDoc.h"
#include "Terrain3DTestView.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
GLuint texturem = 0;
GLfloat XPOS = -MAX/2;
GLfloat YPOS = 0;
GLfloat ZPOS = -MAX/2;
GLfloat XP=0;
GLfloat YP=0;
GLfloat ZP=0;
GLfloat xtrans = MAX/2;
GLfloat ytrans = 0;
GLfloat ztrans = MAX/2;
GLfloat visual_distance = 100;
GLfloat sun_height = 1000;
GLfloat sun_zdistance = -5000;
GLfloat xtexa;
GLfloat ytexa;
GLfloat xtexa2;
GLfloat ytexa2;
int xrange1 ;
int xrange2 ;
int zrange1 ;
int zrange2 ;
GLfloat xrot=0; // 绕 X 轴旋转
GLfloat yrot=0; // 绕 Y 轴旋转
GLfloat zrot=0; // 绕 Z 轴旋转
GLfloat Throttlei;
GLfloat Throttle = 5;
GLfloat _Throttle=Throttle;
GLfloat Speed = Throttle;
GLfloat Speedi;
GLfloat piover180 = 0.0174532925f;
GLfloat sceneroty;
GLfloat heading;
GLfloat pitch = 0;
GLfloat yaw = 0;
GLfloat zprot;
int quality = 3;
GLfloat H = 0;
GLfloat glow = .4;
GLfloat glowp = 0;
bool wireframe = FALSE; // 线框绘制模式ON/OFF
bool water = true; // 是否绘制水 ON/OFF
bool Afterburner = false;
GLUquadricObj *quadratic;
GLuint texture[8];
GLuint MODEL;
GLfloat V;
GLfloat Angle;
int loop;
/////////////////////////////////////////////////////////////////////////////
// CTerrain3DTestView
IMPLEMENT_DYNCREATE(CTerrain3DTestView, CView)
BEGIN_MESSAGE_MAP(CTerrain3DTestView, CView)
//{{AFX_MSG_MAP(CTerrain3DTestView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTerrain3DTestView construction/destruction
CTerrain3DTestView::CTerrain3DTestView()
{
// TODO: add construction code here
pModel = NULL;
}
CTerrain3DTestView::~CTerrain3DTestView()
{
}
BOOL CTerrain3DTestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
////////////////////////////////////////////////////////////////
//设置窗口类型
cs.style |=WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
////////////////////////////////////////////////////////////////
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTerrain3DTestView drawing
void CTerrain3DTestView::OnDraw(CDC* pDC)
{
CTerrain3DTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//////////////////////////////////////////////////////////////////
RenderScene(); //渲染场景
//////////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////
// CTerrain3DTestView printing
BOOL CTerrain3DTestView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CTerrain3DTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CTerrain3DTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CTerrain3DTestView diagnostics
#ifdef _DEBUG
void CTerrain3DTestView::AssertValid() const
{
CView::AssertValid();
}
void CTerrain3DTestView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CTerrain3DTestDoc* CTerrain3DTestView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTerrain3DTestDoc)));
return (CTerrain3DTestDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTerrain3DTestView message handlers
int CTerrain3DTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//////////////////////////////////////////////////////////////////
//初始化OpenGL和设置定时器
m_pDC = new CClientDC(this);
SetTimer(1, 20, NULL);
InitializeOpenGL(m_pDC);
//////////////////////////////////////////////////////////////////
pModel = new MilkShapeModel(); // Memory To Hold The Model
if ( pModel->loadModelData( "model.ms3d" ) == false ) // Loads The Model And Checks For Errors
{
MessageBox( "Couldn't load the model data\\model.ms3d", "Error", MB_OK | MB_ICONERROR );
return 0; // If Model Didn't Load Quit
}
InitGL();
return 0;
}
void CTerrain3DTestView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
/////////////////////////////////////////////////////////////////
//删除调色板和渲染上下文、定时器
::wglMakeCurrent(0,0);
::wglDeleteContext( m_hRC);
if (m_hPalette)
DeleteObject(m_hPalette);
if ( m_pDC )
{
delete m_pDC;
}
KillTimer(1);
/////////////////////////////////////////////////////////////////
}
void CTerrain3DTestView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if (cy==0)
{
cy=1;
}
/////////////////////////////////////////////////////////////////
//添加窗口缩放时的图形变换函数
glViewport(0,0,cx,cy);
/////////////////////////////////////////////////////////////////
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.9f,50000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void CTerrain3DTestView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
/////////////////////////////////////////////////////////////////
//添加定时器响应函数和场景更新函数
Invalidate(FALSE);
/////////////////////////////////////////////////////////////////
CView::OnTimer(nIDEvent);
}
/////////////////////////////////////////////////////////////////////
// 设置逻辑调色板
//////////////////////////////////////////////////////////////////////
void CTerrain3DTestView::SetLogicalPalette(void)
{
struct
{
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
} logicalPalette = { 0x300, 256 };
BYTE reds[] = {0, 36, 72, 109, 145, 182, 218, 255};
BYTE greens[] = {0, 36, 72, 109, 145, 182, 218, 255};
BYTE blues[] = {0, 85, 170, 255};
for (int colorNum=0; colorNum<256; ++colorNum)
{
logicalPalette.aEntries[colorNum].peRed =
reds[colorNum & 0x07];
logicalPalette.aEntries[colorNum].peGreen =
greens[(colorNum >> 0x03) & 0x07];
logicalPalette.aEntries[colorNum].peBlue =
blues[(colorNum >> 0x06) & 0x03];
logicalPalette.aEntries[colorNum].peFlags = 0;
}
m_hPalette = CreatePalette ((LOGPALETTE*)&logicalPalette);
}
//////////////////////////////////////////////////////////
// 初始化openGL场景
//////////////////////////////////////////////////////////
BOOL CTerrain3DTestView::InitializeOpenGL(CDC* pDC)
{
m_pDC = pDC;
SetupPixelFormat();
//生成绘制描述表
m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc());
//置当前绘制描述表
::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);
return TRUE;
}
//////////////////////////////////////////////////////////
// 设置像素格式
//////////////////////////////////////////////////////////
BOOL CTerrain3DTestView::SetupPixelFormat()
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // pfd结构的大小
1, // 版本号
PFD_DRAW_TO_WINDOW | // 支持在窗口中绘图
PFD_SUPPORT_OPENGL | // 支持 OpenGL
PFD_DOUBLEBUFFER, // 双缓存模式
PFD_TYPE_RGBA, // RGBA 颜色模式
24, // 24 位颜色深度
0, 0, 0, 0, 0, 0, // 忽略颜色位
0, // 没有非透明度缓存
0, // 忽略移位位
0, // 无累加缓存
0, 0, 0, 0, // 忽略累加位
32, // 32 位深度缓存
0, // 无模板缓存
0, // 无辅助缓存
PFD_MAIN_PLANE, // 主层
0, // 保留
0, 0, 0 // 忽略层,可见性和损毁掩模
};
int pixelformat;
pixelformat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);//选择像素格式
::SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd); //设置像素格式
if(pfd.dwFlags & PFD_NEED_PALETTE)
SetLogicalPalette(); //设置逻辑调色板
return TRUE;
}
//////////////////////////////////////////////////////////
// 场景绘制与渲染
//////////////////////////////////////////////////////////
BOOL CTerrain3DTestView::RenderScene()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
RestoreMyDefaultSettings();
if (-XPOS < 0) XPOS -= MAX;
if (-XPOS > MAX) XPOS += MAX;
if (-ZPOS < 0) ZPOS -= MAX;
if (-ZPOS > MAX) ZPOS += MAX;
xtrans = -XPOS;
ytrans = YPOS;
ztrans = -ZPOS;
yrot = heading;
sceneroty = 360.0f - yrot;
H = sceneroty;
if (H > 360) H = 0;
else if (H < 0) H = 360;
glLoadIdentity();
glTranslatef(0,0,-10);
glRotatef(sceneroty,0,1,0);
glTranslatef(xtrans,ytrans-3.5-ABS(Speed)/5,ztrans);
xrange1 = int(MAX-xtrans - visual_distance);
xrange2 = int(MAX-xtrans + visual_distance);
zrange1 = int(MAX-ztrans - visual_distance);
zrange2 = int(MAX-ztrans + visual_distance);
if (quality != 1)
{
xrange1 /= quality;
xrange1 *= quality;
xrange2 /= quality;
xrange2 *= quality;
zrange1 /= quality;
zrange1 *= quality;
zrange2 /= quality;
zrange2 *= quality;
}
if (wireframe)
{
DrawWireframe();
}
else
{
DrawTexture();
}
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
Caculate();
::SwapBuffers(m_pDC->GetSafeHdc()); //交互缓冲区
return TRUE;
}
bool CTerrain3DTestView::InitGL(GLvoid)
{
if (!m_texture.LoadGLTextures()) // 装入纹理
{
return FALSE; // 如果纹理不存在,则返回FALSE
}
float fog_r = 211.f/255.f;
float fog_g = 237.f/255.f;
float fog_b = 254.f/255.f;
glClearColor(fog_r, fog_g, fog_b, 1); // 黑背景颜色
glClearDepth(1.0f); // 深度缓冲设置
RestoreMyDefaultSettings();
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
// 设置光照效果
GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightSpecular[]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightPosition[]= { 0.0f, 0.0f, 0.0f, 1.0f };
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR,LightSpecular);
glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
glEnable(GL_LIGHT1);
// 设置雾化效果
GLuint fogMode[]= { GL_EXP, GL_EXP2, GL_LINEAR }; // 保存三种雾的模式
GLuint fogfilter = 0; // 当前使用的雾的模式
GLfloat fogColor[4] = {fog_r, fog_g, fog_b, 1}; // 雾的颜色
glFogi(GL_FOG_MODE, fogMode[2]); // 设置雾的模式
glFogfv(GL_FOG_COLOR, fogColor); // 设置雾的颜色
glFogf(GL_FOG_DENSITY, 0.294f); // 设置雾的浓度
glHint(GL_FOG_HINT, GL_NICEST); // Fog Hint Value
glFogf(GL_FOG_START, 10.0f); // 设置雾的开始深度
glFogf(GL_FOG_END, visual_distance); // 设置雾的结束深度
glEnable(GL_FOG); // 使用雾
quadratic=gluNewQuadric();
gluQuadricNormals(quadratic, GLU_SMOOTH); // 生成光滑法向
gluQuadricTexture(quadratic, GL_TRUE); // 生成纹理坐标
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
InitTerrain();
InitSmoke();
MODEL = pModel->makeDisplayList(); // 生成模型的显示列表
return TRUE;
}
GLfloat CTerrain3DTestView::Hypot(GLfloat A, GLfloat B)
{
return sqrt(A*A+B*B);
}
GLfloat CTerrain3DTestView::ABS(GLfloat A)
{
if (A < 0)
A = -A;
return A;
}
void CTerrain3DTestView::RestoreMyDefaultSettings()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_FOG);
}
void CTerrain3DTestView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -