Files
GTSchoolShit/CS4451/proj5/Renderer.cpp
2025-06-07 01:59:34 -04:00

442 lines
11 KiB
C++

#include "Renderer.h"
#include "structs.h"
#include "utils.h"
#include "cwrappers.h"
#include "Input.h"
#include <GL/glut.h>
//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<Triangle>::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<Triangle>::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<Point>::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<Triangle>::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<Point>::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