Running water, early video

Interesting stuff :slight_smile:



Would be really interesting if you could place a few “springs” on the terrain and it would automatically run the water downhill from there and erode/join them until they find other water :slight_smile:



Erosion would need to be able to carve a bit deeper and make real valleys for that to really work though.

@zarch said:
Erosion would need to be able to carve a bit deeper and make real valleys for that to really work though.

I guess its kinda hard to implement so that its usable for anything but terrain editing really which would probably not justify bloating the api itself with such things. Maybe thats better done with external tools / classes.. I mean you wouldn't want your MMO world to erode all the time ;)

Yeah that stuff sounds more like what those particle systems does. This will be a somewhat cheap approach with simple generation and shading. It will be good enough for the nature scenes and stuff that I’m trying to do. If it turns out ok, maybe it can be used in games and stuff as well.



The forking I think will be the first thing to fix after it’s good to go. I know another system uses graphs, and it works well. That system also has a very clever idea - when two channels join, the one below gets bigger. Like if a river joins with another river, the result is a bigger river. This would be trivial to implement, just modify the width/depth value of the verts downstream. :slight_smile: Maybe just by adding the two widths and depths together.



That other water stuff is found here btw: http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/



Been working on a similar system on and off, with all manner of terrain generation stuff, but I am getting a bit turned off. Even the author himself says it may not be good focusing too hard on a particular aspect of the game/app, trying to make it perfect. It may be better to concentrate on what is practical, so that’s what I’m doing (I guess that’s Normens sentiment as well).

@normen said:
I guess its kinda hard to implement so that its usable for anything but terrain editing really which would probably not justify bloating the api itself with such things. Maybe thats better done with external tools / classes.. I mean you wouldn't want your MMO world to erode all the time ;)

Yep, absolutely. The erosion thing would be a world generation tool, not a part of the core API. It is connected to the stuff about modifying the terrain to fit the river into it/etc though. Really that could all be done as part of world generation and then the realtime API just handles filling the channel with water.

@androlo said:
The forking I think will be the first thing to fix after it's good to go. I know another system uses graphs, and it works well. That system also has a very clever idea - when two channels join, the one below gets bigger. Like if a river joins with another river, the result is a bigger river. This would be trivial to implement, just modify the width/depth value of the verts downstream. :) Maybe just by adding the two widths and depths together.


Just remember to add the volumes together, not the separate width and depth. (i.e. if you have a 2*2 stream join a 3*3 river the result is a 3.6*3.6 river not a 5*5 river)

I didn’t specify this, but the system is supposed to be run once (or once every time the parameters are changed), then the data should be saved. It creates a new heightmap and splat map. It then creates a flow-map for the water, and a mesh that is used to draw the water on. The heightmap, splatmap and flowmap is written to image files so they can be re-used. The river data (mesh and other stuff) will be put in a class that can be written as well. It is not designed for real time modifications of neither terrain nor water (at least its not optimized for that).



There is no real separation between terrain modification and the other river generation stuff either, they depend heavily on each other to make flowmaps and meshes smooth. Getting it right is hard. Once this is working well, the highest priority will be to extend the graph to make it possible for channels to join and split. For example, to create two channels around an island. Minor splits (around rocks etc) will be handled on the “micro level” (by diverting flow vectors locally).

2 Likes

This is progressing nicely. I chose a catmull-rom spline for the river curve works now, but I have not yet applied any noise to it. That will be done when the basic stuff works.



The terrain brush works well.



The mesh is coded, but I haven’t tried it yet. It’ll probably need to be debugged for some time, and then smoothed out etc.



The part I’m working on now is the final part - the flowmap generation. It is the hardest part, but I figured out a way to deal with it.



It’s great having a well thought out process to follow. Everything happens quicker, and you can focus a lot on the details.

2 Likes

Some crappy pictures of the river terrain brush. It works now, but there needs to be noised and smoothed etc. Also I will splat the river texture next, then the terrain part is finished.



The first one is a pretty shallow canal on a flat terrain (black heightmap).



http://www.jamtlandoutdoors.se/images/dist/riverbrush_1.png



This one is of a slightly more complex path, running diagonally down a terrain with a constant 45 degree slope.



http://www.jamtlandoutdoors.se/images/dist/riverbrush_2.png



This one is taken of the river splitting around a small strip of land, then joining again. The terrain brush can handle it, but the flowmap and water mesh generators can’t.



http://www.jamtlandoutdoors.se/images/dist/riverbrush_3.png



All in all, it works well. The river is also affected by how many verts are added initially etc, so it can be made to look better and worse.



I’m thinking about including a simple point and direction, then generate the river along a random path, but centered around that line. Maybe its useful.

2 Likes

A video with some info.



http://www.youtube.com/watch?v=h5zqcU6ySRw

3 Likes

Thanks for the vid :slight_smile:



Will I be able to use this with my normal premade heightmap? I also have water filter in my map as lakes. So in order to use this, I have to make the river vertex points at a higher ground, in order not to mix with the water filter, right?

@staugaard said:
Will I be able to use this with my normal premade heightmap? I also have water filter in my map as lakes. So in order to use this, I have to make the river vertex points at a higher ground, in order not to mix with the water filter, right?


First of all yes, you can use with any heightmap. Also I have thought about the lake stuff. The rivers will of course have to connect with lakes and seas, but that is a later problem. The graph will probably be extended to create lakes and seas later (introducing different kinds of points). Until then it's a matter of fitting things together. It can be done by trying different depth values at the final vert, and by moving the water geometry around (it's just a normal geometry, and there will be some margins).
1 Like

So, you are saying that this will have the underwater effect, as the waterfilter have?

I haven’t really thought about that stuff yet.



Anyways, here’s the river from the vid, but with a gaussian blur applied to the splat map and depth values. Sharp edges are gone. Next I will start noising.



http://www.jamtlandoutdoors.se/images/dist/blurred_river.png

some inspiration



http://topmy.com/2012/02/24/glacier-river/

http://blogs.nature.com/a_mad_hemorrhage/2011/11/14/waterfall.jpg



Keep pushing the limits.

I’m no physics expert but I haven’t seen velocity discussed much.8)

The velocity is in the flowmap. There’s some stuff about that in the video in the first post (tho the water looks better now then it did then).



Made a vid of the water mesh.



http://www.youtube.com/watch?v=fbFlPNYSzKM

2 Likes

Dang, androlo! I missed this somehow?! Definitely will this use in my project at a later stage :slight_smile:

On top of the stuff mentioned in the vid, I’m probably also gonna run some mesh processing to correct for folds etc.



The mesh topology is extremely simple. It’s just two curves put together. The curves have the same amount of verts, and finding the corresponding vert on the other side is just looking one element forward in the buffer (or back, depending on how you iterate).



A height correction step would be easy to make. For example, check the the heights of the verts (like 5 verts at a time). If the height differences are too large, just smooth them out over that interval. It would also be simple to decimate the mesh and do a bunch of other stuff,



That does not fix poor design tho. When the mesh folds it does so because it has to. Like for example, if you make a crappy uv-mapping in blender and it doesn’t fit, the best solution isn’t always to run a relaxation script or something. It may be better to re-do the seams.

@androlo

You say its a problem with the folding of the mesh, but is it? If you have a sharp corner like that, the water will create some turbulense. Maybe it will look realistic after all? :slight_smile:



Cant wait to see more of this project!

And a height difference in the river, may also be realistic, if the water flow runs fast.

@staugaard

Pretty interesting.I guess with some well placed “foam” particles or something (like in skyrim) it could look pretty good. At least if it’s just a sharp downward slope (not going back under then out again i guess).



Some smoothing will make the mesh look better tho I think. In fact just running the gaussian blur filter used on the splatmap would suffice. It can be used on a 1D array as well. Gonna try that right away.



Also I think an underwater filter could be applied by raytracing from the camera and up (instead of checking if cam.y < waterlevel). Maybe a version of the jme post processing water could be used. Haven’t looked into it.



Btw. I set up a google code page, It’s at http://code.google.com/p/jme-running-water/. No contents yet but I’ll start updating the repo with alpha code as soon as the flowmap stuff is finished, and shaders are linked etc.

1 Like

I’ve been thinking about a simple vertex sorting algorithm. The height is not a problem and can be smoothed etc. It’s the xz location that has to be fixed.



Basically, the goal should be to make sure that the position of vertex v(n + 1) is not less then that of v(n).



In practical terms I need to determine if the verts v(n - 1) and v(n + 1) lie on the same side of the line drawn between v(n) and its counterpart on the other side of the river. In that case we get a fold. That can be checked by dotting v(n - 1) - v(n) and v(n + 1) - v(n) with the unit normal of that line, for example. The unit normal of that line is also the normalized tangent of the river spline at that point, which is already stored.



The algorithm should also not push verts too far away from their original positions. If the verts are displaced too much it may create gaps between terrain and water etc.



I think I will start by using this method:



Algorithm pseudo code:



for( n = 1 ; n < array.length - 1; n++ ){



v(n - 1) = array[n - 1]

v(n) = array[n]

v(n + 1) = array[n + 1]



vec2 curveTan = “Tangent of river spline at v(n)” (normalized)

vec2 first = normalize(v(n - 1) - v(n))

vec2 second = normalize(v(n + 1) - v(n))



val1 = dot(first, curveTan)

val2 = dot(second, curveTan)



if( sign(val1) != sign(val2) )

continue



else

v(n+1).pos = v(n).pos ← Move v(n+1) to the position of v(n).

v(n).pos = (v(n+1).pos + v(n-1).pos) * 0.5 ← put v(n) half way between its old position and v(n-1)

continue

}



If v(0) < v(1), then v(n-1) is less then v(n) for all n (by induction). A separate step should be done first to ensure that.



If this is run over a number of verts that are clumped together, the distance between the first and last vert in that cluster would be low. I think maybe it would be better to just merge all the weird points into one, but I don’t want to destroy the one-to-one relation between the two sides. Gonna see how this turns out.