Is opengl convert gl_polygon to triangles ?

Dear Experts,

Im drawing a semi circled image with texture mapping. When I rendered using GL_POLYGON, I found circular shape is changed to straight line.


http://tinyurl.com/2c77ses

This is the outline of semicircle. I want texture mapping for this shape. Ie,entire texture should be mapped to the semi circle. When GL_POLYGON is used to render the texture mapped image, semi circle shape is changed. The outer curve is changed to a straight line and one triange is drawn. From the image I suspect opengl convert the polygon into a triangle

http://tinyurl.com/29lkstl

Source code,
#include “stdAfx.h”
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include “resource.h”
#include “math.h”

//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
HWND g_hWnd = NULL;
HDC g_hDC = NULL;
HGLRC g_hRC = NULL;
GLuint g_textureID = -1;

#define WIDTH 2500.0f
#define HEIGHT 2500.0f

struct Vertex
{
// GL_T2F_V3F
float tu, tv;
float x, y, z;
};

Vertex* MyVertex;

//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void loadTexture(void);
void init(void);
void render(void);
void shutDown(void);

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application’s entry point
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
WNDCLASSEX winClass;
MSG uMsg;

memset(&uMsg,0,sizeof(uMsg));

winClass.lpszClassName = "MY_WINDOWS_CLASS";
winClass.cbSize        = sizeof(WNDCLASSEX);
winClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
winClass.lpfnWndProc   = WindowProc;
winClass.hInstance     = hInstance;
winClass.hIcon	       = LoadIcon(hInstance, (LPCTSTR)IDI_OPENGL_ICON);
winClass.hIconSm	   = LoadIcon(hInstance, (LPCTSTR)IDI_OPENGL_ICON);
winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName  = NULL;
winClass.cbClsExtra    = 0;
winClass.cbWndExtra    = 0;

if( !RegisterClassEx(&winClass) )
	return E_FAIL;

g_hWnd = CreateWindowEx( NULL, "MY_WINDOWS_CLASS", 
                         "OpenGL - Texturing",
					     WS_OVERLAPPEDWINDOW | WS_VISIBLE,
				         0, 0, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL );

if( g_hWnd == NULL )
	return E_FAIL;

ShowWindow( g_hWnd, nCmdShow );
UpdateWindow( g_hWnd );

init();

while( uMsg.message != WM_QUIT )
{
	if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
	{
		TranslateMessage( &uMsg );
		DispatchMessage( &uMsg );
	}
    else
		render();
}

shutDown();

UnregisterClass( "MY_WINDOWS_CLASS", hInstance );

return uMsg.wParam;

}

//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: The window’s message handler
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
switch( msg )
{
case WM_KEYDOWN:
{
switch( wParam )
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
}
break;

	case WM_SIZE:
	{
		int nWidth  = LOWORD(lParam); 
		int nHeight = HIWORD(lParam);
		glViewport(0, 0, nWidth, nHeight);

		glMatrixMode( GL_PROJECTION );
		glLoadIdentity();
		gluPerspective( 45.0, (GLdouble)nWidth / (GLdouble)nHeight, 0.1, 100.0);
	}
	break;

	case WM_CLOSE:
	{
		PostQuitMessage(0);	
	}

    case WM_DESTROY:
	{
        PostQuitMessage(0);
	}
    break;
	
	default:
	{
		return DefWindowProc( hWnd, msg, wParam, lParam );
	}
	break;
}

return 0;

}

//-----------------------------------------------------------------------------
// Name: loadTexture()
// Desc:
//-----------------------------------------------------------------------------
void loadTexture(void)
{
AUX_RGBImageRec *pTextureImage = auxDIBImageLoad( “.\woodfloor.bmp” );

if( pTextureImage != NULL )
{
    glGenTextures( 1, &g_textureID );

	glBindTexture( GL_TEXTURE_2D, g_textureID );

	glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR );

	glTexImage2D( GL_TEXTURE_2D, 0, 3, pTextureImage-&gt;sizeX, pTextureImage-&gt;sizeY, 0,
			GL_RGB, GL_UNSIGNED_BYTE, pTextureImage-&gt;data );
}

if( pTextureImage )
{
	if( pTextureImage-&gt;data )
		free( pTextureImage-&gt;data );

	free( pTextureImage );
}

}
int nNumLines = 100;
//-----------------------------------------------------------------------------
// Name: init()
// Desc:
//-----------------------------------------------------------------------------
void init( void )
{
GLuint PixelFormat;

PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));

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

g_hDC = GetDC( g_hWnd );
PixelFormat = ChoosePixelFormat( g_hDC, &pfd );
SetPixelFormat( g_hDC, PixelFormat, &pfd);
g_hRC = wglCreateContext( g_hDC );
wglMakeCurrent( g_hDC, g_hRC );

loadTexture();

glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glEnable( GL_TEXTURE_2D );

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45.0f, WIDTH / HEIGHT, 0.1f, 100.0f);


MyVertex = new Vertex[nNumLines * 2+ 2];

Vertex* MyVertexBottom = new Vertex[nNumLines];
Vertex* MyVertexTop = new Vertex[nNumLines];

int Radius[2] = {150,350};
int CenterY = 0;
int CenterX = 0;
float PI = 3.14;
double dStartAngle = 100;
for( int nLineIndex = 0; nLineIndex &lt; nNumLines; ++nLineIndex )
{
	double dAngValue = dStartAngle + ( double )nLineIndex * ( PI / 180.0 );
	for ( int nColIndex = 0; nColIndex &lt; 2; ++nColIndex )
	{
		double XValue = Radius[ nColIndex ] * cos( dAngValue ) + CenterX;
		double YValue = Radius[ nColIndex ] * sin( dAngValue ) + CenterY;

		XValue /= 350;
		YValue /= 350;

		TRACE( "XValue:%f YValue:%f

", XValue ,YValue );

		if( nColIndex == 0 )
		{
			MyVertexTop[nLineIndex].x = XValue;
			MyVertexTop[nLineIndex].y = YValue;
			MyVertexTop[nLineIndex].z = 0.0;
			MyVertexTop[nLineIndex + nColIndex].tu = nColIndex;
			MyVertexTop[nLineIndex].tv = (float)nLineIndex / nNumLines;
		}
		else
		{
			MyVertexBottom[nLineIndex ].x = XValue;
			MyVertexBottom[nLineIndex ].y = YValue;
			MyVertexBottom[nLineIndex ].z = 0.0;
			MyVertexBottom[nLineIndex ].tu = nColIndex;
			MyVertexBottom[nLineIndex ].tv = (float)nLineIndex / nNumLines;
		}

		
	}
}

int nCount = 0;
// Adding Top points to Vertex array.
for( int n =0; n&lt; nNumLines; n++ )
{
	MyVertex[nCount].x = MyVertexTop[n].x;
	MyVertex[nCount].y = MyVertexTop[n].y;
	MyVertex[nCount].z = MyVertexTop[n].z;
	MyVertex[nCount].tu = MyVertexTop[n].tu;
	MyVertex[nCount].tv = MyVertexTop[n].tv;
	nCount++;
}

// Connecting top points and bottom points.
MyVertex[nCount].x = MyVertexTop[nNumLines -1].x;
MyVertex[nCount].y = MyVertexTop[nNumLines -1].y;
MyVertex[nCount].z = MyVertexTop[nNumLines -1].z;
MyVertex[nCount].tu = MyVertexTop[nNumLines -1].tu;
MyVertex[nCount].tv = MyVertexTop[nNumLines -1].tv;
nCount++;


// Adding bottom points.
for( int n =0; n&lt; nNumLines; n++ )
{
	MyVertex[nCount].x = MyVertexBottom[nNumLines -1 - n].x;
	MyVertex[nCount].y = MyVertexBottom[nNumLines -1 - n].y;
	MyVertex[nCount].z = MyVertexBottom[nNumLines -1 - n].z;
	MyVertex[nCount].tu = MyVertexBottom[nNumLines -1 - n].tu;
	MyVertex[nCount].tv = MyVertexBottom[nNumLines -1 - n].tv;
	nCount++;
}

// Connecting bottom point and and top point.
MyVertex[nCount].x = MyVertexTop[0].x;
MyVertex[nCount].y = MyVertexTop[0].y;
MyVertex[nCount].z = MyVertexTop[0].z;
MyVertex[nCount].tu = MyVertexTop[0].tu;
MyVertex[nCount].tv = MyVertexTop[0].tv;
nCount++;

}

//-----------------------------------------------------------------------------
// Name: shutDown()
// Desc:
//-----------------------------------------------------------------------------
void shutDown( void )
{
glDeleteTextures( 1, &g_textureID );

if( g_hRC != NULL )
{
	wglMakeCurrent( NULL, NULL );
	wglDeleteContext( g_hRC );
	g_hRC = NULL;
}

if( g_hDC != NULL )
{
	ReleaseDC( g_hWnd, g_hDC );
	g_hDC = NULL;
}

}

//-----------------------------------------------------------------------------
// Name: render()
// Desc:
//-----------------------------------------------------------------------------
void render( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0f, 0.0f, -4.0f );

//glColor4f(1,1,1,1);
glBindTexture( GL_TEXTURE_2D, g_textureID );
glInterleavedArrays( GL_T2F_V3F, 0, MyVertex );


 // glDrawArrays( GL_POLYGON, 0, nNumLines * 2 + 2  ); 
// Change below line with GL_POLYGON to draw the polygon, You will see the issue.
// I dont know, how the outer circle change to a straight line.
glDrawArrays( GL_LINES, 0, nNumLines * 2 + 2  );

SwapBuffers( g_hDC );

}

How circle is changed to straight line. confusing issue,
Thanks in advance

Your polygon is concave. OpenGL does not like this. Solving this would be a computationally expensive problem for the general case.

In your situation you can draw a triangle strip and simply order outside vert 1, inside vert 1, outside vert 2, inside vert 2, outside vert 3, inside vert 3, etc.

Iris GL used to solve this but it was SLOW, OpenGL could solve it but would be SLOW unless it was display listed or the data were marked as non-volatile using a VBO.

So really this feature keeps the pipeline efficient, triangulation of comcave and other complex polygons is something best left to applications (although an API like OpenGV supports it).

There are also image based approaces to solcving this using the stencil buffer…

Thanks dorbie,
Now its working with triangle strip.