Homework 7, due Wednesday, Oct 23.

This is a very simple homework - I'm giving you a break here. Basically, it's the first part of a two-parter. Next week's homework will be more challenging, and will build on this one.

Your assignment is to enhance the results of using your motion machine by putting "meat" on the bones, so to speak, by making shapes that that consist of polyhedral meshes (ie: surfaces formed from meshes of polygons). If you are feeling creative, please feel free to change the content of your motion machine for this assignment.

The simplest way to create a polyhedral mesh is as a two dimensional array of vertices, where each vertex contains both a location vector and a normal vector:

   double vertices[nrows][ncols][6];
The six values per vertex refer, respectively, to {x,y,z,normalx,normaly,normalz}. You can make many useful shapes this way. For example, to generate a unit sphere that is swept out parametrically by a longitude angle θ and a latitude angle φ:
   vertices = new double[NPHI+1][NTHETA+1];
   for (int i = 0 ; i <= NPHI ; i++) {

      // PHI (LATITUDE) VARIES FROM -PI/2 TO +PI/2

      double phi = Math.PI * (double)i / NPHI - Math.PI/2;
      for (int j = 0 ; j <= NTHETA ; j++) {

	 // THETA (LONGITUDE) VARIES FROM 0 TO 2*PI

         double theta = 2 * Math.PI * (double)j / NTHETA;
	 double v[] = vertices[i][j];

	 // SET THE LOCATION VECTOR, FROM LONGITUDE AND LATITUDE

	 v[0] = Math.cos(phi) * Math.cos(theta);
	 v[1] = Math.cos(phi) * Math.sin(theta);
	 v[2] = Math.sin(phi);

	 // SET THE NORMAL VECTOR

	 v[3] = v[0];
	 v[4] = v[1];
	 v[5] = v[2];
      }
   }
This defines a sphere whose "north/south" poles are in positive and negative z. Notice that in the above example, the normal vector has the same values as the location vector. This is true only in the special case of a unit sphere.

Since you're going to be rendering your polyhedral mesh in wireframe (ie: just drawing the lines) you won't need to use the normal vectors yet. But it's a good idea to put them in now, because you're going to need to use them later.

As a minimum, use the parametrized sphere as your geometry, but transform it as appropriate for your content. For example, if you're creating limbs for a moving humanoid character, you probably want to stretch the geometry along the limb direction, by scaling your geometry along one local axis (for example, invoking something like km.scale(0.2,1.5,0.2); in the local coordinate system). When you do this, remember to surround your scale call with matching push() and pop() calls, so that the entire remaining subtree doesn't get scaled - just the geometry at that limb. The following fragment of code will give you the idea:

   ...
   km.rotateZ(values[L_HIP_Z]);  // SWING HIP OUT
   km.rotateX(values[L_HIP_X]);  // BEND AT HIP
   push();                       // LOCALLY:
      km.translate(0,-1.5,0);    //   MOVE TO MIDDLE OF THIGH
      km.scale(0.2,1.5,0.2);     //   SCALE THIGH SHAPE
      drawUnitSphere(g);         //   DRAW THIGH ELLIPSOID
   pop();
   km.translate(0,-3,0);         // MOVE FROM HIP TO KNEE
   km.rotateX(values[L_KNEE_X]); // BEND KNEE
   ...

For extra credit, try making other sorts of shapes. For example, try to figure out the parametric description of a torus, or a section from a general second-order surface. Try to make polyhedral topologies which are not rectangular meshes. For example, try making a sphere that is a refinement of a dodecahedron or icosahedron.

Better yet, surprise me.