gis-data.c gis-data.h \
gis-tile.c gis-tile.h \
gis-wms.c gis-wms.h \
- gis-prims.c gis-prims.h \
+ gis-object.c gis-object.h \
roam.c roam.h \
gpqueue.c gpqueue.h
libgis_la_CPPFLAGS = $(AM_CPPFLAGS) \
#include <glib.h>
#include <GL/glu.h>
-#include "gis-prims.h"
+#include "gis-object.h"
#include "gis-util.h"
/* TODO
GisTriangle *gis_triangle_new(GisPoint *a, GisPoint *b, GisPoint *c, guint tex)
{
GisTriangle *self = g_new0(GisTriangle, 1);
- gis_point_set_xyz(&GIS_PRIMITIVE(self)->center,
+ GIS_OBJECT(self)->type = GIS_TYPE_TRIANGLE;
+ gis_point_set_xyz(&GIS_OBJECT(self)->center,
(a->x + b->x + c->x)/3,
(a->y + b->y + c->y)/3,
(a->z + b->z + c->z)/3);
GisQuad *gis_quad_new(GisPoint *a, GisPoint *b, GisPoint *c, GisPoint *d, guint tex)
{
GisQuad *self = g_new0(GisQuad, 1);
- gis_point_set_xyz(&GIS_PRIMITIVE(self)->center,
+ GIS_OBJECT(self)->type = GIS_TYPE_QUAD;
+ gis_point_set_xyz(&GIS_OBJECT(self)->center,
(a->x + b->x + c->x + d->x)/4,
(a->y + b->y + c->y + d->y)/4,
(a->z + b->z + c->z + d->z)/4);
GisCallback *gis_callback_new(GisCallbackFunc callback, gpointer user_data)
{
GisCallback *self = g_new0(GisCallback, 1);
+ GIS_OBJECT(self)->type = GIS_TYPE_CALLBACK;
self->callback = callback;
self->user_data = user_data;
return self;
{
g_free(self);
}
+
+
+/* GisCallback */
+GisMarker *gis_marker_new(const gchar *label)
+{
+ GisMarker *self = g_new0(GisMarker, 1);
+ GIS_OBJECT(self)->type = GIS_TYPE_MARKER;
+ self->label = g_strdup(label);;
+ return self;
+}
+
+void gis_marker_free(GisMarker *self)
+{
+ g_free(self->label);
+ g_free(self);
+}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __GIS_PRIMITIVES_H__
-#define __GIS_PRIMITIVES_H__
+#ifndef __GIS_OBJECT_H__
+#define __GIS_OBJECT_H__
#include <glib.h>
gint refs;
};
-/* Primitives */
-#define GIS_PRIMITIVE(primitive) ((GisPrimitive*)primitive)
-#define GIS_TRIANGLE (triangle ) ((GisTriangle *)triangel )
-#define GIS_QUAD (quad ) ((GisQuad *)quad )
-#define GIS_CALLBACK (callback ) ((GisCallback *)callback )
+/* Objects */
+#define GIS_OBJECT(object) ((GisObject *)object)
+#define GIS_TRIANGLE(triangle) ((GisTriangle*)triangle)
+#define GIS_QUAD(quad) ((GisQuad *)quad)
+#define GIS_CALLBACK(callback) ((GisCallback*)callback)
+#define GIS_MARKER(marker) ((GisMarker *)marker)
-typedef struct _GisPrimitive GisPrimitive;
-typedef struct _GisTriangle GisTriangle;
-typedef struct _GisQuad GisQuad;
-typedef struct _GisCallback GisCallback;
+typedef enum {
+ GIS_TYPE_TRIANGLE,
+ GIS_TYPE_QUAD,
+ GIS_TYPE_CALLBACK,
+ GIS_TYPE_MARKER,
+ GIS_NUM_TYPES,
+} GisObjectType;
+
+typedef struct _GisObject GisObject;
+typedef struct _GisTriangle GisTriangle;
+typedef struct _GisQuad GisQuad;
+typedef struct _GisCallback GisCallback;
+typedef struct _GisMarker GisMarker;
typedef gpointer (*GisCallbackFunc)(GisCallback *callback, gpointer user_data);
-struct _GisPrimitive {
+struct _GisObject {
+ GisObjectType type;
GisPoint center;
GisProjection *proj;
+ gdouble lod;
};
struct _GisTriangle {
- GisPrimitive parent;
- GisPoint *verts[3];
- guint tex;
+ GisObject parent;
+ GisPoint *verts[3];
+ guint tex;
};
struct _GisQuad {
- GisPrimitive parent;
- GisPoint *verts[4];
- guint tex;
+ GisObject parent;
+ GisPoint *verts[4];
+ guint tex;
};
struct _GisCallback {
- GisPrimitive parent;
+ GisObject parent;
GisCallbackFunc callback;
gpointer user_data;
};
+struct _GisMarker {
+ GisObject parent;
+ gchar *label;
+};
/* Support functions */
+#define gis_object_center(object) \
+ (&GIS_OBJECT(object)->center)
+
GisPoint *gis_point_new();
void gis_point_set_lle(GisPoint *point, gdouble lat, gdouble lon, gdouble elev);
void gis_point_set_xyz(GisPoint *point, gdouble x, gdouble y, gdouble z);
GisCallback *gis_callback_new(GisCallbackFunc callback, gpointer user_data);
void gis_callback_free(GisCallback *cb);
+GisMarker *gis_marker_new(const gchar *label);
+void gis_marker_free(GisMarker *marker);
+
#endif
#include <config.h>
#include <math.h>
+#include <string.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include "gis-opengl.h"
#include "gis-util.h"
+#include "gis-object.h"
#include "roam.h"
#define FOV_DIST 2000.0
#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)
+{
+}
+
+static void _gis_opengl_draw_callback(GisOpenGL *self, GisCallback *cb)
+{
+}
+
+static void _gis_opengl_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;
+
+ 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");
+
+ 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);
+
+ /* 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);
+ 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);
+ 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);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); glPopMatrix();
+ glMatrixMode(GL_MODELVIEW); glPopMatrix();
+}
+
/***********
* Helpers *
double width = GTK_WIDGET(self)->allocation.width;
double height = GTK_WIDGET(self)->allocation.height;
- glViewport(0, 0, width, height);
+ /* Setup OpenGL Window */
+ glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
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
return FALSE;
}
-static void on_expose_plugin(GisPlugin *plugin, gchar *name, GisOpenGL *self)
+static void _on_expose_plugin(GisPlugin *plugin, gchar *name, GisOpenGL *self)
{
_set_visuals(self);
glMatrixMode(GL_PROJECTION); glPushMatrix();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#ifndef ROAM_DEBUG
- gis_plugins_foreach(GIS_VIEWER(self)->plugins, G_CALLBACK(on_expose_plugin), self);
-
+ gis_plugins_foreach(GIS_VIEWER(self)->plugins,
+ G_CALLBACK(_on_expose_plugin), self);
+ gis_opengl_draw_objects(self);
if (self->wireframe) {
_set_visuals(self);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
roam_sphere_draw(self->sphere);
-
//roam_sphere_draw_normals(self->sphere);
#endif
#else
gdk_threads_enter();
#endif
-
- return TRUE;
+ return FALSE;
}
static gboolean _update_errors_cb(gpointer sphere)
self->sm_source[1] = g_timeout_add_full(G_PRIORITY_HIGH_IDLE+10, 500, (GSourceFunc)on_idle, self, NULL);
#endif
- g_signal_connect(self, "realize", G_CALLBACK(on_realize), NULL);
- g_signal_connect(self, "configure-event", G_CALLBACK(on_configure), NULL);
- g_signal_connect(self, "expose-event", G_CALLBACK(on_expose), NULL);
+ g_signal_connect(self, "realize", G_CALLBACK(on_realize), NULL);
+ g_signal_connect(self, "configure-event", G_CALLBACK(on_configure), NULL);
+ g_signal_connect(self, "expose-event", G_CALLBACK(on_expose), NULL);
- g_signal_connect(self, "key-press-event", G_CALLBACK(on_key_press), NULL);
+ g_signal_connect(self, "key-press-event", G_CALLBACK(on_key_press), NULL);
- g_signal_connect(self, "location-changed", G_CALLBACK(on_view_changed), NULL);
- g_signal_connect(self, "rotation-changed", G_CALLBACK(on_view_changed), NULL);
+ g_signal_connect(self, "location-changed", G_CALLBACK(on_view_changed), NULL);
+ g_signal_connect(self, "rotation-changed", G_CALLBACK(on_view_changed), NULL);
}
static void gis_opengl_dispose(GObject *_self)
{
}
G_OBJECT_CLASS(gis_opengl_parent_class)->dispose(_self);
}
+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)
{
g_debug("GisOpenGL: class_init");
/* instance members */
RoamSphere *sphere;
guint sm_source[2];
+ cairo_t *canvas;
+ guint canvas_tex;
/* for testing */
gboolean wireframe;
void gis_plugin_expose(GisPlugin *self)
{
- g_return_if_fail(GIS_IS_PLUGIN(self));
+ if (!GIS_IS_PLUGIN(self))
+ return;
+ GisPluginInterface *iface = GIS_PLUGIN_GET_INTERFACE(self);
+ if (iface->expose)
+ return
GIS_PLUGIN_GET_INTERFACE(self)->expose(self);
}
GtkWidget *gis_plugin_get_config(GisPlugin *self)
{
- g_return_val_if_fail(GIS_IS_PLUGIN(self), NULL);
+ if (!GIS_IS_PLUGIN(self))
+ return NULL;
GisPluginInterface *iface = GIS_PLUGIN_GET_INTERFACE(self);
return iface->get_config ? iface->get_config (self) : NULL;
}
else if (kv == GDK_J) gis_viewer_rotate(self, 2, 0, 0);
else if (kv == GDK_K) gis_viewer_rotate(self, -2, 0, 0);
else if (kv == GDK_L) gis_viewer_rotate(self, 0, 0, 2);
- return TRUE;
+ return FALSE;
}
static void on_view_changed(GisViewer *self,
gdouble _1, gdouble _2, gdouble _3)
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)
#include "gis-tile.h"
#include "gis-plugin.h"
+#include "gis-object.h"
struct _GisViewer {
GtkDrawingArea parent_instance;
/* instance members */
GisPlugins *plugins;
+ GList *objects;
gchar *time;
gchar *site;
gdouble location[3];
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);
gtk_widget_show_all(window);
gdk_threads_leave();
- gis_plugins_load(plugins, "bmng", viewer, prefs);
- gis_plugins_load(plugins, "srtm", viewer, prefs);
+ //gis_plugins_load(plugins, "bmng", viewer, prefs);
+ //gis_plugins_load(plugins, "srtm", viewer, prefs);
gis_plugins_load(plugins, "test", viewer, prefs);
gis_viewer_set_site(viewer, "KLSX");
g_debug("GisPluginTest: new");
GisPluginTest *self = g_object_new(GIS_TYPE_PLUGIN_TEST, NULL);
self->viewer = viewer;
- return self;
-}
-
-static void gis_plugin_test_expose(GisPlugin *_self)
-{
- GisPluginTest *self = GIS_PLUGIN_TEST(_self);
- g_debug("GisPluginTest: expose");
-
- double width = GTK_WIDGET(self->viewer)->allocation.width;
- double height = GTK_WIDGET(self->viewer)->allocation.height;
- // St. Charles
- // lat = 38.841847
- // lon = -90.491982
- gdouble px, py, pz;
- gis_viewer_project(self->viewer,
- 38.841847, -90.491982, 0, &px, &py, &pz);
- py = height-py;
+ 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));
- //cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
- //cairo_t *cairo = cairo_create(surface);
- //cairo_set_source_rgba(cairo, 1, 1, 1, 1);
- //cairo_arc(cairo, px, py, 4, 0, 2*G_PI);
- //cairo_fill(cairo);
- //cairo_move_to(cairo, px+4, py-8);
- //cairo_set_font_size(cairo, 10);
- //cairo_show_text(cairo, "Marker!");
-
- //guint tex;
- //glEnable(GL_TEXTURE_2D);
- //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- //glPixelStorei(GL_PACK_ALIGNMENT, 1);
- //glGenTextures(1, &tex);
- //glBindTexture(GL_TEXTURE_2D, tex);
- //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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);
-
- //glMatrixMode(GL_PROJECTION);
- //glLoadIdentity();
- //glMatrixMode(GL_MODELVIEW);
- //glLoadIdentity();
-
- //glDisable(GL_COLOR_MATERIAL);
- //glDisable(GL_CULL_FACE);
- //glDisable(GL_DEPTH_TEST);
- //glDisable(GL_LIGHTING);
- //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);
- //glEnd();
- //glDeleteTextures(1, &tex);
- //cairo_destroy(cairo);
- //cairo_surface_destroy(surface);
+ return self;
}
{
g_debug("GisPluginTest: plugin_init");
/* Add methods to the interface */
- iface->expose = gis_plugin_test_expose;
}
/* Class/Object init */
static void gis_plugin_test_init(GisPluginTest *self)