]> Pileus Git - grits/commitdiff
Markers as individual textures
authorAndy Spencer <andy753421@gmail.com>
Sun, 15 Nov 2009 08:10:49 +0000 (08:10 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sun, 15 Nov 2009 08:10:49 +0000 (08:10 +0000)
src/gis-object.c
src/gis-object.h
src/gis-opengl.c
src/gis-opengl.h
src/gis-viewer.c
src/gis-viewer.h
src/gis_test.c
src/plugins/test.c

index 8c041b7a706bc08da491ea800dbc18e12c8374fe..cfd1870f137ab62456aa658b9177cf937ab316e5 100644 (file)
@@ -145,14 +145,30 @@ void gis_callback_free(GisCallback *self)
 /* GisCallback */
 GisMarker *gis_marker_new(const gchar *label)
 {
+       static const int RADIUS =   4;
+       static const int WIDTH  = 100;
+       static const int HEIGHT =  20;
+
        GisMarker *self = g_new0(GisMarker, 1);
        GIS_OBJECT(self)->type = GIS_TYPE_MARKER;
-       self->label = g_strdup(label);;
+       self->xoff  = RADIUS;
+       self->yoff  = HEIGHT-RADIUS;
+       self->label = g_strdup(label);
+       self->cairo = cairo_create(cairo_image_surface_create(
+                               CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT));
+       cairo_set_source_rgba(self->cairo, 1, 1, 1, 1);
+       cairo_arc(self->cairo, self->xoff, self->yoff, RADIUS, 0, 2*G_PI);
+       cairo_fill(self->cairo);
+       cairo_move_to(self->cairo, self->xoff+4, self->yoff-8);
+       cairo_set_font_size(self->cairo, 10);
+       cairo_show_text(self->cairo, self->label);
        return self;
 }
 
 void gis_marker_free(GisMarker *self)
 {
+       cairo_surface_destroy(cairo_get_target(self->cairo));
+       cairo_destroy(self->cairo);
        g_free(self->label);
        g_free(self);
 }
index f5ab5a8c13c310094e3cbef5ef7cab333a6c16a4..a58b8157b5d7cf604f5022f8a55b3fa98166ef3e 100644 (file)
@@ -19,6 +19,7 @@
 #define __GIS_OBJECT_H__
 
 #include <glib.h>
+#include <cairo.h>
 
 /* Base types */
 typedef struct _GisProjection GisProjection;
@@ -99,7 +100,10 @@ struct _GisCallback {
 };
 struct _GisMarker   {
        GisObject  parent;
+       gint       xoff, yoff;
        gchar     *label;
+       cairo_t   *cairo;
+       guint      tex;
 };
 
 /* Support functions */
index 6b70f14a53c1638946d2d6c263bb8f183881917c..0bcde3d9279a288ce45a36ac4606dfa6a6a43e01 100644 (file)
 #define MPPX(dist) (4*dist/FOV_DIST)
 
 // #define ROAM_DEBUG
-/******************
- * Object drawing *
- ******************/
-static void _gis_opengl_draw_triangle(GisOpenGL *self, GisTriangle *tri)
-{
-}
 
-static void _gis_opengl_draw_quad(GisOpenGL *self, GisQuad *quad)
+/***********
+ * Helpers *
+ ***********/
+static void _gis_opengl_begin(GisOpenGL *self)
 {
+       g_assert(GIS_IS_OPENGL(self));
+
+       GdkGLContext   *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(self));
+       GdkGLDrawable  *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
+
+       if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
+               g_assert_not_reached();
 }
 
-static void _gis_opengl_draw_callback(GisOpenGL *self, GisCallback *cb)
+static void _gis_opengl_end(GisOpenGL *self)
 {
+       g_assert(GIS_IS_OPENGL(self));
+       GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
+       gdk_gl_drawable_gl_end(gldrawable);
 }
 
-static void _gis_opengl_draw_marker(GisOpenGL *self, GisMarker *marker)
+
+/********************
+ * Object handleing *
+ ********************/
+static void _draw_marker(GisOpenGL *self, GisMarker *marker)
 {
        GisProjection *proj = (GisProjection*)self->sphere->view;
        GisPoint *point = gis_object_center(marker);
        gis_point_project(point, proj);
 
-       double width  = GTK_WIDGET(self)->allocation.width;
-       double height = GTK_WIDGET(self)->allocation.height;
+       g_debug("GisOpenGL: draw_marker - texture=%d", marker->tex);
 
-       cairo_set_source_rgba(self->canvas, 1, 1, 1, 1);
-       cairo_arc(self->canvas, point->px, height-point->py, 4, 0, 2*G_PI);
-       cairo_fill(self->canvas);
-       cairo_move_to(self->canvas, point->px+4, height-point->py-8);
-       cairo_set_font_size(self->canvas, 10);
-       cairo_show_text(self->canvas, marker->label);
-}
-
-static void gis_opengl_draw_object(GisOpenGL *self, GisObject *object)
-{
-       g_debug("GisOpenGL: draw_object - Drawing object of type %d", object->type);
-       switch (object->type) {
-       case GIS_TYPE_TRIANGLE: _gis_opengl_draw_triangle(self, GIS_TRIANGLE(object)); break;
-       case GIS_TYPE_QUAD    : _gis_opengl_draw_quad    (self, GIS_QUAD    (object)); break;
-       case GIS_TYPE_CALLBACK: _gis_opengl_draw_callback(self, GIS_CALLBACK(object)); break;
-       case GIS_TYPE_MARKER  : _gis_opengl_draw_marker  (self, GIS_MARKER  (object)); break;
-       default: g_warning("GisOpenGL: draw_object - invalid type %d", object->type);
-       }
-}
-static void gis_opengl_draw_objects(GisOpenGL *self)
-{
-       g_debug("GisOpenGL: draw_objects");
+       cairo_surface_t *surface = cairo_get_target(marker->cairo);
+       gdouble width  = cairo_image_surface_get_width(surface);
+       gdouble height = cairo_image_surface_get_height(surface);
 
-       double width  = GTK_WIDGET(self)->allocation.width;
-       double height = GTK_WIDGET(self)->allocation.height;
-       cairo_surface_t *surface = cairo_get_target(self->canvas);
-       int stride = cairo_image_surface_get_stride(surface);
-       guchar *data = cairo_image_surface_get_data(surface);
-       memset(data, 0, height*stride);
+       glMatrixMode(GL_PROJECTION); glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);  glLoadIdentity();
+       glOrtho(0, GTK_WIDGET(self)->allocation.width,
+               0, GTK_WIDGET(self)->allocation.height, -1, 1);
+       glTranslated(gis_object_center(marker)->px - marker->xoff,
+                    gis_object_center(marker)->py - marker->yoff, 0);
 
-       /* Draw objects */
-       for (GList *cur = GIS_VIEWER(self)->objects; cur; cur = cur->next)
-               gis_opengl_draw_object(self, cur->data);
-
-       /* Copy canvas to opengl */
-       glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
-       glMatrixMode(GL_MODELVIEW);  glPushMatrix(); glLoadIdentity();
-       glDisable(GL_CULL_FACE);
-       glDisable(GL_DEPTH_TEST);
        glDisable(GL_LIGHTING);
        glDisable(GL_COLOR_MATERIAL);
+       glDisable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);
-       glBindTexture(GL_TEXTURE_2D, self->canvas_tex);
-       //glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, width,height,
-       //              GL_RGBA, GL_UNSIGNED_BYTE, data);
+       glBindTexture(GL_TEXTURE_2D, marker->tex);
+       g_debug("bind_texture: %d", marker->tex);
        glBegin(GL_QUADS);
-       glTexCoord2d(0, 0); glVertex3f(-1,  1, 1);
-       glTexCoord2d(1, 0); glVertex3f( 1,  1, 1);
-       glTexCoord2d(1, 1); glVertex3f( 1, -1, 1);
-       glTexCoord2d(0, 1); glVertex3f(-1, -1, 1);
+       glTexCoord2f(1, 1); glVertex3f(width, 0     , 0);
+       glTexCoord2f(1, 0); glVertex3f(width, height, 0);
+       glTexCoord2f(0, 0); glVertex3f(0    , height, 0);
+       glTexCoord2f(0, 1); glVertex3f(0    , 0     , 0);
        glEnd();
-       glMatrixMode(GL_PROJECTION); glPopMatrix();
-       glMatrixMode(GL_MODELVIEW);  glPopMatrix();
 }
 
 
-/***********
- * Helpers *
- ***********/
-static void _gis_opengl_begin(GisOpenGL *self)
+static void _draw_objects(GisOpenGL *self)
 {
-       g_assert(GIS_IS_OPENGL(self));
+       g_debug("GisOpenGL: draw_objects");
+       /* Draw objects */
+       for (GList *cur = self->objects; cur; cur = cur->next) {
+               glMatrixMode(GL_PROJECTION); glPushMatrix();
+               glMatrixMode(GL_MODELVIEW);  glPushMatrix();
+               GisObject *object = cur->data;
+               switch (object->type) {
+               case GIS_TYPE_MARKER:
+                       _draw_marker(self, GIS_MARKER(object));
+                       break;
+               default:
+                       break;
+               }
+               glMatrixMode(GL_PROJECTION); glPopMatrix();
+               glMatrixMode(GL_MODELVIEW);  glPopMatrix();
+       }
+}
 
-       GdkGLContext   *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(self));
-       GdkGLDrawable  *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
+static void _load_object(GisOpenGL *self, GisObject *object)
+{
+       g_debug("GisOpenGL: load_object");
+       switch (object->type) {
+       case GIS_TYPE_MARKER: {
+               GisMarker *marker = GIS_MARKER(object);
+               cairo_surface_t *surface = cairo_get_target(marker->cairo);
+               gdouble width  = cairo_image_surface_get_width(surface);
+               gdouble height = cairo_image_surface_get_height(surface);
 
-       if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
-               g_assert_not_reached();
+               _gis_opengl_begin(self);
+               glEnable(GL_TEXTURE_2D);
+               glGenTextures(1, &marker->tex);
+               glBindTexture(GL_TEXTURE_2D, marker->tex);
+
+               glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+               glPixelStorei(GL_PACK_ALIGNMENT, 1);
+               glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                               cairo_image_surface_get_data(surface));
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+               g_debug("load_texture: %d", marker->tex);
+               _gis_opengl_end(self);
+               break;
+       }
+       default:
+               break;
+       }
 }
 
-static void _gis_opengl_end(GisOpenGL *self)
+static void _free_object(GisOpenGL *self, GisObject *object)
 {
-       g_assert(GIS_IS_OPENGL(self));
-       GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self));
-       gdk_gl_drawable_gl_end(gldrawable);
+       g_debug("GisOpenGL: free_object");
+       switch (object->type) {
+       case GIS_TYPE_MARKER: {
+               GisMarker *marker = GIS_MARKER(object);
+               g_debug("delete_texture: %d", marker->tex);
+               glDeleteTextures(1, &marker->tex);
+               break;
+       }
+       default:
+               break;
+       }
 }
 
 /*************
@@ -237,26 +261,6 @@ static gboolean on_configure(GisOpenGL *self, GdkEventConfigure *event, gpointer
        double ang = atan(height/FOV_DIST);
        gluPerspective(rad2deg(ang)*2, width/height, 1, 20*EARTH_R);
 
-       /* Recreate the canvas */
-       if (self->canvas) {
-               cairo_surface_destroy(cairo_get_target(self->canvas));
-               cairo_destroy(self->canvas);
-               glDeleteTextures(1, &self->canvas_tex);
-       }
-       g_message("creating %fx%f canvas", width, height);
-       cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
-       self->canvas = cairo_create(surface);
-       glEnable(GL_TEXTURE_2D);
-       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-       glPixelStorei(GL_PACK_ALIGNMENT, 1);
-       glGenTextures(1, &self->canvas_tex);
-       glBindTexture(GL_TEXTURE_2D, self->canvas_tex);
-       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
-                       cairo_image_surface_get_data(cairo_get_target(self->canvas)));
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-
 #ifndef ROAM_DEBUG
        roam_sphere_update_errors(self->sphere);
 #endif
@@ -284,7 +288,7 @@ static gboolean on_expose(GisOpenGL *self, GdkEventExpose *event, gpointer _)
 #ifndef ROAM_DEBUG
        gis_plugins_foreach(GIS_VIEWER(self)->plugins,
                        G_CALLBACK(_on_expose_plugin), self);
-       gis_opengl_draw_objects(self);
+       _draw_objects(self);
        if (self->wireframe) {
                _set_visuals(self);
                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
@@ -519,6 +523,22 @@ static void gis_opengl_end(GisViewer *_self)
        _gis_opengl_end(GIS_OPENGL(_self));
 }
 
+static void gis_opengl_add(GisViewer *_self, GisObject *object)
+{
+       g_assert(GIS_IS_OPENGL(_self));
+       GisOpenGL *self = GIS_OPENGL(_self);
+       _load_object(self, object);
+       self->objects = g_list_prepend(self->objects, object);
+}
+
+static void gis_opengl_remove(GisViewer *_self, GisObject *object)
+{
+       g_assert(GIS_IS_OPENGL(_self));
+       GisOpenGL *self = GIS_OPENGL(_self);
+       _free_object(self, object);
+       self->objects = g_list_remove(self->objects, object);
+}
+
 /****************
  * GObject code *
  ****************/
@@ -582,11 +602,6 @@ static void gis_opengl_finalize(GObject *_self)
 {
        g_debug("GisViewer: finalize");
        GisOpenGL *self = GIS_OPENGL(_self);
-       if (self->canvas) {
-               cairo_surface_destroy(cairo_get_target(self->canvas));
-               cairo_destroy(self->canvas);
-               self->canvas = NULL;
-       }
        G_OBJECT_CLASS(gis_opengl_parent_class)->finalize(_self);
 }
 static void gis_opengl_class_init(GisOpenGLClass *klass)
@@ -604,4 +619,6 @@ static void gis_opengl_class_init(GisOpenGLClass *klass)
        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;
+       viewer_class->remove            = gis_opengl_remove;
 }
index b1f7b567f8640a0fa5541f3f15f58790f4897333..c6aa5060d6bc20e63dad8d21ac2b8672d0b11f0f 100644 (file)
@@ -38,10 +38,9 @@ struct _GisOpenGL {
        GisViewer parent_instance;
 
        /* instance members */
+       GList      *objects;
        RoamSphere *sphere;
        guint       sm_source[2];
-       cairo_t    *canvas;
-       guint       canvas_tex;
 
        /* for testing */
        gboolean    wireframe;
index 89812b06c0be4b72d063a4e893b1a561289c0440..e00d9517f805e4211228891899737e7ec94c424f 100644 (file)
@@ -254,18 +254,6 @@ gboolean gis_viewer_get_offline(GisViewer *self)
        return self->offline;
 }
 
-void gis_viewer_add_object(GisViewer *self, GisObject *object)
-{
-       g_debug("GisViewer: add_object - %d, %p", object->type, object);
-       self->objects = g_list_prepend(self->objects, object);
-}
-
-void gis_viewer_remove_object(GisViewer *self, GisObject *object)
-{
-       g_debug("GisViewer: remove_object - %d, %p", object->type, object);
-       self->objects = g_list_remove(self->objects, object);
-}
-
 /* To be implemented by subclasses */
 void gis_viewer_center_position(GisViewer *self,
                gdouble lat, gdouble lon, gdouble elev)
@@ -336,6 +324,22 @@ void gis_viewer_end(GisViewer *self)
        klass->end(self);
 }
 
+void gis_viewer_add(GisViewer *self, GisObject *object)
+{
+       GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
+       if (!klass->add)
+               g_warning("GisViewer: add - Unimplemented");
+       klass->add(self, object);
+}
+
+void gis_viewer_remove(GisViewer *self, GisObject *object)
+{
+       GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
+       if (!klass->remove)
+               g_warning("GisViewer: remove - Unimplemented");
+       klass->remove(self, object);
+}
+
 /****************
  * GObject code *
  ****************/
index d1d8caa3492ed64dd673fd4253b20e451ca3fc5f..214ce932959267aa92810ed3a4c1c0eba9bd0160 100644 (file)
@@ -43,7 +43,6 @@ struct _GisViewer {
 
        /* instance members */
        GisPlugins *plugins;
-       GList      *objects;
        gchar      *time;
        gchar      *site;
        gdouble     location[3];
@@ -72,6 +71,9 @@ struct _GisViewerClass {
 
        void (*begin)            (GisViewer *viewer);
        void (*end)              (GisViewer *viewer);
+
+       void (*add)              (GisViewer *viewer, GisObject *object);
+       void (*remove)           (GisViewer *viewer, GisObject *object);
 };
 
 GType gis_viewer_get_type(void);
@@ -100,9 +102,6 @@ void gis_viewer_refresh(GisViewer *viewer);
 void gis_viewer_set_offline(GisViewer *viewer, gboolean offline);
 gboolean gis_viewer_get_offline(GisViewer *viewer);
 
-void gis_viewer_add_object(GisViewer *self, GisObject *object);
-void gis_viewer_remove_object(GisViewer *self, GisObject *object);
-
 /* To be implemented by subclasses */
 void gis_viewer_center_position(GisViewer *viewer,
                gdouble lat, gdouble lon, gdouble elev);
@@ -122,4 +121,7 @@ void gis_viewer_render_tiles(GisViewer *viewer, GisTile *root);
 void gis_viewer_begin(GisViewer *viewer);
 void gis_viewer_end  (GisViewer *viewer);
 
+void gis_viewer_add(GisViewer *self, GisObject *object);
+void gis_viewer_remove(GisViewer *self, GisObject *object);
+
 #endif
index e41fec1d70d0bf09772e227a70562e3e8a28297f..746c058a197cd7b39ba6036633dafcf68557e6d2 100644 (file)
@@ -57,7 +57,7 @@ int main(int argc, char **argv)
        gtk_widget_show_all(window);
        gdk_threads_leave();
 
-       //gis_plugins_load(plugins, "bmng", viewer, prefs);
+       gis_plugins_load(plugins, "bmng", viewer, prefs);
        //gis_plugins_load(plugins, "srtm", viewer, prefs);
        gis_plugins_load(plugins, "test", viewer, prefs);
 
index 9c3a96340bd2a104d3c0843863966ee3e444b4f0..5be0fd7a0eb9f6feef69dc8d360e42b0e3bc1952 100644 (file)
@@ -34,7 +34,7 @@ GisPluginTest *gis_plugin_test_new(GisViewer *viewer)
 
        GisMarker *marker = gis_marker_new("St. Charles");
        gis_point_set_lle(gis_object_center(marker), 38.841847, -90.491982, 0);
-       gis_viewer_add_object(self->viewer, GIS_OBJECT(marker));
+       gis_viewer_add(self->viewer, GIS_OBJECT(marker));
 
        return self;
 }