E, Robot

The E, Robot project was an experiment in modeling and animation.  As a basis, the robots from the movie I, Robot were used.  It was written using C++ and Microsoft Visual Studio 2003 for Professor Wood's CSC 471: Intro to Computer Graphics class at Cal Poly, San Luis Obispo.  Further information about the project is organized as follows:

Use Instructions

E-Robot is capable of many different actions, all of which are controllable via either the keyboard or the mouse.

Movement

E-Robot is moved in a variety of ways:

All movement is attenuated based on how much movement is requested.  Thus if four steps are requested, the first step will be at single speed until the second step is requested, at which point it will move to double speed.  If three steps are queued, then triple speed will be used.  The final step (in this case the fourth step) will always be at single speed again because nothing else is queued.

Character Animations

E-Robot can perform other animations as well:

Camera Movement

The camera is capable of both lateral (i.e. along latitude lines) and horizontal (longitude lines) movement around an invisible sphere in the scene.  The sphere is effectively enlarged via zooming the camera in and out.  Camera movement is achieved as follows:

 

Modeling

E-Robot is a compilation of 115 cone and sphere models and 19 other containing modules (to more easily manipulate a group of primitive models).  He is fully hierarchical, and is laid out as follows (an item designated as (C) is a container only):


This is in fact even a simplified diagram of the actual model, as only containers have been expanded as hierarchical.  In the actual model, almost all things are a child of their predecessor.  As an example, the hand is not at the same level as the elbow in the arm, but the hand is actually a child of the wrist, who is a child of the lower arm, who is a child of elbow, who is a child of the upper arm, who is a child of the shoulder (...I know, it's like a bible verse...), who finally is a child of the base figure.  All this hierarchy allows for easy modeling since a rotation or translation applied to any one object is then also applied appropriately to its children object.  Scaling is applied somewhat differently in that scaling is applied only to a single object (not its children), unless that object is a container, in which case the scaling is applied to the children as well (thus the convenience of using containers).

Overall, I'm quite pleased with the results of the model.  It is sufficiently flexible for animations and such, and does in fact resemble the I, Robot animations.  For comparison, a picture is available here.

 

Animation

Animation was done using a two-dimensional vector and a timer function.  The animations vector was composed, at the top level, of more vectors, with each second level vector representing a queue of animations in a certain group which were in the process of being acted out.  As an example, the top level vector held vectors for groups such as stepping (which included walking steps, both forward and back, and running steps), falling down, and raising E-Robot's arm.  Each group has its own queue, and as animations are required, they are pushed onto the appropriate queue.  By having separate groups (as opposed to one single vector of pending animations), the character could then perform multiple animations simultaneously, adding an additional element of timing.

The actions which are to be performed for each animation are dictated in a number of functions, one for each action to be performed.  A pointer to that function is placed on the queue and when required the timer function calls the function using the pointer and an integer value representing the step to perform for that animation.  The step number is decremented each call, and thus the function being called generally consists of a switch statement, with each case representing a step in the animation.

There is also an aspect of attenuation to the animations.  Rather than simple suddenly walking full speed, then stopping suddenly, E-Robot's first and last steps will be slower than the middle steps because the speed of the animation is based on the number of items in the group's queue.  For the first and last steps, only one item would be in the queue, so it would be at its slowest.  The speed is a linear relation to the number of items in the queue.  Thus, with a max queue of five items (the value used in the demo), and a max frame rate of 50 FPS, if three items were queued, then they would run at (3 / 5 * 50) = 30 FPS for the first one, then 20 FPS for the second, and finally 10 FPS for the final one  (in reality the fastest frame rates are generally lower than expected because the hardware can't keep up).

 

Other Graphics Concepts

This project makes use of a large variety of the concepts prevalent in computer graphics today, besides animation and hierarchical modeling, which are described in detail above, some of the more important concepts are described below.

Collision Detection

E-Robot is capable of colliding with the walls of his room.  This is observed in a variety of instances, such as when he raises his hand to stop a walking advance into a wall, when he falls down from a running advance, or when he simply backs into a wall and is unable to go through it.  The form of collision detection used was very basic, in that, for two objects, it used two orthonormal aligned bounding boxes and tested that for all three dimensions the maximum value of one object was less than the minimum value of the other or vice versa.  If this was not true then a collision had occurred.  This sufficed quite well for this project.  The bounding box of the robot was padded considerably to keep any flying limbs from reaching through the walls, and so that when he outstretched his arm it reached to the wall (and not through it).

Pixel to Object Coordinate Conversion

 The click-move feature of E-Robot was done using a mapping of the 2D pixel coordinates to 3D object coordinates on the floor of E-Robot's room.  This was achieved with two calls to gluUnProject(), which provided the world coordinates corresponding to the 2D click point at the near and far clipping planes.  Using these coordinates and the known height (y-value) of the floor, it was simple algebra to scale the x- and z-range given by gluUnProject() and get a point on the floor in 3D space.  E-Robot is then rotated towards the point (he is facing the right direction when the normalized vector from the point to E-Robot's center, dotted with E-Robot's forward facing unit vector, is approximately one), and told to step the necessary steps in that direction.

Lighting

Three different lights are used for the E, Robot project: an overhead point light, that same point light dimmed for flashlight mode, and a directional light which is used for the flashlight.  As described above, a spot light would have been preferable for the flashlight, however it did not interact well with the single-polygon walls, and thus a directional light was chosen.  The directional light is manipulated such that it follows E-Robot's movement, illuminating the wall in front of him.

Texture Mapping

Texture maps were created and applied for E-Robot's eyes.  They are loaded from a 24-bit 512 x 512 pixel bitmap image using file reads, and mapped to gluQuadric spheres using glBindTexture().

Materials

Three custom materials were created to finish E-Robot: a shiny plastic, a silver metal, and a black metal.  The combination of reflective attributes of these materials, mixed with the lights created for the scene, allow for a reflection appropriate for a metallic material, but not so bright as to obscure the features of E-Robot.  Originally it was planned that The plastic pieces (such as his chest, head, and lower legs) were to be translucent with a solid white version scaled slightly smaller inside of them.  This however was foiled by OpenGL's hidden surface removal and depth buffer, which doesn't compensate for translucency when deciding if one object obscures another.  Because of this, the inner object was never rendered because OpenGL didn't think it would be visible.