Convert triangle strips to Octagonal?

Viewed 187

I'm using the gl.h library and it outputs triangle strips. The example shows this:

#include <windows.h>
#include <gl/gl.h>
#include <math.h>
#include <stdio.h>
#define step 8
#define angle 3.1415926 * 2.f / step

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


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;

    /* 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,
                          600,
                          600,
                          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);

            glPushMatrix();
            //glRotatef(theta, 0.0f, 0.0f, 1.0f);

  
                float xPos = 0;
                float yPos = 0;
                float radius = 0.5f;
                float prevX = xPos;
                float prevY = yPos - radius;


            for (int i=0;i<=step;i++)
            {
                float newX =   radius *   sin(angle * i);
                float newY = - radius * cos(angle * i);

                glBegin(GL_TRIANGLES);
                glColor3f(0,0.5f,0);

                glVertex3f(0.0f,0.0f,0.0f);
                glVertex3f(prevX , prevY , 0.0f);
                glVertex3f(newX , newY   , 0.0f);



                prevX = newX;
                prevY = newY;


            }

            glEnd();






            glPopMatrix();
            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);
}

                float xPos = 0;
                float yPos = 0;
                float radius = 0.5f;
                float prevX = xPos;
                float prevY = yPos - radius;


        for (int i=0;i<=step;i++)
        {
            float newX =   radius *   sin(angle * i);
            float newY = - radius * cos(angle * i);

            glBegin(GL_TRIANGLES);
            glColor3f(0,0.5f,0);

            glVertex3f(0.0f,0.0f,0.0f);
            glVertex3f(prevX , prevY , 0.0f);
            glVertex3f(newX , newY   , 0.0f);



            prevX = newX;
            prevY = newY;


        }

        glEnd();

enter image description here


The issue is in the fact that this renders multiple triangle strips. This is a problem for me. My application renders with IDE - code Blocks v17.12 and I need a way to modify the above code so that instead it could look something more like this:

enter image description here

1 Answers

Use the polygon rasterization mode GL_LINE to render a wire frame:

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
float xPos = 0.0f;
float yPos = 0.0f;
float radius = 0.5f;
int steps = 8;
float prevX = xPos;
float prevY = yPos - radius;

glBegin(GL_TRIANGLES);
glColor3f(0.0f, 0.5f, 0.0f);

for (int i=0; i <= step; ++i)
{
    float angle = 3.1415926f * 2.0f * i / step;
    float newX =   radius * sin(angle);
    float newY = - radius * cos(angle);

    glVertex3f(0.0f, 0.0f, 0.0f);
    glVertex3f(prevX, prevY, 0.0f);
    glVertex3f(newX, newY, 0.0f);

    prevX = newX;
    prevY = newY;
}
glEnd();

Use a GL_TRIANGLE_FAN Triangle primitive to simplify your code:

glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.5f, 0.0f);

for (int i=0; i <= step; ++i)
{
    float angle = 3.1415926f * 2.0f * i / step;
    float newX =   radius * sin(angle);
    float newY = - radius * cos(angle);
    glVertex3f(newX, newY, 0.0f);
}
glEnd();

If you want to use a triangle GL_TRIANGLE_STRIP, you must change the order of the vertices:

glBegin(GL_TRIANGLE_STRIP);
glColor3f(0.0f, 0.5f, 0.0f);

for (int i=0; i <= step; ++i)
{
    int strip_i = i % 2 == 0 ? i/2 : step - i/2;
    float angle = 3.1415926f * 2.0f * strip_i / step;
    float newX =   radius * sin(angle);
    float newY = - radius * cos(angle);
    glVertex3f(newX, newY, 0.0f);
}
glEnd();

If you want to render the wire frame on top of the polygon, you need to enable the depth test and render the polygon first. Note the default depth test function is GL_LESS:

for (int pass = 0; pass < 2; ++pass)
{
    if (pass == 0)
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glColor3f(1.0f, 1.0f, 1.0f);
    }
    else
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glColor3f(0.0f, 0.5f, 0.0f);
    }

    glBegin(GL_TRIANGLE_STRIP);
    for (int i=0; i <= step; ++i)
    {
        int strip_i = i % 2 == 0 ? i/2 : step - i/2;
        float angle = 3.1415926f * 2.0f * strip_i / step;
        float newX =   radius * sin(angle);
        float newY = - radius * cos(angle);
        glVertex3f(newX, newY, 0.0f);
    }
    glEnd();
}

Related