jc.clothes |
Aug 2008 |
| Last update: 28 Nov 2008 |
|
The ideal way of making clothes is to actually model the patterns,
sew them together, make the character 'wear' them and use cloth
simulation to deform them to achieve realistic results. But there must
be a good cloth simulation technology to support this process. Here I'm
trying to use Maya's nCloth system to do this.
Workflow Overview
In essence, pattern is polygon object, stitch is implemented using
joints. But the building process, is quite complicated. Fortunately, it
is possible to be automated and the majority of the tasks can be
encapsulated and hidden inside a few commands (see figure below). So it
can be summarised into the following steps:
- Make body measurement
- Outline patterns
- Create patterns
- involves Create Pattern, Create Garment
- Create stitches
- involves Create Stitch, Create Weld Constraint
- Set keyframes
- involves Set Keyframes, Attach Adjacent Stitches
- Play simulation for stitching
- Play simulation for posing
- involves Duplicate Garment
As
you see, most of the work are done by the commands. It remains tailor's
work: making body measurement, outlining pattern, which are up to you.
All the other work are mechanical and can be automated. The following
sections will describe the process in detail by making a simple blouse
so that you'll see how the commands work. |
 |
Download and Install
The jc.clothes module (together with other modules) and userSetup.py can be downloaded from here: jcScripts.zip. Then,
- Unzip jcScripts.zip under your script directory (default is C:\Documents and Settings\User\My Documents\maya\2008\scripts, replace User with your user name).
- If userSetup.py already exists, cut-and-paste the content to your existing one.
- Copy Maya.env to your Maya directory (C:\Documents and Settings\User\My Documents\maya\2008, replace User with your user name). If it already exists, append the following line:
PYTHONPATH=C:\Documents and Settings<\em>User\My Documents\maya\2008\scripts
Replace User
with your user name. If your script directory is somewhere else, make
PYTHONPATH to be the same as your MAYA_SCRIPT_PATH as follows:
MAYA_SCRIPT_PATH=/my/python/script
PYTHONPATH=/my/python/script
- Restart Maya.
- Enter
jc.clothes.doMenu()
into the command line (toggle language
selection to become Python) or Script Editor (click Python tab) and
you'll see the jc.clothes menu in your Maya menu bar.
It
is recommended that you should turn off Undo before using the scripts.
Because each command involves a lot of actions, especially jc.clothes
-> Create Stitch which can involve thousands if pattern division is
high. Each command invocation would be stored in one undo step which
occupies memory. More memory would be taken if more actions are
involved. Maya would nearly come to a halt if the amount taken exceeds
the amount you've got and it won't tell you there's not enough until a
Runtime Error dialog box pops up.
Walkthrough
As you may prefer, there's a Walkthrough guide which would walk you through the steps to create a blouse by using the commands. Its pattern outlines are prepared in a sample scene
so that you don't need to take time to create anything before starting.
You can go through the guide first and come back to learn more about
the commands at a later time.
Creating Patterns
 |
| Figure 1. Measurement and pattern outlines |
Basically, it involves taking body measurements
and laying out flat patterns according to them. So the first step is to
prepare and rig your character. The character must be in a standing
pose of course. But the arms should be pointing downwards at an angle
(see Figure 1). Because this would affect the inside and outside
lengths of the sleeves and the lengths would affect the appearance of
wrinkles under the armpit for different arm poses.
The scale
of the character is important because it would affect the parameters
used in the nCloth nodes. The best thing to do is to use real life
scale and unit should better be centimeter in order to minimized loss
in resolution due to rounding in numbers. But there's no need to change
Space Scale in the nucleus node for physically correct scale (otherwise
simulation will be a lot slower). The use of real scale for the
character is just to make things consistent.
A basic blouse
is composed of four patterns: front, back and a pair of sleeves. In
Figure 1, you can see what measurements are required and how they're
translated into flat patterns (see the matching colors). As this is a
ladies' blouse, there's a cut (brown) in the front pattern below the
chest line (red) in order to make rooms for the breasts. You can learn
more about this kind of fitting technique in most garment manufacturing
literatures (or by disintegrating your own clothes). You should refer
to them for better understanding of the principles.
To make
measurement, you can create curves and use arc length tool to determine
their lengths. Then create curves in the front view port to outline
patterns, measure their lengths using arc length tool, match their
lengths with those around the body manually. But lengths can never be
matched precisely. This doesn't matter as long as they're within a
tolerable difference. Care should be taken if the edge is a seam (where
stitch exists).
 |
| Figure 2. Front pattern for blouse |
After outlining the patterns, make sure the
curves are touching and planar. Then create a NURBS plane to cover the
curves. Its width-length ratio must be equal to 1 so as to prevent UV
distortion. UV divisions are equal to the width and length respectively
so that the patterns are composed of 1-cm squares (see Figure 2). This
is intentional because cloth simulation can perform better if the
topology is composed of squares. To obtain finer wrinkles, you can
increase UV divisions.
Project the curves onto the plane,
trim it, and convert it into polygon. You can see the faces at the
borders are irregular in shape (eg. triangles, pentagons, etc), which
is fine. Although non-quad faces are not desirable, they are
unavoidable. They're allowed to exist at the borders so that the
majority of the area is covered with squares.
Mirror the
polygon patch if necessary. Remember to modify UV (normalize and pivot
at U=0.5) after mirroring as shown in Figure 2. Don't forget to reverse
normal for back pattern. Also make sure different patterns have the
same scale in UV space. The simplest way to do this is to combine them
into one single object, then create UV by projection. Combining
patterns can not only match their UV scale, but also ease nCloth
creation. Because only one nCloth node is needed to deform a single
piece of garment as all patterns are sharing the same nCloth settings.
Scripted workflow
The work described above have been automated with the jc.clothes -> Create Pattern command. See its option box below:
After
outlining the pattern, select all curves and invoke the command. Turn
on 'Mirror' if it's just the outline of the left side. Turn on 'Reverse
Normal' if it's a back pattern. 0 in 'Division' means 1-cm squares. As
it creates and trims a NURBS object before converting it into polygon,
you must indicate which part of the NURBS plane (by specifying a point
in UV) is chosen in the trim command. The U and V parameters in the
option box are to let you do this. Try to adjust them if you can't
obtain the piece you expect.
This command would create an
attribute jcPattern on the input curves and connect this attribute to
the resulting pattern. This is to preserve relation between curves and
pattern so that the latter can be found via the curves in later
commands.
Garment is a single object composed of patterns.
So creation of garment includes combining patterns. To create garment,
select all patterns and then invoke the command jc.clothes -> Create
Garment whose option box is shown below:
After
combing patterns, this command would create UV by projection and then
create nCloth. The connections between the patterns and the curves
would be rebuilt to point to the new object. If there's only one
pattern in the garment (eg. a belt), you can still use this command to
setup nCloth properly.
Normally nCloth is created after
binding because skin cluster deforms object before nCloth. If nCloth is
created before skin cluster, the latter must deform the intermediate
object (inMesh of nCloth node). This will be taken care of by the
command jc.clothes -> Create Stitches which will be explained in
next section.
Stitching
After creating patterns,
the next thing to do is to make them 'wrap' around the character and
join or stitch the patterns together. The steps are:
- Create joints at the seams in both pattern and measurement curves
- Bind the patterns to the joints (not required in scripted workflow)
- Create nCloth (not required in scripted workflow)
- Create dynamic constraints (not required in scripted workflow)
- Animate the joints, nCloth and constraints
Firstly,
create joint chains at the measurement curves corresponding to the
seams. For straight seams, two joints (root and end) are enough. For
curved seams, there'll be more joints but the number of them involved
depends on how precise you want to do stitching. Then duplicate them,
'flatten' them in the front plane (by zero out rotation and joint
orient) and match the corresponding edges in the patterns by manually
rotating the joints as you can see in Figure 1.
Note that the
joints on the patterns must be duplicated from those on the measurement
curves because these joints will snap together for the sake of wrapping
the patterns around the character. So they must be identical.
Then
mirror the joint chains if necessary. Put the joints (affecting the
same pattern) into a single group. Bind the garment to the joints (bind
to 'Joint hierarchy' in Skin -> Smooth bind). Create nCloth. Make
character Passive. Set Input Mesh Attract to 2 in all patterns. See
Figure 3 below.
 |
| Figure 3. nCloth attributes |
Set Input Mesh Attract for the vertices along stitch borders to 1 and the rest 0. Use Duncan's nClothVertexEditor to perform this task. See Figure 4 below.
Those
vertices on the border which are outside the seams (not on the joints)
should have their Input Attract value set to 0 as they won't follow the
deformation caused by the joints.
 |
| Figure 4. nCloth vertex properties |
Create weld constraints among the connecting
patterns (select both patterns and nConstraint -> Create weld
constraint) and within the same pattern (select one pattern and
nConstraint -> Create weld constraint) if needed. Those which are
required for the blouse are shown in the following table:
| Weld constraint |
Pattern 1 |
Pattern 2 |
seam |
| 1 |
Front |
|
2 from chest to waist |
| 2 |
Front |
Back |
shoulder, body side |
| 3 |
Left sleeve |
|
inside arm |
| 4 |
Right sleeve |
|
inside arm |
| 5 |
Front |
Left sleeve |
armhole |
| 6 |
Front |
Right sleeve |
armhole |
| 7 |
Back |
Left sleeve |
armhole |
| 8 |
Back |
Right sleeve |
armhole |
Then turn on Exclude Collision. Turn off Enable. See Figure 5 below.
 |
| Figure 5. Weld constraint 1 |
Here comes simulation. The sequence is:
| Time |
Action |
| 1 |
Move patterns to initial positions |
| 40 |
Snap joints |
| 50 |
Turn on weld constraints |
| 60 |
Turn off Input Mesh Attract |
At time=1, move the patterns by translating and
rotating the joint group to initial positions and set key for its
translations and rotations. See Figure 6.
 |
| Figure 6. Initial positions |
At time=40, snap the joints to the corresponding ones around the body. Then set key for their translations and rotations.
This
snapping process is not trivial. There're two ways to accomplish this:
by using IKs or orient constraints. Doing this manually is tedious. So
this step is automated and can be carried out easily with a single
command jc.clothes -> Match Joints which is further encapsulated
within jc.clothes -> Create Stitch. Details will be described later
in this section.
At time=49, set key for weld constraints' Enable (which is off). At time=50, turn it on and set key.
At time=59, set key for patterns' (nCloth) Input Mesh Attract (which is 2). At time=60, make it 0 and set key.
The last two steps has been automated. It'll be described later in this section.
Finally, play simulation. It took less than 3 minutes for 100 frames in my P4 machine. See Figure 7.
 |
| Figure 7. Stitching simulation |
It is impossible to achieve the best result in
your first attempt. If the garment isn't fit enough, you have to adjust
the patterns and do it all over again. So you may want to do it
incrementally. For the blouse above, you can make it without sleeves in
your first attempt. After you're satisfied with the result, build the
sleeves and combine them with the other patterns in your next attempt.
Scripted workflow
With
automation, the work above can be simplified tremendously within a few
steps. To create joints, select a measurement curve and shift-select
the corresponding pattern curve (there can be two of them as you see in
the front pattern of the blouse). Then invoke the command jc.clothes
-> Create Stitch. See its option box below:
It'll then create the joint chains along the curves, mirror them to the
right side, and bind the garment to them (by creating skin cluster or
add influence if it already exists). The garment is found by following
the jcPattern attributes of the curves.
'Count' is the
number of joints along the curve. Sometime it fails to create joint
chain due to parameterization of the curve. You can turn on 'Rebuild
Curve' to fix it. If the curve lengths don't match and your actual
intention is to stretch or shrink the pattern seam during stitching,
turn on 'Stretch'. If 'Bind' is on, it'll bind the joints to the
pattern to which the curves correspond. It will create a weld
constraint between the edges along the curves if 'Constraint' is
enabled.
Before invoking the command, be careful about the
direction of the curves because it determines the direction of the
joint chain. In other words, the direction of the measurement curves
and that of the pattern curves must match.
This command would
also create an extra attribute (called jcDestinationJoint) in the root
joint on the pattern curve. It is connected to the corresponding joint
on the measurement curve. The command jc.clothes -> Set Keyframes
would rely on this connection to find out the matching joint chains so
as to do the snapping and set keyframes. So if you create the joint
chains manually, you have to do the snapping also manually yourself by
calling jc.clothes -> Match Joints.
There's also no need
to update per vertex attributes along the pattern border. Because this
command can find out the vertices along the border edge and set
appropriate values for them. Because of this, it can also find out the
connecting edges and create weld constraints between them. So there's
no need to create constraints by hand as well.
If weld
constraint is created each time you create a stitch, there'll be a
number of them because there're a number of stitches. But actually one
single constraint is enough to weld all the edges in different
stitches. So there's a command jc.clothes -> Create Weld Constraint
to do this.
If
you want to use this command, 'Constraint' should be off when you
invoke jc.clothes -> Create Stitch. After all stitches are created,
select pattern curves sitting on the edges which are to weld. Then
invoke jc.clothes -> Create Weld Constraint and it'll create one
dynamic constraint for all stitches.
Then group the pattern joints. Move the groups into start position.
To
set keyframes for the stitch joints, nCloth and constraints, select
garment and then invoke jc.clothes -> Set Keyframes and it'll clear
all keyframes, animate the stitch joints, turn on all constraints and
turn off Input Mesh Attract of the nCloth node at the specified times
indicated in the option box below:

If
your 'Stich Start Time' is not 1, don't forget to change 'Start Frame'
in the nucleus node as well. There're two ways to match the joint
chains, either by orient or by IK. If problem happens when joints are
matched by orient, it can probably be fixed by using IK. The reverse is
also true.
When you play simulation, you may probably found
that some stitches which are along the same continues border are
snapping to the destinations without following each other as if the
border is broken up. This can be fixed by using the command jc.clothes
-> Attach Adjacent Stitches.
This
command would create a point constraint between the ending joint and
the starting joint between two joint chains so that the latter will
follow the former. If keyframes have already been set on the latter, a
pairBlend node will be created automatically and a blendPoint1
attribute will be created on the affected joint to control the weight
of the contraint. This blendPoint1 will be keyframed so that the effect
of the point contraint will be vanished at the end of simulation.
That's why its option box requies the Stitch Start Time and Stitch End
Time.
To use this command, select one joint in the leading
stitch (joint chain) and then shift-select one joint in the following
stitch. It'll find out the ending joint of the former and the starting
joint of the latter, and then create the point constraint.
Finally,
if you want to throw away everything constructed (except pattern
curves) and start it all over again, you can select garment and invoke
jc.clothes -> Delete Garment.
Rebuild Garment
When
the garment is about finished, you'll find that you need to fine-tune
the pattern curves and rebuild the garment repetitively. It is a kind
of hassle you want to get rid of. This is possible because the process
is scriptable. Before writing the script, you should have built the
garment at least once or until you no longer add pattern curves or
change pattern structure. Delete the garment (invoke jc.clothes ->
Delete Garment). Name the curves properly. Retain the stitch groups
(together with their keyframes). Retain Passive object or anything
outside the garment. Write the script in Script Editor (in Python
pane). Save it to the shelf and execute it after making adjustment to
the curves. The basic structure of the script is as follows:
# create garment
p1 = jc.clothes.createPattern(curves..., u=0.1, v=0.1, mirror=True, division=0, reverseNormal=False)
p2 = jc.clothes.createPattern(curves..., u=0.1, v=0.1, mirror=True, division=0, reverseNormal=True)
...
g = jc.clothes.createGarment(p1, p2, ...)
# create stitches
s1 = jc.clothes.createStitch(curves..., count=10, rebuildCurve=False, mirror=True, stretch=False, bind=True, constraint=True)
s2 = jc.clothes.createStitch(curves..., count=10, rebuildCurve=False, mirror=True, stretch=False, bind=True, constraint=True)
...
# create weld constraint (optional)
# jc.clothes.createWeldConstraint(curves..., mirror=True)
# group stitches
maya.cmds.currentTime(0)
maya.cmds.parent(s1[0], s2[0], ..., "bodyStitchN_1")
maya.cmds.parent(s1[1], s2[1], ..., "stitchN_1")
...
# set keyframes
maya.cmds.currentTime(1)
jc.clothes.setKeyframes(g, setKeyframesFor="Stitches nConstraints nCloth", stitchStartTime=1, stitchEndTime=40, jointsMatchBy="IK", turnOnConstraintsTime=50, turnOffInputMeshAttractTime=60)
# attach adjacent stitches (optional)
# jc.clothes.attachAdjacentStitches(s1[1][0], ..., stitchStartTime=1, stitchEndTime=40)
# jc.clothes.attachAdjacentStitches(s1[1][1], ..., stitchStartTime=1, stitchEndTime=40)
...
It
is necessary to understand the return values of each command before
writing the script. Those of jc.clothes.createPattern and
jc.clothes.createGarment are trivial. They're the pattern object and
the garment object respectively.
The return value of
jc.clothes.createStitch is a list of joints. Its sequence depends on
the sequence of arguments (curves) you put into the command. The first
argument is always the measurement curve. So the first item (index 0)
in the output list is always the joint chain created on the measurement
curve. Then you should know the next item corresponds to which curve.
If 'mirror' is on, the items in the list would be tuples in which the
first item (index 0) is the joint chain on the left, the second item
(index 1) is that on the right. You can find an example at the end of
the walkthrough guide.
Posing

Posing
should be considered as a different process after stitching. The
purpose of stitching is to build the default pose of a garment from its
flat shape. Garment posing is analogous to character posing which
starts from the default pose. In order to avoid going through stitching
every time you pose a garment, it is necessary to separate the two
processes and make posing start from the default pose. To do this, we
have to make a new garment which would be created out from the shape
obtained at the end of stitching. The rest shape of this garment would
be the shape at the beginning of stitching.
To create new garment, select the garment at the end of stitching. Invoke Edit -> Duplicate Special
.
From option box, select Edit -> Reset Settings, check "Assign unique
name to child nodes". Press "Duplicate Special". The default (start)
shape is now duplicated. While the shape is still selected, invoke
nCloth -> Create nCloth.
To find the rest shape, open
Attribute Editor while the new garment is selected. You'll see there're
three shapes. Two of them are intermediate objects. To see them,
uncheck their "Intermediate Object" attributes. The rest shape is the
flat one before being deformed by stitching. While its tab is being
selected in the Attribute Editor, press the "Select" button. Then
ctrl-select the new nCloth node from Outliner and invoke Edit nCloth
-> Rest Shape -> Connect Selected Mesh to Rest Shape. You can
check its "Intermediate Object" attribute after this to hide it again.
To make sure the connection is done, you can open Hypergraph to find
out.
The next step is to duplicate the weld constraints.
Because we do not want to make new stitches which would ruin the seams
and affect the subsequent deformation. So we want to duplicate stitches
to the new garment to make the patterns weld together in exactly the
same way as in the old garment. This is possible but it would involve
manual duplication and connection of the dynamicConstraint and
nComponent nodes using Hypergraph and Connection Editor. Because we
need to duplicate the component lists which are present inside the
nComponent nodes. The details will not be described here. You may rely
on the Duplicate Garment function described in the next paragraph.
Scripted workflow
At the end of stitching, select
garment and invoke jc.clothes -> Duplicate Garment.
Its option box is shown below:

It
has the option to let you create new solver for the new garment so that
it won't collide with the old one which can be delete from the scene.
It'll duplicate the rest shape to a new transform node and you'll see
it in the Outliner. Only weld constraints will be duplicated. You'll
have to create other contraints if there's any. It'll also disable and
hide the old garment after execution. In fact, you can not only
duplicate garment from the default pose (shape after stitching), you
can also duplicate other poses so that you can perform different stages
of posing. But these duplicated garments will share the same rest
shape. That's why it is parented under a separate tranform so that it
would remain intact in case you want to delete poses.
After
duplication, the start frame of the new garment will be the beginning
of the stitching process (start frame of the nucleus node which is 1 by
default). This is when you start your posing simulation or animation of
your character.
Conclusion
With these tools ,
you can always throw away bad clothes and go back to the beginning to
rebuild garment without regret. Because the effort to make clothes is
reduced so much that you can experiment on a number of different
patterns within a short time before deciding the best one you need.
These
tools can let you create clothes shapes which are very difficult to
achieve by any kind of modeling or sculpting technique. You can create
better real-life, non-nude characters rather than keep struggling with
those game characters which are always wearing body-tight armor and
simple cloak. But you must be able to create body models and rigs which
are good enough to deform clothes properly. You must acquire some
tailoring skill as well especially if you want to make designer clothes.
The
shortcomings of this technique are: it's available in Maya only because
it relies on nCloth. Simulation for high-res clothes is too slow for
animation purposes. Simulation can only be performed by one CPU or one
core in multi-core CPUs. So, unlike rendering, it cannot be speeded up
by adding more CPUs.
.