X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fmolecule.c;h=57827b2b3d2e6fdbbbf30e374454653218ed5639;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hp=f8078b2c4534257319f0db0d53b30b392c4f73f5;hpb=f0261d8acab611f3433160e4f07367b870439739;p=xscreensaver diff --git a/hacks/glx/molecule.c b/hacks/glx/molecule.c index f8078b2c..57827b2b 100644 --- a/hacks/glx/molecule.c +++ b/hacks/glx/molecule.c @@ -1,4 +1,4 @@ -/* molecule, Copyright (c) 2001-2006 Jamie Zawinski +/* molecule, Copyright (c) 2001-2016 Jamie Zawinski * Draws molecules, based on coordinates from PDB (Protein Data Base) files. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -12,7 +12,7 @@ /* Documentation on the PDB file format: - http://en.wikipedia.org/wiki/Protein_Data_Bank_%28file_format%29 + https://en.wikipedia.org/wiki/Protein_Data_Bank_%28file_format%29 http://www.wwpdb.org/docs.html http://www.wwpdb.org/documentation/format32/v3.2.html http://www.wwpdb.org/documentation/format32/sect9.html @@ -27,10 +27,11 @@ #define DEFAULTS "*delay: 10000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ - "*atomFont: -*-helvetica-medium-r-normal-*-240-*\n" \ - "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ - "*noLabelThreshold: 30 \n" \ + "*atomFont: -*-helvetica-medium-r-normal-*-*-240-*-*-*-*-*-*\n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \ + "*noLabelThreshold: 150 \n" \ "*wireframeThreshold: 150 \n" \ + "*suppressRotationAnimation: True\n" \ # define refresh_molecule 0 # define release_molecule 0 @@ -41,7 +42,7 @@ #include "colors.h" #include "sphere.h" #include "tube.h" -#include "glxfonts.h" +#include "texfont.h" #include "rotator.h" #include "gltrackball.h" @@ -65,8 +66,8 @@ #define DEF_MOLECULE "(default)" #define DEF_VERBOSE "False" -#define SPHERE_SLICES 24 /* how densely to render spheres */ -#define SPHERE_STACKS 12 +#define SPHERE_SLICES 48 /* how densely to render spheres */ +#define SPHERE_STACKS 24 #define SMOOTH_TUBE /* whether to have smooth or faceted tubes */ @@ -76,9 +77,9 @@ # define TUBE_FACES 8 #endif -#define SPHERE_SLICES_2 7 -#define SPHERE_STACKS_2 4 -#define TUBE_FACES_2 3 +#define SPHERE_SLICES_2 14 +#define SPHERE_STACKS_2 8 +#define TUBE_FACES_2 6 # ifdef __GNUC__ @@ -86,11 +87,16 @@ ISO C89 compilers are required to support" when includng the following data file... */ # endif -const char * const builtin_pdb_data[] = { +static const char * const builtin_pdb_data[] = { # include "molecules.h" }; +#ifndef HAVE_MOBILE +# define LOAD_FILES +#endif + + typedef struct { const char *name; GLfloat size, size2; @@ -104,10 +110,10 @@ typedef struct { and their approximate size in angstroms. */ static const atom_data all_atom_data[] = { - { "H", 1.17, 0.40, "#FFFFFF", "#B3B3B3", { 0, }}, + { "H", 1.17, 0.40, "#FFFFFF", "#000000", { 0, }}, { "C", 1.75, 0.58, "#999999", "#FFFFFF", { 0, }}, { "CA", 1.80, 0.60, "#0000FF", "#ADD8E6", { 0, }}, - { "N", 1.55, 0.52, "#A2B5CD", "#836FFF", { 0, }}, + { "N", 1.55, 0.52, "#A2B5CD", "#EE99FF", { 0, }}, { "O", 1.40, 0.47, "#FF0000", "#FFB6C1", { 0, }}, { "P", 1.28, 0.43, "#9370DB", "#DB7093", { 0, }}, { "S", 1.80, 0.60, "#8B8B00", "#FFFF00", { 0, }}, @@ -155,18 +161,20 @@ typedef struct { int mode; /* 0 = normal, 1 = out, 2 = in */ int mode_tick; + int next; /* 0 = random, -1 = back, 1 = forward */ GLuint molecule_dlist; GLuint shell_dlist; - XFontStruct *xfont1, *xfont2; - GLuint font1_dlist, font2_dlist; + texture_font_data *atom_font, *title_font; + int polygon_count; time_t draw_time; int draw_tick; - int scale_down; + GLfloat overall_scale; + int low_rez_p; } molecule_configuration; @@ -240,8 +248,8 @@ static int sphere (molecule_configuration *mc, GLfloat x, GLfloat y, GLfloat z, GLfloat diameter, Bool wire) { - int stacks = (mc->scale_down ? SPHERE_STACKS_2 : SPHERE_STACKS); - int slices = (mc->scale_down ? SPHERE_SLICES_2 : SPHERE_SLICES); + int stacks = (mc->low_rez_p ? SPHERE_STACKS_2 : SPHERE_STACKS); + int slices = (mc->low_rez_p ? SPHERE_SLICES_2 : SPHERE_SLICES); glPushMatrix (); glTranslatef (x, y, z); @@ -257,8 +265,8 @@ static void load_fonts (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; - load_font (mi->dpy, "atomFont", &mc->xfont1, &mc->font1_dlist); - load_font (mi->dpy, "titleFont", &mc->xfont2, &mc->font2_dlist); + mc->atom_font = load_texture_font (mi->dpy, "atomFont"); + mc->title_font = load_texture_font (mi->dpy, "titleFont"); } @@ -333,6 +341,16 @@ set_atom_color (ModeInfo *mi, const molecule_atom *a, gl_color[3] = alpha; + /* If we're not drawing atoms, and the color is black, use white instead. + This is a kludge so that H can have black text over its white ball, + but the text still shows up if balls are off. + */ + if (font_p && !do_atoms && + gl_color[0] == 0 && gl_color[1] == 0 && gl_color[2] == 0) + { + gl_color[0] = gl_color[1] = gl_color[2] = 1; + } + if (font_p) glColor4f (gl_color[0], gl_color[1], gl_color[2], gl_color[3]); else @@ -458,20 +476,23 @@ draw_bounding_box (ModeInfo *mi) glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1); glEnd(); - glPushAttrib (GL_LIGHTING); glDisable (GL_LIGHTING); glColor3f (c2[0], c2[1], c2[2]); glBegin(GL_LINES); - if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0; - if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0; - if (z1 > 0) z1 = 0; if (z2 < 0) z2 = 0; + if (x1 > 0) x1 = 0; + if (x2 < 0) x2 = 0; + if (y1 > 0) y1 = 0; + if (y2 < 0) y2 = 0; + if (z1 > 0) z1 = 0; + if (z2 < 0) z2 = 0; glVertex3f(x1, 0, 0); glVertex3f(x2, 0, 0); glVertex3f(0 , y1, 0); glVertex3f(0, y2, 0); glVertex3f(0, 0, z1); glVertex3f(0, 0, z2); glEnd(); - glPopAttrib(); + if (!wire) + glEnable (GL_LIGHTING); } @@ -500,14 +521,15 @@ ensure_bounding_box_visible (ModeInfo *mi) mc->molecule_size = size; - mc->scale_down = 0; + mc->low_rez_p = 0; + mc->overall_scale = 1; if (size > max_size) { - GLfloat scale = max_size / size; - glScalef (scale, scale, scale); + mc->overall_scale = max_size / size; + glScalef (mc->overall_scale, mc->overall_scale, mc->overall_scale); - mc->scale_down = scale < 0.3; + mc->low_rez_p = mc->overall_scale < 0.3; } glTranslatef (-(x1 + w/2), @@ -569,21 +591,23 @@ build_molecule (ModeInfo *mi, Bool transparent_p) } else { - int faces = (mc->scale_down ? TUBE_FACES_2 : TUBE_FACES); + int faces = (mc->low_rez_p ? TUBE_FACES_2 : TUBE_FACES); # ifdef SMOOTH_TUBE int smooth = True; # else int smooth = False; # endif - GLfloat thickness = 0.07 * b->strength; - GLfloat cap_size = 0.03; + Bool cap_p = (!do_atoms || do_shells); + GLfloat base = 0.07; + GLfloat thickness = base * b->strength; + GLfloat cap_size = (cap_p ? base / 2 : 0); if (thickness > 0.3) thickness = 0.3; polys += tube (from->x, from->y, from->z, to->x, to->y, to->z, thickness, cap_size, - faces, smooth, (!do_atoms || do_shells), wire); + faces, smooth, cap_p, wire); } } @@ -854,6 +878,7 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line) } +#ifdef LOAD_FILES static int parse_pdb_file (molecule *m, const char *name) { @@ -900,6 +925,7 @@ parse_pdb_file (molecule *m, const char *name) return 0; } +#endif /* LOAD_FILES */ typedef struct { char *atom; int count; } atom_and_count; @@ -1017,16 +1043,17 @@ static void load_molecules (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; - int wire = MI_IS_WIREFRAME(mi); int i; mc->nmolecules = 0; +# ifdef LOAD_FILES if (molecule_str && *molecule_str && strcmp(molecule_str, "(default)")) /* try external PDB files */ { /* The -molecule option can point to a .pdb file, or to a directory of them. */ + int wire = MI_IS_WIREFRAME(mi); struct stat st; int nfiles = 0; int list_size = 0; @@ -1130,6 +1157,7 @@ load_molecules (ModeInfo *mi) files = 0; mc->nmolecules = molecule_ctr; } +# endif /* LOAD_FILES */ if (mc->nmolecules == 0) /* do the builtins if no files */ { @@ -1172,6 +1200,14 @@ reshape_molecule (ModeInfo *mi, int width, int height) 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); +# ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */ + { + int o = (int) current_device_rotation(); + if (o != 0 && o != 180 && o != -180) + glScalef (1/h, 1/h, 1/h); + } +# endif + glClear(GL_COLOR_BUFFER_BIT); } @@ -1195,10 +1231,9 @@ startup_blurb (ModeInfo *mi) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; const char *s = "Constructing molecules..."; - print_gl_string (mi->dpy, mc->xfont2, mc->font2_dlist, - mi->xgwa.width, mi->xgwa.height, - 10, mi->xgwa.height - 10, - s, False); + print_texture_label (mi->dpy, mc->title_font, + mi->xgwa.width, mi->xgwa.height, + 0, s); glFinish(); glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); } @@ -1208,53 +1243,40 @@ molecule_handle_event (ModeInfo *mi, XEvent *event) { molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; - if (event->xany.type == ButtonPress && - event->xbutton.button == Button1) - { - mc->button_down_p = True; - gltrackball_start (mc->trackball, - event->xbutton.x, event->xbutton.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); - return True; - } - else if (event->xany.type == ButtonRelease && - event->xbutton.button == Button1) - { - mc->button_down_p = False; - return True; - } - else if (event->xany.type == ButtonPress && - (event->xbutton.button == Button4 || - event->xbutton.button == Button5 || - event->xbutton.button == Button6 || - event->xbutton.button == Button7)) - { - gltrackball_mousewheel (mc->trackball, event->xbutton.button, 10, - !!event->xbutton.state); - return True; - } - else if (event->xany.type == KeyPress) + if (gltrackball_event_handler (event, mc->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &mc->button_down_p)) + return True; + else { - KeySym keysym; - char c = 0; - XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (event->xany.type == KeyPress) + { + KeySym keysym; + char c = 0; + XLookupString (&event->xkey, &c, 1, &keysym, 0); + if (c == '<' || c == ',' || c == '-' || c == '_' || + keysym == XK_Left || keysym == XK_Up || keysym == XK_Prior) + { + mc->next = -1; + goto SWITCH; + } + else if (c == '>' || c == '.' || c == '=' || c == '+' || + keysym == XK_Right || keysym == XK_Down || + keysym == XK_Next) + { + mc->next = 1; + goto SWITCH; + } + } - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) { - GLfloat speed = 4.0; + SWITCH: mc->mode = 1; - mc->mode_tick = 10 * speed; + mc->mode_tick = 4; return True; } } - else if (event->xany.type == MotionNotify && - mc->button_down_p) - { - gltrackball_track (mc->trackball, - event->xmotion.x, event->xmotion.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); - return True; - } return False; } @@ -1266,14 +1288,7 @@ init_molecule (ModeInfo *mi) molecule_configuration *mc; int wire; - if (!mcs) { - mcs = (molecule_configuration *) - calloc (MI_NUM_SCREENS(mi), sizeof (molecule_configuration)); - if (!mcs) { - fprintf(stderr, "%s: out of memory\n", progname); - exit(1); - } - } + MI_INIT (mi, mcs, NULL); mc = &mcs[MI_SCREEN(mi)]; @@ -1316,7 +1331,7 @@ init_molecule (ModeInfo *mi) spin_accel, do_wander ? wander_speed : 0, (spinx && spiny && spinz)); - mc->trackball = gltrackball_init (); + mc->trackball = gltrackball_init (True); } orig_do_labels = do_labels; @@ -1353,14 +1368,11 @@ draw_labels (ModeInfo *mi) molecule_configuration *mc = &mcs[MI_SCREEN(mi)]; int wire = MI_IS_WIREFRAME(mi); molecule *m = &mc->molecules[mc->which]; - int i, j; + int i; if (!do_labels) return; - if (!wire) - glDisable (GL_LIGHTING); /* don't light fonts */ - for (i = 0; i < m->natoms; i++) { molecule_atom *a = &m->atoms[i]; @@ -1374,7 +1386,7 @@ draw_labels (ModeInfo *mi) /* First, we translate the origin to the center of the atom. - Then we retrieve the prevailing modelview matrix (which + Then we retrieve the prevailing modelview matrix, which includes any rotation, wandering, and user-trackball-rolling of the scene. @@ -1407,28 +1419,27 @@ draw_labels (ModeInfo *mi) glTranslatef (0, 0, (size * 1.1)); /* move toward camera */ - glRasterPos3f (0, 0, 0); /* draw text here */ - - /* Before drawing the string, shift the origin to center - the text over the origin of the sphere. */ - glBitmap (0, 0, 0, 0, - -string_width (mc->xfont1, a->label, 0) / 2, - -mc->xfont1->descent, - NULL); + glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */ - for (j = 0; j < strlen(a->label); j++) - - glCallList (mc->font1_dlist + (int)(a->label[j])); + { + XCharStruct e; + int w, h; + GLfloat s; + + texture_string_metrics (mc->atom_font, a->label, &e, 0, 0); + w = e.width; + h = e.ascent + e.descent; + + s = 1.0 / h; /* Scale to unit */ + s *= mc->overall_scale; /* Scale to size of atom */ + s *= 0.8; /* Shrink a bit */ + glScalef (s, s, 1); + glTranslatef (-w/2, -h/2, 0); + print_texture_string (mc->atom_font, a->label); + } glPopMatrix(); } - - /* More efficient to always call glEnable() with correct values - than to call glPushAttrib()/glPopAttrib(), since reading - attributes from GL does a round-trip and stalls the pipeline. - */ - if (!wire) - glEnable (GL_LIGHTING); } @@ -1446,6 +1457,18 @@ pick_new_molecule (ModeInfo *mi, time_t last) { mc->which = random() % mc->nmolecules; } + else if (mc->next < 0) + { + mc->which--; + if (mc->which < 0) mc->which = mc->nmolecules-1; + mc->next = 0; + } + else if (mc->next > 0) + { + mc->which++; + if (mc->which >= mc->nmolecules) mc->which = 0; + mc->next = 0; + } else { int n = mc->which; @@ -1548,7 +1571,7 @@ draw_molecule (ModeInfo *mi) { /* randomize molecules every -timeout seconds */ mc->mode = 1; /* go out */ - mc->mode_tick = 10 * speed; + mc->mode_tick = 80 / speed; mc->draw_time = now; } } @@ -1557,10 +1580,9 @@ draw_molecule (ModeInfo *mi) { if (--mc->mode_tick <= 0) { - mc->mode_tick = 10 * speed; + mc->mode_tick = 80 / speed; mc->mode = 2; /* go in */ pick_new_molecule (mi, mc->draw_time); - mc->draw_time = now; } } else if (mc->mode == 2) /* in */ @@ -1594,8 +1616,8 @@ draw_molecule (ModeInfo *mi) if (mc->mode != 0) { GLfloat s = (mc->mode == 1 - ? mc->mode_tick / (10 * speed) - : ((10 * speed) - mc->mode_tick + 1) / (10 * speed)); + ? mc->mode_tick / (80 / speed) + : ((80 / speed) - mc->mode_tick + 1) / (80 / speed)); glScalef (s, s, s); } @@ -1613,10 +1635,9 @@ draw_molecule (ModeInfo *mi) if (do_titles && m->label && *m->label) { set_atom_color (mi, 0, True, 1); - print_gl_string (mi->dpy, mc->xfont2, mc->font2_dlist, - mi->xgwa.width, mi->xgwa.height, - 10, mi->xgwa.height - 10, - m->label, False); + print_texture_label (mi->dpy, mc->title_font, + mi->xgwa.width, mi->xgwa.height, + 1, m->label); } } glPopMatrix();