Infoforall

BLENDER JEIA - 03 - Utiliser Python pour créer des objets

Voici le genre d'objet assez pénible à faire à la main :

Image créée par script

Utiliser Python dans Blender va ainsi permettre d'automatiser certains placements.

1 - Console Python

Commençons par montrer où se trouve la console qui permet de rentrer du code en direct.

01° Ouvrir Python Console plutôt que info.

Menu

Agrandir un peu la fenêtre pour voir un peu plus de code. Ou appuyer sur le bouton console pour la placer en plein écran ou revenir à la configuration initiale.

Menu Menu

Vous devriez obtenir un message d'accueil du style :

PYTHON INTERACTIVE CONSOLE 3.5.1 (default, Feb 17 2016, 17:09:19) [MSC v.1800 64 bit (AMD64)]


Command History: Up/Down Arrow

Cursor: Left/Right Home/End

Remove: Backspace/Delete

Execute: Enter

Autocomplete: Ctrl-Space

Zoom: Ctrl +/-, Ctrl-Wheel

Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bpy.utils, bgl, blf, mathutils

Convenience Imports: from mathutils import *; from math import *

Convenience Variables: C = bpy.context, D = bpy.data

Ce texte vous explique surtout que certains modules sont déja importés dans cette console. Notamment les modules commençant par bpy (pour Blender Python).

02° Faire disparaitre le cube de départ PUIS taper ceci dans la console :

>>> bpy.ops.mesh.primitive_cube_add()

Vous devriez constater qu'un nouveau cube vient d'apparaitre juste sur le curseur 3D.

03° Décaler le cube avec les flèches de direction et retaper la ligne de code (CTRL+C, CTRL+V).

04° Avec un clic gauche, placer le curseur 3D à un autre endroit. Retaper la ligne de code.

Vous devriez au final obtenir un résultat du type :

Trois cubes

Comment fonctionne ce code ? Il suffit de faire un clic-droit sur le carré du menu Tools et de sélectionner Online Python reference pour trouver des informations complètes :

  1. aller dans le menu de création (CREATE) sur l'objet voulu
  2. rester statique au dessus du bouton voulu
ONGLET CREATION

Retenons déjà que

bpy.ops.mesh.primitive_cube_add()

veut dire :

Les points signalant les liaisons.

La documentation en ligne donne ceci :

bpy.ops.mesh.primitive_cube_add(radius=1.0, calc_uvs=False, view_align=False, enter_editmode=False, location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), layers=(False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))

Construct a cube mesh.


    Parameters:

  •     radius (float in [0, inf], (optional)) – Radius
  •     calc_uvs (boolean, (optional)) – Generate UVs, Generate a default UV map
  •     view_align (boolean, (optional)) – Align to View, Align the new object to the view
  •     enter_editmode (boolean, (optional)) – Enter Editmode, Enter editmode when adding this object
  •     location (float array of 3 items in [-inf, inf], (optional)) – Location, Location for the newly added object
  •     rotation (float array of 3 items in [-inf, inf], (optional)) – Rotation, Rotation for the newly added object
  •     layers (boolean array of 20 items, (optional)) – Layer

Remarquons que tous les arguments transmissibles sont optionnels. C'est pour cela qu'on peut créer un cube en ne notant rien entre les parenthèses de la méthode.

Mais on peut créer un cube ayant un radius de 2 en tapant :

>>> bpy.ops.mesh.primitive_cube_add(radius=2.0)

05° Créer un autre objet qu'un cube en vous renseignant sur le code à utiliser :

  1. aller dans le menu de création (CREATE) sur l'objet voulu
  2. rester statique au dessus du bouton voulu
ONGLET CREATION

Imaginons maintenant que nous voulions créer un cube mais en ne le plaçant pas à l'emplacement du curseur 3D. Pour cela, il faut renseigner le paramètre location.

On peut trouver la documentation facilement : plutôt que de rester statique au dessus de la touche de l'objet à créer, il faut faire un clic droit et sélectionner Online Python References. En regardant via la documentation, on trouve alors dans l'intitulé de la méthode :

bpy.ops.mesh.primitive_cube_add(radius=1.0, ... location = (0.0, 0.0, 0.0), rotation = (0.0, 0.0, 0.0), ...)

On voit donc que certains paramètres ont des valeurs par défaut.

Lorsqu'on note bpy.ops.mesh.primitive_cube_add(), location prend la valeur par défaut : (0.0, 0.0, 0.0).

location = (0.0, 0.0, 0.0)

Pourquoi avoir noter cela avec des parenthèses rouges ?

Et bien parce que c'est important pour la suite ! On n'envoie pas un 0.0 puis un 0.0 puis un 0.0.

On envoie les trois 0.0 d'un coup dans un objet qui comporte 3 données. On nomme cela un N-uplets. C'est un type de données :

  • ouvert par une parenthèse,
  • dont les valeurs sont séparées par des virgules,
  • fermé par une parenthèse

Ici, nous avons un 3-uplet. On nomme également cela tuple.

06° Créer un cube en utilisant bpy.ops.mesh.primitive_cube_add(location=(5,5,0)).

Trois cubes

Cela donne :

Trois cubes

Vous pouvez constatez qu'on travaille depuis l'origine O (0,0,0) du plan. Vous pouvez changer les valeurs pour vous en convaincre.

Voilà pour le premier contact. Il vous reste à voir comment créer un script dans un fichier plutôt que de taper les instructions à chaque fois.

2 - Script

La console est bien pratique mais elle ne permet pas de stocker du code pour pouvoir le réutiliser au besoin. Pour cela, nous allons devoir créer un script : enregistrer un fichier d'extension .py qui va contenir notre "programme". Puisque ce programme n'est pas autonome, mais est destiné à être utilisé par Blender, on ne le nomme pas programme mais script.

07° Pour créer un script, remplacer la console par text editor.

Vous devriez pour l'instant avoir ceci :

Python console

Et vous allez passer à :

Text editor

08° Utiliser new pour créer un nouveau fichier qui va nous permettre de créer un fichier python .py.

Voici le script que nous allons utiliser :

import bpy # On importe la bibliothèque Blender Python

bpy.ops.mesh.primitive_cube_add( location = (0,0,0))

bpy.ops.mesh.primitive_cube_add( location = (5,5,0))

bpy.ops.mesh.primitive_cube_add( location = (5,-5,0))

bpy.ops.mesh.primitive_cube_add( location = (-5,5,0))

bpy.ops.mesh.primitive_cube_add( location = (-5,-5,0))

L'interpréteur Python va suivre le script dans l'ordre, comme si vous aviez tapé les lignes les unes après les autres :

L'interpréteur va suivre les instructions de façon séquentielle : il les lit et les execute les unes à la suite des autres, dans l'ordre qu'on lui a fourni. Il n'exécute pas les instructions dans un ordre aléatoire.

09° Utiliser le code pour voir le résultat en appuyant sur Run Script.

Text editor

Et voilà. Vous avez vu les bases fondamentales de la manipulation d'objets via Blender.

Quelques remarques :

  • Pour passer sur une vue plus grande du script, il faut utiliser VIEW - Toggle Max Area.
  • Menu View
  • Pour enregistrer le script, il faut utiliser TEXT - Save as. On y trouve également le choix OPEN pour ouvrir un fichier préexistant.
  • Menu Text
  • Pour convertir les espaces en tabulation, il faut utiliser FORMAT - Convert Whitespace.
  • Menu Convert
  • Si une erreur survient, pensez à cliquer sur l'icone Blender dans le menu bas de l'écran : vous aurez ainsi accés à la console qui affiche en direct les actions et erreurs qui sont survenues dans le logiciel. C'est toujours pratique de savoir pourquoi le script ne fonctionne pas. Sans cela, pas facile de savoir d'où vient l'erreur.
  • Menu Convert
  • Si vous ne parvenez plus à atteindre la console, vous pouvez la faire apparaître à l'aide d'un des menus de info - Window - Toggle System Console.

    Menu Convert
  • ERREUR TYPIQUE : lorsqu'on tape les coordonnées, on utilise parfois le systême français des virgules. Pour affecter une coordonnée x à 2,5 vous risquez de taper x=2,5 ! Attention, avec Python, c'est le systême anglosaxon qu'il faut utiliser : x = 2.5. Utilisez donc bien le clavier numérique si vous en avez un et vérifier bien cette histoire de point et de virgule dès qu'il y a un nombre "à virgule".

3 - Les variables dans Blender

Une fois que les élèves ont vu le principe on peut partir sur la notion de variables.

Dans les activités suivantes, ils verront comment éviter de taper trop de lignes identiques à l'aide des boucles. Ect, ect... Le principe est d'amener la notion au moment où ils se rendront compte de son utilité.

10° Revenir à une configuration de type Ecran pour la vue 3D et Text Editor pour la fenêtre du haut. Utiliser ensuite new pour créer un nouveau fichier qui va nous permettre de créer un fichier python .py.

Text editor

Voici le script Python que nous avions executé au début:

import bpy # On importe la bibliothèque Blender Python

bpy.ops.mesh.primitive_cube_add( location = (0,0,0))

bpy.ops.mesh.primitive_cube_add( location = (5,5,0))

bpy.ops.mesh.primitive_cube_add( location = (5,-5,0))

bpy.ops.mesh.primitive_cube_add( location = (-5,5,0))

bpy.ops.mesh.primitive_cube_add( location = (-5,-5,0))

Et bien, nous pourrions réecrire la même chose mais en utilisant une variable pour stocker 5.

11° Modifier le programme pour stocker ce 5 dans une variable puis utiliser cette variable pour dessiner les cubes plutôt que de taper réellement 5... Lancer votre script.

import bpy # On importe la bibliothèque Blender Python

distance = 5

bpy.ops.mesh.primitive_cube_add( location = (0,0,0))

bpy.ops.mesh.primitive_cube_add( location = (distance,distance,0))

bpy.ops.mesh.primitive_cube_add( location = (distance,-distance,0))

bpy.ops.mesh.primitive_cube_add( location = (-distance,distance,0))

bpy.ops.mesh.primitive_cube_add( location = (-distance,-distance,0))

12° Dernière question : faites preuve d'imagination et réalisez une scène difficilement réalisable si on ne connait recours pas aux variables. En gros, il s'agit des scènes où un grand nombre de formes sont précisement positionnées et déformées.

A titre d'exemple, voici ce qu'on peut obtenir à l'aide du script suivant : on génère les cubes. Normalement, après cela les élèves sont convaincus de l'utilité des boucles !

J'ai ensuite dû associer manuellement deux matériaux différents aux différents cubes. Nous verrons cela bientôt.

Si vous savez déjà comment gérer les matériaux, voici quelques indications.

Les couleurs sont le rose et le vert avec :

  • Transparency : une transparencealpha de 0,6.
  • Shading : Translucency à 0,5. Shadeless pour ne pas laisser l'objet être influencé par la lumière exterieur.

import bpy # On importe la bibliothèque Blender Python


decalage = 2


# Création des cubes dans le plan xy (z reste à 0)

bpy.ops.mesh.primitive_cube_add( location = (0,0,0))


bpy.ops.mesh.primitive_cube_add( location = (decalage,0,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage,decalage,0))


bpy.ops.mesh.primitive_cube_add( location = (decalage*2,0,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*2,decalage,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*2,decalage*2,0))


bpy.ops.mesh.primitive_cube_add( location = (decalage*3,0,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*3,decalage,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*3,decalage*2,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*3,decalage*3,0))


bpy.ops.mesh.primitive_cube_add( location = (decalage*4,0,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*4,decalage,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*4,decalage*2,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*4,decalage*3,0))

bpy.ops.mesh.primitive_cube_add( location = (decalage*4,decalage*4,0))


# Création des cubes dans le plan yz (x reste à 0)

bpy.ops.mesh.primitive_cube_add( location = (0,0,decalage))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage,decalage))


bpy.ops.mesh.primitive_cube_add( location = (0,0,decalage*2))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage,decalage*2))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage*2,decalage*2))


bpy.ops.mesh.primitive_cube_add( location = (0,0,decalage*3))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage,decalage*3))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage*2,decalage*3))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage*3,decalage*3))


bpy.ops.mesh.primitive_cube_add( location = (0,0,decalage*4))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage,decalage*4))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage*2,decalage*4))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage*3,decalage*4))

bpy.ops.mesh.primitive_cube_add( location = (0,decalage*4,decalage*4))

Image créée par script

Voici le genre de vue trop complexe à faire sans boucle :

vue de face

La partie suivante vous présente des fonctions bien pratiques pour traiter du déplacement d'objets et des animations.

4 - La configuration Scripting

L'un des points 'faibles' de Blender en Python, c'est la multiplicité des sources d'informations et d'affichage. Pour rappel :

La console ou le terminal de votre ordinateur correspond en windows à l'invité de commande qu'on trouve dans le sous-menu Système Windows. On ne l'utilise pas avec Blender.

Terminal

Même si Blender fonctionne avec Python, nul besoin de passer par votre propre interpréteur Python : tout est intégré directement à Blender. Oubliez donc le IDLE Python (icone blanche) et l'icone vers la console Python (icone noire) que vous avez peut-être sur votre ordinateur.

IDLE

Dans Blender, il existe trois endroits qu'il faut savoir activer :

  1. Le TextEditor qui permet d'écrire des scripts Python et de les executer
  2. La Console Python interne à Blender qui permet d'executer du code Python en direct
  3. Console Python
  4. La Console System de Blender qui permet de voir les messages qu'affiche Blender, notamment les erreurs
  5. Console system

13° Changer la disposition par défaut pour utiliser plutôt la disposition Scripting.

Scripting : choix

On arrive normalement à ceci :

Configuration Scripting

Toutes les fenêtres utiles pour programmer sont là.

14° Dans TextEditor, sélectionner la numérotation des lignes et la mise en couleur synthaxique.

15° Tirer le menu Info pour qu'il prenne un peu plus de place si possible. Sélectionner ensuite Window - Toggle System Console. Attention, je parle bien de la console Systeme, pas juste la console Python qu'on peut sélectionner comme fenêtre active.

Console system

Au final, vous devriez avoir la bonne configuration de travail, à savoir une interface qui ressemble à ceci:

Configuration Scripting finale

Et avec cela, nous allons pouvoir travailler correctement.

5 - Utilisation du FOR dans Blender

Gérer les translations

16° Tenter de voir ce que fait le code suivant puis le lancer dans Blender.

import bpy # On importe la bibliothèque Blender Python

for x in range(-16,17,4):

    bpy.ops.mesh.primitive_cube_add(location = (x,0,0))

...CORRECTION...

On part de -16 et on augmente de 4 à chaque retour de boucle.

Ceci est vrai tant que le compteur donne un résultat strictement inférieur à 17.

Il devrait vous créer des cubes en x = -16, x = -12, x = -8, x = -4, x = 0, x = 4, x = 8, x = 12 et x = 16.

Pour supprimer les objets créés, vous pouvez utiliser la touche C pour activer le curseur de sélection. Appuyer sur le bouton de gauche le temps de sélectionner les objets voulus, cliquer sur le bouton de droite puis supprimer la sélection avec la touche SUPPR.

Text editor

Gérer les rotations

On peut aussi gérer les rotations. Il faut alors faire un peu de math, surtout de la trigonométrie.

Imaginons qu'on désire créer un cercle de cube. Il faut falloir importer le module math pour parvenir à calculer les sinus et les cosinus. Et convertir les angles qu'on exprime en degrés en radians, unité naturelle des angles pour Python.

Voici le code qui permet d'obtenir les coordonnées d'un cube qui subit une rotation autour de (0,0) avec un rayon fourni dans la variable rayon :

import bpy # On importe la bibliothèque Blender Python

import math # On importe la bibliothèque math pour calculer les cos...


rayon = 10


for angle_degre in range(-0,360,36):

    angle = math.radians(angle_degre) # math.radians permet de convertir en radians

    x = rayon*math.cos(angle)

    y = rayon*math.sin(angle)

    bpy.ops.mesh.primitive_cube_add(location=(x,y,0))

Nous allons donc plusieurs calculs en boucle avec les valeurs angle_degre de 0°, 36°, 72° ... puisqu'on part de 0 et qu'on augmente de 36° à chaque retour.

17° Lancer le code pour voir le résultat. Tentons d'en comprendre le sens :

pyramide de cube

17° Je vous laisse tenter de faire ceci (vous ne pouvez pas faire la colorisation via un script pour l'instant) :

vue de face Text editor

Une proposition de correction : un for dans un for et un nombre de cubes et une altitude variable en fonction du rayon;

import bpy # On importe la bibliothèque Blender Python

import math # On importe la bibliothèque math pour calculer les cos...


rayon = 10


for rayon in range (6,23,4):

    for angle_degre in range(0,360,int(36*6/rayon)):

        angle = math.radians(angle_degre) # math.radians permet de convertir en radians

        x = rayon*math.cos(angle)

        y = rayon*math.sin(angle)

        altitude = -rayon//2

        bpy.ops.mesh.primitive_cube_add( location=(x,y,altitude) )

Les lumières, le plan et son effet miroir ont été rajoutés après l'utilisation du script pour permettre de mieux voir la structure obtenue.

Faire cette structure à la main aurait demandé des heures de travail (et un positionnement final approximatif, à moins de refaire les calculs un à un).