Create water effect like WOG with ODE or Box2D

26 replies [Last post]
Joined: 01/29/2011

hi Everybody,

I want to create Water in my game. I know Physics Engin, ODE and Box2D. my game created with SDL in C++.

For create water, i found one solution: http://www.patrickmatte.com/stuff/physicsLiquid/
But it is very CPU-consuming so it's not good Idea.

WOG used a simple way but i don't know how can implement this water effect, see this picture that captured when a goo ball jump into water!!

http://www.freeimagehosting.net/uploads/91ead07a1f.jpg

really realistic!!

Can anyone help me to create a water like WOG in ODE or Box2D.

Joined: 09/01/2009

Hmm... the water simulation in World of Goo has puzzled me for a while, also. I think that, like you stated, it is actually far simpler than it looks, but I have no knowledge as to the technical setup as to how they did it. The readme.html lists all the open-source libraries they used, and I see nothing there that talks about their water setup. My best guess would be that they created their own water simulator, using some part of ODE or something, but I don't know for sure. I doubt anyone else here knows, either, as we are the goo fans, not goo developers. I would recommend trying to contact 2DBoy via their contact form. They may or may not respond, but it's worth a shot.

If you find out anything, let me know. I'm highly interested, too. Smile

As far as interacting with the Goo Balls, the water simulator is incredibly simple, however. It's just a rectangular force field that has an upward force. But for the actual wave simulations, I have no idea (The splashes look fairly simple, just a few random water droplets flying upwards. It doesn't look like they depend on how forcefully a Goo Ball hits the water or how big the Goo Ball is).

Joined: 01/29/2011

I try to contact 2DBoy via their contact form. it's worth a shot Smile

I think splashes are random water droplets flying upward, too. ،The Question is about Waves!!

I have an idea: if we create a chain top of water like this:

--------------------------------------

then when a ball falling into the water, the chain will be changed like this:

(remove dots from your Image)
.............. /\........./\...........
..________/..\......./..\______
................. \...../..............
...................\O/...............
....................\/................

and for waves: if we tremble one-side of chain the problem will be solved:

\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

It means the chain will be control water surface.

What do you think, it will be Worked?

Joined: 09/01/2009

Erm, maybe, but it would be slightly more complex, as the chain itself would have to be springy and elastic to make it spring back to level, rather than hanging down. Might be worth a shot, but I dunno.

Joined: 08/06/2010

The splashes are a particle effect called "splash" in fx.xml.bin. They aren't affected size, force, water color, or anything else. The chain sounds good, but I'm not sure.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 01/29/2011

I test chain. It works for waves!! when density of chain is zero.

but collision between ball and water, it isn't similar to WOG!! all rings in chain go up and down.

Joined: 01/29/2011

Hi,
I Found it!!

Book: Special Effects Game Programming With DirectX

I implement it and it run very well.

psudocode is here (C++):

if you implement it in flash aware me, thanks.

void main()
{
    currentT = 0;
mRight = 600;
mLeft = 50;
// resolution (number of line for create water)
mStep = 100;
mHeight = 50;
mDampValue = 1.05;
mWaveLen = 5;
mWaveHight = 5;
mWavespeed = 20;
m_pWaterActive = new int[mStep];
m_pWaterScratch = new int[mStep];
m_pWave = new int[mStep];
for (int i=0; i < mStep; i++)
	m_pWave[i] = m_pWaterActive[i] = m_pWaterScratch[i] = 0;
// create sample collision
m_pWaterActive[mStep/2]=300;
}
 
void Water::CreateWave(int *water, int size, int t, int speed)
{
	for (int i=0; i<mStep; i++)
		water[i]=size*sin(Convert::convertDegreeToRadian(t*i+currentT));
	currentT = currentT + speed;
}
 
void Water::ProcessWater(int *oldwater, int *newwater, float fDampValue)
{
  // loop through all the water values...
	for (int x=0; x < mStep; x++) {
 
      // add up the values of all the neighboring water values...
      int value;
      int xminus1 = x-1; if (xminus1 < 0) xminus1 = 0;
      int xminus2 = x-2; if (xminus2 < 0) xminus2 = 0;
 
      int xplus1 = x+1; if (xplus1 >= mStep) xplus1 = mStep-1;
      int xplus2 = x+2; if (xplus2 >= mStep) xplus2 = mStep-1;
 
      {
 
        value  = (float)oldwater[xminus1];
        value += (float)oldwater[xminus2];
        value += (float)oldwater[xplus1];
        value += (float)oldwater[xplus2];
 
        // average them
        value /= 2;
 
      }
 
      // subtract the previous water value
      value -= newwater[x];
 
      // dampen it!
      value = (int)((float)value / fDampValue);
 
      // store it in array
      newwater[x] = value;
    }
}
 
void Water::onEachFrame(/*.........*/) 
{
	CreateWave(m_pWave, mWaveHight, mWaveLen, mWavespeed);
 
	ProcessWater(m_pWaterActive, m_pWaterScratch, mDampValue);
 
	for (int i = 0; i<mStep; i++)
	{
		int s = Math::roundf((mRight-mLeft)/float(mStep+1));
		Vector2 v1;
		Vector2 v2;
 
		if (i==0) 
		{
			v1.x = mLeft;
			v1.y = mHeight+m_pWaterActive[i]+m_pWave[i];
			v2.x = mLeft + s * (i+1);
			v2.y = mHeight+m_pWaterActive[i]+m_pWave[i];
		}
		else if (i==mStep)
		{
			v1.x = mLeft + s * i;
			v1.y = mHeight+m_pWaterActive[i-1]+m_pWave[i-1];
			v2.x = mRight;
			v2.y = mHeight+m_pWaterActive[i-1]+m_pWave[i-1];
		}
		else
		{
			v1.x = mLeft + s * i;
			v1.y = mHeight+m_pWaterActive[i-1]+m_pWave[i-1];
			v2.x = mLeft + s * (i+1);
			v2.y = mHeight+m_pWaterActive[i]+m_pWave[i];
		}
 
		drawLineToScene(v1,v2,255,255,255);
	}
 
	int *temp = m_pWaterActive;
	m_pWaterActive = m_pWaterScratch;
	m_pWaterScratch = temp;
}

Joined: 09/01/2009

Wow, cool! Thanks! Smile That looks really simple, too.

I see... so this just uses some sine waves to simulate the water. Clever. Do you have a screenshot or video of what this looks like?

Joined: 08/06/2010

That looks cool! Mind if I port it to JavaScript for a game I'm making? I'll give you credit.

Another Planet finally has an official release! Download chapters 1 through 3 here! Thank you for waiting so long while I kept starting over.

Joined: 09/01/2009

Yeah, what AP said. ^^ Mind if I use this in my game?

Joined: 01/29/2011

MOM4Evr wrote:
Wow, cool! Thanks! Smile That looks really simple, too.

I see... so this just uses some sine waves to simulate the water. Clever. Do you have a screenshot or video of what this looks like?

I write a Demo with SDL, Box2D, C++. please, download it here:
http://www.4shared.com/file/GaiekC45/demo.html

It not completed , just a demo. collision in water must be correct,
I try to correct it any way.

note: after download demo run "bin\Exe\MGames.exe" so press start and drag some goo and release it above water, enjoy.

Regards
vahid b.

Joined: 02/12/2011
Joined: 07/08/2011

That's really amazing. I have yet to find a purpose for simulated water in my games but that looks great! I know box2d uses particles rather than a good liquid simulation, but it's still do-able.

Joined: 01/29/2011

Finally, I upload last version of water in my Framework.
see this in youtube:

Joined: 09/01/2009

Bump.

After digging around a LOT to try to make my own WOG-esque water simulation for my game, I finally found something that works. The basic idea is slightly more simple than the pseudocode posted above. The best code that I found is here: http://www.box2d.org/forum/viewtopic.php?f=3&t=2746#p14093 based off of a "hello world" example from a presentation at siggraph 2007 (the PDF is here: http://www.double.co.nz/dust/GDC03.pdf )

There's a lot out there when it comes to water simulations, and very little of what I found was directly usable/actually worked. This, however, did. My implementation of it follows:

  1. //Update the velocities:
  2. for (int i=1; i<m_iComplexity-1; i++) //m_iComplexity is how many segments the water has
  3. {
  4. v[i] += (h[i-1] + h[i+1] + m_fHeight) / 3.0f - h[i]; //m_fHeight is the "calm water height"
  5. v[i] *= m_fWaterDamping; //Dampen how this water moves
  6. }
  7. //And the actual height data
  8. for(int i = 1; i < m_iComplexity-1; i++)
  9. {
  10. h[i] += v[i] * m_fViscosity; //Viscosity = framerate for this example (or basically
  11. //how much the fluid moves per frame)
  12. }
  13. // boundary conditions
  14. h[0] = h[1];
  15. h[m_iComplexity-1] = h[m_iComplexity-2];

A Viscosity and Waterdamping of 0.95 gives a reasonably WOG-like water simulation for me (For a 32-pixel deep water pool), and I've toyed with different values for each. For me, viscosity=0.1 and waterdamping=0.999 gives epically slow water waves that are mezmerizing to watch. Of course, this will depend on how much force you add to the water from a collision. (I happen to add a lot)

All that's left is to alter the velocity of the part of the water that an object splashes into, add the splashy particle effect, and you're done. I'm very pleased.

Joined: 01/29/2011

Congratulation, your code seems faster. can you add your simulation video to see how it work.

I see the paper that you share(pdf file). i think it has a CD. can you share the link of cd?

Joined: 09/01/2009

I don't have a CD link, sorry. All I found was the Box2D forum topic, then the PDF from there. And limited-bandwidth internet means I can't upload a video, I'm afraid. At least not for a month or so. I will when I get the chance. I think it's basically the same code as yours, just laid out slightly differently.

Joined: 01/29/2011

I am hopeful to see your video in this month.
thanks.

Joined: 01/29/2011

if you want, i can share my source code with you (c++, Box2d), you can use it ever you want, Commercial or non-commercial.
mail me: v [dot] babaee [at] gmail [dot] com

Joined: 02/20/2011

careful!! spam can read that. put it as:
v.babaee (at) gmail (dot) com

-_-

Joined: 01/29/2011

kirdneh wrote:
careful!! spam can read that. put it as:
v.babaee (at) gmail (dot) com

thanks.

Joined: 12/23/2010

Or write it vertically, super safe.

v
(dot)
b
a
b
a
e
e
(at)
g
m
a
i
l
(dot)
c
o
m

Laughing out loud

Joined: 01/29/2011

puggsoy wrote:
Or write it vertically, super safe.

v
(dot)
b
a
b
a
e
e
(at)
g
m
a
i
l
(dot)
c
o
m

Laughing out loud

clever method!!thanks

Joined: 09/01/2009

Actually, I got it working how I like it. Thanks for the offer, though. Smile

Joined: 09/01/2009

And apologies for being so slow on getting around to it, but here's the video, in case you're still around and interested:

Joined: 01/29/2011

useful, thanks.
Currently, I am working on 3d water simulation with Fast Fourier Transform!!

Joined: 09/01/2009

Sweet! Let me know how it turns out. Smile