Geometry Batches

Ok, to support some of the tools we are building here, we needed to modify a fairly core component. Here's what we've done:



Instead of Geometry/Trimesh maintaining DirectBuffers to the data used to display renderables it maintains a list of Batches. These batches in turn contain the buffers. Basically, they are a container class to hold the buffer data. Geometry objects can then hold any number of these batch elements. When rendering, the Renderer simply goes through the list of batches and sends the data to the card one after the other.



One positive about the current set up is it affected 0 tests, that is, no public interfaces are changed. Therefore, all current code will work with it without any problems. Old geometry will simply have a single batch that is passed to the renderer like normal.



What does this give you? Batches have the capability to override states. Therefore, you can assign states on a per face level rather than a per mesh. Doing it this way saves the overhead of say breaking a mesh into multiple geometries. It will also provide a mechanism to future enhancements such as defining a batch's method of rendering (triangle strip, fan, quad, etc).



This currently does have a couple issues we wanted to work through (although our priorities are elsewhere at the moment so I decided to go ahead and bring it up to see if the community wanted it before fixing these issues).


  1. RenderQueue sorting only knows about the top level mesh and its render states. This would require quite a bit of overhauling to know about batches.
  2. Triangle collisions respect the batches now, but there are a few oddities here and there. I didn't have time to go through and confirm if the oddity is based on the batching system or a problem in the test itself. (TestOBBTree will show the second batch colliding with the PQ Torus (coloring it blue), but doesn't color the second batch red).
  3. ClodMesh will not work with batches currently, that's just simply low priority for us at the moment.
  4. It has not been optimized yet, we have not yet pulled out the profiler.



    There are probably a few other issues that need to be worked through, but for our current cases it seems solid. Allowing us to render fairly complex models how they should be rendered.



    So, I can commit these changes today, if so desired. These changes will be required if we are to contribute back other cool features in the future, so probably the sooner the better. Plus, we'd always love free testing. :wink:



    Basically, this isn't a sexy contribution, but gives a framework for being able to do cooler things in the future. If you all want it in CVS, I'll put it in today.

I motion to bring it in.  :stuck_out_tongue:



darkfrog

got me!  :slight_smile:

Do the "batch" object themselves contain several buffers now, or does a geometry object contain several batches?



If the second is true, I think it'd be easy enough to change the RenderQueue to sort batch objects rather than geometry objects. Though I assume with whatever structure, as long as none of the batches overide any rendering states, the sorting is just as optimal as before.



Oh and I think it's clear from the other thread you mentioned this in that I'm in favor of this, since I more or less came to the conclusion we need such a system before you said you had one done already :smiley:

I haven't quite understood how the benefit of not breaking the mesh up is big enough to justify that effort. No criticism intended, just trying to understand what's going on. Why/how is it that much of an overhead to break the mesh up into some different material groups?

llama said:

Oh and I think it's clear from the other thread you mentioned this in that I'm in favor of this

Maybe that thread would help me, can anybody point me there?
(Oh, and sorry if I am stupid :| )

Not that much to see there… (with regards to this topic I mean)



http://www.jmonkeyengine.com/jmeforum/index.php?topic=2953

Hevee, stupidity needs no apology. :-p



That wasn't to say you're stupid, I just wanted to say that. :o



darkfrog

Do the "batch" object themselves contain several buffers now, or does a geometry object contain several batches?


batch contains a single set of buffers, and geometry contains 1...N batches.

Why/how is it that much of an overhead to break the mesh up into some different material groups?


if you mean break a mesh up into several meshes to allow for different states, it can be. This creates additional boundings that have to be merged, world vectors that have to be updated, multiple calls to renderer (apply the world matrix), etc.

Ok, get ready for a ton of files to be committed soon.



Really, feel free to pick this apart, improve, suggest, critique, whatever you want. This should not affect any existing code, if it does, then that needs to be fixed ASAP.

ok, in CVS now.

Wow! Just realized a major issue that probably should have been solved before check-in. This will break .jme and the binary reader/writer. Don't update from CVS if you rely on the .jme format.



My apologies, while going through the ramifications of the batching system at work, this never came up as we aren't using .jme. I won't be able to work on patching the JmeBinaryWriter/Reader classes this weekend as I don't actually have a computer at home yet. It's still in storage. I'll fix this first thing Monday, unless someone else is able to take care of it over the next couple days.



Sorry about that.

Are there supposed to be two different setVBOInfo methods in GeomBatch?

Nope, that's an artifact. Looks like an auto-generated setter. Should be removed.

I got the following with TestCompositeSphere:



org.lwjgl.opengl.OpenGLException: Stack overflow (1283)
        at org.lwjgl.opengl.Util.checkGLError(Util.java:56)
        at org.lwjgl.opengl.Display.update(Display.java:567)
        at com.jme.renderer.lwjgl.LWJGLRenderer.displayBackBuffer(LWJGLRenderer.java:514)
        at com.jme.app.BaseGame.start(BaseGame.java:80)
        at jmetest.renderer.TestCompositeSphere.main(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at jmetest.TestChooser.main(Unknown Source)



It displays a single frame, then stops with the above error. It happens with all meshes based on CompositeMesh.

LWJGLRenderer::draw(CompositeMesh)



needs: undoTransforms(); called after postDrawGeometry();



You can make that change to your local copy, until I can fix it Monday. Or another dev can make that change.

Commited. There's no issue for this in the tracker right?

No there is no general issue for the batches, but I was going to put in all the known issues against it (the 5 or so that have been mentioned in this thread).

mojomonk said:

LWJGLRenderer::draw(CompositeMesh)

needs: undoTransforms(); called after postDrawGeometry();

You can make that change to your local copy, until I can fix it Monday. Or another dev can make that change.

Thanks! It works now.

BTW, old .jme files should load/save just fine with the new batching system. So, the initial post I made regarding it breaking .jme loading for old files. Support for batches in .jme is on my todo list.

Few batch fixes checked into CVS as well as support for batches in .jme.



Old .jme files will load properly (or should, let me know if you have any problems). If there is only a single batch (which is true for most people), then the .jme file looks no different.



As always, if anyone is trying out batch and finds a problem, let me know. Or if your old .jme files stop loading, let me know.