PDA

View Full Version : Dragging a 2D object with mouse help pls!!



bod2na
07-11-2008, 12:51 AM
Hello, I am very new to opengl.
I succeed to draw something, But now, I need to add some movement. Let me try to explain. I have a code which draws a square on the screen. What I am trying to do is, user will be able to move this square in this gl window by draggin it with mouse left button.
But It does not do exactly right thing. It moves upward when I pull down an moves downward when I try to move it up.
And also it always blinks.
Here is my code:

Draw square func:

void GLWidget::drawQuad(GLfloat xx, GLfloat yy, GLfloat side){

glTranslatef(xx,yy,0.0f); // Move Right 3 Units
SqPoint.setX(200 + 96 * xx);
SqPoint.setY(200 + 96 * yy);
glBegin(GL_QUADS);
glVertex3f(-(side/2), (side/2), 0.0f); // Top Left
glVertex3f( (side/2), (side/2), 0.0f); // Top Right
glVertex3f( (side/2),-(side/2), 0.0f); // Bottom Right
glVertex3f(-(side/2),-(side/2), 0.0f); // Bottom Left
glEnd();
glTranslatef(-xx,-yy,0.0f);
}
My initialize code:

void GLWidget::initializeGL()
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
xCord =0;
yCord = 0;
}

My paintgl code:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(0.0f,0.0f,-10.0f);
qglColor(kareRenk);
drawQuad(xCord,yCord,1);
Mouse event:


void GLWidget::mouseMoveEvent(QMouseEvent *event)
{

GLfloat iy;
GLfloat ix = (event->x() - SqPoint.x())/96;
// if ( event->y()> 200)
iy = ((event->y() - SqPoint.y() )/96);
// else
// iy = (SqPoint.y() - event->y() )/96;

if (event->buttons() & Qt::LeftButton) {
SqPoint.setX (event->x());
SqPoint.setY (event->y());
xCord = ix;
yCord = iy;
updateGL();
} else if (event->buttons() & Qt::RightButton) {

}

}

How can I make this run correct and without blinking??

ZbuffeR
07-11-2008, 02:03 AM
GL default coordinates have positive Y going up. Windowing mouse coordintaes typically have Y going down. Just invert in the mouse event handler.
About the blinking, make sure to request a double-buffered GL context, and call swapbuffers at the end of your paintgl code.

dletozeun
07-11-2008, 02:05 AM
But It does not do exactly right thing. It moves upward when I pull down an moves downward when I try to move it up.


This should because with opengl the screen coordinates origin is a the bottom left corner of the screen.
you can resolve this problem taking screen_height - mouseY instead of mouseY.
Another solution is setting orthographic projection like this:



/**
* @brief Sets the orthographic projection to draw 2D objects. Here it is used to display texts on the screen.
* Note that origin is the upper left corner and coordinates unit is the pixel.
*/
void setOrthographicProjection()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// set a 2D orthographic projection
gluOrtho2D(0, w, 0, h);
// invert the y axis, down is positive
glScalef(1, -1, 1);
// mover the origin from the bottom left corner
// to the upper left corner
glTranslatef(0, -h, 0);
glMatrixMode(GL_MODELVIEW);
}




And also it always blinks.


How do you create the window. Is double buffering enabled?

bod2na
07-11-2008, 02:15 AM
I solved the blinking problem and the wrong way problem. But still there is a problem. It behaves like it moves in a matrix.
It behaves like it has predefined locations and it only moves between those locations.
It's because of the converting position cordinates between mouse and glwindow iguess. glwindow's position(0,0,0) is at the center of window. However mouse's (0,0) coordinate is at the left top of the gl screen. So I tried to convert between those values. It seems I couldn't. Is there a function defined in opengl standart library to convert these coordinates to each other??

predaeus
07-11-2008, 02:42 AM
I think it should be glTranslatef(-w * 0.5, -h, 0); in setOrthographicProjection to achieve just that.

dletozeun
07-11-2008, 02:56 AM
glTranslatef(-w * 0.5, -h, 0);

To achieve what?



glwindow's position(0,0,0) is at the center of window


No. See my last post.

bod2na
07-11-2008, 03:39 AM
What does ur code do dletozeun??
I couln't understan it?
Where will I wrote it?When will I call it??

bod2na
07-11-2008, 06:30 AM
My problem now is; when I drag the square slowly, it does not move. But when I reach a certain point, it jumps to that point suddenly.
It's like there r certain points on the coordinate plain and square just travels on those points. Its because of convert mistakes.
I'm drawing the square with using the gltranslatef func as u see above from my code. But glwidget coordinates is different than that.I found that 1f translate is equal to 96 pixel.
So compute the difference between last position and orevious position, and divide it by 96. So it should give me the x and values for gl translation, but it does not.
Is it possible to make this approach work?
Or can you show me another way please ??

dletozeun
07-11-2008, 06:32 AM
As I said my code is useful to set orthographic projection (You are working in 2D, aren't you?)

This just set 2D projection and and set the viewport in a way that the origin is at the top left corner (like mouse coordinates), viewport width is screen width and viexport height is screen height.

Then if you do:
glVertex2i(50, 20);

It will draw a point (in point mode) at exactly (50, 20) in pixel coordinates from the top left screen corner.

bod2na
07-14-2008, 02:19 AM
I added this setOrthographicProjection() function to my class. And I call it in my initialize function. Am I doing the right thing?
Cuz it does not draw anything..

bod2na
07-14-2008, 02:28 AM
setOrthographicProjection();
glBegin(GL_QUADS);
glVertex2i(150, 20);
glVertex2i(170, 20);
glVertex2i(150, 40);
glVertex2i(170, 40);
glEnd();

I Just wanted to draw a square but I Couldnot managed to do it. It draws a a square whose lefd side is not complete. It draw a square like a packman. I mean looks like there is a black triangle in the square, Whose vertices are the square's left vertices and the vertex in the square's middle.

dletozeun
07-14-2008, 03:21 AM
reverse the order of the two last lines. When culling is enabled, always set vertices in a cyclic order (clockwise or counter clockwise depends on what type of face is shown: GL_FRONT, GL_BACK or GL_FRONT_AND_BACK).

bod2na
07-15-2008, 07:25 AM
It worked perfectly with the help of the dletozeun with 1 object.
I need to make it work with 2 objects.When I draw another rectangle to the glwindow. The program stopped working correctly.
I guess there can be a problem with setOrthographicProjection.
I define that function in the class. And called it in initializeGL and PaintGL. So everytime paintgl is called, it calls this function also. an at the end of this function there is a translatef() call. Maybe this causes the problem.
It only moves in the direction of right bottom. No left no right or no up. only to the right bottom.
Can you help me once again pls??

dletozeun
07-15-2008, 07:36 AM
take care of what you put in your matrices, don't forget to clear them when it is needed. Opengl don't do this for you.
One other thing, if I am right, your work just with one orthogrophic projection, so you don't have to set the projection matrix at each frame. Like I said, while you don't modify it, this matrix stay the same in the matrix stack.

bod2na
07-15-2008, 08:08 AM
Actually, I don't know Much about matrices.It's like a layer in photoshop isn't it?
I think I'm using just one matrix. I'm just repeating a drawing operation on each mouse move. Here is my initialize code:


void GLWidget::initializeGL()
{
//glClearColor(0.0, 0.0, 0.0, 0.0);

glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f);// Depth Buffer Setup
gluOrtho2D(-200,200,-200,200);
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
xCord =0;
yCord = 0;
sqSide = 20;
xrCord = 50;
yrCord = 20;
rSide = 30;
rectChosen=false;
sqChosen =false;
setOrthographicProjection();
//object = makeObject();
}

Here is my paintglcode:

void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
setOrthographicProjection();
qglColor(kareRenk);
drawQuad(xCord,yCord,sqSide);
qglColor(ucgenRenk);
drawRect(xrCord,yrCord,rSide);
}

If the user clicks inside of a square or rectangle, it becomes selected.I display it by changing its color.
Here is my mouse pressed code:

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
GLfloat iy;
GLfloat ix= event->x();
iy = event->y();
QPointF tmp(ix,iy);
if (isInSquare(tmp)){
if (event->buttons() & Qt::LeftButton) {
SqPoint.setX (event->x());
SqPoint.setY (event->y());
xCord = ix;
yCord = iy;
updateGL();
return;
} //else if (event->buttons() & Qt::RightButton) {

//}
}
if (isInRect(tmp)){
if (event->buttons() & Qt::LeftButton) {
RectPoint.setX(event->x());
RectPoint.setY(event->y());
xrCord= ix;
yrCord=iy;
updateGL();
}
}
}

Here is my function for drawing the square:

void GLWidget::drawQuad(GLfloat xx, GLfloat yy, GLfloat side){

//glTranslatef(xx,yy,0.0f); // Move Right 3 Units
SqPoint.setX(xx);
SqPoint.setY(yy);
glBegin(GL_QUADS);
//qglColor("blue");// Draw A Quad
glVertex2f(xx, yy); // Top Left
glVertex2f(xx+side,yy); // Top Right
glVertex2f(xx+side,yy+side); // Bottom Right
glVertex2f(xx,yy+side); // Bottom Left
glEnd();
// glTranslatef(-xx,-yy-side,0.0f);?-->DO I NEED THIS LINE?
}

Here is My function for drawing rectangle:

void GLWidget::drawRect(GLfloat xx, GLfloat yy, GLfloat side){
RectPoint.setX(xx);
RectPoint.setY(yy);
glBegin(GL_QUADS);
//qglColor("blue");// Draw A Quad
glVertex2f(xx, yy); // Top Left
glVertex2f(xx+60,yy); // Top Right
glVertex2f(xx+60,yy+side); // Bottom Right
glVertex2f(xx,yy+side); // Bottom Left
glEnd();
//glTranslatef(-xx,-yy-side,0.0f);--->DO I NEED THS LINE?
}

And at last here is my setOrtho, which was written by you:

void GLWidget::setOrthographicProjection()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// set a 2D orthographic projection
gluOrtho2D(0, 399, 0, 399);
// invert the y axis, down is positive
glScalef(1, -1, 1);
// mover the origin from the bottom left corner
// to the upper left corner
glTranslatef(0, -399, 0);
glMatrixMode(GL_MODELVIEW);
}


I guess maybe in the last function.
glTranslatef(0, -399, 0);-> this line can cause a problem.
Because I call this function in the paintgl function.
But If i comment out that line from the paintgl, it does not draw anything to the glwidget.
So I wrote that in both initialize and paingl functions.
So what are your opinions.

dletozeun
07-15-2008, 10:34 AM
gluOrtho2D(-200,200,-200,200);


This is not useful in the initialization function if you set after orthographic projection and more if you don't specify which matrix will be modified by this call putting a glMatrixMode(GL_PROJECTION).

Then, in your draw function the glLoadIdentity alone means nothing. Before, set matrix mode glMatrixMode(GL_MODELVIEW).

I think you really have to read a tutorial about the opengl transformations or the opengl FAQ here (http://www.opengl.org/resources/faq/technical/transformations.htm).

And please don't compare opengl to photoshop :) . Matrices are not layers at all, they just are matrices... :) They are used to transform vertices like rotations, translations, projections,...

If you are not used to matrices math I suggest you to read some books about it, otherwise you may be always lost when using them in opengl.

And in opengl when you set a transformation like with glTranslate all the geometry defined after will be transformed not the one before. Take care of this I have seen that you do the opposite in your code.

bod2na
07-15-2008, 10:46 PM
I need 2 matrices right?
ok. I started to read about matrices.
I know matrix math.

bod2na
07-16-2008, 06:46 AM
I found that wrong movement occurs because of the "if condition" in the mousemove.IF I comment out the "if( isInSquare() )"
it moves it correctly.

Why do you think it behaves like this??

edutucci
12-03-2009, 08:15 AM
Hi,

I have an application where you can draw 2D objects with the mouse. I am studying opengl too, but I have been creating a small library to study opengl. I am beginneer on this. Translate 2D object with the mouse is not hard, I can write function easily to translate 2D objects.

My msn is edutucci@hotmail.com