« Programmation objet et géométrie/Objets Python sous Blender/Création de surfaces paramétrées avec bpy » : différence entre les versions

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
DannyS712 (discussion | contributions)
m <source> -> <syntaxhighlight> (phab:T237267)
 
Ligne 28 : Ligne 28 :
Comme précédemment, on importe les classes Blender et bpy, mais aussi les fonctions trigonométriques et <math>\pi</math>, qui sont des méthodes (et propriété pour <math>\pi</math>) de l'objet ''math'':
Comme précédemment, on importe les classes Blender et bpy, mais aussi les fonctions trigonométriques et <math>\pi</math>, qui sont des méthodes (et propriété pour <math>\pi</math>) de l'objet ''math'':


<source lang="python">
<syntaxhighlight lang="python">
from Blender import *
from Blender import *
import bpy
import bpy
from math import pi, cos, sin
from math import pi, cos, sin
sommets=[]
sommets=[]
</syntaxhighlight>
</source>


===Liste des sommets===
===Liste des sommets===
Ligne 39 : Ligne 39 :
Lors de sa création, la liste des sommets est vide. Il reste donc à la remplir, ce qui se fait par quelque chose qu'on n'a pas utilisé dans l'article précédent: Une boucle. Celle-ci est double (puisqu'il y a deux paramètres) et ses deux indices sont choisis entre 0 et 100 (pour ''i'') et entre 0 et 50 (pour ''j''). Pour passer de <math>0 \leqslant i \leqslant 100</math> à <math>0 \leqslant u \leqslant \pi</math>, on multiplie ''i'' par <math>\frac{\pi}{100}</math> pour avoir ''u''. De même, <math>v=j \times \frac{\pi}{50}</math>:
Lors de sa création, la liste des sommets est vide. Il reste donc à la remplir, ce qui se fait par quelque chose qu'on n'a pas utilisé dans l'article précédent: Une boucle. Celle-ci est double (puisqu'il y a deux paramètres) et ses deux indices sont choisis entre 0 et 100 (pour ''i'') et entre 0 et 50 (pour ''j''). Pour passer de <math>0 \leqslant i \leqslant 100</math> à <math>0 \leqslant u \leqslant \pi</math>, on multiplie ''i'' par <math>\frac{\pi}{100}</math> pour avoir ''u''. De même, <math>v=j \times \frac{\pi}{50}</math>:


<source lang="python">
<syntaxhighlight lang="python">
for i in range(0,100):
for i in range(0,100):
u=i*pi/100
u=i*pi/100
Ligne 48 : Ligne 48 :
z=cos(u)*sin(2*v)
z=cos(u)*sin(2*v)
sommets.append([x,y,z])
sommets.append([x,y,z])
</syntaxhighlight>
</source>


''x'', ''y'' et ''z'' sont calculés à partir de ''u'' et ''v'' avec les formules ci-dessus, puis le sommet (x,y,z) est ajouté à la base de donnée des sommets. À l'issue de cette boucle, la surface de Steiner sera riche de <math>101 \times 51 = 5151</math> points.
''x'', ''y'' et ''z'' sont calculés à partir de ''u'' et ''v'' avec les formules ci-dessus, puis le sommet (x,y,z) est ajouté à la base de donnée des sommets. À l'issue de cette boucle, la surface de Steiner sera riche de <math>101 \times 51 = 5151</math> points.
Ligne 61 : Ligne 61 :




<source lang="javascript">
<syntaxhighlight lang="javascript">
| | | |
| | | |
4--54-104-154-
4--54-104-154-
Ligne 73 : Ligne 73 :
0--50-100-150-
0--50-100-150-


</syntaxhighlight>
</source>


===tableau des faces===
===tableau des faces===
Ligne 79 : Ligne 79 :
Ainsi, chaque sommet a un numéro de la forme <math>50i+j</math>, et est relié successivement aux sommets de numéros <math>50i+j+50</math>, <math>50i+j+51</math> et <math>50i+j+1</math>. Il suffit alors de créer un tableau initialisé à 0 pour les faces, et d'y ajouter des listes telles que celle ci-dessus, au fur et à mesure, dans une double boucle:
Ainsi, chaque sommet a un numéro de la forme <math>50i+j</math>, et est relié successivement aux sommets de numéros <math>50i+j+50</math>, <math>50i+j+51</math> et <math>50i+j+1</math>. Il suffit alors de créer un tableau initialisé à 0 pour les faces, et d'y ajouter des listes telles que celle ci-dessus, au fur et à mesure, dans une double boucle:


<source lang="python">
<syntaxhighlight lang="python">
faces=[]
faces=[]
for i in range(0,99):
for i in range(0,99):
for j in range(0,49):
for j in range(0,49):
faces.append([50*i+j,50*i+j+50,50*i+j+51,50*i+j+1])
faces.append([50*i+j,50*i+j+50,50*i+j+51,50*i+j+1])
</syntaxhighlight>
</source>


En réalité, il manque des faces telles que 49-99-50-0 et 5000-0-1-5001 mais leur absence ne se verra pas, et corriger cet oubli, est laissé en exercice...
En réalité, il manque des faces telles que 49-99-50-0 et 5000-0-1-5001 mais leur absence ne se verra pas, et corriger cet oubli, est laissé en exercice...
Ligne 101 : Ligne 101 :
Ce qui s'écrit ainsi:
Ce qui s'écrit ainsi:


<source lang="python">
<syntaxhighlight lang="python">
st=bpy.data.meshes.new('pp')
st=bpy.data.meshes.new('pp')
st.verts.extend(sommets)
st.verts.extend(sommets)
Ligne 107 : Ligne 107 :
scn = bpy.data.scenes.active
scn = bpy.data.scenes.active
ob = scn.objects.new(st, 'steiner')
ob = scn.objects.new(st, 'steiner')
</syntaxhighlight>
</source>


Ensuite il suffit de cocher le bouton ''Set smooth'' pour arrondir les angles (et en profiter pour décocher le bouton ''double sided'' puisque pour une fois, on a défini une surface unilatère), à texturer la surface avec un matériau transparent, puis à effectuer un rendu:
Ensuite il suffit de cocher le bouton ''Set smooth'' pour arrondir les angles (et en profiter pour décocher le bouton ''double sided'' puisque pour une fois, on a défini une surface unilatère), à texturer la surface avec un matériau transparent, puis à effectuer un rendu:

Version actuelle du 16 avril 2020 à 10:06


Pour représenter des surfaces paramétrées, on utilise la seule chose que Blender sache gérer: Des polyèdres. Seulement ils ont tellement de faces et elles sont si petites, que le polyèdre aura l'air, si on n'y fait trop attention, d'une surface de classe . Cette représentation des surfaces par des approximations polyédrales est à la base de chapitres entiers des mathématiques:

Dans les deux cas, la surface est approchée par une triangulation. Comme les deux paramètres de la surface

s'appellent souvent et , le nom d' uv-mapping est souvent utilisé dans les logiciels de 3D (comme Blender) pour désigner les coordonnées de textures.

Ci-dessous on va représenter une surface unilatère, la surface romane de Steiner.

Expression paramétrique[modifier | modifier le wikicode]

La surface de Steiner est donnée par la représentation paramétrique suivante:

avec et .

sommets[modifier | modifier le wikicode]

Entête du fichier[modifier | modifier le wikicode]

Comme précédemment, on importe les classes Blender et bpy, mais aussi les fonctions trigonométriques et , qui sont des méthodes (et propriété pour ) de l'objet math:

from Blender import *
import bpy
from math import pi, cos, sin
sommets=[]

Liste des sommets[modifier | modifier le wikicode]

Lors de sa création, la liste des sommets est vide. Il reste donc à la remplir, ce qui se fait par quelque chose qu'on n'a pas utilisé dans l'article précédent: Une boucle. Celle-ci est double (puisqu'il y a deux paramètres) et ses deux indices sont choisis entre 0 et 100 (pour i) et entre 0 et 50 (pour j). Pour passer de à , on multiplie i par pour avoir u. De même, :

for i in range(0,100):
		u=i*pi/100
		for j in range(0,50):
				v=j*pi/50
				x=sin(2*u)*sin(v)**2
				y=sin(u)*sin(2*v)
				z=cos(u)*sin(2*v)
				sommets.append([x,y,z])

x, y et z sont calculés à partir de u et v avec les formules ci-dessus, puis le sommet (x,y,z) est ajouté à la base de donnée des sommets. À l'issue de cette boucle, la surface de Steiner sera riche de points.

Il reste à trouver, dans cette immense collection, quels sommets sont reliés à quels autres.

faces[modifier | modifier le wikicode]

plan des (u,v)[modifier | modifier le wikicode]

Les faces seront des quadrilatères, bordés horizontalement par des lignes de niveau de v et verticalement par des lignes de niveau de u. Les numéros des sommets correspondent à l'ordre de leur création, soit colonne par colonne:


|   |   |   |  
4--54-104-154-  
|   |   |   |
3--53-103-153-
|   |   |   |
2--52-102-152-
|   |   |   |
1--51-101-151-
|   |   |   |
0--50-100-150-

tableau des faces[modifier | modifier le wikicode]

Ainsi, chaque sommet a un numéro de la forme , et est relié successivement aux sommets de numéros , et . Il suffit alors de créer un tableau initialisé à 0 pour les faces, et d'y ajouter des listes telles que celle ci-dessus, au fur et à mesure, dans une double boucle:

faces=[]
for i in range(0,99):
		for j in range(0,49):
					faces.append([50*i+j,50*i+j+50,50*i+j+51,50*i+j+1])

En réalité, il manque des faces telles que 49-99-50-0 et 5000-0-1-5001 mais leur absence ne se verra pas, et corriger cet oubli, est laissé en exercice...


Création de la surface de Steiner[modifier | modifier le wikicode]

Ensuite comme précédemment il reste à

  • Instancier un objet héritant de la classe meshes, et l'appeler pp (comme plan projectif)
  • Y placer les sommets calculés ci-dessus;
  • Y ajouter les faces calculées ci-dessus;
  • Rendre la scène Blender active pour pouvoir la modifier;
  • En profiter pour y placer l'objet surface de Steiner

Ce qui s'écrit ainsi:

st=bpy.data.meshes.new('pp')
st.verts.extend(sommets)
st.faces.extend(faces)
scn = bpy.data.scenes.active    
ob = scn.objects.new(st, 'steiner')

Ensuite il suffit de cocher le bouton Set smooth pour arrondir les angles (et en profiter pour décocher le bouton double sided puisque pour une fois, on a défini une surface unilatère), à texturer la surface avec un matériau transparent, puis à effectuer un rendu:

Exercice[modifier | modifier le wikicode]

Construire une bouteille de Klein en utilisant la représentation paramétrique de Jeener [1]: