bracelet

Übersicht: Python & Blender


Lernziele

Schmuck herstellen, persönlich und indivduell?
Angeregt vom japasichen Autor *Takuro Wada* wird gezeigt, wie mit Blender ein Armreif für den 3D-Druck vorbereitet wird. Wie so oft, hilft ein Python-Script, bei der Automatisierung der vielen Arbeitsschritte.


Aufgaben:
  1. verwende dieses Skript (am Ende des Artikels)

  2. erstelle daraus eine eigenen Version z.B. mit Löchern

    c

  3. bereite den 3D-Druck vor

  4. schicke ein Foto mit Deinem Armreif an pkoppatz[at]web.de

Erläuterungen

Das Grundelement

Für einen wiederholten Start des Scripts werden alle Objekte aus der Szene entfernt. Das Armband soll aus einer Kugel (uv_sphere) als Grundform erstellt werden. Diese Kugel muss nun mehrfach erzeugt und eingefügt werden. Die dafür benötigeten Positionen müssen für jede Kugel berechnet werden.

Löschen: siehe Funktion delete_all() Objekte erstellen: siehe Funktion create_objects()

Alle Einzelobjekte zusammenfügen

Wenn der erste Schritt vollendet ist, erhält man ein Band. Für die nächsten Schritte werden alle Einzelteile zu einem Objekt vereint.

Objekte verbinden: siehe Funktion glue_all()

Ein Objekt, das gebogen werden kann

Zur Steuerung des Biegevorgangs wird ein zweites Objekt benötigt. Dafür kommt ein "EMPTY" vom typ "Pfeil" zum Einsatz.

Objekte verbinden: siehe Funktion bend_object_add()

Das Pfeil-Objekt biegen

Mit einem Modifier wird nun der "imaginäre/unsichtbare" Pfeil gebogen. Um den Winkel in Grad angeben zu können, wird eine Umrechnungsfunktion eingesetzt.

Umrechnung: siehe Funktion deg_to_rad(d) Biegen (des aktiven Objects) mit einem zweiten Modifier.

Biegevorgang: siehe Funktion bend()

b

Farbe

Für die Farbe kann das Objekt ausgewählt und ein neues Material erstellt und zugewiesen werden (hier nicht gezeigt).

Vorschaubild rendern

Wenn Du eine Vorschau erstellen willst, wie in den Bildern gezeigt, brauchst Du noch eine Kamera, eine Lichtquelle und eine Hintergrundfarbe. Alle Drei Elemente werden mit dem zweiten Skript gneriert. Die Kamera ist an ein Empty (camera_control) gebunden und wird immer daran ausgerichtet. Verschiebe also die Objekte "Empty" und/oder "Camera" um den gewüschten Ausschnitt für das Rendern einzustellen.

Scripte

Generator-Skript für das Armband

use-cases/art/bracelet/gen-bracelet-en.py (Source)

#!bpy
"""
Name: 'Generator for bracelts'
Blender: 2.7x
Group: 'Generators'
Tooltip: 'Creat a basic shape for a bracelet'
"""
import bpy

def create_objects(x=0, y=0, z=0, anz=20):

   for i in range(anz):
      bpy.ops.mesh.primitive_uv_sphere_add(size=1,
                                           segments=64,
                                           ring_count=32,
                                           view_align=False,
                                           enter_editmode=False,
                                           location=(i*1.4, y, z+2))
      # maybe more flat...
      # bpy.ops.transform.resize(value=(0.65, 0.65, 0.65),
      #                         constraint_axis=(False, False, True))
def deg_to_rad(d):
    import math
    return d * math.pi / 180.0

def glue_all():
   scn = bpy.context.scene
   teil = scn.objects['Sphere']
   scn.objects.active = teil
   for i, sphere in enumerate(bpy.data.objects):
      if i == 0:
         continue
      boolean = teil.modifiers.new('SphereBoolean', 'BOOLEAN')
      boolean.object = sphere
      boolean.operation = 'UNION'
      bpy.ops.object.modifier_apply(apply_as='DATA', modifier='SphereBoolean')
      bpy.context.scene.objects.unlink(sphere)


def bend_object_add():
   rx = deg_to_rad(90)
   ry = deg_to_rad(-180)
   rz = deg_to_rad(-90)

   bpy.ops.object.empty_add(
      type='ARROWS',
      radius=1,
      view_align=False,
      location=(0, 0, 0),
      rotation=(rx, ry, rz)
   )
   return

def bend():
   scn = bpy.context.scene
   teil = scn.objects['Sphere']
   scn.objects.active = teil
   bpy.ops.object.modifier_add(type='SIMPLE_DEFORM')
   bpy.context.object.modifiers["SimpleDeform"].deform_method = 'BEND'
   bpy.context.object.modifiers["SimpleDeform"].angle = deg_to_rad(350)
   bpy.ops.object.modifier_apply(apply_as='DATA', modifier="SimpleDeform")

def delete_all():
    for item in bpy.context.scene.objects:
        bpy.context.scene.objects.unlink(item)

    for item in bpy.data.objects:
        bpy.data.objects.remove(item)

    for item in bpy.data.meshes:
        bpy.data.meshes.remove(item)

    for item in bpy.data.materials:
        bpy.data.materials.remove(item)

if __name__ == "__main__":
   delete_all()
   # first ring
   create_objects(1,3,1,40)
   # second ring
   create_objects(1,3,2,40)
   # third ring
   create_objects(1,3,3,40)

   glue_all()
   bend_object_add()
   bend()

Setup für das Rendern eines Bildes

use-cases/art/bracelet/settings.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):
        pass

    def light(self):

        bpy.ops.object.lamp_add(type='HEMI',
        radius=1, view_align=False, location=(1, -30, 90))

    def cam2empty(self):
        """Trac camera to empty

        Move the empty and the camera will point in this direction
        """
        bpy.ops.object.empty_add(type='PLAIN_AXES',
                                 view_align=False,
                                 location=(0, 11, 4))
        bpy.context.object.name = "camera_control"

        bpy.ops.object.camera_add(view_align=True,
                                  enter_editmode=False,
                                  location=(0, -40, 24),
                                  rotation=(0, 0, 0))
        #bpy.ops.object.select_pattern(pattern='Empty')
        #bpy.ops.object.select_pattern(pattern='Camera')
        bpy.ops.object.constraint_add(type='TRACK_TO')
        bpy.context.object.constraints["Track To"].target = bpy.data.objects["camera_control"]
        bpy.context.object.constraints["Track To"].track_axis = 'TRACK_NEGATIVE_Z'
        bpy.context.object.constraints["Track To"].up_axis = 'UP_Y'

    def sky(self):
        bpy.context.scene.world.use_sky_paper = True
        bpy.context.scene.world.use_sky_blend = True
        bpy.context.scene.world.horizon_color = (0.606907, 0.613911, 0.837134)

    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()
    ctrl.remove(name="camera_control")
    ctrl.remove(name="Camera")
    ctrl.remove(name="Hemi")
    ctrl.light()
    ctrl.cam2empty()
    ctrl.sky()

Kommentare