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.