mirror of
https://github.com/processing/processing4.git
synced 2026-01-29 11:21:06 +01:00
Re-adding Topics to SVN
This commit is contained in:
68
java/examples/Topics/Simulate/Chain/Chain.pde
Normal file
68
java/examples/Topics/Simulate/Chain/Chain.pde
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Chain.
|
||||
*
|
||||
* One mass is attached to the mouse position and the other
|
||||
* is attached the position of the other mass. The gravity
|
||||
* in the environment pulls down on both.
|
||||
*/
|
||||
|
||||
|
||||
Spring2D s1, s2;
|
||||
|
||||
float gravity = 6.0;
|
||||
float mass = 2.0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
size(200, 200);
|
||||
smooth();
|
||||
fill(0);
|
||||
// Inputs: x, y, mass, gravity
|
||||
s1 = new Spring2D(0.0, width/2, mass, gravity);
|
||||
s2 = new Spring2D(0.0, width/2, mass, gravity);
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
background(204);
|
||||
s1.update(mouseX, mouseY);
|
||||
s1.display(mouseX, mouseY);
|
||||
s2.update(s1.x, s1.y);
|
||||
s2.display(s1.x, s1.y);
|
||||
}
|
||||
|
||||
class Spring2D {
|
||||
float vx, vy; // The x- and y-axis velocities
|
||||
float x, y; // The x- and y-coordinates
|
||||
float gravity;
|
||||
float mass;
|
||||
float radius = 20;
|
||||
float stiffness = 0.2;
|
||||
float damping = 0.7;
|
||||
|
||||
Spring2D(float xpos, float ypos, float m, float g) {
|
||||
x = xpos;
|
||||
y = ypos;
|
||||
mass = m;
|
||||
gravity = g;
|
||||
}
|
||||
|
||||
void update(float targetX, float targetY) {
|
||||
float forceX = (targetX - x) * stiffness;
|
||||
float ax = forceX / mass;
|
||||
vx = damping * (vx + ax);
|
||||
x += vx;
|
||||
float forceY = (targetY - y) * stiffness;
|
||||
forceY += gravity;
|
||||
float ay = forceY / mass;
|
||||
vy = damping * (vy + ay);
|
||||
y += vy;
|
||||
}
|
||||
|
||||
void display(float nx, float ny) {
|
||||
noStroke();
|
||||
ellipse(x, y, radius*2, radius*2);
|
||||
stroke(255);
|
||||
line(x, y, nx, ny);
|
||||
}
|
||||
}
|
||||
196
java/examples/Topics/Simulate/Flocking/Boid.pde
Normal file
196
java/examples/Topics/Simulate/Flocking/Boid.pde
Normal file
@@ -0,0 +1,196 @@
|
||||
// The Boid class
|
||||
|
||||
class Boid {
|
||||
|
||||
PVector loc;
|
||||
PVector vel;
|
||||
PVector acc;
|
||||
float r;
|
||||
float maxforce; // Maximum steering force
|
||||
float maxspeed; // Maximum speed
|
||||
|
||||
Boid(PVector l, float ms, float mf) {
|
||||
acc = new PVector(0,0);
|
||||
vel = new PVector(random(-1,1),random(-1,1));
|
||||
loc = l.get();
|
||||
r = 2.0;
|
||||
maxspeed = ms;
|
||||
maxforce = mf;
|
||||
}
|
||||
|
||||
void run(ArrayList boids) {
|
||||
flock(boids);
|
||||
update();
|
||||
borders();
|
||||
render();
|
||||
}
|
||||
|
||||
// We accumulate a new acceleration each time based on three rules
|
||||
void flock(ArrayList boids) {
|
||||
PVector sep = separate(boids); // Separation
|
||||
PVector ali = align(boids); // Alignment
|
||||
PVector coh = cohesion(boids); // Cohesion
|
||||
// Arbitrarily weight these forces
|
||||
sep.mult(1.5);
|
||||
ali.mult(1.0);
|
||||
coh.mult(1.0);
|
||||
// Add the force vectors to acceleration
|
||||
acc.add(sep);
|
||||
acc.add(ali);
|
||||
acc.add(coh);
|
||||
}
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
// Update velocity
|
||||
vel.add(acc);
|
||||
// Limit speed
|
||||
vel.limit(maxspeed);
|
||||
loc.add(vel);
|
||||
// Reset accelertion to 0 each cycle
|
||||
acc.mult(0);
|
||||
}
|
||||
|
||||
void seek(PVector target) {
|
||||
acc.add(steer(target,false));
|
||||
}
|
||||
|
||||
void arrive(PVector target) {
|
||||
acc.add(steer(target,true));
|
||||
}
|
||||
|
||||
// A method that calculates a steering vector towards a target
|
||||
// Takes a second argument, if true, it slows down as it approaches the target
|
||||
PVector steer(PVector target, boolean slowdown) {
|
||||
PVector steer; // The steering vector
|
||||
PVector desired = target.sub(target,loc); // A vector pointing from the location to the target
|
||||
float d = desired.mag(); // Distance from the target is the magnitude of the vector
|
||||
// If the distance is greater than 0, calc steering (otherwise return zero vector)
|
||||
if (d > 0) {
|
||||
// Normalize desired
|
||||
desired.normalize();
|
||||
// Two options for desired vector magnitude (1 -- based on distance, 2 -- maxspeed)
|
||||
if ((slowdown) && (d < 100.0)) desired.mult(maxspeed*(d/100.0)); // This damping is somewhat arbitrary
|
||||
else desired.mult(maxspeed);
|
||||
// Steering = Desired minus Velocity
|
||||
steer = target.sub(desired,vel);
|
||||
steer.limit(maxforce); // Limit to maximum steering force
|
||||
}
|
||||
else {
|
||||
steer = new PVector(0,0);
|
||||
}
|
||||
return steer;
|
||||
}
|
||||
|
||||
void render() {
|
||||
// Draw a triangle rotated in the direction of velocity
|
||||
float theta = vel.heading2D() + PI/2;
|
||||
fill(200,100);
|
||||
stroke(255);
|
||||
pushMatrix();
|
||||
translate(loc.x,loc.y);
|
||||
rotate(theta);
|
||||
beginShape(TRIANGLES);
|
||||
vertex(0, -r*2);
|
||||
vertex(-r, r*2);
|
||||
vertex(r, r*2);
|
||||
endShape();
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
// Wraparound
|
||||
void borders() {
|
||||
if (loc.x < -r) loc.x = width+r;
|
||||
if (loc.y < -r) loc.y = height+r;
|
||||
if (loc.x > width+r) loc.x = -r;
|
||||
if (loc.y > height+r) loc.y = -r;
|
||||
}
|
||||
|
||||
// Separation
|
||||
// Method checks for nearby boids and steers away
|
||||
PVector separate (ArrayList boids) {
|
||||
float desiredseparation = 20.0;
|
||||
PVector steer = new PVector(0,0,0);
|
||||
int count = 0;
|
||||
// For every boid in the system, check if it's too close
|
||||
for (int i = 0 ; i < boids.size(); i++) {
|
||||
Boid other = (Boid) boids.get(i);
|
||||
float d = PVector.dist(loc,other.loc);
|
||||
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
|
||||
if ((d > 0) && (d < desiredseparation)) {
|
||||
// Calculate vector pointing away from neighbor
|
||||
PVector diff = PVector.sub(loc,other.loc);
|
||||
diff.normalize();
|
||||
diff.div(d); // Weight by distance
|
||||
steer.add(diff);
|
||||
count++; // Keep track of how many
|
||||
}
|
||||
}
|
||||
// Average -- divide by how many
|
||||
if (count > 0) {
|
||||
steer.div((float)count);
|
||||
}
|
||||
|
||||
// As long as the vector is greater than 0
|
||||
if (steer.mag() > 0) {
|
||||
// Implement Reynolds: Steering = Desired - Velocity
|
||||
steer.normalize();
|
||||
steer.mult(maxspeed);
|
||||
steer.sub(vel);
|
||||
steer.limit(maxforce);
|
||||
}
|
||||
return steer;
|
||||
}
|
||||
|
||||
// Alignment
|
||||
// For every nearby boid in the system, calculate the average velocity
|
||||
PVector align (ArrayList boids) {
|
||||
float neighbordist = 25.0;
|
||||
PVector steer = new PVector(0,0,0);
|
||||
int count = 0;
|
||||
for (int i = 0 ; i < boids.size(); i++) {
|
||||
Boid other = (Boid) boids.get(i);
|
||||
float d = PVector.dist(loc,other.loc);
|
||||
if ((d > 0) && (d < neighbordist)) {
|
||||
steer.add(other.vel);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
steer.div((float)count);
|
||||
}
|
||||
|
||||
// As long as the vector is greater than 0
|
||||
if (steer.mag() > 0) {
|
||||
// Implement Reynolds: Steering = Desired - Velocity
|
||||
steer.normalize();
|
||||
steer.mult(maxspeed);
|
||||
steer.sub(vel);
|
||||
steer.limit(maxforce);
|
||||
}
|
||||
return steer;
|
||||
}
|
||||
|
||||
// Cohesion
|
||||
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
|
||||
PVector cohesion (ArrayList boids) {
|
||||
float neighbordist = 25.0;
|
||||
PVector sum = new PVector(0,0); // Start with empty vector to accumulate all locations
|
||||
int count = 0;
|
||||
for (int i = 0 ; i < boids.size(); i++) {
|
||||
Boid other = (Boid) boids.get(i);
|
||||
float d = loc.dist(other.loc);
|
||||
if ((d > 0) && (d < neighbordist)) {
|
||||
sum.add(other.loc); // Add location
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
sum.div((float)count);
|
||||
return steer(sum,false); // Steer towards the location
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
22
java/examples/Topics/Simulate/Flocking/Flock.pde
Normal file
22
java/examples/Topics/Simulate/Flocking/Flock.pde
Normal file
@@ -0,0 +1,22 @@
|
||||
// The Flock (a list of Boid objects)
|
||||
|
||||
class Flock {
|
||||
ArrayList boids; // An arraylist for all the boids
|
||||
|
||||
Flock() {
|
||||
boids = new ArrayList(); // Initialize the arraylist
|
||||
}
|
||||
|
||||
void run() {
|
||||
for (int i = 0; i < boids.size(); i++) {
|
||||
Boid b = (Boid) boids.get(i);
|
||||
b.run(boids); // Passing the entire list of boids to each boid individually
|
||||
}
|
||||
}
|
||||
|
||||
void addBoid(Boid b) {
|
||||
boids.add(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
32
java/examples/Topics/Simulate/Flocking/Flocking.pde
Normal file
32
java/examples/Topics/Simulate/Flocking/Flocking.pde
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Flocking
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* An implementation of Craig Reynold's Boids program to simulate
|
||||
* the flocking behavior of birds. Each boid steers itself based on
|
||||
* rules of avoidance, alignment, and coherence.
|
||||
*
|
||||
* Click the mouse to add a new boid.
|
||||
*/
|
||||
|
||||
Flock flock;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
flock = new Flock();
|
||||
// Add an initial set of boids into the system
|
||||
for (int i = 0; i < 150; i++) {
|
||||
flock.addBoid(new Boid(new PVector(width/2,height/2), 3.0, 0.05));
|
||||
}
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(50);
|
||||
flock.run();
|
||||
}
|
||||
|
||||
// Add a new boid into the System
|
||||
void mousePressed() {
|
||||
flock.addBoid(new Boid(new PVector(mouseX,mouseY),2.0f,0.05f));
|
||||
}
|
||||
208
java/examples/Topics/Simulate/Fluid/Fluid.pde
Normal file
208
java/examples/Topics/Simulate/Fluid/Fluid.pde
Normal file
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Fluid
|
||||
* by Glen Murphy.
|
||||
*
|
||||
* Click and drag the mouse to move the simulated fluid.
|
||||
* Adjust the "res" variable below to change resolution.
|
||||
* Code has not been optimised, and will run fairly slowly.
|
||||
*/
|
||||
|
||||
int res = 2;
|
||||
int penSize = 30;
|
||||
int lwidth;
|
||||
int lheight;
|
||||
int pnum = 30000;
|
||||
vsquare[][] v;
|
||||
vbuffer[][] vbuf;
|
||||
particle[] p = new particle[pnum];
|
||||
int pcount = 0;
|
||||
int mouseXvel = 0;
|
||||
int mouseYvel = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
size(200, 200);
|
||||
noStroke();
|
||||
frameRate(30);
|
||||
lwidth = width/res;
|
||||
lheight = height/res;
|
||||
v = new vsquare[lwidth+1][lheight+1];
|
||||
vbuf = new vbuffer[lwidth+1][lheight+1];
|
||||
for (int i = 0; i < pnum; i++) {
|
||||
p[i] = new particle(random(res,width-res),random(res,height-res));
|
||||
}
|
||||
for (int i = 0; i <= lwidth; i++) {
|
||||
for (int u = 0; u <= lheight; u++) {
|
||||
v[i][u] = new vsquare(i*res,u*res);
|
||||
vbuf[i][u] = new vbuffer(i*res,u*res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
background(#666666);
|
||||
|
||||
int axvel = mouseX-pmouseX;
|
||||
int ayvel = mouseY-pmouseY;
|
||||
|
||||
mouseXvel = (axvel != mouseXvel) ? axvel : 0;
|
||||
mouseYvel = (ayvel != mouseYvel) ? ayvel : 0;
|
||||
|
||||
for (int i = 0; i < lwidth; i++) {
|
||||
for (int u = 0; u < lheight; u++) {
|
||||
vbuf[i][u].updatebuf(i,u);
|
||||
v[i][u].col = 32;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < pnum-1; i++) {
|
||||
p[i].updatepos();
|
||||
}
|
||||
for (int i = 0; i < lwidth; i++) {
|
||||
for (int u = 0; u < lheight; u++) {
|
||||
v[i][u].addbuffer(i, u);
|
||||
v[i][u].updatevels(mouseXvel, mouseYvel);
|
||||
v[i][u].display(i, u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class particle {
|
||||
float x;
|
||||
float y;
|
||||
float xvel;
|
||||
float yvel;
|
||||
int pos;
|
||||
particle(float xIn, float yIn) {
|
||||
x = xIn;
|
||||
y = yIn;
|
||||
}
|
||||
|
||||
void updatepos() {
|
||||
float col1;
|
||||
if (x > 0 && x < width && y > 0 && y < height) {
|
||||
int vi = (int)(x/res);
|
||||
int vu = (int)(y/res);
|
||||
vsquare o = v[vi][vu];
|
||||
|
||||
float ax = (x%res)/res;
|
||||
float ay = (y%res)/res;
|
||||
|
||||
xvel += (1-ax)*v[vi][vu].xvel*0.05;
|
||||
yvel += (1-ay)*v[vi][vu].yvel*0.05;
|
||||
|
||||
xvel += ax*v[vi+1][vu].xvel*0.05;
|
||||
yvel += ax*v[vi+1][vu].yvel*0.05;
|
||||
|
||||
xvel += ay*v[vi][vu+1].xvel*0.05;
|
||||
yvel += ay*v[vi][vu+1].yvel*0.05;
|
||||
|
||||
o.col += 4;
|
||||
|
||||
x += xvel;
|
||||
y += yvel;
|
||||
}
|
||||
else {
|
||||
x = random(0,width);
|
||||
y = random(0,height);
|
||||
xvel = 0;
|
||||
yvel = 0;
|
||||
}
|
||||
|
||||
xvel *= 0.5;
|
||||
yvel *= 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
class vbuffer {
|
||||
int x;
|
||||
int y;
|
||||
float xvel;
|
||||
float yvel;
|
||||
float pressurex = 0;
|
||||
float pressurey = 0;
|
||||
float pressure = 0;
|
||||
|
||||
vbuffer(int xIn,int yIn) {
|
||||
x = xIn;
|
||||
y = yIn;
|
||||
pressurex = 0;
|
||||
pressurey = 0;
|
||||
}
|
||||
|
||||
void updatebuf(int i, int u) {
|
||||
if (i>0 && i<lwidth && u>0 && u<lheight) {
|
||||
pressurex = (v[i-1][u-1].xvel*0.5 + v[i-1][u].xvel + v[i-1][u+1].xvel*0.5 - v[i+1][u-1].xvel*0.5 - v[i+1][u].xvel - v[i+1][u+1].xvel*0.5);
|
||||
pressurey = (v[i-1][u-1].yvel*0.5 + v[i][u-1].yvel + v[i+1][u-1].yvel*0.5 - v[i-1][u+1].yvel*0.5 - v[i][u+1].yvel - v[i+1][u+1].yvel*0.5);
|
||||
pressure = (pressurex + pressurey)*0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class vsquare {
|
||||
int x;
|
||||
int y;
|
||||
float xvel;
|
||||
float yvel;
|
||||
float col;
|
||||
|
||||
vsquare(int xIn,int yIn) {
|
||||
x = xIn;
|
||||
y = yIn;
|
||||
}
|
||||
|
||||
void addbuffer(int i, int u) {
|
||||
if (i>0 && i<lwidth && u>0 && u<lheight) {
|
||||
xvel += (vbuf[i-1][u-1].pressure*0.5
|
||||
+vbuf[i-1][u].pressure
|
||||
+vbuf[i-1][u+1].pressure*0.5
|
||||
-vbuf[i+1][u-1].pressure*0.5
|
||||
-vbuf[i+1][u].pressure
|
||||
-vbuf[i+1][u+1].pressure*0.5
|
||||
)*0.25;
|
||||
yvel += (vbuf[i-1][u-1].pressure*0.5
|
||||
+vbuf[i][u-1].pressure
|
||||
+vbuf[i+1][u-1].pressure*0.5
|
||||
-vbuf[i-1][u+1].pressure*0.5
|
||||
-vbuf[i][u+1].pressure
|
||||
-vbuf[i+1][u+1].pressure*0.5
|
||||
)*0.25;
|
||||
}
|
||||
}
|
||||
|
||||
void updatevels(int mvelX, int mvelY) {
|
||||
if (mousePressed) {
|
||||
float adj = x - mouseX;
|
||||
float opp = y - mouseY;
|
||||
float dist = sqrt(opp*opp + adj*adj);
|
||||
if (dist < penSize) {
|
||||
if (dist < 4) dist = penSize;
|
||||
float mod = penSize/dist;
|
||||
xvel += mvelX*mod;
|
||||
yvel += mvelY*mod;
|
||||
}
|
||||
}
|
||||
|
||||
xvel *= 0.99;
|
||||
yvel *= 0.99;
|
||||
}
|
||||
|
||||
void display(int i, int u) {
|
||||
float tcol = 0;
|
||||
if (col > 255) col = 255;
|
||||
if (i>0 && i<lwidth-1 && u>0 && u<lheight-1) {
|
||||
tcol = (+ v[i][u+1].col
|
||||
+ v[i+1][u].col
|
||||
+ v[i+1][u+1].col*0.5
|
||||
)*0.4;
|
||||
tcol = (int)(tcol+col*0.5);
|
||||
}
|
||||
else {
|
||||
tcol = (int)col;
|
||||
}
|
||||
fill(tcol, tcol, tcol);
|
||||
rect(x,y,res,res);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// A subclass of Particle
|
||||
|
||||
class CrazyParticle extends Particle {
|
||||
|
||||
// Just adding one new variable to a CrazyParticle
|
||||
// It inherits all other fields from "Particle", and we don't have to retype them!
|
||||
float theta;
|
||||
|
||||
// The CrazyParticle constructor can call the parent class (super class) constructor
|
||||
CrazyParticle(PVector l) {
|
||||
// "super" means do everything from the constructor in Particle
|
||||
super(l);
|
||||
// One more line of code to deal with the new variable, theta
|
||||
theta = 0.0;
|
||||
|
||||
}
|
||||
|
||||
// Notice we don't have the method run() here; it is inherited from Particle
|
||||
|
||||
// This update() method overrides the parent class update() method
|
||||
void update() {
|
||||
super.update();
|
||||
// Increment rotation based on horizontal velocity
|
||||
float theta_vel = (vel.x * vel.mag()) / 10.0f;
|
||||
theta += theta_vel;
|
||||
}
|
||||
|
||||
// Override timer
|
||||
void timer() {
|
||||
timer -= 0.5;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void render() {
|
||||
// Render the ellipse just like in a regular particle
|
||||
super.render();
|
||||
|
||||
// Then add a rotating line
|
||||
pushMatrix();
|
||||
translate(loc.x,loc.y);
|
||||
rotate(theta);
|
||||
stroke(255,timer);
|
||||
line(0,0,25,0);
|
||||
popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Multiple Particle Systems
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Click the mouse to generate a burst of particles
|
||||
* at mouse location.
|
||||
*
|
||||
* Each burst is one instance of a particle system
|
||||
* with Particles and CrazyParticles (a subclass of Particle)
|
||||
* Note use of Inheritance and Polymorphism here.
|
||||
*/
|
||||
|
||||
ArrayList psystems;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
colorMode(RGB, 255, 255, 255, 100);
|
||||
psystems = new ArrayList();
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
|
||||
// Cycle through all particle systems, run them and delete old ones
|
||||
for (int i = psystems.size()-1; i >= 0; i--) {
|
||||
ParticleSystem psys = (ParticleSystem) psystems.get(i);
|
||||
psys.run();
|
||||
if (psys.dead()) {
|
||||
psystems.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// When the mouse is pressed, add a new particle system
|
||||
void mousePressed() {
|
||||
psystems.add(new ParticleSystem(int(random(5,25)),new PVector(mouseX,mouseY)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// A simple Particle class
|
||||
|
||||
class Particle {
|
||||
PVector loc;
|
||||
PVector vel;
|
||||
PVector acc;
|
||||
float r;
|
||||
float timer;
|
||||
|
||||
// One constructor
|
||||
Particle(PVector a, PVector v, PVector l, float r_) {
|
||||
acc = a.get();
|
||||
vel = v.get();
|
||||
loc = l.get();
|
||||
r = r_;
|
||||
timer = 100.0;
|
||||
}
|
||||
|
||||
// Another constructor (the one we are using here)
|
||||
Particle(PVector l) {
|
||||
acc = new PVector(0,0.05,0);
|
||||
vel = new PVector(random(-1,1),random(-2,0),0);
|
||||
loc = l.get();
|
||||
r = 10.0;
|
||||
timer = 100.0;
|
||||
}
|
||||
|
||||
|
||||
void run() {
|
||||
update();
|
||||
render();
|
||||
}
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
vel.add(acc);
|
||||
loc.add(vel);
|
||||
timer -= 1.0;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void render() {
|
||||
ellipseMode(CENTER);
|
||||
stroke(255,timer);
|
||||
fill(100,timer);
|
||||
ellipse(loc.x,loc.y,r,r);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean dead() {
|
||||
if (timer <= 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// An ArrayList is used to manage the list of Particles
|
||||
|
||||
class ParticleSystem {
|
||||
|
||||
ArrayList particles; // An arraylist for all the particles
|
||||
PVector origin; // An origin point for where particles are birthed
|
||||
|
||||
ParticleSystem(int num, PVector v) {
|
||||
particles = new ArrayList(); // Initialize the arraylist
|
||||
origin = v.get(); // Store the origin point
|
||||
for (int i = 0; i < num; i++) {
|
||||
// We have a 50% chance of adding each kind of particle
|
||||
if (random(1) < 0.5) {
|
||||
particles.add(new CrazyParticle(origin));
|
||||
} else {
|
||||
particles.add(new Particle(origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
// Cycle through the ArrayList backwards b/c we are deleting
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = (Particle) particles.get(i);
|
||||
p.run();
|
||||
if (p.dead()) {
|
||||
particles.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin));
|
||||
}
|
||||
|
||||
void addParticle(Particle p) {
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
// A method to test if the particle system still has particles
|
||||
boolean dead() {
|
||||
if (particles.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// A simple Particle class
|
||||
|
||||
class Particle {
|
||||
PVector loc;
|
||||
PVector vel;
|
||||
PVector acc;
|
||||
float r;
|
||||
float timer;
|
||||
|
||||
// Another constructor (the one we are using here)
|
||||
Particle(PVector l) {
|
||||
acc = new PVector(0,0.05,0);
|
||||
vel = new PVector(random(-1,1),random(-2,0),0);
|
||||
loc = l.get();
|
||||
r = 10.0;
|
||||
timer = 100.0;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
render();
|
||||
}
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
vel.add(acc);
|
||||
loc.add(vel);
|
||||
timer -= 1.0;
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void render() {
|
||||
ellipseMode(CENTER);
|
||||
stroke(255,timer);
|
||||
fill(100,timer);
|
||||
ellipse(loc.x,loc.y,r,r);
|
||||
displayVector(vel,loc.x,loc.y,10);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean dead() {
|
||||
if (timer <= 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void displayVector(PVector v, float x, float y, float scayl) {
|
||||
pushMatrix();
|
||||
float arrowsize = 4;
|
||||
// Translate to location to render vector
|
||||
translate(x,y);
|
||||
stroke(255);
|
||||
// Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate
|
||||
rotate(v.heading2D());
|
||||
// Calculate length of vector & scale it to be bigger or smaller if necessary
|
||||
float len = v.mag()*scayl;
|
||||
// Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction)
|
||||
line(0,0,len,0);
|
||||
line(len,0,len-arrowsize,+arrowsize/2);
|
||||
line(len,0,len-arrowsize,-arrowsize/2);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// A class to describe a group of Particles
|
||||
// An ArrayList is used to manage the list of Particles
|
||||
|
||||
class ParticleSystem {
|
||||
|
||||
ArrayList particles; // An arraylist for all the particles
|
||||
PVector origin; // An origin point for where particles are born
|
||||
|
||||
ParticleSystem(int num, PVector v) {
|
||||
particles = new ArrayList(); // Initialize the arraylist
|
||||
origin = v.get(); // Store the origin point
|
||||
for (int i = 0; i < num; i++) {
|
||||
particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
// Cycle through the ArrayList backwards b/c we are deleting
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = (Particle) particles.get(i);
|
||||
p.run();
|
||||
if (p.dead()) {
|
||||
particles.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin));
|
||||
}
|
||||
|
||||
void addParticle(float x, float y) {
|
||||
particles.add(new Particle(new PVector(x,y)));
|
||||
}
|
||||
|
||||
void addParticle(Particle p) {
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
// A method to test if the particle system still has particles
|
||||
boolean dead() {
|
||||
if (particles.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Simple Particle System
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* Particles are generated each cycle through draw(),
|
||||
* fall with gravity and fade out over time
|
||||
* A ParticleSystem object manages a variable size (ArrayList)
|
||||
* list of particles.
|
||||
*/
|
||||
|
||||
ParticleSystem ps;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
colorMode(RGB, 255, 255, 255, 100);
|
||||
ps = new ParticleSystem(1, new PVector(width/2,height/2,0));
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
ps.run();
|
||||
ps.addParticle(mouseX,mouseY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
264
java/examples/Topics/Simulate/Smoke/Smoke.pde
Normal file
264
java/examples/Topics/Simulate/Smoke/Smoke.pde
Normal file
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* Smoke
|
||||
* by Glen Murphy.
|
||||
*
|
||||
* Drag the mouse across the image to move the particles.
|
||||
* Code has not been optimised and will run fairly slowly.
|
||||
*/
|
||||
|
||||
int res = 2;
|
||||
int penSize = 30;
|
||||
int lwidth;
|
||||
int lheight;
|
||||
int pnum = 30000;
|
||||
vsquare[][] v;
|
||||
vbuffer[][] vbuf;
|
||||
particle[] p;
|
||||
int pcount = 0;
|
||||
int mouseXvel = 0;
|
||||
int mouseYvel = 0;
|
||||
|
||||
int randomGust = 0;
|
||||
int randomGustMax;
|
||||
float randomGustX;
|
||||
float randomGustY;
|
||||
float randomGustSize;
|
||||
float randomGustXvel;
|
||||
float randomGustYvel;
|
||||
|
||||
void setup()
|
||||
{
|
||||
size(200, 200);
|
||||
lwidth = width/res;
|
||||
lheight = height/res;
|
||||
v = new vsquare[lwidth+1][lheight+1];
|
||||
vbuf = new vbuffer[lwidth+1][lheight+1];
|
||||
p = new particle[pnum];
|
||||
noStroke();
|
||||
for(int i = 0; i < pnum; i++) {
|
||||
p[i] = new particle(random(width/2-20,width/2+20),random(height-20,height));
|
||||
}
|
||||
for(int i = 0; i <= lwidth; i++) {
|
||||
for(int u = 0; u <= lheight; u++) {
|
||||
v[i][u] = new vsquare(i*res,u*res);
|
||||
vbuf[i][u] = new vbuffer(i*res,u*res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
background(#cccccc);
|
||||
|
||||
int axvel = mouseX-pmouseX;
|
||||
int ayvel = mouseY-pmouseY;
|
||||
|
||||
mouseXvel = (axvel != mouseXvel) ? axvel : 0;
|
||||
mouseYvel = (ayvel != mouseYvel) ? ayvel : 0;
|
||||
|
||||
if(randomGust <= 0) {
|
||||
if(random(0,10)<1) {
|
||||
randomGustMax = (int)random(5,12);
|
||||
randomGust = randomGustMax;
|
||||
randomGustX = random(0,width);
|
||||
randomGustY = random(0,height-10);
|
||||
randomGustSize = random(0,50);
|
||||
if(randomGustX > width/2) {
|
||||
randomGustXvel = random(-8,0);
|
||||
} else {
|
||||
randomGustXvel = random(0,8);
|
||||
}
|
||||
randomGustYvel = random(-2,1);
|
||||
}
|
||||
randomGust--;
|
||||
}
|
||||
|
||||
for(int i = 0; i < lwidth; i++) {
|
||||
for(int u = 0; u < lheight; u++) {
|
||||
vbuf[i][u].updatebuf(i,u);
|
||||
v[i][u].col = 0;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < pnum-1; i++) {
|
||||
p[i].updatepos();
|
||||
}
|
||||
for(int i = 0; i < lwidth; i++) {
|
||||
for(int u = 0; u < lheight; u++) {
|
||||
v[i][u].addbuffer(i, u);
|
||||
v[i][u].updatevels(mouseXvel, mouseYvel);
|
||||
v[i][u].display(i, u);
|
||||
}
|
||||
}
|
||||
randomGust = 0;
|
||||
}
|
||||
|
||||
class particle
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float xvel;
|
||||
float yvel;
|
||||
float temp;
|
||||
int pos;
|
||||
|
||||
particle(float xIn, float yIn) {
|
||||
x = xIn;
|
||||
y = yIn;
|
||||
}
|
||||
|
||||
void reposition() {
|
||||
x = width/2+random(-20,20);
|
||||
y = random(height-10,height);
|
||||
|
||||
xvel = random(-1,1);
|
||||
yvel = random(-1,1);
|
||||
}
|
||||
|
||||
void updatepos() {
|
||||
int vi = (int)(x/res);
|
||||
int vu = (int)(y/res);
|
||||
|
||||
if(vi > 0 && vi < lwidth && vu > 0 && vu < lheight) {
|
||||
v[vi][vu].addcolour(2);
|
||||
|
||||
float ax = (x%res)/res;
|
||||
float ay = (y%res)/res;
|
||||
|
||||
xvel += (1-ax)*v[vi][vu].xvel*0.05;
|
||||
yvel += (1-ay)*v[vi][vu].yvel*0.05;
|
||||
|
||||
xvel += ax*v[vi+1][vu].xvel*0.05;
|
||||
yvel += ax*v[vi+1][vu].yvel*0.05;
|
||||
|
||||
xvel += ay*v[vi][vu+1].xvel*0.05;
|
||||
yvel += ay*v[vi][vu+1].yvel*0.05;
|
||||
|
||||
v[vi][vu].yvel -= (1-ay)*0.003;
|
||||
v[vi+1][vu].yvel -= ax*0.003;
|
||||
|
||||
if(v[vi][vu].yvel < 0) v[vi][vu].yvel *= 1.00025;
|
||||
|
||||
x += xvel;
|
||||
y += yvel;
|
||||
}
|
||||
else {
|
||||
reposition();
|
||||
}
|
||||
if(random(0,400) < 1) {
|
||||
reposition();
|
||||
}
|
||||
xvel *= 0.6;
|
||||
yvel *= 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
class vbuffer
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
float xvel;
|
||||
float yvel;
|
||||
float pressurex = 0;
|
||||
float pressurey = 0;
|
||||
float pressure = 0;
|
||||
|
||||
vbuffer(int xIn,int yIn) {
|
||||
x = xIn;
|
||||
y = yIn;
|
||||
pressurex = 0;
|
||||
pressurey = 0;
|
||||
}
|
||||
|
||||
void updatebuf(int i, int u) {
|
||||
if(i>0 && i<lwidth && u>0 && u<lheight) {
|
||||
pressurex = (v[i-1][u-1].xvel*0.5 + v[i-1][u].xvel + v[i-1][u+1].xvel*0.5 - v[i+1][u-1].xvel*0.5 - v[i+1][u].xvel - v[i+1][u+1].xvel*0.5);
|
||||
pressurey = (v[i-1][u-1].yvel*0.5 + v[i][u-1].yvel + v[i+1][u-1].yvel*0.5 - v[i-1][u+1].yvel*0.5 - v[i][u+1].yvel - v[i+1][u+1].yvel*0.5);
|
||||
pressure = (pressurex + pressurey)*0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class vsquare {
|
||||
int x;
|
||||
int y;
|
||||
float xvel;
|
||||
float yvel;
|
||||
float col;
|
||||
|
||||
vsquare(int xIn,int yIn) {
|
||||
x = xIn;
|
||||
y = yIn;
|
||||
}
|
||||
|
||||
void addbuffer(int i, int u) {
|
||||
if(i>0 && i<lwidth && u>0 && u<lheight) {
|
||||
xvel += (vbuf[i-1][u-1].pressure*0.5
|
||||
+vbuf[i-1][u].pressure
|
||||
+vbuf[i-1][u+1].pressure*0.5
|
||||
-vbuf[i+1][u-1].pressure*0.5
|
||||
-vbuf[i+1][u].pressure
|
||||
-vbuf[i+1][u+1].pressure*0.5
|
||||
)*0.49;
|
||||
yvel += (vbuf[i-1][u-1].pressure*0.5
|
||||
+vbuf[i][u-1].pressure
|
||||
+vbuf[i+1][u-1].pressure*0.5
|
||||
-vbuf[i-1][u+1].pressure*0.5
|
||||
-vbuf[i][u+1].pressure
|
||||
-vbuf[i+1][u+1].pressure*0.5
|
||||
)*0.49;
|
||||
}
|
||||
}
|
||||
|
||||
void updatevels(int mvelX, int mvelY) {
|
||||
float adj;
|
||||
float opp;
|
||||
float dist;
|
||||
float mod;
|
||||
|
||||
if(mousePressed) {
|
||||
adj = x - mouseX;
|
||||
opp = y - mouseY;
|
||||
dist = sqrt(opp*opp + adj*adj);
|
||||
if(dist < penSize) {
|
||||
if(dist < 4) dist = penSize;
|
||||
mod = penSize/dist;
|
||||
xvel += mvelX*mod;
|
||||
yvel += mvelY*mod;
|
||||
}
|
||||
}
|
||||
if(randomGust > 0) {
|
||||
adj = x - randomGustX;
|
||||
opp = y - randomGustY;
|
||||
dist = sqrt(opp*opp + adj*adj);
|
||||
if(dist < randomGustSize) {
|
||||
if(dist < res*2) dist = randomGustSize;
|
||||
mod = randomGustSize/dist;
|
||||
xvel += (randomGustMax-randomGust)*randomGustXvel*mod;
|
||||
yvel += (randomGustMax-randomGust)*randomGustYvel*mod;
|
||||
}
|
||||
}
|
||||
xvel *= 0.99;
|
||||
yvel *= 0.98;
|
||||
}
|
||||
|
||||
void addcolour(int amt) {
|
||||
col += amt;
|
||||
if(col > 196) col = 196;
|
||||
}
|
||||
|
||||
void display(int i, int u) {
|
||||
float tcol = 0;
|
||||
if(i>0 && i<lwidth-1 && u>0 && u<lheight-1) {
|
||||
|
||||
tcol = (+ v[i][u+1].col
|
||||
+ v[i+1][u].col
|
||||
+ v[i+1][u+1].col*0.5
|
||||
)*0.3;
|
||||
tcol = (int)(tcol+col*0.5);
|
||||
}
|
||||
|
||||
fill(255-tcol, 255-tcol, 255-tcol);
|
||||
rect(x,y,res,res);
|
||||
col = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
// A simple Particle class, renders the particle as an image
|
||||
|
||||
class Particle {
|
||||
PVector loc;
|
||||
PVector vel;
|
||||
PVector acc;
|
||||
float timer;
|
||||
PImage img;
|
||||
|
||||
// One constructor
|
||||
Particle(PVector a, PVector v, PVector l, PImage img_) {
|
||||
acc = a.get();
|
||||
vel = v.get();
|
||||
loc = l.get();
|
||||
timer = 100.0;
|
||||
img = img_;
|
||||
}
|
||||
|
||||
// Another constructor (the one we are using here)
|
||||
Particle(PVector l,PImage img_) {
|
||||
acc = new PVector(0.0,0.0,0.0);
|
||||
float x = (float) generator.nextGaussian()*0.3f;
|
||||
float y = (float) generator.nextGaussian()*0.3f - 1.0f;
|
||||
vel = new PVector(x,y,0);
|
||||
loc = l.get();
|
||||
timer = 100.0;
|
||||
img = img_;
|
||||
}
|
||||
|
||||
void run() {
|
||||
update();
|
||||
render();
|
||||
}
|
||||
|
||||
// Method to apply a force vector to the Particle object
|
||||
// Note we are ignoring "mass" here
|
||||
void add_force(PVector f) {
|
||||
acc.add(f);
|
||||
}
|
||||
|
||||
// Method to update location
|
||||
void update() {
|
||||
vel.add(acc);
|
||||
loc.add(vel);
|
||||
timer -= 2.5;
|
||||
acc.mult(0);
|
||||
}
|
||||
|
||||
// Method to display
|
||||
void render() {
|
||||
imageMode(CORNER);
|
||||
tint(255,timer);
|
||||
image(img,loc.x-img.width/2,loc.y-img.height/2);
|
||||
}
|
||||
|
||||
// Is the particle still useful?
|
||||
boolean dead() {
|
||||
if (timer <= 0.0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// A class to describe a group of Particles
|
||||
// An ArrayList is used to manage the list of Particles
|
||||
|
||||
class ParticleSystem {
|
||||
|
||||
ArrayList particles; // An arraylist for all the particles
|
||||
PVector origin; // An origin point for where particles are birthed
|
||||
PImage img;
|
||||
|
||||
ParticleSystem(int num, PVector v, PImage img_) {
|
||||
particles = new ArrayList(); // Initialize the arraylist
|
||||
origin = v.get(); // Store the origin point
|
||||
img = img_;
|
||||
for (int i = 0; i < num; i++) {
|
||||
particles.add(new Particle(origin, img)); // Add "num" amount of particles to the arraylist
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
// Cycle through the ArrayList backwards b/c we are deleting
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = (Particle) particles.get(i);
|
||||
p.run();
|
||||
if (p.dead()) {
|
||||
particles.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method to add a force vector to all particles currently in the system
|
||||
void add_force(PVector dir) {
|
||||
for (int i = particles.size()-1; i >= 0; i--) {
|
||||
Particle p = (Particle) particles.get(i);
|
||||
p.add_force(dir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void addParticle() {
|
||||
particles.add(new Particle(origin,img));
|
||||
}
|
||||
|
||||
void addParticle(Particle p) {
|
||||
particles.add(p);
|
||||
}
|
||||
|
||||
// A method to test if the particle system still has particles
|
||||
boolean dead() {
|
||||
if (particles.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Smoke Particle System
|
||||
* by Daniel Shiffman.
|
||||
*
|
||||
* A basic smoke effect using a particle system.
|
||||
* Each particle is rendered as an alpha masked image.
|
||||
*/
|
||||
|
||||
ParticleSystem ps;
|
||||
Random generator;
|
||||
|
||||
void setup() {
|
||||
|
||||
size(640, 200);
|
||||
colorMode(RGB, 255, 255, 255, 100);
|
||||
|
||||
// Using a Java random number generator for Gaussian random numbers
|
||||
generator = new Random();
|
||||
|
||||
// Create an alpha masked image to be applied as the particle's texture
|
||||
PImage msk = loadImage("texture.gif");
|
||||
PImage img = new PImage(msk.width,msk.height);
|
||||
for (int i = 0; i < img.pixels.length; i++) img.pixels[i] = color(255);
|
||||
img.mask(msk);
|
||||
ps = new ParticleSystem(0, new PVector(width/2,height-20 ),img);
|
||||
|
||||
smooth();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(75);
|
||||
|
||||
// Calculate a "wind" force based on mouse horizontal position
|
||||
float dx = (mouseX - width/2) / 1000.0;
|
||||
PVector wind = new PVector(dx,0,0);
|
||||
displayVector(wind,width/2,50,500);
|
||||
ps.add_force(wind);
|
||||
ps.run();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ps.addParticle();
|
||||
}
|
||||
}
|
||||
|
||||
void displayVector(PVector v, float x, float y, float scayl) {
|
||||
pushMatrix();
|
||||
float arrowsize = 4;
|
||||
// Translate to location to render vector
|
||||
translate(x,y);
|
||||
stroke(255);
|
||||
// Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate
|
||||
rotate(v.heading2D());
|
||||
// Calculate length of vector & scale it to be bigger or smaller if necessary
|
||||
float len = v.mag()*scayl;
|
||||
// Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction)
|
||||
line(0,0,len,0);
|
||||
line(len,0,len-arrowsize,+arrowsize/2);
|
||||
line(len,0,len-arrowsize,-arrowsize/2);
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
99
java/examples/Topics/Simulate/SoftBody/SoftBody.pde
Normal file
99
java/examples/Topics/Simulate/SoftBody/SoftBody.pde
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Soft Body
|
||||
* by Ira Greenberg.
|
||||
*
|
||||
* Softbody dynamics simulation using curveVertex() and curveTightness().
|
||||
*/
|
||||
|
||||
// center point
|
||||
float centerX = 0, centerY = 0;
|
||||
|
||||
float radius = 45, rotAngle = -90;
|
||||
float accelX, accelY;
|
||||
float springing = .0009, damping = .98;
|
||||
|
||||
//corner nodes
|
||||
int nodes = 5;
|
||||
float nodeStartX[] = new float[nodes];
|
||||
float nodeStartY[] = new float[nodes];
|
||||
float[]nodeX = new float[nodes];
|
||||
float[]nodeY = new float[nodes];
|
||||
float[]angle = new float[nodes];
|
||||
float[]frequency = new float[nodes];
|
||||
|
||||
// soft-body dynamics
|
||||
float organicConstant = 1;
|
||||
|
||||
void setup() {
|
||||
size(640, 360);
|
||||
//center shape in window
|
||||
centerX = width/2;
|
||||
centerY = height/2;
|
||||
// iniitalize frequencies for corner nodes
|
||||
for (int i=0; i<nodes; i++){
|
||||
frequency[i] = random(5, 12);
|
||||
}
|
||||
noStroke();
|
||||
smooth();
|
||||
frameRate(30);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
//fade background
|
||||
fill(0, 100);
|
||||
rect(0,0,width, height);
|
||||
drawShape();
|
||||
moveShape();
|
||||
}
|
||||
|
||||
void drawShape() {
|
||||
// calculate node starting locations
|
||||
for (int i=0; i<nodes; i++){
|
||||
nodeStartX[i] = centerX+cos(radians(rotAngle))*radius;
|
||||
nodeStartY[i] = centerY+sin(radians(rotAngle))*radius;
|
||||
rotAngle += 360.0/nodes;
|
||||
}
|
||||
|
||||
// draw polygon
|
||||
curveTightness(organicConstant);
|
||||
fill(255);
|
||||
beginShape();
|
||||
for (int i=0; i<nodes; i++){
|
||||
curveVertex(nodeX[i], nodeY[i]);
|
||||
}
|
||||
for (int i=0; i<nodes-1; i++){
|
||||
curveVertex(nodeX[i], nodeY[i]);
|
||||
}
|
||||
endShape(CLOSE);
|
||||
}
|
||||
|
||||
void moveShape() {
|
||||
//move center point
|
||||
float deltaX = mouseX-centerX;
|
||||
float deltaY = mouseY-centerY;
|
||||
|
||||
// create springing effect
|
||||
deltaX *= springing;
|
||||
deltaY *= springing;
|
||||
accelX += deltaX;
|
||||
accelY += deltaY;
|
||||
|
||||
// move predator's center
|
||||
centerX += accelX;
|
||||
centerY += accelY;
|
||||
|
||||
// slow down springing
|
||||
accelX *= damping;
|
||||
accelY *= damping;
|
||||
|
||||
// change curve tightness
|
||||
organicConstant = 1-((abs(accelX)+abs(accelY))*.1);
|
||||
|
||||
//move nodes
|
||||
for (int i=0; i<nodes; i++){
|
||||
nodeX[i] = nodeStartX[i]+sin(radians(angle[i]))*(accelX*2);
|
||||
nodeY[i] = nodeStartY[i]+sin(radians(angle[i]))*(accelY*2);
|
||||
angle[i]+=frequency[i];
|
||||
}
|
||||
}
|
||||
|
||||
97
java/examples/Topics/Simulate/Spring/Spring.pde
Normal file
97
java/examples/Topics/Simulate/Spring/Spring.pde
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Spring.
|
||||
*
|
||||
* Click, drag, and release the horizontal bar to start the spring.
|
||||
*/
|
||||
|
||||
// Spring drawing constants for top bar
|
||||
int s_height = 16; // Height
|
||||
int left = 50; // Left position
|
||||
int right = 150; // Right position
|
||||
int max = 100; // Maximum Y value
|
||||
int min = 20; // Minimum Y value
|
||||
boolean over = false; // If mouse over
|
||||
boolean move = false; // If mouse down and over
|
||||
|
||||
// Spring simulation constants
|
||||
float M = 0.8; // Mass
|
||||
float K = 0.2; // Spring constant
|
||||
float D = 0.92; // Damping
|
||||
float R = 60; // Rest position
|
||||
|
||||
// Spring simulation variables
|
||||
float ps = 60.0; // Position
|
||||
float vs = 0.0; // Velocity
|
||||
float as = 0; // Acceleration
|
||||
float f = 0; // Force
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
size(200, 200);
|
||||
rectMode(CORNERS);
|
||||
noStroke();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
background(102);
|
||||
updateSpring();
|
||||
drawSpring();
|
||||
}
|
||||
|
||||
void drawSpring()
|
||||
{
|
||||
// Draw base
|
||||
fill(0.2);
|
||||
float b_width = 0.5 * ps + -8;
|
||||
rect(width/2 - b_width, ps + s_height, width/2 + b_width, 150);
|
||||
|
||||
// Set color and draw top bar
|
||||
if(over || move) {
|
||||
fill(255);
|
||||
} else {
|
||||
fill(204);
|
||||
}
|
||||
rect(left, ps, right, ps + s_height);
|
||||
}
|
||||
|
||||
|
||||
void updateSpring()
|
||||
{
|
||||
// Update the spring position
|
||||
if(!move) {
|
||||
f = -K * (ps - R); // f=-ky
|
||||
as = f / M; // Set the acceleration, f=ma == a=f/m
|
||||
vs = D * (vs + as); // Set the velocity
|
||||
ps = ps + vs; // Updated position
|
||||
}
|
||||
if(abs(vs) < 0.1) {
|
||||
vs = 0.0;
|
||||
}
|
||||
|
||||
// Test if mouse is over the top bar
|
||||
if(mouseX > left && mouseX < right && mouseY > ps && mouseY < ps + s_height) {
|
||||
over = true;
|
||||
} else {
|
||||
over = false;
|
||||
}
|
||||
|
||||
// Set and constrain the position of top bar
|
||||
if(move) {
|
||||
ps = mouseY - s_height/2;
|
||||
if (ps < min) { ps = min; }
|
||||
if (ps > max) { ps = max; }
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
if(over) {
|
||||
move = true;
|
||||
}
|
||||
}
|
||||
|
||||
void mouseReleased()
|
||||
{
|
||||
move = false;
|
||||
}
|
||||
162
java/examples/Topics/Simulate/Springs/Springs.pde
Normal file
162
java/examples/Topics/Simulate/Springs/Springs.pde
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* Springs.
|
||||
*
|
||||
* Move the mouse over one of the circles and click to re-position.
|
||||
* When you release the mouse, it will snap back into position.
|
||||
* Each circle has a slightly different behavior.
|
||||
*/
|
||||
|
||||
|
||||
int num = 3;
|
||||
Spring[] springs = new Spring[num];
|
||||
|
||||
void setup()
|
||||
{
|
||||
size(200, 200);
|
||||
noStroke();
|
||||
smooth();
|
||||
springs[0] = new Spring( 70, 160, 20, 0.98, 8.0, 0.1, springs, 0);
|
||||
springs[1] = new Spring(150, 110, 60, 0.95, 9.0, 0.1, springs, 1);
|
||||
springs[2] = new Spring( 40, 70, 120, 0.90, 9.9, 0.1, springs, 2);
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
background(51);
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
springs[i].update();
|
||||
springs[i].display();
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed()
|
||||
{
|
||||
for (int i = 0; i < num; i++) {
|
||||
springs[i].pressed();
|
||||
}
|
||||
}
|
||||
|
||||
void mouseReleased()
|
||||
{
|
||||
for (int i=0; i<num; i++) {
|
||||
springs[i].released();
|
||||
}
|
||||
}
|
||||
|
||||
class Spring
|
||||
{
|
||||
// Screen values
|
||||
float xpos, ypos;
|
||||
float tempxpos, tempypos;
|
||||
int size = 20;
|
||||
boolean over = false;
|
||||
boolean move = false;
|
||||
|
||||
// Spring simulation constants
|
||||
float mass; // Mass
|
||||
float k = 0.2; // Spring constant
|
||||
float damp; // Damping
|
||||
float rest_posx; // Rest position X
|
||||
float rest_posy; // Rest position Y
|
||||
|
||||
// Spring simulation variables
|
||||
//float pos = 20.0; // Position
|
||||
float velx = 0.0; // X Velocity
|
||||
float vely = 0.0; // Y Velocity
|
||||
float accel = 0; // Acceleration
|
||||
float force = 0; // Force
|
||||
|
||||
Spring[] friends;
|
||||
int me;
|
||||
|
||||
// Constructor
|
||||
Spring(float x, float y, int s, float d, float m,
|
||||
float k_in, Spring[] others, int id)
|
||||
{
|
||||
xpos = tempxpos = x;
|
||||
ypos = tempypos = y;
|
||||
rest_posx = x;
|
||||
rest_posy = y;
|
||||
size = s;
|
||||
damp = d;
|
||||
mass = m;
|
||||
k = k_in;
|
||||
friends = others;
|
||||
me = id;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (move) {
|
||||
rest_posy = mouseY;
|
||||
rest_posx = mouseX;
|
||||
}
|
||||
|
||||
force = -k * (tempypos - rest_posy); // f=-ky
|
||||
accel = force / mass; // Set the acceleration, f=ma == a=f/m
|
||||
vely = damp * (vely + accel); // Set the velocity
|
||||
tempypos = tempypos + vely; // Updated position
|
||||
|
||||
force = -k * (tempxpos - rest_posx); // f=-ky
|
||||
accel = force / mass; // Set the acceleration, f=ma == a=f/m
|
||||
velx = damp * (velx + accel); // Set the velocity
|
||||
tempxpos = tempxpos + velx; // Updated position
|
||||
|
||||
|
||||
if ((over() || move) && !otherOver() ) {
|
||||
over = true;
|
||||
} else {
|
||||
over = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test to see if mouse is over this spring
|
||||
boolean over() {
|
||||
float disX = tempxpos - mouseX;
|
||||
float disY = tempypos - mouseY;
|
||||
if (sqrt(sq(disX) + sq(disY)) < size/2 ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure no other springs are active
|
||||
boolean otherOver() {
|
||||
for (int i=0; i<num; i++) {
|
||||
if (i != me) {
|
||||
if (friends[i].over == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void display()
|
||||
{
|
||||
if (over) {
|
||||
fill(153);
|
||||
} else {
|
||||
fill(255);
|
||||
}
|
||||
ellipse(tempxpos, tempypos, size, size);
|
||||
}
|
||||
|
||||
void pressed()
|
||||
{
|
||||
if (over) {
|
||||
move = true;
|
||||
} else {
|
||||
move = false;
|
||||
}
|
||||
}
|
||||
|
||||
void released()
|
||||
{
|
||||
move = false;
|
||||
rest_posx = xpos;
|
||||
rest_posy = ypos;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user