PeasyCam change/disable DampedAction

engeng
edited July 2017 in Library Questions

I have an urgent question about PeasyCam's damping property.. When I use PeasyCam to rotate a 3D object, after the mouse stops the object still moves with a decreasing velocity (damping). PeasyCam has a class called DampedAction for this movement. My question is: How can I change the damping value (original 0.16) or disable the damping property. For example in the PeasyCam sample bellow I would like to change (extend) this class in peasy library or Override it.. How is it possible to do it in this code:

import peasy.*;

PeasyCam cam;

void setup() {
  size(800,600,P3D);
  cam = new PeasyCam(this, 100);
  cam.setMinimumDistance(50);
  cam.setMaximumDistance(500);
}

void draw() {
  rotateX(-.5);
  rotateY(-.5);
  background(0);
  fill(255,0,0);
  box(50);
  pushMatrix();
  translate(0,0,30);
  fill(0,0,255);
  box(5);
  popMatrix();
}

Thanks for any help!..

Answers

  • edited July 2017

    Check out a previous discussion here:

    If you want to do it yourself, one guess at a starting point: here is the constructor for a DampedAction with a custom friction:

    - https://github.com/jdf/peasycam/blob/master/src/peasy/DampedAction.java#L38

    ...and here are the DampedActions built into a PeasyCam object:

    Perhaps you could extend this PeasyCam constructor:

    public PeasyCam(final PApplet parent, PGraphics pg,
      final double lookAtX, final double lookAtY,
      final double lookAtZ, final double distance) {
    

    ...and also pass in a friction value, which the constructor would in turn would pass it to new DampedAction constructors.

    Alternately, create a setFriction() method.

  • Thank you very much for your reply.. I have read the previous discussion before, but I couldn't make it work. I also would like to use the original peasy library and make it in my own code if possible. Creating something like setFriction() method is exactly what I am looking for, but I don't know how to make it. Could you please give a sample setFriction() code? Thanks..

  • edited July 2017

    I'd suggest starting by looking at the setDamping() example code linked from the previous discussion. You should either extend PeasyCam or else edit the library and create your own version -- or contribute a commit to the main peasycam repo.

  • I have also tried to use the PeasyCam+ library. Dowloaded it and there is a "core.jar" file in a lib folder (instead of peasycam.jar in library folder). I have no idea, what to do with it.. If I use the peasy+ files in peasy folder it won't work.. How should I use this peasycam+ library? Where and how to locate it?.. Please help..

  • Well, the simplest of all possible ways to change it is to fork PeasyCam on github and change 0.16 to some other value.

  • Isn't the simplest way to use the hook already within peasycam to set your own drag handler?

  • @ jeremydouglass

    I have tried to change DampedAction.java in PeasyCam package, but I could not make class files and jar file (using javac). I don't have enough knowledge for that. Could you please give a link showing how to do it or an example?.. Thanks..

    @koogs

    I don't think we can change the damping with drag handler.. Is it possible? It could be a perfect solution. Could you please give an example how to do it?

  • In the peasy source there is setLeftDragHandler, and two others for right and centre.

    public void setLeftDragHandler(final PeasyDragHandler handler) {
        leftDragHandler = handler;
    }
    

    this is initially set to

    private PeasyDragHandler leftDragHandler = rotateHandler;
    

    which is defined immeditely above that as

    private final PeasyDragHandler rotateHandler = new PeasyDragHandler() {
        public void handleDrag(final double dx, final double dy) {
            mouseRotate(dx, dy);
        }
    };
    

    which is defined on line 332

    https://github.com/jdf/peasycam/blob/master/src/peasy/PeasyCam.java#L332

    so just copy that code, change it to what you want and call setLeftDragHandler with your new code. no need to recompile peasycam.

    i would guess it'd just be a case of returning mouseRotate(dx, dy) without the handleDrag wrapper. (DragHandler is just an interface, contains no code)

  • edited July 2017

    @koogs -- very nice -- I didn't realize that the set*DragHandler methods were there.

  • i've never used them tbh 8)

  • engeng
    edited July 2017

    I think that I am missing something.

    I have tried to use setLeftDragHandler, but I don't know if you mean that..

    Here is the code:

    import peasy.*;
    
    PeasyCam cam;
    
    void setup() {
      size(800,600,P3D);
      cam = new PeasyCam(this, 100);
      cam.setMinimumDistance(50);
      cam.setMaximumDistance(500);
    
      PeasyDragHandler RotateDragHandler;
      RotateDragHandler = cam.getRotateDragHandler();
      cam.setLeftDragHandler(RotateDragHandler);
    }
    
    void draw() {
      rotateX(-.5);
      //rotateY(-.5);
      background(0);
      fill(255,0,0);
      box(50);
      pushMatrix();
      translate(0,0,30);
      fill(0,0,255);
      box(5);
      popMatrix();
    }
    

    But it did not change anything..

    mouseRotate(dx, dy); uses RotateX, RotateY, RotateZ which are difined as damped rotations:

    rotateX = new DampedAction(this) {
        @ Override
        protected void behave(final double velocity) {
            rotation = rotation.applyTo(new Rotation(Vector3D.plusI, velocity));
        }
    };
    

    So what am I doing wrong?

  • ok, problems.

    the rotateX, rotateY and rotateZ members are dampedActions and private final and any drag handler only calls impulse() on those (which is a velocity rather than an absolute, and the damping is done there, not in the drag handler)

    you might be able to write a drag handler that calls cam.rotateX etc to set the rotation (absolute position rather than a velocity). but i've had no luck so far.

  • Answer ✓

    ok, this is better. not sure it's what you want though.

    // in setup
    cam.setLeftDragHandler(new MyHandler(this, cam));
    
    
    
    // this code goes in a new JAVA tab called MyHandler.java
    import processing.core.PApplet;
    import peasy.PeasyCam;
    import peasy.PeasyDragHandler;
    import peasy.org.apache.commons.math.geometry.Vector3D;
    
    class MyHandler implements PeasyDragHandler {
    
      // copied from PeasyCam
      private static final Vector3D LOOK = Vector3D.plusK;
      // this is the distance set in the peasycam constructor
      private final double startDistance = 100f;
    
      PeasyCam cam;
      PApplet p;
    
      MyHandler(PApplet p, PeasyCam cam) {
        this.cam = cam;
        this.p = p;
      }
    
      // based on peasycam.mouseRotate() but using rotate[XYZ]() rather than rotate[XYZ].impulse()
      // it's basically just trackball maths
      public void handleDrag(final double dx, final double dy) {
        final Vector3D u = LOOK.scalarMultiply(100 + .6 * startDistance).negate();
    
        final int xSign = dx > 0 ? -1 : 1;
        final int ySign = dy < 0 ? -1 : 1;
    
        final double eccentricity = Math.abs((p.height / 2d) - p.mouseY)
            / (p.height / 2d);
        final double rho = Math.abs((p.width / 2d) - p.mouseX) / (p.width / 2d);
        final double adx = Math.abs(dx) * (1 - eccentricity);
        final Vector3D vx = u.add(new Vector3D(adx, 0, 0));
        cam.rotateY(Vector3D.angle(u, vx) * xSign);
        final double ady = Math.abs(dy) * (1 - rho);
        final Vector3D vy = u.add(new Vector3D(0, ady, 0));
        cam.rotateX(Vector3D.angle(u, vy) * ySign);
        {
        final double adz = Math.abs(dy) * rho;
        final Vector3D vz = u.add(new Vector3D(0, adz, 0));
        cam.rotateZ(Vector3D.angle(u, vz) * -ySign
            * (p.mouseX < p.width / 2 ? -1 : 1));
        }
        {
        final double adz = Math.abs(dx) * eccentricity;
        final Vector3D vz = u.add(new Vector3D(0, adz, 0));
        cam.rotateZ(Vector3D.angle(u, vz) * xSign
            * (p.mouseY > p.height / 2 ? -1 : 1));
        }
      }
    }
    
  • koogs thank you very much for the code.. I didn't think to make it with drag handlers.. It works like I want, without damping..

    I didn't make any MyHandler.jave, but put your class in the code.. I have used both damping movement with left drag and base mouse movement with right drag to show the difference..

    Here is the end code:

    import peasy.*;
    import processing.core.PApplet;
    import peasy.org.apache.commons.math.geometry.Vector3D;
    
    PeasyCam cam;
      private static final Vector3D LOOK = Vector3D.plusK;
    
    void setup() {
      size(800,600,P3D);
      cam = new PeasyCam(this, 100);
      cam.setMinimumDistance(50);
      cam.setMaximumDistance(500);
      cam.setRightDragHandler(new MyHandler(this, cam));
    }
    
    void draw() {
      rotateX(-.5);
      //rotateY(-.5);
      background(0);
      fill(255,0,0);
      box(50);
      pushMatrix();
      translate(0,0,30);
      fill(0,0,255);
      box(5);
      popMatrix();
    }
    
    class MyHandler implements PeasyDragHandler {
      private final double startDistance = 100f;
    
      PeasyCam cam;
      PApplet p;
    
      MyHandler(PApplet p, PeasyCam cam) {
        this.cam = cam;
        this.p = p;
      }
    
      public void handleDrag(final double dx, final double dy) {
        final Vector3D u = LOOK.scalarMultiply(100 + .6 * startDistance).negate();
    
        final int xSign = dx > 0 ? -1 : 1;
        final int ySign = dy < 0 ? -1 : 1;
    
        final double eccentricity = Math.abs((p.height / 2d) - p.mouseY)
            / (p.height / 2d);
        final double rho = Math.abs((p.width / 2d) - p.mouseX) / (p.width / 2d);
        final double adx = Math.abs(dx) * (1 - eccentricity);
        final Vector3D vx = u.add(new Vector3D(adx, 0, 0));
        cam.rotateY(Vector3D.angle(u, vx) * xSign);
        final double ady = Math.abs(dy) * (1 - rho);
        final Vector3D vy = u.add(new Vector3D(0, ady, 0));
        cam.rotateX(Vector3D.angle(u, vy) * ySign);
        {
        final double adz = Math.abs(dy) * rho;
        final Vector3D vz = u.add(new Vector3D(0, adz, 0));
        cam.rotateZ(Vector3D.angle(u, vz) * -ySign
            * (p.mouseX < p.width / 2 ? -1 : 1));
        }
        {
        final double adz = Math.abs(dx) * eccentricity;
        final Vector3D vz = u.add(new Vector3D(0, adz, 0));
        cam.rotateZ(Vector3D.angle(u, vz) * xSign
            * (p.mouseY > p.height / 2 ? -1 : 1));
        }
      }
    }
    
  • Now I have a little question more..

    If I move the mouse, I want that the object rotates more.. It means that I would like to change the rotation angle/ mouse movement ratio.

    How can I make it in this class??

  • Answer ✓

    (i put the handler into a java class because processing compiler was complaining about calling rotateX, which i guess was due to the fact there's a member called rotateX and a method called rotateX(). it shouldn't, really, but it was. after moving it to a java class it stopped complaining)

    making it rotate faster might just be a case of adding a multiplier to each of the 4 rotation angles. and / or multiplying the distance moved by the mouse, maybe by modifying dx and dy (which i'm guessing are the delta movements) right at the start of the method. but i can't check that here / now.

  • OK, I did it. I just made a multiplier (rmult), to control rotation angle..

    import peasy.*;
    import processing.core.PApplet;
    import peasy.org.apache.commons.math.geometry.Vector3D;
    
    PeasyCam cam;
    private static final Vector3D LOOK = Vector3D.plusK;
    float rmult= 3.0;  
    
    void setup() {
      size(800,600,P3D);
      cam = new PeasyCam(this, 100);
      cam.setMinimumDistance(50);
      cam.setMaximumDistance(500);
      cam.setRightDragHandler(new MyHandler(this, cam));
    }
    
    void draw() {
      rotateX(-.5);
      //rotateY(-.5);
      background(0);
      fill(255,0,0);
      box(50);
      pushMatrix();
      translate(0,0,30);
      fill(0,0,255);
      box(5);
      popMatrix();
    }
    
    class MyHandler implements PeasyDragHandler {
      private final double startDistance = 100f;
    
      PeasyCam cam;
      PApplet p;
    
      MyHandler(PApplet p, PeasyCam cam) {
        this.cam = cam;
        this.p = p;
      }
    
      public void handleDrag(final double dx, final double dy) {
        final Vector3D u = LOOK.scalarMultiply(100 + .6 * startDistance).negate();
    
        final int xSign = dx > 0 ? -1 : 1;
        final int ySign = dy < 0 ? -1 : 1;
    
        final double eccentricity = Math.abs((p.height / 2d) - p.mouseY) / (p.height / 2d);
        final double rho = Math.abs((p.width / 2d) - p.mouseX) / (p.width / 2d);
        final double adx = Math.abs(dx) * (1 - eccentricity);
        final Vector3D vx = u.add(new Vector3D(adx, 0, 0));
        cam.rotateY(Vector3D.angle(u, vx) * xSign * rmult);
        final double ady = Math.abs(dy) * (1 - rho);
        final Vector3D vy = u.add(new Vector3D(0, ady, 0));
        cam.rotateX(Vector3D.angle(u, vy) * ySign * rmult);
        {
        final double adz = Math.abs(dy) * rho;
        final Vector3D vz = u.add(new Vector3D(0, adz, 0));
        cam.rotateZ(Vector3D.angle(u, vz) * -ySign * (p.mouseX < p.width / 2 ? -1 : 1) * rmult);
        }
        {
        final double adz = Math.abs(dx) * eccentricity;
        final Vector3D vz = u.add(new Vector3D(0, adz, 0));
        cam.rotateZ(Vector3D.angle(u, vz) * xSign * (p.mouseY > p.height / 2 ? -1 : 1) * rmult);
        }
      }
    }
    

    @koogs Thank you very much for your ideas!..

Sign In or Register to comment.