Comment faire pour convertir un point 3D en 2D projection en perspective?
Je suis actuellement en train de travailler avec l'aide de courbes de Bézier et les surfaces de dessiner la fameuse théière de l'Utah. À l'aide de courbes de Bézier patchs de 16 points de contrôle, j'ai été en mesure de tirer la théière et les afficher à l'aide d'un "monde à la caméra" est la fonction qui donne la capacité à tourner la résultante d'une théière, et je suis actuellement à l'aide d'une projection orthographique.
Le résultat est que j'ai un "plat" théière, qui est attendu que l'objet de la projection orthographique est de préserver les lignes parallèles.
Cependant, je voudrais utiliser une projection en perspective pour donner la théière de profondeur. Ma question est, comment fait-on prendre la 3D xyz vertex retourné à partir de la "world à la caméra" de la fonction, et de le convertir en 2D coordonner. Je suis désireux d'utiliser le plan de projection de z=0, et permettre à l'utilisateur de déterminer la distance focale et la taille de l'image en utilisant les touches fléchées du clavier.
Je suis de la programmation, cette en java et ont tous de l'entrée de gestionnaire d'événement mis en place, et ont également écrit une matrice de la classe qui gère à la multiplication de matrice de base. J'ai lu dans wikipédia et d'autres ressources pour un certain temps, mais je n'arrive pas à obtenir une poignée sur la façon dont on réalise cette transformation.
- stackoverflow.com/questions/701504/...
- Une très bonne interactive exemple , comment les trois D les points sont projetés sur deux d espace, ce mathdisk.com/pub/safi/worksheets/Perspective_Projection
- Avez-vous plus loin avec cette? J'ai quelques questions à propos de la courbe de Bézier ou partie de cette tâche here et here.
Vous devez vous connecter pour publier un commentaire.
Je vois cette question est un peu vieux, mais j'ai décidé de donner une réponse de toute façon pour ceux qui trouvent cette question par la recherche.
La méthode standard de représentation 2D/3D transformations de nos jours est par l'utilisation de homogène coordonnées. [x,y,w] pour la 2D, et [x,y,z,w] pour la 3D. Puisque vous avez trois axes en 3D ainsi que de la traduction, que l'information s'intègre parfaitement dans un 4x4 matrice de transformation. Je vais utiliser de la colonne principale de la matrice de notation dans cette explication. Toutes les matrices sont des 4x4, sauf mention contraire.
Les étapes à partir de points 3D et à un pixellisé point, ligne ou polygone ressemble à ceci:
Cette étape est en fait la projection, parce que z n'est pas utilisé comme un composant dans la position de plus.
Les algorithmes:
Calcul de champ de vue
Ce calcule le champ de vue. Si tan prend en radians ou en degrés n'est pas pertinent, mais angle doivent correspondre. Notez que le résultat atteint l'infini comme angle approche de 180 degrés. C'est une singularité, qu'il est impossible d'avoir un point focal que large. Si vous voulez stabilité numérique, garder angle inférieur ou égal à 179 degrés.
Également remarquer que 1.0 /tan(45) = 1. Quelqu'un ici a suggéré de simplement diviser par z. Le résultat ici est clair. Vous désirez obtenir un FOV de 90 degrés et un aspect ratio de 1:1. À l'aide de coordonnées homogènes comme cela a plusieurs autres avantages; on peut par exemple effectuer un écrêtage à l'encontre de la de près et de loin les avions sans la traiter comme un cas spécial.
Calcul de l'élément de la matrice
C'est la mise en page de l'élément de la matrice. aspectRatio est-Largeur/Hauteur. De sorte que le CHAMP de vision pour la composante x est dimensionné en fonction de FOV pour y. De loin et de près sont des coefficients qui sont les distances à respecter pour les de près et de loin les plans de découpe.
Écran De Projection
Après la tonte, c'est la transformation finale pour obtenir nos coordonnées de l'écran.
Trivial exemple d'implémentation en C++
Si vous réfléchissez à ce sujet, la spécification OpenGL est vraiment une bonne référence pour les mathématiques impliquées.
Le DevMaster forums à http://www.devmaster.net/ ont beaucoup de bons articles liés au logiciel rasterizers ainsi.
trivial
exemple n'a même pas compiler.Je pense que cette sera probablement répondre à votre question. Voici ce que j'ai écrit là:
Vous pouvez le projet de points 3D en 2D à l'aide d': Communes De Mathématiques: L'Apache Commons Bibliothèque De Mathématiques avec deux classes.
Exemple pour Java Swing.
Maintenant vous avez seulement besoin de mise à jour de la
planeX
etplaneY
pour changer le point de vue de projection, pour obtenir ce genre de choses:Pour obtenir la correction de perspective coordonnées, juste diviser par le
z
coordonner:Les travaux ci-dessus en supposant que la caméra est à
(0, 0, 0)
et vous êtes en train de projeter de l'avion àz = 1
- vous besoin de traduire le co-ords par rapport à la caméra autrement.Il y a quelques complications pour les courbes, dans la mesure où la projection des points 3D d'une courbe de Bézier ne sera pas, en général, de vous donner les mêmes points que le dessin 2D courbe de Bézier à travers les points projetés.
En regardant l'écran du haut, vous obtenez x et z de l'axe.
La recherche à l'écran sur le côté, vous obtenez des y et l'axe z.
Calculer les distances focales des haut et des vues de côté, à l'aide de la trigonométrie, qui est la distance entre l'œil et le milieu de l'écran, qui est déterminé par le champ de vision de l'écran.
Cela rend la forme de deux triangles rectangles dos à dos.
hw = screen_width /2
hh = screen_height /2
fl_top = hw /tan(θ/2)
fl_side = hh /tan(θ/2)
Puis prendre la moyenne de la longueur focale.
fl_average = (fl_top + fl_side) /2
Calculons maintenant le nouveau x et de nouvelles y avec l'arithmétique de base, depuis le plus grand triangle de droite fait de la 3d, le point et le point de vue est congruent avec le petit triangle formé par la 2d point et le point de vue.
x' = (x * fl_top) /(z + fl_top)
y' = (y * fl_top) /(z + fl_top)
Ou vous pouvez tout simplement mis
x' = x /(z + 1)
et
y' = y /(z + 1)
Je ne suis pas sûr à quel niveau vous vous posez cette question. Il semble que si vous avez trouvé les formules en ligne, et sont juste essayer de comprendre ce qu'il fait. Sur que la lecture de votre question, je vous propose:
Toutes les réponses répondre à la question posée dans le titre. Cependant, je voudrais ajouter une mise en garde qui est implicite dans le texte. De Bézier, les patchs sont utilisés pour représenter la surface, mais vous ne pouvez pas simplement de transformer les points de la pièce et paver le patch en polygones, parce que cela va entraîner une déformation de la géométrie. Vous pouvez, cependant, le maillage par approximation le patch d'abord dans les polygones à l'aide d'une transformée de l'écran de tolérance, et de transformer les polygones, ou vous pouvez convertir le de Bézier patchs rationnelle de Bézier patchs, puis le maillage par approximation de ceux avec l'aide d'un espace de tolérance. Le premier est plus facile, mais celle-ci est mieux pour un système de production.
Je soupçonne que vous voulez la façon la plus facile. Pour ce faire, vous l'échelle de l'écran de la tolérance par la norme de la Jacobienne de l'inverse de la perspective de la transformation et de l'utiliser pour déterminer le montant de pavage que vous avez besoin dans l'espace de modélisation (il peut être plus facile de calculer le Jacobien de l'avant, inverser, alors prenez la norme). Notez que cette norme est dépendant de la position, et vous pouvez évaluer ce à plusieurs endroits, selon le point de vue. Rappelez-vous aussi que, depuis la transformation projective qui est rationnel, vous devez appliquer le quotient de la règle à calculer les dérivées.
Je sais que c'est un vieux sujet, mais votre illustration n'est pas correct, le code source définit le clip de la matrice correcte.
certains plus de vos choses:
Ce clip de la matrice ne fonctionne que si vous êtes en saillie sur la statique de plan en 2D si vous souhaitez ajouter le mouvement de la caméra et de la rotation:
cela vous permet de faire pivoter la 2D et de la déplacer..-
Vous pourriez voulez déboguer votre système avec des sphères de déterminer si oui ou non vous avez un bon champ de vision. Si vous avez trop large, les sphères de la déformation sur les bords de l'écran en plus ovale formes pointée vers le centre de l'image. La solution à ce problème est de faire un zoom sur l'image, en multipliant les coordonnées x et y pour les 3 dimensions point par un scalaire, puis la réduction de l'objet ou du monde par un facteur similaire. Puis vous aurez l'agréable, même ronde sphère à travers la totalité de l'image.
Je suis presque gêné qu'il m'a fallu toute la journée pour celui-ci et je suis presque convaincu qu'il y avait certains spooky mystérieux géométrique phénomène qui se passe ici, qui exigeait une approche différente.
Encore, l'importance de l'étalonnage de la zoom-cadre-de-vue coefficient par le rendu des sphères ne peut pas être surestimée. Si vous ne savez pas où la "zone habitable" de votre univers, vous allez finir par marcher sur le soleil et la mise au rebut du projet. Vous voulez être en mesure de rendre une sphère n'importe où dans votre cadre de vue un pour qu'elle s'affiche à la ronde. Dans mon projet, la sphère unité est énorme par rapport à la région que je vais décrire.
Aussi, l'obligation de l'entrée de wikipedia:
Système De Coordonnées Sphérique
Grâce à @Mads Elvenheim pour un bon exemple de code. J'ai fixé le mineur a des erreurs de syntaxe dans le code (juste un peu de const problèmes et évident manque d'opérateurs). Aussi, près de et loin ont très différentes significations dans contre
Pour votre plaisir, voici les compileable (MSVC2013) version. Avoir du plaisir.
L'esprit que j'ai fait NEAR_Z et FAR_Z constante. Vous probablement ne voulez pas ça comme ça.
operator/=
déchets 2 divisions et renvoie une référence à un temporaire. Au lieu de cela, il devrait changerthis
etreturn *this
. En outre, c'est le C++, mais la question est de java.Vector::operator=/
.operator/=
selon votre suggestion. Vous avez raison en ce qu'il devrait changer le vecteur lui-même.Unit()
si la longueur est inférieure à 1e-6? Que faire si tous les 3 composantes du vecteur sont plus petits? Soit vous ne faites rien (et retour NaNs si length=0), ou, si vous ne vérifiez length==0.