OpenGL - Moving Primitives along the X and Y using arrow keys - c++

I'm building a 2D drawing canvas that allows users to draw shapes on the screen by first selecting which shape you want to draw, and then clicking into the drawing area to draw your shape. Here's what the UI looks like for a better visualization:
So far, I have some code that allows the user to click on the derired shape, draw the shape, then click on another shape to draw, and so on...
First I check if a button has been clicked on in my processMouse() function:
if (x >= 0 && x <= 95 && y >= 302 && y <= 380) { // area of SQUARE shape
// squareShape = false by default
squareShape = true;
}
else squareShape = false;
If it has, we highlight the shape in my display() function:
if (squareShape != false) {
drawHighlight(100, 50, 350, true); // highlighted SQUARE
}
and in the same function, we enable some points to be drawn:
if (areaClicked2 != false) {
for (int i = 0; i < points.size();i++)
{
//areaClicked2 = true;
glLineWidth(1);
glBegin(GL_LINES);
glVertex2i(points[i].x + lineOffset.x, points[i].y + lineOffset.y);
}
}
I have applied this exact same method for every other button, and they all seem to be working fine...
My issue?
If I click on a button to draw squares, it draws a few squares, but when I click on an another button, my squares disappear because I don't have the square button selected. So for every button when I click to draw, the shapes are only visible until I click on an another button. How can I fix this?
EDIT:
Everytime I want to make a new points vector for a new shape, I make a new vector like this:
std::vector <point> lines; // old vector
point OnePoint;
std::vector <point> dots; // new vector
point OneDot;
Should I not be doing this? If not, how should I be? I tried to keep lines and just make new point variables but then when I draw, they're exactly the same point.

Just a guess, I think you are clearing(or creating new) points[] collection on each shape selection. You should preserve old point collection and append new shape points so that it will be visible even on different shape selection.

Related

How to move 2D multiple drawn shapes (Squares and Rectanagles) seperately in OpenGl?

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.

Change Cursor Image While Hovering Over An Object Drawn At OpenGL And Displaying Object's Variables

I am currently working on a project that I use C++, OpenGL, Qt 5.9.2 and Microsoft Visual Studio Professional 2015 on a 64 bit Operating System, Windows 10 Pro.
I have a user interface that I have created and in that user interface, there is a QGLWidget, that I am using for draw processes, with other widgets like push buttons and a dockWidget. I have a class Ball and it has variables(distance(double) and angle(int)) that determines where an instance of that Ball is going to be drawn inside the QGLWidget. Ball class has got 2 more variables that is, id(int), model(String) and year(int) Every other draw process draws lines except Ball drawings.
Drawings are 2 dimensional.
Every Ball has the same color(rgb)!
First problem: I want to left click to one of the Ball instances and I want to display it's id, model and year at The dockWidget.
Second Problem: While doing the stuff that I have mentioned at the First Problem section. I want the cursor image to change while hovering above any of the Ball instances, and change back to default Windows mouse cursor while not.
I have created a function that checks if the MouseEvent is LeftClick:
void DisplayManager::mousePressEvent(QMouseEvent* ev) {
if (ev->buttons() & Qt::LeftButton) { // Balls Are Green
if(// CHECK IF THERE IS A BALL AT THE CLICKED COORDINATES) {
// DISPLAY THE X and Y OF THE BALL AT THE DOCK WIDGET
}
}
}
This is my initializeGL function: (DisplayManager is the name of my QGLWidget)
void DisplayManager::initializeGL() {
glEnable(GL_COLOR_MATERIAL); // Enables the changing of the draw color with glColor() functions
glColor3f(0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1); //sets a black background 1 0 0 1
}
On the basis this is a Picking problem and there are several information about it at the internet but I am not using GLUT and I am not using any shader. So in the light of all these I was unable to find any effective solution or clue about how can I accomplish all that I want.
I would be really glad if someone could help me with at least one of these problems.
I have currently finished working with the project. I thought that I should provide an answer to my question in case someone with a similar problem comes across with my question in the future.
void DisplayManager::mousePressEvent(QMouseEvent* ev) {
// The processes that are being executed after a left mouse button click on the DisplayManager.
if (ev->buttons() & Qt::LeftButton) {
double aspectRatio = openGLWidgetWidth / openGLWidgetHeight;
int xOfClicked = ev->x() - (openGLWidgetWidth / 2);
int yOfClicked = - (ev->y() - (openGLWidgetHeight / 2));
// The variable to be used for calculating fault tolerance of the click event.
int distanceBetweenPressAndDraw = 0;
// Executes the processes inside for every ball in vector.
for (int i = 0; i < ballVector.length(); i++) {
// Calculates the screen coordinates of the i'th ball.
int rangeOfBallInScreenDistance = rangeToScreenDistance(ballVector.at(i).range);
double screenXOfBall = rangeOfBallInScreenDistance * sin(ballVector.at(i).degree * DEGTORAD);
double screenYOfBall = rangeOfBallInScreenDistance * cos(ballVector.at(i).degree * DEGTORAD);
// Calculates the distance between pressed position and the i'th ball according to the screen coordinates.
distanceBetweenPressAndDraw = sqrt(pow((screenXOfBall - xOfClicked), 2) + pow((screenYOfBall - yOfClicked), 2));
// Decides if the clicked position is a ball (considering the fault tolerance).
if (distanceBetweenPressAndDraw < 10) {
emit printXY(QPointF(xOfClicked, yOfClicked)); // Prints the screen coordinates of the clicked positions (At the Dock Widget inside Main Window).
}
}
}
}
This was the solution for my First Problem. I would be glad though if someone could answer my Second problem in a comment or answer somehow.

Shuffling rendered primitives

This is just an experiment I'm doing, but suppose that we have three rectangles that are drawn:
void thisDialog::paintEvent(QPaintEvent *ev)
{
rectangle = new QRect(40, 80, 40, 90);
painter = new QPainter(this);
brush = new QBrush(QColor(QColor::green);
painter->fillRect(...);
painter->drawRect(...);
rectangle2 = new QRect(140, 80, 40, 90);
// and draw
rectangle3 = new QRect(240, 80, 40, 90);
// and draw...
}
And now I want to somehow shuffle the rectangles drawn. My solution is to use std::random_shuffle. The plan is we push all the rectangles into a vector thereof:
vector<QRect*> vecRect;
vecRect.push_back(rectangle);
// push back other rectangles
std::random_shuffle(vecRect.begin(), vecRect.end());
At this point, the order of the rectangles have been shuffled. The only problem is that although they're shuffled I have to somehow reflect that in their positions and also update what's shown on-screen for the changes to be apparent. So, I propose creating a function called shuffle. I want only the x-values to change, so the y-values and the spacings of the rectangles should be left alone.
void shuffle()
{
std::random_shuffle(vecRect.begin(), vecRect.end());
for (auto it : vecRect)
{
// do something to the x-values in rectangle; e.g.
it->setX(/*set something...*/);
}
}
To shuffle the rectangles along the x-axis and maintain the y-axis, and maintain the spacing in between I'd have to get a random number and add the spacing and ensure that it is within the window boundaries say 800x600.
Since I am new to Qt I have to know how Qt handles primitive positions, and so I guess that setX() from the docs would modify the x-position of the rectangle. My other enquiry is: how do we update the positions so they're reflected on what's drawn on-screen? Whenever I update positions it doesn't seem to take effect. I've tried update() but that doesn't seem to work.
Btw, I call the foresaid function through a key press, so if the key 'S' is pressed then the function is called.
TLDR; How can I shuffle x-positions in these rectangles and update their positions rendered?

c++ How to wait for multiple mouse clicks

I want to draw a Triangle in CImg library. However, I do not know how to write the code that will allow me to draw the triangle using three mouse clicks.
The code in the documentation is this:
while (!main_disp.is_closed() && !draw_disp.is_closed())
{
main_disp.wait();
if (main_disp.button() && main_disp.mouse_y()>=0)
http://cimg.sourceforge.net/reference/group__cimg__tutorial.html
But it is for one mouse click, which I implemented successfully to draw a circle on the mouse click. But to do for three mouse clicks or two has proven to be difficult for me.
I also have the problem of inputting the color I want. I wrote red for example as:
const unsigned char red[] = {250, 0, 0};
Then I want the user to choose which color, enter his choice(assume it's red) and then pass this definition of red into the image.
Anyone can help with this ?!
If you know how to detect when the mouse button is clicked, you can store information about that click for later. For example, you can store previous mouse clicks in a deque.
struct point
{
int x,y;
};
...
std::deque<point> clicks;
while (!main_disp.is_closed() && !draw_disp.is_closed())
{
main_disp.wait();
if (main_disp.button())
{
clicks.push_front({mouse_disp.mouse_x(), mouse_disp.mouse_y()});
if (clicks.size() >= 3)
{
// draw a triangle using clicks[0], clicks[1] and clicks[2]
}
}
}

How to get the x,y coordinate of a mouse-click with win32 C++ on a directx object?

How can I get the x,y coordinate of a mouse click, to see if it is over my menu button drawn by directx? Currently, my codebase has the following mouse-related class that doesn't seem to be able to give me this..I'm not sure how this might work.
InputMouse::InputMouse() :
m_LastX(-1),
m_LastY(-1)
{
m_MouseActionEvent.clear();
}
InputMouse::~InputMouse()
{
}
void InputMouse::PostUpdate()
{
m_CurrentAction.clear();
}
bool InputMouse::IsEventTriggered(int eventNumber)
{
for (unsigned int i = 0; i < m_CurrentAction.size(); i++)
{
if (m_MouseActionEvent.size() > 0 && m_MouseActionEvent[m_CurrentAction[i]] == eventNumber)
{
return true;
}
}
return false;
}
void InputMouse::AddInputEvent(int action, int eventNumber)
{
m_MouseActionEvent[action] = eventNumber;
}
void InputMouse::SetMouseMouse(int x, int y)
{
if (m_LastX != -1)
{
if (x > m_LastX)
{
m_CurrentAction.push_back(MOUSE_RIGHT);
}
else if (x < m_LastX)
{
m_CurrentAction.push_back(MOUSE_LEFT);
}
if (y > m_LastY)
{
m_CurrentAction.push_back(MOUSE_UP);
}
else if (y < m_LastY)
{
m_CurrentAction.push_back(MOUSE_DOWN);
}
}
m_LastX = x;
m_LastY = y;
}
DirectX or not, GetCursorPos is going to retrieve the position of the mouse in screen co-ordinates. ScreenToClient will map the screen relative point to a point relative to the client area of your window/directX surface.
If your menu buttons are 2D, this should be as simple as remembering the screen co-ordinates used for your buttons.
If you're trying to determine if a click lands on a 3D object that's been rendered, then the technique you are looking for is called Picking.
A simple Google for "directx picking" comes up with some good results:
http://www.mvps.org/directx/articles/rayproj.htm
http://www.gamedev.net/community/forums/topic.asp?topic_id=316274
Basically, the technique involves converting the mouse click into a ray into the scene. For your menu items, a simple bounding box will probably suffice for determining a 'hit'.
Once an object is drawn, the system has no knowledge of which pixels on the screen it changed, nor do those pixels know which object or objects changed it (nor if those objects even still exist). Therefore, if you need to know where something is on-screen, you have to track it yourself. For buttons and other GUI elements this usually means keeping your GUI in memory along with the rectangles that define the boundaries of each element. Then you can compare your mouse position to the boundary of each element to see which one it is pointing at.