Follow vector path

Thanks

here is a simple movement using curvepoint (comparable to lerp)

A more complex sketch

here is a more complex sketch:

The ArrayList<PointMy> listPointMy are the vectors (I my sketch this is a track for a rollercoaster);
you want to look at function rollerCoaster()

Chrisir


// Track for the rollercoaster: 
// holding the curveVertex points in 3D - the core data. Here you add and edit your points. 
ArrayList<PointMy> listPointMy = new ArrayList();

// move a sphere along the curve (Rollercoaster) 
boolean showRollercoasterFlag = false; 
int showRollercoaster_i; // current number of sphere on track for the Rollercoaster CAR 
int i2=0; // counter for the taken steps between 2 single points of track for rollercoaster  
boolean firstTime=true;
PVector camPV=new PVector();

// ---------------------------------------------------------------------
// CORE functions 

void setup() {
  size(1440, 880, P3D);
  background(255);

  makeArrayList();  // the track
}// func 

void draw() {
  drawForNormal();
}//draw

//------------------------------------------------------------------------------

void drawForNormal() {

  background(255);
  lights();

  // show ArrayList
  showArrayList(); 

  if (true) {
    rollerCoaster();
  }//if
}// func 

// -------------------------------------------------------------------------

void makeArrayList() {
  // http://de.wikipedia.org/wiki/Ellipse#Ellipsengleichung_.28Parameterform.29

  float radiusX=300; 
  float radiusY=110;

  float centerX=0;
  float centerZ=0; 

  for (int angleStar = 0; angleStar <= 360; angleStar += 4) {

    float starX = centerX + (cos (radians(angleStar)) * radiusX);
    float starY = 0;
    float starZ = centerZ + (sin (radians(angleStar)) * radiusY);

    // the part on the right gets elevated 
    if (starX>220) {
      starY=map(starX-220, 0, 310, -10, -420);
    }

    PVector newPVector = new PVector(starX, starY, starZ);
    listPointMy.add (  new PointMy ( newPVector, false) );   // 3D
  }//for
  listPointMy.get(65).p.y -= 155;
}//func 

void showArrayList() {
  // show the curve 

  noFill();
  stroke(0);
  beginShape();
  int i=0;
  if (listPointMy.size()>0) {
    listPointMy.get(i).useAsCurveVertexPVector();
    for ( i = 0; i < listPointMy.size(); i++) {
      listPointMy.get(i).useAsCurveVertexPVector();
    }
    i=listPointMy.size()-1;
    listPointMy.get(i).useAsCurveVertexPVector();
  }//if
  endShape();

  //show the points (additionally)
  noStroke();
  float rad=3;
  for ( i = 0; i < listPointMy.size(); i++) {
    PointMy pm = listPointMy.get(i);
    PVector pv=pm.p;
    // if we are close to the mouse, color green, else red
    if (dist(mouseX, mouseY, pv.x, pv.y)<11 || pm.selected) {
      // near to mouse 
      fill( 0, 255, 0); // green
      rad=7;
    } else {
      // normal 
      fill(255, 0, 0);  // red
      rad=3;
    }
    pm.showAsSphere(rad);
  }//for
}//func

// ------------------------------------------------------------------------

// interprete the spline as a rollercoaster track with a CAR on it

void rollerCoaster() {

  ellipseMode(CENTER);

  // get two points between which the CAR currently is running  
  PointMy pm1=listPointMy.get( showRollercoaster_i );
  PointMy pm2=listPointMy.get( showRollercoaster_i+1 ); 

  // get dist between 2 points 
  float dist1 = pm1.p.dist(pm2.p);
  // calculate the steps between the 2 points depending on dist1 between them (smooth running) 
  int steps; // = 9;
  steps = int(dist1 / 2);

  // calc t (can be seen as amt in lerp() / curvePoint) 
  float t = i2 / float(steps);

  // similar to lerp() wth amt:  
  float x = curvePoint(pm1.p.x, pm1.p.x, pm2.p.x, pm2.p.x, t);
  float y = curvePoint(pm1.p.y, pm1.p.y, pm2.p.y, pm2.p.y, t);
  float z = curvePoint(pm1.p.z, pm1.p.z, pm2.p.z, pm2.p.z, t);

  // different camera view for rollercoaster view
  setRollerCoasterCamera(x, y, z, t); 

  // show ball&box [the rollercoaster car] 
  if (true) { 
    fill(255, 2, 244);
    noStroke(); 
    pushMatrix(); 
    translate(x, y, z);
    box(9);
    translate(0, -5, 0);
    sphere(7); 
    popMatrix();
  }

  i2++; 
  if (i2>steps) {
    showRollercoaster_i++; 
    if (showRollercoaster_i>listPointMy.size()-2) { // little rough management at the end of arraylist... ??? 
      showRollercoaster_i=0;
    }//if
    i2=0;
  }//if
}//func

void setRollerCoasterCamera(float x, float y, float z, 
  float t) {
  // camera view for rollercoaster view 
  camPV = getCameraPositionFromBall(x, y, z); 
  camera(camPV.x, camPV.y-4, camPV.z, 
    0, 0, 0, 
    0, 1, 0);
}//func 

PVector getCameraPositionFromBall(float bx, float by, float bz) {

  // leading to a result that has the points nicely on a circle. 

  // Usage: centerPV is at the center of a virtual circle, outsidePV on its circumference. 
  // Function returns the point (new PVector(x1, y1, z1)) with the radius radius1 that prolongs the Radius 
  // from centerPV over outsidePV (further out) to the resulting PVector new PVector(x1, y1, z1).

  PVector centerPV  = new PVector(0, 0, 0); 
  PVector outsidePV = new PVector(bx, by, bz);

  float angle1 = atan2(outsidePV.z-centerPV.z, outsidePV.x-centerPV.x);

  float radius1 = 0;// pre-init
  // adjust : we calculate the radius here
  // radius1 = 700/2 + 120;

  float d0 = centerPV.dist(outsidePV);
  // d0 = dist(centerPV.x, centerPV.y, outsidePV.x, outsidePV.y);
  float d1 = map (d0, 10, 1000, 140, 1450); // float d1 = map (d0, 10, 1000, 40, 1350);
  radius1 = d1; 

  float x1 = cos(angle1) * radius1 + centerPV.x;
  float y1 = 0;
  //y1 = lerp(centerPV.y, outsidePV.y, map (d0, 10, 1000, 1.5, 1.9));
  //y1 = lerp(centerPV.y, outsidePV.y, 1.3);
  y1 = outsidePV.y-26;
  float z1 = sin(angle1) * radius1 + centerPV.y;

  return new PVector(x1, y1, z1);
} // method 

// ==================================================================

class PointMy {

  // one point one the track 

  PVector p;  // position 
  boolean selected=false; // selected y/n

  float theX, theY;  // screenX and screenY

  // constructor 
  PointMy( PVector p_, boolean selected_ ) {
    p        = p_.copy();
    selected = selected_;
  } // constructor

  void showAsSphere( float rad ) {
    pushMatrix();
    translate(p.x, p.y, p.z);

    theX = screenX(0, 0, 0);  // monitor and store screen position 
    theY = screenY(0, 0, 0);

    noStroke();
    sphere(rad); 
    popMatrix();
  } // method

  void useAsCurveVertexPVector() {
    // like curveVertex but gets a PVector as input  
    // (just an easy way to use vectors for curveVertex)
    curveVertex(p.x, p.y, p.z);
  } // method 
  //
}//class
//