5
$\begingroup$

I am new to Blender. I create a cube and want to render it. Since, we are later going to do this for large number of shapes, we are working with Blender's Python API. I want to save this rendering as a png.

I have the following code:

image = bpy.ops.mesh.primitive_cube_add(radius=1, location = (0,0,0))
image.save_render("/Users/tarun/Work/check.png")

But it gives an error :

AttributeError: 'set' object has no attribute 'save_render'

Although when I do only bpy.ops.mesh.primitive_cube_add(radius=1, location = (0,0,0)), it shows the cube in the scene.

How can I create and save a shape like cube from the Python console in Blender?

$\endgroup$
1
  • 1
    $\begingroup$ You would normally set up a camera and then render the view from camera and save the result. try bpy.ops.render.render() $\endgroup$
    – rob
    Commented Oct 15, 2018 at 11:53

1 Answer 1

19
$\begingroup$

Please invest time into researching about the Blender API and Python interface, before asking questions!

image = bpy.ops.mesh.primitive_cube_add(radius=1, location = (0,0,0))

This line does not make any sense at all. primitive_cube_add is an operation, which returns a status set. In this case it returns {FINISHED}. {FINISHED} is most definitely not a python object with a save_render method.

To tackle the problem requires several steps.

  1. Avoid using ops.
  2. Create the cube.
  3. Avoid using ops.
  4. Create a camera, only cameras can render images.
  5. Avoid using ops.
  6. Create a light, otherwise your unlit cube is going to be black.
  7. Render an image (this can only by done with bpy.ops).

First import the necessary modules. Store the current scene inside a variable, that way we can access it later on.

import bpy
import mathutils

scene = bpy.context.scene

A method for creating the cube is found here. I have blatantly copied it. We will have to import the bmesh module.

# Create the cube
mesh = bpy.data.meshes.new('cube')
ob = bpy.data.objects.new('cube', mesh)

scene.objects.link(ob)

import bmesh
bm = bmesh.new()
bmesh.ops.create_cube(bm, size=1.0)
bm.to_mesh(mesh)
bm.free()

Creating the light need a lamp data-block and an object block as well. light.location changes the position of the lamp object. If it is at (0, 0, 0), it will not affect the result, because it will be stuck inside the cube.

# Create a light
light_data = bpy.data.lamps.new('light', type='POINT')
light = bpy.data.objects.new('light', light_data)
scene.objects.link(light)
light.location = mathutils.Vector((3, -4.2, 5))

The camera has to be repositioned and reoriented.

# Create the camera
cam_data = bpy.data.cameras.new('camera')
cam = bpy.data.objects.new('camera', cam_data)
scene.objects.link(cam)
scene.camera = cam

cam.location = mathutils.Vector((6, -3, 5))
cam.rotation_euler = mathutils.Euler((0.9, 0.0, 1.1))

Set the render settings of the current scene, and render it. write_still is necessary if you want the result to be written to the filepath. There will be no visual feedback during the render process.

# render settings
scene.render.image_settings.file_format = 'PNG'
scene.render.filepath = "F:/image.png"
bpy.ops.render.render(write_still = 1)

I'd post a result image, but it's just the default cube.

$\endgroup$
4
  • $\begingroup$ Nice answer! Could you briefly explain why you recommend to "avoid using ops"? The examples I've seen so far mostly rely on using bpy.ops and it seems to work fine in their cases. $\endgroup$
    – bluenote10
    Commented Oct 7, 2019 at 5:54
  • 1
    $\begingroup$ This answer is as ridiculously polemic as the question's code is ridiculous. However, I have not yet seen a good addon relying on bpy.ops. The search for this kind query lists this this top-voted question. $\endgroup$
    – Leander
    Commented Oct 7, 2019 at 9:38
  • 2
    $\begingroup$ Note that for newer (2.8+?) versions of Blender, you'll need to link using bpy.context.collection.objects.link instead of bpy.context.scene.objects.link and bpy.data.lamps is now bpy.data.lights. $\endgroup$
    – Nathan
    Commented Jan 19, 2020 at 0:17
  • 2
    $\begingroup$ @Bill Cheatham (1) The patronising text contains a hint "search the Blender Api". OP may not be aware of the api or its search function. (2) The repeated "avoid ops" steps stress the importance of avoiding ops and show that it may only be used in the last step for rendering. | Your edits don't fall in the editing categories (they are neither correcting mistakes, nor clarifying meaning). If you could revise your editing without changing the intent&meaning of (1) and (2) I would accept it. | If you think the answer is bad, simply downvote =) $\endgroup$
    – Leander
    Commented Jan 30, 2020 at 8:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .