Biomes

In honor of the new forum I decided to start adding “Biome” code into the lib. There’s a demo in the coming test project.



The current version has limitations. First it’s based on terrainquad, not terrain grid. This is because Forester isn’t gonna be terrain-grid compatible until next version. It also does not contain any world generation, but relies on pre-made alpha- and heightmaps. It is also not integrated with forester, so there are lots of stuff to fix.



The system itself is pretty simple tho. There’s an “EcoManager” that handles everything at the top. Through the eco manager you will add EcoSystems (large scale systems). Currently there’s only one ecosystem, and there is only one tile to display it and that’s the single terrain quad.



Each ecosystem has a name and a list of “Biotopes”. Biotopes are like small eco systems. Each biotope has a ground texture associated with it, and a list of plants. There’s also some other data, like which alpha map channel it should use, and texture scale etc.



Plants are divided up into grass and trees, so that forester can decide the proper system for loading them. It covers everything. Flowers are grass, and bushes and stuff are trees. Rocks are trees. Generally - if something has a 3d model, it is a tree, otherwise its a grass. Just like in forester.





The setup is not very advanced. Biotopes together with their plant lists contains all the information forester needs, and all the information the TerrainLighting material needs. Ecosystems contains a list of biotopes. The EcoManager handles everything. Here’s a snippet:







// Setup biotopes.



// Grassy groundtexture

Texture grassGroundTex = assetManager.loadTexture(“Textures/Terrain/splat/grass.dds”);

grassGroundTex.setWrap(WrapMode.Repeat);



// Biotope 1

Biotope grassyFields = new Biotope(“Grassy Fields”);

grassyFields.setGroundTex(grassGroundTex, grassScale);

grassyFields.setTextureData(0, Channel.Red);



// Grass texture

Material grassMat = assetManager.loadMaterial(“Materials/Grass/Greengrass.j3m”);

AlphaMipmapGenerator.generateMipMaps(grassMat.getTextureParam(“ColorMap”).getTextureValue().getImage(),1.4f);



// Plant object (only gonna be one)

Grass grass = new Grass(“Green grass”, grassMat, MeshType.CROSSQUADS);

grassyFields.addPlant(grass);



// Mountain texture

Texture mt = assetManager.loadTexture(“Textures/Terrain/splat/dirt.dds”);

mt.setWrap(WrapMode.Repeat);



// Biotope 2

Biotope mountains = new Biotope(“Mountains”);

mountains.setGroundTex(mt, dirtScale);

mountains.setTextureData(0, Channel.Green);



// Road texture

Texture road = assetManager.loadTexture(“Textures/Terrain/splat/dirt_ground.dds”);

road.setWrap(WrapMode.Repeat);



// Biotope 3.

Biotope roads = new Biotope(“Roads”);

roads.setGroundTex(road, dirtScale);

roads.setTextureData(0, Channel.Blue);



// Setup the EcoManager

EcoManager manager = new EcoManager();

manager.setTerrain(terrain);

// Add the biotopes.

Ecosystem ecoSystem = manager.getEcoSystem();

ecoSystem.addBiotope(grassyFields);

ecoSystem.addBiotope(mountains);

ecoSystem.addBiotope(roads);

7 Likes

I can barely wait to play with the next version of this lib :slight_smile:

Hehe and the bio stuff is working now. Gonna change EcoSystem into Biome I think. Honestly didn’t know how to translate, but I think Biome is the proper term for a large scale ecosystem.

Do you know if there is any built in way of generating the splat maps needed in the terrain system? Like saying “I want all areas below 10 units and maximal slope of 0.5 to have this texture” and then it returns an image with this information (given I’ve provided s heightmap). I hope you get what I mean…

Yes I get it, but I dont think there is a system like that. The TerrainFractalGridTest uses the height based terrain material, but it calculates which texture to use in the shader, based on height data. I don’t think it stores any splat maps. Sploreg probably knows.



EDIT: I know someone made a system like that as a school project and linked to it in the forums. Can’t find it in the search tho.

It should be a fairly simple filter to write though to take the terrain hightmap and then generate various other maps from it (for example a “steepness+height” filter to select areas for different vegetation, etc.

Yeah, it would not be to hard I think. I was just wondering if such thing already existed somewhere. In my eyes it would be a helpful tool inside the terraineditor and could beused to generate basic density maps for the BioMonkey (forester) aswell.

@kwando said:
Yeah, it would not be to hard I think. I was just wondering if such thing already existed somewhere. In my eyes it would be a helpful tool inside the terraineditor and could beused to generate basic density maps for the BioMonkey (forester) aswell.

Yeah, I just started writing stuff like this to generate splat maps so +1 about the usefulness :)

@jmaasing

Nice, if you want to trade some ideas or just discuss implementation details/problems etc. just post here.



Most of the stuff I got was made some time ago, and I haven’t looked at it for some time, but it’s very simple. It’s a regular height and slope based system. You feed it a heightmap and some numbers (like water level and maximum altitude), then the different terrain types has a few enums so the system knows what texture should be where.



This is how they look atm.





public enum Zone {

// This biotope is present under the water level.

Water,

// This biotope is present at low altitudes.

Low_Elevation,

// This biotope is present at medium altitudes.

Medium_Elevation,

// This biotope is present at high altitudes.

High_Elevation

}



public enum LandSubZone {

// This biotope is present at flat areas.

Flat,

// This biotope is present at slopes.

Slopes,

// This biotope is present at flat areas and slopes.

Uniform

}



public enum WaterSubZone {

// This biotope is present in deep areas only (as opposed to littoral areas).

Deep,

// This biotope is present near land (as opposed to deep areas).

Littoral,

// This biotope is present inside littoral areas, closest to land.

Coastal,

// This biotope is present inside littoral areas, but is further out

// from land then the coastal area.

Offshore,

// This biotope is present in both littoral and deep areas.

Uniform

}





I’m probably gonna revise this, but it works atm. There can be 3 zones below water, in case someone want that, but I guess one or two would be used normally. One beach type ground texture near land, and one for deeper areas.



There are three levels above water, and they can have two textures each - one for flat areas and one for sloped areas. Just like heightbasedterrain. It’s not gonna use the heightbased terrain material tho, but use generated textures instead.



Gonna add the posibility to randomize the terrains a bit later (use several textures at each level). Like maybe use a perlin noise with a threshold value to spread out two textures over the same zone. An example would be using both a forest and a plains area in the middle zone. A noise can be used with threshold value, 0.5 for example. If the value is 0.4 or below, the area is 100% forest. If it’s 0.6 or above, it’s 100% plains. With forest it would gradually go from 100% to 0% between 0.4 to 0.6, and the opposite for plains, which would make 50% of each at 0.5. Also it should be possible to change the ratio, of course.



I think it could be three-tiered as well. For example, forest between 0 and 0.4, plains between 0.6 and 1.0, then some shrubby type of intermediary zone in between. Like in a deep forest it’s usually just moss and stuff, but at the edges there are more grass and flowers but still some trees and bushes.

@androlo said:
@jmaasing
Nice, if you want to trade some ideas or just discuss implementation details/problems etc. just post here.


I'm having a hard time keeping up with your stuff as it is so I don't think I have a lot to contribute :) Will be away for a week also.

But basically I'm toying with generating terrain for a space game so my "biomes" have names like carbon dioxide, regolith and the like. Still, it is fun to see that I've come up with similar stuff although not as advanced, and mine is a lot more hardwired hack.

This is what I'm doing currently to generate the terrain and splat map:
* I generate a heightmap from Perlin noise, the splatmap is set to 0xff for that color component (say Red).
* Then I generate a "layer" of regolith for each point in the height map unless the height is too high or the slope is to great. This goes into the splat map color component (say Green) I use a transition area for the slope "patches" so that I get a bit of gradient blending in the splat map.
* Next I generate a Perlin noise map-based "layer" for frozen carbon dioxide with a height threshold (i.e. this layer should not be higher than x in the terrain). This goes into the splat map as Blue.
* Next is a frozen water ice layer in the Alpha component with the same logic as carbon dioxide.

Currently for each step I normalize the color components in the splat map so the sum is 255. Don't know if that is needed but I thought it looked better, or I was to tired so I just fooled myself :)

This is a naive and simple algorithm but still creates pretty nice terrain. I guess that many types of terrain can be created using the ideas you write about. You have some "constraints" on where a certain type of zone/biome or layer as I called them should be, it can be constrained on height, on slope, on noise functions or even static (tileable) images. When the layers have been created one needs to make a splat map with some nice blending of the layers and maybe adjust the heightmap (I adjust it upwards for each "layer" to simulate accretion of material).

The next thing I was planning on was to place game related resource in the terrain, it could be boulders or anthills :) Just to get a bit of weird space feeling I was thinking about using a voronoi type of image as a density seed to place them. This is pretty inspired by your grass density maps.

I thought about making some kind of image viewing tool to make it easier to see the layers/zones as grayscale images. And also to tie in some type of scripting to generate them. I find myself doing a lot of tweaking of constants and re-running the app to see what happened. A lot of that could probably go quicker if I could just press play on a beanshell-script and look at the image it generates.

Yeah, so anyhoo, that is what I'm doing. I'm sure a lot of people are doing similar things so I think there is a good chance the forum could whip up some framework/lib/tools we all could benefit from.

@jmaasing

Yes sounds like the “general idea” is pretty similar. I think zarchs image tools will be great for this kind of stuff. It’ll make everything a lot easier.



Btw, I think normalizing colors is a good idea. Ran a terrain with a poorly made alpha map once, when I just started testing AtoC, and the terrain became semi transparent at some places. I figured it had something to do with how the textures are blended. Maybe each layer gets an alpha value or something, depending on the color values, and if they dont add up to 1 the final color becomes partially transparent. Didn’t follow up on it tho.


Yes sounds like the "general idea" is pretty similar. I think zarchs image tools will be great for this kind of stuff. It'll make everything a lot easier.

Btw, I think normalizing colors is a good idea. Ran a terrain with a poorly made alpha map once, when I just started testing AtoC, and the terrain became semi transparent at some places. I figured it had something to do with how the textures are blended. Maybe each layer gets an alpha value or something, depending on the color values, and if they dont add up to 1 the final color becomes partially transparent. Didn't follow up on it tho.


Yeah I just got started with Java2D-image conversions when zarch posted his stuff, it will make this stuff so much easier, really hope it gets put in core (I'll use it anyway but still).

What you describe about texture blending makes sense, I think that is exactly how it works: If you give it (50,50,0,0) it will mix 20% from one texture, 20% from another and the rest will be left with full transparency. I was worried about the other case: the difference between (128,128, 0, 0) and (255, 255, 0, 0). I'll look into the terrain shader one of these days :)

I’m adding a very simple actor to the system now. He has a first person view (no model), but is using a charater control so that you can move him around and jump etc. It’ll work like in the hello collision tutorial.



The class itself implements ActionListener, and contains the charactercontrol, so it’ll be possible to add the actor to a scene and have the physics objects + keyboard/mouse controls set up automatically.



On top of this, the actor will have access to terrain/biome data. The first feature I intend to add is the ability to know what type of terrain the actor is on, and alter values such as walk- and running speed depending on that.



I have already begun working on that system. Every update the terrain alpha map is read. The biome system knows what terrain type is in each channel, and each terrain type is associated with a speed reduction constant.



To calculate speed reduction, the system calculates the sum of the values of the alpha map weighted by the speed reduction of each terrain type. Here’s an example:



The actor is in a position that corresponds to rgb = (0.6 , 0.4 , 0.0) on the alpha map.



Red channel is grass, which has a 1.0 speed modifier.

Green channel is forest, which has a 0.7 speed modifier.

Blue channel is swamp, which has a 0.3 speed modifier.



The total speed modifier is 0.61.0 + 0.40.7 + 0.0*0.3 = 0.88 (a 12% slowdown from default).



Why bother with many channels? Because alphamaps are generally smooth. This means if the values are blended, the speed increases/decreases will also be somewhat smooth.The system will also keep track of which terrain type is dominant at each point. This is done simply by comparing the values and choosing the highest one.



Keeping track of the dominant terrain type can be useful for debugging and other stuff. One possibility is for example to use Biotope.toString() to write the name of the dominant (active) terrain type as text onto the screen. In fact I’m gonna make a bitmap text object available in the Actor class that writes out the active terrain type name.



I don’t know exactly where to place the values yet. Maybe I’ll just add a terrain type enum, and then let people set the base speed modification values (in percent) within the Actor class. Or they could be added to the terrain types themselves. That would be unnecessary data for many systems tho, so I don’t know. This is just a preliminary system atm.



Also it will of course be based on the new getPixel stuff, so I woun’t finalize it until the getPixel stuff is in place.

Sounds nice. The only thing I wonder though is if you aren’t specialising it a little too much by doing the speed thing. There are all sorts of other things that might be effected too (for example fire based spells not so good in swamp, etc)



It might be better to have an enummap (or whatever) of terraintype->float amount that gives you the % for each terrain type and that can be queried. People can then use whatever algorithm they like on top of that.

Yeah, I second what zarch just said.

Yeah what those guys said. I think you need some way to get at the terrain meta-data and setting the speed is a good example but don’t get hung up on that. On my todo-list is generating particles based on the terrain texture - say a wheel skidding in the sand or even better a hover craft (like I’m doing) since then speed is uninteresting but the terrain type still is.



Not so sure that sampling the splat-map is the best way tho. There might be more information used in creating the terrain than is visible in the splat-map. For example I layer things on top of each other (say, stone, mud, grass) when generating terrain, the layer of mud can affect the height of the terrain but it is completely covered by the grass-texture but still significant.

I toyed with using an array of generation parameter objects associated with each point in the height map and a getTerrainMetaData(int x, int z) addition to the TerrainQuad (input is height map coords - but could be converted from world using terrain scale and rounding). This is so that if I explode something I can change the height of the terrain and redo the splat-map and remove the grass while still keeping the underlying mud intact.



So in this case I really don’t want interpolated values directly from the terrain, I want the basic data structure used when generating. Or put it another way, I have a game significant interest in getting terrain data used in calculating the terrain and not the resulting artifacts like splat maps or heightfields.



There is a use case for getting the value of the splat map and use that and also for getting data tied to the generation of the heightmap+splatmap and why not even getting interpolated values from the TerrainQuad in the same way as getHeight does it.



I suggest you leave that to the application, as long as there are nice places to hook that up (like subclassing or maybe some BiomeGeneratorInterface that I could implement).



Those are the things I’m playing with, don’t have any solutions or proposals on how to design this yet, hope that crystalizes on this forum :slight_smile:

This works through alpha maps. It’s just to give people a feel of how to interact with the terrains etc. Show that it can be used for that kind of stuff.

The actor stuff will be put in the demo only, not the lib. Haven’t figured out yet how to do with the rest, but there is a TerrainAdapter interface that provides biomonkey with all info it could ever need from terrrains and terrain materials.



EDIT: I have figured it out. The terrain adapter has a method to get alpha map values now based on a world location (same value can be used for getHeight as well). Now people can just use that hook to do whaterver they like. I will add the speed and dominant terrain type into the actor class, just as an example of how to use the terrain adapter. The blending formula etc. will all be in the actor class, including a Map that links biotope indices with speed modifiers.

Aha, now I get it, yeah, that sounds fine :slight_smile: Will be a lot of fun to use this.

I have now got the basic structure in place, btw. The EcoManager (name will likely change) will be responsible for the terrain and vegetation stuff. Originally I was gonna go with a forester instance and a terrainquad/grid instance within the EcoManager, but I will instead change the Forester class into the EcoManager.



Instead of adding grass and treeloaders manually, they will be set up automatically with basic settings derived from the terrain object (tile size etc.). The parameters can be tweaked tho.



The big difference is you’ll not be setting up the tree/grassloaders manually anymore, like in forester. You just initialize the EcoManager with some stuff, then add a new grass and trees objects, and maybe tweak some params (like tile resolution and stuff). The Loaders and Layers etc. (forester objects) will no longer be exposed.

Example:



[java]

EcoManager em= new EcoManager(blahblahblah); // <-- Mandatory



em.getGrassParams().setFarViewingRange(500f); // <-- Optional

em.getTreeParams().setPageResolution(4); // <-- Optional



Grass tg = em.createGrass(“Timothy grass”,grassTex); // <-- Mandatory



tg.getGrassParams().setMeshType(MeshType.QUADS); // <-- Optional

tg.getGrassParams().setMaximumSlope(40) // <-- Optional



Biotope fields = em.createBiotope(“Grassy Fields”); // <-- Mandatory

fields.addPlant(tg);





[/java]







The eco manager will put up one grass and one treeloader instance, and those will handle grass and trees. It will use terramonkey for everything terrain-related.