X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=src%2Fgis-opengl.c;h=1d629574644e8d93a7bafd1768f07b4f6e62083c;hb=3812f4ecfc3894f0118ec6eb173a0cc705ec2ceb;hp=0fff2bf4a57dfd2460363cac5f42841d718822bc;hpb=37170f3b0fe9625d75a294eeef1b4442fa63a7f1;p=grits diff --git a/src/gis-opengl.c b/src/gis-opengl.c index 0fff2bf..1d62957 100644 --- a/src/gis-opengl.c +++ b/src/gis-opengl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Andy Spencer + * Copyright (C) 2009-2010 Andy Spencer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,9 +30,12 @@ #include "gis-opengl.h" #include "gis-util.h" -#include "gis-object.h" #include "roam.h" +#include "objects/gis-object.h" +#include "objects/gis-marker.h" +#include "objects/gis-callback.h" + #define FOV_DIST 2000.0 #define MPPX(dist) (4*dist/FOV_DIST) @@ -88,7 +91,7 @@ static void _set_visuals(GisOpenGL *self) float material_ambient[] = {0.2, 0.2, 0.2, 1.0}; float material_diffuse[] = {0.8, 0.8, 0.8, 1.0}; - float material_specular[] = {0.0, 0.0, 0.0, 1.0}; + float material_specular[] = {0.1, 0.1, 0.1, 1.0}; float material_emission[] = {0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse); @@ -102,12 +105,6 @@ static void _set_visuals(GisOpenGL *self) glRotatef(lat, 1, 0, 0); glRotatef(-lon, 0, 1, 0); - /* Misc */ - gdouble rg = MAX(0, 1-(elev/20000)); - gdouble blue = MAX(0, 1-(elev/50000)); - glClearColor(MIN(0.65,rg), MIN(0.65,rg), MIN(1,blue), 1.0f); - glColor4f(1, 1, 1, 1); - glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -134,6 +131,89 @@ static void _set_visuals(GisOpenGL *self) /******************** * Object handleing * ********************/ +static void _draw_tile(GisOpenGL *self, GisTile *tile) +{ + if (!tile || !tile->data) + return; + GList *triangles = roam_sphere_get_intersect(self->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); + //g_message("drawing %4d triangles for tile edges=%7.2f,%7.2f,%7.2f,%7.2f", + // g_list_length(triangles), tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); + for (GList *cur = triangles; cur; cur = cur->next) { + RoamTriangle *tri = cur->data; + + gdouble lat[3] = {tri->p.r->lat, tri->p.m->lat, tri->p.l->lat}; + gdouble lon[3] = {tri->p.r->lon, tri->p.m->lon, tri->p.l->lon}; + + if (lon[0] < -90 || lon[1] < -90 || lon[2] < -90) { + if (lon[0] > 90) lon[0] -= 360; + if (lon[1] > 90) lon[1] -= 360; + if (lon[2] > 90) lon[2] -= 360; + } + + gdouble n = tile->edge.n; + gdouble s = tile->edge.s; + gdouble e = tile->edge.e; + gdouble w = tile->edge.w; + + gdouble londist = e - w; + gdouble latdist = n - s; + + gdouble xy[3][2] = { + {(lon[0]-w)/londist, 1-(lat[0]-s)/latdist}, + {(lon[1]-w)/londist, 1-(lat[1]-s)/latdist}, + {(lon[2]-w)/londist, 1-(lat[2]-s)/latdist}, + }; + + //if ((lat[0] == 90 && (xy[0][0] < 0 || xy[0][0] > 1)) || + // (lat[1] == 90 && (xy[1][0] < 0 || xy[1][0] > 1)) || + // (lat[2] == 90 && (xy[2][0] < 0 || xy[2][0] > 1))) + // g_message("w,e=%4.f,%4.f " + // "lat,lon,x,y=" + // "%4.1f,%4.0f,%4.2f,%4.2f " + // "%4.1f,%4.0f,%4.2f,%4.2f " + // "%4.1f,%4.0f,%4.2f,%4.2f ", + // w,e, + // lat[0], lon[0], xy[0][0], xy[0][1], + // lat[1], lon[1], xy[1][0], xy[1][1], + // lat[2], lon[2], xy[2][0], xy[2][1]); + + /* Fix poles */ + if (lat[0] == 90 || lat[0] == -90) xy[0][0] = 0.5; + if (lat[1] == 90 || lat[1] == -90) xy[1][0] = 0.5; + if (lat[2] == 90 || lat[2] == -90) xy[2][0] = 0.5; + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data); + 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); + glNormal3dv(tri->p.l->norm); glTexCoord2dv(xy[2]); glVertex3dv((double*)tri->p.l); + glEnd(); + } + g_list_free(triangles); +} + +static void _draw_tiles(GisOpenGL *self, GisTile *tile) +{ + /* Only draw children if possible */ + gboolean has_children = TRUE; + 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(self, child); + else + /* No children, draw this tile */ + _draw_tile(self, tile); +} + static void _draw_marker(GisOpenGL *self, GisMarker *marker) { GisPoint *point = gis_object_center(GIS_OBJECT(marker)); @@ -194,15 +274,12 @@ static void _draw_object(GisOpenGL *self, GisObject *object) glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glPushAttrib(GL_ALL_ATTRIB_BITS); - switch (object->type) { - case GIS_TYPE_MARKER: + if (GIS_IS_MARKER(object)) { _draw_marker(self, GIS_MARKER(object)); - break; - case GIS_TYPE_CALLBACK: + } else if (GIS_IS_CALLBACK(object)) { _draw_callback(self, GIS_CALLBACK(object)); - break; - default: - break; + } else if (GIS_IS_TILE(object)) { + _draw_tiles(self, GIS_TILE(object)); } glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -212,8 +289,7 @@ static void _draw_object(GisOpenGL *self, GisObject *object) static void _load_object(GisOpenGL *self, GisObject *object) { g_debug("GisOpenGL: load_object"); - switch (object->type) { - case GIS_TYPE_MARKER: { + if (GIS_IS_MARKER(object)) { GisMarker *marker = GIS_MARKER(object); cairo_surface_t *surface = cairo_get_target(marker->cairo); gdouble width = cairo_image_surface_get_width(surface); @@ -232,25 +308,16 @@ static void _load_object(GisOpenGL *self, GisObject *object) 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 _unload_object(GisOpenGL *self, GisObject *object) { g_debug("GisOpenGL: unload_object"); - switch (object->type) { - case GIS_TYPE_MARKER: { + if (GIS_IS_MARKER(object)) { GisMarker *marker = GIS_MARKER(object); g_debug("delete_texture: %d", marker->tex); glDeleteTextures(1, &marker->tex); - break; - } - default: - break; } } @@ -315,7 +382,8 @@ static gboolean _draw_level(gpointer key, gpointer value, gpointer user_data) /* Freeze depth buffer and draw transparent objects sorted */ /* TODO: sorting */ - glDepthMask(FALSE); + //glDepthMask(FALSE); + glAlphaFunc(GL_GREATER, 0.1); for (cur = level->sorted.next; cur; cur = cur->next, nsorted++) _draw_object(self, GIS_OBJECT(cur->data)); @@ -419,11 +487,11 @@ static gboolean on_idle(GisOpenGL *self) /********************* * GisViewer methods * *********************/ -GisViewer *gis_opengl_new(GisPlugins *plugins) +GisViewer *gis_opengl_new(GisPlugins *plugins, GisPrefs *prefs) { g_debug("GisOpenGL: new"); GisViewer *self = g_object_new(GIS_TYPE_OPENGL, NULL); - self->plugins = plugins; + gis_viewer_setup(self, plugins, prefs); return self; } @@ -449,91 +517,6 @@ static void gis_opengl_project(GisViewer *_self, px, py, pz); } -static void gis_opengl_render_tile(GisViewer *_self, GisTile *tile) -{ - GisOpenGL *self = GIS_OPENGL(_self); - if (!tile || !tile->data) - return; - GList *triangles = roam_sphere_get_intersect(self->sphere, FALSE, - tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); - if (!triangles) - g_warning("GisOpenGL: render_tiles - No triangles to draw: edges=%f,%f,%f,%f", - tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); - //g_message("rendering %4d triangles for tile edges=%7.2f,%7.2f,%7.2f,%7.2f", - // g_list_length(triangles), tile->edge.n, tile->edge.s, tile->edge.e, tile->edge.w); - for (GList *cur = triangles; cur; cur = cur->next) { - RoamTriangle *tri = cur->data; - - gdouble lat[3] = {tri->p.r->lat, tri->p.m->lat, tri->p.l->lat}; - gdouble lon[3] = {tri->p.r->lon, tri->p.m->lon, tri->p.l->lon}; - - if (lon[0] < -90 || lon[1] < -90 || lon[2] < -90) { - if (lon[0] > 90) lon[0] -= 360; - if (lon[1] > 90) lon[1] -= 360; - if (lon[2] > 90) lon[2] -= 360; - } - - gdouble n = tile->edge.n; - gdouble s = tile->edge.s; - gdouble e = tile->edge.e; - gdouble w = tile->edge.w; - - gdouble londist = e - w; - gdouble latdist = n - s; - - gdouble xy[3][2] = { - {(lon[0]-w)/londist, 1-(lat[0]-s)/latdist}, - {(lon[1]-w)/londist, 1-(lat[1]-s)/latdist}, - {(lon[2]-w)/londist, 1-(lat[2]-s)/latdist}, - }; - - //if ((lat[0] == 90 && (xy[0][0] < 0 || xy[0][0] > 1)) || - // (lat[1] == 90 && (xy[1][0] < 0 || xy[1][0] > 1)) || - // (lat[2] == 90 && (xy[2][0] < 0 || xy[2][0] > 1))) - // g_message("w,e=%4.f,%4.f " - // "lat,lon,x,y=" - // "%4.1f,%4.0f,%4.2f,%4.2f " - // "%4.1f,%4.0f,%4.2f,%4.2f " - // "%4.1f,%4.0f,%4.2f,%4.2f ", - // w,e, - // lat[0], lon[0], xy[0][0], xy[0][1], - // lat[1], lon[1], xy[1][0], xy[1][1], - // lat[2], lon[2], xy[2][0], xy[2][1]); - - /* Fix poles */ - if (lat[0] == 90 || lat[0] == -90) xy[0][0] = 0.5; - if (lat[1] == 90 || lat[1] == -90) xy[1][0] = 0.5; - if (lat[2] == 90 || lat[2] == -90) xy[2][0] = 0.5; - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data); - 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); - glNormal3dv(tri->p.l->norm); glTexCoord2dv(xy[2]); glVertex3dv((double*)tri->p.l); - glEnd(); - } - g_list_free(triangles); -} - -static void gis_opengl_render_tiles(GisViewer *_self, GisTile *tile) -{ - GisOpenGL *self = GIS_OPENGL(_self); - /* Only render children if possible */ - gboolean has_children = TRUE; - GisTile *child; - gis_tile_foreach(tile, child) - if (!child || !child->data) - has_children = FALSE; - if (has_children) - /* Only render children */ - gis_tile_foreach(tile, child) - gis_opengl_render_tiles(_self, child); - else - /* No children, render this tile */ - gis_opengl_render_tile(_self, tile); -} - static void gis_opengl_set_height_func(GisViewer *_self, GisTile *tile, RoamHeightFunc height_func, gpointer user_data, gboolean update) { @@ -703,8 +686,6 @@ static void gis_opengl_class_init(GisOpenGLClass *klass) viewer_class->project = gis_opengl_project; viewer_class->clear_height_func = gis_opengl_clear_height_func; viewer_class->set_height_func = gis_opengl_set_height_func; - viewer_class->render_tile = gis_opengl_render_tile; - 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;