Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Liquid flow over heightmap

Discussion in 'Scripting' started by jomsa, Nov 28, 2016.

  1. jomsa

    jomsa

    Joined:
    Nov 10, 2013
    Posts:
    23
    I've been in search for code example (in language that i can actually understand C / C#) of an algorithm which allows me to "flood" heightmap with liquid (water) step by step.

    All i have found so far are bits and pieces but nothing solid.

    So the situtation is that ihave array of heights (float) Hmap[x,y] and i want to make simple simulation of water flowing over this heightmap. I am also hoping to get a read on somesort of "displacement" power how much water is travelling over certain point in the map for use of other functions i might add (maybe erosion or something).

    Any tips or straight algorithms that deal with this? (and yes i've googled it around, but i am not sure if i got the proper technical keywords)
     
  2. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    marching cubes?
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,848
    Ha ha. Good one! :D

    There is no simple solution for this. Simulating incompressible fluids is really, really hard. Simulating compressible ones is only slightly easier.

    So, yeah, of course it can be done, but expect to spend a few months digging deeply into very technical papers (or hiring someone to do it for you).

    I guess the simplest I can think of is probably to model your fluid as a bunch of little spheres. Drop 'em on the terrain and let the physics engine roll them around. This will be a decent approximation of fluid behavior, though of course it won't look anything like fluid. To solve that, you could hide them, and compute a mesh around wherever they are (perhaps using marching cubes, as @jister suggested).
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    JoeStrout likes this.
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Liquid simulations are complex. I mean really, really complex. I spent several years studying fluid dynamics at University. And yet I am still struggling to build a basic believable simulation from scratch in Unity. Of course I'm trying to incorporate rain and evaporation, which are likely not needed for your approach.

    There are two basic approaches to fluid simulations.
    • Grid simulation. This basically involves building an array that holds data on every position. Fluid movement is calculated by calculating the movement of fluid into and out of every cell.
    • Particle simulation. Fluid is broken up into a bunch of particles. Each particle has physics applied.
    Both techniques then require a rendering step to convert the concentrations into an actual surface.

    Depending on exactly what you are looking for, you can also get away with just simulating the water surface. This can be much easier, but much less accurate.

    So given all of that, I would suggest a grid based approach. Use a 2D grid. Set each cell to be the height of the water. To figure out flows, compare the height of the water + terrain to the height of the water + terrain in all the surrounding cells.
     
  6. jomsa

    jomsa

    Joined:
    Nov 10, 2013
    Posts:
    23
    This is exactly what i was thinking. The water does not need to exist on.. break waves. Just 2d flow. I had the algorithm that did this years written in C and it worked like a charm. I dont need "realistic" waterflow. Just need the grid stuff to do some simple erosion calculation.
     
  7. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    In that case the algorithm becomes very simple. In psuedo code

    Code (CSharp):
    1. float [,] waterHeight; // Needs to be buffered, not shown here
    2. float [,] heightMap;
    3. float diffusionFactor; // Anything above about 0.2 will give an unstable simulation.
    4.  
    5. void DoFlowTick (){
    6.     for (int x = 0; x < waterHeight.GetLength(0); x++){
    7.         for (int y = 0; y < waterHeight.GetLength(0); y++){
    8.             float heightDifference = TotalHieght(x-1, y) - TotalHeight(x, y);
    9.             if (heightDifference > 0) {
    10.                 float waterLevel = waterHeight [x-1, y];
    11.                 waterHeight [x, y] += heightDifference * waterLevel * diffusionFactor;
    12.                 waterHeight [x-1 ,y] -= heightDifference * waterLevel * diffusionFactor;
    13.             }
    14.             // And so on in all the cardinal directions.
    15.         }
    16.     }
    17. }
    18.  
    19. float TotalHeight (int x, int y){
    20.     return waterHeight[x,y] + heightMap[x,y];
    21. }
    This was written on the fly, expect bugs.

    In practice I find I get a more stable simulation with a double buffer system. You'll also need to deal with the viscosity artefacts that this simulation brings if your tick time is too small. You will also get 'square flow' and diagonal artefacts if your cell size is too small. You'll also need to deal with bounds checking and the like.

    Like I said, fluid simulations can get complex. And there are a thousand edge cases that will crop up. But they are certainly fun.
     
    rbisso, likeprog and LiterallyJeff like this.