opengl学习手记(三) 旋转的三维立方体
- 格式:doc
- 大小:44.00 KB
- 文档页数:5
opengl学习(三)----绘制简单图形(⼀)今天说⼀说⼏种简单的图元。
所有的⼏何图元都是根据它们的顶点来描绘的。
⽽顶点就是它们在屏幕上的坐标位置。
我喜欢把这⼏个简单的图元称为点线⾯。
点,可以看到⼀个顶点;线,就是两个顶点指定的⼀条有限长度的线段;⾯,其实更准确讲是⼀个凸多边形。
opengl⾥所讲的多边形是内部⽤颜⾊填充的,视觉上称为⾯我个⼈认为是更贴近的。
当然,多边形也是由指定的顶点组成的。
需要注意的是,要想被opengl按照设计被绘制必须正确的认识到,所谓的多边形是顶点都处于⼀个平⾯上,凸多边形。
凸多边形不能理解的,请问度娘。
来看⼀个例⼦:C++代码1. glBegin(GL_POLYGON);2. glVertex2f(0.0, 0.0);3. glVertex2f(0.0, 3.0);4. glVertex2f(4.0, 3.0);5. glVertex2f(6.0, 1.5);6. glVertex2f(4.0, 0.0);7. glEnd();先不去关⼼代码本⾝,这段代码最终的结果是要指定5个顶点绘制⼀个凸五边形。
注意,不是5条线段⽽是⼀个凸五边形的平⾯。
不管是点线⾯的哪⼀种,都是需要指定⼀组顶点的。
如何判定顶点指定的开始和结束就是glBegin和glEnd的⼯作。
引⽤void glBegin(Glenum mode);标志着⼀个顶点数据列表的开始,它描述了⼀个⼏何图元。
mode参数指定了图元的类型。
void glEnd(void);标志着⼀个顶点数据列表的结束。
mode设置的不同,代表着将要绘制的图元也不同。
下⾯这个表就是图元的名称和含义:值含义GL_POINTS 单个的点GL_LINES ⼀对顶点被解释为⼀条直线GL_LINE_STRIP ⼀系列的连接直线GL_LINE_LOOP 和上⾯相同,但第⼀个顶点和最后⼀个顶点彼此相连GL_TRIANGLES 3个顶点被解释为⼀个三⾓形GL_TRIANGLES_STRIP 三⾓形的连接串GL_TRIANGLES_FAN 连接成扇形的三⾓形系列GL_QUADS 4个顶点被解释为⼀个四边形GL_QUADS_STRIP 四边形的连接串GL_POLYGON 简单的凸多边形的边界试想着,如果将glBegin(GL_POLYGON)修改为glBegin(GL_POINTS),绘制出来的将是什么图形呢? 哈哈,那就是5个点⽽已么。
glLoadIdentity()与glTranslatef()和glRotatef()--坐标变换glLoadIdentity()将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作1.X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
3.中心左面的坐标值是负值,右面是正值。
移向屏幕顶端是正值,移向屏幕底端是负值。
移入屏幕深处是负值,移出屏幕则是正值。
glTranslatef(x, y, z)沿着X, Y 和Z 轴移动。
注意在glTranslatef(x, y, z)中,当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。
其作用就是将你绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////glLoadIdentity();glTranslatef(-1.5f,0.0f,-6.0f);glBegin(GL_TRIANGLES);glVertex3f(0.0f,0.0f, 0.0f);glVertex3f(1.0f,0.0f, 0.0f);glVertex3f(0.0f,1.0f, 0.0f);glEnd();glLoadIdentity();glTranslatef(0.0f,0.0f,-6.0f);glBegin(GL_TRIANGLES);glVertex3f(0.0f,0.0f, 0.0f);glVertex3f(1.0f,0.0f, 0.0f);glVertex3f(0.0f,1.0f, 0.0f);glEnd();/////////////////////////////////////////////////////////////////////////////////////程序的运行结果如下:左边的三角形是第一步绘制的,可以看到该三角形绘制的坐标系,实际上是以(-1.5f,0.0f,-6.0f)为原点的。
OpenGL实现3DS文件中的模型自由旋转文章出处:/course/3_program/c++/cppsl/20071119/86921_2.html摘要简述如何在OpenGL中,读入和显示3DS文件中的模型,并着重阐述通过鼠标拖动对其进行自由旋转的数学基础和编程实现的方法。
关键词OpenGL 3DS文件格式VC++ 自由旋转现在已经有很多论文和书籍提到在OpenGL中实现读入和显示3DS文件中的模型。
但是在很多场合,仅读入和显示是不够的。
我们需要从各个角度观察模型,以便更好地理解模型的形态,形成更为直观的感性认识。
例如,在医学髁上骨折诊断中,如果把骨折后,断骨错位旋转的情况用三维模型模拟出来,并仅用鼠标的拖动就能实现从任何角度观看骨折的情况,这将对医生做出正确的诊断大有裨益。
这也是我们为何考虑实现此项功能的初衷。
本文将简要介绍3DS文件格式,怎样读入和显示模型,而重点放在通过鼠标拖动实现模型自由旋转的数学基础和编程实现的方法和经验。
3DS文件的格式以及读入和显示文件中模型的一些经验.3DS文件是由许多块(chunk)组成的(大块中镶嵌子块)。
由于至今为止,没有一个官方的文献说明其格式,所以还有很多未知的块。
不过这并不影响我们读入3DS文件中的模型。
因为我们在读入时,可以根据自己的需要选择性地读入自己需要的块,而忽略掉那些不感兴趣或未知的块。
这正是块结构给我们带来的好处。
一个块由块信息和块数据组成。
块信息又由块的ID(两个字节长的标识,如4D4D)和块的长度(四个字节,其实也就是下一个块的偏移字节数)组成。
用VC++以十六进制方式打开一3DS文件可以很清楚的看到其结构。
在读入这种块结构(大块中嵌套小块,而块的结构固定)的文件时,完全可以用递归的方法实现,而返回上一级(子块读完,返回父块)的条件则是当前已经读入的块的字节数是否等于块的长度。
从父块转向读入其子块,则可用switch语句实现,通过子块的ID判断进入哪个分支。
/** This Code Was Created By Jeff Molofee 2000* A HUGE Thanks To Fredric Echols For Cleaning Up* And Optimizing The Base Code, Making It More Flexible!* If You've Found This Code Useful, Please Let Me Know.* Visit My Site At */#include <windows.h> // Header File For Windows#include <gl\gl.h> // Header File For The OpenGL32 Library#include <gl\glu.h> // Header File For The GLu32 Library#include <gl\glaux.h> // Header File For The Glaux LibraryHDC hDC=NULL; // Private GDI Device ContextHGLRC hRC=NULL; // Permanent Rendering ContextHWND hWnd=NULL; // Holds Our Window HandleHINSTANCE hInstance; // Holds The Instance Of The Applicationbool keys[256]; // Array Used For The Keyboard Routinebool active=TRUE; // Window Active Flag Set To TRUE By Defaultbool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By DefaultGLfloat rtri; // Angle For The Triangle ( NEW )GLfloat rquad; // Angle For The Quad ( NEW )LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProcGLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window{if (height==0) // Prevent A Divide By Zero By{height=1; // Making Height Equal One }glViewport(0,0,width,height); // Reset The Current ViewportglMatrixMode(GL_PROJECTION); // Select The Projection MatrixglLoadIdentity(); // Reset The Projection Matrix// Calculate The Aspect Ratio Of The WindowgluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);glMatrixMode(GL_MODELVIEW); // Select The Modelview MatrixglLoadIdentity(); // Reset The Modelview Matrix}int InitGL(GLvoid) // All Setup For OpenGL Goes Here{glShadeModel(GL_SMOOTH); // Enable Smooth ShadingglClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black BackgroundglClearDepth(1.0f); // Depth Buffer Setup glEnable(GL_DEPTH_TEST); // Enables Depth TestingglDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To DoglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculationsreturn TRUE; // Initialization Went OK}int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth BufferglLoadIdentity(); // Reset The Current Modelview MatrixglTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0glRotatef(rtri,0.0f,1.0f,0.0f); // Rotate The Triangle On The Y axis ( NEW )glBegin(GL_TRIANGLES); // Start Drawing A TriangleglColor3f(1.0f,0.0f,0.0f); // RedglVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front) glColor3f(0.0f,1.0f,0.0f); // GreenglVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)glColor3f(0.0f,0.0f,1.0f); // BlueglVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)glColor3f(1.0f,0.0f,0.0f); // RedglVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right) glColor3f(0.0f,0.0f,1.0f); // BlueglVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)glColor3f(0.0f,1.0f,0.0f); // GreenglVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)glColor3f(1.0f,0.0f,0.0f); // RedglVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back) glColor3f(0.0f,1.0f,0.0f); // GreenglVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back) glColor3f(0.0f,0.0f,1.0f); // BlueglVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)glColor3f(1.0f,0.0f,0.0f); // RedglVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left) glColor3f(0.0f,0.0f,1.0f); // BlueglVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left) glColor3f(0.0f,1.0f,0.0f); // GreenglVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)glEnd(); // Done Drawing The PyramidglLoadIdentity(); // Reset The Current Modelview MatrixglTranslatef(1.5f,0.0f,-7.0f); // Move Right 1.5 Units And Into The Screen 7.0glRotatef(rquad,1.0f,1.0f,1.0f); // Rotate The Quad On The X axis ( NEW )glBegin(GL_QUADS); // Draw A Quad glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top)glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top)glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom)glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom)glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom)glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom)glColor3f(1.0f,0.0f,0.0f); // Set The Color To RedglVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front)glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front)glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow glVertex3f( 1.0f,-1.0f,-1.0f); // Top Right Of The Quad (Back)glVertex3f(-1.0f,-1.0f,-1.0f); // Top Left Of The Quad (Back)glVertex3f(-1.0f, 1.0f,-1.0f); // Bottom Left Of The Quad (Back)glVertex3f( 1.0f, 1.0f,-1.0f); // Bottom Right Of The Quad (Back)glColor3f(0.0f,0.0f,1.0f); // Set The Color To BlueglVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left)glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left)glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left)glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right)glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right)glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right)glEnd(); // Done Drawing The Quadrtri+=0.2f; // Increase The Rotation Variable For The Triangle ( NEW )rquad-=0.15f; // Decrease The Rotation Variable For The Quad ( NEW )return TRUE; // Keep Going}GLvoid KillGLWindow(GLvoid) // Properly Kill The Window{if (fullscreen) // Are We In Fullscreen Mode?{ChangeDisplaySettings(NULL,0); // If So Switch Back To The DesktopShowCursor(TRUE); // Show Mouse Pointer }if (hRC) // Do We Have A Rendering Context?{if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?{MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);}if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?{MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);}hRC=NULL; // Set RC To NULL }if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC{MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);hDC=NULL; // Set DC To NULL }if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The{MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);hWnd=NULL; // Set hWnd To NULL }if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class{MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);hInstance=NULL; // Set hInstance To NULL }}/* This Code Creates Our OpenGL Window. Parameters Are: ** title - Title To Appear At The Top Of The Window ** width - Width Of The GL Window Or Fullscreen Mode ** height - Height Of The GL Window Or Fullscreen Mode ** bits - Number Of Bits To Use For Color (8/16/24/32) ** fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) {GLuint PixelFormat; // Holds The Results After Searching For A Match WNDCLASS wc; // Windows Class StructureDWORD dwExStyle; // Window Extended StyleDWORD dwStyle; // Window StyleRECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values WindowRect.left=(long)0; // Set Left Value To 0WindowRect.right=(long)width; // Set Right Value To Requested WidthWindowRect.top=(long)0; // Set Top Value To 0WindowRect.bottom=(long)height; // Set Bottom Value To Requested Heightfullscreen=fullscreenflag; // Set The Global Fullscreen FlaghInstance = GetModuleHandle(NULL); // Grab An Instance For Our Windowwc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messageswc.cbClsExtra = 0; // No Extra Windowwc.cbWndExtra = 0; // No Extra Window Datawc.hInstance = hInstance; // Set The Instancewc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Iconwc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointerwc.hbrBackground = NULL; // No Background Required For GLwc.lpszMenuName = NULL; // We Don't Want A Menuwc.lpszClassName = "OpenGL"; // Set The Class Nameif (!RegisterClass(&wc)) // Attempt To Register The Window Class{MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }if (fullscreen) // Attempt Fullscreen Mode?{DEVMODE dmScreenSettings; // Device Modememset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's CleareddmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode StructuredmScreenSettings.dmPelsWidth = width; // Selected Screen WidthdmScreenSettings.dmPelsHeight = height; // Selected Screen HeightdmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per PixeldmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) {// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not SupportedBy\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES){fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE}else{// Pop Up A Message Box Letting User Know The Program Is Closing.MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);return FALSE; // Return FALSE }}}if (fullscreen) // Are We Still In Fullscreen Mode?{dwExStyle=WS_EX_APPWINDOW; // Window Extended StyledwStyle=WS_POPUP; // Windows StyleShowCursor(FALSE); // Hide Mouse Pointer}else{dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended StyledwStyle=WS_OVERLAPPEDWINDOW; // Windows Style }AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size// Create The Windowif (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window"OpenGL", // Class Nametitle, // Window TitledwStyle | // Defined Window StyleWS_CLIPSIBLINGS | // Required Window StyleWS_CLIPCHILDREN, // Required Window Style0, 0, // Window PositionWindowRect.right-WindowRect.left, // Calculate Window WidthWindowRect.bottom-WindowRect.top, // Calculate Window HeightNULL, // No Parent WindowNULL, // No MenuhInstance, // InstanceNULL))) // Dont Pass Anything To WM_CREATE{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be{sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor1, // Version NumberPFD_DRAW_TO_WINDOW | // Format Must Support WindowPFD_SUPPORT_OPENGL | // Format Must Support OpenGLPFD_DOUBLEBUFFER, // Must Support Double BufferingPFD_TYPE_RGBA, // Request An RGBA Formatbits, // Select Our Color Depth0, 0, 0, 0, 0, 0, // Color Bits Ignored0, // No Alpha Buffer0, // Shift Bit Ignored0, // No Accumulation Buffer0, 0, 0, 0, // Accumulation Bits Ignored16, // 16Bit Z-Buffer (Depth Buffer)0, // No Stencil Buffer0, // No Auxiliary BufferPFD_MAIN_PLANE, // Main Drawing Layer0, // Reserved0, 0, 0 // Layer Masks Ignored };if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Can't Activate The GL RenderingContext.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }ShowWindow(hWnd,SW_SHOW); // Show The WindowSetForegroundWindow(hWnd); // Slightly Higher Priority SetFocus(hWnd); // Sets Keyboard Focus To The WindowReSizeGLScene(width, height); // Set Up Our Perspective GL Screenif (!InitGL()) // Initialize Our Newly Created GL Window{KillGLWindow(); // Reset The DisplayMessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);return FALSE; // Return FALSE }return TRUE; // Success}LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This WindowUINT uMsg, // Message For This WindowWPARAM wParam, // Additional Message InformationLPARAM lParam) // Additional Message Information{switch (uMsg) // Check For Windows Messages {case WM_ACTIVATE: // Watch For Window Activate Message{// LoWord Can Be WA_INACTIVE, WA_ACTIVE, WA_CLICKACTIVE,// The High-Order Word Specifies The Minimized State Of The Window Being Activated Or Deactivated.// A NonZero Value Indicates The Window Is Minimized.if ((LOWORD(wParam) != WA_INACTIVE) && !((BOOL)HIWORD(wParam)))active=TRUE; // Program Is Activeelseactive=FALSE; // Program Is No Longer Activereturn 0; // Return To The Message Loop }case WM_SYSCOMMAND: // Intercept System Commands{switch (wParam) // Check System Calls{case SC_SCREENSAVE: // Screensaver Trying To Start?case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?return 0; // Prevent From Happening }break; // Exit}case WM_CLOSE: // Did We Receive A Close Message?{PostQuitMessage(0); // Send A Quit Messagereturn 0; // Jump Back}case WM_KEYDOWN: // Is A Key Being Held Down?{keys[wParam] = TRUE; // If So, Mark It As TRUEreturn 0; // Jump Back}case WM_KEYUP: // Has A Key Been Released?{keys[wParam] = FALSE; // If So, Mark It As FALSEreturn 0; // Jump Back}case WM_SIZE: // Resize The OpenGL Window{ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Heightreturn 0; // Jump Back}}// Pass All Unhandled Messages To DefWindowProcreturn DefWindowProc(hWnd,uMsg,wParam,lParam);}int WINAPI WinMain( HINSTANCE hInstance, // InstanceHINSTANCE hPrevInstance, // Previous InstanceLPSTR lpCmdLine, // Command Line Parametersint nCmdShow) // Window Show State{MSG msg; // Windows Message StructureBOOL done=FALSE; // Bool Variable To Exit Loop// Ask The User Which Screen Mode They Preferif (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO){fullscreen=FALSE; // Windowed Mode }// Create Our OpenGL Windowif (!CreateGLWindow("NeHe's Solid Object Tutorial",640,480,16,fullscreen)){return 0; // Quit If Window Was Not Created}while(!done) // Loop That Runs While done=FALSE {if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?{if (msg.message==WM_QUIT) // Have We Received A Quit Message?{done=TRUE; // If So done=TRUE}else // If Not, Deal With Window Messages{TranslateMessage(&msg); // Translate The MessageDispatchMessage(&msg); // Dispatch The Message }}else // If There Are No Messages{// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?{done=TRUE; // ESC or DrawGLSceneSignalled A Quit}else // Not Time To Quit, Update Screen{SwapBuffers(hDC); // Swap Buffers (Double Buffering)}if (keys[VK_F1]) // Is F1 Being Pressed?{keys[VK_F1]=FALSE; // If So Make Key FALSEKillGLWindow(); // Kill Our Current Windowfullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode// Recreate Our OpenGL Windowif (!CreateGLWindow("NeHe's Solid Object Tutorial",640,480,16,fullscreen)){return 0; // Quit If Window Was Not Created}}}}// ShutdownKillGLWindow(); // Kill The Windowreturn (msg.wParam); // Exit The Program}。
OpenGL入门学习——第五课三维的空间变换今天要讲的是三维变换的内容,课程比较枯燥。
主要是因为很多函数在单独使用时都不好描述其效果,我只好在最后举一个比较综合的例子。
希望大家能一口气看到底了。
只看一次可能不够,如果感觉到迷糊,不妨多看两遍。
有疑问可以在下面跟帖提出。
我也使用了若干图形,希望可以帮助理解。
在前面绘制几何图形的时候,大家是否觉得我们绘图的范围太狭隘了呢?坐标只能从-1到1,还只能是X轴向右,Y轴向上,Z轴垂直屏幕。
这些限制给我们的绘图带来了很多不便。
我们生活在一个三维的世界——如果要观察一个物体,我们可以:1、从不同的位置去观察它。
(视图变换)2、移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它。
(模型变换)3、如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果。
另外,我们可能只希望看到物体的一部分,而不是全部(剪裁)。
(投影变换)4、我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部。
(视口变换)这些,都可以在OpenGL中实现。
OpenGL变换实际上是通过矩阵乘法来实现。
无论是移动、旋转还是缩放大小,都是通过在当前矩阵的基础上乘以一个新的矩阵来达到目的。
关于矩阵的知识,这里不详细介绍,有兴趣的朋友可以看看线性代数(大学生的话多半应该学过的)。
OpenGL可以在最底层直接操作矩阵,不过作为初学,这样做的意义并不大。
这里就不做介绍了。
1、模型变换和视图变换从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。
在OpenGL中,实现这两种功能甚至使用的是同样的函数。
由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。
设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数,像这样:glMatrixMode(GL_MODELVIEW);通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。
旋转的立方体通过本例学习,应掌握三维图层、“摄像机”图层、“空白”图层的建立,图层素材“替换”、“父源”属性设置的方法,以及“位置”和立体“旋转”设置方法。
1.建立一个新的合成图像“旋转的立方体”,参数:宽640,高480,30帧/秒,长度为10秒。
2.建立一个固态层,参数:宽200,高200,正方形像素,颜色为255,0,0。
3.选择固态层,按<Ctrl+D>组合键5次,复制出5个图层,分别改变5个固态层的颜色为不同的颜色经。
(选择某个固态层,选择“图层/固态层设置”命令)。
4.单击三维图层按钮,将6个固态层转换为三维图层。
5.创建摄像机层。
在时间线窗口中单击右键,在弹出的快捷菜单中选择“新建/摄像机”命令。
然后在弹出的对话框设置参数:预置50MM,其他不变。
6.为便于观察立方体,按<C>键切换到图层旋转工具,在预览窗口中拖动鼠标旋转视图。
7.制作立方体。
同时选择6个固态层,按<R>键打开旋转参数设置,6个固态层的“方向”值依次是:90,0,0/0,90,0/0,0,90/270,0,0/0,0,0/0,270,0。
(在调整过程中可不断旋转视图,以便观察各面的位置)8.按<P>键打开位置参数设置,依次是:320,340,100/220,240,100/320,240,200/320,240,100/320,240,0/420,240,100。
9.用图片替换不同颜色的固态层。
在“项目”窗口中选择一个固态层,然后右击,在弹出的快捷菜单中选择“替换素材/文件”命令,接着在弹出的对话框中选择需要替换的图片文件。
(切记:把对话框左下方的“序列不可用”取消钩选)10.制作立方体旋转着飞入场景画面。
要时间线窗口的空白处单击右键,从弹出的快捷菜单中选择“新建/空白对象”命令,新建一个“空白1”层。
目录1.课程设计介绍 (1)1.1.内容 (1)1.2.目的 (1)1.3.取得的成果 (1)2.程序分析 (2)2.1. 程序原理 (2)2.1. 程序流程 (3)2.3. 数据结构 (8)2.4. 重要函数用法分析 (8)3.结果演示与程序分析 (9)3.1. 成果演示 (9)3.2. 程序分析 (11)4.编程中遇到的问题 (12)5.课程设计小结 (13)参考文献 (14)基于OpenGL的3D旋转魔方实现1.课程设计介绍1.1目的当今计算机技术流行,引领了各行各业。
而程序是计算机的灵魂,因此编程能力对当今的学生而言至关重要。
虽然我们在前期已经学习了C语言,但是还只对程序有一些简单的认识,说实话,是很浅显的认识。
通过本软件课程设计的学习,可以从整体上对软件工程和项目有全面的认识。
通过此次课程设计,可以锻炼编程能力,激发对编程的兴趣,同时也能培养良好的编程习惯。
这对于个人今后的学习,今后的工作乃至今后的生活都会产生重要的影响。
对于国家而言,极大的推动了计算机普及教育,提高了大学生的计算机使用水平,具有重大的意义。
1.2内容(1)通过此次项目掌握软件开发模式,模块化结构分析以及程序设计流程(2)学会使用VC++6.0进行编程(3)掌握有关程序设计的思想,数据结构的知识,掌握C语言算法,掌握OpenGL 编程知识如贴图与键盘控制(4)掌握win32编程知识,了解windows程序内部运行机制(5)初步培养需求分析、软件测试、调试的能力(6)在2X2魔方的基础上,尝试编写3X3的魔方,并实现其旋转1.3取得的成果在理解Magic2D例子程序的基础上,借助了Win32平台进行了一系列调试和学习。
在此次项目中,学习了Visual C++6.0软件开发环境,熟练掌握了Win32 Application开发流程。
同时也学习了OpenGL的基本知识,掌握了一些OpenGL的重要技术与重要函数的使用,编写了一些简单的OpenGL程序。
XXXXXXXX大学(计算机图形学)实验报告实验名称利用OpenGL实现图形的平移、旋转、缩放实验时间年月日专业姓名学号预习操作座位号教师签名总评一、实验目的:1.了解OpenGL下简单图形的平移、旋转、缩放变换的编程的基本思想;2.掌握OpenGL下简单图形的平移、旋转、缩放变换的编程的基本步骤;二、实验原理:在OpenGL中,可以使用下面三个函数便捷地实现简单图形平移、旋转、缩放变换的功能:glRotatef(theta, vx, vy, vz);glTranslatef(dx, dy, dz);glScalef(sx,sy,sz);三、实验内容:// 1.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "glut.h"#include "math.h"void display(){glClear( GL_COLOR_BUFFER_BIT); // Clear the frame bufferglColor3f( 0.0, 1.0, 1.0); // Set current color to greenglBegin( GL_POL YGON); // Draw the triangleglVertex2f( 0.0, -0.2);glVertex2f( 0.2, 0.0);glVertex2f( 0.0, 0.0);glEnd();glFlush();}void dsp()glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Clear the frame bufferglColor3f( 0.0, 1.0, 1.0); // Set current color to greendisplay();//-------------------------- //平移glPushMatrix();glTranslatef(0.5,0.5,0.0);display();glPopMatrix();//-------------------------- //缩放glPushMatrix();glScalef(0.5,0.5,0.0);display();glPopMatrix();//-------------------------- //旋转glPushMatrix();glRotatef(60,0.0,0.0,1.0);display();glPopMatrix();}void init(){glClearColor( 0.0, 0.0, 0.0, 0.0); // Set the clear color to black// Specify the boundaries of the viewing windowglMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(-1.0, 1.0, -1.0, 1.0); // The para are: (left, right, bottom, top)glMatrixMode(GL_MODELVIEW);}int main(int argc, char* argv[]){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);glEnable(GL_DEPTH_TEST);glutCreateWindow("simple");glutDisplayFunc(dsp);init();glutMainLoop();return 0;原图:平移:缩放:旋转:四、实验总结:1.在分别查看图像的平移、缩放、旋转中的其中一个功能时,需要将其他两个的代码注释掉,否则只会显示旋转一个功能。
华中科技大学电子科学与技术系课程设计报告( 2010-- 2011年度第2 学期)名称:软件课程设计题目:基于OpenGL的3D旋转魔方实现院系:班级:学号:学生姓名:指导教师:设计周数:成绩:日期:年月日目录1.课程设计介绍............................................................................................ (2)1.1目的.............................................................................................................. (2)1.2内容.............................................................................................................. (2)1.3取得的成果 (2)2.程序分析..................................................................................................... (3)2.1 程序原理 (3)2.2 程序流程 (4)2.3 数据结构 (13)2.4 重要函数 (13)3.程序分析与结果演示 (16)3.1 成果演示 (16)3.2 程序分析 (17)4.出现过的问题 (18)5.心得和小节 (19)1.课程设计介绍1.1目的21世纪是高科技时代,是信息技术时代,而计算机技术无疑会引领各行各业,为我们带来一个全新的时代。
作为新世纪的接班人,我们必须拥有良好的计算机应用能力,才能跟上世界发展的大流,不至于在激烈的竞争中被淘汰。
而程序作为计算机的灵魂,因此编程能力对当代大学生来说至关重要。
opengl学习手记(三) 旋转的三维立方体
注意:
1. 在onInit函数中加入了,开启深度测试的代码。
2. glClear清屏的时候多个参数GL_DEPTH_BUFFER_BIT,因为开启了深度测试,
所以要清除深度缓存。
尝试:
1. 你可以先注释onInit函数中的代码,并且不使用GL_DEPTH_BUFFER_BIT看下
效果。
2. 再试下,启用onInit函数中的代码,但不使用GL_DEPTH_BUFFER_BIT看下效
果。
说明:
使用左右方向键,可以旋转立方体。
// 包含windows的头文件
#include
// 包含opengl需要用到的头文件(完整的vs编辑器中会自带这些文件)
#include
#include
#include
// 设置链接时的库文件
#pragma comment(lib, "OPENGL32.LIB")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glaux.lib")
// 所有的初始化都放这个函数
bool onInit()
{
glClearDepth(1.0f); // 设置深度缓存
glEnable(GL_DEPTH_TEST); // 启用深度测试
return true;
}
// 当窗口大小改变时的处理函数
void CALLBACK onSize(GLint w, GLint h)
{
// 防止h为0时,后面计算w/h时出现除法错误
if (h == 0) h = 1;
// 指定视口的位置和大小(可以自己改下参数看下效果)
glViewport(0, 0, w, h);
// 切换当前矩阵到投影矩阵
glMatrixMode(GL_PROJECTION);
// 设置投影矩阵为一个单位矩阵
glLoadIdentity();
// 设置45度角的投影矩阵,aspect一般都是设置成宽/高(是视景体的宽
高比)
gluPerspective(45.0, (GLdouble)w/(GLdouble)h, 1.0, 100.0);
// 切换当前矩形到模型视景矩阵
glMatrixMode(GL_MODELVIEW);
// 设置模型视景矩阵为一个单位矩阵
glLoadIdentity();
}
// 渲染一个立方体
void DrawBox()
{
glBegin(GL_QUADS);
// 前面
glColor3f(1,0,0);
glVertex3f(-1.0f, -1.0f, 1.0f); // 四边形的左下
glVertex3f( 1.0f, -1.0f, 1.0f); // 四边形的右下
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右上
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左上
// 后面
glColor3f(0,1,0);
glVertex3f(-1.0f, -1.0f, -1.0f); // 四边形的右下
glVertex3f(-1.0f, 1.0f, -1.0f); // 四边形的右上
glVertex3f( 1.0f, 1.0f, -1.0f); // 四边形的左上
glVertex3f( 1.0f, -1.0f, -1.0f); // 四边形的左下
// 顶面
glColor3f(0,0,1);
glVertex3f(-1.0f, 1.0f, -1.0f); // 四边形的左上
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左下
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右下
glVertex3f( 1.0f, 1.0f, -1.0f); // 四边形的右上
// 底面
glColor3f(1,1,0);
glVertex3f(-1.0f, -1.0f, -1.0f); // 四边形的右上
glVertex3f( 1.0f, -1.0f, -1.0f); // 四边形的左上
glVertex3f( 1.0f, -1.0f, 1.0f); // 四边形的左下
glVertex3f(-1.0f, -1.0f, 1.0f); // 四边形的右下
// 右面
glColor3f(0,1,1);
glVertex3f( 1.0f, -1.0f, -1.0f); // 四边形的右下
glVertex3f( 1.0f, 1.0f, -1.0f); // 四边形的右上
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的左上
glVertex3f( 1.0f, -1.0f, 1.0f); // 四边形的左下
// 左面
glColor3f(1,0,1);
glVertex3f(-1.0f, -1.0f, -1.0f); // 四边形的左下
glVertex3f(-1.0f, -1.0f, 1.0f); // 四边形的右下
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的右上
glVertex3f(-1.0f, 1.0f, -1.0f); // 四边形的左上
glEnd();
}
float ratX = 60;
float ratY = 60;
float ratZ = 60;
// 这个函数是渲染循环的回调函数
void CALLBACK onRender(void)
{
// 设置清屏颜色
glClearColor(0, 0, 0, 0);
// 用glClearColor设置的颜色来清除屏幕
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -6.0f);
// 绕x,y,z轴旋转
glRotatef(ratX, 1.0f, 0.0f, 0.0f);
glRotatef(ratY, 0.0f, 1.0f, 0.0f);
glRotatef(ratZ, 0.0f, 0.0f, 1.0f);
DrawBox();
// 渲染到后备缓冲
// 注意auxInitDisplayMode中不是AUX_AUX_SINGLE,而是AUX_DOUBLE
// 这个例子里使用了双缓冲机制,所以glFlush只渲染到后缓冲,不画到
窗口上了
// 使用双缓冲是为了解决闪屏的问题
glFlush();
// 把后缓冲中的渲染结果一次性渲染到窗口
auxSwapBuffers();
}
void CALLBACK leftKeyProc()
{
ratX += 2;
ratY += 2;
ratZ += 2;
}
void CALLBACK rightKeyProc()
{
ratX -= 2;
ratY -= 2;
ratZ -= 2;
}
void main()
{
// 调用glaux.h中的设置显示模式的接口
auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA);
// 调用glaux.h中的设置窗口位置和大小
auxInitPosition(512,300,250,200);
// 调用glaux.h中的创建窗口
auxInitWindow("sample");
// 注册left键的处理函数
auxKeyFunc(AUX_LEFT, leftKeyProc);
// 注册right键的处理函数
auxKeyFunc(AUX_RIGHT, rightKeyProc);
// 注册窗口大小改变时的处理函数
auxReshapeFunc(onSize);
// 自定义初始化
onInit();
// 注册主渲染循环(注册了这个以后)
auxMainLoop(onRender);
}