camera2path

Übersicht: Python & Blender


Lernziel

Das Setup mit Kamera und Empty soll nun durch einen Pfad erweitert werden. Die Kamera soll nicht nur auf das Empty ausgerichtet sein, sondern zusätzlich ein Objekt umkreisen. Dadurch entsteht eine dynamische Filmaufnahme vom Objekt, als würde es auf einem Drehteller präsentiert.

Handlungsanweisungen

Tasks:
  1. Füge das Skript in die eigene Szene ein.
  2. Führe das Skript aus.
  3. Starte das Test-Rendering gefolgt von folgenden Arbeitsschritten:
    • korrektur von Einstellungen
    • Veränderung der Einstellungen zur Qualität
    • Rendering des Video mit den finalen Einstellungen.

Welche Schritte sind notwendig?

Ausgehend vom schon vorhandenen Skript, fügen wir noch einen Pfad hinzu und binden die Kamera an den Pfad. Die Entwicklung eines solchen Skripts ist schon recht komplex. Wichtig ist die Aufteilung des Quellcodes in kleine Funktionen, die individuell getestet werden können. Als Beispiel-Objekt wurde Suzanne in der Mitte platziert. Sie kann durch eigenen Objekte ersetzt werden.

Ein Beispiel zeigt, wie ...

  1. das Setup ausgeführt wurde

  2. ein zweites Skript eine DNA-Struktur erzeugt hat

    Molekül-Beispiel

  3. die DNA an die Position von Suzanne platziert wurde

Das Ergebnis:

Das Script für das erweiterte Setup:

blender-extended/blender-setup-set/camera2path.py (Source)

#!bpy
"""
Name: 'SceneConfigurator'
Blender: 2.7x
Group: 'Low poly'
Tooltip: 'Configure standard settings in a new scene'
"""
import bpy


class SceneConfigurator:
    """Configure a scene"""

    def __init__(self):
        
        self.ctx = bpy.context
        
        self.remove(name="Empty")
        self.remove(name="Camera")
        self.remove(name="BezierCircle*")
        self.remove(name="Suzanne")
        self.remove(name="Sun*")
        
        bpy.ops.object.empty_add(type='PLAIN_AXES',
                                 view_align=False,
                                 location=(0, 0, 0))
        bpy.ops.object.camera_add(view_align=True,
                                  enter_editmode=False,
                                  location=(8, 8, 3),
                                  rotation=(90, 0, 0))
        
        bpy.ops.curve.primitive_bezier_circle_add(radius=50,
                                                  view_align=False,
                                                  enter_editmode=False,
                                                  location=(0, 0, 0))
        bpy.ops.mesh.primitive_monkey_add(radius=1,
                                          view_align=False,
                                          enter_editmode=False,
                                          location=(0, 0, 1))
        bpy.ops.object.lamp_add(type='SUN', radius=1,
                                view_align=False,
                                location=(10, 0, 10))
        
    def cam2empty(self):
        """Trac camera to empty

        Move the empty and the camera will point to this direction
        """
        bpy.ops.object.select_pattern(pattern='Empty')
        bpy.ops.object.select_pattern(pattern='Camera')
        bpy.ops.object.constraint_add(type='TRACK_TO')
        self.ctx.object.constraints["Track To"].target = bpy.data.objects["Empty"]
        self.ctx.object.constraints["Track To"].track_axis = 'TRACK_NEGATIVE_Z'
        self.ctx.object.constraints["Track To"].up_axis = 'UP_Y'

    def cam2path(self):
        """Bind the camera to a path"""
        
        bpy.ops.object.select_all(action='DESELECT')
        circ = bpy.data.objects['BezierCircle']
        cam  = bpy.data.objects['Camera']
        fp = cam.constraints.new(type='FOLLOW_PATH')
        fp.target = circ
        fp.forward_axis = 'TRACK_NEGATIVE_Z'
        fp.up_axis = 'UP_Y'
        cam.select = True
        self.ctx.scene.objects.active = cam
        override={'constraint':cam.constraints["Follow Path"]}
        bpy.ops.constraint.followpath_path_animate(override,
                                                   constraint='Follow Path')
        ctx_path = self.ctx.object.constraints["Follow Path"]
        ctx_path.forward_axis = 'TRACK_NEGATIVE_Z'
        ctx_path.up_axis = 'UP_Y'
        ctx_path.target = bpy.data.objects["BezierCircle"]
        ctx_path.use_curve_follow = True

    def sky(self):
        """A colorful sky"""
        
        self.ctx.scene.world.use_sky_paper = True
        self.ctx.scene.world.use_sky_blend = True
        self.ctx.scene.world.horizon_color = (0.606907, 0.613911, 0.837134)

    def output_format(self, folder="//render_out.avi"):
        """Some basic settings for rendering a movie"""
        
        self.ctx.scene.render.filepath = folder
        self.ctx.scene.render.image_settings.file_format = 'XVID'
        self.ctx.scene.render.resolution_percentage = 20

    def remove(self, name=None):
        """ Delete an object by name"""

        if name:
            bpy.ops.object.select_pattern(pattern=name)
        else:
            print('nothing to do')
         
        bpy.ops.object.delete()

if __name__ == "__main__":

    # switch to object mode, if nessasary
    if bpy.ops.object.mode_set.poll():
        bpy.ops.object.mode_set(mode='OBJECT')
    ctrl = SceneConfigurator()
    # the order matters...
    ctrl.cam2path()
    ctrl.cam2empty()
    ctrl.sky()
    ctrl.output_format()

Quellen: http://blender.stackexchange.com/questions/15307/scripting-cant-figure-out-how-to-use-correct-contexts

Kommentare