These notes are to help you make different kinds of shapes. Remember that our goal is to describe various shapes in terms of the two arrays

int faces[][]; double vertices[][6];

As we said in class,
we will make room for a *normal vector* to each vertex,
so each vertex contains not three numeric values but rather six.
Eventually we will create the illusion of smooth
curved surfaces by using this normal vector data -
two adjoining polygonal faces of a shape can be made to
appear smooth and rounded by having them share
vertices, since they will then share the same normal vector
at that vertex.

But we are not going to use the surface normal yet. But I'm going to define them when I describe the shapes below, so that you'll be ready when it is time to do shading and lighting.

**TUBE**

We make curved shapes by having different faces
share vectors, so that they will have the same surface normal
at that point.
For example,
as we discussed in class,
to describe an
**
n
**
sided
approximation to an open cylindrical tube
(where the opening is along the z axis)
we need a total of
**
2n
**
vertices.
There is a row of back vertices
**
0..n-1
**

v_{i}= { cos θ , sin θ , -1 , cos θ , sin θ , 0 }

and a row of front vertices
**
n..2n-1
**:

v_{n+i}= { cos θ , sin θ , 1 , cos θ , sin θ , 0 }

where
** θ = 2π i / n **.

We also need
**
n
**
faces, each with four vertices:

face[i][0] = i; face[i][1] = (i + 1) % n; face[i][2] = (i + 1) % n + n; face[i][3] = i + n;

Given a geometry object

Geometry g = new Geometry();

you can implement the above logic by defining a method
`tube(int n)`

in the `Geometry`

class.
Implementing this method consists of filling in a geometry object's
`faces[]`

and
`vertices[]`

arrays
as described above.

**GLOBE**

To create a sphere as a longitude/latitude globe,
we again need to create an array of vertices,
and also an array of faces that index into the vertices array.
We can create a method in the Geometry class called
`globe(int m, int n)`

where `m`

is the number of longitude steps
around the equator of our polygon approximation to a sphere,
and `n`

is the number of steps from the south
pole to the north pole.

Internally we allocate `m × n`

vertices.

There is a little trickiness here
because we are thinking of this as a two dimensional
array of vertices, but our
Geometry data structure for storing vertices
is indexed by a single number.
We are going to deal with this as follows:
First we will
act as though we really two have two indices
**
(i,j)
**,
and then we will come up with a single index I
to describe the index pair
**
(i,j)
**.

As we discussed in class,
the location of a single vertex on the globe
**
v _{i,j}
**
in is given by computing the polar coordinates:

θ = 2π i / m

φ = -π/2 + π j / (n-1)x = cos θ cos φ

y = sin θ cos φ

z = sin φ

v_{i,j}= { x , y , z , x , y , z }

Note that the normal vector for each vertex is the same as its location. This is only true in the special case where the shape is a unit sphere.

As we said above, we really need to this data into a singly-indexed array of vertices. We do that by defining a single array

double vertices[ m * n ][6];which is indexed by

`I = i + m * j`

.
For convenience you mght want to define a function within the geometry object
that does this mapping:
double I(int i, int j) { return (i % m) + m * j; }The faces will refer to this single index. The globe will have

`m × (n-1)`

faces, each with four vertices.
int faces[][] = new int[m * (n-1)][4];Using our handy dandy index mapping function

`I(i,j)`

,
each face is described as a counterclockwise loop of four vertex indices:
face[i + m * j][0] = I(i,j); face[i + m * j][1] = I(i+1,j); face[i + m * j][2] = I(i+1,j+1); face[i + m * j][3] = I(i,j+1);

**DISK**

A flat circular disk can be approximated by an n-sided polygon.
In this case it is useful to introduce one extra
vertex, in the center of the disk, so that you can
define the disk as a ring of triangles.
There will be
**
n+1
**
vertices:

θ = 2π i / nv

_{i}= { cos θ , sin θ , 0 , 0 , 0 , 1 }where0 ≤ i < n

v_{n}= { 0 , 0 , 0 , 0 , 0, 1 }

Rather than one giant polygon, it is better
to use `n`

triangular faces:

int i1 = (i + 1) % n; face[i][0] = i; face[i][1] = (i + 1) % n; face[i][2] = n;

You can make a closed cylinder adding extra
vertices and faces to your open tube.
Instead of
**
2n
**
vertices and
**
n
**
rectangular faces,
you have all that plus
the vertices and faces you would need for
two sets of disks (one for the front and one for the back).

So you need a total of
**
2n + n+1 + n+1 = 4n + 2
**
vertices,
and a total of n rectangular faces, plus
**
2n
**
triangular faces.

**HOMEWORK**

Your assignment, due next Wednesday, February 25, is to implement some of these shapes - as many as you can - and to make a cool and fun animated scene using them. Also, see if you can make other sorts of shapes, like extruded shapes with non-circualar cross-section, such as an elliptical cylinder, or a cylinder with a star-shaped cross-section.

If you are ambitious, you might also try a torus. The location of one surface point on a torus is as follows:

x = cos θ (R + r cos φ)

y = sin θ (R + r cos φ)

z = r sin φ

where
**
R
**
is the radius of the large ring,
and
**
r
**
is the radius (ie half-thickness) of the tube.