// // // // //
CLAUS RYTTER BRUUN DE NEERGAARD phone: +45 2243 9306 mail: clausneergaard@hotmail.com web: clausclaus.com address: Sankt Hans Gade 6, 4. th.
// CONTENT // 1. Code-based collaborative work with Marius Watz, New York, Spring 2012 // 2. Graduation project, ‘Artspace Nordvest’, Department 7, Fall 2012
// Code-based collaborative work // New York, Spring 2012 // With Marius Watz (www.mariuswatz.com)
// Claus Rytter Bruun de Neergaard // www.clausclaus.com, March, 2013 // Tested in Processing 2.0b8 // RANDOM WALK, TWO-DIMENSIONAL WORLD, SLOW-GROW int N = 0, NE = 1, E = 2, SE = 3, S = 4, SW = 5, W = 6, NW= 7; int step = 1; int dir; float x, y; void setup() { size(670, 400); background(255); smooth(); strokeWeight(0.25); fill(200, 200);
}
// start at center x = width/2; y = height/2;
void draw() { // for each loop draw 25 pts for (int i = 0; i < 25; i++) { dir = int(random(0, 8)); // compare dir to all ‘world’ directions if (dir == N) { y -= step; } else if (dir == NE) { x += step; y -= step; } else if (dir == E) { x += step; } else if (dir == SE) { x += step; y += step; } else if (dir == S) { y += step; } else if (dir == SW) { x -= step; y += step; } else if (dir == W) { x -= step; } else if (dir == NW) { x -= step; y -= step; } // if if if if
}
}
screen wrap (x > width) x = 0; (x < 0) x = width; (y < 0) y = height; (y > height) y = 0;
// draw point point(x+step, y+step);
code studies
---
3 | 35
code studies
---
4 | 35
// Claus Rytter Bruun de Neergaard // www.clausclaus.com, March, 2013 // Tested in Processing 2.0b8
else if (r == x -= step; y -= step; z += step; } else if (r == x -= step; z += step; } else if (r == z += step; } else if (r == x -= step; y += step; } else if (r == y += step; } else if (r == x += step; y += step; } else if (r == x += step; } else if (r == x += step; y -= step; } else if (r == y -= step; } else if (r == x -= step; y -= step; } else if (r == x -= step; } else if (r == x -= step; y += step; z -= step; } else if (r == y += step; z -= step; } else if (r == x += step; y += step; z -= step; } else if (r == x += step; z -= step; } else if (r == x += step; y -= step; z -= step; } else if (r == y -= step; z -= step; } else if (r == x -= step; y -= step; z -= step; } else if (r == x -= step; z -= step; } else if (r == z -= step; }
// RANDOM WALK, THREE-DIMENSIONAL WORLD, FULLY GROWN, TIME-BASED REGEN import peasy.*; // declare object instances PeasyCam cam; Wander w; // global variables int n = 3000; int step = 5; float angle = 0.5; int savedTime; int totalTime = 1500; int space = 500; int subdiv = 10;
// // // // // // //
number of points random movement step size beginning rotation time vars to regulate recalc time vars to regulate recalc size of box(es) size of sub-box(es)
// declare array to contain PVector PVector[] pos = new PVector[n]; void setup() { size(670, 250, P3D); background(245); savedTime = millis(); cam = new PeasyCam(this, 400);
}
w = new Wander(); w.calc();
void draw() { background(245); // rotate camera to begin with rotateX(-0.5); rotateY(angle); angle += 0.01; // recalculate every five (5) secs int passedTime = millis() - savedTime; if (passedTime > totalTime) { w.calc(); savedTime = millis(); }
}
for (int i = 0; i < n; i++) { // point float d = dist(0, 0, 0, pos[i].x, pos[i].y, pos[i].z); float dmap = map(d, 0, 1000, 2, 45); strokeWeight(dmap); stroke(50, dmap*2); point(pos[i].x, pos[i].y, pos[i].z); }
// class Wander class Wander { int x, y, z; Wander() { for (int i = 0; i < n; i++) { pos[i] = new PVector(0, 0, 0); } } void calc() { // reset coordinates x = 0; y = 0; z = 0; for (int i = 0; i < n; i++) { // create random integer for direction int r = int(random(0, 25)); // compare random integer to direction numbers, // and add position value if (r == 0) { x -= step; y += step; z += step; } else if (r == 1) { y += step; z += step; } else if (r == 2) { x += step; y += step; z += step; } else if (r == 3) { x += step; z += step; } else if (r == 4) { x += step; y -= step; z += step; } else if (r == 5) { y -= step; z += step; }
}
}
}
6) {
7) {
8) { 9) {
10) { 11) {
12) { 13) {
14) { 15) {
16) { 17) {
18) {
19) {
20) {
21) {
22) {
23) {
24) {
25) {
// write position values to array pos[i].set(x, y, z);
code studies
---
5 | 35
code studies
---
6 | 35
// Claus Rytter Bruun de Neergaard // www.clausclaus.com, March, 2013 // Tested in Processing 2.0b8
} else if (r == x += step; } else if (r == x += step; y -= step; } else if (r == y -= step; } else if (r == x -= step; y -= step; } else if (r == x -= step; } else if (r == x -= step; y += step; z -= step; } else if (r == y += step; z -= step; } else if (r == x += step; y += step; z -= step; } else if (r == x += step; z -= step; } else if (r == x += step; y -= step; z -= step; } else if (r == y -= step; z -= step; } else if (r == x -= step; y -= step; z -= step; } else if (r == x -= step; z -= step; } else if (r == z -= step; }
// RANDOM WALK import peasy.*; PeasyCam cam; int n = 3000; int step = 5; int space = 500; int x = 0, y = 0, z = 0; int[] posX = new int[n]; int[] posY = new int[n]; int[] posZ = new int[n]; void setup() { size(500, 500, P3D); background(235); stroke(0, 100); cam = new PeasyCam(this, 900); }
compare();
void draw() { background(235); stroke(0, 100); strokeWeight(5.0); for (int i = 0; i < n; i++) { point(posX[i], posY[i], posZ[i]); }
}
noFill(); strokeWeight(0.25); box(space);
void keyPressed() { if (key == ‘r’) { x = 0; y = 0; z = 0; compare(); } } void compare() { for (int i = 0; i < n; i++) { // create random integer for direction int r = int(random(0, 25)); println(r); // compare random integer to direction numbers, // and add position value if (r == 0) { x -= step; y += step; z += step; } else if (r == 1) { y += step; z += step; } else if (r == 2) { x += step; y += step; z += step; } else if (r == 3) { x += step; z += step; } else if (r == 4) { x += step; y -= step; z += step; } else if (r == 5) { y -= step; z += step; } else if (r == 6) { x -= step; y -= step; z += step; } else if (r == 7) { x -= step; z += step; } else if (r == 8) { z += step; } else if (r == 9) { x -= step; y += step; } else if (r == 10) { y += step; } else if (r == 11) { x += step; y += step;
}
}
12) { 13) {
14) { 15) {
16) { 17) {
18) {
19) {
20) {
21) {
22) {
23) {
24) {
25) {
// write position values to array posX[i] = x; posY[i] = y; posZ[i] = z;
code studies
---
7 | 35
code studies
---
8 | 35
code studies
---
9 | 35
Rules (metho R01: R02: R03: R04: R05: R06: R07: R08: R09: R10: R11: R01: Separation
R02: Alignment
R03: Cohesion
R04: Avoidance
R05: Seek
S A C A S F P E F Q L
Form:
F01: .
Scenar
S01: .
R06: Flee
R07: Pursue
R08: Evade
R09: Flow field following
R10: Queing
R11: Leader following
code studies
---
10 | 35
// Claus Rytter Bruun de Neergaard // www.clausclaus.com, March, 2013 // Tested in Processing 2.0b8
} if (loc.y > height) { loc.y = 0; } else if (loc.y < 0) { loc.y = height; }
// AGENT BEHAVIOR, TWO-DIMENSIONAL WORLD // VARS ///////////////////////////////////////////////////////////////// int na = 200; // number of agents float range = 125.0; // range of each agent float sepscale = 0.5; // separation scale float aliscale = 10.5; // alignment scale float cohscale = 7.5; // cohesion scale color acolor = color(100); // agent color float aradius = 7.5; // agent size boolean connect = true;
// determins if connections are drawn
ArrayList agents = new ArrayList();
// an ArrayList to store all agents
} // DISPLAY //////////////////////////////////////////////////////////// void display() { fill(0, 0, 150, 50); strokeWeight(0.1); stroke(acolor); ellipse(loc.x, loc.y, maxvel*8.25, maxvel*8.25); strokeWeight(3.5); point(loc.x, loc.y);
// SETUP //////////////////////////////////////////////////////////////// void setup() { size(1189, 841); background(230); smooth(); ellipseMode(CENTER);
}
} // RULE 1 - SEPARATION //////////////////////////////////////////////// PVector separation(ArrayList pop) { PVector sum = new PVector(); // vector to return int n = 0; // counter
for (int i = 0; i < na; i++) { agents.add(new Agent()); }
for (int i = 0; i < pop.size(); i++) { Agent a = (Agent) pop.get(i); float d = loc.dist(a.loc);
// DRAW ///////////////////////////////////////////////////////////////// void draw() { background(230);
// if dist is within range, and larger than zero if ((d > 0) && (d < range/3)) { // calculate vector pointing away from neighbor(s) sum = loc.get(); sum.sub(a.loc); sum.normalize(); sum.mult(1/d); n++; }
// create trail for each agent noStroke(); // calling functions of all of the objects in the ArrayList for (int i = 0; i < agents.size(); i++) { Agent a = (Agent) agents.get(i); a.update(agents); }
}
} // calculate average (based on how many agents within range) if (n > 0) { sum.mult(1/float(n)); }
// draw connections if (connect == true) { for (int i = 0; i < agents.size(); i++) { Agent ca = (Agent) agents.get(i); for (int j = i; j < agents.size(); j++) { Agent oa = (Agent) agents.get(j); if (dist(ca.loc.x, ca.loc.y, oa.loc.x, oa.loc.y) < (range/2)) { stroke(150); strokeWeight(0.5); line(ca.loc.x, ca.loc.y, oa.loc.x, oa.loc.y); } } } }
return sum;
// RULE 2 - COHESION ////////////////////////////////////////////////// PVector cohesion(ArrayList pop) { PVector sum = new PVector(); // vector to return int n = 0; // counter for (int i = 0; i < pop.size(); i++) { Agent a = (Agent) pop.get(i); float d = loc.dist(a.loc);
// KEYPRESSED /////////////////////////////////////////////////////////// void keyPressed() {
}
// if dist is within range, and larger than zero if ((d > 0) && (d < range)) { sum.add(a.loc); n++; }
// enable or disable connections if (key == ‘1’) { connect = true; } else if (key == ‘2’) { connect = false; }
} // calculate average (based on how many agents within range) if (n > 0) { sum.mult(1/float(n)); sum = steer(sum, true); }
class Agent { PVector loc, vel, acc, ploc; float maxforce, maxvel;
return sum;
// RULE 3 - ALIGNMENT ///////////////////////////////////////////////// PVector alignment(ArrayList pop) { PVector sum = new PVector(); // vector to return int n = 0; // counter
// three vectors to describe agent loc, vel and acc loc = new PVector(random(0, width), random(0, height)); vel = new PVector(0, 0); acc = new PVector(0, 0); ploc = loc;
for (int i = 0; i < pop.size(); i++) { Agent a = (Agent) pop.get(i); float d = loc.dist(a.loc);
// maxforce makes sure that not all agents move with same speed //maxforce = random(0.10, 0.75); maxvel = random(3.5, 10.5);
// if dist is within range, and larger than zero if ((d > 0) && (d < range)) { sum.add(a.vel); n++; }
// UPDATE ///////////////////////////////////////////////////////////// void update(ArrayList pop) { }
// update the movement animate(pop); // update position vel.add(acc); vel.limit(maxvel); loc.add(vel); acc.set(0, 0, 0);
}
// // // //
// calculate average (based on how many agents within range) if (n > 0) { sum.mult(1/float(n)); sum.limit(maxforce); }
add acceleration to velocity (increase speed) make sure there is a movement speed limit add velocity to location make sure we set acceleration back to zero
return sum;
// (RULE 4) - STEER /////////////////////////////////////////////////// PVector steer(PVector target, boolean slow) { PVector steerforce; // the steering vector target.sub(loc); float m = target.mag(); // calc the magnitude of the vector
// calculate the steering vectors PVector sep = separation(pop); PVector coh = cohesion(pop); PVector ali = alignment(pop);
// if dist is within range, and larger than zero (zero being itself) if (m > 0 && m < range) { target.normalize(); // calc deceleration if slow is on, else, just continue if ((slow == true) && (m < (range/2))) { target.mult(maxvel * (range/width)); } else { target.mult(maxvel); }
// scale all vectors sep.mult(sepscale); coh.mult(cohscale); ali.mult(aliscale); // add all steering vectors to movement acc.add(sep); acc.add(coh); acc.add(ali);
// EDGES ////////////////////////////////////////////////////////////// void edges() { if (loc.x > width) { loc.x = 0; } else if (loc.x < 0) { loc.x = width;
// return the vector
}
// standard update functions edges(); display();
// ANIMATE //////////////////////////////////////////////////////////// void animate(ArrayList pop) {
}
// return the vector
}
Agent() {
}
// return the vector
}
target.sub(vel); steerforce = target.get(); steerforce.limit(maxforce); } else { steerforce = new PVector(0, 0); } return steerforce;
// return the vector
} }
code studies
---
11 | 35
SCENARIO 1 Defined number of agents in a two dimensional space, random point of initiation. Each agent is visualized as a point in space. Subsequent patterns of movement based on separation. There are no external relations, only internal relations define the movement of each agent.
code studies
---
12 | 35
SCENARIO 2 Defined number of agents in a two dimensional space, random point of initiation. Each agent is visualized as a point in space. Subsequent patterns of movement based on separation and cohesion. There are no external relations, only internal relations define the movement of each agent.
code studies
---
13 | 35
SCENARIO 3 Defined number of agents in a two dimensional space, random point of initiation. Each agent is visualized as a point in space. Subsequent patterns of movement based on cohesion and alignment. There are no external relations, only internal relations define the movement of each agent.
code studies
---
14 | 35
SCENARIO 4 Defined number of agents in a two dimensional space, random point of initiation. Each agent is visualized as a point in space. Subsequent patterns of movement based on separation, cohesion and alignment. There are no external relations, only internal relations define the movement of each agent.
code studies
---
15 | 35
SCENARIO 5 Defined number of agents in a two dimensional space, random point of initiation. Each agent is visualized as a circle in space. Subsequent patterns of movement based on separation, cohesion and alignment. There are no external relations, only internal relations define the movement of each agent.
code studies
---
16 | 35
SCENARIO 6 Defined number of agents in a two dimensional space, random point of initiation. Each agent is visualized as a circle in space. All agents located within a defined range of another agent is visually connected by a line. Subsequent patterns of movement based on separation, cohesion and alignment. There are no external relations, only internal relations define the movement of each agent.
code studies
---
17 | 35
SCENARIO 7 Defined number of agents in a two dimensional space, random point of initiation. Agents are not visualized, only agents located within a defined range of another agent is visually connected by a line. Subsequent patterns of movement based on separation, cohesion and alignment. There are no external relations, only internal relations define the movement of each agent.
code studies
---
18 | 35
SCENARIO 8 Defined number of agents in a three dimensional space, random point of initiation. Each agent is visualized as a sphere in space. All agents located within a defined range of another agent is visually connected by a line. Subsequent patterns of movement based on separation, cohesion and alignment. There are no external relations, only internal relations define the movement of each agent.
code studies
---
19 | 35
code studies
---
20 | 35
code studies
---
21 | 35
// Claus Rytter Bruun de Neergaard // www.clausclaus.com, March, 2013 // Tested in Processing 2.0b8
loc.x = 0; } else if (loc.x < 0) { loc.x = world; }
// AGENT BEHAVIOR, THREE-DIMENSIONAL WORLD, AFFECTING / CREATING GEOMETRY import peasy.*;
// y-direction if (loc.y > world) { loc.y = 0; } else if (loc.y < 0) { loc.y = world; }
PeasyCam cam; int n = 100; int grayscale = 255; int subgrid = 50; float strokethick = 3.5; float speed = 10.0; float acceleration = 0.35; int world = 500; float noiseX = 100, noiseY = 110, noiseZ = 120; float nX = (world/2), nY = (world/2), nZ = -(world/2); float inc = 0.015;
}
// z-direction if (loc.z > 0) { loc.z = -world; } else if (loc.z < -world) { loc.z = 0; }
ArrayList agents = new ArrayList(n);
}
void setup() { size(670, 450, P3D); background(120);
void grid() { noFill(); stroke(255); strokeWeight(1); pushMatrix(); translate(world/2, world/2, -(world/2)); box(world); popMatrix();
// set camera from the beginning cam = new PeasyCam(this, 750); cam.setRotations(0.75, 0.65, -0.2); cam.lookAt(world/2, world/2, -world/2);
}
// create number of starting agents for (int i = 0; i < n-1; i++) { agents.add(new Agent()); }
// check if agents inside subgrid for (int x = 0; x < world; x += subgrid) { for (int y = 0; y < world; y += subgrid) { for (int z = -world; z < 0; z += subgrid) {
void draw() { background(120);
// for each subgrid field - loop through all agents for (int i = 0; i < agents.size(); i++) { Agent a = (Agent) agents.get(i);
// update noise attractor noiseAtt();
// if agent is inside subgrid, draw box if ((a.loc.x > x) && (a.loc.x < x+subgrid) && (a.loc.y > y) && (a.loc.y < y+subgrid) && (a.loc.z < z) && (a.loc.z > z-subgrid)) {
// call functions within each agent for (int i = 0; i < agents.size(); i++) { Agent a = (Agent) agents.get(i); a.movement(); a.display(); a.edges(); }
}
stroke(255, 35); noFill();
// evaluate grid background, based on agent pos grid();
void noiseAtt() { // calc noise movement nX = noise(noiseX) * world; nY = noise(noiseY) * world; nZ = noise(noiseZ) * (-world); noiseX = noiseX + inc; noiseY = noiseY + inc; noiseZ = noiseZ + inc;
}
}
}
}
}
}
}
// (a bit weird translate, since box is drawn at center) pushMatrix(); translate(x+(subgrid/2), y+(subgrid/2), z-(subgrid/2)); box(subgrid); popMatrix();
// draw attractor stroke(255, 0, 0); strokeWeight(6.0); point(nX, nY, nZ);
class Agent { PVector loc; PVector vel; PVector acc; // constructor Agent() { loc = new PVector(random(0, world), random(0, world), random(-world, 0)); vel = new PVector(0, 0, 0); } void movement() { // algorithm for calculating acceleration PVector att = new PVector(nX, nY, nZ); PVector dir = PVector.sub(att, loc); dir.normalize(); dir.mult(acceleration); acc = dir;
}
// // // // //
find vector pointing towards mouse normalize scale set to acceleration
// vel changes by acc; loc changes by vel vel.add(acc); vel.limit(speed); loc.add(vel);
void display() { stroke(grayscale); strokeWeight(strokethick); point(loc.x, loc.y, loc.z); } void edges() { // x-direction if (loc.x > world) { code studies
---
22 | 35
code studies
---
23 | 35
code studies
---
24 | 35
GRID DEFORMATION In extension of working with agent-based geometry, we tried to figure out how to apply deformation strategies to existing geometry, such as a mesh. Beginning with a simple surface, the experiments evolved to applying deformation on more advanced shapes, randomly generated by the algorithm.
code studies
---
25 | 35
code studies
---
26 | 35
code studies
---
27 | 35
code studies
---
28 | 35
code studies
---
29 | 35