I have found that when I parent a model to another, the child model begins to inherit textures from it’s parent. I don’t want this to happen, but I can’t find a way in the API to turn it off. Is there anyway to disable this behavior?
I got around the problem by changing my parenting structure.
What I was doing before looked like this:
Model | Actor | --------------------- | | Exposed Joint Exposed Joint | | Model Model
Now I’m creating my model tree like this:
Actor | ---------------------------- | | | Model Exposed Joint Exposed Joint | | Model Model
So that none of the things with textures on them are ancestors of other things with textures. It works, but I still think there is/ought-to-be some way to prevent texture inheriting.
In general, this is the usually the best approach to solving unwanted inheritance. The scene graph is designed to propagate state from parents to children, and if you don’t want that to happen, the best way is to structure the parent/child relationship accordingly.
But, there are ways to avoid it, if you can’t do this or don’t want to. One way is to use setTextureOff() on a lower node. If you do child.setTextureOff(ts), it means to disable the texture on the indicated texture stage that was inherited from above.
Remember, each different TextureStage object corresponds to a different “slot” that might hold a texture. If a child inherits two different TextureStages from its parent(s), it will be rendered with two different textures at once. If you want to disable one of those textures, you can explicitly turn it off with setTextureOff().
The other part of this is overrides (sometimes called priority) on the scene graph attributes. The override is the additional numeric parameter to any state change, e.g. node.setTexture(tex, 1). If you never specify an override, then the default behavior is for a child state to be the union of its own state and its parent states, and for those slots where the parent and child both specify a different value, the child will override the parent. If you start specifying priority values, then the the node with the higher priority value overrides the rest. So node.setTexture(tex, 1) applies the indicated texture to the default TextureStage, overriding any children to force them also to have the same texture on the default TextureStage. (Except for any children who have a higher priority value, of course.)
It’s a powerful system, but it can be a little confusing to wrap your head around at first. This is part of why it’s best to manage state inheritance by structuring the scene graph properly in the first place, rather than mucking about overmuch with override values.
I was hoping there would be a way to stop the inheriting without having to put in a code line to disable the texture stage on each child.
If that’s not possible, I’ll just proceed with this work around to avoid all those lines of code. I’ve gotten an offer to author a beginner’s guide to Panda3D, and I’m using this game for that book. For that reason, I want to keep the code as clean and concise as possible.
Another approach is to disable all textures, and then reapply the ones you want:
child.setTextureOff() child.setTexture(myTs, myTex)
setTextureOff() with no parameters means to disable all TextureStages.
Still, I think depending on setTextureOff() is usually the wrong approach to avoid inheriting unwanted state. Restructuring the scene graph is cleaner and just as powerful.
I have to agree. I don’t like having to separate the joints I’m using to mount the children in their correct places from the models, and then load an actor and a model for the pieces that have children, but it works well enough and the actor files are less than a kb.
It’s a compromise I’ll make.