#include #include #include #include #include "shape.h" #include "geometry.h" Triangle::Triangle(Tuple& v0, Tuple& v1, Tuple& v2) { // initialize vertices u[0]=v0; u[1]=v1; u[2]=v2; color=Tuple(1,1,1); //default color is white } Triangle::Triangle(Tuple& v0, Tuple& v1, Tuple& v2, Tuple col) { // initialize vertices u[0]=v0; u[1]=v1; u[2]=v2; color=Tuple(col[0],col[1],col[2]); } Triangle::Triangle(const Triangle& toCopy) { if (this != &toCopy) { u[0]=toCopy.u[0]; u[1]=toCopy.u[1]; u[2]=toCopy.u[2]; color = toCopy.color; } } Triangle& Triangle::operator = (const Triangle &toCopy) { if (this != &toCopy) { u[0]=toCopy.u[0]; u[1]=toCopy.u[1]; u[2]=toCopy.u[2]; color = toCopy.color; } return *this; } Tuple& Triangle::operator [] (int i) { assert(0<=i && i<=2); return u[i]; } const Tuple& Triangle::operator [] (int i) const { assert(0<=i && i<=2); return u[i]; } void Triangle::drawRainbow(void) { glBegin(GL_TRIANGLES); glColor3f(1,0,0); glVertex3f(u[0][0],u[0][1],u[0][2]); glColor3f(0,1,0); glVertex3f(u[1][0],u[1][1],u[1][2]); glColor3f(0,0,1); glVertex3f(u[2][0],u[2][1],u[2][2]); glEnd(); } void Triangle::drawRandom(void) { glColor3f((float) rand()/ (float) RAND_MAX, (float) rand()/ (float) RAND_MAX, (float) rand()/ (float) RAND_MAX); glBegin(GL_TRIANGLES); glVertex3f(u[0][0],u[0][1],u[0][2]); glVertex3f(u[1][0],u[1][1],u[1][2]); glVertex3f(u[2][0],u[2][1],u[2][2]); glEnd(); } void Triangle::draw(void) { glColor3f(color[0],color[1],color[2]); glBegin(GL_TRIANGLES); glVertex3f(u[0][0],u[0][1],u[0][2]); glVertex3f(u[1][0],u[1][1],u[1][2]); glVertex3f(u[2][0],u[2][1],u[2][2]); glEnd(); } /********************************************************/ /* */ /* */ /* This method standardizes a triangle. */ /* When the method concludes */ /* standard contains the standardized triangle */ /* forwardTransform contains the transform from */ /* real world coordinates to the */ /* standardized frame */ /* */ /* We assume the triangle class has vertices stored */ /* in float u[3]. */ /* */ /* We assume the triangle class has an indexing */ /* method t[i], which returns the i-th vertex of */ /* of triangle t. */ /* */ /********************************************************/ Triangle Triangle::standardize(float forwardTransform[], float backwardTransform[]) const { // we assume that the triangle is valid; i.e. the vertices are // distinct and non-collinear -- if not this will BOMB! // you need to take care of this somewhere float myMatrix[16]; // we'll use this to store transforms float sigma, phi; // angles of rotation Tuple v; // axis of rotation Tuple x(1,0,0); // x axis Triangle standard=*this; // this stores the standardized // triangle glPushMatrix(); // save the current matrix // translate our triangle so the first vertex is at the origin standard[1] -= standard[0]; standard[2] -= standard[0]; standard[0] = Tuple(0,0,0); // rotate our triangle to align last edge with the x axis // first we find the axis of rotation v // then we find the angle through which we need to rotate phi Tuple w = standard[2]; // set w to the last edge w.normalize(); // normalize it if (w != x && w!= -x) { // when w is not on the x-axis // the vector of rotation v is found by taking a cross product of // w and the x-vector v = w.cross(x); v.normalize(); // the angle of rotation is found by taking the arcos of // the dot product of w and x // we then convert to degrees phi = (float) acos((double) w.dot(x)); phi *= 360.f/(2.0f*3.14159f); } else { // when w is on the x-axis v=Tuple(0,1,0); // the axis of rotation is the y-vector if (w == x) // the angle is either 0 or 180 degrees phi=0; else phi = 180; } // have openGL compute the rotation transform and write it into myMatrix glLoadIdentity(); glRotatef(phi,v[0],v[1],v[2]); glGetFloatv(GL_MODELVIEW_MATRIX,myMatrix); // update second and third vertex -- first won't change for (int i=1; i<=2; i++) { Tuple tmp(0,0,0); for (int j=0; j<3; j++) { // for each row of the matrix for (int k=0; k<3; k++) { // for each column tmp[j] += myMatrix[j+4*k]*standard[i][k]; // the matrix is column-major } } standard[i]=tmp; } // correct for rounding errors -- third vertex should lie on x axis standard[2][1]=0; standard[2][2]=0; // rotate our triangle about the x axis to bring second vertex into y=0 plane w=standard[1]; // set w to the first edge w[0]=0.0f; // w into the x=0 plane // compute the angle of rotation sigma in degrees sigma= (float) acos((double) (w[2]/w.length())); sigma *= 360.f/(2.0f*3.14159f); // axis of rotation is either +x or -x if (w[1]<0) x *= -1.0f; // have openGL compute the transform and write it into myMatrix glLoadIdentity(); glRotatef(sigma,x[0],x[1],x[2]); glGetFloatv(GL_MODELVIEW_MATRIX,myMatrix); // update the second vertex -- the first and third won't change Tuple tmp(0,0,0); for (int j=0; j<3; j++) { // for each row of the matrix for (int k=0; k<3; k++) { // for each column tmp[j] += myMatrix[j+4*k]*standard[1][k]; // the matrix is column-major } } standard[1]=tmp; // correct for rounoff errors standard[1][1]=0; // now compute the single forward (standardizing) transform glLoadIdentity(); glRotatef(sigma,x[0],x[1],x[2]); glRotatef(phi,v[0],v[1],v[2]); glTranslatef(-this->u[0][0],-this->u[0][1], -this->u[0][2]); glGetFloatv(GL_MODELVIEW_MATRIX,forwardTransform); // now compute the single backward transform glLoadIdentity(); glTranslatef(this->u[0][0],this->u[0][1], this->u[0][2]); glRotatef(-phi,v[0],v[1],v[2]); glRotatef(-sigma,x[0],x[1],x[2]); glGetFloatv(GL_MODELVIEW_MATRIX,backwardTransform); glPopMatrix(); // restore current matrix Triangle oldTriangle=standard; Tuple tup; tup=this->u[0]; standard[0]=tup.matrixMultiply(forwardTransform); tup=this->u[1]; standard[1]=tup.matrixMultiply(forwardTransform); tup=this->u[2]; standard[2]=tup.matrixMultiply(forwardTransform); return standard; } Edge::Edge(Tuple v1, Tuple v2) { // initialize vertices u[0]=v1; u[1]=v2; } Edge& Edge::operator = (const Edge &toCopy) { if (this != &toCopy) { u[0]=toCopy.u[0]; u[1]=toCopy.u[1]; } return *this; } Tuple& Edge::operator [] (int i) { assert(0<=i && i<=1); return u[i]; } const Tuple& Edge::operator [] (int i) const { assert(0<=i && i<=2); return u[i]; } /********************************************************/ /* */ /* */ /* This method standardizes a edge. */ /* When the method concludes */ /* standard contains the standardized edge */ /* forwardTransform contains the transform from */ /* real world coordinates to the */ /* standardized frame */ /* */ /* We assume the edge class has vertices stored */ /* in float u[2]. */ /* */ /* We assume the edge class has an indexing */ /* method e[i], which returns the i-th vertex of */ /* of edge t. */ /* */ /********************************************************/ Edge Edge::standardize(float forwardTransform[], float backwardTransform[]) const { // we assume that the edge is valid; i.e. the vertices are // distinct -- if not this will BOMB! // you need to take care of this somewhere float myMatrix[16]; // we'll use this to store transforms float phi; // angle of rotation Tuple v; // axis of rotation Tuple x(1,0,0); // x axis Edge standard=*this; // this stores the standardized // edge glPushMatrix(); // save the current matrix // translate our edge so the first vertex is at the origin standard[1] -= standard[0]; standard[0] = Tuple(0,0,0); // rotate our edge to align last edge with the x axis // first we find the axis of rotation v // then we find the angle through which we need to rotate phi Tuple w = standard[1]; // set w to the last edge w.normalize(); // normalize it if (w != x && w!= -x) { // when w is not on the x-axis // the vector of rotation v is found by taking a cross product of // w and the x-vector v = w.cross(x); v.normalize(); // the angle of rotation is found by taking the arcos of // the dot product of w and x // we then convert to degrees phi = (float) acos((double) w.dot(x)); phi *= 360.f/(2.0f*3.14159f); } else { // when w is on the x-axis v=Tuple(0,1,0); // the axis of rotation is the y-vector if (w == x) // the angle is either 0 or 180 degrees phi=0; else phi = 180; } // have openGL compute the rotation transform and write it into myMatrix glLoadIdentity(); glRotatef(phi,v[0],v[1],v[2]); glGetFloatv(GL_MODELVIEW_MATRIX,myMatrix); // update second vertex -- first won't change int i=1; Tuple tmp(0,0,0); for (int j=0; j<3; j++) { // for each row of the matrix for (int k=0; k<3; k++) { // for each column tmp[j] += myMatrix[j+4*k]*standard[i][k]; // the matrix is column-major } } standard[i]=tmp; // correct for rounding errors -- third vertex should lie on x axis standard[1][1]=0; standard[1][2]=0; // now compute the single forward (standardizing) transform glLoadIdentity(); glRotatef(phi,v[0],v[1],v[2]); glTranslatef(-this->u[0][0],-this->u[0][1], -this->u[0][2]); glGetFloatv(GL_MODELVIEW_MATRIX,forwardTransform); // now compute the single backward transform glLoadIdentity(); glTranslatef(this->u[0][0],this->u[0][1], this->u[0][2]); glRotatef(-phi,v[0],v[1],v[2]); glGetFloatv(GL_MODELVIEW_MATRIX,backwardTransform); glPopMatrix(); // restore current matrix Edge oldEdge=standard; Tuple tup; tup=this->u[0]; standard[0]=tup.matrixMultiply(forwardTransform); tup=this->u[1]; standard[1]=tup.matrixMultiply(forwardTransform); return standard; }