c++winapiopenglgraphics

glBegin(GL_QUADS) is not drawing a kite


I am trying to draw a kite:

enter image description here

...using glBegin(GL_QUADS):

// g++ main.cpp -lopengl32 -lgdi32 -municode
#include <windows.h>
#include <GL/gl.h>
#include <cstdlib>  //system
#include <cstdio>   //printf, puts

void RenderQuad(HDC DeviceContext){
    GLdouble A[] = {0, -1};
    GLdouble B[] = {-1, 1};
    GLdouble C[] = {1, 1};
    GLdouble O[] = {0, 0};
    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);
    
    //Render kite
    glBegin(GL_QUADS);
    glVertex2dv(A);
    glVertex2dv(B);
    glVertex2dv(O);
    glVertex2dv(C);
    glEnd();
    
    //Check For Errors
    for (bool ErrorOccured; ;){
        switch(glGetError()){
            #define OTG_CASE(C) case C: puts("ERROR: "#C); ErrorOccured = true; break;
            case GL_NO_ERROR:
                if (ErrorOccured){
                    puts("Failed To Render Quad");
                    return;
                }
                goto noerrors;
            OTG_CASE(GL_INVALID_ENUM)
            OTG_CASE(GL_INVALID_VALUE)
            OTG_CASE(GL_INVALID_OPERATION)
            OTG_CASE(GL_STACK_OVERFLOW)
            OTG_CASE(GL_STACK_UNDERFLOW)
            OTG_CASE(GL_OUT_OF_MEMORY)
            default: puts("ERROR: Unknown"); ErrorOccured = true; break;
            #undef OTG_CASE
        }
    }
  noerrors:
    //Swap Buffers
    if (!SwapBuffers(DeviceContext)){
        printf("Failed To Swap Buffers %lu", GetLastError());
        return;
    }
    
    system("PAUSE");
}

int wWinMain(HINSTANCE Instance, HINSTANCE, PWSTR, int CmdShow){
    HWND Window;
    HDC DeviceContext;
    HGLRC RenderingContext;
    WNDCLASSW WindowClass = {0};

    //Register Window Class
    WindowClass.lpfnWndProc = DefWindowProcW;
    WindowClass.hInstance = Instance;
    WindowClass.lpszClassName = L"OTG";
    { 
        ATOM WindowClassAtom;
        WindowClassAtom = RegisterClassW(&WindowClass);
        if (!WindowClassAtom){
            printf("Failed To Register Class %lu", GetLastError());
            return -1;
        }
        SetLastError(NO_ERROR);
    }
    
    //Create Window
    Window = CreateWindowExW(
            0,
            WindowClass.lpszClassName,
            L"firstwindow",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            Instance,
            NULL
    );
    if (!Window){
        printf("Failed To Create Window %lu", GetLastError());
        goto unregisterclass;
    }
    SetLastError(NO_ERROR);
    
    ShowWindow(Window,  CmdShow);
    
    //Get Device Context
    DeviceContext = GetDC(Window);
    if (!DeviceContext){
        printf("Failed To Retrieve Device Context %lu", GetLastError());
        goto destroywindow;
    }
    SetLastError(NO_ERROR);
    
    {
        //Find A Suitable Pixel Format, Manually
        PIXELFORMATDESCRIPTOR PixelFormatDescriptor = {0};
        int PixelFormat;
        PixelFormat = 1;
        for (;;++PixelFormat){
            int NumPixelFormats;
            printf("Checking Pixel Format %d\n", PixelFormat);
            NumPixelFormats = DescribePixelFormat(
                DeviceContext, 
                PixelFormat, 
                sizeof(PixelFormatDescriptor),
                &PixelFormatDescriptor
            );
            if (!NumPixelFormats){
                printf("Failed To Describe PixelFormat %lu", GetLastError());
                goto releasedevicecontext;
            } 
            SetLastError(NO_ERROR);
            if (
                PixelFormatDescriptor.dwFlags & PFD_SUPPORT_OPENGL
                && PixelFormatDescriptor.dwFlags & PFD_DOUBLEBUFFER
                && PixelFormatDescriptor.cDepthBits > 1
            )
                break;
            if (PixelFormat == NumPixelFormats){
                puts("All Formats Checked - Cannot Find A Suitable OpenGL Pixel Format");
                goto releasedevicecontext;
            }
        }
        puts("Format Is Suitable");
        
        //Set Pixel Format
        if (!SetPixelFormat(DeviceContext, PixelFormat, &PixelFormatDescriptor)){
            printf("Failed To Set Pixel Format %lu", GetLastError());
            goto releasedevicecontext;
        }
        SetLastError(NO_ERROR);
    }
    
    //Create OpenGl Rendering Context
    RenderingContext = wglCreateContext(DeviceContext);
    if (!RenderingContext){
        printf("Failed To Create OpenGL Rendering Context %lu", GetLastError());
        goto releasedevicecontext;
    }
    SetLastError(NO_ERROR);
    
    //Make OpenGl Rendering Context Current
    if (!wglMakeCurrent(DeviceContext, RenderingContext)){
        printf("Failed To Make OpenGL Rending Context Current %lu", GetLastError());
        goto deleterenderingcontext;
    }
    puts("Initialized OpenGL Rendering Context");
    
    RenderQuad(DeviceContext);

    //Make OpenGl Rendering Context Not Current
    if(!wglMakeCurrent(NULL, NULL))
        printf("\nFailed To Make OpenGL Rendering Context Not Current %lu", GetLastError());
  
  deleterenderingcontext:
    SetLastError(NO_ERROR);
    if (!wglDeleteContext(RenderingContext))
        printf("\nFailed To Delete OpenGL Rendering Context %lu", GetLastError());
  
  releasedevicecontext:
    SetLastError(NO_ERROR);
    if (!ReleaseDC(Window, DeviceContext))
        printf("\nFailed To Release Device Context %lu", GetLastError());
  
  destroywindow:
    SetLastError(NO_ERROR);
    if (!DestroyWindow(Window))
        printf("\nFailed To Destroy Window %lu", GetLastError());
  
  unregisterclass:
    SetLastError(NO_ERROR);
    if (!UnregisterClassW(WindowClass.lpszClassName, Instance))
        printf("\nFailed To Unregister Class %lu", GetLastError());
    return 0;
}

...however it keeps drawing a triangle:

enter image description here

Why is a triangle being rendered? How does glBegin(GL_QUADS) work? How can I fix RenderQuad such that it produces the expected output?


Solution

  • Your shape is concave. Drawing such shapes with quads or polygons mode may not work properly.

    Only convex polygons are guaranteed to be drawn correctly by the GL. If a specified polygon is nonconvex when projected onto the window, then the rendered polygon need only lie within the convex hull of the projected vertices defining its boundary.

    The rules given for polygons also apply to each quad generated in a quad strip or from separate quads.

    taken from legacy spec .

    To get your kite just render two separate triangles.