Well i try to load a bunch of modles in a background thread and then enque them to be attached to scenegraph.
This works without problems.
Now due to the GeometryBatchFactory needing some time if I optimize in the opengl thread and this is leading to a lag, I tried to let it do it’s work before attaching to the scenegraph, this leads always and reproducable to errors like the following ones (often multiple since the modles are loaded in up to 16 Threads, to make use of modern cpu’s and speed up everything a bit)
[java]
java.lang.NullPointerException
at com.jme3.util.IntMap$IntMapIterator.next(IntMap.java:261)
at com.jme3.util.IntMap$IntMapIterator.next(IntMap.java:207)
at jme3tools.optimize.GeometryBatchFactory.mergeGeometries(GeometryBatchFactory.java:109)
at jme3tools.optimize.GeometryBatchFactory.makeBatches(GeometryBatchFactory.java:278)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:329)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:313)
at online.newhorizons.client.entity.terrain.Tile.vegetation(Tile.java:87)
at online.newhorizons.client.entity.terrain.Tile.load(Tile.java:61)
at online.newhorizons.client.entity.terrain.CTerrain$1.run(CTerrain.java:128)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
[/java]
[java]
java.lang.IllegalArgumentException
at java.nio.Buffer.position(Buffer.java:236)
at java.nio.DirectFloatBufferU.put(DirectFloatBufferU.java:313)
at com.jme3.scene.VertexBuffer.copyElement(VertexBuffer.java:755)
at jme3tools.optimize.GeometryBatchFactory.mergeGeometries(GeometryBatchFactory.java:191)
at jme3tools.optimize.GeometryBatchFactory.makeBatches(GeometryBatchFactory.java:278)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:329)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:313)
at online.newhorizons.client.entity.terrain.Tile.vegetation(Tile.java:87)
at online.newhorizons.client.entity.terrain.Tile.load(Tile.java:61)
at online.newhorizons.client.entity.terrain.CTerrain$1.run(CTerrain.java:128)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
[/java]
Can you replace the iterator() method in IntMap with the following:
[java]public Iterator<Entry<T>> iterator() {
IntMapIterator iter = new IntMapIterator();
iter.beginUse();
return iter;
}[/java]
And see if it helps?
Well one of the erros is now complelty gone, however this one is stil there
[java]
java.lang.IllegalArgumentException
at java.nio.Buffer.position(Buffer.java:236)
at java.nio.DirectFloatBufferU.put(DirectFloatBufferU.java:313)
at com.jme3.scene.VertexBuffer.copyElement(VertexBuffer.java:755)
at jme3tools.optimize.GeometryBatchFactory.mergeGeometries(GeometryBatchFactory.java:191)
at jme3tools.optimize.GeometryBatchFactory.makeBatches(GeometryBatchFactory.java:278)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:329)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:313)
at online.newhorizons.client.entity.terrain.Tile.vegetation(Tile.java:87)
at online.newhorizons.client.entity.terrain.Tile.load(Tile.java:61)
at online.newhorizons.client.entity.terrain.CTerrain$1.run(CTerrain.java:128)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)[/java]
Do your geometries share vertex buffers?
I guess that could be problematic since Java’s nio Buffers are sort of single-threaded use.
Yes, its mostly a small forest that I want to batch.
Hm, maybe best make your own “batch factory” that creates an arbitrary forest from some base models you give it?
If you are already building from jme source… another thing you can try…
In VertexBuffer.copyElement()… you can data.duplicate() instead of operating on the raw data field.
So before about line 721, put:
ByteBuffer localData = data.duplicate();
localData.clear();
…etc.
and then replace all references to data with localData in that method.
duplicate() shouldn’t duplicate the underlying buffer data but will allow that method to have its own index into it… and you can remove some of the extra clears at the end or whatever.
If this is a real solution then it might be better to have a bulk copy method in this case. Because it’s kind of wasteful once per-element.
I believe I have fixed this in SVN.
I modified VertexBuffer so that it can provide a read-only copy of its data buffer and so that any of its operations that are read only are safe from being clobbered by other reads.
I modified GeometryBatchFactory to use the safe read-only buffers where applicable.
Hopefully that fixes the issue.