Blender Dokumentation: Ein Beispielscript in Python

Aus Wikibooks
Wechseln zu: Navigation, Suche
<<<Zurück
Python in Blender
Inhaltsverzeichnis

Handbuch durchsuchen

Weiter>>>
Mitgelieferte Scripte


Diese Seite bezieht sich auf Blender v2.42a


Inhaltsverzeichnis

[Bearbeiten] Ein Beispiel in Python

Nun wissen Sie, dass Blender mit Python erweiterbar ist, wie man damit umgeht und ein Script ausführt. Bevor Sie Ihrem Gehirn nun die volle Breitseite mit der Python API Referenz geben, wollen wir uns erst ein kleines Beispiel zu Gemüte führen.

Wir bauen uns ein kleines Script, welches Polygone erzeugt. Das macht zwar so ziemlich das Gleiche wie die Space>>Add>>Mesh>>Circle Toolboxoption, es erzeugt aber 'gefüllte' Polygone - nicht nur die Aussenlinie.

Um das Script schön einfach bedienbar zu machen, spendieren wir ihm eine Benutzerschnittstelle (GUI), welche wir komplett mit der Blender API erzeugen.

[Bearbeiten] Headers, Import von Modulen und globale Variablen

Hier kommen die ersten 32 Zeilen des Scripts

Script Header

001 ######################################################
002 #
003 # Demo Script für das Blender Handbuch
004 #
005 ######################################################
006 # Diese Script erzeugt Polygone. Funktionell ist es 
007 # überflüssig, da gefüllte Polygone mit  
008 # ADD->Mesh->Circle erzeugt werden können. Aber es 
009 # ist ein schönes, komplettes Beispielscript.
010 ######################################################
011 
012 ######################################################
013 # Import der Module
014 ######################################################
015 
016 import Blender
017 from Blender import NMesh
018 from Blender.BGL import *
019 from Blender.Draw import *
020 
021 import math
022 from math import *
023 
024 # Polygon Parameters
025 T_NumberOfSides = Create(3)
026 T_Radius        = Create(1.0)
027 
028 # Events
029 EVENT_NOEVENT = 1
030 EVENT_DRAW    = 2
031 EVENT_EXIT    = 3
032 


Zuerst kommt der Kommentar mit der Erklärung, was das Script macht. In den Zeilen 016-022 importieren wir die Pythonmodule:

  • Blender ist das Blender-Python API Hauptmodul
  • NMesh ist das Modul welches den Zugriff auf Blenders Meshes unterstützt,
  • BGL gibt Zugriff auf die OpenGL Funktionen
  • Draw gibt Zugriff auf Blenders Fensterschnittstelle
  • Das math Modul ist, wie unschwer zu erraten, Pythons Mathemodul.


Blender3D FreeTip.gif

Wenn Sie Python nicht komplett installiert haben oder nicht wollen, dann ändern Sie die Zeilen
021 import math
022 from math import *
in
021 from Blender import Mathutils
022 from Blender.Mathutils import *



Die Polygone werden durch die Anzahl ihrer Seiten und ihren Radius definiert. Die Werte dieser Parameter werden durch den Benutzer über die GUI eingegeben. In den Zeilen 025-026 erzeugen wir zwei Generic Button Objekte mit ihren Startwerten.

Intern erzeugen die GUI-Objekte Events. Events IDs [Events identifier] sind Integer, die der Programmierer definiert. Es hat sich als sinnvoll erwiesen, den Events Mnemonic Namen zu geben, wie es hier in den Zeilen 029-031 gemacht wurde.

[Bearbeiten] Zeichnen der GUI

Der Code, der für das Zeichnen der GUI verantwortlich ist, wird in eine draw Funktion geschrieben.

033 ######################################################
034 # Zeichnen der GUI
035 ######################################################
036 def draw():
037     global T_NumberOfSides
038     global T_Radius
039     global EVENT_NOEVENT, EVENT_DRAW, EVENT_EXIT
040 
041     ########## Titel
042     glClear(GL_COLOR_BUFFER_BIT)
043     glRasterPos2d(8, 103)
044     Text('Demo Polygon Script')
045 
046     ######### Die Parameter der GUI Buttons
047     glRasterPos2d(8, 83)
048     Text("Parameter:")
049     T_NumberOfSides = Number('Anz. Seiten: ', EVENT_NOEVENT, 10, 55, 210, 18,
050                     T_NumberOfSides.val, 3, 20, 'Anzahl der Polygonaussenkanten');
051     T_Radius        = Slider('Radius: ', EVENT_NOEVENT, 10, 35, 210, 18,
052                     T_Radius.val, 0.001, 20.0, 1, 'Radius des Polygons');
053 
054     ######### Zeichnen- und Exitbuttons
055     Button('Zeichnen',EVENT_DRAW , 10, 10, 80, 18)
056     Button('Exit',EVENT_EXIT , 140, 10, 80, 18)
057 

Die Zeilen 037-039 gewähren lediglich Zugriff auf globale Daten. Wirklich interessant wird es erst ab den Zeilen 042-044. Hier wird das OpenGL Fenster initialisiert und auf die Position X=8 und Y=103 gesetzt. Dabei wird die linke untere Ecke des Scriptfensters als Ausgangspunkt angenommen. Dort wird der Titel Demo Polygon Script ausgegeben.

Unter dem String Parameter: (Zeilen 047-048) werden die Buttons für die Parameter erzeugt. Der Erste ist ein Number Buttom (Zeile 049-050), wie er in den verschiedenen Buttons Fenstern von Blender zu finden ist. Grundsätzliche Parameter sind:

  • der Buttonname (das was draufsteht)
  • das Event, welches durch den Button ausgelöst wird
  • die Position (x,y), die Größe (Höhe, Breite)
  • der Initialwert
  • der minimal und maximal mögliche Wert
  • einen String, welcher als Tooltip erscheint, wenn Sie mit der Maus darüberfahren.


Blender3D FreeTip.gif

Schauen Sie bitte in die API-Referenz für mehr Informationen über die Parameter.



In den Zeilen 051-052 wird ein Number Button mit einem Slider definiert. Die Zeilen 055-056 erzeugen einen Klickbutton mit dem Titel 'Zeichnen', welcher das Polygon generiert, und einen Exit Button.

[Bearbeiten] Eventbehandlung

Die GUI wird nicht ohne den dazugehörigen und registrierten Eventhandler gezeichnet.

058 def event(evt, val):        
059     if (evt == QKEY and not val): 
060             Exit()
061 
062 def bevent(evt):
063     global T_NumberOfSides
064     global T_Radius
065     global EVENT_NOEVENT, EVENT_DRAW, EVENT_EXIT
066 
067     ######### GUI Events behandeln
068     if (evt == EVENT_EXIT): 
069             Exit()
070     elif (evt== EVENT_DRAW):
071             Polygon(T_NumberOfSides.val, T_Radius.val)
072             Blender.Redraw()
073 
074 Register(draw, event, bevent)
075

In den Zeilen 058-060 wird ein Eventhandler für die Tastatur definiert, welcher auf das Drücken der Q-Taste mit dem Aufruf der Funktion Exit() reagiert und das Script verlässt.

Viel interessanter sind die Zeilen 062-072, da sie die GUI Events steuern. Diese Funktion wird jedes Mal aufgerufen, wenn ein GUI Button benutzt wird. Ihr wird die Eventnummer der Buttons als Parameter übergeben. Der Kern dieser Funktion ist daher eine "Switch" Struktur, die je nach Event verschiedenen Code ausführt.

Als letztes wird die Register Funktion aufgerufen. Sie zeichnet schlußendlich die GUI und startet eine Dauerschleife für die Eventerfassung.

[Bearbeiten] Meshes

Am Ende kommen wir noch zur Hauptfunktion [main function], die das Polygon erzeugt. Hier wird eigentlich einfach nur ein Mesh editiert, aber es offenbart eine Menge wichtiger Punkte der internen Datenstruktur von Blender.

076 ######################################################
077 # Hauptfunktion
078 ######################################################
079 def Polygon(NumberOfSides,Radius):
080
081     ######### Erstellt ein neues Mesh
082     poly = NMesh.GetRaw()
083
084     ######### Fügt Vertices zu dem Mesh hinzu 
085     for i in range(0,NumberOfSides):
086       phi = 3.141592653589 * 2 * i / NumberOfSides
087       x = Radius * cos(phi)
088       y = Radius * sin(phi)
089       z = 0
090
091       v = NMesh.Vert(x,y,z)
092       poly.verts.append(v)
093
094     ######### Fügt einen neuen Vertex in die Mitte ein
095     v = NMesh.Vert(0.,0.,0.)
096     poly.verts.append(v)
097
098     ######### Verbindet die Vertices zu einem Face
099     for i in range(0,NumberOfSides):
100             f = NMesh.Face()
101             f.v.append(poly.verts[i])
102             f.v.append(poly.verts[(i+1)%NumberOfSides])
103             f.v.append(poly.verts[NumberOfSides])
104             poly.faces.append(f)
105
106     ######### Erstellt ein neues Objekt aus dem Mesh
107     polyObj = NMesh.PutRaw(poly)
108
109     Blender.Redraw()

Die erste wichtige Zeile ist 082. Hier wird ein neues Meshobjekt namens poly erzeugt. Das Meshobjekt besteht aus einer Reihe Vertices und Faces, plus einigen anderen interessanten Sachen. Für unsere Zwecke reichen die Vertices und Faces aus.

Naturgemäß ist ein neues Mesh leer. Die erste Schleife in den Zeilen 085-092 errechnet die x,y,z Position der NumberOfSides Vertices, welche für das Erzeugen des Polygons nötig sind. Weil z=0 ist, ist das Polygon flach.

Die Zeile 091 ruft die Methode vert von NMesh auf, die ein neues Vertexobjekt mit den Koordinaten (x,y,z) erzeugt. Dieses Objekt wird dann in die verts' Liste des Meshobjekts poly hinzugefügt (Zeile 092).

Zum Schluss wird noch ein letztes Vertex in die Mitte eingefügt (Zeilen 095-096).

Die Zeilen 099-104 verbinden die Vertices um ein Face zu erstellen. Es ist nicht notwendig zuerst alle Vertices und dann die Faces zu erstellen. Ein neues Face kann erstellt werden, wenn alle seine Vertices erstellt sind.

Die Zeile 100 erzeugt ein neues Faceobjekt. Ein Faceobjekt bringt seine eigene, leere, Liste v (mehr als 4 Vertices) mit, wodurch es definiert wird. Die Zeilen 101-103 fügen der leeren Liste f.v 3 Vertices hinzu. Die Vertices sind 2 nachfolgende Vertices des Polygons und des zentralen Vertice. Diese Vertices müssen von der Meshliste verts genommen werden. Die letzte Zeile der Schleife 104 fügt das neu erzeugte Face der faces Liste unseres Meshobjektes poly hinzu.

[Bearbeiten] Ergebnis

Abbildung 2: Unsere erzeugte GUI

Erstellen Sie nun eine Datei polygon.py mit dem Code als Inhalt und laden Sie sie in Blenders Textfenster, wie es oben erklärt wurde. Drücken Sie nun Alt-P um das Script zu starten. Das Textfenster wird grau und in der linken unteren Ecke wird die GUI gezeichnet.


Wenn Sie nun, sagen wir mal, 5 Vertices und einen Radius von 0.5 einstellen und auf den Zeichnen Button drücken, erscheint eine XZ Ebene im 3D Fenster.

Abbildung 3: Unser erzeugtes Polygon


[Bearbeiten] Scriptlisting

Hier ist das Script ohne Zeilennummern:

import Blender
from Blender import NMesh
from Blender.BGL import *
from Blender.Draw import *

import math
from math import *

# Polygon Parameters
T_NumberOfSides = Create(3)
T_Radius        = Create(1.0)

# Events
EVENT_NOEVENT = 1
EVENT_DRAW    = 2
EVENT_EXIT    = 3

######################################################
# Zeichnen der GUI
######################################################
def draw():
    global T_NumberOfSides
    global T_Radius
    global EVENT_NOEVENT, EVENT_DRAW, EVENT_EXIT

    ########## Titel
    glClear(GL_COLOR_BUFFER_BIT)
    glRasterPos2d(8, 103)
    Text('Demo Polygon Script')

    ######### Die Parameter der GUI Buttons
    glRasterPos2d(8, 83)
    Text("Parameter:")
    T_NumberOfSides = Number('Anz. Seiten: ', EVENT_NOEVENT, 10, 55, 210, 18,
                    T_NumberOfSides.val, 3, 20, 'Anzahl der Polygonaussenkanten');
    T_Radius        = Slider('Radius: ', EVENT_NOEVENT, 10, 35, 210, 18,
                    T_Radius.val, 0.001, 20.0, 1, 'Radius des Polygons');

    ######### Zeichnen- und Exitbuttons
    Button('Zeichnen',EVENT_DRAW , 10, 10, 80, 18)
    Button('Exit',EVENT_EXIT , 140, 10, 80, 18)

def event(evt, val):       
    if (evt == QKEY and not val):
            Exit()

def bevent(evt):
    global T_NumberOfSides
    global T_Radius
    global EVENT_NOEVENT, EVENT_DRAW, EVENT_EXIT

    ######### GUI Events behandeln
    if (evt == EVENT_EXIT):
            Exit()
    elif (evt== EVENT_DRAW):
            Polygon(T_NumberOfSides.val, T_Radius.val)
            Blender.Redraw()

Register(draw, event, bevent)

######################################################
# Main Body
######################################################
def Polygon(NumberOfSides,Radius):

    ######### Creates a new mesh
    poly = NMesh.GetRaw()

    ######### Populates it of vertices
    for i in range(0,NumberOfSides):
      phi = pi * 2 * i / NumberOfSides
      x = Radius * cos(phi)
      y = Radius * sin(phi)
      z = 0

      v = NMesh.Vert(x,y,z)
      poly.verts.append(v)

    ######### Adds a new vertex to the center
    v = NMesh.Vert(0.,0.,0.)
    poly.verts.append(v)

    ######### Connects the vertices to form faces
    for i in range(0,NumberOfSides):
            f = NMesh.Face()
            f.v.append(poly.verts[i])
            f.v.append(poly.verts[(i+1)%NumberOfSides])
            f.v.append(poly.verts[NumberOfSides])
            poly.faces.append(f)

    ######### Creates a new Object with the new Mesh
    polyObj = NMesh.PutRaw(poly)

    Blender.Redraw()


<<<Zurück

Python in Blender

Inhaltsverzeichnis
Glossar
Weiter>>>

Mitgelieferte Scripte


Meine Werkzeuge
Namensräume

Varianten
Aktionen
Navigation
Mitmachen
Werkzeuge
Drucken/exportieren