]> Pileus Git - grits/blob - src/objects/grits-poly.c
Minor cleanup in GritsPoly
[grits] / src / objects / grits-poly.c
1 /*
2  * Copyright (C) 2010-2011 Andy Spencer <andy753421@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 /**
19  * SECTION:grits-poly
20  * @short_description: Single point polys
21  *
22  * Each #GritsPoly represents a 3 dimentional polygon.
23  */
24
25 #include <config.h>
26 #include "gtkgl.h"
27 #include "grits-poly.h"
28
29 /* Drawing */
30 static void grits_poly_tess(gdouble (**points)[3])
31 {
32         //g_debug("GritsPoly: tess");
33         GLUtesselator *tess = gluNewTess();
34         gluTessCallback(tess, GLU_TESS_BEGIN,  (void*)glBegin);
35         gluTessCallback(tess, GLU_TESS_VERTEX, (void*)glVertex3dv);
36         gluTessCallback(tess, GLU_TESS_END,    (void*)glEnd);
37         for (int pi = 0; points[pi]; pi++) {
38                 gluTessBeginPolygon(tess, NULL);
39                 gluTessBeginContour(tess);
40                 for (int ci = 0; points[pi][ci][0]; ci++) {
41                         gluTessVertex(tess,
42                                 points[pi][ci],
43                                 points[pi][ci]);
44                 }
45                 gluTessEndContour(tess);
46                 gluTessEndPolygon(tess);
47         }
48         gluDeleteTess(tess);
49 }
50
51 static void grits_poly_outline(gdouble (**points)[3])
52 {
53         //g_debug("GritsPoly: outline");
54         for (int pi = 0; points[pi]; pi++) {
55                 glBegin(GL_POLYGON);
56                 for (int ci = 0; points[pi][ci][0] &&
57                                  points[pi][ci][1] &&
58                                  points[pi][ci][2]; ci++)
59                         glVertex3dv(points[pi][ci]);
60                 glEnd();
61         }
62 }
63
64 static gboolean grits_poly_runlist(GritsPoly *poly, int i,
65                 void (*render)(gdouble(**)[3]))
66 {
67         if (poly->list[i]) {
68                 glCallList(poly->list[i]);
69         } else {
70                 guint list = glGenLists(1);
71                 glNewList(list, GL_COMPILE_AND_EXECUTE);
72                 render(poly->points);
73                 glEndList();
74                 poly->list[i] = list;
75                 //g_debug("GritsPoly: genlist");
76         }
77         return FALSE;
78 }
79
80 static void grits_poly_draw(GritsObject *_poly, GritsOpenGL *opengl)
81 {
82         //g_debug("GritsPoly: draw");
83         GritsPoly *poly = GRITS_POLY(_poly);
84
85         glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT |
86                         GL_POINT_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
87         glDisable(GL_TEXTURE_2D);
88         glDisable(GL_ALPHA_TEST);
89         glDisable(GL_CULL_FACE);
90         glDisable(GL_LIGHTING);
91
92         glEnable(GL_POLYGON_OFFSET_FILL);
93         glEnable(GL_POLYGON_OFFSET_LINE);
94         glEnable(GL_POLYGON_OFFSET_POINT);
95
96         if (poly->color[3]) {
97                 /* Draw background farthest back */
98                 glPolygonOffset(3, 3);
99                 glColor4dv(poly->color);
100                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
101                 grits_poly_runlist(poly, 0, grits_poly_tess);
102         }
103
104         glEnable(GL_POLYGON_SMOOTH);
105         glEnable(GL_LINE_SMOOTH);
106         glEnable(GL_POINT_SMOOTH);
107
108         if (!poly->color[3] && poly->border[3] && poly->width > 1) {
109                 /* Draw line border in the middle */
110                 glColor4d(0,0,0,1);
111
112                 glPointSize(poly->width*2);
113                 glLineWidth(poly->width*2);
114
115                 glPolygonOffset(2, 2);
116
117                 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
118                 grits_poly_runlist(poly, 1, grits_poly_outline);
119                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
120                 grits_poly_runlist(poly, 1, grits_poly_outline);
121         }
122
123         if (poly->border[3]) {
124                 /* Draw border front-most */
125                 glColor4dv(poly->border);
126
127                 glPointSize(poly->width);
128                 glLineWidth(poly->width);
129
130                 glPolygonOffset(1, 1);
131                 if (poly->width > 1) {
132                         glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
133                         grits_poly_runlist(poly, 1, grits_poly_outline);
134                 }
135                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
136                 grits_poly_runlist(poly, 1, grits_poly_outline);
137         }
138
139         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
140         glPopAttrib();
141 }
142
143 static void grits_poly_pick(GritsObject *_poly, GritsOpenGL *opengl)
144 {
145         //g_debug("GritsPoly: pick");
146         GritsPoly *poly = GRITS_POLY(_poly);
147         glPushAttrib(GL_ENABLE_BIT);
148         glDisable(GL_CULL_FACE);
149         grits_poly_runlist(poly, 0, grits_poly_tess);
150         glPopAttrib();
151 }
152
153 static gboolean grits_poly_delete(gpointer list)
154 {
155         glDeleteLists((guintptr)list, 1);
156         return FALSE;
157 }
158
159 /**
160  * grits_poly_new:
161  * @points:  TODO
162  * @npoints: TODO
163  *
164  * Create a new GritsPoly which TODO.
165  *
166  * Returns: the new #GritsPoly.
167  */
168 GritsPoly *grits_poly_new(gdouble (**points)[3])
169 {
170         //g_debug("GritsPoly: new - %p", points);
171         GritsPoly *poly = g_object_new(GRITS_TYPE_POLY, NULL);
172         poly->points    = points;
173         return poly;
174 }
175
176 GritsPoly *grits_poly_parse(const gchar *str,
177                 const gchar *poly_sep, const gchar *point_sep, const gchar *coord_sep)
178 {
179         GritsPoint center;
180         gdouble (**polys)[3] = parse_points(str,
181                         poly_sep, point_sep, coord_sep, NULL, &center);
182
183         GritsPoly *poly = grits_poly_new(polys);
184         GRITS_OBJECT(poly)->center = center;
185         GRITS_OBJECT(poly)->skip   = GRITS_SKIP_CENTER;
186         g_object_weak_ref(G_OBJECT(poly), (GWeakNotify)free_points, polys);
187         return poly;
188 }
189
190 /* GObject code */
191 G_DEFINE_TYPE(GritsPoly, grits_poly, GRITS_TYPE_OBJECT);
192 static void grits_poly_init(GritsPoly *poly)
193 {
194         poly->border[0] = 1;
195         poly->border[1] = 1;
196         poly->border[2] = 1;
197         poly->border[3] = 0.2;
198         poly->width     = 1;
199         GRITS_OBJECT(poly)->skip = GRITS_SKIP_STATE;
200 }
201
202 static void grits_poly_finalize(GObject *_poly)
203 {
204         //g_debug("GritsPoly: finalize");
205         GritsPoly *poly = GRITS_POLY(_poly);
206         if (poly->list[0]) g_idle_add(grits_poly_delete, (gpointer)(guintptr)poly->list[0]);
207         if (poly->list[1]) g_idle_add(grits_poly_delete, (gpointer)(guintptr)poly->list[1]);
208 }
209
210 static void grits_poly_class_init(GritsPolyClass *klass)
211 {
212         g_debug("GritsPoly: class_init");
213         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
214         gobject_class->finalize = grits_poly_finalize;
215
216         GritsObjectClass *object_class = GRITS_OBJECT_CLASS(klass);
217         object_class->draw = grits_poly_draw;
218         object_class->pick = grits_poly_pick;
219 }