Procedural mesh

I have a python program that generates a terrain mesh of various levels of detail (could be millions of polygons, in theory). Is there a faster way to modify the vertex data and GeomPrimitive data than just blowing it away and recreating it every frame? If so, could anyone provide an explanation and examples?

A simpler question would be: I know how to add data to these structures, how do I remove triangles from the structure in a logical manner? I can probably extrapolate from this.

I ask because I cannot find a way to do this (heh, its probably blindingly obvious, but I’ve been away from 3d programming for a while).

I cannot use the normal terrain renderers as my terrain is spherical and not flat :slight_smile:

Thank you for your help.

Patrick

Don’t recreate all the geometry every frame. There are many approaches which work fine without doing this. The built in GeoMipTerrain breaks the terrain up to blocks, and transitions then between LODs only when needed (then patches any seams this created).

Another approach is geoClipMapping, or other vertex shade shader approaches (these also work on the CPU, but its slower, especially from python). Leave all the triangles, but just update the vertex positions. GPU side, you can use a vertex shader, CPU side you can use a GeomVertexWriter.

Another approach is to regenerate your terrain every so often, this is the approached used by the built in HeightfieldTesselator

Choose ont of these, and optionally add some tiling/paging based approach, and you can do a pretty good job. See [url]Procedural Plants + Procedural Terrain] for my unified terrain system that implements multiple of these approaches, though only one of the solutions is ready for serious use and it is just a tiling system, with no real LOD.

These issues can be applied to spherical terrain, though you are right that the provided solutions won’t work, you will have to modify or recreate them to work on it. Of note: see this: http://www.craigm.info/portfolio:fg - Its a rather crummy write up about my planet render I wrote for some of my classes. Its geometry basically entirely implemented in the vertex shader, applied to a static grid.

There is no high-level way to remove triangles from a GeomTriangles structure, but you can do it using low-level access to the underlying data. Note that the method GeomPrimitive.modifyVertices() returns a modifiable GeomVertexArrayData object, which contains just a list of integers. Taken three at a time, these integers define the indices into the vertex data that specify the triangles it should draw. In fact, this is the structure that you build up with your calls to GeomPrimitive.addVertex() and closePrimitive().

So, you can simply modify this structure directly to remove the rows you wish, for instance using setNumRows() to remove rows at the end, or using setSubdata() to remove data in the middle. You have to be careful about byte alignment when you use a low-level operation like setSubdata().

David

I can find no mention of setsubdata in the API reference. Do you have any documentation?

Also what do you mean by byte order?

Out of curiosity, seeing that there are methods to add data to these structures, why are there no methods to remove data? (without trashing everything) Is it just optimization?

This page turned up when I typed “setSubdata” in the API reference search form:
http://www.panda3d.org/reference/latest/python/class:panda3d.core.GeomVertexArrayDataHandle#a89be9125e7c38d3050024f4c26bc0c90

I said byte alignment, not byte order. I meant that the parameters to setSubdata() are byte offsets, not row positions, so you have to be aware of whether you are dealing with 16-bit indices or 32-bit indices, and compute the values appropriately. Of course, you have to be aware of byte order as well–it’s possible for the order to be little-endian or big-endian, but this will match your CPU’s preference (which is almost certainly little-endian unless you are coding on an old PPC mac or an exotic Linux box).

I guess it just never occurred to me that this would be a useful feature. Almost all rendering problems involve building geometry up; maintaining dynamic geometry in the way you describe is often too complicated to bother with, and possibly too expensive to do on a per-frame basis, so it’s not often done. When geometry does have to be maintained dynamically, it’s usually just rebuilt every frame anyway (which is probably too expensive in Python, but usually not a problem in C++).

Of course, I’ve been constantly surprised with the sorts of algorithms that people dream up and successfully implement, so don’t let my limited experience cloud your thinking. If people do indeed see a need to dynamically remove vertices and primitives, I’ll be happy to add a high-level interface for it. :slight_smile:

David

Thank you for pointing me in the right direction :slight_smile:

My algorithm is nothing special right now, it just starts with a cube and subdivides each of the quads recursively based on the distance from the viewer (This is a bit of a hack for now, I just needed a way to determine when a quad would split or join to test with) It maintains a tree structure of quads and various data on them (neighbor references, child/parent relationships, locations, etc.) and the panda geom data.

The problem I am having is that when quads are split, the parent quad needs hidden, and vice versa, when quads are joined, the child quads need hidden. Is it possible I’m missing something obvious here?

Thank you for your help.

Patrick