So, I have one model file for each character and want to reuse as possible, for example if “Panda with Python” sentence is created, load “a” and “P” only once, to save resources (file reading, model rendering).
I want to change one character color (via material replacing), like the first “P”, and here is my question:
If I instance the “P” model, the two places where it appears will be changed because are instances and the “original” loaded scene is the modified. (I assume it is right, is there a way to change just one instance and maintain others untouched?)
If I load letters every time are needed, no matter if it repeats, there will be a performance issue when rendering many words in a more complex scene.
One solution can be to load only Geometry data and add materials on the fly, but before getting deep on it I decided to ask you if there is another more simple way.
I think that colours set on the individual instance-nodes (that is, via such methods as “setColor”) should be separate from those set on the original model. (Pretty much in the same way that setting the position of an instance node doesn’t alter the position of the original model.) You may possibly have to specify an override value to have them take priority (I don’t think so, but I may be wrong), but overall such a setting should just work.
Just to check: Have you confirmed that there is such a performance issue? If not, then I’d suggest doing so–beware of premature optimisation!
(And if anything, I’d be more worried about your node-count than anything else, myself.)
Note that instead of instancing, you can also rely on the copy-on-write nature of Panda’s Geom objects: even just copying a piece scene graph will not cause a duplication of the underlying geometry in Panda unless you try to modify the geometry in one particular copy.
Geom, the class that stores geometry information, is considered a “copy-on-write” class.
A GeomNode is a scene graph node that contains Geoms. When you copy a GeomNode object, the underlying Geom objects are not copied (yet), only its reference counter is incremented. It is only when you call, say, node.modifyGeom(0) that you get a unique Geom object for that GeomNode.
This means that the underlying Geom objects will not be duplicated when you copy a part of the scene graph even when you perform a deep copy.
Instancing is a level higher: it means the same node is parented to two different nodes. For example, you can have the same GeomNode parented to different scene graphs or different scene graph branches, so that it gets visited multiple times during rendering (this is why there is NodePath: representing a particular path to a node from the root). It achieves the same effect, except that in this case the GeomNode object itself is not duplicated either, but it was only a fairly thin container of Geom pointers to begin with.
In terms of reducing node count, instancing doesn’t really help, because you still pay the performance cost of multiple nodes if you have the same node instanced multiple times, since it gets visited more than once by the cull traverser. It just takes up a bit less memory.
You can also potentially use “setColorScale”, which should work with a material, I think. (It essentially “tints” the final colour, so if you start off with a white material you should just end up with whatever colour you’ve applied via “setColorScale”, I daresay.)
Ah. I would suggest being cautious about premature optimisation–it can lead one into spending time and energy on things that turn out to in fact not be bottlenecks, I fear.
Using setColorScale() with white material works and looking at about loaded scene, I figured out how to save a lot of node creations, so there is only one PandaNode with only one GeomNode inside for each letter.