OpenGL入门笔记(十一)

本文介绍了一个3D世界的加载和渲染过程,包括从文件中读取世界数据、定义3D对象的数据结构,并通过OpenGL进行渲染。文中详细解释了如何通过变换镜头位置和旋转角度来模拟用户在3D世界中的移动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

每个3D世界基本上可以看作是sector(区段)的集合。一个sector(区段)可以是一个房间、一个立方体、或者任意一个闭合的区间。在程序内部直接存储数据会让程序显得太过死板和无趣。从磁盘上载入世界资料,会给我们带来更多的弹性,可以让我们体验不同的世界,而不用被迫重新编译程序。另一个好处就是用户可以切换世界资料并修改它们而无需知道程序如何读入输出这些资料的。

数据文件中每个三角形都以如下形式声明:

X1 Y1 Z1 U1 V1
X2 Y2 Z2 U2 V2
X3 Y3 Z3 U3 V3

ContractedBlock.gifExpandedBlockStart.gif坐标数据文件
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
NUMPOLLIES
36

//Floor1
-3.00.0-3.00.06.0
-3.00.03.00.00.0
3.00.03.06.00.0

-3.00.0-3.00.06.0
3.00.0-3.06.06.0
3.00.03.06.00.0

//Ceiling1
-3.01.0-3.00.06.0
-3.01.03.00.00.0
3.01.03.06.00.0
-3.01.0-3.00.06.0
3.01.0-3.06.06.0
3.01.03.06.00.0

//A1

-2.01.0-2.00.01.0
-2.00.0-2.00.00.0
-0.50.0-2.01.50.0
-2.01.0-2.00.01.0
-0.51.0-2.01.51.0
-0.50.0-2.01.50.0

//A2

2.01.0-2.02.01.0
2.00.0-2.02.00.0
0.50.0-2.00.50.0
2.01.0-2.02.01.0
0.51.0-2.00.51.0
0.50.0-2.00.50.0

//B1

-2.01.02.02.01.0
-2.00.02.02.00.0
-0.50.02.00.50.0
-2.01.02.02.01.0
-0.51.02.00.51.0
-0.50.02.00.50.0

//B2

2.01.02.02.01.0
2.00.02.02.00.0
0.50.02.00.50.0
2.01.02.02.01.0
0.51.02.00.51.0
0.50.02.00.50.0

//C1

-2.01.0-2.00.01.0
-2.00.0-2.00.00.0
-2.00.0-0.51.50.0
-2.01.0-2.00.01.0
-2.01.0-0.51.51.0
-2.00.0-0.51.50.0

//C2

-2.01.02.02.01.0
-2.00.02.02.00.0
-2.00.00.50.50.0
-2.01.02.02.01.0
-2.01.00.50.51.0
-2.00.00.50.50.0

//D1

2.01.0-2.00.01.0
2.00.0-2.00.00.0
2.00.0-0.51.50.0
2.01.0-2.00.01.0
2.01.0-0.51.51.0
2.00.0-0.51.50.0

//D2

2.01.02.02.01.0
2.00.02.02.00.0
2.00.00.50.50.0
2.01.02.02.01.0
2.01.00.50.51.0
2.00.00.50.50.0

//Upperhallway-L
-0.51.0-3.00.01.0
-0.50.0-3.00.00.0
-0.50.0-2.01.00.0
-0.51.0-3.00.01.0
-0.51.0-2.01.01.0
-0.50.0-2.01.00.0

//Upperhallway-R
0.51.0-3.00.01.0
0.50.0-3.00.00.0
0.50.0-2.01.00.0
0.51.0-3.00.01.0
0.51.0-2.01.01.0
0.50.0-2.01.00.0

//Lowerhallway-L
-0.51.03.00.01.0
-0.50.03.00.00.0
-0.50.02.01.00.0
-0.51.03.00.01.0
-0.51.02.01.01.0
-0.50.02.01.00.0

//Lowerhallway-R
0.51.03.00.01.0
0.50.03.00.00.0
0.50.02.01.00.0
0.51.03.00.01.0
0.51.02.01.01.0
0.50.02.01.00.0


//Lefthallway-Lw

-3.01.00.51.01.0
-3.00.00.51.00.0
-2.00.00.50.00.0
-3.01.00.51.01.0
-2.01.00.50.01.0
-2.00.00.50.00.0

//Lefthallway-Hi

-3.01.0-0.51.01.0
-3.00.0-0.51.00.0
-2.00.0-0.50.00.0
-3.01.0-0.51.01.0
-2.01.0-0.50.01.0
-2.00.0-0.50.00.0

//Righthallway-Lw

3.01.00.51.01.0
3.00.00.51.00.0
2.00.00.50.00.0
3.01.00.51.01.0
2.01.00.50.01.0
2.00.00.50.00.0

//Righthallway-Hi

3.01.0-0.51.01.0
3.00.0-0.51.00.0
2.00.0-0.50.00.0
3.01.0-0.51.01.0
2.01.0-0.50.01.0
2.00.0-0.50.00.0

到目前为止,我们所作过的都是些简单的旋转和平移。但我们的镜头始终位于原点(000)处。任何一个不错的3D引擎都会允许用户在这个世界中游走和遍 历,我们的这个也一样。实现这个功能的一种途径是直接移动镜头并绘制以镜头为中心的3D环境。这样做会很慢并且不易用代码实现。我们的解决方法如下:

1)根据用户的指令旋转并变换镜头位置。

2)围绕原点,以与镜头相反的旋转方向来旋转世界。(让人产生镜头旋转的错觉)

3)以与镜头平移方式相反的方式来平移世界(让人产生镜头移动的错觉)

实现很简单。当左右方向键按下后,旋转变量yrot相应增加或减少。当前后方向键按下后,我们使用sinecosine函数重新生成镜头位置。Piover180是一个很简单的折算因子用来折算度和弧度。

walkbias基本上就是当人行走时头部产生上下摆动的幅度。我们使用简单的sine正弦波来调节镜头的Y轴位置。如果不添加这个而只是前后移动的话,程序看起来就没这么棒了。

ContractedBlock.gifExpandedBlockStart.gifdemo10
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
#include
<windows.h>//HeaderFileForWindows
#include<math.h>//MathLibraryHeaderFile
#include<stdio.h>//HeaderFileForStandardInput/Output
#include<gl/gl.h>//HeaderFileForTheOpenGL32Library
#include<gl/glu.h>//HeaderFileForTheGLu32Library
#include<gl/glaux.h>//HeaderFileForTheGlauxLibrary

HDChDC
=NULL;//PrivateGDIDeviceContext
HGLRChRC=NULL;//PermanentRenderingContext
HWNDhWnd=NULL;//HoldsOurWindowHandle
HINSTANCEhInstance;//HoldsTheInstanceOfTheApplication

boolkeys[256];//ArrayUsedForTheKeyboardRoutine
boolactive=TRUE;//WindowActiveFlagSetToTRUEByDefault
boolfullscreen=TRUE;//FullscreenFlagSetToFullscreenModeByDefault
boolblend;//BlendingON/OFF
boolbp;//BPressed?
boolfp;//FPressed?

constfloatpiover180=0.0174532925f;
floatheading;
floatxpos;
floatzpos;

GLfloatyrot;
//YRotation
GLfloatwalkbias=0;
GLfloatwalkbiasangle
=0;
GLfloatlookupdown
=0.0f;
GLfloatz
=0.0f;//DepthIntoTheScreen

GLuintfilter;
//WhichFilterToUse
GLuinttexture[3];//StorageFor3Textures

typedef
structtagVERTEX
{
floatx,y,z;//3D坐标
floatu,v;//纹理坐标
}VERTEX;

typedef
structtagTRIANGLE
{
//Triangle三角形结构
VERTEXvertex[3];
}TRIANGLE;

typedef
structtagSECTOR
{
intnumtriangles;//Sector中的三角形个数
TRIANGLE*triangle;//指向三角数组的指针
}SECTOR;

SECTORsector1;
//OurModelGoesHere:

LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
//DeclarationForWndProc

voidreadstr(FILE*f,char*string)
{
//读入一个字符串
do
{
fgets(
string,255,f);
}
while((string[0]=='/')||(string[0]=='/n'));
return;
}

voidSetupWorld()
{
//设置我们的世界
floatx,y,z,u,v;
intnumtriangles;
FILE
*filein;
charoneline[255];
filein
=fopen("data/world.txt","rt");//FileToLoadWorldDataFrom

readstr(filein,oneline);
sscanf(oneline,
"NUMPOLLIES%d/n",&numtriangles);

sector1.triangle
=newTRIANGLE[numtriangles];
sector1.numtriangles
=numtriangles;
for(intloop=0;loop<numtriangles;loop++)
{
for(intvert=0;vert<3;vert++)
{
readstr(filein,oneline);
sscanf(oneline,
"%f%f%f%f%f",&x,&y,&z,&u,&v);
sector1.triangle[loop].vertex[vert].x
=x;
sector1.triangle[loop].vertex[vert].y
=y;
sector1.triangle[loop].vertex[vert].z
=z;
sector1.triangle[loop].vertex[vert].u
=u;
sector1.triangle[loop].vertex[vert].v
=v;
}
}
fclose(filein);
return;
}

AUX_RGBImageRec
*LoadBMP(char*Filename)//LoadsABitmapImage
{
FILE
*File=NULL;//FileHandle

if(!Filename)//MakeSureAFilenameWasGiven
{
returnNULL;//IfNotReturnNULL
}

File
=fopen(Filename,"r");//CheckToSeeIfTheFileExists

if(File)//DoesTheFileExist?
{
fclose(File);
//CloseTheHandle
returnauxDIBImageLoad(Filename);//LoadTheBitmapAndReturnAPointer
}
returnNULL;//IfLoadFailedReturnNULL
}

intLoadGLTextures()//LoadBitmapsAndConvertToTextures
{
intStatus=FALSE;//StatusIndicator

AUX_RGBImageRec
*TextureImage[1];//CreateStorageSpaceForTheTexture

memset(TextureImage,
0,sizeof(void*)*1);//SetThePointerToNULL

//LoadTheBitmap,CheckForErrors,IfBitmap'sNotFoundQuit
if(TextureImage[0]=LoadBMP("Data/Mud.bmp"))
{
Status
=TRUE;//SetTheStatusToTRUE

glGenTextures(
3,&texture[0]);//CreateThreeTextures

//CreateNearestFilteredTexture
glBindTexture(GL_TEXTURE_2D,texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,
0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);

//CreateLinearFilteredTexture
glBindTexture(GL_TEXTURE_2D,texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);

//CreateMipMappedTexture
glBindTexture(GL_TEXTURE_2D,texture[2]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D,
3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);
}
if(TextureImage[0])//IfTextureExists
{
if(TextureImage[0]->data)//IfTextureImageExists
{
free(TextureImage[
0]->data);//FreeTheTextureImageMemory
}

free(TextureImage[
0]);//FreeTheImageStructure
}

returnStatus;//ReturnTheStatus
}

GLvoidReSizeGLScene(GLsizeiwidth,GLsizeiheight)
//ResizeAndInitializeTheGLWindow
{
if(height==0)//PreventADivideByZeroBy
{
height
=1;//MakingHeightEqualOne
}

glViewport(
0,0,width,height);//ResetTheCurrentViewport

glMatrixMode(GL_PROJECTION);
//SelectTheProjectionMatrix
glLoadIdentity();//ResetTheProjectionMatrix

//CalculateTheAspectRatioOfTheWindow
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);
//SelectTheModelviewMatrix
glLoadIdentity();//ResetTheModelviewMatrix
}

intInitGL(GLvoid)//AllSetupForOpenGLGoesHere
{
if(!LoadGLTextures())//JumpToTextureLoadingRoutine
{
returnFALSE;//IfTextureDidn'tLoadReturnFALSE
}

glEnable(GL_TEXTURE_2D);
//EnableTextureMapping
glBlendFunc(GL_SRC_ALPHA,GL_ONE);//SetTheBlendingFunctionForTranslucency
glClearColor(0.0f,0.0f,0.0f,0.0f);//ThisWillClearTheBackgroundColorToBlack
glClearDepth(1.0);//EnablesClearingOfTheDepthBuffer
glDepthFunc(GL_LESS);//TheTypeOfDepthTestToDo
glEnable(GL_DEPTH_TEST);//EnablesDepthTesting
glShadeModel(GL_SMOOTH);//EnablesSmoothColorShading
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);//ReallyNicePerspectiveCalculations

SetupWorld();
//建立世界

returnTRUE;//InitializationWentOK
}

intDrawGLScene(GLvoid)//Here'sWhereWeDoAllTheDrawing
{
glClear(GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT);//ClearTheScreenAndTheDepthBuffer
glLoadIdentity();//ResetTheView

GLfloatx_m,y_m,z_m,u_m,v_m;
GLfloatxtrans
=-xpos;
GLfloatztrans
=-zpos;
GLfloatytrans
=-walkbias-0.25f;
GLfloatsceneroty
=360.0f-yrot;

intnumtriangles;

glRotatef(lookupdown,
1.0f,0,0);
glRotatef(sceneroty,
0,1.0f,0);

glTranslatef(xtrans,ytrans,ztrans);
glBindTexture(GL_TEXTURE_2D,texture[filter]);

numtriangles
=sector1.numtriangles;

//ProcessEachTriangle
for(intloop_m=0;loop_m<numtriangles;loop_m++)
{
glBegin(GL_TRIANGLES);
glNormal3f(
0.0f,0.0f,1.0f);
x_m
=sector1.triangle[loop_m].vertex[0].x;
y_m
=sector1.triangle[loop_m].vertex[0].y;
z_m
=sector1.triangle[loop_m].vertex[0].z;
u_m
=sector1.triangle[loop_m].vertex[0].u;
v_m
=sector1.triangle[loop_m].vertex[0].v;
glTexCoord2f(u_m,v_m);glVertex3f(x_m,y_m,z_m);

x_m
=sector1.triangle[loop_m].vertex[1].x;
y_m
=sector1.triangle[loop_m].vertex[1].y;
z_m
=sector1.triangle[loop_m].vertex[1].z;
u_m
=sector1.triangle[loop_m].vertex[1].u;
v_m
=sector1.triangle[loop_m].vertex[1].v;
glTexCoord2f(u_m,v_m);glVertex3f(x_m,y_m,z_m);

x_m
=sector1.triangle[loop_m].vertex[2].x;
y_m
=sector1.triangle[loop_m].vertex[2].y;
z_m
=sector1.triangle[loop_m].vertex[2].z;
u_m
=sector1.triangle[loop_m].vertex[2].u;
v_m
=sector1.triangle[loop_m].vertex[2].v;
glTexCoord2f(u_m,v_m);glVertex3f(x_m,y_m,z_m);
glEnd();
}
returnTRUE;//EverythingWentOK
}

GLvoidKillGLWindow(GLvoid)
//ProperlyKillTheWindow
{
if(fullscreen)//AreWeInFullscreenMode?
{
ChangeDisplaySettings(NULL,
0);//IfSoSwitchBackToTheDesktop
ShowCursor(TRUE);//ShowMousePointer
}

if(hRC)//DoWeHaveARenderingContext?
{
if(!wglMakeCurrent(NULL,NULL))//AreWeAbleToReleaseTheDCAndRCContexts?
{
MessageBox(NULL,
"ReleaseOfDCAndRCFailed.","SHUTDOWNERROR",MB_OK|MB_ICONINFORMATION);
}

if(!wglDeleteContext(hRC))//AreWeAbleToDeleteTheRC?
{
MessageBox(NULL,
"ReleaseRenderingContextFailed.","SHUTDOWNERROR",MB_OK|MB_ICONINFORMATION);
}
hRC
=NULL;//SetRCToNULL
}

if(hDC&&!ReleaseDC(hWnd,hDC))//AreWeAbleToReleaseTheDC
{
MessageBox(NULL,
"ReleaseDeviceContextFailed.","SHUTDOWNERROR",MB_OK|MB_ICONINFORMATION);
hDC
=NULL;//SetDCToNULL
}

if(hWnd&&!DestroyWindow(hWnd))//AreWeAbleToDestroyTheWindow?
{
MessageBox(NULL,
"CouldNotReleasehWnd.","SHUTDOWNERROR",MB_OK|MB_ICONINFORMATION);
hWnd
=NULL;//SethWndToNULL
}

if(!UnregisterClass("OpenGL",hInstance))//AreWeAbleToUnregisterClass
{
MessageBox(NULL,
"CouldNotUnregisterClass.","SHUTDOWNERROR",MB_OK|MB_ICONINFORMATION);
hInstance
=NULL;//SethInstanceToNULL
}
}

/*ThisCodeCreatesOurOpenGLWindow.ParametersAre:*
*title-TitleToAppearAtTheTopOfTheWindow*
*width-WidthOfTheGLWindowOrFullscreenMode*
*height-HeightOfTheGLWindowOrFullscreenMode*
*bits-NumberOfBitsToUseForColor(8/16/24/32)*
*fullscreenflag-UseFullscreenMode(TRUE)OrWindowedMode(FALSE)
*/

BOOLCreateGLWindow(
char*title,intwidth,intheight,intbits,boolfullscreenflag)
{
GLuintPixelFormat;
//HoldsTheResultsAfterSearchingForAMatch
WNDCLASSwc;//WindowsClassStructure
DWORDdwExStyle;//WindowExtendedStyle
DWORDdwStyle;//WindowStyle
RECTWindowRect;//GrabsRectangleUpperLeft/LowerRightValues
WindowRect.left=(long)0;//SetLeftValueTo0
WindowRect.right=(long)width;//SetRightValueToRequestedWidth
WindowRect.top=(long)0;//SetTopValueTo0
WindowRect.bottom=(long)height;//SetBottomValueToRequestedHeight

fullscreen
=fullscreenflag;//SetTheGlobalFullscreenFlag

hInstance
=GetModuleHandle(NULL);//GrabAnInstanceForOurWindow
wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;//RedrawOnSize,AndOwnDCForWindow.
wc.lpfnWndProc=(WNDPROC)WndProc;//WndProcHandlesMessages
wc.cbClsExtra=0;//NoExtraWindowData
wc.cbWndExtra=0;//NoExtraWindowData
wc.hInstance=hInstance;//SetTheInstance
wc.hIcon=LoadIcon(NULL,IDI_WINLOGO);//LoadTheDefaultIcon
wc.hCursor=LoadCursor(NULL,IDC_ARROW);//LoadTheArrowPointer
wc.hbrBackground=NULL;//NoBackgroundRequiredForGL
wc.lpszMenuName=NULL;//WeDon'tWantAMenu
wc.lpszClassName="OpenGL";//SetTheClassName

if(!RegisterClass(&wc))//AttemptToRegisterTheWindowClass
{
MessageBox(NULL,
"FailedToRegisterTheWindowClass.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

if(fullscreen)//AttemptFullscreenMode?
{
DEVMODEdmScreenSettings;
//DeviceMode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));//MakesSureMemory'sCleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings);//SizeOfTheDevmodeStructure
dmScreenSettings.dmPelsWidth=width;//SelectedScreenWidth
dmScreenSettings.dmPelsHeight=height;//SelectedScreenHeight
dmScreenSettings.dmBitsPerPel=bits;//SelectedBitsPerPixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

//TryToSetSelectedModeAndGetResults.NOTE:CDS_FULLSCREENGetsRidOfStartBar.
if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
//IfTheModeFails,OfferTwoOptions.QuitOrUseWindowedMode.
if(MessageBox(NULL,"TheRequestedFullscreenModeIsNotSupportedBy/nYourVideoCard.UseWindowedModeInstead?","NeHeGL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen
=FALSE;//WindowedModeSelected.Fullscreen=FALSE
}
else
{
//PopUpAMessageBoxLettingUserKnowTheProgramIsClosing.
MessageBox(NULL,"ProgramWillNowClose.","ERROR",MB_OK|MB_ICONSTOP);
returnFALSE;//ReturnFALSE
}
}
}

if(fullscreen)//AreWeStillInFullscreenMode?
{
dwExStyle
=WS_EX_APPWINDOW;//WindowExtendedStyle
dwStyle=WS_POPUP;//WindowsStyle
ShowCursor(FALSE);//HideMousePointer
}
else
{
dwExStyle
=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;//WindowExtendedStyle
dwStyle=WS_OVERLAPPEDWINDOW;//WindowsStyle
}

AdjustWindowRectEx(
&WindowRect,dwStyle,FALSE,dwExStyle);//AdjustWindowToTrueRequestedSize

//CreateTheWindow
if(!(hWnd=CreateWindowEx(dwExStyle,//ExtendedStyleForTheWindow
"OpenGL",//ClassName
title,//WindowTitle
dwStyle|//DefinedWindowStyle
WS_CLIPSIBLINGS|//RequiredWindowStyle
WS_CLIPCHILDREN,//RequiredWindowStyle
0,0,//WindowPosition
WindowRect.right-WindowRect.left,//CalculateWindowWidth
WindowRect.bottom-WindowRect.top,//CalculateWindowHeight
NULL,//NoParentWindow
NULL,//NoMenu
hInstance,//Instance
NULL)))//DontPassAnythingToWM_CREATE
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"WindowCreationError.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

staticPIXELFORMATDESCRIPTORpfd=//pfdTellsWindowsHowWeWantThingsToBe
{
sizeof(PIXELFORMATDESCRIPTOR),//SizeOfThisPixelFormatDescriptor
1,//VersionNumber
PFD_DRAW_TO_WINDOW|//FormatMustSupportWindow
PFD_SUPPORT_OPENGL|//FormatMustSupportOpenGL
PFD_DOUBLEBUFFER,//MustSupportDoubleBuffering
PFD_TYPE_RGBA,//RequestAnRGBAFormat
bits,//SelectOurColorDepth
0,0,0,0,0,0,//ColorBitsIgnored
0,//NoAlphaBuffer
0,//ShiftBitIgnored
0,//NoAccumulationBuffer
0,0,0,0,//AccumulationBitsIgnored
16,//16BitZ-Buffer(DepthBuffer)
0,//NoStencilBuffer
0,//NoAuxiliaryBuffer
PFD_MAIN_PLANE,//MainDrawingLayer
0,//Reserved
0,0,0//LayerMasksIgnored
};

if(!(hDC=GetDC(hWnd)))//DidWeGetADeviceContext?
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"Can'tCreateAGLDeviceContext.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

if(!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))//DidWindowsFindAMatchingPixelFormat?
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"Can'tFindASuitablePixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd))//AreWeAbleToSetThePixelFormat?
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"Can'tSetThePixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

if(!(hRC=wglCreateContext(hDC)))//AreWeAbleToGetARenderingContext?
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"Can'tCreateAGLRenderingContext.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

if(!wglMakeCurrent(hDC,hRC))//TryToActivateTheRenderingContext
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"Can'tActivateTheGLRenderingContext.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

ShowWindow(hWnd,SW_SHOW);
//ShowTheWindow
SetForegroundWindow(hWnd);//SlightlyHigherPriority
SetFocus(hWnd);//SetsKeyboardFocusToTheWindow
ReSizeGLScene(width,height);//SetUpOurPerspectiveGLScreen

if(!InitGL())//InitializeOurNewlyCreatedGLWindow
{
KillGLWindow();
//ResetTheDisplay
MessageBox(NULL,"InitializationFailed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
returnFALSE;//ReturnFALSE
}

returnTRUE;//Success
}

LRESULTCALLBACKWndProc(HWNDhWnd,
//HandleForThisWindow
UINTuMsg,//MessageForThisWindow
WPARAMwParam,//AdditionalMessageInformation
LPARAMlParam)//AdditionalMessageInformation
{
switch(uMsg)//CheckForWindowsMessages
{
caseWM_ACTIVATE://WatchForWindowActivateMessage
{
if(!HIWORD(wParam))//CheckMinimizationState
{
active
=TRUE;//ProgramIsActive
}
else
{
active
=FALSE;//ProgramIsNoLongerActive
}

return0;//ReturnToTheMessageLoop
}

caseWM_SYSCOMMAND://InterceptSystemCommands
{
switch(wParam)//CheckSystemCalls
{
caseSC_SCREENSAVE://ScreensaverTryingToStart?
caseSC_MONITORPOWER://MonitorTryingToEnterPowersave?
return0;//PreventFromHappening
}
break;//Exit
}

caseWM_CLOSE://DidWeReceiveACloseMessage?
{
PostQuitMessage(
0);//SendAQuitMessage
return0;//JumpBack
}

caseWM_KEYDOWN://IsAKeyBeingHeldDown?
{
keys[wParam]
=TRUE;//IfSo,MarkItAsTRUE
return0;//JumpBack
}

caseWM_KEYUP://HasAKeyBeenReleased?
{
keys[wParam]
=FALSE;//IfSo,MarkItAsFALSE
return0;//JumpBack
}

caseWM_SIZE://ResizeTheOpenGLWindow
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
//LoWord=Width,HiWord=Height
return0;//JumpBack
}
}

//PassAllUnhandledMessagesToDefWindowProc
returnDefWindowProc(hWnd,uMsg,wParam,lParam);
}

intWINAPIWinMain(HINSTANCEhInstance,//Instance
HINSTANCEhPrevInstance,//PreviousInstance
LPSTRlpCmdLine,//CommandLineParameters
intnCmdShow)//WindowShowState
{
MSGmsg;
//WindowsMessageStructure
BOOLdone=FALSE;//BoolVariableToExitLoop

//AskTheUserWhichScreenModeTheyPrefer
if(MessageBox(NULL,"WouldYouLikeToRunInFullscreenMode?","StartFullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen
=FALSE;//WindowedMode
}

//CreateOurOpenGLWindow
if(!CreateGLWindow("LionelBrits&NeHe's3DWorldTutorial",640,480,16,fullscreen))
{
return0;//QuitIfWindowWasNotCreated
}

while(!done)//LoopThatRunsWhiledone=FALSE
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))//IsThereAMessageWaiting?
{
if(msg.message==WM_QUIT)//HaveWeReceivedAQuitMessage?
{
done
=TRUE;//IfSodone=TRUE
}
else//IfNot,DealWithWindowMessages
{
TranslateMessage(
&msg);//TranslateTheMessage
DispatchMessage(&msg);//DispatchTheMessage
}
}
else//IfThereAreNoMessages
{
//DrawTheScene.WatchForESCKeyAndQuitMessagesFromDrawGLScene()
if((active&&!DrawGLScene())||keys[VK_ESCAPE])//Active?WasThereAQuitReceived?
{
done
=TRUE;//ESCorDrawGLSceneSignalledAQuit
}
else//NotTimeToQuit,UpdateScreen
{
SwapBuffers(hDC);
//SwapBuffers(DoubleBuffering)
if(keys['B']&&!bp)
{
bp
=TRUE;
blend
=!blend;
if(!blend)
{
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
else
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}
}
if(!keys['B'])
{
bp
=FALSE;
}

if(keys['F']&&!fp)
{
fp
=TRUE;
filter
+=1;
if(filter>2)
{
filter
=0;
}
}
if(!keys['F'])
{
fp
=FALSE;
}

if(keys[VK_PRIOR])
{
z
-=0.02f;
}

if(keys[VK_NEXT])
{
z
+=0.02f;
}

if(keys[VK_UP])
{

xpos
-=(float)sin(heading*piover180)*0.05f;
zpos
-=(float)cos(heading*piover180)*0.05f;
if(walkbiasangle>=359.0f)
{
walkbiasangle
=0.0f;
}
else
{
walkbiasangle
+=10;
}
walkbias
=(float)sin(walkbiasangle*piover180)/20.0f;
}

if(keys[VK_DOWN])
{
xpos
+=(float)sin(heading*piover180)*0.05f;
zpos
+=(float)cos(heading*piover180)*0.05f;
if(walkbiasangle<=1.0f)
{
walkbiasangle
=359.0f;
}
else
{
walkbiasangle
-=10;
}
walkbias
=(float)sin(walkbiasangle*piover180)/20.0f;
}

if(keys[VK_RIGHT])
{
heading
-=1.0f;
yrot
=heading;
}

if(keys[VK_LEFT])
{
heading
+=1.0f;
yrot
=heading;
}

if(keys[VK_PRIOR])
{
lookupdown
-=1.0f;
}

if(keys[VK_NEXT])
{
lookupdown
+=1.0f;
}

if(keys[VK_F1])//IsF1BeingPressed?
{
keys[VK_F1]
=FALSE;//IfSoMakeKeyFALSE
KillGLWindow();//KillOurCurrentWindow
fullscreen=!fullscreen;//ToggleFullscreen/WindowedMode
//RecreateOurOpenGLWindow
if(!CreateGLWindow("LionelBrits&NeHe's3DWorldTutorial",640,480,16,fullscreen))
{
return0;//QuitIfWindowWasNotCreated
}
}
}
}
}

//Shutdown
KillGLWindow();//KillTheWindow
return(msg.wParam);//ExitTheProgram
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值