Hi, I’m trying to load an OBJ file with more than one texture, using VTK 9.1.0 in Python. This post shows the basic idea and there is some further discussion here.
The following code shows the essential steps. Given a polydata
object, an actor
and a mapper
, (vtkPolyData
, vtkPolyDataMapper
and vtkActor
respectively), query the polydata
field data to get the material names, then for each material load the appropriate texture file, link the texture to the material’s texture coordinates and set the texture on the actor
's vtkProperty
.
matNames = polydata.GetFieldData().GetAbstractArray('MaterialNames')
for n in range(matNames.GetNumberOfValues()):
matName = matNames.GetValue(n)
textureFilename = materials[matName]
tReader = vtk.vtkJPEGReader()
tReader.SetFileName(textureFilename)
texture = vtk.vtkTexture()
texture.SetInputConnection(tReader.GetOutputPort())
blendingMode = (
vtk.vtkTexture.VTK_TEXTURE_BLENDING_MODE_REPLACE if n == 0 else vtk.vtkTexture.VTK_TEXTURE_BLENDING_MODE_ADD
)
texture.SetBlendingMode(blendingMode)
texture.SetWrap(vtk.vtkTexture.ClampToBorder)
tName = f'texture{n:01}'
mapper.MapDataArrayToMultiTextureAttribute(
tName,
matName,
vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS)
actor.GetProperty().SetTexture(tName, texture);
This code works as expected as long as there are only two or fewer texture files. Once there are three or more the textures do not blend as expected, with the textures rendered earlier in the render process getting more and more saturated.
The following minimal OBJ example is a cube with a different material for each face:
mtllib cube.mtl
v -50.00 -50.00 50.00
v -50.00 50.00 50.00
v 50.00 -50.00 50.00
v 50.00 50.00 50.00
v 50.00 -50.00 -50.00
v 50.00 50.00 -50.00
v -50.00 -50.00 -50.00
v -50.00 50.00 -50.00
usemtl material_0
vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
f 4/1 2/2 1/3
f 3/4 4/1 1/3
usemtl material_1
vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
f 8/5 6/6 5/7
f 7/8 8/5 5/7
usemtl material_2
vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
f 6/9 4/10 3/11
f 5/12 6/9 3/11
usemtl material_3
vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
f 2/13 8/14 7/15
f 1/16 2/13 7/15
usemtl material_4
vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
f 6/17 8/18 2/19
f 4/20 6/17 2/19
usemtl material_5
vt 1.00 1.00
vt 0.00 1.00
vt 0.00 0.00
vt 1.00 0.00
f 3/21 1/22 7/23
f 5/24 3/21 7/23
When the above Python code is used to map the same image to each face and render the cube, this is the result:
Only one face (the face assigned material_5
) maps the texture correctly; the other five are more or less washed-out. (The expected outcome is a cube with the same image on each face.) If instead only two materials are used, the cube renders as expected.
Can anyone spot any errors in my approach, or is this likely to be a bug in VTK? Any help would be appreciated. I have a full working example if anyone would like to try it out, but cannot upload here as I am a new user