I have open gl rendering in a static window within my form. The code to pick the objects seems to work, but it is offset from where it should be on the y axis being an inch above where the objects are actually drawn. If anyone can see where my problem is I would really appreciate it.
I am adjusting the mouse coordinates in the following way:
case WM_LBUTTONDOWN:
if (wParam==MK_LBUTTON)
{
maininterface.handle_mouse_click((int)LOWORD(lParam), (int)HIWORD(lParam));
}
else
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
then maininterface.handle_mouse_click(..) looks like this
I subtrack 390 from the x position because that is the offset of the static window on the main form.
void windowsinterface::handle_mouse_click(int x, int y)
{
char valc[100]="";
// adjust for window shift (from main)
x = x - 390;
if (x < 0)
return;
itoa(renderwindow.check_collision(x,y),valc, 100);
MessageBox(NULL, valc, "test", MB_OK);
}
Then finally my opengl class (renderwindow object) looks like this.
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
struct line
{
float x1;
float y1;
float x2;
float y2;
int ID;
float r;
float g;
float b;
};
struct quad
{
RECT box;
int ID;
float r;
float g;
float b;
};
class OpenGL
{
public:
OpenGL()
{
m_RC=NULL;
m_DC=NULL;
m_hwnd=NULL;
m_hinstance=NULL;
m_clear_c=0;
m_linecount=0;
m_quadcount=0;
lines=NULL;
quads=NULL;
m_width=0;
m_height=0;
};
~OpenGL();
GLvoid resize_scene(GLsizei width, GLsizei height);
int init(HWND hwnd, int width, int height);
int drawscene(GLvoid);
void render();
void set_clear_color(int val);
void add_line(float x1, float y1, float x2, float y2, int val, float r, float g, float b);
int remove_line(int ID);
void add_quad(quad toadd);
int remove_quad(int ID);
int check_collision(int x, int y);
private:
HGLRC m_RC;
HDC m_DC;
HWND m_hwnd;
HINSTANCE m_hinstance;
int m_clear_c;
int m_linecount;
int m_quadcount;
struct line* lines;
struct quad* quads;
int m_width;
int m_height;
};
OpenGL::~OpenGL()
{
if (m_RC)
{
if (!wglMakeCurrent(NULL, NULL))
{
MessageBox(NULL, "DC and RC release Failed", "SHUTDOWN ERROR", MB_OK | MB_ICONEXCLAMATION);
}
if (!wglDeleteContext(m_RC))
{
MessageBox(NULL, "Rendering Context Release Failed", "SHUTDOWN ERROR", MB_OK | MB_ICONEXCLAMATION);
}
m_RC = NULL;
}
if (m_DC && (!ReleaseDC(m_hwnd, m_DC)))
{
MessageBox(NULL, "Device Context Release Failed", "SHUTDOWN ERROR", MB_OK | MB_ICONEXCLAMATION);
m_DC=NULL;
}
if (m_hwnd)
{
m_hwnd=NULL;
}
}
GLvoid OpenGL::resize_scene(GLsizei width, GLsizei height)
{
if (height==0)
height=1;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int OpenGL::init(HWND hwnd, int width, int height)
{
m_hwnd = hwnd;
m_width = width;
m_height = height;
glShadeModel(GL_SMOOTH);
// set background color to black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// set nice perspective calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// variable for pixle format
GLuint PixelFormat;
// set up pixle format descriptor
static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_TYPE_RGBA,
32, // number of bits
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
// get the device context
if (!(m_DC = GetDC(hwnd)))
{
MessageBox(NULL, "Can't Create a GL Device Context", "ERROR", MB_OK | MB_ICONEXCLAMATION);
delete this;
return 0;
}
// get the pixel format
if (!(PixelFormat=ChoosePixelFormat(m_DC, &pfd)))
{
MessageBox(NULL, "Can't find a Suitable Pixel Format Check that 32 bit color is enabled", "ERROR", MB_OK | MB_ICONEXCLAMATION);
delete this;
return 0;
}
// set the pixel format
if (!SetPixelFormat(m_DC, PixelFormat, &pfd))
{
MessageBox(NULL, "Can't Set the Pixel Format", "ERROR", MB_OK | MB_ICONEXCLAMATION);
delete this;
return 0;
}
// get the render context
if (!(m_RC=wglCreateContext(m_DC)))
{
MessageBox(NULL, "Can't Create a GL Rendering Context", "ERROR", MB_OK | MB_ICONEXCLAMATION);
delete this;
return 0;
}
// activate render context
if (!(wglMakeCurrent(m_DC, m_RC)))
{
MessageBox(NULL, "Can't Activate GL Rendering Context", "ERROR", MB_OK | MB_ICONEXCLAMATION);
delete this;
return 0;
}
resize_scene(width, height);
drawscene();
return 1;
}
int OpenGL::drawscene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
gluLookAt(0,0,3, 0,0,0, 0,1,0);
glInitNames();
if (m_quadcount)
{
for (int i=0; i<m_quadcount+1;i++)
{
glLoadName(quads.ID);
glBegin(GL_QUADS);
glColor3f(quads.r, quads.g, quads.b);
glVertex3d(quads.box.left, quads.box.top,0);
glVertex3d(quads.box.right, quads.box.top,0);
glVertex3d(quads.box.right, quads.box.bottom,0);
glVertex3d(quads.box.left, quads.box.bottom,0);
glEnd();
}
}
if (m_linecount)
{
for (int i=0; i<m_linecount+1;i++)
{
glLoadName(lines.ID);
glBegin(GL_LINES);
glColor3f(lines.r, lines.g, lines.b);
glVertex2d(lines.x1, lines.y1);
glVertex2d(lines.x2, lines.y2);
glEnd();
}
}
glPopMatrix();
glFlush();
return 1;
}
void OpenGL::render()
{
drawscene();
SwapBuffers(m_DC);
}
void OpenGL::set_clear_color(int val)
{
m_clear_c = val;
if (val==0)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
}
else if (val==1)
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 0.0f);
}
}
void OpenGL::add_line(float x1, float y1, float x2, float y2, int val, float r=0, float g=0, float b=0)
{
lines = (struct line*)realloc(lines, sizeof(line)*(m_linecount+1));
lines[m_linecount].ID = val;
lines[m_linecount].x1 = x1;
lines[m_linecount].y1 = y1;
lines[m_linecount].x2 = x2;
lines[m_linecount].y2 = y2;
lines[m_linecount].r = r;
lines[m_linecount].g = g;
lines[m_linecount].b = b;
m_linecount++;
}
int OpenGL::remove_line(int ID)
{
int remove_count=0;
for (int i=0; i<m_linecount+1;i++)
{
if (lines.ID == ID)
{
for (int j=i;j<m_linecount+1;j++)
{
lines[j] = lines[j+1];
}
remove_count++;
m_linecount--;
if (m_linecount)
lines = (struct line*)realloc(lines, sizeof(line)*m_linecount);
}
}
return remove_count;
}
void OpenGL::add_quad(quad toadd)
{
quads = (struct quad*)realloc(quads, sizeof(quad)*(m_quadcount+1));
quads[m_quadcount].box = toadd.box;
quads[m_quadcount].ID = toadd.ID;
quads[m_quadcount].r = toadd.r;
quads[m_quadcount].g = toadd.g;
quads[m_quadcount].b = toadd.b;
m_quadcount++;
}
int OpenGL::remove_quad(int ID)
{
int remove_count=0;
for (int i=0;i<m_quadcount+1;i++)
{
if (quads.ID == ID)
{
for (int j=i;j<m_quadcount+1;j++)
{
quads = quads[i+1];
}
remove_count++;
m_quadcount--;
if (m_quadcount)
quads = (struct quad*)realloc(quads, sizeof(quad)*m_quadcount);
}
}
return remove_count;
}
#include <stdio.h>
int OpenGL::check_collision(int x, int y)
{
int objectcount=0;
int viewportcoords[4]= {0};
unsigned int selectbuffer[32] = {0};
// set the select buffer
glSelectBuffer(32, selectbuffer);
// get the coordinates for the viewport
glGetIntegerv(GL_VIEWPORT, viewportcoords);
// switch to project matrix mode
glMatrixMode(GL_PROJECTION);
// push on a new matrix so I don't effect the back buffer
glPushMatrix();
// set the render mode so that what we render isn't actually drawn to screen
glRenderMode(GL_SELECT);
// reset the projection matrix
glLoadIdentity();
// get the projection matrix for the pick region
gluPickMatrix(x, viewportcoords[3]-y, 2, 2, viewportcoords);
// reset the aspect ratio
gluPerspective(45.0f, (GLfloat)(viewportcoords[2]-viewportcoords[0])/(GLfloat)(viewportcoords[3]-viewportcoords[1]), 0.1f, 100.0f);
// change to modelview mode
glMatrixMode(GL_MODELVIEW);
// render
drawscene();
// get the number of objects in the clicked region
objectcount = glRenderMode(GL_RENDER);
// change back to projection matrix
glMatrixMode(GL_PROJECTION);
// pop the projection matrix
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
return objectcount;
}