3
\$\begingroup\$

I want to move the camera sideways (strafe). I had the following in mind, but it doesn't look like there are standard methods to achieve this in Libgdx.

If I want to move the camera sideways by x, I think I need to do the following:

  1. Create a Matrix4 mat
  2. Determine the orthogonal vector v between camera.direction and camera.up
  3. Translate mat by v*x
  4. Multiply camera.position by mat

Will this approach do what I think it does, and is it a good way to do it? And how can I do this in libgdx? I get "stuck" at step 2, as I have not found any standard method in Libgdx to calculate an orthogonal vector.

EDIT: I think I can use camera.direction.crs(camera.up) to find v. I'll try this approach tonight and see if it works.

EDIT2: I got it working and didn't need the matrix after all:

Vector3 right = camera.direction.cpy().crs(camera.up).nor();
camera.position.add(right.mul(x));
\$\endgroup\$
2
\$\begingroup\$

It'll do what you think it does. If you check the Camera class source code, you'll see that they're doing exactly what you suggest, plus they're normalizing the result:

93 final Vector3 right = new Vector3();
94
95 public void normalizeUp () {
96     right.set(direction).crs(up).nor();
97     (...)
98 }

The "standard" method of finding a vector orthogonal to two others is indeed to compute their cross product (in libgdx or anywhere).

There's an additional benefit of knowing this: if you're sure that normalizeUp() gets called in your case, you can just use camera.right directly, e.g.:

camera.position += camera.right * someFactor;
\$\endgroup\$
2
  • \$\begingroup\$ Thanks, i got it working, i came to the same conclusion a few moments ago, that i didn't really need the matrix if i had the right vector. I have to create my own right though, as it is private field. I've updated my question with the code i'm using now. \$\endgroup\$
    – Bubblewrap
    Apr 2 '12 at 17:19
  • 1
    \$\begingroup\$ Have you thought about using TweenEngine to move cameras? It can let you do some really cool effects with the camera. aurelienribon.com/blog/2011/04/java-universal-tween-engine \$\endgroup\$
    – Chuck D
    Apr 2 '12 at 17:22
0
\$\begingroup\$
boolean forward = false;
boolean back = false;
boolean right = false;
boolean left = false;

// when WASD keys are pressed, turn booleans on/off
// call this on create()
// you didn't ask for but I also included the relation between mouse and cam
// if you have a camera controller, please delete mouse moved function.
// also don't forget to override other methods.
Gdx.input.setInputProcessor(new InputProcessor() {
        private int dragX, dragY;
        @Override
        public boolean keyDown(int keycode) {
            switch (keycode) {
            case (Input.Keys.W):
                forward = true;
                break;
            case (Input.Keys.A):
                left = true;
                break;
            case (Input.Keys.S):
                back = true;
                break;
            case (Input.Keys.D):
                right = true;
                break;
            }
            return true;
        }
        @Override
        public boolean keyUp(int keycode) {
            switch (keycode) {
            case (Input.Keys.W):
                forward = false;
                break;
            case (Input.Keys.A):
                left = false;
                break;
            case (Input.Keys.S):
                back = false;
                break;
            case (Input.Keys.D):
                right = false;
                break;
            }
            return true;
        }

        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            Vector3 direction = cam.direction.cpy();

            float x = dragX -screenX;
            cam.rotate(Vector3.Y,x/5.0f);

            float y = dragY -screenY;
            cam.direction.y +=   Math.sin( y/180f) ;

            cam.update();
            dragX = screenX;
            dragY = screenY;
            return true;
        }

    });

// call on render() or anywhere you see fit.
public void walking () {
    if (forward) {
        Vector3 v = cam.direction.cpy();
        v.y=0f;
        cam.translate(v);
        cam.update();
    }
    if (back) {
        Vector3 v = cam.direction.cpy();
        v.y=0f;
        v.x = - v.x;
        v.z = - v.z;
        cam.translate(v);
        cam.update();
    }
    if (left) {
        Vector3 v = cam.direction.cpy();
        v.y=0f;
        v.rotate(Vector3.Y, 90);
        cam.translate(v);
        cam.update();
    }
    if (right) {
        Vector3 v = cam.direction.cpy();
        v.y=0f;
        v.rotate(Vector3.Y, -90);
        cam.translate(v);
        cam.update();
    }
}

In this case you need to multiply the Vector3 v with the value of x. You can multiply x, y, z one by one, right before the translation. One other thing, My up is Y axis but of course yours is probably dynamic. SO instead of using Vector3.Y, please use cam.up. I am not sure it will work, but please Experiment. And most importantly have a nice day.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .