/****************************************************************************** * SAGE - Scalable Adaptive Graphics Environment * Copyright (C) 2004 Electronic Visualization Laboratory, * University of Illinois at Chicago * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the distribution. * * Neither the name of the University of Illinois at Chicago nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Direct questions, comments etc about SAGE to bijeong@evl.uic.edu *****************************************************************************/ //Shalini Venkataraman //A simple glut program that draws spheres and cones, reads the frame buffer //and sends it across to a display client //Feb 2004 // //modified by Byungil Jeong //July 2004 #include #include #include #if defined(__APPLE__) #include #else #include #endif #include #ifdef WIN32 #include "gettimeofday.hxx" #else #include #include #endif // headers for SAGE #include "sail.h" #include "misc.h" #define PI 3.1415926535898f #define DEG_TO_RAD PI/180.0f #define TRANSLATION_RATE 0.2f #define ROTATION_RATE 0.01f enum {SPHERE = 1, CONE}; enum {X, Y, Z}; int winWidth = 400, winHeight = 400; bool refresh = false; int cnt, target; float rgbReadTime; GLubyte *rgbBuffer = 0; GLfloat transformMatrix[] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0}; float eyeX, eyeY, eyeZ; //for the camera position for glulookat float centreX, centreY, centreZ; //the point the camera looks at in glulookat float rot = 0.0f; sail sageInf; // sail object double getTimeInSecs() { const double oneMicroSec = 0.000001; struct timeval timeSec; gettimeofday(&timeSec, NULL); return (((double) timeSec.tv_sec) + (((double) timeSec.tv_usec) * oneMicroSec)); } void rotateCameraY(float rot_inc) { rot += rot_inc; centreX = eyeX - sin(rot); centreZ = eyeZ - cos(rot); } void moveCameraZ(float trans_inc) { float inc_x = -trans_inc*sin(rot); //increment in camera X for the given translation float inc_z = -trans_inc*cos(rot); //increment in camera Y for the given translation eyeX += inc_x; eyeZ += inc_z; centreX += inc_x; centreZ += inc_z; } void moveCameraY(float trans_inc) { eyeY += trans_inc; centreY += trans_inc; } GLfloat *make_texture(int maxs, int maxt) { int s, t; static GLfloat *texture; texture = (GLfloat *)malloc(3*maxs * maxt * sizeof(GLfloat)); for(t = 0; t < maxt; t++) { for(s = 0; s < maxs; s++) { texture[s*3 + 3*maxs * t] = 0.0f; texture[s*3 + 3*maxs * t+1] = 0.4f*(((s >> 4) & 0x1) ^ ((t >> 4) & 0x1)); texture[s*3 + 3*maxs * t+2] = 0.0f*(((s >> 4) & 0x1) ^ ((t >> 4) & 0x1)); } } return texture; } //writes the grabbed framebuffer to a ppm file void writePPM(const char* filename) { if (!rgbBuffer) return; FILE* fp = fopen(filename, "wb"); if (fp==NULL) { printf("PPM ERROR (WritePPM) : unable to open %s!\n",filename); return; } fprintf(fp, "P6\n%d %d\n255\n", winWidth, winHeight); fwrite(rgbBuffer,sizeof(GLubyte),winWidth*winHeight*3,fp); fclose(fp); printf("RGB data written to file %s\n",filename); } //key handler //'s' - will save the grabbed image to a ppm file void key(unsigned char key, int x, int y) { switch(key) { case 's': //save the read pixels to out.ppm writePPM("out.ppm"); break; case 't': //display time taken for readpixels printf("Frame Buffer Readback Time: %dx%d %f \n",winWidth, winHeight, rgbReadTime); break; case '\033': sageInf.shutdown(); exit(0); break; } glutPostRedisplay(); } // The function called whenever a "special" key is pressed. void special(int key, int x, int y) { switch (key) { case GLUT_KEY_UP: moveCameraZ(TRANSLATION_RATE); break; case GLUT_KEY_DOWN: moveCameraZ(-TRANSLATION_RATE); break; case GLUT_KEY_LEFT: rotateCameraY(ROTATION_RATE); break; case GLUT_KEY_RIGHT: rotateCameraY(-ROTATION_RATE); break; case GLUT_KEY_PAGE_UP: moveCameraY(TRANSLATION_RATE); break; case GLUT_KEY_PAGE_DOWN: moveCameraY(-TRANSLATION_RATE); break; } glutPostRedisplay(); } void motion(int x, int y) { y = winHeight - y; glutPostRedisplay(); } /* //reallocate the rgbBuffer depending on the new window dimesions void reshape(int width, int height) { glViewport(0, 0, width, height); winWidth = width; winHeight = height; if (rgbBuffer) delete [] rgbBuffer; rgbBuffer = new GLubyte[width*height*3]; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0,(GLfloat)width/ (GLfloat)height, 0.5, 100.0); glMatrixMode(GL_MODELVIEW); } */ void mouse(int button, int state, int x, int y) { y = winHeight - y; if(state == GLUT_DOWN) { switch(button) { case GLUT_LEFT_BUTTON: //rotate break; case GLUT_MIDDLE_BUTTON: //zoom break; case GLUT_RIGHT_BUTTON: break; } } else {//GLUT_UP switch(button) { case GLUT_LEFT_BUTTON: break; case GLUT_MIDDLE_BUTTON: break; case GLUT_RIGHT_BUTTON: break; } } glutPostRedisplay(); } //display function void redraw(void) { /* material properties for objects in scene */ static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f}; static GLfloat sphere_mat[] = {0.5f, 0.0f, 1.f, 1.f}; static GLfloat cone_mat[] = {1.0f, 0.5f, 0.0f, 1.f}; static GLfloat sphere_mat2[] = {1.0f, 0.0f, 0.5f, 1.f}; static GLfloat cone_mat2[] = {0.0f, 0.5f, 1.0f, 1.f}; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glClearColor(0.0, 0.0, 0.2, 0.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(eyeX, eyeY, eyeZ, centreX, centreY, centreZ, 0.0,1.0,0.0); /* ** Note: wall verticies are ordered so they are all front facing ** this lets me do back face culling to speed things up. */ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glNormal3f(0.f, 1.f, 0.f); glTexCoord2i(0, 0); glVertex3f(-6.f, -4.f, -2.f); glTexCoord2i(1, 0); glVertex3f( 6.f, -4.f, -2.f); glTexCoord2i(1, 1); glVertex3f( 6.f, -4.f, -15.f); glTexCoord2i(0, 1); glVertex3f(-6.f, -4.f, -15.f); glEnd(); glDisable(GL_TEXTURE_2D); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat); glPushMatrix(); glTranslatef(-3.f, 0.5f, -10.f); glScalef(1, 1, 1); glCallList(SPHERE); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat); glPushMatrix(); glTranslatef(0.f, 0.3f, -3.f); glRotatef(30.f, 2.f, 0.0, -1.0f); glScalef(1.0, 1.0, 1.0); glCallList(CONE); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat2); glPushMatrix(); glTranslatef(-2.f, -2.f, -7.f); glScalef(1, 1, 1); glCallList(SPHERE); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat2); glPushMatrix(); glTranslatef(4.f, -2.f, -13.f); glRotatef(-45.f, 1.f, 0.0f, 0.0f); glScalef(0.8, 0.8, 0.8); glCallList(CONE); glPopMatrix(); //finished drawing. At this point capture the frame buffer //expensive new!! TODO: put this in reshape double prevtime = getTimeInSecs(); glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, rgbBuffer); rgbReadTime = getTimeInSecs()-prevtime; //TODO-send it to QUANTA sageInf.swapBuffer(); rgbBuffer = (GLubyte *)sageInf.getBuffer(); // if (refresh) { // cnt++; // if (cnt >= target) // refresh = false; // } glutSwapBuffers(); } void update(int value) { //std::cout << "swap buffer " << winWidth << "," << winHeight << std::endl; // sageInf.swapBuffer((void *)rgbBuffer); // sageInf.mainLoop(); //glutPostRedisplay(); sageMessage msg; if (sageInf.checkMsg(msg, false) > 0) { switch (msg.getCode()) { case APP_QUIT : { exit(0); break; } //case APP_REFRESH_FRAME : { //glutPostRedisplay(); //refresh = true; //target = atoi((char *)msg.getData()); //cnt = 0; //break; // } } } // if (refresh) { // glutPostRedisplay(); // } glutTimerFunc(50, update, 1); } main(int argc, char *argv[]) { GLfloat *tex; static GLfloat lightpos[] = {10.f, 10.f, -20.0f, 1.f}; GLUquadricObj *sphere, *cone, *base; glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE); glutInitWindowSize(winWidth,winHeight); glutCreateWindow("sage render"); glutDisplayFunc(redraw); //glutIdleFunc(redraw); glutKeyboardFunc(key); glutMouseFunc(mouse); glutMotionFunc(motion); glutSpecialFunc(special); // glutReshapeFunc(reshape); glViewport(0, 0, winWidth, winHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0,(GLfloat)winWidth/ (GLfloat)winHeight, 0.5, 100.0); glMatrixMode(GL_MODELVIEW); //glutFullScreen(); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, lightpos); glCullFace(GL_BACK); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //create the display list to draw a sphere glNewList(SPHERE, GL_COMPILE); sphere = gluNewQuadric(); gluSphere(sphere, 1.f, 20, 20); gluDeleteQuadric(sphere); glEndList(); //create the display list to draw a cone glNewList(CONE, GL_COMPILE); cone = gluNewQuadric(); base = gluNewQuadric(); glRotatef(-90.f, 1.f, 0.f, 0.f); gluQuadricOrientation(base, GLU_INSIDE); gluDisk(base, 0., 1., 20, 1); gluCylinder(cone, 1., 0., 2., 20, 20); gluDeleteQuadric(cone); gluDeleteQuadric(base); glEndList(); //create a 2D texture for our floor tex = make_texture(256, 256); glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_FLOAT, tex); free(tex); eyeX = eyeY = centreX = centreY = 0.0f; eyeZ = 10.0f; centreZ = 9.0f; glutTimerFunc(100, update, 1); int appID; if (argc < 2) appID = 0; else appID = atoi(argv[1]); int nodeID; if (argc < 3) nodeID = 0; else nodeID = atoi(argv[2]); sailConfig cfg; cfg.init("render.conf"); // every app has a config file named "appName.conf" std::cout << "SAIL configuration was initialized by render.conf" << std::endl; cfg.setAppName("render"); cfg.rank = nodeID; //cfg.appID = appID; //appLauncher will do this cfg.resX = winWidth; cfg.resY = winHeight; sageRect renderImageMap; renderImageMap.left = 0.0; renderImageMap.right = 1.0; renderImageMap.bottom = 0.0; renderImageMap.top = 1.0; cfg.imageMap = renderImageMap; cfg.pixFmt = PIXFMT_888; cfg.rowOrd = BOTTOM_TO_TOP; cfg.master = true; sageInf.init(cfg); std::cout << "sail initialized " << std::endl; if (rgbBuffer) delete [] rgbBuffer; rgbBuffer = (GLubyte *)sageInf.getBuffer(); glutMainLoop(); return 0; }