#include "Renderer.h" #include "structs.h" #include "utils.h" #include "cwrappers.h" #include "Input.h" #include //Initialize static member Renderer Renderer::m_instance; void Renderer::init(int* argc, char** argv) { this->windowID = init_glut(argc,argv); this->init_opengl(); //Generate Subdivision clock_t start = clock(); for (int i = 0; i < atoi(argv[1]); i++) { Subdivision::getInstance()->performSubdivision(*(argv[2])); } std::cout << "Subdivision time: " << (clock()-start)/(float)CLOCKS_PER_SEC << " seconds.\n"; std::cout << "Generating Normals.."; this->generateNormals(); std::cout << "Done.\nGenerating Scene.."; this->create_scene(); std::cout << "Done.\n"; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX,currModelTransform); glPopMatrix(); std::cout << "Total time: " << (clock()-start)/(float)CLOCKS_PER_SEC << " seconds.\n"; std::cout << "Final number of vertices : " << (int) points->size() << std::endl; std::cout << "Final number of triangles : " << (int) triangles->size() << std::endl; } //Calculate the normals for each triangle void Renderer::generateNormals() { /* Generate normals for triangles and Vertices */ Vector tempNormal; Point a1a2, a1a3; Point a1, a2, a3; std::vector::iterator t_iter; for (t_iter = triangles->begin(); t_iter != triangles->end(); t_iter++) { a1 = points->at(t_iter->a1); a2 = points->at(t_iter->a2); a3 = points->at(t_iter->a3); a1a2 = a2 - a1; a1a3 = a3 - a1; cross(tempNormal,a1a2,a1a3); tempNormal.i *= -1; tempNormal.j *= -1; tempNormal.k *= -1; /* Store the normal for the triangle */ t_iter->normal = tempNormal; } } void Renderer::init_opengl() { // back-face culling on glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // We want to cull the back glFrontFace(GL_CW); // The vertices we get are clockwise // automatically scale normals to unit length after transformation glEnable(GL_NORMALIZE); //Flat shading glShadeModel(GL_FLAT); // clear to BLACK glClearColor(0.0, 0.0, 0.0, 1.0); // Enable depth test glEnable(GL_DEPTH_TEST); } GLint Renderer::init_glut(int* argc, char** argv) { int id; glutInit(argc,argv); /* size and placement hints to the window system */ glutInitWindowSize(vpd, vpd); glutInitWindowPosition(10,10); /* double buffered, RGB color mode */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); /* create a GLUT window (not drawn until glutMainLoop() is entered) */ id = glutCreateWindow("cs4451 project 5: Subdivision fancyness!"); /* register callbacks */ /* window size changes */ glutReshapeFunc(reshape); /* keypress handling when the current window has input focus */ glutKeyboardFunc(keyboard_event); /* mouse event handling */ glutMouseFunc(mouse_button); /* button press/release */ glutMotionFunc(button_motion); /* mouse motion w/ button down */ glutPassiveMotionFunc(passive_motion); /* mouse motion with button up */ /* window obscured/revealed event handler */ glutVisibilityFunc(NULL); /* handling of keyboard SHIFT, ALT, CTRL keys */ glutSpecialFunc(NULL); /* what to do when mouse cursor enters/exits the current window */ glutEntryFunc(NULL); /* what to do on each display loop iteration */ glutDisplayFunc(redraw); /* Create the menu */ //Create the Zoom Menu GLint menuID = glutCreateMenu(menu); glutAddMenuEntry("Zoom in (w)",Input::ZOOM_IN_EVENT); glutAddMenuEntry("Zoom out (s)",Input::ZOOM_OUT_EVENT); glutAddMenuEntry("Animate (a)",Input::ANIMATE_EVENT); glutAddMenuEntry("Lines Only (l)",Input::LINES_EVENT); glutAddMenuEntry("Full Model (f)",Input::FULL_EVENT); glutSetMenu(menuID); glutAttachMenu(GLUT_RIGHT_BUTTON); return id; } void Renderer::render() { //Initialize glutSetWindow(windowID); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* set the projection matrix */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(viewDist,1.0,15.0,25.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); init_lightsource(); glTranslatef(0,0,-20); if (!animate) { glMultMatrixf(currModelTransform); } else { glMultMatrixf(currModelTransform); this->rotAngle1 += this->dAngle1; this->rotAngle2 += this->dAngle2; glRotatef(this->rotAngle1,1,2,3); glRotatef(this->rotAngle2,-2,-1,0); } #ifdef SCENELIST glCallList(this->sceneID); #else this->create_scene(); #endif //Draw glFlush(); glutSwapBuffers(); if (animate) { glutPostRedisplay(); } } void Renderer::window_resize(GLint vpw, GLint vph) { glutSetWindow(this->windowID); /* maintain a square viewport, not too small, not too big */ if( vpw < vph ) vpd = vph; else vpd = vpw; if( vpd < VPD_MIN ) vpd = VPD_MIN; if( vpd > VPD_MAX ) vpd = VPD_MAX; glViewport(0, 0, vpd, vpd); glutReshapeWindow(vpd, vpd); glutPostRedisplay(); } void Renderer::set_material_properties(GLfloat r, GLfloat g, GLfloat b) { GLfloat mat_specular[4] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_ambient_and_diffuse[4] = { 0.5, 0.5, 0.5, 1.0 }; GLfloat mat_shininess[1] = { 0.0 }; mat_specular[0] = mat_ambient_and_diffuse[0] = r; mat_specular[1] = mat_ambient_and_diffuse[1] = g; mat_specular[2] = mat_ambient_and_diffuse[2] = b; glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient_and_diffuse); } void Renderer::init_lightsource() { GLfloat light_ambient[] = { .1, .1, .1, 1.0 }; GLfloat light_diffuse[] = { .7, .7, .7, 1.0 }; GLfloat light_specular[] = { 0, 0, 0, 1.0 }; GLfloat light_position[] = { 2, 2, 2, 0.0 }; glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0); glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.0); glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.0); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } #ifdef SCENELIST GLuint Renderer::init_sceneList() { GLuint sceneList = glGenLists(1); Point a1, a2, a3; Vector tempNormal; std::vector::iterator t_iter; glNewList(sceneList,GL_COMPILE); glBegin(GL_TRIANGLES); for (t_iter = triangles->begin(); t_iter != triangles->end(); t_iter++) { a1 = points->at(t_iter->a1); a2 = points->at(t_iter->a2); a3 = points->at(t_iter->a3); tempNormal = t_iter->normal; glNormal3f(tempNormal.i, tempNormal.j, tempNormal.k); glVertex3f(a1.x, a1.y, a1.z); glVertex3f(a2.x, a2.y, a2.z); glVertex3f(a3.x, a3.y, a3.z); } glEnd(); glEndList(); return sceneList; } GLvoid Renderer::create_scene() { GLuint scene = this->init_sceneList(); GLuint sceneList = glGenLists(1); glNewList(sceneList,GL_COMPILE); set_material_properties(1.0,1.0,1.0); Point Max; Point Min; Point Center; std::vector::iterator p_iter; p_iter = points->begin(); Max.x = Min.x = p_iter->x; Max.y = Min.y = p_iter->y; Max.z = Min.z = p_iter->z; p_iter++; for(; p_iter != points->end(); p_iter++) { if (p_iter->x > Max.x) { Max.x = p_iter->x; } else if (p_iter->x < Min.x) { Min.x = p_iter->x; } if (p_iter->y > Max.y) { Max.y = p_iter->y; } else if (p_iter->y < Min.y) { Min.y = p_iter->y; } if (p_iter->z > Max.z) { Max.z = p_iter->z; } else if (p_iter->z < Min.z) { Min.z = p_iter->z; } } Center.x = (Max.x + Min.x) / 2.; Center.y = (Max.y + Min.y) / 2.; Center.z = (Max.z + Min.z) / 2.; float scaleX, scaleY, scaleZ; scaleX = (Max.x - Min.x) / 2.; scaleY = (Max.y - Min.y) / 2.; scaleZ = (Max.z - Min.z) / 2.; float scaleFactor; scaleFactor = scaleX > scaleY ? scaleX : scaleY; scaleFactor = scaleZ > scaleFactor ? scaleZ : scaleFactor; scaleFactor = 1. / scaleFactor; glPushMatrix(); glTranslatef(0.-(Center.x*scaleFactor),0.-(Center.y*scaleFactor),0.-(Center.z*scaleFactor)); glScalef(scaleFactor,scaleFactor,scaleFactor); glCallList(scene); glPopMatrix(); glEndList(); this->sceneID = sceneList; } #else GLuint Renderer::init_sceneList() { Point a1, a2, a3; Vector tempNormal; std::vector::iterator t_iter; glBegin(GL_TRIANGLES); for (t_iter = triangles->begin(); t_iter != triangles->end(); t_iter++) { a1 = points->at(t_iter->a1); a2 = points->at(t_iter->a2); a3 = points->at(t_iter->a3); tempNormal = t_iter->normal; glNormal3f(tempNormal.i, tempNormal.j, tempNormal.k); glVertex3f(a1.x, a1.y, a1.z); glVertex3f(a2.x, a2.y, a2.z); glVertex3f(a3.x, a3.y, a3.z); } glEnd(); return 0; } GLvoid Renderer::create_scene() { set_material_properties(1.0,1.0,1.0); Point Max; Point Min; Point Center; std::vector::iterator p_iter; p_iter = points->begin(); Max.x = Min.x = p_iter->x; Max.y = Min.y = p_iter->y; Max.z = Min.z = p_iter->z; p_iter++; for(; p_iter != points->end(); p_iter++) { if (p_iter->x > Max.x) { Max.x = p_iter->x; } else if (p_iter->x < Min.x) { Min.x = p_iter->x; } if (p_iter->y > Max.y) { Max.y = p_iter->y; } else if (p_iter->y < Min.y) { Min.y = p_iter->y; } if (p_iter->z > Max.z) { Max.z = p_iter->z; } else if (p_iter->z < Min.z) { Min.z = p_iter->z; } } Center.x = (Max.x + Min.x) / 2.; Center.y = (Max.y + Min.y) / 2.; Center.z = (Max.z + Min.z) / 2.; float scaleX, scaleY, scaleZ; scaleX = (Max.x - Min.x) / 2.; scaleY = (Max.y - Min.y) / 2.; scaleZ = (Max.z - Min.z) / 2.; float scaleFactor; scaleFactor = scaleX > scaleY ? scaleX : scaleY; scaleFactor = scaleZ > scaleFactor ? scaleZ : scaleFactor; scaleFactor = 1. / scaleFactor; glPushMatrix(); glTranslatef(0.-(Center.x*scaleFactor),0.-(Center.y*scaleFactor),0.-(Center.z*scaleFactor)); glScalef(scaleFactor,scaleFactor,scaleFactor); this->init_sceneList(); glPopMatrix(); } #endif