VII. Utilisation (un peu) plus avancée▲
VII-A. #if #else #end▲
Le branchement conditionnel permet d'effectuer un traitement si une condition est vérifiée. Exemple :
#if (truc = 1)
height_field{"machin.bmp" pigment{Red}}
#else
sphère{<0,0,0>,1 pigment{Blue}}
#end
dessinera un height_field ou une sphère selon la valeur de la variable truc.
Il n'est pas obligatoire de mettre un traitement alternatif #else.
VII-B. #switch #case #range #break #else #end▲
L'instruction #switch permet de réaliser des branchements selon la valeur d'une variable. C'est un #if particulier.
#switch(var)
/* si var vaut 0 */
#case (0) sphère{<0,2,0>,2 pigment{ Red }} #break;
/* si var vaut 1 */
#case (1) sphère{<0,2,0>,2 pigment{ Blue }} #break;
/* si var est entre 2 et 10 */
#range(2,10) sphère{<0,2,0>,2 pigment{ Green }} #break;
/* tous les autres cas */
#else sphère{<0,2,0>,2 pigment{ Brown }} #break;
#end
Ce code dessinera une sphère dont la couleur dépend de la valeur de var. Si var vaut 0, elle sera rouge, si var vaut 1, elle sera bleue, si var est entre 2 et 10, elle sera verte et elle sera brune dans tous les autres cas.
Pensez bien à ne pas oublier les instructions #break en fin de chaque cas. Sans quoi toutes les conditions décrites après la condition résolue seront interprétées. Et vous obtiendrez plusieurs sphères de couleurs différentes, les unes dans les autres.
VII-C. #while #end▲
Pour boucler tant qu'une condition est vérifiée
#declare i=0;
#while (i < 10)
sphère{<3*i,0,0>,1 pigment{Orange}}
#declare i=i+1;
#end
dessinera 10 sphères alignées
VII-D. #macro #end▲
Voici l'instruction que tout le monde attend : la fonction. Elle permet d'effectuer des traitements ou des affichages selon des arguments. Voici un exemple d'utilisation de macro dessinant des sphères entre deux abscisses données :
#macro dessiner_spheres(absc1, abcs2, pas, rayon)
#if (absc1 < abcs2)
#local i=absc1:
#while (i < absc2)
sphère{<i,0,0>,rayon pigment{Red}}
#local i=i+pas;
#end
#end
#end
Et maintenant voici l'appel de la macro :
dessiner_spheres(0,50,1,.5)
On notera l'utilisation de l'instruction #local permettant de déclarer une variable locale à la macro. Cette variable ne sera pas connue en dehors de la macro.
VII-E. La manipulation d'objets▲
Supposez que vous ayez une texture que vous utilisez sans arrêt, ce serait dommage de l'écrire à chaque fois, d'autant plus que si vous changez ensuite la texture, il vous faudra la changer partout où vous vous en servez. POV-Ray n'est pas typé, on peut tout à fait assigner à une variable une texture, ou un objet, un pigment, un finish … Exemple d'utilisation pour factoriser un code :
#declare ma_texture = texture{
pigment{Blue}
normal {
ripples
turbulence 2
normal_map {
[0 bozo]
[.5 ripples]
[1 agate]
}
}
// [...]
sphère{<0,0,0>,1 texture{ma_texture}}
torus{10,.1 texture{ma_texture}}
De même si vous avez un objet utilisé plusieurs fois avec des textures différentes :
#declare mon_objet = sphère{<0,0,0>,1}
// [...]
object{mon_objet texture{ma_texture1}}
object{mon_objet translate <10,0,0> texture{ma_texture2}}
VII-F. La manipulation de fichiers▲
POV-Ray permet de lire et écrire des fichiers texte. Il peut être intéressant de sauvegarder dans un fichier le résultat d'un traitement très long, de manière à le récupérer lors des prochains rendus d'image, sans avoir à le recalculer. Les procédures de sauvegarde et de chargement sont entièrement à la charge du programmeur. Vous n'avez que les outils de base suivants :
- #fopen. Cette instruction permet d'ouvrir un fichier texte. Cette instruction prend trois arguments : un identifiant pour le fichier, le nom du fichier et le mode d'ouverture du fichier. Exemple :
#fopen mon_fichier "machin.txt" read
Le symbole mon_fichier n'a pas besoin d'avoir été déclaré précédemment.
Les différents modes d'ouverture de fichiers sont : read (ouverture en lecture), write (ouverture en écriture, si un fichier du même nom existe déjà, il est écrasé) et append (ouverture en écriture, si un fichier du même nom existe déjà, le pointeur interne est positionné à la fin du fichier).
- #read. Cette instruction permet de lire dans un fichier une liste de valeurs séparées par des virgules.
#read mon_fichier var1, var2, var3
Cette instruction est à nombre d'arguments variables. Il est donc possible de lire un grand nombre de variables en une seule fois.
- #write. Cette instruction permet d'écrire dans un fichier. Le fichier doit auparavant avoir été ouvert en écriture. Cette instruction est aussi à nombre d'arguments variables. Son premier argument est l'identifiant du fichier. L'instruction reçoit ensuite une suite de variables ou de chaînes de caractères.
#write mon_fichier var1, ",", var2, ",", var3, "\n"
Toutes les variables sont écrites les unes à la suite des autres dans le fichier. Pensez donc à les séparer par des virgules ou des retours chariot (\n), sans quoi vous ne réussirez pas à relire vos données, qui seront considérées comme étant une seule grande chaîne de caractères.
- #fclose. Cette instruction ferme un fichier.
#fclose mon_fichier
VII-G. Une fonction très utile : trace▲
La fonction trace peut rendre bien des services, elle permet d'obtenir les coordonnées d'un point sur un objet, quel que soit cet objet, et aussi compliqué soit-il. La fonction trace va calculer le point d'intersection entre un objet et une droite (définie par un point et un vecteur). La syntaxe de la fonction trace est la suivante :
trace(nom d'un objet,
point de départ de la droite,
vecteur directeur de la droite)
Le nom de l'objet doit être une variable contenant un objet. Exemple :
#declare obj = sphère{<0,0,0>,1}
#declare intersect = trace(obj,<0,10,0>,<0,-1,0>);
// trace renvoie <0,1,0>
La fonction trace admet une seconde syntaxe : elle prend un quatrième argument : une variable dans laquelle elle renverra le vecteur normal à l'objet au point d'intersection. Exemple :
#declare result_norm = <0,0,0>;
#declare obj = sphère{<0,0,0>,1}
#declare intersect = trace(obj,<0,10,0>,<0,-1,0>, result_norm);
VII-H. Les fichiers ini▲
Le fichier ini est à un script POV-Ray ce qu'un fichier Makefile est à un projet C/C++, il regroupe toutes les options de rendu. Règles à respecter pour écrire un fichier ini :
une ligne commençant par un point-virgule est un commentaire ;
il faut indiquer le nom du fichier source ainsi que le nom de l'image à créer ;
il faut indiquer les dimensions de l'image à créer.
Il y a une foultitude d'autres options que l'on peut rajouter, celles-ci ne sont que les plus courantes.
Exemple de fichier ini :
; ceci est un commentaire
; options d'antialing
Antialias=On
Antialias_Threshold=.4
Antialias_Depth=3
; dimensions, w pour width ( largeur) et h pour height (hauteur)
+w1024
+h768
; noms des fichiers d'entrée et de sortie
Input_File_Name=developpez.pov
Output_File_Name=developpez.bmp
Les fichiers ini sont surtout utiles sous Linux, en ligne de commande. Leur utilisation sous Windows est transparente, l'IDE s'occupe de tout (ou presque).
VII-I. Les animations▲
Il est possible de calculer des animations. Par defaut, POV-Ray ne calcule qu'une seule image par script, mais on peut lui en faire calculer plusieurs, à la manière d'une boucle. POV-Ray met à votre disposition la variable clock, qui est incrémentée à chaque nouvelle image. La valeur de clock dépend du nombre d'images à calculer (dépend des indices de la première et de la dernière image) ainsi que des valeurs minimum et maximum de clock. À vous ensuite de prendre compte de la valeur de clock dans votre scène pour la faire évoluer. Toutes ces informations peuvent figurer dans un fichier ini. Exemple
Initial_Frame=0
Final_Frame=10
Initial_Clock=0.0
Final_Clock=1.0
Sous Windows, ces valeurs sont à rajouter dans le fichier POVRAY.INI modifiable à partir du menu Tools -> Edit Master POVRAY.INI.
VII-J. Le hasard : les fonctions seed et rand▲
Comment obtenir des valeurs aléatoires en POV-Ray ? Le mot juste serait plutôt des valeurs 'pseudoaléatoires', ainsi d'un rendu à l'autre, nous obtiendrons les mêmes valeurs. Pour obtenir des valeurs aléatoires, il faut créer une variable représentant le générateur de nombres pseudoaléatoires. Le générateur est initialisé avec une valeur entière (la racine du générateur). Par la suite, le générateur fournira des flottants compris entre 0 et 1. Exemple d'utilisation :
#declare le_generateur = seed(5); // la racine du générateur est 5
sphere{<6*rand(le_generateur), -3*rand(le_generateur), rand(le_generateur)+2>,1 pigment{Red}}
Ce code dessinera une sphère de rayon 1 et dont le centre sera quelque part dans l'objet
box{<0,0,2>,<6,-3,3>}
Notez qu'il est possible d'utiliser plusieurs générateurs de nombres pseudoaléatoires, il suffit de déclarer plusieurs variables et de les initialiser avec des racines différentes.