X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fglsnake.c;h=bc9c631399f9057f23d1ced0014bd7299b66ddce;hp=66c125551948e771a6bce7891ecc6e44d5eab0ef;hb=3f9592851ce4ed76a9979bfdd6ec7dc5c457e183;hpb=cccbddbc4140cf9a06d7d95cc5c0ca36eb5d6e28 diff --git a/hacks/glx/glsnake.c b/hacks/glx/glsnake.c index 66c12555..bc9c6313 100644 --- a/hacks/glx/glsnake.c +++ b/hacks/glx/glsnake.c @@ -38,7 +38,8 @@ extern XtAppContext app; #define DEF_YSPIN "0.10" #define DEF_ZSPIN "0.14" #define DEF_SCARYCOLOUR "False" -#define DEF_LABELS "True" +#define DEF_LABELS "True" +#define DEF_BBOX "False" #define DEFAULTS "*delay: 30000 \n" \ "*count: 30 \n" \ @@ -54,6 +55,7 @@ extern XtAppContext app; "*scarycolour:" DEF_SCARYCOLOUR " \n" \ "*labels: " DEF_LABELS " \n" \ "*labelfont: -*-times-bold-r-normal-*-180-*\n" \ + "*bbox: " DEF_BBOX "\n" \ @@ -81,42 +83,42 @@ extern XtAppContext app; #define RIGHT 3 typedef struct model_s { - char * name; - float node[24]; + char * name; + float node[24]; } model_t; typedef struct nodeang_s { - float cur_angle; - float dest_angle; + float cur_angle; + float dest_angle; } nodeang_t; typedef struct { - GLXContext * glx_context; - - int node_list; /* name of the display list */ - int is_cyclic; - int is_legal; - int last_turn; - int selected; - struct timeval last_iteration; - struct timeval last_morph; - int morphing; - nodeang_t node[24]; - GLfloat roty; - GLfloat rotz; - int paused; - int dragging; - int m_count; - int m; - int cur_model; - int interactive; - GLfloat colour_t[3]; - GLfloat colour_i[3]; - GLfloat colour[3]; - model_t * models; - - XFontStruct * font; - GLuint font_list; + GLXContext * glx_context; + + int node_list; /* name of the display list */ + int is_cyclic; + int is_legal; + int last_turn; + int selected; + struct timeval last_iteration; + struct timeval last_morph; + int morphing; + nodeang_t node[24]; + GLfloat roty; + GLfloat rotz; + int paused; + int dragging; + int m_count; + int m; + int cur_model; + int interactive; + GLfloat colour_t[3]; + GLfloat colour_i[3]; + GLfloat colour[3]; + model_t * models; + + XFontStruct * font; + GLuint font_list; } glsnake_configuration; static glsnake_configuration *glc = NULL; @@ -130,6 +132,7 @@ static GLfloat yspin; static GLfloat zspin; static Bool scarycolour; static Bool labels; +static Bool do_bbox; static XrmOptionDescRec opts[] = { { "-speed", ".speed", XrmoptionSepArg, 0 }, @@ -143,6 +146,10 @@ static XrmOptionDescRec opts[] = { { "+scarycolour", ".scarycolour", XrmoptionNoArg, "False" }, { "-labels", ".labels", XrmoptionNoArg, "True" }, { "+labels", ".labels", XrmoptionNoArg, "False" }, +#if 0 + { "-bbox", ".bbox", XrmoptionNoArg, "True" }, + { "+bbox", ".bbox", XrmoptionNoArg, "False" }, +#endif }; static argtype vars[] = { @@ -156,6 +163,7 @@ static argtype vars[] = { /* {(caddr_t *) &interactive, "interactive", "Interactive", DEF_INTERACTIVE, t_Bool}, */ {(caddr_t *) &scarycolour, "scarycolour", "Scary Colour", DEF_SCARYCOLOUR, t_Bool}, {(caddr_t *) &labels, "labels", "Labels", DEF_LABELS, t_Bool}, + {(caddr_t *) &do_bbox, "bbox", "BBox", DEF_BBOX, t_Bool}, }; ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL}; @@ -163,76 +171,76 @@ ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL}; /* prism models */ #define VOFFSET 0.045 float solid_prism_v[][3] = { - /* first corner, bottom left front */ - { VOFFSET, VOFFSET, 1.0 }, - { VOFFSET, 0.0, 1.0 - VOFFSET }, - { 0.0, VOFFSET, 1.0 - VOFFSET }, - /* second corner, rear */ - { VOFFSET, VOFFSET, 0.00 }, - { VOFFSET, 0.0, VOFFSET }, - { 0.0, VOFFSET, VOFFSET }, - /* third, right front */ - { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 }, - { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET }, - { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET }, - /* fourth, right rear */ - { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 }, - { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET }, - { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET }, - /* fifth, upper front */ - { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 }, - { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET }, - { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET}, - /* sixth, upper rear */ - { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 }, - { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET }, - { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET } + /* first corner, bottom left front */ + { VOFFSET, VOFFSET, 1.0 }, + { VOFFSET, 0.0, 1.0 - VOFFSET }, + { 0.0, VOFFSET, 1.0 - VOFFSET }, + /* second corner, rear */ + { VOFFSET, VOFFSET, 0.00 }, + { VOFFSET, 0.0, VOFFSET }, + { 0.0, VOFFSET, VOFFSET }, + /* third, right front */ + { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 1.0 }, + { 1.0 - VOFFSET / M_SQRT1_2, 0.0, 1.0 - VOFFSET }, + { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, 1.0 - VOFFSET }, + /* fourth, right rear */ + { 1.0 - VOFFSET / M_SQRT1_2, VOFFSET, 0.0 }, + { 1.0 - VOFFSET / M_SQRT1_2, 0.0, VOFFSET }, + { 1.0 - VOFFSET * M_SQRT1_2, VOFFSET, VOFFSET }, + /* fifth, upper front */ + { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 1.0 }, + { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, 1.0 - VOFFSET }, + { 0.0, 1.0 - VOFFSET / M_SQRT1_2, 1.0 - VOFFSET}, + /* sixth, upper rear */ + { VOFFSET, 1.0 - VOFFSET / M_SQRT1_2, 0.0 }, + { VOFFSET / M_SQRT1_2, 1.0 - VOFFSET * M_SQRT1_2, VOFFSET }, + { 0.0, 1.0 - VOFFSET / M_SQRT1_2, VOFFSET } }; /* normals */ float solid_prism_n[][3] = { - /* corners */ - { -VOFFSET, -VOFFSET, VOFFSET }, - { VOFFSET, -VOFFSET, VOFFSET }, - { -VOFFSET, VOFFSET, VOFFSET }, - { -VOFFSET, -VOFFSET, -VOFFSET }, - { VOFFSET, -VOFFSET, -VOFFSET }, - { -VOFFSET, VOFFSET, -VOFFSET }, - /* edges */ - { -VOFFSET, 0.0, VOFFSET }, - { 0.0, -VOFFSET, VOFFSET }, - { VOFFSET, VOFFSET, VOFFSET }, - { -VOFFSET, 0.0, -VOFFSET }, - { 0.0, -VOFFSET, -VOFFSET }, - { VOFFSET, VOFFSET, -VOFFSET }, - { -VOFFSET, -VOFFSET, 0.0 }, - { VOFFSET, -VOFFSET, 0.0 }, - { -VOFFSET, VOFFSET, 0.0 }, - /* faces */ - { 0.0, 0.0, 1.0 }, - { 0.0, -1.0, 0.0 }, - { M_SQRT1_2, M_SQRT1_2, 0.0 }, - { -1.0, 0.0, 0.0 }, - { 0.0, 0.0, -1.0 } + /* corners */ + { -VOFFSET, -VOFFSET, VOFFSET }, + { VOFFSET, -VOFFSET, VOFFSET }, + { -VOFFSET, VOFFSET, VOFFSET }, + { -VOFFSET, -VOFFSET, -VOFFSET }, + { VOFFSET, -VOFFSET, -VOFFSET }, + { -VOFFSET, VOFFSET, -VOFFSET }, + /* edges */ + { -VOFFSET, 0.0, VOFFSET }, + { 0.0, -VOFFSET, VOFFSET }, + { VOFFSET, VOFFSET, VOFFSET }, + { -VOFFSET, 0.0, -VOFFSET }, + { 0.0, -VOFFSET, -VOFFSET }, + { VOFFSET, VOFFSET, -VOFFSET }, + { -VOFFSET, -VOFFSET, 0.0 }, + { VOFFSET, -VOFFSET, 0.0 }, + { -VOFFSET, VOFFSET, 0.0 }, + /* faces */ + { 0.0, 0.0, 1.0 }, + { 0.0, -1.0, 0.0 }, + { M_SQRT1_2, M_SQRT1_2, 0.0 }, + { -1.0, 0.0, 0.0 }, + { 0.0, 0.0, -1.0 } }; /* vertices */ float wire_prism_v[][3] = { - { 0.0, 0.0, 1.0 }, - { 1.0, 0.0, 1.0 }, - { 0.0, 1.0, 1.0 }, - { 0.0, 0.0, 0.0 }, - { 1.0, 0.0, 0.0 }, - { 0.0, 1.0, 0.0 } + { 0.0, 0.0, 1.0 }, + { 1.0, 0.0, 1.0 }, + { 0.0, 1.0, 1.0 }, + { 0.0, 0.0, 0.0 }, + { 1.0, 0.0, 0.0 }, + { 0.0, 1.0, 0.0 } }; /* normals */ float wire_prism_n[][3] = { - { 0.0, 0.0, 1.0}, - { 0.0,-1.0, 0.0}, - { M_SQRT1_2, M_SQRT1_2, 0.0}, - {-1.0, 0.0, 0.0}, - { 0.0, 0.0,-1.0} + { 0.0, 0.0, 1.0}, + { 0.0,-1.0, 0.0}, + { M_SQRT1_2, M_SQRT1_2, 0.0}, + {-1.0, 0.0, 0.0}, + { 0.0, 0.0,-1.0} }; /* default models */ @@ -242,40 +250,41 @@ float wire_prism_n[][3] = { #define R 270.0 static model_t default_models[] = { - { "Ball", - { R, R, L, L, R, L, R, R, L, R, L, L, R, R, L, L, R, L, R, R, L, R, L } - }, - { "Snow", - { R, R, R, R, L, L, L, L, R, R, R, R, L, L, L, L, R, R, R, R, L, L, L } - }, - { "Propellor", - { Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z } - }, - { "Flamingo", - { Z, P, Z, Z, Z, Z, Z, P, R, R, P, R, L, P, L, R, P, R, R, Z, Z, Z, P } - }, - { "Cat", - { Z, P, P, Z, P, P, Z, L, Z, P, P, Z, P, P, Z, P, P, Z, Z, Z, Z, Z, Z } - }, - { "Rooster", - { Z, Z, P, P, Z, L, Z, L, R, P, R, Z, P, P, Z, R, P, R, L, Z, L, Z, P } - } + { "Ball", + { R, R, L, L, R, L, R, R, L, R, L, L, R, R, L, L, R, L, R, R, L, R, L } + }, + { "Snow", + { R, R, R, R, L, L, L, L, R, R, R, R, L, L, L, L, R, R, R, R, L, L, L } + }, + { "Propellor", + { Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z, L, Z, Z, Z, R, L, R, Z } + }, + { "Flamingo", + { Z, P, Z, Z, Z, Z, Z, P, R, R, P, R, L, P, L, R, P, R, R, Z, Z, Z, P } + }, + { "Cat", + { Z, P, P, Z, P, P, Z, L, Z, P, P, Z, P, P, Z, P, P, Z, Z, Z, Z, Z, Z } + }, + { "Rooster", + { Z, Z, P, P, Z, L, Z, L, R, P, R, Z, P, P, Z, R, P, R, L, Z, L, Z, P } + } }; /* add a model to the model list */ -model_t * add_model(model_t * models, char * name, int * rotations, int * count) { - int i; - - (*count)++; - models = realloc(models, sizeof(model_t) * (*count)); - models[(*count)-1].name = strdup(name); +model_t * add_model(model_t * models, char * name, int * rotations, int * count) +{ + int i; + + (*count)++; + models = realloc(models, sizeof(model_t) * (*count)); + models[(*count)-1].name = strdup(name); #ifdef DEBUG - fprintf(stderr, "resized models to %d bytes for model %s\n", sizeof(model_t) * (*count), models[(*count)-1].name); + fprintf(stderr, "resized models to %d bytes for model %s\n", sizeof(model_t) * (*count), models[(*count)-1].name); #endif - for (i = 0; i < 24; i++) { - models[(*count)-1].node[i] = rotations[i] * 90.0; - } - return models; + for (i = 0; i < 24; i++) { + models[(*count)-1].node[i] = rotations[i] * 90.0; + } + return models; } /* filename is the name of the file to load @@ -283,129 +292,131 @@ model_t * add_model(model_t * models, char * name, int * rotations, int * count) * returns a new pointer to models * count is number of models read */ -model_t * load_modelfile(char * filename, model_t * models, int * count) { - int c; - FILE * f; - char buffy[256]; - int rotations[24]; - int name = 1; - int rots = 0; - - f = fopen(filename, "r"); - if (f == NULL) { - int error_msg_len = strlen(filename) + 33 + 1; - char * error_msg = (char *) malloc(sizeof(char) * error_msg_len); - sprintf(error_msg, "Unable to open model data file \"%s\"", filename); - perror(error_msg); - free(error_msg); - return models; - } - - while ((c = getc(f)) != EOF) { - switch (c) { - /* ignore comments */ - case '#': - while (c != '\n') - c = getc(f); - break; - case ':': - buffy[name-1] = '\0'; - name = 0; - break; - case '\n': - if (rots > 0) { +model_t * load_modelfile(char * filename, model_t * models, int * count) +{ + int c; + FILE * f; + char buffy[256]; + int rotations[24]; + int name = 1; + int rots = 0; + + f = fopen(filename, "r"); + if (f == NULL) { + int error_msg_len = strlen(filename) + 33 + 1; + char * error_msg = (char *) malloc(sizeof(char) * error_msg_len); + sprintf(error_msg, "Unable to open model data file \"%s\"", filename); + perror(error_msg); + free(error_msg); + return models; + } + + while ((c = getc(f)) != EOF) { + switch (c) { + /* ignore comments */ + case '#': + while (c != '\n') + c = getc(f); + break; + case ':': + buffy[name-1] = '\0'; + name = 0; + break; + case '\n': + if (rots > 0) { #ifdef DEBUG - /* print out the model we just read in */ - int i; - printf("%s: ", buffy); - for (i = 0; i < rots; i++) { - switch (rotations[i]) { - case LEFT: - printf("L"); - break; - case RIGHT: - printf("R"); - break; - case PIN: - printf("P"); - break; - case ZERO: - printf("Z"); - break; - } - } - printf("\n"); + /* print out the model we just read in */ + int i; + printf("%s: ", buffy); + for (i = 0; i < rots; i++) { + switch (rotations[i]) { + case LEFT: + printf("L"); + break; + case RIGHT: + printf("R"); + break; + case PIN: + printf("P"); + break; + case ZERO: + printf("Z"); + break; + } + } + printf("\n"); #endif - models = add_model(models, buffy, rotations, count); - } - name = 1; - rots = 0; - break; - default: - if (name) { - buffy[name-1] = c; - name++; - if (name > 255) - fprintf(stderr, "buffy overflow warning\n"); - } else { - switch (c) { - case '0': - case 'Z': - rotations[rots] = ZERO; - rots++; - break; - case '1': - case 'L': - rotations[rots] = LEFT; - rots++; - break; - case '2': - case 'P': - rotations[rots] = PIN; - rots++; - break; - case '3': - case 'R': - rotations[rots] = RIGHT; - rots++; - break; - default: - break; - } - } - break; - } - } - return models; + models = add_model(models, buffy, rotations, count); + } + name = 1; + rots = 0; + break; + default: + if (name) { + buffy[name-1] = c; + name++; + if (name > 255) + fprintf(stderr, "buffy overflow warning\n"); + } else { + switch (c) { + case '0': + case 'Z': + rotations[rots] = ZERO; + rots++; + break; + case '1': + case 'L': + rotations[rots] = LEFT; + rots++; + break; + case '2': + case 'P': + rotations[rots] = PIN; + rots++; + break; + case '3': + case 'R': + rotations[rots] = RIGHT; + rots++; + break; + default: + break; + } + } + break; + } + } + return models; } -model_t * load_models(char * dirpath, model_t * models, int * count) { - char name[1024]; - struct dirent * dp; - DIR * dfd; - - if ((dfd = opendir(dirpath)) == NULL) { - if (strstr(dirpath, "data") == NULL) -/* fprintf(stderr, "load_models: can't read %s/\n", dirpath); */ - return models; - } - while ((dp = readdir(dfd)) != NULL) { - if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) - continue; - if (strlen(dirpath) + strlen(dp->d_name) + 2 > sizeof(name)) - fprintf(stderr, "load_models: name %s/%s too long\n", dirpath, dp->d_name); - else { - sprintf(name, "%s/%s", dirpath, dp->d_name); - if (strcmp(&name[(int) strlen(name) - 7], "glsnake") == 0) { +model_t * load_models(char * dirpath, model_t * models, int * count) +{ + char name[1024]; + struct dirent * dp; + DIR * dfd; + + if ((dfd = opendir(dirpath)) == NULL) { + if (strstr(dirpath, "data") == NULL) +/* fprintf(stderr, "load_models: can't read %s/\n", dirpath); */ + return models; + } + while ((dp = readdir(dfd)) != NULL) { + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) + continue; + if (strlen(dirpath) + strlen(dp->d_name) + 2 > sizeof(name)) + fprintf(stderr, "load_models: name %s/%s too long\n", dirpath, dp->d_name); + else { + sprintf(name, "%s/%s", dirpath, dp->d_name); + if (strcmp(&name[(int) strlen(name) - 7], "glsnake") == 0) { #ifdef DEBUG - fprintf(stderr, "load_models: opening %s\n", name); + fprintf(stderr, "load_models: opening %s\n", name); #endif - models = load_modelfile(name, models, count); - } - } - } - closedir(dfd); - return models; + models = load_modelfile(name, models, count); + } + } + } + closedir(dfd); + return models; } /* snake metrics */ @@ -414,284 +425,293 @@ model_t * load_models(char * dirpath, model_t * models, int * count) { #define Z_MASK 4 #define GETSCALAR(vec,mask) ((vec)==(mask) ? 1 : ((vec)==-(mask) ? -1 : 0 )) -int cross_product(int src_dir, int dest_dir) { - return X_MASK * (GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, Z_MASK) - - GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, Y_MASK)) + - Y_MASK * (GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, X_MASK) - - GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Z_MASK)) + - Z_MASK * (GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Y_MASK) - - GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, X_MASK)); +int cross_product(int src_dir, int dest_dir) +{ + return X_MASK * (GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, Z_MASK) - + GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, Y_MASK)) + + Y_MASK * (GETSCALAR(src_dir, Z_MASK) * GETSCALAR(dest_dir, X_MASK) - + GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Z_MASK)) + + Z_MASK * (GETSCALAR(src_dir, X_MASK) * GETSCALAR(dest_dir, Y_MASK) - + GETSCALAR(src_dir, Y_MASK) * GETSCALAR(dest_dir, X_MASK)); } -void calc_snake_metrics(glsnake_configuration * bp) { - int src_dir, dest_dir; - int i, x, y, z; - int prev_src_dir = -Y_MASK; - int prev_dest_dir = Z_MASK; - int grid[25][25][25]; - - /* zero the grid */ - memset(&grid, 0, sizeof(int) * 25*25*25); - - bp->is_legal = 1; - x = y = z = 12; - - /* trace path of snake and keep record for is_legal */ - for (i = 0; i < 23; i++) { - /* establish new state variables */ - src_dir = -prev_dest_dir; - x += GETSCALAR(prev_dest_dir, X_MASK); - y += GETSCALAR(prev_dest_dir, Y_MASK); - z += GETSCALAR(prev_dest_dir, Z_MASK); - - switch ((int) bp->node[i].dest_angle) { - case (int) (ZERO * 90.0): - dest_dir = -prev_src_dir; - break; - case (int) (PIN * 90.0): - dest_dir = prev_src_dir; - break; - case (int) (RIGHT * 90.): - case (int) (LEFT * 90.0): - dest_dir = cross_product(prev_src_dir, prev_dest_dir); - if (bp->node[i].dest_angle == (int) (RIGHT * 90.0)) - dest_dir = -dest_dir; - break; - default: - /* prevent spurious "might be used uninitialised" warnings */ - dest_dir = 0; - break; - } - - if (grid[x][y][z] == 0) - grid[x][y][z] = src_dir + dest_dir; - else if (grid[x][y][z] + src_dir + dest_dir == 0) - grid[x][y][z] = 8; - else - bp->is_legal = 0; - - prev_src_dir = src_dir; - prev_dest_dir = dest_dir; - } - - /* determine if the snake is cyclic */ - bp->is_cyclic = (dest_dir == Y_MASK && x == 12 && y == 11 && x == 12); - - /* determine last turn */ - bp->last_turn = -1; - if (bp->is_cyclic) { - switch (src_dir) { - case -Z_MASK: - bp->last_turn = ZERO * 90.0; - break; - case Z_MASK: - bp->last_turn = PIN * 90.0; - break; - case X_MASK: - bp->last_turn = LEFT * 90.0; - break; - case -X_MASK: - bp->last_turn = RIGHT * 90.0; - break; - } - } +void calc_snake_metrics(glsnake_configuration * bp) +{ + int src_dir, dest_dir; + int i, x, y, z; + int prev_src_dir = -Y_MASK; + int prev_dest_dir = Z_MASK; + int grid[25][25][25]; + + /* zero the grid */ + memset(&grid, 0, sizeof(int) * 25*25*25); + + bp->is_legal = 1; + x = y = z = 12; + + /* trace path of snake and keep record for is_legal */ + for (i = 0; i < 23; i++) { + /* establish new state variables */ + src_dir = -prev_dest_dir; + x += GETSCALAR(prev_dest_dir, X_MASK); + y += GETSCALAR(prev_dest_dir, Y_MASK); + z += GETSCALAR(prev_dest_dir, Z_MASK); + + switch ((int) bp->node[i].dest_angle) { + case (int) (ZERO * 90.0): + dest_dir = -prev_src_dir; + break; + case (int) (PIN * 90.0): + dest_dir = prev_src_dir; + break; + case (int) (RIGHT * 90.): + case (int) (LEFT * 90.0): + dest_dir = cross_product(prev_src_dir, prev_dest_dir); + if (bp->node[i].dest_angle == (int) (RIGHT * 90.0)) + dest_dir = -dest_dir; + break; + default: + /* prevent spurious "might be used uninitialised" warnings */ + dest_dir = 0; + break; + } + + if (grid[x][y][z] == 0) + grid[x][y][z] = src_dir + dest_dir; + else if (grid[x][y][z] + src_dir + dest_dir == 0) + grid[x][y][z] = 8; + else + bp->is_legal = 0; + + prev_src_dir = src_dir; + prev_dest_dir = dest_dir; + } + + /* determine if the snake is cyclic */ + bp->is_cyclic = (dest_dir == Y_MASK && x == 12 && y == 11 && x == 12); + + /* determine last turn */ + bp->last_turn = -1; + if (bp->is_cyclic) { + switch (src_dir) { + case -Z_MASK: + bp->last_turn = ZERO * 90.0; + break; + case Z_MASK: + bp->last_turn = PIN * 90.0; + break; + case X_MASK: + bp->last_turn = LEFT * 90.0; + break; + case -X_MASK: + bp->last_turn = RIGHT * 90.0; + break; + } + } } -void set_colours(glsnake_configuration * bp, int immediate) { - /* set target colour */ - if (!bp->is_legal) { - bp->colour_t[0] = 0.5; - bp->colour_t[1] = 0.5; - bp->colour_t[2] = 0.5; - } else if (bp->is_cyclic) { - bp->colour_t[0] = 0.4; - bp->colour_t[1] = 0.8; - bp->colour_t[2] = 0.2; - } else { - bp->colour_t[0] = 0.3; - bp->colour_t[1] = 0.1; - bp->colour_t[2] = 0.9; - } - if (immediate) { - bp->colour_i[0] = bp->colour_t[0] - bp->colour[0]; - bp->colour_i[1] = bp->colour_t[1] - bp->colour[1]; - bp->colour_i[2] = bp->colour_t[2] - bp->colour[2]; - } else { - /* instead of 50.0, I should actually work out how many times this gets - * called during a morph */ - bp->colour_i[0] = (bp->colour_t[0] - bp->colour[0]) / 50.0; - bp->colour_i[1] = (bp->colour_t[1] - bp->colour[1]) / 50.0; - bp->colour_i[2] = (bp->colour_t[2] - bp->colour[2]) / 50.0; - } +void set_colours(glsnake_configuration * bp, int immediate) +{ + /* set target colour */ + if (!bp->is_legal) { + bp->colour_t[0] = 0.5; + bp->colour_t[1] = 0.5; + bp->colour_t[2] = 0.5; + } else if (bp->is_cyclic) { + bp->colour_t[0] = 0.4; + bp->colour_t[1] = 0.8; + bp->colour_t[2] = 0.2; + } else { + bp->colour_t[0] = 0.3; + bp->colour_t[1] = 0.1; + bp->colour_t[2] = 0.9; + } + if (immediate) { + bp->colour_i[0] = bp->colour_t[0] - bp->colour[0]; + bp->colour_i[1] = bp->colour_t[1] - bp->colour[1]; + bp->colour_i[2] = bp->colour_t[2] - bp->colour[2]; + } else { + /* instead of 50.0, I should actually work out how many times this gets + * called during a morph */ + bp->colour_i[0] = (bp->colour_t[0] - bp->colour[0]) / 50.0; + bp->colour_i[1] = (bp->colour_t[1] - bp->colour[1]) / 50.0; + bp->colour_i[2] = (bp->colour_t[2] - bp->colour[2]) / 50.0; + } } -void start_morph(int model_index, int immediate, glsnake_configuration * bp) { - int i; - - for (i = 0; i < 23; i++) { - bp->node[i].dest_angle = bp->models[model_index].node[i]; - if (immediate) - bp->node[i].cur_angle = bp->models[model_index].node[i]; - } - - calc_snake_metrics(bp); - set_colours(bp, 0); - bp->cur_model = model_index; - bp->morphing = 1; +void start_morph(int model_index, int immediate, glsnake_configuration * bp) +{ + int i; + + for (i = 0; i < 23; i++) { + bp->node[i].dest_angle = bp->models[model_index].node[i]; + if (immediate) + bp->node[i].cur_angle = bp->models[model_index].node[i]; + } + + calc_snake_metrics(bp); + set_colours(bp, 0); + bp->cur_model = model_index; + bp->morphing = 1; } /* convex hull */ /* model labels */ -void draw_label(ModeInfo * mi) { - glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; - - 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); - { - char * s; - int i, /* w, */ l; - - if (bp->interactive) - s = "interactive"; - else - s = bp->models[bp->cur_model].name; - - l = strlen(s); - /* - w = 0; - for (i = 0; i < l; i++) { - w += (bp->font->per_char - ? bp->font->per_char[((int)s[i]) - bp->font->min_char_or_byte2].rbearing - : bp->font->min_bounds.rbearing); - } - */ - - glRasterPos2f(10, mi->xgwa.height - 10 - (bp->font->ascent + bp->font->descent)); - /* mi->xgwa.width - w, bp->font->descent + bp->font->ascent); */ - - /* fprintf(stderr, "afaf.width = %d, w = %d\n", mi->xgwa.width, w); */ - - for (i = 0; i < l; i++) - glCallList(bp->font_list + (int)s[i]); - } - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); +void draw_label(ModeInfo * mi) +{ + glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; + + 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); + { + char * s; + int i, /* w, */ l; + + if (bp->interactive) + s = "interactive"; + else + s = bp->models[bp->cur_model].name; + + l = strlen(s); + /* + w = 0; + for (i = 0; i < l; i++) { + w += (bp->font->per_char + ? bp->font->per_char[((int)s[i]) - bp->font->min_char_or_byte2].rbearing + : bp->font->min_bounds.rbearing); + } + */ + + glRasterPos2f(10, mi->xgwa.height - 10 - (bp->font->ascent + bp->font->descent)); + /* mi->xgwa.width - w, bp->font->descent + bp->font->ascent); */ + + /* fprintf(stderr, "afaf.width = %d, w = %d\n", mi->xgwa.width, w); */ + + for (i = 0; i < l; i++) + glCallList(bp->font_list + (int)s[i]); + } + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glPopAttrib(); } /* load the fonts -- this function borrowed from molecule.c */ -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 = "-*-helvetica-medium-r-*-*-*-120-*"; - - 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 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 = "-*-helvetica-medium-r-*-*-*-120-*"; + + 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; } /* window management */ -void glsnake_reshape(ModeInfo *mi, int w, int h) { - glViewport (0, 0, (GLint) w, (GLint) h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(25.0, w/(GLfloat)h, 1.0, 100.0 ); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); +void glsnake_reshape(ModeInfo *mi, int w, int h) +{ + glViewport (0, 0, (GLint) w, (GLint) h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(25.0, w/(GLfloat)h, 1.0, 100.0 ); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); } -static void gl_init(ModeInfo *mi) { - /* glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; */ - int wire = MI_IS_WIREFRAME(mi); - float light_pos[][3] = {{0.0,0.0,20.0},{0.0,20.0,0.0}}; - float light_dir[][3] = {{0.0,0.0,-20.0},{0.0,-20.0,0.0}}; - - glClearColor(0.0, 0.0, 0.0, 0.0); - glEnable(GL_DEPTH_TEST); - glShadeModel(GL_SMOOTH); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - glEnable(GL_NORMALIZE); - - if (!wire) { - glColor3f(1.0, 1.0, 1.0); - glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]); - glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]); - glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]); - glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_LIGHT1); - glEnable(GL_COLOR_MATERIAL); - } +static void gl_init(ModeInfo *mi) +{ + /* glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; */ + int wire = MI_IS_WIREFRAME(mi); + float light_pos[][3] = {{0.0,0.0,20.0},{0.0,20.0,0.0}}; + float light_dir[][3] = {{0.0,0.0,-20.0},{0.0,-20.0,0.0}}; + + glClearColor(0.0, 0.0, 0.0, 0.0); + glEnable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + + if (!wire) { + glColor3f(1.0, 1.0, 1.0); + glLightfv(GL_LIGHT0, GL_POSITION, light_pos[0]); + glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir[0]); + glLightfv(GL_LIGHT1, GL_POSITION, light_pos[1]); + glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light_dir[1]); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_COLOR_MATERIAL); + } } /* lifted from lament.c */ #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) #define RANDSIGN() ((random() & 1) ? 1 : -1) -void glsnake_init(ModeInfo *mi) { - glsnake_configuration * bp; - int wire = MI_IS_WIREFRAME(mi); - - if (!glc) { - glc = (glsnake_configuration *) calloc(MI_NUM_SCREENS(mi), sizeof(glsnake_configuration)); - if (!glc) { - fprintf(stderr, "%s: out of memory\n", progname); - exit(1); - } - bp = &glc[MI_SCREEN(mi)]; - } - - bp = &glc[MI_SCREEN(mi)]; - - if ((bp->glx_context = init_GL(mi)) != NULL) { - gl_init(mi); - glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - } - - /* initialise config variables */ - memset(&bp->node, 0, sizeof(nodeang_t) * 24); - bp->m_count = sizeof(default_models) / sizeof(model_t); /* overwrite this in a bit */ - bp->selected = 11; - bp->is_cyclic = 0; - bp->is_legal = 1; - bp->last_turn = -1; - bp->roty = 0.0; - bp->rotz = 0.0; - bp->morphing = 0; - bp->paused = 0; - bp->dragging = 0; - bp->interactive = 0; +void glsnake_init(ModeInfo *mi) +{ + glsnake_configuration * bp; + int wire = MI_IS_WIREFRAME(mi); + + if (!glc) { + glc = (glsnake_configuration *) calloc(MI_NUM_SCREENS(mi), sizeof(glsnake_configuration)); + if (!glc) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + bp = &glc[MI_SCREEN(mi)]; + } + + bp = &glc[MI_SCREEN(mi)]; + + if ((bp->glx_context = init_GL(mi)) != NULL) { + gl_init(mi); + glsnake_reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } + + /* initialise config variables */ + memset(&bp->node, 0, sizeof(nodeang_t) * 24); + bp->m_count = sizeof(default_models) / sizeof(model_t); /* overwrite this in a bit */ + bp->selected = 11; + bp->is_cyclic = 0; + bp->is_legal = 1; + bp->last_turn = -1; + bp->roty = 0.0; + bp->rotz = 0.0; + bp->morphing = 0; + bp->paused = 0; + bp->dragging = 0; + bp->interactive = 0; { # ifdef GETTIMEOFDAY_TWO_ARGS @@ -702,193 +722,194 @@ void glsnake_init(ModeInfo *mi) { # endif } - memcpy(&bp->last_morph, &(bp->last_iteration), + memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph)); - /* srand((unsigned int) bp->last_iteration.time); */ - - /* load the model files */ - /* first copy the defaults to bp->m_count */ - bp->models = (model_t *) malloc(sizeof(model_t) * bp->m_count); - memcpy(bp->models, default_models, bp->m_count * sizeof(model_t)); - /* then add on models from the Debian model file location */ - bp->models = load_models("/usr/share/glsnake", bp->models, &(bp->m_count)); - - bp->m = bp->cur_model = RAND(bp->m_count); - start_morph(bp->cur_model, 1, bp); - - calc_snake_metrics(bp); - set_colours(bp, 1); - - /* set up a font for the labels */ - if (labels) - load_font(mi, "labelfont", &bp->font, &bp->font_list); - - bp->node_list = glGenLists(1); - glNewList(bp->node_list, GL_COMPILE); - if (!wire) { - /* corners */ - glBegin(GL_TRIANGLES); - glNormal3fv(solid_prism_n[0]); - glVertex3fv(solid_prism_v[0]); - glVertex3fv(solid_prism_v[2]); - glVertex3fv(solid_prism_v[1]); + /* srand((unsigned int) bp->last_iteration.time); */ + + /* load the model files */ + /* first copy the defaults to bp->m_count */ + bp->models = (model_t *) malloc(sizeof(model_t) * bp->m_count); + memcpy(bp->models, default_models, bp->m_count * sizeof(model_t)); + /* then add on models from the Debian model file location */ + bp->models = load_models("/usr/share/glsnake", bp->models, &(bp->m_count)); + + bp->m = bp->cur_model = RAND(bp->m_count); + start_morph(bp->cur_model, 1, bp); + + calc_snake_metrics(bp); + set_colours(bp, 1); + + /* set up a font for the labels */ + if (labels) + load_font(mi, "labelfont", &bp->font, &bp->font_list); + + bp->node_list = glGenLists(1); + glNewList(bp->node_list, GL_COMPILE); + if (!wire) { + /* corners */ + glBegin(GL_TRIANGLES); + glNormal3fv(solid_prism_n[0]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[2]); + glVertex3fv(solid_prism_v[1]); - glNormal3fv(solid_prism_n[1]); - glVertex3fv(solid_prism_v[6]); - glVertex3fv(solid_prism_v[7]); - glVertex3fv(solid_prism_v[8]); - - glNormal3fv(solid_prism_n[2]); - glVertex3fv(solid_prism_v[12]); - glVertex3fv(solid_prism_v[13]); - glVertex3fv(solid_prism_v[14]); + glNormal3fv(solid_prism_n[1]); + glVertex3fv(solid_prism_v[6]); + glVertex3fv(solid_prism_v[7]); + glVertex3fv(solid_prism_v[8]); + + glNormal3fv(solid_prism_n[2]); + glVertex3fv(solid_prism_v[12]); + glVertex3fv(solid_prism_v[13]); + glVertex3fv(solid_prism_v[14]); - glNormal3fv(solid_prism_n[3]); - glVertex3fv(solid_prism_v[3]); - glVertex3fv(solid_prism_v[4]); - glVertex3fv(solid_prism_v[5]); - - glNormal3fv(solid_prism_n[4]); - glVertex3fv(solid_prism_v[9]); - glVertex3fv(solid_prism_v[11]); - glVertex3fv(solid_prism_v[10]); - - glNormal3fv(solid_prism_n[5]); - glVertex3fv(solid_prism_v[16]); - glVertex3fv(solid_prism_v[15]); - glVertex3fv(solid_prism_v[17]); - glEnd(); - - /* edges */ - glBegin(GL_QUADS); - glNormal3fv(solid_prism_n[6]); - glVertex3fv(solid_prism_v[0]); - glVertex3fv(solid_prism_v[12]); - glVertex3fv(solid_prism_v[14]); - glVertex3fv(solid_prism_v[2]); - - glNormal3fv(solid_prism_n[7]); - glVertex3fv(solid_prism_v[0]); - glVertex3fv(solid_prism_v[1]); - glVertex3fv(solid_prism_v[7]); - glVertex3fv(solid_prism_v[6]); - - glNormal3fv(solid_prism_n[8]); - glVertex3fv(solid_prism_v[6]); - glVertex3fv(solid_prism_v[8]); - glVertex3fv(solid_prism_v[13]); - glVertex3fv(solid_prism_v[12]); - - glNormal3fv(solid_prism_n[9]); - glVertex3fv(solid_prism_v[3]); - glVertex3fv(solid_prism_v[5]); - glVertex3fv(solid_prism_v[17]); - glVertex3fv(solid_prism_v[15]); - - glNormal3fv(solid_prism_n[10]); - glVertex3fv(solid_prism_v[3]); - glVertex3fv(solid_prism_v[9]); - glVertex3fv(solid_prism_v[10]); - glVertex3fv(solid_prism_v[4]); - - glNormal3fv(solid_prism_n[11]); - glVertex3fv(solid_prism_v[15]); - glVertex3fv(solid_prism_v[16]); - glVertex3fv(solid_prism_v[11]); - glVertex3fv(solid_prism_v[9]); - - glNormal3fv(solid_prism_n[12]); - glVertex3fv(solid_prism_v[1]); - glVertex3fv(solid_prism_v[2]); - glVertex3fv(solid_prism_v[5]); - glVertex3fv(solid_prism_v[4]); - - glNormal3fv(solid_prism_n[13]); - glVertex3fv(solid_prism_v[8]); - glVertex3fv(solid_prism_v[7]); - glVertex3fv(solid_prism_v[10]); - glVertex3fv(solid_prism_v[11]); - - glNormal3fv(solid_prism_n[14]); - glVertex3fv(solid_prism_v[13]); - glVertex3fv(solid_prism_v[16]); - glVertex3fv(solid_prism_v[17]); - glVertex3fv(solid_prism_v[14]); - glEnd(); - - /* faces */ - glBegin(GL_TRIANGLES); - glNormal3fv(solid_prism_n[15]); - glVertex3fv(solid_prism_v[0]); - glVertex3fv(solid_prism_v[6]); - glVertex3fv(solid_prism_v[12]); - - glNormal3fv(solid_prism_n[19]); - glVertex3fv(solid_prism_v[3]); - glVertex3fv(solid_prism_v[15]); - glVertex3fv(solid_prism_v[9]); - glEnd(); - - glBegin(GL_QUADS); - glNormal3fv(solid_prism_n[16]); - glVertex3fv(solid_prism_v[1]); - glVertex3fv(solid_prism_v[4]); - glVertex3fv(solid_prism_v[10]); - glVertex3fv(solid_prism_v[7]); - - glNormal3fv(solid_prism_n[17]); - glVertex3fv(solid_prism_v[8]); - glVertex3fv(solid_prism_v[11]); - glVertex3fv(solid_prism_v[16]); - glVertex3fv(solid_prism_v[13]); - - glNormal3fv(solid_prism_n[18]); - glVertex3fv(solid_prism_v[2]); - glVertex3fv(solid_prism_v[14]); - glVertex3fv(solid_prism_v[17]); - glVertex3fv(solid_prism_v[5]); - glEnd(); - } else { - /* build wire display list */ - glBegin(GL_LINE_STRIP); - glVertex3fv(wire_prism_v[0]); - glVertex3fv(wire_prism_v[1]); - glVertex3fv(wire_prism_v[2]); - glVertex3fv(wire_prism_v[0]); - glVertex3fv(wire_prism_v[3]); - glVertex3fv(wire_prism_v[4]); - glVertex3fv(wire_prism_v[5]); - glVertex3fv(wire_prism_v[3]); - glEnd(); - - glBegin(GL_LINES); - glVertex3fv(wire_prism_v[1]); - glVertex3fv(wire_prism_v[4]); - glVertex3fv(wire_prism_v[2]); - glVertex3fv(wire_prism_v[5]); - glEnd(); - } - glEndList(); + glNormal3fv(solid_prism_n[3]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[4]); + glVertex3fv(solid_prism_v[5]); + + glNormal3fv(solid_prism_n[4]); + glVertex3fv(solid_prism_v[9]); + glVertex3fv(solid_prism_v[11]); + glVertex3fv(solid_prism_v[10]); + + glNormal3fv(solid_prism_n[5]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[15]); + glVertex3fv(solid_prism_v[17]); + glEnd(); + + /* edges */ + glBegin(GL_QUADS); + glNormal3fv(solid_prism_n[6]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[12]); + glVertex3fv(solid_prism_v[14]); + glVertex3fv(solid_prism_v[2]); + + glNormal3fv(solid_prism_n[7]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[1]); + glVertex3fv(solid_prism_v[7]); + glVertex3fv(solid_prism_v[6]); + + glNormal3fv(solid_prism_n[8]); + glVertex3fv(solid_prism_v[6]); + glVertex3fv(solid_prism_v[8]); + glVertex3fv(solid_prism_v[13]); + glVertex3fv(solid_prism_v[12]); + + glNormal3fv(solid_prism_n[9]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[5]); + glVertex3fv(solid_prism_v[17]); + glVertex3fv(solid_prism_v[15]); + + glNormal3fv(solid_prism_n[10]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[9]); + glVertex3fv(solid_prism_v[10]); + glVertex3fv(solid_prism_v[4]); + + glNormal3fv(solid_prism_n[11]); + glVertex3fv(solid_prism_v[15]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[11]); + glVertex3fv(solid_prism_v[9]); + + glNormal3fv(solid_prism_n[12]); + glVertex3fv(solid_prism_v[1]); + glVertex3fv(solid_prism_v[2]); + glVertex3fv(solid_prism_v[5]); + glVertex3fv(solid_prism_v[4]); + + glNormal3fv(solid_prism_n[13]); + glVertex3fv(solid_prism_v[8]); + glVertex3fv(solid_prism_v[7]); + glVertex3fv(solid_prism_v[10]); + glVertex3fv(solid_prism_v[11]); + + glNormal3fv(solid_prism_n[14]); + glVertex3fv(solid_prism_v[13]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[17]); + glVertex3fv(solid_prism_v[14]); + glEnd(); + + /* faces */ + glBegin(GL_TRIANGLES); + glNormal3fv(solid_prism_n[15]); + glVertex3fv(solid_prism_v[0]); + glVertex3fv(solid_prism_v[6]); + glVertex3fv(solid_prism_v[12]); + + glNormal3fv(solid_prism_n[19]); + glVertex3fv(solid_prism_v[3]); + glVertex3fv(solid_prism_v[15]); + glVertex3fv(solid_prism_v[9]); + glEnd(); + + glBegin(GL_QUADS); + glNormal3fv(solid_prism_n[16]); + glVertex3fv(solid_prism_v[1]); + glVertex3fv(solid_prism_v[4]); + glVertex3fv(solid_prism_v[10]); + glVertex3fv(solid_prism_v[7]); + + glNormal3fv(solid_prism_n[17]); + glVertex3fv(solid_prism_v[8]); + glVertex3fv(solid_prism_v[11]); + glVertex3fv(solid_prism_v[16]); + glVertex3fv(solid_prism_v[13]); + + glNormal3fv(solid_prism_n[18]); + glVertex3fv(solid_prism_v[2]); + glVertex3fv(solid_prism_v[14]); + glVertex3fv(solid_prism_v[17]); + glVertex3fv(solid_prism_v[5]); + glEnd(); + } else { + /* build wire display list */ + glBegin(GL_LINE_STRIP); + glVertex3fv(wire_prism_v[0]); + glVertex3fv(wire_prism_v[1]); + glVertex3fv(wire_prism_v[2]); + glVertex3fv(wire_prism_v[0]); + glVertex3fv(wire_prism_v[3]); + glVertex3fv(wire_prism_v[4]); + glVertex3fv(wire_prism_v[5]); + glVertex3fv(wire_prism_v[3]); + glEnd(); + + glBegin(GL_LINES); + glVertex3fv(wire_prism_v[1]); + glVertex3fv(wire_prism_v[4]); + glVertex3fv(wire_prism_v[2]); + glVertex3fv(wire_prism_v[5]); + glEnd(); + } + glEndList(); } /* "jwz? no way man, he's my idle" -- Jaq, 2001. * I forget the context :( */ -void glsnake_idol(glsnake_configuration * bp) { - /* time since last iteration */ - long iter_msec; - /* time since the beginning of last morph */ - long morf_msec; - float iter_angle_max; - int i; - struct timeval current_time; - int still_morphing; - - /* Do nothing to the model if we are paused */ - if (bp->paused) { - /* Avoid busy waiting when nothing is changing */ - usleep(1); - return; - } +void glsnake_idol(glsnake_configuration * bp) +{ + /* time since last iteration */ + long iter_msec; + /* time since the beginning of last morph */ + long morf_msec; + float iter_angle_max; + int i; + struct timeval current_time; + int still_morphing; + + /* Do nothing to the model if we are paused */ + if (bp->paused) { + /* Avoid busy waiting when nothing is changing */ + usleep(1); + return; + } { # ifdef GETTIMEOFDAY_TWO_ARGS @@ -899,171 +920,293 @@ void glsnake_idol(glsnake_configuration * bp) { # endif } - /* Well, ftime gives time with millisecond resolution. - * if current time is exactly equal to last iteration, - * then don't do this block - * (or worse, perhaps... who knows what the OS will do) - * So if no discernable amount of time has passed: - * a) There's no point updating the screen, because - * it would be the same - * b) The code will divide by zero - */ - iter_msec = ((long) current_time.tv_usec - bp->last_iteration.tv_usec)/1000L + - ((long) current_time.tv_sec - bp->last_iteration.tv_sec) * 1000L; - if (iter_msec) { - /* save the current time */ - memcpy(&bp->last_iteration, ¤t_time, + /* Well, ftime gives time with millisecond resolution. + * if current time is exactly equal to last iteration, + * then don't do this block + * (or worse, perhaps... who knows what the OS will do) + * So if no discernable amount of time has passed: + * a) There's no point updating the screen, because + * it would be the same + * b) The code will divide by zero + */ + iter_msec = ((long) current_time.tv_usec - bp->last_iteration.tv_usec)/1000L + + ((long) current_time.tv_sec - bp->last_iteration.tv_sec) * 1000L; + if (iter_msec) { + /* save the current time */ + memcpy(&bp->last_iteration, ¤t_time, sizeof(bp->last_iteration)); - - /* work out if we have to switch models */ - morf_msec = (bp->last_iteration.tv_usec - bp->last_morph.tv_usec)/1000L + - ((long) (bp->last_iteration.tv_sec - bp->last_morph.tv_sec) * 1000L); + + /* work out if we have to switch models */ + morf_msec = (bp->last_iteration.tv_usec - bp->last_morph.tv_usec)/1000L + + ((long) (bp->last_iteration.tv_sec - bp->last_morph.tv_sec) * 1000L); - if ((morf_msec > statictime) && !bp->interactive) { - memcpy(&bp->last_morph, &(bp->last_iteration), + if ((morf_msec > statictime) && !bp->interactive) { + memcpy(&bp->last_morph, &(bp->last_iteration), sizeof(bp->last_morph)); - start_morph(RAND(bp->m_count), 0, bp); - } - - if (bp->interactive && !bp->morphing) { - usleep(1); - return; - } - - if (!bp->dragging && !bp->interactive) { - bp->roty += 360/((1000/yspin)/iter_msec); - bp->rotz += 360/((1000/zspin)/iter_msec); - } - - /* work out the maximum angle for this iteration */ - iter_angle_max = 90.0 * (velocity/1000.0) * iter_msec; - - still_morphing = 0; - for (i = 0; i < 24; i++) { - float cur_angle = bp->node[i].cur_angle; - float dest_angle = bp->node[i].dest_angle; - if (cur_angle != dest_angle) { - still_morphing = 1; - if (fabs(cur_angle - dest_angle) <= iter_angle_max) - bp->node[i].cur_angle = dest_angle; - else if (fmod(cur_angle - dest_angle + 360, 360) > 180) - bp->node[i].cur_angle = fmod(cur_angle + iter_angle_max, 360); - else - bp->node[i].cur_angle = fmod(cur_angle + 360 - iter_angle_max, 360); - } - } - - if (!still_morphing) - bp->morphing = 0; - - /* colour cycling */ - if (fabs(bp->colour[0] - bp->colour_t[0]) <= fabs(bp->colour_i[0])) - bp->colour[0] = bp->colour_t[0]; - else - bp->colour[0] += bp->colour_i[0]; - if (fabs(bp->colour[1] - bp->colour_t[1]) <= fabs(bp->colour_i[1])) - bp->colour[1] = bp->colour_t[1]; - else - bp->colour[1] += bp->colour_i[1]; - if (fabs(bp->colour[2] - bp->colour_t[2]) <= fabs(bp->colour_i[2])) - bp->colour[2] = bp->colour_t[2]; - else - bp->colour[2] += bp->colour_i[2]; - } else { - /* We are going too fast, so we may as well let the - * cpu relax a little by sleeping for a millisecond. */ - usleep(1); - } + start_morph(RAND(bp->m_count), 0, bp); + } + + if (bp->interactive && !bp->morphing) { + usleep(1); + return; + } + + if (!bp->dragging && !bp->interactive) { + bp->roty += 360/((1000/yspin)/iter_msec); + bp->rotz += 360/((1000/zspin)/iter_msec); + } + + /* work out the maximum angle for this iteration */ + iter_angle_max = 90.0 * (velocity/1000.0) * iter_msec; + + still_morphing = 0; + for (i = 0; i < 24; i++) { + float cur_angle = bp->node[i].cur_angle; + float dest_angle = bp->node[i].dest_angle; + if (cur_angle != dest_angle) { + still_morphing = 1; + if (fabs(cur_angle - dest_angle) <= iter_angle_max) + bp->node[i].cur_angle = dest_angle; + else if (fmod(cur_angle - dest_angle + 360, 360) > 180) + bp->node[i].cur_angle = fmod(cur_angle + iter_angle_max, 360); + else + bp->node[i].cur_angle = fmod(cur_angle + 360 - iter_angle_max, 360); + } + } + + if (!still_morphing) + bp->morphing = 0; + + /* colour cycling */ + if (fabs(bp->colour[0] - bp->colour_t[0]) <= fabs(bp->colour_i[0])) + bp->colour[0] = bp->colour_t[0]; + else + bp->colour[0] += bp->colour_i[0]; + if (fabs(bp->colour[1] - bp->colour_t[1]) <= fabs(bp->colour_i[1])) + bp->colour[1] = bp->colour_t[1]; + else + bp->colour[1] += bp->colour_i[1]; + if (fabs(bp->colour[2] - bp->colour_t[2]) <= fabs(bp->colour_i[2])) + bp->colour[2] = bp->colour_t[2]; + else + bp->colour[2] += bp->colour_i[2]; + } else { + /* We are going too fast, so we may as well let the + * cpu relax a little by sleeping for a millisecond. */ + usleep(1); + } +} + +static void +snake_bounding_box (ModeInfo *mi, + GLfloat *x1, GLfloat *y1, GLfloat *z1, + GLfloat *x2, GLfloat *y2, GLfloat *z2) +{ + glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; + int i; + GLdouble identity[16] = { 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 }; + GLint vp[4] = { 0, 0, 1, 1 }; + *x1 = *x2 = 0; + *y1 = *y2 = 0; + *z1 = *z2 = 0; + + glPushMatrix(); + glLoadIdentity(); + for (i = 0; i < 24; i++) + { + GLdouble model[16]; + GLdouble x, y, z; + GLfloat ang = bp->node[i].cur_angle; + + glGetDoublev (GL_MODELVIEW_MATRIX, model); + gluProject (0, 0, 0, model, identity, vp, &x, &y, &z); +fprintf (stderr, "%2d: %5.2f %5.2f %5.2f\n", i, (float)x, (float)y, (float)z); + + if (x < *x1) *x1 = x; + else if (x > *x2) *x2 = x; + if (y < *y1) *y1 = y; + else if (y > *y2) *y2 = y; + if (z < *z1) *z1 = z; + else if (z > *z2) *z2 = z; + + glTranslatef(0.5, 0.5, 0.5); + glRotatef(90, 0.0, 0.0, -1.0); + glTranslatef(1.0 + explode, 0.0, 0.0); + glRotatef(180 + ang, 1.0, 0.0, 0.0); + glTranslatef(-0.5, -0.5, -0.5); + } +fprintf(stderr, "\n"); + glPopMatrix(); + +#if 0 + *x1 -= 1; + *y1 -= 1; + *z1 -= 1; + *x2 += 1; + *y2 += 1; + *z2 += 1; +#endif +} + + +static void +draw_bounding_box (ModeInfo *mi) +{ + static GLfloat c1[4] = { 0.4, 0.4, 0.4, 1.0 }; + static GLfloat c2[4] = { 1.0, 0.0, 0.0, 1.0 }; + int wire = MI_IS_WIREFRAME(mi); + GLfloat x1, y1, z1, x2, y2, z2; + snake_bounding_box (mi, &x1, &y1, &z1, &x2, &y2, &z2); + + glColor3f (c1[0], c1[1], c1[2]); +/* glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c1);*/ + glFrontFace(GL_CCW); + + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(x1, y1, z1); glVertex3f(x1, y1, z2); + glVertex3f(x2, y1, z2); glVertex3f(x2, y1, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, -1, 0); + glVertex3f(x2, y2, z1); glVertex3f(x2, y2, z2); + glVertex3f(x1, y2, z2); glVertex3f(x1, y2, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, 1); + glVertex3f(x1, y1, z1); glVertex3f(x2, y1, z1); + glVertex3f(x2, y2, z1); glVertex3f(x1, y2, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(0, 0, -1); + glVertex3f(x1, y2, z2); glVertex3f(x2, y2, z2); + glVertex3f(x2, y1, z2); glVertex3f(x1, y1, z2); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(1, 0, 0); + glVertex3f(x1, y2, z1); glVertex3f(x1, y2, z2); + glVertex3f(x1, y1, z2); glVertex3f(x1, y1, z1); + glEnd(); + glBegin(wire ? GL_LINE_LOOP : GL_QUADS); + glNormal3f(-1, 0, 0); + glVertex3f(x2, y1, z1); glVertex3f(x2, y1, z2); + glVertex3f(x2, y2, z2); glVertex3f(x2, y2, z1); + glEnd(); + + glPushAttrib (GL_LIGHTING); + glDisable (GL_LIGHTING); + + glColor3f (c2[0], c2[1], c2[2]); + glBegin(GL_LINES); + if (x1 > 0) x1 = 0; if (x2 < 0) x2 = 0; + if (y1 > 0) y1 = 0; if (y2 < 0) y2 = 0; + if (z1 > 0) z1 = 0; if (z2 < 0) z2 = 0; + glVertex3f(x1, 0, 0); glVertex3f(x2, 0, 0); + glVertex3f(0 , y1, 0); glVertex3f(0, y2, 0); + glVertex3f(0, 0, z1); glVertex3f(0, 0, z2); + glEnd(); + + glPopAttrib(); } -void glsnake_draw(ModeInfo *mi) { - glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; - Display *dpy = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - - int i; - float ang; - - if (!bp->glx_context) - return; - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); - - /* rotate and translate into snake space */ - glRotatef(45.0, -5.0, 0.0, 1.0); - glTranslatef(-0.5, 0.0, 0.5); - - /* rotate the 0th junction */ - glTranslatef(0.5, 0.0, 0.5); - /* glMultMatrix(rotation); -- quaternion rotation */ - glRotatef(bp->roty, 0.0, 1.0, 0.0); - glRotatef(bp->rotz, 0.0, 0.0, 1.0); - glTranslated(-0.5, 0.0, -0.5); - - /* translate middle node to centre */ - for (i = 11; i >= 0; i--) { - ang = bp->node[i].cur_angle; - glTranslatef(0.5, 0.5, 0.5); - glRotatef(180+ang, -1.0, 0.0, 0.0); - glTranslatef(-1.0 - explode, 0.0, 0.0); - glRotatef(90, 0.0, 0.0, 1.0); - glTranslatef(-0.5, -0.5, -0.5); - } - - /* now draw each node along the snake */ - for (i = 0; i < 24; i++) { - glPushMatrix(); - - /* choose a colour for this node */ - if (bp->interactive && (i == bp->selected || i == bp->selected+1)) - glColor3f(1.0, 1.0, 0.0); - else { - if (i % 2) { - if (scarycolour) - glColor3f(0.6, 0.0, 0.9); - else - glColor3fv(bp->colour); - } else { - if (scarycolour) - glColor3f(0.2, 0.9, 1.0); - else - glColor3f(1.0, 1.0, 1.0); - } - } - - /* draw the node */ - glCallList(bp->node_list); - - /* now work out where to draw the next one */ - - /* interpolate between models */ - ang = bp->node[i].cur_angle; - - glTranslatef(0.5, 0.5, 0.5); - glRotatef(90, 0.0, 0.0, -1.0); - glTranslatef(1.0 + explode, 0.0, 0.0); - glRotatef(180 + ang, 1.0, 0.0, 0.0); - glTranslatef(-0.5, -0.5, -0.5); - } - - /* clear up the matrix stack */ - for (i = 0; i < 24; i++) - glPopMatrix(); - - if (labels) - draw_label(mi); - - if (mi->fps_p) - do_fps (mi); - - glsnake_idol(bp); - - glFlush(); - glXSwapBuffers(dpy, window); + +void glsnake_draw(ModeInfo *mi) +{ + glsnake_configuration *bp = &glc[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + int i; + float ang; + + if (!bp->glx_context) + return; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + + /* rotate and translate into snake space */ + glRotatef(45.0, -5.0, 0.0, 1.0); + glTranslatef(-0.5, 0.0, 0.5); + + /* rotate the 0th junction */ + glTranslatef(0.5, 0.0, 0.5); + /* glMultMatrix(rotation); -- quaternion rotation */ + glRotatef(bp->roty, 0.0, 1.0, 0.0); + glRotatef(bp->rotz, 0.0, 0.0, 1.0); + glTranslated(-0.5, 0.0, -0.5); + + /* translate middle node to centre */ + for (i = 11; i >= 0; i--) { + ang = bp->node[i].cur_angle; + glTranslatef(0.5, 0.5, 0.5); + glRotatef(180+ang, -1.0, 0.0, 0.0); + glTranslatef(-1.0 - explode, 0.0, 0.0); + glRotatef(90, 0.0, 0.0, 1.0); + glTranslatef(-0.5, -0.5, -0.5); + } + + /* now draw each node along the snake */ + glPushMatrix(); + for (i = 0; i < 24; i++) { + + /* choose a colour for this node */ + if (bp->interactive && (i == bp->selected || i == bp->selected+1)) + glColor3f(1.0, 1.0, 0.0); + else { + if (i % 2) { + if (scarycolour) + glColor3f(0.6, 0.0, 0.9); + else + glColor3fv(bp->colour); + } else { + if (scarycolour) + glColor3f(0.2, 0.9, 1.0); + else + glColor3f(1.0, 1.0, 1.0); + } + } + +#if 0 /* #### */ + if (i == 0) glColor3f(0.0, 1.0, 1.0); +#endif + + /* draw the node */ + glCallList(bp->node_list); + + /* now work out where to draw the next one */ + + /* interpolate between models */ + ang = bp->node[i].cur_angle; + + glTranslatef(0.5, 0.5, 0.5); + glRotatef(90, 0.0, 0.0, -1.0); + glTranslatef(1.0 + explode, 0.0, 0.0); + glRotatef(180 + ang, 1.0, 0.0, 0.0); + glTranslatef(-0.5, -0.5, -0.5); + } + + glPopMatrix(); + + if (do_bbox) + draw_bounding_box (mi); + + if (labels) + draw_label(mi); + + if (mi->fps_p) + do_fps (mi); + + glsnake_idol(bp); + + glFlush(); + glXSwapBuffers(dpy, window); } #endif /* USE_GL */