BufferUnderflowException on trying to create a collision mesh from ScalarFieldPolygonizator

Hi!



EDIT: ugh… I just got the openjdk sources and I am recreating the error in a controled code, it seems I still need to get used to java exception tracking lol… sry xD. I will post again if I find something weirdo and related to jme…



I am trying to create a mesh collision shape but I am always getting these errors, no mater what methods I try, below are just 2 of them…

They are all about BufferUnderflowException.

The mesh I have created with the ScalarFieldPolygonisator metaballs code that I updated to JME3.



I dont understand what this mesh can be missing, any tips? thx!



PhysicsNode phys = new PhysicsNode(geom, CollisionShapeFactory.createSingleDynamicMeshShape(geom), 0f);

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.nio.BufferUnderflowException

at java.nio.Buffer.nextGetIndex(Buffer.java:491)

at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:223)

at com.jme3.bullet.util.Converter.convert(Converter.java:162)

at com.jme3.bullet.collision.shapes.GImpactCollisionShape.createCollisionMesh(GImpactCollisionShape.java:72)

at com.jme3.bullet.collision.shapes.GImpactCollisionShape.(GImpactCollisionShape.java:66)

at com.jme3.bullet.util.CollisionShapeFactory.createSingleDynamicMeshShape(CollisionShapeFactory.java:205)

at main.AwGUI.createTerrain(AwGUI.java:912)

at main.AwGUI.simpleInitApp(AwGUI.java:240)

at com.jme3.app.SimpleBulletApplication.initialize(SimpleBulletApplication.java:261)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:102)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:151)

at java.lang.Thread.run(Thread.java:636)




PhysicsNode phys = new PhysicsNode(geom, new MeshCollisionShape(geom.getMesh()), 0f);

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.nio.BufferUnderflowException

at java.nio.Buffer.nextGetIndex(Buffer.java:491)

at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:223)

at com.jme3.bullet.util.Converter.convert(Converter.java:162)

at com.jme3.bullet.collision.shapes.MeshCollisionShape.createCollisionMesh(MeshCollisionShape.java:70)

at com.jme3.bullet.collision.shapes.MeshCollisionShape.(MeshCollisionShape.java:65)

at main.AwGUI.createTerrain(AwGUI.java:913)

at main.AwGUI.simpleInitApp(AwGUI.java:240)

at com.jme3.app.SimpleBulletApplication.initialize(SimpleBulletApplication.java:261)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:102)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:151)

at java.lang.Thread.run(Thread.java:636)





PS.: the new forum edit box is so small, it is hard to see/scroll what we are editing :frowning:

Probably you have to call clear() on all the buffers you worked with, although ideally this should be done inside the JBullet Converter as you never know who touched those buffers…

teique said:
PS.: the new forum edit box is so small, it is hard to see/scroll what we are editing :(

You can make it bigger by dragging the bottom right corner. Dont know whats wrong with your mesh there, cant tell form the stacktrace :/
Cheers,
Normen
normen said:
You can make it bigger by dragging the bottom right corner.

this is a chrome and Safari only feature Normen, doesn't work with Firefox and Internet Eplorer

thx!



I discovered that at the polygonizator, after executing this code:

textureBuffer.flip();

//mesh.setTextureCoords( new TexCoords( textureBuffer ) );

if(mesh.getBuffer(Type.TexCoord) == null)

mesh.setBuffer(Type.TexCoord,2,textureBuffer);

else

mesh.getBuffer(Type.TexCoord).updateData(textureBuffer);





it must call this code



mesh.setTriangleCount( indexBuffer.limit() / 3 ); mesh.setVertexCount( vertexBuffer.limit() / 3 );





the later (setting counts) were being called before texturebuffer setup, and that was messing the counts, making them 1/3 of the max limit that is 16000 (so = 5333) what was giving the exception, now the code is working!



btw, at this edit box, there is no bottom right corner that I can drag, I am using Firefox on Ubuntu, may be it works only on windows?

Hi again!



EDIT: I just found a workaround: indexBuffer.compact(); that makes the limit() be equal to capacity() and the exception vanishes! may be compact() should be called prior to mesh.updateCounts(), but thats is just another blind guess…



Ok I think I found something strange.

Now I am trying to cast a ray for pickables, the exception begin here:

nodePickables.collideWith(ray, results);

It happens on createCollisionData() of a ScalarField created mesh.

exception:

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.IndexOutOfBoundsException: 17448

at java.nio.DirectIntBufferU.get(DirectIntBufferU.java:227)

at com.jme3.scene.mesh.IndexIntBuffer.get(IndexIntBuffer.java:25)

at com.jme3.collision.bih.BIHTree.(BIHTree.java:70)

at com.jme3.collision.bih.BIHTree.(BIHTree.java:94)

at com.jme3.scene.Mesh.createCollisionData(Mesh.java:432)

at com.jme3.scene.Mesh.collideWith(Mesh.java:443)

at com.jme3.scene.Geometry.collideWith(Geometry.java:200)

at com.jme3.scene.Node.collideWith(Node.java:496)

at com.jme3.scene.Node.collideWith(Node.java:496)

at main.AwGUI.castPickingRayGetResults(AwGUI.java:1110)

at main.AwGUI.castPickingRayGetClosestCollision(AwGUI.java:1134)

at main.AwGUI.playerOnGroundCastRay(AwGUI.java:1602)

at main.AwGUI.updateVars(AwGUI.java:1561)

at main.AwGUI.simpleUpdate(AwGUI.java:286)

at com.jme3.app.SimpleBulletApplication.update(SimpleBulletApplication.java:280)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:112)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:101)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:166)

at java.lang.Thread.run(Thread.java:636)






I discovered that this mesh has indexBuffer.limit() = 17448; what should be the base to mesh.getTrianglesCount() = 5816 (17448/3), as there will have no data after that point.

But when mesh.createCollisionData() is called, at BIHTree() constructor, mesh.updateCounts() is called too; now, the problem is that the updateCounts() setup the result of getTrianglesCount() to: getBuffer(Type.Index).getData().capacity() = 32000/3 = 10666; what forces the loop to look for 32000 index buffer, when it should really be looking for 17448; and that leads to the exception.



Could it be that the getTrianglesCount() should be based on a check for existant index buffer? even if being slow initially?



I will play with jme3 code when I really understand all I am talking about xD… otherwise any adjustment I do will be just a blind guess that can mess things up…



If it helps I can try to create a test case.

In jME3 it is assumed that the VertexBuffers are not padded with extra data in the end, that’s why all counts computations are based on the capacity() and not limit().

Cool thx! now I understand that must work that way, without extra data in buffers! Yes it is working very well now!



I would like to argue if you think it wont cause trouble (slowness?) by making a change in the Mesh.createCollisionData() code to always make sure that buffers are compacted before other calculations? This “fix” is needed when casting picking rays, they make the picking ray work with great precision (and dont throw exceptions)!! the change would be to this:

public void createCollisionData(){

Type[] atype = new Type[]{

Type.Index,Type.Position,Type.Color,Type.Normal,Type.TexCoord};

for(Type type : atype){

VertexBuffer buf = getBuffer(type);

if(buf.getData().capacity() > buf.getNumElements())

buf.compact(buf.getNumElements());

}



BIHTree tree = new BIHTree(this);

tree.construct();

collisionTree = tree;

}



I put only the types that were used at ScalaField computations, not sure if other indexes should be compated also. Anyway, if I only compact Index and Position buffers, the collision data will work and wont throw buffer exception!



Currently, I am overriding the createCollisionData() in my class that extends from mesh, and implementing those compact() there.



Also, I would like to contribute back this MetaBalls files I updated to JME3, I just drop them at this forum: Forums/Development/Contributions(JME3)?



Also again, a screenshot showing the ScalarField being useld as dynamic mesh editor, there is a glitch generating unwanted triangles after removing some metaballs, I must look at this later…; the cyan ball is a precise cast ray on the modified mesh.

ScalarField cut isle and glitch (after cutting some triangles generated weirdly up there), also the cyan ball is the precise cast ray collision



And another showing the precise collision, both only work after the createCollisionData(), this also works great with the player ghost physics and its ray cast I use to allow jumping (only jumps if there is a mesh below it).

Some balls precisely colliding in the dynamically cut mesh.



PS.: btw, in chrome the website looks MUCH better; in firefox the font is too big and a few other issues, so I am moving to chrome when accessing here xD.

teique said:
PS.: btw, in chrome the website looks MUCH better; in firefox the font is too big and a few other issues, so I am moving to chrome when accessing here xD.

Quoting our very own Skye here: "FireFox is soo 2005" ;)