static twTriple twColors[] = { {0,0,0}, // black {1,1,1}, // white {1,1,0}, // yellow {1,0.5,0}, // orange {1,0,1}, // magenta {1,0,0}, // red {0.8,0.8,0.8},// silver {0.5,0.5,0.5},// gray {0.5,0.5,0}, // olive {0.5,0,0.5}, // purple {0.7,0.19,0.38}, // maroon {0,1,1}, // cyan {0,0.5,0.5}, // teal {0,1,0}, // green {0,0,1}, // blue {0,0,0.5}, // dark blue {0.7,0.7,1}, // light blue {1.0,0.75, 0.8}, // pink {0.8,0.5,0.3} // brown }; /* **************************************************************** Calculating RGB values from HSV values. Hue is specified as an angle in degrees from pure red. Code adapted from Foley & van Dam, page 593. */ void twHSV2RGB( twTriple rgb, twTriple hsv ) { GLfloat h=hsv[0]; GLfloat s=hsv[1]; GLfloat v=hsv[2]; if( s == 0.0 ) { rgb[0] = rgb[1] = rgb[2] = v; } else { // Color with a hue, since S is non-zero GLfloat f, p, q, t; int i; if(h==360.0) h=0.0; // 360 degrees is the same as zero h /= 60.0; // h is now in [0,6) i = (int) floor(h); // Floor is largest in <= h f = h-i; // f is the fractional part of h p = v*(1.0-s); q = v*(1.0-(s*f)); t = v*(1.0-(s*(1.0-f))); // i essentially tells us which of the six vertices we are closest to. // More precisely, it tells us which triangular wedge we are in. // p is our distance in from the edge of the hexagon. switch(i) { case 0: rgb[0]=v; rgb[1]=t; rgb[2]=p; break; case 1: rgb[0]=q; rgb[1]=v; rgb[2]=p; break; case 2: rgb[0]=p; rgb[1]=v; rgb[2]=t; break; case 3: rgb[0]=p; rgb[1]=q; rgb[2]=v; break; case 4: rgb[0]=t; rgb[1]=p; rgb[2]=v; break; case 5: rgb[0]=v; rgb[1]=p; rgb[2]=q; break; } } } bool twColorOkay(twTriple color) { return (0.0 <= color[0] && color[0] <= 1.0 ) && (0.0 <= color[1] && color[1] <= 1.0 ) && (0.0 <= color[2] && color[2] <= 1.0 ); } /* Remember that RGB color and material are mutually exclusive, so if lighting is enabled, RGB color is ignored, and if lighting is disabled, material is ignored. This function does both, so that your object looks approximately right whether or not lighting is enabled. Note, there is a risk here, because the color is supposed to be a four-place array, and we're using twTriple. So far, that's been okay.*/ void twColor(twTriple color, GLfloat spec, GLfloat shininess) { if( !twColorOkay(color) ) { fprintf(stderr,"color does not have valid components (between 0 and 1): %f %f %f\n", color[0], color[1], color[2] ); } if( shininess < 0 || shininess > 128 ) { fprintf(stderr,"shininess is not between 0 and 128: %f\n", shininess); } twError(); // The following is if lighting is off glColor3fv(color); // The rest is if lighting is on. twTriple matSpecular = {spec,spec,spec}; glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,color); glMaterialfv(GL_FRONT,GL_SPECULAR,matSpecular); glMaterialf(GL_FRONT,GL_SHININESS,shininess); twError(); } // the following is deprecated, being less flexible than the preceding version void twColor(GLfloat r, GLfloat g, GLfloat b, GLfloat specular_shininess) { twTriple color = {r, g, b}; glColor3fv(color); GLfloat spec = specular_shininess/128.0; twTriple matSpecular = {spec,spec,spec}; glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,color); glMaterialfv(GL_FRONT,GL_SPECULAR,matSpecular); glMaterialf(GL_FRONT,GL_SHININESS,specular_shininess); } void twColorName(int i) { // By making the specular and shininess zero, they'll get no specular // reflections if they turn on lighting. if(0 <= i && i < TW_NUM_COLORS) twColor(twColors[i], 0, 0); else printf("invalid color number: %d, must be less than %d\n",i,TW_NUM_COLORS); }