Programmation Blender Python

par Jean-Baptiste PERIN




Ce tutoriel présente les bases de la programmation Python pour Blender. A travers des exemples simples, vous apprendrez à interagir avec Blender par programmation.
Pour lire ce tutoriel, il n'est pas necessaire d'avoir pratiquer la programmation mais il toutefois conseillé de s'être un peu familiariser avec le language Python.
Il est recommandé d'avoir préalablement lu PremierScriptPython et BlenderPythonScript

Les sujets abordés dans ce tutoriel sont les suivants:


Tous les scripts qui sont présentés ici doivent commencer par la ligne :

import Blender

Par soucis de lisibilité, cette ligne n'est pas systématiquement présente dans les exemples de ce tutoriel.
Il faut cependant considérer que sa présence en début de chacun de vos scripts est obligatoire.

C'est par une telle ligne que nous indiquons au python livré avec Blender que nous souhaitons utiliser les modules propres à Blender.


Obtenir des informations générales



import Blender
print Blender.Get('curframe')


Voici quelques explications sur ce script :

print est une commande python permettant d'afficher du texte.
En anglais, Get signifie "obtenir".
La séquence 'curframe' est ce qu'on appelle une chaîne de caractères (string en anglais).
Dans notre exemple, cette chaîne de caractères est passé en paramètre à la fonction Get du module Blender ..
Ainsi, la séquence Blender.Get('curframe') de notre programme peut se comprendre de la façon suivante:
On demande à Blender de nous donner la valeur correspondante à la chaîne 'curframe'
En recevant cet appel, Blender va comprendre qu'on souhaite obtenir le numéro de la frame courante.
Il renverra ce numéro en résultat à l'appel Blender.Get('curframe')
La commande print est là pour effectuer l'affichage de ce numéro ..

Les différentes chaînes de caractères que nous pouvons passer en paramètres à la fonction Get sont décrites ici .

Il est également possible d'obtenir des informations plus spécifiques à certaines parties du logiciel Blender ..

Par exemple, pour obtenir la position courante du curseur 3D nous pouvons utiliser la ligne:

print Blender.Window.GetCursorPos()

Ici, nous interrogons le sous module Window du module Blender.
On peut également attaquer le modules Scene de Blender. Essayez la ligne suivante:

print Blender.Scene.getCurrent().getName()

Elle affiche le nom de la scene courante.

Comme vous avez pu le constater, il est possible d'obtenir tout un tas d'information sur Blender en général.
Il est également possible d'interroger des parties spécifiques de Blender que l'on appel des modules..
Du point de vue du programmeur Python, Blender est composé d'un ensemble de modules desquels on peut obtenir des informations.
Nous verrons plus loin qu'il est même possible d'agir sur ces modules ..
La liste des modules contenus dans Blender se trouve ici.


Obtenir des informations sur un objet de la scène courante:


Afficher les informations de type, de taille et de placement:


Blender Pour toute opération sur un objet, il convient dans un premier temps de récupérer une référence sur cet objet (une sorte d'adresse blender de cet objet).
Pour obtenir une telle référence, il faut connaître le nom de l'objet (Nous utiliserons 'Cube') et obtenir la référence par la fonction Get du module Objet de Blender

lobjet = Blender.Object.Get('Cube')

Cette ligne permet de stocker dans la variable 'lobjet' une référence vers l'objet nommé 'Cube' de notre scène.
A partir de cette référence, on peut obtenir des informations sur l'objet

print 'le type de l\'objet est : ',
print lobjet.getType()

print 'la taille de l\'objet est : ',
print lobjet.getSize()

print 'la position de l
\'objet est : ',
print lobjet.getLocation()

A l'exécution de ce programme, vous devriez voir apparaître sur votre console les lignes suivantes:

<>le type de l'objet est :  (1.0, 1.0, 1.0)
la taille de l'objet est :  (1.0, 1.0, 1.0)
la position de l'objet est :  (0.0, 0.0, 0.0)

Vous remarquerez que les coordonnées sont affichées sous la forme d'une liste de 3 valeurs.
Les appels aux fonctions getSize() et getLocation() renvoie donc des listes de 3 valeurs correspondantes aux 3 dimensions de l'espace dans lequel nous travaillons.
La première valeur de la liste correspond à la dimension X, la seconde à la dimension Y et la dernière à la dimension Z.
Ainsi nous pouvons déduire de l'affichage précédent que l'objet est de taille 1 sur toutes les dimensions et que son centre est situé à l'origine

Déplacez le cube et redimensionnez-le puis ré-exécuter le programme .. Vous constaterez  que les valeurs affichées reflètent les changements que vous avez opéré sur l'objet.

Puisque les informations sont fournies sous la forme d'une liste, on doit accéder aux données individuelles en utilisant ce qu'on appelle un index.
Nous accédons aux valeur propres à chaque dimension, en rajoutant aux appels à getLocation() ou getSize() l'index de la coordonnée à isolée  entre crochet  ([0] pour X, [1] pour Y et [2] pour Z).
Par exemple pour afficher séparément les positions en X, Y et Z de l'objet, rajouter à votre programme les lignes :

print 'la position en X de l\'''objet est : ',
print lobjet.getLocation()[0]

print 'la position en Y de l\'''objet est : ',
print lobjet.getLocation()[1]

print 'la position en Z de l\'''objet est : ',
print lobjet.getLocation()[2]


Sélectionnez-le cube (en mode Object, clic droit dessus),
Déplacez-le cube (G + déplacement souris )
Redimensionnez-le (S+déplacement souris)
Ré-exécuter le programme (souris sur TextEditor, Alt-P)..

Vous constaterez  que les valeurs affichées reflètent les changements que vous avez opéré sur l'objet.

Essayons d'aller un peu plus loin dans l'analyse


Afficher les informations spécifiques au type de l'objet:

L'objet Cube qui se trouve dans notre scène est un objet de type mesh .. cela sous-entend qu'il est consitué de vertices et de faces.
D'autres types d'objet existent dans Blender.. les lampes.. les caméras ..  le ciel .. les materials .. etc.. etc..
Voyons les méthodes pour accéder aux informations relatives à ces objets.

On commence par accéder à l'object Blender.. comme précédemment:

import Blender

lobjet = Blender.Object.Get('Cube')

A partir de cet object Blender, on accède aux données spécifiques à  ce dernier par l'appel à la fonction GetData()

lamesh = lobjet.getData ()

Comme l'object Blender nommé 'Cube' est de type NMesh, on récupère dans la variable lamesh, un object de type NMesh.
Si l'objet avait été une caméra, nous aurions récupérer un objet de type Camera.
On peut s'en assurer en faisant afficher le type de l'objet

En consultant la documentation de la classe NMesh, vous appercevrez un attribut nommé verts qui contient une liste de NMVert.
La liste verts contenue dans l'objet NMesh est une liste contenant autant d'élements que de vertices dans notre mesh.
Pour connaître le nombre de vertices dans notre mesh, on peut afficher la longueur de la liste

print 'Il y a', len(lamesh.verts), ' vertices dans l'objet'

On peut également parcourir la liste des vertex  .. et afficher, pour chaque vertice, son index dans la liste verts et ses coordonnées 3D.

for vertice in lamesh.verts:
   print 'Les coordonnées du vertice d\'index ', vertice.index,
   print 'sont ', vertice.co


Les objets de type NMVert contenus dans la liste verts sont les vertices de notre cube. Ils contiennent , entre autre, les attributs index (qui fournit l'index du vertice dans la liste verts de la mesh) et co (qui donne les coordonnées (X,Y,Z) du vertice).

Récapitulons notre programme:

import Blender

lobjet = Blender.Object.Get('Cube')

lamesh = lobjet.getData ()

print 'Il y a', len(lamesh.verts), ' vertices dans l\'objet'

for vertice in lamesh.verts:
   print 'Les coordonnées du vertice d\'index ', vertice.index,
   print 'sont ', vertice.co


Et exécutons le :

Il y a 8  vertice(s) dans l'objet
Les coordonnÚes du vertice d'index  0 sont  [1.0000, 1.0000, -1.0000]
Les coordonnÚes du vertice d'index  1 sont  [1.0000, -1.0000, -1.0000]
Les coordonnÚes du vertice d'index  2 sont  [-1.0000, -1.0000, -1.0000]
Les coordonnÚes du vertice d'index  3 sont  [-1.0000, 1.0000, -1.0000]
Les coordonnÚes du vertice d'index  4 sont  [1.0000, 1.0000, 1.0000]
Les coordonnÚes du vertice d'index  5 sont  [1.0000, -1.0000, 1.0000]
Les coordonnÚes du vertice d'index  6 sont  [-1.0000, -1.0000, 1.0000]
Les coordonnÚes du vertice d'index  7 sont  [-1.0000, 1.0000, 1.0000]


Notre cube contient bien 8 vertices

Jusqu'à présent nous avons été très passif dans nos programmes. Nous nous sommes contentés de récupérer des informations de Blender et de les afficher.
Nous allons à présent apprendre à agir sur les objets de Blender.

Manipuler un objet de la scène courante:

Ce chapitre présente les méthodes Python utiles à quelques opérations simples (redimensionnement, déplacement, rotation, renommage) d'un objet d'une scène.

Pour toute opération sur un objet il convient, dans un premier temps, de récupérer une référence sur cet objet (une sorte d'adresse blender de cet objet).
Pour obtenir une telle référence, il faut connaître le nom de l'objet (nous utiliserons 'Cube') et obtenir la référence par la fonction Get du module Objet de Blender

lobjet = Blender.Object.Get('Cube')

Cette ligne permet de stocker dans la variable 'lobjet' une référence vers l'objet nommé 'Cube' de notre scène.
Muni de cette référence, nous pouvons appliquer des opérations simples sur cet objet.

On peut le renommer

lobjet.setName('CubeNouveauNom')

Ou le redimensionner, on utilisera pour cela la méthode setSize de l'objet:

lobjet.setSize([2.0,1.0,1.0])


Les valeurs 2.0, 1.0, 1.0 indiquent respectivement les rapports de taille en X, Y et Z.
On peut egalement déplacer l'objet en utilisant la méthode setLocation().

lobjet.setLocation([-2.0,1.0,0.0])

La ligne ci-dessus va placer le centre de l'objet à la position X=-2.0, Y=1.0, Z=0.0
Ou peut également appliquer une rotation sur l'objet en appellant la méthode setEuler()

lobjet.setEuler([90.0,0.0,45.0])


La ligne ci-dessus oriente l'objet de la même manière que si vous aviez sélectionné votre objet,  appuyé sur N, puis saisi les valeurs 90.0., 0.0, 45.0 dans les champs RotX, RotY et RotZ. Les angles doivent être donnés en degrés. Ils représentent la transformation opérée en faisant touner l'objet autour de son axe des X, puis autour de son nouvel axe des Y, puis enfin autour du nouvel axe des Z.
Si on ne souhaite pas affronter l'ambiguïté inhérente à l'utilisation des angles d'euler, on préfèrera alors l'appel à la fonction setMatrix().

En résumé, notre code:
 
# On récupère une référence vers l'objet nommé 'Cube'
lobjet = Blender.Object.Get('Cube')

# On affecte un nouveau nom à cet objet
lobjet.setName('CubeNouveauNom')

# On affecte sa taille en X, Y et Z
lobjet.setSize([2.0,1.0,1.0])

# On place l'objet aux coordonnées (x=-2, y=1, z=0)
lobjet.setLocation([-2.0,1.0,0.0])

# On tourne l'objet
lobjet.setEuler([90.0,0.0,45.0])

# On raffraîchit l'affichage
Blender.Redraw()

Remarque: Dans les instructions de notre programme les valeurs de position, de rotation et de taille sont données en absolues par rapport aux conditions initiales de l'objet en non pas en relatif par rapport à la situation courante de l'objet. Par l'instruction setSize([2.0,1.0,1.0]) , nous ne multiplions pas la taille de l'objet par 2 mais nous la forçons à 2 fois la valeur originelle de l'objet.
Par exemple, si nous voulions multiplier la taille en X de l'objet par 2 (à partir de sa taille courante) il faut d'abord récupérer la taille courante de l'objet et multiplier la composante X par 2.

# On multiplie sa taille en X par 2 et on laisse inchangés les tailles en  Y et Z
lobjet.setSize([ \
  Blender.Object.Get('CubeNouveauNom').getSize()[0]*2,\
  Blender.Object.Get('CubeNouveauNom').getSize()[1],\
  Blender.Object.Get('CubeNouveauNom').getSize()[2]\
  ])


Bien entendu, on peut procéder de la même façon avec les opérations de rotation et de positionnement. Pour travailler en relatif avec les fonctions setLocation() et setEuler(), on utilisera les méthodes getLocation() et getEuler()

Vous trouverez une liste complète des opérations qu'il est possible de faire sur un objet blender à cette adresse.

Créer un objet dans une scène 3D:


Pour créer un objet blender, on utilise la méhode New du module Object de Blender
Cette méthode prend deux paramèrtes de type chaîne de caractères:
Ensuite, pour que l'object soit rendu visible, on fait appel à la méthode link de la scène courante, à laquelle on passe l'objet nouvellement créé.

On obtient la scène courante en utilisant Blender.Scene.GetCurrent()

Exemple:
unobjet = Blender.Object.New('Empty' , 'Mon Empty')
Blender.Scene.GetCurrent().link(unobjet)
Blender.Redraw()


Créer une mesh dans une scène 3D:


On utilise les fonctions du module NMesh de Blender
La démarche consiste à:

Exemple:

Le petit bout de code suivant crée un objet à trois vertex et une face :

from Blender import NMesh

# On crée un object de type NMesh
me=NMesh.New('MaMesh')

# On ajoute 3 vertices à la mesh
me.verts.append(NMesh.Vert(0.0,0.0,0.0))
me.verts.append(NMesh.Vert(1.0,0.0,0.0))
me.verts.append(NMesh.Vert(0.0,1.0,0.0))

# On fabrique une face avec les 3 vertices nouvellement créé
f=NMesh.Face()
f.v.append(me.verts[0])
f.v.append(me.verts[2])
f.v.append(me.verts[1])

# On ajoute la face à l'objet NMesh
me.faces.append(f)

#Et enfin, on crée un objet blender qui s'ajoute à la scène courante
ob=NMesh.PutRaw(me)


Animer un objet de la scène courante:


Pour animer un objet en Blender, il faut lui enregistrer une IPO.
Les Ipos de Blender sont manipulables de la même manière que les autres objet.
Supposons que nous voulions déplacer un objet de sa position initiale vers une position éloignée de 6 unités blender sur l'axe des X.
Et imaginons et nous voulions que ce déplacement dure 25 images.
Pour réaliser cette animation, nous sélectionnerions l'objet à animer, nous insèrerions une clé à la position courante en appuyant sur la touche I et en sélectionnant l'entrée Loc dans le menu apparaissant. Puis, nous avancerions de 25 images dans notre animation (2 fois touche UpArrow puis 5 fois touche RightArrow), nous déplacerions notre objet de 6 unités Blender selon l'axe des X (G, suivi de Ctrl+déplacement souris) et  nous insérerions une seconde "clé" (I puis InsertKey->Loc).
Voyons comment faire cela par programmation.

Nous commencons par récupérer une référence vers l'objet que nous souhaitons animer.

unobjet = Blender.Object.New('Empty' , 'Mon Empty')
Blender.Scene.GetCurrent().link(unobjet)

Ici , nous créons un Empty mais nous aurions pu récupérer un objet de la scène courante en utilisant a fonction Get() du module Object.
Ensuite, nous créons une Ipo en utilisant la fonction New() du module Ipo de Blender. Remarquez que le procédé est très similaire à celui de la création d'un Object . Dans le module Ipo, la fonction New() prend deux paramères. Le premier paramètre permet de stipuler le type d'objet que nous souhaitons animer avec cette Ipo (dans le cadre de notre exemple, il s'agit d'un "Object") et le second permet de donner un nom à l'objet Ipo qui va être créé.
.
lipo = Blender.Ipo.New('Object','UneIpo')

Nous avons à présent créer un objet à animer .. et nous avons créé une Ipo pour décrire notre animation. Il nous faut dire à Blender que cette Ipo s'applique à l'objet que nous avons créer. Pour ce faire, nous utilisons la fonction setIpo() de notre objet à animer.

unobjet.setIpo(lipo)

Nous attachons ainsi l'ipo créée à l'objet à animer .. mais cette ipo est encore vide .. il faut maintenant ajouter des "clés" dans notre courbe.
Dans le cadre de notre exemple, nous souhaitons animer l'objet le long de l'axe des X. Pour cela, nous créons une Curve 'LocX' à l'interieur de notre Ipo lipo et c'est sur cette courbe que nous placerons nos points.

posX = lipo.addCurve('LocX')

Si nous avions voulu animer d'autres propriétés de l'objet (son orientation, sa taille, .. ) nous aurions passer un paramètre différent à la fonction addCurve() de notre Ipo (LocX, LocY, LocZ, RotX, RotT, RotZ, sizeX, SizeY, SizeZ, etc ...)
La liste complète des valeurs possible pour la paramètre de la fonction addCurve() est consultable dans sa documentation.
A présent que nous avons créer une courbe nous déterminons les numéros des frames auxquelles nous allons insérer des "clés".

start_frame = Blender.Get('curframe')
end_frame = start_frame + 25

Les 2 lignes ci-dessus placent dans les variables start_frame et end_frame, les valeurs correspondantes respectivement au numéro de la frame courante et au numéro de la frame courante augmentée de 25.
Ces variables vont nous servir pour placer des points sur la courbe.
Pour placer un point sur une courbe ipo, on utiliser la fonction addBezier () de l'objet Ipo qui prend en paramètre le numéro de la frame et la valeur de la "clé" à insérer.

posX.addBezier ((start_frame, unobjet.getLocation()[0]))
posX.addBezier ((end_frame,   unobjet.getLocation()[0] + 6))

La première ligne ajoute, à la frame courante (que nous avions sockée dans start_frame),  un point à la courbe LocX correspondante à la position courante de l'objet.
La seconde ligne ajoute une clé à la frame finale de notre animation (que nous avions sockée dans end_frame) correspondante à la position décalée de 6 unités Blender sur l'axe des X.
Pour terminer les choses proprement, nous décidons que le déplacement se fera de façon linéaire .. et qu'il se répètera à l'infini.

posX.setInterpolation('Linear')
posX.setExtrapolation('Cyclic')

et nous faisons recalculer les positions intermédaires de la courbe.

posX.Recalc()


Remarque:
  Pour les rotations les valeurs des clés sont à insérer en dizaine de degrés..
  Les valeurs de position sont toujours donné en relatif par rapport à la position de l'objet parent.

Voici donc le code complet de notre petit programme d'animation :

import Blender

unobjet = Blender.Object.New('Empty' , 'Mon Empty')
Blender.Scene.GetCurrent().link(unobjet)

lipo = Blender.Ipo.New('Object','UneIpo')

unobjet.setIpo(lipo)

posX = lipo.addCurve('LocX')


start_frame = Blender.Get('curframe')
end_frame = start_frame + 25

posX.addBezier ((start_frame, unobjet.getLocation()[0]))
posX.addBezier ((end_frame,   unobjet.getLocation()[0] + 6))

posX.setInterpolation('Linear')
posX.setExtrapolation('Cyclic')

posX.Recalc()
Blender.Redraw()




visitors since creation on december the 20th of 2005.
visitors since creation on december the 20th of 2005.
(C) 2005 Jean-Baptiste PERIN - released under Blender Artistic License - www.blender.org