home processing download documents tutorial python tutorial gallery source about
 Tutorials (back to the list of tutorials)

Physics Simulation and Swarm Examples

     Multi-Agent 3D Example 2 (requires iGeo version 7.6.0 or higher)

The example code below takes the previous tutorial code at "Multi-Agent 2D Example 3" and adding height depending on time and creating polygon mesh geometries.

import processing.opengl.*;
import igeo.*;

void setup() {
  size(480, 360, IG.GL);
  IG.duration(300);
  // left 100%, right 4.5%
  new LineAgent(IG.v(0,0,0), IG.v(2,0,0), 100.0, 4.5).clr(0); 
}

static class LineAgent extends IAgent{
  IVec pos;
  IVec dir;
  double pctL, pctR;
  boolean isColliding=false;
  IVec intersection;
  
  LineAgent(IVec pt, IVec dir, double pctL, double pctR) { 
    pos = pt; 
    this.dir = dir;
    this.pctL = pctL;
    this.pctR = pctR;
  }
  
  public void interact(ArrayList < IDynamics > agents){
    
    if(time()==0){
      for(int i=0; i < agents.size() && !isColliding ; i++){
        if(agents.get(i) instanceof LineAgent){
          LineAgent a = (LineAgent)agents.get(i);
          if(a != this){
            IVec pos2 = pos.cp(dir);
            IVec apos2 = a.pos.cp(a.dir);
            
            if(!apos2.eq(pos) && !a.pos.eq(pos)){ //not sharing root
              intersection = IVec.intersectLine(a.pos,apos2,pos,pos2); //keep intersection to draw line later
              if(intersection!=null){ //intersecting
                 isColliding=true;
              }
            }
          }
        }
      }
    }
  }
  
  public void update() {
    if(time()==0){
      IVec pos2 = pos.dup().add(dir);
      
      double thickness = 0.3;
      IVec widthDir = dir.dup().rot(PI/2).len(thickness/2);
      double z1 = sin(IG.time()*0.05)*10+15;
      double z2 = sin((IG.time()+1)*0.05)*10+15;
      IVec meshPt1 = pos;
      IVec meshPt2 = pos2;
      if(isColliding){ meshPt2 = intersection; }
      
      IG.meshBox(meshPt1.dup().sub(widthDir),
                 meshPt2.dup().sub(widthDir),
                 meshPt2.dup().add(widthDir),
                 meshPt1.dup().add(widthDir),
                 meshPt1.dup().sub(widthDir).add(0,0,z1),
                 meshPt2.dup().sub(widthDir).add(0,0,z2),
                 meshPt2.dup().add(widthDir).add(0,0,z2),
                 meshPt1.dup().add(widthDir).add(0,0,z1)).clr(clr());

      if(isColliding){
        del(); 
        return; 
      }
            
      double r = red() + IRand.get(-0.05, 0.05);
      double g = green() + IRand.get(-0.05, 0.05);
      double b = blue() + IRand.get(-0.05, 0.05);
      
      boolean branchL = IRand.pct(pctL);
      boolean branchR = IRand.pct(pctR);

      double lenL = dir.len();
      double lenR = dir.len();
      lenL*=0.995;  //shrinking length
      lenR*=0.995;  //shrinking length
      
      if (branchL && branchR) { //only when branching both
        if(IRand.pct(50.0)){
          if (pctL < pctR) { lenL *= 0.9; }
          else{ lenR *= 0.9; }
	}
        else if(IRand.pct(6.0)){
          if (pctL < pctR) { lenL *= 0.4; }
          else{ lenR *= 0.4; }
        }
        else if(IRand.pct(5.0)){
          if (pctL < pctR) { lenL *= 4; }
          else{ lenR *= 4; }
        }
      }
      
      if (branchL) { //bend left
        IVec dir2 = dir.dup();
        dir2.len(lenL); //update length
        dir2.rot(PI/30);
        
        if(branchR && pctR > pctL){ //swap L/R% when branching both
          new LineAgent(pos2, dir2, pctR, pctL).clr(r,g,b);
        }
        else{
          new LineAgent(pos2, dir2, pctL, pctR).clr(r,g,b);
	}
      }

      if (branchR) { //bend right
        IVec dir2 = dir.dup();
        dir2.len(lenR); //update length
        dir2.rot(-PI/30);

        if(branchL && pctR < pctL){ //swap L/R% when branching both
          new LineAgent(pos2, dir2, pctR, pctL).clr(r,g,b);
        }
        else{
          new LineAgent(pos2, dir2, pctL, pctR).clr(r,g,b);
        }
      }
    }
  }
}

The example code below takes the previous tutorial code at "Multi-Agent 2D Example 3" and layering multiple agents in different z levels and interconnect them. All the branches and interconnection lines are made out of polygon mesh sticks.

import processing.opengl.*;
import igeo.*;

void setup() {
  size(480, 360, IG.GL);
  IG.duration(80);
  double z = 0;
  for(int i=0; i < 20; i++){
    //IRand.dir() is giving a random direction with given length perpendicular to given axis
    new LineAgent(IRand.pt(-30,-30,z,30,30,z), IRand.dir(IG.zaxis,2), 100.0, 4.5).clr(0); 
    z += IRand.get(1,5);
  }
}

static class LineAgent extends IAgent{
  IVec pos;
  IVec dir;
  double pctL, pctR;
  boolean isColliding=false;
  IVec intersection;
  
  LineAgent(IVec pt, IVec dir, double pctL, double pctR) { 
    pos = pt; 
    this.dir = dir;
    this.pctL = pctL;
    this.pctR = pctR;
  }
  
  public void interact(ArrayList < IDynamics > agents){
    
    if(time()==0){
      for(int i=0; i < agents.size() && !isColliding ; i++){
        if(agents.get(i) instanceof LineAgent){
          LineAgent a = (LineAgent)agents.get(i);
          if(a != this){
            //draw interconnection in z
            if( !pos.eqZ(a.pos) ){ //z is not equal
              double minLen = dir.len();
              if(a.dir.len() < minLen){ minLen = a.dir.len(); }
              double threshold = minLen * 2.5;
              if( pos.eqX(a.pos, threshold) && pos.eqY(a.pos, threshold) ){ //x and y is equal with in given tolerance
                if(IRand.pct(60)){
                  //new ICurve(pos, a.pos).clr(clr());
                  IG.meshSquareStick(pos, a.pos, 0.3).clr(clr());
                }
              }
            }
            else{
              IVec pos2 = pos.cp(dir);
              IVec apos2 = a.pos.cp(a.dir);
            
              if(!apos2.eq(pos) && !a.pos.eq(pos)){ //not sharing root
                intersection = IVec.intersectLine(a.pos,apos2,pos,pos2); //keep intersection to draw line later
                if(intersection!=null){ //intersecting
                   isColliding=true;
                }
              }
            }
          }
        }
      }
    }
  }
  
  public void update() {
    if(time()==0){
      if(isColliding){ 
         //new ICurve(pos, intersection).clr(clr());
        IG.meshSquareStick(pos, intersection, 0.5).clr(clr()); //keep line to intersection
        del(); 
        return; 
      }
      
      IVec pos2 = pos.dup().add(dir);
       //new ICurve(pos, pos2).clr(clr());
      IG.meshSquareStick(pos, pos2, 0.5).clr(clr());
      
      double r = red() + IRand.get(-0.05, 0.05);
      double g = green() + IRand.get(-0.05, 0.05);
      double b = blue() + IRand.get(-0.05, 0.05);
      
      boolean branchL = IRand.pct(pctL);
      boolean branchR = IRand.pct(pctR);

      double lenL = dir.len();
      double lenR = dir.len();
      lenL*=0.995;  //shrinking length
      lenR*=0.995;  //shrinking length
      
      if (branchL && branchR) {  //only when branching both
        if(IRand.pct(50.0)){
          if (pctL < pctR) { lenL *= 0.9; }
          else{ lenR *= 0.9; }
	}
        else if(IRand.pct(6.0)){
          if (pctL < pctR) { lenL *= 0.4; }
          else{ lenR *= 0.4; }
        }
        else if(IRand.pct(5.0)){
          if (pctL < pctR) { lenL *= 1.4; }
          else{ lenR *= 1.4; }
        }
      }
      
      if (branchL) {  //bend left
        IVec dir2 = dir.dup();
        dir2.len(lenL);  //update length
        dir2.rot(PI/30);
        
        if(branchR && pctR > pctL){  //swap L/R% when branching both
          new LineAgent(pos2, dir2, pctR, pctL).clr(r,g,b);
        }
        else{
          new LineAgent(pos2, dir2, pctL, pctR).clr(r,g,b);
	}
      }

      if (branchR) {  //bend right
        IVec dir2 = dir.dup();
        dir2.len(lenR);  //update length
        dir2.rot(-PI/30);

        if(branchL && pctR < pctL){  //swap L/R% when branching both
          new LineAgent(pos2, dir2, pctR, pctL).clr(r,g,b);
        }
        else{
          new LineAgent(pos2, dir2, pctL, pctR).clr(r,g,b);
        }
      }
    }
  }
}


(back to the list of tutorials)

HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java / Python)
GALLERY
SOURCE CODE(GitHub)
ABOUT