perlin noise movement
in
Contributed Library Questions
•
1 year ago
Hey guys
Ive made this flocking type sketch, which will drive 5 robotic arms for an installation. What i want to do is make a function that will add a contant perlin noise movement to the balls you see in the sketch, so they do not remain still.
a bit like this -
I cannot get my head round how noise works for this. can someone help me write a function into the sketch? Or give me an example to work from?
thanks in advance!
Rich
import toxi.geom.*;
//DECLARE
ArrayList ballCollection;
Ball ball1; //class "Ball" is now a variable type, ball1 is an instance of a variable
//for delayFollow:
float lastTriggered = 900000000;
boolean eventOneTriggered = false;
boolean eventTwoTriggered = false;
int closestToAudience = 0;
void setup() {
size(500, 500);
smooth();
//INITIALISE CLASS VARIABLE
ballCollection = new ArrayList();
ballCollection.add(new Ball(new Vec3D(150, 150, 0)));
ballCollection.add(new Ball(new Vec3D(350, 150, 0)));
ballCollection.add(new Ball(new Vec3D(250, 250, 0)));
ballCollection.add(new Ball(new Vec3D(150, 350, 0)));
ballCollection.add(new Ball(new Vec3D(350, 350, 0)));
}//close setup
float getTiltAngle(int ballIndex)
{
return ((Ball)ballCollection.get(ballIndex)).getTiltAngle();
}
float getPanAngle(int ballIndex)
{
return ((Ball)ballCollection.get(ballIndex)).getPanAngle();
}
void draw() {
background(0);
int closestToAudience = 0;
float motorDistanceToAudience = 0;
for (int i = 0; i < ballCollection.size(); i ++) {
// find which motor is closes to the audience
float c = ((Ball)ballCollection.get(i)).distToAudience();
if (i == 0 || c < motorDistanceToAudience) {
motorDistanceToAudience = c;
closestToAudience = i;
}
}
//CALL FUNCTIONALITY
for (int i = 0; i < ballCollection.size(); i ++) {
Ball theBall = (Ball) ballCollection.get(i);
theBall.run(i == closestToAudience);
}
/* prints motor angle information:
Ball b = (Ball) ballCollection.get(0);
print((b.loc.x - b.circle.x) + ", ");
print((b.loc.y - b.circle.y) + "\t");
print((getPanAngle(0) * (180 / PI)) + "\t"); //last bit of line just coverts from radians to degrees
println(getTiltAngle(0) * (180 / PI));
*/
delayFollow();
if ( eventOneTriggered == true ) {
closeFollow();
}
if ( eventTwoTriggered == true ) {
farFollow();
}
}//close draw
void delayFollow() {
/*
desired functionality (using array object "1" as example)
if mouseclicked && closest to audience = 1, then motor 0 & 5 follow mouse in
random(3, 6 seconds), motor 4 follow in random(6, 9 seconds)
*/
float timeDlyCloser = random( 1000, 3000 );
float timeDlyFar = random( 3500, 6000 );
if ( millis()-lastTriggered > timeDlyCloser && !eventOneTriggered ) {
println( "" + timeDlyCloser + " milliseconds passed - Trigger Event One");
eventOneTriggered = true;
}
if ( millis()-lastTriggered > timeDlyFar && !eventTwoTriggered ) {
println( "" + timeDlyFar + " milliseconds passed - Trigger Event Two");
eventTwoTriggered = true;
(( Ball )ballCollection.get( 3 )).run( true );
}
}
void mousePressed() {
lastTriggered = millis();
//events below are "false" because draw() will constantly loop through checking the status,
//so having this "true" would repeatedly send the messages
eventOneTriggered = false;
eventTwoTriggered = false;
}
void closeFollow() {
//this applies a function to just on element in the list -
(( Ball )ballCollection.get( 0 )).run( true );
(( Ball )ballCollection.get( 1 )).run( true );
(( Ball )ballCollection.get( 2 )).run( true );
(( Ball )ballCollection.get( 4 )).run( true );
}
void farFollow() {
(( Ball )ballCollection.get( 3 )).run( true );
}
class Ball {
//GLOBAL VARIABLES
// static variable : not specific to each instance, but for the class itself
// final : value cannot be changed once set
static final float vDistanceToPlaneMM = 620;
static final float maxTiltAngle = 50 * (PI / 180);
static final int radius = 250;
final float pixelToMMRatio = tan(maxTiltAngle) * vDistanceToPlaneMM / (radius / 2);
Vec3D loc = new Vec3D (0, 0, 0);
Vec3D speed = new Vec3D (random(-2, 2), random(-2, 2), 0);
Vec3D grav = new Vec3D (0, 0.2, 0);
Vec3D acc = new Vec3D (0, 0, 0);
Vec3D circle;
float easing;
//CONSTRUCTOR (this code happens once when the class is called)
Ball(Vec3D _loc) { //these 2 floats are only available inside the constructor
loc = _loc;
easing = 0.05;
circle = new Vec3D(loc);
}
//GROUPED FUNCTIONS
void run(boolean leader) { //emcompasses other functions
display();
//bounce();
// gravity();
// lineBetween();
if (leader)
lead();
else
{
// mover();
flock();
}
}
void flock() { //emcompasses flocking rule functions
separate(5); //(float) = magnitude. put these as variables at top.
cohesion(5.5);
align(10.1);
}
//FUNCTIONS
float getPanAngle()
{
float x = loc.x - circle.x;
float y = loc.y - circle.y;
if (x == 0)
{
if (y > 0)
return PI / 2;
else
return (3 * PI)/2;
}
float P = atan(y / x);
if (x > 0 && y > 0)
return P;
if (x < 0 && y > 0)
return P + PI;
if (x > 0 && y < 0)
return P + 2 * PI;
if (x < 0 && y < 0)
return P + PI;
// Never reached
return 0;
}
float getTiltAngle()
{
float x = loc.x - circle.x;
float y = loc.y - circle.y;
float r = sqrt(pow(x, 2) + pow(y, 2));
return atan(r / (vDistanceToPlaneMM / pixelToMMRatio));
}
void lead() {
Vec3D m = new Vec3D(mouseX, mouseY, 0);
if (dist(m.x, m.y, circle.x, circle.y) > radius/2) {
m.subSelf(circle);
m.normalize();
m.scaleSelf(radius/2);
m.addSelf(circle);
}
loc.x = loc.x + (m.x - loc.x) * easing;
loc.y = loc.y + (m.y - loc.y) * easing;
}
void constrainSoftener()
{
float multiplier = (radius/2 - circle.distanceTo(loc)) / (radius/2);
speed.scaleSelf(multiplier);
}
/////////////
void separate(float magnitude) {
Vec3D steer = new Vec3D();
int count = 0;
for (int i = 0; i < ballCollection.size(); i ++) {
Ball other = (Ball) ballCollection.get(i);
float distance = loc.distanceTo(other.loc);
if (distance > 0 && distance < 30) {
Vec3D diff = loc.sub(other.loc);
diff.normalizeTo(1.0/distance); //smoothing sep. motion
steer.addSelf(diff);
count++;
}
}
if (count > 0) {
steer.scaleSelf(1.0/count);
}
steer.scaleSelf(magnitude);
acc.addSelf(steer);
}//close separate
void cohesion(float coMagnitude) {
Vec3D sum = new Vec3D();
int count = 0;
for (int i = 0; i < ballCollection.size(); i ++) {
Ball other = (Ball) ballCollection.get(i);
float distance = loc.distanceTo(other.loc);
if (distance > 0 && distance < 200) { //2nd float is the max distance at which an average will be taken
sum.addSelf(other.loc);
count++;
}
}
if (count > 0) {
sum.scaleSelf(1.0/count);
}
Vec3D steer = sum.sub(loc);
steer.scaleSelf(coMagnitude);
acc.addSelf(steer);
}//close cohesion
void align(float aliMagnitude) {
Vec3D steer = new Vec3D();
int count = 0;
for (int i = 0; i < ballCollection.size(); i ++) {
Ball other = (Ball) ballCollection.get(i);
float distance = loc.distanceTo(other.loc);
if (distance > 0 && distance < 40) {
steer.addSelf(other.speed);
count++;
}
}
if (count > 0) {
steer.scaleSelf(1.0/count);
}
steer.scaleSelf(aliMagnitude);
acc.addSelf(steer);
} //close align
//////////
void display() {
stroke(0);
fill(255);
ellipse(loc.x, loc.y, 10, 10);
noFill();
stroke(255);
ellipse(circle.x, circle.y, radius, radius);
}
void mover() {
speed.addSelf(acc);
constrainSoftener();
speed.limit(2); //speed limiter!!
loc.addSelf(speed);
// The following code keeps the ball within the constraining circle - just in case we have stepped outside of it;
float xDist = (loc.x - circle.x);
float yDist = (loc.y - circle.y);
float distFromCentre = sqrt(pow(xDist, 2) + pow(yDist, 2)); // get distance from centre of circle;
if (distFromCentre > radius/2)
{
// We are outside - need to scale the location back;
loc.x = xDist * ((radius/2) / distFromCentre) + circle.x;
loc.y = yDist * ((radius/2) / distFromCentre) + circle.y;
}
acc.clear();
}
void bounce() {
if (loc.x > width) {
speed.x = speed.x * -1;
}
if (loc.x < 0) {
speed.x = speed.x * -1;
}
if (loc.y > height) {
speed.y = speed.y * -1;
}
if (loc.y < 0) {
speed.y = speed.y * -1;
}
}
void gravity() {
speed.addSelf(grav);
}
void lineBetween() {
// ballCollection
for (int i = 0; i < ballCollection.size(); i ++) {
Ball other = (Ball) ballCollection.get(i);
float distance = loc.distanceTo(other.loc);
if (distance > 0 && distance < 60) {
stroke(255, 0, 0);
strokeWeight(0.4);
line(loc.x, loc.y, other.loc.x, other.loc.y);
}
}
}
float distToAudience() {
return dist(loc.x, loc.y, mouseX, mouseY);
}
}//class close
1