Problem with MouseMotionListener and AWTGLCanvas

Started by Uncle, February 27, 2006, 09:38:17

Previous topic - Next topic

Uncle

Hello.
I have create an applet with AWTGLCanvas and added all kinds of Listeners : MouseMotionListener, MouseListener, KeyListener, MouseWheelListener.
I override the method paintGL in AWTGLCanvas class and everything works fine  :) - applet with GLcanvas. But the problems begins when I implement the MouseMotionListener. The idea was that the user can move scene this mouse (hold right mouse button and move the scene). When this action I doing slowly all is OK, but when I move mouse more fatser the scene freeze for a moment (2-3 seconds) and the CPU usage jump to 100% - it's very nervy  :x I don't have idea what I'm doing wrong and where is the problem ? :( In KeyListener this also occur but not so often. I thought that where is a problem this canvas.repaint() or Swapbuffers(), so in MouseMove method I added Sleep(10) but that not help :( If U have any idea or maybe U know where could be the problem please help.
There's the code which I use:

   public void init()
   {
      try
      {
         
         this.setLayout(new BorderLayout(1, 1));
         canvas = new GLCanvas(640, 480, 10, CCamera);
         this.add(canvas, BorderLayout.CENTER);

         canvas.addMouseListener(this);
         canvas.addMouseMotionListener(this);
         this.addMouseWheelListener(this);
         canvas.addKeyListener(this);
         canvas.requestFocus();
         
      }
      catch (Exception ex)
      {
         ex.printStackTrace();
      }
   }

   public synchronized void mousePressed(MouseEvent arg0)
   {
      if (arg0.getButton() == MouseEvent.BUTTON1)
      {
         clickX = arg0.getX();
         clickY = arg0.getY();
         
         Lpressed = true;
      }
      else if (arg0.getButton() == MouseEvent.BUTTON3)
      {
         clickX = arg0.getX();
         clickY = arg0.getY();
         
         Rpressed = true;
      }
   }
   
   public synchronized void mouseReleased(MouseEvent arg0)
   {
      if (Lpressed) Lpressed = false;
      else if (Rpressed) Rpressed = false;
   }
   
   public synchronized void  mouseDragged(MouseEvent arg0)
   {
      mouseMoved(arg0);
   }
   
   public synchronized void mouseMoved(MouseEvent arg0)
   {
      if (Lpressed == true) {
      }
      else if ((Rpressed == true) && (!moving)) {
         moving = true;
         
         int mouseX = arg0.getX();
         int mouseY = arg0.getY();
            
         if ((mouseX - clickX) > 0)   CCamera.StrafeRight(-0.06f);
         else if ((mouseX - clickX) < 0) CCamera.StrafeRight(0.06f);
         
         if ((mouseY - clickY) < 0) CCamera.MoveForwards(0.06f);
         else if ((mouseY - clickY) > 0) CCamera.MoveForwards(-0.06f);
         
         clickX = mouseX;
         clickY = mouseY;
         
         try{
            canvas.repaint();
            Thread.sleep(10);
         }
         catch (Exception ex){
            ex.printStackTrace();
         }         
      }      
   }

CCmaera is my class with all operations this the scen (glRotate, glTranslate ets.), GLcanvas is my AWTGLCanvas class (public class GLCanvas extends AWTGLCanvas) with paintGL() method.

PS.
Sorry for my english :)

Fool Running

My guess is that it is taking a while to repaint(). Every time you move the mouse (i.e. like one pixel) it redraws the whole screen. You might try only redrawning every (n) milliseconds.
some suedo code:
if(timeSinceLastRepaint > 10) <-- In milliseconds
    repaint();

The problem with this is that its easy to miss movements. Another idea is to create a Timer that updates every (n) milliseconds and check if the mouse has moved since the last timer update. If it has then do a repaint().
suedo code:
public void timerEventHappened(){
    if(mouseWasDragged)
        repaint();
}


EDIT: After looking more at the code I see you have a moving flag... How can it ever be called more than once? (you don't seem to ever set it to false)
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

Uncle

Hello.
Yes, I have tried many options and now I know that the problem is with canvas.repaint() :( As U write "Every time you move the mouse (i.e. like one pixel) it redraws the whole screen". I tried with creating a stan alone Thread which repaint every n miliseconds, with Timer (that after R reply) and with calling canvas.repaint() after each move and the problem still exists. When I set a refresh after each one second it's work OK but ... U know :(
I also tried with boolean flags (as U noticed - the moving flag was changed to false on the end of repaint() method) .
The problem still exists :(
Thanks for reply.

Uncle

So maybe someone could help by another way ? :)
What is the best method to draw on the screen for about 2000 - 3000 lines ?
I create CallList and then in paintGL CreateCallList(). I know that it's not the best method but how can I speed up this ?

There is the code which I use:

   private void DrawScene()
   {
       GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
       GL11.glLoadIdentity();
       
       CCamera.setCameraView(0.0f, 100.0f);

       GL11.glListBase(CallListID);
       GL11.glCallList(CallListID);
   }

   public int CreateCallList()
   {
      int MapCL;

      MapCL = GL11.glGenLists(1);

      GL11.glNewList(MapCL, GL11.GL_COMPILE);
      
         for (int i = 0; i < Lines.size(); i++)
         {
            Vector OneLine = new Vector();
            Point old_point = new Point();
            
            OneLine = (Vector)Lines.get(i);
            
            GL11.glColor3f(1.0f, 1.0f, 1.0f);
            GL11.glBegin(GL11.GL_LINES);
                 
            for (int k = 0; k < OneLine.size(); k++)
            {
               if (k == 0)
               {
                  Point tmp = (Point)OneLine.get(k);
                  old_point.setLocation(tmp.getX(), tmp.getY());
               }
               else
               {
                  Point new_point = (Point)OneLine.get(k);
               
                  GL11.glVertex3f((float)old_point.getX(), 0.0f, (float)old_point.getY());
                  GL11.glVertex3f((float)new_point.getX(), 0.0f, (float)new_point.getY());
                  
                  old_point.setLocation(new_point.getX(), new_point.getY());
               }                  
            }      

            GL11.glEnd();
         }
      
         GL11.glEndList();

      return(MapCL);
   }

}

Fool Running

I don't think you want to do:
GL11.glListBase(CallListID);

Back to the question:
A display list is the best way to do that, but just make sure you aren't creating the display list every time. (i.e. Create it once and then just call glCallList() )

QuoteI tried with creating a stan alone Thread which repaint every n miliseconds, with Timer (that after R reply) and with calling canvas.repaint() after each move and the problem still exists.
I'm not sure exactly what you mean, but how often was the timer firing? The problem should have gone away... Maybe the drawing of your scene is taking a REALLY long time. Is there a way to find the length of time it takes to draw the scene? Or post the drawing code here? Or all of the code?
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

kevglass

I'm seeing this same behavior - and you can get it to happen with the AWTGears test.

If we have a thread going all out calling repaint() on an AWTGLCanvas then we get a nice updating display. However, if you move the mouse over that canvas the MouseMove events that are caused (a hell of a lot of them) spam out the AWT event queue which makes the rendering pause. This happens even if you arn't listening for mouse events (it seems).

Is there a known solution for this? If not, it basically makes AWTGLCanvas used as a mouse controlled applet game impossible.

Kev

KenRussell

This recently came up in the context of JOGL as well. The workaround in this thread might help:

http://www.javagaming.org/forums/index.php?topic=13009.0

kevglass

The workaround didn't seem to have any effect in my scenario. :/

Kev