Customizing FluidVolume

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Phippu
Posts: 24
Joined: Fri Jun 03, 2011 3:39 pm

Customizing FluidVolume

Post by Phippu »

Hi norbo

I am just playing around with the FluidVolume class. I've implemented a little game that now uses gerstner waves to render a more realistic ocean than just a textured plane. For now these waves have only been a visual eye-candy, but the waves have no physical influence to the objects that are floating within. So I was wondering how I could implement this. To do so I've modified the FluidVolume a bit. What I have from my wave function is:

- a method that returns the normal of the wave at a specific point
- a method that returns the height of the wave at a specific point
- a method that returns the complete offset for a specific point (my wavefunction includes longitudinal waves as well, so this might be useful)

Code: Select all

        float GetWaveHeight(Vector2 initialPosition);
        Vector3 GetWaveNormal(Vector2 initialPosition);
        Vector3 GetWavePosition(Vector2 initialPosition);
So my question is how do I combine this into the FluidVolume? I've tried already the following:
[*]I've replaced the code that checks if the entity is in the water just by the following:

Code: Select all

                    Vector3 position = entityEntry.worldTransform.Position;
                    if (position.Y > WaveSampler.GetWaveHeight(new Vector2(position.X, position.Z)))
                    {
                        return;
                    }
[*]I've replaced the upvector with the normal of the wave

Well, that works, but as usual not as expected:-D Now my boat jumps up and down a bit unrealistic and the boat seems to float around instead of performing something like rolling.

I guess I not doing this correctly, can you give me a hint how to implement proper behaviour (i.E the boat should drift and climb if a huge wave comes in).

PS: there's a little video of my game, it includes several boats with the BEPU logo on it :P http://www.youtube.com/watch?v=MwX8_taklLM
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Customizing FluidVolume

Post by Norbo »

I've replaced the code that checks if the entity is in the water just by the following:
Checking only the position of the entity to determine if buoyancy should be computed will tend to produce nasty oscillatory behavior. Consider what happens if the position is just barely above the surface, but the boat's hull extends under the water. Under this system, no buoyancy is applied and the boat will 'fall' into the water until the position hits the surface. Then, it will find that the hull is quite deep and apply a large buoyancy force, pushing it out of the water.
I've replaced the upvector with the normal of the wave
While this could produce some types of desired behavior, it will confuse other parts of the system.

One possible 'proper' solution would look something like this:
1) Since the surface of the water is no longer a flat plane, the bounding box based early outs at the start of the GetBuoyancyInformation are less useful. They could still be used if you could grab the minimum and maximum water surface heights for comparison against the maximum and minimum of the entity bounding box, but doing that probably won't be worth it unless you have an appropriate acceleration structure built for the water surface (which probably doesn't exist, and if it doesn't, it's probably not worth adding).

Note: If you remove these early outs, keep an eye out for later systems that may have depended on the guarantees offered by the early outs. I may have forgotten about some since it's been a while since I've fiddled with the FluidVolume.

2) Embrace the columnar numerical integration used by the fluid volume to detect submerged volume.

Some background:
This numerical integration works by checking a grid of rays against the entity. The rays originate at the bottom of the entity's bounding box and point straight up. Each ray corresponds to a column of volume. If the ray hits the entity, it will use a second ray starting in the same horizontal location but at the water surface and pointing down.

The height between the lower ray intersection and the upper ray intersection gives the height of the submerged column. The size of each grid cell in the integration (given by the number of samples per dimension and the size of the bounding box) gives the width and length of the column. Multiplying these together gives you the approximate submerged volume of the entity for that column.

This process is repeated for all grid samples. The more samples are used, the more accurate the resulting submerged volume is.

The necessary modification:
Right now, a "maxLength" is passed into each call of the GetSubmergedHeight method. It represents the distance from the ray origin to the surface of the water. In the current system, the surface of the water is always at y = 0. You'll need to replace this with the distance from the ray origin to the water surface at each ray sample's horizontal location. So, move the definition of maxLength inside the sampling loop and change it to:

Code: Select all

float maxLength = GetWaveHeight(horizontalLocation) - entityBoundingBox.Min.Y;
Note: All of this integration takes place in the FluidVolume's local space. Watch out for this when sampling your wave function; make sure you're picking the right place or the graphics will be offset.

3) Make sure the bounding box of the fluid volume contains the highest waves.

4) Probably a couple of small things I've forgotten about :)

By doing all of the above, the integrated center of submerged volume will be in the correct location. This gives you 'rolling' behavior (when a wave hits the side of the boat, the submerged volume will tend to be on one side, so most buoyancy force will be on that one side, and gravity will pull down the other side) and 'surfing' and just about everything else.

The above won't simulate horizontal 'flow' behaviors, though. If you have a particularly large wave which is expected to cause an undertow or similar flow effect, you could apply arbitrary horizontal impulses separate from the buoyancy.

I should mention that revisions to the fluid volume, possibly containing changes like this, could show up eventually- but it could be months or even more than a year. FluidVolumes aren't exactly the highest priority :)
PS: there's a little video of my game, it includes several boats with the BEPU logo on it http://www.youtube.com/watch?v=MwX8_taklLM
Very nice :)
Phippu
Posts: 24
Joined: Fri Jun 03, 2011 3:39 pm

Re: Customizing FluidVolume

Post by Phippu »

Wow, great, thank you!

I've have built something like the acceleration structure and implemented an custom FluidVolume. It is not yet perfect, but I am definitifely on the right way.

Great support Norbo, thx again!
Post Reply