
PDE Download: OOG1zSquareArrayFeedbackDouble.pde
JAVA Download: OOG1zSquareArrayFeedbackDouble.java
Click on anar+ terms to get the documentation.
import processing.opengl.*;
import anar.*;
Obj myObj;
Sliders mySliders;
int n = 10;
Param[] myArrayZ;
Param[] myArrayX;
Param[] myArrayY;
Pt sun;
boolean[] clockwiseZ;
boolean[] clockwiseX;
boolean[] clockwiseY;
float[][] distance;
Obj faces;
void setup(){
size(1000,600,OPENGL);
Anar.init(this);
initForm();
initSun();
}
void initSun(){
// initialise distance array
distance = new float[myArrayZ.length][3];
for (int i = 0; i<distance.length; i++){
distance[i][0] = 0;
distance[i][1] = 0;
distance[i][2] = 0;
}
// initialize turn direction array
clockwiseZ = new boolean[myArrayZ.length];
clockwiseX = new boolean[myArrayZ.length];
clockwiseY = new boolean[myArrayZ.length];
for (int i = 0; i<clockwiseZ.length; i++){
clockwiseZ[i] = true;
clockwiseX[i] = true;
clockwiseY[i] = true;
}
// create "sun"
sun = Anar.Pt(50,10,50);
myObj.add(sun);
// add "sun" parameters to sliders
mySliders = new Sliders();
mySliders.add(sun);
}
void initForm(){
// Create a new Object to store our shape
myObj = new Obj();
// Create another object to store faces htat will be oriented toward the
// "sun"
faces = new Obj();
// Create a vertical translation defining the height of tower floors
Transform tZ = new Translate(0,0,10);
Transform tX = new Translate(10,0,0);
// Create parameter array to store individual rotations values
// use linear array instead of 2-dimensional
myArrayZ = new Param[n*n];
myArrayX = new Param[n*n];
myArrayY = new Param[n*n];
for (int i = 0; i<myArrayZ.length/n; i++){
for (int j = 0; j<myArrayZ.length/n; j++){
// transform 2 dimension i and j into linear index
int index = j+n*i;
// Create individual rotations randomly
myArrayZ[index] = new Param(random(1.4f));
myArrayX[index] = new Param(random(1.4f));
myArrayY[index] = new Param(random(1.4f));
// Define position translation
Transform pos = new Transform();
for (int k = 0; k<j; k++){
pos.apply(tX);
}
for (int k = 0; k<i; k++){
pos.apply(tZ);
}
// Add module according to position and rotation parameter
myObj.add(createModule(pos,myArrayZ[index],myArrayX[index],myArrayY[index]));
}
}
myObj.pts.render = new RenderPtsAll();
// Center on the object
Anar.camTarget(myObj);
}
void draw(){
background(150);
mySliders.draw();
myObj.draw();
updateParameters();
}
void keyPressed(){
// reset shape
if(key==' '){
initForm();
initSun();
}
}
Obj createModule(Transform t, Param pZ, Param pX, Param pY){
int edge = 10;
int h = 1;
// Create the base points (here a square)
// Create a new Face
Face mySquare = new Face();
mySquare.add(Anar.Pt( -edge/2,0, -edge/2));
mySquare.add(Anar.Pt(edge/2,0, -edge/2));
mySquare.add(Anar.Pt(edge/2,0,edge/2));
mySquare.add(Anar.Pt( -edge/2,0,edge/2));
Obj cube = new Extrude(mySquare,Anar.Pt(0,h,0));
Transform tt = new Transform();
tt.rotateZ(pZ);
tt.rotateX(pX);
tt.rotateY(pY);
tt.add(t);
cube.apply(tt);
// store face of the cube to compute distance to "sun"
// see update tab
faces.add(cube.face(5));
return cube;
}
//TODO: (1) (Julien)No Object Creation in the drawLoop
void updateParameters(){
float hStep = 0;
// distance of measure point to surface
int h = 5;
// new object for displaying measure points
Obj points = new Obj();
for (int i = 0; i<faces.numOfFaces(); i++){
Face f = faces.face(i);
// find center of the face
float[] w = new float[f.numOfPts()];
for (int j = 0; j<w.length; j++)
w[j] = 1;
PtBary centre = new PtBary(f,w).normalizeWeight();
// create a point normal to the face at the center
PtNormal n = new PtNormal(f.pt(0),centre,f.pt(1),h);
// add normal to object for visualization
points.add(n);
// compute the distance to the "sun"
float dist = (float)n.length(sun);
float l = (float)centre.length(sun);
// compute step according to cosine theorem
// this approximation is planar
hStep = acos( (sq(h)+sq(l)-sq(dist))/ (2*h*l));
// reduce amplitude to smooth movement
hStep /= 50;
// change rotation selecting randomly on each axis
// this is necessary to circumvent the planarity of the step approximation
float prob = random(1.0f);
int change = 0;
if(prob<0.333f){
clockwiseX[i] = changeRotation(myArrayX[i],clockwiseX[i],hStep,distance[i][0],dist);
change = 0;
}
else
if(prob<0.666f){
clockwiseY[i] = changeRotation(myArrayY[i],clockwiseY[i],hStep,distance[i][1],dist);
change = 1;
}
else{
clockwiseZ[i] = changeRotation(myArrayZ[i],clockwiseZ[i],hStep,distance[i][2],dist);
change = 2;
}
// store previous distance
distance[i][change] = dist;
}
// remove comment to se the measure points
// points.draw();
}
// update parameters for rotation according to step
boolean changeRotation(Param p, boolean clock, float step, float dist, float newDist){
// clockwise
if(clock){
if(dist>newDist)
p.set(p.get()+step);
else{
p.set(p.get()-step);
clock = false;
}
}
// or anti clockwise
else{
if(dist>newDist)
p.set(p.get()-step);
else{
p.set(p.get()+step);
clock = true;
}
}
return clock;
}

|