\subsection{Le module \emph{luadraw\_povray}} \newcommand*{\povray}{POV-Ray\xspace}% Ce module ne renvoie rien, il ajoute de nouvelles méthodes graphiques à la classe \emph{ld.graph3d} ainsi qu'une fonction dans l'espace de noms \emph{luadraw}. \subsubsection{Prérequis et introduction} Avant toute chose, le logiciel \povray doit être installé sur votre ordinateur en version ligne de commande (version non graphique). \begin{itemize} \item Sous linux : \povray est forcément en ligne de commande et s'installe avec le gestionnaire de paquets. \item Sous macOS : la version de \povray en ligne de commande peut être installée via \href{https://formulae.brew.sh/formula/povray\#default)}{HomeBrew}. \item Sous windows : l'installateur est à télécharger sur le site de \href{https://www.povray.org/download/}{\povray}. \end{itemize} Ce module permet de créer des fichiers sources (relativement basiques) pour le logiciel \povray (en ligne de commande) et de les compiler à la volée. Une fois créée, l'image (format \emph{png}) peut être incluse automatiquement dans le graphique en cours, ce qui permet de dessiner dessous et dessus. L'image s'insérera parfaitement, c'est à dire que les repères 3D du graphique et de l'image seront parfaitement identiques, à condition d'être en mode de \textbf{projection orthographique}. Les fichiers sources et images sont créés dans le dossier de travail de \luadrawenv. Les fichiers sources peuvent être évidemment compilés à part par l'utilisateur, les options à transmettre à \povray sont écrites en commentaires au début du source. Le source est en trois parties : un préambule, la déclaration des objets, et le rendu des objets. \subsubsection{Réglages par défaut} L'utilisation de ce module nécessite certains réglages par défaut qui peuvent dépendre du système d'exploitation, ces valeurs par défaut peuvent être modifiées avec la fonction: \cmdln{ld.povray\_default(options)} \writeoptions : \begin{itemize} \item \opt{bg=""}, cette option permet de définir le fond, soit c'est une chaîne vide (valeur par défaut) alors le fond sera transparent (indispensable si on doit dessiner sous l'image), soit c'est une chaîne non vide et alors ce doit un nom de couleur connu de \povray, soit c'est une table de la forme $\{r,g,b\}$ représentant une couleur avec les valeurs $r$, $g$ et $b$ entre $0$ et $1$. \item \opt{shadow=true}, ce booléen indique si les objets doivent créer une ombre ou pas (ce booléen peut être modifié localement pour chaque objet créé). \item \opt{imagescale=1}, cette option permet de modifier la taille de l'image \emph{png} produite, pour des valeurs supérieures à $1$ cela augmente évidemment son poids. \item \opt{param="-V +A +FN"}, ce sont les paramètres de base transmis à \povray, à ceux-ci s'ajouteront automatiquement la largeur et la hauteur de l'image, ainsi que l'option "+UA" si le fond doit être transparent. \item \opt{pov\_cmd=}, nom de la commande pour exécuter \povray, sous unix la valeur par défaut est \val{"povray"}, sous windows la valeur par défaut est \val{"pvengine64.exe"}. \item \opt{pov\_cmd\_ext=""}, chaîne de caractères qui est ajoutée à la fin de chaque commande envoyée à \povray (vide par défaut). \item \opt{win\_param\_ext="/RENDER /EXIT"}, paramètres supplémentaires qui ne concernent que windows. \item \opt{include=\{\}}, cette option permet de demander à \povray d'inclure des fichiers \emph{*.inc}, par exemple : \par \hfil\opt{include=\{"textures.inc", "colors.inc"\}}\hfil\par ces deux fichiers sont normalement distribués avec \povray, le premier définit des textures, le second des couleurs. Par défaut, aucune inclusion n'est faite. \end{itemize} Si vous modifiez une de ces options, la valeur que vous lui donnez devient la nouvelle valeur par défaut pour toute la suite du document, mais il n'est pas nécessaire de répéter cette fonction dans chaque graphique de votre document utilisant \povray, il suffit de le faire une seule fois dans le préambule, par exemple, sous macOS si vous avec installé \povray via \emph{HomeBrew}, alors ceci convient: \begin{minted}{TeX} \documentclass{standalone}% \usepackage[svgnames]{xcolor} \usepackage[3d]{luadraw} \directlua{% require "luadraw_povray" luadraw.povray_default( {pov_cmd = "/opt/homebrew/bin/povray"} ) }% ... \end{minted} Bien sûr, si les valeurs par défaut conviennent à votre système (cela devrait être le cas sous linux), vous n'avez pas besoin d'utiliser la fonction \cmd{ld.povray\_default()}. \subsubsection{Avant la création des objets} Il faut \textbf{obligatoirement initialiser} le dessin \povray avec la méthode : \cmdln{g:Pov\_new(options).} L'argument \argu{options} est exactement le même que pour la fonction précédente \cmd{ld.povray\_default()}, sauf que l'effet sera uniquement local au graphique en cours. \subsubsection{Création des objets} Les objets sont créés à partir de méthodes sur le format \cmd{g:Pov\_(, options)}. Chaque objet est d'abord déclaré dans le source \povray en portant un nom (comme une variable), puis cet objet est ensuite "rendu" dans la troisième partie du source avec une texture définie à partir des options. L'argument \emph{options} est une table dont les champs définissent les options de l'objet, voici les \textbf{options communes à tous les objets} avec leur valeur par défaut: \begin{itemize} \item \opt{name="object"}, chaîne de caractères représentant le nom de l'objet créé, par défaut c'est le mot "object" suivi d'un numéro (ordre d'apparition). Donner un nom est utile lorsqu'on a besoin de réutiliser l'objet par la suite. \item \opt{shadow=true}, booléen indiquant si l'objet crée une ombre. \item \opt{render=true}, booléen indiquant si l'objet doit être affiché. On peut ne pas vouloir afficher un objet lorsque celui-ci intervient dans la construction d'un autre objet par exemple. \item Options définissant la texture de base, celle-ci est composée d'un \emph{pigment} (couleur + opacité) et d'un \emph{finish} (ambient + diffuse + phong): \begin{itemize} \item \opt{color=ld.White}, cette option peut être soit une table au format $\{r,g,b\}$ (avec $r$, $g$ et $b$ entre $0$ et $1$), soit une chaîne de caractères, auquel cas celle-ci doit représenter une couleur connue de \povray, ou bien une texture définie uniquement avec un \emph{pigment} (par exemple \opt{color="Blue\_Sky3"}, ce nom est défini dans le fichier \emph{textures.inc}). \item \opt{usepalette=nil}, cette option permet d'utiliser une palette de couleurs, la syntaxe est \opt{usepalette=\{palette, func, minmax\}} où \argu{palette} est la liste (table) des couleurs, chacune d'elles étant une liste au format $\{r,g,b\}$ avec $r$, $g$ et $b$ ente $0$ et $1$, l'argument \argu{func} est une chaîne qui définit le type de gradient, ce peut être soit \val{"x"} ou \val{"y"} ou \val{"z"} (dans ce cas, l'argument \argu{mimax} doit être une liste contenant la valeur minimale et la valeur maximale), soit une chaîne de la forme \val{"function{ }"}, l'expression qui dépend de $x$, $y$ et $z$ est une fonction (pour \povray) qui doit renvoyer une valeur entre $0$ et $1$ (dans ce cas, l'argument \argu{minmax} est inutile). \item \opt{opacity=1}, nombre entre $0$ et $1$ définissant l'opacité de l'objet. \item \opt{ambient=0.35}, \opt{diffuse=0.8} et \opt{phong=0.5} : trois paramètres définissant le \emph{finish}. \item \opt{mytexture=nil}, ce paramètre permet définir sous forme d'une chaîne sa propre texture, ou bien de donner le nom d'une texture déjà connue de \povray, dans ce cas les paramètres précédents ne sont pas pris en compte. Par exemple: \opt{mytexture="texture\{Silver\_Metal\}"} (cette texture est déclarée dans le fichier \emph{textures.inc}). \end{itemize} \item \opt{matrix=nil}, matrice de transformation 3D qui s'appliquera localement à l'objet. La matrice 3D de transformation globale du graphique est également prise en compte. \item \opt{clipbox=nil}, cette option permet de définir une liste (table) d'objets pour clipper celui qui est en cours de construction, ces objets peuvent être : soit un objet déjà créé, dans ce cas on donne son nom sous forme d'une chaîne, soit une boite, dans ce cas on donne une table de la forme \emph{\{M(xinf,yinf,zinf), M(xsup,ysup,zsup)\}} (cela représente une diagonale de la boîte), soit une sphère, dans ce cas on donne une table de la forme \emph{\{center,radius\}}, où \emph{center} est un point 3D et \emph{radius} un nombre positif. \item \opt{clipplane=nil}, cette option permet de définir une liste (table) de plans pour clipper l'objet en cours de construction, chaque plan doit être de la forme $\{A,n\}$ où $A$ est un point du plan (point 3D) et $n$ un vecteur normal au plan. Seule la partie de l'objet se situant dans le demi-espace contenant $n$ est conservée. \end{itemize} \subsubsection{Liste des objets prédéfinis} Voici la liste des objets que l'on peut dessiner avec les méthodes correspondantes : \begin{itemize} \item \textbf{Surfaces implicites} d'équation $f(x,y,z)=0$. C'est la méthode : \cmdln{g:Pov\_implicit( povfunction, luafunction, options).} L'argument \argu{povfunction} est une chaîne contenant l'expression de $f(x,y,z)$, \povray connaît les fonctions mathématiques, il faut cependant savoir que la fonction puissance est la fonction \emph{pow}: $x\mapsto \mathrm{pow}(x,n)$, et que \povray ne gère pas les erreurs de calculs comme la division par zéro par exemple. Les options sont celles qui ont déjà été données, plus l'option spécifique : \opt{containedby=}, celle-ci indique dans quelle boîte (ou sphère) seront faits les calculs, par défaut cette boîte est la fenêtre 3D du graphique en cours. Une boîte est une table de la forme \emph{\{M(xinf,yinf,zinf), M(xsup,ysup,zsup)\}} (cela représente une diagonale de la boîte), une sphère est une table de la forme $\{C,r\}$, où $C$ est le centre (point 3D) et $r$ le rayon. Exemple : \begin{Luacode} local f = function(x,y,z) return x^2+y^2+z^2 - 1 end local r = 1.1 g:Pov_implicit("x*x+y*y+z*z-1", f, {color=ld.SteelBlue, containedby={M(-r,-r,-r), M(r,r,r)}}) \end{Luacode} \item \textbf{Surfaces paramétrées}. Deux syntaxes possibles : \begin{enumerate} \item La méthode : \cmd{g:Pov\_surface( f, u1, u2, v1, v2, options)} dessine la surface (lissée) paramétrée par la fonction \argu{f}$\colon(u,v) \mapsto f(u,v)\in \mathbf R^3$. L'intervalle pour le paramètre $u$ est donné par \argu{u1} et \argu{u2}. L'intervalle pour le paramètre $v$ est donné par \argu{v1} et \argu{v2}. Les options sont celles qui ont déjà été données, plus deux options spécifiques : \begin{itemize} \item \opt{grid=\{25,25\}}, cette option définit le nombre de points à calculer pour le paramètre $u$ suivi du nombre de points à calculer pour le paramètre $v$ ($25$ par défaut). \item \opt{clip=\false}, avec la valeur \true la surface est clippée par la fenêtre 3D courante. \end{itemize} Exemple : \begin{Luacode} local f = function(x,y) return M(x,y,x^2+y^2) end g:Pov_surface(f,-2,2,-2,2, {color=ld.SteelBlue, clip=true}) \end{Luacode} \item La méthode : \cmd{g:Pov\_surface( xfunc, yfunc, zfunc, u1, u2, v1, v2, options)} dessine la surface paramétrée par $(u,v)\mapsto (x(u,v), y(u,v), z(u,v))$. Les arguments \argu{xfunc}, \argu{yfunc} et \argu{zfunc} sont trois chaînes contenant respectivement les expressions $x(u,v)$, de $y(u,v)$ et de $z(u,v)$. Les arguments \argu{u1} et \argu{u2}, respectivement \argu{v1} et \argu{v2}, définissent les bornes de l'intervalle pour le paramètre $u$, respectivement pour le paramètre $v$. Les options sont celles qui ont déjà été données, plus deux options spécifiques : \begin{itemize} \item \opt{containedby=}, celle-ci indique dans quelle boîte (ou sphère) seront faits les calculs, par défaut cette boîte est la fenêtre 3D du graphique en cours. Une boîte est une table de la forme \emph{\{M(xinf,yinf,zinf), M(xsup,ysup,zsup)\}} (cela représente une diagonale de la boîte), une sphère est une table de la forme $\{C,r\}$, où $C$ est le centre (point 3D) et $r$ le rayon. \item \opt{max\_grad=nil}, valeur numérique (optionnelle) permettant d'optimiser les calculs, voici ce que dit l'aide de \povray sur ce nombre : \begin{small} \begin{verbatim} The max_gradient is the maximum magnitude of all six partial derivatives over the specified ranges of u and v. Take dx/du, dx/dv, dy/du, dy/dv, dz/du, and dz/dv and calculate them over the entire range. The max_gradient should be at least the maximum (absolute value) of all of those values. Choosing a too small of a value will create holes or artifacts in the object. \end{verbatim} \end{small} \end{itemize} Exemple : \begin{Luacode} g:Pov_surface("x", "y", "x*x+y*y",-2,2,-2,2, {color=ld.SteelBlue, max_grad=4}) \end{Luacode} Remarque : il s'agit de la même surface dans les deux exemples, mais la deuxième méthode est plus longue, et si on ne précise par l'option \opt{max\_grad=4} alors on n'a pas la surface en entier. \end{enumerate} \item \textbf{Polyèdre ou liste de facettes}. C'est la méthode: \cmdln{g:Pov\_facet(F, options).} L'argument \argu{F} est soit un polyèdre, soit une liste de facettes. Les options sont les options communes, plus les options spécifiques suivantes (avec les valeurs par défaut): \begin{itemize} \item \opt{edge=false}, booléen indiquant si les arêtes doivent être dessinées. \item \opt{edgestyle=