4
$\begingroup$

I'd like to do a map in a game that moves with the actor. What is the proper syntax to move uv coordinates around and have the game engine update the result?

$\endgroup$
3
$\begingroup$

If you want to perform a linear transform such as translate or scale over all UVs, you can use the mesh.transformUV function. To use this function, you would usually set up two channels like so:

uv_offset = [0, 0]
def init(c):
    # Copy UVs to second channel using an identity matrix.
    c.owner.meshes[0].transformUV(-1, mathutils.Matrix(), 1, 0)

Thereafter you can transform from that second channel using a custom matrix:

def update(c):
    # Transform stored original values and write to first channel.
    uv_offset[0] += SPEED_X
    uv_offset[1] += SPEED_Y
    uv_mat = mathutils.Matrix.Translation((uv_offset[0], uv_offset[1], 0))
    c.owner.meshes[0].transformUV(-1, uv_mat, 0, 1)

This avoids the need to iterate over the vertices in your script, so it may be faster for large meshes. You can also perform multiple transforms at once, e.g. scale and translate, by multiplying two matrices together.

$\endgroup$
2
  • $\begingroup$ Very interesting! Could you explain in your answer what you mean by 'channels'? Assume the reader having very little knowledge. $\endgroup$ – Haunt_House Sep 15 '13 at 14:35
  • $\begingroup$ Actually I'm not sure! Maybe this would conflict with the multiple UV maps that a mesh can have. In any case if your mesh only has one UV map, this code should be fine. $\endgroup$ – z0r Sep 15 '13 at 14:49
3
$\begingroup$

After another search session, I found the answer here:

For a working blendfile, see the Blenderartists thread, thanks to HG1

from bge import logic # get the controller that executes the script
cont = logic.getCurrentController() # get the object that uses the controller
own = cont.owner     

speed_x = 0.002 # speed by which the coordinates are moved      
speed_y = 0.0   # speed by which the coordinates are moved    
mesh = own.meshes[0] # access the mesh of the object in question    
v_array = mesh.getVertexArrayLength(0) # how many verts are there?      
for v in range(0,v_array): # go through the uv's of every vert
    vert = mesh.getVertex(0,v) 
    uv = vert.getUV()         
    uv[0] += speed_x # change the uv coordinates. uv[0] = x, uv[1] = y
    uv[1] += speed_y        
    vert.setUV(uv) # get the game engine to notice the change!!

The name of your script belongs into the controller.

enter image description here

$\endgroup$
2
  • $\begingroup$ It hasn't been my intention to answer my own question when I asked it, but since I found the solution in the meantime... If anything is outdated or improvable, make a second answer and I'll approve that. $\endgroup$ – Haunt_House Sep 15 '13 at 14:02
  • 1
    $\begingroup$ It's fine to answer your own question, it is even encouraged if you have a great answer $\endgroup$ – zeffii Sep 15 '13 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.