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?
2 Answers
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.
-
$\begingroup$ Very interesting! Could you explain in your answer what you mean by 'channels'? Assume the reader having very little knowledge. $\endgroup$ Commented Sep 15, 2013 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$– z0rCommented Sep 15, 2013 at 14:49
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.
-
$\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$ Commented Sep 15, 2013 at 14:02
-
1$\begingroup$ It's fine to answer your own question, it is even encouraged if you have a great answer $\endgroup$– zeffiiCommented Sep 15, 2013 at 14:27