#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" \
"*scarycolour:" DEF_SCARYCOLOUR " \n" \
"*labels: " DEF_LABELS " \n" \
"*labelfont: -*-times-bold-r-normal-*-180-*\n" \
+ "*bbox: " DEF_BBOX "\n" \
#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;
static GLfloat zspin;
static Bool scarycolour;
static Bool labels;
+static Bool do_bbox;
static XrmOptionDescRec opts[] = {
{ "-speed", ".speed", XrmoptionSepArg, 0 },
{ "+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[] = {
/* {(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};
/* 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 */
#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
* 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 */
#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
# 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
# endif
}
- /* <spiv> Well, ftime gives time with millisecond resolution.
- * <Jaq> if current time is exactly equal to last iteration,
- * then don't do this block
- * <spiv> (or worse, perhaps... who knows what the OS will do)
- * <spiv> So if no discernable amount of time has passed:
- * <spiv> a) There's no point updating the screen, because
- * it would be the same
- * <spiv> 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,
+ /* <spiv> Well, ftime gives time with millisecond resolution.
+ * <Jaq> if current time is exactly equal to last iteration,
+ * then don't do this block
+ * <spiv> (or worse, perhaps... who knows what the OS will do)
+ * <spiv> So if no discernable amount of time has passed:
+ * <spiv> a) There's no point updating the screen, because
+ * it would be the same
+ * <spiv> 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 */