Bonjour a tous,
Je me suis mis (sérieusement) Irrlicht il y a peu, et je ne parviens pas à réaliser un picking "correctement".
D'abord, je ne savais pas comment faire, et où chercher. Puis j'ai appris le terme de picking, collisions, etc...
Ensuite, j'ai eu la fonction GetSceneNodeFromScreenCoordinatesBB, qui a commencé par me sélectionner un objet si et seulement si le curseur se superposait parfaitement sur le centre. Erreur stupide de ma part autre part dans le code.
Il y a eu aussi le coup du vide sélectionné par le getSceneNodeFromCameraBB().
Finalement, j'ai un picking qui fonctionne uniquement si le cube n'est pas positionné par l'utilisateur (ni par le constructeur, ni par la fonction setPosition());
Je n'ai pas encore essayé les TriangleSelector, a vrai dire, les exemples de codes que j'ai vu dessus m'ont... un peu effrayé.
Bref, j'aimerais savoir si quelqu'un pourrait :
- Me donner un exemple de picking qui fonctionne... (bien expliqué commenté, etc...)
- Soit m'expliquer le fonctionnement du TriangleSelector et me confirmer que cette solution est bien adéquate (je sais à moitié ce que ça fait).
- Soit m'expliquer et corriger mon bug; si vous avez besoin du code n'hésitez pas, c'est juste que je pense avoir été clair : je crée un mesh, sélectionné par Get...CameraBB(), qui refuse d'être selectionné si positionné par setPosition().
Merci d'avance pour vos réponses !
Hors ligne
Bon, pour mon problème, apparemment, la scène créerait un node géant et invisible qui engloberait tout, et serait omniprésent.
Il peut-être sélectionné, et lorsque le cube change de position, il est placé derrière ce node de vide, et c'est le node en question qui est pické.
Quelqu'un sait il quel est le nom de ce node (ce n'est pas 'RootSceneNode', déjà essayé), afin que je puisse empêcher le programme de le sélectionner ?
Hors ligne
Finalement, après avoir supprimé une caméra obsolète, je me suis rendu compte que la caméra se sélectionnait toute seule. Le problème (courant) est donc résolu.
Il me reste une petite question : savez vous comment "picker" une face de l'objet ?
Merci à l'avance pour vos réponses !
Hors ligne
Je te colle vite fait une fonction à la suite, les commetaires devraient suffir, la récupération du node et du maillage sont dans un ordre qui me va bien, tu peux évidemment la changer pour toi.
MVector3d GrIrrlicht::findPoint3D_withScreenPos(const MVector2d& cursor,ISceneNode* meshNode,triangle3df* triangleImpacted) { ISceneCollisionManager* collision = m_device->getSceneManager()->getSceneCollisionManager(); ISceneManager* manager = m_device->getSceneManager(); vector3df outCollisionPoint; // Sortie: coordonnées du point de collision. triangle3df outTriangle; // Sortie: coordonnées du triangle de collision. // On récupère la ligne de projection du curseur de souris par rapport au champ de vision de la caméra. line3df line = collision->getRayFromScreenCoordinates( vector2d<s32>( (s32)cursor.x,(s32)cursor.y) , m_cameraFPS ); // Là, tu récupères le ITriangleSelector de ton maillage, son pointeur peut être // stocké dans le node pour un accès plus facile. ITriangleSelector* triangleSelector = meshNode->getTriangleSelector(); const ISceneNode* outNode; // Ce premier "triangleSelector " correspond à la bounding box de ton objet, // on fait ce premier test pour augmenter les performances, une boite ne // contient que quelques triangles de maillages. if(triangleSelector != 0) if(collision->getCollisionPoint(line,triangleSelector,outCollisionPoint,outTriangle,outNode) == true) { IMesh* mesh = //Là, tu récupères le maillage à proprement dit avec ta propre technique. if(mesh!=0) { // Ce second "triangleSelector" correspond au maillage exacte de ton objet, // donc on a la possibilité de récupérer le point et le triangle de collision précisément. triangleSelector = manager->createTriangleSelector(mesh,meshNode); collision->getCollisionPoint(line,triangleSelector,outCollisionPoint,outTriangle,outNode); triangleSelector->drop(); if(triangleImpacted != 0) *triangleImpacted = outTriangle; } } // Renvoi les coordonnées x, y et Z du point de collision trouvé sur le mailage. return irrToVector(outCollisionPoint); }
Bon courage.
Dernière modification par Gehogor (02-08-2012 20:10:45)
Hors ligne
Merci beaucoup Gehogor pour ta réponse et tes explications; cependant, je ne comprends pas tout : les initialisations des variables node, mesh et triangleSeletor ont été remplacées par des commentaires.
Bien qu'ils m'expliquent un peu mieux comment on s'y prend pour utiliser un triangleSelector, j'aimerais que tu me donnes un exemple plus concret, et que tu donnes les constructeurs avec leurs paramètres, au moins pour le triangleSelector. Je peux br aller chercher dans la doc mais je pien sûréfère que l'on m'explique.
Merci en tout ca !
Hors ligne
Je te conseille de regarder la doc pour plus d'info sur chacune des méthodes suivantes. Il est vrai que la doc d'Irrlicht est vraiment trop insuffisante, surtout comparée à celle de Qt que j'utilise souvent !
Alors, tu crées un maillage tout d'abord:
IMesh* irrMesh = manager->getMesh( "MonSuperFichier3d.3ds" );
Après, tu associes un nœud "node" à ce maillage afin de pouvoir lui faire subir des transformations comme les rotations, translations, échelle...
ImeshSceneNode* meshNode = manager->addMeshSceneNode(irrMesh,0,-1,
pos.getTranslation(),
pos.getRotationDegrees(),
GrIrrlicht::vectorToIrr( mesh3D->scale() ));
if( meshNode == 0 )
return;
Après, tu crées le "triangleSelector" qui représente la "bounding box" de notre maillage.
ISceneManager* manager = m_engine->device()->getSceneManager(); ITriangleSelector* triangleSelector = manager->createTriangleSelectorFromBoundingBox(meshNode); if(triangleSelector == 0) return; meshNode->setTriangleSelector(triangleSelector);
De cette manière, chaque "node" aura stocké son propre pointeur de "triangleSelector" pour d'éventuelles détections.
Et là, tu peux reprendre le code du dessus pour récupérer ton "triangleSelector".
Par contre, il faut bien comprendre que cette technique impose de parcourir tous les "nodes" pour tester s'il y a collision ou non. D'un point de vue calcul c'est très rapide car nous testons dans un premier temps les "triangleSelector" des "bouding box" qui représentent juste des boites, soit 6 cotés x 2 triangles par boites (12 triangles en tout).
C'est pourquoi dans le code du dessus je teste d'abord la collision avec les "bounding box" puis, s'il y a collision, je teste plus précisément avec le maillage complet fraichement convertit en "triangleSelector".
J'espère que ça ira.
Hors ligne
Je pense que je devrai pouvoir m'en sortir...
Merci beaucoup !
Hors ligne