Annonce

>>> Bienvenue sur codelab! >>> Première visite ? >>> quelques mots sur codelab //// une carte des membres//// (apéros) codelab


#1 2013-03-03 12:39:57 sélection d'objets avec la souris dans environnement 3D

Marty
membre
Date d'inscription: 2012-04-27
Messages: 143

sélection d'objets avec la souris dans environnement 3D



Hello !

J'avance dans mon projet.
Je crée un nouveau post pour avoir une problématique par post, ça me parait plus clair.

Note : je rappelle que je cherche à mettre tout ce qui suit en place sans librairie externe, le but étant aussi de me familiariser avec Processing et surtout de comprendre ce que je fais !

Petit historique :

- J'ai construit mon cube en 3D :
http://codelab.fr/4018

- J'ai ajouté la possibilité de tourner autour pour pouvoir sélectionner les éléments (sphères) :
http://codelab.fr/4023

Troisième étape, et c'est ce qui m'amène ici : ajouter la possibilité de sélectionner les éléments du cube avec la souris. J'ai réussi plus ou moins à mettre quelque chose en place, mais ça ne fonctionne pas comme je le souhaiterai. Le cahier des charges :

- lorsque la souris passe sur un élément (sphère) l'élément s'affiche en surbrillance (ici couleur rouge)
- lorsque l'on est sur un élément en surbrillance et qu'on clique (clic droit au gauche) l'élément est sélectionné. Un élément sélectionné est affiché en bleu.
- dans tous les autres cas les éléments sont à l'état initial (gris)

Dans mon code ci-dessous j'arrive à avoir un semblant de truc fonctionnel mais il n'y a que le premier élément qui semble actif (cube plus gros en bas à gauche) et cela ne fonctionne pas comme je le souhaites (tous les éléments sont activés et pas seulement l'élément sur lequel est la souris)

Je pense qu'il y a encore et toujours un problème de positionnement de repère dans l'espace, j'ai vraiment du mal avec ça ! smile

J'ai essayé d'être clair dans le code en commentant proprement.
Si quelqu'un à une idée de l'origine du problème (c'est le cas de le dire !) smile

Led[] ledCube = new Led[64];

// detection tollerance for mouse hovering led
int tollerance = 5;
float ledPosArray[][]; // coordinates of leds on screen (see method for use)
int cubeSize = 150;

// widht and height of window
int wWidth = 640;
int wHeight = 480;

// scene center
int cx = wWidth/2;
int cy = wHeight/2;
int cz = -cubeSize/2;

// camera positions
float camEyeX = 0;
float camEyeY = 0;
float camEyeZ = 0;
float viewX = 0;
float viewY = 0;
float viewZ = 0;
float camUpX = 0;
float camUpY = 1;
float camUpZ = 0;

// Polar coordinates for camera
float theta = 0;      
float phi = 90;       
float rho = 300;   //distance from cam to point of view

void setup(){
  int c = 0; // counter = number of leds
  ledPosArray = new float[64][2]; // init screen coordinates array
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      for (int k = 0; k < 4; k++) {
        ledCube[c] = new Led(j,-i,-k, false, 120, col, i+1);
        c++;
      }
    }
  }
  size(wWidth,wHeight, P3D);
}

void draw(){
  background(0);
  pointLight(150,255,255,200,200,200);
  noLights();
  noStroke();
  noSmooth();
  fill(160);
  drawAxis(); // debug
  updateCamPosition();
  camera(camEyeX,camEyeY,camEyeZ,viewX,viewY,viewZ,camUpX,camUpY,camUpZ);
  translate(-(cubeSize / 2), (cubeSize / 2), (cubeSize / 2));
  updateArray(); // update coordinates of spheres on screen for mouse hover detection
  box(8); // debug : identifies start point for the construction of the cube
  drawCube();
}

// One Led (sphere) of the cube and its properties
class Led {
  int x;
  int y;
  int z;
  boolean isOn; // true when led is lit
  boolean isHover = false; // true when mouse hover
  color ledColor;
  int activeCol; // columns 1 to 16 (in dev, not used yet)
  int activePlan; // number of cube active plan where the Led belongs (1 low level to 4 high level) (in dev, not used yet)

// constructor
  Led (int xPos, int yPos, int zPos, boolean state, color col, int column, int line) {
    x = xPos;
    y = yPos;
    z = zPos;
    isOn = state; // Led On/Off
    ledColor = col;
    activeCol = column; // position of LED in cube (x and z axis) (in dev, not used yet)
    activePlan = line; // position of LED in cube (plane = y axis) (in dev, not used yet)
  }
  
// Led display method  
  void display() {
    pushMatrix();
    translate(x * (cubeSize / 3), y * (cubeSize / 3), z * (cubeSize / 3));
    if (isOn) 
    {
      fill(color(0,0,255));
    }
    else if (isHover)
    {
      fill(color(255,0,0));
    }
    else 
    {
      fill(color(166,166,166));
    }
    box(4);
    popMatrix();
  }
}

// for debug : draw axis x (green), y (blue) and z (red)
void drawAxis(){
  stroke(0,255,0);
  line(0,0,0,100,0,0);
  stroke(0,0,255);
  line(0,0,0,0,100,0);
  stroke(255,0,0);
  line(0,0,0,0,0,-100);
  noStroke();
}

// draw cube with spheres
void drawCube() {
   for (int i = 0; i < 64; i++) {
    ledCube[i].display();
  } 
}

// calculate x and y screen : list[led_number][coordinates] with coordinates = 0 (x) and 1 (y)
void updateArray(){
 for (int i = 0; i < 64; i++) {
   ledPosArray[i][0] = (int)screenX(ledCube[i].x,ledCube[i].y,ledCube[i].z); 
   ledPosArray[i][1] = (int)screenY(ledCube[i].x,ledCube[i].y,ledCube[i].z); 
 } 
}

// update position of camera moved with mouse click and drag
void updateCamPosition(){
    camEyeX = rho * cos(radians(theta)) * cos(radians(phi));
    camEyeY = rho * sin(radians(theta));
    camEyeZ = rho * cos(radians(theta)) * sin(radians(phi));
    
      //Prevent flipping if camera moves past top or bottom of cube
      if ((theta > 90.0 && theta < 270.0) || (theta < -90.0 && theta > -270.0))
    {
      camUpY = -1.0;
    }
    else
    {
      camUpY = 1.0;
    }
}

// colorize spheres when mouse hover or selected
void mousePressed()
{
  for (int i=0 ; i < 64 ; i++) {
  if (ledCube[i].isHover && !ledCube[i].isOn) ledCube[i].isOn = true;
  else if (ledCube[i].isHover && ledCube[i].isOn) ledCube[i].isOn = false;
  }

}

// rotate camera whith mouse click and drag
void mouseDragged(){
  if (mouseButton == LEFT){
    theta = theta + (pmouseY - mouseY);
    phi = phi - (pmouseX - mouseX);
  }
  if (mouseButton == RIGHT){
    rho = rho - (pmouseY - mouseY);    
  }
}

// detects mouse hover and change state
void mouseMoved()
{
  for (int i=0 ; i < 64 ; i++)
  {
    if (mouseX >= ledPosArray[i][0] - tollerance && mouseX <= ledPosArray[i][0] + tollerance && mouseY >= ledPosArray[i][1] - tollerance && mouseY <= ledPosArray[i][1] + tollerance)
    //if (mouseX >= ledCube[i].x - tollerance && mouseX <= ledCube[i].x + tollerance && mouseY >= ledCube[i].y + tollerance && mouseY <= ledCube[i].y - tollerance)
    {
      ledCube[i].isHover = true;
    }
    else
      ledCube[i].isHover = false;
  }
}

Dernière modification par Marty (2013-03-03 12:45:00)

Hors ligne

 

#2 2013-03-03 14:00:28 Re : sélection d'objets avec la souris dans environnement 3D

Mushussu
membre
Lieu: Orléans
Date d'inscription: 2012-05-24
Messages: 802

Re: sélection d'objets avec la souris dans environnement 3D



Bonjour,

Suite à ta proposition initiale, j'avais écrit ce bout de code :

Led[] ledCube = new Led[64];

int cubeSize = 150;

int wWidth = 640;
int wHeight = 480;

//camera positions
float camEyeX = 0;
float camEyeY = 0;
float camEyeZ = 0;
float viewX = 0;
float viewY = 0;
float viewZ = 0;
float camUpX = 0;
float camUpY = 1;
float camUpZ = 0;

//Polar coordinates
float theta = 0.01;      
float phi = 90;       
float rho = 300;   //distance from cam to point of view

void setup() {
  size(wWidth, wHeight, P3D);
  int c = 0;
  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      for (int k = 0; k < 4; k++) {
        ledCube[c] = new Led(j, -i, -k, false, 120);
        c++;
      }
    }
  }
  ledCube[0].bColor = color(255, 255, 255); 
  ledCube[12].bColor = color(255, 0, 0); 
  ledCube[48].bColor = color(0, 255, 0); 
  ledCube[60].bColor = color(0, 0, 255); 
  noLights();
  noStroke();
  noSmooth();
}

void draw() {
  background(0);
  //pointLight(150, 255, 255, 200, 200, 200);
  testCube();

  fill(160);
  drawAxis();
  updateCamPosition();
  camera(camEyeX, camEyeY, camEyeZ, viewX, viewY, viewZ, camUpX, camUpY, camUpZ);
  translate(-(cubeSize / 2), (cubeSize / 2), (cubeSize / 2));
  drawCube();
}


void testCube() {
  pushMatrix();
  translate(-(cubeSize / 2), (cubeSize / 2), (cubeSize / 2));
  for (int i = 0; i < 64; i++) {
    ledCube[i].display(64 + i * 2);
  }  
  if (mousePressed) {
    int c = ((int)brightness(get(mouseX, mouseY)) - 64) / 2;
    if ((c >= 0) && ( c < 64)) {
      ledCube[c].setEtat();
    }
  }
  popMatrix();
}

class Led {
  int x;
  int y;
  int z;
  boolean isOn;
  color bColor;

  Led (int xPos, int yPos, int zPos, boolean state, color col) {
    x = xPos;
    y = yPos;
    z = zPos;
    isOn = state;
    bColor = col;
  }

  void display() {
    pushMatrix();
    translate(x * (cubeSize / 3), y * (cubeSize / 3), z * (cubeSize / 3));
    if (isOn) {
      fill(255, 0, 0);
    }
    else {
      fill(bColor);
    }
    box(3);
    popMatrix();
  }

  void display(int niveauGris) {
    pushMatrix();
    translate(x * (cubeSize / 3), y * (cubeSize / 3), z * (cubeSize / 3));
    fill(niveauGris);
    box(3);
    popMatrix();
  }

  void setEtat() {
    isOn = !isOn;
  }
}

void drawAxis() {
  stroke(0, 255, 0);
  line(0, 0, 0, 100, 0, 0);
  stroke(0, 0, 255);
  line(0, 0, 0, 0, 100, 0);
  stroke(255, 0, 0);
  line(0, 0, 0, 0, 0, -100);
  noStroke();
}

void drawCube() {
  for (int i = 0; i < 64; i++) {
    ledCube[i].display();
  }
}


void updateCamPosition() {
  camEyeX = rho * cos(radians(theta)) * cos(radians(phi));
  camEyeY = rho * sin(radians(theta)) ;
  camEyeZ = rho * cos(radians(theta)) * sin(radians(phi));

  //Prevent flipping if camera moves past top or bottom of cube
  if ((theta > 90.0 && theta < 270.0) || (theta < -90.0 && theta > -270.0))
  {
    camUpY = -1.0;
  }
  else
  {
    camUpY = 1.0;
  }
}

void mouseDragged() {
  if (mouseButton == LEFT) {
    theta = theta + (pmouseY - mouseY);
    println(theta);
    phi = phi - (pmouseX - mouseX);
  }
  if (mouseButton == RIGHT) {
    rho = rho - (pmouseY - mouseY);
  }
}

Il permet de cliquer sur les cubes. Il faudrait l'améliorer et mette une petite temporisation pour éviter le déselectionnement rapide.

Je regarderais ton code lorsque j'aurais un peu plus de temps.

Dernière modification par Mushussu (2013-03-03 14:01:11)

Hors ligne

 

#3 2013-03-03 14:21:17 Re : sélection d'objets avec la souris dans environnement 3D

Marty
membre
Date d'inscription: 2012-04-27
Messages: 143

Re: sélection d'objets avec la souris dans environnement 3D



Salut,

Merci pour le code. Visiblement on ne passe pas tout à fait par la même logique. Tu fais une détection par niveau de gris ?

Je remarque en tout cas que tu fais un changement d'origine dans tes manipulations, ce que je ne comprend toujours pas... smile

je scrute ton code pour essayer de voir la démarche.

Hors ligne

 

#4 2013-03-03 23:07:30 Re : sélection d'objets avec la souris dans environnement 3D

Mushussu
membre
Lieu: Orléans
Date d'inscription: 2012-05-24
Messages: 802

Re: sélection d'objets avec la souris dans environnement 3D



Attention dans ton calcul de la projection des coordonnées, tu ne prenais pas les coordonnées d'affichage. Dans le tableau ledCube les coordonnées sont celles du cube par rapport aux autres de 0 à 3. C'est dans l'affichage que l'on transforme en coordonnées d'affichage. Donc la fonction est la suivante :

void updateArray(){
 for (int i = 0; i < 64; i++) {
    ledPosArray[i][0] = (int)screenX(ledCube[i].x * (cubeSize / 3), ledCube[i].y * (cubeSize / 3), ledCube[i].z * (cubeSize / 3) ); 
    ledPosArray[i][1] = (int)screenY(ledCube[i].x * (cubeSize / 3), ledCube[i].y * (cubeSize / 3), ledCube[i].z * (cubeSize / 3) );  
 } 
}

Hors ligne

 

#5 2013-03-04 08:07:53 Re : sélection d'objets avec la souris dans environnement 3D

cgiles
membre
Lieu: Est de la France
Date d'inscription: 2005-05-25
Messages: 329

Re: sélection d'objets avec la souris dans environnement 3D



as tu regardé comment marchais le picking ?

Hors ligne

 

#6 2013-03-04 08:45:54 Re : sélection d'objets avec la souris dans environnement 3D

Mushussu
membre
Lieu: Orléans
Date d'inscription: 2012-05-24
Messages: 802

Re: sélection d'objets avec la souris dans environnement 3D



J'ai utilisé cette méthode de picking dans le bout de code proposé. Le voici avec le survol des cubes actif et la temporisation :

Si il y a des passages abscons, dit le moi.

Dernière modification par Mushussu (2013-03-04 08:53:10)

Hors ligne

 

#7 2013-03-04 12:14:33 Re : sélection d'objets avec la souris dans environnement 3D

Marty
membre
Date d'inscription: 2012-04-27
Messages: 143

Re: sélection d'objets avec la souris dans environnement 3D



Mushussu a écrit:

Attention dans ton calcul de la projection des coordonnées, tu ne prenais pas les coordonnées d'affichage. Dans le tableau ledCube les coordonnées sont celles du cube par rapport aux autres de 0 à 3. C'est dans l'affichage que l'on transforme en coordonnées d'affichage.

Elémentaire mon cher Watson !!
Tellement évident quand on vous le dit smile Merci en tout cas pour la piste encore une fois.

@cgiles : oui j'ai regardé la librairie que tu m'avais conseillé et le principe. Ca pourra me servir pour un autre projet c'est cool. Mais dans ce cas ici j'ai étudié ma problématique e j'ai suivi ma logique, le résultat est un traitement différent et ça ne me semble pas si mal smile

Le Picking c'est effectivement l'approche qu'avais eue Mushussu dans sa solution précédente. J'ai testé pour voir, cela fonctionne aussi cela dit je note plus de lourdeur dans l'utilisation (affichage) par rapport à ma solution. Dans mon cas, le cube et la détection/sélection des éléments est beaucoup plus réactive, par le picking la sensibilité est moindre et ça "lag" légèrement. La technique est plus gourmande en ressources ? ou peut être nécessite un peu d'optimisation dans le code, j'avoue je n'ai pas regardé dans les détails.

Merci à vous en tout cas.

Hors ligne

 

fil rss de cette discussion : rss

Pied de page des forums

Powered by FluxBB

codelab, graphisme & code : emoc / 2008-2025