Mouse camera control

Moderator
Posts: 133
Joined: 2008.05
Post: #1
I'm using Carbon to detect when the mouse is dragged, and when it is, it turns off all other drawing, shows the axis' in different colors, and rotates the camera based on which way you drag the mouse. For the most part, looks great... until I drag in two directions on the same drag. For example, I click and hold down, drag left, then drag right while still holding down. It keeps going in the same direction for a bit, then turns around like it's supposed. Very visually ugly, the lag is also apparent when you unclick the mouse, the camera readjusts itself, like it was a few frames back. Also, I know it's stuck in a loop, in an event handler. However, that's what the Carbon documentation says to do. If anyone knows a better way of handling that(maybe putting the drag code on a seperate thread?), I'd like to know. Here's the relevant code.
Code:
pascal OSStatus MouseDragged(EventHandlerCallRef inCallRef, EventRef inEvent, void* inUser)
{
    ParticleWriter* app = (ParticleWriter*) inUser;
    XCamera* cam = app->cam;
    Point mouseLoc;
    Point dragLoc;
    UInt32 modifiers;
    EventMouseButton mouseButton;
    MouseTrackingResult trackingResult = kMouseTrackingMouseDown;
    
    GetEventParameter(inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(UInt16), NULL, &mouseButton);
    GetEventParameter(inEvent, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mouseLoc);
    GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
    app->cameraMode = kShowAxis;
    char xRotate[25];

    while (trackingResult != kMouseTrackingMouseUp)
    {        
        aglSetCurrentContext ((app->showContext));
        aglUpdateContext((app->showContext));
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glColor4f(1,1,1,1);
        glClearColor(0,0,0,1);
        
        TrackMouseLocation (NULL, &dragLoc, &trackingResult);

        int lenX = dragLoc.h - mouseLoc.h;
        int lenY = dragLoc.v - mouseLoc.v;
        
        if(mouseButton == kEventMouseButtonPrimary)
        {
            cam->RotateYaw((float)lenX/45.0f);
        //    cam->RotatePitch((float)lenY/45.0f);
        }
        else if(mouseButton == kEventMouseButtonSecondary
             || (modifiers & controlKey && mouseButton == kEventMouseButtonPrimary))
        {
            cam->MoveToNow(cam->position.x + lenX/100.0f, cam->position.y + lenY/100.0f, cam->position.z);
        }
        else if(mouseButton == kEventMouseButtonTertiary)
        {
            cam->MoveToNow(cam->position.x, cam->position.y, cam->position.z + lenY/100.0f);
        }
        sprintf(xRotate, "XRotate: %f", cam->yaw);
        glPushMatrix();
            glRasterPos3d(-2.04,2,-5); //sweet guess work
            DrawFrameRate(app->fontList);
            glRasterPos3d(-2.04,1.88, -5);
            DrawCStringGL(xRotate, app->fontList);
        glPopMatrix();
        glPushMatrix();
            cam->Animate(0);
            glBegin(GL_LINES);
                glColor4f(1,0,0,1);
                glVertex3f(0.0f, -1000.0f, 0.0f);
                glVertex3f(0.0f,  1000.0f, 0.0f);
                
                glColor4f(0,1,0,1);
                glVertex3f(-1000.0f, 0.0f, 0.0f);
                glVertex3f( 1000.0f, 0.0f, 0.0f);
                
                glColor4f(0,0,1,1);
                glVertex3f(0.0f, 0.0f, -1000.0f);
                glVertex3f(0.0f, 0.0f,  1000.0f);
            glEnd();
        glPopMatrix();

        aglSwapBuffers((app->showContext));
    }
    app->cameraMode = kShowParticles;

    return noErr;
}
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #2
Thats a really common problem to do with 3d rotation done with just two scalars (x and y), quaternion rotation will fix it but its not completly simple.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #3
I'm not talking about the rotation itself, that is fine. It is how the the event essentially locks up the rest of the app and therefore lags behind, giving me undesired results.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #4
I would suggest putting much less code in the mouseDragged function it looks awfly rich, using boolean flags to tell if the camera is being moved inside the main graphics loop would speed things up. If you could move the while loop to outside the mouse dragged event that would probably help loads.

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #5
You're supposed to pump the event loop every once in a while. I'm in a hurry here, but I'll post source when I get back! Sorry.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #6
unknown Wrote:I would suggest putting much less code in the mouseDragged function it looks awfly rich, using boolean flags to tell if the camera is being moved inside the main graphics loop would speed things up. If you could move the while loop to outside the mouse dragged event that would probably help loads.


Ok, if you don't know what you are talking about and just typing to look at the pretty words on the screen, stop answering, you aren't helping.
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #7
Call:
Quote:GetNextEvent (nullEvent, &theEvent))

from within your loop. That might do the trick.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #8
LongJumper Wrote:Ok, if you don't know what you are talking about and just typing to look at the pretty words on the screen, stop answering, you aren't helping.

His answer seemed quite reasonable to me. Your mouseDragged handler should only be processing a single event each time it's called, not blocking until the mouse is released.

- Alex Diener
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #9
The first time he answered he didn't even read the question, at least not carefully. The second time didn't really apply to the situation, but perhaps I was stating my question wrong. Fact of the matter is, moving the tracking to my "main graphics loop" isn't going to help. TrackMouseLocation can block the application, or at least that is what Apple's docs say. If I were to put the TrackMouseLocation in my update callback, I could potentially be wasting a lot of time waiting for a mouse to move, when I could be drawing instead. That is why I wait for the mouse dragged event to occur, or as Fenris explains, fetching that event instead.

The current code takes into account that I will be blocked from the rest of my application, so I turn my mouse dragged event into my new update function, since I only need to draw the axis' when I'm turning the camera. I am going ot try a different approach regardless, I don't like TrackMouseLocation.
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #10
I had exactly the same problem when I was working on Chopper2, but with cocoa events. Didn't find a solution sorry. My next approach would have been trying to get the deltas instead of the mouse position in the window.
And I'd have to agree with you, unknown's posts were way OT, and didn't make any sense. and the cocoa docs give examples of implementing dragging with exactly the same method, ie. within your own loop. It should work, but in my experience it does not work well.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #11
sorry, I was just trying to help but you should be able to understand how a mere mortal such as I cannot grasp such concepts as event loop code properly, The way youve done your event loop is quite different to any way ive seen before (i.e. having a while loop inside) and if its not working I was just suggesting that you could try a more conventional method that works (like not having a while loop inside).
I did read the question and the code (three times) before answering and I guess I just didnt understand you cos im a dumb pancake fish.

ooh pretty words
LOL LOL LOL LOL LOL

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Camera Class using Mouse Deltas Nick 6 3,249 Oct 11, 2004 09:27 AM
Last Post: Nick