9
votes

Sélection de surfaces 3D avec une boîte de sélection (de deux manières différentes)

Je crée un logiciel de modélisation. Mes modèles sont tous constitués de polygones plats, qui sont simplement un ensemble commandé de sommets que j'affiche avec OpenGL. J'ai fait un peu de recherche et à ma surprise n'a pas trouvé beaucoup d'informations pour l'application que je recherche.

Je tente d'utiliser une boîte rectangulaire pour sélectionner des surfaces. Cela semble assez simple, mais je veux que cela fonctionne de la même manière que cette méthode fonctionne dans beaucoup de programmes. Ce sont les exigences que je cherche:

  1. Je veux un rectangle qui commence à gauche et passe à droite pour sélectionner uniquement ces objets entièrement contenus dans la zone.
  2. rectangles qui commencent à droite et à gauche doivent sélectionner n'importe quelle surface touchée (il n'est pas nécessaire d'être entièrement enfermé.
  3. tous les objets dans / toucher le rectangle doit être sélectionné. En d'autres termes, je veux sélectionner des objets s'ils sont visibles ou non. Tout ce qui convient à l'intérieur de la boîte, même si couvert d'une autre surface, devrait toujours être sélectionné.

    numéro 3 sur la liste est le plus important. Avoir les deux options 1 et 2 est préférable, mais je peux vivre avec une seule d'entre elles si elle s'avère trop difficile à les mettre en œuvre.

    J'ai examiné divers autres postes sur la cueillette 3D et il semble que la plupart suggèrent la cueillette de couleur ou la coulée de rayons. J'utilise la sélection de couleurs pour une sélection de clic normal, mais parce que je veux que la sélection de la boîte inclue des surfaces qui ne sont pas visibles, ce n'est pas une option. Il semble également que la coulée de rayons ne fonctionne que avec un seul point de clic plutôt qu'une boîte. Alors y a-t-il d'autres méthodes assez simples pour accomplir mon objectif? Je pensais que ce serait une tâche assez courante car il semble être présent dans beaucoup de logiciels de modélisation, mais malheureusement, je n'ai pas été en mesure de trouver une méthode qui convient à mes besoins.

    pseudocode d'un algorithme serait apprécié mais n'est pas nécessaire. À tout le moins, je cherche une méthode que je serais en mesure de rechercher et de trouver quelques exemples à moi; Je ne sais tout simplement pas du bon endroit pour regarder.


0 commentaires

3 Réponses :


5
votes

Je peux vous dire à plat que la cueillette de couleur sont de travail non; Vous devriez faire une passe par objet pour satisfaire les exigences (3) puisque un seul pixel le rend jamais dans la tramebuffer.

Comme pour le casting à rayons, il est vrai que cela ne teste qu'un seul point, mais vous pouvez créer un volume de test en incrojectant les quatre coins de votre rectangle de sélection. Vous trouverez les coordonnées dans l'espace mondial au plan près ( Win_Z = 0 ) et au plan lointain ( Win_Z = 1 ) et l'utiliser pour construire un volume 3D de votre zone de sélection 2D.

Le volume que vous allez obtenir de cela s'appelle cela est appelé troncum (en supposant une projection en perspective), il ressemble à une pyramide avec le dessus coupé. Les tests d'intersection de tronctume sont très bien documentés et tout ce qui discute "frustum culling" doit vous fournir un contexte suffisant pour la mettre en œuvre. Votre vie sera beaucoup plus facile si vous pouvez approcher les limites de ces objets à l'aide de boîtiers de liaison et / ou de sphères alignés à l'axe.

Le schéma suivant illustre ce volume de test bien:

 Entrez la description de l'image ici


0 commentaires

7
votes

Effectuer vos propres calculs d'intersection sur la CPU est certainement une option. Mais sur la base de la façon dont je comprends vos exigences, je pense que vous pouvez également laisser OpenGL faire le travail, ce qui devrait être beaucoup plus facile et plus efficace.

Présentation de la méthode h3>

Le mécanisme qui me vient à l'esprit est des requêtes d'occlusion. . Ils vous permettent de compter les pixels qui ont été rendus. Si vous combinez ceci avec l'utilisation du test de ciseaux, vous pouvez compter les pixels rendu dans votre rectangle de sélection. P>

Application à utiliser des cas h3>

Utiliser Case 2 est le plus simple pour cette approche. Vous configurez le rectangle de sélection en tant que rectangle de ciseaux et rendez toutes les surfaces avec une requête d'occlusion pour chacune d'elles. Ensuite, vous vérifiez le résultat des requêtes et toutes les surfaces où le résultat de la requête est supérieur à 0 avait des pixels à l'intérieur du rectangle de sélection. P>

Utilisation de cas 1 est légèrement plus difficile. Pour savoir si la surface est complètement contenue à l'intérieur du rectangle, vous avez besoin de deux passes. Vous passez par le rendu avec des requêtes d'occlusion une fois ci-dessus, avec le test de ciseaux activé. Ensuite, vous faites la même chose une seconde fois, avec le test de ciseaux désactivé. Si une surface a le même résultat de la requête pour les deux passes, il est complètement à l'intérieur du rectangle. P>

Mise en œuvre h3>

Je ne vais pas fournir de code complet pour cela. Cela devrait tous être assez simple. Mais voici quelques pointeurs et fragments de code. Les appels sont affichés avec des liaisons C. J'espère que c'est assez évident de voir la même chose avec les liaisons python. P>

Premièrement, car vous souhaitez inclure des surfaces cachées dans la sélection, vous devez désactiver le test de profondeur: P>

GLint pixelCounts[surfaceCount];
// for all surfaces k
glGetQueryObjectiv(queryIds[k], GL_QUERY_RESULT, &pixelCounts[k]);


3 commentaires

+1 C'est une idée vraiment intéressante. J'avais considéré une solution pixelle parfaite dès que les mots "la cueillette de couleur ne fonctionneront pas" est sorti de ma bouche, mais la latence de plusieurs réveils m'a effrayé. Les exigences n'ont jamais rien dit sur la latence et je me sens stupide maintenant. Cela semble décourageant avec qui sait combien de requêtes sont nécessaires, mais seraient effectivement plus faciles et plus précises à mettre en œuvre.


Si je comprends bien cela correctement, je pense qu'il est possible que l'abattage de visage doit être désactivé pour gérer chaque cas d'objet "invisible" dans l'exigence (3).


@ Andonm.Coleman je ne pense pas que la latence serait mauvaise. Comme il est fait en réponse à la saisie de l'utilisateur, cela ne sera pas exécuté très fréquemment. La clé est de soumettre tout le rendu avec toutes les requêtes et de ne demander que les résultats de la requête à la fin. Vous n'avez donc qu'un seul point de synchronisation, lorsque vous commencez à demander les résultats de la requête à la fin. Le mauvais cas pour les requêtes d'occlusion est si vous bloquez pour le résultat immédiatement après avoir soumis la requête.



0
votes

Je sais que je sais que je suis en retard, mais en réalité la cueillette de couleur peut fonctionner pour sélectionner des objets en couches profonds tout en effectuant une performance via la solution de contournement: sélectionnez la sélection épluchée lorsque vous appuyez sur Maj + Souris.

ou en d'autres termes lorsque vous faites un premier test rectangle, souvenez-vous de la position rectangle, laissez l'utilisateur appuyer sur SHIFT + Souris par défilement et lorsque l'utilisateur Scrolls Retirez temporairement les objets sélectionnés (par conséquent éplucher) du rendu (uniquement lorsque vous renduez au tampon de sélection) et ajoutez tout nouvel objet sélectionné vers le réseau sélectionné. Continuez jusqu'à ce que l'utilisateur arrête de faire défiler ou de faire pression sur Maj.

CAVEAT est que dès que vous déplacez ou faites pivoter la caméra, cette méthode ne fonctionnera pas bien, mais lorsque l'utilisateur est invalider que vous pouvez invalider le dernier rectangle ou appliquer temporairement la matrice delta de la caméra dans le monde entier lorsque l'utilisateur Do SHIFT + Scroll de la souris lorsque l'utilisateur n'a pas Invalidez la dernière sélection, mais pour cette raison, il est probablement toujours préférable de coller à la requête d'occlusion à moins que vous êtes coincé sur votre matériel ou mobile de Reeealy OUT (OpenGL ES 2 ne l'a pas sans extension)

Un autre est que pour un objet inférieur à 1 pixel cueillette de couleur échoue, mais c'est rarement émettre (bien que le rectangle cueillette, il peut être logique de sélectionner des objets "invisibles" en fonction des cas d'utilisation)


0 commentaires