Week 10 Assignment

Yasmin Elayat

 

Problem 2. Add a function called calculateNormal() to the Mesh class that calculates and stores a normal vector for every point in the mesh. This normal vector should be based upon the normal vectors of the faces surrounding the point.
Problem 3. Add a function called drawShadedSolid2 that draws the mesh as a solid form and utilizes the per-point normal vectors. This function does not need to calculate the shading, since that is now done by the OpenGL lighting system.
void Mesh::calculateNormal() {

    //   1. set all normals to (0,0,0)
    for(int i=0; i<_w; i++) {
            for(int j=0; j<_h; j++) {
                    _norm[i][j] = Vec3d(0,0,0);

            }
     }  
     
     //   2. calculate normals for every triangle and add each normal to
    //        the normals of every point in the tirangle
    
         
      for(int i=0; i<_w-1; i++) { //_w -1 ? and _h - 1?
            for(int j=0; j<_h-1; j++) {
                    
                    //3 pts of triangle1
                    Vec3d A = grid[i][j];
                    Vec3d B = grid[i+1][j];
                    Vec3d C = grid[i+1][j+1];
                    //3 pts of triangle 2 
                    Vec3d D = grid[i][j];    
                    Vec3d E = grid[i][j+1];        
                    Vec3d F = grid[i+1][j+1]; 
                                                   
                    //define vetors within triangle
                    Vec3d AB = B - A;
                    Vec3d AC = C - A;
                    Vec3d DE = E - D;
                    Vec3d DF = F - D; 
                    
                    //compute normal to triangle
                    Vec3d norm1 = AB.cross(AC);  
                    Vec3d norm2 = DE.cross(DF);
                    
                    //add each triangle's normal to it's 3 points
                    _norm[i][j] = _norm[i][j] + norm1;
                    _norm[i+1][j] =  _norm[i+1][j] +norm1;
                    _norm[i+1][j+1] =  _norm[i+1][j+1] + norm1;

                    _norm[i][j] = _norm[i][j]  + norm2;
                    _norm[i][j+1] = _norm[i][j+1] + norm2;
                    _norm[i+1][j+1] = _norm[i+1][j+1] + norm2;
            }
     }  
     
     //    3. normalize all the normals
      for(int i=0; i<_w; i++) {
            for(int j=0; j<_h; j++) {
                     //normalize normal to triangle (len = 1.0)
                    _norm[i][j].normalize(); // = _norm[i][j]/_norm[i][j].getLength();
            }
     }  
}     

void Mesh::drawShadedSolid2() {
     glColor3f(0.1,0.3,0);     
     for(int i=0; i<_w-1; i++) {
            for(int j=0; j<_h-1; j++) {
                    
                    glNormal3f(_norm[i][j].x,_norm[i][j].y,_norm[i][j].z);
                    glBegin(GL_TRIANGLES);
                    glVertex3fv((float*)&grid[i][j]);                      
                    glVertex3fv((float*)&grid[i+1][j]); 
                    glVertex3fv((float*)&grid[i+1][j+1]); 
                    glEnd();
                     
                    glBegin( GL_TRIANGLES);                       
                    glVertex3fv((float*)&grid[i][j]); 
                    glVertex3fv((float*)&grid[i][j+1]); 
                    glVertex3fv((float*)&grid[i+1][j+1]); 
                    glEnd();
            }
     }
                    

}
	  

 

 

Problem 4. Add a function called makeExtrusionOnPath. This function should take as inputs an array of points that define the extrusion shape and an array of points that define the extrusion path. For this to work correctly, the number of point in the extrusion shape should equal width of the Mesh. Likewise, the number of points in the extrusion path should equal the height of the Mesh.

void Mesh::makeExtrusionOnPath(Vec3d* shape, Vec3d* path) {
     //shape[_w] and path[_h]
    //  for every point on the path, calculate:   
    Vec3d side[_h] ;
    Vec3d norm[_h];
    
    
    for(int i = 0; i < _h; i++) { //100 points in path
               Vec3d A, B;
               if(i == 0) { 
                     A = path[i];
                     B = path[i+1];
               }
               else if( i == (_h - 1)) {
                     A = path[i-1];
                     B = path[i];
               }
               else {
                     A = path[i-1];
                     B = path[i+1];
                }     
               
               //1. a parallel vector that is based upon the previous point and the next point
               Vec3d P = B - A; //(x)
               //V.normalize();
               
               //2. a normal vector that is equal to the parallel vector crossed with the up vector (0,1,0)
               Vec3d UpVector(0,1,0);
               Vec3d N = P.cross(UpVector); //(y) or  P.cross(UpVector); 
               
               //3. a side vector that is equal to the normal vector crossed with the parallel vector
               Vec3d D = N.cross(P); //depth/side vector (z)
               
               //4. normalize both the side and the normal vectors
               N.normalize();
               D.normalize(); 
              // norm[i] = N;
               //side[i] = D;
               for(int j = 0; j < _w; j++ ) {
               //5. for very every point in the shape being extruded, calculate
                    //a. point O = path[i] + ( side vector * shape[j].x ) + ( normal vector * shape[j].y )
                    //b. set grid[i][j] to O
                       Vec3d O = path[i] + (D*shape[j].x) + (N*shape[j].y);
                       grid[j][i] = O; 
               }        
    }         

}     
	  


 

Problem 5. Add a function called makeScaledExtrusionOnPath. This function should be identical to the makeExtrusionOnPath function, but should also take as an input an array of scaling parameters. The array should have as many scaling parameters as the extrusion path (which is also equal to the height of the Mesh.) Each scaling parameter should be used to scale the extruded shape at each point along the path.

void Mesh::makeScaledExtrusionOnPath(Vec3d* shape, Vec3d* path, float* scale) {
     //shape[_w] and path[_h] and scale[_h]
         //  for every point on the path, calculate:   
    Vec3d side[_h] ;
    Vec3d norm[_h];
    
    
    for(int i = 0; i < _h; i++) { //100 points in path
               Vec3d A, B;
               if(i == 0) { 
                     A = path[i];
                     B = path[i+1];
               }
               else if( i == (_h - 1)) {
                     A = path[i-1];
                     B = path[i];
               }
               else {
                     A = path[i-1];
                     B = path[i+1];
                }     
               
               //1. a parallel vector that is based upon the previous point and the next point
               Vec3d P = B - A; //(x)
               //V.normalize();
               
               //2. a normal vector that is equal to the parallel vector crossed with the up vector (0,1,0)
               Vec3d UpVector(0,1,0);
               Vec3d N = P.cross(UpVector); //(y) or  P.cross(UpVector); 
               
               //3. a side vector that is equal to the normal vector crossed with the parallel vector
               Vec3d D = N.cross(P); //depth/side vector (z)
               
               //4. normalize both the side and the normal vectors
               N.normalize();
               D.normalize(); 
              // norm[i] = N;
               //side[i] = D;
               for(int j = 0; j < _w; j++ ) {
               //5. for very every point in the shape being extruded, calculate
                    //a. point O = path[i] + ( side vector * shape[j].x ) + ( normal vector * shape[j].y )
                    //b. set grid[i][j] to O
                       Vec3d O = path[i] + (D*shape[j].x *scale[i] ) + (N*shape[j].y*scale[i] );
                       grid[j][i] = O; 
               }        
    }
}

void makeScaledExtrusionShape() {
      Vec3d shape[30];
      Vec3d path[100];
      float scale[100];
      for (int i = 0; i < 30; i++) {
         float A = 2.0*3.14159 / (30.0-1.0)*i;
         float rad = 50; //20;
         shape[i].x = rad*cos(A); //moving it left by 100 makes it a torus
         shape[i].y = rad*sin(A);
         shape[i].z = 0;
     }
              glColor3d(1,0,0);
         glBegin(GL_LINE_LOOP);
     for(int j = 0; j < 100; j++) {
                        
         srand ( 10 );
         path[j].x = 100*sin(j) - 800;
         path[j].z = j*20 - 800;         
         path[j].y = 50*j - 800;//50*sin(path[j].x);
         
         scale[j] = ((j+1)*10)/100;

         glVertex3f( path[j].x, path[j].y, path[j].z);
     }       
     glEnd();
     
     myMesh->makeScaledExtrusionOnPath(shape,path,scale);     
}     
	  

Problem 6. Utilizing the makeScaledExtrusionOnPath function, create a cornucopia.

void makeScaledExtrusionShape2() {
      Vec3d shape[30];
      Vec3d path[100];
      float scale[100];
      for (int i = 0; i < 30; i++) {
         float A = 2.0*3.14159 / (30.0-1.0)*i;
         float rad = 50; //20;
         shape[i].x = rad*cos(A) - 100; //moving it left by 100 makes it a torus
         shape[i].y = rad*sin(A);
         shape[i].z = 0;
     }
              glColor3d(1,0,0);
         glBegin(GL_LINE_LOOP);
     for(int j = 0; j < 100; j++) {
                        
         path[j].x = 5*j - 800;
         path[j].z = j*2  - 800;         
         path[j].y = 5*j  - 800;
         
         scale[j] = j*.1; //((j+1)*10)/100;

         glVertex3f( path[j].x, path[j].y, path[j].z);
     }       
     glEnd();
     
     myMesh->makeScaledExtrusionOnPath(shape,path,scale);     
}