Unused Elements in Mesh Vertex Buffer

Hey, I’m wondering if there is a way to reduce the buffer capacity so it doesn’t generate stuff that’s unneeded.



when you run this code the rendered triangles in the stats view is 1 more than usual. so it works perfectly fine. However, if you change the buffer size from 9 to say 18, then the stats view will say it’s 2 more, even though there is only 1 triangles data in the buffer.

So the question is, how do I set my buffer size to 18, put 9 floats into the buffer and than have it reduce to the actual amount of data in the buffer so it only shows that there is 1 triangle being rendered.



[java]

FloatBuffer buffer = BufferUtils.createFloatBuffer(9);



// simple triangle

buffer.put(0).put(0).put(0);

buffer.put(1).put(0).put(0);

buffer.put(0).put(1).put(0);

buffer.flip();



Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.setColor(“Color”, ColorRGBA.Blue);



Mesh mesh = new Mesh();

mesh.setBuffer(Type.Position, 3, buffer);

mesh.updateBound();

Geometry geo = new Geometry(“Test”, mesh);

geo.setMaterial(mat);



rootNode.attachChild(geo);

[/java]



Sorry if this has been spoken about already, or is in the docs… After a little bit of researching I wasn’t able to find anything on it.



Thanks,

Nyfinscyf

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:mesh

look for Mesh.Mode - setting mesh mode to, let’s say, LineLoop will let you decrease the amount of points needed to construct the mesh, and so the buffers.

1 Like

I would gues thta the stats are just getting capacity/elements/3 = triangecount

Probably they should use the limit instead.

(Not sure if this is true however, but except for custom meshes you usually have the capacity exactly the same as the limit)

@EmpirePhoenix I figured out what I need to do. Create the the buffer to the maximum size, add all the data, then store it in a temp array and recreate the buffer to the size of actual data, then add the temp array to the new buffer, which is the one used on the mesh for rendering.



[java]

// make max expected size

FloatBuffer buffer = BufferUtils.createFloatBuffer(18);



// add data: simple triangle

buffer.put(0).put(0).put(0);

buffer.put(1).put(0).put(0);

buffer.put(0).put(1).put(0);



// store data temporarily. Stored at size “position” because at this point the position is the data in the buffer + 1.

float[] data = new float[buffer.position()];

buffer.position(0); // set the position back to zero, ready for the “get” function call

buffer.get(data, 0, data.length); // get the data from position(0) to data.length

buffer.clear(); // clean the buffer, it’s data has been stored

buffer = BufferUtils.createFloatBuffer(data.length); // create the new buffer at the exact size needed

buffer.put(data); // add all the data back into the buffer



// flip buffer

buffer.flip();



// set buffer to be used

setBuffer(Type.Position, 3, buffer);

[/java]



A little annoying that there isn’t a method to resize the buffers capacity. oh well, it works now.

(The clear could be ommited btw, as you create a new buffer, and clear ust overwrites the old one with zeros. (As c++ does not have default values like java,it just interpretes the bit’s that were in that memory location as the type specified))



Well you usually dont want to resize those buffers.



They are native

→ There position in memory is fixed, and pointers to their memory address exists. There can be other stuff in ram after the buffer.

→ If you enlarge such a buffer, the additional data would simply overwrite the adjacent stored data (as there are no checks in c++/c used for such things (btw one of the reasons it’s faster, all those checks java does add up))

→ If you would just create a larger one at another location in ram, old pointers in the native code (opengl driver) would still point to the old memory and read and process random stuff in that location. (wild pointer, there is no way opengl driver would know the changes)



The only proper way is to let the garbagecollector kill the old object (by not referencing it anymore), wich in turn calls the native stuff to release the pointers and other data still using them and the release of the memory used. And then create a new one with the correct size and pass that to the opengl stuff.



Btw you can easily do the opposite by using a large Buffer and use sub* somewhat on it, wich provides a shallow to that smaller part. (and the opengl stuff using this will get the appropiate pointers to the buffer part then) (Of course you need to make sure that the subbuffers dont intersect yourself then, else the os does this)

With this you would be able to release the opengl stuff without having to release the direct buffer.



If this will be usefull, I highly doubt it.

Normally you know how much data you need for an object and can create the buffers exactly with this length. (Prove me wrong)

Well the old data isn’t being referenced any more and so the garbage collector should clean it up, eventually. Right?

Watching the mem usage it seems like the gb was doing it’s job and cleaning mem when things were changed. So, currently I have no complaint about how it’s working in that department.



All that info is useful to know, definitely. So thank you. :)… I’ve always hated OpenGL. When I used to do things in C++ I always used Dx, guess it’s time to learn the GL way.



I agree, Normally you know exactly how much you need. However, what I’m doing is generating voxels, so the amount of triangles I need per chunk isn’t known. Only the max is known. The entire chunk could be empty, or it could be full, or it could be scattered, it’s unknown and so I needed a way to save some memory by resizing the buffers down and letting the garbage collector clean the old unused memory.





Only issue I’m having now is the frustum culling on my mesh. It’s culling when it shouldn’t be. Though I had this issue before so I’m sure I have the fix for it.



Thanks for you help.

Since you have some kind of data structure for your voxels, (and probably a chunk structure??) you could add tracking information there, have counters for the vertexes and adjust them when adding/removing stuff. This will probably be way faster than churning directbuffer.



(Btw directx might just be hiding that it recreates a larger buffer fully transparent (kinda like Arraylist vs Array) since after all both need to store the data somewhere in the graficcard, and the problem of having no free spaces after the current item apply there as well)