Reputation: 1
I have just started using OpenGl in visual studio.
I used the drawsquare()
and drawRoundRect ()
to draw multiple shapes in seperate void functions which I called seperately in an another function named Display (void return type) which I then called in int main using glutDisplayFunc(Display)
to display.
In the Display function I used glutPushmatrix()
and glutPopMatrix ()
keeping the function of 1 shape in between like this
glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(50, 50, 50, colors[BALCK]);
glutPopMatrix ();
glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(300, 300, 50, colors[BALCK]);
glutPopMatrix ();
The issue is that the when I click the mouse anywhere on the screen(even not on the shapes) both of these shapes start moving together.
Q1) How to move the shapes one by one only when the mouse is clicked and dragged on the specific shape ?
Q2) What should I do so that the shape only moves when it is clicked and dragged and nothing happens when I click anywhere else on the screen.
I used glutPushMatrix()
, glutPopMatrix()
and glTranslatef ()
functions which worked fine for moving one shape but I don't know how I can move multiple shapes only when they are clicked and dragged.
glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(50, 50, 50, colors[BALCK]);
glutPopMatrix ();
glutPushmatrix();
glutTranslatef(x,y,0); // z = 0 because i am making 2D shape
DrawSquare(300, 300, 50, colors[BALCK]);
glutPopMatrix ();
Using this code both of my figures move together not seperately. Also even if the mouse is not clicked on any of the shapes they both start to move.
Upvotes: 0
Views: 127
Reputation: 139
You need to use different position values. Because you are using the same (x,y) values (same variables) they will move at the same rate in the same direction because (x,y) are the same position.
// object 1
glutPushmatrix();
glutTranslatef(x1,y1,0); // x1,y1 is the position of object 1
DrawSquare(300, 300, 50, colors[BALCK]);
glutPopMatrix ();
// object 2
glutPushmatrix();
glutTranslatef(x2,y2,0); // x2,y2 is the position of object 2
DrawSquare(300, 300, 50, colors[BALCK]);
glutPopMatrix ();
You will probably want a scene graph, though, that contains your objects and manages their data.
Objects should be stored in a scene graph, whether in 2D or 3D. A scene graph for 2D is basically the array of objects stored in the order they are drawn.
For example, create an "entity" class, and then part of that class is a coordinate "position" .. ie:
class Entity { // a base class for objects
public:
double x,y,z,w,h; // position, size
int r,g,b; // identifying color rgba 0-255, unique to each object
Entity() { r=g=b=a=x=y=z=0.0; }
virtual void Render() {
// do your gl drawing here, push and pop
}
bool Within( double mx, double my ) { // return true if mx,my inside boundary
return (mx > x && my > y && mx < x+w && my < y+h );
}
virtual void RenderOffscreenForPicking() { /* ... different for drawing for a different reason ... */ }
};
The above example would be a single "object" and should also contain the geometry you are drawing. It would contain an identifying color, do the rendering, for a single object at a single position. Such an object could be extended using polymorphism. It could include velocity, direction, rotation, and many other values to define behavior, drawing style, geometry, et cetera.
Q1) How to move the shapes one by one only when the mouse is clicked and dragged on the specific shape ?
Q2) What should I do so that the shape only moves when it is clicked and dragged and nothing happens when I click anywhere else on the screen.
The answer to both of these questions requires the use of a concept called "Picking" - there are many different approaches to picking. If your objects are "Axis Aligned Bounding Boxes"(Rectangles) and the x,y values are in the same scope/scale as the screen coordinates, you can use a simple AA box test (pseudocode):
selected_object=null;
if ( mx > object1_x && my > object1_y
&& mx < object1_x+object1_width && my < object1_y+object1_height )
selected_object=object1;
Another way to do picking is to assign a color to each object, to draw the objects on a framebuffer (an off-screen buffer).
The advantage of this method is that the selection of the object is "pixel perfect" and is not determined by a square box, and if the object is occluded ("behind another object") you can still pick it up.
Side note, if you are new to using OpenGL, you may wish to get shy from using the *f functions and use the *d functions, like glTranslated()
instead of glTranslatef()
, because they use double precision, not floating point.
Upvotes: 0