X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=src%2Fobjects%2Fgrits-poly.c;h=67dca9a9156302f1fe84c83f55c376dfc0529d60;hb=156f921ad641a2f89d0355383d8e53a316edaa9a;hp=da35b36c792333b7d043a174253f8be137997c3a;hpb=1d0635977583ad84faaa1978f1fd78fa3ec83052;p=grits diff --git a/src/objects/grits-poly.c b/src/objects/grits-poly.c index da35b36..67dca9a 100644 --- a/src/objects/grits-poly.c +++ b/src/objects/grits-poly.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andy Spencer + * Copyright (C) 2010-2011 Andy Spencer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,8 +35,8 @@ static void grits_poly_tess(gdouble (**points)[3]) gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)glBegin); gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)glVertex3dv); gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)glEnd); - gluTessBeginPolygon(tess, NULL); for (int pi = 0; points[pi]; pi++) { + gluTessBeginPolygon(tess, NULL); gluTessBeginContour(tess); for (int ci = 0; points[pi][ci][0]; ci++) { gluTessVertex(tess, @@ -44,8 +44,8 @@ static void grits_poly_tess(gdouble (**points)[3]) points[pi][ci]); } gluTessEndContour(tess); + gluTessEndPolygon(tess); } - gluTessEndPolygon(tess); gluDeleteTess(tess); } @@ -53,13 +53,7 @@ static void grits_poly_outline(gdouble (**points)[3]) { //g_debug("GritsPoly: outline"); for (int pi = 0; points[pi]; pi++) { - glBegin(GL_LINE_LOOP); - for (int ci = 0; points[pi][ci][0] && - points[pi][ci][1] && - points[pi][ci][2]; ci++) - glVertex3dv(points[pi][ci]); - glEnd(); - glBegin(GL_POINTS); + glBegin(GL_POLYGON); for (int ci = 0; points[pi][ci][0] && points[pi][ci][1] && points[pi][ci][2]; ci++) @@ -67,18 +61,20 @@ static void grits_poly_outline(gdouble (**points)[3]) glEnd(); } } -static gboolean grits_poly_genlist(gpointer _poly) + +static gboolean grits_poly_runlist(GritsPoly *poly, int i, + void (*render)(gdouble(**)[3])) { //g_debug("GritsPoly: genlist"); - GritsPoly *poly = GRITS_POLY(_poly); - guint list = glGenLists(2); - glNewList(list+0, GL_COMPILE); - grits_poly_tess(poly->points); - glEndList(); - glNewList(list+1, GL_COMPILE); - grits_poly_outline(poly->points); - glEndList(); - poly->list = list; + if (poly->list[i]) { + glCallList(poly->list[i]); + } else { + guint list = glGenLists(1); + glNewList(list, GL_COMPILE_AND_EXECUTE); + render(poly->points); + glEndList(); + poly->list[i] = list; + } return FALSE; } @@ -87,26 +83,61 @@ static void grits_poly_draw(GritsObject *_poly, GritsOpenGL *opengl) //g_debug("GritsPoly: draw"); GritsPoly *poly = GRITS_POLY(_poly); - if (!poly->list) - return; - - glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT); + glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT | + GL_POINT_BIT | GL_LINE_BIT | GL_POLYGON_BIT); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); + glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1, 1); + glEnable(GL_POLYGON_OFFSET_LINE); + glEnable(GL_POLYGON_OFFSET_POINT); + if (poly->color[3]) { + /* Draw background farthest back */ + glPolygonOffset(3, 3); glColor4dv(poly->color); - glCallList(poly->list+0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + grits_poly_runlist(poly, 0, grits_poly_tess); } + + glEnable(GL_POLYGON_SMOOTH); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_POINT_SMOOTH); + + if (!poly->color[3] && poly->border[3] && poly->width > 1) { + /* Draw line border in the middle */ + glColor4d(0,0,0,1); + + glPointSize(poly->width*2); + glLineWidth(poly->width*2); + + glPolygonOffset(2, 2); + + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + grits_poly_runlist(poly, 1, grits_poly_outline); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + grits_poly_runlist(poly, 1, grits_poly_outline); + } + if (poly->border[3]) { + /* Draw border front-most */ + glColor4dv(poly->border); + glPointSize(poly->width); glLineWidth(poly->width); - glColor4dv(poly->border); - glCallList(poly->list+1); + + glPolygonOffset(1, 1); + if (poly->width > 1) { + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + grits_poly_runlist(poly, 1, grits_poly_outline); + } + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + grits_poly_runlist(poly, 1, grits_poly_outline); } + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPopAttrib(); } @@ -114,14 +145,18 @@ static void grits_poly_pick(GritsObject *_poly, GritsOpenGL *opengl) { //g_debug("GritsPoly: pick"); GritsPoly *poly = GRITS_POLY(_poly); - if (!poly->list) - return; glPushAttrib(GL_ENABLE_BIT); glDisable(GL_CULL_FACE); - glCallList(poly->list+0); + grits_poly_runlist(poly, 0, grits_poly_tess); glPopAttrib(); } +static gboolean grits_poly_delete(gpointer list) +{ + glDeleteLists((guintptr)list, 1); + return FALSE; +} + /** * grits_poly_new: * @points: TODO @@ -136,10 +171,16 @@ GritsPoly *grits_poly_new(gdouble (**points)[3]) //g_debug("GritsPoly: new - %p", points); GritsPoly *poly = g_object_new(GRITS_TYPE_POLY, NULL); poly->points = points; - g_idle_add(grits_poly_genlist, poly); return poly; } +static void _free_points(gdouble (**points)[3]) +{ + for (int i = 0; points[i]; i++) + g_free(points[i]); + g_free(points); +} + GritsPoly *grits_poly_parse(const gchar *str, const gchar *poly_sep, const gchar *point_sep, const gchar *coord_sep) { @@ -173,6 +214,7 @@ GritsPoly *grits_poly_parse(const gchar *str, polys[pi] = coords; g_strfreev(scoords); } + g_strfreev(spolys); /* Create GritsPoly */ GritsPoly *poly = grits_poly_new(polys); @@ -180,6 +222,7 @@ GritsPoly *grits_poly_parse(const gchar *str, GRITS_OBJECT(poly)->center.lon = lon_avg(bounds.e, bounds.w); GRITS_OBJECT(poly)->center.elev = 0; GRITS_OBJECT(poly)->skip = GRITS_SKIP_CENTER; + g_object_weak_ref(G_OBJECT(poly), (GWeakNotify)_free_points, polys); return poly; } @@ -192,14 +235,15 @@ static void grits_poly_init(GritsPoly *poly) poly->border[2] = 1; poly->border[3] = 0.2; poly->width = 1; + GRITS_OBJECT(poly)->skip = GRITS_SKIP_STATE; } static void grits_poly_finalize(GObject *_poly) { - g_debug("GritsPoly: finalize"); + //g_debug("GritsPoly: finalize"); GritsPoly *poly = GRITS_POLY(_poly); - (void)poly; - // TODO: free points + if (poly->list[0]) g_idle_add(grits_poly_delete, (gpointer)(guintptr)poly->list[0]); + if (poly->list[1]) g_idle_add(grits_poly_delete, (gpointer)(guintptr)poly->list[1]); } static void grits_poly_class_init(GritsPolyClass *klass)