Quote:let's assume I have an array of boxes (e.g. with quarks Shapes3D).
I now want to tell them to fly slowly from the current position to a new position. It would be a method like "flyTo".
This is a nice programming problem with a number of solutions some of which have already been suggested in this post. I would like to consider the problem of moving directly between two 3D positions and then see if this can be extended to non-linear paths.
Let's start by clearly defining the problem we want to solve
1) move an object (a shape from the Shape3D library) from it's current position to a user specified position (the destination)
2) the user can specify the speed or how long it should take to reach the destination.
3) the rate of movement should not be affected by the frame rate.
4) all positions will be represented by PVector objects.
5) the shape will stopped when the destination has been reached.
6) the ability to have multiple shapes following different paths.
Let's assume we have the following information
PVector s :- the position of the shape when the instruction to move was issued
PVector d :- destination for the shape
long time :- the current time
long sTime :- the time when the movement instruction was issued.
long durTime :- the amount of time allowed to reach the destination, specified when the movement instruction was issued.
PVector pos :- the current position of the shape calculated from the above info.
pos can be calculated from the following statements
Code:float factor = (time - sTime)/(float)(durTime);
if(factor > 1.0) factor = 1.0;
PVector move = PVector.mult(PVector.sub(d, s), factor);
pos = PVector.add(s, move);
NOTE each shape that we are moving will need their own variables!!!
From the analysis above we still need to consider how we are going to cope with animating multiple shapes, stopping the movement when we reach the destination and making it frame rate independent.
You can see we need many variables to control the movement of a single shape, what if we have many shapes to move - very messy.
The solution is to create our own class to represent a shape's path. The class would have a reference to the shape being moved, attributes for the variables needed to control the movement, a constructor to create a path and a method to update its position based on the current time.
The following sketch demonstrates a solution that could easily be extended by adding methods to the LinePath class to increase functionality. It would be possible to create other Path classes for non-linear paths.
This will work with any shapes from the Shapes3D library
Code:import shapes3d.utils.*;
import shapes3d.*;
class LinePath{
private Shape3D shape = null;
private PVector s, d, pos;
private long sTime, durTime;
private boolean destReached = false;
LinePath(Shape3D object, PVector dest, long duration){
shape = object;
s = shape.getPosVec();
d = new PVector(dest.x, dest.y, dest.z);
sTime = millis();
durTime = duration;
}
public void updatePos(long time){
if(!destReached){
float factor = (time - sTime)/(float)(durTime);
if(factor > 1.0) {
factor = 1.0;
destReached = true;
}
PVector move = PVector.mult(PVector.sub(d, s), factor);
pos = PVector.add(s, move);
b.moveTo(pos);
}
}
public void endMove(){
destReached = true;
}
} // end of LinePath class
Box b;
LinePath lp;
void setup(){
size(200,200,P3D);
b = new Box(this,50);
b.rotateBy(radians(45),0,radians(45));
// Move the object to a new psotion over the next 5 seconds
lp = new LinePath(b, new PVector(100,50,-50), 5000);
}
void draw(){
camera(0,0,300,0,0,0,0,1,0);
background(64);
lp.updatePos(millis());
b.draw();
}