OpenGL / GLUT change callbacks inside glutMainLoop() - opengl

normally a GLUT application will be structured in the following pattern:
some initialization stuff
glutMainLoop()
I only have access to a drawing callback function inside the main Loop.
I will not be able to change the initialization part.
Is there any way to change a callback function like glutKeyboardFunc() within this Loop? Or is there another way to capture keyboard inputs without access to the initialization part?
Thanks

Yes, you can call glut…Func anytime. For example you could have to keyboard handler functions and switch between them (contextual keys)
void keyfunc_edit(unsigned char key, int x, int y);
void keyfunc_select(unsigned char key, int x, int y);
void keyfunc_edit(unsigned char key, int x, int y)
{
switch( key ){
case 'x':
case 'X':
/* switch to select mode */
glutKeyboardFunc(keyfunc_select);
break;
}
void keyfunc_select(unsigned char key, int x, int y)
{
switch( key ){
case 'e':
case 'E':
/* switch to edit mode */
glutKeyboardFunc(keyfunc_edit);
break;
}
This works for any GLUT callback, so you can switch callbacks for display, idle and so on, at any time. For example say you want to show a load screen, then it makes perfect sense to switch the display callback to a loading screen display function, and once loading is complete change to a scene render function.

Related

glfw input callback to modify an object with a member function

As you know, glfw works with callbacks for inputs and callback functions have certain signatures that users need to match. Here is an example from the documentation:
void key_callback(GLFWwindow* window, int key, int scancode, int action, int
mods)
{
if (key == GLFW_KEY_E && action == GLFW_PRESS)
activate_airship();
}
Now, activate airship seems to be a global function here. What I really want to do is, to modify some object, possibly, at each input stage. So I want something like:
void key_callback(Airship a, GLFWwindow* window, int key, int scancode, int
action, int mods)
{
if (key == GLFW_KEY_W && action == GLFW_PRESS)
a.render_Wireframe();
}
As you can see, I want to pass the object I am trying to modify, Airship here. But this time, callback signature is distrupted. I can't use it anymore. What is the best way to achieve this? I am trying to come up with ideas but in the future, I might want to change this to work with not just airships but a new object I add as well. What should be the design here?
The thing is, with the ability to set one callback for whole program, I don't know how to achieve the following. Let's say I have two objects Airship and Battlesip. I want both of them to have their own input handling mechanism. Pressing W should do something if Airship is the picked object in the scene and something else if Battleship is the picked object.
So I want to have something like following in the end;
class Airship : public SceneObject
{
...
void input_handle(){
if(is_picked && pressed == GLFW_KEY_W)
launch_missile();
}
}
class Battleship : public SceneObject
{
...
void input_handle(){
if(is_picked && pressed == GLFW_KEY_W)
do_something_else();
}
}
And in my main loop, I have a vector of SceneObject and I call input_handle on each frame, for each object. I don't know how can I handle something like this with a single callback scheme of glfw. I can't pass those things as callback functions to a window even if I matched the signature because they are class members. Well nothing would change if I could pass class members, since I can only set one callback.
Here is how I ended up solving this issue in a simplified manner. I am not sure if this is the correct design but it might be of help to a future viewer. I have a scene graph like object, say SceneGraph that holds all the SceneObjects mentioned in the question. I ended up making this SceneGraph object a singleton. I have one scene graph per run so it seemed logical to me to make it a singleton.
class SceneGraph
{
// ...
// many more code
friend void key_callback(GLFWwindow* window, int key, int scancode,
int action, int mods)
{
// get the singleton instance, singleton is static and this is
// a friend function, so I can register this as a callback
SceneGraph* d = SceneGraph::handle();
d->input_handle();
}
void input_handle()
{
for(auto& s : objs)
s.input_handle()
}
private:
std::vector<SceneObject> objs;
}
Of course, you can pass button state etc. to your input routines. I just wanted show the bare minimum design that I went with. Object picking example that I talked about in the original question can also be handled now.

GLUT animation with glutPostRedisplay

Is there any difference between calling glutPostRedisplay() at the end of my display function and using an idle function callback that does nothing but call my display function? I have seen both ways used in examples and cannot tell the difference by observation.
A main loop generally looks like this:
Process and handle events
calling stuff like glutKeyboardFunc/glutMouseFunc.
Advance/update 3D state (physics/animation etc)
typically in glutIdleFunc
Re-draw the scene if needed
use glutDisplayFunc
glutPostRedisplay simply sets a flag, that tells glut to call the display callback on the next loop iteration. It doesn't actually call display [1] [2].
If you have a game, which always updates every frame this might not be that useful. Maybe if you're alt-tabbed or dragging the window you don't need to be calling display. Or you might be frame limiting by dropping frames (although I'd suggest this).
void idle()
{
...
animatedThing.value += deltaTime
glutPostRedisplay(); //scene is always changing. always call display
}
Having a "dirty" flag becomes more useful when you don't need to re-render continuously. Maybe in something like a 3D modelling package where there isn't any animation and you only move the camera occasionally. Or a GUI where you only need to update when you hover and click on stuff.
void mousedown(int button, int state, int x, int y)
{
if (clickedGUI(x, y))
glutPostRedisplay();
}
void idle()
{
...
if (myKeys[MOVE_VIEW_FORWARD])
{
view.z -= deltaTime;
glutPostRedisplay();
}
}
Anyway, to answer your question, no, there's probably not much difference. However...
I'd put the glutPostRedisplay in idle as above. Calling from within display works but gives up some control you might want later. It's essentially this:
bool shouldDraw = true;
while (1)
{
// check events, input etc
// idle/update state
if (shouldDraw)
{
shouldDraw = false;
// draw
shouldDraw = true;
}
}
I also wouldn't call display from idle from a design perspective as it removes some control from glut. For example if there's a case where glut needs to override the post-redisplay (not that I know of one) it won't be able to.

how to use cv::setMouseCallback

I'm trying to use cv::setMouseCallback in my c++ project. I just don't get it.
let that I habe a class Stuff how can tell this class you got a frame and run the cv::setMouseCallback on this frame here is an example of what I'm trying to do :
class Stuff{
public:
Stuff();
void setFrame(cv::Mat);
void mouse (int,int, int, int,void*);
private :
cv::Mat frame;
int key;
};
Stuff::Stuff(){}
void Stuff::setFrame(cv::Mat framex){
frame = framex;
}
int main (){
Stuff obj;
cv::Mat frame = cv::imread ("examople.jpg");
char* name;
cv::imshow(name,frame);
cv::setMouseCallback(name,obj.mouse,&frame) // I' stop here because that's exactlly what just don't work
}
this the error message that get:
Stuff::mouse : function call missing argument list; use '&Stuff::mouse ' to create a pointer to member
the real program is too big to put its code here that why I'm trying to simplify the question
you must declare a mouse handler as static inside your class. For instance, I have a dragger with a member mouser, that I want to be called. I declare an helper static void mouser, that cast the void* received and calls the member:
class dragger {
void mouser(int event, int x, int y) {
current_img = original_img.clone();
Point P(x, y);
...
}
static void mouser(int event, int x, int y, int, void* this_) {
static_cast<dragger*>(this_)->mouser(event, x, y);
}
and instance in dragger constructor in this way
dragger(string w, Mat m) :
window_id(w), status(0), original_img(m), /*black(0, 0, 0),*/ K(5, 5)
{
...
setMouseCallback(w, mouser, this);
}
...
}
First of all you need to create a named window in the main function. namedWindow( "image", 0 ); or something similar will do the job.
The mouse callback function is not associated to the frame variable but it is associated to the window. In your case it would be:
char* name = "image";
cv::namedWindow( name, 0 );
cv::setMousCallback(name, obj.mouse,&frame);
The callbacks are functions that call other functions when an event happens on a window. For the mouse, an event can be the mouse movement, the left, right or middle clicks. Here you can find a list of them, as well as good explanations.
So when this "event" takes place in the window, opencv calls the function whose name was specified in the setMouseCallback as an argument, in your case Stuff::mouse. if you define the function like this:
Stuff::mouse( int event, int x, int y, int flags, void* params )
when it is called the event variable will be filled with the value of the trigger, the x and y with the positions off the mouse on the image etc.
If you want to pass the frame in the mouse function you use it as in this question, if you consider the correction of patxiska's answer.
So with a switch you can find out what kind of event it was:
switch( event ){
case CV_EVENT_LBUTTONDOWN:
//...
break;
case CV_EVENT_RBUTTONDOWN:
//...
break;
case CV_EVENT_FLAG_CTRLKEY:
//...
break;
}
and take your frame typecasting it from void* back to a cv::Mat.
Here you can find another example of Opencv's site on how to use a mouse callback.
Hope I helped, I haven't used opencv for a while and I don't have my sample source files now. Callbacks are simplified in the Opencv GUI but that's the logic of working with any GUI. Input such as mouse and keyboard trigger events and the callback functions pass the events to the functions of your implementation.

C++, (GLUT) - maintaining a global vector of booleans in the display loop - crashes program

I've got a bit of a tricky problem in my opinion. I'm new to C++ and OpenGL/ glut so be gentle!
I'm writing a platform-independent simple program (only 2D) and need a basic UI, so I have a Button class which generates a Button object. This hopefully will be able to be called dynamically (i think that's the right word) from inside the displayFunc() loop in OpenGL/ glut.
Every time the loop starts, it instantiates the correct button objects and then destroys them at the end. Of course, the buttons need to be able to do something, so in the glutMouseFunc function, it checks if the mouse clicked in the place needed to set off the button.
It is allowed access to the button member variables (xMin.. yMax) via get/set functions, which are public. However since the button is instantiated by the display loop, I had to create a global vector of pointers to the buttons which is updated as they are created, and cleaned up, along with the objects, at the end of the display loop. This is all fine and dandy I believe.
The tricky thing comes when I actually want a button to change state. The only thing I can come up with is having std::vector<bool> buttonStates;, which is augmented when the button is created, changed when the button is clicked, and destroyed when the button is.
Of course, this change of state doesn't carry through to the next loop of display, so I tried std::vector<bool> btnStatesCopy;, which maintains a copy of the buttonStates vector by using btnStatesCopy = buttonStates;when it changes, but is not destroyed at the end of the display loop. When the buttons are created, the button states now are copied from the btnStatesCopy vector, which has not changed since the last loop.
Unfortunately, this crashes my program, even when trying to print the btnStatesCopy vector. So I was wondering if you had any idea why it might crash, and what I might do to avoid it! I can post code, but I'm not sure it would help. Is there a better, more obvious way of doing this stuff that I haven't thought of? I would love to hear any ideas! Thanks a lot,
Patrick
Edit: Here's a concise version of the code if it help (keep in mind, I am really new at this stuff!):
//*in global scope*
// Stores pointers to the ui buttons.
std::vector<Button*> buttons;
// Stores button states, which are copied from buttonStates and
// destroyed every time display() runs.
std::vector<bool> buttonStates;
// Stores a copy of buttonstates which is written to when
// a button is pressed.
std::vector<bool> btnStatesCopy;
// Prototype functions:
void init(void);
void display(void);
void key(unsigned char key, int x, int y);
void processHits(GLint hits, GLuint buffer[]);
void click(int button, int state, int x, int y);
void idle(void);
void resize(int width, int height);
void drawMenu(void);
void circle(float x,float y,float size,int segments);
void initialiseButtons();
// Main loop goes here; calls glutDisplayFunc(display);
void display(void) {
initialiseButtons();
drawMenu();
}
bool changeBinaryState(bool state){
/* Changes 1 to 0 and 0 to 1. */
if (state == 0) state = 1;
else state = 0;
return state;
}
void click(int button, int state, int x, int y) {
/* Called when a mouse button is clicked. */
if (button == GLUT_LEFT_BUTTON && state != GLUT_DOWN) {
std::cout<<x<<", "<<y<<std::endl;
for(int i = 0; i<buttons.size();i++){
//put a pointer of a button in variable but
Button* but = buttons.at(i);
if (x > but->getMinX() && x < but->getMaxX()) {
if (y > but->getMinY() && y < but->getMaxY()){
but->buttonFunc();
changeButtonState(buttonStates.at(i));
buttonStates.at(i) = 1;
btnStatesCopy = buttonStates;
}
}
}
}
}
void drawMenu(void) {
// Create a button and its pointer and add pointer to buttons vector.
Button* p_b = new InfoButton("User Manual",20,spacing+yOffset);
buttons.push_back(p_b);
// Add button state of previous button state.
buttonStates.push_back(btnStatesCopy.back());
// Turn on buttons if their state is on.
for (unsigned i = 0; i<buttonStates.size();i++){
if (buttonStates[i]==1) {
Button* but = buttons.at(i);
but->buttonFunc();
}
}
void initialiseButtons(){
for (unsigned i = 0; i < buttons.size();i++)
{
delete buttons[i];
}
buttons.clear();
buttonStates.clear();
}
The title of your question reads
Blockquote C++, (GLUT) - maintaining a global vector of pointers to booleans in the display loop - crashes program
(emphasis added). If I understand you correctly, that means you have
std::vector<bool*> buttonStates;
std::vector<bool*> btnStatesCopy;
and not std::vector<bool>.
If this is indeed the case, and if the bools which these pointers point to are deleted in the display loop, then they will be deleted in the display loop. You are retaining pointers to freed memory, and this is the most likely reason for a crash.
On the other hand, if this were Java (or any other garbage collected language) as opposed to C++, storing a pointer to an object protects it from being garbage collected.

How to do Game logics in OpenGL (GLUT) and C++? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am programming the game Battleship in OpenGL(GLUT) and C++.
I know how do to the graphics stuff (like displaying the field and predefined ships),
but where should I put my game code like:
if key left pressed select one field left and display it
if a ship is placed then display the ship
Things like place a ship (switching between the fields) I can't do in the display() function, but if a ship is placed it must be drawn by the display() function, right?
I don't know where to put the game logic.
What you are looking for is the basic, classic game loop. Effectively, your game runs in one giant loop. In this loop, you handle user input, react to the user input, run AI, and update the video/audio in response. This is, of course, a very simplified take on it, but it will suffice for Battleship.
Conceptually, more or less:
while(Game.IsRunning)
{
Input = GetInput();
Game.Update(Input);
Display(Game);
}
If you're actually doing real-time as opposed to event-driven, then you need to make your updates take into account the time-passed since the last update, as well as player input. I'll keep this short and limited to what you're asking though.
GLUT provides functions to intercept mouse keyboards events, like
void keyboardDown(unsigned char key, int x, int y);
void mouseClick(int button, int state, int x, int y);
void mouseMotion(int x, int y);
You may reimplement those function to get a custom behavior of your program.
For example, if you want to draw a ship after the user pushes "s" then, in your keyboardDown function, you may set a global flag to 1. Then, in the display function, you may check that flag. If it's 1 then you'll draw your ship.
Of course it's up to you how to place/move your ship :)
For further informations, take a look at the documentation
you probably want to use keyboard function and save the key pressed on stack and compare on the display which keys where pressed by the player so you can get multiple key detection something like this:
// for pressed keys
void keybd(unsigned char key,int x, int y){
//int pe;
switch(key){
case 'w':up=true;break;
case 's':down=true;break;
case 'd':right=true;break;
case 'a':left=true;break;
case ' ':trig=true;break;
}
}
// for released keys
void ms_r(unsigned char key,int x, int y){
//int pe;
switch(key){
case 'w':up=false;break;
case 's':down=false;break;
case 'd':right=false;break;
case 'a':left=false;break;
}
}
and then just compare which keys have true and act based on that
and when you are calling the glut main loop and functions
use:
glutIgnoreKeyRepeat(1);
glutKeyboardUpFunc(ms_r);
glutKeyboardFunc(keybd);