PDA

View Full Version : Getting GLFW mouseclick just once in a do-while loop?



eratic-magician
02-28-2017, 02:37 PM
I'm trying to fire a ray into my scene just once when the user left clicks, and it should print out either hit or miss just once. My game is in a do-while loop, and I basically have:

if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)) {
//Fire ray
}

However, right now it's constantly just printing either hit or miss while the left mouse button is held down (and even if I press it once quickly, it still prints quite a few results). How can I make it so that the ray is only fired when you click down and then release the button so that one click = one ray firing, even if it's a long click?

Thanks guys.

GClements
02-28-2017, 02:42 PM
Register a callback with glfwSetMouseButtonCallback() then call glfwPollEvents() (or glfwWaitEvents() etc) in the loop.

eratic-magician
02-28-2017, 02:59 PM
I'm not quite sure how to use that, I did look through the API. I've tried this:


glfwSetMouseButtonCallback(window, GLFW_MOUSE_BUTTON_LEFT);
glfwPollEvents();
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)) {
//ray casting
}

But I'm obviously doing something wrong.

I'm not sure how to use something like:


void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
//Ray cast
}


When I call my ray casting method inside the loop with parameters like the view/projection matrix.

john_connor
03-01-2017, 01:17 AM
I'm not quite sure how to use that, I did look through the API. I've tried this:


glfwSetMouseButtonCallback(window, GLFW_MOUSE_BUTTON_LEFT);

look at the glfw documentation:
http://www.glfw.org/docs/latest/input_guide.html

you can find there everything you need for your application, like cursor position:
http://www.glfw.org/docs/latest/input_guide.html#cursor_pos

after you've created your window, call this function:

glfwSetCursorPosCallback(window, cursor_position_callback);

that sets a "function pointer" to a certain function YOU have to provide, that function has to look like this:

void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
}

that function will be invoked automatically when you move the cursor

take a look at my example "Main.cpp", it's very similar (easy to understand) to the glfw example:
https://sites.google.com/site/john87connor/home/1-1-creating-a-window
http://www.glfw.org/documentation.html

NOTE:
the "glfw window hints" i've set require a opengl 4.5 core profile context, so if your system doesnt support opengl 4.5, try setting them to 3.3 for example:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

using that Main.cpp, you can detect framebuffer (= window) resize events key input, cursor moves, mouse button clicks, mouse scrolling and available joysticks (joystick inputs have to setup by querying pointers, explained here: http://www.glfw.org/docs/latest/input_guide.html#joystick)

eratic-magician
03-01-2017, 09:28 AM
Thanks for all that, I'm fine now with setting up a callback method (I have one that just prints "Right click" when clicking once just to make sure I'm doing that part right) so that side of it is alright. My issue now is since the callback method is declared before main and my game's do loop is inside main, how can I call my ray casting method in the mouse_callback method when it requires updated variables that exist in the main function's game loop (such as the updated view/projection matrix)?

I have this outside main:


void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
printf("Left Click");
}
}

And then in my main's do loop:



//glfwSetMouseButtonCallback(window, mouse_button_callback); Just to make sure it works
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)) { //Curently firing multiple rays, hence the need for the callback
glm::vec3 out_origin;
glm::vec3 out_direction;
ScreenPosToWorldRay(
1024 / 2, 768 / 2,
1024, 768,
ViewMatrix,
ProjectionMatrix,
out_origin,
out_direction
);

glm::vec3 out_end = out_origin + out_direction*1000.0f;
}


If I move the ScreenPosToWorldRay() method into the callback method, it wont have access to glm::vec3 out_origin and glm::vec3 out_direction, or the updated matrices.

john_connor
03-01-2017, 11:06 AM
...how can I call my ray casting method in the mouse_callback method when it requires updated variables that exist in the main function's game loop (such as the updated view/projection matrix)?

your problem is about general c++ programming, not opengl

to be frank: there are tousands of ways to do it, 1 of them would be to declare the "shared variables" globally (out_origin etc pp). if you want to have access to those variables in the callbacks, declare "function prototypes" right at the beginning of main.cpp, but frankly, putting the game logic into the main loop isnt a "good strategy", i'd suggest to look for some game programming tutorials or something else ...

google for "c++ singleton class", make use of "headder files", dont put implementations into them, use therefore .cpp files, google for "functor objects" <functional>, lambda expressions, put the gamelogic into a separate files, ...

http://www.cplusplus.com/reference/std
http://www.cplusplus.com/forum

http://gameprogrammingpatterns.com/contents.html