From 151d4a843de192794f824440f8ebba1b0cce74c9 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Tue, 24 Jun 2008 06:45:20 +0000 Subject: [PATCH] got levels working, plus faster --- src/aweather.c | 6 +- src/cube.c | 4 +- src/opengl.c | 42 +++++----- src/radar.c | 209 ++++++++++++++++++++++++++++++++++--------------- 4 files changed, 174 insertions(+), 87 deletions(-) diff --git a/src/aweather.c b/src/aweather.c index 56d9979..58fc7a8 100644 --- a/src/aweather.c +++ b/src/aweather.c @@ -63,9 +63,9 @@ int main(int argc, char *argv[]) GtkWidget *tab_area = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tab_area), GTK_POS_BOTTOM); gtk_paned_pack2(GTK_PANED(paned), tab_area, FALSE, FALSE); - GtkWidget *label = gtk_label_new("Hello"); - GtkWidget *contents = gtk_label_new("World"); - gtk_notebook_append_page(GTK_NOTEBOOK(tab_area), contents, label); + //GtkWidget *label = gtk_label_new("Hello"); + //GtkWidget *contents = gtk_label_new("World"); + //gtk_notebook_append_page(GTK_NOTEBOOK(tab_area), contents, label); /* Load plugins */ opengl_init(GTK_DRAWING_AREA(drawing), GTK_NOTEBOOK(tab_area)); diff --git a/src/cube.c b/src/cube.c index c20f702..18bdb4c 100644 --- a/src/cube.c +++ b/src/cube.c @@ -107,8 +107,8 @@ static gboolean rotate(gpointer user_data) ang++; - gdk_window_invalidate_rect (da->window, &da->allocation, FALSE); - gdk_window_process_updates (da->window, FALSE); + gdk_window_invalidate_rect(da->window, &da->allocation, FALSE); + gdk_window_process_updates(da->window, FALSE); return TRUE; } diff --git a/src/opengl.c b/src/opengl.c index 3561869..18d71c1 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -5,11 +5,11 @@ static gboolean expose_start(GtkWidget *da, GdkEventExpose *event, gpointer user_data) { - GdkGLContext *glcontext = gtk_widget_get_gl_context (da); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (da); + GdkGLContext *glcontext = gtk_widget_get_gl_context(da); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); - if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) { - g_assert_not_reached (); + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) { + g_assert_not_reached(); } /* draw in here */ @@ -18,37 +18,37 @@ static gboolean expose_start(GtkWidget *da, GdkEventExpose *event, gpointer user /* Plugins run stuff here */ static gboolean expose_end(GtkWidget *da, GdkEventExpose *event, gpointer user_data) { - GdkGLContext *glcontext = gtk_widget_get_gl_context (da); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (da); + GdkGLContext *glcontext = gtk_widget_get_gl_context(da); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); - if (gdk_gl_drawable_is_double_buffered (gldrawable)) - gdk_gl_drawable_swap_buffers (gldrawable); + if (gdk_gl_drawable_is_double_buffered(gldrawable)) + gdk_gl_drawable_swap_buffers(gldrawable); else - glFlush (); + glFlush(); - gdk_gl_drawable_gl_end (gldrawable); + gdk_gl_drawable_gl_end(gldrawable); return FALSE; } static gboolean configure(GtkWidget *da, GdkEventConfigure *event, gpointer user_data) { - GdkGLContext *glcontext = gtk_widget_get_gl_context (da); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (da); + GdkGLContext *glcontext = gtk_widget_get_gl_context(da); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); - if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) - g_assert_not_reached (); + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + g_assert_not_reached(); glLoadIdentity(); - glViewport (0, 0, da->allocation.width, da->allocation.height); - glOrtho (-10,10,-10,10,-20050,10000); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glViewport(0, 0, da->allocation.width, da->allocation.height); + glOrtho(-10,10,-10,10,-20050,10000); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glScalef (10., 10., 10.); + glScalef(10., 10., 10.); - gdk_gl_drawable_gl_end (gldrawable); + gdk_gl_drawable_gl_end(gldrawable); - return TRUE; + return FALSE; } gboolean opengl_init(GtkDrawingArea *drawing, GtkNotebook *config) diff --git a/src/radar.c b/src/radar.c index d31343a..a9ae4a7 100644 --- a/src/radar.c +++ b/src/radar.c @@ -9,65 +9,131 @@ #include "radar.h" -static GtkWidget *rotate_button; -static Radar *radar; -static Sweep *sweep; +GtkWidget *drawing; +static Sweep *cur_sweep; // make this not global static int nred, ngreen, nblue; -static unsigned char red[256], green[256], blue[256]; +static guint8 red[256], green[256], blue[256]; -static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data) +/* Convert a sweep to an 2d array of data points */ +static void bscan_sweep(Sweep *sweep, guint8 **data, int *width, int *height) { - GdkGLContext *glcontext = gtk_widget_get_gl_context (da); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (da); + /* Calculate max number of bins */ + int i, max_bins = 0; + for (i = 0; i < sweep->h.nrays; i++) + max_bins = MAX(max_bins, sweep->ray[i]->h.nbins); + + /* Allocate buffer using max number of bins for each ray */ + char *buf = g_malloc0(sweep->h.nrays * max_bins * 3); + + /* Fill the data */ + int ri, bi; + for (ri = 0; ri < sweep->h.nrays; ri++) { + Ray *ray = sweep->ray[ri]; + for (bi = 0; bi < ray->h.nbins; bi++) { + Range bin = ray->range[bi]; + /* copy RGB into buffer */ + buf[(ri*max_bins+bi)*3+0] = red[(guint8)ray->h.f(bin)]; + buf[(ri*max_bins+bi)*3+1] = green[(guint8)ray->h.f(bin)]; + buf[(ri*max_bins+bi)*3+2] = blue[(guint8)ray->h.f(bin)]; + } + } - /* draw in here */ - glPushMatrix(); - - glRotatef(0, 0, 0, 0); + /* set output */ + *width = max_bins; + *height = sweep->h.nrays; + *data = buf; + + /* debug */ + //static int fi = 0; + //char fname[128]; + //sprintf(fname, "image-%d.ppm", fi); + //FILE *fp = fopen(fname, "w+"); + //fprintf(fp, "P6\n"); + //fprintf(fp, "# Foo\n"); + //fprintf(fp, "%d %d\n", *width, *height); + //fprintf(fp, "255\n"); + //fwrite(buf, 3, *width * *height, fp); + //fclose(fp); + //fi++; +} + +/* Load a sweep as the active texture */ +static void load_sweep(Sweep *sweep) +{ + cur_sweep = sweep; + int height, width; + guint8 *data; + bscan_sweep(sweep, &data, &width, &height); + glEnable(GL_TEXTURE_2D); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + free(data); + gdk_window_invalidate_rect(drawing->window, &drawing->allocation, FALSE); +} - glShadeModel(GL_FLAT); +/* Load the default sweep */ +static gboolean configure(GtkWidget *da, GdkEventConfigure *event, gpointer user_data) +{ + GdkGLContext *glcontext = gtk_widget_get_gl_context(da); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); - glBegin(GL_QUADS); + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + g_assert_not_reached(); - int rayi; - for (rayi = 0; rayi < sweep->h.nrays; rayi++) { - Ray *ray = sweep->ray[rayi]; - - /* right and left with respect to north */ - double right = ((ray->h.azimuth + ray->h.beam_width)*M_PI)/180.0; - double left = ((ray->h.azimuth - ray->h.beam_width)*M_PI)/180.0; - - double rx = sin(right), ry = cos(right); - double lx = sin(left), ly = cos(left); - - int nbins = ray->h.nbins; - //int nbins = 20; - int max_dist = nbins * ray->h.gate_size + ray->h.range_bin1; - int bini, dist = ray->h.range_bin1; - for (bini = 0; bini < nbins; bini++, dist += ray->h.gate_size) { - if (ray->range[bini] == BADVAL) continue; - - /* (find middle of bin) / scale for opengl */ - double nd = ((double)dist - ((double)ray->h.gate_size)/2.) / (double)max_dist; - double fd = ((double)dist + ((double)ray->h.gate_size)/2.) / (double)max_dist; - - glColor3ub( - red[(unsigned char)ray->h.f(ray->range[bini])], - green[(unsigned char)ray->h.f(ray->range[bini])], - blue[(unsigned char)ray->h.f(ray->range[bini])] - ); - - glVertex3f(lx*nd, ly*nd, 0.); // near left - glVertex3f(lx*fd, ly*fd, 0.); // far left - glVertex3f(rx*fd, ry*fd, 0.); // far right - glVertex3f(rx*nd, ry*nd, 0.); // near right + /* Load the texture */ + load_sweep(cur_sweep); - } + gdk_gl_drawable_gl_end(gldrawable); - g_print("\n"); - } + return FALSE; +} +static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data) +{ + Sweep *sweep = cur_sweep; + + GdkGLContext *glcontext = gtk_widget_get_gl_context(da); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); + + /* draw in here */ + glPushMatrix(); + glRotatef(0, 0, 0, 0); + + /* Draw the rays */ + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUAD_STRIP); + int _ri; // not really used, creates strange fragments.. + for (_ri = 0; _ri < sweep->h.nrays; _ri++) { + /* Do the first sweep twice to complete the last Quad */ + int ri = _ri % sweep->h.nrays; + Ray *ray = sweep->ray[ri]; + + /* right and left looking out from radar */ + double left = ((ray->h.azimuth - ((double)ray->h.beam_width/2.))*M_PI)/180.0; + double right = ((ray->h.azimuth + ((double)ray->h.beam_width/2.))*M_PI)/180.0; + + double lx = sin(left); + double ly = cos(left); + + /* TODO: change this to meters instead of 0..1 */ + double max_dist = ray->h.nbins*ray->h.gate_size + ray->h.range_bin1; + double near_dist = (double)(ray->h.range_bin1) / max_dist; + double far_dist = (double)(ray->h.nbins*ray->h.gate_size + ray->h.range_bin1) / max_dist; + + /* (find middle of bin) / scale for opengl */ + glTexCoord2d(0.0, ((double)ri)/sweep->h.nrays); glVertex3f(lx*near_dist, ly*near_dist, 0.); // near left + glTexCoord2d(0.7, ((double)ri)/sweep->h.nrays); glVertex3f(lx*far_dist, ly*far_dist, 0.); // far left + } + g_printf("ri=%d, nr=%d, bw=%f\n", _ri, sweep->h.nrays, sweep->h.beam_width); glEnd(); + /* Texture debug */ + //glBegin(GL_QUADS); + //glTexCoord2d( 0., 0.); glVertex3f(-1., 0., 0.); // bot left + //glTexCoord2d( 0., 1.); glVertex3f(-1., 1., 0.); // top left + //glTexCoord2d( 1., 1.); glVertex3f( 0., 1., 0.); // top right + //glTexCoord2d( 1., 0.); glVertex3f( 0., 0., 0.); // bot right + //glEnd(); + glDisable(GL_TEXTURE_2D); /* Print the color table */ glBegin(GL_QUADS); @@ -81,30 +147,51 @@ static gboolean expose(GtkWidget *da, GdkEventExpose *event, gpointer user_data) } glEnd(); - glPopMatrix (); + glPopMatrix(); return FALSE; } -gboolean radar_init(GtkDrawingArea *drawing, GtkNotebook *config) +gboolean radar_init(GtkDrawingArea *_drawing, GtkNotebook *config) { - /* Add configuration tab */ - GtkWidget *label = gtk_label_new("Radar"); - rotate_button = gtk_toggle_button_new_with_label("Rotate"); - gtk_notebook_append_page(GTK_NOTEBOOK(config), rotate_button, label); - + drawing = GTK_WIDGET(_drawing); /* Set up OpenGL Stuff */ - g_signal_connect(drawing, "expose-event", G_CALLBACK(expose), NULL); + g_signal_connect(drawing, "expose-event", G_CALLBACK(expose), NULL); + g_signal_connect(drawing, "configure-event", G_CALLBACK(configure), NULL); /* Parse hard coded file.. */ - RSL_read_these_sweeps("0", NULL); - radar = RSL_wsr88d_to_radar("/scratch/aweather/src/KABR_20080609_0224", "KABR"); - RSL_load_refl_color_table(); + RSL_read_these_sweeps("all", NULL); + //RSL_read_these_sweeps("all", NULL); + Radar *radar = RSL_wsr88d_to_radar("/scratch/aweather/src/KABR_20080609_0224", "KABR"); + //radar = RSL_wsr88d_to_radar("/scratch/aweather/src/KABX_20080622_2229", "KABX"); + RSL_load_vel_color_table(); RSL_get_color_table(RSL_RED_TABLE, red, &nred); RSL_get_color_table(RSL_GREEN_TABLE, green, &ngreen); RSL_get_color_table(RSL_BLUE_TABLE, blue, &nblue); if (radar->h.nvolumes < 1 || radar->v[0]->h.nsweeps < 1) g_print("No sweeps found\n"); - sweep = radar->v[0]->sweep[0]; - RSL_volume_to_gif(radar->v[DZ_INDEX], "dz_sweep", 1024, 1024, 200.0); + cur_sweep = radar->v[0]->sweep[0]; + + /* Add configuration tab */ + GtkWidget *hbox = gtk_hbox_new(TRUE, 0); + GtkWidget *button = NULL; + int vi = 0, si = 0; + for (vi = 0; vi < radar->h.nvolumes; vi++) { + Volume *vol = radar->v[vi]; + if (vol == NULL) continue; + GtkWidget *vbox = gtk_vbox_new(TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + for (si = 0; si < vol->h.nsweeps; si++) { + Sweep *sweep = vol->sweep[si]; + if (sweep == NULL) continue; + char *label = g_strdup_printf("Tilt: %.2f (%s)", sweep->h.elev, vol->h.type_str); + button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(button), label); + g_signal_connect_swapped(button, "clicked", G_CALLBACK(load_sweep), sweep); + gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); + free(label); + } + } + GtkWidget *label = gtk_label_new("Radar"); + gtk_notebook_append_page(GTK_NOTEBOOK(config), hbox, label); + } -- 2.43.2