]> Pileus Git - grits/blobdiff - src/gis-opengl.c
Markers as individual textures
[grits] / src / gis-opengl.c
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;
 }