0
$\begingroup$

I'm not sure I understand the UV image editor and its ability to hold images. I thought it was purely to get a visual comparison between your UVs and the image you use for texture mapping, but it seems that if you have an image in there, it affects OBJ material export. I would like to ask if this is an intended effect, and if not how to fix it, or just remove all UV editor images in a script.

More background:

I'm working with a mesh format for a game. I can already convert into this format from an OBJ file with some existing tools.

To export directly from blender, I have written an addon that first writes out an OBJ file and hands it on to the other conversion tool.

The OBJ files blender exports cannot fully support rich materials, but for my application all I really need is the filename of a single texture. My model uses the old blender renderer (no cycles), and has some number of objects/meshes, where each mesh has some number of material slots, and each material has just one shadeless texture and no other properties.

For the most part these are written out into a .mtl file and into usemtl directives in the OBJ.

However some of them are written correctly as

usemtl material_name

but are then using the wrong .png file in the .mtl file.

I dug into the builtin blender OBJ export addon and found that it writes a different image name by picking up something called the 'face image', which turned out to be Image data blocks that are linked to the UV editor. This only affected certain materials that I had manually loaded a UV Image for to manually align things.

So back in the python console I find the following:

>>> bpy.data.meshes[2].polygons[0].material_index
3
>>> bpy.data.meshes[2].materials[3].texture_slots[0].texture.image.name
'om_decals_02a.png'
>>> bpy.data.meshes[2].uv_textures.active.data[0].image
bpy.data.images['om_floor_03d.png']

This shows that it is possible to have one image in the texture, and a different one shown in the UV editor, and it is this latter one that is preferentially exported (but only if it's present).

I can fix all this up in my export by removing all the UV editor images, but my questions are:

  • why does the UV image preview affect the exported material when the actual material assigned to that poly disagrees?
  • How can I remove them all from python safely and what impact might that have beyond having to load the image again to align UV layouts.
  • Have I set this whole thing up wrong and should be building the model in a different way in the first place?

For removing the uv images I have this:

for mesh in bpy.data.meshes:
    for data in mesh.uv_textures.active.data:
        data.image = None

Will this do the job, or will it break things? Is there an API that will correctly handle removal of things like this instead? Is the python internal reference counter the same thing as blender's user counts, or does one track the other?

$\endgroup$
0
$\begingroup$

I think I've found a workable answer. My fragment of python for setting these images to None was almost there, there's a more in depth version in this answer: How to unlink material from a mesh, with python script? I keep my materials, but the answer also covers this UV tex_face property that is the problem.

The whole tex_face feature is going away in 2.8 (which is a good thing as it's old and really well hidden and rarely used): https://developer.blender.org/T51382

However there is one more crucial step which is to drop out of edit mode, otherwise none of the changes to the uv_texture images take effect before the export goes out, see the gotchas here: https://docs.blender.org/api/2.79/info_gotcha.html#modes-and-mesh-access

So my final code fragment is as follows:

bpy.ops.object.mode_set(mode='OBJECT')

# Strip all the tex_face data, otherwise the obj export will use it
# We want it to use the material textures.
for mesh in bpy.data.meshes:
    if mesh.uv_textures.active is not None:
        for tf in mesh.uv_textures.active.data:
            tf.image = None

for mesh in bpy.data.meshes:
    for texlay in mesh.uv_textures:
        for tf in texlay.data:
            tf.image = None

Now my export seems to be behaving itself.

$\endgroup$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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