4
\$\begingroup\$

Introduction:

The following script contains code that performs what I would usually do when starting a new scene (add lights, camera, objects). The script will serve as a starting point for most of my future scripts.

In the future, I might use more complex materials, create animations, or use the built-in physics simulator (for example, rigid body, fluid, smoke).

This is what the script below renders:

monkey


The command to run the code is blender --background --python-exit-code 1 --python monkey.py. The code has been tested on Blender 2.81a (released December 5, 2019).

Here are some of my concerns:

  • There are quite a few lines which use bpy.ops. bpy.ops should be avoided.
  • Clearing all objects in the beginning with select_all and then delete looks like a workaround to me. There might be a way to start a scene without the default cube, light, and camera.

monkey.py

import bpy
import shutil
import os
import time

def add_light(location, light_type='POINT', color=(1.00, 1.00, 1.00), energy=1000.00):
    bpy.ops.object.add(type='LIGHT', location=location)
    obj = bpy.context.object

    obj.data.type = light_type
    obj.data.color = color
    obj.data.energy = energy

def set_smooth(obj, level=None, smooth=True):
    if level:
        modifier = obj.modifiers.new('Subsurf', 'SUBSURF')
        modifier.levels = level
        modifier.render_levels = level

    mesh = obj.data
    for p in mesh.polygons:
        p.use_smooth = smooth

def create_focal_point(location=(0.00, 0.00, 0.00)):
    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.10, location=location)
    focal_point = bpy.context.object
    focal_point.hide_render = True
    return focal_point

def set_focal_point(camera, focal_point):
    bpy.context.view_layer.objects.active = camera
    bpy.ops.object.constraint_add(type='TRACK_TO')
    camera.constraints['Track To'].target = focal_point
    camera.constraints['Track To'].track_axis = 'TRACK_NEGATIVE_Z'
    camera.constraints['Track To'].up_axis = 'UP_Y'

def create_monkey(origin=(0.00, 0.00, 0.00)):
    bpy.ops.mesh.primitive_monkey_add(location=origin)
    obj = bpy.context.object
    return obj

if __name__ == '__main__':
    # Delete all objects
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete()

    main_object = create_monkey()

    yellow_rgba = (1.00, 1.00, 0.00, 1.00)

    mat = bpy.data.materials.new(name='yellow')
    mat.use_nodes = True
    mat.diffuse_color = yellow_rgba
    nodes = mat.node_tree.nodes

    nodes.clear()
    node_material_output = nodes.new(type='ShaderNodeOutputMaterial')

    node_diffuse = nodes.new(type='ShaderNodeBsdfDiffuse')
    node_diffuse.name = 'Yellow Diffuse'
    node_diffuse.inputs['Color'].default_value = yellow_rgba

    input = node_material_output.inputs['Surface']
    output = node_diffuse.outputs['BSDF']
    mat.node_tree.links.new(input, output)

    main_object = bpy.context.active_object
    main_object.active_material = mat


    set_smooth(main_object, level=5)

    add_light(location=(5.00, -7.50, 5.00))

    bpy.ops.object.camera_add(location=(0.00, -5.00, 0.00))
    main_camera = bpy.context.object
    bpy.context.scene.camera = main_camera

    focal_point = create_focal_point(main_object.location)
    set_focal_point(main_camera, focal_point)


    bpy.context.scene.render.engine = 'CYCLES'
    bpy.context.scene.cycles.samples = 50

    bpy.context.scene.render.tile_x = 256
    bpy.context.scene.render.tile_y = 256

    bpy.context.scene.render.resolution_x = 600
    bpy.context.scene.render.resolution_y = 600

    bpy.context.scene.render.resolution_percentage = 100

    bpy.context.scene.render.image_settings.compression = 100

    base_filename = time.strftime('%Y %m %d - %H %M %S - ') + os.path.basename(__file__)
    base_filename_no_extension = os.path.splitext(base_filename)[0]
    shutil.copy(__file__, base_filename)

    bpy.ops.wm.save_as_mainfile(filepath=base_filename_no_extension+'.blend')

    bpy.context.scene.render.filepath = base_filename_no_extension+'.png'
    bpy.ops.render.render(write_still=True)
\$\endgroup\$

1 Answer 1

-1
\$\begingroup\$

Use alphabetical order for imports

import bpy
import os
import shutil
import time
\$\endgroup\$
4
  • 2
    \$\begingroup\$ Welcome to Code Review and thank you for supplying an answer. Is there a reason you suggest alphabetical order (e.g. a style guide like PEP8)? If so, please edit your post to add this explanation. \$\endgroup\$ Commented Feb 13, 2020 at 6:49
  • \$\begingroup\$ This is the start of a good review, but it's a bit small don't you think? \$\endgroup\$ Commented Feb 13, 2020 at 7:24
  • 1
    \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ As Pythonist I can confirm it's simply good practice to keep them ordered alphabetically and on import type (keep the import os separated from the from os import sleep from the import os as o statements). Oddly enough the latter isn't part of the PEP8. \$\endgroup\$ Commented Feb 13, 2020 at 7:27
  • \$\begingroup\$ isort sorts __futures__, builtin, 3rd part, own code. I prefer that to all alphabetically. Since there are tools to do this for me, and IDE's who make using these tools very simple, I haven't manually ordered my imports \$\endgroup\$ Commented Feb 13, 2020 at 8:44

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.