From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/glx/extrusion.c | 556 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 hacks/glx/extrusion.c (limited to 'hacks/glx/extrusion.c') diff --git a/hacks/glx/extrusion.c b/hacks/glx/extrusion.c new file mode 100644 index 0000000..3dee71c --- /dev/null +++ b/hacks/glx/extrusion.c @@ -0,0 +1,556 @@ +/* -*- Mode: C; tab-width: 4 -*- */ +/* extrusion --- extrusion module for xscreensaver */ +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + + * Revision History: + * Tue Oct 19 22:24:47 PDT 1999 Initial creation by David Konerding + * + * + * Notes: + * This screensaver requires the GLE ("OpenGL Tubing and Extrusion Library") + * which can be obtained from http://www.linas.org/gle/index.html + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define free_extrusion 0 +# define release_extrusion 0 +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL /* whole file */ + +#ifdef HAVE_XMU +# ifndef VMS +# include +#else /* VMS */ +# include +# endif /* VMS */ +#endif + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "ximage-loader.h" +#include "rotator.h" +#include "gltrackball.h" +#include "extrusion.h" + +#define checkImageWidth 64 +#define checkImageHeight 64 + + +#define WIDTH 640 +#define HEIGHT 480 + +#define DEF_LIGHT "True" +#define DEF_TEXTURE "False" +#define DEF_TEX_QUAL "False" +#define DEF_MIPMAP "False" +#define DEF_NAME "RANDOM" +#define DEF_IMAGE "BUILTIN" + +static int do_light; +static int do_texture; +static int do_tex_qual; +static int do_mipmap; +static char *which_name; +static char *which_image; + +static XrmOptionDescRec opts[] = { + {"-light", ".extrusion.light", XrmoptionNoArg, "true" }, + {"+light", ".extrusion.light", XrmoptionNoArg, "false" }, + {"-texture", ".extrusion.texture", XrmoptionNoArg, "true" }, + {"+texture", ".extrusion.texture", XrmoptionNoArg, "false" }, + {"-texture", ".extrusion.texture", XrmoptionNoArg, "true" }, + {"+texture_quality", ".extrusion.texture", XrmoptionNoArg, "false" }, + {"-texture_quality", ".extrusion.texture", XrmoptionNoArg, "true" }, + {"+mipmap", ".extrusion.mipmap", XrmoptionNoArg, "false" }, + {"-mipmap", ".extrusion.mipmap", XrmoptionNoArg, "true" }, + {"-name", ".extrusion.name", XrmoptionSepArg, 0 }, + {"-image", ".extrusion.image", XrmoptionSepArg, 0 }, +}; + + +static argtype vars[] = { + {&do_light, "light", "Light", DEF_LIGHT, t_Bool}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool}, + {&do_tex_qual, "texture_quality", "Texture_Quality", DEF_TEX_QUAL, t_Bool}, + {&do_mipmap, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, + {&which_name, "name", "Name", DEF_NAME, t_String}, + {&which_image, "image", "Image", DEF_IMAGE, t_String}, +}; + + +static OptionStruct desc[] = +{ + {"-name num", "example 'name' to draw (helix2, helix3, helix4, joinoffset, screw, taper, twistoid)"}, + {"-/+ light", "whether to do enable lighting (slower)"}, + {"-/+ texture", "whether to apply a texture (slower)"}, + {"-image ", "texture image to load"}, + {"-/+ texture_quality", "whether to use texture smoothing (slower)"}, + {"-/+ mipmap", "whether to use texture mipmap (slower)"}, +}; + +ENTRYPOINT ModeSpecOpt extrusion_opts = {countof(opts), opts, countof(vars), vars, desc}; + +#ifdef USE_MODULES +ModStruct extrusion_description = +{"extrusion", "init_extrusion", "draw_extrusion", NULL, + "draw_extrusion", "init_extrusion", NULL, &extrusion_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "OpenGL extrusion", 0, NULL}; +#endif + + +/* structure for holding the extrusion data */ +typedef struct { + int screen_width, screen_height; + GLXContext *glx_context; + rotator *rot; + trackball_state *trackball; + Bool button_down_p; + Bool button2_down_p; + int mouse_start_x, mouse_start_y; + int mouse_x, mouse_y; + int mouse_dx, mouse_dy; + Window window; + XColor fg, bg; + int extrusion_number; +} extrusionstruct; + +static extrusionstruct *Extrusion = NULL; + + + +/* set up a light */ +static const GLfloat lightOnePosition[] = {40.0, 40, 100.0, 0.0}; +static const GLfloat lightOneColor[] = {0.99, 0.99, 0.00, 1.0}; + +static const GLfloat lightTwoPosition[] = {-40.0, 40, 100.0, 0.0}; +static const GLfloat lightTwoColor[] = {0.00, 0.99, 0.99, 1.0}; + +float rot_x=0, rot_y=0, rot_z=0; +float lastx=0, lasty=0; + +static float max_lastx=400, max_lasty=400; +static float min_lastx=-400, min_lasty=-400; + +struct functions { + void (*InitStuff)(void); + void (*DrawStuff)(void); + char *name; +}; + +/* currently joinoffset and twistoid look funny- + like we're looking at them from the back or something +*/ + +static const struct functions funcs_ptr[] = { + {InitStuff_helix2, DrawStuff_helix2, "helix2"}, + {InitStuff_helix3, DrawStuff_helix3, "helix3"}, + {InitStuff_helix4, DrawStuff_helix4, "helix4"}, + {InitStuff_joinoffset, DrawStuff_joinoffset, "joinoffset"}, + {InitStuff_screw, DrawStuff_screw, "screw"}, + {InitStuff_taper, DrawStuff_taper, "taper"}, + {InitStuff_twistoid, DrawStuff_twistoid, "twistoid"}, +}; + +static int num_extrusions = countof(funcs_ptr); + + +/* BEGINNING OF FUNCTIONS */ + + +static GLubyte * +Generate_Image(int *width, int *height, int *format) +{ + GLubyte *result; + int i, j, c; + int counter=0; + + *width = checkImageWidth; + *height = checkImageHeight; + result = (GLubyte *)malloc(4 * (*width) * (*height)); + + counter = 0; + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = (((((i&0x8)==0))^(((j&0x8))==0)))*255; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) c; + result[counter++] = (GLubyte) 255; + } + } + + *format = GL_RGBA; + return result; +} + + +/* Create a texture in OpenGL. First an image is loaded + and stored in a raster buffer, then it's */ +static void Create_Texture(ModeInfo *mi, const char *filename) +{ + int height, width; + GLubyte *image; + int format; + + if ( !strncmp(filename, "BUILTIN", 7)) + { + BUILTIN: + image = Generate_Image(&width, &height, &format); + } + else + { + XImage *ximage = file_to_ximage (MI_DISPLAY (mi), MI_VISUAL (mi), + filename); + if (!ximage) + goto BUILTIN; + image = (GLubyte *) ximage->data; + width = ximage->width; + height = ximage->height; + format = GL_RGBA; + } + + /* GL_MODULATE or GL_DECAL depending on what you want */ + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + /* perhaps we can edge a bit more speed at the expense of quality */ + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + if (do_tex_qual) { + /* with texture_quality, the min and mag filters look *much* nice but are *much* slower */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + else { + /* default is to do it quick and dirty */ + /* if you have mipmaps turned on, but not texture quality, nothing will happen! */ + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + /* mipmaps make the image look much nicer */ + if (do_mipmap) + { + int status; + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, format, + GL_UNSIGNED_BYTE, image); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, width, height, + (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); + } + else + { + clear_gl_error(); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, image); + check_gl_error("texture"); + } +} + + +static void +init_rotation (ModeInfo *mi) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + double spin_speed = 0.5; + gp->rot = make_rotator (spin_speed, spin_speed, spin_speed, + 0.2, + 0.005, + True); + gp->trackball = gltrackball_init (True); + + lastx = (random() % (int) (max_lastx - min_lastx)) + min_lastx; + lasty = (random() % (int) (max_lasty - min_lasty)) + min_lasty; +} + + +/* draw the extrusion once */ +ENTRYPOINT void +draw_extrusion(ModeInfo * mi) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + static const GLfloat color[4] = {0.6, 0.6, 0.4, 1.0}; + /* static const GLfloat spec[4] = {0.6, 0.6, 0.6, 1.0}; */ + /* static const GLfloat shiny = 40.0; */ + + double x, y, z; + + if (!gp->glx_context) + return; + + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context)); + + glPushMatrix(); + + gltrackball_rotate (gp->trackball); + + get_rotation (gp->rot, &x, &y, &z, + !(gp->button_down_p || gp->button2_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); + + /* track the mouse only if a button is down. */ + if (gp->button2_down_p) + { + gp->mouse_dx += gp->mouse_x - gp->mouse_start_x; + gp->mouse_dy += gp->mouse_y - gp->mouse_start_y; + gp->mouse_start_x = gp->mouse_x; + gp->mouse_start_y = gp->mouse_y; + } + + { + float scale = (max_lastx - min_lastx); + get_position (gp->rot, &x, &y, &z, + !(gp->button_down_p || gp->button2_down_p)); + lastx = x * scale + min_lastx + gp->mouse_dx; + lasty = y * scale + min_lasty + gp->mouse_dy; + } + + glScalef(0.5, 0.5, 0.5); + + /* glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); */ + /* glMateriali (GL_FRONT_AND_BACK, GL_SHININESS, shiny); */ + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glFrontFace(GL_CCW); + + funcs_ptr[gp->extrusion_number].DrawStuff(); + + glPopMatrix(); + + if (mi->fps_p) do_fps (mi); + glXSwapBuffers(display, window); +} + + +/* set up lighting conditions */ +static void +SetupLight(void) +{ + glLightfv (GL_LIGHT0, GL_POSITION, lightOnePosition); + glLightfv (GL_LIGHT0, GL_DIFFUSE, lightOneColor); + glLightfv (GL_LIGHT1, GL_POSITION, lightTwoPosition); + glLightfv (GL_LIGHT1, GL_DIFFUSE, lightTwoColor); + + glEnable (GL_LIGHT0); + glEnable (GL_LIGHT1); + glEnable (GL_LIGHTING); + + glColorMaterial (GL_FRONT, GL_DIFFUSE); + glColorMaterial (GL_BACK, GL_DIFFUSE); + glEnable (GL_COLOR_MATERIAL); +} + +/* Standard reshape function */ +ENTRYPOINT void +reshape_extrusion (ModeInfo *mi, int width, int height) +{ + 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; + } + + 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); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +/* decide which extrusion example to run */ +static void +chooseExtrusionExample (ModeInfo *mi) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + int i; + /* call the extrusion init routine */ + + if (!strncmp(which_name, "RANDOM", strlen(which_name))) { + gp->extrusion_number = random() % num_extrusions; + } + else { + gp->extrusion_number=-1; + for (i=0; i < num_extrusions; i++) { + if (!strncmp(which_name, funcs_ptr[i].name, strlen(which_name))) { + gp->extrusion_number = i; + } + } + } + + if (gp->extrusion_number < 0 || gp->extrusion_number >= num_extrusions) { + fprintf(stderr, "%s: invalid extrusion example number!\n", progname); + fprintf(stderr, "%s: known extrusions:\n", progname); + for (i=0; i < num_extrusions; i++) + fprintf(stderr,"\t%s\n", funcs_ptr[i].name); + exit(1); + } + init_rotation(mi); + funcs_ptr[gp->extrusion_number].InitStuff(); +} + + +/* main OpenGL initialization routine */ +static void +initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) +{ + int style; + int mode; + + reshape_extrusion(mi, width, height); + glViewport( 0, 0, width, height ); + + glEnable(GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, True); + glShadeModel(GL_SMOOTH); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + MI_IS_WIREFRAME(mi) = 0; +# endif + + if (do_light) + SetupLight(); + if (MI_IS_WIREFRAME(mi)) { + glPolygonMode(GL_FRONT,GL_LINE); + glPolygonMode(GL_BACK,GL_LINE); + } + if (do_texture) { + Create_Texture(mi, which_image); + glEnable(GL_TEXTURE_2D); + + /* configure the pipeline */ + style = TUBE_JN_CAP; + style |= TUBE_CONTOUR_CLOSED; + style |= TUBE_NORM_FACET; + style |= TUBE_JN_ANGLE; + gleSetJoinStyle (style); + + if (do_texture) { + mode = GLE_TEXTURE_ENABLE | GLE_TEXTURE_VERTEX_MODEL_FLAT; + glMatrixMode (GL_TEXTURE); glLoadIdentity (); + glScalef (0.25, 0.1, 1); glMatrixMode (GL_MODELVIEW); + gleTextureMode (mode); + } + } + +} + +ENTRYPOINT Bool +extrusion_handle_event (ModeInfo *mi, XEvent *event) +{ + extrusionstruct *gp = &Extrusion[MI_SCREEN(mi)]; + + if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + } + else if (event->xany.type == ButtonPress && /* rotate with left button */ + !event->xbutton.state) /* if no modifier keys */ + { + } + else if (event->xany.type == ButtonPress) /* deform with other buttons */ + { /* or with modifier keys */ + gp->button2_down_p = True; + } + else if (event->xany.type == ButtonRelease) + { + gp->button_down_p = False; + gp->button2_down_p = False; + } + else if (event->xany.type == MotionNotify) + { + if (gp->button2_down_p) + { + gp->mouse_x = event->xmotion.x; + gp->mouse_y = event->xmotion.y; + } + } + + if (gltrackball_event_handler (event, gp->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &gp->button_down_p)) + return True; + + return False; +} + + +/* xextrusion initialization routine */ +ENTRYPOINT void +init_extrusion (ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + extrusionstruct *gp; + + if (MI_IS_WIREFRAME(mi)) do_light = 0; + + MI_INIT(mi, Extrusion); + gp = &Extrusion[screen]; + + gp->window = MI_WINDOW(mi); + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_extrusion(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + chooseExtrusionExample(mi); + } else { + MI_CLEARWINDOW(mi); + } + +} + +XSCREENSAVER_MODULE ("Extrusion", extrusion) + +#endif /* USE_GL */ -- cgit v1.2.3-55-g7522