Displaying 3D-graphics on a 2 dimensional screen

When movies such as 'Toy Story' or 'Bugs Life' are created, hundreds of hours of computer time are used to generate a single minute of film.  The computers must turn three dimensional coordinates and other data into vivid still frames on the computer screen.  Producing a single image with computer graphics uses much of the calculus and linear algebra that one learns in a first year sequence in college.

We will consider in this assignment a very special case of the more general problem described in the title by looking at convex three dimensional solids that are made up of polygonal faces.  In this project we will rotate these solids and then draw only those faces which are visible when they are viewed from a certain point.  Maple has convenient functions for dealing with 3-dimensional graphics, here we will do essentially what Maple does 'by hand.'

Assume that an object that we are working with consists of a set of faces and that each face is made up of a list of points (the first and last point will always be the same) and that the points are listed counterclockwise around the face.  For example, the following data describes the faces of a cube.

> cube:={[[-1,-1,-1],[-1,1,-1],[1,1,-1],[1,-1,-1], [-1,-1,-1]], [[-1,-1,1],[1,-1,1],[1,1,1],[-1,1,1],[-1,-1,1]], [[-1,-1,-1],[1,-1,-1],[1,-1,1],[-1,-1,1],[-1,-1,-1]], [[-1,1,-1],[-1,1,1],[1,1,1],[1,1,-1],[-1,1,-1]], [[-1,-1,-1],[-1,-1,1],[-1,1,1],[-1,1,-1],[-1,-1,-1]], [[1,-1,-1],[1,1,-1],[1,1,1],[1,-1,1],[1,-1,-1]]};

With a single command, we may use Maple to display this object.  But how does Maple decide what lines to draw and which not to draw?  When Maple puts the picture on the computer screen it is projecting the 3 dimensional data onto a flat image, it somehow decides what lines are hidden and which are 'in front.'

> plots[display3d](map(plottools[polygon],cube));

The first operation that we want to consider is a rotation about the origin.  To rotate leaving the z-coodinate fixed, the point [x,y,z] will be sent to [x cos(alpha) + y sin(alpha), - x sin(alpha) + y cos(alpha), z].  This may be expressed in terms of a matrix transformation applied to the column vector [x,y,z].  Simliarly, a rotation about the x-axis by an angle beta sends the point [x,y,z] to the point [x, y cos(beta) + z sin(beta), - y sin(beta) + z cos(beta)] and a rotation about the y-axis sends the point [x,y,z] to the point [x cos(gamma) + z sin(gamma), y, - x sin(gamma) + z cos(gamma)] .  The composition of these transformations is sufficient to express any rotational transformation about the origin.  Write a function that takes as parameters an object (such as the cube above), and angles alpha, beta and gamma and returns the object with the respective rotational transformations.

You should probably write this function in several steps.  First write a function which rotates a single point about the x-axis.  Next, a function which rotates a single point about the y-axis and also a function that rotates a point about the z-axis.  Next, create a function which is a composition of three functions.  Finally, apply this function to every single point in an object (recall there is a useful procedure, map, built into Maple).

Let us begin by drawing the object on a three dimensional plot.  This time instead of drawing each face of the object as a polygon, we will display each edge of the object as a line.  Simply put, the following pseudo-code describes the first step.

For each face do
  For each pair of adjacent points in a face do
    draw a line
  end do
end do

This may be translated into the following Maple function

> drawobject:=proc(obj) local i,j;

  {seq(seq(plottools[line](obj[i][j],obj[i][j+1], color=black),



> plots[display3d](drawobject(cube));

This is still a 3 dimensional plot in Maple and so we are able to click on the image and rotate the view of the cube.  Maple sets as an initial position of the observer at the point (1, 1, 1) looking at the origin.  We wish to transform this to a 2-dimensional plot by projecting the image into a plane.  Say that there is an observer at the point (0, 0, -z0) who is looking up at the origin.  We will place a piece of paper at the position of the observer and draw what the observer sees by projecting each point of the object into the page.

How do we project each point into this plane?  Simply by 'forgetting' the z-coordinate of each of the points of the object and drawing each of the faces in the xy-plane.  Write a function that generates the commands to draw these lines, then display the image.  Use the rotation functions that you wrote to display a sequence of images of the cube spinning about the origin.

Next, we need to hide the faces that are in back and only draw those faces which are closest to the observer.  Because we have assumed that the points in each face are listed counterclockwise around the edges, we can say something about the orientation of the face.  For example in the cube below, the points of one of the faces are labeled with p1, p2, p3, p4.  Notice that the vectors, v1, between p1 and p2 and, v2, between p1 and p4 both lie in the face of the cube.  The cross product v1 x v2 of these two vectors is then perpendicular to the face and points away from the center of the object (make sure that you understand why this is true...remember the right hand rule?).  If this vector has a negative z coordinate, then the face will be visible to an observer at the point (0, 0, -z0).  If the z-coordinate of that vector is positive then the face will not be visible.  What happens if the z-coordinate of this vector is zero?

Write a function called visible that will return true if a face is visible and false if it is not visible to an observer at (0, 0, -z0).  Next, combine this function with the Maple function select to display only those faces of the cube which are visible to the observer on the negative z-axis.  Redo the animation that you did of the cube spinning about the origin, this time only drawing the appropriate faces.

Finally show off all of the functions that you wrote for this assignment by animating some other 3 dimensional object besides the cube.  What goes wrong if we try a more complex 3 dimensional object like a chair or a star shaped object?  Do these functions still work?  Which ones do not?  What condition do you need to place on your 3 dimensional objects to ensure that these functions work correctly?

Now that you have drawn the stick figure version of your object, there is one more effect that you will add into this project.  We will add a crude light source to the picture and color each of the faces based on how much light is reflected.

We see in the picture above that each face of the cube is illuminated depending on how much light is reflected from the light source to the observer.  The faces that are aimed directly at the light source will reflect a lot of light, while the faces that are facing away from the light source reflect little or no light.  We measure how much a face is aimed towards our light source by looking at the dot product between the unit normal vector to each face and a vector that points towards the light source.  If that dot product is a maximum, then the face of the cube reflects a lot of light.  If that vector points away from the light source, then the dot product will be zero or negative and little or no light will be reflected from the face.

Animate the cube and your other objects to rotate about the orgin while the light source stays fixed.

Mike Zabrocki
Math 2042