Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

animation with opengl

Posted on 2003-10-27
5
Medium Priority
?
1,757 Views
Last Modified: 2008-03-17
I'm trying to do two simultaneous animations.

One is a rectangle that moves back and forth by control of the mouse. Ie. when the left mouse button is held down the rectangle moves up, when it is released it stops; when the right mouse button is held down it moves down, when released it stops moving.
At the same time when I press 's' on the keyboard a ball starts moving. It should move continously regardless of what happens with the rectangle or the mouse.

The only way I know to do animation is by using glutIdleFunc(). I have a method for moving the rectangle and one for moving the ball. I pass one of these to glutIdleFunc(), however I need glutIdleFunc to handle both of them. Is there any way to do this???

Please, please help!
0
Comment
Question by:joannak
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
5 Comments
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9631144
you should use glutMouseFunc( ) to handle mouse events, and glutKeyboardFunc( ) for keyboard events. Use double buffer (and swap them) if you need to. Using glutIdleFunc( ) to handle drawing is a very bad idea, because you would slow down the response time for other events. glutIdleFunc() should contain the less code the better. What you can do is to do the computational stuff when you handle the mouse/keyboard events. To be able to draw more efficiently (faster - less flickering) you can use display lists and double buffer (and the depth buffer if need be).

To use a mouse function:

void OnMouseClick(int btn, int state, int x, int y) {
   if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
   {
   }
   if(btn == GLUT_LEFT_BUTTON && state == GLUT_UP)
   {
   }
   if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
   {
   }
   if(btn == GLUT_RIGHT_BUTTON && state == GLUT_UP)
   {
   }
  //or middle button etc.
}

and in main

glutMouseFunc(OnMouseClick);
glutKeyboardFunc( ) is very similar.

You can keep track of the mouse motion while the mouse is being dragged by glutMotionFunc( ).
Quite fundamental stuff! There are many OpenGL tutorials/examples out there you can learn a lot from.
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9631161
For your idle function, the best way is to have something like:

int ypos, isMouseClicked;

void myIdle() {
   if(isMouseClicked) { //you can modify this to distinguish between left and right.
      ypos += 2; //going up
      glutPostRedisplay(); //request your redraw.
   }
}

something like that. If you don't know how to create a display list just ask.
0
 

Author Comment

by:joannak
ID: 9631267
hmm.... I guess I wasn't very clear with my question:

here's my basic code structure:

int main(int argc, char **argv)
{
// basic initialization stuff
      GLint windowW=DEFAULT_WINDOW_WIDTH, windowH=DEFAULT_WINDOW_HEIGHT;
      glutInit(&argc,argv);
      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
      glutInitWindowSize(windowW, windowH);
      glutCreateWindow("my window");

      init();
      createMenus();

      glutDisplayFunc(display);
      glutReshapeFunc(reshape);
  // here are my keyboard and mouse event handlers
      glutKeyboardFunc(keyboard);
      glutMouseFunc(mouse);
      glutMainLoop();

      return 0;
}


// callbacks.c (pseudocode)
void keyboard(unsigned char key, int x, int y)
{
      switch(key)
      {
      case 's':
      case 'S':
            glutIdleFunc(ball);
                }
}
void mouse(int button, int state, int x, int y)
{
      switch(button)
      {

      case GLUT_LEFT_BUTTON:  // move paddle up
            if (state == GLUT_DOWN)
                glutIdleFunc(moveUp);
            else if (state == GLUT_UP)
               glutIdleFunc(NULL);
            break;
      case GLUT_RIGHT_BUTTON: // move paddle down
            if (state == GLUT_DOWN)
                glutIdleFunc(moveDown);
            else if (state == GLUT_UP)
               glutIdleFunc(NULL);
            break;
      default:
            break;
      }
}

ball()
{
    change translation parameters;
    glutPostRedisplay();
}

moveUP()
{
    change translation parameters;
    glutPostRedisplay();
}

moveDown()
{
    change translation parameters;
    glutPostRedisplay();
}


So when I press "s" the ball gets going. Now I need to move my rectangle up or down with the mouse. When I press and hold the left button it should move up, when I release it should stop. (similarly with right button).  BUT, when the mouse button is pressed the ball() function stops executing and moveUp() starts instead. Is there a way for both of them to keep executing or do I have to do my animation some other way. If so, then how do I get my rectangle to move without using glutIdleFunc(). The way you described it above it only moves by one translation parameter at each click. I need it to keep moving when the button is held down.
0
 
LVL 4

Accepted Solution

by:
n_fortynine earned 375 total points
ID: 9634518
>> Is there a way for both of them to keep executing
You can map all events to one single idle function and distinguish the individual events in there. for example:

int leftClk, rightClk, kbHit;

void mouse(int button, int state, int x, int y)
{
     switch(button)
     {

     case GLUT_LEFT_BUTTON:  // move paddle up
          if (state == GLUT_DOWN) {
              leftClk = 1;
              glutIdleFunc(moveUp);
          }
          else if (state == GLUT_UP) {
             leftClk = 0;
             glutIdleFunc(NULL);
          }
          break;
     case GLUT_RIGHT_BUTTON: // move paddle down
          if (state == GLUT_DOWN) {
              rightClk = 1;
              glutIdleFunc(moveDown);
          }
          else if (state == GLUT_UP) {
             rightClk = 0;
             glutIdleFunc(NULL);
         }
          break;
     default:
          break;
     }
}

void keyboard(unsigned char key, int x, int y)
{
    kbHit = key == 's' || key == 'S' ? 1 : 0;
}
void myIdle( ) {
    if(kbHit) {
       //change ball param
    }
    if(leftClk) {
       //change param to move up
    }
    if(rightClk) {
      //change param to move down.
    }
}

void myDisplay( ) {
  //Draw your things in here together accordingly to the params
}

You can tweak these around so that they'll fit in your program.
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9634528
One thing I forgot to call glutPostRedisplay() in myIdle( )
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

610 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question