2010-11-08 27 views
1

J'ai récemment rencontré des problèmes lors de l'implémentation d'une fonction de zoom dans une application de peinture. S'il vous plaît laissez-moi commencer par vous donner quelques informations générales. Tout d'abord, j'ai commencé par modifier l'application de démonstration glPaint d'Apple. Je pense que c'est une excellente source, car elle vous montre comment configurer EAGLView, etc ...Zoom avant/arrière et peinture dans openGL

Maintenant, ce que je voulais faire, était d'implémenter la fonctionnalité de zoom. Après avoir fait quelques recherches, j'ai essayé deux approches différentes.

1) utilisent glOrthof

2) changer la taille du cadre de mon EAGLView.

Alors que les deux moyens me permettent de zoomer parfaitement in/out, j'éprouve des problèmes différents, quand il est en fait à la peinture en zoomant.

Quand j'utiliser (1), je dois rendre la vue comme celui-ci :

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrthof(left, right, bottom, top, -1.0f, 1.0f); //those values have been previously calculated 
glDisable(GL_BLEND); 
//I'm using Apple's Texture2D class here to render an image 
[_textures[kTexture_MyImage] drawInRect:[self bounds]]; 
glEnable(GL_BLEND); 
[self swapBuffers]; 

maintenant, supposons que je zoome un peu, puis je peins et après cela, je veux effectuer un zoom arrière. Pour que cela fonctionne, je dois m'assurer que "kTexture_MyImage" contient toujours les dernières modifications. Pour ce faire, je dois capturer le contenu de l'écran après que les modifications ont été apportées et les fusionner avec l'image originale. Le problème ici est que lorsque je zoome, mon écran n'affiche qu'une partie de l'image (agrandie) et je n'ai pas encore trouvé de moyen de m'en occuper.

J'ai essayé de calculer quelle partie de l'écran a été agrandie, puis effectuez la capture. Après cela, je redimensionner cette partie à sa taille d'origine et utiliser une autre méthode pour le coller dans l'image originale à la bonne position.

Maintenant, je pourrais aller plus en détail sur la façon dont j'ai réalisé cela, mais c'est vraiment compliqué et je me suis dit, il doit y avoir un moyen plus facile. Il y a déjà plusieurs applications là-bas, c'est parfait, ce que j'essaie de réaliser, donc ça doit être possible.

En ce qui concerne l'approche (2), je peux éviter la plupart de ce qui précède, puisque je ne change que la taille de ma fenêtre EAGLView. Cependant, en peignant, les coups sont loin de leur position attendue. J'ai probablement besoin de prendre en compte le niveau de zoom lors de la peinture et de recalculer les CGPoints d'une manière différente.

Cependant, si vous avez déjà fait des choses similaires ou si vous pouvez me donner un indice, comment puis-je implémenter le zoom dans mon application de peinture, je l'apprécierais vraiment.

Merci d'avance.

Répondre

1

Oui, c'est certainement possible. En ce qui concerne les programmes de peinture, vous devriez conserver une liste chaînée ou un arbre d'objets à dessiner pour une insertion/suppression facile. Lorsque l'utilisateur arrête de peindre (c'est-à-dire touches touchées), vous ajoutez des objets à la structure de données contenant votre scène. Lorsque votre utilisateur effectue un zoom, vous devez moduler les coordonnées des objets que vous dessinez par rapport aux transformations actuelles de la fenêtre, de la projection et du modelview. Dans votre cas, vous ne modifiez pas la fenêtre ou les transformations modelview, vous n'avez donc besoin que de rendre compte de la transformation de projection. Vous pouvez également implémenter votre zoom en utilisant une translation et une échelle sur la matrice modelview mais je vais ignorer ce cas pour la simplicité car cela implique d'inverser les transformations.La bonne nouvelle est que vous utilisez une projection orthographique pour que les coordonnées du monde correspondent aux coordonnées de la fenêtre quand aucun zoom n'est en vigueur. Le "monde" dans votre cas est une toile simple qui correspond probablement à la taille de l'appareil dans les coordonnées de la fenêtre. Avant d'ajouter un objet à la structure de données de votre scène, convertissez toutes les coordonnées en utilisant la transformation de projection actuelle (c'est-à-dire les paramètres de l'appel glOrthof()) en coordonnées mondiales (coordonnées canvas complètes). Vous ne resterez sain que si vous gardez toutes les choses dans votre modèle dans le même espace de coordonnées. Pour convertir les coordonnées, en supposant que vous ne puissiez jamais effectuer un zoom arrière sur les dimensions complètes du périphérique dans votre appel glOrtho(), vous devrez les réduire proportionnellement aux ratios de vos dimensions ortho agrandies par rapport aux dimensions ortho non agrandies, puis biaiser par la différence entre vos valeurs ortho bottom, left et celles des valeurs ortho originales non zoomées.