OpenGL: échelle de traduire? et comment?
J'ai un peu de géométrie 2D. Je veux prendre quelques rect délimitation autour de ma géométrie, puis rendre une version plus petite de quelque part d'autre sur l'avion. Voici plus ou moins le code que j'ai à faire de mise à l'échelle et à la traduction:
//source and dest are arbitrary rectangles.
float scaleX = dest.width /source.width;
float scaleY = dest.height /source.height;
float translateX = dest.x - source.x;
float translateY = dest.y - source.y;
glScalef(scaleX, scaleY, 0.0);
glTranslatef(translateX, translateY, 0.0);
//Draw geometry in question with its normal verts.
Cela fonctionne exactement comme prévu pour une dimension donnée lorsque la destination d'origine est de 0. Mais si l'origine pour, disons, x, est différente de zéro, le résultat est toujours mis à l'échelle correctement mais ressemble (?) il est traduit en quelque chose de proche de zéro sur l'axe de toute façon-- s'avère qu'il n'est pas exactement le même que si dest.x est zéro.
Quelqu'un peut-il point quelque chose d'évident, je suis absent?
Merci!
Dernière mise à JOUR Par Bahbar et Marcus réponses ci-dessous, j'ai fait un peu plus d'expériences et d'réglé ce problème. Adam de Bowen commentaire a été à la pointe. J'ai été absent à deux faits:
- J'avais besoin d'être mise à l'échelle vers le centre de la géométrie, je m'y intéressai.
- J'avais besoin pour appliquer les transformations dans l'ordre inverse de l'intuition (pour moi).
La première est une sorte d'évidence avec le recul. Mais pour ce dernier, pour d'autres de bons programmeurs/mauvais mathématiciens comme moi: - s'avère que mon intuition était d'exploitation en ce que le Livre Rouge appelle un "Grand Système de Coordonnées Fixe", dans lequel il y a un absolu de l'avion, et votre géométrie se déplace sur l'avion à l'aide de transformations. C'est OK, mais compte tenu de la nature des mathématiques derrière cumul de plusieurs transforme en une matrice, il est à l'opposé de la façon dont les choses fonctionnent réellement (voir les réponses ci-dessous ou Livre Rouge pour plus de détails). Fondamentalement, les transformations sont "appliqués" dans "ordre inverse" à la façon dont ils apparaissent dans le code. Voici la dernière solution de travail:
//source and dest are arbitrary rectangles.
float scaleX = dest.width /source.width;
float scaleY = dest.height /source.height;
Point sourceCenter = centerPointOfRect(source);
Point destCenter = centerPointOfRect(dest);
glTranslatef(destCenter.x, destCenter.y, 0.0);
glScalef(scaleX, scaleY, 0.0);
glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0);
//Draw geometry in question with its normal verts.
Vous devez vous connecter pour publier un commentaire.
En OpenGL, matrices que vous spécifiez sont multipliés à la droite de la matrice, et le sommet est à l'extrême droite de l'expression.
Ainsi, la dernière opération que vous spécifiez sont dans le système de coordonnées de la géométrie elle-même.
(Le premier est généralement la transformation de la vue, c'est à dire l'inverse de votre appareil photo de transformation du monde.)
Bahbar fait un bon point que vous devez considérer le point central de mise à l'échelle. (ou le point de pivot pour les rotations.) Habituellement, vous traduire là, rotation/échelle, puis traduire en arrière. (ou, en général, appliquer la base de transformer l'opération, puis l'inverse). Ceci est appelé Changement de Base, que vous pouvez lire sur.
De toute façon, pour obtenir de l'intuition au sujet de la façon dont il fonctionne, essayez avec quelques valeurs simples (zéro, etc) puis les modifier légèrement (peut-être une animation) et voir ce qui se passe à la sortie. Ensuite, il est beaucoup plus facile de voir ce que vos transformations sont en train de faire à votre géométrie.
Mise à jour
Que la commande est "inversée" w.r.t. l'intuition est assez courant chez les débutants OpenGL-codeurs. J'ai été de tutorat d'un ordinateur graphiques de cours et de nombreux réagir d'une manière similaire. Il devient plus facile de penser à la façon dont OpenGL t-il si vous envisagez l'utilisation de pushmatrix/popmatrix rendu d'un arbre (la scène graphique) de transformations et de géométries. Ensuite, l'ordre actuel des choses devient assez naturelle, et le contraire serait faire qu'il est assez difficile d'obtenir quelque chose d'utile à faire.
Échelle, tout comme la Rotation, fonctionne à partir de l'origine. donc, si la mise à l'échelle par la moitié d'un objet qui s'étend sur le segment [10:20] (sur l'axe X, par exemple), vous obtenez [5:10]. L'objet était donc mis à l'échelle, et il s'est rapproché de l'origine. Exactement ce que vous avez observé.
C'est pourquoi vous appliquer à l'Échelle d'abord en général (parce que les objets ont tendance à être définie autour de 0).
Donc, si vous souhaitez mettre à l'échelle un objet par rapport à un point de Centre, vous pouvez traduire l'objet de Centre à l'origine, l'échelle de là, et de les traduire en arrière.
Note de côté, si vous traduire tout d'abord, et ensuite à l'échelle, puis, à votre échelle est appliquée à la traduction précédente, qui est pourquoi vous avez probablement eu des problèmes avec cette méthode.
Je n'ai pas joué avec OpenGL ES, juste un peu avec OpenGL.
Il semble que vous voulez transformer à partir d'un autre poste, par opposition à l'origine, ne sais pas, mais pouvez-vous essayer de faire les transformations et attire que peu dans glPushMatrix() et glPopMatrix() ?
Voici un simple Traitement de l'esquisse que j'ai écrit pour illustrer ce point:
Voici une image de l'esquisse en cours d'exécution, le même vert triangle est dessiné, avec la traduction et de l'échelle appliquée, puis le rouge, outsie le push/pop "en bloc", de sorte qu'il n'est pas affecté par la transformation:
HTH,
George