aboutsummaryrefslogtreecommitdiff
path: root/src/glbits.c
diff options
context:
space:
mode:
authortaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-12-20 21:03:24 +0000
committertaw27 <taw27@bf6ca9ba-c028-0410-8290-897cf20841d1>2007-12-20 21:03:24 +0000
commitfa3a0f357371cf1b9da58c2e00334c905a898f96 (patch)
treed4c14deb5580b033de689eb896eb6d808389a01d /src/glbits.c
parentbf06787466886fc0353b57fdcb3b4b3186e5fbdf (diff)
Move OpenGL stuff to new module
git-svn-id: svn://cook.msm.cam.ac.uk:745/diff-tomo/dtr@233 bf6ca9ba-c028-0410-8290-897cf20841d1
Diffstat (limited to 'src/glbits.c')
-rw-r--r--src/glbits.c814
1 files changed, 814 insertions, 0 deletions
diff --git a/src/glbits.c b/src/glbits.c
new file mode 100644
index 0000000..194a919
--- /dev/null
+++ b/src/glbits.c
@@ -0,0 +1,814 @@
+/*
+ * glbits.c
+ *
+ * OpenGL bits
+ *
+ * (c) 2007 Thomas White <taw27@cam.ac.uk>
+ *
+ * dtr - Diffraction Tomography Reconstruction
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdkgl.h>
+#include <gtk/gtkgl.h>
+#define GL_GLEXT_PROTOTYPES 1
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glu.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "displaywindow.h"
+#include "trackball.h"
+#include "reflections.h"
+#include "image.h"
+
+#define BLOB_BITS 5
+#define VERTICES_IN_A_BLOB 4*BLOB_BITS*BLOB_BITS*2
+#define ADD_VERTEX \
+ vertices[3*i + 0] = reflection->x/1e9 + size*xv; \
+ vertices[3*i + 1] = reflection->y/1e9 + size*yv; \
+ vertices[3*i + 2] = reflection->z/1e9 + size*zv; \
+ normals[3*i + 0] = xv; \
+ normals[3*i + 1] = yv; \
+ normals[3*i + 2] = zv; \
+ i++;
+
+#define DRAW_BLOB \
+ double step = M_PI/(double)BLOB_BITS; \
+ int is, js; \
+ for ( is=0; is<BLOB_BITS; is++ ) { \
+ for ( js=0; js<BLOB_BITS*2; js++ ) { \
+ double theta, phi; \
+ GLfloat xv, yv, zv; \
+ theta = (M_PI/(double)BLOB_BITS) * (double)js; \
+ phi = (M_PI/(double)BLOB_BITS) * (double)is; \
+ xv = sin(theta)*sin(phi); \
+ yv = cos(phi); \
+ zv = cos(theta)*sin(phi); \
+ ADD_VERTEX \
+ xv = sin(theta)*sin(phi+step); \
+ yv = cos(phi+step); \
+ zv = cos(theta)*sin(phi+step); \
+ ADD_VERTEX \
+ xv = sin(theta+step)*sin(phi+step); \
+ yv = cos(phi+step); \
+ zv = cos(theta+step)*sin(phi+step); \
+ ADD_VERTEX \
+ xv = sin(theta+step)*sin(phi); \
+ yv = cos(phi); \
+ zv = cos(theta+step)*sin(phi); \
+ ADD_VERTEX \
+ } \
+ }
+
+#define DRAW_POINTER_LINE \
+ glBegin(GL_LINES); \
+ glVertex3f(1.0, 0.0, 0.0); \
+ glVertex3f(0.0, 0.0, 0.0); \
+ glEnd();
+
+#define DRAW_POINTER_HEAD \
+ glPushMatrix(); \
+ for ( pointer_head_face = 1; pointer_head_face <= 4; pointer_head_face++ ) { \
+ glRotatef(90.0, 1.0, 0.0, 0.0); \
+ glBegin(GL_TRIANGLES); \
+ /* One face */ \
+ glNormal3f(0.2, 0.8, 0.0); \
+ glVertex3f(1.0, 0.0, 0.0); \
+ glVertex3f(0.8, 0.2, 0.2); \
+ glVertex3f(0.8, 0.2, -0.2); \
+ /* One quarter of the "bottom square" */ \
+ glNormal3f(1.0, 0.0, 0.0); \
+ glVertex3f(0.8, 0.2, 0.2); \
+ glVertex3f(0.8, 0.2, -0.2); \
+ glVertex3f(0.8, 0.0, 0.0); \
+ glEnd(); \
+ } \
+ glPopMatrix();
+
+void glbits_prepare(DisplayWindow *dw) {
+
+ GLfloat bblue[] = { 0.0, 0.0, 1.0, 1.0 };
+ GLfloat blue[] = { 0.0, 0.0, 0.5, 1.0 };
+ GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
+ GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
+ GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
+ GLfloat glass[] = { 0.2, 0.0, 0.8, 000.1 };
+ GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
+ Reflection *reflection;
+ int i;
+ ControlContext *ctx;
+ GLfloat *vertices;
+ GLfloat *normals;
+
+ ctx = dw->ctx;
+
+ /* "Measured" reflections */
+ if ( dw->gl_use_buffers ) {
+ glGenBuffersARB(1, &dw->gl_ref_vertex_buffer);
+ glGenBuffersARB(1, &dw->gl_ref_normal_buffer);
+ }
+ reflection = ctx->reflectionlist->reflections;
+ i = 0;
+ while ( reflection != NULL ) {
+ if ( reflection->type == REFLECTION_NORMAL ) i++;
+ reflection = reflection->next;
+ };
+ dw->gl_ref_num_vertices = i;
+ if ( dw->gl_ref_num_vertices ) {
+ i = 0;
+ reflection = ctx->reflectionlist->reflections;
+ vertices = malloc(3*dw->gl_ref_num_vertices*sizeof(GLfloat));
+ normals = malloc(3*dw->gl_ref_num_vertices*sizeof(GLfloat));
+ while ( reflection != NULL ) {
+ 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;
+ normals[3*i + 0] = reflection->x/1e9;
+ normals[3*i + 1] = reflection->y/1e9;
+ normals[3*i + 2] = reflection->z/1e9;
+ i++;
+ }
+ reflection = reflection->next;
+ };
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_ref_vertex_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_ref_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
+ free(vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_ref_normal_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_ref_num_vertices*sizeof(GLfloat), normals, GL_STATIC_DRAW);
+ free(normals);
+ } else {
+ dw->gl_ref_vertex_array = vertices;
+ dw->gl_ref_normal_array = normals;
+ }
+ }
+
+ /* Marker "reflections" */
+ if ( dw->gl_use_buffers ) {
+ glGenBuffersARB(1, &dw->gl_marker_vertex_buffer);
+ glGenBuffersARB(1, &dw->gl_marker_normal_buffer);
+ }
+ reflection = ctx->reflectionlist->reflections;
+ i = 0;
+ while ( reflection != NULL ) {
+ if ( reflection->type == REFLECTION_MARKER ) i++;
+ reflection = reflection->next;
+ };
+ dw->gl_marker_num_vertices = i*VERTICES_IN_A_BLOB;
+ if ( dw->gl_marker_num_vertices ) {
+ i = 0;
+ reflection = ctx->reflectionlist->reflections;
+ vertices = malloc(3*dw->gl_marker_num_vertices*sizeof(GLfloat));
+ normals = malloc(3*dw->gl_marker_num_vertices*sizeof(GLfloat));
+ while ( reflection != NULL ) {
+ if ( reflection->type == REFLECTION_MARKER ) {
+ double size = 0.15;
+ DRAW_BLOB
+ }
+ reflection = reflection->next;
+ };
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_marker_vertex_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_marker_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
+ free(vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_marker_normal_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_marker_num_vertices*sizeof(GLfloat), normals, GL_STATIC_DRAW);
+ free(normals);
+ } else {
+ dw->gl_marker_vertex_array = vertices;
+ dw->gl_marker_normal_array = normals;
+ }
+ }
+
+ /* Generated reflections */
+ if ( dw->gl_use_buffers ) {
+ glGenBuffersARB(1, &dw->gl_gen_vertex_buffer);
+ glGenBuffersARB(1, &dw->gl_gen_normal_buffer);
+ }
+ if ( ctx->integrated != NULL ) {
+ reflection = ctx->integrated->reflections;
+ i = 0;
+ while ( reflection != NULL ) {
+ if ( reflection->type == REFLECTION_GENERATED ) i++;
+ reflection = reflection->next;
+ };
+ dw->gl_gen_num_vertices = i*VERTICES_IN_A_BLOB;
+ if ( dw->gl_gen_num_vertices ) {
+ i = 0;
+ reflection = ctx->integrated->reflections;
+ vertices = malloc(3*dw->gl_gen_num_vertices*sizeof(GLfloat));
+ normals = malloc(3*dw->gl_gen_num_vertices*sizeof(GLfloat));
+ while ( reflection != NULL ) {
+ double size = 5.0 * log(1+0.1*reflection->intensity);
+ DRAW_BLOB
+ reflection = reflection->next;
+ };
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_gen_vertex_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_gen_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
+ free(vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_gen_normal_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_gen_num_vertices*sizeof(GLfloat), normals, GL_STATIC_DRAW);
+ free(normals);
+ glBindBufferARB(GL_ARRAY_BUFFER, 0); /* ************* */
+ } else {
+ dw->gl_gen_vertex_array = vertices;
+ dw->gl_gen_normal_array = normals;
+ }
+ }
+ } else {
+ dw->gl_gen_num_vertices = 0;
+ }
+
+ /* Indexing lines */
+ glLineWidth(2.0);
+ if ( ctx->cell && dw->lines ) {
+
+ int max_ind;
+ signed int h, k, l;
+
+ max_ind = 10;
+ dw->gl_line_num_vertices = 3*2*((2*1+1)*(2*1+1));
+
+ if ( dw->gl_use_buffers ) {
+ glGenBuffersARB(1, &dw->gl_line_vertex_buffer);
+ }
+ reflection = ctx->reflectionlist->reflections;
+ vertices = malloc(3*dw->gl_line_num_vertices*sizeof(GLfloat));
+
+ i=0;
+
+ /* Lines parallel to a */
+ for ( k=-1; k<=1; k++ ) {
+ for ( l=-1; l<=1; l++ ) {
+ vertices[3*i + 0] = (ctx->cell->a.x*(-max_ind) + ctx->cell->b.x*k + ctx->cell->c.x*l)/1e9;
+ vertices[3*i + 1] = (ctx->cell->a.y*(-max_ind) + ctx->cell->b.y*k + ctx->cell->c.y*l)/1e9;
+ vertices[3*i + 2] = (ctx->cell->a.z*(-max_ind) + ctx->cell->b.z*k + ctx->cell->c.z*l)/1e9;
+ i++;
+ vertices[3*i + 0] = (ctx->cell->a.x*(max_ind) + ctx->cell->b.x*k + ctx->cell->c.x*l)/1e9;
+ vertices[3*i + 1] = (ctx->cell->a.y*(max_ind) + ctx->cell->b.y*k + ctx->cell->c.y*l)/1e9;
+ vertices[3*i + 2] = (ctx->cell->a.z*(max_ind) + ctx->cell->b.z*k + ctx->cell->c.z*l)/1e9;
+ i++;
+ }
+ }
+ /* Lines parallel to b */
+ for ( h=-1; h<=1; h++ ) {
+ for ( l=-1; l<=1; l++ ) {
+ vertices[3*i + 0] = (ctx->cell->a.x*h + ctx->cell->b.x*(-max_ind) + ctx->cell->c.x*l)/1e9;
+ vertices[3*i + 1] = (ctx->cell->a.y*h + ctx->cell->b.y*(-max_ind) + ctx->cell->c.y*l)/1e9;
+ vertices[3*i + 2] = (ctx->cell->a.z*h + ctx->cell->b.z*(-max_ind) + ctx->cell->c.z*l)/1e9;
+ i++;
+ vertices[3*i + 0] = (ctx->cell->a.x*h + ctx->cell->b.x*(max_ind) + ctx->cell->c.x*l)/1e9;
+ vertices[3*i + 1] = (ctx->cell->a.y*h + ctx->cell->b.y*(max_ind) + ctx->cell->c.y*l)/1e9;
+ vertices[3*i + 2] = (ctx->cell->a.z*h + ctx->cell->b.z*(max_ind) + ctx->cell->c.z*l)/1e9;
+ i++;
+ }
+ }
+ /* Lines parallel to c */
+ for ( h=-1; h<=1; h++ ) {
+ for ( k=-1; k<=1; k++ ) {
+ vertices[3*i + 0] = (ctx->cell->a.x*h + ctx->cell->b.x*k + ctx->cell->c.x*(-max_ind))/1e9;
+ vertices[3*i + 1] = (ctx->cell->a.y*h + ctx->cell->b.y*k + ctx->cell->c.y*(-max_ind))/1e9;
+ vertices[3*i + 2] = (ctx->cell->a.z*h + ctx->cell->b.z*k + ctx->cell->c.z*(-max_ind))/1e9;
+ i++;
+ vertices[3*i + 0] = (ctx->cell->a.x*h + ctx->cell->b.x*k + ctx->cell->c.x*(max_ind))/1e9;
+ vertices[3*i + 1] = (ctx->cell->a.y*h + ctx->cell->b.y*k + ctx->cell->c.y*(max_ind))/1e9;
+ vertices[3*i + 2] = (ctx->cell->a.z*h + ctx->cell->b.z*k + ctx->cell->c.z*(max_ind))/1e9;
+ i++;
+ }
+ }
+
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_line_vertex_buffer);
+ glBufferDataARB(GL_ARRAY_BUFFER, 3*dw->gl_line_num_vertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
+ free(vertices);
+ } else {
+ dw->gl_line_vertex_array = vertices;
+ }
+
+ }
+
+ dw->gl_list_id = glGenLists(1);
+ glNewList(dw->gl_list_id, GL_COMPILE);
+
+ #if 0
+ GLUquadric *quad;
+ quad = gluNewQuadric();
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, yellow);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0);
+ gluSphere(quad, 10, 32, 32);
+ #endif
+
+ /* Bounding cube: 100 nm^-1 side length */
+ if ( dw->cube ) {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, blue);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glBegin(GL_LINE_LOOP);
+ glNormal3f(50.0, 50.0, 50.0);
+ glVertex3f(50.0, 50.0, 50.0);
+ glNormal3f(-50.0, 50.0, 50.0);
+ glVertex3f(-50.0, 50.0, 50.0);
+ glNormal3f(-50.0, -50.0, 50.0);
+ glVertex3f(-50.0, -50.0, 50.0);
+ glNormal3f(50.0, -50.0, 50.0);
+ glVertex3f(50.0, -50.0, 50.0);
+
+ glEnd();
+ glBegin(GL_LINE_LOOP);
+ glNormal3f(50.0, 50.0, -50.0);
+ glVertex3f(50.0, 50.0, -50.0);
+ glNormal3f(-50.0, 50.0, -50.0);
+ glVertex3f(-50.0, 50.0, -50.0);
+ glNormal3f(-50.0, -50.0, -50.0);
+ glVertex3f(-50.0, -50.0, -50.0);
+ glNormal3f(50.0, -50.0, -50.0);
+ glVertex3f(50.0, -50.0, -50.0);
+ glEnd();
+ glBegin(GL_LINES);
+ glNormal3f(50.0, 50.0, 50.0);
+ glVertex3f(50.0, 50.0, 50.0);
+ glNormal3f(50.0, 50.0, -50.0);
+ glVertex3f(50.0, 50.0, -50.0);
+ glNormal3f(-50.0, 50.0, 50.0);
+ glVertex3f(-50.0, 50.0, 50.0);
+ glNormal3f(-50.0, 50.0, -50.0);
+ glVertex3f(-50.0, 50.0, -50.0);
+ glNormal3f(-50.0, -50.0, 50.0);
+ glVertex3f(-50.0, -50.0, 50.0);
+ glNormal3f(-50.0, -50.0, -50.0);
+ glVertex3f(-50.0, -50.0, -50.0);
+ glNormal3f(50.0, -50.0, 50.0);
+ glVertex3f(50.0, -50.0, 50.0);
+ glNormal3f(50.0, -50.0, -50.0);
+ glVertex3f(50.0, -50.0, -50.0);
+ glEnd();
+ }
+
+ /* x, y, z pointers */
+ int pointer_head_face;
+ glPushMatrix();
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, red);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ glScalef(10.0, 1.0, 1.0);
+ DRAW_POINTER_LINE
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
+ DRAW_POINTER_HEAD
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(90.0, 0.0, 0.0, 1.0);
+ glScalef(10.0, 1.0, 1.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, green);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ DRAW_POINTER_LINE
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green);
+ DRAW_POINTER_HEAD
+ glPopMatrix();
+
+ glPushMatrix();
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ glScalef(10.0, 1.0, 1.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, bblue);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ DRAW_POINTER_LINE
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bblue);
+ DRAW_POINTER_HEAD
+ glPopMatrix();
+
+ /* Plot the other reflections */
+ reflection = ctx->reflectionlist->reflections;
+ while ( reflection != NULL ) {
+
+ if ( reflection->type == REFLECTION_VECTOR_MARKER_1 ) {
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glBegin(GL_LINES);
+ glNormal3f(0.0, 0.0, 0.0);
+ glVertex3f(0.0, 0.0, 0.0);
+ glNormal3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9);
+ glVertex3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9);
+ glEnd();
+
+ }
+
+ if ( reflection->type == REFLECTION_VECTOR_MARKER_2 ) {
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glBegin(GL_LINES);
+ glNormal3f(0.0, 0.0, 0.0);
+ glVertex3f(0.0, 0.0, 0.0);
+ glNormal3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9);
+ glVertex3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9);
+ glEnd();
+
+ }
+
+ if ( reflection->type == REFLECTION_VECTOR_MARKER_3 ) {
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glBegin(GL_LINES);
+ glNormal3f(0.0, 0.0, 0.0);
+ glVertex3f(0.0, 0.0, 0.0);
+ glNormal3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9);
+ glVertex3f(reflection->x/1e9, reflection->y/1e9, reflection->z/1e9);
+ glEnd();
+
+ }
+
+ reflection = reflection->next;
+
+ };
+
+ /* Draw the reciprocal unit cell if one is available */
+ if ( ctx->cell && !dw->lines ) {
+ glBegin(GL_LINE_STRIP);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, red);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glNormal3f(1.0, 0.0, 0.0);
+ glVertex3f(0.0, 0.0, 0.0);
+ glVertex3f(ctx->cell->a.x/1e9, ctx->cell->a.y/1e9, ctx->cell->a.z/1e9);
+ glVertex3f(ctx->cell->a.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->a.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->a.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->b.x/1e9, ctx->cell->b.y/1e9, ctx->cell->b.z/1e9);
+ glVertex3f(0.0, 0.0, 0.0);
+ glVertex3f(ctx->cell->c.x/1e9, ctx->cell->c.y/1e9, ctx->cell->c.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->a.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->a.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->a.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->a.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->a.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->a.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9, ctx->cell->c.y/1e9, ctx->cell->c.z/1e9);
+
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->b.x/1e9, ctx->cell->b.y/1e9, ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->a.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->a.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->a.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->a.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->a.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->a.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->a.x/1e9 + ctx->cell->b.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->a.y/1e9 + ctx->cell->b.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->a.z/1e9 + ctx->cell->b.z/1e9);
+ glVertex3f(ctx->cell->c.x/1e9 + ctx->cell->a.x/1e9,
+ ctx->cell->c.y/1e9 + ctx->cell->a.y/1e9,
+ ctx->cell->c.z/1e9 + ctx->cell->a.z/1e9);
+ glVertex3f(ctx->cell->a.x/1e9, ctx->cell->a.y/1e9, ctx->cell->a.z/1e9);
+ glEnd();
+ }
+
+ /* Tilt axis */
+ if ( ctx->images ) {
+ glPushMatrix();
+ /* Images rotate clockwise by omega to put tilt axis at +x,
+ * so rotate tilt axis anticlockwise by omega.
+ * Since the rotation is about +z, this is already anticlockwise
+ * when looking down z. */
+ glRotatef(ctx->images->images[0].omega, 0.0, 0.0, 1.0);
+ glScalef(50.0, 1.0, 1.0);
+ glTranslatef(-0.5, 0.0, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, yellow);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ DRAW_POINTER_LINE
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, yellow);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ DRAW_POINTER_HEAD
+ glPopMatrix();
+ }
+
+ /* Zero plane (must be drawn last for transparency to work) */
+ glBegin(GL_QUADS);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glass);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ glNormal3f(0.0, 0.0, 1.0);
+ glVertex3f(50.0, 50.0, 0.0);
+ glVertex3f(50.0, -50.0, 0.0);
+ glVertex3f(-50.0, -50.0, 0.0);
+ glVertex3f(-50.0, 50.0, 0.0);
+ glEnd();
+
+ glEndList();
+
+ //printf("DW: Vertex counts: meas:%i, mark:%i, gen:%i\n", dw->gl_ref_num_vertices, dw->gl_marker_num_vertices, dw->gl_gen_num_vertices);
+
+}
+
+void glbits_set_ortho(DisplayWindow *dw, GLfloat w, GLfloat h) {
+
+ GLfloat aspect = w/h;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-aspect*(dw->distance/2.0), aspect*(dw->distance/2.0), -(dw->distance/2.0), (dw->distance/2.0), 0.001, 400.0);
+ glMatrixMode(GL_MODELVIEW);
+
+}
+
+void glbits_set_perspective(DisplayWindow *dw, GLfloat w, GLfloat h) {
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(50.0, w/h, 0.001, 400.0);
+ glMatrixMode(GL_MODELVIEW);
+
+}
+
+gint glbits_expose(GtkWidget *widget, GdkEventExpose *event, DisplayWindow *dw) {
+
+ GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
+ float m[4][4];
+ GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
+ GLfloat blue[] = { 0.0, 0.0, 0.5, 1.0 };
+ GLfloat blue_spec[] = { 0.0, 0.0, 1.0, 1.0 };
+ GLfloat gold[] = { 0.5, 0.5, 0.0, 1.0 };
+ GLfloat gold_spec[] = { 0.9, 0.9, 0.0, 1.0 };
+ GLfloat light0_position[] = { 100.0, 100.0, 100.0, 0.0 };
+ GLfloat light0_diffuse[] = { 0.8, 0.8, 0.8, 1.0 };
+ GLfloat light0_specular[] = { 0.8, 0.8, 0.8, 1.0 };
+ GLfloat bg_top[] = { 0.0, 0.2, 0.0, 1.0 };
+ GLfloat bg_bot[] = { 0.0, 0.0, 0.0, 1.0 };
+ GLfloat grey[] = { 0.6, 0.6, 0.6, 1.0 };
+
+ if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) {
+ return 0;
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if ( dw->background ) {
+
+ GLfloat w = dw->drawing_area->allocation.width;
+ GLfloat h = dw->drawing_area->allocation.height;
+ GLfloat aspect = w/h;
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -20.0);
+ /* Draw the background (this is done before setting up rotations) */
+ /* Set up "private" projection matrix */
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-aspect*3.0, aspect*3.0, -3.0, 3.0, 0.001, 21.0);
+ /* Draw background plane */
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT, GL_SHININESS, 0.0);
+ glBegin(GL_QUADS);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, bg_bot);
+ glVertex3f(-3.0*aspect, -3.0, 0.0);
+ glVertex3f(+3.0*aspect, -3.0, 0.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, bg_top);
+ glVertex3f(+3.0*aspect, +3.0, 0.0);
+ glVertex3f(-3.0*aspect, +3.0, 0.0);
+ glEnd();
+ /* Restore the old projection matrix */
+ glPopMatrix();
+ glClear(GL_DEPTH_BUFFER_BIT); /* Background does not count for depth test purposes */
+
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ /* Set up 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);
+
+ /* The z component of this makes no difference if the projection is orthographic,
+ * but controls zoom when perspective is used */
+ glTranslatef(0.0, 0.0, -400.0);
+ glTranslatef(dw->x_pos, -dw->y_pos, 400.0-dw->distance);
+ build_rotmatrix(m, dw->view_quat);
+ glMultMatrixf(&m[0][0]);
+
+ if ( dw->mode == DW_MAPPED ) {
+
+ /* Draw the "measured" reflections */
+ if ( dw->gl_ref_num_vertices ) {
+ glPointSize(2.0);
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, green);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0);
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_ref_vertex_buffer);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_ref_normal_buffer);
+ glNormalPointer(GL_FLOAT, 0, NULL);
+ glDrawArrays(GL_POINTS, 0, dw->gl_ref_num_vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, 0);
+ } else {
+ glVertexPointer(3, GL_FLOAT, 0, dw->gl_ref_vertex_array);
+ glNormalPointer(GL_FLOAT, 0, dw->gl_ref_normal_array);
+ glDrawArrays(GL_POINTS, 0, dw->gl_ref_num_vertices);
+ }
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glPopClientAttrib();
+ }
+
+ /* Draw marker points */
+ if ( dw->gl_marker_num_vertices ) {
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, blue_spec);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_marker_vertex_buffer);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_marker_normal_buffer);
+ glNormalPointer(GL_FLOAT, 0, NULL);
+ glDrawArrays(GL_QUADS, 0, dw->gl_marker_num_vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, 0);
+ } else {
+ glVertexPointer(3, GL_FLOAT, 0, dw->gl_marker_vertex_array);
+ glNormalPointer(GL_FLOAT, 0, dw->gl_marker_normal_array);
+ glDrawArrays(GL_QUADS, 0, dw->gl_marker_num_vertices);
+ }
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glPopClientAttrib();
+ }
+
+ } else {
+
+ /* Draw generated reflections */
+ if ( dw->gl_gen_num_vertices ) {
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gold);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gold_spec);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.0);
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_gen_vertex_buffer);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_gen_normal_buffer);
+ glNormalPointer(GL_FLOAT, 0, NULL);
+ glDrawArrays(GL_QUADS, 0, dw->gl_gen_num_vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, 0);
+ } else {
+ glVertexPointer(3, GL_FLOAT, 0, dw->gl_gen_vertex_array);
+ glNormalPointer(GL_FLOAT, 0, dw->gl_gen_normal_array);
+ glDrawArrays(GL_QUADS, 0, dw->gl_gen_num_vertices);
+ }
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glPopClientAttrib();
+ }
+
+ }
+
+ /* Draw indexing lines */
+ if ( dw->lines && dw->gl_line_num_vertices ) {
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, grey);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+ if ( dw->gl_use_buffers ) {
+ glBindBufferARB(GL_ARRAY_BUFFER, dw->gl_line_vertex_buffer);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+ glDrawArrays(GL_LINES, 0, dw->gl_line_num_vertices);
+ glBindBufferARB(GL_ARRAY_BUFFER, 0);
+ } else {
+ glVertexPointer(3, GL_FLOAT, 0, dw->gl_line_vertex_array);
+ glDrawArrays(GL_LINES, 0, dw->gl_line_num_vertices);
+ }
+ glPopClientAttrib();
+ }
+
+ /* Draw everything else */
+ glCallList(dw->gl_list_id);
+
+ if ( gdk_gl_drawable_is_double_buffered(gldrawable) ) {
+ gdk_gl_drawable_swap_buffers(gldrawable);
+ } else {
+ glFlush();
+ }
+
+ gdk_gl_drawable_gl_end(gldrawable);
+
+ return TRUE;
+
+}
+
+gboolean glbits_configure(GtkWidget *widget, GdkEventConfigure *event, DisplayWindow *dw) {
+
+ GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
+ GLfloat w = widget->allocation.width;
+ GLfloat h = widget->allocation.height;
+
+ /* Set viewport */
+ if ( !gdk_gl_drawable_gl_begin(gldrawable, glcontext) ) {
+ return FALSE;
+ }
+ glViewport(0, 0, w, h);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_LINE_SMOOTH);
+
+ /* Nudge the projection matrix routines to preserve the aspect ratio */
+ if ( dw->view == DW_ORTHO ) {
+ glbits_set_ortho(dw, w, h);
+ } else {
+ glbits_set_perspective(dw, w, h);
+ }
+
+ gdk_gl_drawable_gl_end(gldrawable);
+
+ return FALSE;
+
+}
+
+void glbits_free_resources(DisplayWindow *dw) {
+
+ if ( dw->gl_use_buffers ) {
+ glDeleteBuffersARB(1, &dw->gl_ref_vertex_buffer);
+ glDeleteBuffersARB(1, &dw->gl_ref_normal_buffer);
+ glDeleteBuffersARB(1, &dw->gl_marker_vertex_buffer);
+ glDeleteBuffersARB(1, &dw->gl_marker_normal_buffer);
+ glDeleteBuffersARB(1, &dw->gl_gen_vertex_buffer);
+ glDeleteBuffersARB(1, &dw->gl_gen_normal_buffer);
+ glDeleteBuffersARB(1, &dw->gl_line_vertex_buffer);
+ } else {
+ free(dw->gl_ref_vertex_array);
+ free(dw->gl_ref_normal_array);
+ free(dw->gl_marker_vertex_array);
+ free(dw->gl_marker_normal_array);
+ free(dw->gl_gen_vertex_array);
+ free(dw->gl_gen_normal_array);
+ free(dw->gl_line_vertex_array);
+ }
+ glDeleteLists(dw->gl_list_id, 1);
+
+}
+