Week 10 Assignment (desc)

Younghyun Chung

 

Problem 1. Add the OpenGL lighting code to your project. This code may be placed in the init() function or in the displayFunc(), if you want to move or change the light.

// inside of init()

	// turn on gl lighting
	glEnable( GL_LIGHTING );
	
	// turn on first light
	glEnable( GL_LIGHT0 );
	
	// set up lighting parameters
	float  ambientLight[4] = { 0.2, 0.2, 0.2, 1.0 }; // r g b a
	float  diffuseLight[4] = { 0.8, 0.8, 0.8, 1.0 }; // r g b a
	float  specularLight[4] = { 0.8, 0.8, 0.8, 1.0 }; // r g b a
	float  lightPosition[4] = { 500, 500, 500, 1.0 }; // x y z other
	
	// glLightfv ( which light, which Property, property Values );
	glLightfv( GL_LIGHT0, GL_AMBIENT, ambientLight );
	glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuseLight );
	glLightfv( GL_LIGHT0, GL_SPECULAR, specularLight );
	glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
	
	// enable glColor3f to affect material color
	glEnable( GL_COLOR_MATERIAL );
	glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );


:

 

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.

// main.cpp
void drawW9_1( void )
{
    myMesh->makeTorus( 70.0, 30.0 );
     
    glPushMatrix();
      glRotatef( angle, 10,10,-2 );
      glScalef( 3,3,3 );
      myMesh->drawSolidShape();
    glPopMatrix();
    angle+= 1;
}

// Mesh.cpp
void Mesh::calculateNormal()
{
     for( int i=0; i<gridW; i++ )
     {
          for( int j=0; j<gridH; j++ )
          {
               normal[i][j] = Vec3d( 0,0,0 );
          }
     }
     
     for( int i=0; i<gridW-1; i++ )
     {
          for( int j=0; j<gridH-1; j++ )
          {
               // find the normal
               Vec3d A = grid[i][j];
               Vec3d B = grid[i+1][j];
               Vec3d C = grid[i+1][j+1];                              

               Vec3d AB = B - A;     // define vectors within triangle
               Vec3d AC = C - A;

               Vec3d Normal = AB.cross( AC );     // compute normal to triangle
               Normal.normalize();     // normalize the normal ( make length = 1.0 )
               
               normal[i][j] = normal[i][j] + Normal;
               normal[i+1][j] = normal[i+1][j] + Normal;
               normal[i+1][j+1] = normal[i+1][j+1] + Normal;
               
               A = grid[i][j];
               B = grid[i+1][j];
               C = grid[i+1][j+1];
               
               AB = B - A;
               AC = C - A;
               
               Normal = AB.cross( AC );
               Normal.normalize();
               
               normal[i][j] = normal[i][j] + Normal;
               normal[i+1][j] = normal[i+1][j] + Normal;
               normal[i+1][j+1] = normal[i+1][j+1] + Normal;

          }
     }

     for( int i=0; i<gridW; i++ )
     {
          for( int j=0; j<gridH; j++ )
          {
               normal[i][j].normalize();
          }
     }     
     
}

: image same with above

 

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.

// main.cpp
void drawW9_3( void )
{
     myMesh->calculateNormal();
     
     glPushMatrix();
       glRotatef( angle, -3,-2,4 );
       glScalef( 3,3,3 );
       myMesh->drawShadedSolid2();
     glPopMatrix();
     angle+= 1;
}

// Mesh.cpp
void Mesh::drawShadedSolid2( void )
{
     for( int i=0; i<gridW-1; i++ )
     {
          for( int j=0; j<gridH-1; j++ )
          {
               glBegin( GL_TRIANGLES );
               glNormal3f( normal[i][j].x, normal[i][j].y, normal[i][j].z );
               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();
          }
     }
}

: image is the same as above

 

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.

// main.cpp
void drawW9_4( void ) 
{
     myMesh4 = new Mesh( 100,50 );
     
     Vec3d   shape[100];
     Vec3d   path[50];

     for( int i=0; i<100; i++) 
     {
          float A = 2.0*PI / (96.0-1.0) * i;
          float rad = 30;
          shape[i].x = rad*cos(A);
          shape[i].y = rad*sin(A);

          float temp = 2 * fmod( i,4 );
          if( temp < 2*4/2 ) temp = 2*4/2 + (2*4 - temp);
          
          shape[i].y += temp;   
     }          

     for( int i=0; i<50; i++ )
     {
          path[i].x = i * 20 - 500;
          path[i].y = 50*cos_deg(i*15);
          
     }

     //myMesh4->makeExtrusion( shape, 200 );
     myMesh4->makeExtrusionOnPath( shape, path );
     myMesh4->calculateNormal();

    glPushMatrix();
      glRotatef( angle, -1,-2,3 );
      glScalef( 3,3,3 );
      myMesh4->drawShadedSolid2();
    glPopMatrix();
    angle+= 0.5;
}     

// Mesh.cpp
void Mesh::makeExtrusionOnPath( Vec3d* shape, Vec3d* path )
{
     Vec3d* parallelV;
     Vec3d* normalV;
     Vec3d* sideV;

     parallelV = new Vec3d [ gridH ];
     normalV   = new Vec3d [ gridH ];
     sideV     = new Vec3d [ gridH ];

     Vec3d upV( 0,1,0 );

     for( int i=0; i<gridH-1; i++ )
     {
          if ( i==0 ) parallelV[ 0 ] = path[ 1 ] - path[ 0 ];
          else parallelV[ i ] = path[ i+1 ] - path[ i-1 ];
         //parallelV[ gridH ] = path[ gridH ] - path[ gridH-1 ];

         // normal vector = parallel vector CROSS up vector
         normalV[ i ] = parallelV[ i ].cross( upV );
         
         // side V = normal V CROSS parallel V
         sideV[ i ] = normalV [ i ].cross( parallelV[ i ] ); 
          
         // normalize side V, normal V
         normalV[ i ].normalize();
         sideV[ i ].normalize();
          
     }

     // for very every point in the shape being extruded, calculate
	 //   a. point P = path[i] + ( side vector * shape[j].x ) 
     //                        + ( normal vector * shape[j].y )
     //   b. set grid[i][j] to P     
     
     for( int i=0; i<gridH; i++ )
     {
          for( int j=0; j<gridW; j++ )
          {              
               grid[j][i] = path[i] + ( sideV[i] * shape[j].x )
                                    + ( normalV[i] * shape[j].y );
          }
     }          

}     



:

 

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 )
{
     Vec3d* parallelV;
     Vec3d* normalV;
     Vec3d* sideV;

     parallelV = new Vec3d [ gridH ];
     normalV   = new Vec3d [ gridH ];
     sideV     = new Vec3d [ gridH ];

     Vec3d upV( 0,1,0 );

     for( int i=0; i<gridH-1; i++ )
     {
          if ( i==0 ) parallelV[ 0 ] = path[ 1 ] - path[ 0 ];
          else parallelV[ i ] = path[ i+1 ] - path[ i-1 ];
         //parallelV[ gridH ] = path[ gridH ] - path[ gridH-1 ];

         normalV[ i ] = parallelV[ i ].cross( upV );
         sideV[ i ] = normalV [ i ].cross( parallelV[ i ] ); 
          
         normalV[ i ].normalize();
         sideV[ i ].normalize();
     }

     for( int i=0; i<gridH; i++ )
          for( int j=0; j<gridW; j++ )
               grid[j][i] = path[i] + ( sideV[i] * shape[j].x * scale[i] )
                                    + ( normalV[i] * shape[j].y * scale[i] );
     
}


:

 

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

void drawW9_6( void )
{
     myMesh5 = new Mesh( 200,3000 );
     
     Vec3d   shape[200];
     Vec3d   path[3000];
     float   scale[3000];
     
     float   rad = 3;
     
     for( int i=0; i<200; i++) 
     {
          float A = 2.0*PI / (200.0-1.0) * i;
          shape[i].x = rad *cos(A);
          shape[i].y = rad *sin(A);
     }

     float R = 50;
     for( int i=0; i<3000; i++ )
     {
          R /= 1.0005;
          float A = 2.0*PI / (100.0-1.0) * i;
         
          path[i].x = R * cos(A);
          path[i].y = R * sin(A);
          path[i].z = i/10;

          scale[i] = 2;
     }

     myMesh5->makeScaledExtrusionOnPath( shape, path, scale );
     myMesh5->calculateNormal();

    glPushMatrix();
      glRotatef( 150, 1,-10,1 );
      glScalef( 3,3,3 );
      myMesh5->drawShadedSolid2();
    glPopMatrix();
    angle+= 10;
          
}

: http://www.inkart.com/images/ColorArt/cornicopia.jpg




:

 

Problem 7. Optionally, utilizing the makeExtrusionOnPath function, make some or all of the squashes shown in the cornucopia.


: