Texture Weirdness

This may be a bug or just my lack of knowledge.

I’ve attached a blend plus some textures to demonstrate an issue with dynamically changing textures that is apparent in 2.78, UPBGE and 2.79 TextureCycler.zip (968 KB). Also refer to the code below.

The point of the example is that on a 50-tick delay the texture of a cube should cycle among the three textures in the directory: a grass texture, a color grid and a tile pattern.

What actually happens is that every second change reverts back to the original texture of the cube which happens to be the blender gray grid pattern. Note that grey grid pattern is never referenced in the code.

If anyone can explain why this happens I would love to know.

Thanks


import bge 
def doCycle(cont):
    obj=cont.owner    
    tex=pickTex(obj['iter'])
    if obj['iter']<2:
        obj['iter']+=1
    else:
        obj['iter']=0   
        
    changeTexture(obj,tex)
    
def pickTex(i):
    if i==0:
        tex="grass"                
    if i==1:
        tex="colorGrid"       
    if i==2:
        tex="Tile"  
        
    return tex  
        
def changeTexture(owner,tex):
      
    path = bge.logic.expandPath("//"+tex+".png")    
    imageSource = bge.texture.ImageFFmpeg(path)
    imageSource.refresh()
    
    object_texture = bge.texture.Texture(owner, 0,0)  # points to 0th material slot, 0th texture slot
    object_texture.source = imageSource               # SHOULD assign image each time but flip flops back to original texture
    object_texture.refresh(True)
    
    #store it
    owner["prop_+tex"] = object_texture
    # ==== read out
    print (path)


It works in BGE as well.
I think this is due to it needs a frame to unload the texture, so it falls back on the basic(greyscale) texture that you already have on it.

I would say use replaceMesh with deffrent textures, but the problem with this is that you going to use alot more Vram. Or you should grab the desired texture at startup, so if you want to change the settings let them restart the game (like 90% of the games do).

Other then that i have no clue.

Thanks, Cotaks that is an interesting thought. I would have to wonder why it unloads and properly refreshes the source exactly every other time. I would think that the 50 tick delay would help with that issue too.

I’m beginning to suspect that the texture can only be updated from the original texture and never from any dynamically loaded texture.

For what it is worth, the main benefit of the approach I am taking is that I can add textures to an object by simply dragging images into a folder or library and grabbing them with the script so I could access dozens of textures for any given mesh with fairly low overhead.

Ok, I took a look at the API and removing the permanent binding seems to do the trick. Previously this was obj[‘prop_’+tex] in the code below it is logic.texture.

from bge import logic
from bge import texture

def doCycle(cont):
    obj=cont.owner    
    tex=pickTex(obj['iter'])
    if obj['iter']<2:
        obj['iter']+=1
    else:
        obj['iter']=0   
         
    removeTexture()   
    createTexture(obj,tex)
    
def pickTex(i):
    if i==0:
        tex="grass"                
    if i==1:
        tex="colorGrid"       
    if i==2:
        tex="Tile"  
        
    return tex  
def createTexture(obj,tex):
    """Create a new Dynamic Texture"""
    # create a texture object
    object_texture = texture.Texture(obj, 0)
    # create a new source with an external image
    url = logic.expandPath("//"+tex+".png")
    new_source = texture.ImageFFmpeg(url)
    # the texture has to be stored in a permanent Python object
    logic.texture = object_texture
    # update/replace the texture
    logic.texture.source = new_source
    logic.texture.refresh(False)

def removeTexture():
    """Delete the Dynamic Texture, reversing back the final to its original state."""
    try:
        del logic.texture
    except:
        pass