diff options
-rw-r--r-- | src/control.h | 15 | ||||
-rw-r--r-- | src/displaywindow.c | 306 |
2 files changed, 241 insertions, 80 deletions
diff --git a/src/control.h b/src/control.h index ac3a357..69d57f6 100644 --- a/src/control.h +++ b/src/control.h @@ -18,6 +18,7 @@ #include <gtk/gtk.h> #include <inttypes.h> +#include <GL/gl.h> #define MAX_IMAGES 256 @@ -115,6 +116,20 @@ typedef struct cctx_struct { GtkWidget *combo_peaksearch; GtkWidget *checkbox_prealign; GtkWidget *checkbox_savecache; + GLuint gl_list_id; +// GLuint gl_ref_buffer; +// GLuint gl_element_buffer; + GLfloat *gl_ref_vertex_array; + GLuint *gl_ref_element_array; + GLsizei gl_ref_num_vertices; + + GLfloat *gl_marker_vertex_array; + GLuint *gl_marker_element_array; + GLsizei gl_marker_num_vertices; + + GLfloat *gl_gen_vertex_array; + GLuint *gl_gen_element_array; + GLsizei gl_gen_num_vertices; } ControlContext; diff --git a/src/displaywindow.c b/src/displaywindow.c index e73cbc5..762ab0f 100644 --- a/src/displaywindow.c +++ b/src/displaywindow.c @@ -21,6 +21,7 @@ #include <gdk/gdkgl.h> #include <gtk/gtkgl.h> #include <GL/gl.h> +#include <GL/glext.h> #include <GL/glu.h> #include "trackball.h" @@ -239,54 +240,159 @@ static gint displaywindow_gl_motion_notify(GtkWidget *widget, GdkEventMotion *ev return TRUE; } -static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, ControlContext *ctx) { - - GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); - GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); - GLfloat light0_position[] = { 0.0, 0.0, 100.0, 0.0 }; - GLfloat light0_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; - GLfloat light0_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - GLfloat light1_position[] = { 0.0, 0.0, -100.0, 0.0 }; - GLfloat light1_diffuse[] = { 0.8, 0.8, 0.8, 1.0 }; - GLfloat light1_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 }; +#define VERTICES_IN_A_BLOB 24 +#define DRAW_BLOB \ + GLfloat d; \ + GLfloat size=0.2; \ + for ( d = -1.4*size; d<= 1.4*size; d+=2.8*size-0.001 ) { /* Precision issues.. */ \ + vertices[3*i + 0] = reflection->x/1e9 - size; \ + vertices[3*i + 1] = reflection->y/1e9 - size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 - size; \ + vertices[3*i + 1] = reflection->y/1e9 + size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9; \ + vertices[3*i + 1] = reflection->y/1e9; \ + vertices[3*i + 2] = reflection->z/1e9 + d; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 - size; \ + vertices[3*i + 1] = reflection->y/1e9 + size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 + size; \ + vertices[3*i + 1] = reflection->y/1e9 + size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9; \ + vertices[3*i + 1] = reflection->y/1e9; \ + vertices[3*i + 2] = reflection->z/1e9 + d; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 + size; \ + vertices[3*i + 1] = reflection->y/1e9 + size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 + size; \ + vertices[3*i + 1] = reflection->y/1e9 - size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9; \ + vertices[3*i + 1] = reflection->y/1e9; \ + vertices[3*i + 2] = reflection->z/1e9 + d; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 + size; \ + vertices[3*i + 1] = reflection->y/1e9 - size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9 - size; \ + vertices[3*i + 1] = reflection->y/1e9 - size; \ + vertices[3*i + 2] = reflection->z/1e9; \ + elements[i] = i; i++; \ + vertices[3*i + 0] = reflection->x/1e9; \ + vertices[3*i + 1] = reflection->y/1e9; \ + vertices[3*i + 2] = reflection->z/1e9 + d; \ + elements[i] = i; i++; \ + } + +static void displaywindow_gl_create_list(ControlContext *ctx) { + GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 }; GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 }; - GLfloat gold[] = { 0.7, 0.7, 0.0, 1.0 }; GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 }; GLfloat yellow_glass[] = { 1.0, 1.0, 0.0, 000.1 }; - float m[4][4]; -// GLfloat fog_density = 0.03; Reflection *reflection; GLUquadricObj *quadric; + int i; + GLfloat *vertices; + GLuint *elements; - if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) { - return 0; - } + /* Put the measured reflections in a buffer object */ +// glGenBuffers(1, &ctx->gl_ref_buffer); +// glGenBuffers(1, &ctx->gl_element_buffer); +// glBindBuffer(GL_ARRAY_BUFFER, ctx->gl_ref_buffer); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnable(GL_DEPTH_TEST); -// glEnable(GL_FOG); -// glFogfv(GL_FOG_DENSITY, &fog_density); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glLoadIdentity(); - glTranslatef(displaywindow_x_pos, -displaywindow_y_pos, -displaywindow_distance); - build_rotmatrix(m, view_quat); - glMultMatrixf(&m[0][0]); + /* Count the number of "normal" reflections */ + reflection = ctx->reflectionctx->reflections; + i = 0; + do { + if ( reflection->type == REFLECTION_NORMAL ) i++; + reflection = reflection->next; + } while ( reflection != NULL ); + ctx->gl_ref_num_vertices = i; + i = 0; + reflection = ctx->reflectionctx->reflections; + vertices = malloc(3*ctx->gl_ref_num_vertices*sizeof(GLfloat)); + elements = malloc(ctx->gl_ref_num_vertices*sizeof(GLuint)); + do { + if ( reflection->type == REFLECTION_NORMAL ) { + vertices[3*i + 0] = reflection->x/1e9; + vertices[3*i + 1] = reflection->y/1e9; + vertices[3*i + 2] = reflection->z/1e9; + elements[i] = i; + i++; + } + reflection = reflection->next; + } while ( reflection != NULL ); + ctx->gl_ref_vertex_array = vertices; +// glBufferData(GL_ARRAY_BUFFER, 3*ctx->gl_ref_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW); +// free(vertices); + ctx->gl_ref_element_array = elements; +// glBufferData(GL_ARRAY_BUFFER, ctx->gl_ref_num_vertices*sizeof(GLushort), elements, GL_STATIC_DRAW); +// free(elements); + + /* Count the number of marker "reflections" */ + reflection = ctx->reflectionctx->reflections; + i = 0; + do { + if ( reflection->type == REFLECTION_MARKER ) i++; + reflection = reflection->next; + } while ( reflection != NULL ); + ctx->gl_marker_num_vertices = i*VERTICES_IN_A_BLOB; + i = 0; + reflection = ctx->reflectionctx->reflections; + vertices = malloc(3*ctx->gl_marker_num_vertices*sizeof(GLfloat)); + elements = malloc(ctx->gl_marker_num_vertices*sizeof(GLuint)); + do { + if ( reflection->type == REFLECTION_MARKER ) { + DRAW_BLOB + } + reflection = reflection->next; + } while ( reflection != NULL ); + ctx->gl_marker_vertex_array = vertices; +// glBufferData(GL_ARRAY_BUFFER, 3*ctx->gl_ref_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW); +// free(vertices); + ctx->gl_marker_element_array = elements; +// glBufferData(GL_ARRAY_BUFFER, ctx->gl_ref_num_vertices*sizeof(GLushort), elements, GL_STATIC_DRAW); +// free(elements); + + /* Count the number of generated reflections */ + reflection = ctx->reflectionctx->reflections; + i = 0; + do { + if ( reflection->type == REFLECTION_GENERATED ) i++; + reflection = reflection->next; + } while ( reflection != NULL ); + ctx->gl_gen_num_vertices = i*VERTICES_IN_A_BLOB; + i = 0; + reflection = ctx->reflectionctx->reflections; + vertices = malloc(3*ctx->gl_gen_num_vertices*sizeof(GLfloat)); + elements = malloc(ctx->gl_gen_num_vertices*sizeof(GLuint)); + do { + if ( reflection->type == REFLECTION_GENERATED ) { + DRAW_BLOB + } + reflection = reflection->next; + } while ( reflection != NULL ); + ctx->gl_gen_vertex_array = vertices; +// glBufferData(GL_ARRAY_BUFFER, 3*ctx->gl_ref_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW); +// free(vertices); + ctx->gl_gen_element_array = elements; +// glBufferData(GL_ARRAY_BUFFER, ctx->gl_ref_num_vertices*sizeof(GLushort), elements, GL_STATIC_DRAW); +// free(elements); - /* Set up lighting */ - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glLightfv(GL_LIGHT0, GL_POSITION, light0_position); - glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); - glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); - glEnable(GL_LIGHT1); - glLightfv(GL_LIGHT1, GL_POSITION, light1_position); - glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); - glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); + ctx->gl_list_id = glGenLists(1); + glNewList(ctx->gl_list_id, GL_COMPILE); /* Bounding cube: 100 nm^-1 side length */ glBegin(GL_LINE_LOOP); @@ -331,18 +437,6 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co glVertex3f(50-5, 1.0, 1.0); glEnd(); - /* Plot all the normal (measured) reflections */ - reflection = ctx->reflectionctx->reflections; - glBegin(GL_POINTS); - do { - if ( reflection->type == REFLECTION_NORMAL ) { - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green); - glVertex3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9); - } - reflection = reflection->next; - } while ( reflection != NULL ); - glEnd(); - /* Plot the other reflections */ reflection = ctx->reflectionctx->reflections; quadric = gluNewQuadric(); @@ -356,34 +450,10 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co gluSphere(quadric, 0.2, 32, 32); glPopMatrix(); - } else if ( reflection->type == REFLECTION_GENERATED ) { - - double x, y, z; - signed int h, k, l; - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gold); - glPushMatrix(); - - /* Change hkl to xyz */ - h = reflection->h; k = reflection->k; l = reflection->l; - x = h*ctx->reflectionctx->basis->a.x + k*ctx->reflectionctx->basis->b.x + l*ctx->reflectionctx->basis->c.x; - y = h*ctx->reflectionctx->basis->a.y + k*ctx->reflectionctx->basis->b.y + l*ctx->reflectionctx->basis->c.y; - z = h*ctx->reflectionctx->basis->a.z + k*ctx->reflectionctx->basis->b.z + l*ctx->reflectionctx->basis->c.z; - glTranslatef(x/1e9, y/1e9, z/1e9); - - gluSphere(quadric, 0.2, 8, 8); - glPopMatrix(); - - } else if ( reflection->type == REFLECTION_MARKER ) { - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gold); - glPushMatrix(); - glTranslatef(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9); - gluSphere(quadric, 0.2, 8, 8); - glPopMatrix(); - } + reflection = reflection->next; + } while ( reflection != NULL ); /* If this is an iterative prediction-refinement reconstruction, draw the unit cell */ @@ -441,6 +511,81 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co glVertex3f(-50, 50, 0.0); glEnd(); + glEndList(); + +} + +static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, ControlContext *ctx) { + + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + float m[4][4]; +// GLfloat fog_density = 0.03; + GLfloat light0_position[] = { 0.0, 0.0, 100.0, 0.0 }; + GLfloat light0_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + GLfloat light0_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + GLfloat light1_position[] = { 0.0, 0.0, -100.0, 0.0 }; + GLfloat light1_diffuse[] = { 0.8, 0.8, 0.8, 1.0 }; + GLfloat light1_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 }; + GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 }; + GLfloat gold[] = { 0.7, 0.7, 0.0, 1.0 }; + + if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) { + return 0; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); +// glEnable(GL_FOG); +// glFogfv(GL_FOG_DENSITY, &fog_density); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glLoadIdentity(); + glTranslatef(displaywindow_x_pos, -displaywindow_y_pos, -displaywindow_distance); + build_rotmatrix(m, view_quat); + glMultMatrixf(&m[0][0]); + + /* Set up lighting */ + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0, GL_POSITION, light0_position); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); + glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1, GL_POSITION, light1_position); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); + + /* Draw the "measured" reflections */ + glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + glEnableClientState(GL_VERTEX_ARRAY); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green); + glVertexPointer(3, GL_FLOAT, 0, ctx->gl_ref_vertex_array); + glDrawRangeElements(GL_POINTS, 0, ctx->gl_ref_num_vertices, ctx->gl_ref_num_vertices, GL_UNSIGNED_INT, ctx->gl_ref_element_array); + glPopClientAttrib(); + + /* Draw marker points */ + glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + glEnableClientState(GL_VERTEX_ARRAY); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue); + glVertexPointer(3, GL_FLOAT, 0, ctx->gl_marker_vertex_array); + glDrawRangeElements(GL_TRIANGLES, 0, ctx->gl_marker_num_vertices, ctx->gl_marker_num_vertices, GL_UNSIGNED_INT, ctx->gl_marker_element_array); + glPopClientAttrib(); + + /* Draw generated reflections */ + glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + glEnableClientState(GL_VERTEX_ARRAY); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gold); + glVertexPointer(3, GL_FLOAT, 0, ctx->gl_gen_vertex_array); + glDrawRangeElements(GL_TRIANGLES, 0, ctx->gl_gen_num_vertices, ctx->gl_gen_num_vertices, GL_UNSIGNED_INT, ctx->gl_gen_element_array); + glPopClientAttrib(); + + /* Draw everything else */ + glCallList(ctx->gl_list_id); + if ( gdk_gl_drawable_is_double_buffered(gldrawable) ) { gdk_gl_drawable_swap_buffers(gldrawable); } else { @@ -453,7 +598,7 @@ static gint displaywindow_gl_expose(GtkWidget *widget, GdkEventExpose *event, Co } -static gint displaywindow_gl_realise(GtkWidget *widget, gpointer data) { +static gint displaywindow_gl_realise(GtkWidget *widget, ControlContext *ctx) { GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); @@ -467,6 +612,7 @@ static gint displaywindow_gl_realise(GtkWidget *widget, gpointer data) { glClearColor(0.002, 0.0, 0.1, 1.0); glClearDepth(1.0); displaywindow_gl_set_ortho(w, h); + displaywindow_gl_create_list(ctx); gdk_gl_drawable_gl_end(gldrawable); @@ -548,11 +694,11 @@ void displaywindow_open(ControlContext *ctx) { gtk_box_pack_start(GTK_BOX(displaywindow_bigvbox), displaywindow_drawing_area, TRUE, TRUE, 0); gtk_widget_add_events(displaywindow_drawing_area, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_VISIBILITY_NOTIFY_MASK); g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "configure_event", G_CALLBACK(displaywindow_gl_configure), NULL); - g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "realize", G_CALLBACK(displaywindow_gl_realise), NULL); + g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "realize", G_CALLBACK(displaywindow_gl_realise), ctx); g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "expose_event", G_CALLBACK(displaywindow_gl_expose), ctx); g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "button_press_event", G_CALLBACK(displaywindow_gl_button_press), NULL); g_signal_connect(GTK_OBJECT(displaywindow_drawing_area), "motion_notify_event", G_CALLBACK(displaywindow_gl_motion_notify), NULL); - + gtk_widget_show_all(displaywindow_window); } |