My thread title is probably inaccurate (I didn’t have space to explain, in the title ). I’m reading, in various forum threads, that using the loader to load a model has some built-in memory benefits. [url]Panda3D Instancing Concept Is Different]
This, in the context of why it’s pointless to try to use any form of instancing in Panda with loaded models, unless (apparently) they share animations.
I have a situation, however, in which I will be generating “enemy” geometries and game objects procedurally, with no models to load using the Loader. All enemies share their geometry with others of the same type. This seems straightforward if I’m going to have a set number of these enemies, in which case I should just duplicate the process to create them, four or five times. But I plan to set up support for a variable number of enemies, which number can be modified by the user in-game. I will set up the four base copies of my dragons, for instance, and just hide the right number if the user wants fewer than four in the game. But if the user wants seven, or fifteen, or thirty dragons, I need to create more of them.
I do this successfully in the Dark Basic Professional version of the game I’m porting, but that’s a wholly different context from Panda. A DBP game is compiled, rather than interpreted, and various things are faster in a DBP context. There may also be differences in memory overhead (an area about which I know little). I am wondering about the best way to go about setting up the sort of process I am considering. Is there any way to allow the different game objects to share or reference the same geometry, allowing me to do the procedural setup only once per enemy type? Or is it best simply to build each new enemy completely from scratch?
Can anyone comment on this? I’ve reached the point where I need to know a bit more about how to design some aspects of my game, before I can really move forward.
I have worked around these concerns by building a “reference” set of geomnodes at game start, then borrowing their geometries using addGeomFrom. This seems to work well, but I wonder whether it presents any sort of problem for refence counting and garbage collection. If I create four copy geometries in four enemy instances this way, then remove the four (set the wrapper class instances to None) and create ten new enemies, do I still have those four geometries hanging around in memory somewhere? One complication of porting a Dark Basic game to Panda Python is perhaps reference handling and memory. In DBP, it seems to be easier to delete a game object and have it be gone from memory, but with Python I’m never completely sure a thing is gone once I’ve taken steps to remove it.
If they really do share the geometry, then basically you can use instanceTo (which basically, under the hood, means that one PandaNode is parented under multiple parent PandaNodes. Alternatively, you can add the same Geom to multiple GeomNodes). This has performance advantages for animation, and memory overhead, not for drawing. (You’d need hardware instancing to decrease the overhead on the draw calls - also read my blog post on that.)
These game objects use identical geometries, built from the same information using the same process. I’m not sure whether that would be considered “shared” geometry in Panda, but that’s how we speak of such things in the Poser 3D community. I’m looking for a shortcut to gather the six (identical between enemies) geometries for each enemy quickly and (perhaps) easily, without too much memory overhead or any performance bottlenecks.
As noted above, I’ve settled on duplicating the same geom(s) among all enemies of the same type. I’m now wondering if that presents any concerns in the area of reference handling. When I use addGeomFrom() to copy the geoms from one node to the others, am I setting up some kind of reference looping, or creating new geoms in memory from that one source? If references are being created, is there any special handling required to be sure I clear the reference counts if/when I remove one of these enemies from the game?
Another complication I’ve come upon is collision handling when trying to “share” geometries in this way. Panda doesn’t seem to have any methods for collision solids which allow duplication like the addGeomFrom() for the visible geometry. That still leaves some extra processing when I create an enemy instance, to give each enemy its own collision handling. With that in mind, I’ve had to switch from my planned use of collision polygons for the enemies to using tight collision boxes, which I can do more quickly for N enemies times 4 or 6 collision solids for each. Collision issues perhaps deserve a different thread, as I’m finding some game design complications in the need to adapt to what Panda will or will not do with collisions. Collision polygons may not have worked for enemies anyway, since the enemies need to be in motion.
I knew Dark Basic Professional wasn’t presenting me with a lot of options for various things, but I didn’t realize how much of that was because DBP automates some areas and presents the user with “higher level” access to certain functionality. Whereas Panda usually has more options that need to be approached as several steps, apparently with “lower level” programming access to much of the functionality. Porting from DBP to Panda isn’t so much a matter of adapting the DBP code to a new language as it is re-engineering the entire project. Which isn’t wholly a bad thing.