I am working on a tiled terrain with shared index buffers used for LODing. Essentially I have 100x100m tiles with 5m resolution (441 vertices). I have a number of predefined static index sets for drawing triangles. Tiles closer to camera are drawn using index sets which contain more vertices from vertex sets and ones farther are drawn using more sparse index sets thus achieving very efficient LODing.
I was digging through (very poor) documentation and I couldn’t find any way to draw primitives using vertex and index buffer.
Can anyone help me with this, or at least point me to the relevant part of the API to do this.
You can use GeomPrimitive::set_vertices() to change the index set; they index into the vertices defined in the GeomVertexData. Have you seen the manual section about creating your own geometry in Panda? It’s hard for me to give you more specific advice without knowing which details you are missing. Do you have a more specific question?
What I would like is something that would give me more direct control over vertex and index buffers. Section in manual doesn’t use index buffers directly. Instead, vertices are added to primitive via addvertex() method (or something similar) and my guess is that engine attaches new index buffer to each primitive.
I would like to explicitly create static vertex and index buffers in video memory, and then draw primitives by pointing to appropriate vertex and index buffers.
The index buffer is stored in a special internal GeomVertexArrayData. When you use add_vertex() etc., it fills in the GeomVertexArrayData object for you. This is the recommended way to manipulate the index buffer, because it is simple and straightforward, and it is unlikely to change with future revisions of Panda.
If you want to use the low-level structures directly, though, you can do so. Use GeomPrimitive::set_vertices() to replace the index buffer with a new one of your design. Use GeomPrimitive::get_vertices() to return the current index buffer.
You can set up your index buffers by hand with a GeomVertexWriter, and use set_vertices() to assign them to all the primitives that are appropriate. Or, you can use the higher-level add_vertex() etc. methods to create your index buffers initially, then use get_vertices() to save it and store its pointer. You can share index buffers between primitives as you like.
Note that OpenGL doesn’t specify that a driver must treat index buffers optimally, so you may or may not get the performance benefit you hope for. A given driver is free to pre-transform all of the vertices in the vertex buffer, even if only a small subset of them are referenced by the index buffer in use. (I don’t know of any hardware drivers that do this, but I think tinydisplay behaves this way.)
Oh, I think I get it now. I just got back to that chapter in the manual, and what confused me is that GeomPrimitive is not connected to GeomVertexData which defines vertices. If I got this right, GeomPrimitve only stores indices and is used to create Geom object.
So, GeomVertexArrayData stored inside GeomPrimitive has only one column of unsigned integers?
Yes; the default add_vertex() et al methods set up a GeomVertexArrayData with a single NT_uint16 column (or whichever type is specified to set_numeric_type()). If you create one yourself, you should create the matching GeomVertexArrayFormat yourself.