Tree/flora gen optimization from Danger - somebody run with it?

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
@TheyCallMeDanger is tweaking at code and ran into an optimization, but isn't big on GitHub, at least not yet. So he sent me this optimization suggestion - somebody world related want to try it out and toss it in a PR? :)

Danger said:
The original: (from FloraProvider.java)

Java:
public void process(GeneratingRegion region) {
    PlantFacet facet = new PlantFacet(region.getRegion(), region.getBorderForFacet(PlantFacet.class));
    SurfaceHeightFacet surface = region.getRegionFacet(SurfaceHeightFacet.class);
    DensityFacet density = region.getRegionFacet(DensityFacet.class);
    BiomeFacet biomeFacet = region.getRegionFacet(BiomeFacet.class);

    int minY = facet.getWorldRegion().minY();
    int maxY = facet.getWorldRegion().maxY();
    for (int z = facet.getRelativeRegion().minZ(); z <= facet.getRelativeRegion().maxZ(); ++z) {
        for (int x = facet.getRelativeRegion().minX(); x <= facet.getRelativeRegion().maxX(); ++x) {
            int height = TeraMath.floorToInt(surface.get(x, z));
            if (height >= minY && height < maxY) {
                CoreBiome biome = biomeFacet.get(x, z);
                height = height - minY + facet.getRelativeRegion().minY();

                if ((biome == CoreBiome.FOREST || biome == CoreBiome.PLAINS) && density.get(x, height, z) > 0  && density.get(x, height + 1, z) <= 0 && noiseTable.noise(x, z) < configuration.density) {
                    facet.set(x, height + 1, z, true);
                }
            }
        }
    }
    region.setRegionFacet(PlantFacet.class, facet);
}
The better way:
Pick a random number of trees/flora appropriate to the facet,
then for each tree/plant, pick a random x,z position in the facet,
then place the tree/plant.
The result is many many less iterations through the loop and all the associated calls.
x10 speed improvement, at least.
The original method iterates for each x for each z. For a 16x16 area, this is 256 iterations, vs probably 4 actual trees/plants.
I'm sure there are many other instances in the world generation that do similar things.

In general, instead of iterating through each x and z, iterate through the number of times you actually want to do something
(like place a tree, place lava, place a plant, etc) and generate a random x, z instead.
Even grass should do this, as it will cut CPU down by about 50%.
There may be some edge-effects where facets cross biomes, but they should be minimal and acceptable...
 

Marcin Sciesinski

Code ALL the Ages!
Contributor
World
Architecture
Problem is, that with the suggested "improvement" it changes what the code wants to accomplish. There is no "number of trees/flora appropriate to the facet" for a chunk/region. Also, due to the fact that this facet may be called multiple times for different region sizes (including overlapping), choosing anything at random would not be deterministic which is a requirement for any generation. A facet has to generate the same data for a specific block, no matter what region (containing said block) it is asked to generate.
 
Top