]> Pileus Git - grits/blobdiff - src/gis-opengl.c
Add locking when modifying for viewer object lists
[grits] / src / gis-opengl.c
index 34e4c8d7349d6f02298e07278612f9cea5e90602..9501781f586336dea6faa1e262edef008a5eb6ad 100644 (file)
@@ -115,7 +115,9 @@ static void _set_visuals(GisOpenGL *opengl)
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        //glShadeModel(GL_FLAT);
 
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        //glShadeModel(GL_FLAT);
 
+       g_mutex_lock(opengl->sphere_lock);
        roam_sphere_update_view(opengl->sphere);
        roam_sphere_update_view(opengl->sphere);
+       g_mutex_unlock(opengl->sphere_lock);
 }
 
 
 }
 
 
@@ -176,7 +178,9 @@ static void _draw_tile(GisOpenGL *opengl, GisTile *tile, GList *triangles)
                if (lat[2] == 90 || lat[2] == -90) xy[2][0] = 0.5;
 
                glEnable(GL_TEXTURE_2D);
                if (lat[2] == 90 || lat[2] == -90) xy[2][0] = 0.5;
 
                glEnable(GL_TEXTURE_2D);
+               glEnable(GL_POLYGON_OFFSET_FILL);
                glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data);
                glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data);
+               glPolygonOffset(0, -tile->zindex);
                glBegin(GL_TRIANGLES);
                glNormal3dv(tri->p.r->norm); glTexCoord2dv(xy[0]); glVertex3dv((double*)tri->p.r);
                glNormal3dv(tri->p.m->norm); glTexCoord2dv(xy[1]); glVertex3dv((double*)tri->p.m);
                glBegin(GL_TRIANGLES);
                glNormal3dv(tri->p.r->norm); glTexCoord2dv(xy[0]); glVertex3dv((double*)tri->p.r);
                glNormal3dv(tri->p.m->norm); glTexCoord2dv(xy[1]); glVertex3dv((double*)tri->p.m);
@@ -233,6 +237,7 @@ static void _draw_marker(GisOpenGL *opengl, GisMarker *marker)
        gis_viewer_project(GIS_VIEWER(opengl),
                        point->lat, point->lon, point->elev,
                        &px, &py, &pz);
        gis_viewer_project(GIS_VIEWER(opengl),
                        point->lat, point->lon, point->elev,
                        &px, &py, &pz);
+
        gint win_width  = GTK_WIDGET(opengl)->allocation.width;
        gint win_height = GTK_WIDGET(opengl)->allocation.height;
        py = win_height - py;
        gint win_width  = GTK_WIDGET(opengl)->allocation.width;
        gint win_height = GTK_WIDGET(opengl)->allocation.height;
        py = win_height - py;
@@ -275,14 +280,23 @@ static void _draw_object(GisOpenGL *opengl, GisObject *object)
        //g_debug("GisOpenGL: draw_object");
        /* Skip out of range objects */
        if (object->lod > 0) {
        //g_debug("GisOpenGL: draw_object");
        /* Skip out of range objects */
        if (object->lod > 0) {
+               /* LOD test */
                gdouble eye[3], obj[3];
                gis_viewer_get_location(GIS_VIEWER(opengl), &eye[0], &eye[1], &eye[2]);
                gdouble eye[3], obj[3];
                gis_viewer_get_location(GIS_VIEWER(opengl), &eye[0], &eye[1], &eye[2]);
+               gdouble elev = eye[2];
                lle2xyz(eye[0], eye[1], eye[2], &eye[0], &eye[1], &eye[2]);
                lle2xyz(object->center.lat, object->center.lon, object->center.elev,
                        &obj[0], &obj[1], &obj[2]);
                gdouble dist = distd(obj, eye);
                if (object->lod < dist)
                        return;
                lle2xyz(eye[0], eye[1], eye[2], &eye[0], &eye[1], &eye[2]);
                lle2xyz(object->center.lat, object->center.lon, object->center.elev,
                        &obj[0], &obj[1], &obj[2]);
                gdouble dist = distd(obj, eye);
                if (object->lod < dist)
                        return;
+
+               /* Horizon testing */
+               gdouble c = EARTH_R+elev;
+               gdouble a = EARTH_R;
+               gdouble horizon = sqrt(c*c - a*a);
+               if (dist > horizon)
+                       return;
        }
 
        /* Draw */
        }
 
        /* Draw */
@@ -296,7 +310,9 @@ static void _draw_object(GisOpenGL *opengl, GisObject *object)
        } else if (GIS_IS_TILE(object)) {
                glEnable(GL_DEPTH_TEST);
                glDepthFunc(GL_LESS);
        } else if (GIS_IS_TILE(object)) {
                glEnable(GL_DEPTH_TEST);
                glDepthFunc(GL_LESS);
+               g_mutex_lock(opengl->sphere_lock);
                _draw_tiles(opengl, GIS_TILE(object));
                _draw_tiles(opengl, GIS_TILE(object));
+               g_mutex_unlock(opengl->sphere_lock);
        }
        glPopAttrib();
        glMatrixMode(GL_PROJECTION); glPopMatrix();
        }
        glPopAttrib();
        glMatrixMode(GL_PROJECTION); glPopMatrix();
@@ -465,9 +481,13 @@ static gboolean on_key_press(GisOpenGL *opengl, GdkEventKey *event, gpointer _)
        return FALSE;
 }
 
        return FALSE;
 }
 
-static gboolean _update_errors_cb(gpointer sphere)
+static gboolean _update_errors_cb(gpointer _opengl)
 {
 {
-       roam_sphere_update_errors(sphere);
+       GisOpenGL *opengl = _opengl;
+       g_mutex_lock(opengl->sphere_lock);
+       roam_sphere_update_errors(opengl->sphere);
+       g_mutex_unlock(opengl->sphere_lock);
+       opengl->ue_source = 0;
        return FALSE;
 }
 static void on_view_changed(GisOpenGL *opengl,
        return FALSE;
 }
 static void on_view_changed(GisOpenGL *opengl,
@@ -476,8 +496,9 @@ static void on_view_changed(GisOpenGL *opengl,
        g_debug("GisOpenGL: on_view_changed");
        _set_visuals(opengl);
 #ifndef ROAM_DEBUG
        g_debug("GisOpenGL: on_view_changed");
        _set_visuals(opengl);
 #ifndef ROAM_DEBUG
-       opengl->ue_source = g_idle_add_full(G_PRIORITY_HIGH_IDLE+30,
-                       _update_errors_cb, opengl->sphere, NULL);
+       if (!opengl->ue_source)
+               opengl->ue_source = g_idle_add_full(G_PRIORITY_HIGH_IDLE+30,
+                               _update_errors_cb, opengl, NULL);
        //roam_sphere_update_errors(opengl->sphere);
 #endif
 }
        //roam_sphere_update_errors(opengl->sphere);
 #endif
 }
@@ -590,6 +611,7 @@ static gpointer gis_opengl_add(GisViewer *_opengl, GisObject *object,
        g_assert(GIS_IS_OPENGL(_opengl));
        GisOpenGL *opengl = GIS_OPENGL(_opengl);
        _load_object(opengl, object);
        g_assert(GIS_IS_OPENGL(_opengl));
        GisOpenGL *opengl = GIS_OPENGL(_opengl);
        _load_object(opengl, object);
+       g_mutex_lock(opengl->objects_lock);
        struct RenderLevel *level = g_tree_lookup(opengl->objects, (gpointer)key);
        if (!level) {
                level = g_new0(struct RenderLevel, 1);
        struct RenderLevel *level = g_tree_lookup(opengl->objects, (gpointer)key);
        if (!level) {
                level = g_new0(struct RenderLevel, 1);
@@ -602,6 +624,7 @@ static gpointer gis_opengl_add(GisViewer *_opengl, GisObject *object,
        next->prev = list;
        next->next = list->next;
        list->next = next;
        next->prev = list;
        next->next = list->next;
        list->next = next;
+       g_mutex_unlock(opengl->objects_lock);
        return next;
 }
 
        return next;
 }
 
@@ -612,12 +635,14 @@ static GisObject *gis_opengl_remove(GisViewer *_opengl, gpointer _link)
        GList *link = _link;
        GisObject *object = link->data;
        _unload_object(opengl, object);
        GList *link = _link;
        GisObject *object = link->data;
        _unload_object(opengl, object);
+       g_mutex_lock(opengl->objects_lock);
        /* Just unlink and free it, link->prev is assured */
        link->prev->next = link->next;
        if (link->next)
                link->next->prev = link->prev;
        g_free(link);
        g_object_unref(object);
        /* Just unlink and free it, link->prev is assured */
        link->prev->next = link->next;
        if (link->next)
                link->next->prev = link->prev;
        g_free(link);
        g_object_unref(object);
+       g_mutex_unlock(opengl->objects_lock);
        return object;
 }
 
        return object;
 }
 
@@ -656,6 +681,7 @@ static void gis_opengl_init(GisOpenGL *opengl)
        g_object_unref(glconfig);
 
        opengl->objects = g_tree_new_full(_objects_cmp, NULL, NULL, _objects_free);
        g_object_unref(glconfig);
 
        opengl->objects = g_tree_new_full(_objects_cmp, NULL, NULL, _objects_free);
+       opengl->objects_lock = g_mutex_new();
        opengl->sphere = roam_sphere_new(opengl);
        opengl->sphere_lock = g_mutex_new();
 
        opengl->sphere = roam_sphere_new(opengl);
        opengl->sphere_lock = g_mutex_new();
 
@@ -698,6 +724,7 @@ static void gis_opengl_finalize(GObject *_opengl)
        GisOpenGL *opengl = GIS_OPENGL(_opengl);
        roam_sphere_free(opengl->sphere);
        g_tree_destroy(opengl->objects);
        GisOpenGL *opengl = GIS_OPENGL(_opengl);
        roam_sphere_free(opengl->sphere);
        g_tree_destroy(opengl->objects);
+       g_mutex_free(opengl->objects_lock);
        g_mutex_free(opengl->sphere_lock);
        G_OBJECT_CLASS(gis_opengl_parent_class)->finalize(_opengl);
 }
        g_mutex_free(opengl->sphere_lock);
        G_OBJECT_CLASS(gis_opengl_parent_class)->finalize(_opengl);
 }