I’ve developed a way of adding teary eyes to your character rigs to help squeeze out that extra bit of emotion in your shots. This tutorial is a bit advanced, but if you’re not in tears by the end of it, your character will be.
I created this tutorial using Aia from Animation Mentor. The process and methods are applicable not only to other AM rigs, but also many of the free rigs out there that have eyes.
This is what we’re going for:
Part 1: Whip up some tears
If you are following along with this tutorial using either Aia or Jules from Animation Mentor, this first step is necessary (otherwise this step can be skipped). You must select the ‘root’ control of Aia and be sure that “Body Selectable” is set to ‘ON’
Now select Aia’s outer left eye. This is generally what will be selected when you click on the eye. You may find selecting the outer eye to be easier through the Outliner. It’s name within maya is aia_anim_lf_outer_eye_geo
After selecting the outer eye, press ctrl+D to create a duplicate of the geometry. This will eventually become our tears. I renamed this duplicated geometry to lf_tear_geo We will be using a Wrap Deformer to ensure that our tears go wherever our eyes go.
Note: A wrap deformer is a lot heavier and demanding than doing a simple parent. I found that in rigs such as Aia, there are so many layers of blendshapes and connections going on that the best and most reliable way to keep our tears on the eyeball is through a Wrap Deformer. This will always be the easiest and most reliable way when you are not familiar with the intricacies of how your rig was constructed. With that being said, the lag from the Wrap Deformer in this case is negligible.
Select both lf_tear_geo and aia_anim_lf_outer_eye_geo being sure to select our newly created geometry first. Be sure your Maya Menu Set is set to ‘Animation’. Click on the ‘Create Deformers’ menu at the top of the screen, then click on the square to the right of ‘Wrap’. This will bring up the Wrap Deformer options. ‘Exclusive bind’ should be checked. This will help immensely with any lag potentially created with a Wrap Deformer. Now click ‘Create’ to create the Wrap Deformer.
The tear geometry is now attached to the eyeball! Next, we need a system for hiding and revealing the tears.
Part 2: Cut through the tears
We will be using a boolean operation in Maya to basically say, I need you to cut away the portion of object A that is touching object B. In the ‘Create’ menu at the top of the screen, select ‘Polygon Primitives’ and then click the square to the right of ‘Cube’.
Enter 9 for Width/Height/Depth. Now click in any Orthographic Viewport (Front/Side/Top/Bottom). A cube with the dimensions of 9/9/9 will be created. In my case, it has been named pCube1.
The idea is to create a cube that covers the eyeball. You may need to adjust the size of the cube to fit the eye of your character.
This cube will be the object we use to cut away from our tear geometry. Currently it’s edges are very sharp. We don’t want any sharp edges on our final tears. Select pCube1, then click and hold the right mouse button. Select ‘Edge’ from the menu that appears. Now drag a box around the cube, selecting all of the edges.
Switch your Maya Menu Set to “Polygons” and open the ‘Edit Mesh’ menu. Click on the square to the right of ‘Bevel’. Set the Width to .1 and the Segments to 2. Click ‘Bevel’
The Bevel looks good. Now the cube needs to be smoothed, for two reasons. The first is to further ensure that the edges of our tear geometry will be smooth/rounded as much as possible. The second reason for smoothing the cube will be clear later in the tutorial when we add the ‘wobble’ to the tears. The extra geometry will be necessary to get a smooth wave motion throughout the cube.
With the cube selected (in object mode: If you are still in edge mode after the Bevel operation, right click and hold on the cube and select ‘object mode, then click on the cube to select it) Open the ‘Mesh’ menu at the top of the screen and click on smooth.
At this point, add a material to your lf_tear_geo to make it easier to see what we are working with. This can be accomplished through the Hypershade Window, or by simply right click and holding on the geometry in the viewport and selecting ‘Assign New Material.’ Leave the material as a solid color for now. We will make it look watery later in this tutorial.
This is also a good time to move your cube into place over the eyeball. Ensure that it covers everything properly.
Once everything is aligned and fitted, move the cube up on the y-axis so it is clear of the head. This step is simply for clarity to help you understand what is happening. Select lf_tear_geo followed by selecting pCube1. Open the ‘Mesh’ menu at the top of the screen and select ‘Booleans’ followed by ‘Difference’. This operation gives pCube1 the ability to cut away from lf_tear_geo.
You will see that once the operation was completed, the cube disappeared. This is normal and ok. In order to work with the boolean we’ve created however, we’re going to need to see our cutting object.
Open your Outliner and select transform11 (your # may vary) which is nested underneath pCube1. Once transform(#) is selected, look to your Attribute Editor. Roll out the ‘Display’ Menu and make sure ‘Visibility’ is checked. Next, select pCubeShape1 from the Attribute Editor, you should see it directly to the right of the tab which contains transform11. Once selected, roll out the ‘Object Display’ menu and UNcheck ‘Intermediate Object’. Voilla! pCube1 should once again be visible in the viewport.
If you came here from Part 3 of the tutorial, click here to get back to where you were. I hate scrolling.
At this point you can select pCube1 and move it up and down on the Y axis (in wireframe mode) and see how it cuts away and replaces lf_tear_geo as it moves through it. When you are done, return pCube1 to a position above the character’s head so that we have room to work with it.
The last bit of construction to be done is to create the ‘wobble’ effect on the tears. This will help keep the tears from looking robotic as they well up in the eyes. This will be accomplished with a Nonlinear Wave Deformer.
Right click and hold on pCube1. Switch to ‘Vertex’ mode. Select the bottom couple rows of vertices. This will limit the Wave Deformer to these vertices.
Switch your Menu Set to ‘Animation’ and click on the ‘Create Deformers’ Menu, followed by ‘Nonlinear’, finally clicking on the square to the right of ‘Wave’.
Enter .0150 for Amplitude
Enter .750 for Wavelength
You will now see a Wave Deformer sitting inside of pCube1. If you do not see the Wave Deformer, be sure you are in wireframe mode and that Deformers are toggled on in the ‘show’ menu of your viewport.
Select the Wave Deformer. We need to adjust it’s scale to be sure the wave is reaching all of the desired geometry on pCube1. The following settings should work for you if you created a 9/9/9 square. If you did not, you will need to adjust accordingly.
Scale X: 7.6
Scale Y: 4.5
Scale Z: 9.5
The next step is a bit of cleanup. I like to try to keep things organized in case I need to go back and tweak. Open your Outliner. Middle click and drag wave1Handle onto pCube1. This will nest the Wave Deformer under our cube. Meaning, they will never get separated when the cube starts moving about.
It is imperative that our tear system moves with the head of our character. lf_tear_geo will stick to the eye no matter what as it is Wrap Deformed. However, pCube1 and it’s Wave Deformer will be left behind if the head of the character is moved. Try it.
To solve this, we will nest our tear system underneath the head control of our character. Select Aia’s head control in the viewport, then open your Outliner and press ‘F’. You should see the head control in the Outliner, aia_head_ctrl. Select pCube1 and lf_tear_geo in the Outliner, middle click and drag them onto aia_head_ctrl. They are now nested beneath the head control and as such, will go anywhere the head goes. Try it.
A bit more housekeeping. I took this opportunity to rename pCube1 to something more descriptive. It is now lf_tear_cutter. I selected both lf_tear_cutter and lf_tear_geo in the Outliner and pressed CTRL+G. This places the two objects into a group, which I then named Left_Tear. None of this changes any functionality, it simply makes things cleaner to work with.
The final step before moving on to Part 3 is to move lf_tear_cutter to it’s final resting place and zero out our transformations on lf_tear_cutter. We will be writing a bit of MEL script and it is always easier to work from a clean slate. Maya makes this task simple.
Select lf_tear_cutter either in the Outliner or the Viewport.
Move lf_tear_cutter into place so that it completely encases the eyeball.
Click on the ‘Modify’ Menu at the top of the screen. Click ‘Freeze Transformations’. That’s it!
Note: Ignore the seemingly extra sphere inside of my lf_tear_cutter. I misjudged the size of the cube so what you are seeing is the back of the eyeball that was not cut out by the boolean. It is not another object stemming from a step of the tutorial that you missed. Ignore it.
Part 3: Control your emotions
The stage has been set. All of the tools that we need to create convincing tears are in place. But we’re animators and we need control. The thought of selecting lf_tear_cutter in the outliner and moving it manually over and over and over makes me ill. Fortunately you’re about to create a really slick system for controlling your tears.
First things first. Remember when we switched off ‘Intermediate Object’ in the attribute editor? We need to switch that back on, as we no longer want to, nor need to, see our lf_tear_cutter. Here’s a shortcut back to that part of the tutorial. Remember we changed the name of pCube1 to lf_tear_cutter.
Select lf_tear_cutter in the Outliner (since we can no longer see it in the Viewport.) Move it up in the Y Axis. You will see lf_tear_geo start to appear! What we are looking for right now is the maximum distance in Y that lf_tear_cutter needs to move to reveal as much of lf_tear_cutter that we might need while animating. I found this number to be 7. To reiterate, when lf_tear_cutter is at Y=0, none of lf_tear_geo is visible. When it is at Y=7, all of (that I want) lf_tear_geo is visible.
Now that we have our limit information, let’s create the control.
Select the Left Eye Control (aia_lf_eye_ctrl) or whichever controller you want the tear controls to live on.
In the Channel Box, click the ‘Edit’ Menu and select ‘Add Attribute’. A window will pop up asking for more information. Give the control a name. I used ‘Tear’. Select ‘Float’ as the data type (this means that the value can be any number, decimals included, between the min and max.) Finally, set the Minimum to 0 and the Maximum to 7 (or whichever number you decided was appropriate in the previous step). Click ‘OK’
Now to give the control some functionality.
Click on ‘Window’ at the top of the screen, followed by ‘Animation Editors’ and then ‘Expression Editor’.
You only need to concern yourself with the part circled in yellow below. All of the information in the Expression Editor is there to serve as a reference to you while writing your MEL Script. Luckily for you, I wrote it, so just cut and paste and click ‘Create’.
lf_tear_cutter.translateY = aia_lf_eye_ctrl.Tear;
This script is saying the translate Y of lf_tear_cutter is equal to whatever the number is in the Tear attribtue of aia_lf_eye_ctrl. This is why it was important to freeze the transformations on our cube. So we can work with 0-7 instead of something silly like 138.5 – 145.5.
It is important to note that if you used different naming than I did, you will need to be sure that is reflected in these code snippets.
At this point, select aia_lf_eye_ctrl and try out the new attribute you created. You should see the tear reacting to the value in the ‘Tear’ attribute as expected. Nice work! If for some reason it is not working, the first thing to check is that the names of the objects in the code are correct.
So now we can control the tears welling up and down in the eye. Let’s add a switch to turn the wobble on and off.
Add a new attribute to the aia_lf_eye_ctrl just as we did above. I named mine ‘Wobble’ Only this time the Data Type will be Boolean instead of Float. As the wobble is either on (1) or off (0).
Open the Expression Editor once again. We are going to hook up the Wobble Attribute with the following bit of MEL script. Cut, Paste, Click Create.
if (aia_lf_eye_ctrl.Wobble == 1) wave1.offset = wave1.offset + time*.1;
if (aia_lf_eye_ctrl.Wobble == 0) wave1.offset = wave1.offset;
The offset of the Wave Deformer is the number, that when changed, animates the Wave Deformer along the amplitude and wavelength we set. The faster the offset changes, the faster the Wave Deformer ‘waves’. Therefore, you can change the .1 number in the script to anything you want to adjust the speed of the wobble. I actually found .025 to be more to my liking.
This script is a little more advanced in that it uses conditional statements. In this case, an ‘IF’ statement. IF this is true THEN do THIS. So, if Wobble is set to 1 (ON), the offset of our Wave Deformer is increased by 0.1 multiplied by ‘time’ which is the amount of time that has passed in the animation. So for example, if we are on frame 2400 of an animation, 100 seconds have passed and the offset of our Wave Deformer is increased by 1.
You now have functional, animatable tears that you can control in a very manageable way. Congratulations for making it this far! There is one more part to this tutorial to bring us across the finish line. Our tears need to look like tears!
Part 4: Tears are wet
It is important to note that at this stage of the game, I have switched my viewport to Viewport 2.0 rather than the Legacy Viewport. I have also added a directional light and enabled lights and shadows in the viewport. This will give you a much better representation of the what the tears will look like in a lit and/or rendered scenario.
Select the material that you applied to lf_tear_geo earlier in the tutorial. Open the Attribute Editor and proceed to make it look like mine. (Ignore sections 1,2,3 for now) All I have really done here is made the material transparent, given it some specular shading to catch the highlights. I used maps to create the reflection color (make the material appear wet), the reflection amount (make it more reflective in certain areas than others) and bump map (create some shimmer).
Let’s look at these maps one at a time
Bump Map: Click on the checkered box to the right of ‘Bump Mapping’. Select ‘Noise’ from the list that appears. Adjust the settings of your noise map to what I have shown in (1). This is going to create the impression that our surface is not totally smooth, as the water is moving ever so slightly as it builds up in the eye. We will animate this later to really punch up the ‘shimmer’ effect.
Go back to your Tear material
Reflectivity: Click the checkered box to the right of ‘Reflectivity’. Select ‘Ramp’ from the list that appears. Adjust the settings of your ramp map to what I have shown in (2). We are going to revisit this ramp in a moment. For now, just know that it is affecting the strength of the reflection in different areas of the tears.
Go back to your Tear material
Reflected Color: Click the checkered box to the right of ‘Reflected Color’. Select ‘File’ from the list that appears. Click the yellow file folder next to ‘Image Name’. Select a photo. I just grabbed something off of google images that had bright colors to reflect. Whatever image you choose is what is going to be reflected in the tears. It doesn’t really matter too much as the reflection will be so subtle and obscured that it will no longer resemble the original image.
That sets up the basis of our Tear Material. You are probably noticing in your viewport right now that the reflection looks…not good. There is one final step in creating the material that will clear that up. Open your Hypergraph, right click on the Tear material you created and select ‘Graph Network’
In the Work Area we can see the material we just created, including all of the maps. If you hover over any of those connections you can see how they feed into the final material. From the list on the far left, click ‘Utilties’. Select ‘Sampler Info’ from the list next to it.
You will see a samplerInfo node appear in the Work Area. samplerInfo nodes let us…sample info from an object. We can use that sampled info to drive something else. In this case, it will drive our ramp that we created for the reflectivity in a previous step.
Middle click on the samplerInfo node and drag it onto the Ramp node. When you let go, a menu will pop up. Select ‘Other’. A Connection Editor window pops up asking you how you want the samplerInfo node to interact with the Ramp node. Select ‘facingratio’ from the samplerInfo node. Roll out ‘uvCoord’ from the Ramp node and select vCoord. Close the Connection Editor.
You will notice the reflection on your Tear material is looking a lot better. The ramp used the samplerInfo to create a nice falloff of reflection across lf_tear_geo for us. Nice! Could these tears get any better?
Bonus Round: Animate the shimmer. On your own!
You’ve created an entire system for controlling welling tears in your character’s eyes! But there’s even MORE you can do to get that little bit extra if you’re up for it. You’ll use what you’ve learned to create a control that will animate the bump map on our Tear material, plussing the shimmering effect of the tears.
Create a new attribute on your eye controller of choice called ‘Shimmer’. This Attribute will be of Boolean Data Type.
Open the Expression Editor
The noise map that feeds our bump in the Tear material has a value on it called ‘time’. This is very similar to the ‘offset’ value of the Wave Deformer. We’ll be accessing that value to create our shimmer.
The relevant object names you will need to write this MEL script are:
aia_lf_eye_ctrl.Shimmer (the new attribute we just created)
aia_tear:noise1.time (the time value from the noise map from our tear material)
In plain English, you are looking to write a MEL script that says
If the Shimmer control is set to 1 (ON) then the time value in the noise map should increase by X (choose a value) over time.
But if the Shimmer control is set to 0 (OFF) then the time value in the noise map should no longer increase.
SPOILER ALERT – Below is the answer, which you already know…but maybe you’re just curious?
if (aia_lf_eye_ctrl.Shimmer == 1) aia_tear_noise1.time = aia_tear:noise1.time + time*.25;
if (aia_lf_eye_ctrl.Shimmer == 0) aia_tear_noise1.time = aia_tear:noise1.time;
This was the first tutorial I have written and you survived. I tend to be long winded, but having read countless tutorials myself, it’s out of a desire for people to understand why they are doing the things they are doing. When you understand why something works, you are more able to adapt what you know to your current, or future challenge. I hope this tutorial was helpful to you all and I’m excited to see what you’re able to do in your animations. I’d love to see them so please come back and share!