logo

[C]ucarachas

Gallery details

Culebra MultiBehavior Connectivity System – OcTree Optimized

Download the App – prolebra.0.9Beta snippet Test

A multi behavior octree optimized multi agent system built in Processing 3.0 inspired by flocking and Silkworm Behaviors.

PROCESSING 3.0 SKETCH CODE
MAIN
import java.util.List;
import toxi.geom.*;
import toxi.geom.PointOctree;
import toxi.color.*;
import controlP5.*;
import peasy.*;

Tracker a;
ControlP5 cp5;
Culebra_UI cgui;
Path tempPath;

PVector locStart;
PVector triggerLoc = new PVector(0, 0, 0);

boolean simulate, spawnEdge, addNew, D2;
boolean drawPathTargets, toggleUI, drawMovement, mathBehavior, genRandom, triggerSeekers, drawBoundary, drawConn, createOctree;
boolean toggleColor = true;
boolean masterBehavior_A = true;
boolean masterBehavior_B, masterBehavior_C, masterBehavior_D, masterBehavior_E, subBehavior_AA, subBehavior_AB;
boolean drawPaths = false;
boolean SpawnEdge = true;
boolean Dimension = true;
boolean enablePathTrack = true;
boolean showOctree = true;

int triggerCount = 0;
int agentCount = 500;
int resetAmount = 0; 
int camToggle = 0;  
int pathCount = 15;

int nWidth = 1920;
int nDepth = 1080;
int nHeight = 1000;

float WanderRadius, WanderDist, WanderTheta, WanderRotTrigger, MaxChildren;
float PathRad, ScalarProjectDist, PathThresh;
float InitSpeed, MaxSpeed, MaxForce, MaxSep;
float AgentCount;
float seekerTrail, childSeekerTrail;
float HeadWidth, StrokeWidth, Transparency;
float stepCount = 0;
float sepTrigger = 0.0f;

ArrayList<PVector>childSpawners;
ArrayList childSpawnType;
ArrayList<Path> pathList;

List<Tracker> agentList;
java.util.List occTreeList;
List<Vec3D>vec3DList;
VisibleOctree octree;

Button btypeA, btypeAA, btypeAB, btypeB, btypeC, btypeD, btypeE;

PeasyCam cam;
CameraState state;
//---------------------------------------Settings--------------------------------------------
void settings() {
  size(1920, 1080, P3D);
  smooth();
}
//---------------------------------------Setup-----------------------------------------------
void setup() {
  background(0);
  this.octree = new VisibleOctree(new Vec3D(0, 0, 0), nWidth);
  this.octree.setTreeAutoReduction(true);
  
  this.agentList = new ArrayList<Tracker>();
  this.childSpawners = new ArrayList<PVector>();
  this.childSpawnType = new ArrayList();
  this.pathList = new ArrayList<Path>();

  if (!this.D2 && this.camToggle < 1) {
    this.camToggle ++;  
    this.cam = new PeasyCam(this, 1500);
    this.cam.setMinimumDistance(100);
    this.cam.setMaximumDistance(10000);
    this.cam.lookAt(this.nWidth/2, this.nDepth/2, this.nHeight/2);
    this.cam.setSuppressRollRotationMode();
  }
  if (D2) {
    this.cam.reset();
    this.cam.setMinimumDistance(100);
    this.cam.setMaximumDistance(10000);
    this.cam.lookAt(this.nWidth/2, this.nDepth/2, 0);
    this.cam.setDistance(1000);  // distance from looked-at point
    this.cam.setSuppressRollRotationMode();
  }
  simulate = true;
  if (this.resetAmount == 0) {
    this.cgui = new Culebra_UI();
    this.cgui.run(this);
  }
  for (int pth = 0; pth < this.pathCount; pth++) {
    newPath();
  }
  for (int i = 0; i < this.agentCount; i ++) {
    PVector speed;
    if (this.D2) {
      if (this.spawnEdge) {
        locStart = new PVector(0, random(height), 0);
        speed = new PVector(1, 0, 0);
      } else {
        locStart = new PVector(random(width), random(height), 0);
        speed = new PVector(random(-1, 1), random(-1, 1), 0);
      }
      //this.octree.addPoint(new Vec3D(locStart.x,locStart.y,locStart.z));
      this.a = new Tracker(locStart, speed, true, "parent", "main");
    } else {
      if (this.spawnEdge) {
        locStart = new PVector(random(width), random(height), 0);
        speed = new PVector(random(-1, 1), random(-1, 1), random(0, 2));
      } else {
        locStart = new PVector(random(width), random(height), random(0, nHeight));
        speed = new PVector(random(-1, 1), random(-1, 1), random(-1, 1));
      }
      //this.octree.addPoint(new Vec3D(locStart.x,locStart.y,locStart.z));
      this.a = new Tracker(locStart, speed, true, "parent", "main");
    }
    this.agentList.add(this.a);
  }
}
//---------------------------------------Draw------------------------------------------------
void draw() {
  background(0);
  this.sepTrigger = this.cgui.msep.getValue();
  if (this.createOctree || this.masterBehavior_E || this.sepTrigger > 0) {
    this.createOctree = true;
    this.octree.empty();
    this.vec3DList = new ArrayList<Vec3D>();
    //--Sets the octree pts------------------------------------------------------------------
    for (Tracker ag : agentList) {
      this.vec3DList.add(new Vec3D(ag.loc.x, ag.loc.y, ag.loc.z));
    }
    this.octree.addAll(vec3DList);
  }
  this.D2 = this.cgui.d.getState();
  if (!this.D2 && this.drawBoundary) {
    drawExtents();
  }
  this.spawnEdge = this.cgui.se.getState();
  this.agentCount = (int)this.cgui.ac.getValue();
  for (Path pths : pathList) {
    if (this.drawPaths) {
      pths.display();
    }
    pths.dim = this.cgui.d.getState();
    pths.radius = this.cgui.pr.getValue();
  }
  //--Agents-------------------------------------------------------------------------------
  for (Tracker ag : agentList) {
    if (ag.type == "parent") {
      ag.wanderD = this.cgui.wd.getValue();
      ag.wanderR = this.cgui.wr.getValue();
      ag.wanderT = this.cgui.wt.getValue();
      ag.wanderTVal = this.cgui.wrt.getValue();

      ag.headWidth = this.cgui.hw.getValue();
      ag.strokeWidth = this.cgui.stw.getValue();
      ag.tranparency = this.cgui.t.getValue();

      ag.seekerMT = (int)this.cgui.st.getValue();

      ag.maxforce = this.cgui.mf.getValue();
      ag.max = this.cgui.ms.getValue();
      ag.amp = this.cgui.sd.getValue();
      ag.vel = this.cgui.is.getValue();
      ag.maxDist = this.cgui.pt.getValue();
      ag.r = this.cgui.msep.getValue();
      ag.maxChildren = (int)this.cgui.mc.getValue();
      ag.dim = this.cgui.d.getState();
      ag.randomize = this.genRandom;
      ag.wandertheta = 0.0f; 

      ag.av = this.cgui.f_av.getValue();
      ag.cv = this.cgui.f_cv.getValue();
      ag.sv = this.cgui.f_sv.getValue();
      ag.searchRad = this.cgui.f_sR.getValue();
      ag.creeperCollection = this.agentList;

      ag.run();
    } else {
      ag.wanderD = this.cgui.c_wd.getValue();
      ag.wanderR = this.cgui.c_wr.getValue();
      ag.wanderT = this.cgui.c_wt.getValue();
      ag.wanderTVal = this.cgui.c_wrt.getValue();

      ag.headWidth = this.cgui.c_hw.getValue();
      ag.strokeWidth = this.cgui.c_stw.getValue();
      ag.tranparency = this.cgui.c_t.getValue();

      ag.seekerChildMT = (int)this.cgui.c_ct.getValue();

      ag.maxforce = this.cgui.c_mf.getValue();
      ag.max = this.cgui.c_ms.getValue();
      ag.amp = this.cgui.c_sd.getValue();
      ag.vel = this.cgui.c_is.getValue();
      ag.maxDist = this.cgui.c_pt.getValue();
      //ag.r = this.cgui.c_msep.getValue();
      ag.maxChildren = 0;
      ag.dim = this.cgui.d.getState();
      ag.randomize = this.genRandom;
      ag.wandertheta = 0.0f;

      ag.av = this.cgui.f_av.getValue();
      ag.cv = this.cgui.f_cv.getValue();
      ag.sv = this.cgui.f_sv.getValue();
      ag.searchRad = this.cgui.f_sR.getValue();
      ag.creeperCollection = this.agentList;

      ag.run();
    }
  }
  if (this.createOctree) {
    if (this.showOctree) this.octree.draw();
  }
  //--CreateBabies---------------------------------------------------------------------------
  if (this.childSpawners.size() > 0) {
    newDude();
    this.childSpawners = new ArrayList<PVector>();
    this.childSpawnType = new ArrayList();
  }
  stepCount++;
  if (this.D2) {
    surface.setSize(this.nWidth, this.nDepth);
  }
  this.cgui.createGui();
}
//---------------------------------------Create Static Paths---------------------------------
void newPath() {
  if (this.D2) {
    this.tempPath = new Path();
    this.tempPath.addPoint(random(30, 300), random(height/4, height), 0);
    this.tempPath.addPoint(random(101, width/2), random(0, height), 0);
    this.tempPath.addPoint(random(width/2, width), random(0, height), 0);
    this.tempPath.addPoint(random(width-100, width), height/2, 0);
  } else {
    this.tempPath = new Path();
    this.tempPath.addPoint(random(0, 300), random(0, height), random(0, this.nHeight));
    this.tempPath.addPoint(random(0, width/2), random(0, height), random(0, this.nHeight));
    this.tempPath.addPoint(random(0, width), random(0, height), random(0, this.nHeight));
    this.tempPath.addPoint(random(0, width), 0, random(0, this.nHeight));
  }
  this.pathList.add(this.tempPath);
}
//---------------------------------------Keyboard Inputs-------------------------------------
void keyPressed() {
  if (key == 'r') {
    this.resetAmount ++;
    this.triggerCount = 0;
    setup();
  }
  if (key == 's') this.simulate = !this.simulate;
  if (key == 'w') this.newPath();
  if (key == 'q') this.drawPathTargets = !this.drawPathTargets;
  if (key == 'p') this.drawPaths = !this.drawPaths;
  if (key == 't') this.toggleUI = !this.toggleUI;
  if (key == 'm') this.mathBehavior = !this.mathBehavior;
  if (key == 'n') this.genRandom = !this.genRandom;
  if (key == 'd') this.drawMovement = !this.drawMovement;
  if (key == 'P') this.enablePathTrack = !this.enablePathTrack;
  if (key == 'b') this.triggerSeekers = !this.triggerSeekers;
  if (key == 'c') this.toggleColor = !this.toggleColor;
  if (key == 'i') saveFrame("img-######.png");
  if (key == 'v') this.drawBoundary = !this.drawBoundary;
  if (key=='o') this.showOctree=!this.showOctree;
  if (key=='z') this.createOctree =!this.createOctree;
  if (key=='1') this.drawConn=!this.drawConn;
}
//---------------------------------------Children Creation-----------------------------------
void newDude() {
  int babyCount = 0;
  for (PVector px : this.childSpawners) {
    PVector speed;
    if (this.spawnEdge) {
      speed = new PVector(1, 0, 0);
    } else {
      speed = new PVector(random(-1, 1), random(-1, 1), 0);
    }
    if ((int)this.childSpawnType.get(babyCount) % 2 == 0) {
      this.agentList.add(new Tracker(new PVector(px.x, px.y, px.z), speed, false, "child", "w_a"));
    } else {
      this.agentList.add(new Tracker(new PVector(px.x, px.y, px.z), speed, false, "child", "w_b"));
    }
    babyCount++;
  }
}
//---------------------------------------Draw Bounds-----------------------------------------
void drawExtents()
{
  pushStyle();
  pushMatrix();
  strokeWeight(.5);  
  stroke(200);
  noFill();
  translate(this.nWidth/2, this.nDepth/2, this.nHeight/2);
  box(this.nWidth, this.nDepth, this.nHeight);
  popMatrix();
  popStyle();
}
//---------------------------------------Behaviors------------------------------------------
void Beh_A(boolean resetFlag) {
  if (resetFlag) {
    this.masterBehavior_A = !this.masterBehavior_A;
  }
}
void Beh_B(boolean resetFlag) {
  if (resetFlag) {
    this.masterBehavior_B = !this.masterBehavior_B;
  }
}
void Beh_C(boolean resetFlag) {
  if (resetFlag) {
    this.masterBehavior_C = !this.masterBehavior_C;
  }
}
void Beh_D(boolean resetFlag) {
  if (resetFlag) {
    this.masterBehavior_D = !this.masterBehavior_D;
  }
}
void Beh_E(boolean resetFlag) {
  if (resetFlag) {
    this.masterBehavior_E = !this.masterBehavior_E;
  }
}
void Beh_AA(boolean resetFlag) {
  if (resetFlag) {
    this.subBehavior_AA = !this.subBehavior_AA;
  }
}
void Beh_AB(boolean resetFlag) {
  if (resetFlag) {
    this.subBehavior_AB = !this.subBehavior_AB;
  }
}
Update
UI
class Culebra_UI {

  PApplet parent;
  ControlP5 cp5;
  int abc = 100;
  Slider pr, sd, pt, wr, wd, wrt, wt, mc, is, ms, mf, msep, ac, st, sct, hw, stw, t;
  Slider c_sd, c_pt, c_wr, c_wd, c_wrt, c_wt, c_is, c_ms, c_mf, c_msep, c_ct, c_mvr, c_mxvr, c_mvA, c_MvA, c_hw, c_t, c_stw;
  Slider f_sR, f_av, f_sv, f_cv;
  Button cbutt, cbut;
  Toggle se, d, t10;
  List<Slider> sliderList = new ArrayList<Slider>();
  boolean created = false;

  public Culebra_UI () {
  }
  public void run(PApplet _parent) {
    this.parent = _parent;
    this.cp5 = new ControlP5(parent);

    if (!D2) {
      this.cp5.setAutoDraw(false);
    } else {
      this.cp5.setAutoDraw(true);
    }

    this.cp5.setColorForeground(color(0, 255, 0));
    this.cp5.setColorValueLabel(color(255, 255, 255));
    this.cp5.setBackground(color(0, 0, 0));
    this.cp5.setColorActive(color(0, 255, 0));
    this.cp5.setColorBackground(color(50, 50, 50));

    this.pr = cp5.addSlider("PathRad").plugTo(parent).setRange(0, 100).setPosition(10, 10).setValue(28.0).setDecimalPrecision(2).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    this.sd = cp5.addSlider("ScalarProjectDist").plugTo(parent).plugTo(parent).setRange(0.00, 100.00).setPosition(10, 22).setValue(100).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.pt = cp5.addSlider("PathTresh").plugTo(parent).setRange(0.00, 1500.00).setPosition(10, 34).setValue(1000.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;

    this.wr = cp5.addSlider("WanderRadius").plugTo(parent).setRange(0.00, 500.00).setPosition(10, 46).setValue(10).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.wd = cp5.addSlider("WanderDist").plugTo(parent).setRange(0.00, 100.00).setPosition(10, 58).setValue(20).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.wrt = cp5.addSlider("WanderRotTrigger").plugTo(parent).setRange(0.00, 100.00).setPosition(10, 70).setValue(6).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.wt = cp5.addSlider("WanderTheta").plugTo(parent).setRange(0.0, 100.00).setPosition(10, 82).setValue(0.6).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;

    this.mc = cp5.addSlider("MaxChildren").plugTo(parent).plugTo(parent).setRange(0.00, 20.00).setPosition(10, 94).setValue(4).setDecimalPrecision(0).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;

    this.is = cp5.addSlider("InitSpeed").plugTo(parent).setRange(0.00, 10.00).setPosition(10, 106).setValue(2.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    this.ms = cp5.addSlider("MaxSpeed").plugTo(parent).setRange(0.00, 10.00).setPosition(10, 118).setValue(3.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    this.mf = cp5.addSlider("MaxForce").plugTo(parent).setRange(0.00, 2.00).setPosition(10, 130).setValue(0.16).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    this.msep = cp5.addSlider("MaxSep").plugTo(parent).plugTo(parent).setRange(0.00, 20.00).setPosition(10, 142).setValue(0.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;

    this.ac = cp5.addSlider("AgentCount").plugTo(parent).setRange(0.00, 2500.00).setPosition(10, 154).setValue(500).setDecimalPrecision(0).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    this.se = cp5.addToggle("SpawnEdge").plugTo(parent).setPosition(10, 166).setSize(50, 10).setValue(false).setMode(ControlP5.SWITCH).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    this.d = cp5.addToggle("Dimension").plugTo(parent).setPosition(10, 190).setSize(50, 10).setValue(false).setMode(ControlP5.SWITCH).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));

    Button sbutt = cp5.addButton("---TRACKERS---").plugTo(parent).setPosition(10, 220).setSize(100, 5);
    sbutt.setColorActive(color(0, 255, 0));
    sbutt.setColorBackground(color(255, 0, 0));
    this.st =  cp5.addSlider("seekerTrail").plugTo(parent).setRange(0.00, 5000.00).setPosition(10, 230).setValue(5000).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));

    Button wbutt = cp5.addButton("---SEEKERS---").plugTo(parent).setPosition(10, 244).setSize(100, 5);
    wbutt.setColorActive(color(0, 255, 0));
    wbutt.setColorBackground(color(255, 0, 0));
    this.sct =  cp5.addSlider("childSeekerTrail").plugTo(parent).setRange(0.00, 5000.00).setPosition(10, 254).setValue(5000.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));

    Button vbutt = cp5.addButton("---VIZ---").plugTo(parent).setPosition(10, 268).setSize(100, 5);
    vbutt.setColorActive(color(0, 255, 0));
    vbutt.setColorBackground(color(255, 0, 0));
    this.hw = cp5.addSlider("HeadWidth").plugTo(parent).setRange(0.00f, 8.0f).setPosition(10, 278).setValue(0.0f)
      .setDecimalPrecision(2).setSize(50, 10);
    this.stw = cp5.addSlider("StrokeWidth").plugTo(parent).setRange(0.00f, 10).setPosition(10, 290).setValue(1.5f)
      .setDecimalPrecision(2).setSize(50, 10);
    this.t = cp5.addSlider("Transparency").plugTo(parent).setRange(0.00f, 255).setPosition(10, 302)
      .setValue(255.0f).setDecimalPrecision(2).setSize(50, 10);

    this.cbut = cp5.addButton("---BABIES---").plugTo(parent).setPosition(10, 316).setSize(100, 5);
    this.cbut.setColorActive(color(0, 255, 0));
    this.cbut.setColorBackground(color(255, 0, 0));
    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    this.c_sd = cp5.addSlider("c_ScalarProjectDist").plugTo(parent).plugTo(parent).setRange(0.00, 100.00).setPosition(10, 326).setValue(100).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    sliderList.add(this.c_sd);
    this.c_pt = cp5.addSlider("c_PathTresh").plugTo(parent).setRange(0.00, 1500.00).setPosition(10, 338).setValue(1000).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    sliderList.add(this.c_pt);
    this.c_wr = cp5.addSlider("c_WanderRad").plugTo(parent).setRange(0.00, 100.00).setPosition(10, 350).setValue(10).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    sliderList.add(this.c_wr);
    this.c_wd = cp5.addSlider("c_WanderDist").plugTo(parent).setRange(0.00, 100.00).setPosition(10, 362).setValue(20).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    sliderList.add(this.c_wd);
    this.c_wrt = cp5.addSlider("c_WanderRotTrigger").plugTo(parent).setRange(0.00, 100.00).setPosition(10, 374).setValue(6).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    sliderList.add(this.c_wrt);
    this.c_wt = cp5.addSlider("c_WanderTheta").plugTo(parent).setRange(0.0, 100.00).setPosition(10, 386).setValue(0.6).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    sliderList.add(this.c_wt);
    this.c_is = cp5.addSlider("c_InitSpeed").plugTo(parent).setRange(0.00, 10.00).setPosition(10, 398).setValue(2.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    sliderList.add(this.c_is);
    this.c_ms = cp5.addSlider("c_MaxSpeed").plugTo(parent).setRange(0.00, 10.00).setPosition(10, 410).setValue(3.0).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    sliderList.add(this.c_ms);
    this.c_mf = cp5.addSlider("c_MaxForce").plugTo(parent).setRange(0.00, 2.00).setPosition(10, 422).setValue(0.16).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    sliderList.add(this.c_mf);
    this.c_ct =  cp5.addSlider("c_Child_TrailFO").plugTo(parent).setRange(0.00, 5000.00).setPosition(10, 434).setValue(5000).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40));
    sliderList.add(this.c_ct);
    this.cbutt = cp5.addButton("---Child-VIZ---").plugTo(parent).setPosition(10, 448).setSize(100, 5);
    this.cbutt.setColorActive(color(0, 255, 0));
    this.cbutt.setColorBackground(color(255, 0, 0));
    this.c_hw = cp5.addSlider("c_HeadWidth").plugTo(parent).setRange(0.00f, 8.0f).setPosition(10, 460).setValue(0.0f)
      .setDecimalPrecision(2).setSize(50, 10);
    sliderList.add(this.c_hw);
    this.c_stw = cp5.addSlider("c_StrokeWidth").plugTo(parent).setRange(0.00f, 10).setPosition(10, 472).setValue(1.1f)
      .setDecimalPrecision(2).setSize(50, 10);
    sliderList.add(this.c_stw);
    this.c_t = cp5.addSlider("c_Transparency").plugTo(parent).setRange(0.00f, 255).setPosition(10, 484)
      .setValue(255.0f).setDecimalPrecision(2).setSize(50, 10);
    sliderList.add(this.c_t);

    this.f_sR = cp5.addSlider("searchRadius").plugTo(parent).plugTo(parent).setRange(0.00, 300.00).setPosition(10, 500).setValue(30).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.f_av = cp5.addSlider("alignValue").plugTo(parent).plugTo(parent).setRange(0.00, 2.00).setPosition(10, 512).setValue(0.025).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.f_sv = cp5.addSlider("sepValue").plugTo(parent).plugTo(parent).setRange(0.00, 2.00).setPosition(10, 524).setValue(0.09).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;
    this.f_cv = cp5.addSlider("cohVal").plugTo(parent).plugTo(parent).setRange(0.00, 2.00).setPosition(10, 536).setValue(0.24).setDecimalPrecision(3).setSize(50, 10).setHandleSize(10).setColorForeground(color(255, 40)).setColorBackground(color(255, 40)) ;

    btypeA = cp5.addButton("Beh_A").plugTo(parent).setPosition(150, 10).setSize(100, 10);
    btypeA.setColorActive(color(0, 255, 0));              
    btypeA.setColorBackground(color(255, 0, 0));

    btypeAA = cp5.addButton("Beh_AA").plugTo(parent).setPosition(255, 10).setSize(50, 10);
    btypeAA.setColorActive(color(0, 255, 0));
    btypeAA.setColorBackground(color(255, 0, 0));

    btypeAB = cp5.addButton("Beh_AB").plugTo(parent).setPosition(310, 10).setSize(50, 10);
    btypeAB.setColorActive(color(0, 255, 0));
    btypeAB.setColorBackground(color(255, 0, 0));

    btypeB = cp5.addButton("Beh_B").plugTo(parent).setPosition(150, 22).setSize(100, 10);
    btypeB.setColorActive(color(0, 255, 0));
    btypeB.setColorBackground(color(255, 0, 0));

    btypeC = cp5.addButton("Beh_C").plugTo(parent).setPosition(150, 34).setSize(100, 10);
    btypeC.setColorActive(color(0, 255, 0));
    btypeC.setColorBackground(color(255, 0, 0));

    btypeD = cp5.addButton("Beh_D").plugTo(parent).setPosition(150, 46).setSize(100, 10);
    btypeD.setColorActive(color(0, 255, 0));
    btypeD.setColorBackground(color(255, 0, 0));

    btypeE = cp5.addButton("Beh_E").plugTo(parent).setPosition(150, 58).setSize(100, 10);
    btypeE.setColorActive(color(0, 255, 0));
    btypeE.setColorBackground(color(255, 0, 0));
  }
  public void draw() {
    background(0);
  }
  public void createGui() {
    updateUI();
    guiInit();
  }

  public void updateUI() {
    if (cp5.isMouseOver()) {
      cam.setActive(false);
    } else {
      cam.setActive(true);
    }
    if (masterBehavior_A) {
      btypeA.setColorBackground(color(120, 255, 0));
    } else {
      btypeA.setColorBackground(color(255, 0, 0));
    }
    if (masterBehavior_B) {
      btypeB.setColorBackground(color(120, 255, 0));
    } else {
      btypeB.setColorBackground(color(255, 0, 0));
    }
    if (masterBehavior_C) {
      btypeC.setColorBackground(color(120, 255, 0));
    } else {
      btypeC.setColorBackground(color(255, 0, 0));
    }
    if (masterBehavior_D) {
      btypeD.setColorBackground(color(120, 255, 0));
    } else {
      btypeD.setColorBackground(color(255, 0, 0));
    }
    if (masterBehavior_E) {
      btypeE.setColorBackground(color(120, 255, 0));
    } else {
      btypeE.setColorBackground(color(255, 0, 0));
    }
    if (subBehavior_AA) {
      btypeAA.setColorBackground(color(120, 255, 0));
    } else {
      btypeAA.setColorBackground(color(255, 0, 0));
    }
    if (subBehavior_AB) {
      btypeAB.setColorBackground(color(120, 255, 0));
    } else {
      btypeAB.setColorBackground(color(255, 0, 0));
    }
    if (!masterBehavior_E) {
      this.f_sR.setVisible(false);
      this.f_av.setVisible(false);
      this.f_sv.setVisible(false);
      this.f_cv.setVisible(false);
    } else {
      this.f_sR.setVisible(true);
      this.f_av.setVisible(true);
      this.f_sv.setVisible(true);
      this.f_cv.setVisible(true);
    }
    if (toggleUI) {
      this.cbutt.setVisible(true);
      this.cbutt.setLabelVisible(true);
      this.cbut.setVisible(true);
      this.cbut.setLabelVisible(true);
      for (Slider s : sliderList) {
        s.setVisible(true);
        s.setLabelVisible(true);
      }
    } else {
      this.cbutt.setVisible(false);
      this.cbutt.setLabelVisible(false);
      this.cbut.setVisible(false);
      this.cbut.setLabelVisible(false);
      for (Slider s : sliderList) {
        s.setVisible(false);
        s.setLabelVisible(false);
      }
    }
  }
  void guiInit() {
    cp5.setAutoDraw(false);
    hint(DISABLE_DEPTH_TEST);
    cam.beginHUD();
    cp5.draw();
    cam.endHUD();
    hint(ENABLE_DEPTH_TEST);
  }
}
Update
PATH
class Path {
  ArrayList<PVector> points;
  float radius = 20;
  boolean dim;
  Path() {
    this.points = new ArrayList<PVector>();
  }
  void addPoint(float x, float y, float z) {   
    PVector point = new PVector(x, y, z);
    this.points.add(point);
  }
  //-------------------------------------------------------------------------------------
  // Draw the path
  void display() {
    // Draw thick line for radius
    stroke(120,120,120,50);
    strokeWeight(radius*2);
    noFill();
    beginShape();
    for (PVector v : points) {
      vertex(v.x, v.y, v.z);
    }
    endShape();
    // Draw thin line for center of path
    stroke(255);
    strokeWeight(1);
    noFill();
    beginShape();
    for (PVector v : points) {
      vertex(v.x, v.y, v.z);
    }
    endShape();
  }
}
Update
TRACKER
import java.util.List;
class Tracker {
  List<PVector> objectTrails;
  PVector speed, loc;
  PVector acc = new PVector(0, 0, 0);
  float maxforce = 0.01;
  float max = 4.0f;
  float vel = 1.0;
  float maxDist = 100;
  float r, amp;
  float wandertheta, wanderTVal, wanderD, wanderR, wanderT;
  float headWidth, strokeWidth, tranparency;
  boolean sepActive = false;
  boolean wonderTrigger = false;
  boolean instanceable;
  boolean dim;
  boolean randomize;
  int maxChildren = 0;
  int instanceTriggerCount;
  int seekerMT;
  int seekerChildMT;
  int minTrailPtCount = 0;
  int currentTrailSize = 0;
  String type, babyType;

  TColor colorA = TColor.newRGB(255.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f); 
  TColor colorB = TColor.newRGB(120.0f, 0.0f, 0.0f);
  TColor colorB2 = TColor.newRGB(0.0f, 255.0f, 255.0f);
  TColor colorC = TColor.newRGB(187.0f / 255.0f, 216.0f / 255.0f, 40.0f / 255.0f);
  TColor colorD = TColor.newRGB(255.0f, 0.0f, 120.0f);
  TColor colorE = TColor.newRGB(200.0f / 60.0f, 160.0f / 100.0f, 80.0f / 30.0f);

  ColorGradient gradA = new ColorGradient();
  ColorGradient gradB = new ColorGradient();
  ColorGradient gradC = new ColorGradient();
  ToneMap toneMapA, toneMapB, toneMapC;
  //-----------------Flocking Things-----------------------------------------------------
  String objectType;
  String behaviorType = "None";
  PVector cummVec, alignVector, separateVector, cohesionVector;
  float maxSpeed, maxForce;
  float searchRad, av, sv, cv;
  List<PVector> otherPtsList;
  List<PVector> otherMoveValues;
  List<Float> allDist;
  List<Tracker> creeperCollection;
  ArrayList<PVector> creeperTrails;
  //-------------------------------------------------------------------------------------
  Tracker(PVector location, PVector Speed, boolean instance, String Type, String BabyType) {
    this.loc = location;
    this.objectTrails = new ArrayList<PVector>();

    this.instanceTriggerCount = 0;
    this.instanceable = instance;
    this.type = Type;
    this.babyType = BabyType;
    this.speed = Speed;
    this.r = 12;

    this.gradA.addColorAt(0.0f, this.colorA);
    this.gradA.addColorAt(255.0f, this.colorC);
    this.toneMapA = new ToneMap(0.0f, 1.0f, this.gradA);

    this.gradB.addColorAt(0.0f, this.colorB);
    this.gradB.addColorAt(255.0f, this.colorB2);
    this.toneMapB = new ToneMap(0.0f, 1.0f, this.gradB);

    this.gradC.addColorAt(0.0f, this.colorD);
    this.gradC.addColorAt(255.0f, this.colorE);
    this.toneMapC = new ToneMap(0.0f, 1.0f, this.gradC);
  }
  //-------------------------------------------------------------------------------------
  //Run all of the other methods---------------------------------------------------------
  //instanceable is whether or not current creeper is type parent or child, child cannot create instances
  //-------------------------------------------------------------------------------------
  void run() {
    if (enablePathTrack) {
      pathFollow();
    }
    if (this.sepActive && this.instanceable && this.r != 0) {
      separate();
    }
    if (masterBehavior_A || subBehavior_AA || subBehavior_AB) {
      if (enablePathTrack) {
        if (this.wonderTrigger) {
          wander();
        }
      } else {
        wander();
      }
    }  
    if (masterBehavior_B) {
      this.wonderTrigger = true;
      this.randomize = true;
      wanderSolo();
    }  
    if (masterBehavior_C) {
      this.wonderTrigger = true;
      this.randomize = true;
      wanderSolo();
    }  
    if (masterBehavior_D) {
      this.wonderTrigger = true;
      this.randomize = true;
      wanderSolo();
    }  
    if (masterBehavior_E) {
      flock();
    }

    if (simulate) {
      move();
    }
    viz();
    trail();
  }
  //---------------------------------------------------------------------------------------
  public void wanderSolo() {
    if (this.randomize) {
      this.wandertheta += random(-this.wanderT, this.wanderT); // Randomly change wander theta
    } else {
      this.wandertheta += this.wanderT;
    }
    PVector circleLoc = new PVector(this.speed.x, this.speed.y, this.speed.z);
    circleLoc.normalize(); // Normalize to get heading
    circleLoc.mult(this.wanderD);
    circleLoc.add(this.loc);
    PVector circleOffSet = new PVector(0, 0, 0); 
    if (masterBehavior_B) {
      circleOffSet = new PVector(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta), 0);
    } else if (masterBehavior_C) {
      circleOffSet = new PVector(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta), random(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta)));
    } else if (masterBehavior_D) {
      circleOffSet = new PVector(random(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta)), random(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta)), random(this.wanderR*cos(wandertheta), this.wanderR*sin(wandertheta)));
    }
    PVector target = circleLoc.add(circleOffSet);
    if (drawMovement) drawWanderStuff(this.loc, circleLoc, target, this.wanderR); // Render wandering circle, etc.
    PVector steer = target.sub(this.loc);
    steer.normalize();
    steer.mult(1);
    this.acc.add(steer);
  }
  //-------------------------------------------------------------------------------------
  //Wandering Creeper----------------------------------------------------
  //“Wandering is a type of random steering which has some long term order: the steering 
  //direction on one frame is related to the steering direction on the next frame. This 
  //produces more interesting motion than, for example, simply generating a random steering 
  //direction each frame.” Reynolds
  //-------------------------------------------------------------------------------------
  void wander() {
    if (stepCount < this.wanderTVal) {
      if (this.type == "parent") {
        this.wandertheta = this.wanderT;
      } else if (this.type == "child") {
        if (this.babyType == "w_a") {
          this.wandertheta = this.wanderT;
        } else {
          this.wandertheta = -this.wanderT;
        }
      }
    } else if (stepCount >= this.wanderTVal && stepCount < this.wanderTVal*2) {
      if (this.type == "parent") {
        this.wandertheta = -this.wanderT;
      } else if (this.type == "child") {
        if (this.babyType == "w_a") {
          this.wandertheta = -this.wanderT;
        } else {
          this.wandertheta = this.wanderT;
        }
      }
    } else {
      stepCount = 0;
    }
    // Now we have to calculate the new location to steer towards on the wander circle
    PVector circleloc = this.speed.copy();    // Start with velocity
    circleloc.normalize();            // Normalize to get heading
    circleloc.mult(this.wanderD);          // Multiply by distance
    circleloc.add(this.loc);               // Make it relative to boid's location
    float h, headingXY, headingYZ, headingXZ;
    PVector circleOffSet;
    if (D2) {
      h = this.speed.heading();
      circleOffSet = new PVector(this.wanderR*cos(this.wandertheta+h), this.wanderR*sin(this.wandertheta+h), 0);
      headingXZ = 0;
      headingYZ = 0;
      headingXY = 0;
    } else {
      headingXY = (float)Math.atan2(this.speed.y, this.speed.x);
      headingXZ = (float)Math.atan2(this.speed.z, this.speed.x);
      headingYZ = (float)Math.atan2(this.speed.y, this.speed.z);
      if (subBehavior_AA) {
        circleOffSet = new PVector(this.wanderR*cos(this.wandertheta+headingXY), this.wanderR*sin(this.wandertheta+headingXY), this.wanderR*cos(this.wandertheta+headingXZ));
      } else if (subBehavior_AB) {
        circleOffSet = new PVector(this.wanderR*cos(this.wandertheta+headingXY), this.wanderR*sin(this.wandertheta+headingXY), (this.wanderR*cos(this.wandertheta+headingYZ) + this.wanderR*sin(this.wandertheta+headingXZ))/2);
      } else {
        circleOffSet = new PVector(this.wanderR*cos(this.wandertheta+headingXY), this.wanderR*sin(this.wandertheta+headingXY), random(this.wanderR*cos(this.wandertheta+(headingYZ + headingXZ)), this.wanderR*sin(this.wandertheta+(headingYZ + headingXZ))));
      }
    }
    PVector target = PVector.add(circleloc, circleOffSet);
    seek(target);
    if (drawMovement) drawWanderStuff(this.loc, circleloc, target, this.wanderR); // Render wandering circle, etc.
  }  
  //-------------------------------------------------------------------------------------
  //Draw the wandering creeper movements-------------------------------------------------
  //-------------------------------------------------------------------------------------
  // A method just to draw the circle associated with wandering
  void drawWanderStuff(PVector location, PVector circle, PVector target, float rad) {
    pushStyle();
    stroke(255); 
    noFill();
    point(circle.x, circle.y, circle.z);
    popStyle();
    pushStyle();
    stroke(120); 
    point(target.x, target.y, target.z);
    popStyle();
    pushStyle();
    stroke(160);
    strokeWeight(1);
    line(location.x, location.y, location.z, circle.x, circle.y, circle.z);
    line(circle.x, circle.y, circle.z, target.x, target.y, target.z);
    popStyle();
  }
  //-------------------------------------------------------------------------------------
  //Setup for path following-------------------------------------------------------------
  //So lets check if we are inside the virtual path thickness, if we are and we can create
  //children then they would spawn here, depending on the max allowed etc.
  //-------------------------------------------------------------------------------------
  void pathFollow() {
    PVector predict = this.speed.copy();
    predict.normalize();
    predict.mult(this.amp);
    PVector nextPosPrev = PVector.add(loc, predict);
    PVector target = null;
    PVector normal = null;
    float worldRecord = 1000000;
    for (int z = 0; z < pathList.size(); z++) {
      for (int i = 0; i <  pathList.get(z).points.size()-1; i++) { 
        PVector a = pathList.get(z).points.get(i);
        PVector b = pathList.get(z).points.get(i+1);
        PVector normalPoint = getNormalPoint(nextPosPrev, a, b);//[offset-down] Finding the normals for each line segment
        if (D2) {
          if (normalPoint.x < min(a.x, b.x) || normalPoint.x > max(a.x, b.x)) {
            normalPoint = b.copy();
          }
        } else {
          if ((normalPoint.x < min(a.x, b.x) || normalPoint.x > max(a.x, b.x)) || (normalPoint.y < min(a.y, b.y) || normalPoint.y > max(a.y, b.y)) || (normalPoint.z < min(a.z, b.z) || normalPoint.z > max(a.z, b.z))) {
            normalPoint = b.copy();
          }
        }
        float distance = nextPosPrev.dist(normalPoint);
        if (distance < worldRecord) {
          worldRecord = distance;
          normal = normalPoint;
          PVector dir = PVector.sub(b, a); // Look at the direction of the line segment so we can seek a little bit ahead of the normal
          dir.normalize();
          dir.mult(10);
          target = normalPoint.copy();
          target.add(dir);
        }
      }
    }
    //remove if you want to just go to the line
    //maxDist = 10000000000000f;
    if (worldRecord < maxDist) {
      this.sepActive = true;
      this.wonderTrigger = true;
      if (worldRecord > tempPath.radius) {
        seek(target);
      } else {
        if (triggerSeekers && this.instanceable && this.instanceTriggerCount < this.maxChildren) { //check that we have not exceeded the amount of children we are allowed to create
          addNew = true;
          triggerLoc = nextPosPrev.copy();
          childSpawners.add(new PVector(this.loc.x, this.loc.y, this.loc.z));
          childSpawnType.add(this.instanceTriggerCount);
          triggerCount++;        
          this.instanceTriggerCount ++;
        } else {
          addNew = false;
        }
        PVector zero = new PVector(0, 0, 0);
        zero.mult(3);
        acc.add(zero);
      }
    } else {
      this.wonderTrigger = false;
    }
    if (drawPathTargets) { // Draw predicted future location
      pushStyle();
      stroke(255);
      strokeWeight(1);
      fill(0);
      popStyle();
      if (D2) {
        ellipse(nextPosPrev.x, nextPosPrev.y, 4, 4);
      } else {
        pushStyle();
        stroke(255, 255, 0);
        strokeWeight(10);
        point(nextPosPrev.x, nextPosPrev.y, nextPosPrev.z);
        popStyle();
        pushStyle();
        stroke(120);
        line(this.loc.x, this.loc.y, this.loc.z, nextPosPrev.x, nextPosPrev.y, nextPosPrev.z);
        popStyle();
      }
      // Draw normal location
      pushStyle();
      stroke(255);
      fill(0);
      if (D2) {
        ellipse(normal.x, normal.y, 4, 4);
      } else {
        pushStyle();
        strokeWeight(4);
        point(normal.x, normal.y, normal.z);
        popStyle();
      }
      popStyle();
      pushStyle();
      stroke(255);
      strokeWeight(2);
      // Draw actual target (red if steering towards it)
      line(nextPosPrev.x, nextPosPrev.y, nextPosPrev.z, normal.x, normal.y, normal.z);
      popStyle();
      pushStyle();
      if (worldRecord > tempPath.radius) fill(255, 0, 0);
      noStroke();
      if (D2) {
        ellipse(target.x, target.y, 8, 8);
      } else {
        pushStyle();
        stroke(255, 0, 0);
        strokeWeight(10);
        point(target.x, target.y, target.z);
        popStyle();
      }
      popStyle();
    }
  }
  //-------------------------------------------------------------------------------------
  //Gets the normal point of each path---------------------------------------------------
  //Paths are comprised of multiple segments per path------------------------------------
  PVector getNormalPoint(PVector p, PVector a, PVector b) {
    PVector ap = PVector.sub(p, a); 
    PVector ab = PVector.sub(b, a); 
    ab.normalize();
    ab.mult(PVector.dot(ap, ab)); //Using the dot product for scalar projection
    PVector normalPoint = PVector.add(a, ab);// Finding the normal point along the line segment
    return normalPoint;
  }
  //-------------------------------------------------------------------------------------
  //Created the steering vector towards the target position------------------------------
  //-------------------------------------------------------------------------------------
  void seek(PVector target) {
    PVector desired = PVector.sub(target, this.loc);
    desired.normalize();
    desired.mult(this.max);
    PVector steer = desired.sub(this.speed);
    // Limit the magnitude of the steering force.
    steer.limit(this.maxforce);
    //acc.addSelf(steer);
    steer.mult(3);
    applyForce(steer);
  }
  //-------------------------------------------------------------------------------------
  //Apply Force to the acceleration------------------------------------------------------
  //-------------------------------------------------------------------------------------
  void applyForce(PVector force) {
    acc.add(force);
  }
  //-------------------------------------------------------------------------------------
  //Move creeper to the next location----------------------------------------------------
  //-------------------------------------------------------------------------------------
  void move() {
    if (!mathBehavior) {
      this.speed.add(this.acc);
      this.speed.limit(this.max);
      this.loc.add(this.speed);
      this.acc = new PVector();
    } else {
      this.speed.add(this.acc);
      this.speed.normalize();
      this.speed.mult(this.vel);
      this.speed.limit(this.max);
      this.loc.add(this.speed);
      this.acc = new PVector();
    }
  }
  //-------------------------------------------------------------------------------------
  //Draw the heads and set values based on type------------------------------------------
  //-------------------------------------------------------------------------------------
  void viz() {
    if (this.type == "parent" && headWidth != 0.0f) {
      stroke(191, 255, 0);
      strokeWeight(headWidth);
      point(this.loc.x, this.loc.y, this.loc.z);
    } else if (this.type == "child" && headWidth != 0.0f) {
      if (this.babyType == "w_a") {
        stroke(120, 75, 255);
        strokeWeight(headWidth/2);
        point(this.loc.x, this.loc.y, this.loc.z);
      } else {
        stroke(190, 255, 115);
        strokeWeight(headWidth/2);
        point(this.loc.x, this.loc.y, this.loc.z);
      }
    }
  }
  //-------------------------------------------------------------------------------------
  //Separation Method steers away from nearby dudes--------------------------------------
  //-------------------------------------------------------------------------------------
  void separate () {
    float desiredseparation = this.r*2;
    PVector steer = new PVector(0, 0, 0);
    int count = 0;
    // check if we are too close
    for (int i = 0; i < agentList.size(); i++) {
      Tracker other = (Tracker) agentList.get(i);
      float d = loc.dist(other.loc);
      if ((d > 0) && (d < desiredseparation)) { 
        PVector diff = PVector.sub(this.loc, other.loc); 
        diff.normalize();
        diff = PVector.mult(diff, (1.00f / d)); // Weight by distance
        steer.add(diff);
        count++;
      }
    }
    if (count > 0) {
      steer.mult(1.0/(float)count);
    }
    if (steer.mag() > 0) {
      //Steering = Desired - Velocity
      steer.normalize();
      steer.mult(this.max);
      steer.sub(this.speed);
      steer.limit(this.maxforce);
    }
    steer.mult(3);
    applyForce(steer);
  }
  //-------------------------------------------------------------------------------------
  //Draw Tail and decay based on trail point amount--------------------------------------
  //Trail is drawn from segment to segment and colored based on a tonemap----------------
  //-------------------------------------------------------------------------------------
  void trail() {
    this.currentTrailSize++;
    if (this.currentTrailSize > this.minTrailPtCount) {
      this.objectTrails.add(new PVector(this.loc.x, this.loc.y, this.loc.z));
      this.currentTrailSize = 0;
    }
    if (this.type == "parent") { //if the type is a parent then set the trail decay by removing backwards from the tail after a target is met
      if (this.objectTrails.size() > this.seekerMT) {
        this.objectTrails.remove(0);
      }
    } else if (this.type == "child") { //if the type is a child then set the trail decay by removing backwards from the tail after a target is met
      if (this.objectTrails.size() > this.seekerChildMT) {
        this.objectTrails.remove(0);
      }
    }
    if (this.objectTrails.size() > 0) {
      for (int j = 0; j < this.objectTrails.size(); j++) {
        if (j != 0) {
          PVector pos = objectTrails.get(j);
          PVector prevpos = objectTrails.get(j - 1);
          if (this.type == "parent") {
            int a = this.toneMapA.getARGBToneFor(j / (1.0f * this.objectTrails.size()));
            if (toggleColor) {
              stroke(a, map(j, 0, objectTrails.size(), 0, tranparency));
              strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, strokeWidth));
            } else {
              stroke(255, 0, 0, map(j, 0, this.objectTrails.size(), 0, 200));
              strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1.5));
            }
          } else if (this.babyType == "w_a") {
            int a = this.toneMapB.getARGBToneFor(j / (1.0f * this.objectTrails.size()));
            if (toggleColor) {
              stroke(a, map(j, 0, objectTrails.size(), 0, tranparency));
              strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, strokeWidth));
            } else {
              stroke(0, 0, 255, map(j, 0, this.objectTrails.size(), 0, 200));
              strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1.0));
            }
          } else {
            int a = this.toneMapC.getARGBToneFor(j / (1.0f * this.objectTrails.size()));
            if (toggleColor) {
              stroke(a, map(j, 0, objectTrails.size(), 0, tranparency));
              strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, strokeWidth));
            } else {
              stroke(0, 255, 255, map(j, 0, this.objectTrails.size(), 0, 200));
              strokeWeight(map(j, 0, this.objectTrails.size(), 0.45, 1.0));
            }
          } 
          line(pos.x, pos.y, pos.z, prevpos.x, prevpos.y, prevpos.z);
        }
      }
    }
  }
  void drawConnectivity(PVector conv) {
    pushStyle();
    stroke(255, 255, 255, 150);
    strokeWeight(0.5);
    line(loc.x, loc.y, loc.z, conv.x, conv.y, conv.z);
    popStyle();
  }
  void flock() {
    this.otherPtsList = new ArrayList<PVector>();
    this.otherMoveValues = new ArrayList<PVector>();
    this.allDist = new ArrayList<Float>();
    Sphere bs = new Sphere(new Vec3D(this.loc.x, this.loc.y, this.loc.z), this.searchRad);
    occTreeList = octree.getPointsWithinSphere(bs);
    if (occTreeList!=null) {
      if (occTreeList.size()!=50402030) {
        for (int i = 0; i < occTreeList.size(); i++) {
          int index = vec3DList.indexOf((Vec3D)occTreeList.get(i));       
          if (drawConn) {
            Vec3D tconv = new Vec3D((Vec3D)occTreeList.get(i));
            PVector conv = new PVector(tconv.x, tconv.y, tconv.z);
            drawConnectivity(conv);
          }         
          Tracker other = (Tracker) creeperCollection.get(index);
          float distance = this.loc.dist(other.loc);

          if (distance != 0) {
            this.otherPtsList.add(other.loc);
            this.allDist.add(distance);
            if (index != -1) {
              this.otherMoveValues.add(other.speed);
            }
          }
        }
      }
    }
    if (this.otherPtsList.size() > 0) {
      this.cummVec = new PVector();
      // ----------Align-----------------
      alignMethod();
      if (this.alignVector.mag() > 0) {
        this.alignVector.normalize();
      }
      this.alignVector.mult(this.av);
      // ----------Separate-----------------
      separateMethod();
      if (this.separateVector.mag() > 0) {
        this.separateVector.normalize();
      }
      this.separateVector.mult(this.sv);
      // ----------Cohesion-----------------
      cohesionMethod();
      if (this.cohesionVector.mag() > 0) {
        this.cohesionVector.normalize();
      }
      this.cohesionVector.mult(this.cv);
      // -----------------------------------
      this.cummVec.add(this.alignVector);
      this.cummVec.add(this.separateVector);
      this.cummVec.add(this.cohesionVector);
      this.acc.add(this.cummVec);
    }
  }
  void separate(float searchRadius, float separateValue, List<Tracker> collection) {
    this.creeperCollection = collection;
    this.searchRad = searchRadius;
    this.sv = separateValue;
    this.otherPtsList = new ArrayList<PVector>();
    this.otherMoveValues = new ArrayList<PVector>();
    this.allDist = new ArrayList<Float>();
    Sphere bs = new Sphere(new Vec3D(this.loc.x, this.loc.y, this.loc.z), this.searchRad);
    occTreeList = octree.getPointsWithinSphere(bs);
    if (occTreeList!=null) {
      if (occTreeList.size()!=50402030) {
        for (int i = 0; i < occTreeList.size(); i++) {
          int index = vec3DList.indexOf((Vec3D)occTreeList.get(i));        
          if (drawConn) {
            Vec3D tconv = new Vec3D((Vec3D)occTreeList.get(i));
            PVector conv = new PVector(tconv.x, tconv.y, tconv.z);
            drawConnectivity(conv);
          }         
          Tracker other = (Tracker) creeperCollection.get(index);
          float distance = this.loc.dist(other.loc);
          if (distance != 0) {
            this.otherPtsList.add(other.loc);
            this.allDist.add(distance);
            if (index != -1) {
              this.otherMoveValues.add(other.speed);
            }
          }
        }
      }
    }
    if (this.otherPtsList.size() > 0) {
      this.cummVec = new PVector();
      // ----------Separate-----------------
      separateMethod();
      if (this.separateVector.mag() > 0) {
        this.separateVector.normalize();
      }
      this.separateVector.mult(this.sv);
      this.cummVec.add(this.separateVector);
      this.speed.add(this.cummVec);
      this.speed.normalize();
      this.speed.mult(1.5f);
    }
  }
  void align(float searchRadius, float alignThreshold, List<Tracker> collection) {
    this.creeperCollection = collection;
    this.searchRad = searchRadius;
    this.av = alignThreshold;
    this.otherPtsList = new ArrayList<PVector>();
    this.otherMoveValues = new ArrayList<PVector>();
    this.allDist = new ArrayList<Float>();
    
    Sphere bs = new Sphere(new Vec3D(this.loc.x, this.loc.y, this.loc.z), this.searchRad);
    occTreeList = octree.getPointsWithinSphere(bs);
    if (occTreeList!=null) {
      if (occTreeList.size()!=50402030) {
        for (int i = 0; i < occTreeList.size(); i++) {
          int index = vec3DList.indexOf((Vec3D)occTreeList.get(i));          
          if (drawConn) {
            Vec3D tconv = new Vec3D((Vec3D)occTreeList.get(i));
            PVector conv = new PVector(tconv.x, tconv.y, tconv.z);
            drawConnectivity(conv);
          }        
          Tracker other = (Tracker) creeperCollection.get(index);
          float distance = this.loc.dist(other.loc);
          if (distance != 0) {
            this.otherPtsList.add(other.loc);
            this.allDist.add(distance);
            if (index != -1) {
              this.otherMoveValues.add(other.speed);
            }
          }
        }
      }
    }
    if (this.otherPtsList.size() > 0) {
      this.cummVec = new PVector();
      // ----------Align-----------------
      alignMethod();
      if (this.alignVector.mag() > 0) {
        this.alignVector.normalize();
      }
      this.alignVector.mult(this.av);
      // -----------------------------------
      this.cummVec.add(this.alignVector);
      this.speed.add(this.cummVec);
      this.speed.normalize();
      this.speed.mult(1.5f);
    }
  }
  void cohesion(float searchRadius, float cohesionValue, List<Tracker> collection) {
    this.creeperCollection = collection;
    this.searchRad = searchRadius;
    this.cv = cohesionValue;
    this.otherPtsList = new ArrayList<PVector>();
    this.otherMoveValues = new ArrayList<PVector>();
    this.allDist = new ArrayList<Float>();
    Sphere bs = new Sphere(new Vec3D(this.loc.x, this.loc.y, this.loc.z), this.searchRad);
    occTreeList = octree.getPointsWithinSphere(bs);
    if (occTreeList!=null) {
      if (occTreeList.size()!=50402030) {
        for (int i = 0; i < occTreeList.size(); i++) {
          int index = vec3DList.indexOf((Vec3D)occTreeList.get(i));         
          if (drawConn) {
            Vec3D tconv = new Vec3D((Vec3D)occTreeList.get(i));
            PVector conv = new PVector(tconv.x, tconv.y, tconv.z);
            drawConnectivity(conv);
          }         
          Tracker other = (Tracker) creeperCollection.get(index);
          float distance = this.loc.dist(other.loc);
          if (distance != 0) {
            this.otherPtsList.add(other.loc);
            this.allDist.add(distance);
            if (index != -1) {
              this.otherMoveValues.add(other.speed);
            }
          }
        }
      }
    }
    if (this.otherPtsList.size() > 0) {
      this.cummVec = new PVector();
      // ----------Cohesion-----------------
      cohesionMethod();
      if (this.cohesionVector.mag() > 0) {
        this.cohesionVector.normalize();
      }
      this.cohesionVector.mult(this.cv);
      // -----------------------------------
      this.cummVec.add(this.cohesionVector);
      this.speed.add(this.cummVec);
      this.speed.normalize();
      this.speed.mult(1.5f);
    }
  }
  void separateMethod() {
    this.separateVector = new PVector();
    for (int i = 0; i < this.otherPtsList.size(); i++) {
      this.separateVector.add(PVector.mult(PVector.sub(this.loc, this.otherPtsList.get(i)), 
        this.searchRad / this.allDist.get(i)));
    }
  }
  void alignMethod() {
    this.alignVector = new PVector();
    for (int i = 0; i < this.otherPtsList.size(); i++) {
      this.alignVector.add(PVector.mult(this.otherMoveValues.get(i), this.searchRad / this.allDist.get(i)));
    }
  }
  void cohesionMethod() {
    this.cohesionVector = new PVector();
    for (int i = 0; i < this.otherPtsList.size(); i++) {
      this.cohesionVector.add(this.otherPtsList.get(i));
    }
    PVector scaleVec = PVector.mult(this.cohesionVector, (1.00f / this.otherPtsList.size()));
    float dist = this.loc.dist(scaleVec);
    this.cohesionVector = PVector.mult(PVector.sub(scaleVec, this.loc), this.searchRad / dist);
  }
}
OCTREE
/**
 * Extends the default octree class in order to visualize currently
 * occupied cells in the tree.
 */
class VisibleOctree extends PointOctree {
  VisibleOctree(Vec3D o, float d) {
    super(o,d);
  }
  void draw() {
    drawNode(this);
  }
  void drawNode(PointOctree n) {
    if (n.getNumChildren() > 0) {
      noFill();
      stroke(200, 20);
      pushMatrix(); 
      translate(n.x, n.y, n.z);
      box(n.getNodeSize());
      popMatrix();
      PointOctree[] childNodes=n.getChildren();
      for (int i = 0; i < 8; i++) {
        if(childNodes[i] != null) drawNode(childNodes[i]); 
      }
    }
  }
}
CONTROL
  • s – pause/resume simulation
  • w – new path
  • q – draw path targets
  • p – show/hide paths
  • t – open/close trackBabies UI
  • d – draw movement
  • P – enable Path Tracking
  • b – enable/disable spawning of children (will only spawn if inside the radius of path and spawning is enabled by this key)
  • c – toggle color
  • v – draw boundary
  • o – show octree
  • z – create octree
  • 1 – draw flocking inter connectivity
  • r – reset simulation

 

 

  • Share

2 Responses

  1. What a beautiful design! I want to know how you can make the track sure bright. I can use Rhino to make the lines. But how can I capture the drawing from Rhino? or you use rendering software to do that?

    • This video is using processing, I built the original library for java and used it in processing, later I built the .NET version that works with Grasshopper. You can download Culebra 2 and use that with Rhino & GH. I am actually updating it for Rhino 7 as well.

Leave a Reply to admin Cancel reply

Your email address will not be published.