Outils pour utilisateurs

Outils du site


wiki:projets:gaite:projet1

KINECT/MULTITOUCH

Description du projet

Comment joindre le son et son acteur avec l'espace ?

L'installation proposée permet de créer un univers graphique scénique et visuel tout en offrant une grande liberté d'intervention sur la musique. Elle s'adapte au titre Love Like a Sunset de Phoenix. Ce morceau, comme une accumulation sonore, renvoie au voyage. Un résultat abstrait se présente suite aux expériences graphiques opérées sur des visuels de paysages (montagne). Ils permettent une superposition des traits et aplats crées, renvoyant à la manipulation possible des samples de Phoenix. Chque sample correspond à un module (volume pyramidale) et s'active au paysage d'une main en dessous. Ces zones de réactivité sont générées par la Kinect et le programme sous Processing.

Matériaux

Kinect avec connection USB pour PC/MAC + vidéoprojecteur

Tutoriel d'installation de la kinect

Librairies nécessaires pour Kinect:

  • OPENNI (PC)
  • SDK Kinect: driver (PC)
  • SimpleOpenNI

Fichier d'installation : installation_kinect.zip

Photos

code processing (mise à jour 09 Avril 2015)

Attention : deux onglets

// LIBRAIRIES
  import processing.opengl.*; // librairie qui initialise la 3D
  import SimpleOpenNI.*; // librairie de la kinect 
  import ddf.minim.*; // librairie de son 

// VARIABLES GLOBALES
  SimpleOpenNI kinect;
  float rotation = 0;
  Minim minim;
  // Déclaration d'un TABLEAU dynamique "ArrayList" contenant les objets de type "AudioPlayer" (les sons) ( qui sont associés aux cubes/hotpoint)
    ArrayList<AudioPlayer> playList; 
  
  // Déclaration d'un TABLEAU dynamique "ArrayList" contenant les objets de type "Hotpoint" (cubes spatiaux)
    ArrayList<Hotpoint> trigers;
    int nbHotpoint = 8 ; // nombre de hotpoints (cubes spatiaux)
    
  // Déclaration d'un TABLEAU dynamique "ArrayList" de PVector ( de vecteurs) contenant les positions des cubes spatiaux
    ArrayList<PVector> trigerPos;  
  
  // Déclaration d'un TABLEAU dynamique "ArrayList" d' IMAGES 
    ArrayList <PImage> images;
      
  // DEFINTION DE LA  POSITION exact des hotpoints (cubes spatiaux) dans l'espace sachant que 1000 pixels = 1m 
    //IRCAM (devant CS)
      float posX3 = -750, posY3 = 000, posZ3 = 2100; 
    //CS (tout au fond gauche)
      float posX13 = -550, posY13 = 000, posZ13 = 2500; 
    //Reich(tout au fond droite)
      float posX30 = 550, posY30 = 000, posZ30 = 2600;
    //Oiseau (devant reich)
      float posX32 = 750, posY32 = 000, posZ32 = 2200; 
    //Guit
      float posX35 = -500, posY35 = 000, posZ35 = 1800; 
    //AC
      float posX36 = 200, posY36 = 000, posZ36 = 1300; 
    //Nu
      float posX38 = 500, posY38 = 000, posZ38 = 1800; 
    //HH
      float posX54 = -200, posY54 = 000, posZ54 = 1300;       
      
      
    

////////////////////////////////////////////SETUP 
void setup() {
  size(2048, 1100, OPENGL); //taille ecran de la salle : 2048*1100 // ECRAN ORDI PORTABLE MORGANE 2048*745
  kinect = new SimpleOpenNI(this); // instancie la librairie SimpleOpenNi
  kinect.enableDepth(); // permet la profondeur 

  minim = new Minim(this);
  
  // CREATION DE LA LISTE (Arraylist) DE SONS (playList) initialement vide
    playList = new ArrayList<AudioPlayer>();  
  
  // REMPLISSAGE DE LA LISTE (par importation de sons dans la playlist)
    //IRCAM
      playList.add(minim.loadFile("IRCAM3.mp3"));
    //CS
      playList.add(minim.loadFile("CS1.mp3")); 
    //reich
      playList.add(minim.loadFile("Reich.mp3")); 
    //Oiseau
      playList.add(minim.loadFile("GtrOiseaux2.mp3")); 
    //Guit
      playList.add(minim.loadFile("GuitC.mp3"));
    //AC
      playList.add(minim.loadFile("AC.mp3"));
    //Nu
      playList.add(minim.loadFile("Nu1.mp3")); 
    //HH
      playList.add(minim.loadFile("HH3.mp3"));

  
  // CREATION DE LA LISTE (Arraylist) DE POSITIONS (PVector) des Hotpoints (cubes sapatiux) initialement vide
    trigerPos = new ArrayList<PVector>(); 
    
  // REMPLISSAGE DE LA LISTE 
    //ircam
      trigerPos.add( new PVector(posX3,posY3,posZ3)); 
    //CS 
      trigerPos.add( new PVector(posX13,posY13,posZ13)); 
    //Reich  
      trigerPos.add( new PVector(posX30,posY30,posZ30));   
    //Oiseau
      trigerPos.add( new PVector(posX32,posY32,posZ32));   
    //Guit
      trigerPos.add( new PVector(posX35,posY35,posZ35));   
    //AC
      trigerPos.add( new PVector(posX36,posY36,posZ36)); 
    //Nu 
      trigerPos.add( new PVector(posX38,posY38,posZ38)); 
    //HH 
      trigerPos.add( new PVector(posX54,posY54,posZ54)); 
      

  // CREATION DE LA LISTE (Arraylist) D'IMAGES initialement vide
    images = new ArrayList<PImage>(); 
    
  // REMPLISSAGE DE LA LISTE d'images
    //ircam
      images.add(loadImage("araignee.png"));
    //CS 
      images.add(loadImage("gris1.png"));
    //Reich  
      images.add(loadImage("gris2.png"));
    //Oiseau
      images.add(loadImage("gris3.png"));
    //Guit
      images.add(loadImage("mont1.png"));
    //AC
      images.add(loadImage("gris0.png"));
    //Nu 
      images.add(loadImage("mont2.png"));
    //HH 
      images.add(loadImage("vert.png"));
         
  // CREATION DE LA LISTE (Arraylist) HOTPOINTS (Cube spatiaux) "trigers" initialement vide -----> verifier que c'est bien la liste des hotpoints 
    trigers = new ArrayList<Hotpoint>(nbHotpoint);   

  // INITIALISATION DE LA LISTE DES HOTPOINTS (cubes spatiaux): on crée tous les hotPoints de la liste - on utilise le consructeur 2
    for (int i = 0; i < nbHotpoint; i++) { 
       trigers.add( new Hotpoint(trigerPos.get(i), //ajout des données de positions aux hotpoints
                                 100, 100,100, //dimension des hotpoints(/cubes spatiaux) (largeur, hauteur, profondeur)
                                 playList.get(i) , // position du cube // largeur,hauteur,profondeur // son associé 
                                 images.get(i))) ;                
    }

}  
/////////////////////////////////////FIN SETUP 


//////////////////////////////////// DRAW 
void draw() {
  
  background(#FFFFFF); // fond de la fenêtre
  kinect.update(); // mise à jour des données de la kinect

  translate(width/2, height/2,-200); // permet de placer la représentation dans l'esapce // LE DERNIER NOMBRE INDIQUE LA PROFONDEUR Z DE LA REPRESENTAION
  rotateX(radians(180));// determine le placement la représentation et permet une rotation

  //translate(0, 0, 1400); // detemine le placement de la représentation sur l'axe des y 
  //rotateY(radians(map(mouseX, 0, width, -180, 180))); // determine les valeur du mouvement de la rotation exercer avec la souris 

  //translate(0, 0, -1500); // determine l'échelle de la représentation dans l'axe des z (profondeur)

  stroke(#000055); // couleur des lignes de l'environnement (les gens qui se mettent en face de la kinect, le mur au fond ...)
  strokeWeight(0); //épaisseur traits de l'environnement  
  
  
  
  
  PVector[] depthPoints = kinect.depthMapRealWorld(); // création du tableau de vecteur depthPoints : ce sont les points de l'environement, ils sont donnés par la kinect avec la méthode propre à elle qui s'appelle depthMapRealWorld
  
  for (int i = 0; i < depthPoints.length; i+=10) { // boucle permettant de créer tout de 10 en 10 les points detecté par la kinect par depthPoint
  
    PVector currentPoint = depthPoints[i]; // créer les vecteurs du tableau des points(en cours d'analyse) depthPoint qui s'appelera currentPoint 
    
    for (Hotpoint HP : trigers) {
        HP.check(currentPoint);
      }  
    point(currentPoint.x, currentPoint.y, currentPoint.z); //points qui determinent/visualisent l'environnement (le/les corps, les objets, les murs ...) 
  }

   for (Hotpoint HP : trigers) { // pour tous les Hotpoint de la liste "trigers"
      if(HP.sound.isPlaying()){    
         HP.apparaitre();
       }
         
      if (HP.isHit()) {// On effectue les actions suivantes uniquement si le cube (Hotpoint) concerné
      // est touché dans la boucle draw() actuelle et n'était pas touché dans la boucle draw() précédente
      //i.e. ssi currentlyHit() == true (le cube est en train d'être touché dans la boucle draw() actuelle) et wasJustHit==false (le cube n'était pas touchée dans la boucle draw() précédente) 
            
      // si la musique ne joue pas alors on lance la musique en boucle
        if( !HP.sound.isPlaying()){
          
          HP.sound.play();
          
          HP.sound.loop();
          HP.apparaitre();
          }
          
        else { // sinon, si la musique joue, on l'arrête et on rembobine la bande
          HP.sound.pause();
          HP.sound.rewind();
          }        
      }// tant que le cube est touché, on laisse jouer la musique car on ne rentre pas dans le test if(HP.isHit())...
       
       
      //dessine le hotPoint (cube) coloré avec une transparence plus ou moins importante en fonction du porcentage d'inclusion
      HP.draw();//execution de méthode draw issue de la class hotpoint (création des hotpoints) : 
      
      HP.clear(); // garde en mémoire si le hotPoint est touché ou non pour la boucle draw() suivante
      // cette action fixe la valeur de l'attrubut wasJustHit:
  }
  
}
///////////////////////////////////////////////FIN DRAW 

Second onglet :

//création d'une classe créant les cubes interactifs

class Hotpoint {
  PVector center;
  color fillColor;
  color strokeColor;
  float profondeur; // profondeur du carré
  float largeur; //largeur du carré
  float hauteur; //hauteur du carré
  float pointsIncluded;
  int maxPoints;
  boolean wasJustHit;
  int threshold; // seuil
  AudioPlayer sound;
  PImage visuel;
  
  int Imgx,Imgy;  


    float x=-900;
    float y=-500;
  
////////////////////////////////////////// CONSTRUCTEUR 
  Hotpoint(PVector pos, float larg, float haut, float prof, AudioPlayer s,PImage v ) { //constructeur de Hotpoint, déterminé par la position dans l'espace du cube (x,y,z) et la taille du cube (x,y,z)
    center = pos; //création du vecteur attribut de Hotpoint, c'est la position dans l'espace. Il commence au centre du cube
    pointsIncluded = 0; // les points de profondeur vont être analyser, commencer à zéro
    maxPoints = 1000;
    threshold = 0; // threshold = seuil
    largeur=larg;
    profondeur=prof;
    hauteur=haut;
    fillColor = strokeColor = color(random(255), random(255), random(255)); //on commence avec une valeur aléatoire, qui sera redéfinie par setColor
    
    // MUSIQUE associée au Hotpoint (cubes spatiaux) lorsqu'il est touché
    sound = s ;
    
    // IMAGE associée au Hotpoint (cubes spatiaux) lorsqu'il est touché
    visuel = v ;
  }
  
////////////////////////////////////METHODES
  void setThreshold( int newThreshold ){ // changer la valeur du seuil avec celle écrit entre parenthèse lorsque la méthode est appelée
    threshold = newThreshold;
  }

  void setMaxPoints(int newMaxPoints) { // changer la valeur maximum de points
    maxPoints = newMaxPoints;
  }
  
  void setColor(float red, float blue, float green){ // changer la couleur des cubes avec les variable red, blue, green
    fillColor = strokeColor = color(red, blue, green); // les contours et la surface est de la même couleur
  }

  boolean check(PVector point) { //création de la méthode vrai/faux (booléenne) appelé check, elle intervient sur le vecteur point
    boolean result = false; //par défaut le résultat est négatif

    if (point.x > center.x - largeur/2 && point.x < center.x + largeur/2) { //si la valeur en x du point analysé (c'est un point de profondeur définie dans la fenêtre programme principale)
    // n'est pas comprise entre la première valeur x du cube et la dernière
    //(si l'abscisse de point est inférieure à l'abscisse du centre du cube Moins la moitié de la largeur du cube (= la fin du cube en x)
    // ET si l'abscisse de point est inférieure à l'abscisse du centre du cube Plus la moitié de la largeur du cube (= le début du cube en x)
      if (point.y > center.y - hauteur/2 && point.y < center.y + hauteur/2) { //de même que pour x vérifier avec y 
        if (point.z > center.z - profondeur/2 && point.z < center.z + profondeur/2) { //de même que pour x vérifier avec z 
          result = true; // si le point de profondeur analysé est compris dans les valeurs x,y et z du cube, alors changer la variable result en vrai
          pointsIncluded++; //incrémenter pointIncluded de 1
        }
      }
    }

    return result; // réécrir le result, le résultat booléin.
  }

void apparaitre() {
    
    x=x+random(-3,3); //cepermet de faire bouger l'image 
    y=y+random(-3,3);
  
     image(visuel,x,y); // x et y sont définis dans les attributs
  
   // image(visuel,-900 ,-500);
    
  }
  
// void draw spécifique à la classe Hotpoint
  void draw() {
    pushMatrix(); // créer un cube avec un style qui lui est propre
    
      //placer le cube selon PVector center
      translate(center.x, center.y, center.z);
      
      // remplir le cube de couleur définie par fillColor, mais changer Alpha selon le pourcentage percentIncluded, 
      // il dépend de la présence ou non d'un point de profondeur depthPoint dans le cube
      fill(red(fillColor), blue(fillColor), green(fillColor), 255 * percentIncluded()); 

      //définir les contours selon les couleurs définies précédemment, toujours les laisser apparente (alpha = 255)
      stroke(red(strokeColor), blue(strokeColor), green(strokeColor), 255);
      
      // dessiner le cube selon size, une taille définie précedemment, box s'écrit aussi box(w,h,l)
      box(largeur,hauteur, profondeur); // Determiner la largeur, la taille et la profondeur de la box  
    popMatrix(); //fin de la démarquation de style
  }
  
  float percentIncluded() { //création de la valeur de pourcentage
  
    //map permet de changer le nom pointsIncluded
    return map(pointsIncluded, 0, maxPoints, 0, 1); // return permet de remplacer la valeur de pointIncluded dans le reste du code, il sera utilisé plus haut pour définir l'alpha du cube
  }


  boolean currentlyHit() {
    return pointsIncluded > threshold; // vérification : les points de la main inclus dans l'objet sont supérieur à ceux du seuil de l'objet (threshold), vrai ou faux ? (décrit par la boolean)
  }


  boolean isHit() {
    return currentlyHit() && !wasJustHit; // vérification si le cube est touché ou non 
  }

  void clear() {
    wasJustHit = currentlyHit(); // quand la main rentre dans l'objet, si la vérification : les points de la main inclus dans l'objet sont supérieur à ceux du seuil de l'objet (threshold),  
    pointsIncluded = 0; // alors, les points de la mains inclus dans l'objet sont remis à 0
  }
}

Fichier audio pour faire tourner le code

Télécharger les fichiers audios suivants, et les placer dans le dossier “data” de votre “sketch folder” :

  • IRCAM3.mp3
  • CS1.mp3
  • Reich.mp3
  • GtrOiseaux2.mp3
  • GuitC.mp3
  • AC.mp3
  • Nu1.mp3
  • HH3.mp3

——————————- A COMPLETER !!!!!!

wiki/projets/gaite/projet1.txt · Dernière modification: 2015/08/30 16:16 (modification externe)