(n)certainties RMIT-UTS Spring 012

(n)certainties RMIT-UTS Spring 012 header image 3

serra t[err]a_code

/*
* Copyright (c) 2012 Gwyllim Jahn
* http://scripts.crida.net/gh

* Developed By Gwyllim Jahn, Kathryn McKenzie and Sarah Papadopoullos
* during the 2012 RMIT nCertainties studio.
*
* This code makes extensive use of several freely distributed
* processing libraries – thankyou especially to toxi.

*This code is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* http://creativecommons.org/licenses/LGPL/2.1/
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/

  • //—————————————————–Bansia Pumps v2——————————————————–//

import processing.pdf.*;

import processing.video.*;

import controlP5.*;

import processing.dxf.*;

import toxi.geom.*;

import toxi.volume.*;

import peasy.org.apache.commons.math.*;

import peasy.*;

import peasy.org.apache.commons.math.geometry.*;

import processing.opengl.*;

// ———————————————————————————-GLOBALS

int DX=900;

int DY=900;

int DZ=300;

float density = 0.3;

VolumetricSpaceArray volume;

VolumetricBrush brush;

boolean saveRaw = false;

boolean paused = false;

PeasyCam cam;

ControlP5 controlP5;

ControlWindow controlWindow;

MovieMaker mm;

int numAgents = 40;

boolean record = false;

boolean filming = false;

//HashMap<String, ArrayList<Agent>> aMap =new HashMap<String, ArrayList<Agent>> ();

//MultiMap agentPop = MultiValueMap.decorate(aMap);

ArrayList<Agent> agentPop = new ArrayList<Agent>();

ArrayList<SapMonster> sapPop = new ArrayList<SapMonster>();

ArrayList<TreeAttractor>forest = new ArrayList<TreeAttractor>();

ArrayList<Agent>addList = new ArrayList<Agent>();

Boolean drawPts = false;

Boolean drawSingle = false;

int ct =0;

//agent variables

//number of points to draw a trail with

int trailLength = 100;

float agentSpeed = 0.5;

//distance between trail points

int dropSpacing = 5;

//size of field to spawn agents

float spawnSizeXY = 10;

float aAttract = 1;

float aAlign = 0.03;

float aRepel = 3;

float aAccel = 0.02;

//NEW VARIABLES

float maxAgentSize = 15;

float increaseSize = 0.3;

float distToTree = 10;

int firstTree = 7;

//set iso density to spawn size

Vec3D SCALE=new Vec3D(450,450,300);

float sX = SCALE.x/DX;

float sY = SCALE.y/DY;

float sZ = SCALE.z/DZ;

//camera look at point

float camx =200;

float camy = 200;

float camz = 0;

//resolution of the dots

int r = 2;

// ———————————————————————————-SETUP

void setup(){

size(700,700,P3D);

cam = new PeasyCam(this,camx,camy,camz, 400);

stroke(255);

mm = new MovieMaker(this, width, height, “drawing.mov”, 30, MovieMaker.ANIMATION, MovieMaker.HIGH);

//load in the tree locations

importLandscape();

//spawn all the agents

spawn();

//setup the controllers

setupP5();

//volume brush stuff

volume=new VolumetricSpaceArray(SCALE,DX,DY,DZ);

brush=new RoundBrush(volume,5);

}

// ———————————————————————————-DRAW LOOP

void draw(){

background(0);

//this draws the actual voxels as points – very slow…

//only useful for checking if things are working.

if(record){

beginRaw(PDF,”test_####.pdf”);

}

if(drawPts){

drawVox();

}

//—————————————————GUTS

for (Agent a :agentPop){

a.run();

}

for (TreeAttractor t :forest){

t.render();

}

ArrayList<Integer> removeList = new ArrayList<Integer>();

int c =0;

for (SapMonster s :sapPop){

if(s.alive){

s.run();

}else{

removeList.add(c);

}

c++;

}

sapPop.removeAll(removeList);

if(addList.size()>0){

for (Agent a:addList){

agentPop.add(a);

}

addList = new ArrayList<Agent>();

}

//—————————————————GUTS

if(record){

endRaw();

record = false;

}

if(filming)mm.addFrame();

if (saveRaw) {

// save mesh as STL or OBJ file

GsaveData(volume,”F:/gsave”+ct+”.raw”);

saveRaw=false;

ct++;

}

}

void keyPressed(){

//s saves a dxf

if (key == ‘s’) {

record = !record;

}

if(key == ‘v’){

saveRaw = !saveRaw;

}

//c screen capture.

if (key == ‘c’){

saveFrame(“pic_####.png”);

}

if(key == ‘m’){

if(!filming) {

filming = true;

}else{

filming = false;

mm.finish(); // Finish the movie if space bar is pressed!

}

}

if (key == ‘r’){

//reset the sketch

importLandscape();

spawn();

}

if (key == ‘d’){

drawPts = !drawPts;

}

if (key == ‘p’){

paused = !paused;

}

if (key == ‘1’){

drawSingle = !drawSingle;

print(drawSingle);

}

}

//————————————————— Agent ——————————————————–//

//simple agent class to interact with the data

//field and other agents

class Agent {

Vec3D loc,vel,acc;

ArrayList<Vec3D> trail;

float aSize;

float dropNum;

boolean ruptured;

TreeAttractor parent;

float aX,aY,aZ;

Agent(Vec3D _loc, Vec3D _vel, TreeAttractor _parent){

loc = _loc;

vel = _vel;

acc = new Vec3D(0,0,0);

trail = new ArrayList<Vec3D>();

dropNum = 0;

ruptured = false;

aSize =1;

parent = _parent;

aX = aY= aZ=0;

}

void run(){

if(!paused){

//acc = new Vec3D(0,0,0);

getGridPos();

if(parent.volume>0){

aSize = 1;

searchAgents();

}else{

if(aSize>1)aSize-=0.2;

searchTrees();

}

update();

volBrushLocation();

}

if(!drawPts){

render();

}

}

//————————————————————————————-

//Basic Flock Function.

//————————————————————————————-

void searchAgents(){

//reset accel

for (Agent a:agentPop){

//get essential variables

Vec3D diff = a.loc.sub(loc.copy());

float d = diff.magnitude();

if(d<80&&d>0){

attract(diff.copy(),d); //attract to neighbour

align(a.vel.copy(),d); //align with neighbour

if(d<10) {

repel(diff.copy(),d); //avoid neighbour

if(loc.z>15) {

if(aSize<maxAgentSize) aSize+=increaseSize; //increase size of agent

}

}

}

}

//explode if too fat…

if(aSize>8){

// rupture();

}else{

ruptured = false;

}

//pull back to the threshold

pushPullToData(0.1);

}

void attract (Vec3D v, float d){

acc.interpolateToSelf(v,(aAttract/d));

}

void align(Vec3D v, float d){

acc.interpolateToSelf(v,aAlign);

}

void repel (Vec3D v, float d){

v.invert();

acc.interpolateToSelf(v,(aRepel/d));

}

//————————————————————————————-

//random tree search and respawn

//————————————————————————————-

void searchTrees(){

if(loc.z<10){

Vec3D searchDir = new Vec3D(random(-1,1),random(-1,1),random(0));

vel.set(vel.x,vel.y,vel.z/10);

acc.interpolateToSelf(searchDir,0.1);

}else{

vel.addSelf(new Vec3D(0,0,-0.5));

pushPullToData(0.1);

}

//if(loc.z<10)vel.set(vel.x,vel.y,vel.z/10);

//check for nearby trees

for (TreeAttractor t:forest){

if(t.volume>0){

if(loc.distanceTo(t.loc)<distToTree){

parent = t;

respawn(t);

}

}

}

}

void respawn(TreeAttractor t){

for (int i=0;i<20;i++){

// Vec3D loc = new Vec3D(random(0,gW*gRes),random(0,gH*gRes),0);

Vec3D loc = new Vec3D(random(-spawnSizeXY,spawnSizeXY),random(-spawnSizeXY,spawnSizeXY),0);

loc.addSelf(t.loc);

Vec3D vel = new Vec3D(0,0,1);

Agent a = new Agent(loc,vel,t);

addList.add(a);

}

}

//————————————————————————————-

//Spawning/rupture functions

//————————————————————————————-

void rupture(){

if(!ruptured){

for (int i=0;i<10;i++){

// Vec3D sVel = new Vec3D(random(-1,1),random(-1,1),random(-1,1));

Vec3D sVel = vel.cross(new Vec3D(0,0,1));

sVel.rotateZ(random(-0.8,0.8));

SapMonster a = new SapMonster(loc.add(sVel),sVel,this);

sapPop.add(a);

}

}

ruptured = true;

}

//————————————————————————————-

//Voxel and volume brush functions

//————————————————————————————-

void volBrushLocation(){

brush.setSize(aSize);

float aX = constrain(loc.x,0,SCALE.x);

aX = map(aX,0,SCALE.x,0,DX);

float aY = constrain(loc.y,0,SCALE.y);

aY = map(aY,0,SCALE.y,0,DY);

float aZ = constrain(loc.z,0,SCALE.z);

aZ = map(aZ,0,SCALE.z,0,DZ);

brush.drawAtGridPos(aX,aY,aZ,density);

parent.volume-=0.1;

}

void getGridPos(){

aX = constrain(loc.x,0,SCALE.x);

aX = map(aX,0,SCALE.x,0,DX);

aY = constrain(loc.y,0,SCALE.y);

aY = map(aY,0,SCALE.y,0,DY);

aZ = constrain(loc.z,0,SCALE.z);

aZ = map(aZ,0,SCALE.z,0,DZ);

}

void pushPullToData(float t){

float bestThreshDiff = 100;

Vec3D bestThreshPt = new Vec3D(0,0,0);

//iterate over neighbouring grid pos

for (int i =-5;i<=5;i++){

for (int j =-5;j<=5;j++){

for (int k =-5; k<=5;k++){

//if the value of this noisepoints better than the others, then update variables

//scale val by distance

Vec3D vec = new Vec3D(i,j,k);

if((aX+i)>=0&&(aX+i)<DX&&(aY+j)>=0&&(aY+j)<DY&&(aZ+k)>=0&&(aZ+k)<DZ){

float val = volume.getVoxelAt(int(aX+i),int(aY+j),int(aZ+k));

//only use pts within field of view

float angleDiff = vel.angleBetween(vec,true);

angleDiff = map(angleDiff,0,PI*2,0,1);

if(angleDiff<0.5){

float threshVal = abs(val-t);

if(threshVal <bestThreshDiff) bestThreshDiff=threshVal;

//float threshVal = val;

vec.scaleSelf(1-((threshVal)*(1-angleDiff)));

bestThreshPt.addSelf(vec);

if(threshVal<bestThreshDiff)bestThreshDiff=threshVal;

}

}

}

}

}

if(bestThreshDiff<0.01){

//attract to threshold

bestThreshPt.scaleSelf(0.05);

acc.addSelf(bestThreshPt);

}

}

//————————————————————————————-

//Functions for managing trails and rendering the agent.

//————————————————————————————-

void update(){

//move the agent

acc.limit(aAccel);

vel.addSelf(acc);

vel.limit(agentSpeed);

loc.addSelf(vel);

//update the trail geom every 5 moves

if(dropNum%dropSpacing==0){

if(trail.size()<trailLength){

trail.add(new Vec3D(loc.x, loc.y, loc.z));

}else{

trail.remove(0);

}

dropNum=0;

}

dropNum++;

}

void render(){

//render agent trail as lines

Vec3D ls = null;

stroke(255);

for (Vec3D l : trail){

if(ls !=null){

line (l.x,l.y,l.z,ls.x,ls.y,ls.z);

}

ls = l;

}

}

void renderPts(){

//render agent trail as lines

for (Vec3D l : trail){

point (l.x,l.y,l.z);

}

}

}

  • //—————————————————–Controller——————————————————–//

void setupP5 (){

controlP5 = new ControlP5(this);

controlP5.setAutoDraw(false);

controlWindow = controlP5.addControlWindow(“controlP5window”,100,100,400,300);

controlWindow.hideCoordinates();

Controller mySlider1 = controlP5.addSlider(“agentSpeed”,0,3.5).linebreak();

mySlider1.setWindow(controlWindow);

Controller mySlider2 = controlP5.addSlider(“aAttract”,0,5.00).linebreak();

mySlider2.setWindow(controlWindow);

Controller mySlider3 = controlP5.addSlider(“aAlign”,0,0.10).linebreak();

mySlider3.setWindow(controlWindow);

Controller mySlider4 = controlP5.addSlider(“aRepel”,0,5.00).linebreak();

mySlider4.setWindow(controlWindow);

Controller mySlider8 = controlP5.addSlider(“aAccel”,0,0.100).linebreak();

mySlider8.setWindow(controlWindow);

Controller mySlider5 =controlP5.addSlider(“dropSpacing”,1,20).linebreak();

mySlider5.setWindow(controlWindow);

Controller mySlider6 =controlP5.addSlider(“trailLength”,1,200).linebreak();

mySlider6.setWindow(controlWindow);

Controller mySlider7 =controlP5.addSlider(“spawnSizeXY”,10,500).linebreak();

mySlider7.setWindow(controlWindow);

Controller mySlider9 =controlP5.addSlider(“maxAgentSize”,5,30).linebreak();

mySlider9.setWindow(controlWindow);

Controller mySlider10 =controlP5.addSlider(“increaseSize”,0.1,0.6).linebreak();

mySlider10.setWindow(controlWindow);

controlWindow.setTitle(“Spring GUI”);

}

  • //—————————————————–Initialisation——————————————————–//

// this is the function that creates all of the agents that fly through the

// noisefield. So this is where you control the agents initial location

// and also their initial velocity.

void spawn(){

agentPop = new ArrayList();

TreeAttractor p = forest.get(firstTree);

for (int i=0;i<numAgents;i++){

// Vec3D loc = new Vec3D(random(0,gW*gRes),random(0,gH*gRes),0);

Vec3D loc = new Vec3D(random(spawnSizeXY/2,spawnSizeXY*1.5),random(spawnSizeXY/2,spawnSizeXY*1.5),0);

loc.addSelf(p.loc);

Vec3D vel = new Vec3D(0,0,1);

Agent a = new Agent(loc,vel,p);

agentPop.add(a);

}

}

//a couple of voxel functions

void drawVox(){

for (int i=0;i<DX;i+=r){

for (int j =0;j<DY;j+=r){

for (int k=0;k<DZ;k+=r){

//make a point at the current coordinate,

//use the value of the noise at that point

//as the points colour.

float v = volume.getVoxelAt(i,j,k)*200;

if(v>1){

stroke(v);

line(i*sX,j*sY,k*sZ,i*sX,j*sY,k*sZ+1);

}else if(v<-1){

stroke(abs(v),0,0);

line(i*sX,j*sY,k*sZ,i*sX+2,j*sY,k*sZ);

}

}

}

}

}

public void GsaveData(VolumetricSpaceArray v,String fn) {

print(“saving volume data…”);

int c=0;

int tot = v.getData().length;

try {

BufferedOutputStream ds = new BufferedOutputStream(new FileOutputStream(fn));

// ds.writeInt(volumeData.length);

for (float element : v.getData()) {

if(element<0)element=0;

ds.write((int)(element*100));

}

ds.flush();

ds.close();

} catch (IOException e) {

e.printStackTrace();

}

}

void importLandscape() {

forest = new ArrayList<TreeAttractor>();

//load text

String[] txtLines = loadStrings(“trees.txt”);

//splits strand points

String[] arrCoords = split(txtLines[0], ‘_’);

for (int j = 0; j < arrCoords.length; ++j) {

//separates coords

String[] arrToks = split(arrCoords[j], ‘,’);

float xx = Float.valueOf(arrToks[0]);

float yy = Float.valueOf(arrToks[1]);

float zz = Float.valueOf(arrToks[2]);

//create node

Vec3D tmpPt = new Vec3D(xx, yy, 0);

TreeAttractor tree = new TreeAttractor(tmpPt);

forest.add(tree);

}

}

  • //—————————————————–Point——————————————————–//

class TreeAttractor {

Vec3D loc;

float volume;

TreeAttractor(Vec3D LOC){

loc = LOC;

volume = 1000;

}

void render(){

point(loc.x,loc.y,loc.z);

}

}

  • //—————————————————–Sap Monster ——————————————————–//

//simple agent class to interact with the data

//field and other agents

class SapMonster {

Vec3D loc,vel,acc;

float aSize;

float age;

boolean alive;

Agent a;

SapMonster(Vec3D _loc, Vec3D _vel, Agent _a){

loc = _loc;

acc = new Vec3D(0,0,0);

vel = _vel;

aSize =2;

a = _a;

age = 0;

alive = true;

}

void run(){

searchAgents();

updatePos();

volBrushLocation();

render();

if(age>5) alive= false;

}

//————————————————————————————-

//Basic Lace Function. Draws an arc with the agent.

//————————————————————————————-

void updatePos(){

acc.interpolateToSelf(a.vel,0.1);

acc.limit(0.2);

vel.addSelf(acc);

vel.limit(1);

loc.addSelf(vel);

age+=0.1;

}

//————————————————————————————-

//Global Attraction functions

//————————————————————————————-

void searchAgents(){

//reset accel

for (SapMonster s:sapPop){

//get essential variables

Vec3D diff = s.loc.sub(loc.copy());

float d = diff.magnitude();

if(d>30){

attract(diff.copy(),d); //attract to neighbour

}else if (d>1 &&d<30){

repel(diff.copy(),d); //repel

}

}

}

void attract (Vec3D v, float d){

// v.normalizeTo(0.01/d);

acc.interpolateToSelf(v,0.01/d);

}

void repel (Vec3D v, float d){

v.invert();

//v.normalizeTo(0.01/d);

acc.interpolateToSelf(v,1/d);

}

//————————————————————————————-

//Voxel and volume brush functions

//————————————————————————————-

void volBrushLocation(){

brush.setSize(aSize);

float aX = constrain(loc.x,0,SCALE.x);

aX = map(aX,0,SCALE.x,0,DX);

float aY = constrain(loc.y,0,SCALE.y);

aY = map(aY,0,SCALE.y,0,DY);

float aZ = constrain(loc.z,0,SCALE.z);

aZ = map(aZ,0,SCALE.z,0,DZ);

brush.drawAtGridPos(aX,aY,aZ,-density);

}

//————————————————————————————-

//Functions for managing trails and rendering the agent.

//————————————————————————————-

void render(){

point (loc.x,loc.y,loc.z);

}

}