-/* molecule, Copyright (c) 2001-2006 Jamie Zawinski <jwz@jwz.org>
+/* molecule, Copyright (c) 2001-2012 Jamie Zawinski <jwz@jwz.org>
* Draws molecules, based on coordinates from PDB (Protein Data Base) files.
*
* Permission to use, copy, modify, distribute, and sell this software and its
/* 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:
http://www.wwpdb.org/docs.html
*/
+#ifdef HAVE_GLBITMAP
+# define ATOM_FONT "-*-helvetica-medium-r-normal-*-180-*"
+#else
+# define ATOM_FONT "-*-helvetica-medium-r-normal-*-240-*"
+#endif
+
#define DEFAULTS "*delay: 10000 \n" \
"*showFPS: False \n" \
"*wireframe: False \n" \
- "*atomFont: -*-helvetica-medium-r-normal-*-240-*\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" \
#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 */
# 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__
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;
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, }},
GLuint molecule_dlist;
GLuint shell_dlist;
- XFontStruct *xfont1, *xfont2;
- GLuint font1_dlist, font2_dlist;
+# ifdef HAVE_GLBITMAP
+ XFontStruct *xfont1, *xfont2, *xfont3;
+ GLuint font1_dlist, font2_dlist, font3_dlist;
+# else
+ texture_font_data *font1_data, *font2_data, *font3_data;
+# endif
+
+
int polygon_count;
time_t draw_time;
load_fonts (ModeInfo *mi)
{
molecule_configuration *mc = &mcs[MI_SCREEN(mi)];
+# ifdef HAVE_GLBITMAP
load_font (mi->dpy, "atomFont", &mc->xfont1, &mc->font1_dlist);
- load_font (mi->dpy, "titleFont", &mc->xfont2, &mc->font2_dlist);
+ load_font (mi->dpy, "atomFont2", &mc->xfont2, &mc->font2_dlist);
+ load_font (mi->dpy, "titleFont", &mc->xfont3, &mc->font3_dlist);
+# else
+ 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");
+# endif
}
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
glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1);
glEnd();
- glPushAttrib (GL_LIGHTING);
glDisable (GL_LIGHTING);
glColor3f (c2[0], c2[1], c2[2]);
glVertex3f(0, 0, z1); glVertex3f(0, 0, z2);
glEnd();
- glPopAttrib();
+ if (!wire)
+ glEnable (GL_LIGHTING);
}
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)
}
+#ifdef LOAD_FILES
static int
parse_pdb_file (molecule *m, const char *name)
{
return 0;
}
+#endif /* LOAD_FILES */
typedef struct { char *atom; int count; } atom_and_count;
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;
files = 0;
mc->nmolecules = molecule_ctr;
}
+# endif /* LOAD_FILES */
if (mc->nmolecules == 0) /* do the builtins if no files */
{
{
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,
+# ifdef HAVE_GLBITMAP
+ mc->xfont3, mc->font3_dlist,
+# else
+ mc->font3_data,
+# endif
mi->xgwa.width, mi->xgwa.height,
10, mi->xgwa.height - 10,
s, False);
molecule_configuration *mc = &mcs[MI_SCREEN(mi)];
int wire = MI_IS_WIREFRAME(mi);
molecule *m = &mc->molecules[mc->which];
- int i, j;
+# ifdef HAVE_GLBITMAP
+ XFontStruct *xfont = (mc->scale_down ? mc->xfont2 : mc->xfont1);
+ GLuint font_dlist = (mc->scale_down ? mc->font2_dlist : mc->font1_dlist);
+# else
+ texture_font_data *font_data = mc->font1_data; /* don't scale down */
+# endif
+ int i;
if (!do_labels)
return;
glTranslatef (0, 0, (size * 1.1)); /* move toward camera */
+ glRotatef (current_device_rotation(), 0, 0, 1); /* right side up */
+
+# ifdef HAVE_GLBITMAP
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,
+ -string_width (xfont, a->label, 0) / 2,
+ -xfont->descent,
NULL);
-
- for (j = 0; j < strlen(a->label); j++)
-
- glCallList (mc->font1_dlist + (int)(a->label[j]));
+ {
+ int j;
+ for (j = 0; j < strlen(a->label); j++)
+ glCallList (font_dlist + (int)(a->label[j]));
+ }
+# else
+ {
+ int h;
+ int w = texture_string_width (font_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,
+# ifdef HAVE_GLBITMAP
+ xfont, font_dlist,
+# else
+ font_data,
+# endif
+ 0, 0, 0, 0,
+ a->label, False);
+ }
+# endif
glPopMatrix();
}
(y - 0.5) * 9,
(z - 0.5) * 9);
+ /* Do it twice because we don't track the device's orientation. */
+ glRotatef( current_device_rotation(), 0, 0, 1);
gltrackball_rotate (mc->trackball);
+ glRotatef(-current_device_rotation(), 0, 0, 1);
get_rotation (mc->rot, &x, &y, &z, !mc->button_down_p);
glRotatef (x * 360, 1.0, 0.0, 0.0);
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,
+# ifdef HAVE_GLBITMAP
+ mc->xfont3, mc->font3_dlist,
+# else
+ mc->font3_data,
+# endif
mi->xgwa.width, mi->xgwa.height,
10, mi->xgwa.height - 10,
m->label, False);