outdated: 35.Playing AVI Files In OpenGL
AVI视频文件读取,首先得建个AVI(AVISTREAMINFO)文件流指针,具体的结构,
typedef struct { DWORD fccType; // Stream type DWORD fccHandler; // Compressor handler DWORD dwFlags; // Applicable flags for the stream DWORD dwCaps; // Capability flags; currently unused WORD wPriority; // Priority of the stream WORD wLanguage; // Language of the stream DWORD dwScale; // Time scale applicable for the stream DWORD dwRate; // Rate in an integer format DWORD dwStart; // Sample number of the first frame of the AVI file DWORD dwLength; // Length of this stream DWORD dwInitialFrames; // Audio skew DWORD dwSuggestedBufferSize; // Recommended buffer size, in bytes, for the stream DWORD dwQuality; // Quality indicator of the video data in the stream DWORD dwSampleSize; // Size, in bytes, of a single data sample RECT rcFrame; // Dimensions of the video destination rectangle DWORD dwEditCount; // Number of times the stream has been edited DWORD dwFormatChangeCount; // Number of times the stream format has changed TCHAR szName[64]; // Null-terminated string containing a description of the stream } AVISTREAMINFO;
在flipIt函数__asm关键字用于调用内联汇编程序,在C/C++语法合法时出现,不能单独出现,后跟汇编指令,一组大括号中的命令或至少时空括号。
在OpenAVI函数中,AVIFileInit()函数初始化AVIFile库。
AVIStreamOpenFromFile()函数从文件中读取流,具体的格式为,
STDAPI AVIStreamOpenFromFile( PAVISTREAM *ppavi, LPCTSTR szFile, DWORD fccType, LONG lParam, UINT mode, CLSID *pclsidHandler );
AVIStreamInfo()函数读取关于流的头部信息到psi中,这样就可以直接得出文件的宽和高,函数具体格式为,
STDAPI AVIStreamInfo( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize );
AVIStreamLength()函数读取流的长度。
AVIStreamSampleToTime()函数将流从一个位置开始转化为毫秒。若从开始转化再除以长度就可以知道平均每帧的毫秒数。
在GrabAVIFrame()函数中,DrawDibDraw()函数在屏幕上画一个DIB,具体格式为,
BOOL DrawDibDraw( HDRAWDIB hdd, HDC hdc, int xDst, int yDst, int dxDst, int dyDst, LPBITMAPINFOHEADER lpbi, LPVOID lpBits, int xSrc, int ySrc, int dxSrc, int dySrc, UINT wFlags );
glTexSubImage2D()函数指定现有贴图的一部分,但不能创建一个新的贴图。
下面为代码,
#ifndef GL_FRAMEWORK_INCLUDED #define GL_FRAMEWORK_INCLUDED #include <windows.h> typedef struct { // Structure for keyboard stuff BOOL keyDown[256]; } Keys; typedef struct { // Contains information vital to applications HMODULE hInstance; // Application Instance const char* className; } Application; typedef struct { // Window creation info Application* application; char* title; int width; int height; int bitsPerPixel; BOOL isFullScreen; } GL_WindowInit; typedef struct { // Contains information vital to a window Keys* keys; HWND hWnd; // Windows handle HDC hDC; // Device context HGLRC hRC; // Rendering context GL_WindowInit init; BOOL isVisible; // Window visiable? DWORD lastTickCount; // Tick counter } GL_Window; void TerminateApplication(GL_Window* window); // Terminate the application void ToggleFullscreen(GL_Window* window); // Toggle fullscreen / Windowed mode BOOL Initialize(GL_Window* window, Keys* keys); void Deinitialize(void); void Update(DWORD milliseconds); void Draw(void); /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ #endif
#include <Windows.h> #include <GL\glew.h> #include <GL\glut.h> #include "Previous.h" #define WM_TOGGLEFULLSCREEN (WM_USER+1) // Application define message for toggling // between fulscreen / windowed mode static BOOL g_isProgramLooping; // Window creation loop, for fullscreen / windowed mode static BOOL g_createFullScreen; // If true, then create window void TerminateApplication(GL_Window* window) // Terminate the application { PostMessage(window->hWnd, WM_QUIT, 0, 0); // Send a WM_QUIT message g_isProgramLooping = FALSE; // Stop looping of the program } void ToggleFullscreen(GL_Window* window) // Toggle fullscreen /windowed mode { PostMessage(window->hWnd, WM_TOGGLEFULLSCREEN, 0, 0); // Send a WM_TOGGLEFULLSCREEN message } void ReshapeGL(int width, int height) // Reshape the window when it's moved or resized { glViewport(0, 0, (GLsizei)(width), (GLsizei)(height)); // Reset the current viewport glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Calcutate the aspect ratio of the window gluPerspective(45.0f, (GLfloat)(width) / (GLfloat)(height), 1.0, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } BOOL ChangeScreenResolution(int width, int height, int bitsPerPixel) // Change the screen resolution { DEVMODE dmScreenSettings; // Device mode ZeroMemory(&dmScreenSettings, sizeof(DEVMODE)); // Make sure memory is cleared dmScreenSettings.dmSize = sizeof(DEVMODE); // Size of the devmode structure dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bitsPerPixel; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { return FALSE; // Display change failed } return TRUE; } BOOL CreateWindowGL(GL_Window* window) { DWORD windowStyle = WS_OVERLAPPEDWINDOW; // Define window style DWORD windowExtendedStyle = WS_EX_APPWINDOW; // Define the window's extended style ShowCursor(FALSE); PIXELFORMATDESCRIPTOR pdf = { sizeof(PIXELFORMATDESCRIPTOR), // Size of this pixel format descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format must support window PFD_SUPPORT_OPENGL | // Format must support openGL PFD_DOUBLEBUFFER, // Must support double buffering PFD_TYPE_RGBA, // Request an RGBA format window->init.bitsPerPixel, // Select color depth 0, 0, 0, 0, 0, 0, // Color bits ignored 0, // No alpha buffer 0, // Shift bit ignored 0, // No accumulation buffer 0, 0, 0, 0, // Accumulation bits ignored 16, // 16bits Z-buffer (depth buffer) 0, // No stencil buffer 0, // No auxiliary buffer PFD_MAIN_PLANE, // Main drawing layer 0, // Reserved 0, 0, 0 // Layer masks ignored }; RECT windowRect = { 0, 0, window->init.width, window->init.height }; // Window coordiantes GLuint PixelFormat; if (window->init.isFullScreen == TRUE) { if (ChangeScreenResolution(window->init.width, window->init.height, window->init.bitsPerPixel) == FALSE) { // Fullscreen mode failed, run in windowed mode instead MessageBox(HWND_DESKTOP, "Mode Switch Failed.\nRuning In Windowed Mode.", "Error", MB_OK | MB_ICONEXCLAMATION); window->init.isFullScreen = FALSE; } else { /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ ShowCursor(FALSE); /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ windowStyle = WS_POPUP; // Popup window windowExtendedStyle |= WS_EX_TOPMOST; } } else { // Adjust window, account for window borders AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle); } // Create Opengl window window->hWnd = CreateWindowEx(windowExtendedStyle, // Extended style window->init.application->className, // Class name window->init.title, // Window title windowStyle, // Window style 0, 0, // Window X,Y position windowRect.right - windowRect.left, // Window width windowRect.bottom - windowRect.top, // Window height HWND_DESKTOP, // Desktop is window's parent 0, // No menu window->init.application->hInstance, // Pass the window instance window); if (window->hWnd == 0) { // Was window creation a success? return FALSE; } window->hDC = GetDC(window->hWnd); if (window->hDC == 0) { DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } PixelFormat = ChoosePixelFormat(window->hDC, &pdf); // Find a compatible pixel format if (PixelFormat == 0) { ReleaseDC(window->hWnd, window->hDC); // Release device context window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } if (SetPixelFormat(window->hDC, PixelFormat, &pdf) == FALSE) { // Try to set the pixel format ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } window->hRC = wglCreateContext(window->hDC); // Try to get a rendering context if (window->hRC == 0) { ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } // Make the rendering context our current rendering context if (wglMakeCurrent(window->hDC, window->hRC) == FALSE) { wglDeleteContext(window->hRC); // Delete the rendering context window->hRC = 0; ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } ShowWindow(window->hWnd, SW_NORMAL); // Make the window visiable window->isVisible = TRUE; ReshapeGL(window->init.width, window->init.height); // Reshape our GL window ZeroMemory(window->keys, sizeof(Keys)); // Clear all keys window->lastTickCount = GetTickCount(); return TRUE; } BOOL DestoryWindowGL(GL_Window* window) { if (window->hWnd != 0) { if (window->hDC != 0) { wglMakeCurrent(window->hDC, 0); // Setting current active rendering context to zero if (window->hRC != 0) { wglDeleteContext(window->hRC); window->hRC = 0; } ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; } DestroyWindow(window->hWnd); window->hWnd = 0; } if (window->init.isFullScreen) { ChangeDisplaySettings(NULL, 0); // Switch back to desktop resolution ShowCursor(TRUE); } return TRUE; } // Process window message callback LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get the window context GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA)); switch (uMsg) { // Evaluate window message case WM_SYSCOMMAND: // Intercept system commands { switch (wParam) { // Check system calls case SC_SCREENSAVE: // Screensaver trying to start? case SC_MONITORPOWER: // Mointer trying to enter powersave? return 0; // Prevent form happening } break; } return 0; case WM_CREATE: { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store window structure pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong(hWnd, GWL_USERDATA, (LONG)(window)); } return 0; case WM_CLOSE: TerminateApplication(window); return 0; case WM_SIZE: switch (wParam) { case SIZE_MINIMIZED: // Was window minimized? window->isVisible = FALSE; return 0; case SIZE_MAXIMIZED: window->isVisible = TRUE; ReshapeGL(LOWORD(lParam), HIWORD(lParam)); return 0; case SIZE_RESTORED: window->isVisible = TRUE; ReshapeGL(LOWORD(lParam), HIWORD(lParam)); return 0; } break; case WM_KEYDOWN: if ((wParam >= 0) && (wParam <= 255)) { window->keys->keyDown[wParam] = TRUE; // Set the selected key(wParam) to true return 0; } break; case WM_KEYUP: if ((wParam >= 0) && (wParam <= 255)) { window->keys->keyDown[wParam] = FALSE; return 0; } break; case WM_TOGGLEFULLSCREEN: g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE; PostMessage(hWnd, WM_QUIT, 0, 0); break; /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ } return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass unhandle message to DefWindowProc } BOOL RegisterWindowClass(Application* application) { WNDCLASSEX windowClass; ZeroMemory(&windowClass, sizeof(WNDCLASSEX)); // Make sure memory is cleared windowClass.cbSize = sizeof(WNDCLASSEX); // Size of the windowClass structure windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraws the window for any movement / resizing windowClass.lpfnWndProc = (WNDPROC)(WindowProc); // WindowProc handles message windowClass.hInstance = application->hInstance; // Set the instance windowClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);// Class background brush color windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the arrow pointer windowClass.lpszClassName = application->className; // Sets the application className if (RegisterClassEx(&windowClass) == 0) { MessageBox(HWND_DESKTOP, "RegisterClassEx Failed!", "Error", MB_OK | MB_ICONEXCLAMATION); return FALSE; } return TRUE; } int WINAPI WinMain(HINSTANCE hIstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { Application application; GL_Window window; Keys keys; BOOL isMessagePumpActive; MSG msg; DWORD tickCount; application.className = "OpenGL"; application.hInstance = hIstance; ZeroMemory(&window, sizeof(GL_Window)); window.keys = &keys; // Window key structure window.init.application = &application; // Window application window.init.title = "GL Framework"; // Window title window.init.width = 640; // Window width window.init.height = 480; // Window height window.init.bitsPerPixel = 16; // Bits per pixel window.init.isFullScreen = TRUE; // Fullscreen? (set to TRUE) ZeroMemory(&keys, sizeof(Keys)); if (MessageBox(HWND_DESKTOP, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen?", MB_YESNO | MB_ICONQUESTION) == IDNO) { window.init.isFullScreen = FALSE; } if (RegisterWindowClass(&application) == FALSE) { MessageBox(HWND_DESKTOP, "Error Registering Window Class!", "Error", MB_OK | MB_ICONEXCLAMATION); return -1; } g_isProgramLooping = TRUE; g_createFullScreen = window.init.isFullScreen; while (g_isProgramLooping) { // Loop until WM_QUIT is received window.init.isFullScreen = g_createFullScreen; // Set init param of window creation to fullscreen? if (CreateWindowGL(&window) == TRUE) { // Was window creation successful? // At this point we should have a window that is setup to render OpenGL if (Initialize(&window, &keys) == FALSE) { TerminateApplication(&window); // Close window, this will handle the shutdown } else { isMessagePumpActive = TRUE; while (isMessagePumpActive == TRUE) { // Success creating window. Check for window messages if (PeekMessage(&msg, window.hWnd, 0, 0, PM_REMOVE) != 0) { if (msg.message != WM_QUIT) { DispatchMessage(&msg); } else { isMessagePumpActive = FALSE; // Terminate the message pump } } else { if (window.isVisible == FALSE) { WaitMessage(); // Application is minimized wait for a message } else { // Process application loop tickCount = GetTickCount(); // Get the tick count Update(tickCount - window.lastTickCount); // Update the counter window.lastTickCount = tickCount;// Set last count to current count Draw(); // Draw screen SwapBuffers(window.hDC); } } } } // Application is finished Deinitialize(); DestoryWindowGL(&window); } else { MessageBox(HWND_DESKTOP, "Error Creating OpenGL Window", "Error", MB_OK | MB_ICONEXCLAMATION); g_isProgramLooping = FALSE; } } UnregisterClass(application.className, application.hInstance); // UnRegister window class return 0; }
/******************************************************************************************************************************************/ /******************************************************************************************************************************************/ #include <windows.h> #include <stdio.h> #include <Vfw.h> #include <gl/glew.h> #include <GL\glut.h> #include <GL\GLUAX.H> #include "Previous.h" #pragma comment(lib, "legacy_stdio_definitions.lib") #pragma comment(lib, "vfw32.lib") #ifndef CDS_FULLSCREEN #define CDA_FULLSCREEN #endif GL_Window* g_window; Keys* g_keys; /* * Every OpenGL program is linked to a Rendering Context. * A Rendering Context is what links OpenGL calls to the Device Context. * In order for your program to draw to a Window you need to create a Device Context. * The DC connects the Window to the GDI (Graphics Device Interface). */ HGLRC hRC = NULL; // Permanent rendering context HDC hdc = CreateCompatibleDC(0); // Private GDI device context HWND hWnd = NULL; // Holds our window handle HINSTANCE hInstance; // Holds the instance of the application /* * It's important to make this global so that each procedure knows if * the program is running in fullscreen mode or not. */ bool keys[256]; // Array used for the keyboard routine bool active = TRUE; // Window active flag set to TRUE by default bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default float angle; // Rotation int next; // Animtion int frame = 0; // Frame counter int effect; // Current effect bool sp; // 'space' pressed ? bool env = TRUE; // Environment mapping bool ep; // 'E' pressed ? bool bg = TRUE; // Background bool bp; // 'B' pressed ? AVISTREAMINFO psi; // Pointer to a structure containing stream info PAVISTREAM pavi; // Handle to an open stream PGETFRAME pgf; // Pointer to a GetFrame object BITMAPINFOHEADER bmih; // Header information for DrawDibDraw decoding long lastframe; // Last frame of the stream int width; // Video int height; char* pdata; // Texture data int mpf; // Will hold rough millisecond per frame GLUquadricObj* quadratic; HDRAWDIB hdd; // Handle for dib HBITMAP hBitmap; // Handle to a device dependant bitmap unsigned char* data = 0;// Resized image void flipIt(void* buffer) // Flips the red and blue bytes { void* b = buffer; __asm { // Assembler mov ecx, 256 * 256 // Set up a counter mov ebx, b // Points ebx to data label : // Label used for looping mov al, [ebx + 0] // Loads value at ebx into al mov ah, [ebx + 2] // Loads value at ebx+2 into ah mov [ebx + 2], al // Stores value in al at ebx+2 mov [ebx + 0], ah // Stores value in ah at ebx add ebx, 3 // Moves through the data by 3 bytes dec ecx // Decreases loop counter jnz label // If not zero jump back to label } } void OpenAVI(LPCSTR szFile) { TCHAR title[100]; AVIFileInit(); // Opens the AVIFile library if (AVIStreamOpenFromFile(&pavi, szFile, streamtypeVIDEO, 0, OF_READ, NULL) != 0) { MessageBox(HWND_DESKTOP, "Failed to open the AVI stream", "ERROR", MB_OK | MB_ICONEXCLAMATION); } AVIStreamInfo(pavi, &psi, sizeof(psi)); // Reads infomation about the stream into psi width = psi.rcFrame.right - psi.rcFrame.left; // Width is right side of frame minus left height = psi.rcFrame.bottom - psi.rcFrame.top; // Height lastframe = AVIStreamLength(pavi); // The last frame of the stream mpf = AVIStreamSampleToTime(pavi, lastframe) / lastframe; // Calculate rough milliseconds per frame bmih.biSize = sizeof(BITMAPINFOHEADER); // The dimensions and color format of a device-independent bitmap bmih.biPlanes = 1; bmih.biBitCount = 24; // Bits format (24 bit, 3 bytes) bmih.biWidth = 256; bmih.biHeight = 256; bmih.biCompression = BI_RGB; // Requested mode hBitmap = CreateDIBSection(hdc, (BITMAPINFO*)(&bmih), DIB_RGB_COLORS, (void**)(&data), NULL, NULL); SelectObject(hdc, hBitmap); // Select hBitmap into device context pgf = AVIStreamGetFrameOpen(pavi, NULL); // Create the PGETFRAME using request mode if (pgf == NULL) { MessageBox(HWND_DESKTOP, "Failed to open the AVI frame", "ERROR", MB_OK | MB_ICONEXCLAMATION); } // Information for the title bar wsprintf(title, "AVI player: width: %d, height: %d, frames: %d", width, height, lastframe); SetWindowText(g_window->hWnd, title); // Modify the title bar } void GrabAVIFrame(int frame) // Grabs a frame from the stream { LPBITMAPINFOHEADER lpbi; // Holds the bitmap header information lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pgf, frame); // Grabs data from the AVI stream // Pointer to data returned by AVIStreamGetFrame pdata = (char*)lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD); // Convert data to requested bitmap format DrawDibDraw(hdd, hdc, 0, 0, 256, 256, lpbi, pdata, 0, 0, width, height, 0); flipIt(data); // Swap the red and blue bytes (GL compatability // Update the texture glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, data); } void closeAVI(void) // Properly closes the AVI file { DeleteObject(hBitmap); // Delete the device dependant bitmap object DrawDibClose(hdd); // Closes the DrawDib device context AVIStreamGetFrameClose(pgf); // Deallocates the GetFrame resource AVIStreamRelease(pavi); // Release the stream AVIFileExit(); // Release the file } BOOL Initialize(GL_Window* window, Keys* keys) { g_window = window; g_keys = keys; angle = 0.0f; hdd = DrawDibOpen(); // Grabs a device context for Dib glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); // The type of depth testing (less or equal) glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Set perspective calculations to most accurate quadratic = gluNewQuadric(); // Create a pointer to the quadric object gluQuadricNormals(quadratic, GLU_SMOOTH); // Create smooth noraml gluQuadricTexture(quadratic, GL_TRUE); // Create texture coords glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);// Set the texture generation mode for S to sphere mapping glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);// Set the texture generation mode for T to sphere mapping OpenAVI("Data/face2.avi"); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, data); return TRUE; } void Deinitialize(void) { closeAVI(); } void Update(DWORD milliseconds) { ShowCursor(TRUE); if (g_keys->keyDown[VK_ESCAPE] == TRUE) { TerminateApplication(g_window); } if (g_keys->keyDown[VK_F1] == TRUE) { ToggleFullscreen(g_window); } if ((g_keys->keyDown[' ']) && !sp) { sp = TRUE; effect++; if (effect >= 3) effect = 0; } if (!g_keys->keyDown[' ']) sp = FALSE; if ((g_keys->keyDown['B']) && !bp) { bp = TRUE; bg = !bg; } if (!g_keys->keyDown['B']) bp = FALSE; if ((g_keys->keyDown['E']) && !ep) { ep = TRUE; env = !env; } if (!g_keys->keyDown['E']) ep = FALSE; angle += (float)(milliseconds) / 60.0f; // Update angle based on the timer next += milliseconds; // Increase next based on the timer frame = next / mpf; // Calculate the current frame if (frame >= lastframe) { frame = 0; next = 0; // Reset the animation timer } } void Draw(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GrabAVIFrame(frame); if (bg) { // Is background visiable? glLoadIdentity(); glBegin(GL_QUADS); glTexCoord2f(1.0f, 1.0f); glVertex3f(11.0f, 8.3f, -20.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-11.0f, 8.3f, -20.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-11.0f, -8.3f, -20.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(11.0f, -8.3f, -20.0f); glEnd(); } glLoadIdentity(); glTranslatef(0.0f, 0.0f, -10.0f); if (env) { // Is environment mapping on? glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } glRotatef(angle * 2.3f, 1.0f, 0.0f, 0.0f); glRotatef(angle * 1.8f, 0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 0.0f, 2.0f); switch (effect) { case 0: glRotatef(angle * 1.3f, 1.0f, 0.0f, 0.0f); glRotatef(angle * 1.1f, 0.0f, 1.0f, 0.0f); glRotatef(angle * 1.2f, 0.0f, 0.0f, 1.0f); glBegin(GL_QUADS); // Front Face glNormal3f(0.0f, 0.0f, 0.5f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Back Face glNormal3f(0.0f, 0.0f, -0.5f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Top Face glNormal3f(0.0f, 0.5f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Bottom Face glNormal3f(0.0f, -0.5f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Right Face glNormal3f(0.5f, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Left Face glNormal3f(-0.5f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); break; case 1: glRotatef(angle * 1.3f, 1.0f, 0.0f, 0.0f); glRotatef(angle * 1.1f, 0.0f, 1.0f, 0.0f); glRotatef(angle * 1.2f, 0.0f, 0.0f, 1.0f); gluSphere(quadratic, 1.3f, 20, 20); // Sphere break; case 2: glRotatef(angle * 1.3f, 1.0f, 0.0f, 0.0f); glRotatef(angle * 1.1f, 0.0f, 1.0f, 0.0f); glRotatef(angle * 1.2f, 0.0f, 0.0f, 1.0f); gluCylinder(quadratic, 1.0f, 1.0f, 3.0f, 32, 32); break; } if (env) { glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } glFlush(); } /******************************************************************************************************************************************/ /******************************************************************************************************************************************/
Thanks for Nehe's tutorials, this is his home.