Help with integrating sliders!!!
in
Contributed Library Questions
•
2 years ago
Hi guys,
I'd really appreciate some help with my project.
Does anyone know why my slider controls aren't working how I want? Basically I have sliders for the number of surface_attractors, interstitial_attractors, x_particles and y_particles and I want the number of each of these to change as per their respective sliders.
The x_particles and y_particles seem to be sort of working although if you move the slider above the original variable input you get an error. I also want the 'fixed' particles, shown in blue, to move as the grid is changes in the x and y direction so their position at the boundary of the surface (in the x direction) remains.
I also want the number of attractors to change as per the sliders but I cannot get that working at all! I realise that my problems come from the fact that the arraylists holding the attractors are initialised in the setup via mesh.init(), so cannot be updated. How can I amend my script to accomodate this?
I know this might be quite a lot of work and the script is quite long (and probably messy!!), but I'd really appreciate some pointers. Hopefully i've explained myself. I have posted the script below.
Basically what I'm trying to make is 2 undulating surfaces, the overall size of which can be changed via sliders, which respond to attractors, the amount of which can again be varied.
Cheers guys, and thanks for the help!!
// IMPORT EXTERNAL LIBRARIES
import processing.pdf.*;
import processing.opengl.*; // openGL library
import peasy.*; // the camera library
import controlP5.*; // the interface library
/*------------------------------------------------------------------
*** GLOBAL VARIABLES ***
------------------------------------------------------------------*/
PMatrix3D currCameraMatrix;
PGraphics3D g3;
// camera
PeasyCam theCamera;
boolean record = false;
boolean export = false;
// inteface
ControlP5 theGUI;
ControlWindow theGUIWindow;
// particle variables
int X_PARTICLES = 28;
int Y_PARTICLES = 70;
// x and y increments
int xInc = 12;
int yInc = 12;
// environment
int bBoxX = X_PARTICLES * xInc;
int bBoxY = Y_PARTICLES * yInc;
int bBoxZ = 100;
// spring variables
//PVector gravity = new PVector(0, 0, 0);
float SPRING_REST_LENGTH = 8.0; // the length a spring is at rest
float SPRING_DAMPING_FORCE = 0.3; // equiv hydraulic damping of a piston
// ArrayLists of attractors
ArrayList attList1 = new ArrayList();
ArrayList attList2 = new ArrayList();
ArrayList attList3 = new ArrayList();
int SURFACE_ATTRACTORS = 20;
int INTERSTITIAL_ATTRACTORS = 2;
float meshHeight = bBoxZ + bBoxX;
float midAttHeight = bBoxZ + ((meshHeight - bBoxZ)/2);
float attRange = midAttHeight - bBoxZ;
// declare meshes
Mesh bottomMesh;
Mesh topMesh;
/*------------------------------------------------------------------
*** GLOBAL SETUP ***
------------------------------------------------------------------*/
void setup() {
//----------general
size(1200, 700, OPENGL);
smooth();
g3 = (PGraphics3D)g;
//----------make the camera
theCamera = new PeasyCam(this, bBoxX*1.65);
theCamera.lookAt(bBoxX/2, bBoxY/2, bBoxZ/2);
//----------setup interface
theGUI = new ControlP5(this);
theGUI.setColorLabel(color(0, 0, 0)); //Text Color
Controller slider_SPRING_REST_LENGTH = theGUI.addSlider( "SPRING_REST_LENGTH", 1.0, 20.0, SPRING_REST_LENGTH, 15, 15, 200, 13 );
Controller slider_SPRING_DAMPING_FORCE = theGUI.addSlider( "SPRING_DAMPING_FORCE", 0.1, 2.0, SPRING_DAMPING_FORCE, 15, 40, 200, 13 );
Controller slider_SURFACE_ATTRACTORS = theGUI.addSlider( "SURFACE_ATTRACTORS", 0, 30, SURFACE_ATTRACTORS, 15, 65, 200, 13 );
Controller slider_INTERSTITIAL_ATTRACTORS = theGUI.addSlider( "INTERSTITIAL_ATTRACTORS", 0, 6, INTERSTITIAL_ATTRACTORS, 15, 90, 200, 13 );
Controller slider_X_PARTICLES = theGUI.addSlider( "X_PARTICLES", 0, 40, X_PARTICLES, 15, 115, 200, 13 );
Controller slider_Y_PARTICLES = theGUI.addSlider( "Y_PARTICLES", 0, 100, Y_PARTICLES, 15, 140, 200, 13 );
theGUI.setAutoDraw(false);
//----------make mesh
initMesh();
}
/*------------------------------------------------------------------
*** GLOBAL CONTINUOUS DRAW ***
------------------------------------------------------------------*/
void draw() {
if (theGUI.window(this).isMouseOver()) {
theCamera.setActive(false);
}
else {
theCamera.setActive(true);
}
//----------general
background(250);
/*strokeWeight(4);
stroke(0);
box(200,200,SURFACE_ATTRACTORS*2);*/
hint(ENABLE_DEPTH_TEST);
if (record) {
beginRaw(PDF, "3D####.pdf");
}
//----------draw meshes
topMesh.createMesh();
topMesh.createSprings();
topMesh.createFaces();
bottomMesh.createMesh();
bottomMesh.createSprings();
bottomMesh.createFaces();
//----------draw attractors
for (int i = 0; i < attList1.size(); ++i) {
Attractor myAtt = (Attractor) attList1.get(i);
myAtt.run();
myAtt.display();
}
for (int i = 0; i < attList2.size(); ++i) {
Attractor myAtt = (Attractor) attList2.get(i);
myAtt.run();
myAtt.display();
}
for (int i = 0; i < attList3.size(); ++i) {
Attractor myAtt = (Attractor) attList3.get(i);
myAtt.run();
myAtt.display();
}
if (export) {
//topMesh.exportToTxt(1);
//bottomMesh.exportToTxt(2);
}
if (record) {
endRaw();
record = false;
}
// makes the gui stay on top of elements
// drawn before.
hint(DISABLE_DEPTH_TEST);
gui();
}
/*-------------------------------------------------------------
*** MAKE PARTICLES, SPRINGS AND ATTRACTORS ***
--------------------------------------------------------------*/
void initMesh() {
bottomMesh = new Mesh(bBoxZ, attList1, attList3);
topMesh = new Mesh(meshHeight, attList2, attList3);
}
void keyPressed() {
if (key == 'p' || key == 'P') {
record = true;
export = true;
}
}
void gui() {
currCameraMatrix = new PMatrix3D(g3.camera);
camera();
theGUI.draw();
g3.camera = currCameraMatrix;
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Attractor {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
PVector aPos;
PVector aVel;
float pSize;
int range;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Attractor(PVector aPos_, PVector aVel_, int range_) {
// assign all the class variables
aPos = aPos_;
aVel = aVel_;
pSize = 10.0;
range = range_;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
void run() {
move();
bounce();
}
void move() {
aPos.add(aVel);
}
void bounce() {
if (aPos.x > bBoxX) {
aVel.x *= -1;
}
if (aPos.x < 0) {
aVel.x *= -1;
}
if (aPos.y > bBoxY-range) {
aVel.y *= -1;
}
if (aPos.y < range) {
aVel.y *= -1;
}
}
void display() {
strokeWeight(0.25);
stroke(100);
//point(aPos.x, aPos.y, aPos.z);
line(aPos.x-pSize, aPos.y, aPos.z, aPos.x+pSize, aPos.y, aPos.z);
line(aPos.x, aPos.y-pSize, aPos.z, aPos.x, aPos.y+pSize, aPos.z);
line(aPos.x, aPos.y, aPos.z-pSize, aPos.x, aPos.y, aPos.z+pSize);
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Face {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
// declare all the class variables
Particle p00;
Particle p01;
Particle p02;
Particle p03;
float tmpMeshHeight;
float Dist1;
float Dist2;
float DistA;
float DistB;
float DistC;
float colValG;
float colValB;
float colValR;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Face (Particle INPUT_00, Particle INPUT_01, Particle INPUT_02, Particle INPUT_03, float meshHeight_) {
// assign all the class variables
p00 = INPUT_00;
p01 = INPUT_01;
p02 = INPUT_02;
p03 = INPUT_03;
tmpMeshHeight = meshHeight_;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
//----------Draw myself
void showMe() {
Dist1 = dist(p00.pos.x, p00.pos.y, tmpMeshHeight, p00.pos.x, p00.pos.y, midAttHeight);
Dist2 = dist(p00.pos.x, p00.pos.y, p00.pos.z, p00.pos.x, p00.pos.y, tmpMeshHeight);
DistA = dist(p00.pos.x, p00.pos.y, p00.pos.z, p00.pos.x, p00.pos.y, tmpMeshHeight);
DistB = dist(p00.pos.x, p00.pos.y, (tmpMeshHeight+midAttHeight)/2, p00.pos.x, p00.pos.y, p00.pos.z);
DistC = dist(p00.pos.x, p00.pos.y, midAttHeight, p00.pos.x, p00.pos.y, p00.pos.z);
if (Dist2 < Dist1/4) {
// green fades in
colValG = map(DistA, 0, Dist1/4, 0, 255);
fill(0, colValG, 255);
}
else if (Dist2 < Dist1/2) {
// blue fades out
colValB = map(DistB, 0, Dist1/4, 0, 255);
fill(0, 255, colValB);
}
else if (Dist2 < Dist1/2 + Dist1/4) {
// red fades in
colValR = map(DistB, 0, Dist1/4, 0, 255);
fill(colValR, 255, 0);
}
else {
//green fades out
colValG = map(DistC, 0, Dist1/4, 0, 255);
fill(255, colValG, 0);
}
/*else if (Dist1 < (Dist3/2 + Dist3/4)) {
// red fades in
colValR = map(Dist1, (Dist3/2 + Dist3/4), Dist3/4, 0, 255);
fill(colValR, 255, 0);
}
else {
// green fades out
colValG = map(Dist2, 0, (Dist3/2 + Dist3/4), 0, 255);
fill(255, colValG, 0);
}*/
noStroke();
beginShape();
vertex(p00.pos.x, p00.pos.y, p00.pos.z);
vertex(p01.pos.x, p01.pos.y, p01.pos.z);
vertex(p02.pos.x, p02.pos.y, p02.pos.z);
vertex(p03.pos.x, p03.pos.y, p03.pos.z);
endShape();
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Mesh {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
float tmpMeshHeight;
Particle[][] particleList;
ArrayList springList;
Spring s0, s1;
ArrayList faceList;
Face f0;
ArrayList tmpAttList1;
ArrayList tmpAttList2;
Attractor tmpAtt;
PrintWriter output;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Mesh(float meshHeight_, ArrayList attList_, ArrayList attList2_) {
tmpMeshHeight = meshHeight_;
particleList = new Particle[X_PARTICLES][Y_PARTICLES];
springList = new ArrayList();
faceList = new ArrayList();
tmpAttList1 = attList_;
tmpAttList2 = attList2_;
//-----initialise particles
for (int i=0; i < X_PARTICLES; ++i) {
for (int j=0; j < Y_PARTICLES; ++j) {
// make a vector
PVector tmpPos = new PVector(i*xInc, j*yInc, tmpMeshHeight);
// make a particle
Particle newP = new Particle(tmpPos, tmpAttList1, tmpAttList2);
// fix perimeter particles
if ( (i < X_PARTICLES && j==0) || (i < X_PARTICLES && j==Y_PARTICLES-1) ) {
newP.fixMe();
}
// store the particle in our list
particleList[i][j] = newP;
}
}
//-----initialise springs
for (int i=0; i < X_PARTICLES; ++i) {
for (int j=0; j < Y_PARTICLES; ++j) {
if ( i>0 ) {
s0 = new Spring( particleList[i][j], particleList[i-1][j] );
springList.add(s0);
particleList[i][j].addSpring(s0);
particleList[i-1][j].addSpring(s0);
}
if ( j>0 ) {
s1 = new Spring( particleList[i][j], particleList[i][j-1] );
springList.add(s1);
particleList[i][j].addSpring(s1);
particleList[i][j-1].addSpring(s1);
}
}
}
//-----initialise faces
for (int i=0; i<X_PARTICLES; ++i) {
for (int j=0; j<Y_PARTICLES; ++j) {
if (i>0 && j>0) {
f0 = new Face( particleList[i][j], particleList[i][j-1], particleList[i-1][j-1], particleList[i-1][j], tmpMeshHeight );
faceList.add(f0);
}
}
}
// print how many springs we made
println("Number of springs " + springList.size() );
//-----initialise surface attractors
for (int i = 0; i < SURFACE_ATTRACTORS; ++i) {
//if (i < SURFACE_ATTRACTORS) {
PVector aPos = new PVector(random(0, bBoxX), random(150, bBoxY-150), tmpMeshHeight);
PVector aVel = new PVector(random(0.5, 2.5), random(0.5, 2.5), 0);
tmpAtt = new Attractor(aPos, aVel, 20);
tmpAttList1.add(tmpAtt);
}
//-----initialise middle attractors
for (int i = 0; i < INTERSTITIAL_ATTRACTORS; ++i) {
//if (i < SURFACE_ATTRACTORS) {
PVector aPos = new PVector(random(0, bBoxX), random(150, bBoxY-150), midAttHeight+30);
PVector aVel = new PVector(random(1, 2), random(1, 2), 0);
tmpAtt = new Attractor(aPos, aVel, 150);
tmpAttList2.add(tmpAtt);
}
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
void createMesh() {
//----------update particle physics
for (int i=0; i<X_PARTICLES; ++i) {
for (int j=0; j<Y_PARTICLES; ++j) {
particleList[i][j].solveForce();
}
}
//----------update particle positions
for (int i=0; i<X_PARTICLES; ++i) {
for (int j=0; j<Y_PARTICLES; ++j) {
particleList[i][j].update();
}
}
}
void createSprings() {
for (int i=0; i<springList.size(); i++) {
// get a spring from the arraylist
Spring currS = (Spring) springList.get(i);
currS.showMe();
}
}
void createFaces() {
for (int i=0; i<faceList.size(); i++) {
// get a spring from the arraylist
Face currF = (Face) faceList.get(i);
//currF.showMe();
}
}
void exportToTxt(int num_) {
int num = num_;
output = createWriter("data/points" + num + ".txt");
for (int i = 0; i < X_PARTICLES; i++) {
for (int j = 0; j < Y_PARTICLES; j++) {
output.println (particleList[i][j].pos.x + "," + particleList[i][j].pos.y + "," + particleList[i][j].pos.z);
}
}
output.flush();
output.close();
println("points have been exported");
exit();
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Particle {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
int pID;
PVector pos;
PVector vel;
PVector acc;
float pSize;
boolean pFixed;
ArrayList conSprings = new ArrayList();
ArrayList tmpAttList1;
ArrayList tmpAttList2;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Particle(PVector STARTPOS, ArrayList attList1_, ArrayList attList2_) {
// assign all the class variables
pos = STARTPOS;
vel = new PVector();
acc = new PVector();
pSize = 10.0;
pID = 0;
pFixed = false;
tmpAttList1 = attList1_;
tmpAttList2 = attList2_;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
//----------MOVE AND DRAW TO SCREEN
void update() {
if (pFixed==false) {
updatePos();
attraction();
attractionB();
}
showMe();
}
//----------SOLVE THE SPRINGS
void solveForce() {
if (pFixed==false) {
Particle otherP;
PVector sumForces = new PVector();
//sumForces.add(gravity);
sumForces.add(acc);
// loop thru our connections
for (int i = 0; i<conSprings.size(); ++i) {
// get a spring
Spring s = (Spring) conSprings.get(i);
// get other end of spring
if ( s.p00 == this ) {
otherP = s.p01;
}
else {
otherP = s.p00;
}
// calculate the push/pull of spring
PVector vecBet = PVector.sub(otherP.pos, pos);
float currLen = vecBet.mag();
float desiredLen = currLen-SPRING_REST_LENGTH;
vecBet.normalize();
vecBet.mult(desiredLen/2);
// add this force to our sum of forces
sumForces.add(vecBet);
}
// apply a damping to the force
sumForces.mult(SPRING_DAMPING_FORCE);
// add the resultant force to our vel
vel.add(sumForces);
}
}
void updatePos() {
vel.limit(2);
pos.add(0, 0, vel.z);
acc = new PVector(0, 0, 0);
/*pos.add(vel); // move the particle
vel.mult(0); */ // reset the vel for next time
}
//----------A typical class function!!
void showMe() {
// set appearance
noFill();
if (pFixed==true) {
// draw as 'FIXED' geometry
strokeWeight(0.25);
stroke(0, 0, 250);
line(pos.x-pSize, pos.y, pos.z, pos.x+pSize, pos.y, pos.z);
line(pos.x, pos.y-pSize, pos.z, pos.x, pos.y+pSize, pos.z);
line(pos.x, pos.y, pos.z-pSize, pos.x, pos.y, pos.z+pSize);
}
else {
// draw as 'FREE' geometry
strokeWeight(0.25);
stroke(140);
line(pos.x-pSize/2, pos.y, pos.z, pos.x+pSize/2, pos.y, pos.z);
line(pos.x, pos.y-pSize/2, pos.z, pos.x, pos.y+pSize/2, pos.z);
line(pos.x, pos.y, pos.z-pSize/2, pos.x, pos.y, pos.z+pSize/2);
}
}
//----------Make the particle fixed / free
void fixMe() {
pFixed=true;
}
void freeMe() {
pFixed=false;
}
//----------Add a spring to my list of springs
void addSpring(Spring S) {
// store this spring
conSprings.add(S);
}
void attraction() {
PVector steer = new PVector();
int count = 0;
for (int i = 0; i < tmpAttList1.size(); i++) {
// get a PVector from the list
Attractor tmpAtt = (Attractor) tmpAttList1.get(i);
float distance = PVector.dist(tmpAtt.aPos, pos);
if (distance > 0 && distance < attRange+21) {
PVector vecBetween = PVector.sub(tmpAtt.aPos, pos);
// get the length of the vector
vecBetween.normalize();
steer.add(vecBetween);
count++;
}
}
if (count > 0) {
steer.mult(1.0/count);
}
steer.mult(2);
acc.add(steer);
}
void attractionB() {
PVector steer = new PVector();
int count = 0;
for (int i = 0; i < tmpAttList2.size(); i++) {
// get a PVector from the list
Attractor tmpAtt = (Attractor) tmpAttList2.get(i);
float distance = PVector.dist(tmpAtt.aPos, pos);
if (distance > 0 && distance < attRange+31) {
PVector vecBetween = PVector.sub(tmpAtt.aPos, pos);
// get the length of the vector
vecBetween.normalize();
steer.add(vecBetween);
count++;
}
}
if (count > 0) {
steer.mult(1.0/count);
}
steer.mult(2);
acc.add(steer);
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Spring {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
// declare all the class variables
Particle p00;
Particle p01;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Spring (Particle INPUT_00, Particle INPUT_01) {
// assign all the class variables
p00 = INPUT_00;
p01 = INPUT_01;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
//----------Draw myself
void showMe() {
stroke(180);
strokeWeight(0.5);
noFill();
line(
p00.pos.x, p00.pos.y, p00.pos.z,
p01.pos.x, p01.pos.y, p01.pos.z
);
}
}
I'd really appreciate some help with my project.
Does anyone know why my slider controls aren't working how I want? Basically I have sliders for the number of surface_attractors, interstitial_attractors, x_particles and y_particles and I want the number of each of these to change as per their respective sliders.
The x_particles and y_particles seem to be sort of working although if you move the slider above the original variable input you get an error. I also want the 'fixed' particles, shown in blue, to move as the grid is changes in the x and y direction so their position at the boundary of the surface (in the x direction) remains.
I also want the number of attractors to change as per the sliders but I cannot get that working at all! I realise that my problems come from the fact that the arraylists holding the attractors are initialised in the setup via mesh.init(), so cannot be updated. How can I amend my script to accomodate this?
I know this might be quite a lot of work and the script is quite long (and probably messy!!), but I'd really appreciate some pointers. Hopefully i've explained myself. I have posted the script below.
Basically what I'm trying to make is 2 undulating surfaces, the overall size of which can be changed via sliders, which respond to attractors, the amount of which can again be varied.
Cheers guys, and thanks for the help!!
// IMPORT EXTERNAL LIBRARIES
import processing.pdf.*;
import processing.opengl.*; // openGL library
import peasy.*; // the camera library
import controlP5.*; // the interface library
/*------------------------------------------------------------------
*** GLOBAL VARIABLES ***
------------------------------------------------------------------*/
PMatrix3D currCameraMatrix;
PGraphics3D g3;
// camera
PeasyCam theCamera;
boolean record = false;
boolean export = false;
// inteface
ControlP5 theGUI;
ControlWindow theGUIWindow;
// particle variables
int X_PARTICLES = 28;
int Y_PARTICLES = 70;
// x and y increments
int xInc = 12;
int yInc = 12;
// environment
int bBoxX = X_PARTICLES * xInc;
int bBoxY = Y_PARTICLES * yInc;
int bBoxZ = 100;
// spring variables
//PVector gravity = new PVector(0, 0, 0);
float SPRING_REST_LENGTH = 8.0; // the length a spring is at rest
float SPRING_DAMPING_FORCE = 0.3; // equiv hydraulic damping of a piston
// ArrayLists of attractors
ArrayList attList1 = new ArrayList();
ArrayList attList2 = new ArrayList();
ArrayList attList3 = new ArrayList();
int SURFACE_ATTRACTORS = 20;
int INTERSTITIAL_ATTRACTORS = 2;
float meshHeight = bBoxZ + bBoxX;
float midAttHeight = bBoxZ + ((meshHeight - bBoxZ)/2);
float attRange = midAttHeight - bBoxZ;
// declare meshes
Mesh bottomMesh;
Mesh topMesh;
/*------------------------------------------------------------------
*** GLOBAL SETUP ***
------------------------------------------------------------------*/
void setup() {
//----------general
size(1200, 700, OPENGL);
smooth();
g3 = (PGraphics3D)g;
//----------make the camera
theCamera = new PeasyCam(this, bBoxX*1.65);
theCamera.lookAt(bBoxX/2, bBoxY/2, bBoxZ/2);
//----------setup interface
theGUI = new ControlP5(this);
theGUI.setColorLabel(color(0, 0, 0)); //Text Color
Controller slider_SPRING_REST_LENGTH = theGUI.addSlider( "SPRING_REST_LENGTH", 1.0, 20.0, SPRING_REST_LENGTH, 15, 15, 200, 13 );
Controller slider_SPRING_DAMPING_FORCE = theGUI.addSlider( "SPRING_DAMPING_FORCE", 0.1, 2.0, SPRING_DAMPING_FORCE, 15, 40, 200, 13 );
Controller slider_SURFACE_ATTRACTORS = theGUI.addSlider( "SURFACE_ATTRACTORS", 0, 30, SURFACE_ATTRACTORS, 15, 65, 200, 13 );
Controller slider_INTERSTITIAL_ATTRACTORS = theGUI.addSlider( "INTERSTITIAL_ATTRACTORS", 0, 6, INTERSTITIAL_ATTRACTORS, 15, 90, 200, 13 );
Controller slider_X_PARTICLES = theGUI.addSlider( "X_PARTICLES", 0, 40, X_PARTICLES, 15, 115, 200, 13 );
Controller slider_Y_PARTICLES = theGUI.addSlider( "Y_PARTICLES", 0, 100, Y_PARTICLES, 15, 140, 200, 13 );
theGUI.setAutoDraw(false);
//----------make mesh
initMesh();
}
/*------------------------------------------------------------------
*** GLOBAL CONTINUOUS DRAW ***
------------------------------------------------------------------*/
void draw() {
if (theGUI.window(this).isMouseOver()) {
theCamera.setActive(false);
}
else {
theCamera.setActive(true);
}
//----------general
background(250);
/*strokeWeight(4);
stroke(0);
box(200,200,SURFACE_ATTRACTORS*2);*/
hint(ENABLE_DEPTH_TEST);
if (record) {
beginRaw(PDF, "3D####.pdf");
}
//----------draw meshes
topMesh.createMesh();
topMesh.createSprings();
topMesh.createFaces();
bottomMesh.createMesh();
bottomMesh.createSprings();
bottomMesh.createFaces();
//----------draw attractors
for (int i = 0; i < attList1.size(); ++i) {
Attractor myAtt = (Attractor) attList1.get(i);
myAtt.run();
myAtt.display();
}
for (int i = 0; i < attList2.size(); ++i) {
Attractor myAtt = (Attractor) attList2.get(i);
myAtt.run();
myAtt.display();
}
for (int i = 0; i < attList3.size(); ++i) {
Attractor myAtt = (Attractor) attList3.get(i);
myAtt.run();
myAtt.display();
}
if (export) {
//topMesh.exportToTxt(1);
//bottomMesh.exportToTxt(2);
}
if (record) {
endRaw();
record = false;
}
// makes the gui stay on top of elements
// drawn before.
hint(DISABLE_DEPTH_TEST);
gui();
}
/*-------------------------------------------------------------
*** MAKE PARTICLES, SPRINGS AND ATTRACTORS ***
--------------------------------------------------------------*/
void initMesh() {
bottomMesh = new Mesh(bBoxZ, attList1, attList3);
topMesh = new Mesh(meshHeight, attList2, attList3);
}
void keyPressed() {
if (key == 'p' || key == 'P') {
record = true;
export = true;
}
}
void gui() {
currCameraMatrix = new PMatrix3D(g3.camera);
camera();
theGUI.draw();
g3.camera = currCameraMatrix;
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Attractor {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
PVector aPos;
PVector aVel;
float pSize;
int range;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Attractor(PVector aPos_, PVector aVel_, int range_) {
// assign all the class variables
aPos = aPos_;
aVel = aVel_;
pSize = 10.0;
range = range_;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
void run() {
move();
bounce();
}
void move() {
aPos.add(aVel);
}
void bounce() {
if (aPos.x > bBoxX) {
aVel.x *= -1;
}
if (aPos.x < 0) {
aVel.x *= -1;
}
if (aPos.y > bBoxY-range) {
aVel.y *= -1;
}
if (aPos.y < range) {
aVel.y *= -1;
}
}
void display() {
strokeWeight(0.25);
stroke(100);
//point(aPos.x, aPos.y, aPos.z);
line(aPos.x-pSize, aPos.y, aPos.z, aPos.x+pSize, aPos.y, aPos.z);
line(aPos.x, aPos.y-pSize, aPos.z, aPos.x, aPos.y+pSize, aPos.z);
line(aPos.x, aPos.y, aPos.z-pSize, aPos.x, aPos.y, aPos.z+pSize);
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Face {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
// declare all the class variables
Particle p00;
Particle p01;
Particle p02;
Particle p03;
float tmpMeshHeight;
float Dist1;
float Dist2;
float DistA;
float DistB;
float DistC;
float colValG;
float colValB;
float colValR;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Face (Particle INPUT_00, Particle INPUT_01, Particle INPUT_02, Particle INPUT_03, float meshHeight_) {
// assign all the class variables
p00 = INPUT_00;
p01 = INPUT_01;
p02 = INPUT_02;
p03 = INPUT_03;
tmpMeshHeight = meshHeight_;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
//----------Draw myself
void showMe() {
Dist1 = dist(p00.pos.x, p00.pos.y, tmpMeshHeight, p00.pos.x, p00.pos.y, midAttHeight);
Dist2 = dist(p00.pos.x, p00.pos.y, p00.pos.z, p00.pos.x, p00.pos.y, tmpMeshHeight);
DistA = dist(p00.pos.x, p00.pos.y, p00.pos.z, p00.pos.x, p00.pos.y, tmpMeshHeight);
DistB = dist(p00.pos.x, p00.pos.y, (tmpMeshHeight+midAttHeight)/2, p00.pos.x, p00.pos.y, p00.pos.z);
DistC = dist(p00.pos.x, p00.pos.y, midAttHeight, p00.pos.x, p00.pos.y, p00.pos.z);
if (Dist2 < Dist1/4) {
// green fades in
colValG = map(DistA, 0, Dist1/4, 0, 255);
fill(0, colValG, 255);
}
else if (Dist2 < Dist1/2) {
// blue fades out
colValB = map(DistB, 0, Dist1/4, 0, 255);
fill(0, 255, colValB);
}
else if (Dist2 < Dist1/2 + Dist1/4) {
// red fades in
colValR = map(DistB, 0, Dist1/4, 0, 255);
fill(colValR, 255, 0);
}
else {
//green fades out
colValG = map(DistC, 0, Dist1/4, 0, 255);
fill(255, colValG, 0);
}
/*else if (Dist1 < (Dist3/2 + Dist3/4)) {
// red fades in
colValR = map(Dist1, (Dist3/2 + Dist3/4), Dist3/4, 0, 255);
fill(colValR, 255, 0);
}
else {
// green fades out
colValG = map(Dist2, 0, (Dist3/2 + Dist3/4), 0, 255);
fill(255, colValG, 0);
}*/
noStroke();
beginShape();
vertex(p00.pos.x, p00.pos.y, p00.pos.z);
vertex(p01.pos.x, p01.pos.y, p01.pos.z);
vertex(p02.pos.x, p02.pos.y, p02.pos.z);
vertex(p03.pos.x, p03.pos.y, p03.pos.z);
endShape();
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Mesh {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
float tmpMeshHeight;
Particle[][] particleList;
ArrayList springList;
Spring s0, s1;
ArrayList faceList;
Face f0;
ArrayList tmpAttList1;
ArrayList tmpAttList2;
Attractor tmpAtt;
PrintWriter output;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Mesh(float meshHeight_, ArrayList attList_, ArrayList attList2_) {
tmpMeshHeight = meshHeight_;
particleList = new Particle[X_PARTICLES][Y_PARTICLES];
springList = new ArrayList();
faceList = new ArrayList();
tmpAttList1 = attList_;
tmpAttList2 = attList2_;
//-----initialise particles
for (int i=0; i < X_PARTICLES; ++i) {
for (int j=0; j < Y_PARTICLES; ++j) {
// make a vector
PVector tmpPos = new PVector(i*xInc, j*yInc, tmpMeshHeight);
// make a particle
Particle newP = new Particle(tmpPos, tmpAttList1, tmpAttList2);
// fix perimeter particles
if ( (i < X_PARTICLES && j==0) || (i < X_PARTICLES && j==Y_PARTICLES-1) ) {
newP.fixMe();
}
// store the particle in our list
particleList[i][j] = newP;
}
}
//-----initialise springs
for (int i=0; i < X_PARTICLES; ++i) {
for (int j=0; j < Y_PARTICLES; ++j) {
if ( i>0 ) {
s0 = new Spring( particleList[i][j], particleList[i-1][j] );
springList.add(s0);
particleList[i][j].addSpring(s0);
particleList[i-1][j].addSpring(s0);
}
if ( j>0 ) {
s1 = new Spring( particleList[i][j], particleList[i][j-1] );
springList.add(s1);
particleList[i][j].addSpring(s1);
particleList[i][j-1].addSpring(s1);
}
}
}
//-----initialise faces
for (int i=0; i<X_PARTICLES; ++i) {
for (int j=0; j<Y_PARTICLES; ++j) {
if (i>0 && j>0) {
f0 = new Face( particleList[i][j], particleList[i][j-1], particleList[i-1][j-1], particleList[i-1][j], tmpMeshHeight );
faceList.add(f0);
}
}
}
// print how many springs we made
println("Number of springs " + springList.size() );
//-----initialise surface attractors
for (int i = 0; i < SURFACE_ATTRACTORS; ++i) {
//if (i < SURFACE_ATTRACTORS) {
PVector aPos = new PVector(random(0, bBoxX), random(150, bBoxY-150), tmpMeshHeight);
PVector aVel = new PVector(random(0.5, 2.5), random(0.5, 2.5), 0);
tmpAtt = new Attractor(aPos, aVel, 20);
tmpAttList1.add(tmpAtt);
}
//-----initialise middle attractors
for (int i = 0; i < INTERSTITIAL_ATTRACTORS; ++i) {
//if (i < SURFACE_ATTRACTORS) {
PVector aPos = new PVector(random(0, bBoxX), random(150, bBoxY-150), midAttHeight+30);
PVector aVel = new PVector(random(1, 2), random(1, 2), 0);
tmpAtt = new Attractor(aPos, aVel, 150);
tmpAttList2.add(tmpAtt);
}
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
void createMesh() {
//----------update particle physics
for (int i=0; i<X_PARTICLES; ++i) {
for (int j=0; j<Y_PARTICLES; ++j) {
particleList[i][j].solveForce();
}
}
//----------update particle positions
for (int i=0; i<X_PARTICLES; ++i) {
for (int j=0; j<Y_PARTICLES; ++j) {
particleList[i][j].update();
}
}
}
void createSprings() {
for (int i=0; i<springList.size(); i++) {
// get a spring from the arraylist
Spring currS = (Spring) springList.get(i);
currS.showMe();
}
}
void createFaces() {
for (int i=0; i<faceList.size(); i++) {
// get a spring from the arraylist
Face currF = (Face) faceList.get(i);
//currF.showMe();
}
}
void exportToTxt(int num_) {
int num = num_;
output = createWriter("data/points" + num + ".txt");
for (int i = 0; i < X_PARTICLES; i++) {
for (int j = 0; j < Y_PARTICLES; j++) {
output.println (particleList[i][j].pos.x + "," + particleList[i][j].pos.y + "," + particleList[i][j].pos.z);
}
}
output.flush();
output.close();
println("points have been exported");
exit();
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Particle {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
int pID;
PVector pos;
PVector vel;
PVector acc;
float pSize;
boolean pFixed;
ArrayList conSprings = new ArrayList();
ArrayList tmpAttList1;
ArrayList tmpAttList2;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Particle(PVector STARTPOS, ArrayList attList1_, ArrayList attList2_) {
// assign all the class variables
pos = STARTPOS;
vel = new PVector();
acc = new PVector();
pSize = 10.0;
pID = 0;
pFixed = false;
tmpAttList1 = attList1_;
tmpAttList2 = attList2_;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
//----------MOVE AND DRAW TO SCREEN
void update() {
if (pFixed==false) {
updatePos();
attraction();
attractionB();
}
showMe();
}
//----------SOLVE THE SPRINGS
void solveForce() {
if (pFixed==false) {
Particle otherP;
PVector sumForces = new PVector();
//sumForces.add(gravity);
sumForces.add(acc);
// loop thru our connections
for (int i = 0; i<conSprings.size(); ++i) {
// get a spring
Spring s = (Spring) conSprings.get(i);
// get other end of spring
if ( s.p00 == this ) {
otherP = s.p01;
}
else {
otherP = s.p00;
}
// calculate the push/pull of spring
PVector vecBet = PVector.sub(otherP.pos, pos);
float currLen = vecBet.mag();
float desiredLen = currLen-SPRING_REST_LENGTH;
vecBet.normalize();
vecBet.mult(desiredLen/2);
// add this force to our sum of forces
sumForces.add(vecBet);
}
// apply a damping to the force
sumForces.mult(SPRING_DAMPING_FORCE);
// add the resultant force to our vel
vel.add(sumForces);
}
}
void updatePos() {
vel.limit(2);
pos.add(0, 0, vel.z);
acc = new PVector(0, 0, 0);
/*pos.add(vel); // move the particle
vel.mult(0); */ // reset the vel for next time
}
//----------A typical class function!!
void showMe() {
// set appearance
noFill();
if (pFixed==true) {
// draw as 'FIXED' geometry
strokeWeight(0.25);
stroke(0, 0, 250);
line(pos.x-pSize, pos.y, pos.z, pos.x+pSize, pos.y, pos.z);
line(pos.x, pos.y-pSize, pos.z, pos.x, pos.y+pSize, pos.z);
line(pos.x, pos.y, pos.z-pSize, pos.x, pos.y, pos.z+pSize);
}
else {
// draw as 'FREE' geometry
strokeWeight(0.25);
stroke(140);
line(pos.x-pSize/2, pos.y, pos.z, pos.x+pSize/2, pos.y, pos.z);
line(pos.x, pos.y-pSize/2, pos.z, pos.x, pos.y+pSize/2, pos.z);
line(pos.x, pos.y, pos.z-pSize/2, pos.x, pos.y, pos.z+pSize/2);
}
}
//----------Make the particle fixed / free
void fixMe() {
pFixed=true;
}
void freeMe() {
pFixed=false;
}
//----------Add a spring to my list of springs
void addSpring(Spring S) {
// store this spring
conSprings.add(S);
}
void attraction() {
PVector steer = new PVector();
int count = 0;
for (int i = 0; i < tmpAttList1.size(); i++) {
// get a PVector from the list
Attractor tmpAtt = (Attractor) tmpAttList1.get(i);
float distance = PVector.dist(tmpAtt.aPos, pos);
if (distance > 0 && distance < attRange+21) {
PVector vecBetween = PVector.sub(tmpAtt.aPos, pos);
// get the length of the vector
vecBetween.normalize();
steer.add(vecBetween);
count++;
}
}
if (count > 0) {
steer.mult(1.0/count);
}
steer.mult(2);
acc.add(steer);
}
void attractionB() {
PVector steer = new PVector();
int count = 0;
for (int i = 0; i < tmpAttList2.size(); i++) {
// get a PVector from the list
Attractor tmpAtt = (Attractor) tmpAttList2.get(i);
float distance = PVector.dist(tmpAtt.aPos, pos);
if (distance > 0 && distance < attRange+31) {
PVector vecBetween = PVector.sub(tmpAtt.aPos, pos);
// get the length of the vector
vecBetween.normalize();
steer.add(vecBetween);
count++;
}
}
if (count > 0) {
steer.mult(1.0/count);
}
steer.mult(2);
acc.add(steer);
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------
class Spring {
/*------------------------------------------------------------------
*** CLASS VARIABLES ***
------------------------------------------------------------------*/
// declare all the class variables
Particle p00;
Particle p01;
/*------------------------------------------------------------------
*** CLASS CONSTRUCTOR ***
------------------------------------------------------------------*/
Spring (Particle INPUT_00, Particle INPUT_01) {
// assign all the class variables
p00 = INPUT_00;
p01 = INPUT_01;
}
/*------------------------------------------------------------------
*** CLASS FUNCTIONS ***
------------------------------------------------------------------*/
//----------Draw myself
void showMe() {
stroke(180);
strokeWeight(0.5);
noFill();
line(
p00.pos.x, p00.pos.y, p00.pos.z,
p01.pos.x, p01.pos.y, p01.pos.z
);
}
}
1