program 3D model orbit

edited January 2017 in How To...

Howdy, I'm making a program that shows a 3d model I import from a file.

I already have the basic stuff such as loading and displaying the model, and I calcolate the angle I want to rotate by dragging the mouse movements.

The probem is that a simple conversion to rotateX/Y/Z gives a non intuitive navigation in the 3d space.

I would like a movement similar to that seen in every 3d modeling program ever, like sketchup, autocad, etc.

An example in processing would be under /examples/demos/graphics/ribbons.

Any idea on how to do this? Or where to look at? I'm not sure of the terminology here, so every google search gave unrelated results to me.

Answers

  • look at the peasycam library, it does all this in 2 lines of code (and 1 import)

  • Do you mind to show your code?

    I am curious?

  • edited January 2017

    PeasyCam is "a dead-simple mouse-driven camera for Processing" -- it can be installed using the Processing IDE Contributions Manager > Add Library.

    For more details, see:

    ...including the minimal example that @koogs mentioned:

    PeasyCam camera;
    
    void setup() {
      camera = new PeasyCam(this, 0, 0, 0, 50);
    }
    

    For previous sketches discussed on the forum that involved orbiting planets (or protons), try looking at these threads:

    ...and these searches:

  • Thanks, I've been looking into PEasycam, it is quite interesting but is a bit...too dead easy. I will report any news.

    P.S. Did anyone notice that with sizes>200x200 the cam moves wildly?

  • edited April 2017

    You wrote:

    Did anyone notice that with sizes>200x200 the cam moves wildly?

    I haven't noticed this. Ever.

    Simple Sketch

    Here is a small approach without peasyCam (look at lines 17 and 18):

        // 3D-arrow as a PShape 
    
        PShape shapeArrow; 
    
        // -------------------------------------------------
    
        void setup() {
          size(600, 400, P3D);
          makeArrow();
        }
    
        void draw() {
          background(0);
          lights();
    
          translate(width/2, 200, 0);
          rotateY(map(mouseX, 0, width, 0, TWO_PI)); 
          rotateX(map(mouseY, 0, height, 0, TWO_PI)); 
          displayArrow();
        }
    
        // ----------------------------------------
    
        void makeArrow() {
    
          // some color consts
          final color RED = color(255, 0, 0);
          final color GREEN = color(0, 255, 0);
          final color BLUE = color(0, 0, 255);
    
          final color LIGHTGRAY = color(111);
    
          // points in 2D
          final int[] x = {
            -50, 0, 50, 25, 25, -25, -25, -50
          };
          final int[] y = {
            0, -50, 0, 0, 50, 50, 0, 0
          };
    
          // how thick is the arrow (1/2)
          final int halfOfTheThickness = 12; 
    
          shapeArrow=createShape(GROUP); 
    
          // all no Stroke
          // noStroke();
    
          // 1 -----------------------------------------
          // arrow Form - ceiling 
          PShape helperChildShape = createShape(); 
          helperChildShape.beginShape();
          helperChildShape.fill(RED); // RED
          helperChildShape.noStroke(); 
          for (int i = 0; i<8; i++) {
            helperChildShape.vertex(x[i], y[i], -halfOfTheThickness);
          }
          helperChildShape.endShape(CLOSE);
          //
          shapeArrow.addChild(helperChildShape); 
    
          // 2 -----------------------------------------
          // arrow Form - floor
          helperChildShape =  createShape();   
          helperChildShape.beginShape();
          helperChildShape.fill(GREEN); // 
          helperChildShape.noStroke(); 
          for (int i = 0; i<8; i++) {
            helperChildShape.vertex(x[i], y[i], halfOfTheThickness);
          }
          helperChildShape.endShape(CLOSE);
    
          shapeArrow.addChild(helperChildShape); 
          //
    
          // 3 -----------------------------------------
          // walls of the arrow
          helperChildShape = createShape(); 
          helperChildShape.beginShape(QUAD_STRIP);
          helperChildShape.fill(BLUE); //  
          helperChildShape.noStroke(); 
          for (int i = 0; i<x.length; i++) {
            helperChildShape.vertex(x[i], y[i], -halfOfTheThickness);
            helperChildShape.vertex(x[i], y[i], halfOfTheThickness);
          }
          helperChildShape.endShape(CLOSE);
    
          shapeArrow.addChild(helperChildShape);
        }//func
        // --------------------------------------------------------------
    
        void displayArrow() {
          shape( shapeArrow, 0, 0 );
        } // func
        //
    
  • edited April 2017

    more advanced sketch with a Camera class and different ways (try keys 0..6) :

        // see also peasycam.
        // see also http : // forum.processing.org/two/discussion/comment/16112#Comment_16112 
    
        // states of program 
        final int stateKeyboard                    = 0; 
        final int stateRotateAroundScene           = 1;
        final int stateCameraRotatesAroundItself   = 2;
        final int stateCameraBall                  = 3;
        final int stateCameraBall2                 = 4;
        final int stateCameraBall3                 = 5;
        final int stateCameraMouse                 = 6;
        int state = stateRotateAroundScene;
    
        // cubes 
        float angleCubes=45; // angle for the cubes in the scene
    
        // the camera 
        CameraClass cam; 
    
        // a ball
        PVector ballPos = new PVector (300, 300, -100);
        PVector ballVel = new PVector (1, -1, -1);
    
        // -------------------------------------------------------
    
        void setup() {
          size (1200, 600, P3D);
          cam = new CameraClass ();
        }
    
        void draw() {
          background(111);
          avoidClipping();
          lights();
    
          switch (state) {
    
          case stateCameraBall:
            cam.moveToAngle(); 
            // set the values of the class to the real camera
            cam.set();
            // make the scene with the boxes 
            scene();
            ballPos.add(ballVel);
            fill(0, 255, 0);
            noStroke();
            mySphere(ballPos.x, ballPos.y, ballPos.z, 10);
            contain();
            // upper left corner 
            cam.HUD_text("The ball mode 1. ");
            break;
    
          case stateCameraBall2:
            cam.lookAtPVector(ballPos); 
            // set the values of the class to the real camera
            cam.set();
            ballPos.add(ballVel);
            fill(0, 255, 0);
            noStroke();
            mySphere(ballPos.x, ballPos.y, ballPos.z, 10);
            contain();
            // make the scene with the boxes 
            scene();
            // upper left corner 
            cam.HUD_text("The ball mode 2. ");
            break;
    
          case stateCameraBall3:
            // follow 
            cam.follow(ballPos); 
            // set the values of the class to the real camera
            cam.set();
            // 
            ballPos.add(ballVel);
            fill(0, 255, 0);
            noStroke();
            mySphere(ballPos.x, ballPos.y, ballPos.z, 10);
            contain();
            // make the scene with the boxes 
            scene();
            // upper left corner 
            cam.HUD_text("The ball mode 3 (camera flies and follows ball). ");
            break;
    
          case stateKeyboard:
            // set the values of the class to the real camera
            cam.set();
            // cam data
            cam.printData();
            // make the scene with the boxes 
            scene();
            // upper left corner 
            cam.HUD_text("Use keyboard to move the camera. ");
            break;
    
          case stateRotateAroundScene:
            // rotate 
            cam.camCurrentAngle--;
            cam.moveToAngle(); 
            // set the values of the class to the real camera
            cam.set();
            // make the scene with the boxes 
            scene();
            // upper left corner 
            cam.HUD_text("Camera flies around a center. ");
            break;
    
          case stateCameraRotatesAroundItself:
            cam.camCurrentAngle--;
            cam.lookAtAngle();
            // set the values of the class to the real camera
            cam.set();
            // make the scene with the boxes 
            scene();
            // upper left corner 
            cam.HUD_text("Camera is fixed but rotates around itself ");
            break;
    
          case stateCameraMouse:
            // mouse 
            cam.moveToAngleWithTwoParameters(map(mouseX, 0, width, 0, 360), 
              map(mouseY, 0, height, -550, 560)  ); 
            // set the values of the class to the real camera
            cam.set();
            // make the scene with the boxes 
            scene();
            // upper left corner 
            cam.HUD_text("Camera Mouse ");
            break;
    
          default:
            // upper left corner 
            cam.HUD_text("State is not in use. This state is "
              +state
              +".");
            break;
          } // switch
        } // func 
    
        // ------------------------------------------------------------
    
        void keyPressed () {
    
          if (key==CODED) 
          {
            // special keys like cursor keys 
            switch (keyCode) { 
              //
              // 4 cursors signify parallel movement (y and x)
            case UP:
              cam.moveParallelAbsolute ( new PVector ( 0, -1, 0 ) );
              break;
            case DOWN:
              cam.moveParallelAbsolute ( new PVector ( 0, 1, 0 ) );
              break;
            case LEFT:
              cam.moveParallelAbsolute ( new PVector ( -1, 0, 0 ) );
              break;
            case RIGHT:
              cam.moveParallelAbsolute ( new PVector ( 1, 0, 0 ) );
              break;
            } // switch
          } else 
          {
            // normal keys like letters etc.
            switch (key) {
    
              // movement back and forth (Z)
            case 'w':
              cam.moveParallelAbsolute ( new PVector ( 0, 0, -1 ) );
              break;
            case 's':
              cam.moveParallelAbsolute ( new PVector ( 0, 0, 1 ) );
              break;
    
              // turn / rotate on the spot Left/Right: change camLookAt (look left / right)    
            case 'a':
              // left
              cam.camCurrentAngle--;
              cam.lookAtAngle(); 
              break;
            case 'd':
              // right
              cam.camCurrentAngle++;
              cam.lookAtAngle();
              break;
    
              // rot       
            case 'p':
              cam.camCurrentAngle--;
              cam.moveToAngle(); 
              break; 
            case 'o':
              cam.camCurrentAngle++;
              cam.moveToAngle();
              break; 
    
              // reset view completely
            case 'r':
              cam.reset();
              break; 
    
            default:
              // 
              if (key>='0' && key <= '9') {
                state = int(key)-48;
                cam.reset();
                println ("state is now "+state);
                // exit();
              } 
              break;
            } // switch
          } // else
        } // func 
    
        // ---------------------------------------------------
    
        void scene () {
    
          pushMatrix(); 
    
          stroke(2);
    
          float z ; 
    
          // one wall of boxes
          for (int x = 10; x < 600; x+= 100)
          {
            fill(x/3, 2, 2);
            for (int y = 10; y < 600; y+= 100)
            {
              z = -600;
              myBox(x, y, z, 24);
            }
            fill(0, 0, 254);
            z=-800;
            myBox(x, 10, z, 24);
          }
    
          // a few additional boxes
          fill(0, 0, 254);
          z=-400;
          myBox(220, 10, z, 24);
          myBox(600, 10, z, 24);
          z=-400;
          myBox(220, 510, z, 24);
          myBox(600, 510, z, 24);
          z=399;
          myBox(220, 510, z, 24);
          myBox(600, 510, z, 24);
          z=900;
          myBox(220, 510, z, 24);
          myBox(600, 510, z, 24);
          angleCubes++;
    
          popMatrix();
        }
    
        void myBox(float x, float y, float z, 
          float size1) {
    
          // nice wrapper for build in box-command
    
          pushMatrix();
          translate(x, y, z);
          rotateY(radians(angleCubes));
          rotateX(radians(45));
          box(size1);
          popMatrix();
        }
    
        void mySphere(float x, float y, float z, 
          float size1) {
    
          // nice wrapper for build in sphere-command
    
          pushMatrix();
          translate(x, y, z);
          rotateY(radians(angleCubes));
          rotateX(radians(45));
          sphere(size1);
          popMatrix();
        }
    
        void contain() {
    
          // for the ball: boundaries
    
          boolean changed=false;
    
          //bigger
          if (ballPos.x>500) {
            ballVel.x=abs(ballVel.x)*-1;
            changed=true;
          }
          if (ballPos.y>500) { 
            ballVel.y=abs(ballVel.y)*-1;
            changed=true;
          }
          if (ballPos.z>500) {
            ballVel.z=abs(ballVel.z)*-1;
            changed=true;
          }
    
          //smaller
          if (ballPos.x<-200) { 
            ballVel.x=abs(ballVel.x);
            changed=true;
          }
          if (ballPos.y<-200) { 
            ballVel.y=abs(ballVel.y);
            changed=true;
          }
          if (ballPos.z<-200) { 
            ballVel.z=abs(ballVel.z);
            changed=true;
          }
    
          if (changed) {
            //random
            ballVel.x+=random(-.2, .2);
            ballVel.y+=random(-.2, .2);
            ballVel.z+=random(-.1, .1);
          }
        }
    
        void avoidClipping() {
          // avoid clipping (at camera): 
          // https : // 
          // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
          perspective(PI/3.0, (float) width/height, 1, 1000000);
        }
    
        // ====================================================================
    
        class CameraClass {
    
          // capsules the normal camera() command and its vectors
    
          PVector camPos;     // camera vectors 
          PVector camLookAt;
          PVector camUp;
    
          PVector camPosInitial;     // camera vectors - the default (unchanged) 
          PVector camLookAtInitial;
          PVector camUpInitial; 
    
          // for follow
          PVector camWhereItShouldBe = new PVector(0, 0, 0);
          PVector camAdd = new PVector(10, -50, 0); // cam is a little above the ball
          float easing = .0212; // .07; // .027 // 1.0 how fast it changes
    
          float camCurrentAngle=-90;   // for cam rotation around itself (around Y-axis)
          float camRadius;             // same situation 
    
          // constructor without parameters
          CameraClass() {
            // constr
    
            // set vectors 
            camPos    = new PVector(width/2.0, height/2.0, 0);
            camLookAt = new PVector(width/2.0, height/2.0, -600);
            camUp     = new PVector( 0, 1, 0 );
    
            // save the initial values
            camPosInitial    = camPos.copy();
            camLookAtInitial = camLookAt.copy();
            camUpInitial     = camUp.copy();
          }  // constr
    
          void set() {
            // apply vectors to actual camera
            camera (camPos.x, camPos.y, camPos.z, 
              camLookAt.x, camLookAt.y, camLookAt.z, 
              camUp.x, camUp.y, camUp.z);
          }
    
          void reset() {
            // restore the initial vectors
            camPos    = camPosInitial.copy();
            camLookAt = camLookAtInitial.copy();
            camUp     = camUpInitial.copy();
          } 
    
          // -------------------------------------------------
    
          void setLookAt (float x1, float y1, float z1) {
            camLookAt = new PVector(x1, y1, z1);
          }
    
          void setPos (float x1, float y1, float z1) {
            camPos = new PVector(x1, y1, z1);
          }
    
          // -------------------------------------------------
    
          void printData() {
            println ( "Cam at " + camPos 
              + " looking at " + camLookAt 
              + " (angle = "
              +camCurrentAngle
              +").");
          }
    
          // --- rotate: two ways of rotation
          void lookAtAngle() { 
            // cam rotates in the plane (around itself); the pos of the cam is fixed.
            camRadius = camLookAt.dist (camPos); 
            camLookAt.x = camRadius * cos (radians(camCurrentAngle)) + camPos.x;
            camLookAt.z = camRadius * sin (radians(camCurrentAngle)) + camPos.z;
          }
    
          void moveToAngle() { 
            // rotate in the plane (around center of the scene); the pos of the cam flies
            // on a circle looking to its center.
            camRadius = camLookAt.dist (camPos); 
            camPos.x = (1.0 * camRadius) * cos (radians(camCurrentAngle)) + camLookAt.x;
            camPos.z = (1.0 * camRadius) * sin (radians(camCurrentAngle)) + camLookAt.z;
          }
    
          void moveToAngleWithOneParameter(float camCurrentAngle) {
            // expects degrees 
            // rotate in the plane (around center of the scene); the pos of the cam flies
            // on a circle looking to its center.
            camRadius = camLookAt.dist (camPos); 
            camPos.x = (1.0 * camRadius) * cos (radians(camCurrentAngle)) + camLookAt.x;
            camPos.z = (1.0 * camRadius) * sin (radians(camCurrentAngle)) + camLookAt.z;
          }  
    
          void moveToAngleWithTwoParameters(float camCurrentAngle1, float camHigh) {
            // expects degrees 
            // rotate in the plane (around center of the scene); the pos of the cam flies
            // on a circle looking to its center.
            camRadius = 990; // camLookAt.dist (camPos); 
            camPos.x = (1.0 * camRadius) * cos (radians(camCurrentAngle1)) + camLookAt.x;
            camPos.z = (1.0 * camRadius) * sin (radians(camCurrentAngle1)) + camLookAt.z;
    
            camPos.y = camHigh;  // not working : camPos.y = (1.0 * camRadius) * cos (radians(camCurrentAngle2)) ; //+ camLookAt.y;
            //camPos.z = (1.0 * camRadius) * sin (radians(camCurrentAngle2)) + camLookAt.z;
          }  
    
          // ---- move parallel
    
          void moveParallelAbsolute( PVector MovementParallel ) {
            // 4 cursors signify parallel movement (of lookAt and pos).
            // E.g. you fly parallel to a wall and the angle of your looking stays 90° to the wall
            // because camPos and LookAt changes the same amount.
            // Absolute here means that the movement is the same no matter whether you rotated 
            // around yourself or not (which is a difference for x and z but not for y).
            camPos.add   ( MovementParallel );
            camLookAt.add( MovementParallel );
          } // method
    
          void moveParallelRelative( PVector MovementParallel ) {
            // 4 cursors signify parallel movement (of lookAt and pos).
            // E.g. you fly parallel to a wall and the angle of your looking stays 90°.
            // Relative (or locally) here means that the movement is according your previous rotation 
            // around yourself (which is a difference for x and z but not for y).
            camPos.add   ( MovementParallel );
            camLookAt.add( MovementParallel );
          } // method
    
          // --------
    
          void lookAtPVector (PVector followMe) {
            // follows a running player (e.g.)
            camLookAt = followMe.copy();
          }
    
          void follow (PVector followMe) {
            // follows a running player or a flying ball (e.g.) at Pos followMe
            camLookAt = followMe.copy(); // could also have easing here 
    
            // behind ball but with easing
            camWhereItShouldBe.set(followMe.x+camAdd.x, followMe.y+camAdd.y, followMe.z+camAdd.z);
            camPos.x+= ( camWhereItShouldBe.x - camPos.x ) * easing; 
            camPos.y+= ( camWhereItShouldBe.y - camPos.y ) * easing;   
            camPos.z+= ( camWhereItShouldBe.z - camPos.z ) * easing;
          }
    
          // ---------------------------------
    
          void HUD_text (String a1) {
            // HUD text upper left corner 
            // this must be called at the very end of draw()
    
            // this is a 2D HUD 
            camera();
            hint(DISABLE_DEPTH_TEST);
            noLights();
            // ------------------
            textSize(16);
            fill(0, 0, 255);
            text (a1 + " Hit 0..6 to change mode.", 20, 20);
            text ("state is "
              +state, 20, height-20);
    
            // ------------------
            // reset all parameters to defaults
            textAlign(LEFT, BASELINE);
            rectMode(CORNER);
            textSize(32);
    
            // no HUD anymore
            hint(ENABLE_DEPTH_TEST); 
            lights();
          } // method
          //
        } // class
    
        // ==========================================================
    
  • @Chrisir , I've taken some bits from your code here to try and make a simple "orbital" camera... rotate around an object at the center of a scene with the ability to zoom in and out on the object. I'm using LMB+drag to navigate around the object and mouse wheel to zoom because I need to be able to move cursor within the view and right click on objects in scene without reframing the viewpoint (if that makes sense) Problem I'm now stuck on is that every time I click and drag, the view navigation/rotation will start from the position of that new 'drag'. I need to somehow save the last position and then add the magnitude of the last drag ?

    I have a horrible feeling from looking at the "ribbons" demo(even though that's rotating the objects not a camera-which I can't do) that this is going to involve some deep vector shenanigans well beyond me. Do you or anyone else have any suggestions ?

    stripped down version of code here (just a box to nav around and no right clicking to select) :

        CameraClass cam;
    
        void setup() {
          size(800, 600, P3D);
          cam = new CameraClass();
        }
    
        void draw() {
          perspective(PI/3.0, (float) width/height, 1, 1000000);
          background(0);
          stroke(255);
          noFill();
          pushMatrix();
          translate(width/2, height/2, 0);
          box(40);
          popMatrix();
          cam.run();
          //cam.printData();
        }
    
        void mouseDragged() {
          cam.mouseDragged();
        }
    
        void mousePressed(MouseEvent event) {
          if (mouseButton == LEFT) {
            if (event.getCount()==2) { // if left button double-clicked reset cam view to default
              cam.reset();
            }
          }
        }
    
        void mouseWheel(MouseEvent event) {  // mouse wheel for zoom
          float zoom = event.getCount();  
          cam.camRadius = constrain(cam.camRadius+zoom, 10, 300);
        }
    
        //---------------->>> Camera Class
        public class CameraClass {
          //--->>> class variables  
          PVector camPos, camLookAt, camUp; // camera vectors
          PVector camPosStart, camLookAtStart, camUpStart; //default start up and reset
          float theta, phi;
          float camRadius = 300;
    
          float mouseNowX, mouseNowY;
    
    
          CameraClass() {
            //setVectors
            camPos = new PVector(width/2.0, height/2.0, 300);
            camLookAt = new PVector(width/2.0, height/2.0, 0);
            camUp = new PVector(0, 1, 0);
            //save initial values
            camPosStart = camPos.copy();  
            camLookAtStart = camLookAt.copy();
            camUpStart = camUp.copy();
          }
          //--->>> Class methods
    
          void mouseDragged() {
            if (mouseButton == LEFT) {
              mouseNowX = mouseX;
              mouseNowY = mouseY;
            }
          }
    
          void run() {
            //calc angles
            cam.theta = map(mouseNowX, 0, width, 0, 360);
            cam.phi = map(mouseNowY, 0, height, 40, 240);
            cam.phi = constrain(cam.phi, 60, 220);
            //calc position from angles 
            camPos.x = (1.0* camRadius) * cos (radians(theta)) +camLookAt.x; 
            camPos.z = (1.0* camRadius) * sin (radians(theta)) +camLookAt.z;  
            camPos.y = (1.0* camRadius) * cos (radians(phi)) +camLookAt.y;           
            //apply vectors to camera
            camera(camPos.x, camPos.y, camPos.z, camLookAt.x, camLookAt.y, camLookAt.z, camUp.x, camUp.y, camUp.z);
          }
    
    
          void reset() {
            //restore starting vectors
            camPos = camPosStart.copy();
            camLookAt = camLookAtStart.copy();
            camUp = camUpStart.copy();
            camRadius = 300;
            camera(camPos.x, camPos.y, camPos.z, camLookAt.x, camLookAt.y, camLookAt.z, camUp.x, camUp.y, camUp.z);
          }
    
        } //--->>> END CLASS
    
  • I don't understand this:

    Problem I'm now stuck on is that every time I click and drag, the view navigation/rotation will start from the position of that new 'drag'.

    You mean where you click the mouse to begin the dragging the cam jumps to and that annoys you?

    Just store the mouse pos at beginning of drag (I suppose in mousePressed) and during drag take the difference and add it to the old mouse position in the cam class.

    Clear?

  • edited April 2017

    ah, much easier solution (lines 68 and 69 plus 77):

    CameraClass cam;
    
    void setup() {
      size(800, 600, P3D);
      cam = new CameraClass();
    }
    
    void draw() {
      perspective(PI/3.0, (float) width/height, 1, 1000000);
      background(0);
      lights(); 
    
      cam.run();
      //cam.printData();
    
      stroke(255);
      // noFill();
      fill(255, 21, 21);
    
      pushMatrix();
      translate(width/2, height/2, 0);
      box(40);
      popMatrix();
    }
    
    void mouseDragged() {
      cam.mouseDragged();
    }
    
    void mousePressed(MouseEvent event) {
      if (mouseButton == LEFT) {
        if (event.getCount()==2) { // if left button double-clicked reset cam view to default
          cam.reset();
        }
      }
    }
    
    void mouseWheel(MouseEvent event) {  // mouse wheel for zoom
      float zoom = event.getCount();  
      cam.camRadius = constrain(cam.camRadius+zoom, 10, 300);
    }
    
    //---------------->>> Camera Class
    public class CameraClass {
      //--->>> class variables  
      PVector camPos, camLookAt, camUp; // camera vectors
      PVector camPosStart, camLookAtStart, camUpStart; //default start up and reset
      float theta, phi;
      float camRadius = 300;
    
      float mouseNowX, mouseNowY;
    
    
      CameraClass() {
        //setVectors
        camPos = new PVector(width/2.0, height/2.0, 300);
        camLookAt = new PVector(width/2.0, height/2.0, 0);
        camUp = new PVector(0, 1, 0);
        //save initial values
        camPosStart = camPos.copy();  
        camLookAtStart = camLookAt.copy();
        camUpStart = camUp.copy();
      }
      //--->>> Class methods
    
      void mouseDragged() {
        if (mouseButton == LEFT) {
          mouseNowX += mouseX-pmouseX;
          mouseNowY += mouseY-pmouseY;
        }
      }
    
      void run() {
        //calc angles
        cam.theta = map(mouseNowX, 0, width, 0, 360);
        cam.phi = map(mouseNowY, 0, height, 40, 240);
        // cam.phi = constrain(cam.phi, 60, 220);
    
        //calc position from angles 
        camPos.x = (1.0* camRadius) * cos (radians(theta)) +camLookAt.x; 
        camPos.z = (1.0* camRadius) * sin (radians(theta)) +camLookAt.z;  
        camPos.y = (1.0* camRadius) * cos (radians(phi)) +camLookAt.y;
    
        //apply vectors to camera
        camera(camPos.x, camPos.y, camPos.z, 
          camLookAt.x, camLookAt.y, camLookAt.z, 
          camUp.x, camUp.y, camUp.z);
      }
    
    
      void reset() {
        //restore starting vectors
        camPos = camPosStart.copy();
        camLookAt = camLookAtStart.copy();
        camUp = camUpStart.copy();
        camRadius = 300;
        camera(camPos.x, camPos.y, camPos.z, camLookAt.x, camLookAt.y, camLookAt.z, camUp.x, camUp.y, camUp.z);
      }
    } //--->>> END CLASS
    
  • I need more sleep... haha was obvious. Thanks Chris ;)

Sign In or Register to comment.