diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/surfaces.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/glx/surfaces.c')
-rw-r--r-- | hacks/glx/surfaces.c | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/hacks/glx/surfaces.c b/hacks/glx/surfaces.c new file mode 100644 index 0000000..4c79740 --- /dev/null +++ b/hacks/glx/surfaces.c @@ -0,0 +1,648 @@ +/* Surface --- Parametric 3d surfaces visualization */ + +/* + * Revision History: + * 2000: written by Andrey Mirtchovski <mirtchov@cpsc.ucalgary.ca> + * + * 01-Mar-2003 mirtchov Modified as a xscreensaver hack. + * 01-jan-2009 steger Renamed from klein.c to surfaces.c. + * Removed the Klein bottle. + * Added many new surfaces. + * Added many command line options. + * + */ + +/* surfaces to draw */ +#define SURFACE_RANDOM -1 +#define SURFACE_DINI 0 +#define SURFACE_ENNEPER 1 +#define SURFACE_KUEN 2 +#define SURFACE_MOEBIUS 3 +#define SURFACE_SEASHELL 4 +#define SURFACE_SWALLOWTAIL 5 +#define SURFACE_BOHEMIAN 6 +#define SURFACE_WHITNEY 7 +#define SURFACE_PLUECKER 8 +#define SURFACE_HENNEBERG 9 +#define SURFACE_CATALAN 10 +#define SURFACE_CORKSCREW 11 +#define NUM_SURFACES 12 + +/* primitives to draw with + * note that we skip the polygons and + * triangle fans -- too slow + * + * also removed triangle_strip and quads -- + * just doesn't look good enough + */ +#define RENDER_RANDOM -1 +#define RENDER_POINTS 0 +#define RENDER_LINES 1 +#define RENDER_LINE_LOOP 2 +#define NUM_RENDER 3 + +#ifdef STANDALONE +# define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*suppressRotationAnimation: True\n" \ + +# define free_surface 0 +# define release_surface 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +#define DEF_SURFACE "random" +#define DEF_MODE "random" +#define DEF_SPIN "True" +#define DEF_WANDER "False" +#define DEF_SPEED "300" + +#include "rotator.h" +#include "gltrackball.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + + +static char *surface_type; +static char *render_mode; +static int render; +static int speed; +static Bool do_spin; +static Bool do_wander; + +static XrmOptionDescRec opts[] = { + { "-surface", ".surface", XrmoptionSepArg, 0 }, + { "-random-surface", ".surface", XrmoptionNoArg, "random" }, + { "-dini", ".surface", XrmoptionNoArg, "dini" }, + { "-enneper", ".surface", XrmoptionNoArg, "enneper" }, + { "-kuen", ".surface", XrmoptionNoArg, "kuen" }, + { "-moebius", ".surface", XrmoptionNoArg, "moebius" }, + { "-seashell", ".surface", XrmoptionNoArg, "seashell" }, + { "-swallowtail", ".surface", XrmoptionNoArg, "swallowtail" }, + { "-bohemian", ".surface", XrmoptionNoArg, "bohemian" }, + { "-whitney", ".surface", XrmoptionNoArg, "whitney" }, + { "-pluecker", ".surface", XrmoptionNoArg, "pluecker" }, + { "-henneberg", ".surface", XrmoptionNoArg, "henneberg" }, + { "-catalan", ".surface", XrmoptionNoArg, "catalan" }, + { "-corkscrew", ".surface", XrmoptionNoArg, "corkscrew" }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-random-mode", ".mode", XrmoptionNoArg, "random" }, + { "-points", ".mode", XrmoptionNoArg, "points" }, + { "-lines", ".mode", XrmoptionNoArg, "lines" }, + { "-line-loops", ".mode", XrmoptionNoArg, "line-loops" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-wander", ".wander", XrmoptionNoArg, "True" }, + { "+wander", ".wander", XrmoptionNoArg, "False" }, +}; + +static argtype vars[] = { + {&surface_type, "surface", "Surface", DEF_SURFACE, t_String }, + {&render_mode, "mode", "Mode", DEF_MODE, t_String }, + {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool }, + {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool }, + {&speed, "speed", "Speed", DEF_SPEED, t_Int }, +}; + + +ENTRYPOINT ModeSpecOpt surface_opts = +{countof(opts), opts, countof(vars), vars, NULL}; + + + +typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; +} GL_VECTOR; + +typedef struct { + GLXContext *glx_context; + Window window; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + + int render; + Bool random_render; + int surface; + Bool random_surface; + int frame; + + float du, dv; + float a, b, c; + + float draw_step; +} surfacestruct; + +static surfacestruct *surface = NULL; + + +static void draw(ModeInfo *mi) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + double u, v; + float coord[3]; + int render; + + mi->polygon_count = 0; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + glPushMatrix(); + + { + double x, y, z; + get_position(sp->rot, &x, &y, &z, !sp->button_down_p); + glTranslatef((x-0.5)*10, (y-0.5)*10, (z-0.5)*20); + + gltrackball_rotate(sp->trackball); + + get_rotation(sp->rot, &x, &y, &z, !sp->button_down_p); + glRotatef(x*360, 1.0, 0.0, 0.0); + glRotatef(y*360, 0.0, 1.0, 0.0); + glRotatef(z*360, 0.0, 0.0, 1.0); + } + + glScalef(4.0, 4.0, 4.0); + + switch(sp->surface) + { + case SURFACE_DINI: + for (v=0.11; v<=2.0; v+=sp->dv) + { + glBegin(sp->render); + for (u=0; u<=6.0*M_PI; u+=sp->du) + { + coord[0] = sp->a*cos(u)*sin(v); + coord[1] = sp->a*sin(u)*sin(v); + coord[2] = sp->a*(cos(v)+log(tan(0.5*v)))+0.2*sp->b*u; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_ENNEPER: + for (u=-M_PI; u<=M_PI; u+=sp->du) + { + glBegin(sp->render); + for (v=-M_PI; v<M_PI; v+=sp->dv) + { + coord[0] = sp->a*(u-(1.0/3.0*u*u*u)+u*v*v); + coord[1] = sp->b*(v-(1.0/3.0*v*v*v)+u*u*v); + coord[2] = u*u-v*v; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_KUEN: + for (u=-4.48; u<=4.48; u+=sp->du) + { + glBegin(sp->render); + for (v=M_PI/51; v<M_PI; v+=sp->dv) + { + coord[0] = 2*(cos(u)+u*sin(u))*sin(v)/(1+u*u*sin(v)*sin(v)); + coord[1] = 2*(sin(u)-u*cos(u))*sin(v)/(1+u*u*sin(v)*sin(v)); + coord[2] = log(tan(0.5*v))+2*cos(v)/(1+u*u*sin(v)*sin(v)); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_MOEBIUS: + for (u=-M_PI; u<M_PI; u+=sp->du) + { + glBegin(sp->render); + for (v=-0.735; v<0.74; v+=sp->dv) + { + coord[0] = cos(u)+v*cos(u/2)*cos(u); + coord[1] = sin(u)+v*cos(u/2)*sin(u); + coord[2] = v*sin(u/2); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_SEASHELL: + for (u=0; u<2*M_PI; u+=sp->du) + { + glBegin(sp->render); + for (v=0; v<2*M_PI; v+=sp->dv) + { + coord[0] = sp->a*(1-v/(2*M_PI))*cos(2*v)*(1+cos(u))+sp->c*cos(2*v); + coord[1] = sp->a*(1-v/(2*M_PI))*sin(2*v)*(1+cos(u))+sp->c*sin(2*v); + coord[2] = 2*sp->b*v/(2*M_PI)+sp->a*(1-v/(2*M_PI))*sin(u); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_SWALLOWTAIL: + for (u=-2.5; u<2.0; u+=sp->du) + { + glBegin(sp->render); + for (v=-1.085; v<1.09; v+=sp->dv) + { + coord[0] = u*v*v+3*v*v*v*v; + coord[1] = -2*u*v-4*v*v*v; + coord[2] = u; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_BOHEMIAN: + for (u=-M_PI; u<M_PI; u+=sp->du) + { + glBegin(sp->render); + for (v=-M_PI; v<M_PI; v+=sp->dv) + { + coord[0] = sp->a*cos(u); + coord[1] = sp->b*cos(v)+sp->a*sin(u); + coord[2] = sin(v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_WHITNEY: + for (v=-1.995; v<2.0; v+=sp->dv) + { + glBegin(sp->render); + for (u=-1.995; u<2.0; u+=sp->du) + { + coord[0] = u*v; + coord[1] = u; + coord[2] = v*v-2; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_PLUECKER: + for (u=0; u<2.5; u+=sp->dv) + { + glBegin(sp->render); + for (v=-M_PI; v<M_PI; v+=sp->du) + { + coord[0] = u*cos(v); + coord[1] = u*sin(v); + coord[2] = 2*cos(v)*sin(v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_HENNEBERG: + for (u=0.9; u<2.55; u+=sp->dv) + { + glBegin(sp->render); + for (v=-M_PI; v<M_PI; v+=sp->du) + { + coord[0] = sinh(1.0/3.0*u)*cos(v)-1.0/3.0*sinh(u)*cos(3.0*v); + coord[1] = sinh(1.0/3.0*u)*sin(v)+1.0/3.0*sinh(u)*sin(3.0*v); + coord[2] = cosh(2.0/3.0*u)*cos(2.0*v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_CATALAN: + for (v=-2; v<2; v+=sp->du) + { + glBegin(sp->render); + for (u=-2*M_PI; u<2*M_PI+0.05; u+=sp->dv) + { + coord[0] = 0.33*(u-sin(u)*cosh(v)); + coord[1] = 0.33*(1.0-cos(u)*cosh(v)); + coord[2] = 0.33*4.0*sin(0.5*u)*sinh(0.5*v); + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + case SURFACE_CORKSCREW: + for (v=-M_PI; v<M_PI; v+=sp->du) + { + glBegin(sp->render); + for (u=-M_PI; u<M_PI; u+=sp->dv) + { + coord[0] = 0.5*(sp->a+2.0)*cos(u)*cos(v); + coord[1] = 0.5*(sp->a+2.0)*sin(u)*cos(v); + coord[2] = 0.5*(sp->a+2.0)*sin(v)+u; + glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7); + glVertex3fv(coord); + mi->polygon_count++; + } + glEnd(); + } + break; + } + glPopMatrix(); + + if (sp->render == GL_LINES) + mi->polygon_count /= 2; + + sp->a = sin(sp->draw_step+=0.01); + sp->b = cos(sp->draw_step+=0.01); + sp->c = sin(sp->draw_step+0.25*M_PI); + + if (sp->random_surface || sp->random_render) + { + sp->frame++; + if (sp->frame >= speed) + { + sp->frame = 0; + if (sp->random_surface) + sp->surface = random() % NUM_SURFACES; + if (sp->random_render) + { + render = random() % NUM_RENDER; + switch (render) + { + case RENDER_POINTS: + sp->render = GL_POINTS; + break; + case RENDER_LINES: + sp->render = GL_LINES; + break; + case RENDER_LINE_LOOP: + if (sp->surface == SURFACE_BOHEMIAN || + sp->surface == SURFACE_PLUECKER || + sp->surface == SURFACE_HENNEBERG) + sp->render = GL_LINE_LOOP; + else + sp->render = GL_LINE_STRIP; + break; + default: + sp->render = GL_LINE_LOOP; + break; + } + } + } + } +} + + +/* new window size or exposure */ +ENTRYPOINT void reshape_surface(ModeInfo *mi, int width, int height) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + GLfloat h = (GLfloat) height / (GLfloat) width; + int y = 0; + + if (width > height * 5) { /* tiny window: show middle */ + height = width * 9/16; + y = -height/2; + h = height / (GLfloat) width; + } + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context)); + + glViewport(0, y, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective (30.0, 1/h, 1.0, 100.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 30.0, 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); +} + + +ENTRYPOINT Bool surface_handle_event(ModeInfo *mi, XEvent *event) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + + if (gltrackball_event_handler (event, sp->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &sp->button_down_p)) + return True; + + return False; +} + + +ENTRYPOINT void init_surface(ModeInfo *mi) +{ + int screen = MI_SCREEN(mi); + surfacestruct *sp; + + MI_INIT (mi, surface); + sp = &surface[screen]; + + sp->window = MI_WINDOW(mi); + + { + double spin_speed = 1.0; + double wander_speed = 0.03; + sp->rot = make_rotator(do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + do_spin ? spin_speed : 0, + 1.0, + do_wander ? wander_speed : 0, + True); + sp->trackball = gltrackball_init (True); + } + + if (!strcasecmp(surface_type,"random")) + { + sp->random_surface = True; + sp->surface = random() % NUM_SURFACES; + } + else if (!strcasecmp(surface_type,"dini")) + { + sp->random_surface = False; + sp->surface = SURFACE_DINI; + } + else if (!strcasecmp(surface_type,"enneper")) + { + sp->random_surface = False; + sp->surface = SURFACE_ENNEPER; + } + else if (!strcasecmp(surface_type,"kuen")) + { + sp->random_surface = False; + sp->surface = SURFACE_KUEN; + } + else if (!strcasecmp(surface_type,"moebius")) + { + sp->random_surface = False; + sp->surface = SURFACE_MOEBIUS; + } + else if (!strcasecmp(surface_type,"seashell")) + { + sp->random_surface = False; + sp->surface = SURFACE_SEASHELL; + } + else if (!strcasecmp(surface_type,"swallowtail")) + { + sp->random_surface = False; + sp->surface = SURFACE_SWALLOWTAIL; + } + else if (!strcasecmp(surface_type,"bohemian")) + { + sp->random_surface = False; + sp->surface = SURFACE_BOHEMIAN; + } + else if (!strcasecmp(surface_type,"whitney")) + { + sp->random_surface = False; + sp->surface = SURFACE_WHITNEY; + } + else if (!strcasecmp(surface_type,"pluecker")) + { + sp->random_surface = False; + sp->surface = SURFACE_PLUECKER; + } + else if (!strcasecmp(surface_type,"henneberg")) + { + sp->random_surface = False; + sp->surface = SURFACE_HENNEBERG; + } + else if (!strcasecmp(surface_type,"catalan")) + { + sp->random_surface = False; + sp->surface = SURFACE_CATALAN; + } + else if (!strcasecmp(surface_type,"corkscrew")) + { + sp->random_surface = False; + sp->surface = SURFACE_CORKSCREW; + } + else + { + sp->random_surface = True; + sp->surface = random() % NUM_SURFACES; + } + + if (!strcasecmp(render_mode,"random")) + { + sp->random_render = True; + render = random() % NUM_RENDER; + } + else if (!strcasecmp(render_mode,"points")) + { + sp->random_render = False; + render = RENDER_POINTS; + } + else if (!strcasecmp(render_mode,"lines")) + { + sp->random_render = False; + render = RENDER_LINES; + } + else if (!strcasecmp(render_mode,"line-loops")) + { + sp->random_render = False; + render = RENDER_LINE_LOOP; + } + else + { + sp->random_render = True; + render = random() % NUM_RENDER; + } + + switch (render) + { + case RENDER_POINTS: + sp->render = GL_POINTS; + break; + case RENDER_LINES: + sp->render = GL_LINES; + break; + case RENDER_LINE_LOOP: + if (sp->surface == SURFACE_BOHEMIAN || + sp->surface == SURFACE_PLUECKER || + sp->surface == SURFACE_HENNEBERG) + sp->render = GL_LINE_LOOP; + else + sp->render = GL_LINE_STRIP; + break; + default: + sp->render = GL_LINE_LOOP; + break; + } + + sp->frame = 0; + + sp->du = 0.07; + sp->dv = 0.07; + sp->a = sp->b = 1; + sp->c = 0.1; + + if ((sp->glx_context = init_GL(mi)) != NULL) + { + reshape_surface(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + else + { + MI_CLEARWINDOW(mi); + } +} + + +ENTRYPOINT void draw_surface(ModeInfo * mi) +{ + surfacestruct *sp = &surface[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!sp->glx_context) + return; + + glDrawBuffer(GL_BACK); + + glXMakeCurrent(display, window, *(sp->glx_context)); + draw(mi); + if (mi->fps_p) + do_fps(mi); + glFinish(); + glXSwapBuffers(display, window); +} + + +XSCREENSAVER_MODULE_2("Surfaces", surfaces, surface) + +#endif |