/********************************************************/ /* */ /* */ /* 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 an array of tuples: u[3]. */ /* */ /* We assume the triangle class has an indexing */ /* method t[i], which returns the i-th vertex of */ /* of triangle t. */ /* */ /********************************************************/ void Triangle::standardize(void) 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 float forwardTransform[16]; 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); glPopMatrix(); // restore current matrix }