Creating Simple Eyes with Blinking Eyelids in Maya (Cartoon Eyes)
By Brian Immel
This tutorial assumes that the user has a basic understanding of how to create and assign shaders, creating blend shapes, basic NURBS modeling, using layers, locking and hiding attributes, basics of using constraints, Hypergraph, and basic understanding of Set Driven Keys.
This tutorial works with Maya 4+. Enjoy!
Modeling the
Eye
1. Create a NURBS sphere and name it Eyeball. Position, rotate and scale the Eyeball so that it fits into your character’s eye socket.
2. Select the Eyeball and go to Modify > Freeze Transformations. This will reset all the attributes back to zero without resetting the geometry’s location, rotation and size. This step is important when we go to set up the constraint system later on.
3. Assign a phong shader to the Eyeball geometry and give the color attribute a near white color.
4. Duplicate the Eyeball geometry. Rename this new geometry to Pupil. Move and scale the Pupil so that it sits in front off of the Eyeball. Since this is a cartoony eye setup, we are allowed (artistic license) to make the Pupil geometry to penetrate the Eyeball geometry as seen in Figure 2.
5. Assign a lambert shader to the Pupil and turn the color attribute to near black.
6. Duplicate the Eyeball again and pull it away from the eye temporarily. We're going to use this sphere to create an eyelid.
7. Right-click on the sphere and select the control vertex option. Using the translate and scale tools, model the eyelid so it looks something like Figure 3. You shouldn't have to worry about the tessellation issues or the overlapping geometry of the backside of the eyelids. This part of the eye will be inside the head anyway.
8. Rename it to Lid_upper. Assign your skin-colored shader.
9. Duplicate Lid_upper and rename it to Lid_lower. Rotate the Lid_lower geometry until it looks like the position in Figure 4. Select everything, duplicate and move it away or hide in a layer so you can set up the other eye later.
Setting up the Constraints
1. Now lets build some relationships. Parent the Pupil to the Eyeball by selecting the Pupil, shift selecting the Eyeball, and hitting the p key for parenting the selected objects.
2. Use Maya’s Create Text Tool (Create > Text > option box) to make the E NURBS curve. I like using icons that look like or represent the object(s) it is meant to control. When you first create any text shapes, Maya puts everything (even if it is one character or curve) in a group. Deselect and reselect just the E shaped curve. Rename this curve to Look_L. Position the Look_L curve in front of the eye. In this case for our CG friend Oscar, I put the Look_L curve 1 unit in front of the eye. At this point we should have something that looks like Figure 5. Before we go any further, it would be a good idea to Freeze Transformations on the Look_L.
3. Select the Look_L curve, shift-select the Eyeball and go to Animation > Constrain > Aim. If the Eyeball happens to flip around when you perform this function, try adjusting the options for Aim Constraints (Animation > Constrain > Aim > option box). In order to get the Eyeball to look at Look_L properly, look at the direction Eyeball is facing. In this case, the Eyeball is looking down the X-axis. This is a good clue. Change the Aim Constraint so that the Aim Vector is set to 1, 0, 0 (X, Y, Z). If your Eyeball were facing the Z-axis, then you would set the Aim Vector to 0, 0, 1.
There are other options to set up the Aim Constraint like go ahead and just constrain it and then adjust the offsets. This is fine, but be warned! This may cause problems later on if you try set up multiple constraints.

Now our Eyeball and Pupil should follow Look_L’s position (Figure 6).
4. Now lets set up a system that allows the eye to look and stare at objects in the world (world view) and to look as if his eyes are focused on himself (local view) or move with the character. Make a Locator and place it in the center of the character’s face but away from the Look_L curve. Rename the locator to Eyes_master. By this point, your setup should look something like Figure 7.
5. Freeze Transformations (just translate and rotate) on Eyes_master. Freezing Transformations on both the Look_L (as we did earlier) and Eyes_master allows the animator to know exactly where the reset position is (translate 0,0,0, rotate 0,0,0).
6. Duplicate and offset Eyes_master twice. We are going to use these duplicates to set up a world-view control and a local-view control for where the eyes will be focusing. Name one duplicate Eyes_local and the other Eyes_world. Hopefully, you set up the locators to something like Figure 8.
7. Parent Look_L to Eyes_master. By parenting the Look_L to the Eyes_master, we set up a system that will allows us to keep both eyes (eventually) together or to separate as we need (going cross-eyed, one eye looking to the left while the other stands still and other comical possibilities). With this setup, we can keep both eyes looking at the same thing together or move each Look individual to allow for individual eye movement.
8. Now lets set up a Point Constraint between the local-view and world view locators. Select Eyes_local, shift-select Eyes_world, shift-select Eyes_master and go to Constrain > Point. This procedure will set up a 1-to-1 relationship for the Eyes_master to be perfected centered between the location of Eyes_local and Eyes_world. Go ahead and play with both local and world Eyes and note how the Eyes_master stays in between the two at all times.
9. Select the Eyes_local and Eyes_world locators and Freeze Transformations to reset their positions to zero. Also, we should Freeze Transformations on the Look_L curve as well.
10. Finally, we should lock and hide all the attributes of the Eyes_master so that we don’t accidentally keyframe any of these attributes. Locking attributes won’t interfere with Constraints.
Adding Custom Attributes—Eye Blinking and Looking
1. As we start animating, you will more than likely want to keep the eyes in “local mode”. Therefore, we are going to set up the switching ability between local and world views on the Look_L control. The Look_L control will be bouncing back and forth from local and world views so its only logical to place the switch controls and blinking controls on this control object.
2. Lets hide the attributes we are not going to use and then add the ones we do want to use. Select all three locators. In the Channel Box, select all the Rotates, Scales and Visibility attributes. Lock them and hide them using the Channel Box and Channel Control window.
3. Select the Look_L curve and repeat the last step for locking and hiding attributes that we are not going to use.
4. Next we need to create an attribute that will allow us to switch between local and world views by controlling the Point Constraint weights. Select the Look_L curve and go to Modify > Add Attribute.
5. In Attribute Name type in Local_World.
6. Leave Date Type to Float and Attribute Type to Scalar (the defaults).
7. Under Numeric Attribute Properties, give Minimum a value of 0, Maximum of 1 and Default of 0. We are going to set up the local view to be the default view (0) and the world view to 1 with this custom attribute. Hit the Add button.
8. Now lets add one more attribute named Blink. Give the minimum a value of -5, maximum of 10 and a default of 0. I use the minimum of -5 because the eyelids normally don't open to the utmost rotation when a person is surprised. Hit the OK button. Now we have two new attributes to use to control the left eye. On to the SDKs!
The Magic of Set Driven Keys (SDKs)
1. Okay, maybe it’s not magical. Perhaps it is done right tedious. But this is where we make a complex animation possibility into a simple setup. Lets get the harder stuff out of the way by setting up the local to world view setup. Right-click on Local_World attribute in the Channel Box and go to Set Driven Key.
2. Hit the Load Driver button. Highlight the Local_World attribute in the Driver section.
3. Select the Eyes_master and in the Hypergraph select the Eyes_master_pointConstraint1 node.
4. In the SDK window, hit Load Driven. At this point your SDK window should look like Figure 9.
5. We need to set up a switching of weights between local and world view so that there is no longer a equal pull between both views. With the Eyes_master_pointConstraint1 node still selected, type in 1 for Eyes_localWO and 0 for Eyes_world W1. This is setting the weights to act upon the local view locator.
6. Select both the Eyes_localWO and Eyes_worldW1 attributes in the Driven section of the SDK window. Hit the Key button in the SDK window. At this point the Eye_master locator is completely constrained to the local view.
7. In the Driver section, select the Look_L curve. In the Channel Box, type in 1 in the Local_World attribute.
8. In the Driver section select the Eyes_master_pointConstraint1 and re-highlight both Eyes_localWO and Eyes_worldW1 attributes. In the Channel Box, type in 0 for Eye_localW0 and 1 for Eyes_world W1. Hit the Key button in the SDK window. Now we have the ability to switch from a local view to a world view via the attribute on the Look_L curve. Figure 10 illustrates what we have accomplished so far.
9. Now it’s onto setting up the blinking of the eyelids. Load Look_L as the Driver and the both eyelids as the Driven. Select the Blink attribute of Look_L and the Rotate Z on the lids and hit the Key button (Figure 11). Before setting the base location for the eyelids and the Blink attribute, make sure all the attributes involved are set to their original starting values. In this case, since we froze transformations a while back, all involved parties should have been set to zero.
10. Select the Look_L in the Set Driven Key window and then change the value of Blink to 10 in the Channel Box.
11. Select the Lid_upper in the Set Driven Key window and then rotate the upper eyelid geometry until it reaches about 80% of the closed position (in this case, about –60 on Rotate Z).
12. Select the Lid_lower in the Set Driven Key window and rotate the lower eyelid until it meets the upper eyelid (which will be about 20 on Rotate Z). The main reason we want to tell the upper eyelid to do most of the work is because as humans, our upper eyelids do the majority of rotating over the Eyeball. If you wish to make the eyelids close more like a cartoon, then make both halves meet somewhere in the middle.
13. Select both the lids in the Set Driven Key window and hit the Key button. Now the Blink attribute should drive the lids to close but not to open all the up.
14. Select the Look_L in the Set Driven Key window and then change the value of Blink to -5 in the Channel Box.
15. Rotate both eyelids so that they form a wide-open, surprised look.
16. In the Driven section of the SDK window, select both the Lid_upper and Lid_lower and then select RotateZ. Hit the Key button. Now we have both a blinking eye and a wide and surprised eye.
A Little More Character
1. Select the Eyeball, Lid_upper, and Lid_lower and put them in a group (Ctrl-g). This will put all the elements of the left eye in a neat and tidy package for us to use with lattices and blend shapes. Name this group Eye_L.
2. Select the Eye_L group and go to Deform > Create Lattice > option box. To keep things simple for us, use a 2 x 2 x 2 lattice. Click on Center Around Selection and hit the Create button.
3. Rename this lattice to Eye_L_lattice.
4. At this point, you can resculpt the eye to make any shape you want with it by right-clicking on the lattice and moving the lattice points around. Notice how the eye will conform to the new shape of the lattice and still maintain its functions within the lattice (looking around and blinking). Figure 12 shows what has happened so far. Before we move on to the next step, be sure to undo all the experimenting we just did with the lattice points.
5. Optional: You can right-click on the lattice again, select all the points, hit s (for key all), move to a different frame in the TimeSlider, move some of the lattice points around to make another shape and key all the lattice points again.
Using Lattices for Making The Eye More Expressive
1. To further the emotion of the eye, we'll use the lattice to animate various emotional stages of the eye via blend shapes. For this exercise, lets create a lattice that will express anger, sadness and surprise. Select the lattice surrounding the Eye_L group and duplicate it as many number times you want to create different expressions for the eye (in this case, three times). Make sure that you offset each new lattice so that we don’t overlap the original and confuse ourselves.
2. Model each lattice into the shape of each eye expression. See Figure 13 for some basic examples. As you finish sculpting each new lattice, name each one according to the expression it represents.
3. Select all the lattices your modeled and then your original lattice last. Go to Deform > Create Blend Shape. In the Channel Box, under INPUTS, rename the blend shape node that was just created to expression_L. From here, we should be able to animate the whole eye with several different emotions. Also, keep in mind that blend shapes are additive and subtractive. Meaning, you can use two or more blend shapes at once to create multiple emotional qualities.
4. Note: Using a simple lattice of 2 x 2 x 2 will cause your eye to 'float' from blend shape to blend shape when keying between extreme values. Using a heavier lattice shouldn't have this problem. Try using a lattice of 4 x 4 x 4 or more and don't move the center lattice points. Plus, with a heavier lattice, you can get a few more animation possibilities.
A Little Some Extra
1. Now we should look into making the Pupil have a little character. Create an attribute on the Look_L curve called pupil with a minimum of -10, a maximum of 5 and default at 0.
2. Open up the Set Driven Key and set Look_L as the Driver and the Pupil geometry as the Driven.
3. Select the pupil attribute of the Look_L in the Set Driven Key and select Pupil (the geometry) and everything but visibility of the Pupil's attributes and hit Key button. Make sure all your attributes are at their default values before keying (Pupil attribute at 0, scales at 0, etc.).
4. Select the pupil attribute of the Look_L in the Set Driven Key window and set the value to 5 in the Channel Box.
5. Select Pupil (the geometry) in the Set Driven Key window and transform the eye so it looks likes it’s surprised (similar to Figure 14). After you have transformed the geometry of the Pupil, hit Key in the Set Driven Key window with all the attributes selected except for rotate and visibility. The values I used are: Translate X=-0.048, Translate Z=-0.002, Scale XYZ=1.332. These values may not work, so you may have to customize these attributes to fit your eye. Note: Don’t make the Pupil too large. If you make it too big, when you make the eyelids blinks, they won’t be able to enclose the Pupil completely.
6. Select the Pupil attribute of the Look_L in the Set Driven Key window and set the value to -10 in the Channel Box.
7. Select Pupil (the geometry) in the Set Driven Key window and transform the eye so it looks something like Figure 15. After you have transformed the geometry of the Pupil, hit Key button in the Set Driven Key window with all the attributes selected except for rotates and visibility. The values I used are: Translate X=0.033, Scale XYZ=0.23. Now your eye should be able to get tiny and large to help emote your character's feelings with the Pupil.
Attaching The Eye System to The Rest of The Character
1. Select the Eye_L_lattice.
2. Shift-select the nearest joint to this eye system (like the joint in the head as seen in Figure 16) and hit p for parent (otherwise go to Edit > Parent). Warning! Don’t attach this setup to a joint that is suppose to rotate, move or do anything else other than sit still! Otherwise, your eyes will bounce around like a bunch of hot potatoes.
3. Finally, we need to make the Eyes_local control object to be localized to the character’s motions. Select the Eyes_local and shift-select the character’s root joint or a non-moving joint and parent it. Now the local view will stay with the character and the world view will stay where we place it in the world.
Here's looking at you!

Questions, Thoughts and Known Issues:
- If your eye or parts of your eye 'pops' when its moving, it may be due the geometry moving in and out of the lattice around it. To solve this popping problem, select the lattice, open up the attribute editor and go to it's base. Resize the base using the scale tool so that the base is slightly larger.
- “Why not parent the lattice to the head geometry?”
- Answer: because we can set up the head geometry with all sorts of other deformers (lattices, blend shapes, wrap deformers, etc.) that will cause the head to distort. This distortion will not affect the eye setup we just created and therefore cause the eyes to float away or move into the head. Bad! Very bad. This is very bad….
- If you noticed, we only did one eye in this tutorial. This system can be set up with two eyes at once using one lattice. However, you should use two Look curves (text curves) so that you can set up a constraint system for each eyeball.












