* 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>
#include "objects/gis-marker.h"
#include "objects/gis-callback.h"
-#define FOV_DIST 2000.0
-#define MPPX(dist) (4*dist/FOV_DIST)
-
// #define ROAM_DEBUG
+/* Tessellation, "finding intersecting triangles" */
+/* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */
+/* http://www.opengl.org/wiki/Alpha_Blending */
+
/***********
* Helpers *
***********/
/********************
* 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)
{
- GisPoint *point = gis_object_center(GIS_OBJECT(marker));
+ GisPoint *point = gis_object_center(marker);
gdouble px, py, pz;
gis_viewer_project(GIS_VIEWER(opengl),
point->lat, point->lon, point->elev,
} 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();
/*********************
* 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");