Panda3D Manual: Simple Texture Replacement
<<prev | top | next>> |
Although usually you will load and display models that are already textured, you can also apply or replace a texture image on a model at runtime. To do this, you must first get a handle to the texture, for instance by loading it directly:
    myTexture = loader.loadTexture("myTexture.png")
The above loadTexture() call will search along the current model-path for the named image file (in this example, a file named "myTexture.png"). If the texture is not found or cannot be read for some reason, None is returned. Once you have a texture, you can apply it to a model with the `setTexture()` call. For instance, suppose you used the CardMaker class to generate a plain white card:
    cm = CardMaker('card')
    card = render.attachNewNode(cm.generate())
Then you can load up a texture and apply it to the card like this:
    tex = loader.loadTexture('maps/noise.rgb')
    card.setTexture(tex)
In order for this to work, the model you apply it to must already have texture coordinates defined (see Simple Texturing). As it happens, the CardMaker generates texture coordinates by default when it generates a card, so no problem there. You can also use `setTexture()` to replace the texture on an already-textured model. In this case, you must specify a second parameter to setTexture, which is the same optional Panda override parameter you can specify on any kind of Panda state change. Normally, you simply pass 1 as the second parameter to setTexture(). Without this override, the texture that is assigned directly at the Geom level will have precedence over the state change you make at the model node, and the texture change won't be made. For instance, to change the appearance of smiley:
    smiley = loader.loadModel('smiley.egg')
    smiley.reparentTo(render)
    tex = loader.loadTexture('maps/noise.rgb')
    smiley.setTexture(tex, 1)
Often, you want to replace the texture on just one piece of a model, rather than setting the texture on every element. To do this, you simply get a NodePath handle to the piece or pieces of the model that you want to change, as described in the section Manipulating a Piece of a Model, and make the `setTexture()` call on those NodePaths. For instance, this car model has multiple textures available in different colors: For the most part, this car was painted with one big texture image, which looks like this: But we also have a blue version of the same texture image: Although it is tempting to use setTexture() to assign the blue texture to the whole car, that would also assign the blue texture to the car's tires, which need to use a different texture map. So instead, we apply the blue texture just to the pieces that we want to change:
    car = loader.loadModel('bvw-f2004--carnsx/carnsx.egg')
    blue = loader.loadTexture('bvw-f2004--carnsx/carnsx-blue.png')
    car.find('**/body/body').setTexture(blue, 1)
    car.find('**/body/polySurface1').setTexture(blue, 1)
    car.find('**/body/polySurface2').setTexture(blue, 1)
And the result is this:
<<prev | top | next>> |