![]() |
| Tutorial for styling tiny layers of hairs, mainly using "Follow NURBS" modifier. |
| Geometries |
![]() |
| First of all, create a high resolution copy of your model. It will be used many times later as target object for shrink wrap operator. It's good idea to make it smooth as possible, without ears or internal surfaces. It needs to match base model in areas where hair is growing. We call it: "collider". |
![]() |
| Now, we will create main NURBS emitter object. I doing that by lofting, then by shrink wrapping the loft object to collider, with shrink wrap operator above in stack. |
![]() |
| When is finished, NURBS emitter may look like this one. It should encompass a bit more space than hair. For better performance, we will set NURBS surface to linear degree : Model > Create > Surf.Mesh > Fit .. . We will also set first U row at hair splitting area. We call it: "nurbs emitter". Be sure it's normals are pointing in correct direction, outwards of model. |
| - A lot of operators in this hair rig rely on correct UV's layout on NURBS surfaces. To see first U and V rows, go to main menu>display> visibility options> attributes, enable Nurbs Boundaries. - For adjusting NURBS UVs, go to Model> Modify> Surf.Mesh> Swap UV. If UV doesn't fit at first, repeat Swap UV operator. - ICE allows replacing geometry inputs at any time. So, if some geometry doesn't look nice at first, don't worry, you can change it later. Also, anything you create, it can be re-used later for another hair rig. - It's good idea to use "common" rule for units, 1 SI unit = 10 cm, because of default distance cutoffs for geometry queries - With ICE, you can copy/paste ICE trees between different scenes. Exactly, you can open another scene, copy ICE compounds, close that scene and open new one, then paste compounds in desired ICE tree. |
![]() |
| Now, emitter mesh. Guides will start from it's points. Hair rig is able to work without this one, but it's there to provide better, more even distribution. I creating it from NURBS emitter : Model > Create > Poly Mesh > NURBS to mesh. First I create high density mesh, then I getting the final one by filtering points : Model > Modify > Filter Points. It may have about 300 - 700 points. We call it: "mesh emitter". It should match with nurbs emitter as close as possible. So, shrink wrap again... |
| Guides |
![]() |
| Guides Point Cloud. Go to Model > Get > Primitive > Point Cloud > Empty. Create ICE tree on point cloud. Just ICE tree, what means, un simulated UCE tree. Add compounds, so your ICE tree should be like one in picture. "Add Controller Along Normals" is there only to provide basic strand creation, also for testing purposes. At "Emit Guides" compound, set ABCDEFG to 1, set strand segments to about 30. |
| - Count of strand segments is a very important for modeling performance. When modeling, keep it low as possible. |
| Follow NURBS modifier, clump, curls... |
| Now, first "Follow NURBS" modifier. It's designed mainly for creating a tiny layers of hair along body, which is very hard to create in another ways. It acts as an opposite to "Controller" modifiers. "Follow NURBS" forces strands to follow NURBS surface, "Controller" modifiers are cross sections for lofting hair. Let's see how Follow NURBS works: |
![]() |
| It starting from first U row of NURBS surface. Point positions (hair roots) are projected to NURBS surface, then hairs are automatically aligned in layers. You can specify area where hairs "grow". If hair roots are outside of cutoff distance in SI units, or outside of "U limit" area on NURBS surface, modifier won't catch hairs. In order to work properly, NURBS surface should match closely to NURBS emitter, where you want it to take strands. Shrink wrap again... As usually, keep Cutoff Distance as low as it possible. |
![]() |
| When using more than one Follow NURBS modifier, the last one takes precedence. |
![]() |
| NURBS surface for modifier. For simple setups where hairs doesn't go outside of hair growing area, we can use nurbs emitter, but there we want more. So, lofting and shrink wrapping again... |
![]() |
| ... so after lot of tweaking, it looking like this. Here we were used two Follow Nurbs modifiers. |
| - After you tweak points on NURBS surface, you may notice that UV isn't "uniform" anymore. That is especially visible when applying Curls. To fix that, go to Model > Modify > Surf.Mesh > Reparametrize. For these compounds, probably the best reparametrization is along Chord Length. If that isn't enough, you can use "Resample Strands" compound - this one uses hard coded Mt_Strands_Fitting node, and it's doing even segment distribution along strands. Just be sure to apply the compound *before* Curls. - Sometimes, NURBS surfaces in Softimage can be "broken", they just don't react properly to ICE point locators, also to shrink wrap operator. From my experience, this can happen when merging or snipping surfaces. Lofting seems to be always OK. To test NURBS surface, shrink wrap another object to it - it should catch along whole surface correctly. Here I've used Softimage for everything, anyway, imported NURBS from another application may be nice too. |
![]() |
| Now it's time to make guides more interesting. Here is "Grouping Strands" compound in action. It creates "clumps" on guides. As an side effect it can display created groups. Compound itself has a lot of options, here we will choose simplest one: "use strand tips", where compound tries to define groups, according to distance between strand tips. This option doesn't work very well with heavy motion, because strand groups can change, but for now, we will stay with it. |
![]() |
| Of course, curls...... I think that "Curls Along Strands" compound is enough self-explanatory. Anyway, just notice the difference: on the left, Curls were applied *before* grouping. On right, they were applied *after*. |
| Hair |
![]() |
| Finally, hair. Create a new, empty point cloud, create un simulated ICE tree, add "Point Sample Set to UV" compound. These black dots, that's a hair. In compound, tweak "start" and "end" values, until area covered with hair, matches area where are guides- as close they are, it's better. Don't worry about "hole" around splitting area, we will fix that later. |
![]() |
| "Point Sample Set to UV" compound has options for variable hair density over NURBS emitter - exponent along U, function curve along V. I found that very useful for rendering. You can get a better render time by using lower count of hairs where hairs are less visible. |
![]() |
| Your initial hair ICE tree may look like this. Now, in "Emit Hair" compound, we will set "Move Roots" value, so hair will cover splitting area too. These fourth-back steps are there for "foolish" the ICE point locators. They looking only for closest points, regardless on discontinuities in NURBS emitter's geometry. Here we were supplied one hair root position at searching stage, but we used another at the end. Otherwise, hair will be interpolated in wrong way. Strand Size and Point Size parameters in "Emit Hair" compound: Strand size is rendering size, if you want variable size along strand, plug "Strand FCurve" compound there. Point Size: has effect only in viewport. There is a number of options in Emit Hair, how hair interpolates along guides. I think it's best to try them, anyway: Default is even interpolation between three closest guides, the same as in "Emit Filler Strands" from PhilPack. It's enabled when "Locks> Weight" is at zero. Default interpolation looking nice, but we don't want it anywhere, especially when hair splits. Fourth-back trick, that we used on hair splitting area can't be used all the time. So there are another ways of interpolation: Clump: hairs are moved to match guides. At one, hairs will completely match the corresponding guide. Locks group: when "Locks> Weight" is at one, hair is interpolated according to the distance to closest guide at hair roots. Actually, only one guide is used. Hair is grouped in strips along guides. One typical look of long female hair would be default, even interpolation at roots, locks at tips. 'By distance' is median cut, it will enable locks, considering distance between guides, when these distances are higher than provided values. For example, you can use this option for proper interpolation around shoulders - when you want even interpolation, which still doesn't penetrate into the body. 'Align Locks' will do proper align along guides, but it's slower. |
| - Whenever you want to make some variable value along strand length, such as clump, interpolation type, whatever, use "Strand fCurve" compound. . |
![]() |
| Details again... We want only a few hairs to go in different way. We'll use "Turbulence along strands" compound. It's using standard ICE turbulence node, but there, input position for turbulence is strand length, so turbulence should look the same when strands are moved. For only a few strands, there is "every nth" parameter. "Every Nth" is exactly the same as factory "Every Nth Particle" compound, parameter is included here only for convenience. |
| Rendering, transforms |
![]() |
| Crossover For random hair length, there are many ways. Here it is something unusual, random length will appear only in rendering. First, crossover is created as an custom scalar attribute, then this attribute is used in render tree. We will also use hair colors from ICE tree. |
| - Only point cloud with hair is considered for rendering. - By default, "Emit Hair" compounds will set particle type to segment, which means hair primitive, exactly the same as for standard Softimage hair. |
![]() |
| At the end, we may get something like that. For transformations, everything that's involved in hair creation need to move too, except... ... two point clouds itself. Even nothing may happen when you move point clouds, just leave them at world zero transform, all the time. For all other details, take look at support files within tutorial. |
| Best Regards, Anto Matkovic September 2009 anto@matkovic.com |