Ho messo assieme un piccolo esempio per realizzare il picking su tre cubi in modo da cambiare colore al cubo cliccato, è un file unico compilabile come applicativo per Windows.

codice:
#include <windows.h>
#include <math.h>

#include <GL/gl.h> 
#include <GL/glu.h> 
#include <GL/glaux.h>

#define MAXFLT 3.402823466e+38F // Maximum value for the float type.


HDC   ghDC;
HGLRC ghRC;

CHAR  szAppName[] = "Picking";

static LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM); 


typedef struct
{
	GLdouble	x,y,z;	
} Posit; // New type for XYZ position.

typedef struct
{
	GLdouble	R,G,B;	
} Color; // New type for RGB color.

struct
{
	GLdouble fovy, ratio, zNear, zFar;
} Cam; // Camera properties.

struct
{
	GLdouble x,y,z;
} Rot; // Rotation

typedef struct
{
	GLint	id;
	Posit	pos;
	Color	clr;
	void	(*RenderObj)(GLint, void*);	// Rendering procedure.
} Obj; // New tuype for graphic obj in the scene.

#define nObjs 3

Obj obj[nObjs];

GLdouble deepz;   // Deep in the scene.
GLint selected;     // Currently selected object id.


static void RenderAxes(void)
{
	glColor3f(1,0,0);
	glBegin(GL_LINES);
		glVertex3i(0,0,0);
		glVertex3i(2,0,0);
	glEnd();
	glColor3f(0,1,0);
	glBegin(GL_LINES);
		glVertex3i(0,0,0);
		glVertex3i(0,2,0);
	glEnd();
	glColor3f(0,0,1);
	glBegin(GL_LINES);
		glVertex3i(0,0,0);
		glVertex3i(0,0,2);
	glEnd();
}


static void Cube(GLint mode, void* pobj)
{
	if(mode == GL_RENDER)
	{
		glColor3f(1,1,1);
		auxWireCube(1.01);
	}

	Obj *p = pobj;
	if (p->id == selected) glColor3f(1.0, 1.0, 0.0);
	else glColor3f(p->clr.R, p->clr.G, p->clr.B);
	auxSolidCube(1.0);
}


static void DrawScene(GLint mode)
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslated(0, 0, deepz);
	glRotated(Rot.x, 1,0,0);
	glRotated(Rot.y, 0,1,0);
	glRotated(Rot.z, 0,0,1);

	RenderAxes();

	for(int i=0; i<nObjs; i++)
	{
		glPushMatrix();
			glTranslated(obj[i].pos.x,obj[i].pos.y,obj[i].pos.z);

			if(mode == GL_SELECT)	
				glPushName(obj[i].id);

			obj[i].RenderObj(mode, &obj[i]);

			if(mode == GL_SELECT)
				glPopName();
		glPopMatrix();
	}
}


void SizeView(int w, int h)
{
	glViewport(0, 0, w, h);
	Cam.ratio = (GLfloat)w/(GLfloat)h;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(Cam.fovy, Cam.ratio, Cam.zNear, Cam.zFar);
	DrawScene(GL_RENDER);
}


void Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	DrawScene(GL_RENDER);
	SwapBuffers(ghDC);
}


GLint ProcessHits(GLint hits, GLuint selBuf[])
{
	GLuint	names;
	GLint	nearest = -1;
	GLfloat	minz;
	GLfloat	depth = MAXFLT;
	GLuint * ptr = selBuf;

	for (int i=0; i<hits; i++)
	{
		names = *ptr++;
		minz = *ptr++;		
		ptr++;

		for (int j=0; j<names; j++)
		{ 
			if (minz < depth)
			{
				depth = minz;
				nearest = *ptr; 
			}
			ptr++;
		}
	}

	return nearest;
}


#define	BUFSIZE	512
GLuint HitTest(int x, int y)
{
	GLint	hits;
	GLint	viewport[4];
	GLuint	nearest = -1;
	GLuint	selectBuf[BUFSIZE];
	
	glGetIntegerv(GL_VIEWPORT, viewport);
	glSelectBuffer(BUFSIZE, selectBuf);
	glRenderMode(GL_SELECT);
	
	glInitNames();
	
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
		glLoadIdentity();
		gluPickMatrix((GLdouble)x, (GLdouble)(viewport[3] - y), 3.0, 3.0, viewport);
		gluPerspective(Cam.fovy, Cam.ratio, Cam.zNear, Cam.zFar);
			
			DrawScene(GL_SELECT);

		glMatrixMode(GL_PROJECTION);
	glPopMatrix();

	glFlush();
	hits = glRenderMode(GL_RENDER);

	return ProcessHits(hits, selectBuf);
}


void InitView(void)
{
	Cam.fovy = 45;
	Cam.ratio = 1.5;
	Cam.zNear = 1;
	Cam.zFar = 1000;

	Rot.x = 15.0;
	Rot.y = -15.0;

	deepz = -10.0;
	selected = -1;

	for(int i = 0 ; i < nObjs ; i++)
	{
			obj[i].id = i;
	}

	obj[0].pos.x = 1.0;
	obj[0].pos.y = 1.5;
	obj[0].pos.z = -1.0;

	obj[0].clr.R = 0.0;
	obj[0].clr.G = 0.6;
	obj[0].clr.B = 0.0;

		obj[0].RenderObj = Cube;


	obj[1].pos.x = 1.5;
	obj[1].pos.y = 1.0;
	obj[1].pos.z = 1.5;

	obj[1].clr.R = 0.8;
	obj[1].clr.G = 0.0;
	obj[1].clr.B = 0.2;

		obj[1].RenderObj = Cube;


	obj[2].pos.x = -1.0;
	obj[2].pos.y = 0.5;
	obj[2].pos.z = 0.0;

	obj[2].clr.R = 0.2;
	obj[2].clr.G = 0.0;
	obj[2].clr.B = 0.8;

		obj[2].RenderObj = Cube;


	glClearColor(0.0, 0.0, 0.0, 0.0);

	glEnable(GL_DEPTH_TEST);
}

BOOL bSetupPixelFormat(HDC hdc) 
{ 
    PIXELFORMATDESCRIPTOR pfd = 
   { 
       sizeof(PIXELFORMATDESCRIPTOR), 
       1, 
       PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
       PFD_TYPE_RGBA, 
       24, 
       0, 0, 0, 0, 0, 0, 
       0, 0, 0, 
       0, 0, 0, 0, 
       32, 0, 0, 
       PFD_MAIN_PLANE, 
       0, 0, 0, 0 
   };

    GLint pixelformat = ChoosePixelFormat(hdc, &pfd); 

    if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0 ) 
		return FALSE; 

    if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE) 
		return FALSE; 

    return TRUE; 
} 


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
	MSG		msg;
	HWND  		hWnd;
	WNDCLASS	wndclass;

    wndclass.style         = 0; 
    wndclass.lpfnWndProc   = (WNDPROC)MainWndProc; 
    wndclass.cbClsExtra    = 0; 
    wndclass.cbWndExtra    = 0; 
    wndclass.hInstance     = hInstance; 
    wndclass.hIcon         = LoadIcon (hInstance, szAppName); 
    wndclass.hCursor       = LoadCursor (NULL,IDC_ARROW); 
    wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
    wndclass.lpszMenuName  = szAppName; 
    wndclass.lpszClassName = szAppName;  
    if (!RegisterClass (&wndclass) ) 
        return FALSE; 
 
    hWnd = CreateWindow (szAppName,
                          szAppName,
                          WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          NULL,
                          NULL,
                          hInstance,
                          NULL);
 
    if (!hWnd) 
        return FALSE; 
 
    ShowWindow (hWnd, nCmdShow); 
    UpdateWindow (hWnd); 
 
    while(GetMessage(&msg,NULL,0,0))
    {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}

 
static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{
    LONG lRet = 1;

    switch (uMsg) 
    { 
 
    case WM_CREATE: 
        ghDC = GetDC(hWnd);
        if (!bSetupPixelFormat(ghDC))
        			PostQuitMessage (0);
        ghRC = wglCreateContext(ghDC);
        wglMakeCurrent(ghDC, ghRC);
		InitView();
        break;

	case WM_SIZE:
		SizeView(LOWORD(lParam),HIWORD(lParam));
		InvalidateRect(hWnd, NULL, FALSE);
		break;

    case WM_PAINT:
		Display();
        break;

	case WM_ERASEBKGND:
		InvalidateRect(hWnd,NULL,FALSE);
		break;

	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;

    case WM_DESTROY:
        if (ghRC) wglDeleteContext(ghRC);
        if (ghDC) ReleaseDC(hWnd, ghDC);
        PostQuitMessage (0);
        break;

	case WM_LBUTTONDOWN:
		selected = HitTest(LOWORD(lParam), HIWORD(lParam));
		InvalidateRect(hWnd, NULL, FALSE);
		break;

	case WM_LBUTTONUP:
		InvalidateRect(hWnd, NULL, FALSE);
		break;

	case WM_KEYDOWN:

		switch (wParam)
		{ 

		case VK_UP: 
			Rot.x -= 1%360;
			InvalidateRect(hWnd,NULL,FALSE);
			break; 

		case VK_DOWN: 
			Rot.x += 1%360;
			InvalidateRect(hWnd,NULL,FALSE);
			break;
			
		case VK_LEFT: 
			Rot.y -= 1%360;
			InvalidateRect(hWnd,NULL,FALSE);
			break; 

		case VK_RIGHT: 
			Rot.y += 1%360;
			InvalidateRect(hWnd,NULL,FALSE);
			break;
        }
	
    default: 
        lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); 
        break; 
    } 
 
    return lRet; 
}
Come vedi dal codice, con i tasti "freccia" si ruota la vista.
Dovrebbe compilare senza problemi anche su un compilatore C.