-/* xscreensaver, Copyright (c) 2002 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2002-2014 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* surfaces would be too hard.
*/
-#include <X11/Intrinsic.h>
-
-extern XtAppContext app;
-
-#define PROGCLASS "Spheremonics"
-#define HACK_INIT init_spheremonics
-#define HACK_DRAW draw_spheremonics
-#define HACK_RESHAPE reshape_spheremonics
-#define HACK_HANDLE_EVENT spheremonics_handle_event
-#define EVENT_MASK PointerMotionMask
-#define ccs_opts xlockmore_opts
-
-#define DEF_DURATION "100"
-#define DEF_SPIN "XYZ"
-#define DEF_WANDER "False"
-#define DEF_RESOLUTION "64"
-#define DEF_BBOX "False"
-#define DEF_GRID "True"
-#define DEF_SMOOTH "True"
-#define DEF_PARMS "(default)"
-
-#define DEFAULTS "*delay: 30000 \n" \
- "*resolution: " DEF_RESOLUTION "\n" \
- "*showFPS: False \n" \
- "*wireframe: False \n" \
- "*duration: " DEF_DURATION "\n" \
- "*spin: " DEF_SPIN "\n" \
- "*wander: " DEF_WANDER "\n" \
- "*bbox: " DEF_BBOX "\n" \
- "*grid: " DEF_GRID "\n" \
- "*smooth: " DEF_SMOOTH "\n" \
- "*parameters: " DEF_PARMS "\n" \
+#define DEFAULTS "*delay: 30000 \n" \
+ "*showFPS: False \n" \
+ "*wireframe: False \n" \
+ "*suppressRotationAnimation: True\n" \
+ "*labelfont: -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n"
+# define refresh_spheremonics 0
+# define release_spheremonics 0
#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
#include "xlockmore.h"
+#include "texfont.h"
+#include "normals.h"
#include "colors.h"
#include "rotator.h"
#include "gltrackball.h"
#ifdef USE_GL /* whole file */
-#include <GL/glu.h>
-
-typedef struct {
- double x,y,z;
-} XYZ;
+#define DEF_DURATION "100"
+#define DEF_SPIN "XYZ"
+#define DEF_WANDER "False"
+#define DEF_RESOLUTION "64"
+#define DEF_BBOX "False"
+#define DEF_GRID "True"
+#define DEF_SMOOTH "True"
+#define DEF_PARMS "(default)"
typedef struct {
GLXContext *glx_context;
int mesher;
int polys1, polys2; /* polygon counts */
- XFontStruct *font;
- GLuint font_list;
+ texture_font_data *font_data;
+
+ int change_tick;
+ int done_once;
} spheremonics_configuration;
};
static argtype vars[] = {
- {(caddr_t *) &do_spin, "spin", "Spin", DEF_SPIN, t_String},
- {(caddr_t *) &do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
- {(caddr_t *) &res, "resolution", "Resolution", DEF_RESOLUTION, t_Int},
- {(caddr_t *) &duration, "duration", "Duration", DEF_DURATION, t_Int},
- {(caddr_t *) &do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool},
- {(caddr_t *) &do_grid, "grid", "Grid", DEF_GRID, t_Bool},
- {(caddr_t *) &smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool},
- {(caddr_t *) &static_parms, "parameters", "Parameters", DEF_PARMS, t_String},
+ {&do_spin, "spin", "Spin", DEF_SPIN, t_String},
+ {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
+ {&res, "resolution", "Resolution", DEF_RESOLUTION, t_Int},
+ {&duration, "duration", "Duration", DEF_DURATION, t_Int},
+ {&do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool},
+ {&do_grid, "grid", "Grid", DEF_GRID, t_Bool},
+ {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool},
+ {&static_parms, "parameters", "Parameters", DEF_PARMS, t_String},
};
-ModeSpecOpt ccs_opts = {countof(opts), opts, countof(vars), vars, NULL};
+ENTRYPOINT ModeSpecOpt spheremonics_opts = {countof(opts), opts, countof(vars), vars, NULL};
/* Window management, etc
*/
-void
+ENTRYPOINT void
reshape_spheremonics (ModeInfo *mi, int width, int height)
{
GLfloat h = (GLfloat) height / (GLfloat) width;
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);
}
/* spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; */
int wire = MI_IS_WIREFRAME(mi);
- static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0};
+ static const GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0};
glEnable(GL_NORMALIZE);
lighting effect.
*/
glDisable(GL_CULL_FACE);
- glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, TRUE);
+ glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, True);
+ }
+
+ if (smooth_p)
+ {
+ glEnable (GL_LINE_SMOOTH);
+ glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
}
}
}
-/* Normalise a vector */
-static void
-normalize (XYZ *p)
-{
- double length;
- length = sqrt(p->x * p->x + p->y * p->y + p->z * p->z);
- if (length != 0) {
- p->x /= length;
- p->y /= length;
- p->z /= length;
- } else {
- p->x = 0;
- p->y = 0;
- p->z = 0;
- }
-}
-
-/*-------------------------------------------------------------------------
- Calculate the unit normal at p given two other points
- p1,p2 on the surface. The normal points in the direction
- of p1 crossproduct p2
- */
-static XYZ
-calc_normal (XYZ p, XYZ p1, XYZ p2)
-{
- XYZ n, pa, pb;
- pa.x = p1.x - p.x;
- pa.y = p1.y - p.y;
- pa.z = p1.z - p.z;
- pb.x = p2.x - p.x;
- pb.y = p2.y - p.y;
- pb.z = p2.z - p.z;
- n.x = pa.y * pb.z - pa.z * pb.y;
- n.y = pa.z * pb.x - pa.x * pb.z;
- n.z = pa.x * pb.y - pa.y * pb.x;
- normalize (&n);
- return (n);
-}
-
-
static void
do_color (int i, XColor *colors)
{
static void
draw_bounding_box (ModeInfo *mi)
{
- spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)];
+ /* spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)]; */
- static GLfloat c1[4] = { 0.2, 0.2, 0.6, 1.0 };
- static GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 };
+ static const GLfloat c1[4] = { 0.2, 0.2, 0.6, 1.0 };
+ static const GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 };
int wire = MI_IS_WIREFRAME(mi);
- GLfloat x1 = cc->bbox[0].x;
- GLfloat y1 = cc->bbox[0].y;
- GLfloat z1 = cc->bbox[0].z;
- GLfloat x2 = cc->bbox[1].x;
- GLfloat y2 = cc->bbox[1].y;
- GLfloat z2 = cc->bbox[1].z;
+ GLfloat x1,y1,z1,x2,y2,z2;
-#if 1
+# if 0
+ x1 = cc->bbox[0].x;
+ y1 = cc->bbox[0].y;
+ z1 = cc->bbox[0].z;
+ x2 = cc->bbox[1].x;
+ y2 = cc->bbox[1].y;
+ z2 = cc->bbox[1].z;
+# else
x1 = y1 = z1 = -0.5;
x2 = y2 = z2 = 0.5;
-#endif
+# endif
if (do_bbox && !wire)
{
glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c1);
glFrontFace(GL_CCW);
+ glEnable(GL_CULL_FACE);
glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
glNormal3f(0, 1, 0);
glVertex3f(x2, y1, z1); glVertex3f(x2, y1, z2);
glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1);
glEnd();
+ glDisable(GL_CULL_FACE);
}
- glPushAttrib (GL_LIGHTING);
- glDisable (GL_LIGHTING);
-
- glColor3f (c2[0], c2[1], c2[2]);
-
if (do_grid)
{
+ glDisable (GL_LIGHTING);
+ glColor3f (c2[0], c2[1], c2[2]);
glPushMatrix();
glBegin(GL_LINES);
glVertex3f(0, -0.66, 0);
}
else
{
+#if 0
glBegin(GL_LINES);
if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0;
if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0;
glVertex3f(0 , y1, 0); glVertex3f(0, y2, 0);
glVertex3f(0, 0, z1); glVertex3f(0, 0, z2);
glEnd();
+#endif
}
-
- glPopAttrib();
}
if (s > 0.001)
{
- static GLfloat c[4] = { 0.6, 0.5, 1.0, 1.0 };
+ static const GLfloat c[4] = { 0.6, 0.5, 1.0, 1.0 };
- glPushAttrib (GL_LIGHTING);
glDisable (GL_LIGHTING);
glPushMatrix();
draw_circle (mi, False);
glPopMatrix();
- glPopAttrib();
+ if (! MI_IS_WIREFRAME(mi)) glEnable (GL_LIGHTING);
}
cc->tracer += 5;
tweak_parameters (mi);
- {
- static Bool done = False;
- if (!done || (0 == (random() % 20)))
- {
- init_colors (mi);
- done = True;
- }
- }
+ if (!cc->done_once || (0 == (random() % 20)))
+ {
+ init_colors (mi);
+ cc->done_once = True;
+ }
{
glNewList(cc->dlist, GL_COMPILE);
glEndList();
glNewList(cc->dlist2, GL_COMPILE);
- glPushAttrib (GL_LIGHTING);
- glDisable (GL_LIGHTING);
glPushMatrix();
glScalef (1.05, 1.05, 1.05);
cc->polys2 = unit_spheremonics (mi, cc->resolution, 2, cc->m, cc->colors);
glPopMatrix();
- glPopAttrib();
glEndList();
}
}
\f
-static void
-load_font (ModeInfo *mi, char *res, XFontStruct **fontP, GLuint *dlistP)
-{
- const char *font = get_string_resource (res, "Font");
- XFontStruct *f;
- Font id;
- int first, last;
-
- if (!font) font = "-*-times-bold-r-normal-*-140-*";
-
- f = XLoadQueryFont(mi->dpy, font);
- if (!f) f = XLoadQueryFont(mi->dpy, "fixed");
-
- id = f->fid;
- first = f->min_char_or_byte2;
- last = f->max_char_or_byte2;
-
- clear_gl_error ();
- *dlistP = glGenLists ((GLuint) last+1);
- check_gl_error ("glGenLists");
- glXUseXFont(id, first, last-first+1, *dlistP + first);
- check_gl_error ("glXUseXFont");
-
- *fontP = f;
-}
-
-static void
-draw_label (ModeInfo *mi, const char *s)
-{
- spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)];
- int i;
-
- glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT);
- glDisable(GL_LIGHTING);
- glDisable(GL_DEPTH_TEST);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
- glColor3f(1.0, 1.0, 0.0);
-
- glRasterPos2f (10,
- (mi->xgwa.height
- - 10
- - (cc->font->ascent + cc->font->descent)));
- for (i = 0; i < strlen(s); i++)
- glCallList (cc->font_list + (int)s[i]);
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glPopAttrib();
-}
-
-
-\f
-
-void
+ENTRYPOINT void
init_spheremonics (ModeInfo *mi)
{
spheremonics_configuration *cc;
- if (!ccs) {
- ccs = (spheremonics_configuration *)
- calloc (MI_NUM_SCREENS(mi), sizeof (spheremonics_configuration));
- if (!ccs) {
- fprintf(stderr, "%s: out of memory\n", progname);
- exit(1);
- }
-
- cc = &ccs[MI_SCREEN(mi)];
- }
+ MI_INIT (mi, ccs, NULL);
cc = &ccs[MI_SCREEN(mi)];
reshape_spheremonics (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
}
- if (smooth_p)
- {
- glEnable (GL_LINE_SMOOTH);
- glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- }
-
{
Bool spinx=False, spiny=False, spinz=False;
double spin_speed = 1.0;
if (*s == 'x' || *s == 'X') spinx = True;
else if (*s == 'y' || *s == 'Y') spiny = True;
else if (*s == 'z' || *s == 'Z') spinz = True;
+ else if (*s == '0') ;
else
{
fprintf (stderr,
}
cc->rot = make_rotator (spinx ? spin_speed : 0,
- spiny ? spin_speed : 0,
spinz ? spin_speed : 0,
+ spiny ? spin_speed : 0,
1.0,
do_wander ? wander_speed : 0,
- True);
- cc->trackball = gltrackball_init ();
+ (spinx && spiny && spinz));
+ cc->trackball = gltrackball_init (True);
}
cc->tracer = -1;
cc->resolution = res;
- load_font (mi, "labelfont", &cc->font, &cc->font_list);
+ cc->font_data = load_texture_font (mi->dpy, "labelfont");
cc->dlist = glGenLists(1);
cc->dlist2 = glGenLists(1);
cc->m_max = 4; /* 9? */
{
- int i;
+ unsigned int i;
for (i = 0; i < countof(cc->dm); i++)
cc->dm[i] = 1; /* going up! */
}
-Bool
+ENTRYPOINT Bool
spheremonics_handle_event (ModeInfo *mi, XEvent *event)
{
spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)];
- if (event->xany.type == ButtonPress &&
- event->xbutton.button & Button1)
- {
- cc->button_down_p = True;
- gltrackball_start (cc->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)
- {
- cc->button_down_p = False;
- return True;
- }
- else if (event->xany.type == MotionNotify &&
- cc->button_down_p)
+ if (gltrackball_event_handler (event, cc->trackball,
+ MI_WIDTH (mi), MI_HEIGHT (mi),
+ &cc->button_down_p))
+ return True;
+ else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
{
- gltrackball_track (cc->trackball,
- event->xmotion.x, event->xmotion.y,
- MI_WIDTH (mi), MI_HEIGHT (mi));
+ cc->change_tick = duration;
return True;
}
}
-void
+ENTRYPOINT void
draw_spheremonics (ModeInfo *mi)
{
spheremonics_configuration *cc = &ccs[MI_SCREEN(mi)];
if (!cc->glx_context)
return;
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cc->glx_context));
+
+ gl_init(mi);
+
glShadeModel(GL_SMOOTH);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCallList (cc->dlist);
mi->polygon_count += cc->polys1;
- if (cc->mesher >= 0 /* || mouse_p */)
+ if (cc->mesher >= 0 /* || cc->button_down_p */)
{
+ glDisable (GL_LIGHTING);
glCallList (cc->dlist2);
mi->polygon_count += cc->polys2;
if (cc->mesher >= 0)
: "%d %d %d %d %d %d %d %d"),
cc->m[0], cc->m[1], cc->m[2], cc->m[3],
cc->m[4], cc->m[5], cc->m[6], cc->m[7]);
- draw_label (mi, buf);
+
+ glColor3f(1.0, 1.0, 0.0);
+ print_texture_label (mi->dpy, cc->font_data,
+ mi->xgwa.width, mi->xgwa.height,
+ 1, buf);
}
if (!static_parms)
{
- static int tick = 0;
- if (tick++ >= duration && !cc->button_down_p)
+ if (cc->change_tick++ >= duration && !cc->button_down_p)
{
generate_spheremonics(mi);
- tick = 0;
+ cc->change_tick = 0;
cc->mesher = -1; /* turn off the mesh when switching objects */
}
}
glXSwapBuffers(dpy, window);
}
+XSCREENSAVER_MODULE ("Spheremonics", spheremonics)
+
#endif /* USE_GL */