diff options
Diffstat (limited to 'hacks/glx/klein.c')
-rw-r--r-- | hacks/glx/klein.c | 815 |
1 files changed, 575 insertions, 240 deletions
diff --git a/hacks/glx/klein.c b/hacks/glx/klein.c index 0fac5d2..7be5157 100644 --- a/hacks/glx/klein.c +++ b/hacks/glx/klein.c @@ -2,10 +2,10 @@ can walk */ #if 0 -static const char sccsid[] = "@(#)klein.c 1.1 08/10/04 xlockmore"; +static const char sccsid[] = "@(#)klein.c 1.1 04/10/08 xlockmore"; #endif -/* Copyright (c) 2005-2014 Carsten Steger <carsten@mirsanmir.org>. */ +/* Copyright (c) 2005-2020 Carsten Steger <carsten@mirsanmir.org>. */ /* * Permission to use, copy, modify, and distribute this software and its @@ -21,61 +21,83 @@ static const char sccsid[] = "@(#)klein.c 1.1 08/10/04 xlockmore"; * other special, indirect and consequential damages. * * REVISION HISTORY: - * C. Steger - 08/10/04: Initial version - * C. Steger - 09/08/03: Changes to the parameter handling - * C. Steger - 13/12/25: Added the squeezed torus Klein bottle - * C. Steger - 14/10/03: Moved the curlicue texture to curlicue.h + * C. Steger - 04/10/08: Initial version + * C. Steger - 03/08/09: Changes to the parameter handling + * C. Steger - 25/12/13: Added the squeezed torus Klein bottle + * C. Steger - 03/10/14: Moved the curlicue texture to curlicue.h + * C. Steger - 11/01/20: Added the changing colors mode. */ /* - * This program shows three different Klein bottles in 4d: the figure-8 Klein - * bottle, the squeezed torus Klein bottle, or the Lawson Klein bottle. You - * can walk on the Klein bottle, see it turn in 4d, or walk on it while it - * turns in 4d. The figure-8 Klein bottle is well known in its 3d form. The - * 4d form used in this program is an extension of the 3d form to 4d that - * does not intersect itself in 4d (which can be seen in the depth colors - * mode). The squeezed torus Klein bottle also does not intersect itself in - * 4d (which can be seen in the depth colors mode). The Lawson Klein bottle, - * on the other hand, does intersect itself in 4d. Its primary use is that - * it has a nice appearance for walking and for turning in 3d. The Klein - * bottle is a non-orientable surface. To make this apparent, the two-sided - * color mode can be used. Alternatively, orientation markers (curling - * arrows) can be drawn as a texture map on the surface of the Klein bottle. - * While walking on the Klein bottle, you will notice that the orientation - * of the curling arrows changes (which it must because the Klein bottle is - * non-orientable). The program projects the 4d Klein bottle to 3d using - * either a perspective or an orthographic projection. Which of the two - * alternatives looks more appealing depends on the viewing mode and the - * Klein bottle. For example, the Lawson Klein bottle looks nicest when - * projected perspectively. The figure-8 Klein bottle, on the other - * hand, looks nicer while walking when projected orthographically from 4d. - * For the squeezed torus Klein bottle, both projection modes give equally - * acceptable projections. The projected Klein bottle can then be projected - * to the screen either perspectively or orthographically. When using the - * walking modes, perspective projection to the screen should be used. There - * are three display modes for the Klein bottle: mesh (wireframe), solid, or - * transparent. Furthermore, the appearance of the Klein bottle can be as - * a solid object or as a set of see-through bands. Finally, the colors - * with with the Klein bottle is drawn can be set to two-sided, rainbow, or - * depth. In the first case, the Klein bottle is drawn with red on one - * "side" and green on the "other side". Of course, the Klein bottle only - * has one side, so the color jumps from red to green along a curve on the - * surface of the Klein bottle. This mode enables you to see that the Klein - * bottle is non-orientable. The second mode draws the Klein bottle with - * fully saturated rainbow colors. This gives a very nice effect when - * combined with the see-through bands mode or with the orientation markers - * drawn. The third mode draws the Klein bottle with colors that are chosen - * according to the 4d "depth" of the points. This mode enables you to see - * that the figure-8 and squeezed torus Klein bottles do not intersect - * themselves in 4d, while the Lawson Klein bottle does intersect itself. - * The rotation speed for each of the six planes around which the Klein - * bottle rotates can be chosen. For the walk-and-turn more, only the - * rotation speeds around the true 4d planes are used (the xy, xz, and yz - * planes). Furthermore, in the walking modes the walking direction in the - * 2d base square of the Klein bottle and the walking speed can be chosen. - * This program is somewhat inspired by Thomas Banchoff's book "Beyond the - * Third Dimension: Geometry, Computer Graphics, and Higher Dimensions", - * Scientific American Library, 1990. + * This program shows three different Klein bottles in 4d: the + * figure-8 Klein bottle, the pinched torus Klein bottle, or the + * Lawson Klein bottle. You can walk on the Klein bottle, see it turn + * in 4d, or walk on it while it turns in 4d. The figure-8 Klein + * bottle is well known in its 3d form. The 4d form used in this + * program is an extension of the 3d form to 4d that does not + * intersect itself in 4d (which can be seen in the depth colors mode + * when using static colors). The pinched torus Klein bottle also + * does not intersect itself in 4d (which can be seen in the depth + * colors mode when using static colors). The Lawson Klein bottle, on + * the other hand, does intersect itself in 4d. Its primary use is + * that it has a nice appearance for walking and for turning in 3d. + * + * The Klein bottle is a non-orientable surface. To make this + * apparent, the two-sided color mode can be used. Alternatively, + * orientation markers (curling arrows) can be drawn as a texture map + * on the surface of the Klein bottle. While walking on the Klein + * bottle, you will notice that the orientation of the curling arrows + * changes (which it must because the Klein bottle is non-orientable). + * + * The program projects the 4d Klein bottle to 3d using either a + * perspective or an orthographic projection. Which of the two + * alternatives looks more appealing depends on the viewing mode and + * the Klein bottle. For example, the Lawson Klein bottle looks + * nicest when projected perspectively. The figure-8 Klein bottle, on + * the other hand, looks nicer while walking when projected + * orthographically from 4d. For the pinched torus Klein bottle, both + * projection modes give equally acceptable projections. + * + * The projected Klein bottle can then be projected to the screen + * either perspectively or orthographically. When using the walking + * modes, perspective projection to the screen should be used. + * + * There are three display modes for the Klein bottle: mesh + * (wireframe), solid, or transparent. Furthermore, the appearance of + * the Klein bottle can be as a solid object or as a set of + * see-through bands. Finally, the colors with with the Klein bottle + * is drawn can be set to one-sided, two-sided, rainbow, or depth. In + * one-sided mode, the Klein bottle is drawn with the same color on + * both "sides." In two-sided mode (using static colors), the Klein + * bottle is drawn with red on one "side" and green on the "other + * side." Of course, the Klein bottle only has one side, so the color + * jumps from red to green along a curve on the surface of the Klein + * bottle. This mode enables you to see that the Klein bottle is + * non-orientable. If changing colors are used in two-sided mode, + * changing complementary colors are used on the respective "sides." + * The rainbow color mode (using static colors) draws the Klein bottle + * with a color wheel of fully saturated rainbow colors. If changing + * colors are used, the color wheel's colors change dynamically. The + * rainbow color mode gives a very nice effect when combined with the + * see-through bands mode or with the orientation markers drawn. The + * depth color mode draws the Klein bottle with colors that are chosen + * according to the 4d "depth" of the points. If static colors are + * used, this mode enables you to see that the figure-8 and pinched + * torus Klein bottles do not intersect themselves in 4d, while the + * Lawson Klein bottle does intersect itself. + * + * The rotation speed for each of the six planes around which the + * Klein bottle rotates can be chosen. For the walk-and-turn mode, + * only the rotation speeds around the true 4d planes are used (the + * xy, xz, and yz planes). + * + * Furthermore, in the walking modes the walking direction in the 2d + * base square of the Klein bottle and the walking speed can be + * chosen. + * + * This program is somewhat inspired by Thomas Banchoff's book "Beyond + * the Third Dimension: Geometry, Computer Graphics, and Higher + * Dimensions", Scientific American Library, 1990. */ #include "curlicue.h" @@ -84,54 +106,56 @@ static const char sccsid[] = "@(#)klein.c 1.1 08/10/04 xlockmore"; #define M_PI 3.14159265358979323846 #endif -#define KLEIN_BOTTLE_FIGURE_8 0 -#define KLEIN_BOTTLE_SQUEEZED_TORUS 1 -#define KLEIN_BOTTLE_LAWSON 2 -#define NUM_KLEIN_BOTTLES 3 - -#define DISP_WIREFRAME 0 -#define DISP_SURFACE 1 -#define DISP_TRANSPARENT 2 -#define NUM_DISPLAY_MODES 3 - -#define APPEARANCE_SOLID 0 -#define APPEARANCE_BANDS 1 -#define NUM_APPEARANCES 2 - -#define COLORS_TWOSIDED 0 -#define COLORS_RAINBOW 1 -#define COLORS_DEPTH 2 -#define NUM_COLORS 3 - -#define VIEW_WALK 0 -#define VIEW_TURN 1 -#define VIEW_WALKTURN 2 -#define NUM_VIEW_MODES 3 - -#define DISP_3D_PERSPECTIVE 0 -#define DISP_3D_ORTHOGRAPHIC 1 -#define NUM_DISP_3D_MODES 2 - -#define DISP_4D_PERSPECTIVE 0 -#define DISP_4D_ORTHOGRAPHIC 1 -#define NUM_DISP_4D_MODES 2 - -#define DEF_KLEIN_BOTTLE "random" -#define DEF_DISPLAY_MODE "random" -#define DEF_APPEARANCE "random" -#define DEF_COLORS "random" -#define DEF_VIEW_MODE "random" -#define DEF_MARKS "False" -#define DEF_PROJECTION_3D "random" -#define DEF_PROJECTION_4D "random" -#define DEF_SPEEDWX "1.1" -#define DEF_SPEEDWY "1.3" -#define DEF_SPEEDWZ "1.5" -#define DEF_SPEEDXY "1.7" -#define DEF_SPEEDXZ "1.9" -#define DEF_SPEEDYZ "2.1" -#define DEF_WALK_DIRECTION "7.0" -#define DEF_WALK_SPEED "20.0" +#define KLEIN_BOTTLE_FIGURE_8 0 +#define KLEIN_BOTTLE_PINCHED_TORUS 1 +#define KLEIN_BOTTLE_LAWSON 2 +#define NUM_KLEIN_BOTTLES 3 + +#define DISP_WIREFRAME 0 +#define DISP_SURFACE 1 +#define DISP_TRANSPARENT 2 +#define NUM_DISPLAY_MODES 3 + +#define APPEARANCE_SOLID 0 +#define APPEARANCE_BANDS 1 +#define NUM_APPEARANCES 2 + +#define COLORS_ONESIDED 0 +#define COLORS_TWOSIDED 1 +#define COLORS_RAINBOW 2 +#define COLORS_DEPTH 3 +#define NUM_COLORS 4 + +#define VIEW_WALK 0 +#define VIEW_TURN 1 +#define VIEW_WALKTURN 2 +#define NUM_VIEW_MODES 3 + +#define DISP_3D_PERSPECTIVE 0 +#define DISP_3D_ORTHOGRAPHIC 1 +#define NUM_DISP_3D_MODES 2 + +#define DISP_4D_PERSPECTIVE 0 +#define DISP_4D_ORTHOGRAPHIC 1 +#define NUM_DISP_4D_MODES 2 + +#define DEF_KLEIN_BOTTLE "random" +#define DEF_DISPLAY_MODE "random" +#define DEF_APPEARANCE "random" +#define DEF_COLORS "random" +#define DEF_VIEW_MODE "random" +#define DEF_MARKS "False" +#define DEF_CHANGE_COLORS "False" +#define DEF_PROJECTION_3D "random" +#define DEF_PROJECTION_4D "random" +#define DEF_SPEEDWX "1.1" +#define DEF_SPEEDWY "1.3" +#define DEF_SPEEDWZ "1.5" +#define DEF_SPEEDXY "1.7" +#define DEF_SPEEDXZ "1.9" +#define DEF_SPEEDYZ "2.1" +#define DEF_WALK_DIRECTION "7.0" +#define DEF_WALK_SPEED "20.0" #ifdef STANDALONE # define DEFAULTS "*delay: 10000 \n" \ @@ -168,6 +192,7 @@ static char *appear; static char *color_mode; static char *view_mode; static Bool marks; +static Bool change_colors; static char *proj_3d; static char *proj_4d; static float speed_wx; @@ -184,7 +209,7 @@ static XrmOptionDescRec opts[] = { {"-klein-bottle", ".kleinBottle", XrmoptionSepArg, 0 }, {"-figure-8", ".kleinBottle", XrmoptionNoArg, "figure-8" }, - {"-squeezed-torus", ".kleinBottle", XrmoptionNoArg, "squeezed-torus" }, + {"-pinched-torus", ".kleinBottle", XrmoptionNoArg, "pinched-torus" }, {"-lawson", ".kleinBottle", XrmoptionNoArg, "lawson" }, {"-mode", ".displayMode", XrmoptionSepArg, 0 }, {"-wireframe", ".displayMode", XrmoptionNoArg, "wireframe" }, @@ -194,15 +219,18 @@ static XrmOptionDescRec opts[] = {"-solid", ".appearance", XrmoptionNoArg, "solid" }, {"-bands", ".appearance", XrmoptionNoArg, "bands" }, {"-colors", ".colors", XrmoptionSepArg, 0 }, + {"-onesided", ".colors", XrmoptionNoArg, "one-sided" }, {"-twosided", ".colors", XrmoptionNoArg, "two-sided" }, {"-rainbow", ".colors", XrmoptionNoArg, "rainbow" }, {"-depth", ".colors", XrmoptionNoArg, "depth" }, + {"-change-colors", ".changeColors", XrmoptionNoArg, "on"}, + {"+change-colors", ".changeColors", XrmoptionNoArg, "off"}, {"-view-mode", ".viewMode", XrmoptionSepArg, 0 }, {"-walk", ".viewMode", XrmoptionNoArg, "walk" }, {"-turn", ".viewMode", XrmoptionNoArg, "turn" }, {"-walk-turn", ".viewMode", XrmoptionNoArg, "walk-turn" }, - {"-orientation-marks", ".marks", XrmoptionNoArg, "on"}, - {"+orientation-marks", ".marks", XrmoptionNoArg, "off"}, + {"-orientation-marks", ".marks", XrmoptionNoArg, "on"}, + {"+orientation-marks", ".marks", XrmoptionNoArg, "off"}, {"-projection-3d", ".projection3d", XrmoptionSepArg, 0 }, {"-perspective-3d", ".projection3d", XrmoptionNoArg, "perspective" }, {"-orthographic-3d", ".projection3d", XrmoptionNoArg, "orthographic" }, @@ -225,6 +253,7 @@ static argtype vars[] = { &mode, "displayMode", "DisplayMode", DEF_DISPLAY_MODE, t_String }, { &appear, "appearance", "Appearance", DEF_APPEARANCE, t_String }, { &color_mode, "colors", "Colors", DEF_COLORS, t_String }, + { &change_colors, "changeColors", "ChangeColors", DEF_CHANGE_COLORS, t_Bool }, { &view_mode, "viewMode", "ViewMode", DEF_VIEW_MODE, t_String }, { &marks, "marks", "Marks", DEF_MARKS, t_Bool }, { &proj_3d, "projection3d", "Projection3d", DEF_PROJECTION_3D, t_String }, @@ -246,12 +275,17 @@ ENTRYPOINT ModeSpecOpt klein_opts = /* Radius of the figure-8 Klein bottle */ #define FIGURE_8_RADIUS 2.0 -/* Radius of the squeezed torus Klein bottle */ -#define SQUEEZED_TORUS_RADIUS 2.0 +/* Radius of the pinched torus Klein bottle */ +#define PINCHED_TORUS_RADIUS 2.0 /* Offset by which we walk above the Klein bottle */ #define DELTAY 0.02 +/* Color change speeds */ +#define DRHO 0.7 +#define DSIGMA 1.1 +#define DTAU 1.7 + /* Number of subdivisions of the Klein bottle */ #define NUMU 128 #define NUMV 128 @@ -268,11 +302,14 @@ typedef struct { int display_mode; int appearance; int colors; + Bool change_colors; int view; int projection_3d; int projection_4d; /* 4D rotation angles */ float alpha, beta, delta, zeta, eta, theta; + /* Color rotation angles */ + float rho, sigma, tau; /* Movement parameters */ float umove, vmove, dumove, dvmove; int side; @@ -451,6 +488,77 @@ static void rotateall4d(float ze, float et, float th, float m[4][4]) } +/* Add a rotation around the x-axis to the matrix m. */ +static void rotatex(float m[3][3], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<3; i++) + { + u = m[i][1]; + v = m[i][2]; + m[i][1] = c*u+s*v; + m[i][2] = -s*u+c*v; + } +} + + +/* Add a rotation around the y-axis to the matrix m. */ +static void rotatey(float m[3][3], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<3; i++) + { + u = m[i][0]; + v = m[i][2]; + m[i][0] = c*u-s*v; + m[i][2] = s*u+c*v; + } +} + + +/* Add a rotation around the z-axis to the matrix m. */ +static void rotatez(float m[3][3], float phi) +{ + float c, s, u, v; + int i; + + phi *= M_PI/180.0; + c = cos(phi); + s = sin(phi); + for (i=0; i<3; i++) + { + u = m[i][0]; + v = m[i][1]; + m[i][0] = c*u+s*v; + m[i][1] = -s*u+c*v; + } +} + + +/* Compute the 3d rotation matrix m from the 3d rotation angles. */ +static void rotateall3d(float al, float be, float de, float m[3][3]) +{ + int i, j; + + for (i=0; i<3; i++) + for (j=0; j<3; j++) + m[i][j] = (i==j); + rotatex(m,al); + rotatey(m,be); + rotatez(m,de); +} + + /* Multiply two rotation matrices: o=m*n. */ static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4]) { @@ -499,54 +607,79 @@ static void quats_to_rotmat(float p[4], float q[4], float m[4][4]) /* Compute a fully saturated and bright color based on an angle. */ -static void color(kleinstruct *kb, double angle, float col[4]) +static void color(kleinstruct *kb, double angle, float mat[3][3], float col[4]) { int s; - double t; + double t, ca, sa; + float m; - if (kb->colors == COLORS_TWOSIDED) - return; + if (!kb->change_colors) + { + if (kb->colors == COLORS_ONESIDED || kb->colors == COLORS_TWOSIDED) + return; - if (angle >= 0.0) - angle = fmod(angle,2.0*M_PI); - else - angle = fmod(angle,-2.0*M_PI); - s = floor(angle/(M_PI/3)); - t = angle/(M_PI/3)-s; - if (s >= 6) - s = 0; - switch (s) - { - case 0: - col[0] = 1.0; - col[1] = t; - col[2] = 0.0; - break; - case 1: - col[0] = 1.0-t; - col[1] = 1.0; - col[2] = 0.0; - break; - case 2: - col[0] = 0.0; - col[1] = 1.0; - col[2] = t; - break; - case 3: - col[0] = 0.0; - col[1] = 1.0-t; - col[2] = 1.0; - break; - case 4: - col[0] = t; - col[1] = 0.0; - col[2] = 1.0; - break; - case 5: - col[0] = 1.0; - col[1] = 0.0; - col[2] = 1.0-t; - break; + if (angle >= 0.0) + angle = fmod(angle,2.0*M_PI); + else + angle = fmod(angle,-2.0*M_PI); + s = floor(angle/(M_PI/3)); + t = angle/(M_PI/3)-s; + if (s >= 6) + s = 0; + switch (s) + { + case 0: + col[0] = 1.0; + col[1] = t; + col[2] = 0.0; + break; + case 1: + col[0] = 1.0-t; + col[1] = 1.0; + col[2] = 0.0; + break; + case 2: + col[0] = 0.0; + col[1] = 1.0; + col[2] = t; + break; + case 3: + col[0] = 0.0; + col[1] = 1.0-t; + col[2] = 1.0; + break; + case 4: + col[0] = t; + col[1] = 0.0; + col[2] = 1.0; + break; + case 5: + col[0] = 1.0; + col[1] = 0.0; + col[2] = 1.0-t; + break; + } + } + else /* kb->change_colors */ + { + if (kb->colors == COLORS_ONESIDED || kb->colors == COLORS_TWOSIDED) + { + col[0] = mat[0][2]; + col[1] = mat[1][2]; + col[2] = mat[2][2]; + } + else + { + ca = cos(angle); + sa = sin(angle); + col[0] = ca*mat[0][0]+sa*mat[0][1]; + col[1] = ca*mat[1][0]+sa*mat[1][1]; + col[2] = ca*mat[2][0]+sa*mat[2][1]; + } + m = 0.5f/fmaxf(fmaxf(fabsf(col[0]),fabsf(col[1])),fabsf(col[2])); + col[0] = m*col[0]+0.5f; + col[1] = m*col[1]+0.5f; + col[2] = m*col[2]+0.5f; } if (kb->display_mode == DISP_TRANSPARENT) col[3] = 0.7; @@ -573,10 +706,13 @@ static void setup_figure8(ModeInfo *mi, double umin, double umax, double vmin, k = i*(NUMV+1)+j; u = -ur*j/NUMU+umin; v = vr*i/NUMV+vmin; - if (kb->colors == COLORS_DEPTH) - color(kb,(cos(u)+1.0)*M_PI*2.0/3.0,kb->col[k]); - else - color(kb,v,kb->col[k]); + if (!kb->change_colors) + { + if (kb->colors == COLORS_DEPTH) + color(kb,(cos(u)+1.0)*M_PI*2.0/3.0,NULL,kb->col[k]); + else if (kb->colors == COLORS_RAINBOW) + color(kb,v,NULL,kb->col[k]); + } kb->tex[k][0] = -32*u/(2.0*M_PI); kb->tex[k][1] = 32*v/(2.0*M_PI); cu = cos(u); @@ -612,9 +748,9 @@ static void setup_figure8(ModeInfo *mi, double umin, double umax, double vmin, } -/* Set up the squeezed torus Klein bottle coordinates, colors, and texture. */ -static void setup_squeezed_torus(ModeInfo *mi, double umin, double umax, - double vmin, double vmax) +/* Set up the pinched torus Klein bottle coordinates, colors, and texture. */ +static void setup_pinched_torus(ModeInfo *mi, double umin, double umax, + double vmin, double vmax) { int i, j, k, l; double u, v, ur, vr; @@ -630,10 +766,13 @@ static void setup_squeezed_torus(ModeInfo *mi, double umin, double umax, k = i*(NUMV+1)+j; u = -ur*j/NUMU+umin; v = vr*i/NUMV+vmin; - if (kb->colors == COLORS_DEPTH) - color(kb,(sin(u)*sin(0.5*v)+1.0)*M_PI*2.0/3.0,kb->col[k]); - else - color(kb,v,kb->col[k]); + if (!kb->change_colors) + { + if (kb->colors == COLORS_DEPTH) + color(kb,(sin(u)*sin(0.5*v)+1.0)*M_PI*2.0/3.0,NULL,kb->col[k]); + else if (kb->colors == COLORS_RAINBOW) + color(kb,v,NULL,kb->col[k]); + } kb->tex[k][0] = -32*u/(2.0*M_PI); kb->tex[k][1] = 32*v/(2.0*M_PI); cu = cos(u); @@ -642,23 +781,23 @@ static void setup_squeezed_torus(ModeInfo *mi, double umin, double umax, sv = sin(v); cv2 = cos(0.5*v); sv2 = sin(0.5*v); - kb->x[k][0] = (SQUEEZED_TORUS_RADIUS+cu)*cv; - kb->x[k][1] = (SQUEEZED_TORUS_RADIUS+cu)*sv; + kb->x[k][0] = (PINCHED_TORUS_RADIUS+cu)*cv; + kb->x[k][1] = (PINCHED_TORUS_RADIUS+cu)*sv; kb->x[k][2] = su*cv2; kb->x[k][3] = su*sv2; kb->xu[k][0] = -su*cv; kb->xu[k][1] = -su*sv; kb->xu[k][2] = cu*cv2; kb->xu[k][3] = cu*sv2; - kb->xv[k][0] = -(SQUEEZED_TORUS_RADIUS+cu)*sv; - kb->xv[k][1] = (SQUEEZED_TORUS_RADIUS+cu)*cv; + kb->xv[k][0] = -(PINCHED_TORUS_RADIUS+cu)*sv; + kb->xv[k][1] = (PINCHED_TORUS_RADIUS+cu)*cv; kb->xv[k][2] = -0.5*su*sv2; kb->xv[k][3] = 0.5*su*cv2; for (l=0; l<4; l++) { - kb->x[k][l] /= SQUEEZED_TORUS_RADIUS+1.25; - kb->xu[k][l] /= SQUEEZED_TORUS_RADIUS+1.25; - kb->xv[k][l] /= SQUEEZED_TORUS_RADIUS+1.25; + kb->x[k][l] /= PINCHED_TORUS_RADIUS+1.25; + kb->xu[k][l] /= PINCHED_TORUS_RADIUS+1.25; + kb->xv[k][l] /= PINCHED_TORUS_RADIUS+1.25; } } } @@ -683,10 +822,13 @@ static void setup_lawson(ModeInfo *mi, double umin, double umax, double vmin, k = i*(NUMU+1)+j; u = -ur*j/NUMU+umin; v = vr*i/NUMV+vmin; - if (kb->colors == COLORS_DEPTH) - color(kb,(sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,kb->col[k]); - else - color(kb,v,kb->col[k]); + if (!kb->change_colors) + { + if (kb->colors == COLORS_DEPTH) + color(kb,(sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,NULL,kb->col[k]); + else if (kb->colors == COLORS_RAINBOW) + color(kb,v,NULL,kb->col[k]); + } kb->tex[k][0] = -32*u/(2.0*M_PI); kb->tex[k][1] = 32*v/(2.0*M_PI); cu = cos(u); @@ -717,19 +859,25 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin, double vmax) { int polys = 0; - static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; - static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; - static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; - static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; - float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4]; + static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; + static const GLfloat mat_diff_oneside[] = { 0.9, 0.4, 0.3, 1.0 }; + static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 }; + float mat_diff_dyn[4], mat_diff_dyn_compl[4]; + float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3]; int i, j, k, l, m, o; - double u, v; + double u, v, ur, vr; double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4]; double q, r, s, t; double cu, su, cv, sv, cv2, sv2, c2u, s2u; float q1[4], q2[4], r1[4][4], r2[4][4]; kleinstruct *kb = &klein[MI_SCREEN(mi)]; + if (kb->change_colors) + rotateall3d(kb->rho,kb->sigma,kb->tau,matc); + if (kb->view == VIEW_WALK || kb->view == VIEW_WALKTURN) { /* Compute the rotation that rotates the Klein bottle in 4D without the @@ -931,22 +1079,60 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin, } } - if (kb->colors == COLORS_TWOSIDED) + if (!kb->change_colors) { - glColor3fv(mat_diff_red); - if (kb->display_mode == DISP_TRANSPARENT) + if (kb->colors == COLORS_ONESIDED) { - glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); - glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + glColor3fv(mat_diff_oneside); + if (kb->display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, + mat_diff_trans_oneside); + } + else + { + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, + mat_diff_oneside); + } } - else + else if (kb->colors == COLORS_TWOSIDED) { - glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); - glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + glColor3fv(mat_diff_red); + if (kb->display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + } + else + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + } + } + } + else /* kb->change_colors */ + { + color(kb,0.0,matc,mat_diff_dyn); + if (kb->colors == COLORS_ONESIDED) + { + glColor3fv(mat_diff_dyn); + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn); + } + else if (kb->colors == COLORS_TWOSIDED) + { + mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0]; + mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1]; + mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2]; + mat_diff_dyn_compl[3] = mat_diff_dyn[3]; + glColor3fv(mat_diff_dyn); + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl); } } glBindTexture(GL_TEXTURE_2D,kb->tex_name); + ur = umax-umin; + vr = vmax-vmin; for (i=0; i<NUMU; i++) { if (kb->appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2)) @@ -964,7 +1150,20 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin, o = l*(NUMV+1)+m; glNormal3fv(kb->pn[o]); glTexCoord2fv(kb->tex[o]); - if (kb->colors != COLORS_TWOSIDED) + if (kb->change_colors) + { + if (kb->colors == COLORS_DEPTH) + { + u = -ur*m/NUMU+umin; + color(kb,(cos(u)+1.0)*M_PI*2.0/3.0,matc,kb->col[o]); + } + else if (kb->colors == COLORS_RAINBOW) + { + v = vr*l/NUMV+vmin; + color(kb,v,matc,kb->col[o]); + } + } + if (kb->colors != COLORS_ONESIDED && kb->colors != COLORS_TWOSIDED) { glColor3fv(kb->col[o]); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]); @@ -980,24 +1179,30 @@ static int figure8(ModeInfo *mi, double umin, double umax, double vmin, } -/* Draw a squeezed torus Klein bottle projected into 3D. */ -static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin, - double vmax) +/* Draw a pinched torus Klein bottle projected into 3D. */ +static int pinched_torus(ModeInfo *mi, double umin, double umax, double vmin, + double vmax) { int polys = 0; - static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; - static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; - static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; - static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; - float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4]; + static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; + static const GLfloat mat_diff_oneside[] = { 0.9, 0.4, 0.3, 1.0 }; + static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 }; + float mat_diff_dyn[4], mat_diff_dyn_compl[4]; + float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3]; int i, j, k, l, m, o; - double u, v; + double u, v, ur, vr; double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4]; double q, r, s, t; double cu, su, cv, sv, cv2, sv2; float q1[4], q2[4], r1[4][4], r2[4][4]; kleinstruct *kb = &klein[MI_SCREEN(mi)]; + if (kb->change_colors) + rotateall3d(kb->rho,kb->sigma,kb->tau,matc); + if (kb->view == VIEW_WALK || kb->view == VIEW_WALKTURN) { /* Compute the rotation that rotates the Klein bottle in 4D without the @@ -1012,23 +1217,23 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin, sv = sin(v); cv2 = cos(0.5*v); sv2 = sin(0.5*v); - xx[0] = (SQUEEZED_TORUS_RADIUS+cu)*cv; - xx[1] = (SQUEEZED_TORUS_RADIUS+cu)*sv; + xx[0] = (PINCHED_TORUS_RADIUS+cu)*cv; + xx[1] = (PINCHED_TORUS_RADIUS+cu)*sv; xx[2] = su*cv2; xx[3] = su*sv2; xxu[0] = -su*cv; xxu[1] = -su*sv; xxu[2] = cu*cv2; xxu[3] = cu*sv2; - xxv[0] = -(SQUEEZED_TORUS_RADIUS+cu)*sv; - xxv[1] = (SQUEEZED_TORUS_RADIUS+cu)*cv; + xxv[0] = -(PINCHED_TORUS_RADIUS+cu)*sv; + xxv[1] = (PINCHED_TORUS_RADIUS+cu)*cv; xxv[2] = -0.5*su*sv2; xxv[3] = 0.5*su*cv2; for (l=0; l<4; l++) { - xx[l] /= SQUEEZED_TORUS_RADIUS+1.25; - xxu[l] /= SQUEEZED_TORUS_RADIUS+1.25; - xxv[l] /= SQUEEZED_TORUS_RADIUS+1.25; + xx[l] /= PINCHED_TORUS_RADIUS+1.25; + xxu[l] /= PINCHED_TORUS_RADIUS+1.25; + xxv[l] /= PINCHED_TORUS_RADIUS+1.25; } for (l=0; l<4; l++) { @@ -1103,12 +1308,12 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin, sv = sin(v); cv2 = cos(0.5*v); sv2 = sin(0.5*v); - xx[0] = (SQUEEZED_TORUS_RADIUS+cu)*cv; - xx[1] = (SQUEEZED_TORUS_RADIUS+cu)*sv; + xx[0] = (PINCHED_TORUS_RADIUS+cu)*cv; + xx[1] = (PINCHED_TORUS_RADIUS+cu)*sv; xx[2] = su*cv2; xx[3] = su*sv2; for (l=0; l<4; l++) - xx[l] /= SQUEEZED_TORUS_RADIUS+1.25; + xx[l] /= PINCHED_TORUS_RADIUS+1.25; for (l=0; l<4; l++) { r = 0.0; @@ -1193,22 +1398,60 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin, } } - if (kb->colors == COLORS_TWOSIDED) + if (!kb->change_colors) { - glColor3fv(mat_diff_red); - if (kb->display_mode == DISP_TRANSPARENT) + if (kb->colors == COLORS_ONESIDED) { - glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); - glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + glColor3fv(mat_diff_oneside); + if (kb->display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, + mat_diff_trans_oneside); + } + else + { + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, + mat_diff_oneside); + } } - else + else if (kb->colors == COLORS_TWOSIDED) { - glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); - glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + glColor3fv(mat_diff_red); + if (kb->display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + } + else + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + } + } + } + else /* kb->change_colors */ + { + color(kb,0.0,matc,mat_diff_dyn); + if (kb->colors == COLORS_ONESIDED) + { + glColor3fv(mat_diff_dyn); + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn); + } + else if (kb->colors == COLORS_TWOSIDED) + { + mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0]; + mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1]; + mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2]; + mat_diff_dyn_compl[3] = mat_diff_dyn[3]; + glColor3fv(mat_diff_dyn); + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl); } } glBindTexture(GL_TEXTURE_2D,kb->tex_name); + ur = umax-umin; + vr = vmax-vmin; for (i=0; i<NUMU; i++) { if (kb->appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2)) @@ -1226,7 +1469,20 @@ static int squeezed_torus(ModeInfo *mi, double umin, double umax, double vmin, o = l*(NUMV+1)+m; glNormal3fv(kb->pn[o]); glTexCoord2fv(kb->tex[o]); - if (kb->colors != COLORS_TWOSIDED) + if (kb->change_colors) + { + v = vr*l/NUMV+vmin; + if (kb->colors == COLORS_DEPTH) + { + u = -ur*m/NUMU+umin; + color(kb,(sin(u)*sin(0.5*v)+1.0)*M_PI*2.0/3.0,matc,kb->col[o]); + } + else if (kb->colors == COLORS_RAINBOW) + { + color(kb,v,matc,kb->col[o]); + } + } + if (kb->colors != COLORS_ONESIDED && kb->colors != COLORS_TWOSIDED) { glColor3fv(kb->col[o]); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]); @@ -1247,19 +1503,25 @@ static int lawson(ModeInfo *mi, double umin, double umax, double vmin, double vmax) { int polys = 0; - static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; - static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; - static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; - static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; - float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4]; + static const GLfloat mat_diff_red[] = { 1.0, 0.0, 0.0, 1.0 }; + static const GLfloat mat_diff_green[] = { 0.0, 1.0, 0.0, 1.0 }; + static const GLfloat mat_diff_oneside[] = { 0.9, 0.4, 0.3, 1.0 }; + static const GLfloat mat_diff_trans_red[] = { 1.0, 0.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 }; + static const GLfloat mat_diff_trans_oneside[] = { 0.9, 0.4, 0.3, 0.7 }; + float mat_diff_dyn[4], mat_diff_dyn_compl[4]; + float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4], matc[3][3]; int i, j, k, l, m, o; - double u, v; + double u, v, ur, vr; double cu, su, cv, sv, cv2, sv2; double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4]; double q, r, s, t; float q1[4], q2[4], r1[4][4], r2[4][4]; kleinstruct *kb = &klein[MI_SCREEN(mi)]; + if (kb->change_colors) + rotateall3d(kb->rho,kb->sigma,kb->tau,matc); + if (kb->view == VIEW_WALK || kb->view == VIEW_WALKTURN) { /* Compute the rotation that rotates the Klein bottle in 4D without the @@ -1447,22 +1709,60 @@ static int lawson(ModeInfo *mi, double umin, double umax, double vmin, } } - if (kb->colors == COLORS_TWOSIDED) + if (!kb->change_colors) { - glColor3fv(mat_diff_red); - if (kb->display_mode == DISP_TRANSPARENT) + if (kb->colors == COLORS_ONESIDED) { - glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); - glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + glColor3fv(mat_diff_oneside); + if (kb->display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, + mat_diff_trans_oneside); + } + else + { + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, + mat_diff_oneside); + } } - else + else if (kb->colors == COLORS_TWOSIDED) + { + glColor3fv(mat_diff_red); + if (kb->display_mode == DISP_TRANSPARENT) + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green); + } + else + { + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + } + } + } + else /* kb->change_colors */ + { + color(kb,0.0,matc,mat_diff_dyn); + if (kb->colors == COLORS_ONESIDED) + { + glColor3fv(mat_diff_dyn); + glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn); + } + else if (kb->colors == COLORS_TWOSIDED) { - glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red); - glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green); + mat_diff_dyn_compl[0] = 1.0f-mat_diff_dyn[0]; + mat_diff_dyn_compl[1] = 1.0f-mat_diff_dyn[1]; + mat_diff_dyn_compl[2] = 1.0f-mat_diff_dyn[2]; + mat_diff_dyn_compl[3] = mat_diff_dyn[3]; + glColor3fv(mat_diff_dyn); + glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn); + glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_dyn_compl); } } glBindTexture(GL_TEXTURE_2D,kb->tex_name); + ur = umax-umin; + vr = vmax-vmin; for (i=0; i<NUMV; i++) { if (kb->appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2)) @@ -1480,7 +1780,20 @@ static int lawson(ModeInfo *mi, double umin, double umax, double vmin, o = l*(NUMU+1)+m; glNormal3fv(kb->pn[o]); glTexCoord2fv(kb->tex[o]); - if (kb->colors != COLORS_TWOSIDED) + if (kb->change_colors) + { + v = vr*l/NUMV+vmin; + if (kb->colors == COLORS_DEPTH) + { + u = -ur*m/NUMU+umin; + color(kb,(sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,matc,kb->col[o]); + } + else if (kb->colors == COLORS_RAINBOW) + { + color(kb,v,matc,kb->col[o]); + } + } + if (kb->colors != COLORS_ONESIDED && kb->colors != COLORS_TWOSIDED) { glColor3fv(kb->col[o]); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]); @@ -1509,7 +1822,7 @@ static void gen_texture(ModeInfo *mi) glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); - glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_DIMENSION,TEX_DIMENSION,0, + glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0, GL_LUMINANCE,GL_UNSIGNED_BYTE,texture); } @@ -1540,7 +1853,7 @@ static void init(ModeInfo *mi) } kb->zeta = 0.0; if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8 || - kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS) + kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS) kb->eta = 0.0; else kb->eta = 45.0; @@ -1551,6 +1864,10 @@ static void init(ModeInfo *mi) kb->dvmove = 0.0; kb->side = 1; + kb->rho = frand(360.0); + kb->sigma = frand(360.0); + kb->tau = frand(360.0); + if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8) { kb->offset4d[0] = 0.0; @@ -1565,7 +1882,7 @@ static void init(ModeInfo *mi) kb->offset3d[2] = -1.9; kb->offset3d[3] = 0.0; } - else if (kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS) + else if (kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS) { kb->offset4d[0] = 0.0; kb->offset4d[1] = 0.0; @@ -1598,8 +1915,8 @@ static void init(ModeInfo *mi) gen_texture(mi); if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8) setup_figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); - else if (kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS) - setup_squeezed_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); + else if (kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS) + setup_pinched_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); else /* kb->bottle_type == KLEIN_BOTTLE_LAWSON */ setup_lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); @@ -1736,6 +2053,18 @@ static void display_klein(ModeInfo *mi) if (kb->umove < 0.0) kb->umove += 2.0*M_PI; } + if (kb->change_colors) + { + kb->rho += DRHO; + if (kb->rho >= 360.0) + kb->rho -= 360.0; + kb->sigma += DSIGMA; + if (kb->sigma >= 360.0) + kb->sigma -= 360.0; + kb->tau += DTAU; + if (kb->tau >= 360.0) + kb->tau -= 360.0; + } } glMatrixMode(GL_PROJECTION); @@ -1760,8 +2089,8 @@ static void display_klein(ModeInfo *mi) if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8) mi->polygon_count = figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); - else if (kb->bottle_type == KLEIN_BOTTLE_SQUEEZED_TORUS) - mi->polygon_count = squeezed_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); + else if (kb->bottle_type == KLEIN_BOTTLE_PINCHED_TORUS) + mi->polygon_count = pinched_torus(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); else /* kb->bottle_type == KLEIN_BOTTLE_LAWSON */ mi->polygon_count = lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI); } @@ -1874,9 +2203,9 @@ ENTRYPOINT void init_klein(ModeInfo *mi) { kb->bottle_type = KLEIN_BOTTLE_FIGURE_8; } - else if (!strcasecmp(klein_bottle,"squeezed-torus")) + else if (!strcasecmp(klein_bottle,"pinched-torus")) { - kb->bottle_type = KLEIN_BOTTLE_SQUEEZED_TORUS; + kb->bottle_type = KLEIN_BOTTLE_PINCHED_TORUS; } else if (!strcasecmp(klein_bottle,"lawson")) { @@ -1936,6 +2265,10 @@ ENTRYPOINT void init_klein(ModeInfo *mi) { kb->colors = random() % NUM_COLORS; } + else if (!strcasecmp(color_mode,"one-sided")) + { + kb->colors = COLORS_ONESIDED; + } else if (!strcasecmp(color_mode,"two-sided")) { kb->colors = COLORS_TWOSIDED; @@ -1953,6 +2286,8 @@ ENTRYPOINT void init_klein(ModeInfo *mi) kb->colors = random() % NUM_COLORS; } + kb->change_colors = change_colors; + /* Set the view mode. */ if (!strcasecmp(view_mode,"random")) { |