4
$\begingroup$

I'm trying to use Blender's mesh displacement from a script to create stl's. Once this works, I'll run blender with --background to create the stl files from the command line.

I start Blender with:

blender ~/3D/Models/4x4UVSquare.blend -d -P ./test.py

the script is:

import bpy

bpy.ops.image.open(filepath="junk.jpg", \
    directory="/Users/me/3D/Art Work/", \
    files=[{"name":"junk.jpg", "name":"junk.jpg"}], \
    relative_path=True, show_multiview=False \
)
bpy.data.images["junk.jpg"].reload()
bpy.data.textures['displaceImage'].image = bpy.data.images['junk.jpg']

I put in the ".reload()" hoping it would help. It doesn't. Blender starts up, loads the .blend file, loads the image and assigns the image to the texture. When the UI comes up and displays the scene, there's no displacement. In the UI Image area under Texture, the filename is correct, but a little message reads "Can't load image".

When I hit the "reload" icon, the image reloads, the displacement appears and all it well.

Why do I have to reload the image at all? Why doesn't image.reload() work in the script?

$\endgroup$
6
$\begingroup$

To load an image from disk doesn't require bpy.ops. You could use:

bpy.data.images.load(filepath, check_existing=False)
# Load a new image into the main database

>>> bpy.data.images.load("/home/zeffii/Desktop/some_image.png")
# bpy.data.images['some_image.png']

# if an image exists by that name already, you could set the name
bpy.data.images['some_image.png.001'].name = 'some_image.png'

# check_exist=True will reuse an existing image with that name
>>> bpy.data.images.load("/home/zeffii/Desktop/some_image.png", check_existing=True)

bpy.ops.* are triggered each time you interact in some way with the UI (buttons, shortcuts..). Often the UI triggers a bpy.ops.whatever with information about which window the event occurred in - this is important because you could have two UV image editors open, or two TextEditors (just an example). Therefor sometimes just calling the ops isn't enough, and some ops even expect a UI which isn't present in background mode.

All these ops eventually operate on lower level bpy database content. So when possible avoid bpy.ops and look through bpy.data to find a more direct route. The auto-complete function of the bpy console is great for finding methods and attributes.

|improve this answer|||||
$\endgroup$
  • $\begingroup$ Thanks for you reply. I was able to load the image using bpy.data.images as you suggested. My goal is to using blender in a script without invoking to GUI. Is there a bpy.data.objects equivalent of bpy.ops.object.modifier_apply? I know there must be scriptable equivalents to apply anything from the GUI since the rendering process has to be able to do it. I'm new to Blender, it's amazing, but information about it very scattered. $\endgroup$ – S'rCat Dec 21 '15 at 21:35
  • $\begingroup$ Yep. Most things can be done via lower level calls. Don't hesitate to ask new separate questions. That way the answers can be found by others who search the site / google. instead of modifiers_apply I would use obj.data.to_mesh() which returns a mesh with modifiers applied if you want, then you assign the mesh to the old object or new object.. Ask a new question . more space to answer. $\endgroup$ – zeffii Dec 21 '15 at 21:59

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.