Additional Methods for Camera Interface

Hi,



i think it would be nice to have an easy to use

camera interface. All operations are relative to

current position. If you wish i might try to give

an sample implementation of these operations.



/**

*

  • A easy to use camera interface like the one in COMPUTER GRAPHICS with
  • OpenGL (F.S. HILL, JR.).

    *
  • <code>
  • ICamera camera = …
  • camera.set(eye, look, up); // initialize, like gluLookAt, with default frustum
  • camera.slide(1, -2, 0); // slide forward and to the left
  • camera.roll(30); // roll camera 30 degree
  • camera.yaw(20); // yaw camera 20 degree
  • </code>

    *

    */

    public interface ICamera

    {

    public void set(Point3f eye, Point3f look, Vector3f up);



    public void roll(float angle);



    public void pitch (float angle);



    public void yaw(float angle);



    public void slide(float forward, float sideways, float up);



    public void setShape(float viewAngle, float aspect, float nearDistance, float farDistance); // this changes the frustum

    }

I think we are on similar pages here. However, my current design has the Camera class maintaining ONLY the view and frustum. While controllers alter the view and frustum of the camera object. This controllers (in the current jME and soon to be in the revamped jME) contain the yaw, pitch, roll methods.



I’ll reply again when I implement this into the new version and you can take a look to see if it’s how you were wanting it. Or at least acceptable variation.

if You want i could try to implement a CameraController.

This should enable game developers to implement a flying

camera. This then can be used for ingame-graphic-animations when

the charakter dies or as a level introduction flythrough.



I think this CameraController would also be useful when implementing further

InputControllers since these could be based on the CameraController than on the Camera

directly. This would lead (and thats the central idea) to less code redundancy.



I concretely faced the problem as i tried to roll the camera using

FirstPersonInputController. I like to take the mouse to look around and

to take keys to slide and to roll. So I have to implement my own InputController

to bind the roll operation to some keys.

Please do! I wrote the InputControllers and InputActions in such as way as to allow for easy creation of new Controllers (hopefully). This will be the perfect test to see if the design is solid. Please create the fly through and let me know what your thoughts are.

I have written a class that implements this interface:



public interface ICamera
{
        public abstract void slide(final Vector3f v);
        public abstract void roll(final float angle);
        public abstract void pitch(final float angle);
        public abstract void yaw(final float angle);
        public abstract void slideLeft(float units);
        public abstract void slideRight(float units);
        public abstract void slideForward(float units);
        public abstract void slideBack(float units);
        public abstract void slideUp(final float units);
        public abstract void slideDown(final float units);
}



The code is:


public class RollPitchYawCamera implements ICamera
{
        private Camera camera;

        private final static double rad = Math.PI / 180;

        private RollPitchYawCamera(final Camera c)
        {
                this.camera = c;
        }

        public void slide(final Vector3f v)
        {
                this.camera.getLocation().add(v);
                this.camera.update();
        }

        public void slideLeft(final float unit)
        {
                Vector3f u = this.camera.getLocation();
                Vector3f v = this.camera.getLeft();

                u.x += v.x * unit;
                u.y += v.y * unit;
                u.z += v.z * unit;

                this.camera.update();
        }

        public void slideRight(final float unit)
        {
                Vector3f u = this.camera.getLocation();
                Vector3f v = this.camera.getLeft();

                u.x -= v.x * unit;
                u.y -= v.y * unit;
                u.z -= v.z * unit;

                this.camera.update();
        }

        public void slideForward(final float unit)
        {
                Vector3f u = this.camera.getLocation();
                Vector3f v = this.camera.getDirection();

                u.x += v.x * unit;
                u.y += v.y * unit;
                u.z += v.z * unit;

                this.camera.update();
        }

        public void slideBack(final float unit)
        {
                Vector3f u = this.camera.getLocation();
                Vector3f v = this.camera.getDirection();

                u.x -= v.x * unit;
                u.y -= v.y * unit;
                u.z -= v.z * unit;

                this.camera.update();
        }

        public void slideUp(final float unit)
        {
                Vector3f u = this.camera.getLocation();
                Vector3f v = this.camera.getUp();

                u.x += v.x * unit;
                u.y += v.y * unit;
                u.z += v.z * unit;

                this.camera.update();
        }

        public void slideDown(final float unit)
        {
                Vector3f u = this.camera.getLocation();
                Vector3f v = this.camera.getUp();

                u.x -= v.x * unit;
                u.y -= v.y * unit;
                u.z -= v.z * unit;

                this.camera.update();
        }

        public void roll(final float angle)
        {
                double xRad = rad * angle;

                float cs = (float) Math.cos(xRad);
                float sn = (float) Math.sin(xRad);

                Vector3f u = this.camera.getLeft();
                Vector3f v = this.camera.getUp();

                this.camera.setLeft(
                        new Vector3f(
                                cs * u.x - sn * v.x,
                                cs * u.y - sn * v.y,
                                cs * u.z - sn * v.z));

                v.x = sn * u.x + cs * v.x;
                v.y = sn * u.y + cs * v.y;
                v.z = sn * u.z + cs * v.z;

                this.camera.update();
        }

        public void pitch(final float angle)
        {
                double xRad = rad * angle;

                float cs = (float) Math.cos(xRad);
                float sn = (float) Math.sin(xRad);

                Vector3f u = this.camera.getDirection();
                Vector3f v = this.camera.getUp();

                this.camera.setDirection(
                        new Vector3f(
                                cs * u.x - sn * v.x,
                                cs * u.y - sn * v.y,
                                cs * u.z - sn * v.z));

                v.x = sn * u.x + cs * v.x;
                v.y = sn * u.y + cs * v.y;
                v.z = sn * u.z + cs * v.z;

                this.camera.update();
        }

        public void yaw(final float angle)
        {
                double xRad = rad * angle;

                float cs = (float) Math.cos(xRad);
                float sn = (float) Math.sin(xRad);

                Vector3f u = this.camera.getDirection();
                Vector3f v = this.camera.getLeft();

                this.camera.setDirection(
                        new Vector3f(
                                cs * u.x - sn * v.x,
                                cs * u.y - sn * v.y,
                                cs * u.z - sn * v.z));

                v.x = sn * u.x + cs * v.x;
                v.y = sn * u.y + cs * v.y;
                v.z = sn * u.z + cs * v.z;

                this.camera.update();
        }

        public static ICamera createCamera(Camera camera)
        {
                return new RollPitchYawCamera(camera);
        }
}


Passing a JME Camera to the createCamera Method creates
a new camera with pitch(), yaw () and roll () methods. This enables me to create my fly through. But it could also be used
by InputActions:


        public static class Roll implements InputAction
        {
      private ICamera camera;
      private float angle;
                public Roll(final ICamera camera, final float angle)
                {
                        this.camera = camera;
         this.angle =  angle;
                }
 
                public void performAction(float time)
                {
                        this.camera.roll(this.angle);
                }
        }


But from my point of view a fly through is not an InputAction,
it is triggered by a timer --- maybe like

java.util.Timer

So maybe there is a need for this other kind of controller that emits camera movement
events in regular time intervalls.

PS: Your InputControllers/InputAction-Pattern works well and
is very easy to understand and extend. Good design.

Oops. I have just seen there is already functionality of a timer

in jme. I will look at it and see how i have to use it. Sorry.

That definately looks promising. So, once you get it working to your own satisfaction, I’d love to get a copy to see it in action.