I’ve spent a couple of days, and multiple books, trying to implement picking for multiple 2D shapes. Currently however I only have one shape, and I’ve been trying to make it so that you can click and drag the shape around the canvas.
My problem is that, after multiple attempts, I always arrive at a situation where clicking and dragging anywhere moves the shape, rather than only if you click within the area of the shape.
Could someone please take a quick look at my code to see if theres an obvious mistake I’m making. I would be very thankful.
The main/canvas class:
#include <cstdlib>
#include <gl/glut.h>
#include "TableComponent.h"
#define SIZE 512
using namespace std;
int w = 250, h = 250;
float ratio = 1.0;
unsigned char buttons[2] = {0};
float mouseX, mouseY = 0;
TableComponent *t = new TableComponent(556, 100,100, 50, 50);
bool check = false;
GLuint selectBuf[SIZE];
GLint hits;
int mode = GL_RENDER;
void glEnable2D()
{
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
void glDisable2D()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}
void reshape(int width, int height)
{
w = width;
h = height;
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void startPicking()
{
GLint viewport[4];
glSelectBuffer(SIZE,selectBuf);
glGetIntegerv(GL_VIEWPORT,viewport);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(mouseX,viewport[3]-mouseY,1,1,viewport);
glOrtho(0, viewport[2], 0, viewport[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glInitNames();
glPushName(0);
}
void processHits(GLint hits, GLuint buffer[])
{
unsigned int i, j;
GLuint names, *ptr;
ptr = (GLuint *) buffer;
for (i= 0; i < hits; i++)
{
names = *ptr;
ptr += 3;
for (j = 0; j < names; j++)
{
if (*ptr == t->getName())
{
check = true;
}
else
{
check = false;
}
ptr++;
}
}
}
void stopPicking()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glFlush();
hits = glRenderMode(GL_RENDER);
if (hits != 0){
processHits(hits,selectBuf);
}
mode = GL_RENDER;
}
void display()
{
//display crap
glClear(GL_COLOR_BUFFER_BIT);
if (mode == GL_SELECT)
{
startPicking();
}
glEnable2D();
t->draw(mode);
glDisable2D();
if (mode == GL_SELECT)
{
stopPicking();
}
else
{
glutSwapBuffers();
glFlush();
}
}
void mouseResponse(int button, int state, int xPos, int yPos)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
mouseX = xPos;
mouseY = yPos;
buttons[0] = 1;
mode = GL_SELECT;
}
else if (state == GLUT_UP)
{
buttons[0] = 0;
}
glutPostRedisplay();
}
void mouseMotion(int x, int y)
{
if( buttons[0] && check == true )
{
float xDiff = (x - mouseX); // how far the mouse has moved horizontally
float yDiff = (mouseY - y); // how far the mouse has moved vertically
mouseX = x;
mouseY = y;
int testx = t->getX();
int testy = t->getY();
t->setX((testx + (float) xDiff));
t->setY((testy + (float) yDiff));
}
glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100); // set the window's position
glutInitWindowSize(w,h); // set the size of the window
glutCreateWindow("Tabletop Interface");
init();
//glutFullScreen(); // set the display to fullscreen
glutDisplayFunc(display); // our display function
glutReshapeFunc(reshape); // called when we resize the window
//glutKeyboardFunc(keyboard); // called when a key is pressed
glutMouseFunc(mouseResponse);
glutMotionFunc(mouseMotion);
// start the main loop
glutMainLoop();
return(0);
}
The object/square class:
#include "TableComponent.h"
TableComponent::TableComponent(int id, int w, int h, int xPos, int yPos)
{
name = id;
width = w;
height = h;
x = xPos;
y = yPos;
}
TableComponent::TableComponent()
{
}
void TableComponent::draw(GLenum mode)
{
if (mode == GL_SELECT) glLoadName(name);
glTranslatef(x,y,0);
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glVertex2d(0, 0);
glVertex2d(0, height);
glVertex2d(width, height);
glVertex2d(width, 0);
glEnd();
}
void TableComponent::setX(int xPos)
{
x = xPos;
}
void TableComponent::setY(int yPos)
{
y = yPos;
}
int TableComponent::getX()
{
return x;
}
int TableComponent::getY()
{
return y;
}
int TableComponent::getName()
{
return name;
}