Week 10 Assignment - Computational Forms

Lucas Longo

 

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.

void init ( GLvoid )
{
glShadeModel( GL_SMOOTH );
glClearColor( 0.0, 0.0, 0.0, 0.0 );
glEnable ( GL_COLOR_MATERIAL );
glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

GLfloat light_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);

GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);

GLfloat position[] = {0, 0, 0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, position);
}

*** before glVertex3fv - N1 is the normal vector to the point

glNormal3f(N1.x, N1.y, N1.z);

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

void Mesh::calculateNormal(){
//Set to zero
for (int x = 0; x < gridW; x++){
for (int z = 0; z < gridH; z++){
gridN[x][z] = Vec3d(0,0,0);
}
}

for (int x = 0; x < gridW; x++){
for (int z = 0; z < gridH; z++){

if (x == 0 && z == 0) {
Vec3d cB = grid[x][z] - grid[x][z+1];
Vec3d cC = grid[x][z] - grid[x+1][z+1];
Vec3d cE = grid[x][z] - grid[x+1][z];

gridN[x][z] = cB.cross(cC) + cC.cross(cE);
}
else if (x == 0 && z == gridH) {
Vec3d cE = grid[x][z] - grid[x+1][z];
Vec3d cG = grid[x][z] - grid[x][z-1];
Vec3d cH = grid[x][z] - grid[x+1][z-1];

gridN[x][z] = cE.cross(cH) + cH.cross(cG);
}
else if (x == gridW && z == 0) {
Vec3d cD = grid[x][z] - grid[x-1][z];
Vec3d cA = grid[x][z] - grid[x-1][z+1];
Vec3d cB = grid[x][z] - grid[x][z+1];

gridN[x][z] = cD.cross(cA) + cA.cross(cB);
}
else if (x == gridW && z == gridH) {
Vec3d cD = grid[x][z] - grid[x-1][z];
Vec3d cF = grid[x][z] - grid[x-1][z-1];
Vec3d cG = grid[x][z] - grid[x][z-1];

gridN[x][z] = cD.cross(cF) + cF.cross(cG);
}
else if (x == 0) {
Vec3d cB = grid[x][z] - grid[x][z+1];
Vec3d cC = grid[x][z] - grid[x+1][z+1];
Vec3d cE = grid[x][z] - grid[x+1][z];
Vec3d cG = grid[x][z] - grid[x][z-1];
Vec3d cH = grid[x][z] - grid[x+1][z-1];

gridN[x][z] = cB.cross(cC) + cC.cross(cE) + cE.cross(cH) + cH.cross(cG);
}
else if (z == 0) {
Vec3d cA = grid[x][z] - grid[x-1][z+1];
Vec3d cB = grid[x][z] - grid[x][z+1];
Vec3d cC = grid[x][z] - grid[x+1][z+1];
Vec3d cD = grid[x][z] - grid[x-1][z];
Vec3d cE = grid[x][z] - grid[x+1][z];

gridN[x][z] = cD.cross(cA) + cA.cross(cB) + cB.cross(cC) + cC.cross(cE);
}
else {
Vec3d cA = grid[x][z] - grid[x-1][z+1];
Vec3d cB = grid[x][z] - grid[x][z+1];
Vec3d cC = grid[x][z] - grid[x+1][z+1];
Vec3d cD = grid[x][z] - grid[x-1][z];
Vec3d cE = grid[x][z] - grid[x+1][z];
Vec3d cF = grid[x][z] - grid[x-1][z-1];
Vec3d cG = grid[x][z] - grid[x][z-1];
Vec3d cH = grid[x][z] - grid[x+1][z-1];

gridN[x][z] = cA.cross(cB) + cB.cross(cC) + cC.cross(cE) + cE.cross(cH) + cH.cross(cG) + cG.cross(cF) + cF.cross(cD) + cD.cross(cA);
}

}
}
//Normalize
for (int x = 0; x < gridW; x++){
for (int z = 0; z < gridH; z++){
gridN[x][z].normalize();
}
}
}

void Mesh::drawShadedSolid(){

calculateNormal();

glBegin(GL_TRIANGLES);
for (int x = 0; x < gridW-1; x++){
for (int z = 0; z < gridH-1; z++){

//Lighting
glNormal3f(gridN[x][z].x, gridN[x][z].y, gridN[x][z].z);

glColor3f(1, 1, 1);
glVertex3fv((float*) &grid[x][z]);
glVertex3fv((float*) &grid[x+1][z]);
glVertex3fv((float*) &grid[x+1][z+1]);

glVertex3fv((float*) &grid[x][z]);
glVertex3fv((float*) &grid[x][z+1]);
glVertex3fv((float*) &grid[x+1][z+1]);
}
}
glEnd();
}

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.

(already done 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

void Mesh::makeExtrusionOnPath(Vec3d extrusionShape[100], Vec3d extrusionPath[100]){

Vec3d upVector(0,1,0);

//Parallel vectors
for (int i = 0; i < 100 - 1; i++){
if (i == 0){
pathP[i] = extrusionPath[i+1] - extrusionPath[i];
}
else {
pathP[i] = extrusionPath[i+1] - extrusionPath[i-1];
}

// normal vector crossed with up
pathN = pathP[i].cross(upVector);
// side vector
pathS = pathN.cross(pathP[i]);

// normailze vectors
pathN.normalize();
pathS.normalize();
}

for (int i = 0; i < 100; i++){
for (int j = 0; j < 100; j++){
grid[i][j] = extrusionPath[i] + (pathS * extrusionShape[j].x ) + ( pathN * extrusionShape[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 extrusionShape[100], Vec3d extrusionPath[100], float scale[100]){

Vec3d upVector(0,1,0);

//Parallel vectors
for (int i = 0; i < 100 - 1; i++){
if (i == 0){
pathP[i] = extrusionPath[i+1] - extrusionPath[i];
}
else {
pathP[i] = extrusionPath[i+1] - extrusionPath[i-1];
}

// normal vector crossed with up
pathN = pathP[i].cross(upVector);
// side vector
pathS = pathN.cross(pathP[i]);

// normailze vectors
pathN.normalize();
pathS.normalize();
}

for (int i = 0; i < 100; i++){
for (int j = 0; j < 100; j++){
//extrusionShape[j] = extrusionShape[j] * scale[i];
grid[i][j] = extrusionPath[i] + (pathS * (extrusionShape[j].x * scale[i])) + ( pathN * (extrusionShape[j].y * scale[i]));
}
}
}

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

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