outdated: 42.Multiple Viewports
一个屏幕分为四个小窗口,如下图。
UpdateTex()为绘制函数,
void UpdateTex(int dmx, int dmy) // Update pixel dmx, dmy on the texture { tex_data[0 + ((dmx + (width * dmy)) * 3)] = 255; // Set red pixel to full bright tex_data[1 + ((dmx + (width * dmy)) * 3)] = 255; // Green tex_data[2 + ((dmx + (width * dmy)) * 3)] = 255; // Blue }
在绘制完所有迷宫时,会设置标题题目“SetWindowText()函数”且重置贴图数据“ZeroMemory()函数”,最后重新绘制。
在Initialize()函数中,对quadric贴图时,需要先对quadric贴图坐标设置。
gluQuadricTexture(quadric, GL_TRUE);
每次的Update都会检查迷宫是否绘制完成,
done = TRUE;
for (int x = 0; x < width; x+=2) { for (int y = 0; y < height; y+=2) { if (tex_data[((x + (width * y)) * 3)] == 0) done = FALSE; // Check } }
if (done) {
...
}
在确定下一步绘制哪里时,先得判断是否是在边缘和现在位置的上下左右是否绘制过。如下,
if (((mx > (width - 4) || tex_data[(((mx + 2) + (width*my)) * 3)] == 255)) && ((mx < 2 || tex_data[(((mx - 2) + (width*my)) * 3)] == 255)) && ((my >(height - 4) || tex_data[((mx + (width*(my + 2))) * 3)] == 255)) && ((my < 2 || tex_data[((mx + (width*(my - 2))) * 3)] == 255))) { do { mx = int(rand() % (width / 2)) * 2; my = int(rand() % (width / 2)) * 2; } while (tex_data[((mx + (width*my)) * 3)] == 0); }
接下来再随机选方向,来绘制,
dir = int(rand() % 4); // Pick a random direction if ((dir == 0) && (mx <= (width - 4))) { if (tex_data[(((mx + 2) + (width * my)) * 3)] == 0) { UpdateTex(mx + 1, my); // Update the texture to show path cut out between rooms mx += 2; // Move to the right } } if ((dir == 1) && (my <= (width - 4))) { if (tex_data[((mx + (width * (my + 2))) * 3)] == 0) { UpdateTex(mx, my + 1); my += 2; } } if ((dir == 2) && (mx >= 2)) { if (tex_data[(((mx - 2) + (width * my)) * 3)] == 0) { UpdateTex(mx - 1, my); mx -= 2; } } if ((dir == 3) && (my >= 2)) { if (tex_data[((mx + (width * (my - 2))) * 3)] == 0) { UpdateTex(mx, my - 1); my -= 2; } } UpdateTex(mx, my);
在Draw()函数中,GetClientRect()函数可以获取窗口的尺寸。glViewport()函数用来分割窗口。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 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 DestroyWindowGL(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) { DWORD tickCount; // Holds current tick count __int64 timer; // Used for the tick count /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ // Get the window context GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA)); switch (uMsg) { // Evaluate window message case WM_PAINT: { tickCount = GetTickCount(); Update(tickCount - window->lastTickCount); window->lastTickCount = tickCount; Draw(); SwapBuffers(window->hDC); } return 0; 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; /******************************************************************************************************************************************/ /******************************************************************************************************************************************/ 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 = "Multiple Viewports...Building Maze!"; // Window title window.init.width = 1024; // Window width window.init.height = 768; // Window height window.init.bitsPerPixel = 32; // 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(); DestroyWindowGL(&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 <GL/glew.h> #include <GL/glut.h> #include <GL/GLUAX.H> #include <math.h> #include <stdio.h> #include "Previous.h" #pragma comment(lib, "legacy_stdio_definitions.lib") #ifndef CDS_FULLSCREEN #define CDS_FULLSCREEN 4 #endif GL_Window* g_window; Keys* g_keys; int mx, my; // Used for loops const int width = 128; // Maze const int height = 128; BOOL done; // Flag to let us know when it's done BOOL sp; // Spacebar pressed? BYTE r[4], g[4], b[4]; // Random color BYTE* tex_data; GLfloat xrot, yrot, zrot; // Rotation GLUquadricObj* quadric; // The quadric object void UpdateTex(int dmx, int dmy) // Update pixel dmx, dmy on the texture { tex_data[0 + ((dmx + (width * dmy)) * 3)] = 255; // Set red pixel to full bright tex_data[1 + ((dmx + (width * dmy)) * 3)] = 255; // Green tex_data[2 + ((dmx + (width * dmy)) * 3)] = 255; // Blue } void Reset(void) // Reset the maze,colors,start point,etc { ZeroMemory(tex_data, width * height * 3); srand(GetTickCount()); for (int loop = 0; loop < 4; ++loop) { // Color r[loop] = rand() % 128 + 128; g[loop] = rand() % 128 + 128; b[loop] = rand() % 128 + 128; } mx = int(rand() % (width / 2)) * 2; // Position my = int(rand() % (height / 2)) * 2; } BOOL Initialize(GL_Window* window, Keys* keys) { tex_data = new BYTE[width * height * 3]; g_window = window; g_keys = keys; Reset(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, tex_data); glEnable(GL_TEXTURE_2D); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); // Enable color material quadric = gluNewQuadric(); // Create a pointer to the quadric bject gluQuadricNormals(quadric, GLU_SMOOTH); // Create smooth normal gluQuadricTexture(quadric, GL_TRUE); // Create texture coords glEnable(GL_LIGHT0); return TRUE; } void Deinitialize(void) { delete[] tex_data; } void Update(DWORD milliseconds) { 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; Reset(); } if (!g_keys->keyDown[' ']) sp = FALSE; int dir; // Direction xrot += (float)(milliseconds)* 0.02f; yrot += (float)(milliseconds)* 0.03f; zrot += (float)(milliseconds)* 0.015f; done = TRUE; for (int x = 0; x < width; x+=2) { for (int y = 0; y < height; y+=2) { if (tex_data[((x + (width * y)) * 3)] == 0) done = FALSE; // Check } } // Title if (done) { // Display a message at the top of the window, pause for a bit and then start building a new maze SetWindowText(g_window->hWnd, "Multiple Viewports...Maze Complete!"); Sleep(5000); SetWindowText(g_window->hWnd, "Multiple Viewports...Building Maze!"); Reset(); } if (((mx > (width - 4) || tex_data[(((mx + 2) + (width*my)) * 3)] == 255)) && ((mx < 2 || tex_data[(((mx - 2) + (width*my)) * 3)] == 255)) && ((my >(height - 4) || tex_data[((mx + (width*(my + 2))) * 3)] == 255)) && ((my < 2 || tex_data[((mx + (width*(my - 2))) * 3)] == 255))) { do { mx = int(rand() % (width / 2)) * 2; my = int(rand() % (width / 2)) * 2; } while (tex_data[((mx + (width*my)) * 3)] == 0); } dir = int(rand() % 4); // Pick a random direction if ((dir == 0) && (mx <= (width - 4))) { if (tex_data[(((mx + 2) + (width * my)) * 3)] == 0) { UpdateTex(mx + 1, my); // Update the texture to show path cut out between rooms mx += 2; // Move to the right } } if ((dir == 1) && (my <= (width - 4))) { if (tex_data[((mx + (width * (my + 2))) * 3)] == 0) { UpdateTex(mx, my + 1); my += 2; } } if ((dir == 2) && (mx >= 2)) { if (tex_data[(((mx - 2) + (width * my)) * 3)] == 0) { UpdateTex(mx - 1, my); mx -= 2; } } if ((dir == 3) && (my >= 2)) { if (tex_data[((mx + (width * (my - 2))) * 3)] == 0) { UpdateTex(mx, my - 1); my -= 2; } } UpdateTex(mx, my); } void Draw(void) { RECT rect; GetClientRect(g_window->hWnd, &rect); // Get window dimensions int window_width = rect.right - rect.left; int window_height = rect.bottom - rect.top; // Update texture glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, tex_data); glClear(GL_COLOR_BUFFER_BIT); for (int loop = 0; loop < 4; ++loop) { glColor3ub(r[loop], g[loop], b[loop]); // Assign color to current view if (loop == 0) { glViewport(0, window_height / 2, window_width / 2, window_height / 2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, window_width / 2, window_height / 2, 0); } if (loop == 1) { glViewport(window_width / 2, window_height / 2, window_width / 2, window_height / 2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)(width) / (GLfloat)(height), 0.1f, 500.0f); } if (loop == 2) { glViewport(window_width / 2, 0, window_width / 2, window_height / 2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)(width) / (GLfloat)(height), 0.1f, 500.0f); } if (loop == 3) { glViewport(0, 0, window_width / 2, window_height / 2); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)(width) / (GLfloat)(height), 0.1f, 500.0f); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_DEPTH_BUFFER_BIT); if (loop == 0) { glBegin(GL_QUADS); glTexCoord2f(1.0f, 0.0f); glVertex2f(window_width / 2, 0); glTexCoord2f(0.0f, 0.0f); glVertex2f(0, 0); glTexCoord2f(0.0f, 1.0f); glVertex2f(0, window_width / 2); glTexCoord2f(1.0f, 1.0f); glVertex2f(window_width / 2, window_width / 2); glEnd(); } if (loop == 1) { glTranslatef(0.0f, 0.0f, -14.0f); glRotatef(xrot, 1.0f, 0.0f, 0.0f); glRotatef(yrot, 0.0f, 1.0f, 0.0f); glRotatef(zrot, 0.0f, 0.0f, 1.0f); glEnable(GL_LIGHTING); gluSphere(quadric, 4.0f, 32, 32); glDisable(GL_LIGHTING); } if (loop == 2) { glTranslatef(0.0f, 0.0f, -2.0f); glRotatef(-45.0f, 1.0f, 0.0f, 0.0f); glRotatef(zrot / 1.5f, 0.0f, 0.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 0.0f); glEnd(); } if (loop == 3) { glTranslatef(0.0f, 0.0f, -7.0f); glRotatef(-xrot / 2, 1.0f, 0.0f, 0.0f); glRotatef(-yrot / 2, 0.0f, 1.0f, 0.0f); glRotatef(-zrot / 2, 0.0f, 0.0f, 1.0f); glEnable(GL_LIGHTING); glTranslatef(0.0f, 0.0f, -2.0f); gluCylinder(quadric, 1.5f, 1.5f, 4.0f, 32, 16); glDisable(GL_LIGHTING); } } glFlush(); }
Thanks for Nehe's tutorials, this is his home.