We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Water simulation help
Pages: 1 2 
Water simulation help (Read 2873 times)
Water simulation help
Feb 7th, 2007, 6:37pm
 
Hey folks,

I've been playing with Processing for a while now, but I'm a largely self-taught programmer.  I'm also a rather new programmer.

Anyway, I'm playing with the water surface simulation that I've seen done so many places:

http://bodytag.org/nav.php?u=tp02/

and

http://www.neilwallis.com/java/water.html

, for instance.

I've written some code to do this, but it is running very slowly!  Rather than run at screen resolution, I'm drawings rects to the canavas as pixels, but still it is slow.  I was hoping that somebody could offer me some insight as to why this is happening.

Here's the code:


int[][] buffer1;
int[][] buffer2;
int holder;

int numCells, cellWidth, cellHeight, up, down, left, right;


void setup(){
 size (400,400);
 colorMode(HSB,200);
 numCells = 50;
 buffer1 = new int[numCells][numCells];
 buffer2 = new int[numCells][numCells];
 cellWidth = width/numCells;
 cellHeight = height/numCells;
 for (int i = 0; i < width/cellWidth; i++)
 {
   for (int j = 0; j < height/cellWidth; j++)
   {
     buffer1[i][j] = 0;
     buffer2[i][j] = 0;
   }
 }
}

void draw(){
 if (mousePressed)
 {
   buffer1[constrain(mouseX,0,width-1)/cellWidth][constrain(mouseY,0,height-1)/cellHeight] = 50;
 }

 for (int i = 0; i < width/cellWidth; i++)
 {
   for (int j = 0; j < height/cellWidth; j++)
   {
     up = buffer2[i][constrain(j-1,0,numCells-1)];
     down = buffer2[i][constrain(j+1,0,numCells-1)];
     left = buffer2[constrain(i-1,0,numCells-1)][j];
     right = buffer2[constrain(i+1,0,numCells-1)][j];
     buffer1[i][j] = (int)((up+down+left+right)/2.0 - buffer1[i][j]);
     buffer1[i][j] = int(buffer1[i][j] - buffer1[i][j]/1024.0);
   }
 }

 int maxdis = 0;

 //display
 for (int i = 0; i < width/cellWidth; i++)
 {
   for (int j = 0; j < height/cellWidth; j++)
   {
     if (buffer1[i][j] > maxdis)
     {
       maxdis = buffer1[i][j];
     }
     fill(120,200,buffer1[i][j]*20+80);
     rect(i*cellWidth,j*cellHeight,cellWidth,cellHeight);
   }
 }

 println(maxdis);

 //switch buffers
 for (int i = 0; i < width/cellWidth; i++)
 {
   for (int j = 0; j < height/cellWidth; j++)
   {
     holder = buffer1[i][j];
     buffer1[i][j] = buffer2[i][j];
     buffer2[i][j] = holder;
   }
 }
}


Many thanks for any assistance!

Charlie
Re: Water simulation help
Reply #1 - Feb 7th, 2007, 9:38pm
 
Well, I grabbed your code, and immdeiately sped it up many times with a frameRate(30); in the setup!  

Using rects might actually be slowing it down when compared to accessing pixels[] directly.

Also, probably the biggest optimization that can be made to the water effect is to, instead of copying the whole 2D array data from buffer1 to buffer2 in each frame, use pointers (are they called that in processing?) to these arrays and just switch what they point to:

Code:

float map1[]=new float[640*480]; //first buffer
float map2[]=new float[640*480]; //second buffer

float pt1[]; //variable to "point" to one of the buffers
float pt2[]; //variable to "point" to one of the buffers
float tmpt[]; //temp pointer

pt1=map1; //pt1 references map1 to begin
pt2=map2; //pt1 references map2 to begin

//Do all the water effect stuff using pt1, pt2 (not map1,map2), then instead of copying
//from one buffer to the other, just switch what your "pointers" point to:

tmpt=pt2;
pt2=pt1;
pt1=tmpt;


Check out my water effect with source code which uses this method, and is pretty darn fast even at hi res:

http://www.spacefillingcurve.net/programming/processing/splish/
Re: Water simulation help
Reply #2 - Feb 7th, 2007, 10:22pm
 
Thanks very much!!

My naive belief was that no frameRate() call meant that it would run as quickly as possible.

Your comment about switching the buffers is really a demonstration of the kind of sensibility I need to learn.

Gonna give it a shot right now.  Thanks again!

Charlie
Re: Water simulation help
Reply #3 - Feb 7th, 2007, 10:37pm
 
some other bits:

+ when using colorMode(HSB), fill() and stroke() take a little bit of time. fastest is to use fill(#ffcc00) and that sort of thing. or work out colors beforehand using an array.

+ use P3D if you want to play with pixels directly. rect() may also be faster in P3D.

+ you might even consider using createImage(w, h, RGB) where w  and h are the size of your simulation, and messing with its pixels directly, then drawing it scaled up by cellWidth/cellHeight.
Re: Water simulation help
Reply #4 - Feb 8th, 2007, 12:11am
 
hmmm but i am having trouble implementing it the way you describe.

I think I have a solution, though.  Im going to try dropping the two buffers into a 3d array and just switching the index variables each frame.  Pretty similar to your solution.

Works pretty well!  still not too fast, but maybe if I go directly to pixels[] I'll make it the rest of the way there.

Here's the code if you're interested:

int[][][] buffers;
int numCells, cellWidth, cellHeight, up, down, left, right, curBuf, prevBuf;

void setup(){
 size (800,800);
 frameRate(30);
 colorMode(HSB,400);
 numCells = 100;
 curBuf = 0;
 prevBuf = 1;
 buffers = new int[2][numCells][numCells];
 cellWidth = width/numCells;
 cellHeight = height/numCells;
 for (int k =0; k < 2; k++)
 {
   for (int i = 0; i < numCells; i++)
   {
     for (int j = 0; j < numCells; j++)
     {
       buffers[curBuf][i][j] = 0;
       buffers[prevBuf][i][j] = 0;
     }
   }
 }
}

void draw(){
 if (mousePressed)
 {
   //disturb with the mouse
   buffers[prevBuf][constrain(mouseX,0,width-1)/cellWidth][constrain(mouseY,0,height-1)/cellHeight] = 300;
 }
 else
 {
   //random disturbances
   // buffers[curBuf][(int)random(0,width-1)/cellWidth][(int)random(0,height-1)/cellHeight] = 100;
 }

 //switching the buffers
 curBuf = (curBuf+1)%2;
 prevBuf = (prevBuf+1)%2;
 
 //running the CA
 for (int i = 0; i < numCells; i++)
 {
   for (int j = 0; j < numCells; j++)
   {
     up = buffers[prevBuf][i][constrain(j-1,0,numCells-1)];
     down = buffers[prevBuf][i][constrain(j+1,0,numCells-1)];
     left = buffers[prevBuf][constrain(i-1,0,numCells-1)][j];
     right = buffers[prevBuf][constrain(i+1,0,numCells-1)][j];
     buffers[curBuf][i][j] = (int)((up+down+left+right)/2.0 - buffers[curBuf][i][j]);
     buffers[curBuf][i][j] = int(buffers[curBuf][i][j] - buffers[curBuf][i][j]/1024.0);
   }
 }

 //display
 for (int i = 0; i < numCells; i++)
 {
   for (int j = 0; j < numCells; j++)
   {
     fill(120,200,buffers[curBuf][i][j]*20+80);
     rect(i*cellWidth,j*cellHeight,cellWidth,cellHeight);
   }
 }

}

void keyPressed(){
 if (key == 's')
 {
   saveFrame("cap.jpg");
 }
}
Re: Water simulation help
Reply #5 - Feb 8th, 2007, 10:35am
 
Hi,

Movax thank you very much for sharing your experience !

I've tried to use OpenGL rendering with your code, but i only get a black screen.
If we can use OpenGl with it, do you think we'll get a faster effect ?
Re: Water simulation help
Reply #6 - Feb 8th, 2007, 9:29pm
 
jaylfk, glad to help.  Its one of my favorite effects and I've spent a lot of time coding it on various different platforms.

Hm as far as openGL, I don't really use it in Processing too much, but glancing at my code, I don't notice anything *obvious* that should break it.

I guess any possible speed difference in openGL would depend on whether openGL is faster to access and write individual pixels, which I think it is not. (?)  

There might be other optimizations, although I can get >30fps @ 640x480 over here (dual core intel), so I haven't been hitting it too hard Smiley
Re: Water simulation help
Reply #7 - Feb 12th, 2007, 2:26am
 
Can a P5/OPENGL's specialist help to understand why the Movax splish's code is not working in OPENGL ?

i've added this to the code:

Quote:
import processing.opengl.*;

setup(){
size(640,480,OPENGL);
}


The result is a Black screen.
It is getting grey if i comment out background(0); located in draw()

Thank you,
any suggestion is welcome.
Re: Water simulation help
Reply #8 - Feb 12th, 2007, 4:48am
 
Hey there.

I'm not sure of your implementation, but I'ven oticed in the past that OPENGL treats many things a bit differently than the other graphics modes.  For instance, when I was plotting some lines and points, in OPENGL a line or point with stroke 1 (or was it 0?) did not show up at all, whereas it did in the other modes.

So my guess is that the pixels[] array is either not accessible in OPENGL or that it must be interacted with in some other way.  It's likely not a problem with your code per se.

By the way, since I started this topic, I've had a lot of success.  I am still working on making my stimulations video interactive, but what ive done so far is up on my blog:

http://www.charliemezak.com/blog/

Thansk for all the help, fellas!
Re: Water simulation help
Reply #9 - Feb 17th, 2007, 12:02am
 
Somebody knows how to make it work in OpenGL ?

I've got an idea, but did not found yet how to put it in practice.

Maybe by mapping the pixels[] array to a rect() that has the size of the sketch screen (width/height).

Question for Fry,

Is there a trick to activate OpenGL(JOGL or direct call) in Processing when using the pixels[] array ?

I've read this :

Quote:
http://processing.org/reference/size_.html

If you're manipulating pixels (using methods like get() or blend(), or manipulating the pixels[] array), P3D (and eventually P2D as well) will be faster than the default (JAVA2D) setting, as well as the OPENGL setting. Similarly, when handling lots of images, or doing video playback, P3D will often be faster.


Does this mean that OpenGL is supposed to work, but slower than P3D ?

Is it possible to write the Opengl code to directly in Pure Java ?
Thanks.
Re: Water simulation help
Reply #10 - Feb 19th, 2007, 7:50pm
 
Maybe you can attack the problem from the other direction: What features of openGL do you need that P3D doesn't have?
Re: Water simulation help
Reply #11 - Jul 23rd, 2007, 10:48am
 
Hi, i dig up this topic to ask a question about movax's splish effect.

Splash() generates a ripple from a x/y position.

I have been trying to modify it to make the ripples ( splash() ) react around a shape (circle, rectangle or anything else) without success.

Anybody knows how to modify it ?

Thanks.
Re: Water simulation help
Reply #12 - Jul 25th, 2007, 11:46pm
 
Sure, you simply set desired corresponding pixels in pt2[] to some 'depth'.  So in my code, the splash() function just sets a small square of pixels to a depth of .10, based on
mouse position.

But which pixels you set could be determined by anything.. A
shape you specify, or perhaps brightness() values of a bitmap. (Or mpg/webcam) etc..  

Re: Water simulation help
Reply #13 - Jul 26th, 2007, 1:25am
 
Nice explanation !

I'm gonna try right now Smiley
Re: Water simulation help
Reply #14 - Aug 19th, 2007, 7:52pm
 
Hi,

after getting inspired by your code, this is what i've got so far.

1st example based on background picture and motion detection.

http://www.mediafire.com/?9jcmb3ojjxm

2nd example based on live video stream from a webcam.

http://www.mediafire.com/?8rbpy1zixnc
Pages: 1 2