* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Tessellation, "finding intersecting triangles" */
-/* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */
-/* http://www.opengl.org/wiki/Alpha_Blending */
+/**
+ * SECTION:gis-opengl
+ * @short_description: OpenGL based virtual globe
+ *
+ * #GisOpenGL is the core rendering engine used by libgis. Theoretically other
+ * renderers could be writte, but they have not been. GisOpenGL uses the ROAM
+ * algorithm for updating surface mesh the planet. The only thing GisOpenGL can
+ * actually render on it's own is a wireframe of a sphere.
+ *
+ * GisOpenGL relies on #GtkGlExt and requires (at least) OpenGL 2.0.
+ */
#include <config.h>
#include <math.h>
/********************
* Object handleing *
********************/
-static void _draw_tile(GisOpenGL *opengl, GisTile *tile)
+static void _draw_tile(GisOpenGL *opengl, GisTile *tile, GList *triangles)
{
if (!tile || !tile->data)
return;
- GList *triangles = roam_sphere_get_intersect(opengl->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);
static void _draw_tiles(GisOpenGL *opengl, GisTile *tile)
{
/* Only draw children if possible */
- gboolean has_children = TRUE;
+ gboolean has_children = FALSE;
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(opengl, child);
- else
- /* No children, draw this tile */
- _draw_tile(opengl, tile);
+ if (child && child->data)
+ has_children = TRUE;
+
+ GList *triangles = NULL;
+ if (has_children) {
+ /* TODO: simplify this */
+ const gdouble rows = G_N_ELEMENTS(tile->children);
+ const gdouble cols = G_N_ELEMENTS(tile->children[0]);
+ const gdouble lat_dist = tile->edge.n - tile->edge.s;
+ const gdouble lon_dist = tile->edge.e - tile->edge.w;
+ const gdouble lat_step = lat_dist / rows;
+ const gdouble lon_step = lon_dist / cols;
+ int row, col;
+ gis_tile_foreach_index(tile, row, col) {
+ GisTile *child = tile->children[row][col];
+ if (child && child->data) {
+ _draw_tiles(opengl, child);
+ } else {
+ const gdouble n = tile->edge.n-(lat_step*(row+0));
+ const gdouble s = tile->edge.n-(lat_step*(row+1));
+ const gdouble e = tile->edge.w+(lon_step*(col+1));
+ const gdouble w = tile->edge.w+(lon_step*(col+0));
+ GList *these = roam_sphere_get_intersect(opengl->sphere, FALSE, n, s, e, w);
+ triangles = g_list_concat(triangles, these);
+ }
+ }
+ } else {
+ triangles = roam_sphere_get_intersect(opengl->sphere, FALSE,
+ tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w);
+ }
+ if (triangles)
+ _draw_tile(opengl, tile, triangles);
}
static void _draw_marker(GisOpenGL *opengl, GisMarker *marker)
} else if (GIS_IS_CALLBACK(object)) {
_draw_callback(opengl, GIS_CALLBACK(object));
} else if (GIS_IS_TILE(object)) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
_draw_tiles(opengl, GIS_TILE(object));
}
glPopAttrib();
GList sorted;
};
-static void on_realize(GisOpenGL *opengl, gpointer _)
-{
- g_debug("GisOpenGL: on_realize");
-
- GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(opengl));
- GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(opengl));
- if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
- g_assert_not_reached();
-
- _set_visuals(opengl);
- g_mutex_lock(opengl->sphere_lock);
- roam_sphere_update_errors(opengl->sphere);
- g_mutex_unlock(opengl->sphere_lock);
-}
-
static gboolean on_configure(GisOpenGL *opengl, GdkEventConfigure *event, gpointer _)
{
g_debug("GisOpenGL: on_configure");
return FALSE;
}
+static void on_realize(GisOpenGL *opengl, gpointer _)
+{
+ g_debug("GisOpenGL: on_realize");
+
+ GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(opengl));
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(opengl));
+ if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
+ g_assert_not_reached();
+
+ _set_visuals(opengl);
+ on_configure(opengl, NULL, NULL);
+}
+
static gboolean _draw_level(gpointer key, gpointer value, gpointer user_data)
{
g_debug("GisOpenGL: _draw_level - level=%-4d", (int)key);
/*********************
* GisViewer methods *
*********************/
+/**
+ * gis_opengl_new:
+ * @plugins: the plugins store to use
+ * @prefs: the preferences object to use
+ *
+ * Create a new OpenGL renderer.
+ *
+ * Returns: the new #GisOpenGL
+ */
GisViewer *gis_opengl_new(GisPlugins *plugins, GisPrefs *prefs)
{
g_debug("GisOpenGL: new");