CY_glass Dripping Simulation


//20081003
//processing code

import processing.opengl.*;

boolean printScreen = false;

int updateCount = 0;

int currentAgent = 0;
agentGroup[] myAgents;

float defaultDist = 1000;

float gravity = 10;
float maintain = 5;
float maintainC = 0.1;
float adherence = 5;
float inertia = 0.5;
float speed = 1.5;

boolean stopped = false;

float meshMin = 20;
boolean toggleParticleDisplay = false;
boolean toggleMeshDisplay = false;
boolean toggleShadeDisplay = true;
boolean toggleSphereDisplay = false;
boolean toggleHistoryDisplay = false;
boolean toggleTransparency = true;

float mouseXX;
float mouseYY;

float cameraRXX;
float cameraRZZ;
float cameraYY;

float cameraX;
float cameraY;
float cameraZ;

float cameraRX;
float cameraRY;
float cameraRZ;

float cameraTZ;
float cameraTX;
float cameraTZZ;
float cameraTXX;

int meshDensity = 6;
float solidifacation = 0.0055;
float particleSize = 2;

float createX = 0;
float createY = 0;
float createZ = 0;
float createXD = 1;
float createYD = 0;
float createZD = 0;
float createR = 20;

boolean creating = false;
boolean working = false;
boolean automated = false;

gDrop[] dropArray;

String myTrace = “”;

PFont font;

procedure myProcedure;

boolean exportMaya = false;

void mayaExport(){
PrintWriter mayaOutput = createWriter(month()+”_”+day()+”_”+hour()+”_”+minute()+”_”+second()+”.txt”);
if(dropArray != null){
for(int i=0;i<dropArray.length;i++){
for(int j=0;j<dropArray[i].rings.length;j++){
//export the main geometry
if(j<dropArray[i].rings.length-1){
for(int k=0;kmeshDensity-1){
t=0;
}
mayaOutput.println(exportQuad(dropArray[i].rings[j].particles[k].pos, dropArray[i].rings[j+1].particles[k].pos, dropArray[i].rings[j+1].particles[t].pos, dropArray[i].rings[j].particles[t].pos));
}
}
}
//export the added starting ring
//export the starting and ending cap
int ringLength = dropArray[i].rings.length-1;
for(int k=0;kmeshDensity-1){
t=0;
}
mayaOutput.println(exportQuad(dropArray[i].capStart.particles[k].pos, dropArray[i].rings[0].particles[k].pos, dropArray[i].rings[0].particles[t].pos, dropArray[i].capStart.particles[t].pos));
mayaOutput.println(exportTri(dropArray[i].capStart.particles[k].pos, dropArray[i].capStart.particles[t].pos, dropArray[i].capStart.pos));
mayaOutput.println(exportTri(dropArray[i].rings[ringLength].particles[k].pos, dropArray[i].rings[ringLength].particles[t].pos, dropArray[i].rings[ringLength].pos));
}
}
}
mayaOutput.flush(); // Writes the remaining data to the file
mayaOutput.close(); // Finishes the file
}

String exportQuad(float[] pos1, float[] pos2, float[] pos3, float[] pos4){
String out;
out = “polyCreateFacet”;
out += ” -p “+pos1[0]+” “+pos1[1]+” “+pos1[2];
out += ” -p “+pos2[0]+” “+pos2[1]+” “+pos2[2];
out += ” -p “+pos3[0]+” “+pos3[1]+” “+pos3[2];
out += ” -p “+pos4[0]+” “+pos4[1]+” “+pos4[2];
out += “;”;
return out;
}

String exportTri(float[] pos1, float[] pos2, float[] pos3){
String out;
out = “polyCreateFacet”;
out += ” -p “+pos1[0]+” “+pos1[1]+” “+pos1[2];
out += ” -p “+pos2[0]+” “+pos2[1]+” “+pos2[2];
out += ” -p “+pos3[0]+” “+pos3[1]+” “+pos3[2];
out += “;”;
return out;
}

void setup(){
size(720, 480, OPENGL);
//frameRate(30);
font = createFont(“Tahoma”, 12);
textFont(font);

cameraX = 0;
cameraY = 400;
cameraZ = 10;
cameraRX = 0;
cameraRY = 0;
cameraRZ = 0;
cameraTZ = -150;
cameraTX = 0;

background(255);
//set up the agents

agent a1 = new agent(createArray3(0,0,20), 40, createArray3(0,0,1));
agent a2 = new agent(createArray3(300,0,15), 30, createArray3(0,0,1));
agent a3 = new agent(createArray3(150,300*cos(radians(30)),25), 50, createArray3(0,0,1));

agent a4 = new agent(createArray3(-500,0,20), 40, createArray3(0,0,1));
agent a5 = new agent(createArray3(-200,0,15), 30, createArray3(0,0,1));
agent a6 = new agent(createArray3(-350,300*cos(radians(30)),25), 50, createArray3(0,0,1));

agent a7 = new agent(createArray3(-250,400,20), 40, createArray3(0,0,1));
agent a8 = new agent(createArray3(50,400,15), 30, createArray3(0,0,1));
agent a9 = new agent(createArray3(-100,300*cos(radians(30))+400,25), 50, createArray3(0,0,1));

myAgents = new agentGroup[9];
myAgents[0] = new agentGroup(a1, 0);
myAgents[1] = new agentGroup(a2, 1);
myAgents[2] = new agentGroup(a3, 2);

myAgents[3] = new agentGroup(a4, 3);
myAgents[4] = new agentGroup(a5, 4);
myAgents[5] = new agentGroup(a6, 5);

myAgents[6] = new agentGroup(a7, 6);
myAgents[7] = new agentGroup(a8, 7);
myAgents[8] = new agentGroup(a9, 8);

myAgents[0].chase = new int[1];
myAgents[1].chase = new int[1];
myAgents[2].chase = new int[3];
myAgents[0].avoid = new int[1];
myAgents[1].avoid = new int[1];
myAgents[2].avoid = new int[1];

myAgents[3].chase = new int[1];
myAgents[4].chase = new int[1];
myAgents[5].chase = new int[3];
myAgents[3].avoid = new int[1];
myAgents[4].avoid = new int[1];
myAgents[5].avoid = new int[1];

myAgents[6].chase = new int[1];
myAgents[7].chase = new int[1];
myAgents[8].chase = new int[3];
myAgents[6].avoid = new int[1];
myAgents[7].avoid = new int[1];
myAgents[8].avoid = new int[1];

myAgents[0].chase[0] = 2;
myAgents[1].chase[0] = 0;
myAgents[2].chase[0] = 1;
myAgents[2].chase[1] = 5;
myAgents[2].chase[2] = 8;
myAgents[0].avoid[0] = 1;
myAgents[1].avoid[0] = 2;
myAgents[2].avoid[0] = 0;

myAgents[3].chase[0] = 5;
myAgents[4].chase[0] = 3;
myAgents[5].chase[0] = 4;
myAgents[5].chase[1] = 2;
myAgents[5].chase[2] = 8;
myAgents[3].avoid[0] = 4;
myAgents[4].avoid[0] = 5;
myAgents[5].avoid[0] = 3;

myAgents[6].chase[0] = 8;
myAgents[7].chase[0] = 6;
myAgents[8].chase[0] = 7;
myAgents[8].chase[1] = 2;
myAgents[8].chase[2] = 5;
myAgents[6].avoid[0] = 7;
myAgents[7].avoid[0] = 8;
myAgents[8].avoid[0] = 6;

myAgents[0].tailon = 2;
myAgents[1].tailon = 0;
myAgents[2].tailon = 1;
myAgents[3].tailon = 5;
myAgents[4].tailon = 3;
myAgents[5].tailon = 4;
myAgents[6].tailon = 8;
myAgents[7].tailon = 6;
myAgents[8].tailon = 7;
}

void draw(){

if(exportMaya){
mayaExport();
exportMaya = false;
}

background(70);
camera(cameraX, cameraY, cameraZ, // eyeX, eyeY, eyeZ
0.0, 0.0, 0.0, // centerX, centerY, centerZ
0.0, 1.0, 0.0); // upX, upY, upZ
rotateX(radians(cameraRX));
rotateY(radians(cameraRY));
rotateZ(radians(cameraRZ));
translate(cameraTX, 0, cameraTZ);

//lights();
directionalLight(255, 255, 255, // Color
-1, -1, -1); // The x-, y-, z-axis direction
directionalLight(100, 100, 100, // Color
1, 1, 1);
fill(0,128);
noStroke();
rect(-600, -600, 1200, 1200);

//
updateCount = 0;
if(dropArray != null){
for(int i=0; i<dropArray.length; i++){
if(dropArray[i].solid<dropArray[0].rings.length){
dropArray[i].update();
updateCount ++;
}
if(toggleShadeDisplay){
if(working){//draw the link to the nozzle
if(toggleMeshDisplay){
stroke(0, 128);
}
else{
noStroke();
}
int index1 = dropArray.length-1;
int index2 = dropArray[index1].rings.length-1;
for(int j = 0; jmeshDensity-1){
t=0;
}
beginShape(TRIANGLES);
fill(255, ((1-dropArray[index1].rings[index2].liquefaction)*255), ((1-dropArray[index1].rings[index2].liquefaction)*255), 128);
vertex(dropArray[index1].rings[index2].particles[j].pos[0], dropArray[index1].rings[index2].particles[j].pos[1], dropArray[index1].rings[index2].particles[j].pos[2]);
fill(255, 0, 0, 128);
vertex(createX, createY, createZ);
fill(255, ((1-dropArray[index1].rings[index2].liquefaction)*255), ((1-dropArray[index1].rings[index2].liquefaction)*255), 128);
vertex(dropArray[index1].rings[index2].particles[t].pos[0], dropArray[index1].rings[index2].particles[t].pos[1], dropArray[index1].rings[index2].particles[t].pos[2]);
endShape(TRIANGLES);
}
}
dropArray[i].plot(toggleParticleDisplay, toggleMeshDisplay);
}
}
}

//
//

//draw history
if(toggleHistoryDisplay){
if(myProcedure != null){
if(myProcedure.history[0] != null){
myProcedure.plotHistory();
}
}
}
//
if(creating){
//uniify the direction
float[] uz = {
createXD, createYD, createZD };
uz = unifyVector(uz);
float[] t = {
0,0,1 };
float[] ux = new float[3];
ux = unifyVector(crossProduct(uz, t));
float[] uy = unifyVector(crossProduct(uz, ux));
fill(0,128);
stroke(0);
int nL = 30;
int nW = 4;
pushMatrix();
translate(createX, createY, createZ);
beginShape(QUADS);
vertex(ux[0]*nW- uy[0]*nW , ux[1]*nW- uy[1]*nW , ux[2]*nW- uy[2]*nW);
vertex(ux[0]*nW- uy[0]*nW+ uz[0]*nL, ux[1]*nW- uy[1]*nW+ uz[1]*nL, ux[2]*nW- uy[2]*nW+ uz[2]*nL);
vertex(ux[0]*nW+ uy[0]*nW+ uz[0]*nL, ux[1]*nW+ uy[1]*nW+ uz[1]*nL, ux[2]*nW+ uy[2]*nW+ uz[2]*nL);
vertex(ux[0]*nW+ uy[0]*nW , ux[1]*nW+ uy[1]*nW , ux[2]*nW+ uy[2]*nW);
//
vertex(-ux[0]*nW+ uy[0]*nW , -ux[1]*nW+ uy[1]*nW , -ux[2]*nW+ uy[2]*nW);
vertex(-ux[0]*nW+ uy[0]*nW+ uz[0]*nL, -ux[1]*nW+ uy[1]*nW+ uz[1]*nL, -ux[2]*nW+ uy[2]*nW+ uz[2]*nL);
vertex(ux[0]*nW+ uy[0]*nW+ uz[0]*nL, ux[1]*nW+ uy[1]*nW+ uz[1]*nL, ux[2]*nW+ uy[2]*nW+ uz[2]*nL);
vertex(ux[0]*nW+ uy[0]*nW , ux[1]*nW+ uy[1]*nW , ux[2]*nW+ uy[2]*nW);
//
vertex(-ux[0]*nW+ uy[0]*nW , -ux[1]*nW+ uy[1]*nW , -ux[2]*nW+ uy[2]*nW);
vertex(-ux[0]*nW+ uy[0]*nW+ uz[0]*nL, -ux[1]*nW+ uy[1]*nW+ uz[1]*nL, -ux[2]*nW+ uy[2]*nW+ uz[2]*nL);
vertex(-ux[0]*nW- uy[0]*nW+ uz[0]*nL, -ux[1]*nW- uy[1]*nW+ uz[1]*nL, -ux[2]*nW- uy[2]*nW+ uz[2]*nL);
vertex(-ux[0]*nW- uy[0]*nW , -ux[1]*nW- uy[1]*nW , -ux[2]*nW- uy[2]*nW);
//
vertex(ux[0]*nW- uy[0]*nW , ux[1]*nW- uy[1]*nW , ux[2]*nW- uy[2]*nW);
vertex(ux[0]*nW- uy[0]*nW+ uz[0]*nL, ux[1]*nW- uy[1]*nW+ uz[1]*nL, ux[2]*nW- uy[2]*nW+ uz[2]*nL);
vertex(-ux[0]*nW- uy[0]*nW+ uz[0]*nL, -ux[1]*nW- uy[1]*nW+ uz[1]*nL, -ux[2]*nW- uy[2]*nW+ uz[2]*nL);
vertex(-ux[0]*nW- uy[0]*nW , -ux[1]*nW- uy[1]*nW , -ux[2]*nW- uy[2]*nW);
//
endShape();
popMatrix();
}

if(automated){
myProcedure.update();
}

//2D interface
beginCamera();
camera();
fill(0,128);
noStroke();
rect(0,height-20,width,20);
endCamera();

fill(255);
textMode(SCREEN);
//myTrace = “FPS: “+(round(frameRate))+” update: “+updateCount;
myTrace = “FPS: “+(round(frameRate))+” update: “+updateCount+” “+month()+”/”+day()+” “+hour()+”:”+minute()+”:”+second();
text(myTrace, 5, height-5);
if(printScreen){
saveFrame(month()+”_”+day()+”_”+hour()+”_”+minute()+”_”+second()+”.png”);
println(“saved”);
printScreen = false;
}
}

class agent{
float[] pos = new float[3];
float radius;
float[] direction = new float[3];

agent(float[] p, float r, float[] d){
pos = p;
radius = r;
direction = d;

}
void update(){
float[] tempV = new float[3];
tempV = unifyVector(direction);
for(int i = 0;i<3;i++){
tempV[i] = tempV[i]*radius*1.6;
pos[i] += tempV[i];
}
//check on collision
//looping through dropArray
boolean collision = true;
int detectTime = 0;
while(collision && detectTime 9){
println(“can’t avoid collision”);
}
}
}

boolean checkCollision(){
boolean out = false;
if(dropArray != null){
for(int i=0;i<dropArray.length;i++){
for(int j=0;j<dropArray[i].rings.length;j++){
float d = getDistance(dropArray[i].rings[j].pos, pos);
if(d< (dropArray[i].rings[j].radius+radius)*0.6){
out = true;
//println(“collision”);
float[] tV = new float[3];
for(int k = 0;k<3;k++){
tV[k] = pos[k] – dropArray[i].rings[j].pos[k];
}
//tV = unifyVector(tV);
if(tV[2] ==0){
tV[2] = 1;
}
else if(tV[2]<0){
tV[2] = -tV[2];
}
tV = unifyVector(tV);
for(int k = 0;k<3;k++){
tV[k] = tV[k]*dropArray[i].rings[j].radius;
pos[k] += tV[k];
//pos[k] += 200;
}
}
}
}
}
return out;
}
}

class agentGroup{
int ID;
int phase = 0;
int[] chase;
int[] avoid;
int tailon;
agent[] agents = new agent[3];
float[] oDirection = new float[3];

agentGroup(agent a1, int id){
agents[0] = a1;
float[] t1 = {
0,0,0 };
float[] t2 = {
0,0,0 };
float[] t3 = {
0,0,0 };
float[] t4 = {
0,0,0 };
agents[1] = new agent(t1, 20, t2);
agents[2] = new agent(t3, 3, t4);
ID = id;
for(int i=0;i<3;i++){
oDirection[i] = agents[0].direction[i];
}
}

void update(){
//adddrop
float[][] p = new float[3][3];
int[] time = new int[3];
float[] r = new float[3];
for(int i=0;i myAgents.length-1){
currentAgent = 0;
}
}

void updateRelation(){
if(phase ==0){//chasing and avoiding
//reset the direction
for(int i=0;i<3;i++){
agents[0].direction[i] = oDirection[i];
}
//chase
if(chase!=null){
for(int i = 0;i<chase.length;i++){
//get the vector between
float[] tV = new float[3];
//float tD = getDistance(myAgents[chase[i]].agents[0].pos, agents[0].pos);
for(int j=0;j<3;j++){
tV[j] = myAgents[chase[i]].agents[0].pos[j] – agents[0].pos[j];
}
tV = unifyVector(tV);
for(int j=0;j<3;j++){
agents[0].direction[j] += (tV[j]/chase.length);
}
}
}
//avoid
if(avoid != null){
for(int i = 0;i<avoid.length;i++){
//get the vector between
float[] tV = new float[3];
//float tD = getDistance(myAgents[avoid[i]].agents[0].pos, agents[0].pos);
for(int j=0;j<3;j++){
tV[j] = agents[0].pos[j] – myAgents[avoid[i]].agents[0].pos[j];
}
tV = unifyVector(tV);
for(int j=0;j<3;j++){
agents[0].direction[j] += (tV[j]/avoid.length);
}
}
}

if(tailon != ID){//put the tail on the top of the other agent
for(int i=0;i<3;i++){
agents[2].pos[i] = myAgents[tailon].agents[0].pos[i];
if(i==2){
agents[2].pos[i] += myAgents[tailon].agents[0].radius;
}
agents[1].pos[i] = agents[2].pos[i] – agents[0].pos[i];
agents[1].pos[i] = agents[1].pos[i]/4;
agents[1].pos[i] += agents[0].pos[i];
}
}
else{//put the tail on the back of the direction
//unify the direction to control the length
float[] tD = unifyVector(agents[0].direction);
for(int i=0;i<2;i++){
agents[2].pos[i] = agents[0].pos[i]-(tD[i]*agents[0].radius*4);
agents[1].pos[i] = agents[0].pos[i]-(tD[i]*agents[0].radius);
}
agents[2].pos[2] = agents[0].pos[2]+agents[0].radius*2;
agents[1].pos[2] = agents[0].pos[2]+agents[0].radius*2;
}
agents[0].update();
}
}
}

class procedure{
procedureDrop[] drops;
int currentDrop = 0;
float[][] history = new float[1][3];

procedure(procedureDrop d){
drops = new procedureDrop[1];
drops[0] = d;
}

void addDrop(procedureDrop d){
procedureDrop[] tempD = new procedureDrop[drops.length+1];
arraycopy(drops, tempD);
tempD[drops.length] = d;
drops = tempD;
}

void update(){
drops[currentDrop].update();
}

void start(){
history[0] = drops[currentDrop].pos[0];
drops[currentDrop].start();
}

void addHistory(float[] p){
float[][] tempH = new float[history.length+1][3];
arraycopy(history, tempH);
tempH[history.length] = p;
history = tempH;
}

void plotHistory(){
fill(0);
noStroke();
for(int i=0;i<history.length;i++){
pushMatrix();
translate(history[i][0],history[i][1],history[i][2]);
sphereDetail(2);
sphere(2);
popMatrix();
}
stroke(128);
noFill();
beginShape();
for(int i=0;imyProcedure.currentDrop +1){
myProcedure.currentDrop ++;
myProcedure.drops[myProcedure.currentDrop].start();
}
}
currentTime = 0;
}
//animate the createRing to next step
if(!ended){
if(currentStep>0){

createX = pos[currentStep-1][0] + (pos[currentStep][0] – pos[currentStep-1][0])*currentTime/timer[currentStep];
createY = pos[currentStep-1][1] + (pos[currentStep][1] – pos[currentStep-1][1])*currentTime/timer[currentStep];
createZ = pos[currentStep-1][2] + (pos[currentStep][2] – pos[currentStep-1][2])*currentTime/timer[currentStep];

createR = radius[currentStep-1] + (radius[currentStep] – radius[currentStep-1])*currentTime/timer[currentStep];

//check the distance between the last ring
int index1= dropArray.length-1;
int index2= dropArray[index1].rings.length-1;
float d = dist(dropArray[index1].rings[index2].pos[0],dropArray[index1].rings[index2].pos[1],dropArray[index1].rings[index2].pos[2], createX, createY, createZ);
if(d > dropArray[index1].rings[index2].radius+createR && d>meshMin){
dropArray[dropArray.length-1].addRing(createX,createY,createZ, createXD, createY, createZD,createR);
}
}

currentTime++;
if(currentTime%10 ==0){
float[] tH = {
createX, createY, createZ };
myProcedure.addHistory(tH);
}
}
}
}
}

class gDrop{
//float[] pos = new float[3];
int ID;
gRing[] rings;
int solid = 0;
gRing capStart;
gRing capEnd;
gParticle[] cap = new gParticle[2];

gDrop(int id, float x1, float y1, float z1, float x2, float y2, float z2, float r){
ID = id;
int[] tempid = {
id, 0 };
int[] tempid2 = {
id, -1 };
rings = new gRing[1];
//unify direction
float[] dir = {
x2,y2,z2 };
dir = unifyVector(dir);
rings[0] = new gRing(tempid, x1, y1, z1, dir[0], dir[1], dir[2], r);
capStart = new gRing(tempid2, x1 – dir[0]*(r/2), y1- dir[1]*(r/2), z1- dir[2]*(r/2), x2, y2, z2, r/2);
}

void addRing(float x1, float y1, float z1, float x2, float y2, float z2, float r){
int[] tempid = {
ID, rings.length };
gRing tempRing = new gRing(tempid, x1, y1, z1, x2, y2, z2, r);
gRing[] tempArray = new gRing[rings.length+1];
arraycopy(rings, tempArray);
tempArray[rings.length] = tempRing;
rings = tempArray;
}

void deleteRing(){
gRing[] tempArray = new gRing[rings.length-1];
arraycopy(rings,0, tempArray,0,rings.length-1);
rings = tempArray;
}

void update(){
solid = 0;
for(int i = 0; i0){
if(rings[i].liquefaction !=0){
rings[i].update(true);
}
else{
rings[i].update(false);
solid++;
}
}
else{
rings[i].update(false);
solid++;
}
}
if(capStart !=null){
capStart.update(false);
}
}

void plot(boolean particleDisplay, boolean meshDisplay){
for(int i = 0; i<rings.length; i++){
if(particleDisplay){
rings[i].plot();
}
if(meshDisplay){
stroke(0);
strokeWeight(1.2);
}
else{
noStroke();
}
if(i<rings.length-1){
for(int j = 0; jmeshDensity-1){
t=0;
}
if(toggleTransparency){
drawMesh(rings[i].particles[j].pos, rings[i+1].particles[j].pos, rings[i+1].particles[t].pos, rings[i].particles[t].pos, rings[i+1].liquefaction, rings[i].liquefaction, 128);
}
else{
drawMesh(rings[i].particles[j].pos, rings[i+1].particles[j].pos, rings[i+1].particles[t].pos, rings[i].particles[t].pos, 0, 0, 255);
}
}
}
}
if(meshDisplay){
stroke(0,128);
}
//draw the starting and ending cap
for(int j = 0; jmeshDensity-1){
t=0;
}
if(toggleTransparency){
drawMesh(capStart.particles[j].pos, rings[0].particles[j].pos, rings[0].particles[t].pos, capStart.particles[t].pos, capStart.liquefaction, rings[0].liquefaction,128);
drawCap(capStart.particles[j].pos, capStart.particles[t].pos, capStart.pos, capStart.liquefaction,128);
drawCap(rings[rings.length-1].particles[j].pos, rings[rings.length-1].particles[t].pos, rings[rings.length-1].pos, rings[rings.length-1].liquefaction,128);
}
else{
drawMesh(capStart.particles[j].pos, rings[0].particles[j].pos, rings[0].particles[t].pos, capStart.particles[t].pos, 0, 0,255);
drawCap(capStart.particles[j].pos, capStart.particles[t].pos, capStart.pos, 0,255);
drawCap(rings[rings.length-1].particles[j].pos, rings[rings.length-1].particles[t].pos, rings[rings.length-1].pos, 0,255);
}
}
}

void drawMesh(float[] pos1, float[] pos2, float[] pos3, float[] pos4, float l1, float l2, float tr){
beginShape(QUADS);
fill(255, ((1-l1)*255), ((1-l1)*255), tr);
vertex(pos1[0], pos1[1], pos1[2]);
fill(255, ((1-l2)*255), ((1-l2)*255), tr);
vertex(pos2[0], pos2[1], pos2[2]);
vertex(pos3[0], pos3[1], pos3[2]);
fill(255, ((1-l1)*255), ((1-l1)*255), tr);
vertex(pos4[0], pos4[1], pos4[2]);
endShape(QUADS);
}

void drawCap(float[] pos1, float[] pos2, float[] pos3, float l1, float tr){
beginShape(TRIANGLES);
fill(255, ((1-l1)*255), ((1-l1)*255), tr);
vertex(pos1[0], pos1[1], pos1[2]);
vertex(pos3[0], pos3[1], pos3[2]);
vertex(pos2[0], pos2[1], pos2[2]);
endShape(TRIANGLES);
}
}

class gRing{
int[] ID;
float[] pos = new float[3];
float[] direction = new float[3];
float[] motion = new float[3];
float radius;
float liquefaction = 1;
float[][] myAxis = new float[3][3];
gParticle[] particles = new gParticle[meshDensity];

gRing(int[] id, float x1, float y1, float z1, float x2, float y2, float z2, float r){
ID = id;
pos[0] = x1;
pos[1] = y1;
pos[2] = z1;
direction[0] = x2;
direction[1] = y2;
direction[2] = z2;
motion[0] =0;
motion[1] =0;
motion[2] =0;
radius = r;

for(int i =0; i0){
for(int i=0;i<3;i++){
myAxis[i] = unifyVector(dropArray[ID[0]].rings[ID[1]-1].myAxis[i]);
}
float dd = getDistance(createArray3(0,0,0), myAxis[2]);
//println(“using previous axis: “+myAxis[2][0]+”, “+dropArray[ID[0]].rings[ID[1]-1].myAxis[2][0]);
//println(“using previous axis: “+dd);
}
else{
//println(“generated axis”);
myAxis[0] = createArray3(1,0,0);
myAxis[1] = createArray3(0,1,0);
myAxis[2] = createArray3(0,0,-1);
}
}
else{
myAxis[0] = unifyVector(crossProduct(myAxis[2], t));
myAxis[1] = unifyVector(crossProduct(myAxis[2], myAxis[0]));
}

for(int i =0; i<meshDensity; i++){
float[] temp2 = new float[3];
for(int j=0; j0){
if(move){
//movement
float[] tempD = new float[3];
//add the inertia

//add the garvity
tempD[2] -= gravity;
//the force with lastRing
if(ID[1] >0){
float distanceT = dropArray[ID[0]].rings[ID[1]-1].radius+dropArray[ID[0]].rings[ID[1]].radius;
if(distanceT<meshMin){
distanceT = meshMin;
}
float[] tempDD = getMaintainForce(distanceT, dropArray[ID[0]].rings[ID[1]].pos, dropArray[ID[0]].rings[ID[1]-1].pos);
for(int i=0; i<3;i++){
tempD[i] += tempDD[i];
}
}
//the force with nextRing
if(ID[1] <dropArray[ID[0]].rings.length-1){
float distanceT = dropArray[ID[0]].rings[ID[1]+1].radius+dropArray[ID[0]].rings[ID[1]].radius;
if(distanceT<meshMin){
distanceT = meshMin;
}
float[] tempDD = getMaintainForce(distanceT, dropArray[ID[0]].rings[ID[1]].pos, dropArray[ID[0]].rings[ID[1]+1].pos);
for(int i=0; i<3;i++){
tempD[i] += tempDD[i];
}
}

//adhere to solid surface
//check the distance between all existing rings
for(int i=0; i<dropArray.length;i++){
if(i != ID[0]){//check if its self
for(int j=0;j<dropArray[i].rings.length;j++){
float d = getDistance(pos, dropArray[i].rings[j].pos);
if(d < radius + dropArray[i].rings[j].radius){
liquefaction = 0;
}
}
}
}
//unify the vector
tempD = unifyVector(tempD);
//move the vector
for(int i=0;i<3;i++){
pos[i] += tempD[i]*liquefaction*speed;
}
if(pos[2] 0){//if its not the first ring
float[] dArray = new float[3];
for(int i=0;i<3;i++){
dArray[i] = pos[i] – dropArray[ID[0]].rings[ID[1]-1].pos[i];
}
dArray = unifyVector(dArray);
//direction = dArray;
for(int i=0;i<3;i++){
tempD[i] += dArray[i];
}
ringNum++;
}
if(ID[1] ID[1]+1){
float[] dArray = new float[3];
for(int i=0;i<3;i++){
dArray[i] = dropArray[ID[0]].rings[ID[1]+1].pos[i] – pos[i];
}
dArray = unifyVector(dArray);
//direction = dArray;
for(int i=0;i<3;i++){
tempD[i] += dArray[i];
}
ringNum++;
}
if(ID[1] == -1){//if its the capstart ring
//get the new position, direction, r
float[] dArray = unifyVector(dropArray[ID[0]].rings[0].direction);
float r = dropArray[ID[0]].rings[0].radius/2;
for(int i=0;i<3;i++){
pos[i] = dropArray[ID[0]].rings[0].pos[i] – dArray[i]*r;
}
radius = r;
dArray = unifyVector(dArray);
//direction = dArray;
for(int i=0;i0){
direction = unifyVector(tempD);
}
/*direction = unifyVector(direction);
if(direction[0]==0 && direction[1] ==0){
println(“modify direction”);
if(ID[1]>0){
direction = unifyVector(dropArray[ID[0]].rings[ID[1]-1].direction);
liquefaction = 0;
}
}*/
//update the particles position
updateParticles();
}

void updateManually(float x1, float y1, float z1, float x2, float y2, float z2, float r){
pos[0] = x1;
pos[1] = y1;
pos[2] = z1;
direction[0] = x2;
direction[1] = y2;
direction[2] = z2;
radius = r;
updateParticles();
}

float[] getMaintainForce(float originDist, float[] sp, float[] p){
float distance = getDistance(sp, p);
distance -= originDist;
float[] out = new float[3];
for(int i =0;i<3;i++){
out[i] = sp[i] – p[i];
}
out = unifyVector(out);
for(int i =0;i<3;i++){
out[i] = out[i]*distance*maintain*-1;
}
return out;
}

void plot(){
if(toggleSphereDisplay){
fill(255,128);
noStroke();
sphereDetail(12);
pushMatrix();
translate(pos[0], pos[1], pos[2]);
sphere(radius);
//draw the direction
stroke(255,0,0);
line(0,0,0,direction[0]*20,direction[1]*20,direction[2]*20);
popMatrix();
//draw the line to first particle
stroke(0,255,0);
line(pos[0],pos[1],pos[2],particles[0].pos[0],particles[0].pos[1],particles[0].pos[2]);
//draw the line to 90 degree particle
stroke(0,0,255);
int ii = round(meshDensity/4);
line(pos[0],pos[1],pos[2],particles[ii].pos[0],particles[ii].pos[1],particles[ii].pos[2]);
}
for(int j = 0; j<meshDensity; j++){
noStroke();
particles[j].plot();
}
}
}

class gParticle{
int[] ID;
float[] pos = new float[3];

gParticle(int[] id, float x, float y, float z){
ID = id;
pos[0] = x;
pos[1] = y;
pos[2] = z;
}

void plot(){
pushMatrix();
translate(pos[0], pos[1], pos[2]);
fill(255);
sphereDetail(4);
sphere(particleSize);
popMatrix();
}
}

float[] unifyVector(float[] v){
float[] zero = {
0,0,0 };
float[] out = new float[3];
float d = getDistance(zero, v);
for(int i =0; i<3; i++){
out[i] = v[i]/d;
}
return out;
}

float getDistance(float[] x1, float[] x2){
float temp = 0;
for(int i = 0; i<x1.length; i++){
float temp2 = x1[i] – x2[i];
temp2 = temp2*temp2;
temp += temp2;
}
temp = sqrt(temp);
return temp;
}

void startDrop(){
int tempID;
if(dropArray == null){
tempID = 0;
dropArray = new gDrop[1];
}
else{
tempID = dropArray.length;
gDrop[] tempArray = new gDrop[dropArray.length+1];
arraycopy(dropArray, tempArray);
dropArray = tempArray;
}
dropArray[tempID] = new gDrop(tempID, createX,createY,createZ,createXD,createYD,createZD,createR);
working = true;
}

void endDrop(){
dropArray[dropArray.length-1].addRing(createX,createY,createZ, createXD, createYD, createZD,createR);
working = false;
}

float[] crossProduct(float[] v1, float[] v2){
//A x B =
float[] out = new float[3];
out[0] = v1[1]*v2[2] – v1[2]*v2[1];
out[1] = v1[2]*v2[0] – v1[0]*v2[2];
out[2] = v1[0]*v2[1] – v1[1]*v2[0];
if(out[0] ==0 && out[1]==0 && out[2]==0){
println(“crossproduct error!!”);
}
return out;
}

float[] createArray3(float x, float y, float z){
float[] out = {
x,y,z };
return out;
}

void mousePressed(){
mouseXX = mouseX;
mouseYY = mouseY;
cameraRXX = cameraRX;
cameraRZZ = cameraRZ;
cameraTXX = cameraTX;
cameraTZZ = cameraTZ;
cameraYY = cameraY;
}

void mouseDragged(){
if(mouseButton ==LEFT){
if (keyPressed == true){
if (key == CODED) {
if(keyCode == ALT){
//println(“mouse”);
cameraRZ = cameraRZZ – (mouseX – mouseXX)/2;
cameraRX = cameraRXX – (mouseY – mouseYY)/2;
}
else if(keyCode == CONTROL){
cameraTZ = cameraTZZ – (mouseY – mouseYY)/2;
//cameraTX = cameraTXX + (mouseX – mouseXX)/2;
}
}
}
}
if(mouseButton == RIGHT){
cameraY = cameraYY – (mouseY – mouseYY)*5;
}
}

void keyPressed() {
if(key == ‘z’){
cameraTZ = 0;
}
else if(key == ‘p’){
if(!automated){
myAgents[0].update();
//myProcedure.start();
}
else{
stopped = true;
}
}
else if(key == ‘o’){
toggleParticleDisplay = !toggleParticleDisplay;
}
else if(key ==’i’){
toggleMeshDisplay = !toggleMeshDisplay;
}
else if(key ==’u’){
toggleSphereDisplay = !toggleSphereDisplay;
}
else if(key ==’l’){
toggleShadeDisplay = !toggleShadeDisplay;
}
else if(key ==’k’){
toggleHistoryDisplay = !toggleHistoryDisplay;
}
else if(key ==’j’){
toggleTransparency = !toggleTransparency;
}
else if(key == ‘c’){
creating = !creating;
}
else if(key == ‘m’){
exportMaya = true;

}
else if(key == ‘n’){
printScreen = true;
}

}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s