Historique des modifications - Message

Message #6542

Sujet: Comment sélectionner un objet dans un objet ?


Type Date Auteur Contenu
Dernière modification 20-09-2009 07:19:28 Gehogor
Bon, comme promis, je vais faire un petit bilan sur l'intitulé de cette discussion, à savoir, comment sélectionner un objet dans un objet.


Tout d'abord pour faire simple, j'ai déclaré dans mon .h un tableau de ITriangleSelector:

 ITriangleSelector*  m_TriangleSelector[NB_MAX_OBJETS_3D];	// Objet Irrlicht représentant les objets 3D en triangle 3D
int m_NbObjectForCollision;             // Nombre d'objet détecté dans le scène 3D dont l'identifiant est différent de -1
int m_Node_ID[NB_MAX_OBJETS_3D];        // Représentation des identifiants des objets 3D classés

Pour des raisons particulières, j'ai créé un tableau statique, il est clair qu'il est préférable de faire une liste dynamique moins gourmande en mémoire.
Ensuite, j'ai créé une fonction qui scanne une grande fourchette d'ID pour récupérer tous les nodes présents dans la scène dont l'ID est différent de-1:

void QIrrlicht::ComputeCollision()
{
	m_NbObjectForCollision=0;
    if(m_Smgr->getSceneNodeFromId(-1) != NULL){
            printf("Il y a au moins un objet 3D avec l'identifiant à -1");
            printf("Si l'identifiant d'un objet 3D est à -1, il ne sera pas pris en compte pour la gestion de la sélection");
	}

    for(int i=0;i<NB_MAX_OBJETS_3D;i++){					// NB_MAX_OBJETS_3D fixé à 2000
        ISceneNode* Node = m_Smgr->getSceneNodeFromId(i);	// Récupération des nodes en fonction de leur ID
        if(Node != NULL){
            m_TriangleSelector[m_NbObjectForCollision] = m_Smgr->createTriangleSelectorFromBoundingBox(Node);
            // On attache au node un ITrangleSelector pour faire de la collision Volume/Volume par exemple mais inutile pour notre cas.
            Node->setTriangleSelector(m_TriangleSelector[m_NbObjectForCollision]);
            m_Node_ID[m_NbObjectForCollision] = i;    		// On peut récupérer cette valeur grâce à "int* getNode_ID();"	
			m_NbObjectForCollision++;	            		// On peut récupérer cette valeur grâce à "int getNbObjectForCollision()"			
		}
    }
 }
 
int* QIrrlicht::getNode_ID()	// Récupération du tableau des IDs des nodes classés
{
    return m_Node_ID;
}
int QIrrlicht::getNbObjectForCollision()	// Récupération du nombre d'objet détecté pour de la sélection ou de la collision
{
    return m_NbObjectForCollision;
}

Il faut appeller cette méthode après le chargement d'une scène irrEdit par exemple ou dès l'ajout d'un nouvel élément pour qu'il soit pris en compte.

Maintenant, la dernière fonction, celle qui retourne une liste de "ISceneNode*" en fonction de la position de la caméra (ici "m_Camera_FPS", variable membre qui est ma caméra) et celle de la souris également (ici le paramètre "pos"). Ma liste est en fait une QList car j'utilise Qt pour ce projet.
Petite note: On pourrait très clairement passé le paramètre de la caméra également pour rendre plus portable cette petite méthode.

QList<ISceneNode*> QIrrlicht::findNodeWithScreenPos(position2d<s32> pos)
{
    vector3df outCollisionPoint;
    triangle3df outTriangle;
    QList<ISceneNode*> listSceneNode;               // Liste locale qui sera retournée
    line3df line = m_Collision->getRayFromScreenCoordinates(pos,m_Camera_FPS);

    for(int i=0;i<getNbObjectForCollision();i++)    // Permet de récupérer le nombre d'objet pris en compte et transformer en "TriangleSelector"
    {   // S'il y a une collison entre une ligne (projection du curseur de la souris sur le monde en fonction de ma caméra) et un objet 3d
        if(m_Collision->getCollisionPoint(line,getTriangleSelector()[i],outCollisionPoint,outTriangle) == true)
        {
            ISceneNode* node = m_Smgr->getSceneNodeFromId(getNode_ID()[i]);   // On récupère le bon ID venant de l'indice "i"
            if(node != NULL) listSceneNode.append(node);                      // Ajout du node trouvé dans une liste
        }
    }
    return listSceneNode;                           // On retourne la liste de node
}

Et voilà, après on peut appeler cette méthode dans le gestionnaire des évènements d'Irrlicht par exemple et afficher une boundingbox autour des nodes trouvés....

Je sais que c'est très simple, mais ça peut toujours aider. Bonne soirée à vous.
Création du message 19-06-2009 20:14:45 Gehogor
Bon, comme promis, je vais faire un petit bilan sur l'intitulé de cette discussion, à savoir, comment sélectionner un objet dans un objet.


Tout d'abord pour faire simple, j'ai déclaré dans mon .h un tableau de ITriangleSelector:

 ITriangleSelector*  m_TriangleSelector[NB_MAX_OBJETS_3D];	// Objet Irrlicht représentant les objets 3D en triangle 3D
int m_NbObjectForCollision;             // Nombre d'objet détecté dans le scène 3D dont l'identifiant est différent de -1
int m_Node_ID[NB_MAX_OBJETS_3D];        // Représentation des identifiants des objets 3D classés

Pour des raisons particulières, j'ai créé un tableau statique, il est clair qu'il est préférable de faire une liste dynamique moins gourmande en mémoire.
Ensuite, j'ai créé une fonction qui scanne une grande fourchette d'ID pour récupérer tous les nodes présents dans la scène dont l'ID est différent de-1:

void QIrrlicht::ComputeCollision()
{
	m_NbObjectForCollision=0;
    if(m_Smgr->getSceneNodeFromId(-1) != NULL){
            printf("Il y a au moins un objet 3D avec l'identifiant à -1");
            printf("Si l'identifiant d'un objet 3D est à -1, il ne sera pas pris en compte pour la gestion de la sélection");
	}

    for(int i=0;i<NB_MAX_OBJETS_3D;i++){					// NB_MAX_OBJETS_3D fixé à 2000
        ISceneNode* Node = m_Smgr->getSceneNodeFromId(i);	// Récupération des nodes en fonction de leur ID
        if(Node != NULL){
            m_TriangleSelector[m_NbObjectForCollision] = m_Smgr->createTriangleSelectorFromBoundingBox(Node);
            // On attache au node un ITrangleSelector pour faire de la collision Volume/Volume par exemple mais inutile pour notre cas.
            Node->setTriangleSelector(m_TriangleSelector[m_NbObjectForCollision]);
            m_Node_ID[m_NbObjectForCollision] = i;    		// On peut récupérer cette valeur grâce à "int* getNode_ID();"	
			m_NbObjectForCollision++;	            		// On peut récupérer cette valeur grâce à "int getNbObjectForCollision()"			
		}
    }
 }
 
int* QIrrlicht::getNode_ID()	// Récupération du tableau des IDs des nodes classés
{
    return m_Node_ID;
}
int QIrrlicht::getNbObjectForCollision()	// Récupération du nombre d'objet détecté pour de la sélection ou de la collision
{
    return m_NbObjectForCollision;
}

Il faut appeller cette méthode après le chargement d'une scène irrEdit par exemple ou dès l'ajout d'un nouvel élément pour qu'il soit pris en compte.

Maintenant, la dernière fonction, celle qui retourne une liste de "ISceneNode*" en fonction de la position de la caméra (ici "m_Camera_FPS", variable membre qui est ma caméra) et celle de la souris également (ici le paramètre "pos"). Ma liste est en fait une QList car j'utilise Qt pour ce projet.
Petite note: On pourrait très clairement passé le paramètre de la caméra également pour rendre plus portable cette petite méthode.

QList<ISceneNode*> QIrrlicht::findNodeWithScreenPos(position2d<s32> pos)
{
    vector3df outCollisionPoint;
    triangle3df outTriangle;
    QList<ISceneNode*> listSceneNode;               // Liste locale qui sera retournée
    line3df line = m_Collision->getRayFromScreenCoordinates(pos,m_Camera_FPS);

    for(int i=0;i<getNbObjectForCollision();i++)    // Permet de récupérer le nombre d'objet pris en compte et transformer en "TriangleSelector"
    {   // S'il y a une collison entre une ligne (projection du curseur de la souris sur le monde en fonction de ma caméra) et un objet 3d
        if(m_Collision->getCollisionPoint(line,getTriangleSelector()[i],outCollisionPoint,outTriangle) == true)
        {
            ISceneNode* node = m_Smgr->getSceneNodeFromId(getNode_ID()[i]);   // On récupère le bon ID venant de l'indice "i"
            if(node != NULL) listSceneNode.append(node);                      // Ajout du node trouvé dans une liste
        }
    }
    return listSceneNode;                           // On retourne la liste de node
}

Et voilà, après on peut appeler cette méthode dans le gestionnaire des évènements d'Irrlicht par exemple et afficher une boundingbox autour des nodes trouvés....

Je sais que c'est très simple, mais ça peut toujours aider. Bonne soirée à vous.

Retour

Options Liens officiels Caractéristiques Statistiques Communauté
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1440 sujets
11337 messages
Dernier membre inscrit: Saidov17
113 invités en ligne
membre en ligne: -
RSS Feed