Bonjour,
J'ai un objet (visage) composé de n triangles.
Je cherche a pouvoir selectionner un de ces triangles avec un clic de souris, pour par exemple lui changer sa couleur.
Comment peut on s'y prendre ?
Merci bcp pr tte aide
Bonjour,
J'ai un objet (visage) composé de n triangles.
Je cherche a pouvoir selectionner un de ces triangles avec un clic de souris, pour par exemple lui changer sa couleur.
Comment peut on s'y prendre ?
Merci bcp pr tte aide
je suis juste un debutant...
il doit sans doute y avoir plus simple, mais comme personne ne repond...
Tu peux recuperer les coordonnées du point que tu clic à l'ecran.
En fonction du type de projection que tu utilise, tu en deduit une droite (la projection de cette droite est le point que tu as cliqué ).
Il faut ensuite calculer les intersections entre ta droite et tous les triangles...
hum... si qq'un connais une methode plus rapide...
Bonjour, une méthode simple et rapide:
Dessine dans un buffer en mémoire tes objets en affectant une couleur par objet, et en prenant soin de désactiver blending, lighting et tout le tremblement.
Lit la couleur du pixel sous la souris avec glReadPixels() et tu peut retrouver l'objet sélectionné.
Limitations : tu ne peut sélectionner que l'objet le plus près ( à moins de sélectionner récursivement ), et si la carte graphique force l'antialiasing, la selection peut etre erronée sur le bord des objets.
Merci, c'est une pas bete idée !
Apres, va falloir que je trouve une methode pr m'y retrouver ds mes couleurs (g 9000 triangles a differencier...), ms c jouable.
Quant au fait de ne selectionner que le triangle en 1er, c'est tt ce que je demande.
Pour ta solution, c'est ce que le principe du raytracing m'avait fait penser au debut, mais elle est bien trop lourde : deja pr avoir la droite, fo avoir 2 pts, le premier etant les coordonnees de la camera, ce qui est pas si simple que ca a avoir, surtt en combinant les glRotated ou glTranslate, dans les 2 modes : PROJECTION et MODELVIEW. Et le 2e fo le convertir : des coordonnees de l'ecran en coordonnees reelles. Apres c faisable
merci de ton idée
Salut,
la méthode générale pour sélectionner un objet à la souris est le "picking".
En gros ça consiste à dessiner chaque objet en leur donnant un nom différent (un nombre identifiant) en mode GL_SELECT (le mode par défaut est GL_RENDER). OpenGL va te renvoyer les identifiants des objets (y compris les objets cachés) qui sont placés sous le curseur de la souris, avec une valeur de profondeur pour déterminer quel objet est le plus proche de l'oeil.
Je te conseille de chercher de la doc sur ces fonctions :
glRenderMode : change le mode GL_SELECT/GL_RENDER
gluPickMatrix : définit la zone de clic (dans ton cas 1 pixel devrait suffir)
glSelectBuffer : spécifie le buffer qui recevra les id des objets cliqués
glInitNames
glPushName
glPopName
Un exemple :
Voici une fonction qui te permet d'afficher le contenu du select buffer (j'avoue que c'est assez compliqué...) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 //clic souris en (x, y) void select(int x, int y) { unsigned int selectBuffer[BUFFERSIZE]; int hits; int viewport[4]; float proj[16]; float mod[16]; glGetIntegerv( GL_VIEWPORT, viewport ); glGetFloatv( GL_PROJECTION_MATRIX, proj ); glGetFloatv( GL_MODELVIEW_MATRIX, mod ); glSelectBuffer( BUFFERSIZE, selectBuffer ); glRenderMode( GL_SELECT ); glInitNames(); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); //zone de clic de 1x1 pixel gluPickMatrix( (float)(x), (float)(y), 1.0f, 1.0f, viewport ); glMultMatrixd( proj ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glMultMatrixd( mod ); //dessin de la scène avec les noms des objets drawNamedScene(); glFlush(); //récup du nombre d'objets sous le curseur et remplissage du select buffer hits = glRenderMode( GL_RENDER ); //manipulation du select buffer pour déterminer quel objet est le plus proche processHits( hits, selectBuffer ); } void drawNamedScene() { for( int i = 0; i<nbTriangles; i++ ) { glPushName( i ); ... //dessin triangle i ... glPopName(); } }
J'espère que c'est assez clair :)...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 void displaySelectBuffer( int hits, unsigned int buffer[] ) { cout<<"nombre de hits : "<<hits<<endl; if( hits == 0 ) return; unsigned int i, j, nbNoms, *ptr, zmin; ptr = buffer; for(i=0; i<hits; i++) { nbNoms = ptr[0]; zmin = ptr[1]; cout<<"hit "<<i<<" :"<<endl; cout<<"nombre de noms dans la pile lors du hit : "<<nbNoms<<"(adresse : "<<&ptr[0]<<")"<<endl; cout<<"zmin : "<<zmin<<endl; cout<<"contenu de la pile lors du hit :"<<endl; for(j=0;j<nbNoms;j++) { cout<<ptr[3+j]<<endl; } cout<<endl; ptr += (3+nbNoms); //hit suivant } }
A+
Ouais c clair El Brujo, c'est d'ailleurs la méthode la plus propre jcrois qu'on puisse trouver.
Le problème c'est que c valable que pour un nb limité d'objets (ds mon cas g l'impression que c aux alentours de 600-700). Or j'ai 9000 triangles à considerer comme objet
La méthode que j'ai trouvée pour faire ca, c de :
- utiliser le mode : glRenderMode(GL_FEEDBACK), qui permet de récupérer les coordonnées des triangles, coordonnées compatibles avec le repère de la fenêtre
- pour chaque triangle, chercher a quels pixels ils correspondent (normalement c trouvable sur le net)
- j'obtiens alors une table[800][600] qui me permet de savoir a quel triangle correspond quel pixel
Voilà, j'espere que tu m'auras compris, j'ai parfois moi meme du mal a me comprendre , mais la solution est en soi assez simple.
Merci pr ta reponse !!
Si tu ve un exemple d'utilisation, je pourrais le poster d'ici peu : qd j'aurais trouvé comment calculer pour un triangle donné quels pixels il contient.
je ne comprends pas trop l'histoire de la limitation du nombre d'objets dans le cas du GL_SELECT...
Je ne sais pas comment tu as procédé, mais il faut qu'à chaque glPushName corresponde un glPopName immédiatement après le dessin d'un triangle, sinon il y a stack overflow.
Pour éviter de faire des push/pop de tous les côtés, il est possible d'utiliser glLoadName.
Bon courage pour le feedback, ça me semble bien compliqué pour ce que tu veux faire :)
A+
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager