2016-02-13 2 views
0

Я создал простую программу OpenGL на C, которая рисует треугольник, вращающийся внутри коробки. Треугольник должен быть равносторонним, но даже когда ширина и высота окна одинаковы, треугольники треугольников сжимаются и выдавливаются, когда они идут по ширине и длине окна. Я могу сказать, потому что я создал статическую равноугольную коробку, а вершины треугольника выходят за ее пределы. Вот короткий клип того, что он делает: https://edwardseverinsen1717-gmail.tinytake.com/sf/NDg5NjQ0XzI2MDQzMDM Извините отставание в некоторые моменты.примитивы OpenGL в окне Win32, искаженные в соответствии с размером окна

И вот мой код:

#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, это еще не равностороннее. (Bottom = 1.0, Other sides = sqrt (0.5^2 + 1.0^2) = 1.12)

Как вы уже отметили, вы должны компенсировать соотношение сторон рендерируемой области (которая не является квадратичной при прохождении 500x500 до CreateWindowEx, поскольку заголовок и границы включены здесь). Обычно это делается путем определения матрицы проекции с правильным соотношением сторон клиентской области. Посмотрите на GetClientRect, чтобы запросить размер клиентской области и glOrtho, чтобы указать матрицу проецирования.

+0

Спасибо, после использования 'GetClientRect' я узнал, что ширина моей клиентской области была примерно на 22 больше ее высоты и скомпенсирована. :) –

Смежные вопросы