Picking with Processing

Sélectionner un objet dans un espace 3D : explications - demonstration - code source

La classe Cube.

class Cube {
  
  // variables
  int id;          // identifiant
  int x, y, z, w;  // position (x, y, z) et taille (w)
  color c;         // couleur dans la scène
  
  // constructeur
  public Cube(int id, int x, int y, int z, int w) {
    this.id = id;
    this.x = x; this.y = y; this.z = z; this.w = w;
    c = color(random(255), 250, 50);
  }
  
  // changement de couleur
  public void changeColor() {
    int r = (int)red(c);
    int g = (int)green(c);
    int b = (int)blue(c);
    c = color(r, 255 - g, b);
  }
  
  // affichage du cube à l'écran
  public void display(PGraphics ecran) {
    ecran.fill(c);
    drawCube(ecran);
  }
  
  // dessin du cube dans le buffer
  public void drawBuffer(PGraphics buffer) {
    color idColor = getColor(id);
    buffer.fill(idColor);
    drawCube(buffer);
  }
  
  private void drawCube(PGraphics g) {
    g.pushMatrix();
      g.translate(x, y, z);
      g.box(w);
    g.popMatrix();
  }
  
}

Initialisation de l'application.

import processing.opengl.*;

PGraphics buffer;   // buffer
Cube[] cubes;       // cubes de la scène

float a = 0;        // angle pour la rotation de la scène

void setup() {
  
  // on utilise OPENGL pour l'affichage principal
  size(200, 200, OPENGL);
  
  // le buffer est créé aux dimensions de la fenêtre
  buffer = createGraphics(width, height, P3D);
  
  // création des cubes à des positions aléatoires
  cubes = new Cube[10];
  for (int i = 0; i < cubes.length; i++) {
    cubes[i] = new Cube(
      i,                      // identifiant
      -15 + (int)random(30),  // position x
      -15 + (int)random(30),  // position y
      -15 + (int)random(30),  // position z
      5 + (int)random(15)     // taille
    );
  }
  
}

Dessin de la scène à chaque frame.

void draw() {
  
  background(255);
  
  camera(-20, -20, 50, 0, 0, 0, 0, 1, 0);
  
  rotateY(a);
  
  lights();
  for (int i = 0; i < cubes.length; i++) {
    cubes[i].display(this.g);
  }
  
  a += 0.002;
  if (a > TWO_PI) a -= TWO_PI;
  
}

Gestion du clic souris sur un objet.

void mouseClicked() {
  
  // dessine la scène épurée dans le buffer
  buffer.beginDraw();
  
  // la couleur de fond du buffer ne doit correspondre à aucun
  // objet : on lui affecte la couleur de l'identifiant -1
  buffer.background(getColor(-1));
  buffer.noStroke();
  
  buffer.camera(-20, -20, 50, 0, 0, 0, 0, 1, 0);
  buffer.rotateY(a);
  for (int i = 0; i < cubes.length; i++) {
    cubes[i].drawBuffer(buffer);
  }
  
  buffer.endDraw();
  
  // récupère la couleur du pixel sous la souris
  color pick = buffer.get(mouseX, mouseY);
  // récupère l'identifiant de l'objet
  int id = getId(pick);
  // s'il ne s'agit pas de la couleur du fond (id = -1)
  if (id >= 0) {
    // change la couleur du cube cliqué
    cubes[id].changeColor();
  }
  
}

Correspondance identifiant - couleur dans le buffer.

// l'identifiant 0 renvoie la couleur -2, etc.
color getColor(int id) {
  return -(id + 2);
}

// la couleur -2 renvoie l'identifiant 0, etc.
int getId(color c) {
  return -(c + 2);
}