Je suis en train de développer un éditeur 3D basique. Il utilise OpenGL pour rendre un monde 3D. En ce moment, ma scène n'est que quelques boîtes de différentes tailles et je suis au stade où je veux pouvoir sélectionner chaque boîte, puis la déplacer / la mettre à l'échelle / la faire pivoter pour obtenir la transformation que je veux.
Comment puis-je résoudre le problème de l'implémentation du rendu des gizmos (ou des poignées de ces outils, ou comment les gens les appellent généralement), ainsi que de les choisir sur chaque axe pour effectuer le changement de transformation avec ma souris? Pour plus de clarté:
Jusqu'à présent, mes recherches ont suggéré que l'approche la plus propre consiste à avoir un cadre de délimitation aligné sur chaque axe par flèche dans le gizmo et un autre par carré (ceux qui déplacent l'objet dans un plan plutôt que sur un seul axe), puis de lancer un rayon à partir de la souris. position et voir ce avec quoi il entre en collision. Mais c'est encore un peu trop abstrait pour moi, j'apprécierais davantage de conseils sur la façon dont cet algorithme se passerait (le pseudocode est plus que suffisant)
Réponses:
À un moment donné de mon passage chez e-on, j'ai conservé les gadgets de la gamme de produits Vue .
Je peux vous dire que cela vous prendra plusieurs jours à plein temps.
À moins que vous ne trouviez une bibliothèque ou un moyen super intelligent, la méthode classique consiste à obtenir les coordonnées de la souris dans la fenêtre lorsque vous cliquez, si c'est une coordonnée relative à la fenêtre, vous pouvez simplement diviser x et y par largeur et hauteur, vous obtenir un vecteur (float 2d) dans la plage [0,1]. soustrayez-le (0,5,0,5) pour entrer dans la plage [-0,5, 0,5] pour x et y.
Ensuite, vous créez un rayon à partir de cette coordonnée en utilisant simplement les x et y comme rayons x et y, et vous définissez z à la distance focale. parfois le rapport d'aspect est une douleur dans le cul dans cette opération. Un peu de tripotage et d'erreur d'essai vous permettront de résoudre le problème.
Ensuite, vous devez vérifier l'intersection avec vos éléments de gizmos, soit vous avez un maillage que vous avez généré, ou modélisé dans Blender ou un autre DCC, soit des pièces de maillage qui peuvent s'articuler entre elles ... Utilisez simplement cette partie de maillage comme un rayon / requête d'intersection de triangle.
Ou si vous l'avez, rayon / cylindre, rayon / sphère selon l'apparence et les pièces de votre gizmo.
Vous devez disposer de routines d'intersection capables d'appliquer une matrice de transformation sur la primitive qu'elles entrent en collision . Extrêmement important car votre gizmo se traduira par l'objet qu'il sert à déplacer, il pivotera et il sera mis à l'échelle avec l'inverse de la distance à la caméra, de sorte qu'il conserve une taille projetée fixe à l'écran.
Ensuite, vous avez la partie d'interaction, la plus simple est de prendre le delta du point lorsque la souris a été le premier événement "souris vers le bas", et la position actuelle "Déplacer la souris", en 2D pur, et d'utiliser ce delta comme mouvement d'axe actuel dans l'espace mondial, multiplié par certains
k
que vous décidez empiriquement. Selon vos unités internes versus pixel versus échelle actuelle de zoom etc.La dernière étape consiste simplement à appliquer la matrice du gizmo à l'objet manipulé, afin qu'il le suive.
Je vous dis que c'est tout un voyage en enfer à mettre en œuvre, et si vous le faites pendant votre temps libre, attendez plus d'une semaine. Plusieurs semaines si vous découvrez complètement le domaine. Plus d'un mois si vos week-ends sont occupés par d'autres activités :)
Je vous suggère de télécharger Embree 2.0 d'Intel pour faire la requête d'intersection rayon / triangle pour vous, donc vous n'avez pas à vous soucier de coder cela. Ou vous pourriez sans pitié copier / coller et adapter le code de Blender ... Je pense qu'ils sont passés à la licence Apache? Devrait être possible légalement.
la source
Pour le manipulateur-traducteur, j'utilise l'algorithme suivant:
1) Lorsque la souris est enfoncée, nous devons vérifier si le rayon croise la flèche. Par exemple, nous considérons la flèche X. Nous construisons Ray dans l'espace mondial (basé sur le tronc de la caméra et la position de la souris). Nous construisons un plan dans lequel se trouve l'axe des x: sa normale est égale à V croix X croix V, où V - vecteur du centre à la caméra, X - représente l'axe x. Ensuite, nous coupons le rayon avec le plan et nous trouvons donc le point d'intersection en coordonnées mondiales. Ensuite, nous projetons le segment de l'axe x et le point résultant sur l'écran, trouvons la distance entre le segment projeté et le point projeté sur l'écran. si elle est inférieure à quelques pixels, la souris intersecte l'axe. Nous calculons également le vecteur delta de l'espace mondial entre le centre de sélection et notre intersection.
Cette procédure que nous faisons pour 3 axes, nous trouvons donc des distances à tous les axes. Trouvez la distance minimale. nous avons donc trouvé avec quel axe la souris est intersecte.
2) Lorsque la souris bouge. nous savons par quel axe l'objet se déplace (à partir de 1). nous trouvons l'intersection spatiale mondiale du rayon avec le plan (comme en 1). de plus, nous projetons le point d'intersection sur la ligne le long de laquelle l'objet se déplace. position finale du manipulateur = intersection + delta.
la source