2016-02-13 90 views
0

我在C中製作了一個簡單的OpenGL程序,它繪製了一個在盒子內旋轉的三角形。三角形應該是等邊的,但即使窗口的寬度和高度相同,三角形頂點沿着窗口的寬度和長度方向也會收縮和擠壓。我可以說,因爲我製作了一個靜態等角盒子,三角形的頂點在它外面。以下是它正在執行的一個簡短剪輯:https://edwardseverinsen1717-gmail.tinytake.com/sf/NDg5NjQ0XzI2MDQzMDM在某些時刻請原諒延遲。Win32窗口中的OpenGL圖元根據窗口大小扭曲

這裏是我的代碼:您使用不跨越正三角形

#include <windows.h> 
#include <gl/gl.h> 
#include <gl/glu.h> 

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 
void EnableOpenGL(HWND hwnd, HDC*, HGLRC*); 
void DisableOpenGL(HWND, HDC, HGLRC); 
void DrawTriangle(float theta); 
void DrawBox(void); 

int WINAPI WinMain(HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine, 
        int nCmdShow) 
{ 
    WNDCLASSEX wcex; 
    HWND hwnd; 
    HDC hDC; 
    HGLRC hRC; 
    MSG msg; 
    BOOL bQuit = FALSE; 
    float theta = 0.0f; 
    int i; 

    /* register window class */ 
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style = CS_OWNDC; 
    wcex.lpfnWndProc = WindowProc; 
    wcex.cbClsExtra = 0; 
    wcex.cbWndExtra = 0; 
    wcex.hInstance = hInstance; 
    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
    wcex.lpszMenuName = NULL; 
    wcex.lpszClassName = "GLSample"; 
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);; 


    if (!RegisterClassEx(&wcex)) 
     return 0; 

    /* create main window */ 
    hwnd = CreateWindowEx(0, 
          "GLSample", 
          "OpenGL Sample", 
          WS_OVERLAPPEDWINDOW, 
          CW_USEDEFAULT, 
          CW_USEDEFAULT, 
          500, 
          500, 
          NULL, 
          NULL, 
          hInstance, 
          NULL); 

    ShowWindow(hwnd, nCmdShow); 

    /* enable OpenGL for the window */ 
    EnableOpenGL(hwnd, &hDC, &hRC); 

    /* program main loop */ 
    while (!bQuit) 
    { 
     /* check for messages */ 
     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
     { 
      /* handle or dispatch messages */ 
      if (msg.message == WM_QUIT) 
      { 
       bQuit = TRUE; 
      } 
      else 
      { 
       TranslateMessage(&msg); 
       DispatchMessage(&msg); 
      } 
     } 
     else 
     { 
      /* OpenGL animation code goes here */ 

      glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
      glClear(GL_COLOR_BUFFER_BIT); 

      DrawTriangle(theta); 

      DrawBox(); 

      SwapBuffers(hDC); 

      theta += 1.0f; 
      Sleep (1); 
     } 
    } 

    /* shutdown OpenGL */ 
    DisableOpenGL(hwnd, hDC, hRC); 

    /* destroy the window explicitly */ 
    DestroyWindow(hwnd); 

    return msg.wParam; 
} 

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
     case WM_CLOSE: 
      PostQuitMessage(0); 
     break; 

     case WM_DESTROY: 
      return 0; 

     case WM_KEYDOWN: 
     { 
      switch (wParam) 
      { 
       case VK_ESCAPE: 
        PostQuitMessage(0); 
       break; 
      } 
     } 
     break; 

     default: 
      return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } 

    return 0; 
} 

void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC) 
{ 
    PIXELFORMATDESCRIPTOR pfd; 

    int iFormat; 

    /* get the device context (DC) */ 
    *hDC = GetDC(hwnd); 

    /* set the pixel format for the DC */ 
    ZeroMemory(&pfd, sizeof(pfd)); 

    pfd.nSize = sizeof(pfd); 
    pfd.nVersion = 1; 
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | 
        PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
    pfd.iPixelType = PFD_TYPE_RGBA; 
    pfd.cColorBits = 24; 
    pfd.cDepthBits = 16; 
    pfd.iLayerType = PFD_MAIN_PLANE; 

    iFormat = ChoosePixelFormat(*hDC, &pfd); 

    SetPixelFormat(*hDC, iFormat, &pfd); 

    /* create and enable the render context (RC) */ 
    *hRC = wglCreateContext(*hDC); 
    wglMakeCurrent(*hDC, *hRC); 
} 

void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC) 
{ 
    wglMakeCurrent(NULL, NULL); 
    wglDeleteContext(hRC); 
    ReleaseDC(hwnd, hDC); 
} 

void DrawTriangle(float theta) 
{ 
    glPushMatrix(); 

    if(theta != 0) 
    { 
     glRotatef(theta, 0.0f, 0.0f, 1.0f); 
    } 
    if(theta == 1) 
    { 
     glRotatef(89, 0.0f, 0.0f, 1.0f); 
    } 

    glBegin(GL_TRIANGLES); 

     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.0f, 0.50f); 
     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.45f, -0.50f); 
     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.45f, -0.50f); 

    glEnd(); 

    glPopMatrix(); 
} 

void DrawBox(void) 
{ 
    glPushMatrix(); 

    glBegin(GL_LINE_LOOP); 

     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.45f, 0.5f);  /*I decremented each x value by 0.05 to compensate for the bullshit with the window throwing off scale*/ 
     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(0.45f, -0.5f); 
     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.45f, -0.5f); 
     glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.45f, 0.5f); 

    glEnd(); 

    glPopMatrix(); 
} 
+1

你的三角形的長度爲1.096586,1.096586,和0.9的兩側,所以不是等邊三角形。在直線朝上的位置,您可以看到它適合框內(在影片剪輯的0:09處)。當你從那個位置旋轉它後,_當然,它會延伸到盒子之外!你有什麼理由相信它會留在盒子裏? –

回答

4

座標。等邊三角形總是具有三條相同長度的邊。在你的例子中,底部長度爲0.9,但其他兩個長度爲sqrt(0.45^2 + 1.0^2)= 1.097。即使假設你用0.45而不是0.5,這仍然不是等邊的。 (底= 1.0,其它兩側= SQRT(0.5^2 + 1.0^2)= 1.12)

正如你已經指出的那樣,必須以補償渲染區域的縱橫比(這不是二次經過時因爲標題欄和邊框在這裏包括在內,因此可以使用500x500到CreateWindowEx)。這通常通過定義具有客戶區域的正確縱橫比的投影矩陣來完成。查看GetClientRect來查詢客戶區大小,glOrtho指定投影矩陣。

+0

謝謝,在使用'GetClientRect'後,我發現我的客戶區域的寬度比其高度大約多22,並且得到了補償。 :) –