X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fmolecule.c;h=f1b4f7e958d06e0f0d1ceef67ecdf17600e9973b;hb=6afd6db0ae9396cd7ff897ade597cd5483f49b0e;hp=3658ada5218aba371afd9a7c9a7ad8933ead926c;hpb=488f2fa8fbdbc77e91a70da2962d73af49e6cace;p=xscreensaver diff --git a/hacks/glx/molecule.c b/hacks/glx/molecule.c index 3658ada5..f1b4f7e9 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-2014 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,10 @@ /* Documentation on the PDB file format: + http://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 http://www.rcsb.org/pdb/file_formats/pdb/pdbguide2.2/guide2.2_frame.html Good source of PDB files: @@ -21,11 +24,14 @@ http://www.wwpdb.org/docs.html */ +#define ATOM_FONT "-*-helvetica-medium-r-normal-*-240-*" + #define DEFAULTS "*delay: 10000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ - "*atomFont: -*-times-bold-r-normal-*-240-*\n" \ - "*titleFont: -*-times-bold-r-normal-*-180-*\n" \ + "*atomFont: " ATOM_FONT "\n" \ + "*atomFont2: -*-helvetica-bold-r-normal-*-80-*\n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-180-*\n" \ "*noLabelThreshold: 30 \n" \ "*wireframeThreshold: 150 \n" \ @@ -56,14 +62,14 @@ #define DEF_TITLES "True" #define DEF_ATOMS "True" #define DEF_BONDS "True" -#define DEF_SHELLS "True" +#define DEF_ESHELLS "True" #define DEF_BBOX "False" #define DEF_SHELL_ALPHA "0.3" #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 */ @@ -73,9 +79,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__ @@ -83,11 +89,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 USE_IPHONE +# define LOAD_FILES +#endif + + typedef struct { const char *name; GLfloat size, size2; @@ -101,10 +112,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, }}, @@ -156,8 +167,8 @@ typedef struct { GLuint molecule_dlist; GLuint shell_dlist; - XFontStruct *xfont1, *xfont2; - GLuint font1_dlist, font2_dlist; + texture_font_data *font1_data, *font2_data, *font3_data; + int polygon_count; time_t draw_time; @@ -218,7 +229,7 @@ static argtype vars[] = { {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, {&do_atoms, "atoms", "Atoms", DEF_ATOMS, t_Bool}, {&do_bonds, "bonds", "Bonds", DEF_BONDS, t_Bool}, - {&do_shells, "eshells", "EShells", DEF_SHELLS, t_Bool}, + {&do_shells, "eshells", "EShells", DEF_ESHELLS, t_Bool}, {&do_labels, "labels", "Labels", DEF_LABELS, t_Bool}, {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, {&do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool}, @@ -254,8 +265,9 @@ 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->font1_data = load_texture_font (mi->dpy, "atomFont"); + mc->font2_data = load_texture_font (mi->dpy, "atomFont2"); + mc->font3_data = load_texture_font (mi->dpy, "titleFont"); } @@ -330,6 +342,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 @@ -455,7 +477,6 @@ 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]); @@ -468,7 +489,8 @@ draw_bounding_box (ModeInfo *mi) glVertex3f(0, 0, z1); glVertex3f(0, 0, z2); glEnd(); - glPopAttrib(); + if (!wire) + glEnable (GL_LIGHTING); } @@ -751,13 +773,26 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line) else if (!strncmp (s, "ATOM ", 7)) { int id; + const char *end = strchr (s, '\n'); + int L = end - s; char *name = (char *) calloc (1, 4); GLfloat x = -999, y = -999, z = -999; if (1 != sscanf (s+7, " %d ", &id)) parse_error (filename, line, s); + /* Use the "atom name" field if that is all that is available. */ strncpy (name, s+12, 3); + + /* But prefer the "element" field. */ + if (L > 77 && !isspace(s[77])) { + /* fprintf(stderr, " \"%s\" -> ", name); */ + name[0] = s[76]; + name[1] = s[77]; + name[2] = 0; + /* fprintf(stderr, "\"%s\"\n", name); */ + } + while (isspace(*name)) name++; ss = name + strlen(name)-1; while (isspace(*ss) && ss > name) @@ -838,6 +873,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) { @@ -884,6 +920,7 @@ parse_pdb_file (molecule *m, const char *name) return 0; } +#endif /* LOAD_FILES */ typedef struct { char *atom; int count; } atom_and_count; @@ -1001,16 +1038,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; @@ -1114,6 +1152,7 @@ load_molecules (ModeInfo *mi) files = 0; mc->nmolecules = molecule_ctr; } +# endif /* LOAD_FILES */ if (mc->nmolecules == 0) /* do the builtins if no files */ { @@ -1179,10 +1218,10 @@ 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, + print_gl_string (mi->dpy, mc->font3_data, mi->xgwa.width, mi->xgwa.height, 10, mi->xgwa.height - 10, - s); + s, False); glFinish(); glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); } @@ -1192,49 +1231,15 @@ 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) + if (gltrackball_event_handler (event, mc->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &mc->button_down_p)) + return True; + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) { - mc->button_down_p = False; - return True; - } - else if (event->xany.type == ButtonPress && - (event->xbutton.button == Button4 || - event->xbutton.button == Button5)) - { - gltrackball_mousewheel (mc->trackball, event->xbutton.button, 10, - !!event->xbutton.state); - return True; - } - else if (event->xany.type == KeyPress) - { - KeySym keysym; - char c = 0; - XLookupString (&event->xkey, &c, 1, &keysym, 0); - - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - { - GLfloat speed = 4.0; - mc->mode = 1; - mc->mode_tick = 10 * speed; - 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)); + GLfloat speed = 4.0; + mc->mode = 1; + mc->mode_tick = 10 * speed; return True; } @@ -1298,7 +1303,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; @@ -1335,7 +1340,7 @@ 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; @@ -1389,18 +1394,20 @@ draw_labels (ModeInfo *mi) glTranslatef (0, 0, (size * 1.1)); /* move toward camera */ - glRasterPos3f (0, 0, 0); /* draw text here */ + glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */ - /* 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) / 2, - -mc->xfont1->descent, - NULL); - - for (j = 0; j < strlen(a->label); j++) - - glCallList (mc->font1_dlist + (int)(a->label[j])); + { + int h; + int w = texture_string_width (mc->font1_data, a->label, &h); + GLfloat s = 1.0 / h; + GLfloat max = 18; /* max point size to avoid pixellated text */ + if (h > max) s *= max/h; + glScalef (s, s, 1); + glTranslatef (-w/2, h*2/3, 0); + print_gl_string (mi->dpy, mc->font1_data, + 0, 0, 0, 0, + a->label, False); + } glPopMatrix(); } @@ -1595,10 +1602,10 @@ 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, + print_gl_string (mi->dpy, mc->font3_data, mi->xgwa.width, mi->xgwa.height, 10, mi->xgwa.height - 10, - m->label); + m->label, False); } } glPopMatrix();