// The contents of this file are subject to the Mozilla Public License // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is the Berkeley Open Infrastructure for Network Computing. // // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 // University of California at Berkeley. All Rights Reserved. // // Contributor(s): // #include #include #include #include #ifdef _WIN32 #include #include #include #include #endif #ifdef __APPLE_CC__ #include #include #endif #include "gutil.h" GLfloat mat_diffuse[] = {0.7, 0.5, 1.0, 0.4}; GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat mat_shininess[] = {40.0}; void mode_shaded(GLfloat* color) { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel (GL_SMOOTH); glDepthMask(GL_TRUE); glMaterialfv(GL_FRONT, GL_DIFFUSE, color); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); } void mode_texture() { glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); } void mode_unshaded() { glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel (GL_SMOOTH); glDepthMask(GL_TRUE); } void mode_lines() { glEnable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); //glBlendFunc(GL_SRC_ALPHA, GL_ONE); //glDepthMask(GL_TRUE); //glEnable(GL_LINE_SMOOTH); //glHint(GL_LINE_SMOOTH, GL_NICEST); //glDisable(GL_DEPTH_TEST); } static double HuetoRGB(double m1, double m2, double h ) { if( h < 0 ) h += 1.0; if( h > 1 ) h -= 1.0; if( 6.0*h < 1 ) return (m1+(m2-m1)*h*6.0); if( 2.0*h < 1 ) return m2; if( 3.0*h < 2.0 ) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0); return m1; } void HLStoRGB( double H, double L, double S, COLOR& c) { double m1, m2; if(S==0) { c.r=c.g=c.b=L; } else { if(L <=0.5) m2 = L*(1.0+S); else m2 = L+S-L*S; m1 = 2.0*L-m2; c.r = HuetoRGB(m1,m2,H+1.0/3.0); c.g = HuetoRGB(m1,m2,H); c.b = HuetoRGB(m1,m2,H-1.0/3.0); } } float frand() { return rand()/(float)RAND_MAX; } void drawSphere(GLfloat* pos, GLfloat rad) { GLUquadricObj* x = gluNewQuadric(); glPushMatrix(); glTranslatef(pos[0], pos[1], pos[2]); gluSphere(x, rad, 20, 20); gluDeleteQuadric(x); glPopMatrix(); } void drawCylinder(bool vertical, GLfloat* pos, GLfloat len, GLfloat rad) { GLUquadricObj* x = gluNewQuadric(); glPushMatrix(); glTranslatef(pos[0], pos[1], pos[2]); if (vertical) { glRotated(-90., 1., 0., 0.); } else { glRotated(90., 0., 1., 0.); } gluCylinder(x, rad, rad, len, 20, 1); gluDeleteQuadric(x); glPopMatrix(); } #define STROKE_SCALE 120 // GLUT stroke characters are about 120 units high GLfloat text_width(char* text) { GLfloat sum = 0; char* p; for (p=text; *p; p++) { sum += glutStrokeWidth(GLUT_STROKE_ROMAN, *p); } return sum/STROKE_SCALE; } static void draw_text_line_aux(char *text) { char *p; for (p = text; *p; p++) { glutStrokeCharacter(GLUT_STROKE_ROMAN, *p); } } static void draw_text_start(GLfloat* pos, GLfloat char_height, GLfloat line_width) { glLineWidth(line_width); glPushMatrix(); glTranslatef(pos[0], pos[1], pos[2]); float w = char_height/STROKE_SCALE; glScalef(w, w, w); } static void draw_text_end() { glPopMatrix(); } // draw a line of text in the XY plane at the given starting position, // character height, and line width. // void draw_text_line( GLfloat* _pos, GLfloat char_height, GLfloat line_width, char *text, int justify ) { GLfloat pos[3]; GLfloat w; memcpy(pos, _pos, sizeof(pos)); switch(justify) { case TEXT_LEFT: break; case TEXT_CENTER: w = text_width(text); pos[0] -= w/2; break; case TEXT_RIGHT: w = text_width(text); pos[0] -= w; break; } draw_text_start(pos, char_height, line_width); draw_text_line_aux(text); draw_text_end(); } // draw multiple lines of text // void draw_text( GLfloat* _pos, GLfloat char_height, GLfloat line_width, GLfloat line_spacing, char* text ) { char* q, *p; char buf[4096]; GLfloat pos[3]; memcpy(pos, _pos, sizeof(pos)); strcpy(buf, text); p = buf; while (*p) { q = strchr(p, '\n'); if (q) *q = 0; draw_text_start(pos, char_height, line_width); draw_text_line_aux(p); draw_text_end(); pos[1] -= line_spacing; if (!q) break; p = q+1; } } // draw a rectangle of the given color in the XY plane // and draw the given test in it // void draw_text_panel( GLfloat* _pos, GLfloat* size, GLfloat margin, COLOR color, GLfloat char_height, GLfloat line_width, GLfloat line_spacing, char* text ) { GLfloat pos0[3], pos1[3], pos2[3], pos3[3]; memcpy(pos0, _pos, sizeof(pos0)); memcpy(pos1, _pos, sizeof(pos0)); pos1[0] += size[0]; memcpy(pos2, pos1, sizeof(pos0)); pos2[1] += size[1]; memcpy(pos3, pos2, sizeof(pos0)); pos3[0] -= size[0]; mode_unshaded(); glColor4fv(&color.r); glBegin(GL_QUADS); glVertex3fv(pos0); glVertex3fv(pos1); glVertex3fv(pos2); glVertex3fv(pos3); // draw flanges // color.r /= 2; color.g /= 2; color.b /= 2; glColor4fv(&color.r); GLfloat posa0[3], posa1[3], posa2[3], posa3[3]; memcpy(posa0, pos0, sizeof(pos0)); memcpy(posa1, pos1, sizeof(pos0)); memcpy(posa2, pos2, sizeof(pos0)); memcpy(posa3, pos3, sizeof(pos0)); posa0[2] -= .2; posa1[2] -= .2; posa2[2] -= .2; posa3[2] -= .2; glVertex3fv(pos0); glVertex3fv(pos1); glVertex3fv(posa1); glVertex3fv(posa0); glVertex3fv(pos1); glVertex3fv(pos2); glVertex3fv(posa2); glVertex3fv(posa1); glVertex3fv(pos2); glVertex3fv(pos3); glVertex3fv(posa3); glVertex3fv(posa2); glVertex3fv(pos3); glVertex3fv(pos0); glVertex3fv(posa0); glVertex3fv(posa3); glEnd(); pos3[0] += margin; pos3[1] -= (margin+char_height); pos3[2] += 0.01; glColor3f(1, 1, 1); draw_text(pos3, char_height, line_width, line_spacing, text); } PROGRESS::PROGRESS( GLfloat* p, GLfloat l, GLfloat r, GLfloat in, GLfloat* c, GLfloat* ic ) { memcpy(pos, p, sizeof(pos)); len = l; rad = r; inner_rad = in; memcpy(color, c, sizeof(color)); memcpy(inner_color, ic, sizeof(inner_color)); } void PROGRESS::draw(float x) { mode_shaded(inner_color); drawCylinder(false, pos, x*len, inner_rad); mode_shaded(color); drawCylinder(false, pos, len, rad); } GRAPH_2D::GRAPH_2D(float* p, float* s, float* c, float* tc) { memcpy(pos, p, sizeof(pos)); memcpy(size, s, sizeof(size)); memcpy(color, c, sizeof(color)); memcpy(tick_color, tc, sizeof(tick_color)); } float yvec[] = {0., 1., 0.}; float xvec[] = {1., 0., 0.}; float xvecneg[] = {-1., 0., 0.}; float zvec[] = {0, 0, 1}; // draw horizontal plate from i to i+1, with height data[i] // void GRAPH_2D::draw_x(int i) { GLfloat pt[3]; double r1 = i/(double)len; double r2 = (i+1)/(double)len; glNormal3fv(yvec); pt[0] = pos[0] + r1*size[0]; pt[1] = pos[1] + data[i]*size[1]/dmax; pt[2] = pos[2]; glVertex3fv(pt); pt[0] = pos[0] + r2*size[0]; glVertex3fv(pt); pt[2] = pos[2] + size[2]; glVertex3fv(pt); pt[0] = pos[0] + r1*size[0]; glVertex3fv(pt); glNormal3fv(zvec); pt[0] = pos[0] + r1*size[0]; pt[1] = pos[1] + data[i]*size[1]/dmax; pt[2] = pos[2]+size[2]; glVertex3fv(pt); pt[1] = pos[1]; glVertex3fv(pt); pt[0] = pos[0] + r2*size[0]; glVertex3fv(pt); pt[1] = pos[1] + data[i]*size[1]/dmax; glVertex3fv(pt); } // draw vertical plate at position i, with height from data[i-1] to data[i] // void GRAPH_2D::draw_y(int i) { GLfloat pt[3]; double r1 = i/(double)len; (data[i]>data[i-1])?glNormal3fv(xvecneg):glNormal3fv(xvec); pt[0] = pos[0] + r1*size[0]; pt[1] = pos[1] + data[i-1]*size[1]/dmax; pt[2] = pos[2]; glVertex3fv(pt); pt[1] = pos[1] + data[i]*size[1]/dmax; glVertex3fv(pt); pt[2] = pos[2] + size[2]; glVertex3fv(pt); pt[1] = pos[1] + data[i-1]*size[1]/dmax; glVertex3fv(pt); } void GRAPH_2D::draw(float* d, int ln) { int i; data = d; len = ln; dmax = 0; for (i=0; i dmax) dmax = data[i]; } mode_shaded(color); glBegin(GL_QUADS); draw_x(0); for (i=1; i