Procedurally generated foliage distribution

BlitzMax Forums/BlitzMax Programming/Procedurally generated foliage distribution

JoshK(Posted 2007) [#1]
I was reading about deco layers in the Unreal engine:
http://udn.epicgames.com/Two/CreatingDecoLayers

It looks like they use a "density map" to indicate where the foliage is. This is better than storing 10,000 instances of a mesh on the terrain. Presumably, you just input the player position on the terrain and generate a somewhat random distribution of foliage around them.

Any ideas on how I can procedurally a circle of foliage positions around the player? The foliage would be the same if the player left and came back, but I want to do this without storing 10,000 instances of foliage...I just want to be able to input a random seed or something, and have all the foliage instances get generated.

I supposed you could treat each pixel as a discreet area, and input the x and y pixel coordinates as the random seed, then use that to generate some number of foliage instances distributed across the area of that pixel...but I have a feeling there is a better way to do this.

Also, I'll need to z-sort the instances, so keep that in mind...maybe there is a way of generating the positions "radially"?


impixi(Posted 2007) [#2]
Banshee and/or jfk EO-11110 might be able to help you. They briefly discuss such issues in this thread:

Overlord (Terrain System)


SoggyP(Posted 2007) [#3]
Hello.

What about the use of fractals or some such bizarro maths thingymubob? At a very basic level using a sine wave would work in one dimension, eg, where the value of sin(x_pos) is above a certain level plant a tree. Obviously, this would be far too regular (and single dimensioned, obviously) but with a more complex formula would allow you the functionality you're after.

Goodbye.


impixi(Posted 2007) [#4]
For one of my prototype B3D landscape systems, I was dividing the terrain into a grid, and then pre-generating and storing the following information for each cell:

* Central coordinates
* Random coordinate offset values for each foliage item
* Foliage type for each set of offset values
* Foliage scaling, rotation and tilting for each instance

I used a pre-generated heightmap to determine the type of foliage (if any) that existed in a cell. A different heightmap was used to determine foliage density.

This method, while probably not the most optimal, constructed a reasonably realistic landscape. It also had the added benefit of a ‘built-in’ LOD system – for the immediate cells around the player’s position I created the relevant sprites/meshes, the rest, beyond the player’s visibility, I destroyed.

My biggest problem was performance. All the creating and deleting of entities reduced the frame-rate considerably. On its own it was acceptable, but when I factored in the other calculations that must be done in the main loop (enemy AI, collisions, etc) it was just too slow.

I tried another technique, based on Banshee’s suggestions, I think, whereby the foliage instances were hidden, rather than destroyed, when they moved out of the player’s visibility range. They were later ‘shifted’ into a new position and unhidden if a foliage item of the same type came into the player’s view. I can’t remember why, but I hit a barrier with this technique. At that point I more or less gave up on B3D, due to the size my project had attained.

Incidentally, if you want heightmap generating code for your experiments, see my sig…

EDIT: Clarification: When I mention foliage ‘type’, I mean a byte or integer ID number. NOT a sprite/mesh instance.


sswift(Posted 2007) [#5]
I think you have the right idea halo.

First, decide on the granularity of your grid. Ie, all locations where a plant could be. Then for each location within the player's view, using floating point locations if you need to to make your grid fine enough, multiply the Y by the width, and then add the X and use that as your unique random number seed.

Then, for each location, after you set the random number seed, do rnd(0, 1) and multiply this by the foliage density map's color divided by 255.0. This will produce a number from 0..1 with 0 wherever the foliage density map is black, and a random ditribution within it.

Then, if your result is say, > 0.9, randomly select, scale, and rotate a plant, or randomly generate a plant using however many random numbers you need.

This will ensure that plants appear at the same locatons, and look the same every time. And it will still allow you to generate only those numbers for the region surrounding the player, and adjust the foliage density for each area according to your density map!


SoggyP(Posted 2007) [#6]
Hello.

I still say go for the bizarro maths thingymubob because it means you don't have to store anything apart from a formula. So nyaah. :o)

Goodbye.


JoshK(Posted 2007) [#7]
Yeah, I am thinking bizarro maths is the way to go.

There's no "entities" to create and destroy, I just need a list of positions, and then I'll render however many instances of my mesh I need. I'd prefer not to generate any stored data, because the sheer numbers of things to sift through will slow it down.

So the player's xz position, rounded to the nearest pixel of the density map or heightmap, is input as the random seed...

It would be nice to be able to generate a circular shape around the player, instead of generating a square shape and distance-culling and z-ordering the instances. It would also be nice to be able to generate an arbitrary circle for any float position, instead of having to generate the data for all the "nearby" tiles.

hmmmm...

Maybe it would work to start by generating a grid of plant positions with a circle...use sin and cos to generate the grid, starting from the furthest out, and working your way inwards. Then you can add some randomness to the positions (but not enough that you would need to change the z-order).

So the first step would be to write an algorithm to generate points with a circle, in the order of distance from the center:



SoggyP(Posted 2007) [#8]
Hello.

Hurrah! I've managed to help Halo - perhaps he'll forgive me for pi55ing him off all those years ago by explaining that a plane was a thing that flew in the sky, but was different to a bird because it didn't have feathers, ask any chemist.

Though he's probably forgotten, of course, it's weighed terribly on me, I can tell you. Night after night of sheer worry I've had, never believing I could be so cruel. But that's all over now, of course. Because I'VE helped. So just watch it.

Ahem.

:o)

Goodbye.


impixi(Posted 2007) [#9]

Yeah, I am thinking bizarro maths is the way to go.



I agree! The only reason I did not go that route myself is because I’m useless at trigonometry. I’d be very interested to see what you come up with.


sswift(Posted 2007) [#10]
The method I outlined does not require you to generate any stored data. Other than that foliage density map you wanted. I only suggested that you COULD generate unique foliage for each location using that method. You could simply choose one of four static meshes and not even rotate or scale them at all.

If you don't want a density map, you don't need to use it with that method. But then your foliage will be of uniform density everywhere. But it will be randomly placed, yet remain the same when you come back.

If you don't want to use a density map and you don't want it uniform everywhere, you could use some kind of equation, but why go to all that trouble finding one that looks okay? YOu could just procedurally generate a small perlin noise map and use that as your density map if you must and you can make a unique one for each level by storing a single random number seed.


Chroma(Posted 2007) [#11]
Look and see how speedtree is doing it. Shouldn't be too hard to find. Plus I seem to remember reading about how they were doing foilage.


impixi(Posted 2007) [#12]
LOD/Performance-related article:

Rendering of Forest Scenes