Panda3d paged geometry?

I’m seeing the FPS drop too when moving in close. It appears to be related to the number of pixels on the screen covered by the branch textures. If I make it full screen it drops more than when it is a smaller area.

As far as the Ogre paged geom, I have an example called forests/Example1, and they are using “Impostors” as part of their level of detail, so they draw distant trees into a 2d texture buffer and put on a card. Here is a few lines of their set up:

	//-------------------------------------- LOAD TREES --------------------------------------
	//Create and configure a new PagedGeometry instance
	trees = new PagedGeometry();
	trees->setCamera(camera);	//Set the camera so PagedGeometry knows how to calculate LODs
	trees->setPageSize(80);	//Set the size of each page of geometry
	trees->setInfinite();		//Use infinite paging mode
	trees->addDetailLevel<BatchPage>(150, 50);		//Use batches up to 150 units away, and fade for 30 more units
	trees->addDetailLevel<ImpostorPage>(500, 50);	//Use impostors up to 400 units, and for for 50 more units

This must help their performance too when displaying lots of trees.

Haven’t tried doing anything like that in Panda yet, but I have used the Fade lod with cross quad tree fading into a 3d type tree like yours.

I miss one thing about that design - the load callback mechanism (or otherwise the ability to specify the paths to the models), which is the core of a paging system.

It wouldn’t be hard to implement a paging system, but I can assure you that it will not provide a millisecond of speed boost in the case of rendering trees. Paging systems are designed to bring back memory usage by unloading parts of the world from memory when the player is not in them, but in your case that is not an issue whatsoever because you’re only using a few tree models.

You (and possibly the Ogre developers) are probably confusing paging for LOD and hierarchical culling, both of which are possible in Panda3D. I’ve already explained Anon how to implement the latter, but it seems that he tends not to read half of my posts.

For the record, everything that you described in your use of the PagedGeometry API is already possible in Panda3D. Adding the PagedGeometry class will not only be adding a class with a misleading name, but it will also be pointless because the functionality is already there.

I agree about the definition of PagedGeometry. I always thought that it was more for large terrains, where the terrain was broken up into smaller tiles and kept in some structured folders where the code would swap in and out these tiles depending if a particular tile area was in or out of view. Looks like the Ogre “paged geo” is loading meshes into what they call batches, sounds kind of what has been explained for Panda code to load models that are close to one another under a single parent “batch” and then flatten and apply a LOD to the whole parent “batch”. I haven’t seen any file structures of tiles being loaded into any of the Ogre example I have; they do have Octree though and use that on terrains, and like geomip terrain, change the number of polys based on distance from camera.

Firstly, I’m still working on it. Few trees means more fps, since theres no actual optimization trick used yet. More fps just makes it easier to develop.
Second:

I don’t know whats the universal definition of paged geometry and if it for some reason is only used for terrains. But this makes sense to me as it really tries to save memory usage.

First, that was kinda harsh, don’t you think? And not true, actually I could argue the same: firstly, Ive read it and said I would implement it, I just said thats not the cause of the problem with the low fps, because its still there in Pview, with a single tree. Have you read that post?
secondly, Ive asked how can I use flattening with LOD, as by my knowledge flattening is a one way operation and flattening by my knowledge will break LODing. That was my 4th post in this topic.

Maybe its time to settle on a few terms. I had a look at the Ogre PageGeometry code two or so years ago, but never found time to “translate” it to Panda3D.

Impostors: Impostors are nothing but billboards. An utility loads the full 3D model, e. g. a tree, and makes a “screenshot” with alpha background. The cute thing is that there is not just one image, but several images (front, left, upside, …). The billboard displays the right image depending on the camera position relative to the object. This might be nice if you have a very mountainy terrain where you look down at a forrest valley from the peaks of a mountain, but usually it’s enough to have just one billboard (from the side).

BatchPage: This is a single (!) Geom. Adding an object to a BatchPage means that it’s vertices/polygons are added to the single Geom, and the object itself is discarded.

ImpostorPage: Again, a single Geom. For each object added to the page a new vertex is added to this Geom, and the Geom is rendered in point sprite mode.

And theres my question again: if you have everything in a single node or geom, how can you have LODing and paging as in “only entities which are immediately needed (to be displayed) are loaded”? Thats basically all I want to know from this thread, other than the transparency performance issue Im having

1.) Paging:
A page is a rectangular piece of your terrain. Every page is one Geom. A page can contain dozens of “trees”, “rocks” or other objects, but all of them are merged into only one Geom.
Now paging not only means that you don’t render pages which are beyond maximum view distance (e. g. by stashing them or removing them from the scene graph completely). It means that you unload those pages which and re-load them again when your camera get’s in view range of a page again.

Paging doesn’t increase rendering performance! It is just a way to keep the memory consumption low, at the cost of having to load/unload pages.

2.) LODing:
At a given time usually more than one page will be within view range. No the LOD is about how a page is rendered: as 3D geometry (BatchPage) or a point sprites (ImpostorPage). Both versions of a page have to be prepared before rendering, and then you just switch between the two (or more) levels of detail depending on the distance.

Sidenote: The original paging geometry approach is very memory consuming. Having a page with 100 identical trees each 200 vertices means having a page with 200 * 100 = 20000 vertices. I guess hardware instancing is a much better approach for rendering a BatchPage. You might want to talk with rdb about hardware instancing. If I remember right he has a blob about this topic.

Should I have a task checking the cameras position each second or something?
not sure how to divide the terrain into chunks IN panda too. If thats what you meant though.

Right. The problem is they are still in memory.

So the LOD is not per tree, but per ‘page’?

Sadly I dont know shader programming. I imagined that if you can have so many trees In Ogre, you can have so many in Panda, by using the same techniques.

I didn’t mean to come across as harsh; I was making an objective observation, based on the fact that you seemed to ignore my questions and responses several times now. I don’t really mind repeating myself though, for the record. I get paid to help you, after all. :slight_smile:

I’ve explained way up there how to implement more optimal batching while maintaining optimal culling. If you combine that with LOD (using Panda’s LODNode), then you will get more optimal performance with the trees. Paging will not help here.

Let me comment on “only entities which are immediately needed (to be displayed) are loaded”. In the context of paging, “loaded” refers to “loaded from disk”. If you’re talking about trees, then every type of tree will only be loaded into memory once, anyway. So adding paging will literally do nothing but add overhead, in the case of the trees; as I’ve said a couple of times now.

Paging would only help if you had a thousand different types of trees that are grouped by type instead of spread over the entire terrain. You really want to be looking at culling, batching and LOD instead.

Culling is already a sort of paging if you look at it from the GPU perspective (and this is probably the reasoning behind why the Ogre developers confusingly named it PagedGeometry), but Panda3D automatically performs that if you properly structure your scene hierarchy (and do not flatten everything together, but flatten groups of trees).

It looks like Ogre’s PagedGeometry actually does batching, culling and LOD, the same things that you can do with Panda3D in the way that I already explained. I don’t know much about impostors.

For the record, if we were to implement a utility class like Ogre’s PagedGeometry in Panda3D, it’d be much better if it’d be a node in the scene graph, like LODNode. It could probably best be an extension to LODNode.

If you ‘load’ the exact tree thousand times, you will get amount_of_vertices* amount_of_trees into memory right? If thats true, most of them might not be rendered, but they waste memory. Youre saying Im not reading your posts, but its just that I dont simply mean performance, but also memory usage. If this is not true, then tell me and will end at that.
Also, if you rendered the lowest LOD of farther pages, isnt that performance optimization?

So the short answer is no.

The long answer: Panda3D will reuse the same Geom objects, and won’t duplicate it in memory. The problem is that only one Geom is passed per batch, so a large amount of batches is passed to the GPU every frame, which is heavy performance-wise (not memory-wise).

I thought you didnt mean the amount of vertices here. Actually, I didnt know what you meant here, because analyze on the parent node of trees gave me 100000 vertices? Maybe an explanation of “batch”?

analyze() counts the number of vertices that will be sent to the GPU, not the number of vertices actually stored in memory.

For simplicity, define a “batch” to be one geom that is sent to the GPU. Multiple instances of the same geom will be sent as multiple batches, though (unless geometry instancing is used); that is why analyze() is counting so many Geom objects.

If I’m correct, you’re confusing memory related stuff with GPU related stuff, Anon.

Panda loads every model into the memory once. It doesn’t reserve a chunk of memory every time you load the same model as that would be a huge waste.

You can have a thousand trees but as long as they’re the same tree model, there will only be one of it in the memory.

However, once Panda renders that, it must send vertices*trees into the GPU (which wastes GPU cycles, but has nothing to do with memory) because every one of them must be rendered as a separate tree (unless of course you use hardware instancing: panda3d.org/blog/?p=44, which is what you should use if you want many trees of the same or few types, technically).

That’s AFAIU. Hope I haven’t misunderstood anything or introduced more confusion.

That sounds more or less right. Hardware geometry instancing basically reduces the number of batches sent to the GPU; it allows you to send the Geom only once and then write a shader that places several instances of it in the world.

So… I should think of batches as geoms. So merging geoms (trees) into 1 will reduce the amount of geoms-batches. So… the geom I get when grouping them and making a single one isnt called “page”?
By what should I group them anyway?

Close enough. At least in the context of sending them to the GPU.

Nope, at least I’ve never heard of it used that way. Perhaps Ogre calls it that way, but that’d seem rather confusing naming to me.

By location. Every bunch of trees that is close to each other, could be flattened together to a single node.

That clears alot of things.

Okay, so lets assume now that I have a bunch of ‘batches’, each batch will have 2 LOD levels and will be removed when not in view.
I want to allow to remove them as by what Ive learned till now, even with fewer batches, the amount of vertices will still be vertices*trees.
If theres nothing wrong here, Ill finally start implementing it.

Note that by using LODNode, you automatically take advantage of Panda’s culling system, because Panda will automatically cull away nodes that aren’t in view. So I don’t think you’ll need to explicitly remove anything yourself.

I don’t know what you mean by “the amount of vertices will still be vertices*trees”. You mean the amount of vertices in the scene? In memory? Or the amount that is passed to the GPU?

passed to the GPU. Unless if its not rendered, its not even passed to the GPU.
…Id still need to keep the amount of “batches” below 300 (usual geom limit), so even in that case I would need to manually remove them, right?