Generating vegetation – paged geometry style

@mifth

It may sound better then it is heh, also the paging system is far from done. Couple of weeks i think, at least. Not sure what to make of it (a lib, code pages), I’ll make it and see what happens.



The actual generator (at least the parts ive completed) is basically just transcribed from the PG engine source, with a few updates and changes. It uses the CPU to calculate positions, build meshes etc. Some stuff, like grass animations etc. is in the shaders.



Btw. get a load of this:



compile-single:

run-single:

Sampling 100000000 random floating point numbers.

Time taken for fast: 415.36368

Time taken for slow (java): 1530.294

Sampling 100000000 random floating point numbers.

Time taken for fast: 404.29938

Time taken for slow (java): 1530.1299

Sampling 100000000 random floating point numbers.

Time taken for fast: 402.24176

Time taken for slow (java): 1524.5559

BUILD SUCCESSFUL (total time: 6 seconds)




Its from my new random generator :slight_smile:



Not perfect measuring of course just checked system.nanotime before and after each loop. The precision is pretty much the same. This is from sampling and checking if its uniform. Each partition is 1/10th of the interval [0,1], and they seem to land uniformly within those. I’ve tried larger and smaller partitions as well.



Sampling 10000000 random numbers in [0,1].

Number of partitions: 10

Using fast generator

Partition 1: 0.0999716

Partition 2: 0.0999375

Partition 3: 0.1001207

Partition 4: 0.099938

Partition 5: 0.0998954

Partition 6: 0.1001462

Partition 7: 0.1000686

Partition 8: 0.1000338

Partition 9: 0.1000256

Partition 10: 0.0998626

Max deviation: 1.3740361E-4



Sampling 10000000 random numbers in [0,1].

Number of partitions: 10

Using standard generator (java)

Partition 1: 0.1001091

Partition 2: 0.0999581

Partition 3: 0.099842

Partition 4: 0.0997741

Partition 5: 0.099973

Partition 6: 0.1000415

Partition 7: 0.1000817

Partition 8: 0.0999945

Partition 9: 0.1000933

Partition 10: 0.1001327

Max deviation: 2.259016E-4

1 Like

This is the core, feel free to use.



[java]public class FastRandom {



private static long x = System.currentTimeMillis();

private static final long fL = 0xffffffffL;



private static long next()

{

x ^= (x << 21);

x ^= (x >>> 35);

x ^= (x << 4);

return x;

}



public static float unitRandom()

{

return ((float)(next() & fL) / (float)fL);

}



}[/java]

1 Like

Sorry took some time to scramble everything together, but here are some pics of the grass, just to show basic functionality.



This is some thick grass.





This is grass loaded but with a density map restricting where it is loaded. When you work in Ogitor for example, you paint grass onto the terrain like you splat textures, and the painting you do is stored in a density map. The map used here is just a circular gradient from the middle to some way out.







Color maps are also supported. This image is generated with the same grass texture.







A color map is just an image. When a quad is generated and put into the grass mesh, the grassloader reads the color values of the image at the quads loc and stores them as vertex colors. This can be used to create subtle shifts in grass color over an area, for example, or to change grass color based on the color of the terrain. Like the diffuse map (texture) of the grass is for micro control (each patch), while the color map is for macro control (each field).



Both density and colormaps can be stretched over any given area, and to prevent pixelation there is a bi-linear filtering alternative.

Is it possible to use the generator for polygonal suface (not a quad)?



Something like:

http://imageshack.us/photo/my-images/263/generateo.jpg/







I’m interested how to realize collision detection of rays and the surface.

@Mifth

Well, yes. And I’m talking about the generators current, original form now. It may become more versatile later once I’ve got it all in place.



There are three alternatives i can think of.


  1. Density map - I’m assuming the surface is flat, or have got a function to get height (y) data at any point, like a terrain quad.



    You can tell the tree loader to only place instances within the area of the geometry by utilizing a density map.



    Step 1: Create a RectBounds object from the geometries bounding box’s xz-coords (A lot easier then it sounds…).



    Step 2: Create a densitymap of any (square) dimensions.



    Step3: Make the density map white where your geometry is, and black elsewhere. No need to align it with the bounds, that is taken care of by the density map image sampler, just keep the same aspect ratio as the bounds to make it simple.



    Step4: Run the generator. It will only place objects where the white pixels are, and at the proper heights (0 if no height function is available).


  2. Height data



    This requires no density map. It’s the method you use to place grass only above sea level on a terrain, for instance.



    Step 1: Bound your area like in the previous example.



    Step 2: If you have a function providing height data from your geometry (like a ray caster), you can just use the built in yMin yMax filter to restrict instance placement outside the geometry. Make the function return 0 or -1 or something if a point is outside the geometry and set the generator to generate only at height values > yMin.



    Step 3: Run the generator.


  3. Static placement



    Place your geometry and the objects in an editor (Ogitor is the only one i am working with atm., they use ogremeshes also), then export the stuff into jME (there will be lib methods for that).



    This import/export thing is subject to lots of change however.



    I will write tutorials once the lib is made, but its probably gonna be a few weeks. I will go through the standard stuff in those.

Damn shader is crapping out. Gonna have to do a bunch of stuff…

Hell I’m waiting for this, currently polishing up all foliage and tree models for the different binomes :wink:

@EmpirePhoenix

Hehe hope it wount dissapoint.



I’m starting with the paging system now, so I woun’t be able to get any more screens (or run the app) until I’m done. Gonna drop by here every day to check for comments tho. If anyone has any input, suggestions questions etc., add it to this thread please.

It is a pretty big, complex lib after all, with the paging engine and all. And lots of heavy code. It’s hard to balance convenience and speed also, because with too little convenience classes/methods it will be almost impossible to use for a beginner.



I might end up making one “light lib” or something, that’s easier to use, have a ready-to-use simple class for building stuff, but does not have all functions.



Then i put all classes together and make one “pro” lib, with little to no convenience (that you basically have to configure yourself).

Well let’s see how speed will be once done :slight_smile: I bet there are some stuff that can be optimized by then via threading or similar.

I hope so. I’m looking at an article in GPU Gems 2 about virtual botany where they use a slightly different approach to billboard grass, with billboard alignment taking place in the shader (there is both a fixed quad and billboard system in PG).



I normally use billboards for thin layers, like one type of flower, then fixed quads for thick covers of grass.



Most of the stuff from the article is already in place in PG (and my lib soon), but not everything. Like shadow rendering. Hope to try that stuff out.

I am separating the paging system from the rest of the lib, so that it can be used for other purposes.



Also I want to make it possible to save any generated grass/tree pages as j3o binaries. That would be really awesome.



The paging system could then maybe be used for any type of j3o. Ogre3d use a similar technique for terrain paging. Not sure how that would work in practice tho.



Damn im hurrying now, so much stuff to try.

Erm that would be increadibly easy to do. Instead of TreeLoader and GrassLoader i add a separate loader that loads a given binary file instead of creating geometry manually… just have to pack the page index into the filename of the binary lol. Like its usually done…

Don’t use billboards, there is a far more intelligent approach possible:



Use gl_point as they are faster than any triangle based one. However point always look directly at the cam, so you need to correct the perspective in the shader then.

Here is a explanation of what i mean, only it is for mass bullets where tehy use this instead of grass. I think it will come in handy for grass as well.

http://www.shmup-dev.com/forum/index.php?topic=1870.0

Great article, thanks. I had a similar approach in mind, inspired by this article Towards photorealism in virtual botany, but hadn’t thought of any concrete implementation details.



This approach could be used for the impostor system for trees as well (which is included in the PG engine), and will replace the billboard system altogether. Gonna use the dissolve grass fading tech in that article as well as regular alpha (already done) btw.



I have transcribed the entire paging engine now, and I’m pretty sure how to jMonkeyfie geometry loading/batching. I looked at the engines batched geometry class and concluded it’s not very different from the one jmonkeyengine uses, so…

I think also loading will be fairly efficient. There is dynamic caching/loading based on camera speed. The geometry could be stored in binary files (EDIT: Maybe just pre-prepared coord-lists & model(s) reference, with batching taking place on the fly), alongside impostor images. Only have to actually generate them the first time the prog is run (or if its imported - write the binaries on import, or do it in some separate main method or whatever).



That means loading and random number generation is fast, and the focus would have to be mostly on rendering.

Hmm, after looking at the Batched Geometry stuff I think I’m gonna implement my own batching procedures. The only real difference is that mine will use fixed-size arrays. So…

androlo said:
The only real difference is that mine will use fixed-size arrays. So...

The mesh data always has to be saved as ByteBuffers and not as java arrays, so..
1 Like

Yes but the optimize method (and most of its sub routines) probes for geometries and materials and stuff then adds everything into some type of dynamic lists. At least that’s the way I saw it, maybe I didn’t look through it all.



It seems to be a convenience method made for small quantities of geometry, thats how i saw it, not made for huge batches being generated efficiently on the fly.

It is kinda efficient, I woudl first test it and if its not good enough do a own, not the other way round

1 Like