James Dunlop Homepage

Maya EyeLid Node


I was posed with the issue for an eye rig recently “Include the bulge without using deformers that animators can see!”

Why is the cornea bulge important?

Well if you close your eyelids and move your eye around it will deform the lid. Close up to camera you’re going to notice this subtle deformation missing.

Also, animators want to see this while they’re working, which is kinda tricky if you’re wanting to try to keep a speedy rig and looking to avoid deformation approaches (sculpt deformers through curves / blendshapes etc).

I also wasn’t aware of Marco’s Cartoony eyelid even though he was in the building at the time of my starting in on this setup, so it was interesting to see his setup when I did because I could totally understand where he was coming from with that setup.

However; I ended up writing a node to help reduce the clutter of the nodeEditor, and to take advantage of some of the hermite stuff internally to resolve a few issues on my last show. The result is that the node pushes the eyelid joints out along an axis, by using the centroid (of the sphere of the eye), away from the eyeball, with a falloff, to simulate the effect of the cornea bulge. Depending on the amount of joints involved, it’s fairly robust and will not result in the lid slicing through the eyeball too much at all.

The below examples only have 2 rows of joints per lid, and it should be noted I’m being lazy with my examples as I’d most likely go with 3 rows per lid for a final rig.

Centroid for the bulge push?

Looking at wolfram ‘s example of a spherical cap


The geometric centroid occurs at a distance:


It is the center of the flat plane created by slicing through the sphere by a given height.


That meant I could work out a fall off radius for the push distance using the centroid, which ended up giving a more anticipated result rather than using pow’s etc on a point at the surface of the eye’s Z vector… thus

Here is a snippet of the bulge calculation;

MFloatVector sphericalCapBulgeVector(float h, float radius, float bulgeDistance, MFloatVector affectedVector, MFloatVector sphereCenterZAxis){
	float radiusofCap = sqrt(h*(2.0f*radius-h));
	float centrd = sqrt((radius * radius) - (radiusofCap * radiusofCap));

	MFloatVector distVector = affectedVector;

	MFloatVector sphereVector = sphereCenterZAxis;

	MFloatVector distanceBetweenVector = distVector - sphereVector;
	float distanceBetween = std::min(1.0f, distanceBetweenVector.length());

	float factorOf = std::max(0.0f, radiusofCap - distanceBetween);
	float pushResult = bulgeDistance * factorOf;

	MFloatVector affectedVectorResult(0.0f, 0.0f, -pushResult);
	return affectedVectorResult;

And here is a look at the node in action. Just the 2 runs of joints, one along the edge and the other up in the orbital area;


To get this to play nicely I’ve setup some buffers / aim contraints with weightings, but nothing that was too complex to deal with.

The first part of the video is me pulling just the lid control around with a bit of influence from that control going into the eyeball.

The 2nd part is clicking play, and running the animation that also animates the eyeball’s lookat control to get the eye to look around.

Some downsides to consider with this approach;

Some upsides;

Will prob post more on this again later on when I get some time.

Things to work out:


Here’s a low res of both lids, with minimal joints and with some basic corrective blendshapes (4 shapes)… which don’t work very well at all because I’m tired and I kept messing with the skinning :)