andrewowaun
Full Member
Offline
Posts: 202
Barbados
Re: 2d water simulation with refraction
Reply #6 - Dec 13th , 2009, 7:35pm
This is an awesome piece of code. I applied an algorithmic background. float[] temp; int tankX = 401; int tankY = 401; int tankSize = tankX*tankY; float tankScale = 1; float damping = 0.99; int dropSize=20;//10 float lightIntensity=0.6;//0.2 PImage water; public boolean rise = false; float[] waveBuffer1 = new float[tankSize]; float[] waveBuffer2 = new float[tankSize]; int[] wallMap = new int[tankSize]; PImage bbg; import processing.opengl.*; void setup() { frameRate(100); size(round(tankScale*tankX),round(tankScale*tankY),OPENGL); makebg(false,false); background(1); noStroke(); smooth(); colorMode(HSB,1,1,1,1); water=createImage(width,height,ARGB); PFont font1 = createFont("arial",12); textFont(font1, 12); } void draw(){ background(0); processWater(); image(water,0,0); fill(1); text("fps: "+frameRate,10,20); } void processWater(){ float[] dispMap = new float[tankSize]; for(int y=1; y<tankY-1; y++) for(int x=1; x<tankX-1; x++){ int i=y*tankX+x; float sumX=waveBuffer2[i-1]+waveBuffer2[i+1]; float sumY=waveBuffer2[i-tankX]+waveBuffer2[i+tankX]; waveBuffer1[i] = ((sumX+sumY)/2) - waveBuffer1[i]*1; waveBuffer1[i] *= damping*(1-wallMap[i]); //calc displacement map sumX=-waveBuffer2[i-1]+waveBuffer2[i+1]; sumY=-waveBuffer2[i-tankX]+waveBuffer2[i+tankX]; int dispX=x-round(sumX*1); int dispY=y-round(sumY*1); if(dispX>1 && dispX<tankX-1 && dispY>1 && dispY<tankY-1){ dispMap[dispY*tankX+dispX]+=lightIntensity; } } //draw refractions water.loadPixels(); for(int y=1; y<tankY-1; y++) for(int x=1; x<tankX-1; x++){ //water.pixels[y*tankX+x]=color(dispMap[y*tankX+x]/10); water.pixels[y*tankX+x]=blendColor(color(dispMap[y*tankX+x]/10),bbg.pixels[x+width*y],DIFFERENCE); color ff= blendColor(color(dispMap[y*tankX+x]/10),bbg.pixels[x+width*y],DIFFERENCE); //water.pixels[y*tankX+x]=bbg.pixels[x+width*y]; if(wallMap[y*tankX+x] ==1 || wallMap[y*tankX+x] == bbg.pixels[(mouseY)*width+(mouseX)]) { // water.pixels[y*tankX+x]=color(0.2); // water.pixels[y*tankX+x]=color(bbg.pixels[x+width*y+1]); color cp = color(bbg.pixels[x+width*y]); float rr = red(ff); float gg = green (ff); float bb = blue (ff); color po = color (rr,gg,bb); water.pixels[y*tankX+x]=blendColor(color (rr,gg,bb),cp,DIFFERENCE); } } //swap buffers temp=waveBuffer1; waveBuffer1=waveBuffer2; waveBuffer2=temp; water.updatePixels(); } void mouseDragged(){ if (mouseButton==37){ //LEFT if(mouseX>dropSize/2 && mouseX<tankX-dropSize/2 && mouseY>dropSize/2 && mouseY<tankY-dropSize/2) for(int y=-dropSize/2;y<=dropSize/2;y++) for(int x=-dropSize/2;x<=dropSize/2;x++){ wallMap[(mouseY+y)*width+(mouseX+x)]= 1; } } if (rise){ if (mouseButton==39){ //RIGHT if(mouseX>dropSize/2 && mouseX<tankX-dropSize/2 && mouseY>dropSize/2 && mouseY<tankY-dropSize/2) for(int y=-dropSize/2;y<=dropSize/2;y++) for(int x=-dropSize/2;x<=dropSize/2;x++) wallMap[(mouseY+y)*width+(mouseX+x)]=bbg.pixels[(mouseY+y)*width+(mouseX+x)]; } } // println(mouseButton); } void keyPressed(){ if(key==' '){ //32 == SPACE if(mouseX>dropSize/2 && mouseX<tankX-dropSize/2 && mouseY>dropSize/2 && mouseY<tankY-dropSize/2) for(int y=-dropSize/2;y<=dropSize/2;y++) for(int x=-dropSize/2;x<=dropSize/2;x++) waveBuffer1[(mouseY+y)*width+(mouseX+x)]=color(100);//100 } if (key =='r'){ rise =!rise; } } int cpass=0; void makebg(Boolean animate, Boolean invert){ bbg = new PImage(width,height); loadPixels(); color colx = 0; for(int y=0;y<height;y++){ for(int x=0;x<width;x++){ int pos=y*width+x; color col = pixels[pos] ;// colx = color(height-y,x,y-x); if (animate){ //colx = color(height-y,X,cpass+y); colx = color(height-y,x,cpass-X); } float rr= red(colx); float bb= blue(colx); float gg= green(colx); rr = colx >> 16 & 0xff; gg = colx >> 8 & 0xff; bb = colx & 0xff; if (!invert) bbg.pixels[pos]=color(rr,gg,bb); if (invert) bbg.pixels[pos]=-color(rr,gg,bb); } if (!online){ arraycopy(bbg.pixels,pixels); } } if (animate){ cpass++; } if (cpass>4000){ cpass=0; } }