about texturing from code

mhm i have a really newbie question about textures:

imagine you have an .egg model of a barrel, with some texture map applied on, and that you make like 8 different textures that goes well with the model

so wich is the best way to insert various barrels in your scene each one with one of the 8 textures choosed random?

if i export the egg with one texture applied, when i make

tx = loader.loadTexture(txfile)

nothing changes, all barrels keep showing the texture in the .egg file

another question,

i suppose is impossible to apply a diferent texture to an instance of the barrel model
isn’t it?

Thanks as ever!

If you want to use setTexture while you already have a texture supplied, you can set the priority:

model.setTexture(tx, 1)

That will replace the previous texture.

No, I don’t see a reason why it would be impossible.

What about something like this:

from random import randint
barrel = loader.loadModel("barrel.egg")
# Suppose you have textures like barrel0.png, barrel1.png, etc:
textures = [ loader.loadTexture("barrel%d.png" % i) for i in range(8) ]

numberOfBarrels = 10
for bnum in range(numberOfBarrels):
  # Use copyTo instead if this doesn't work:
  instance = barrel.instanceTo(render)
  instance.setTexture(textures[randint(0, 7)], 1)
for bnum in range(numberOfBarrels):
  instance = barrel.instanceTo(render)
  instance.setTexture(textures[randint(0, 7)], 1) 

The above won’t actually work, because each instance shares the same PandaNode, and each time you call setTexture() you are setting it all the instances at once. However, you could do this instead:

for bnum in range(numberOfBarrels):
  dummy = render.attachNewNode('barrel-%s' % (bnum))
  dummy.setTexture(textures[randint(0, 7)], 1) 
  dummy.setPos(bnum * 4, 0, 0)

Note that you want to set each barrel to a different position, too, or they’ll all come up in the same place.

However, this is not an example of good coding practices. Instances are liable to lead to confusions such as the one above, and their overuse can lead to all sorts of difficult-to-debug problems. In return, they provide no performance gain, and no significant memory gain, over using copies.

So use copyTo instead. It’s just better.


model.setTexture(tx, 1) is perfect, replace the texture already embedded as i wanted.

As you imagined, texturizing the instances was only possible using copyTo instead of instanceTo,

but when i look at the stats of render.analyze i see it says 0 instances, so,
is copyTo the same as instanceTo for optimizing performance?

Thanks for simplifying a lotttt my panda learning!

Let me say it one more time. Instancing is not a rendering optimization. It takes exactly as much time to render 100 instances as it does to render 100 copies.

It’s a common mistake: it seems sensible that using instances should be a render optimization. And there do exist exotic platforms (like the original PlayStation) for which this is true. Panda doesn’t run on any of these platforms, however. (It is possible to write a shader to use hardware instancing on the card, which can provide a small performance gain. Panda doesn’t do this at the moment, and even if it did, it could likely do the same thing when you use copyTo() anyway.)

So, bottom line: forget about instancing. It exists for a reason, but that reason has nothing to do with performance optimizations. You can use Panda for years before you ever come across a real need to use instancing.


thanks david,
good to know that for shure.
copyTo looks an excellent option.


what instances do? Speed up when you have many models animating?

If you have many models animating and you want them all to be posed to exactly the same frame, yes, instances can help there. That’s the situation described in the manual, but it’s obviously a pretty contrived situation. Maybe you’ve got a crowd scene, though, and you’ve got hundreds of models walking around, each on one of five or six different frames at the same time. That wouldn’t be so bad.

The main reason we’ve ever found to use instancing is when you want the kind of weird shared behavior it gives you. For instance, in Toontown, there are scenes where a Toon takes out a pie and holds it in his hand in preparation to throw it. This means that we need to load a pie model and parent it to the Toon’s right hand node. The complication is that each Toon has three levels of detail, which means each Toon has three different right hand nodes. If we parented the pie only to the topmost level of detail, then when you took a few steps back, the pie would disappear–so we really need to parent three different pies to three different right hand nodes. That’s a nuisance to keep track of. Instead, we have just one node, which is instanced to each of the three different hand nodes, and we parent one pie to that node instead. That implicitly creates three instances of the pie with one operation.

As you can see, you have to work pretty hard to find a situation in which instancing actually helps you.