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 !
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 !)
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
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
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...
je scrute ton code pour essayer de voir la démarche.
Hors ligne
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
as tu regardé comment marchais le picking ?
Hors ligne
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
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 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
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
Pages: 1