From f93aa6df36b91a106bd9be7e8dd60b83b0f6a0cb Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Wed, 3 Feb 2010 09:02:05 +0000 Subject: [PATCH] Convert GisTile to GisObject - This lets us remove the special gis_veiwer_render_tile[s] interfaces. - We might want to add back in a similar gis_viewer_draw_object at some point. --- src/Makefile.am | 1 + src/gis-opengl.c | 172 ++++++++++++++++++++++----------------------- src/gis-tile.c | 9 ++- src/gis-tile.h | 39 ++++++---- src/gis-viewer.c | 16 ----- src/gis-viewer.h | 6 -- src/plugins/elev.c | 14 +--- src/plugins/env.c | 4 +- src/plugins/map.c | 12 +--- src/plugins/sat.c | 12 +--- 10 files changed, 124 insertions(+), 161 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d55f814..67923f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,6 +52,7 @@ gis_demo_LDFLAGS = -static tile_test_SOURCES = tile-test.c \ gis-util.c gis-util.h \ gis-tile.c gis-tile.h \ + gis-object.c gis-object.h \ gis-wms.c gis-wms.h tile_test_LDADD = $(AM_LDADD) diff --git a/src/gis-opengl.c b/src/gis-opengl.c index 7263ef4..f420e75 100644 --- a/src/gis-opengl.c +++ b/src/gis-opengl.c @@ -128,6 +128,89 @@ static void _set_visuals(GisOpenGL *self) /******************** * Object handleing * ********************/ +static void _draw_tile(GisOpenGL *self, GisTile *tile) +{ + if (!tile || !tile->data) + return; + GList *triangles = roam_sphere_get_intersect(self->sphere, FALSE, + tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); + if (!triangles) + g_warning("GisOpenGL: _draw_tiles - No triangles to draw: edges=%f,%f,%f,%f", + tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); + //g_message("drawing %4d triangles for tile edges=%7.2f,%7.2f,%7.2f,%7.2f", + // g_list_length(triangles), tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); + for (GList *cur = triangles; cur; cur = cur->next) { + RoamTriangle *tri = cur->data; + + gdouble lat[3] = {tri->p.r->lat, tri->p.m->lat, tri->p.l->lat}; + gdouble lon[3] = {tri->p.r->lon, tri->p.m->lon, tri->p.l->lon}; + + if (lon[0] < -90 || lon[1] < -90 || lon[2] < -90) { + if (lon[0] > 90) lon[0] -= 360; + if (lon[1] > 90) lon[1] -= 360; + if (lon[2] > 90) lon[2] -= 360; + } + + gdouble n = tile->edge.n; + gdouble s = tile->edge.s; + gdouble e = tile->edge.e; + gdouble w = tile->edge.w; + + gdouble londist = e - w; + gdouble latdist = n - s; + + gdouble xy[3][2] = { + {(lon[0]-w)/londist, 1-(lat[0]-s)/latdist}, + {(lon[1]-w)/londist, 1-(lat[1]-s)/latdist}, + {(lon[2]-w)/londist, 1-(lat[2]-s)/latdist}, + }; + + //if ((lat[0] == 90 && (xy[0][0] < 0 || xy[0][0] > 1)) || + // (lat[1] == 90 && (xy[1][0] < 0 || xy[1][0] > 1)) || + // (lat[2] == 90 && (xy[2][0] < 0 || xy[2][0] > 1))) + // g_message("w,e=%4.f,%4.f " + // "lat,lon,x,y=" + // "%4.1f,%4.0f,%4.2f,%4.2f " + // "%4.1f,%4.0f,%4.2f,%4.2f " + // "%4.1f,%4.0f,%4.2f,%4.2f ", + // w,e, + // lat[0], lon[0], xy[0][0], xy[0][1], + // lat[1], lon[1], xy[1][0], xy[1][1], + // lat[2], lon[2], xy[2][0], xy[2][1]); + + /* Fix poles */ + if (lat[0] == 90 || lat[0] == -90) xy[0][0] = 0.5; + if (lat[1] == 90 || lat[1] == -90) xy[1][0] = 0.5; + if (lat[2] == 90 || lat[2] == -90) xy[2][0] = 0.5; + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data); + glBegin(GL_TRIANGLES); + glNormal3dv(tri->p.r->norm); glTexCoord2dv(xy[0]); glVertex3dv((double*)tri->p.r); + glNormal3dv(tri->p.m->norm); glTexCoord2dv(xy[1]); glVertex3dv((double*)tri->p.m); + glNormal3dv(tri->p.l->norm); glTexCoord2dv(xy[2]); glVertex3dv((double*)tri->p.l); + glEnd(); + } + g_list_free(triangles); +} + +static void _draw_tiles(GisOpenGL *self, GisTile *tile) +{ + /* Only draw children if possible */ + gboolean has_children = TRUE; + GisTile *child; + gis_tile_foreach(tile, child) + if (!child || !child->data) + has_children = FALSE; + if (has_children) + /* Only draw children */ + gis_tile_foreach(tile, child) + _draw_tiles(self, child); + else + /* No children, draw this tile */ + _draw_tile(self, tile); +} + static void _draw_marker(GisOpenGL *self, GisMarker *marker) { GisPoint *point = gis_object_center(GIS_OBJECT(marker)); @@ -192,6 +275,8 @@ static void _draw_object(GisOpenGL *self, GisObject *object) _draw_marker(self, GIS_MARKER(object)); } else if (GIS_IS_CALLBACK(object)) { _draw_callback(self, GIS_CALLBACK(object)); + } else if (GIS_IS_TILE(object)) { + _draw_tiles(self, GIS_TILE(object)); } glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -429,91 +514,6 @@ static void gis_opengl_project(GisViewer *_self, px, py, pz); } -static void gis_opengl_render_tile(GisViewer *_self, GisTile *tile) -{ - GisOpenGL *self = GIS_OPENGL(_self); - if (!tile || !tile->data) - return; - GList *triangles = roam_sphere_get_intersect(self->sphere, FALSE, - tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); - if (!triangles) - g_warning("GisOpenGL: render_tiles - No triangles to draw: edges=%f,%f,%f,%f", - tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); - //g_message("rendering %4d triangles for tile edges=%7.2f,%7.2f,%7.2f,%7.2f", - // g_list_length(triangles), tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); - for (GList *cur = triangles; cur; cur = cur->next) { - RoamTriangle *tri = cur->data; - - gdouble lat[3] = {tri->p.r->lat, tri->p.m->lat, tri->p.l->lat}; - gdouble lon[3] = {tri->p.r->lon, tri->p.m->lon, tri->p.l->lon}; - - if (lon[0] < -90 || lon[1] < -90 || lon[2] < -90) { - if (lon[0] > 90) lon[0] -= 360; - if (lon[1] > 90) lon[1] -= 360; - if (lon[2] > 90) lon[2] -= 360; - } - - gdouble n = tile->edge.n; - gdouble s = tile->edge.s; - gdouble e = tile->edge.e; - gdouble w = tile->edge.w; - - gdouble londist = e - w; - gdouble latdist = n - s; - - gdouble xy[3][2] = { - {(lon[0]-w)/londist, 1-(lat[0]-s)/latdist}, - {(lon[1]-w)/londist, 1-(lat[1]-s)/latdist}, - {(lon[2]-w)/londist, 1-(lat[2]-s)/latdist}, - }; - - //if ((lat[0] == 90 && (xy[0][0] < 0 || xy[0][0] > 1)) || - // (lat[1] == 90 && (xy[1][0] < 0 || xy[1][0] > 1)) || - // (lat[2] == 90 && (xy[2][0] < 0 || xy[2][0] > 1))) - // g_message("w,e=%4.f,%4.f " - // "lat,lon,x,y=" - // "%4.1f,%4.0f,%4.2f,%4.2f " - // "%4.1f,%4.0f,%4.2f,%4.2f " - // "%4.1f,%4.0f,%4.2f,%4.2f ", - // w,e, - // lat[0], lon[0], xy[0][0], xy[0][1], - // lat[1], lon[1], xy[1][0], xy[1][1], - // lat[2], lon[2], xy[2][0], xy[2][1]); - - /* Fix poles */ - if (lat[0] == 90 || lat[0] == -90) xy[0][0] = 0.5; - if (lat[1] == 90 || lat[1] == -90) xy[1][0] = 0.5; - if (lat[2] == 90 || lat[2] == -90) xy[2][0] = 0.5; - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data); - glBegin(GL_TRIANGLES); - glNormal3dv(tri->p.r->norm); glTexCoord2dv(xy[0]); glVertex3dv((double*)tri->p.r); - glNormal3dv(tri->p.m->norm); glTexCoord2dv(xy[1]); glVertex3dv((double*)tri->p.m); - glNormal3dv(tri->p.l->norm); glTexCoord2dv(xy[2]); glVertex3dv((double*)tri->p.l); - glEnd(); - } - g_list_free(triangles); -} - -static void gis_opengl_render_tiles(GisViewer *_self, GisTile *tile) -{ - GisOpenGL *self = GIS_OPENGL(_self); - /* Only render children if possible */ - gboolean has_children = TRUE; - GisTile *child; - gis_tile_foreach(tile, child) - if (!child || !child->data) - has_children = FALSE; - if (has_children) - /* Only render children */ - gis_tile_foreach(tile, child) - gis_opengl_render_tiles(_self, child); - else - /* No children, render this tile */ - gis_opengl_render_tile(_self, tile); -} - static void gis_opengl_set_height_func(GisViewer *_self, GisTile *tile, RoamHeightFunc height_func, gpointer user_data, gboolean update) { @@ -683,8 +683,6 @@ static void gis_opengl_class_init(GisOpenGLClass *klass) viewer_class->project = gis_opengl_project; viewer_class->clear_height_func = gis_opengl_clear_height_func; viewer_class->set_height_func = gis_opengl_set_height_func; - viewer_class->render_tile = gis_opengl_render_tile; - viewer_class->render_tiles = gis_opengl_render_tiles; viewer_class->begin = gis_opengl_begin; viewer_class->end = gis_opengl_end; viewer_class->add = gis_opengl_add; diff --git a/src/gis-tile.c b/src/gis-tile.c index d92f7b5..cf3f857 100644 --- a/src/gis-tile.c +++ b/src/gis-tile.c @@ -29,7 +29,7 @@ gchar *gis_tile_path_table[2][2] = { GisTile *gis_tile_new(GisTile *parent, gdouble n, gdouble s, gdouble e, gdouble w) { - GisTile *self = g_new0(GisTile, 1); + GisTile *self = g_object_new(GIS_TYPE_TILE, NULL); self->parent = parent; self->edge.n = n; self->edge.s = s; @@ -190,5 +190,10 @@ void gis_tile_free(GisTile *self, GisTileFreeFunc free_func, gpointer user_data) gis_tile_free(child, free_func, user_data); if (free_func) free_func(self, user_data); - g_free(self); + g_object_unref(self); } + +/* GObject code */ +G_DEFINE_TYPE(GisTile, gis_tile, GIS_TYPE_OBJECT); +static void gis_tile_init(GisTile *self) { } +static void gis_tile_class_init(GisTileClass *klass) { } diff --git a/src/gis-tile.h b/src/gis-tile.h index dc571ac..b7e9123 100644 --- a/src/gis-tile.h +++ b/src/gis-tile.h @@ -19,22 +19,18 @@ #define __GIS_TILE_H__ #include +#include "gis-object.h" -typedef struct _GisTile GisTile; +#define GIS_TYPE_TILE (gis_tile_get_type()) -#define gis_tile_foreach(tile, child) \ - for (int _x = 0; _x < G_N_ELEMENTS(tile->children); _x++) \ - for (int _y = 0; child = tile->children[_x][_y], \ - _y < G_N_ELEMENTS(tile->children[_x]); _y++) \ - -#define gis_tile_foreach_index(tile, x, y) \ - for (x = 0; x < G_N_ELEMENTS(tile->children); x++) \ - for (y = 0; y < G_N_ELEMENTS(tile->children[x]); y++) - -typedef void (*GisTileLoadFunc)(GisTile *tile, gpointer user_data); -typedef void (*GisTileFreeFunc)(GisTile *tile, gpointer user_data); +GOBJECT_HEAD( + GIS, TILE, + Gis, Tile, + gis, tile); struct _GisTile { + GisObject parent_instance; + /* Pointer to the tile data */ gpointer data; @@ -51,7 +47,24 @@ struct _GisTile { time_t atime; }; -/* Path to string table, keep in sync with tile->children */ +struct _GisTileClass { + GisObjectClass parent_class; +}; + +typedef void (*GisTileLoadFunc)(GisTile *tile, gpointer user_data); +typedef void (*GisTileFreeFunc)(GisTile *tile, gpointer user_data); + +/* Forech functions */ +#define gis_tile_foreach(tile, child) \ + for (int _x = 0; _x < G_N_ELEMENTS(tile->children); _x++) \ + for (int _y = 0; child = tile->children[_x][_y], \ + _y < G_N_ELEMENTS(tile->children[_x]); _y++) \ + +#define gis_tile_foreach_index(tile, x, y) \ + for (x = 0; x < G_N_ELEMENTS(tile->children); x++) \ + for (y = 0; y < G_N_ELEMENTS(tile->children[x]); y++) + +/* Path to string table, keep in sync with tile->children */ extern gchar *gis_tile_path_table[2][2]; /* Allocate a new Tile */ diff --git a/src/gis-viewer.c b/src/gis-viewer.c index f85f609..e7e772f 100644 --- a/src/gis-viewer.c +++ b/src/gis-viewer.c @@ -271,22 +271,6 @@ void gis_viewer_set_height_func(GisViewer *self, GisTile *tile, klass->set_height_func(self, tile, height_func, user_data, update); } -void gis_viewer_render_tile(GisViewer *self, GisTile *tile) -{ - GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self); - if (!klass->render_tile) - g_warning("GisViewer: render_tile - Unimplemented"); - klass->render_tile(self, tile); -} - -void gis_viewer_render_tiles(GisViewer *self, GisTile *root) -{ - GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self); - if (!klass->render_tiles) - g_warning("GisViewer: render_tiles - Unimplemented"); - klass->render_tiles(self, root); -} - void gis_viewer_begin(GisViewer *self) { GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self); diff --git a/src/gis-viewer.h b/src/gis-viewer.h index 02596f3..89b9583 100644 --- a/src/gis-viewer.h +++ b/src/gis-viewer.h @@ -73,9 +73,6 @@ struct _GisViewerClass { GisHeightFunc height_func, gpointer user_data, gboolean update); - void (*render_tile) (GisViewer *viewer, GisTile *tile); - void (*render_tiles) (GisViewer *viewer, GisTile *root); - void (*begin) (GisViewer *viewer); void (*end) (GisViewer *viewer); @@ -119,9 +116,6 @@ void gis_viewer_set_height_func(GisViewer *self, GisTile *tile, GisHeightFunc height_func, gpointer user_data, gboolean update); -void gis_viewer_render_tile (GisViewer *viewer, GisTile *tile); -void gis_viewer_render_tiles(GisViewer *viewer, GisTile *root); - void gis_viewer_begin(GisViewer *viewer); void gis_viewer_end (GisViewer *viewer); diff --git a/src/plugins/elev.c b/src/plugins/elev.c index 4c28847..65f3b82 100644 --- a/src/plugins/elev.c +++ b/src/plugins/elev.c @@ -258,16 +258,6 @@ static void _on_location_changed(GisViewer *viewer, g_thread_create(_update_tiles, self, FALSE, NULL); } -static gpointer _expose(GisCallback *callback, gpointer _self) -{ - GisPluginElev *self = GIS_PLUGIN_ELEV(_self); - g_debug("GisPluginElev: expose tiles=%p data=%p", - self->tiles, self->tiles->data); - if (LOAD_OPENGL) - gis_viewer_render_tiles(self->viewer, self->tiles); - return NULL; -} - /*********** * Methods * ***********/ @@ -286,8 +276,8 @@ GisPluginElev *gis_plugin_elev_new(GisViewer *viewer) G_CALLBACK(_on_location_changed), self); /* Add renderers */ - GisCallback *callback = gis_callback_new(_expose, self); - gis_viewer_add(viewer, GIS_OBJECT(callback), GIS_LEVEL_WORLD, 0); + if (LOAD_OPENGL) + gis_viewer_add(viewer, GIS_OBJECT(self->tiles), GIS_LEVEL_WORLD, 0); return self; } diff --git a/src/plugins/env.c b/src/plugins/env.c index e0d916a..4c25fc2 100644 --- a/src/plugins/env.c +++ b/src/plugins/env.c @@ -40,9 +40,6 @@ static gpointer expose(GisCallback *callback, gpointer _self) glClearColor(MIN(0.65,rg), MIN(0.65,rg), MIN(1,blue), 1.0f); glClear(GL_COLOR_BUFFER_BIT); - /* Clear the earth */ - gis_viewer_render_tile(self->viewer, self->background); - /* Attempt to render an atmosphere */ /* glEnable(GL_COLOR_MATERIAL); @@ -92,6 +89,7 @@ GisPluginEnv *gis_plugin_env_new(GisViewer *viewer, GisPrefs *prefs) /* Add renderers */ GisCallback *callback = gis_callback_new(expose, self); gis_viewer_add(viewer, GIS_OBJECT(callback), GIS_LEVEL_BACKGROUND, 0); + gis_viewer_add(viewer, GIS_OBJECT(self->background), GIS_LEVEL_BACKGROUND, 0); return self; } diff --git a/src/plugins/map.c b/src/plugins/map.c index b39ae34..6c0b57d 100644 --- a/src/plugins/map.c +++ b/src/plugins/map.c @@ -150,15 +150,6 @@ static void _on_location_changed(GisViewer *viewer, g_thread_create(_update_tiles, self, FALSE, NULL); } -static gpointer _expose(GisCallback *callback, gpointer _self) -{ - GisPluginMap *self = GIS_PLUGIN_MAP(_self); - g_debug("GisPluginMap: expose viewer=%p tiles=%p,%p", - self->viewer, self->tiles, self->tiles->data); - gis_viewer_render_tiles(self->viewer, self->tiles); - return NULL; -} - /*********** * Methods * ***********/ @@ -177,8 +168,7 @@ GisPluginMap *gis_plugin_map_new(GisViewer *viewer) G_CALLBACK(_on_location_changed), self); /* Add renderers */ - GisCallback *callback = gis_callback_new(_expose, self); - gis_viewer_add(viewer, GIS_OBJECT(callback), GIS_LEVEL_OVERLAY, 0); + gis_viewer_add(viewer, GIS_OBJECT(self->tiles), GIS_LEVEL_OVERLAY, 0); return self; } diff --git a/src/plugins/sat.c b/src/plugins/sat.c index d65f833..9ce831b 100644 --- a/src/plugins/sat.c +++ b/src/plugins/sat.c @@ -128,15 +128,6 @@ static void _on_location_changed(GisViewer *viewer, g_thread_create(_update_tiles, self, FALSE, NULL); } -static gpointer _expose(GisCallback *callback, gpointer _self) -{ - GisPluginSat *self = GIS_PLUGIN_SAT(_self); - g_debug("GisPluginSat: expose viewer=%p tiles=%p,%p", - self->viewer, self->tiles, self->tiles->data); - gis_viewer_render_tiles(self->viewer, self->tiles); - return NULL; -} - /*********** * Methods * ***********/ @@ -155,8 +146,7 @@ GisPluginSat *gis_plugin_sat_new(GisViewer *viewer) G_CALLBACK(_on_location_changed), self); /* Add renderers */ - GisCallback *callback = gis_callback_new(_expose, self); - gis_viewer_add(viewer, GIS_OBJECT(callback), GIS_LEVEL_WORLD, 0); + gis_viewer_add(viewer, GIS_OBJECT(self->tiles), GIS_LEVEL_WORLD, 0); return self; } -- 2.43.2