Bonjour.
Est-il possible de faire du remplissage de polygone avec cairo ?
Par exemple je dessine un cube en 2D isométrique avec cairo. Puis-je utiliser une texture quelconque pour remplir les côtés de ce cube comme le ferait OpenGl par exemple ?
Bonjour.
Est-il possible de faire du remplissage de polygone avec cairo ?
Par exemple je dessine un cube en 2D isométrique avec cairo. Puis-je utiliser une texture quelconque pour remplir les côtés de ce cube comme le ferait OpenGl par exemple ?
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Oui, c'est assez bien expliqué dans ce tutoriel: http://www.dil.univ-mrs.fr/~regis/CM-CAIRO/index.html
GraceGTK: a plotting tool at https://sourceforge.net/projects/gracegtk
Je ne suis pas sûr que j'y trouve mes petits .
Ce que je cherche à faire c'est du mapping de texture. La texture appliquée doit se déformée pour prendre toute la surface du polygone.
Histoire de bien illustrer mon propos je désire par rapport à l'image ci-dessous appliquée les textures A, B et C aux polygones correspondants. D'après le lien qu tu m'as donné il semblerait qu'il ne soit possible de travailler que sur des rectangles.
Suis-je dans l'erreur ?
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Je pense que pour arriver à tes fins, il suffit de créer la face comme une image avec la surface texturée et d'appliquer seulement ensuite les transformations qui vont positionner cette image comme tu le souhaite.
Il y a ici un exemple d'image transformée: https://www.cairographics.org/samples/image/
PS: en revanche, je ne suis pas sûr que tu ne soit pas obligé de programmer toi-même les transformations prenant en compte les effets de perspective.
GraceGTK: a plotting tool at https://sourceforge.net/projects/gracegtk
Heu, j'y connais rien à la 3d, mais à mon avis utiliser un framework de dessin 2d pour faire de la 3d, c'est tendre le bâton pour se faire battre. Tu vas devoir gérer différentes matrices de transformation pour chaque face, tu auras sans doute des erreurs de positionnement dû aux arrondis ou à l'alignement sur un pixel plutôt qu'un autre, et sans doute d'autres cas limite... Si tu ne veux pas te retrouver à gérer tout toi même, utilise un framework fait pour ça. Soit directement l'opengl intégré dans GTK via GtkGlArea ou peut être une API comme cogl.
Documentation officielle GTK+ 3:
GTK en C, GTK en Python
Tutoriels GTK+ 3:
GTK en C, GTK en Python
Tutoriels par l'exemple (platform-demos):
GTK (tous langages)
Je lis pas mal de choses sur les transformées avec des matrices mais je ne trouve pas exactement ce que je veux.
Il y a quelques temps je me suis penché sur l'interpolation bilinéaire avec quelques succès. Je crois que je vais implémenter une petite routine adossée à cairo pour réaliser la chose.
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Salut à tous,
D'après mes connaissance, Cairo ne permet pas de faire des transformation en perspective.
Je rejoins liberforce en te proposant une bibliothèque. BABL qui est utilisé par Gimp avec l'outil cage :
PS: J'avoue ne pas savoir comment l'utiliser.
Hum, de ce que me dit la wikipédia, babl gère juste les espaces de couleurs. C'est gegl (qui dépende de babl) qui gère la partie rendu en OpenGL.
Effectivement, après recherche, cairo ne peut pas gérer des projections en perspective. Cela est dû au fait que les matrices de transformation dans cairo ne peut représenter que des transformations affines. Mais deux droites initialement parallèles auxquelles on applique une transformation affine sont forcément parallèles en sortie. Cela veut dire que la transformation de perspective n'est pas affine, et ne peut être représentée par cairo.
Donc penche toi sur cogl ou gegl... Il y en a sans doute un qui fait le job. Tu peux lire le code de l'outil de perspective de GIMP, il doit être basé sur gegl.
Documentation officielle GTK+ 3:
GTK en C, GTK en Python
Tutoriels GTK+ 3:
GTK en C, GTK en Python
Tutoriels par l'exemple (platform-demos):
GTK (tous langages)
Le nom de l'outil (cage) m'a bien aidé...
Le code correspondant, notamment la fonction qui a l'air de faire la transformation a l'air d'être gimp_operation_cage_transform_process dans le fichier gimpoperationcagetransform.c
Documentation officielle GTK+ 3:
GTK en C, GTK en Python
Tutoriels GTK+ 3:
GTK en C, GTK en Python
Tutoriels par l'exemple (platform-demos):
GTK (tous langages)
Merci pour toutes ces recherches.
Même si cette bibliothèque est intéressante, surtout du fait d'éviter de réinventer la roue, je désire aussi éviter l'importation, tant que faire ce peut, de bibliothèques tierces autres que celles de Gtk+. C'est pour cette raison que j'ai écrit plus haut le fait de vouloir me pencher sur l'interpolation.
Après une journée de travail et une bonne nuit de sommeil l'idée a germée. Plutôt que de faire de l'interpolation je me suis dit que je pouvais simplement faire une mise à l'échelle avec une transposition de pixel à pixel en y ajoutant un angle.
Comme je n'ai besoin de dessiner que des parallélogrammes j'ai commencé à écrire quelques lignes de code spécifiques à mes besoins. C'est loin d'être fini mais voila déjà un premier résultat :
À gauche l'image de départ, au centre le polygone dans lequel je veux insérer cette image et à droite le résultat.
Je vais passer à la phase optimisation et test pour les différents cas de figures qui me concernent. Je tiens aussi à préciser que la transformation tient grosso modo en 50 lignes de codes !
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Si je comprend bien, tu va faire de la "perspective cavalière" (https://fr.wikipedia.org/wiki/Perspe...cavali%C3%A8re) dans laquelle, au lieu de converger vers un point de fuite deux lignes parallèles le sont toujours dans le plan de représentation.
Une solution intermédiaire pourrai être de bien représenter la face par un trapèze (et non un parallélogramme) sans rétrécir la texture avec l'éloignement. J'avoue que je ne sais pas ce que ça donne visuellement.
GraceGTK: a plotting tool at https://sourceforge.net/projects/gracegtk
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Je vous livre en pâture la fonction qui permet de mapper un parallélogramme. Elle a quelques contraintes mais elle répond exactement à mes besoins.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 /* Fonction de mapping d'un parallélogramme. * * Les points A, B, C, D doivent être disposés de la sorte : * * B A * A B * ou * C D * D C * * Vous pouvez aussi utiliser cette fonction pour mapper un * rectangle. * * Cette fonction renvoie NULL si src est NULL, si le parallélogramme * représente une simple ligne verticale ou si les points AD * ou les points BC ne sont pas alignés verticalement. * * src : GdkPixbuf original utilisé comme texture à mapper * A, B, C, D : sommets du parallelogramme * * Renvoie un GdkPixbuf nouvellement créé. */ GdkPixbuf* gdk_pixbuf_perspective_new (const GdkPixbuf *src, GdkPoint A, GdkPoint B, GdkPoint C, GdkPoint D) { if (!src) { g_printerr ("Error in gdk_pixbuf_perspective_new (); !\n src must be not NULL !\n"); return NULL; } if (A.x-B.x==0) { g_printerr ("Error in gdk_pixbuf_perspective_new (); !\n A and B points are vertical aligned !\n"); return NULL; } if (A.x!=D.x || B.x!=C.x) { g_printerr ("Error in gdk_pixbuf_perspective_new (); !\n A and D or B and C points are not vertical aligned !\n"); return NULL; } // Les points AB et CD sont inversés if (A.x>B.x) { GdkPoint tmp; tmp.x = A.x; tmp.y = A.y; A.x = B.x; A.y = B.y; B.x = tmp.x; B.y = tmp.y; tmp.x = C.x; tmp.y = C.y; C.x = D.x; C.y = D.y; D.x = tmp.x; D.y = tmp.y; } guchar *pixels = gdk_pixbuf_get_pixels (src); gint rowstride = gdk_pixbuf_get_rowstride (src); guchar channels = gdk_pixbuf_get_n_channels (src); gint width = gdk_pixbuf_get_width (src); gint height = gdk_pixbuf_get_height (src); gdouble scalex, scaley; gint x, y; gint targety; GdkPoint Orig; // Coordonnées dans l'image originale GdkPixbuf *TargetPixbuf; gint xmax, ymax; // Limites du boundingbox 2D gdouble a, b; // coefficient de droite entre les points A et B // Calcul des coefficients a = (A.y - B.y) / (gdouble)(A.x - B.x); b = ((B.y*A.x) - (B.x*A.y)) / (gdouble)(A.x - B.x); // Calcul du boundingbox xmax = A.x; if (B.x>xmax) xmax = B.x; if (C.x>xmax) xmax = C.x; if (D.x>xmax) xmax = D.x; ymax = A.y; if (B.y>ymax) ymax = B.y; if (C.y>ymax) ymax = C.y; if (D.y>ymax) ymax = D.y; TargetPixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, xmax, ymax); guchar *TargetPixels = gdk_pixbuf_get_pixels (TargetPixbuf); gint TargetRowstride = gdk_pixbuf_get_rowstride (TargetPixbuf); gint TargetChannels = gdk_pixbuf_get_n_channels (TargetPixbuf); // Effacement complet du nouveau pixbuf créé memset(TargetPixels, 0, TargetRowstride * (D.y - A.y)); Orig.x = 0; Orig.y = 0; // Coordonnées dans l'image originale scalex = (B.x-A.x) / (gdouble)width; // Rapport d'échelle sur l'axe des x entre l'image source et l'image cible scaley = (D.y - A.y) / (gdouble)height; // Rapport d'échelle sur l'axe des y entre l'image source et l'image cible // Création du pixbuf cible for (y=0; y<(D.y-A.y); y++) { Orig.y = (gint)(y / scaley); for (x=0; x<(B.x-A.x); x++) { Orig.x = (gint)(x / scalex); targety = y + a*x + b; TargetPixels[(x * TargetChannels) + (targety * TargetRowstride)] = pixels [(Orig.x * channels) + (Orig.y * rowstride)]; TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 1] = pixels [(Orig.x * channels) + (Orig.y * rowstride) + 1]; TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 2] = pixels [(Orig.x * channels) + (Orig.y * rowstride) + 2]; if (gdk_pixbuf_get_has_alpha (src)) TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 3] = pixels [(Orig.x * channels) + (Orig.y * rowstride) + 3]; else TargetPixels[(x * TargetChannels) + (targety * TargetRowstride) + 3] = 255; } } return TargetPixbuf; }
Utilisation de Glade avec Gtk+
Code::Blocks et Gtk+ sous Windows
Programmation orientée objet avec Gtk+ v3
- N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk
Salut gerald3d,
je pense que tu te prends beaucoup la tête. Dans ton premier diagramme, tu avais des points de fuite, indiquant une perspective, et donc cela interdisait d'utiliser cairo vu que la forme cible n'était plus un parallélogramme.
Maintenant que tu as mieux expliqué ce que tu voulais (perspective cavalière), cairo peut tout à faire le job. Ne pars surtout pas dans de la manipulation de GdkPixbuf, ce n'est pas adapté pour cela (je le sais, je suis déjà passé par là il y a longtemps). Cairo peut parfaitement avec ses fonctions de transformation te permettre d'obtenir le résultat attendu avec peu d'effort. Ce que tu cherches à faire, c'est du "skew":
Regarde ici, au point "7.4 penchement d'image (skew)". Tu as même le code correspondant. C'est du GTK+ 2, mais tu ne devrais pas avoir de mal à l'adapter pour GTK+ 3.
http://www.dil.univ-mrs.fr/~regis/CM-CAIRO/
Une fois que ta matrice de transformation est calculée, tu peux tout à fait la stocker pour la réutiliser sur les images que tu souhaites.
De plus, cairo fait partie des dépendances de GTK+, donc pas de dépendance supplémentaire.
Ne tombe pas dans le syndrome NIH (Not Invented Here - en français: réinventer la roue).
N'oublie pas non plus d'utiliser les fonctions cairo_user_to_device et cairo_device_to_user qui te permettent de facilement passer d'un repère "écran" à un repère orthogonal "comme à l'école" et te permet de facilement jongler entre les espaces de coordonnées.
Documentation officielle GTK+ 3:
GTK en C, GTK en Python
Tutoriels GTK+ 3:
GTK en C, GTK en Python
Tutoriels par l'exemple (platform-demos):
GTK (tous langages)
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager