aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-08-31 16:23:33 +0000
committertaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-08-31 16:23:33 +0000
commit9211fbeed3b968f3364dcb42f4b3b48b78e4ad0b (patch)
treef3c4e52fe3741a62bd43bc91236e7b4f359d53e2
parent9649fcb9e495eb7943bf939845a36cae192e4f20 (diff)
Big performance increase due to using vertex arrays for rendering
git-svn-id: svn://cook.msm.cam.ac.uk:745/diff-tomo/dtr@102 bf6ca9ba-c028-0410-8290-897cf20841d1
-rw-r--r--src/control.h15
-rw-r--r--src/displaywindow.c306
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);
}