Texture Change Tutorial

Abstract

Change the image texture of an object at runtime. It can be used for things such as thumbnails, radars and others.

Prerequisite

Basic fimluarity with python.
bge.texture

Code

def textureChange(self, ffObj, matId=0, textuId=0, scale=None, swap=False):
  """
  changes the texture of an object
  ffObj can be a strPath, ffobj, or npArry
  Make sure self has an unique mesh, material, texture, and image.
  Passing the original image causes blackness
  scale is 'x' or 'y'.  scales the objs x axis so that it fits the new textures ratio
  swap switches axises to fix the Euclid scanline debate
  places the texture in a weirdly named property on the object
  """
 
  # This gets done in two places so we define it here.
  def doScale(scale):
    # Scale the objects x axis so that the x y raitio is correct.
    if scale == 'x':  self.localScale.x = ffObj.size[0] / ffObj.size[1]
    elif scale == 'y':  self.localScale.x = ffObj.size[1] / ffObj.size[0]
    else:  raise Exception("My hovercraft is full of eels")
 
  # This name will be used to stor the ffObj.  It needs to be unique.
  name = 'newTextu'+';'+str(matId)+','+str(textuId)
 
  # If ffObj is None, reset to the original texture.
  # numpy dosnt like compairng itself to None.  Go figure.
  if id(ffObj) == id(None): # np weirdness
    # Delete the stored ffObj
    try:  del self[name]
    # If its not there then do nothing.
    except KeyError:  pass
    # We did what we wanted so quit the function.
    return True
 
  # If ffObj is a string this will work convert it to an ImageFFmpeg otherwise it will do nothing.
  try:  ffObj = bge.texture.ImageFFmpeg(ffObj)
  except TypeError:  pass
 
  # Create the Texture and place it on self based off the unique name we gave it.
  self[name] = bge.texture.Texture(self, matId, textuId)
 
  # if its a ffObj then do the following otherwise do no thing.  Remember, if it was a string, we already converted it to a ffObj.
  try:
    # Set the bge.texture.Texture that we made's source.
    self[name].source = ffObj
    # I dont know what this dose but I gess it has to be done.
    self[name].refresh(False)
    if scale:  doScale(scale)
    # We did what we wanted so quit the function.    
    return True
  except TypeError:  pass
 
  # If we got this far it should be a numpy array.
  # For a numpy array our source should be a ImageBuff.
  self[name].source = bge.texture.ImageBuff()
  # This tells the ImageBuff that the array is Red, Green, Blue, Alpha, 32 bit.  This is a standard image format. 
  self[name].source.filter = bge.texture.FilterRGBA32()
  if swap:
    from numpy import swapaxes
    # Mathematicians start from the bottom left, artists from the top left.  So sometimes we have to swap the axises.  Go figure.
    ffObj = swapaxes(ffObj, 0, 1)
  # Convert the numpy array into a bytearray
  buf = bytearray(ffObj)
  # Load the bytearray into the ImageBuffer
  self[name].source.load(buf, ffObj.shape[0], ffObj.shape[1])
  self[name].refresh(False)
  if scale:  doScale(scale)

Questions

Log in and edit this post to ask or answer questions.

Further Reading

Thumbnail Tutorial
Byte Arrays
Numpy Quickstart

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License