// SIN_PATTERN_SLIDERS
//
// pattern generator based on the sum of combined sin waves
// play with the sliders to adjust each of the 3 frequencies
// and phases on x and y.
//
// Seb Chevrel | www.seb.cc
// ———————————————————————————————————————————————————————————————
int WIDTH=400;
int HEIGHT=400;
int NUMF=3;
float[] freqV=new float[NUMF];
float[] freqH=new float[NUMF];
float[] phaseV=new float[NUMF];
float[] phaseH=new float[NUMF];
HScrollbar[] freqVScroll=new HScrollbar[NUMF];
HScrollbar[] freqHScroll=new HScrollbar[NUMF];
HScrollbar[] phaseVScroll=new HScrollbar[NUMF];
HScrollbar[] phaseHScroll=new HScrollbar[NUMF];
float sum=0;
int col;
void setup() {
size(WIDTH,HEIGHT+NUMF*20+10);
noBackground();
for(int i=0; i<NUMF; i++) {
freqVScroll[i]=new HScrollbar (5, HEIGHT+i*20+15, 120, 16, 1);
freqHScroll[i]=new HScrollbar (WIDTH/2+5, HEIGHT+i*20+15, 120, 16, 1);
freqV[i]=(random(200)+10)/(1<<i);
freqH[i]=(random(200)+10)/(1<<i);
freqVScroll[i].setPos((float)freqV[i]/210);
freqHScroll[i].setPos((float)freqH[i]/210);
phaseV[i]=random(PI);
phaseH[i]=random(PI);
phaseVScroll[i]=new HScrollbar (135, HEIGHT+i*20+15, 60, 16, 1);
phaseHScroll[i]=new HScrollbar (WIDTH/2+135, HEIGHT+i*20+15, 60, 16, 1);
phaseHScroll[i].setPos(phaseH[i]/PI);
phaseVScroll[i].setPos(phaseV[i]/PI);
}
render();
}
void loop() {
// init
for(int i=0; i<NUMF; i++) {
freqVScroll[i].update();
freqV[i]=freqVScroll[i].getPos()*200+10;
freqVScroll[i].draw();
phaseVScroll[i].update();
phaseV[i]=phaseVScroll[i].getPos()*PI;
phaseVScroll[i].draw();
freqHScroll[i].update();
freqH[i]=freqHScroll[i].getPos()*200+10;
freqHScroll[i].draw();
phaseHScroll[i].update();
phaseH[i]=phaseHScroll[i].getPos()*PI;
phaseHScroll[i].draw();
}
if(HScrollbar.inuse) render();
}
void render() {
for(int i=0;i<WIDTH;i++) {
for(int j=0;j<HEIGHT;j++) {
sum=0;
for(int k=0;k<NUMF;k++) {
sum+= sin(j/freqV[k]+phaseV[k]) * sin(i/freqH[k]+phaseH[k]) ;
}
col=int(sum*255/NUMF);
if (col<0) col=-col;
pixels[i+j*WIDTH]=(col<<16)+(col<<8)+col;
}
}
}
class HScrollbar
{
static boolean inuse;
int swidth, sheight; // width and height of bar
int xpos, ypos; // x and y position of bar
float spos, newspos; // x position of slider
int sposMin, sposMax; // max and min values of slider
int loose; // how loose/heavy
boolean over; // is the mouse over the slider?
boolean locked;
float ratio;
HScrollbar (int xp, int yp, int sw, int sh, int l) {
swidth = sw;
sheight = sh;
int widthtoheight = sw - sh;
ratio = (float)sw / (float)widthtoheight;
xpos = xp;
ypos = yp-sheight/2;
spos = xpos + swidth/2 - sheight/2;
newspos = spos;
sposMin = xpos;
sposMax = xpos + swidth - sheight;
loose = 1;
}
void update() {
if(over() && !inuse) {
over = true;
} else {
over = false;
}
if(mousePressed && over) {
if (! inuse) {
locked = true;
inuse=true;
}
}
if(!mousePressed) {
locked = false;
inuse=false;
}
if(locked) {
newspos = constrain(mouseX-sheight/2, sposMin, sposMax);
}
if(abs(newspos - spos) > 1) {
spos = spos + (newspos-spos)/loose;
}
}
int constrain(int val, int minv, int maxv) {
return min(max(val, minv), maxv);
}
boolean over() {
if(mouseX > xpos && mouseX < xpos+swidth &&
mouseY > ypos && mouseY < ypos+sheight) {
return true;
} else {
return false;
}
}
void draw() {
fill(0);
rect(xpos, ypos, swidth, sheight);
if(over || locked) {
fill(255, 102, 0);
} else {
fill(255, 255, 255);
}
rect(spos, ypos, sheight, sheight);
}
void setPos(float v) {
newspos=spos=xpos+v/ratio*(swidth-sheight);
}
float getPos() {
// convert spos to be values between
// 0 and the total width of the scrollbar
return (spos-xpos)/(swidth-sheight);
}
}