Tutorials | (back to the list of tutorials) |
Template Code with Box![]()
![]()
![]()
import processing.opengl.*;
import igeo.*;
void setup(){
size(960, 540, IG.GL); // set the window size
IConfig.syncDrawAndDynamics=true;
IG.bg(1.0); // setting background color. to set RGB color, put 3 numbers like IG.bg(1.0,0.0,0.0)
IG.fillWire(); // solid shading mode with wireframe. Solid shading without wireframe is IG.fill(). transparent with wireframe is IG.transWire(). transparent without wireframe is IG.trans().
IRand.init(3); // initial seed of random number
// First agent is generated here. The first argument is position, the second is front direction and size, the third is upward normal direction and size, the fourth is a parent agent which needs to be null in the first agent
new ClockStackAgent(new IVec(0,0,0), new IVec(1,0,0), new IVec(0,0,1), null).clr(0.6);
}
class Orientation{
IVec dir, nml; // as xyz coordinates system, dir corresponds to Y and nml corresponds to Z
boolean righthand; // right hand coordinates system or not
double sideLen; // length of side vector. Front length is length of dir. Up length is length of nml.
IVec translate; // just to implement jumping behavior
Orientation(IVec d, IVec n, double sideLength, boolean righthandsys){ dir=d; nml=n; sideLen=sideLength; righthand=righthandsys; }
Orientation(IVec d, IVec n, boolean righthandsys){ dir=d; nml=n; sideLen=dir.len(); righthand=righthandsys; }
Orientation(IVec d, IVec n, IVec side){ dir=d; nml=n; sideLen=side.len(); righthand= dir.cross(nml).dot(side)>0; } // only length and righthand is set by side, not direction.
Orientation(IVec d, IVec n, double sideLength){ this(d,n,sideLength,true); }
Orientation(IVec d, IVec n){ this(d,n,true); }
Orientation(Orientation o){ dir=o.dir.cp(); nml=o.nml.cp(); sideLen=o.sideLen; righthand=o.righthand; }
Orientation cp(){ return new Orientation(this); }
boolean eq(Orientation o){
return o.righthand==righthand && o.dir.eq(dir) && o.nml.eq(nml) && Math.abs(sideLen-o.sideLen) < IConfig.tolerance &&
(o.translate==null && translate==null || o.translate!=null&&translate!=null&&o.translate.eq(translate));
}
boolean isParallel(Orientation o){
return o.righthand==righthand && o.dir.isParallel(dir) && o.nml.isParallel(nml);
}
IVec dir(){ return dir.cp(); }
IVec front(){ return dir(); }
IVec back(){ return dir().neg(); }
IVec nml(){ return nml.cp(); }
IVec up(){ return nml(); }
IVec down(){ return nml().neg(); }
IVec side(){ if(righthand){ return dir.cross(nml).len(sideLen); }else{ return nml.cross(dir).len(sideLen); } }
IVec right(){ return side(); }
IVec left(){ return side().neg(); }
double sideLen(){ return sideLen; }
double frontLen(){ return dir.len(); }
double upLen(){ return nml.len(); }
Orientation setSideLen(double len){ sideLen=len; return this; }
Orientation setFrontLen(double len){ dir.len(len); return this; }
Orientation setUpLen(double len){ nml.len(len); return this; }
Orientation rot(double ang){ dir.rot(nml, ang); return this; }
Orientation rot(IVec ax, double ang){ dir.rot(ax,ang); nml.rot(ax,ang); return this; }
Orientation pitch(double ang){
IVec ax = dir.cross(nml);
dir.rot(ax, ang); nml.rot(ax, ang);
return this;
}
Orientation yaw(double ang){ dir.rot(nml, ang); return this; }
Orientation roll(double ang){ nml.rot(dir, ang); return this; }
Orientation ref(IVec refNml){
dir.ref(refNml); nml.ref(refNml); righthand = !righthand;
return this;
}
Orientation flip(){ dir.flip(); righthand = !righthand; return this; }// flip front/back
Orientation flipNml(){ nml.flip(); righthand = !righthand; return this; }// flip up/down
Orientation flipSide(){ righthand = !righthand; return this; }// flip left/right
Orientation mul(double v){ dir.mul(v); nml.mul(v); sideLen*=v; return this; }
Orientation div(double v){ dir.div(v); nml.div(v); sideLen/=v; return this; }
Orientation scaleFront(double v){ dir.mul(v); return this; }
Orientation scaleUp(double v){ nml.mul(v); return this; }
Orientation scaleSide(double v){ sideLen*=v; return this; }
Orientation add(Orientation o){ dir.add(o.dir); nml.add(o.nml()); return this; }
Orientation add(Orientation o, double f){ dir.add(o.dir, f); nml.add(o.nml(), f); return this; }
Orientation sum(Orientation o, double f){ dir.mul(1-f).add(o.dir, f); nml.mul(1-f).add(o.nml(), f); sideLen=sideLen*(1-f)+o.sideLen*f; return this; }
Orientation mid(Orientation o){ return sum(o,0.5); }
Orientation translate(IVec t){ return jump(t); }
Orientation jump(IVec move){ translate=move; return this; }
Orientation jump(double x, double y, double z){ return jump(new IVec(x,y,z)); }
Orientation jump(Orientation or){ return jump(or.dir.cp()); }
Orientation jump(double factor){ return jump(dir.cp().mul(factor)); }
Orientation jump(){ return jump(dir.cp()); }
}
class Attribute extends IAttribute{
int delay=0;
boolean noCollision=false;
boolean noGeometry=false;
boolean noDeform=true;
int moduleIndex=-1; // default is no module
Attribute(){ super(); }
Attribute(IAttribute at){ super(at); }
Attribute(Attribute at){
super(at);
delay = at.delay;
noCollision = at.noCollision;
noGeometry = at.noGeometry;
moduleIndex=at.moduleIndex;
}
Attribute cp(){
return new Attribute(this);
}
Attribute delay(int d){ delay = d; return this; }
Attribute noCollision(){ noCollision=true; return this; }
Attribute collision(){ noCollision=false; return this; }
Attribute noGeometry(){ noGeometry=true; return this; }
Attribute geometry(){ noGeometry=false; return this; }
Attribute noDeform(){ noDeform=true; return this; }
Attribute deform(){ noDeform=false; return this; }
Attribute module(int module){ moduleIndex=module; return this; }
int module(){ return moduleIndex; }
Attribute layer(String layerName){ super.layer = IG.layer(layerName); return this; }
}
class ClockStackAgent extends IAgent{
final double threshold = 0.5; //collision threshold
IVec pos, pos2, prevPos;
Orientation orient, prevOrient;
int[] clocks;
boolean isColliding = false, isStopped = false;
boolean addGeometry=false;
ArrayList< IVec > pts;
ArrayList< Orientation > nextOrient;
ArrayList< int[] > nextClocks;
ArrayList< Attribute > nextAttr;
IBounds bounds;
int delayCount;
ClockStackAgent parent;
ClockStackAgent(IVec p, Orientation o, int[] clok, ClockStackAgent parentAgent){
pos = p;
orient = o;
clocks = clok;
parent = parentAgent;
if(parent!=null){
prevPos=parent.pos.cp();
prevOrient=parent.orient.cp();
}
delayCount=0;
}
ClockStackAgent(IVec p, IVec d, IVec n, int[] clok, ClockStackAgent parentAgent){
this(p, !d.isParallel(n)?new Orientation(d,d.cross(n).icross(d).len(n.len())):
n.isParallel(IG.zaxis)?new Orientation(d,d.cross(0,1,0).icross(d).len(n.len())):new Orientation(d,d.cross(0,0,1).len(n.len())),
clok, parentAgent);
}
ClockStackAgent(IVec p, IVec d, IVec n, ClockStackAgent parentAgent){
this(p,d,n,new int[0], parentAgent);
}
ClockStackAgent(IVec p, IVec d, ClockStackAgent parentAgent){
this(p,d,new IVec(0,0,1),null, parentAgent);
}
IVec pos2(){
if(pos2==null) pos2 = pos.cp(orient.dir);
return pos2;
}
IVec prevPos(){ return prevPos; }
Orientation prevOrient(){ return prevOrient; }
Attribute defaultAttribute(){ return new Attribute(); }
ClockStackAgent module(int module){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).module(module);
return this;
}
ClockStackAgent delay(int d){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).delay(d);
return this;
}
ClockStackAgent noCollision(){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).noCollision();
return this;
}
ClockStackAgent collision(){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).collision();
return this;
}
boolean isDelayed(){
if(attr()==null) return false;
if(((Attribute)attr()).delay <= delayCount) return true;
return false;
}
int delayedTime(){
if(attr()==null) return time();
return delayCount - ((Attribute)attr()).delay;
}
boolean isCollidable(){
if(attr()==null) return true;
if(((Attribute)attr()).noCollision) return false;
if(((Attribute)attr()).delay <= delayCount) return true;
return false;
}
void interact(ArrayList< IDynamics > agents){
if(threshold > 0 && !isStopped && isCollidable()){
IVec pt2 = pos2();
// collision to the ground
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof ClockStackAgent){
ClockStackAgent a = (ClockStackAgent)agents.get(i);
if(a==this){ // check self collision
for(int j=0; pts!=null && j < pts.size()-2 && !isColliding; j++){ // exclude last segment
if(IVec.isSegCloserThan(pos, pt2, pts.get(j), pts.get(j+1), threshold)){
isColliding = true;
if(pos.distToSegment(pts.get(j), pts.get(j+1))>threshold){
addGeometry=true;
}
}
}
}
else if(a.delayedTime() >= 0){ // a!=this
if(a.bounds!=null && bounds!=null){
IBounds newbounds = bounds.cp();
newbounds.compare(pt2);
if(!newbounds.isCloserThan(a.bounds,threshold)){
continue;
}
}
IVec apt2 = a.pos2();
if(!a.isColliding && IVec.isSegCloserThan(pos, pt2, a.pos, apt2, threshold) && !(pos.eq(a.pos) && !pt2.eq(apt2))/*not sibling*/ && !(a.time() > 0&&apt2.eq(pos))/*not parent*/ ){
isColliding = true;
if(pos.distToSegment(a.pos, apt2)>threshold){
addGeometry=true;
}
}
for(int j=0; a.pts!=null && j < a.pts.size() && !isColliding; j++){
IVec apt3 = a.pos;
if(j < a.pts.size()-1) apt3 = a.pts.get(j+1);
if(IVec.isSegCloserThan(pos, pt2, a.pts.get(j), apt3, threshold)
&& (!pos.eq(a.pos) || pt2.eq(apt2) || j < a.pts.size()-1) ){
if(delayedTime() > 0 || !pos.isOnSegment(a.pts.get(j),apt3)){ // exclude if it came from that line
isColliding = true;
if(pos.distToSegment(a.pts.get(j), apt3)>threshold){
addGeometry=true;
}
}
}
}
}
}
}
}
}
int clock(int i){
if(i >= clocks.length) return 0;
return clocks[i];
}
Attribute next(int incrementClock){
return next(orient, incrementClock);
}
Attribute next(Orientation o, int incrementClock){
if(nextOrient==null){
nextOrient = new ArrayList< Orientation >();
nextClocks = new ArrayList< int[] >();
nextAttr = new ArrayList< Attribute >();
}
nextOrient.add(o);
int[] clocks2 = new int[incrementClock+1 > clocks.length?incrementClock+1:clocks.length];
for(int i=0; i < clocks2.length; i++){
if(i < incrementClock) clocks2[i] = 0;
else if(i < clocks.length) clocks2[i] = clocks[i];
}
clocks2[incrementClock]++;
nextClocks.add(clocks2);
Attribute attr = null;
if(attr()==null) attr = new Attribute();
else{
IAttribute at = attr();
if(at instanceof Attribute) attr = ((Attribute)at).cp();
else attr = new Attribute(at);
}
nextAttr.add(attr);
return attr;
}
void generate(){
if(nextOrient==null || nextOrient.size()==0){
isStopped=true;
return;
}
for(int i=0; i < nextOrient.size(); i++){
Orientation orient2 = nextOrient.get(i);
if(i > 0 || orient2.translate!=null){
if(orient2.translate!=null){ // jump
IVec pos2 = pos.cp(orient2.translate);
orient2.translate = null; // jump happens only once
new ClockStackAgent(pos2, orient2, nextClocks.get(i), null).attr(nextAttr.get(i));
if(i==0) isStopped=true;
}
else{
new ClockStackAgent(pos2(), orient2, nextClocks.get(i), this).attr(nextAttr.get(i));
}
}
else{
if(pts==null){
pts = new ArrayList< IVec >();
bounds = new IBounds(pos);
bounds.compare(pos2);
}
if(pts.size() > 1 && pts.get(pts.size()-1).isOnLine(pos, pts.get(pts.size()-2))){
pts.set(pts.size()-1, pos);
}
else{ pts.add(pos); } // past points
prevPos = pos.cp();
pos = pos2();
prevOrient = orient.cp();
orient = orient2;
clocks = nextClocks.get(i);
attr(nextAttr.get(i));
bounds.compare(pos2); // next pointy
delayCount=0;
}
}
pos2 = null; // reset pos2
nextOrient=null;
nextClocks=null;
nextAttr=null;
}
IVec dir(){ return orient.dir(); }
IVec front(){ return orient.front(); }
IVec back(){ return orient.back(); }
IVec nml(){ return orient.nml(); }
IVec up(){ return orient.up(); }
IVec down(){ return orient.down(); }
IVec right(){ return orient.right(); }
IVec left(){ return orient.left(); }
IVec side(){ return orient.side(); }
IVec prevDir(){ return prevOrient==null?null:prevOrient().dir(); }
IVec prevFront(){ return prevOrient==null?null:prevOrient().front(); }
IVec prevBack(){ return prevOrient==null?null:prevOrient().back(); }
IVec prevNml(){ return prevOrient==null?null:prevOrient().nml().len(prevOrient.dir().len()); }
IVec prevUp(){ return prevOrient==null?null:prevOrient().up().len(prevOrient.dir().len()); }
IVec prevDown(){ return prevOrient==null?null:prevOrient().down().len(prevOrient.dir().len()); }
IVec prevRight(){ return prevOrient==null?null:prevOrient().right().len(prevOrient.dir().len()); }
IVec prevLeft(){ return prevOrient==null?null:prevOrient().left().len(prevOrient.dir().len()); }
IVec prevSide(){ return prevOrient==null?null:prevOrient().side().len(prevOrient.dir().len()); }
// transformation methods
Orientation rot(double angle){ return orient.cp().rot(angle); }
Orientation rot(IVec axis, double angle){ return orient.cp().rot(axis,angle); }
Orientation pitch(double angle){ return orient.cp().pitch(angle); }
Orientation yaw(double angle){ return orient.cp().yaw(angle); }
Orientation roll(double angle){ return orient.cp().roll(angle); }
Orientation mul(double factor){ return orient.cp().mul(factor); }
Orientation div(double factor){ return orient.cp().div(factor); }
Orientation ref(IVec axis){ return orient.cp().ref(axis); }
Orientation flip(){ return orient.cp().flip(); }
Orientation flipNml(){ return orient.cp().flipNml(); }
Orientation flipSide(){ return orient.cp().flipSide(); }
Orientation jump(IVec move){ return orient.cp().jump(move); }
Orientation jump(double x, double y, double z){ return orient.cp().jump(new IVec(x,y,z)); }
Orientation jump(Orientation or){ return orient.cp().jump(or.dir); }
Orientation jump(double factor){return orient.cp().jump(orient.dir.cp().mul(factor)); }
Orientation jump(){ return orient.cp().jump(orient.dir); }
void update(){
if(isStopped){ return; }
if(attr()==null || ((Attribute)attr()).delay <= delayCount){
if(isColliding){
if(attr()==null && time()==0 ||
((Attribute)attr()).delay==time()){ del(); }
else isStopped=true;
if(addGeometry) makeGeometry(); // last one before disappearing
return;
}
pos2 = pos2();
rules();
makeGeometry(); // make geometry
generate();
delayCount=0;
}
else{
delayCount++;
}
}
IPoint makePoint(){ return new IPoint(pos.cp()).attr(attr().cp()); }
ICurve makeLine(){
return new ICurve(pos, pos2).attr(attr());
}
ISurface makeSurface(){
IVec[][] pts = new IVec[2][2];
double len = orient.dir().len()/2;
IVec side = right().cp().len(len);
pts[0][0] = pos.cp().add(side);
pts[0][1] = pos.cp().sub(side);
pts[1][0] = pos2.cp().add(side);
pts[1][1] = pos2.cp().sub(side);
return new ISurface(pts).attr(attr());
}
IBox makeBox(){
IVec[][][] pts = new IVec[2][2][2];
IVec p2 = pos.cp();
IVec p1 = p2.dif(orient.front());
IVec uvec2 = orient.right();;
IVec vvec2 = orient.front();
IVec wvec2 = orient.up();
IVec uvec1 = uvec2;
IVec vvec1 = vvec2;
IVec wvec1 = wvec2;
if(prevOrient != null && !((Attribute)attr()).noDeform){
p1 = prevPos;
uvec1 = prevOrient.right();
vvec1 = prevOrient.front();
wvec1 = prevOrient.up();
}
pts[0][0][1] = p1.cp().add(uvec1, -0.5).add(vvec1, 0.5);
pts[1][0][1] = p1.cp().add(uvec1, 0.5).add(vvec1, 0.5);
pts[0][0][0] = p1.cp().add(uvec1, -0.5).add(vvec1, 0.5).add(wvec1);
pts[1][0][0] = p1.cp().add(uvec1, 0.5).add(vvec1, 0.5).add(wvec1);
pts[0][1][1] = p2.cp().add(uvec2, -0.5).add(vvec2, 0.5);
pts[1][1][1] = p2.cp().add(uvec2, 0.5).add(vvec2, 0.5);
pts[0][1][0] = p2.cp().add(uvec2, -0.5).add(vvec2, 0.5).add(wvec2);
pts[1][1][0] = p2.cp().add(uvec2, 0.5).add(vvec2, 0.5).add(wvec2);
return (IBox)new IBox(pts).attr(attr());
}
void makeGeometry(){
if(attr()!=null && ((Attribute)attr()).noGeometry) return;
//makePoint();
//makeLine();
//makeSurface();
makeBox();
}
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0).module(0);
if(clock(0)==0 && clock(2)==0 && clock(3) < clock(4)){
next(jump(up().add(back())).rot(PI/40), 3).module(1);
if(clock(3)==0){
if(clock(5)==0){
if(IRand.pct(20) && clock(6) < 3 && clock(4) > 3){
next(jump(side()).rot(-PI/2), 5).module(1);
}
}
else if(clock(5)==1){
if(IRand.pct(20) && clock(6) < 2 && clock(4) > 3){
next(jump(left()).rot(PI/2), 6).module(1);
}
}
}
}
}
else{
next(rot(PI/2),1).module(2);
if(clock(3)==0 && clock(2)==0){
if(clock(5)==0){
if(IRand.pct(95) || clock(6)==0){
next(jump(right()).rot(PI/10), 4).module(1);
}
}
else{
if(IRand.pct(95) || clock(6)==0){
next(jump(right()).rot(-PI/6), 4).module(1);
}
}
}
}
}
else{
if(clock(0) < 4){
next(0).module(0);
}
else{
next(rot(PI/2),2).module(2);
}
}
}
}
Rule 1![]()
![]()
![]()
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0);
}
else{
next(rot(PI/2),1);
}
}
else{
if(clock(0) < 4){
next(0);
}
else{
next(rot(PI/2),2);
}
}
}
Rule 2![]()
![]()
![]()
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0);
if(clock(0)==0 && clock(2)==0 && clock(3) < 8){
next(jump(up().add(back())), 3);
}
}
else{
next(rot(PI/2),1);
}
}
else{
if(clock(0) < 4){
next(0);
}
else{
next(rot(PI/2),2);
}
}
}
Rule 3![]()
![]()
![]()
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0);
if(clock(0)==0 && clock(2)==0 && clock(3) < 8){
next(jump(up().add(back())), 3);
}
}
else{
next(rot(PI/2), 1);
if(clock(3)==0 && clock(2)==0){
next(4);
}
}
}
else{
if(clock(0) < 4){
next(0);
}
else{
next(rot(PI/2), 2);
}
}
}
Rule 4![]()
![]()
![]()
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0);
if(clock(0)==0 && clock(2)==0 && clock(3) < 8){
next(jump(up().add(back())), 3);
}
}
else{
next(rot(PI/2), 1);
if(clock(3)==0 && clock(2)==0){
next(jump(right()), 4);
}
}
}
else{
if(clock(0) < 4){
next(0);
}
else{
next(rot(PI/2), 2);
}
}
}
Rule 5![]()
![]()
![]()
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0);
if(clock(0)==0 && clock(2)==0 && clock(3) < 8){
next(jump(up().add(back())), 3);
}
}
else{
next(rot(PI/2), 1);
if(clock(3)==0 && clock(2)==0){
next(jump(right()).rot(PI/10), 4);
}
}
}
else{
if(clock(0) < 4){
next(0);
}
else{
next(rot(PI/2), 2);
}
}
}
Rule 6![]()
![]()
![]()
void rules(){
if(clock(1) < 1){
if(clock(0) < 8){
next(0);
if(clock(0)==0 && clock(2)==0 && clock(3) < 8){
next(jump(up().add(back())), 3);
if(clock(3)==0){
if(clock(5)==0){
if((clock(4)==15 || clock(4)==6) && clock(6) < 2){
next(jump(side()).rot(-PI/2), 5);
}
}
else if(clock(5)==1){
if(clock(4)==4 && clock(6) < 1){
next(jump(left()).rot(PI/2), 6);
}
}
}
}
}
else{
next(rot(PI/2), 1);
if(clock(3)==0 && clock(2)==0){
if(clock(5)==0){
next(jump(right()).rot(PI/10), 4);
}
else{
next(jump(right()).rot(-PI/6), 4);
}
}
}
}
else{
if(clock(0) < 4){
next(0);
}
else{
next(rot(PI/2),2);
}
}
}
Template Code with Imported Geometry![]()
![]()
![]()
import processing.opengl.*;
import igeo.*;
IGeometry[][] modules;
ISurface ground;
ICurve siteBoundary;
ICurve pondBoundary;
void setup(){
size(960, 540, IG.GL);
IConfig.syncDrawAndDynamics=true;
modules = new IGeometry[2][];
IG.open("module1.3dm");
modules[0] = IG.geometries();
IG.delAll();
IG.open("module2.3dm");
modules[1] = IG.geometries();
IG.delAll();
IG.open("ground.3dm");
ground = IG.surface(0);
siteBoundary = IG.layer("site_boundary").curve(0); // comment out this line if you don't need the site boundary collision detection
pondBoundary = IG.layer("pond_boundary").curve(0); // comment out this line if you don't need the pond boundary collision detection
if(siteBoundary !=null) siteBoundary.del();
if(pondBoundary !=null) pondBoundary.del();
IG.showTime();
IRand.init(5); // initialize random number seed
IG.bg(1.0);
IG.pers();
//IG.pers(new IVec(200,200,200), new IVec(-1,-1,-1)); // when you need to set camera position and direction
IG.fill();
//new FocusAgent(); // to automatically focus on all geometry during animatin capture
new ClockStackAgent(new IVec(-60,10,58), new IVec(5,0,0), new IVec(0,0,5), null).module(1);
}
/*
// to capture animation frames
int frameCount=0;
void draw(){
if(frameCount < 1000){
saveFrame("capture/frame_#####.jpg");
}
else{
System.exit(1);
}
frameCount++;
}
// to focus on any generated objects all the time
class FocusAgent extends IAgent{
void update(){ IG.focus(); }
}
*/
class Orientation{
IVec dir, nml; // as xyz coordinates system, dir corresponds to Y and nml corresponds to Z
boolean righthand; // right hand coordinates system or not
double sideLen; // length of side vector. Front length is length of dir. Up length is length of nml.
IVec translate; // just to implement jumping behavior
Orientation(IVec d, IVec n, double sideLength, boolean righthandsys){ dir=d; nml=n; sideLen=sideLength; righthand=righthandsys; }
Orientation(IVec d, IVec n, boolean righthandsys){ dir=d; nml=n; sideLen=dir.len(); righthand=righthandsys; }
Orientation(IVec d, IVec n, IVec side){ dir=d; nml=n; sideLen=side.len(); righthand= dir.cross(nml).dot(side)>0; } // only length and righthand is set by side, not direction.
Orientation(IVec d, IVec n, double sideLength){ this(d,n,sideLength,true); }
Orientation(IVec d, IVec n){ this(d,n,true); }
Orientation(Orientation o){ dir=o.dir.cp(); nml=o.nml.cp(); sideLen=o.sideLen; righthand=o.righthand; }
Orientation cp(){ return new Orientation(this); }
boolean eq(Orientation o){
return o.righthand==righthand && o.dir.eq(dir) && o.nml.eq(nml) && Math.abs(sideLen-o.sideLen) < IConfig.tolerance &&
(o.translate==null && translate==null || o.translate!=null&&translate!=null&&o.translate.eq(translate));
}
boolean isParallel(Orientation o){
return o.righthand==righthand && o.dir.isParallel(dir) && o.nml.isParallel(nml);
}
IVec dir(){ return dir.cp(); }
IVec front(){ return dir(); }
IVec back(){ return dir().neg(); }
IVec nml(){ return nml.cp(); }
IVec up(){ return nml(); }
IVec down(){ return nml().neg(); }
IVec side(){ if(righthand){ return dir.cross(nml).len(sideLen); }else{ return nml.cross(dir).len(sideLen); } }
IVec right(){ return side(); }
IVec left(){ return side().neg(); }
double sideLen(){ return sideLen; }
double frontLen(){ return dir.len(); }
double upLen(){ return nml.len(); }
Orientation setSideLen(double len){ sideLen=len; return this; }
Orientation setFrontLen(double len){ dir.len(len); return this; }
Orientation setUpLen(double len){ nml.len(len); return this; }
Orientation rot(double ang){ dir.rot(nml, ang); return this; }
Orientation rot(IVec ax, double ang){ dir.rot(ax,ang); nml.rot(ax,ang); return this; }
Orientation pitch(double ang){
IVec ax = dir.cross(nml);
dir.rot(ax, ang); nml.rot(ax, ang);
return this;
}
Orientation yaw(double ang){ dir.rot(nml, ang); return this; }
Orientation roll(double ang){ nml.rot(dir, ang); return this; }
Orientation ref(IVec refNml){
dir.ref(refNml); nml.ref(refNml); righthand = !righthand;
return this;
}
Orientation flip(){ dir.flip(); righthand = !righthand; return this; }// flip front/back
Orientation flipNml(){ nml.flip(); righthand = !righthand; return this; }// flip up/down
Orientation flipSide(){ righthand = !righthand; return this; }// flip left/right
Orientation mul(double v){ dir.mul(v); nml.mul(v); sideLen*=v; return this; }
Orientation div(double v){ dir.div(v); nml.div(v); sideLen/=v; return this; }
Orientation scaleFront(double v){ dir.mul(v); return this; }
Orientation scaleUp(double v){ nml.mul(v); return this; }
Orientation scaleSide(double v){ sideLen*=v; return this; }
Orientation add(Orientation o){ dir.add(o.dir); nml.add(o.nml()); return this; }
Orientation add(Orientation o, double f){ dir.add(o.dir, f); nml.add(o.nml(), f); return this; }
Orientation sum(Orientation o, double f){ dir.mul(1-f).add(o.dir, f); nml.mul(1-f).add(o.nml(), f); sideLen=sideLen*(1-f)+o.sideLen*f; return this; }
Orientation mid(Orientation o){ return sum(o,0.5); }
Orientation translate(IVec t){ return jump(t); }
Orientation jump(IVec move){ translate=move; return this; }
Orientation jump(double x, double y, double z){ return jump(new IVec(x,y,z)); }
Orientation jump(Orientation or){ return jump(or.dir.cp()); }
Orientation jump(double factor){ return jump(dir.cp().mul(factor)); }
Orientation jump(){ return jump(dir.cp()); }
}
class Attribute extends IAttribute{
int delay=0;
boolean noCollision=false;
boolean noGeometry=false;
boolean noDeform=true;
int moduleIndex=-1; // default is no module
Attribute(){ super(); }
Attribute(IAttribute at){ super(at); }
Attribute(Attribute at){
super(at);
delay = at.delay;
noCollision = at.noCollision;
noGeometry = at.noGeometry;
moduleIndex=at.moduleIndex;
}
Attribute cp(){
return new Attribute(this);
}
Attribute delay(int d){ delay = d; return this; }
Attribute noCollision(){ noCollision=true; return this; }
Attribute collision(){ noCollision=false; return this; }
Attribute noGeometry(){ noGeometry=true; return this; }
Attribute geometry(){ noGeometry=false; return this; }
Attribute noDeform(){ noDeform=true; return this; }
Attribute deform(){ noDeform=false; return this; }
Attribute module(int module){ moduleIndex=module; return this; }
int module(){ return moduleIndex; }
Attribute layer(String layerName){ super.layer = IG.layer(layerName); return this; }
}
class ClockStackAgent extends IAgent{
final double threshold = 0.5; //collision threshold
IVec pos, pos2, prevPos;
Orientation orient, prevOrient;
int[] clocks;
boolean isColliding = false, isStopped = false;
boolean addGeometry=false;
ArrayList< IVec > pts;
ArrayList< Orientation > nextOrient;
ArrayList< int[] > nextClocks;
ArrayList< Attribute > nextAttr;
IBounds bounds;
int moveCount;
int delayCount;
ClockStackAgent parent;
ClockStackAgent(IVec p, Orientation o, int[] clok, ClockStackAgent parentAgent){
pos = p;
orient = o;
clocks = clok;
parent = parentAgent;
if(parent!=null){
prevPos=parent.pos.cp();
prevOrient=parent.orient.cp();
}
moveCount=0;
delayCount=0;
}
ClockStackAgent(IVec p, IVec d, IVec n, int[] clok, ClockStackAgent parentAgent){
this(p, !d.isParallel(n)?new Orientation(d,d.cross(n).icross(d).len(n.len())):
n.isParallel(IG.zaxis)?new Orientation(d,d.cross(0,1,0).icross(d).len(n.len())):new Orientation(d,d.cross(0,0,1).len(n.len())),
clok, parentAgent);
}
ClockStackAgent(IVec p, IVec d, IVec n, ClockStackAgent parentAgent){
this(p,d,n,new int[0], parentAgent);
}
ClockStackAgent(IVec p, IVec d, ClockStackAgent parentAgent){
this(p,d,new IVec(0,0,1),null, parentAgent);
}
IVec pos2(){
if(pos2==null) pos2 = pos.cp(orient.dir);
return pos2;
}
IVec prevPos(){ return prevPos; }
Orientation prevOrient(){ return prevOrient; }
Attribute defaultAttribute(){ return new Attribute(); }
ClockStackAgent module(int module){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).module(module);
return this;
}
ClockStackAgent delay(int d){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).delay(d);
return this;
}
ClockStackAgent noCollision(){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).noCollision();
return this;
}
ClockStackAgent collision(){
IAttribute attr = attr();
if(attr==null){ attr = defaultAttribute(); attr(attr); }
((Attribute)attr).collision();
return this;
}
boolean isDelayed(){
if(attr()==null) return false;
if(((Attribute)attr()).delay <= delayCount) return true;
return false;
}
int delayedTime(){
if(attr()==null) return time();
return delayCount - ((Attribute)attr()).delay;
}
boolean isCollidable(){
if(attr()==null) return true;
if(((Attribute)attr()).noCollision) return false;
if(((Attribute)attr()).delay <= delayCount) return true;
return false;
}
void interact(ArrayList< IDynamics > agents){
if(threshold > 0 && !isStopped && isCollidable()){
IVec pt2 = pos2();
if(ground!=null){ // collision to the ground
IVec gpt = ground.closePt(pt2);
if(pt2.dif(gpt).z < 0){ // below the ground
isColliding = true;
}
}
if(!isColliding && siteBoundary!=null){ // collision to the site boundary
// check it by polyline of the control points
if(!pos2.isInside2d(siteBoundary.cps())){
isColliding = true;
}
}
if(!isColliding && pondBoundary!=null){ // collision to the pond boundary
if(pos2.isInside2d(pondBoundary.cps())){
isColliding = true;
}
}
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof ClockStackAgent){
ClockStackAgent a = (ClockStackAgent)agents.get(i);
if(a==this){ // check self collision
for(int j=0; pts!=null && j < pts.size()-2 && !isColliding; j++){ // exclude last segment
if(IVec.isSegCloserThan(pos, pt2, pts.get(j), pts.get(j+1), threshold)){
isColliding = true;
if(pos.distToSegment(pts.get(j), pts.get(j+1))>threshold){
addGeometry=true;
}
}
}
}
else if(a.delayedTime() >= 0){ // a!=this
if(a.bounds!=null && bounds!=null){
IBounds newbounds = bounds.cp();
newbounds.compare(pt2);
if(!newbounds.isCloserThan(a.bounds,threshold)){
continue;
}
}
IVec apt2 = a.pos2();
if(!a.isColliding && IVec.isSegCloserThan(pos, pt2, a.pos, apt2, threshold) && !(pos.eq(a.pos) && !pt2.eq(apt2))/*not sibling*/ && !(a.time() > 0&&apt2.eq(pos))/*not parent*/ ){
isColliding = true;
if(pos.distToSegment(a.pos, apt2)>threshold){
addGeometry=true;
}
}
for(int j=0; a.pts!=null && j < a.pts.size() && !isColliding; j++){
IVec apt3 = a.pos;
if(j < a.pts.size()-1) apt3 = a.pts.get(j+1);
if(IVec.isSegCloserThan(pos, pt2, a.pts.get(j), apt3, threshold)
&& (!pos.eq(a.pos) || pt2.eq(apt2) || j < a.pts.size()-1) ){
if(delayedTime() > 0 || !pos.isOnSegment(a.pts.get(j),apt3)){ // exclude if it came from that line
isColliding = true;
if(pos.distToSegment(a.pts.get(j), apt3)>threshold){
addGeometry=true;
}
}
}
}
}
}
}
}
}
int clock(int i){
if(i >= clocks.length) return 0;
return clocks[i];
}
Attribute next(int incrementClock){
return next(orient, incrementClock);
}
Attribute next(Orientation o, int incrementClock){
if(nextOrient==null){
nextOrient = new ArrayList< Orientation >();
nextClocks = new ArrayList< int[] >();
nextAttr = new ArrayList< Attribute >();
}
nextOrient.add(o);
int[] clocks2 = new int[incrementClock+1 > clocks.length?incrementClock+1:clocks.length];
for(int i=0; i < clocks2.length; i++){
if(i < incrementClock) clocks2[i] = 0;
else if(i < clocks.length) clocks2[i] = clocks[i];
}
clocks2[incrementClock]++;
nextClocks.add(clocks2);
Attribute attr = null;
if(attr()==null) attr = new Attribute();
else{
IAttribute at = attr();
if(at instanceof Attribute) attr = ((Attribute)at).cp();
else attr = new Attribute(at);
}
nextAttr.add(attr);
return attr;
}
void generate(){
if(nextOrient==null || nextOrient.size()==0){
isStopped=true;
return;
}
for(int i=0; i < nextOrient.size(); i++){
Orientation orient2 = nextOrient.get(i);
if(i > 0 || orient2.translate!=null){
if(orient2.translate!=null){ // jump
IVec pos2 = pos.cp(orient2.translate);
orient2.translate = null; // jump happens only once
new ClockStackAgent(pos2, orient2, nextClocks.get(i), null).attr(nextAttr.get(i));
if(i==0) isStopped=true;
}
else{
new ClockStackAgent(pos2(), orient2, nextClocks.get(i), this).attr(nextAttr.get(i));
}
}
else{
if(pts==null){
pts = new ArrayList< IVec >();
bounds = new IBounds(pos);
bounds.compare(pos2);
}
if(pts.size() > 1 && pts.get(pts.size()-1).isOnLine(pos, pts.get(pts.size()-2))){
pts.set(pts.size()-1, pos);
}
else{ pts.add(pos); } // past points
prevPos = pos.cp();
pos = pos2();
prevOrient = orient.cp();
orient = orient2;
clocks = nextClocks.get(i);
attr(nextAttr.get(i));
bounds.compare(pos2); // next point
moveCount++;
delayCount=0;
}
}
pos2 = null; // reset pos2
nextOrient=null;
nextClocks=null;
nextAttr=null;
}
IVec dir(){ return orient.dir(); }
IVec front(){ return orient.front(); }
IVec back(){ return orient.back(); }
IVec nml(){ return orient.nml(); }
IVec up(){ return orient.up(); }
IVec down(){ return orient.down(); }
IVec right(){ return orient.right(); }
IVec left(){ return orient.left(); }
IVec side(){ return orient.side(); }
IVec prevDir(){ return prevOrient==null?null:prevOrient().dir(); }
IVec prevFront(){ return prevOrient==null?null:prevOrient().front(); }
IVec prevBack(){ return prevOrient==null?null:prevOrient().back(); }
IVec prevNml(){ return prevOrient==null?null:prevOrient().nml().len(prevOrient.dir().len()); }
IVec prevUp(){ return prevOrient==null?null:prevOrient().up().len(prevOrient.dir().len()); }
IVec prevDown(){ return prevOrient==null?null:prevOrient().down().len(prevOrient.dir().len()); }
IVec prevRight(){ return prevOrient==null?null:prevOrient().right().len(prevOrient.dir().len()); }
IVec prevLeft(){ return prevOrient==null?null:prevOrient().left().len(prevOrient.dir().len()); }
IVec prevSide(){ return prevOrient==null?null:prevOrient().side().len(prevOrient.dir().len()); }
// transformation methods
Orientation rot(double angle){ return orient.cp().rot(angle); }
Orientation rot(IVec axis, double angle){ return orient.cp().rot(axis,angle); }
Orientation pitch(double angle){ return orient.cp().pitch(angle); }
Orientation yaw(double angle){ return orient.cp().yaw(angle); }
Orientation roll(double angle){ return orient.cp().roll(angle); }
Orientation mul(double factor){ return orient.cp().mul(factor); }
Orientation div(double factor){ return orient.cp().div(factor); }
Orientation ref(IVec axis){ return orient.cp().ref(axis); }
Orientation flip(){ return orient.cp().flip(); }
Orientation flipNml(){ return orient.cp().flipNml(); }
Orientation flipSide(){ return orient.cp().flipSide(); }
Orientation jump(IVec move){ return orient.cp().jump(move); }
Orientation jump(double x, double y, double z){ return orient.cp().jump(new IVec(x,y,z)); }
Orientation jump(Orientation or){ return orient.cp().jump(or.dir); }
Orientation jump(double factor){return orient.cp().jump(orient.dir.cp().mul(factor)); }
Orientation jump(){ return orient.cp().jump(orient.dir); }
void update(){
if(isStopped){ return; }
if(attr()==null || ((Attribute)attr()).delay <= delayCount){
if(isColliding){
if(attr()==null && time()==0 ||
((Attribute)attr()).delay==time()){ del(); }
else isStopped=true;
if(addGeometry) makeGeometry(); // last one before disappearing
return;
}
pos2 = pos2();
rules();
makeGeometry(); // make geometry
generate();
delayCount=0;
}
else{
delayCount++;
}
}
IPoint makePoint(){ return new IPoint(pos.cp()).attr(attr().cp()); }
ICurve makeLine(){
return new ICurve(pos, pos2).attr(attr());
}
ISurface makeSurface(){
IVec[][] pts = new IVec[2][2];
double len = orient.dir().len()/2;
IVec side = right().cp().len(len);
pts[0][0] = pos.cp().add(side);
pts[0][1] = pos.cp().sub(side);
pts[1][0] = pos2.cp().add(side);
pts[1][1] = pos2.cp().sub(side);
return new ISurface(pts).attr(attr());
}
IBox makeBox(){
IVec[][][] pts = new IVec[2][2][2];
IVec p2 = pos.cp();
IVec p1 = p2.dif(orient.front());
IVec uvec2 = orient.right();;
IVec vvec2 = orient.front();
IVec wvec2 = orient.up();
IVec uvec1 = uvec2;
IVec vvec1 = vvec2;
IVec wvec1 = wvec2;
if(prevOrient != null && !((Attribute)attr()).noDeform){
p1 = prevPos;
uvec1 = prevOrient.right();
vvec1 = prevOrient.front();
wvec1 = prevOrient.up();
}
pts[0][0][1] = p1.cp().add(uvec1, -0.5).add(vvec1, 0.5);
pts[1][0][1] = p1.cp().add(uvec1, 0.5).add(vvec1, 0.5);
pts[0][0][0] = p1.cp().add(uvec1, -0.5).add(vvec1, 0.5).add(wvec1);
pts[1][0][0] = p1.cp().add(uvec1, 0.5).add(vvec1, 0.5).add(wvec1);
pts[0][1][1] = p2.cp().add(uvec2, -0.5).add(vvec2, 0.5);
pts[1][1][1] = p2.cp().add(uvec2, 0.5).add(vvec2, 0.5);
pts[0][1][0] = p2.cp().add(uvec2, -0.5).add(vvec2, 0.5).add(wvec2);
pts[1][1][0] = p2.cp().add(uvec2, 0.5).add(vvec2, 0.5).add(wvec2);
return (IBox)new IBox(pts).attr(attr());
}
ISphere makeSphere(){
IVec mid = pos.mid(pos2);
double len = pos.dist(pos2);
return (ISphere)new ISphere(mid, len/2).attr(attr());
}
ICurve makeTangentCurve(){
if(prevPos() != null){
IVec m1 = prevPos().mid(pos);
IVec m2 = pos.mid(pos2);
double len = orient.dir().len()/2;
if(!prevOrient().dir.isParallel(orient.dir) || !prevOrient().nml.isParallel(orient.nml)){
IVec[] pts = new IVec[3];
Orientation ori = orient.cp().mid(prevOrient());
pts[0] = m1;
pts[1] = pos;
pts[2] = m2;
return new ICurve(pts, 2).attr(attr());
}
return new ICurve(m1, m2).attr(attr());
}
return null;
}
ISurface makeTangentSurface(){
if(prevPos() != null){
IVec m1 = prevPos().mid(pos);
IVec m2 = pos.mid(pos2);
double len = orient.dir().len()/2;
if(!prevOrient().dir.isParallel(orient.dir) || !prevOrient().nml.isParallel(orient.nml)){
IVec[][] pts = new IVec[3][2];
Orientation ori = orient.cp().mid(prevOrient());
pts[0][0] = m1.cp(prevRight().cp().len(len));
pts[1][0] = pos.cp(ori.right().cp().len(len));
pts[2][0] = m2.cp(right().cp().len(len));
pts[0][1] = m1.cp(prevLeft().cp().len(len));
pts[1][1] = pos.cp(ori.left().cp().len(len));
pts[2][1] = m2.cp(left().cp().len(len));
return new ISurface(pts, 2, 1).attr(attr());
}
return new ISurface(m1.cp(prevRight().cp().len(len)),
m1.cp(prevLeft().cp().len(len)),
m2.cp(left().cp().len(len)),
m2.cp(right().cp().len(len))).attr(attr());
}
return null;
}
ICurve makeCSLine(){
IVec[] pts = new IVec[3];
double len = pos2.dist(pos)/2;
pts[0] = orient.nml().cp().len(len).add(pos2);
pts[1] = pos2.cp();
pts[2] = pos2.cp(orient.front().cp().len(len));
return new ICurve(pts).attr(attr());
}
IBrep makeTetrahedron(){
return makeTetrahedron(pos2, orient.front(), orient.nml(), orient.dir.len()).attr(attr());
}
IBrep makeTetrahedron(IVec center, IVec front, IVec nml, double size){
double len1 = size/4.082*6.124;
double len2 = size/4.082*2.041;
double len3 = size/4.082*5.774;
IVec dir1 = front.cp().len(len1);
IVec dir2 = dir1.cp().flip().len(len2);
IVec dir3 = nml.cp().len(len3).add(dir2);
IVec dir4 = dir3.cp().rot(dir1, PI/3*2);
IVec dir5 = dir3.cp().rot(dir1, PI/3*4);
IVec p1 = center.cp(dir1);
IVec p2 = center.cp(dir3);
IVec p3 = center.cp(dir4);
IVec p4 = center.cp(dir5);
ISurfaceGeo[] srf = new ISurfaceGeo[4];
srf[0] = new ISurfaceGeo(p1,p2,p3);
srf[1] = new ISurfaceGeo(p2,p3,p4);
srf[2] = new ISurfaceGeo(p1,p3,p4);
srf[3] = new ISurfaceGeo(p1,p2,p4);
return new IBrep(srf);
}
IGeometry[] getModuleGeometry(int idx){
if(modules==null){
IG.err("modules is null.");
return null;
}
if(idx < 0 || idx >= modules.length){
IG.err("module index ("+idx+") is out of boundary. ");
return null;
}
return modules[idx];
}
IGeometry[] deformModuleGeometry(int idx){
IGeometry[] geom = getModuleGeometry(idx);
if(geom!=null){
IGeometry[] geom2 = new IGeometry[geom.length];
for(int i=0; i < geom.length; i++){
geom2[i] = geom[i].cp();
IVec[][][] target = new IVec[2][2][2];
IVec p2 = pos.cp();
IVec p1 = p2.dif(orient.front());
IVec uvec2 = orient.right();;
IVec vvec2 = orient.front();
IVec wvec2 = orient.up();
IVec uvec1 = uvec2;
IVec vvec1 = vvec2;
IVec wvec1 = wvec2;
if(prevOrient != null && !((Attribute)attr()).noDeform){
p1 = prevPos;
uvec1 = prevOrient.right();
vvec1 = prevOrient.front();
wvec1 = prevOrient.up();
}
target[0][0][0] = p1.cp().add(uvec1, -0.5).add(vvec1, 0.5);
target[1][0][0] = p1.cp().add(uvec1, 0.5).add(vvec1, 0.5);
target[0][0][1] = p1.cp().add(uvec1, -0.5).add(vvec1, 0.5).add(wvec1);
target[1][0][1] = p1.cp().add(uvec1, 0.5).add(vvec1, 0.5).add(wvec1);
target[0][1][0] = p2.cp().add(uvec2, -0.5).add(vvec2, 0.5);
target[1][1][0] = p2.cp().add(uvec2, 0.5).add(vvec2, 0.5);
target[0][1][1] = p2.cp().add(uvec2, -0.5).add(vvec2, 0.5).add(wvec2);
target[1][1][1] = p2.cp().add(uvec2, 0.5).add(vvec2, 0.5).add(wvec2);
deform(geom2[i], target);
geom2[i].layer(geom[i].layer().name());
String name = String.valueOf(this.hashCode());
geom2[i].name(String.valueOf(this.hashCode())+"_"+String.valueOf(moveCount)); // set object hash code number and moveCount as module geometry name
}
return geom2;
}
return null;
}
IVec deform(IVec uvw, IVec[][][] targetBox){
IVec ret = new IVec();
ret.add(targetBox[0][0][0], (1-uvw.x)*(1-uvw.y)*(1-uvw.z));
ret.add(targetBox[1][0][0], (uvw.x)*(1-uvw.y)*(1-uvw.z));
ret.add(targetBox[0][1][0], (1-uvw.x)*(uvw.y)*(1-uvw.z));
ret.add(targetBox[1][1][0], (uvw.x)*(uvw.y)*(1-uvw.z));
ret.add(targetBox[0][0][1], (1-uvw.x)*(1-uvw.y)*(uvw.z));
ret.add(targetBox[1][0][1], (uvw.x)*(1-uvw.y)*(uvw.z));
ret.add(targetBox[0][1][1], (1-uvw.x)*(uvw.y)*(uvw.z));
ret.add(targetBox[1][1][1], (uvw.x)*(uvw.y)*(uvw.z));
return ret;
}
IGeometry[] deform(IGeometry[] geom,IVec[][][] targetBox){
for(int i=0; i < geom.length; i++){
geom[i] = deform(geom[i], targetBox);
}
return geom;
}
IGeometry deform(IGeometry geom, IVec[][][] targetBox){
if(geom instanceof IPoint){
IPoint point = (IPoint)geom;
point.pos.set(deform(point.pos, targetBox));
point.updateGraphic();
}
else if(geom instanceof ICurve){
ICurve curve = (ICurve)geom;
IVecI[] cps = curve.cps();
for(int i=0; i < cps.length&&cps[0]!=cps[cps.length-1] || i < cps.length-1; i++){
cps[i].set(deform(cps[i].get(), targetBox));
}
curve.updateGraphic();
}
else if(geom instanceof ISurface){
ISurface surface = (ISurface)geom;
IVecI[][] cps = surface.cps();
for(int i=0; i < cps.length; i++){
for(int j=0; j < cps[i].length; j++){
cps[i][j].set(deform(cps[i][j].get(), targetBox));
}
}
surface.updateGraphic();
}
else if(geom instanceof IMesh){
IMesh mesh = (IMesh)geom;
for(int i=0; i < mesh.vertexNum(); i++){
mesh.vertex(i).pos().set(deform(mesh.vertex(i).pos().get(), targetBox));
}
mesh.updateGraphic();
}
else if(geom instanceof IBrep){
IBrep brep = (IBrep)geom;
for(int i=0; i < brep.surfaceNum(); i++){
IVecI[][] cps = brep.surface(i).cps();
for(int j=0; j < cps.length; j++){
for(int k=0; k < cps[j].length; k++){
cps[j][k].set(deform(cps[j][k].get(), targetBox));
}
}
}
brep.updateGraphic();
}
return geom;
}
IGeometry[] makeModule(){
int module = ((Attribute)attr()).module();
if(module>=0){
return deformModuleGeometry(module);
}
return null;
}
void makeGeometry(){
if(attr()!=null && ((Attribute)attr()).noGeometry) return;
//makePoint();
//makeLine();
//makeSurface();
//makeBox();
//makeSphere();
//makeTangentCurve();
//makeTangentSurface();
//makeCSLine();
//makeTetrahedron();
makeModule();
}
void rules(){
int maxClock6 = 7;
if(clock(6)==maxClock6) return;
if(clock(5)==0){ // cube going up
if(clock(2)==0){
if(clock(0)==8){
next(rot(PI/2), 1).module(1);
}
else{
if(clock(0)==0){
if(clock(4)==0){
next(jump(up()), 2).module(0);
}
}
next(rot(0),0).module(0).deform();
}
}
else{
if(clock(2)==7){
next(jump(up()), 4).module(1);
}
else{
next(jump(up()), 2).module(1);
if(IRand.pct(10)){
if(clock(6) < maxClock6){
next(rot(PI/3), 5).module(1); // branch a new cube going down
}
}
}
}
}
else{ // cube going down
if(clock(2)==0){
if(clock(0)==8){
next(rot(PI/2), 1).module(1);
}
else{
if(clock(0)==0){
if(clock(4)==0){
next(jump(down()), 2).module(1);
}
}
next(rot(0), 0).module(0).deform();
}
}
else{
if(clock(2)==7){
next(jump(down()), 4).module(0);
}
else{
next(jump(down()), 2).module(1);
if(IRand.pct(10)){
if(clock(6) < maxClock6){
next(rot(PI/3), 6).module(1); // branch a new cube going up
}
}
}
}
}
}
}
HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java /
Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT