Sommaire Carte Index Recherche Nouvelles Archives Liens A propos
[Barre Superieure]
[Barre Inferieure]
[Photo of the Author]
Carlos Calzada Grau

L´auteur:

Je suis diplomé en informatique et fou de graphisme depuis mon premier spectrum . Je suis un fan de Linux et de sa philosophie sur le développement , et de tout ce qui n'a pas de rapport avec Micro$oft
Deux de mes autres passe-temps non-informatiques sont les bonsais et l'aquariophilie.

Sommaire:

  1. Introduction
  2. Une Scène Simple:
  3. Un Mouvement Rectiligne :
  4. Un Mouvement Parabolique :
  5. References

Renderman Part III

[Ilustration]

Résumé:

Ceci est le troisième article sur Renderman ( I II ). Cette fois , nous allons voir une des parties les plus importantes : lla possibilité de modéliser et d'animer une scène en "C" ou en "C++".



 

Introduction

D'après les deux précédents articles , il est clair que bien qu'il soit possible de décrire une scène en l'écrivant directement dans un fichier texte , l'entreprise est très fastidieuse . Par exemple , essayez d'écrire un fichier ".rib" pour ddécrire le mouvement d'une sphère qui rebondit ! Pour se simplifier la vie , nous avons la possibilité d'écrire des applications en "C" ou "C++" qui modélise la scène et l'animation grâce à des fonctions écrites par l'utilisateur , l'application affichant à l'écran le script ".rib" d'une telle scène . La redirection Unix nous permet ensuite, soit d'envoyer le script généré directement à un autre programme (comme rendrib, rendribv, rgl) , soit de l'envoyer dans un fichier ".rib" .

Notre précédente installation de BMRT (Blue Moon Rendering Tools) a donné deux nouveaux repertoires lib and include dans celui ou nous l'avons installé . Ceci contiennent deux fichiers qui nous intéressent  : ri.h qui contient les entêtes des fonctions "C" et libribout.a qui est la librairie de ces fonctions . Le fichier d'entête peut être copier dans /usr/local/include eet libribout.a dans /usr/local/lib (le programmeur expérimenté peut choisir de les placer ailleurs bien sur) . Après cette petite installation , nous sommes prêts pour notre premier exemple de programme . <
 

Une Scène Simple:

Notre premier exemple montre les rudiments de la programmation avec Renderman . Comme dans tout code C , nous devons inclure le fichier d'entête ccorrespondant à la librairie utilisée , dans notre cas ri.h . De plus , nous devons lier notre programme avec la librairie libribout.a ,, comme ceci :
gcc myprogram.c -o myprogram -lribout -lm
Voici un exemple de Makefile qui vous fera gagner du temps  :
LIBS = -lm -lribout
PROGNAME = primero
         
all: $(PROGNAME)
        
$(PROGNAME).o: $(PROGNAME).c
        gcc -c $(PROGNAME).c
        
$(PROGNAME): $(PROGNAME).o 
        gcc -o $(PROGNAME) $(PROGNAME).o $(LIBS)

 

Notre premier exemple construit des axes de coordonnées et une sphère , nous l'appellerons primero.c, dont voici le code:
 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <ri.h>
 4
 5 void main(void)
 6 {
 7  int i;
 8  int x,y,z;
 9  int nf;
10  float slopex,slopey,slopez;
11
12  RtColor Rojo={1,0,0};
13  RtColor Verde={0,1,0};
14  RtColor Azul={0,0,1};
15  RtColor Blanco={1,1,1};
16
17  RtPoint p1={30,0,10}; /* Position initiale de la sphère */
18  RtPoint p2={0,20,10}; /* Position final de la sphère    */
19              
20  RtPoint from={0,100,100}; /*   Direction de la lumière  */
21  RtPoint to={0,0,0};
22
23  char name[]="primero.tif";
24  RtFloat fov=45;
25  RtFloat intensity1=0.1;
26  RtFloat intensity2=1.5;
27  RtInt init=0,end=1;
28              
29  RiBegin(RI_NULL);
30    RiFormat(320,240,1);
31    RiPixelSamples(2,2);      
32    RiShutter(0,1);
33    RiFrameBegin(1);
34     RiDisplay(name,"file","rgb",RI_NULL);
35     name[7]++;
36     RiProjection("perspective","fov",&fov,RI_NULL);
37     RiTranslate(0,-5,60);
38     RiRotate(-120,1,0,0);
39     RiRotate(25,0,0,1);
40     RiWorldBegin();
41       RiLightSource("ambientlight","intensity",&intensity1,RI_NULL);
42       RiLightSource("distantlight","intensity",&intensity2,"from",from,"to",to,RI_NULL);
43       RiColor(Azul);
44       RiTransformBegin();
45         RiCylinder(1,0,20,360,RI_NULL);
46         RiTranslate(0,0,20);
47         RiCone(2,2,360,RI_NULL);
48       RiTransformEnd();
49       RiColor(Verde);
50       RiTransformBegin();
51         RiRotate(-90,1,0,0);
52         RiCylinder(1,0,20,360,RI_NULL);
53         RiTranslate(0,0,20);
54         RiCone(2,2,360,RI_NULL);
55       RiTransformEnd();
56       RiColor(Rojo);
57       RiTransformBegin();
58         RiRotate(90,0,1,0);
59         RiCylinder(1,0,20,360,RI_NULL);
60         RiTranslate(0,0,20);
61         RiCone(2,2,360,RI_NULL);
62       RiTransformEnd();
63       RiColor(Blanco);
64       RiSphere(5,-5,5,360,RI_NULL);
65     RiWorldEnd();
66    RiFrameEnd();
67  RiEnd();
68 };

Les trois premières lignes servent à inclure les fichiers d'entêtes comme ri.h qui contient les prototypes des fonctions de la librairie Renderman . Chaque fonction Renderman à son équivalent en C , comme TransformBegin qui correspond à la fonction C RiTransformBegin(), etc... Créer l'exécutable primero en tapant make . Notre programme peut être appelé pour créer un fichier en sortie par redirection (primero > primero.rib)  ou en envoyant l'affichage directement à un autre programme (primero | rendrib) . Dans ce dernier cas , rendrib se charge de générer l'image primero.tif :

Les fonctions appelées de la librairie Renderman doivent être encapsulées entre un RiBegin(RI_NULL) et un RiEnd(). Le paramètre passé à RiBegin est normalement RI_NULL . Pour éviter que l'affichage du script Rib ne se fasse à ll'écran , nous pouvons donner le nom du fichier de sortie ("myfile.rib") ou meme le nom d'un programme (comme rendrib), l'exécutable passera ensuite les commandesRenderman au programme de rendu sans créer un fichier RIB intermédiaire.

Le code source de notre premier exemple contient des instructions C typiques , plus des types et fonctions intrinsèques à l'interface Renderman : le type RtColor est un vecteur de trois réels donnant les composantes rouge , vert et bleu (les valeurs sont comprises entre 0.0 et 1.0) ; RtPoint donne une position dans l'espace ; RtFloat et RtInt sont respectivement de type réel et entier .

La ligne 29 contient un appel à RiBegin(RI_NULL), qui comme nous l'avons vu précédemment , est un appel d'initialisation pour l'interface Renderman . Ensuite ,  on retrouve les fonctions Renderman habituelles d'un fichier RIB classique . Essayez de lancer le programme et de redirigez l'affichage dans un fichier (./primero > primero.rib) , ce qui devrait donner :
##RenderMan RIB-Structure 1.0
version 3.03
Format 320 240 1
PixelSamples 2 2
Shutter 0 1
FrameBegin 1
Display "camara.tif" "file" "rgb"
Projection "perspective" "fov" [45 ]
Translate 0 -5 60 
Rotate -120 1 0 0 
Rotate 25 0 0 1 
WorldBegin
LightSource "ambientlight" 1 "intensity" [0.1 ]
LightSource "distantlight" 2 "intensity" [1.5 ] "from" [0 100 100] "to" [0 0 0]
Color [0 0 1]
TransformBegin
Cylinder 1 0 20 360
Translate 0 0 20 
Cone 2 2 360
TransformEnd
Color [0 1 0]
TransformBegin
Rotate -90 1 0 0 
Cylinder 1 0 20 360
Translate 0 0 20 
Cone 2 2 360
TransformEnd
Color [1 0 0]
TransformBegin
Rotate 90 0 1 0 
Cylinder 1 0 20 360
Translate 0 0 20 
Cone 2 2 360
TransformEnd
Color [1 1 1]
Sphere 5 -5 5 360
WorldEnd
FrameEnd

Notre premier exemple n'est pas très utile . Pour générer une autre scène , nous devons écrire un nouveau programme qui effectuerait les opérations similaires . La puissance de la librairie Renderman est vraiment dans la génération d'animations . Dans ce premier exemple , une seule image a été générée ,, dans le prochain , nous allons faire bouger la sphère .
 

Un Mouvement Rectiligne :

Dans ce deuxième exemple , notre scène consiste encore en trois axes de coordonnée et une shpère , mais cette fois , celle-ci va bouger de la coordonnée (30,0,10) à (0,20,10) , ce qui va de la droite de l'écran vers la gauche . Ces deux coordonnées seront définies en utilisant le type RtPoint (lignes 18 et 19) . Le nombre de frames ou d'images de l'animation est définie dans la variable nb . En utilisant ce nombre et les coordonnées initiale et finale , on peut calculer la translation par frame dans les trois directions (slopex, slopey and slopez) . C'est tout ce dont nous avons besoin pour modifier la position de la ssphère à chaque frame . Entre les lignes 75 et 78 , la partie TransformBegin/TransformEnd permet de définir la position de la sphère . Les nouvelles coordonnées sont calculées très simplement ligne 76 .
 
 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <ri.h>
 4 #include "filename.h"
 5
 6 void main(void)
 7 {
 8  int i;
 9  int x,y,z;
10  int nf;
11  float slopex,slopey,slopez;  
12
13  RtColor Rojo={1,0,0};
14  RtColor Verde={0,1,0};
15  RtColor Azul={0,0,1};
16  RtColor Blanco={1,1,1};
17
18  RtPoint p1={30,0,10}; /* Position initiale de la sphère */
19  RtPoint p2={0,20,10}; /* Position finale de la shpère   */
20      
21  RtPoint from={0,100,100}; /*      Direction de la lumière     */
22  RtPoint to={0,0,0};
23
24  char base[]="camara_";
25  char ext[]="tif";
26  char name[50];
27  RtFloat fov=45;
28  RtFloat intensity1=0.1;
29  RtFloat intensity2=1.5;
30  RtInt init=0,end=1;
31      
32  nf=100; /*        Nombre de frames (d'image)      */
33  slopex=(p2[0]-p1[0])/nf;
34  slopey=(p2[1]-p1[1])/nf;
35  slopez=(p2[2]-p1[2])/nf;
36
37  RiBegin(RI_NULL);
38    RiFormat(320,240,1);
39    RiPixelSamples(2,2);      
40    RiShutter(0,1);
41    for (i=1;i <= nf;i++)
42      {
43      RiFrameBegin(i);
44        filename(base,ext,sizeof(base)+4,i-1,name);
45        RiDisplay(name,"file","rgb",RI_NULL);
46        name[7]++;
47        RiProjection("perspective","fov",&fov,RI_NULL);
48        RiTranslate(0,-5,60);
49        RiRotate(-120,1,0,0);
50        RiRotate(25,0,0,1);
51        RiWorldBegin();
52          RiLightSource("ambientlight","intensity",&intensity1,RI_NULL);
53          RiLightSource("distantlight","intensity",&intensity2,"from",from,"to",to,RI_NULL);
54          RiColor(Azul);
55          RiTransformBegin();
56              RiCylinder(1,0,20,360,RI_NULL);
57              RiTranslate(0,0,20);
58              RiCone(2,2,360,RI_NULL);
59          RiTransformEnd();
60          RiColor(Verde);
61          RiTransformBegin();
62              RiRotate(-90,1,0,0);
63              RiCylinder(1,0,20,360,RI_NULL);
64              RiTranslate(0,0,20);
65              RiCone(2,2,360,RI_NULL);
66          RiTransformEnd();
67          RiColor(Rojo);
68          RiTransformBegin();
69              RiRotate(90,0,1,0);
70              RiCylinder(1,0,20,360,RI_NULL);
71              RiTranslate(0,0,20);
72              RiCone(2,2,360,RI_NULL);
73          RiTransformEnd();
74          RiColor(Blanco);
75          RiTransformBegin();
76              RiTranslate(p1[0]+slopex*(i-1),p1[1]+slopey*(i-1),p1[2]+slopez*(i-1));
77              RiSphere(5,-5,5,360,RI_NULL);
78          RiTransformEnd();
79        RiWorldEnd();
80      RiFrameEnd();
81      }
82  RiEnd();
83 };

Ensuite , essayez cet exemple comme précédemment : compilez-le et exécutez-le en le redirigant vers rendribv , par exemple . C'est une méthode simple pour obtenir un rapide apercude notre aanimation à un rythme acceptable . Pour avoir le script RIB généré , il suffit de rediriger vers un nouveau fichier . On peut voir que la taille de ce fichier est très grande (segundo.rib occupe 70kb) car la même scène est définie 100 fois (une fois par frame) .

Les images suivantes montre quelques frames intermédiaires de l'animation :

Bien sur , on peut animer tous les paramètres que nous souhaitons : la position des objets , leurs tailles , l'intensité de la lumière, la caméra (l'oeil de l'observateur) , faire apparaitre et disparaitre des choses , etc ...
 

Un Mouvement Parabolique :

Dans ce dernier exemple , voyons comment faire rebondir la sphère sur le sol . Nous devons définir d'abord la fonction rebote() (qui veut dire rebond) qui prend trois paramètres : le numero du frame actuel , le nombre total de frames par rebonds et l'amplitude maximale que la sphère peut atteindre . Voici son code :
 
float rebote (int i, int nframes, int max)
{
  float min, z;

  while (i > nframes) i-=nframes;

  min=sqrt(max);

  z=i-((float)nframes/2.0);
  z=(z*min)/((float)nframes/2.0);
  z=(float)max - (z*z);
  return(z);
}

Par quelques calculs simples , on associe à l'équation d'une courbe parabole (y=x²) le nombre de frame et le maximum désiré de l'amplitude . Les images suivantes montre quelques frames générés pendant un rebond par le programme tercero.c:

Je vous donne quelques fichiers GIF pour voir les animations ; bien qu'elles soient lentes (au moins avec Netscape) , avec xanim , vous devriez les voir à une vitesse acceptable :

Le Mouvement Rectiligne : segundo_anim.gif

Le Mouvement Parabolique : tercero_anim.gif

Ce dernier exemple termine notre présentation des rudiments de l'interfacage du C avec Renderman . Le plus avancé et le plus spectaculaire des sujets de programmation est le thème des ombrages . Il donne le controle ultime sur le rendu final d'une scène car cela permet de controler les textures , l'ilumination ,  etc ...
 

References


Traduit par Frédéric Nourry

Site Web maintenu par l´équipe d´édition LinuxFocus
© Carlos Calzada Grau
LinuxFocus 1999