Hi guys,
could someone point me in the right direction....I have a sketch (attached) to do with optimal paths based on a particle and springs system. It's working how I want but I need to create a mesh around the 'threads' to give them thickness. The mesh needs to branch where the threads separate and thicken where there are more threads.
The threads themselves never really branch as they don't actually connect and that is why I was thinking some sort of marching cubes algorithm would suit. The threads are made up of a set of springs and particles.
I think the volumeutils part of the toxiclibs library will do what I want but I'm really not sure how to start implementing it. If anyone fancies having a quick look at my sketch and has any ideas on how best to implement the toxiclibs library I'd really appreciate it!
thanks, farley
in my sketch:
// first phase
'a' initiates attraction between primary springs
'p' turns particles on/off
// second phase
'm' makes secondary springs
'a' initiates attraction between secondary springs
could someone point me in the right direction....I have a sketch (attached) to do with optimal paths based on a particle and springs system. It's working how I want but I need to create a mesh around the 'threads' to give them thickness. The mesh needs to branch where the threads separate and thicken where there are more threads.
The threads themselves never really branch as they don't actually connect and that is why I was thinking some sort of marching cubes algorithm would suit. The threads are made up of a set of springs and particles.
I think the volumeutils part of the toxiclibs library will do what I want but I'm really not sure how to start implementing it. If anyone fancies having a quick look at my sketch and has any ideas on how best to implement the toxiclibs library I'd really appreciate it!
thanks, farley
in my sketch:
// first phase
'a' initiates attraction between primary springs
'p' turns particles on/off
// second phase
'm' makes secondary springs
'a' initiates attraction between secondary springs
- //////////////// IMPORT LIBRARIES ////////////////
- import processing.pdf.*;
- import peasy.*; // the camera library
- import processing.opengl.*; // openGL library
- /*------------------------------------------------------------------
- *** GLOBAL VARIABLES ***
- ------------------------------------------------------------------*/
- //////////////// DECLARE GUI AND CAMERA ////////////////
- PMatrix3D currCameraMatrix;
- PGraphics3D g3;
- PeasyCam theCamera;
- //////////////// DECLARE CRITICAL VARIABLES ////////////////
- int numThreads = 40;
- int numParticles = 20;
- ArrayList webSpringList = new ArrayList();
- ArrayList threadList = new ArrayList();
- ArrayList repellerList = new ArrayList();
- float PRI_MEMBERS_RESTLENGTH = 15;
- float SEC_MEMBERS_RESTLENGTH = 1;
- float DAMPING = 3;
- float ATTRACTION_RANGE = 40;
- float ATTRACTION_FORCE = 2;
- //////////////// DECLARE SWITCHES ////////////////
- boolean attraction = false;
- boolean TOGGLE_ATTRACTION_RANGE = false;
- boolean TOGGLE_FIBRES = true;
- boolean TOGGLE_PARTICLES = true;
- boolean TOGGLE_PRI_SPRINGS = false;
- boolean TOGGLE_SEC_SPRINGS = false;
- boolean MAKE_SECONDARY_SPRINGS = false;
- boolean switchSprings = false;
- //////////////// DECLARE ENVIRONMENT ////////////////
- int boundingBoxX = 500;
- int boundingBoxY = 500;
- int boundingBoxZ = 500;
- /*------------------------------------------------------------------
- *** GLOBAL SETUP ***
- ------------------------------------------------------------------*/
- void setup() {
- size(1280, 720, OPENGL);
- smooth();
- g3 = (PGraphics3D)g;
- initCamera();
- initThreads();
- println("number of threads = " + threadList.size());
- println("number of repellers = " + repellerList.size());
- Thread newThread = (Thread) threadList.get(0);
- println("number of particles / thread = " + newThread.particleList.size());
- println("number of springs / thread = " + newThread.springList.size());
- }
- /*------------------------------------------------------------------
- *** GLOBAL CONTINUOUS DRAW ***
- ------------------------------------------------------------------*/
- void draw() {
- background(30);
- drawThreads();
- drawBox();
- }
- /*------------------------------------------------------------------
- *** GLOBAL FUNCTIONS ***
- ------------------------------------------------------------------*/
- //////////////// MAKE THREADS ////////////////
- void initThreads() {
- for (int i = 0; i < numThreads; i++) {
- Thread tmpThread = new Thread();
- threadList.add(tmpThread);
- }
- }
- //////////////// DRAW THREADS ////////////////
- void drawThreads() {
- for (int i = 0; i < threadList.size(); i++) {
- Thread newThread = (Thread) threadList.get(i);
- newThread.createThread();
- newThread.createSprings();
- newThread.makeWebSprings();
- if (TOGGLE_FIBRES) {
- newThread.drawCurve();
- }
- }
- if (MAKE_SECONDARY_SPRINGS) {
- println("total number of websprings = " + webSpringList.size());
- }
- MAKE_SECONDARY_SPRINGS = false;
- for (int i = 0; i < webSpringList.size(); i++) {
- // get a spring from the arraylist
- Spring currS = (Spring) webSpringList.get(i);
- if (TOGGLE_SEC_SPRINGS) {
- currS.showMe();
- }
- }
- }
- //////////////// DRAW BOUNDING BOX ////////////////
- void drawBox() {
- stroke(100);
- strokeWeight(1);
- noFill();
- pushMatrix();
- translate(boundingBoxX/2, boundingBoxY/2, boundingBoxZ/2);
- box(boundingBoxX, boundingBoxY, boundingBoxZ);
- popMatrix();
- }
- //////////////// SETUP CAMERA ////////////////
- void initCamera() {
- //----------make the camera
- theCamera = new PeasyCam(this, boundingBoxX*2);
- //theCamera.setMinimumDistance(700);
- //theCamera.setMaximumDistance(2000);
- theCamera.lookAt(boundingBoxX/2, boundingBoxY/2, boundingBoxZ/2);
- }
- //////////////// ACTIVATE SWITCHES ////////////////
- void keyPressed() {
- if (key == 'a' || key == 'A') {
- attraction =! attraction;
- }
- if (key == 'R' || key == 'R') {
- TOGGLE_ATTRACTION_RANGE =! TOGGLE_ATTRACTION_RANGE;
- }
- if (key == 'f' || key == 'F') {
- TOGGLE_FIBRES =! TOGGLE_FIBRES;
- }
- if (key == 'p' || key == 'P') {
- TOGGLE_PARTICLES =! TOGGLE_PARTICLES;
- }
- if (key == 'S') {
- TOGGLE_PRI_SPRINGS =! TOGGLE_PRI_SPRINGS;
- }
- if (key == 'm' || key == 'M') {
- MAKE_SECONDARY_SPRINGS =! MAKE_SECONDARY_SPRINGS;
- attraction = false;
- switchSprings = true;
- TOGGLE_SEC_SPRINGS =! TOGGLE_SEC_SPRINGS;
- }
- }
- class Particle {
- /*------------------------------------------------------------------
- *** CLASS VARIABLES ***
- ------------------------------------------------------------------*/
- PVector pos;
- PVector vel;
- PVector acc;
- float pSize;
- boolean pFixed;
- ArrayList conSprings = new ArrayList();
- /*------------------------------------------------------------------
- *** CLASS CONSTRUCTOR ***
- ------------------------------------------------------------------*/
- Particle(PVector pos_) {
- pos = pos_;
- vel = new PVector();
- acc = new PVector();
- pSize = 5.0;
- pFixed = false;
- }
- /*------------------------------------------------------------------
- *** CLASS FUNCTIONS ***
- ------------------------------------------------------------------*/
- //////////////// MOVE AND DRAW TO SCREEN ////////////////
- void update(Thread theThread) {
- if (pFixed==false) {
- updatePos();
- attraction(theThread);
- }
- }
- //////////////// !!SOLVE THE SPRINGS!! ////////////////
- void solveForce() {
- if (pFixed==false) {
- Particle otherP;
- PVector sumForces = new PVector();
- sumForces.add(acc);
- // loop thru our connections
- for (int i = 0; i < conSprings.size(); ++i) {
- // get a spring
- Spring s = (Spring) conSprings.get(i);
- // get other end of spring
- if ( s.p00 == this ) {
- otherP = s.p01;
- }
- else {
- otherP = s.p00;
- }
- // calculate the push/pull of spring
- PVector vecBet = PVector.sub(otherP.pos, pos);
- float currLen = vecBet.mag();
- if (s.springID == 0) {
- float desiredLen = currLen-(PRI_MEMBERS_RESTLENGTH);
- vecBet.normalize();
- vecBet.mult(desiredLen/2);
- // add this force to our sum of forces
- sumForces.add(vecBet);
- }
- if (s.springID == 1) {
- float desiredLen = currLen-(SEC_MEMBERS_RESTLENGTH);
- vecBet.normalize();
- vecBet.mult(desiredLen/2);
- // add this force to our sum of forces
- sumForces.add(vecBet);
- }
- }
- // apply a damping to the force
- if (switchSprings == false) {
- sumForces.mult(DAMPING);
- } else if (switchSprings) {
- sumForces.mult(0.2);
- }
- // add the resultant force to our vel
- vel.add(sumForces);
- }
- }
- //////////////// MOVE PARTICLES ////////////////
- void updatePos() {
- vel.limit(2);
- pos.add(vel);
- acc = new PVector(0, 0, 0);
- if (switchSprings) {
- vel = new PVector(0, 0, 0);
- }
- }
- //////////////// !!ATTRACTION!! ////////////////
- void attraction(Thread theThread_) {
- //////////////// INITIATE ATTRACTION ////////////////
- PVector steer = new PVector();
- int count = 0;
- for (int i = 0; i < threadList.size(); i++) {
- Thread tmpThread = (Thread) threadList.get(i);
- if (theThread_ != tmpThread) {
- for (int j = 0; j < tmpThread.particleList.size(); j++) {
- // get a Particle from the list
- Particle tmpPart = (Particle) tmpThread.particleList.get(j);
- float distance = PVector.dist(tmpPart.pos, pos);
- if (distance > 0 && distance < ATTRACTION_RANGE) {
- if (TOGGLE_ATTRACTION_RANGE) {
- strokeWeight(0.5);
- stroke(180);
- line (tmpPart.pos.x, tmpPart.pos.y, tmpPart.pos.z, pos.x, pos.y, pos.z);
- }
- PVector vecBetween = PVector.sub(tmpPart.pos, pos);
- // get the length of the vector
- vecBetween.normalize();
- steer.add(vecBetween);
- count++;
- }
- }
- }
- }
- if (count > 0) {
- steer.mult(1.0/count);
- }
- steer.mult(ATTRACTION_FORCE);
- acc.add(steer);
- }
- //////////////// FIX / FREE PARTICLES ////////////////
- void fixMe() {
- pFixed=true;
- }
- //////////////// ADD SPRING ////////////////
- void addSpring(Spring S) {
- // store this spring
- conSprings.add(S);
- }
- //////////////// DRAW PARTICLES ////////////////
- void showMe() {
- // set appearance
- noFill();
- if (pFixed==true) {
- // draw as 'FIXED' geometry
- strokeWeight(0.75);
- stroke(220);
- line(pos.x-pSize, pos.y, pos.z, pos.x+pSize, pos.y, pos.z);
- line(pos.x, pos.y-pSize, pos.z, pos.x, pos.y+pSize, pos.z);
- line(pos.x, pos.y, pos.z-pSize, pos.x, pos.y, pos.z+pSize);
- }
- else {
- // draw as 'FREE' geometry
- strokeWeight(0.5);
- stroke(160);
- line(pos.x-pSize/2, pos.y, pos.z, pos.x+pSize/2, pos.y, pos.z);
- line(pos.x, pos.y-pSize/2, pos.z, pos.x, pos.y+pSize/2, pos.z);
- line(pos.x, pos.y, pos.z-pSize/2, pos.x, pos.y, pos.z+pSize/2);
- }
- }
- }
- class Spring {
- /*------------------------------------------------------------------
- *** CLASS VARIABLES ***
- ------------------------------------------------------------------*/
- Particle p00;
- Particle p01;
- int springID;
- /*------------------------------------------------------------------
- *** CLASS CONSTRUCTOR ***
- ------------------------------------------------------------------*/
- Spring (Particle INPUT_00, Particle INPUT_01, int springID_) {
- p00 = INPUT_00;
- p01 = INPUT_01;
- springID = springID_;
- }
- /*------------------------------------------------------------------
- *** CLASS FUNCTIONS ***
- ------------------------------------------------------------------*/
- //////////////// DRAW CURVE ////////////////
- void showMe() {
- stroke(120);
- strokeWeight(0.5);
- noFill();
- line(p00.pos.x, p00.pos.y, p00.pos.z, p01.pos.x, p01.pos.y, p01.pos.z);
- }
- boolean doIExist(boolean evalSpring_) {
- for (int i = 0; i < webSpringList.size(); i++) {
- Spring otherS = (Spring) webSpringList.get(i);
- if ((this.p00 == otherS.p01 && this.p01 == otherS.p00)) {
- evalSpring_ = true;
- }
- }
- return evalSpring_;
- }
- }
- class Thread {
- /*------------------------------------------------------------------
- *** CLASS VARIABLES ***
- ------------------------------------------------------------------*/
- Spring s0, s1;
- ArrayList particleList = new ArrayList();
- ArrayList springList = new ArrayList();
- int randomNum = int(random(15));
- int primaryS = 0;
- int secondaryS = 1;
- boolean evalSpring_;
- /*------------------------------------------------------------------
- *** CLASS CONSTRUCTOR ***
- ------------------------------------------------------------------*/
- Thread() {
- //////////////// MAKE THE END AND MID PARTICLES ////////////////
- if (randomNum <= 5) {
- PVector tmpPos1 = new PVector(random(boundingBoxX), random(boundingBoxY), 0);
- PVector tmpPos2 = new PVector(random(boundingBoxX), random(boundingBoxY), boundingBoxZ);
- createMidParts(tmpPos1, tmpPos2);
- }
- else if (randomNum > 5 && randomNum <= 10) {
- PVector tmpPos1 = new PVector(0, random(boundingBoxY), random(boundingBoxZ));
- PVector tmpPos2 = new PVector(boundingBoxX, random(boundingBoxY), random(boundingBoxZ));
- createMidParts(tmpPos1, tmpPos2);
- }
- else {
- PVector tmpPos1 = new PVector(random(boundingBoxX), 0, random(boundingBoxZ));
- PVector tmpPos2 = new PVector(random(boundingBoxX), boundingBoxY, random(boundingBoxZ));
- createMidParts(tmpPos1, tmpPos2);
- }
- //////////////// MAKE THE SPRINGS ////////////////
- for (int i = 0; i < particleList.size(); i++) {
- if (i > 0) {
- Particle p1 = (Particle) particleList.get(i);
- Particle p2 = (Particle) particleList.get(i-1);
- s0 = new Spring(p1, p2, primaryS);
- springList.add(s0);
- p1.addSpring(s0);
- p2.addSpring(s0);
- }
- }
- }
- /*------------------------------------------------------------------
- *** CLASS FUNCTIONS ***
- ------------------------------------------------------------------*/
- //////////////// MAKE THE MID PARTICLES ////////////////
- void createMidParts(PVector tmpPos1_, PVector tmpPos2_) {
- // sub end vectors
- PVector vecBetween = PVector.sub(tmpPos1_, tmpPos2_);
- // divide vecBetween by 10
- vecBetween.div(numParticles-1);
- for (int i = 0; i < numParticles; i++) {
- // scale vecBetween by i
- PVector vecScale = PVector.mult(vecBetween, i);
- // add new vector to end vector
- PVector newVec = PVector.add(vecScale, tmpPos2_);
- // create new Particle at newVec
- Particle tmpPart = new Particle(newVec);
- // fix end particles
- if ( i == 0 || i == numParticles-1) {
- tmpPart.fixMe();
- }
- // add particle to list
- particleList.add(tmpPart);
- }
- }
- //////////////// CREATE THREAD ////////////////
- void createThread() {
- for (int i = 0; i < particleList.size(); i++) {
- Particle tmpPart = (Particle) particleList.get(i);
- if (attraction) {
- tmpPart.solveForce();
- }
- }
- for (int i = 0; i < particleList.size(); i++) {
- Particle tmpPart = (Particle) particleList.get(i);
- if (attraction) {
- tmpPart.update(this);
- }
- if (TOGGLE_PARTICLES) {
- tmpPart.showMe();
- }
- }
- }
- void createSprings() {
- for (int i = 0; i < springList.size(); i++) {
- // get a spring from the arraylist
- Spring currS = (Spring) springList.get(i);
- if (TOGGLE_PRI_SPRINGS) {
- currS.showMe();
- }
- }
- }
- //////////////// MAKE WEB THE SPRINGS ////////////////
- void makeWebSprings() {
- if (MAKE_SECONDARY_SPRINGS) {
- for (int i = 0; i < numThreads; i++) {
- Thread otherThread = (Thread) threadList.get(i);
- if (this != otherThread) {
- for (int j = 0; j < this.particleList.size(); j++) {
- // get a Particle from the list
- Particle p3 = (Particle) this.particleList.get(j);
- for (int k = 0; k < otherThread.particleList.size(); k++) {
- Particle p4 = (Particle) otherThread.particleList.get(k);
- float distance = PVector.dist(p3.pos, p4.pos);
- if (distance > 0 && distance < 20) {
- s1 = new Spring(p3, p4, secondaryS);
- boolean evalSpring = s1.doIExist(evalSpring_);
- if (evalSpring == false) {
- webSpringList.add(s1);
- p3.addSpring(s1);
- p4.addSpring(s1);
- }
- }
- }
- }
- }
- }
- }
- }
- //////////////// DRAW CURVE ////////////////
- void drawCurve() {
- strokeWeight(1);
- stroke(250, 0, 0);
- noFill();
- beginShape();
- Particle tmpPartFixed01 = (Particle) particleList.get(0);
- curveVertex(tmpPartFixed01.pos.x, tmpPartFixed01.pos.y, tmpPartFixed01.pos.z);
- for (int i = 0; i < particleList.size(); i++) {
- Particle tmpPart = (Particle) particleList.get(i);
- curveVertex(tmpPart.pos.x, tmpPart.pos.y, tmpPart.pos.z);
- }
- Particle tmpPartFixed02 = (Particle) particleList.get(numParticles-1);
- curveVertex(tmpPartFixed02.pos.x, tmpPartFixed02.pos.y, tmpPartFixed02.pos.z);
- endShape();
- }
- }
2