Python Tools - Session 3A
Image-Based Mosaic
January 21, 2020
Session Navigation
Overview
This session introduces image-based 3D mosaic creation in Maya using PyMEL. You'll learn how to load an image texture, read its resolution, and use nested FOR loops to create a grid of cubes that tiles out to match the source image dimensions. This forms the foundation for the more advanced height-mapped mosaic in Session 3B.
Key Concepts
- File nodes — creating texture nodes in Maya to read image properties like resolution
- Nested FOR loops — iterating over X and Y axes to build a 2D grid of objects
- Tile sizing — dividing image resolution by tile size to calculate grid dimensions
- Position tracking — incrementing variables outside the loop to track placement coordinates
- List indexing — using
[0]to get the transform node from Maya's returned list
Code
This script creates a file node from a source image, calculates the grid dimensions, then uses nested loops to place cubes in a mosaic pattern.
# Import the PyMel module, and create the alias "pm" for it to save on typing later
import pymel.core as pm
# Create the variables that we may want to change
# The path to the image - change this to a path on your local drive
image_file = r"C:\path\to\your\image.jpg"
# This is the size of each tile in the mosaic
tile_size = 20
# Create a file node inside Maya for us to use
file_node = pm.createNode('file')
# Set the image path to be the image set above
file_node.fileTextureName.set(image_file)
# Now we calculate the number of tiles in each direction
# We do this by getting the resolution of the texture from the file node
# .. and dividing it by the tile size
# i.e. a resolution of 400, with tiles of 10 units, will create 40 tiles
width_count = int(file_node.outSizeX.get() / tile_size)
height_count = int(file_node.outSizeY.get() / tile_size)
# Print them out to make sure we get good values
print width_count, height_count
# Now we start the FOR loops
# Because we are counting along each axis as we go..
# .. we need to create a variable outside the loop to increment
x_pos = 0.0
for x in xrange(0, width_count):
# here we add "tile_size" to the x_pos of the current iteration
# += is short hand - the long form of this would be
# x_pos = x_pos + tile_size
x_pos += tile_size
# Same here for the Y axis
y_pos = 0.0
for y in xrange(0, height_count):
y_pos += tile_size
# Create a poly cube, setting the width, depth and height to be the size of the tile
# REMEMBER - creating most objects in Maya returns a list
# This contains both the Transform and the Shape
# We only want the transform - the first element
# We access the first element by using "[0]", the "zeroth" element in the list
tile = pm.polyCube(width=tile_size, depth=tile_size, height=tile_size)[0]
# Move the transform node to our new coordinates
pm.move(tile, [x_pos, 0, y_pos])