Mouse-drag camera rotation (UDK like)

Started by neo187, October 09, 2011, 01:46:06 PM

Previous topic - Next topic

neo187

Hello all,

I am working on building a simple JPCT map editor, I am trying to implement the same navigation style as Unreal Development Kit (or Blender, 3DSMax, Unity etc...).

Basically in these kits holding a mouse button and dragging makes the camera rotate in a cumulative way, so that for example you rotate 20 degrees on the X axis by moving the mouse up. The next time you drag the mouse, the rotation starts from the same point where it was left....

Currently I have a mouse listener that returns the delta x and delta y whenever the mouse is moved. In my World I am using the same camera code on the Wiki:

       public void rotateView(int dx, int dy){
Matrix rot = world.getCamera().getBack();


if (dx!=0) {
camera.rotateAxis(camera.getYAxis(), dx / 500f);
}

if (dy!=0) {
rot.rotateX(dy / 500f);
}
}


Which work great I think for a continuous movement like in a FPS game, but currently whenever I click the mouse and drag the rotation starts from the center each time, so basically it jerks back into place at each mouse movement...

Can anyone give me a hint as to how i can implement this?

Thanks a lot!

EgonOlsen

I'm not sure, if we are talking about the same thing, but maybe the example at the end of this thread helps: http://www.jpct.net/forum2/index.php/topic,977.msg6099.html#msg6099

neo187

Thank you Egon,

I implemented the code you wrote in this way:


public void rotateView(int dx, int dy){
       
        if (dx !=0 || dy != 0){
        SimpleVector line =new SimpleVector(dx, 0, dy);
            Matrix m = line.normalize().getRotationMatrix();
           
            m.rotateAxis(m.getXAxis(), (float) -Math.PI/2f);
            camera.rotateAxis(m.invert3x3().getXAxis(), line.length() / 500f);
        }

}


However it works in the same way as the simpler code above. So if there is a cube in the scene it works fine if you point at the cube and drag, but if you point away and drag the camera jerks back to point at the cube....

If you think of Google Maps for instance? When you use the street view? And you are able to point anywhere in the screen and dragging the mouse gradually moves the camera/shifts the focus to reflect the mouse movement?

I am thinking that maybe you need to return the current rotation of the camera and add/sub struct from it instead of rotating the camera from scratch at each mouse drag.... But I couldnt find a method on Camera to return the rotation, only the axes?

Anyhow, thanks for your prompt help!

EgonOlsen

I don't get your problem. The camera isn't reset anywhere in that example code of mine. There is no jumping back to the beginning...all the rotations are cummulative.

neo187

mmm, it does jerk back in my case.... maybe it's because in your example you are using lwjgl.input to calculate the delta x and y... i wrote my own listener so as to avoid attaching other libraries, this is what it does:

public void mouseDragged(MouseEvent e) {
    if(lastMousePosX == 0 || lastMousePosY == 0){
    lastMousePosX = e.getX();
    lastMousePosY = e.getY();
    }
   
   
    int newMousePosX = e.getX();
    int newMousePosY = e.getY();
   
    ew.rotateView(newMousePosX - lastMousePosX, newMousePosY - lastMousePosY);
   
    lastMousePosX = newMousePosX;
    lastMousePosY = newMousePosY;

    }


Maybe it's the way that the dx/dy are returned that cause the camera to always reset to point at the origin? Does lwjgl do this differently?

Thanks for your help!

EgonOlsen

That's a little flawed, because in the next drag, you are still working with the old lastMousePos? to calculate the deltas. You have to set them to the current position when a dragging starts, not just for the first time.

neo187

not sure I understand that, so currently at every drag I'm saving the mouse coordinates to newMousePos, then subtract those to the last recorded positions (lastMousePos) and then save newMousePos to lastMousePos.... where's the error there exactly?

Maybe I'll post a video but what happens with that camera code is that the camera rotates fine only when clicking and dragging on the origin (which is where my cube is and what the camera points at when starting up); but if you point anywhere else and drag it just jumps back to pointing at the origin? could it be just the mouse drag code that is causing this?

Also, with lwjgl, do you constantly record the mouse positions as you move the cursor or do you do it only when the mouse is pressed and dragged? I'm currently doing the latter....

EgonOlsen

The error is (at least i think that this is the problem) that your lastMousePos is only valid as long as you are dragging. Once the dragging is over and you start a new one, they have to be set to the current mouse coordinates...not to some position from the end of the last dragging.

neo187

Quote from: EgonOlsen on October 10, 2011, 11:26:13 AM
The error is (at least i think that this is the problem) that your lastMousePos is only valid as long as you are dragging. Once the dragging is over and you start a new one, they have to be set to the current mouse coordinates...not to some position from the end of the last dragging.

Ok, thanks for that! I'm making progress. So now I am recording the mouse positions whenever the cursor is moving, then when I am dragging I stop recording the cursor and calculate the difference between the latest cursor position and the new drag coordinates:


    public void mouseMoved(MouseEvent e) {
    if(!dragging){
    lastMousePosX = e.getX();
    lastMousePosY = e.getY();
    }
    }


public void mouseDragged(MouseEvent e) {
    dragging = true;

    int newMousePosX = e.getX();
    int newMousePosY = e.getY();
   
    ew.rotateView((lastMousePosX - newMousePosX) /50, (newMousePosY - lastMousePosY) / 50);

    System.out.println("" + (lastMousePosX - newMousePosX) + " , " + (newMousePosY - lastMousePosY));
    dragging = false;
    }


This does basically what I wanted it to. Only problem is that if I am dragging left and during the drag I change direction to right the camera keeps going left, which is slightly annoying... any idea what that may be?.....

but for single direction drags this works fine, so thanks for your help!

EgonOlsen

That code doesn't make much sense to me either. What i actually meant was, to lkeave your mouseDragged-code like it was before and add a mouse listener that sets the lastMousePos? variables on mousePressed().

neo187

Hi Egon

So I am trying to improve my camera with a function that allows for it to rotate around a selected object. This code you provided in the post you mentioned does almost exactly that but it seems to make the camera rotate uniquely around the origin of the world:


        SimpleVector line=new SimpleVector(dx, 0, dy);

        Matrix m=line.normalize().getRotationMatrix();

        m.rotateAxis(m.getXAxis(), (float) -Math.PI/2f);
           
        camera.moveCamera(Camera.CAMERA_MOVEIN, 50);
        camera.rotateAxis(m.invert3x3().getXAxis(), line.length() / 200f);
        camera.moveCamera(Camera.CAMERA_MOVEOUT, 50);


I tried editing this in many ways but I cant seem to get anywhere.... would you have an input for that?

Thanks!