TP No1

Graphe de Scène, transformations et Groupes d'objet

Nous allons dans ce TP apprendre à afficher une scene 3D avec le langage processing.


void setup(){
  size(800, 800, P3D);
}

void draw(){
  background(255);
  //ortho();
  float fov = PI/3.0;
  float cameraZ = (height/2.0) / tan(fov/2.0);
  perspective(fov, float(width)/float(height),
              cameraZ/10.0, cameraZ*10.0);

  translate(width/2, height/4);
  //pushMatrix();
    rotateX(frameCount/50.0);
    fill(255, 128, 128);
    sphere(100);
  //popMatrix();

  translate(145,0);

  fill(0, 255, 128);
  box(90);
}
2 modèles 3D
screenshot
Questions 1 :
  1. Essayez la camera ortho () à la place de perspective(...) puis tentez de modifier les parametres de perspective (fov et cameraZ) pour bien comprendre ce qu'ils font.
  2. Enlevez maintenant les commentaires devant pushMatix() et popMatrix() pour debrayer la rotation de la sphère et du cube
  3. Pourquoi faut-il un translate de 145 entre les 2 pour qu'ils se touchent ? que fait -145 à la place de 145 ?
  4. Faîtes tourner le cube dans le sens inverse de la sphère

Questions 2 :
beginShape();
  vertex(-45, 0, 45);
  vertex(45,  0, 45);
  vertex(0,   90, 0);
  endShape(); 
  1. en plus des 2 modèles, nous voulons rajouter un triangle qui ne bouge pas avec le code ci-dessus. N'oubliez de l'encadrer avec un pushMatrix(); / popMatrix(); et de le mettre en bleu.
  2. Rajouter 3 autres faces pour faire un pyramide. Pour ce faire le mode beginShape(); n'est pas pratique car il est fait pour dessiner des polygones. Utilisez plutôt beginShape(TRIANGLES); puis donnez les points par paquets de 3. Faites tourner cette pyramide dans le même sens que le cube.
  3. Mettez tout le code entre beginShape()/endShape(); dans une fonction pyramide() et appelez cette fonction comme vous appeliez box() ou sphere(). Rajouter une base à la pyramide si vous le souhaitez et mettez un paramètre "float taille" à la fonction pyramide() puis remplacez les 45, et 90 pour que la pyramide fasse taille de coté.
  4. Appelez 2 fois pyramide(...) (avec un translate entre les 2 !) pour faire une forme de sablier carré à droite de la sphère
  5. Créez une fonction hourGlass() qui fait ces 2 appels à pyramide() et faites une rangée de 5 sabliers au dessus de la sphère
un triangle
screenshot
une pyramide
screenshot

Questions 3 :

Ces appels en cascade permettent de construire une scene 3D mais restent tres inefficaces car toutes les coordonnées de point sont redonnées à chaque affichage, nous souhaitons maintenant utiliser un modèle pré-construit dans une PShape. Pour se faire on crée une PShape et on appelle nos beginShape(), vertex(), etc. dessus. Il faudrait mettre tout ça dans setup() pour ne le faire qu'une seule fois mais voyons plus loin les amis ... mettons cela dans une fonction dédiée myHourGlass() qui créé et retourne une PShape. Permettons nous de rajouter un paramètre à cette fonction pour un nombre de cotés qui formera un cone à la place d'une pyramide

PShape cone0;

void setup(){
  size(800, 800, P3D);
  cone0 = myCone(90, 13);
}

PShape myCone(float sideSize, int nbSide){
  PShape shape0 = createShape();
  shape0.beginShape(TRIANGLE_FAN);
  shape0.fill(255, 255, 0);
  shape0.stroke(0);
  shape0.vertex(0,0,0);
  for (int i=0; i<=nbSide; i++){
    shape0.vertex(sideSize/2*cos(i*2*PI/nbSide),
                  sideSize/2*sin(i*2*PI/nbSide),
                  sideSize);
  }
  shape0.endShape();
  return shape0;
}
void draw(){
  ...
  pushMatrix();
  // ici eventuels translate/rotate/scale pour se mettre au bon endroit.
  fill(0, 0, 255);
  shape(cone0, 0, 0);
  popMatrix();
} 
un cone
screenshot
  1. Faîtes tourner ce code en remplaçant les ... Comme vous le voyez le cone est jaune et non bleu car c'est la couleur du modèle qui compte (shape0.fill(255, 255, 0);) plus que la couleur au moment d'afficher le modele (fill(0, 0, 255);)
  2. Integrez ce code dans le premier pour remplacer les sabliers par un cone puis par 2 cones qui forment un sablier
  3. On aimerez avoir une fonction myHourGlass(qui fait 2 cones ) mais comment faire ? un PShape ne peut avoir qu'un seul beginShape() et un seul endShape() apparement. Heureusement il est possible de créer un Pshape g = createShape(GROUP); et d'ajouter des PShape à ce groupe avec g.addChild(shape0);. Créez la fonction myHourGlass(...) qui créé, regroupe et retourne un groupe de 2 cones. Dessinez un sablier rond avec un seul appel à shape()
  4. Vous pouvez maintenant rajouter deux "fonds" de couleur orange à votre sablier et en dessiner une ribambelle de 5 plus un gros mieux defini de la'utre coté et les faire tourner tous à des vitess differentes, des sens différents, etc.

screenshot