PDA

View Full Version : Creating a square where I am able to drag one corner



spearsboy
02-11-2015, 09:42 PM
Hi there,

I am a total beginner to coding.

Is there any existing Open GL Glut code which allows One corner of the square to move when you click and drag the mouse around
inside the window. The corner should follow the mouse pointer

Agent D
02-12-2015, 12:41 AM
Handling mouse clicks, etc. is not part of OpenGL(R). The OpenGL(R) specification onyl specifies an abstract API for rasterization based rendering.

Managing a window and handling mouse clicks has to be done over platform dependend functions. In your case, that should be abstracted away by
the GLUT library.

What you would do is simply registering a GLUT callback that receives mouse events (Please refere to the GLUT documentation for that). If you have
the click position in window coordinates, and the rectangle vertices in window coordinates (or you could convert the click window coordinates to the
coordinate space the rect is in), you can determine a distance of the click position to the vertices and if that distance is below a certain threshold, you
assume a vertex has been clicked. Once a vertex has been clicked, apply a scaled relative movement of the mouse cursor to the selected vertex.

spearsboy
02-15-2015, 12:40 AM
Hi, I am still trying things out, but can't really figure out that much. This is what i got below

#include <GL/glut.h>

void init()
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}


void mydisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
}

void OnMouseClick(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
void glscalef(GLfloat x, GLfloat y, GLfloat z);
}
}

static void
key(unsigned char key, int x, int y)
{
switch (key)
case 27:
exit(0);
}

int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(0,0);
glutCreateWindow("simple");
glutDisplayFunc(mydisplay);
glutKeyboardFunc(key);
init();
glutMainLoop();
}

Agent D
02-15-2015, 04:20 AM
First of all, that code shouldn't even compile. You have a function declaration inside your OnMouseClick function.

Second, what was that code intended to do? Scale the polygon when the mouse button is pressed?

The solution I suggested above would store the vertices of the polygon in variables. When the mouse button is pressed, your OnMouseClick function
would determine the closest vertex to the mouse cursor is flagged as being draged. When the mouse button is released, all drag flags are cleared.

In an additional mouse movement callback would add the scaled mouse movement (difference between current and previous mouse position) to the
vertex that is flagged as being draged.

spearsboy
02-15-2015, 09:01 AM
Yea I intended for the on mouseclick to scale the square when the edges are dragged with a mouse click.

Could you guide me a little on what variable I should use to store vertices and do the drag? I understand what you are saying with regards to how it should work, but I am just not sure what I should use even with the documentation. Thanks for the feedback thus far

Agent D
02-16-2015, 12:16 AM
That doesn't make sense. Scaling means multiplying it by some factor. That is something completely different than moving one corner.

What I had in mind was something like this:

struct
{
float x;
float y;
}
vertices[4];

int dragging = -1;
....

void mydisplay()
{
unsigned int i;

glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
for( i=0; i<sizeof(vertices)/sizeof(vertices[0]); ++i )
glVertex2f(vertices[i].x, vertices[i].y);
glEnd();
glFlush();
}

....

void OnMouseClick(int button, int state, int x, int y)
{
unsigned int i;

if( button != GLUT_LEFT_BUTTON )
return;

dragging = -1;

if( state == GLUT_DOWN)
{
for( i=0; i<sizeof(vertices)/sizeof(vertices[0]); ++i )
{
dist = distance( vertices[i], x, y );
if( dist < threshold )
{
dragging = i;
break;
}
}
}
}
....
void OnMouseMove( int x, int y )
{
static int prev_x=0, prev_y=0;

if( dragging >= 0)
{
dx = scale_somewhat_x( x - prev_x );
dy = scale_somewhat_y( y - prev_y );

vertices[dragging].x += dx;
vertices[dragging].y += dy;
}

prev_x = x;
prev_y = y;
}

The Little Body
02-16-2015, 03:40 PM
Here is a simple version that move only the first corner with the initial position (-0.5f, -0.5f)



#include <stdio.h>
#include <GL/glut.h>

GLuint width = 500;
GLuint height = 500;

GLfloat xcorner = -0.5f;
GLfloat ycorner = -0.5f;

int bMoving = 0;

void Screen2GLpos(int x, int y, GLfloat *xpos, GLfloat *ypos)
{
*xpos = ((GLfloat)(x) - (GLfloat)(width/2)) / (GLfloat)(width/2);
*ypos = ((GLfloat)(-y) + (GLfloat)(height/2)) / (GLfloat)(height/2);
printf("Transform Screen position (%d,%d) to OpenGL position (%.3f,%.3f) \n", x, y, *xpos, *ypos);
}

void OnInit()
{
glClearColor (0.0, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}


void OnDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(xcorner, ycorner);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
}



void OnMouseClick(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON )
{
if( state == GLUT_DOWN)
{
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xcorner, &ycorner);
glutPostRedisplay();
bMoving = 1;
}
else
{
bMoving = 0;
}
}
}

void OnMouseMove(int x, int y)
{
if( bMoving )
{
printf("OnMouseMove : x=%d y=%d \n", x, y);
Screen2GLpos(x,y, &xcorner, &ycorner);
glutPostRedisplay();
}
}



static void OnKey(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
}
}

int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(width,height);
glutInitWindowPosition(0,0);
glutCreateWindow("simple");


OnInit();
glutDisplayFunc(OnDisplay);
glutKeyboardFunc(OnKey);
glutMouseFunc(OnMouseClick);
glutMotionFunc(OnMouseMove);


glutMainLoop();

return 0;
}


If you want to select another corner, you have to extend it for to select the good corner point because this code handle only the moving of the first corner

The Little Body
02-16-2015, 04:45 PM
This version select automatically the nearest corner and handle the resizing of the window



#include <stdio.h>
#include <GL/glut.h>

typedef struct
{
GLfloat x;
GLfloat y;
}vertice_t;


GLuint width = 500;
GLuint height = 500;

vertice_t quad[4];

int bMoving = 0;

int corner = 0;


void InitQuad()
{
quad[0].x = -0.5f;
quad[0].y = -0.5f;

quad[1].x = -0.5f;
quad[1].y = 0.5f;


quad[2].x = 0.5f;
quad[2].y = 0.5f;


quad[3].x = 0.5f;
quad[3].y = -0.5f;
}

void Screen2GLpos(int x, int y, GLfloat *xpos, GLfloat *ypos)
{
*xpos = ((GLfloat)(x) - (GLfloat)(width/2)) / (GLfloat)(width/2);
*ypos = ((GLfloat)(-y) + (GLfloat)(height/2)) / (GLfloat)(height/2);
printf("Transform Screen position (%d,%d) to OpenGL position (%.3f,%.3f) \n", x, y, *xpos, *ypos);
}

int BestCorner(float x, float y)
{
int i, idx = -1;
float dist2, bestdist2 = 1000000;

for( i = 0 ; i < 4 ; i++)
{
dist2 = (x - quad[i].x) * (x - quad[i].x) + (y - quad[i].y) * (y - quad[i].y);
if( dist2 < bestdist2 )
{
bestdist2 = dist2;
idx = i;
}
}

return idx;
}

void OnInit()
{
InitQuad();

glClearColor (0.0, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}


void OnDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(quad[0].x, quad[0].y);
glVertex2f(quad[1].x, quad[1].y);
glVertex2f(quad[2].x, quad[2].y);
glVertex2f(quad[3].x, quad[3].y);
glEnd();
glFlush();
}



void OnMouseClick(int button, int state, int x, int y)
{
float xmousef, ymousef;
int corner;

if (button == GLUT_LEFT_BUTTON )
{
if( state == GLUT_DOWN)
{
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
bMoving = 1;
}
else
{
bMoving = 0;
}
}
}

void OnMouseMove(int x, int y)
{
GLfloat xmousef, ymousef;

if( bMoving )
{
printf("OnMouseMove : x=%d y=%d \n", x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
}
}



static void OnKey(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
}
}

static void OnResize(int w, int h)
{
int i;

printf("Onresize(%d,%d) \n", w, h);

width = w;
height = h;

glViewport (0, 0, (GLsizei)w, (GLsizei)h);

glutPostRedisplay();
}


int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(width,height);
glutInitWindowPosition(0,0);
glutCreateWindow("simple");


OnInit();
glutDisplayFunc(OnDisplay);
glutKeyboardFunc(OnKey);
glutMouseFunc(OnMouseClick);
glutMotionFunc(OnMouseMove);
glutReshapeFunc(OnResize);


glutMainLoop();

return 0;
}

spearsboy
02-17-2015, 08:16 AM
thanks guys, I tried adding alittle more to your code 'The Little Body'. I wanted to add a function to allow you to press for example the key F1 to move a certain corner of the square just like the mouse click did.


#include <stdio.h>
#include <GL/glut.h>

typedef struct
{
GLfloat x;
GLfloat y;
}vertice_t;


GLuint width = 500;
GLuint height = 500;

vertice_t quad[4];

int bMoving = 0;

int corner = 0;


void InitQuad()
{
quad[0].x = -0.5f;
quad[0].y = -0.5f;

quad[1].x = -0.5f;
quad[1].y = 0.5f;


quad[2].x = 0.5f;
quad[2].y = 0.5f;


quad[3].x = 0.5f;
quad[3].y = -0.5f;
}

void Screen2GLpos(int x, int y, GLfloat *xpos, GLfloat *ypos)
{
*xpos = ((GLfloat)(x) - (GLfloat)(width/2)) / (GLfloat)(width/2);
*ypos = ((GLfloat)(-y) + (GLfloat)(height/2)) / (GLfloat)(height/2);
printf("Transform Screen position (%d,%d) to OpenGL position (%.3f,%.3f) \n", x, y, *xpos, *ypos);
}

int BestCorner(float x, float y)
{
int i, idx = -1;
float dist2, bestdist2 = 1000000;

for( i = 0 ; i < 4 ; i++)
{
dist2 = (x - quad[i].x) * (x - quad[i].x) + (y - quad[i].y) * (y - quad[i].y);
if( dist2 < bestdist2 )
{
bestdist2 = dist2;
idx = i;
}
}

return idx;
}

void OnInit()
{
InitQuad();

glClearColor (0.0, 0.0, 0.0, 1.0);
glColor3f(0.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}


void OnDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(quad[0].x, quad[0].y);
glVertex2f(quad[1].x, quad[1].y);
glVertex2f(quad[2].x, quad[2].y);
glVertex2f(quad[3].x, quad[3].y);
glEnd();
glFlush();
}



void OnMouseClick(int button, int state, int x, int y)
{
float xmousef, ymousef;
int corner;

if (button == GLUT_LEFT_BUTTON )
{
if( state == GLUT_DOWN)
{
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
bMoving = 1;
}
else
{
bMoving = 0;
}
}
}

void OnMouseMove(int x, int y)
{
GLfloat xmousef, ymousef;

if( bMoving )
{
printf("OnMouseMove : x=%d y=%d \n", x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
}
}



static void OnKey(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
}
}

void glutSpecialFunc(int button, int state, int x, int y)
{
float xmousef, ymousef;
int corner;

if switch (key)
{
{case GLUT_KEY_F1 :
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
bMoving = 1;

case GLUT_KEY_F2 :
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
bMoving = 1;

case GLUT_KEY_F3 :
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
bMoving = 1;

case GLUT_KEY_F4 :
printf("button=%d state=%d x=%d y=%d \n", button, state, x, y);
Screen2GLpos(x,y, &xmousef, &ymousef);
corner = BestCorner(xmousef, ymousef);
quad[corner].x = xmousef;
quad[corner].y = ymousef;
glutPostRedisplay();
bMoving = 1;
}
else
{
bMoving = 0;
}
}


static void OnResize(int w, int h)
{
int i;

printf("Onresize(%d,%d) \n", w, h);

width = w;
height = h;

glViewport (0, 0, (GLsizei)w, (GLsizei)h);

glutPostRedisplay();
}


int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(width,height);
glutInitWindowPosition(0,0);
glutCreateWindow("simple");


OnInit();
glutDisplayFunc(OnDisplay);
glutKeyboardFunc(OnKey);
glutMouseFunc(OnMouseClick);
glutMotionFunc(OnMouseMove);
glutReshapeFunc(OnResize);


glutMainLoop();

return 0;
}


Am I putting the glutSpecialFunc in the right manner?