opengl旋转球程序
OPENGL中物体的旋转变换
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文件中的模型自由旋转
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判断进入哪个分支。
三维物体转动opengl程序
/** 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中创建一个球体动画-使球体在窗口内做自由落体运动.(共6页)
精品资料(完整版)O p e n G L中创建一个球体(q iútǐ)动画-使球体在窗口内做自由落体运动.........................................计算机图形学实验报告1、实验目的(mùdì)和要求利用第七章所学的知识,试在OpenGL中创建一个(yīɡè)球体动画,使球体在窗口内做自由落体运动,并在撞击地面后能够反弹回来。
并用相应的代码表示出来。
2、实验(shíyàn)内容利用(lìyòng)glutSolidSphere函数等其它函数,在OpenGL中创建一个球体动画,使球体在窗口内做自由落体运动(yùndòng),并在撞击地面后能够反弹回来3、实验步骤1)相关算法及原理描述我们所使用的glut实用工具中,正好就有一个绘制球体的现成函数:glutSolidSphere,这个函数在“原点”绘制出一个球体。
由于坐标是可以通过glTranslate*和glRotate*两个函数进行随意变换的,所以我们就可以在任意位置绘制球体了。
2)运行结果如下图,程序调试成功,并且能正常显示4、实验总结通过本次试验,进一步认识,感觉OpenGL的功能很强大,各种各样的物理模拟实验他都不在话下!!不得不说,这软件很好很强大!!由于自己不太擅长编程,所以有些功能还不能完全实现,但我会尽自己最大努力来克服自己的编程不足之处,多加练习。
5、附录(fùlù)带注释(zhùshì)的源程序#include "glut.h"#include<stdlib.h>#include<stdio.h>#include<time.h>#include<math.h>#define PI 3.1415926double move=20.0;int i=0;int down=1;int count=1;double timeSpan=0; //下降(xiàjiàng)到底所需时间double movey=0.0;double duration=0.0; //持续时间double length=0.0;clock_t start,end;void init(void){GLfloat mat_specular[]={220.220,220.0,220.0,220.0};GLfloat mat_shininess[]={100.0};GLfloat light_position[]={0.0, 0.0, 0.0, -2.0}; //r-l u-d f-bGLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };GLfloat diffuseLight[] = { 0.6f, 0.6f, 0.6f, 1.0f };GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};glClearColor(0.2,0.2,1.5,2.0); //bgcglColor3ub(100, 100, 215);glShadeModel(GL_SMOOTH);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);glLightfv(GL_LIGHT0,GL_SPECULAR,specular);glLightfv(GL_LIGHT0,GL_POSITION,light_position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glEnable(GL_DEPTH_TEST);}void reshape(int w,int h){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w<=h)glOrtho(-12,12,-12*(GLfloat)(h)/(GLfloat)(w),12*(GLfloat)(h)/(GLfloat)(w), -1.0,1.0);elseglOrtho(-12*(GLfloat)(w)/(GLfloat)(h),12*(GLfloat)(w)/(GLfloat)(h),-12,12,-1.0,1.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void initDisplay(void){down=1; //向下(xiànɡ xià)运动glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0.0,20.0,0.0);glutSolidSphere(0.4,40,50);glutSwapBuffers();}void display(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0,move,0.0);glutSolidSphere(0.4,40,50);glutSwapBuffers();}void MoveSphereUp(){end=clock();duration = (double)(end - start-16.0) /CLOCKS_PER_SEC;length=5*(timeSpan-duration)*(timeSpan-duration);move=20-length;if(move>19.932) {move=20;down=1;printf("%i",down);start=clock();}display();glLoadIdentity();}void MoveSphereDown(){if(count==1){start=clock();count=0;}end=clock();duration = (double)(end - start) /CLOCKS_PER_SEC;length=5*duration*duration;move=20-length;if(move<-20) {timeSpan=duration; //记下下降(xiàjiàng)所经历的时间 move=-20;start=clock();down=0; //向上(xiàngshàng)运动}display();glLoadIdentity();}void TimerFunc2(int value){if(i==0){ //leftGLfloat light_position[]={2.0,0.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==1){ //left-upGLfloat light_position[]={2.0,2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==2){ //upGLfloat light_position[]={0.0,2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==3){ //up-rightGLfloat light_position[]={-2.0,2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==4){ //rightGLfloat light_position[]={-2.0,0.0,0.0,0.0}; //r-l u-d f-bglLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==5){ //right-downGLfloat light_position[]={-2.0,-2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==6){ //downGLfloat light_position[]={0.0,-2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }if(i==7){ //down-leftGLfloat light_position[]={2.0,-2.0,0.0,0.0}; //r-l u-d f-b glLightfv(GL_LIGHT0,GL_POSITION,light_position); }i=(++i)%8; //控制小球(xiǎo qiú)旋转的glutTimerFunc(60,TimerFunc2,1);}void TimerFunc1(int value){if(down==1){MoveSphereDown();}if(down==0){MoveSphereUp();}glutTimerFunc(10,TimerFunc1,0);}int main(int argc,char **argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);glutInitWindowSize(400,740);glutInitWindowPosition(300,20);glutCreateWindow(argv[0]);init();glutDisplayFunc(initDisplay);glutReshapeFunc(reshape);glutTimerFunc(1400,TimerFunc1,0); //毫秒glutTimerFunc(400,TimerFunc2,1); //毫秒glutMainLoop();return 0;}内容总结(1)(完整版)OpenGL中创建一个球体动画-使球体在窗口内做自由落体运动.。
OpenGL下三维模型的显示和自由旋转
20 世纪 70 年代后期 ,计算机图形工作站的出现推动了基于矢量的 3D 计算机图形学 ( 3D Computer Grap hics) 的迅速发展 . 目前 3D 计算机图形学已经广泛地应用于各个行业和领域 , 如 :3D Max ,Poser 等三维设计软件可以生成复杂的三维模型 . 考虑到软件的通用性 , 本文选 取了图形数据工业标准 — — — DXF 格式的三维模型数据文件作为源文件 , 不仅可以对任意软件 生成的 DXF 格式的三维模型文件进行处理 ,同时还可以处理三维模型和二维模型 . 在三维软件的开发方面 ,目前主要存在 2 种 API : 一个是微软的 Direct 3D ,一个是开放标 准 Open GL . Direct 3D 大量应用于民用产品 ,如游戏领域 ,而 Open GL 作为应用最为广泛的高 性能工业图形标准 ,是开发高质量的二维或三维交互式图形应用程序的首选环境 [ 1 ] . Open GL 提供的应用程序 API 包含了许多现代图形学中的基本功能 , 如 : 图元的绘制 、 颜色指定 、 纹理 映射 、 光照处理 、 双缓存动画和特效等 ; 另外 , 其跨平台的特性也备受用户推崇 ; Open GL 简化 了图形软件的开发过程 ,缩短了产品进入市场的周期 : 因此 ,我们选用 Open GL 作为开发工具 . 在对三维模型的研究中 ,需要对其进行自由旋转 ,以方便从任意角度细致地进行观察 . 本 文提供了一种通过操纵虚拟球实现对模型自由旋转的方法 ,使用户仅通过鼠标的拖动就能从 任何角度观看模型 .
v= b +c , cosβ= c/ v , sinβ= b/ v ;
2 2
1
Rx =
0 0 0
0 β cos sinβ - sinβ cosβ 0 0
openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)
openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)在我的MFC单文档项目中enableview.h和enableview.cpp负责上面的窗口建立,myopenglview.h和myopenglView.cpp主要是功能的实现1.三维网格建立:void GLGrid(float pt1x, float pt1y, float pt1z, float pt2x, float pt2y, float pt2z, int num){const float _xLen = (pt2x - pt1x) / num;const float _yLen = (pt2y - pt1y) / num;const float _zLen = (pt2z - pt1z) / num; glLineWidth(2.f);glLineStipple(1, 0x0303);//线条样式glBegin(GL_LINES);glEnable(GL_LINE_SMOOTH);int xi = 0;int yi = 0;int zi = 0;//绘制平行于X的直线for (zi = 0; zi <= num; zi++){float z = _zLen * zi + pt1z;for (yi = 0; yi <= num; yi++){float y = _yLen * yi + pt1y;glVertex3f(pt1x, y, z);glVertex3f(pt2x, y, z);}}//绘制平行于Y的直线for (zi = 0; zi <= num; zi++){float z = _zLen * zi + pt1z;for (xi = 0; xi <= num; xi++){float x = _xLen * xi + pt1x;glVertex3f(x, pt1y, z);glVertex3f(x, pt2y, z);}}//绘制平行于Z的直线for (yi = 0; yi <= num; yi++){float y = _yLen * yi + pt1y;for (xi = 0; xi <= num; xi++){float x = _xLen * xi + pt1x;glVertex3f(x, y, pt1z);glVertex3f(x, y, pt2z);}}glEnd();}void CmyopenglView::ordination() {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH); //设置反走样glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); //设置反走样glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);glEnable(GL_POL YGON_SMOOTH);glHint(GL_POL YGON_SMOOTH_HINT, GL_NICEST);glRotatef(-45, 0.0, 1.0, 0.0);//网格glPushMatrix();glColor3f(0.9f, 0.9f, 0.9f);glTranslatef(-4, -4, -4);GLGrid(0,0,0,8,0,8,20);glPopMatrix();glPushMatrix();glTranslated(-4,4, -4);glRotatef(90, 1.0, 0.0, 0.0);glColor3f(0.9f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glPushMatrix();glTranslatef(-4, -4, -4);glRotatef(90, 0.0, 0.0, 1.0);glColor3f(0.0f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glDisable(GL_BLEND);glDisable(GL_LINE_SMOOTH);glDisable(GL_POINT_SMOOTH);glDisable(GL_POL YGON_SMOOTH);}我们在ordination()函数中增加绘制x,y,z坐标的代码void CmyopenglView::ordination() {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH); //设置反走样glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); //设置反走样glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);glEnable(GL_POL YGON_SMOOTH);glHint(GL_POL YGON_SMOOTH_HINT, GL_NICEST);glRotatef(-45, 0.0, 1.0, 0.0);//网格glPushMatrix();glColor3f(0.9f, 0.9f, 0.9f);glTranslatef(-4, -4, -4);GLGrid(0,0,0,8,0,8,20);glPopMatrix();glPushMatrix();glTranslated(-4,4, -4);glRotatef(90, 1.0, 0.0, 0.0);glColor3f(0.9f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glPushMatrix();glTranslatef(-4, -4, -4);glRotatef(90, 0.0, 0.0, 1.0);glColor3f(0.0f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();//x//glTranslatef(-2, -2, -2);glColor3f(1.0f, 0.0f, 0.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(3.5, 0.0f, 0.0f);glEnd();glPushMatrix();glTranslatef(3.5, 0.0f, 0.0f);glRotatef(90.0f, 0.0f, 1.0f, 0.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();//yglColor3f(0.0f, 1.0f, 0.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0, 3.5, 0.0f);glEnd();glPushMatrix();glTranslatef(0.0, 3.5, 0.0f);glRotatef(90.0f, -1.0f, 0.0f, 0.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();//zglColor3f(0.0f, 0.0f, 1.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0, 0.0f, 3.5);glEnd();glPushMatrix();glTranslatef(0.0, 0.0f, 3.5);glRotatef(90.0f, 0.0f, 0.0f, 1.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();glDisable(GL_BLEND);glDisable(GL_LINE_SMOOTH);glDisable(GL_POINT_SMOOTH);glDisable(GL_POL YGON_SMOOTH); }、2.基本三维图形创建点模型/线模型/面模型glColor3f(1.0f, 1.0f, 1.0f);if (model == 1){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);auxSolidCube(4);}if (model == 2){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if(type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);auxSolidSphere(3.0);}if (model == 3){glPushMatrix();glRotatef(90, -1.0, 0.0, 0.0);if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);glutSolidCone(3, 3, 100, 100);glPopMatrix();}if (model == 4){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);glutSolidTeapot(2.5);}3.鼠标相应旋转缩放BOOL enableview::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt){// TODO: 在此添加消息处理程序代码和/或调用默认值double a = zDelta / 120;if ((scale + a * 0.1) < 10)scale += a * 0.1;this->InvalidateRect(NULL, FALSE);return CView::OnMouseWheel(nFlags, zDelta, pt);}void enableview::OnMouseMove(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值if (nFlags & MK_LBUTTON == TRUE) {//MessageBox("mouse move function triggered!", "attentino", MB_OK);du += point.x - oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上,这样就左右转了h += 0.03f*(point.y - oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上,就上下转了if (h>15.0f) h = 15.0f; //视点y坐标作一些限制,不会使视点太奇怪else if (h<-5.0f) h = -5.0f;oldmx = point.x, oldmy = point.y; //把此时的鼠标坐标作为旧值,为下一次计算增量做准备/*CString debug;debug.Format(_T("h,du= %0.3f %3d\n"), h, du);OutputDebugString(debug);*///OnPaint();this->OnDraw(this->GetDC()); //重绘界面}else if (nFlags & MK_RBUTTON == TRUE){oldmx += point.x - oldmx;oldmy += point.y - oldmy;glTranslatef(oldmx, oldmy, -0.1f);this->OnDraw(this->GetDC());oldmx = point.x, oldmy = point.y;}else {oldmx = point.x, oldmy = point.y;//OutputDebugString(_T("mouse up\n"));}//CView::OnMouseMove(nFlags, point);}4.键盘相应旋转缩放BOOL CmyopenglView::PreTranslateMessage(MSG* pMsg){if (pMsg->message == WM_KEYDOWN) // If a keydown message{if (pMsg->wParam == _T('W')){this->rotate_x += 6.0;if (this->rotate_x > 360)this->rotate_x = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('X')){this->rotate_x += 6.0;if (this->rotate_x < -360)this->rotate_x = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('A')){this->rotate_y -= 6.0;if (this->rotate_y < -360)this->rotate_y = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('D')){this->rotate_y += 6.0;if (this->rotate_y > 360)this->rotate_y = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('Z')){this->rotate_z -= 6.0;if (this->rotate_z < -360)this->rotate_z = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('E')){this->rotate_z += 6.0;if (this->rotate_z > 360)this->rotate_z = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('Q')){if ((scale + 2) < 10)scale += 2;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('R')){scale -= 2;this->InvalidateRect(NULL, FALSE);}}return CView::PreTranslateMessage(pMsg);}5.灯光设置:单方位灯光/多方位光/多种类型光效果// 设置材质颜色GLfloat mat_ambient[] = { 0.6f, 0.6f, 0.6f, 1.0f }; // 蓝色的材质环境光GLfloat mat_diffuse[] = { 0.6f, 0.6f, 0.9f, 1.0f }; // 蓝色的材质漫反射光GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // 全白色的材质镜面反射光GLfloat mat_emission[] = { 0.5f, 0.5f, 0.5f, 1.0f }; // 淡白色的材质辐射光GLfloat no_mat[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 无光(黑色光),用于关闭某种属性光时应用GLfloat no_shininess[] = { 0.0f }; // 无镜面反射GLfloat low_shininess[] = { 5.0f }; // 低镜面反射指数GLfloat high_shininess[] = { 70.0f }; // 高镜面反射指数void CmyopenglView::InitalLigt(){GLfloat light_position1[4] = { -52, -16, -50, 0 };GLfloat light_position2[4] = { -26, -48, -50, 0 };GLfloat light_position3[4] = { 16, -52, -50, 0 };GLfloat direction1[3] = { 52, 16, 50 };GLfloat direction2[3] = { 26, 48, 50 };GLfloat direction3[3] = { -16, 52, 50 };GLfloat light_position4[4] = { 52, 16, 50, 0 };GLfloat light_position5[4] = { 26, 48, 50, 0 };GLfloat light_position6[4] = { -16, 52, 50, 0 };GLfloat direction4[3] = { -52, -16, -50 };GLfloat direction5[3] = { -26, -48, -50 };GLfloat direction6[3] = { 16, -52, -50 };GLfloat color1[4], color2[4], color3[4], color4[4], color5[4], color6[4];glClearColor(1, 1, 1, 0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);if (color_type == 0) { //彩色灯光color1[0] = 1; color1[1] = 0; color1[2] = 0; color1[3] = 1;color2[0] = 0.5; color2[1] = 1; color2[2] = 0; color2[3] = 1;color3[0] = 0; color3[1] = 0; color3[2] = 1; color3[3] = 1;color4[0] = 1; color4[1] = 0; color4[2] = 0; color4[3] = 1;color5[0] = 0.5; color5[1] = 1; color5[2] = 0; color5[3] = 1;color6[0] = 0; color6[1] = 0; color6[2] = 1; color6[3] = 1;GLfloat ambient[4] = { 0.3f, 0.3f, 0.3f, 1.0f };GLfloat material_color[4] = { 1, 1, 1, 0.5f };GLfloat material_specular[4] = { 0.5f, 0.5f, 0.5f, 0.5f };GLfloat material_ambient[4] = { 0.0, 0.0, 0.0, 0.0 };glLightfv(GL_LIGHT3, GL_POSITION, light_position4);glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, direction4);glLightfv(GL_LIGHT3, GL_DIFFUSE, color4);glLightfv(GL_LIGHT3, GL_SPECULAR, color4);glLightfv(GL_LIGHT4, GL_POSITION, light_position5);glLightfv(GL_LIGHT4, GL_SPOT_DIRECTION, direction5);glLightfv(GL_LIGHT4, GL_DIFFUSE, color5);glLightfv(GL_LIGHT4, GL_SPECULAR, color5);glLightfv(GL_LIGHT5, GL_POSITION, light_position6);glLightfv(GL_LIGHT5, GL_SPOT_DIRECTION, direction6);glLightfv(GL_LIGHT5, GL_DIFFUSE, color6);glLightfv(GL_LIGHT5, GL_SPECULAR, color6);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_color);glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128);glDisable(GL_LIGHT0);glDisable(GL_LIGHTING);glEnable(GL_LIGHTING);glEnable(GL_LIGHT3);glEnable(GL_LIGHT4);glEnable(GL_LIGHT5);glDisable(GL_COLOR_MATERIAL);return;}if (color_type == 1){//白色灯光glDisable(GL_LIGHT3);glDisable(GL_LIGHT4);glDisable(GL_LIGHT5);glDisable(GL_LIGHTING);GLfloat m_LightPostion[4] = { 0.0f, 10.0f, 10.0f, 1.0f };GLfloat ambientLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };GLfloat diffuseLight[] = { 0.5, 0.5f, 0.5f, 1.0f };GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glEnable(GL_LIGHT0);glEnable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);}else {glDisable(GL_LIGHT3);glDisable(GL_LIGHT4);glDisable(GL_LIGHT5);glDisable(GL_LIGHTING);glDisable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);//glDisable(GL_LIGHTING);GLfloat no_ambientLight[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 用于关掉默认的全局环境光// 设置光源的颜色GLfloat ambientLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色环境光GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色漫射光GLfloat specularLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色镜面反射光GLfloat m_LightPostion[] = { 0.0f, 0.0f, 1.0f, 0.0f }; // 光源起始位置// 1.仅漫射光if (color_type == 12) {glEnable(GL_LIGHTING);//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); // 关闭材质的环境反射光颜色glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); // 设置mat_diffuse的材质漫反射光glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); //关闭材质的镜面反射光颜色glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); // 设置材质的镜面反射指数为0glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); // 关闭材质的辐射光glEnable(GL_LIGHT0);}// 2.仅镜面光if (color_type == 13) {glEnable(GL_LIGHTING);//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, no_mat);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);glEnable(GL_LIGHT0);}// 3.漫射光与低镜面光if (color_type == 16) {glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);glEnable(GL_LIGHT0);}// 4.辐射光与低镜面光if (color_type == 18) {glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, no_mat);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);glEnable(GL_LIGHT0);}}}6.纹理载入映射BOOL CmyopenglView::LoadImageResources() {FILE *File = NULL;AUX_RGBImageRec* textrue_Resource[6];if (model == 5 && type == 51)resource_path[0] = "shuijing.bmp";if(model == 5 && type == 52 )resource_path[0] = "earth.bmp";if (model == 5 && type == 53)resource_path[0] = "painting1.bmp";if (model == 5 && type == 54)resource_path[0] = "5.bmp";/*resource_path[1] = "image/2.bmp";resource_path[2] = "image/3.bmp";resource_path[3] = "image/4.bmp";resource_path[4] = "image/5.bmp";resource_path[5] = "image/6.bmp";*///装载图像文件资源for (int i = 0; i < 6; i++)//如果只需要一张贴图其实resource_path数组只需要一个元素就可以了{File = fopen(resource_path[0], "r");if (!File){//MessageBox(NULL, "加载图像资源文件失败!", "Fail", MB_OK);return FALSE;}fclose(File);CString str = CString(resource_path[0]);USES_CONVERSION;LPCWSTR wszClassName = A2CW(W2A(str));textrue_Resource[i] = auxDIBImageLoad(wszClassName);File = NULL;}//生成纹理glGenTextures(6, texture);for (int i = 0; i < 6; i++){glBindTexture(GL_TEXTURE_2D, texture[i]);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//Use the mipmap textureglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, \textrue_Resource[i]->sizeX, textrue_Resource[i]->sizeY, \GL_RGB, GL_UNSIGNED_BYTE, textrue_Resource[i]->data);//删除堆上的临时图像delete textrue_Resource[i]->data;delete textrue_Resource[i];}return TRUE;}void CmyopenglView::Draw_textrue() {GLUquadricObj* qobj;glClearColor(0.0, 0.0, 0.0, 0.0);glShadeModel(GL_FLAT);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);InitalLigt(); ///初始化光照信息glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);glPushMatrix();glTranslatef(0.0f, 0.0f, scale); //滚轮缩放gluLookAt(r*cos(c*du), h, r*sin(c*du), 0, 0, 0, 0, 1, 0); //从视点看远点,y轴方向(0,1,0)是上方向,鼠标拖动glRotatef(this->rotate_x, 1.0, 0.0, 0.0);glRotatef(this->rotate_y, 0.0, 1.0, 0.0);glRotatef(this->rotate_z, 0.0, 0.0, 1.0);if (iao)ordination();glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);qobj = gluNewQuadric();//画球体glBindTexture(GL_TEXTURE_2D, texture[0]);glEnable(GL_TEXTURE_2D);gluQuadricTexture(qobj, GL_TRUE);//纹理函数if (type == 51){glBegin(GL_QUADS);// Front FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, 3.0f, 3.0f);// Back FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, -3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, -3.0f, -3.0f);// Top FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, 3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, 3.0f, -3.0f);// Bottom FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, -3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, -3.0f, 3.0f);// Right faceglTexCoord2f(0.0f, 0.0f); glVertex3f(3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, -3.0f, 3.0f);// Left FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(-3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glEnd();}if( type == 52 )gluSphere(qobj, 4, 60, 60);//二次曲面qobjif( type == 53 )gluCylinder(qobj, 3.5, 3.5, 6, 26, 23);if( type == 54 )gluCylinder(qobj, 3.5, 0.0, 6, 26, 23);glPopMatrix();glDisable(GL_TEXTURE_2D);}6.读取obj模型我只是简单的读取vt,vn,f等基本参数void CmyopenglView::ReadObj(char* Filename) {VN.clear();V.clear();VT.clear();F.clear();FQ.clear();ifstream in(Filename);string aline; //逐行读入string erase;while (getline(in, aline)){if (aline[0] == 'v'){if (aline[1] == 'n') //vn{istringstream sin(aline);V ertex v;sin >> erase >> v.x >> v.y >> v.z;VN.push_back(v);}else if (aline[1] == 't')//vt{istringstream sin(aline);Texture v;sin >> erase >> v.s >> v.t;VT.push_back(v);}else //v{istringstream sin(aline);V ertex v;sin >> erase >> v.x >> v.y >> v.z;V.push_back(v);}}else if (aline[0] == 'f'){istringstream sin(aline);sin >> erase;vector<string> strvector;string temp;while (sin >> temp) {strvector.push_back(temp);}if (strvector.size() == 3) {//三角面片Face fff;for (int count = 0; count < 3; count++) {string kkk = strvector[count];int i = 0;int num = 0;//顶点索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.v[count] = num;i++;num = 0;//vtnum = 0;for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vt[0] = num;i++;num = 0;//法向量索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vn[count] = num;}F.push_back(fff);}else if (strvector.size() == 4){FaceQ fff;for (int count = 0; count < strvector.size(); count++) { string kkk = strvector[count];int i = 0;int num = 0;//顶点索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.v[count] = num;i++;num = 0;//vtnum = 0;for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vt[0] = num;i++;num = 0;//法向量索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vn[count] = num;}FQ.push_back(fff);}}}}绘制obj模型:void CmyopenglView::OnReadobj(){model = 6;wchar_t filters[] =L"3D模型文件(*.obj)\|*.obj|所有文件(*.*)|*.*||";CFileDialog fileDlg(TRUE, NULL, NULL,OFN_HIDEREADONL Y, filters);if (fileDlg.DoModal() == IDOK){CString strBuf = fileDlg.GetPathName();USES_CONVERSION;char *Filename = T2A(strBuf.GetBuffer(0));ReadObj(Filename);}stringstream ss;ss <<"OK!";string str;ss >> str;CString s;s = str.c_str();MessageBox(s);float min_x, min_y, min_z, max_x, max_y, max_z;min_x = min_y = min_z = 10000000;max_x = max_y = max_z = -1000000;for (int i = 0; i < V.size(); i++){min_x = min(min_x, V[i].x);min_y = min(min_y, V[i].y);min_z = min(min_z, V[i].z);max_x = max(max_x, V[i].x);max_y = max(max_y, V[i].y);max_z = max(max_z, V[i].z);}worldx = (min_x + max_x) / 2;worldy = (min_y + max_y) / 2;worldz = (min_z + max_z) / 2;type = 1;Invalidate();CDC* ppDC = GetWindowDC();OnDrawGL(ppDC);// TODO: 在此添加命令处理程序代码}void CmyopenglView::Draw_obj(){if (type == 1) {if (!VN.empty()) {for (int i = 0; i < F.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}else {for (int i = 0; i < F.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}}else if (type == 3) {glBegin(GL_POINTS);for (int i = 0; i < V.size(); i++)glV ertex3f(V[i].x, V[i].y, V[i].z);glEnd();}else{if (!VN.empty()) {for (int i = 0; i < F.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_TRIANGLES);for (int j = 0; j < 3; j++) {glNormal3f(VN[F[i].vn[j] - 1].x, VN[F[i].vn[j] - 1].y, VN[F[i].vn[j] - 1].z);glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_QUADS);for (int j = 0; j < 4; j++) {glNormal3f(VN[FQ[i].vn[j] - 1].x, VN[FQ[i].vn[j] - 1].y, VN[FQ[i].vn[j] - 1].z);glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}else{for (int i = 0; i < F.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_TRIANGLES);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_QUADS);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}}}。
c#winform中的OPENGL旋转、选择
MemoryStream stream = new MemoryStream(); bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); Array.Copy(stream.ToArray(), 54, pixBuffer, 0, pixBuffer.Length); stream.Dispose(); brush.Dispose(); g_bmp.Dispose(); bitmap.Dispose(); return m_size; } /// </summary> /// <param name="x">横坐标</param> /// <param name="y">纵坐标</param> /// <param name="m_text">显示文本</param> public void GLPrintCN(double x, double y, double z, string text,Color fontColor) { Font font = new Font("宋体", 9F); byte[] m_pixBuffer = null; Size m_size = new Size(); //字体大小 m_size = this.BuildFontCN(text, out m_pixBuffer, font, fontColor); GL.glBindTexture(GL.GL_TEXTURE_2D, 0); // 取消材质绑定 GL.glRasterPos3d(x, y, z); GL.glEnable(GL.GL_BLEND); // 让绘制的文字透明 GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); GL.glDrawPixels(m_size.Width, m_size.Height, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, m_pixBuffer); GL.glDisable(GL.GL_BLEND); } 7、c#中 Opengl 的选择物体问题 public uint HitTest(int x, int y) { int BUFFER_LENGTH = 1024; uint[] selBuff = new uint[BUFFER_LENGTH]; int hits; int[] viewport = new int[4]; GL.glGetIntegerv(GL.GL_VIEWPORT, viewport); GL.glSelectBuffer(BUFFER_LENGTH, selBuff); GL.glMatrixMode(GL.GL_PROJECTION); GL.glPushMatrix();itNames(); GL.glPushName(0); GL.glLoadIdentity(); GL.gluPickMatrix(x, y, 8, 8, viewport); GL.glOrtho(-m_showx / aspect, m_showx / aspect, -m_showx, m_showx, m_showx * 100, -m_showx * 100);//设置显示范围 GL.glMatrixMode(GL.GL_MODELVIEW); glDraw(); //窗口 hits = GL.glRenderMode(GL.GL_RENDER); GL.glMatrixMode(GL.GL_PROJECTION);
delphi实例9--用的opengl实现旋转星球
实例九用OpenGL实现旋转星球【程序说明】在游戏制作领域,两个不可逃避的主题就是OpenGL和DirectX。
不管喜欢不喜欢,这两个是游戏设计的利器。
一个大型游戏如果缺少这两种技术是不可想象的。
在本书的最后两个游戏实例中,就介绍关于OpenGL技术的一些常见应用。
本例实现的是在窗口中显示一个旋转的星球,这个星球大小是飘忽不定的。
程序运行结果如图9-1所示。
图9-1 用OpenGL实现旋转星球【编程思路】在Delphi中,OpenGL可以作为自身动态运行时间库(RTL)的一部分,以pas单元的形式放在“……\Borland\Delphi5\Source\Rtl\Win”目录下,可以象使用其他单元文件一样方便地使用。
OpenGL的绘图环境与GDI(Graphic Devic Interface,图形设备接口)的绘图环境不同。
因此各自的使用方法也不一样。
下面详细介绍Opengl的绘图步骤:1.获取显示设备的句柄,这个句柄可以用GetDC开获取。
2.设置象素格式(pixelFormat)。
该步骤先用ChoosePixelFormat选取预先根据显示设备设置好的象素格式,然后用SetPixelFormat来设置象素格式。
3.建立新的OpenGL Rendering Context(HGLRC),这个参数相当于GDI中绘图设备的HDC,两者的调用方法也很相似。
如本例中的hrc:=wglCreateContext(Canvas.Handle),在创建了这样一个HRC之后,在设备上绘图时只要将这个HRC通过wglMakeCurrent(Canvas.Handle, hrc)设置为当前的绘图环境即可。
4.设置视口和透视投影坐标。
Opengl是一个三维绘图系统,所有绘制的图形都是建立在三维空间内的,因此要设置透视投影坐标,以便能观察绘制的图形效果。
经过了上述四个步骤之后,就可以在指定的设备上画图了。
本例中的画图操作在是由夹在glbegin()…glEnd中的函数体中的操作完成的。
openGL图形的旋转与平移
void reshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0, 0.0, 100.0);
opengl图形的旋转与平移旋转图形平移图形的平移图形的旋转和平移旋转与平移图形的旋转平移和图的旋转
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#define PI 3.1415926535
GLsizei w=650, h=550;
}
void shrink()
{
fraction-=2.0;
if (fraction<-1பைடு நூலகம்.0)
fraction=-10.0;
glutPostRedisplay();
}
void rotate()
{
angle+=20.0;
if (angle>=360.0)
angle=0.0;
glutPostRedisplay();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void specialKeyFunc( int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_LEFT:
moveleft();
break;
OpenGL 球面相机旋转算法
旋转作为三维开发的基本功能,在任何3D程序中都需要。
用户通过旋转来实现对模型各个面的浏览,形成直观印象。
球面相机旋转这种旋转方式用户体验方式要优于x轴y轴混合旋转方式,模型旋转的方向和鼠标移动方向保持一致。
下面给出一种“球面相机”实现旋转的方法。
原理:移动鼠标时,通过gluLookAt来改变视点的位置(采用增量的方式),而模型保持不动。
即:只进行视点变换,不进行模型变换。
下图是用户按下左键,在屏幕上移动的一段距离(从A移动到B)。
由于屏幕坐标y轴向下,为了与投影平面坐标系(传统笛卡尔坐标)保持一致。
AM = y1-y2; /*将消息代码描述*/BM = x2-x1;建立屏幕和投影变换近裁截面之间的对应关系(如下图)。
代码实现:1 void setSphereCameraPos()2 {3 // 左键未按下,直接返回4 if (!is_left_button_down)5 return;67 // 从聚焦点指向视点的向量 OA向量8 vector3dd a(eye-target);910 // 计算球面相机半径11 radius = a.getLength();1213 // 将其单位化14 a.normailize();1516 // 当前相机向上方向与a做叉乘,计算投影面水平向右方向向量u17 vector3dd u = upvector.crossProduct(a);18 // 将其单位化19 u.normailize();2021 // 计算相机向上方向在投影面上的投影向量即垂直向上的方向向量v22 vector3dd v = a.crossProduct(u);23 // 将其单位化24 v.normailize();2526 // 计算屏幕AB在投影面上对应的向量 AB向量27 vector3dd m = u*delta_point.x + v*delta_point.y;2829 // 计算m向量的长度30 double len = m.getLength();31 // 降低灵敏度32 len /= 20.0;3334 if (len>0.0)35 {36 // 角度AOB 弧度表示弧长/半径37 double x = len/radius;38 // 将AB向量单位化39 m.normailize();4041 // 按相反方向转动视点到C 从而使得按与鼠标移动一致的方向转动模型42 x = -1*x;43 // 计算新的相机位置 C44 eye = target+(a*cos(x) + m*sin(x))*radius;4546 // 计算新的相机向上方向47 upvector = v;48 }49 }消息代码1 LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window2 UINT uMsg,// Message For This Window3 WPARAM wParam,// Additional Message Information4 LPARAM lParam)// Additional Message Information5 {6 switch(uMsg) // Check For Windows Messages7 {8 case WM_LBUTTONDOWN:9 {10 is_left_button_down = true;11 pre_point.x = LOWORD(lParam);12 pre_point.y = HIWORD(lParam);1314 return 0;15 }1617 case WM_MOUSEMOVE:18 {19 if (is_left_button_down)20 {21 cur_pt.x = LOWORD(lParam);22 cur_pt.y = HIWORD(lParam);// delta_point为增量点23 delta_point.x= cur_pt.x-pre_point.x);// 保持屏幕坐标系和投影平面坐标系一致24 delta_point.y =-1*(cur_pt.y-pre_point.y);// 将当前点赋值给前一个点25 pre_point = cur_pt;26// 计算相机新的位置27 setSphereCameraPos();28 }30 return 0;31 }3233 case WM_LBUTTONUP:34 {35 is_left_button_down = false;36 return 0;37 }38 }3940 // Pass All Unhandled Messages To DefWindowProc41 return DefWindowProc(hWnd,uMsg,wParam,lParam);42 }43vector3dd类vector3dd1 class vector3dd2 {3 private:4 double x,y,z;56 public:7 vector3dd(){};8 vector3dd(double a, double b, double c){x=a;y=b;z=c;}9 vector3dd(const vector3dd& v){*this=v;}11 public:12 void operator=(const vector3dd& v){x=v.x;y=v.y;z=v.z;}13 vector3dd operator*(double a)14 {15 return vector3dd(a*x,a*y,a*z);16 }17 vector3dd operator+(const vector3dd& v)18 {19 return vector3dd(x+v.x,y+v.y,z+v.z);20 }21 vector3dd operator-(const vector3dd& v)22 {23 return vector3dd(x-v.x,y-v.y,z-v.z);24 }2526 public:27 double getX(){return x;}28 double getY(){return y;}29 double getZ(){return z;}3031 void setValue(double a, double b, double c)32 {33 x = a;34 y = b;35 z = c;36 }3738 double getLength()39 {40 return sqrt(x*x+y*y+z*z);41 }4243 void normailize()44 {45 double length = getLength();46 x/=length;47 y/=length;48 z/=length;49 }5051 void invert()52 {53 x*=-1;54 y*=-1;55 z*=-1;56 }5758 vector3dd crossProduct(const vector3dd& v)59 {60 return vector3dd(y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x);61 }6263 double dotProduct(const vector3dd& v)64 {65 return (x*v.x+y*v.y+z*v.z);66 }6768 void traceMsg()69 {70 fprintf(stdout, "%.7f, %.7f, %.7f\n", x, y, z);71 }72 };效果图:。
OpenGL轨迹球实现的鼠标旋转
OpenGL:轨迹球实现的鼠标旋转轨迹球控制By Terence J. Grant 如果只用鼠标来控制你的模型是不是很酷?轨迹球可以帮你做到这一点,我将告诉你我的实现,你可以把它应用在你的工程里。
我的实现是基于Bretton Wade’s,它是基于Ken Shoemake’s 实现的,最初的版本,你可以从游戏编程指南这本图上找到。
但我还是修正了一些错误,并优化了它。
轨迹球实现的内容就是把二维的鼠标点映射到三维的轨迹球,并基于它完成旋转变化。
为了完成这个设想,首先我们把鼠标坐标映射到[-1,1]之间,它很简单:MousePt.X = ((MousePt.X / ((Width -1) / 2)) -1);MousePt.Y = -((MousePt.Y / ((Height -1) / 2))-1);这只是为了数学上的简化,下面我们计算这个长度,如果它大于轨迹球的边界,我们将简单的把z轴设为0,否则我们把z轴设置为这个二维点映射到球面上对应的z值。
一旦我们有了两个点,就可以计算它的法向量了和旋转角了。
下面我们从构造函数开始,完整的讲解这个类:ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)当点击鼠标时,记录点击的位置void ArcBall_t::click(const Point2fT* NewPt)当拖动鼠标时,记录当前鼠标的位置,并计算出旋转的量。
void ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)如果窗口大小改变,设置鼠标移动的范围void ArcBall_t::setBounds(GLfloat NewWidth, GLfloat NewHeight)下面是完成计算所要用到的数据结果,都是一些矩阵和向量Matrix4fT Transform ={ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };Matrix3fT LastRot = { 1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f };Matrix3fT ThisRot = { 1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f };ArcBallT ArcBall(640.0f, 480.0f);Point2fT MousePt;bool isClicked = false; // 是否点击鼠标bool isRClicked = false; // 是否右击鼠标bool isDragging = false; // 是否拖动在上面定义的变量中,transform是我们获得的最终的变换矩阵,lastRot是上一次鼠标拖动得到的旋转矩阵,thisRot为这次鼠标拖动得到的旋转矩阵。
OpenGL旋转变换
OpenGL旋转变换效果图:代码:1#define GLUT_DISABLE_ATEXIT_HACK2 #include "gl/glut.h"34 GLint Angle;5void OnDisplay(void);6void OnReShape(int,int);7void OnTimer(int);8void SetupLights();910void main(int argc,char* argv[])11 {12 glutInit(&argc,argv);13 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);14 glutInitWindowSize(600,480);15 glutCreateWindow("OpenGL旋转变换");1617 glutReshapeFunc(OnReShape);18 glutDisplayFunc(OnDisplay);19 glutTimerFunc(100,OnTimer,1);202122 SetupLights();2324 glutMainLoop();25 }2627void OnDisplay(void)28 {29 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);3031 glEnable(GL_DEPTH_TEST);3233 glMatrixMode(GL_MODELVIEW);34 glLoadIdentity();3536 glRotatef(30.0f,1.0f,0.0f,0.0f);37 glRotatef(15.0f,0.0f,1.0f,0.0f);383940 glColor3f(1.0f,0.0f,0.0f);41 glBegin(GL_LINES);42 glVertex3f(-50.0f,-50.0f,-50.0f);43 glVertex3f(50.0f,50.0f,50.0f);44 glEnd();454647 glPushMatrix();48 glRotatef(Angle,1.0f,1.0f,1.0f);49 glColor3f(1.0f,1.0f,0.0f);50 glutSolidCube(50.0f);51 glPopMatrix();5253 glutSwapBuffers();5455 }5657void OnReShape(int w,int h)58 {59 GLfloat aspect =(GLfloat)w/(GLfloat)h;60 GLfloat nRange=100.0f;6162 glViewport(0,0,w,h);6364 glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影模式65 glLoadIdentity();6667//设置三维投影区6869if (w<=h)70 {71 glOrtho(-nRange,nRange,-nRange*aspect,nRange*aspect,-nRange,nRange);72 }73else74 {75 glOrtho(-nRange,nRange,-nRange/aspect,nRange/aspect,-nRange,nRange);76 }7778 }7980void OnTimer(int value)81 {82 Angle +=10;83 glutPostRedisplay();84 glutTimerFunc(100,OnTimer,1);85 }8687void SetupLights()88 {89 GLfloat ambientLight[]={0.2f,0.2f,0.2f,1.0f};//环境光90 GLfloat diffuseLight[]={0.9f,0.9f,0.9f,1.0f};//漫反射91 GLfloat specularLight[]={1.0f,1.0f,1.0f,1.0f};//镜⾯光92 GLfloat lightPos[]={50.0f,80.0f,60.0f,1.0f};//光源位置9394 glEnable(GL_LIGHTING); //启⽤光照95 glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);//设置环境光源96 glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);//设置漫反射光源97 glLightfv(GL_LIGHT0,GL_SPECULAR,specularLight);//设置镜⾯光源98 glLightfv(GL_LIGHT0,GL_POSITION,lightPos);//设置灯光位置99 glEnable(GL_LIGHT0); //打开第⼀个灯光100101 glEnable(GL_COLOR_MATERIAL); //启⽤材质的颜⾊跟踪102 glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); //指定材料着⾊的⾯103 glMaterialfv(GL_FRONT,GL_SPECULAR,specularLight); //指定材料对镜⾯光的反应104 glMateriali(GL_FRONT,GL_SHININESS,100); //指定反射系数105106107 }。
C语言使用OpenGL制作旋转地球
C语⾔使⽤OpenGL制作旋转地球前置步骤(安装依赖库):sudo apt-get updatesudo apt-get install build-essentialsudo apt-get install libgl1-mesa-devsudo apt-get install libglu1-mesa-dev$sudo apt-get install freeglut3-devsudo apt-get install libfreeimage3 sudo apt-get install libfreeimage-dev1.测试OpenGL环境#include<GL/glut.h>void init(){glClearColor(0.0, 0.0, 0.0, 0.0);glMatrixMode(GL_PROJECTION);glOrtho(-5, 5, -5, 5, 5, 15);gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);return ;}void display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0, 0, 0);glutWireTeapot(3);glFlush();return;}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(0, 0);glutInitWindowSize(300, 300);glutCreateWindow("OpenGL #D View");init();glutDisplayFunc(display);glutMainLoop();return0;}编译:gcc test.c -o test -lGL -lGLU -lglut运⾏:如果能出现这个图⽚,证明环境配置成功。
glm 旋转式编码
glm 旋转式编码
在OpenGL Mathematics (GLM) 库中,glm::rotate 函数用于围绕一个轴向对顶点、向量或矩阵进行旋转操作。
通常用于三维空间中的旋转计算。
下面是一个基本的使用示例:
cpp
include <glm/glm.hpp>
include <glm/gtc/matrix_transform.hpp> // 包含glm::rotate
// 假设我们有一个4x4的模型矩阵modelMatrix和一个要旋转的角度angle(单位通常是弧度),以及一个旋转轴axis
glm::mat4 modelMatrix(1.0f); // 初始化为单位矩阵
glm::vec3 axis(0.0f, 1.0f, 0.0f); // 例如绕Y轴旋转
float angle = glm::radians(45.0f); // 将角度转换为弧度
// 使用GLM进行旋转
modelMatrix = glm::rotate(modelMatrix, angle, axis);
// 现在,modelMatrix包含了旋转后的变换
这里的glm::rotate函数采用的是右手坐标系,并遵循逆时针旋转为正角度的传统约定。
它接受三个参数:要修改的矩阵、旋转的角度(以弧度为单位)以及表示旋转轴的向量(该向量需要归一化)。
通过这个函数,你可以轻松地实现任何三维对象的旋转操作。
OPENGL实现3ds文件中的模型自由旋转
/$/
更新旋转矩阵
有 了 以 上 变 量 的 更 新 #接 下 来 就 是 根 据 这 些 更 新 #实 现 旋
转矩阵的更新 $
=)4< 1S;C<;504;H $$ZC@4?;5 !‘aG@ Ca^T=;C6 " 94E !?>1)?:3;6;< " 9?>1)?:3;6;<]E+3*; & 4E !4*S134(Q;< " I I 如果点击右键 # 重置旋转 9 I I 把 K+*6S)6 重置为单位矩阵 [+654\&EA;6a<;C646b!cK+*6S)6 "& I I 把 @B4*S)6 重置为单位矩阵 [+654\&EA;6a<;C646b!c@B4*S)6 "&
%% 和 %! 的叉乘得到 ! 即 ’
作者简介 ! 张正波 &%ERE= $! 男 ! 硕士研究生 ! 研究方向为信号与信息处理 ( 计算机图形图像 %
!"
!""#$%&
万方数据
计算机工程与应用
!"#$%&%’&!
而旋转角度就是 &% 和 &! 之间的夹角 ’ # 因此 $
!! " !& "
0;(6)5&E@ TC0;( & I I 保存拖动时的向量 ! 终点 " JKE3)+6 U<V7*6L4<6B & I I *;68)7C<* 函数用其来调整窗口 JKE3)+6 U<V7*6M;4NB6 &P
opengl实现__太阳、地球和月亮的运动模型及小球的自由落体运动
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void initDisplay(void)
{ printf(" initDisplay()");
down=1;
//向下运动
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
int count=1;
double timeSpan=0;
//下降到底所需时间
double movey=0.0;
double duration=0.0;
//持续时间
double length=0.0;
专业资料学习参考
WORD 整理版
clock_t start,end; void init(void) { printf(" init");
专业资料学习参考
glutTimerFunc(50,timer,0); glutPostRedisplay(); }
WORD 整理版
int main(int argc,char **argv) { glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("earth,moon,sun"); glutInitWindowSize(400,400); glutDisplayFunc(display); glutTimerFunc(50,timer,0); glutMainLoop(); return 0; }
z); 缩放矩阵函数 void glScale{df}(TYPE x,TYPE y,TYPE z); 如不需要效果积累可调用重置矩阵函数 void glLoadIdentity(void); 该函数将单位矩阵 置为当前变换矩阵。
OpenGL的glRotatef旋转变换函数详解
OpenGL的glRotatef旋转变换函数详解OpenGL的glRotatef旋转变换函数详解先看⼀下函数定义:void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)angle:为旋转的⾓度,单位为度。
x,y,z:为对应xyz轴的布尔值变量。
重点是x,y,z表达的是什么意思呢?应该如何取值?如果说x,y,z表达的是⼀个坐标(x,y,z),那么这个函数就说明了当前⼏何图形围着这个坐标点旋转。
但往哪个⽅向旋转呢?所以很明显,x,y,z表达的意思并不是坐标点,⽽是要围绕哪个坐标轴旋转。
即其实这⾥的x,y,z值相当于⼀个布尔值,0.0表⽰假,⽽⾮零参数则表⽰真。
所以如果你想让当前的⼏何图形围绕着z轴旋转,那么x和y都设为0,⽽z设为⾮零值即可。
如果这⾥的x,y,z的值都设置为0.0,那么将围绕着x轴旋转。
还有⼀点需要注意,如果设置的旋转值(x,y,z的值)为正数,那么旋转的⽅向是逆时针的,如果旋转值是负数,那么旋转的⽅向是顺时针的。
假设:glRotatef(45,1,0,0)物体如何旋转?想象:从坐标(0,0,0)即原点,引出⼀条线到(1,0,0),⽤右⼿握住这条线.这时,你会问,如何握?右⼿⼤拇指指向(0,0,0)⾄(1,0,0)的⽅向才握。
另外四个⼿指的弯曲指向即是物体旋转⽅向。
为什么是右⼿握住,⽽不是左⼿呢?因为OpenGL是右⼿原则。
最后附上代码供参考:1 #include <stdio.h>2 #include <gl/glut.h>34/*5功能描述:使⽤OpenGL简单画⼀个旋转的三⾓形6旋转变换函数glRotatef7*/89//输出模式,0-单缓存模式;⾮0双缓存模式10#define OUTPUT_MODE 11112//⾓度13int angle = 0;1415int xyz[3] = {0, 0, 0};1617void display(void)18 {19//printf("xyz={%d, %d, %d\n}", xyz[0], xyz[1], xyz[2]);2021 glClear(GL_COLOR_BUFFER_BIT);222324 glLoadIdentity();25 glRotatef(angle, xyz[0], xyz[1], xyz[2]);2627 glBegin(GL_TRIANGLES);28 {29 glVertex3f(0.0f, 0.0f, 0.0f);30 glVertex3f(0.5f, 0.0f, 0.0f);31 glVertex3f(0.0f, 0.5f, 0.0f);32 }33 glEnd();3435 angle += 1;36 angle %= 360;3738if (OUTPUT_MODE == 0) {39 glFlush();//单缓存GLUT_SINGLE时使⽤40 } else {41 glutSwapBuffers();//因为使⽤的是双缓存GLUT_DOUBLE,所以这⾥必须要交换缓存才会显⽰42 }43 }4445//按键46void keyboard(unsigned char key, int x, int y)47 {48switch (key)49 {50case'x':51case'X':52 xyz[0] = 1;53 xyz[1] = xyz[2] = 0;54break;55case'y':56case'Y':57 xyz[1] = 1;58 xyz[0] = xyz[2] = 0;59break;60case'z':61case'Z':62 xyz[2] = 1;63 xyz[0] = xyz[1] = 0;64break;65case'a':66case'A':67 xyz[0] = xyz[1] = xyz[2] = 0;68break;69case'b':70case'B':71 xyz[0] = xyz[1] = xyz[2] = 1;72break;73default:74break;75 }76 printf("当前绕%c轴旋转\n", key);77 glutPostRedisplay();78 }7980void reshape(int w, int h)81 {82int offset = 50;83int dis = (w > h ? h : w) - offset * 2;8485//配置显⽰物体屏幕的⼤⼩86 glViewport(offset, offset, (GLsizei)dis, (GLsizei)dis);87 printf("reshape: w=%d, h=%d, dis=%d\n", w, h, dis);8889 glMatrixMode(GL_PROJECTION);90 glLoadIdentity();9192 glOrtho(-1.5, 1.5, -1.5, 1.5, 0, 10);93//gluOrtho2D(-1.5, 1.5, -1.5, 1.5);9495 glMatrixMode(GL_MODELVIEW);96 glLoadIdentity();97 }9899int main(int argc, char *argv[])100 {101 printf("可通过按键xyzab控制图形旋转原点/轴\n");102 glutInit(&argc, argv);103104 glutInitDisplayMode(GLUT_RGB | (OUTPUT_MODE == 0 ? GLUT_SINGLE : GLUT_DOUBLE)); 105 glutInitWindowPosition(100, 100);106 glutInitWindowSize(400, 400);107108 glutCreateWindow("第⼀个 OpenGL 程序");109110 glutDisplayFunc(&display);111 glutIdleFunc(display); //设置不断调⽤显⽰函数112 glutReshapeFunc(reshape);113 glutKeyboardFunc(&keyboard);114 glutMainLoop();115return0;116 }。
用虚拟球实现交互式OpenGL 3D图形的旋转
用虚拟球实现交互式OpenGL 3D图形的旋转
马新武;赵国群;王广春
【期刊名称】《计算机应用》
【年(卷),期】2001(021)0z1
【摘要】该文介绍了用虚拟球模仿3D跟踪球,实现交互式OpenGL 3D图形的旋转.该文还介绍了用四元旋转向量构造旋转矩阵以及把两个旋转向量叠加得到一个新的旋转向量的方法.
【总页数】2页(P169-170)
【作者】马新武;赵国群;王广春
【作者单位】山东大学模具工程技术研究中心;山东大学模具工程技术研究中心;山东大学模具工程技术研究中心
【正文语种】中文
【中图分类】TP391.41
【相关文献】
1.基于OpenGL的交互式PLC虚拟实验系统 [J], 冯清秀;夏俊力
2.OpenGL中交互式任意旋转三维场景的实现 [J], 许万荣;樊自田
3.OpenGL中交互式任意旋转三维场景的实现 [J], 许万荣;樊自田
4.基于OpenGL的交互式虚拟漫游系统开发研究 [J], 李婷婷;余庆军
5.基于OpenGL的交互式虚拟三维事故场景构建 [J], 张伟;李一兵;胡远志
因版权原因,仅展示原文概要,查看原文内容请购买。
opengl教程(11)平移旋转缩放
opengl教程(11)平移旋转缩放在前⾯的教程中,我们通过矩阵变化实现了物体在三维空间的平移、旋转、缩放操作。
在本篇教程中,我们来实现这三种的变化的组合操作。
通常情况下,我们会先缩放三维模型,使得它和其它物体⼤⼩相匹配,然后会旋转该物体,使得它朝向正确的⽅向,最后则是平移操作。
为了实现上述操作,我们只需把三个变化矩阵相乘,就得到了最终的变化矩阵,该矩阵乘以顶点坐标向量,就得到变化后的坐标位置。
看下⾯的公式:M n * M n-1 * ... * M0 * V = (M n* M n-1 * ... * M0) * VN = M n * M n-1 * ... * M0那么M n * M n-1 * ... * M0 * V = N * V所以我们只需在cpu上计算组合矩阵,然后做为uniform变量,传输到shader中区。
在顶点shader中,⽤该矩阵来乘顶点位置,得到最终的坐标。
前⾯说了,通常情况下,先缩放,再旋转,最后平移,矩阵相乘的⽅式,也是按照这个顺序,如果顺序反了或者不对,就会得到不同的结果,⽐如下⾯的图是先旋转,然后平移的效果。
下⾯的图则是先平移,后旋转的结果,可见顺序不同,最终的结果也不同。
在本教程的程序中,我们引⼊了pipeline类,该类隐藏矩阵变化的细节,我们只要传⼊缩放、旋转、平移的参数,就可以得到最终的变化矩阵。
主要代码:在math_3d.h中增加了矩阵类,主要⽤来实现矩阵的乘法操作。
#define ToRadian(x) ((x) * M_PI / 180.0f)#define ToDegree(x) ((x) * 180.0f / M_PI)⾸先定义了2个⾓度弧度转化的宏。
inline Matrix4f operator*(const Matrix4f& Right) const{Matrix4f Ret;for (unsigned int i = 0 ; i < 4 ; i++) {for (unsigned int j = 0 ; j < 4 ; j++) {Ret.m[i][j] = m[i][0] * Right.m[0][j] +m[i][1] * Right.m[1][j] +m[i][2] * Right.m[2][j] +m[i][3] * Right.m[3][j];}}return Ret;}重载矩阵相乘操作符,实现2个4x4矩阵的乘法操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <windows.h>
#include <gl.h>
#include <glut.h>
#include <gl/glaux.h>
#include <stdio.h>
#include <math.h>
#include<stdlib.h>
static GLfloat xAngle = 0.0f;
static GLfloat yAngle = 0.0f; //定义旋转角度
#define PI 3.1415926
typedef struct point
{
float x,y,z;
}PT;
struct point p[2][1000];
void Initial(void)
{
GLfloat mat_ambient[]={0.2f,0.2f,0.2f,1.0f};
GLfloat mat_diffuse[]={0.8f,0.8f,0.8f,1.0f};
GLfloat mat_specular[]={1.0f,1.0f,1.0f,1.0f};
GLfloat mat_shininess[]={50.0f};
GLfloat light0_diffuse[]={0.0f,0.0f,1.0f,1.0f};
GLfloat light0_position[]={1.0f,1.0f,1.0f,0.0f};
GLfloat light1_ambient[]={0.2f,0.2f,0.2f,1.0f};
GLfloat light1_diffuse[]={1.0f,0.0f,0.0f,1.0f};
GLfloat light1_specular[]={1.0f,0.6f,0.6f,1.0f};
GLfloat light1_position[]={-2.0f,-2.0f,1.0f,0.0f};
GLfloat spot_direction[]={1.0f,1.0f,-1.0f};
//定义材质属性
glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient); //指定材质的环境反射光反射系数
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse); //指定材质的漫反射光反射系数
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); //指定材质的镜面反射光反射系数
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); //指定材质的镜面发射指数值
//light0为漫反射的蓝色点光源
glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse); //指定漫反射光成分
glLightfv(GL_LIGHT0,GL_POSITION,light0_position); //设置光源的位置
//light1为红色聚光光源
glLightfv(GL_LIGHT1,GL_AMBIENT,light1_ambient); //指定环境光成分
glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse); //指定漫反射光成分
glLightfv(GL_LIGHT1,GL_SPECULAR,light1_specular); //指定镜面光成分
glLightfv(GL_LIGHT1,GL_POSITION,light1_position); //指定光源位置
glLightf(GL_LIGHT1,GL_SPOT_CUTOFF,30.0); //指定聚光截止角
glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,spot_direction);//指定聚光灯的方向
glEnable(GL_LIGHTING); //启用光源
glEnable(GL_LIGHT0); //启用0号光源
glEnable(GL_LIGHT1); //启用1号光源
glEnable(GL_DEPTH_TEST);
glClearColor(1.0f,1.0f,1.0f,1.0f);
// glShadeModel(GL_FLAT); //设置明暗处理模式
}
void ChangeSize(GLsizei w, GLsizei h)
{
if(h == 0) h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-5.5f,5.5f,-5.5f*h/w,5.5f*h/w,-10.0f,10.0f);
else
glOrtho(-5.5f*w/h,5.5f*w/h,-5.5f,5.5f,-10.0f,10.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Show(PT P1,PT P2,PT P3,GLfloat R)
{
glBegin(GL_TRIANGLES);
//
glColor3f(rand()/(RAND_MAX+1.0),rand()/(RAND_MAX+1.0),rand()/(RAND_MAX+1.0) );
glNormal3f( (P1.x+P2.x+P3.x)/(3*R), (P1.y+P2.y+P3.y)/(3*R), (P1.z+P2.z+P3.z)/(3*R));//计算法线
glVertex3f(P1.x,P1.y,P1.z);
glVertex3f(P2.x,P2.y,P2.z);
glVertex3f(P3.x,P3.y,P3.z);
glEnd();
}
void SolidSphere(GLfloat R)
{
float J,W;
int i,NUM=0;
for (W=0;W<2*PI; W+=PI/50)
{
NUM=0;
for (J=0;J<=PI+PI/40; J=J+PI/50)
{
p[0][NUM].x=R*sin(J)*sin(W);
p[0][NUM].y=R*sin(J)*cos(W);
p[0][NUM].z=R*cos(J);
p[1][NUM].x=R*sin(J)*sin(W+PI/50);
p[1][NUM].y=R*sin(J)*cos(W+PI/50);
p[1][NUM].z=R*cos(J);
NUM++;
}
for (i=0;i<NUM-2;i++)
{
Show(p[0][i],p[1][i+1],p[1][i],R);//第一个三角形
Show(p[0][i],p[1][i+1],p[0][i+1],R);//第二个三角形
}
}
}
void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslated(-3.0f,-3.0f,3.0f);
glRotatef(xAngle, 1.0f, 0.0f, 0.0f);
glRotatef(yAngle, 0.0f, 1.0f, 0.0f);
glFrontFace(GL_CW);
SolidSphere(2.0);
glPopMatrix();
glutSolidSphere(2.0f,50,50);
glutSwapBuffers();
}
void Keyboard(int key, int x, int y)
{
if(key == GLUT_KEY_UP) xAngle-= 5.0f; //增加旋转步长,产生动画效果if(key == GLUT_KEY_DOWN) xAngle += 5.0f;
if(key == GLUT_KEY_LEFT) yAngle -= 5.0f;
if(key == GLUT_KEY_RIGHT) yAngle += 5.0f;
if(xAngle > 356.0f) xAngle = 0.0f;
if(xAngle < -1.0f) xAngle = 355.0f;
if(yAngle > 356.0f) yAngle = 0.0f;。